diff --git a/.gitignore b/.gitignore index 73b2ad82..02566b94 100644 --- a/.gitignore +++ b/.gitignore
@@ -1,4 +1,3 @@ -*.gypcmd *.mk *.ncb *.opensdf
diff --git a/AUTHORS b/AUTHORS index 6bfd1724..e43f6348e 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -174,6 +174,7 @@ Gao Chun <gaochun.dev@gmail.com> George Liaskos <geo.liaskos@gmail.com> Georgy Buranov <gburanov@gmail.com> +Gitanshu Mehndiratta <g.mehndiratt@samsung.com> Giuseppe Iuculano <giuseppe@iuculano.it> Glenn Adams <glenn@chromium.org> Gnanasekar Somanathan <gnanasekar.s@samsung.com> @@ -218,6 +219,7 @@ Jaime Soriano Pastor <jsorianopastor@gmail.com> Jake Helfert <jake@helfert.us> Jakob Weigert <jakob.j.w@googlemail.com> +Jakub Machacek <xtreit@gmail.com> James Choi <jchoi42@pha.jhu.edu> James Vega <vega.james@gmail.com> James Wei <james.wei@intel.com> @@ -303,6 +305,7 @@ Laszlo Radanyi <bekkra@gmail.com> Lauren Yeun Kim <lauren.yeun.kim@gmail.com> Lauri Oherd <lauri.oherd@gmail.com> +Legend Lee <guanxian.li@intel.com> Leith Bade <leith@leithalweapon.geek.nz> Li Yin <li.yin@intel.com> Lidwine Genevet <lgenevet@cisco.com> @@ -376,6 +379,7 @@ Patrasciuc Sorin Cristian <cristian.patrasciuc@gmail.com> Patrick Kettner <patrickkettner@gmail.com> Patrick Riordan <patrickriordan177@gmail.com> +Patrik Ackland <patrikackland@gmail.com> Paul Adolph <padolph@netflix.com> Paul Kehrer <paul.l.kehrer@gmail.com> Paul Lind <paul.lind@imgtec.com>
diff --git a/BUILD.gn b/BUILD.gn index ba6b223a..1b00101d 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -321,7 +321,6 @@ "//base:base_perftests", "//base:base_i18n_perftests", "//base:check_example", - "//base:protect_file_posix", "//base:build_utf8_validator_tables", "//cc:cc_perftests", "//cc/blink:cc_blink_unittests", @@ -577,7 +576,6 @@ "//components/rappor:unit_tests", "//components/sessions:unit_tests", "//media/blink:media_blink_unittests", - "//media/base:base_for_cast_ios", "//media/cast:udp_proxy", "//native_client/src/trusted/platform_qualify:vcpuid", "//native_client/src/trusted/debug_stub:gdb_rsp_unittest", @@ -605,7 +603,6 @@ "//third_party/pdfium/third_party:freetype", "//third_party/libjingle:peerconnnection_server", "//third_party/libjpeg_turbo:simd", - "//third_party/libjpeg_turbo:simd_asm", "//third_party/libsrtp:replay_driver", "//third_party/libsrtp:roc_driver", "//third_party/libsrtp:rtpw", @@ -632,6 +629,9 @@ "//ui/shell_dialogs:shell_dialogs_unittests", "//ui/views/examples:views_examples_exe", ] + if (target_cpu == "x86" || target_cpu == "x64") { + deps += [ "//third_party/libjpeg_turbo:simd_asm" ] + } if (enable_nacl) { deps += [ "//native_client/src/trusted/service_runtime:sel_ldr" ] } @@ -655,6 +655,7 @@ # and figure out how cross-platform they are deps = [ "//chrome/browser/ui/webui/omnibox:mojo_bindings_python", + "//components/window_manager/public/interfaces:interfaces_python", "//content/public/common:mojo_bindings_python", "//content/common:mojo_bindings_python", "//content/test:web_ui_test_mojo_bindings_python", @@ -674,7 +675,6 @@ "//third_party/mojo/src/mojo/public/python:packaged_bindings", "//third_party/mojo/src/mojo/public/cpp/application:test_support_standalone", "//third_party/mojo_services/src/accessibility/public/interfaces:interfaces_python", - "//third_party/mojo_services/src/window_manager/public/interfaces:interfaces_python", ] } } @@ -763,9 +763,10 @@ testonly = true deps = [ "//ash:ash_unittests", # FAILS 4/20/2015 - "//base:base_unittests", # PASSES 4/17/2015 in 32-bit, some 64-bit failures. + "//base:base_unittests", # PASSES 4/20/2015 "//cc:cc_unittests", # PASSES 4/17/2015 "//chrome_elf:chrome_elf_unittests", # FAILS 4/20/2015 + "//chrome/app_installer:app_installer_unittests", "//chrome/test:browser_tests", "//chrome/test:interactive_ui_tests", "//chrome/test:sync_integration_tests", # Note: need to turn off incremental linking for debug. @@ -816,8 +817,8 @@ "//ui/gfx:gfx_unittests", # PASSES (with assertion failure?) 4/20/2015 "//ui/message_center:message_center_unittests", # PASSES 4/20/2015 "//ui/touch_selection:ui_touch_selection_unittests", # PASSES 4/20/2015 - "//ui/views:views_unittests", # Same as WM unittests - "//ui/wm:wm_unittests", # CRASHES, looks like something simple missing. + "//ui/views:views_unittests", # TooltipControllerTest failures + "//ui/wm:wm_unittests", # PASSES 4/21/2015 "//url:url_unittests", # PASSES 4/17/2015 # TODO(GYP) installer_util_unittests
diff --git a/DEPS b/DEPS index d79a5e914..4885033 100644 --- a/DEPS +++ b/DEPS
@@ -34,7 +34,7 @@ 'llvm_url': 'http://src.chromium.org/llvm-project', 'llvm_git': 'https://llvm.googlesource.com', 'webkit_trunk': 'http://src.chromium.org/blink/trunk', - 'webkit_revision': 'ed1c4f3c9dbd0a07e21a4b8b68e39632f474cb20', # from svn revision 194275 + 'webkit_revision': '1fa112a215113081def082878c71ffd95a23001d', # from svn revision 194580 'chromium_git': 'https://chromium.googlesource.com', 'chromiumos_git': 'https://chromium.googlesource.com/chromiumos', 'pdfium_git': 'https://pdfium.googlesource.com', @@ -42,12 +42,12 @@ 'boringssl_git': 'https://boringssl.googlesource.com', 'libvpx_revision': 'c600ca703b712ac0d2db719970a1fce6de70fcb4', 'sfntly_revision': '1bdaae8fc788a5ac8936d68bf24f37d977a13dac', - 'skia_revision': '743be194eda4c1f37c4a5f62f38ef88f09f30649', + 'skia_revision': 'f4219ddf31b2171a5576ab98d1fd2deab4d816fd', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and V8 without interference from each other. 'v8_branch': 'trunk', - 'v8_revision': 'e2ee9248e7c7b2a5a2f919f593290478b5905bb7', + 'v8_revision': 'c541d594a884bef7bfdbdfe46a1db59a9ae6cfb6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling WebRTC # and V8 without interference from each other. @@ -58,11 +58,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'ad0a486b943316caef81084b10fbaa8be70a8956', + 'angle_revision': '2cb7b83595c2a88462b7f9481f920e2960556492', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. - 'buildtools_revision': '3b302fef93f7cc58d9b8168466905237484b2772', + 'buildtools_revision': '15308f469a704c45d15567fa69cd94ce07ad0e1b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -94,7 +94,7 @@ # 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': 'efe1c643770e76a1c4747e4c5bf9338e5a0ef945', + 'nacl_revision': '87d5dd90911a0657c27574f78e86b7dfc4ad8b29', } # Only these hosts are allowed for dependencies in this DEPS file. @@ -132,7 +132,7 @@ Var('chromium_git') + '/crashpad/crashpad.git' + '@' + '1baff4ff92fe1a1ead6b88b5f01633a4f0b6b51c', 'src/third_party/trace-viewer': - Var('chromium_git') + '/external/trace-viewer.git' + '@' + '98cca163de50a003a33712e1bc0b64a400bd3915', + Var('chromium_git') + '/external/trace-viewer.git' + '@' + 'eea44df50707a9c1667b4fe392e7c3998427b65c', 'src/third_party/WebKit': Var('chromium_git') + '/chromium/blink.git' + '@' + Var('webkit_revision'), @@ -210,7 +210,7 @@ Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + '104f872faf2cd809cdada885a1e39be85e5b3316', 'src/third_party/libjingle/source/talk': - Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + '58bf070857c078248d300f2c4bc7daabe0dd43ec', + Var('chromium_git') + '/external/webrtc/trunk/talk.git' + '@' + 'd8bca77284d02b80de15a5420c727a3e1385c542', # commit position 9081 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/usrsctplib.git' + '@' + '36444a999739e9e408f8f587cb4c3ffeef2e50ac', # from svn revision 9215 @@ -222,7 +222,7 @@ Var('chromium_git') + '/chromium/deps/yasm/patched-yasm.git' + '@' + '4671120cd8558ce62ee8672ebf3eb6f5216f909b', 'src/third_party/libjpeg_turbo': - Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '034e9a9747e0983bc19808ea70e469bc8342081f', + Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '9e9058be139a32f2d03eddce97fb15ecca92e6bc', 'src/third_party/flac': Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '0635a091379d9677f1ddde5f2eec85d0f096f219', @@ -234,7 +234,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' + '@' + '0f07171706abb5174bdf002eee928b4852fc6c22', + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '324d9727cd5cc1f2e3434e82cc9f9d83a486abab', # commit position 9084 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'), @@ -243,7 +243,7 @@ Var('chromium_git') + '/external/github.com/open-source-parsers/jsoncpp.git' + '@' + 'f572e8e42e22cfcf5ab0aea26574f408943edfa4', # from svn 248 'src/third_party/libyuv': - Var('chromium_git') + '/external/libyuv.git' + '@' + '32ad6e0e12fec058efdf85a5a4b32ed657f27c36', # from svn revision 1368 + Var('chromium_git') + '/external/libyuv.git' + '@' + '01db3d1d1ddd3f2907a46a41f24add5143b518d5', # from svn revision 1374 'src/third_party/smhasher/src': Var('chromium_git') + '/external/smhasher.git' + '@' + 'e87738e57558e0ec472b2fc3a643b838e5b6e88f', @@ -399,6 +399,9 @@ 'src/chrome/tools/test/reference_build/chrome_linux': Var('chromium_git') + '/chromium/reference_builds/chrome_linux64.git' + '@' + '033d053a528e820e1de3e2db766678d862a86b36', + 'src/third_party/junit/src': + Var('chromium_git') + '/external/junit.git' + '@' + '45a44647e7306262162e1346b750c3209019f2e1', + 'src/third_party/xdg-utils': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -410,11 +413,11 @@ # For Linux and Chromium OS. 'src/third_party/cros_system_api': - Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + 'beb554763c188ae8f0518de6d55661248c907218', + Var('chromium_git') + '/chromiumos/platform/system_api.git' + '@' + '42cdfaada2ae9183f6479531e24d739cc778c4a8', # Note that this is different from Android's freetype repo. 'src/third_party/freetype2/src': - Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + '495a23fce9cd125f715dc20643d14fed226d76ac', + Var('chromium_git') + '/chromium/src/third_party/freetype2.git' + '@' + '1dd5f5f4a909866f15c92a45c9702bce290a0151', # Build tools for Chrome OS. 'src/third_party/chromite': @@ -442,7 +445,7 @@ Var('chromium_git') + '/external/android_protobuf.git' + '@' + '94f522f907e3f34f70d9e7816b947e62fddbb267', 'src/third_party/android_tools': - Var('chromium_git') + '/android_tools.git' + '@' + 'bba2299128013f79b900983f405a65d9b6bdb2fa', + Var('chromium_git') + '/android_tools.git' + '@' + '7200281446186c7192cb02f54dc2b38e02d705e5', 'src/third_party/apache-mime4j': Var('chromium_git') + '/chromium/deps/apache-mime4j.git' + '@' + '28cb1108bff4b6cf0a2e86ff58b3d025934ebe3a', @@ -471,9 +474,6 @@ 'src/third_party/jsr-305/src': Var('chromium_git') + '/external/jsr-305.git' + '@' + '642c508235471f7220af6d5df2d3210e3bfc0919', - 'src/third_party/junit/src': - Var('chromium_git') + '/external/junit.git' + '@' + '45a44647e7306262162e1346b750c3209019f2e1', - 'src/third_party/mockito/src': Var('chromium_git') + '/external/mockito/mockito.git' + '@' + 'ed99a52e94a84bd7c467f2443b475a22fcc6ba8e', @@ -581,16 +581,14 @@ 'action': ['python', 'src/tools/clang/scripts/update.py', '--if-needed'], }, { - # Update LASTCHANGE. This is also run by export_tarball.py in - # src/tools/export_tarball - please keep them in sync. + # Update LASTCHANGE. 'name': 'lastchange', 'pattern': '.', 'action': ['python', 'src/build/util/lastchange.py', '-o', 'src/build/util/LASTCHANGE'], }, { - # Update LASTCHANGE.blink. This is also run by export_tarball.py in - # src/tools/export_tarball - please keep them in sync. + # Update LASTCHANGE.blink. 'name': 'lastchange', 'pattern': '.', 'action': ['python', 'src/build/util/lastchange.py',
diff --git a/WATCHLISTS b/WATCHLISTS index 7f26da13..8bc228b 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -886,7 +886,7 @@ 'browser_resources': ['arv+watch@chromium.org'], 'browsing_data': ['markusheintz@chromium.org'], 'bubble': ['alicet@chromium.org', 'msw+watch@chromium.org'], - 'cache_storage': ['jkarlin+watch@chromium.org'], + 'cache_storage': ['jkarlin+watch@chromium.org', 'nhiroki@chromium.org'], 'cast': ['avayvod+watch@chromium.org', 'hclam+watch@chromium.org', 'hguihot+watch@chromium.org',
diff --git a/android_webview/DEPS b/android_webview/DEPS index 319db9e..d45fa056 100644 --- a/android_webview/DEPS +++ b/android_webview/DEPS
@@ -19,5 +19,4 @@ "+ui/android", "+ui/base", "+ui/gfx", - "+webkit/common/gpu" ]
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp index 9fbaf73..d84660a 100644 --- a/android_webview/android_webview.gyp +++ b/android_webview/android_webview.gyp
@@ -176,8 +176,10 @@ '../gpu/blink/gpu_blink.gyp:gpu_blink', '../gpu/command_buffer/command_buffer.gyp:gles2_utils', '../gpu/gpu.gyp:command_buffer_service', - '../gpu/gpu.gyp:gles2_implementation', '../gpu/gpu.gyp:gl_in_process_context', + '../gpu/gpu.gyp:gles2_c_lib', + '../gpu/gpu.gyp:gles2_implementation', + '../gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings', '../media/media.gyp:media', '../printing/printing.gyp:printing', '../skia/skia.gyp:skia', @@ -185,7 +187,6 @@ '../ui/gl/gl.gyp:gl', '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs', '../v8/tools/gyp/v8.gyp:v8', - '../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu', 'android_webview_pak', 'android_webview_version', ], @@ -236,6 +237,8 @@ 'browser/aw_quota_manager_bridge.h', 'browser/aw_quota_permission_context.cc', 'browser/aw_quota_permission_context.h', + 'browser/aw_render_thread_context_provider.cc', + 'browser/aw_render_thread_context_provider.h', 'browser/aw_request_interceptor.cc', 'browser/aw_request_interceptor.h', 'browser/aw_resource_context.cc',
diff --git a/android_webview/android_webview_tests.gypi b/android_webview/android_webview_tests.gypi index 577cab4..9e4c3d0 100644 --- a/android_webview/android_webview_tests.gypi +++ b/android_webview/android_webview_tests.gypi
@@ -94,6 +94,8 @@ '../base/base.gyp:base_java_test_support', '../content/content_shell_and_tests.gyp:content_java_test_support', '../net/net.gyp:net_java_test_support', + '../testing/android/on_device_instrumentation.gyp:broker_java', + '../testing/android/on_device_instrumentation.gyp:require_driver_apk', 'android_webview_apk_java', ], 'variables': {
diff --git a/android_webview/browser/DEPS b/android_webview/browser/DEPS index e633368..ba8fe5b6 100644 --- a/android_webview/browser/DEPS +++ b/android_webview/browser/DEPS
@@ -29,8 +29,6 @@ "+ui/gfx", "+ui/gl", - "+webkit/gpu", - # Temporary until we bundle our own favicon. See # AwContentBrowserClient::GetDefaultFavicon "!ui/resources/grit/ui_resources.h",
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc index 1623736..e6587fc 100644 --- a/android_webview/browser/aw_browser_context.cc +++ b/android_webview/browser/aw_browser_context.cc
@@ -162,6 +162,7 @@ url_request_context_getter_->GetNetLog(), BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), + false /* enable */, false /* enable_quic */, GetUserAgent())); data_reduction_proxy_settings_.reset(
diff --git a/android_webview/browser/aw_render_thread_context_provider.cc b/android_webview/browser/aw_render_thread_context_provider.cc new file mode 100644 index 0000000..ce31148 --- /dev/null +++ b/android_webview/browser/aw_render_thread_context_provider.cc
@@ -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. + +#include "android_webview/browser/aw_render_thread_context_provider.h" + +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/lazy_instance.h" +#include "base/trace_event/trace_event.h" +#include "cc/output/managed_memory_policy.h" +#include "gpu/blink/webgraphicscontext3d_impl.h" +#include "gpu/command_buffer/client/gl_in_process_context.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h" +#include "third_party/skia/include/gpu/GrContext.h" +#include "third_party/skia/include/gpu/gl/GrGLInterface.h" + +namespace android_webview { + +namespace { + +// Singleton used to initialize and terminate the gles2 library. +class GLES2Initializer { + public: + GLES2Initializer() { gles2::Initialize(); } + + ~GLES2Initializer() { gles2::Terminate(); } + + private: + DISALLOW_COPY_AND_ASSIGN(GLES2Initializer); +}; + +base::LazyInstance<GLES2Initializer> g_gles2_initializer = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +// static +scoped_refptr<AwRenderThreadContextProvider> +AwRenderThreadContextProvider::Create( + scoped_refptr<gfx::GLSurface> surface, + scoped_refptr<gpu::InProcessCommandBuffer::Service> service) { + return new AwRenderThreadContextProvider(surface, service); +} + +AwRenderThreadContextProvider::AwRenderThreadContextProvider( + scoped_refptr<gfx::GLSurface> surface, + scoped_refptr<gpu::InProcessCommandBuffer::Service> service) + : destroyed_(false) { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + blink::WebGraphicsContext3D::Attributes attributes; + attributes.antialias = false; + attributes.depth = false; + attributes.stencil = false; + attributes.shareResources = true; + attributes.noAutomaticFlushes = true; + gpu::gles2::ContextCreationAttribHelper attribs_for_gles2; + gpu_blink::WebGraphicsContext3DImpl::ConvertAttributes(attributes, + &attribs_for_gles2); + attribs_for_gles2.lose_context_when_out_of_memory = true; + + context_.reset(gpu::GLInProcessContext::Create( + service, + surface, + surface->IsOffscreen(), + gfx::kNullAcceleratedWidget, + surface->GetSize(), + NULL /* share_context */, + false /* share_resources */, + attribs_for_gles2, + gfx::PreferDiscreteGpu, + gpu::GLInProcessContextSharedMemoryLimits(), + nullptr, + nullptr)); + + context_->SetContextLostCallback(base::Bind( + &AwRenderThreadContextProvider::OnLostContext, base::Unretained(this))); + + capabilities_.gpu = context_->GetImplementation()->capabilities(); +} + +AwRenderThreadContextProvider::~AwRenderThreadContextProvider() { + DCHECK(main_thread_checker_.CalledOnValidThread()); +} + +bool AwRenderThreadContextProvider::BindToCurrentThread() { + // This is called on the thread the context will be used. + DCHECK(main_thread_checker_.CalledOnValidThread()); + + return true; +} + +cc::ContextProvider::Capabilities +AwRenderThreadContextProvider::ContextCapabilities() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + return capabilities_; +} + +gpu::gles2::GLES2Interface* AwRenderThreadContextProvider::ContextGL() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + return context_->GetImplementation(); +} + +gpu::ContextSupport* AwRenderThreadContextProvider::ContextSupport() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + return context_->GetImplementation(); +} + +static void BindGrContextCallback(const GrGLInterface* interface) { + cc::ContextProvider* context_provider = + reinterpret_cast<AwRenderThreadContextProvider*>( + interface->fCallbackData); + + gles2::SetGLContext(context_provider->ContextGL()); +} + +class GrContext* AwRenderThreadContextProvider::GrContext() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + if (gr_context_) + return gr_context_.get(); + + // The GrGLInterface factory will make GL calls using the C GLES2 interface. + // Make sure the gles2 library is initialized first on exactly one thread. + g_gles2_initializer.Get(); + gles2::SetGLContext(ContextGL()); + + skia::RefPtr<GrGLInterface> interface = + skia::AdoptRef(skia_bindings::CreateCommandBufferSkiaGLBinding()); + interface->fCallback = BindGrContextCallback; + interface->fCallbackData = reinterpret_cast<GrGLInterfaceCallbackData>(this); + + gr_context_ = skia::AdoptRef(GrContext::Create( + kOpenGL_GrBackend, reinterpret_cast<GrBackendContext>(interface.get()))); + + return gr_context_.get(); +} + +void AwRenderThreadContextProvider::SetupLock() { + context_->SetLock(&context_lock_); +} + +base::Lock* AwRenderThreadContextProvider::GetLock() { + return &context_lock_; +} + +bool AwRenderThreadContextProvider::IsContextLost() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + return destroyed_; +} + +void AwRenderThreadContextProvider::VerifyContexts() { +} + +void AwRenderThreadContextProvider::DeleteCachedResources() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + if (gr_context_) { + TRACE_EVENT_INSTANT0("gpu", "GrContext::freeGpuResources", + TRACE_EVENT_SCOPE_THREAD); + gr_context_->freeGpuResources(); + } +} + +bool AwRenderThreadContextProvider::DestroyedOnMainThread() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + return destroyed_; +} + +void AwRenderThreadContextProvider::SetLostContextCallback( + const LostContextCallback& lost_context_callback) { + lost_context_callback_ = lost_context_callback; +} + +void AwRenderThreadContextProvider::SetMemoryPolicyChangedCallback( + const MemoryPolicyChangedCallback& memory_policy_changed_callback) { + // There's no memory manager for the in-process implementation. +} + +void AwRenderThreadContextProvider::OnLostContext() { + DCHECK(main_thread_checker_.CalledOnValidThread()); + + if (destroyed_) + return; + destroyed_ = true; + + if (!lost_context_callback_.is_null()) + base::ResetAndReturn(&lost_context_callback_).Run(); + if (gr_context_) + gr_context_->abandonContext(); +} + +} // namespace android_webview
diff --git a/android_webview/browser/aw_render_thread_context_provider.h b/android_webview/browser/aw_render_thread_context_provider.h new file mode 100644 index 0000000..bb94e655 --- /dev/null +++ b/android_webview/browser/aw_render_thread_context_provider.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 ANDROID_WEBVIEW_BROWSER_AW_RENDER_THREAD_CONTEXT_PROVIDER_H_ +#define ANDROID_WEBVIEW_BROWSER_AW_RENDER_THREAD_CONTEXT_PROVIDER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" +#include "cc/output/context_provider.h" +#include "gpu/command_buffer/service/in_process_command_buffer.h" +#include "skia/ext/refptr.h" + +namespace gfx { +class GLSurface; +} + +namespace gpu { +class GLInProcessContext; +} + +namespace android_webview { + +class AwRenderThreadContextProvider : public cc::ContextProvider { + public: + static scoped_refptr<AwRenderThreadContextProvider> Create( + scoped_refptr<gfx::GLSurface> surface, + scoped_refptr<gpu::InProcessCommandBuffer::Service> service); + + private: + AwRenderThreadContextProvider( + scoped_refptr<gfx::GLSurface> surface, + scoped_refptr<gpu::InProcessCommandBuffer::Service> service); + ~AwRenderThreadContextProvider() override; + + // cc::ContextProvider: + bool BindToCurrentThread() override; + Capabilities ContextCapabilities() override; + gpu::gles2::GLES2Interface* ContextGL() override; + gpu::ContextSupport* ContextSupport() override; + class GrContext* GrContext() override; + void SetupLock() override; + base::Lock* GetLock() override; + bool IsContextLost() override; + void VerifyContexts() override; + void DeleteCachedResources() override; + bool DestroyedOnMainThread() override; + void SetLostContextCallback( + const LostContextCallback& lost_context_callback) override; + void SetMemoryPolicyChangedCallback( + const MemoryPolicyChangedCallback& memory_policy_changed_callback) + override; + + void OnLostContext(); + + base::ThreadChecker main_thread_checker_; + + scoped_ptr<gpu::GLInProcessContext> context_; + skia::RefPtr<class GrContext> gr_context_; + + cc::ContextProvider::Capabilities capabilities_; + + LostContextCallback lost_context_callback_; + + bool destroyed_; + + base::Lock context_lock_; + + DISALLOW_COPY_AND_ASSIGN(AwRenderThreadContextProvider); +}; + +} // namespace android_webview + +#endif // ANDROID_WEBVIEW_BROWSER_AW_RENDER_THREAD_CONTEXT_PROVIDER_H_
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc index fc5f4d69..4eed043 100644 --- a/android_webview/browser/hardware_renderer.cc +++ b/android_webview/browser/hardware_renderer.cc
@@ -5,6 +5,7 @@ #include "android_webview/browser/hardware_renderer.h" #include "android_webview/browser/aw_gl_surface.h" +#include "android_webview/browser/aw_render_thread_context_provider.h" #include "android_webview/browser/child_frame.h" #include "android_webview/browser/deferred_gpu_command_service.h" #include "android_webview/browser/parent_compositor_draw_constraints.h" @@ -22,7 +23,6 @@ #include "cc/scheduler/begin_frame_source.h" #include "cc/trees/layer_tree_host.h" #include "cc/trees/layer_tree_settings.h" -#include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h" #include "gpu/command_buffer/client/gl_in_process_context.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "ui/gfx/frame_time.h" @@ -30,54 +30,9 @@ #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/transform.h" #include "ui/gl/gl_bindings.h" -#include "webkit/common/gpu/context_provider_in_process.h" namespace android_webview { -namespace { - -using gpu_blink::WebGraphicsContext3DImpl; -using gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl; - -scoped_refptr<cc::ContextProvider> CreateContext( - scoped_refptr<gfx::GLSurface> surface, - scoped_refptr<gpu::InProcessCommandBuffer::Service> service) { - const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu; - - blink::WebGraphicsContext3D::Attributes attributes; - attributes.antialias = false; - attributes.depth = false; - attributes.stencil = false; - attributes.shareResources = true; - attributes.noAutomaticFlushes = true; - gpu::gles2::ContextCreationAttribHelper attribs_for_gles2; - WebGraphicsContext3DImpl::ConvertAttributes( - attributes, &attribs_for_gles2); - attribs_for_gles2.lose_context_when_out_of_memory = true; - - scoped_ptr<gpu::GLInProcessContext> context(gpu::GLInProcessContext::Create( - service, - surface, - surface->IsOffscreen(), - gfx::kNullAcceleratedWidget, - surface->GetSize(), - NULL /* share_context */, - false /* share_resources */, - attribs_for_gles2, - gpu_preference, - gpu::GLInProcessContextSharedMemoryLimits(), - nullptr, - nullptr)); - DCHECK(context.get()); - - return webkit::gpu::ContextProviderInProcess::Create( - WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext( - context.Pass(), attributes), - "Parent-Compositor"); -} - -} // namespace - HardwareRenderer::HardwareRenderer(SharedRendererState* state) : shared_renderer_state_(state), last_egl_context_(eglGetCurrentContext()), @@ -240,8 +195,8 @@ void HardwareRenderer::RequestNewOutputSurface() { scoped_refptr<cc::ContextProvider> context_provider = - CreateContext(gl_surface_, - DeferredGpuCommandService::GetInstance()); + AwRenderThreadContextProvider::Create( + gl_surface_, DeferredGpuCommandService::GetInstance()); scoped_ptr<ParentOutputSurface> output_surface_holder( new ParentOutputSurface(context_provider)); output_surface_ = output_surface_holder.get();
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index b7603afd..4a97cab3 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -759,7 +759,7 @@ * Called when the app has requested to exit fullscreen. */ void requestExitFullscreen() { - mContentViewCore.getWebContents().exitFullscreen(); + if (!isDestroyed()) mContentViewCore.getWebContents().exitFullscreen(); } /** @@ -871,11 +871,9 @@ WebContents webContents = nativeGetWebContents(mNativeAwContents); - // WebView does not currently initialize ApplicationStatus, crbug.com/470582. - final boolean listenToActivityState = false; Activity activity = ContentViewCore.activityFromContext(mContext); mWindowAndroid = activity != null - ? new ActivityWindowAndroid(activity, listenToActivityState) + ? new ActivityWindowAndroid(activity) : new WindowAndroid(mContext.getApplicationContext()); mContentViewCore = createAndInitializeContentViewCore( mContainerView, mContext, mInternalAccessAdapter, webContents, @@ -2628,6 +2626,13 @@ }); } + protected void insertVisualStateCallbackIfNotDestroyed( + long requestId, VisualStateCallback callback) { + if (TRACE) Log.d(TAG, "insertVisualStateCallbackIfNotDestroyed"); + if (isDestroyed()) return; + nativeInsertVisualStateCallback(mNativeAwContents, requestId, callback); + } + // -------------------------------------------------------------------------------------------- // This is the AwViewMethods implementation that does real work. The AwViewMethodsImpl is // hooked up to the WebView in embedded mode and to the FullScreenView in fullscreen mode,
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java index 675f5b1..e8aebde 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java +++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java
@@ -7,6 +7,7 @@ import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.Context; +import android.media.AudioManager; import android.net.Uri; import android.os.AsyncTask; import android.os.Handler; @@ -78,9 +79,38 @@ } if (direction != 0 && tryToMoveFocus(direction)) return; } + handleMediaKey(event); mContentsClient.onUnhandledKeyEvent(event); } + /** + * Redispatches unhandled media keys. This allows bluetooth headphones with play/pause or + * other buttons to function correctly. + */ + private void handleMediaKey(KeyEvent e) { + switch (e.getKeyCode()) { + case KeyEvent.KEYCODE_MUTE: + case KeyEvent.KEYCODE_HEADSETHOOK: + case KeyEvent.KEYCODE_MEDIA_PLAY: + case KeyEvent.KEYCODE_MEDIA_PAUSE: + case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: + case KeyEvent.KEYCODE_MEDIA_STOP: + case KeyEvent.KEYCODE_MEDIA_NEXT: + case KeyEvent.KEYCODE_MEDIA_PREVIOUS: + case KeyEvent.KEYCODE_MEDIA_REWIND: + case KeyEvent.KEYCODE_MEDIA_RECORD: + case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: + case KeyEvent.KEYCODE_MEDIA_CLOSE: + case KeyEvent.KEYCODE_MEDIA_EJECT: + case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: + AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + am.dispatchMediaKeyEvent(e); + break; + default: + break; + } + } + @SuppressLint("NewApi") // View#getLayoutDirection requires API level 17. @Override public boolean takeFocus(boolean reverse) {
diff --git a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java index de5dfb13..ec722f6 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java +++ b/android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java
@@ -68,14 +68,15 @@ public void run() { AwContents awContents = mAwContents.get(); if (awContents != null) { - awContents.insertVisualStateCallback(0, new VisualStateCallback() { - @Override - public void onComplete(long requestId) { - AwContentsClient client = mAwContentsClient.get(); - if (client == null) return; - client.onPageCommitVisible(url); - } - }); + awContents.insertVisualStateCallbackIfNotDestroyed( + 0, new VisualStateCallback() { + @Override + public void onComplete(long requestId) { + AwContentsClient client = mAwContentsClient.get(); + if (client == null) return; + client.onPageCommitVisible(url); + } + }); } } });
diff --git a/android_webview/javatests/AndroidManifest.xml b/android_webview/javatests/AndroidManifest.xml index 63e5e0b8..32cc216 100644 --- a/android_webview/javatests/AndroidManifest.xml +++ b/android_webview/javatests/AndroidManifest.xml
@@ -7,7 +7,7 @@ <!-- TODO(boliu): Change minSdkVersion to 19 when bots no longer try to install webview apks on < K devices. crbug.com/474374 --> <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" /> - <instrumentation android:name="android.test.InstrumentationTestRunner" + <instrumentation android:name="org.chromium.base.test.BaseInstrumentationTestRunner" android:targetPackage="org.chromium.android_webview.shell" android:label="Tests for org.chromium.android_webview"/> <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" /> @@ -19,5 +19,7 @@ needed when building test cases. --> <application android:hardwareAccelerated="false"> <uses-library android:name="android.test.runner" /> + <activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker" + android:exported="true"/> </application> </manifest>
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 076df1e..5a6dba78 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc
@@ -295,7 +295,8 @@ const DisplayInfo& display_info = Shell::GetInstance()->display_manager()->GetDisplayInfo(display.id()); ash::ScreenRotationAnimator(display.id()) - .Rotate(GetNextRotation(display_info.rotation())); + .Rotate(GetNextRotation(display_info.GetActiveRotation()), + gfx::Display::ROTATION_SOURCE_USER); } // Rotate the active window.
diff --git a/ash/ash.gyp b/ash/ash.gyp index e0f39d5..14b2192 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp
@@ -80,12 +80,17 @@ 'display/display_pref_util.h', 'display/display_util.cc', 'display/display_util.h', + 'display/extended_mouse_warp_controller.cc', + 'display/extended_mouse_warp_controller.h', 'display/event_transformation_handler.cc', 'display/event_transformation_handler.h', 'display/mirror_window_controller.cc', 'display/mirror_window_controller.h', 'display/mouse_cursor_event_filter.cc', 'display/mouse_cursor_event_filter.h', + 'display/mouse_warp_controller.h', + 'display/null_mouse_warp_controller.cc', + 'display/null_mouse_warp_controller.h', 'display/projecting_observer_chromeos.cc', 'display/projecting_observer_chromeos.h', 'display/resolution_notification_controller.cc', @@ -143,6 +148,8 @@ 'host/ash_window_tree_host_init_params.cc', 'host/ash_window_tree_host_init_params.h', 'host/ash_window_tree_host_ozone.cc', + 'host/ash_window_tree_host_unified.cc', + 'host/ash_window_tree_host_unified.h', 'host/ash_window_tree_host_win.cc', 'host/ash_window_tree_host_x11.cc', 'host/ash_window_tree_host_x11.h', @@ -712,6 +719,8 @@ 'test/test_volume_control_delegate.h', 'test/ui_controls_factory_ash.cc', 'test/ui_controls_factory_ash.h', + 'test/user_metrics_recorder_test_api.cc', + 'test/user_metrics_recorder_test_api.h', 'test/virtual_keyboard_test_helper.cc', 'test/virtual_keyboard_test_helper.h', ], @@ -767,6 +776,7 @@ 'display/display_error_observer_chromeos_unittest.cc', 'display/display_info_unittest.cc', 'display/display_manager_unittest.cc', + 'display/extended_mouse_warp_controller_unittest.cc', 'display/mirror_window_controller_unittest.cc', 'display/mouse_cursor_event_filter_unittest.cc', 'display/projecting_observer_chromeos_unittest.cc', @@ -785,6 +795,7 @@ 'keyboard_overlay/keyboard_overlay_delegate_unittest.cc', 'keyboard_overlay/keyboard_overlay_view_unittest.cc', 'magnifier/magnification_controller_unittest.cc', + 'metrics/user_metrics_recorder_unittest.cc', 'popup_message_unittest.cc', 'root_window_controller_unittest.cc', 'screen_util_unittest.cc',
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc index 4ab34f8..7f052dcd 100644 --- a/ash/ash_switches.cc +++ b/ash/ash_switches.cc
@@ -5,6 +5,7 @@ #include "ash/ash_switches.h" #include "base/command_line.h" +#include "base/sys_info.h" namespace ash { namespace switches { @@ -17,9 +18,6 @@ const char kAshAnimateFromBootSplashScreen[] = "ash-animate-from-boot-splash-screen"; -// Constrains the pointer movement within a root window on desktop. -const char kAshConstrainPointerToRoot[] = "ash-constrain-pointer-to-root"; - // Copies the host window's content to the system background layer at startup. // Can make boot slightly slower, but also hides an even-longer awkward period // where we display a white background if the login wallpaper takes a long time @@ -56,6 +54,7 @@ // Enables key bindings to scroll magnified screen. const char kAshEnableMagnifierKeyScroller[] = "ash-enable-magnifier-key-scroller"; + #endif // Enables mirrored screen. @@ -122,5 +121,24 @@ #endif +#if defined(OS_CHROMEOS) +// Constrains the pointer movement within a root window on desktop. +bool ConstrainPointerToRoot() { + const char kAshConstrainPointerToRoot[] = "ash-constrain-pointer-to-root"; + + return base::SysInfo::IsRunningOnChromeOS() || + base::CommandLine::ForCurrentProcess()->HasSwitch( + kAshConstrainPointerToRoot); +} + +// Enables unified desktop mode. +bool UnifiedDesktopEnabled() { + const char kAshEnableUnifiedDesktop[] = "ash-enable-unified-desktop"; + return base::CommandLine::ForCurrentProcess()->HasSwitch( + kAshEnableUnifiedDesktop); +} + +#endif + } // namespace switches } // namespace ash
diff --git a/ash/ash_switches.h b/ash/ash_switches.h index 40aba02..171272fe 100644 --- a/ash/ash_switches.h +++ b/ash/ash_switches.h
@@ -18,7 +18,6 @@ // Please keep alphabetized. ASH_EXPORT extern const char kAshAnimateFromBootSplashScreen[]; -ASH_EXPORT extern const char kAshConstrainPointerToRoot[]; ASH_EXPORT extern const char kAshCopyHostBackgroundAtBoot[]; ASH_EXPORT extern const char kAshDebugShortcuts[]; ASH_EXPORT extern const char kAshDisableLockLayoutManager[]; @@ -47,6 +46,13 @@ ASH_EXPORT extern const char kForceAshToDesktop[]; #endif +#if defined(OS_CHROMEOS) +// True if the pointer (cursor) position should be kept inside root windows. +ASH_EXPORT bool ConstrainPointerToRoot(); + +ASH_EXPORT bool UnifiedDesktopEnabled(); +#endif + } // namespace switches } // namespace ash
diff --git a/ash/content/display/screen_orientation_controller_chromeos.cc b/ash/content/display/screen_orientation_controller_chromeos.cc index ac15726..eee0ae6 100644 --- a/ash/content/display/screen_orientation_controller_chromeos.cc +++ b/ash/content/display/screen_orientation_controller_chromeos.cc
@@ -44,7 +44,7 @@ ash::Shell::GetInstance()->display_manager()->GetDisplayInfo( gfx::Display::InternalDisplayId()); gfx::Size size = info.size_in_pixel(); - switch (info.rotation()) { + switch (info.GetActiveRotation()) { case gfx::Display::ROTATE_0: case gfx::Display::ROTATE_180: return size.height() >= size.width() @@ -110,14 +110,24 @@ } void ScreenOrientationController::SetDisplayRotation( - gfx::Display::Rotation rotation) { + gfx::Display::Rotation rotation, + gfx::Display::RotationSource source) { if (!gfx::Display::HasInternalDisplay()) return; current_rotation_ = rotation; base::AutoReset<bool> auto_ignore_display_configuration_updates( &ignore_display_configuration_updates_, true); - ash::ScreenRotationAnimator(gfx::Display::InternalDisplayId()) - .Rotate(rotation); + + ash::ScreenRotationAnimator screen_rotation_animator( + gfx::Display::InternalDisplayId()); + if (screen_rotation_animator.CanAnimate()) { + screen_rotation_animator.Rotate(rotation, source); + } else { + // TODO(bruthig): Fix the DisplayManager so that display rotations set on + // inactive displays are persisted. See www.crbug.com/480703. + Shell::GetInstance()->display_manager()->SetDisplayRotation( + gfx::Display::InternalDisplayId(), rotation, source); + } } void ScreenOrientationController::OnWindowActivated(aura::Window* gained_active, @@ -198,7 +208,7 @@ DisplayManager* display_manager = Shell::GetInstance()->display_manager(); gfx::Display::Rotation user_rotation = display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId()) - .rotation(); + .GetActiveRotation(); if (user_rotation != current_rotation_) { // A user may change other display configuration settings. When the user // does change the rotation setting, then lock rotation to prevent the @@ -217,7 +227,7 @@ Shell::GetInstance() ->display_manager() ->GetDisplayInfo(gfx::Display::InternalDisplayId()) - .rotation(); + .GetActiveRotation(); } if (!rotation_locked_) LoadDisplayRotationProperties(); @@ -229,13 +239,14 @@ chromeos::AccelerometerReader::GetInstance()->RemoveObserver(this); Shell::GetInstance()->display_controller()->RemoveObserver(this); if (current_rotation_ != user_rotation_) - SetDisplayRotation(user_rotation_); + SetDisplayRotation(user_rotation_, gfx::Display::ROTATION_SOURCE_USER); } void ScreenOrientationController::LockRotation( - gfx::Display::Rotation rotation) { + gfx::Display::Rotation rotation, + gfx::Display::RotationSource source) { SetRotationLocked(true); - SetDisplayRotation(rotation); + SetDisplayRotation(rotation, source); } void ScreenOrientationController::LockRotationToOrientation( @@ -268,7 +279,8 @@ blink::WebScreenOrientationLockLandscape); break; case blink::WebScreenOrientationLockNatural: - LockRotation(gfx::Display::ROTATE_0); + LockRotation(gfx::Display::ROTATE_0, + gfx::Display::ROTATION_SOURCE_ACTIVE); break; default: NOTREACHED(); @@ -280,14 +292,16 @@ blink::WebScreenOrientationLockType lock_orientation) { LockRotation(natural_orientation_ == lock_orientation ? gfx::Display::ROTATE_0 - : gfx::Display::ROTATE_90); + : gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_ACTIVE); } void ScreenOrientationController::LockRotationToSecondaryOrientation( blink::WebScreenOrientationLockType lock_orientation) { LockRotation(natural_orientation_ == lock_orientation ? gfx::Display::ROTATE_180 - : gfx::Display::ROTATE_270); + : gfx::Display::ROTATE_270, + gfx::Display::ROTATION_SOURCE_ACTIVE); } void ScreenOrientationController::LockToRotationMatchingOrientation( @@ -298,20 +312,22 @@ DisplayManager* display_manager = Shell::GetInstance()->display_manager(); gfx::Display::Rotation rotation = display_manager->GetDisplayInfo(gfx::Display::InternalDisplayId()) - .rotation(); + .GetActiveRotation(); if (natural_orientation_ == lock_orientation) { if (rotation == gfx::Display::ROTATE_0 || rotation == gfx::Display::ROTATE_180) { SetRotationLocked(true); } else { - LockRotation(gfx::Display::ROTATE_0); + LockRotation(gfx::Display::ROTATE_0, + gfx::Display::ROTATION_SOURCE_ACTIVE); } } else { if (rotation == gfx::Display::ROTATE_90 || rotation == gfx::Display::ROTATE_270) { SetRotationLocked(true); } else { - LockRotation(gfx::Display::ROTATE_90); + LockRotation(gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_ACTIVE); } } } @@ -363,14 +379,16 @@ if (new_rotation != current_rotation_ && IsRotationAllowedInLockedState(new_rotation)) - SetDisplayRotation(new_rotation); + SetDisplayRotation(new_rotation, + gfx::Display::ROTATION_SOURCE_ACCELEROMETER); } void ScreenOrientationController::LoadDisplayRotationProperties() { DisplayManager* display_manager = Shell::GetInstance()->display_manager(); if (!display_manager->registered_internal_display_rotation_lock()) return; - SetDisplayRotation(display_manager->registered_internal_display_rotation()); + SetDisplayRotation(display_manager->registered_internal_display_rotation(), + gfx::Display::ROTATION_SOURCE_ACCELEROMETER); SetRotationLocked(true); }
diff --git a/ash/content/display/screen_orientation_controller_chromeos.h b/ash/content/display/screen_orientation_controller_chromeos.h index aa45734..0a84b8cd 100644 --- a/ash/content/display/screen_orientation_controller_chromeos.h +++ b/ash/content/display/screen_orientation_controller_chromeos.h
@@ -69,8 +69,11 @@ // display rotation. void SetRotationLocked(bool rotation_locked); - // Sets the display rotation and suppresses display notifications. - void SetDisplayRotation(gfx::Display::Rotation rotation); + // Sets the display rotation for the given |source|. The new |rotation| will + // also become active. Display changed notifications are surpressed for this + // change. + void SetDisplayRotation(gfx::Display::Rotation rotation, + gfx::Display::RotationSource source); // aura::client::ActivationChangeObserver: void OnWindowActivated(aura::Window* gained_active, @@ -102,7 +105,8 @@ // Sets the display rotation to |rotation|. Future accelerometer updates // should not be used to change the rotation. SetRotationLocked(false) removes // the rotation lock. - void LockRotation(gfx::Display::Rotation rotation); + void LockRotation(gfx::Display::Rotation rotation, + gfx::Display::RotationSource source); // Sets the display rotation based on |lock_orientation|. Future accelerometer // updates should not be used to change the rotation. SetRotationLocked(false)
diff --git a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc index 342e958..487d44c 100644 --- a/ash/content/display/screen_orientation_controller_chromeos_unittest.cc +++ b/ash/content/display/screen_orientation_controller_chromeos_unittest.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <vector> + #include "ash/ash_switches.h" #include "ash/content/display/screen_orientation_controller_chromeos.h" #include "ash/display/display_info.h" @@ -9,6 +11,7 @@ #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/test/ash_test_helper.h" +#include "ash/test/display_manager_test_api.h" #include "ash/test/test_shell_delegate.h" #include "ash/test/test_system_tray_delegate.h" #include "ash/wm/maximize_mode/maximize_mode_controller.h" @@ -35,26 +38,18 @@ const float kDegreesToRadians = 3.1415926f / 180.0f; const float kMeanGravity = 9.8066f; +DisplayInfo CreateDisplayInfo(int64 id, const gfx::Rect& bounds) { + DisplayInfo info(id, "dummy", false); + info.SetBounds(bounds); + return info; +} + void EnableMaximizeMode(bool enable) { Shell::GetInstance() ->maximize_mode_controller() ->EnableMaximizeModeWindowManager(enable); } -gfx::Display::Rotation GetInternalDisplayRotation() { - return Shell::GetInstance() - ->display_manager() - ->GetDisplayInfo(gfx::Display::InternalDisplayId()) - .rotation(); -} - -gfx::Display::Rotation Rotation() { - return Shell::GetInstance() - ->display_manager() - ->GetDisplayInfo(gfx::Display::InternalDisplayId()) - .rotation(); -} - bool RotationLocked() { return Shell::GetInstance() ->screen_orientation_controller() @@ -63,7 +58,8 @@ void SetInternalDisplayRotation(gfx::Display::Rotation rotation) { Shell::GetInstance()->display_manager()->SetDisplayRotation( - gfx::Display::InternalDisplayId(), rotation); + gfx::Display::InternalDisplayId(), rotation, + gfx::Display::ROTATION_SOURCE_USER); } void SetRotationLocked(bool rotation_locked) { @@ -166,12 +162,12 @@ scoped_ptr<content::WebContents> content(CreateWebContents()); scoped_ptr<aura::Window> focus_window(CreateTestWindowInShellWithId(0)); ASSERT_NE(nullptr, content->GetNativeView()); - ASSERT_EQ(gfx::Display::ROTATE_0, Rotation()); + ASSERT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); ASSERT_FALSE(RotationLocked()); AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); - EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); EXPECT_TRUE(RotationLocked()); } @@ -180,12 +176,12 @@ scoped_ptr<content::WebContents> content(CreateWebContents()); scoped_ptr<aura::Window> focus_window(CreateTestWindowInShellWithId(0)); ASSERT_NE(nullptr, content->GetNativeView()); - ASSERT_EQ(gfx::Display::ROTATE_0, Rotation()); + ASSERT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); ASSERT_FALSE(RotationLocked()); AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); - EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); EXPECT_TRUE(RotationLocked()); delegate()->Unlock(content.get()); @@ -198,16 +194,16 @@ scoped_ptr<content::WebContents> content(CreateWebContents()); scoped_ptr<aura::Window> focus_window(CreateTestWindowInShellWithId(0)); ASSERT_NE(nullptr, content->GetNativeView()); - ASSERT_EQ(gfx::Display::ROTATE_0, Rotation()); + ASSERT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); ASSERT_FALSE(RotationLocked()); AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockPortrait); - EXPECT_EQ(gfx::Display::ROTATE_90, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); EXPECT_TRUE(RotationLocked()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); - EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); } // Tests that orientation can only be set by the first content::WebContents that @@ -223,7 +219,7 @@ AttachWebContents(content2.get(), focus_window2.get()); delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape); delegate()->Lock(content2.get(), blink::WebScreenOrientationLockPortrait); - EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); } // Tests that only the content::WebContents that set a rotation lock can perform @@ -274,17 +270,17 @@ delegate()->Lock(content1.get(), blink::WebScreenOrientationLockLandscape); delegate()->Lock(content2.get(), blink::WebScreenOrientationLockPortrait); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); aura::client::ActivationClient* activation_client = Shell::GetInstance()->activation_client(); activation_client->ActivateWindow(focus_window2.get()); EXPECT_TRUE(RotationLocked()); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); activation_client->ActivateWindow(focus_window1.get()); EXPECT_TRUE(RotationLocked()); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); } // Tests that a rotation lock is removed when the setting window is hidden, and @@ -334,13 +330,13 @@ EnableMaximizeMode(true); // Now test rotating in all directions. TriggerLidUpdate(gfx::Vector3dF(-kMeanGravity, 0.0f, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_180, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_270, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); } // Tests that low angles are ignored by the accelerometer (i.e. when the device @@ -348,15 +344,15 @@ TEST_F(ScreenOrientationControllerTest, RotationIgnoresLowAngles) { EnableMaximizeMode(true); TriggerLidUpdate(gfx::Vector3dF(0.0f, -kMeanGravity, -kMeanGravity)); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(-2.0f, 0.0f, -kMeanGravity)); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(0.0f, 2.0f, -kMeanGravity)); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(2.0f, 0.0f, -kMeanGravity)); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(0.0f, -2.0f, -kMeanGravity)); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); } // Tests that the display will stick to the current orientation beyond the @@ -365,7 +361,7 @@ EnableMaximizeMode(true); gfx::Vector3dF gravity(0.0f, -kMeanGravity, 0.0f); TriggerLidUpdate(gravity); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); // Turn past half-way point to next direction and rotation should remain // the same. @@ -373,14 +369,14 @@ gravity.set_x(-sin(degrees * kDegreesToRadians) * kMeanGravity); gravity.set_y(-cos(degrees * kDegreesToRadians) * kMeanGravity); TriggerLidUpdate(gravity); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); // Turn more and the screen should rotate. degrees = 70.0; gravity.set_x(-sin(degrees * kDegreesToRadians) * kMeanGravity); gravity.set_y(-cos(degrees * kDegreesToRadians) * kMeanGravity); TriggerLidUpdate(gravity); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); // Turn back just beyond the half-way point and the new rotation should // still be in effect. @@ -388,7 +384,7 @@ gravity.set_x(-sin(degrees * kDegreesToRadians) * kMeanGravity); gravity.set_y(-cos(degrees * kDegreesToRadians) * kMeanGravity); TriggerLidUpdate(gravity); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); } // Tests that the display will stick to its current orientation when the @@ -403,11 +399,11 @@ -cos(degrees * kDegreesToRadians) * kMeanGravity, 0.0f); TriggerLidUpdate(gravity); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); SetRotationLocked(false); TriggerLidUpdate(gravity); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); } // The TrayDisplay class that is responsible for adding/updating MessageCenter @@ -429,10 +425,10 @@ // Make sure notifications are still displayed when // adjusting the screen rotation directly when in maximize mode - ASSERT_NE(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); + ASSERT_NE(gfx::Display::ROTATE_270, GetCurrentInternalDisplayRotation()); SetInternalDisplayRotation(gfx::Display::ROTATE_270); SetRotationLocked(false); - EXPECT_EQ(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_270, GetCurrentInternalDisplayRotation()); EXPECT_EQ(1u, message_center->NotificationCount()); EXPECT_TRUE(message_center->HasPopupNotifications()); @@ -444,9 +440,9 @@ // Make sure notifications are blocked when adjusting the screen rotation // via the accelerometer while in maximize mode // Rotate the screen 90 degrees - ASSERT_NE(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + ASSERT_NE(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(-kMeanGravity, 0.0f, 0.0f)); - ASSERT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + ASSERT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); EXPECT_EQ(0u, message_center->NotificationCount()); EXPECT_FALSE(message_center->HasPopupNotifications()); @@ -457,11 +453,11 @@ SetInternalDisplayRotation(gfx::Display::ROTATE_0); // Clear all notifications message_center->RemoveAllNotifications(false); - ASSERT_NE(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); + ASSERT_NE(gfx::Display::ROTATE_180, GetCurrentInternalDisplayRotation()); ASSERT_EQ(0u, message_center->NotificationCount()); ASSERT_FALSE(message_center->HasPopupNotifications()); SetInternalDisplayRotation(gfx::Display::ROTATE_180); - EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_180, GetCurrentInternalDisplayRotation()); EXPECT_EQ(1u, message_center->NotificationCount()); EXPECT_TRUE(message_center->HasPopupNotifications()); } @@ -473,10 +469,10 @@ EnableMaximizeMode(true); TriggerLidUpdate(gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_180, GetCurrentInternalDisplayRotation()); EnableMaximizeMode(false); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); } // Tests that if a user sets a display rotation that accelerometer rotation @@ -499,7 +495,7 @@ // maximize mode was activated. SetInternalDisplayRotation(gfx::Display::ROTATE_0); EnableMaximizeMode(false); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); } // Tests that when the orientation lock is set to Landscape, that rotation can @@ -511,18 +507,18 @@ AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockLandscape); - EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); EXPECT_TRUE(RotationLocked()); // Inverse of orientation is allowed TriggerLidUpdate(gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_180, GetCurrentInternalDisplayRotation()); // Display rotations between are not allowed TriggerLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_180, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(-kMeanGravity, 0.0f, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_180, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_180, GetCurrentInternalDisplayRotation()); } // Tests that when the orientation lock is set to Portrait, that rotaiton can be @@ -534,18 +530,18 @@ AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockPortrait); - EXPECT_EQ(gfx::Display::ROTATE_90, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); EXPECT_TRUE(RotationLocked()); // Inverse of orientation is allowed TriggerLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_270, GetCurrentInternalDisplayRotation()); // Display rotations between are not allowed TriggerLidUpdate(gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_270, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_270, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_270, GetCurrentInternalDisplayRotation()); } // Tests that for an orientation lock which does not allow rotation, that the @@ -558,16 +554,16 @@ AttachAndActivateWebContents(content.get(), focus_window.get()); delegate()->Lock(content.get(), blink::WebScreenOrientationLockPortraitPrimary); - EXPECT_EQ(gfx::Display::ROTATE_90, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); EXPECT_TRUE(RotationLocked()); // Rotation does not change. TriggerLidUpdate(gfx::Vector3dF(kMeanGravity, 0.0f, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(0.0f, -kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_90, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); } // Tests that after a content::WebContents has applied an orientation lock which @@ -583,10 +579,10 @@ SetRotationLocked(true); EXPECT_TRUE(RotationLocked()); - EXPECT_EQ(gfx::Display::ROTATE_0, Rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); TriggerLidUpdate(gfx::Vector3dF(0.0f, kMeanGravity, 0.0f)); - EXPECT_EQ(gfx::Display::ROTATE_0, GetInternalDisplayRotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, GetCurrentInternalDisplayRotation()); } // Tests that when MaximizeMode is triggered before the internal display is @@ -608,4 +604,48 @@ EXPECT_TRUE(RotationLocked()); } +// Verifies rotating an inactive Display is sucessful. +TEST_F(ScreenOrientationControllerTest, RotateInactiveDisplay) { + const int64 kInternalDisplayId = 9; + const int64 kExternalDisplayId = 10; + const gfx::Display::Rotation kNewRotation = gfx::Display::ROTATE_180; + + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + + const DisplayInfo internal_display_info = + CreateDisplayInfo(kInternalDisplayId, gfx::Rect(0, 0, 500, 500)); + const DisplayInfo external_display_info = + CreateDisplayInfo(kExternalDisplayId, gfx::Rect(1, 1, 500, 500)); + + std::vector<DisplayInfo> display_info_list_two_active; + display_info_list_two_active.push_back(internal_display_info); + display_info_list_two_active.push_back(external_display_info); + + std::vector<DisplayInfo> display_info_list_one_active; + display_info_list_one_active.push_back(external_display_info); + + // The DisplayInfo list with two active displays needs to be added first so + // that the DisplayManager can track the |internal_display_info| as inactive + // instead of non-existent. + ash::Shell::GetInstance()->display_manager()->UpdateDisplays( + display_info_list_two_active); + ash::Shell::GetInstance()->display_manager()->UpdateDisplays( + display_info_list_one_active); + + test::DisplayManagerTestApi(display_manager) + .SetInternalDisplayId(kInternalDisplayId); + + ASSERT_NE(kNewRotation, display_manager->GetDisplayInfo(kInternalDisplayId) + .GetActiveRotation()); + + delegate()->SetDisplayRotation(kNewRotation, + gfx::Display::ROTATION_SOURCE_ACTIVE); + + // TODO(bruthig): Uncomment when www.crbug.com/480703 is fixed. This test + // still adds value by ensuring a crash does not occur. See + // www.crbug.com/479503. + // ASSERT_EQ(kNewRotation, display_manager->GetDisplayInfo(kInternalDisplayId) + // .GetActiveRotation()); +} + } // namespace ash
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc index 0068e95c..2aa2fc6 100644 --- a/ash/display/display_controller.cc +++ b/ash/display/display_controller.cc
@@ -109,7 +109,7 @@ const char kInternalProp[] = "_CHROME_DISPLAY_INTERNAL"; const char kCARDINAL[] = "CARDINAL"; int xrandr_rotation = RR_Rotate_0; - switch (info.rotation()) { + switch (info.GetActiveRotation()) { case gfx::Display::ROTATE_0: xrandr_rotation = RR_Rotate_0; break; @@ -140,7 +140,7 @@ scale *= kCursorMultiplierForExternalDisplays; ui::CursorController::GetInstance()->SetCursorConfigForWindow( - host->GetAcceleratedWidget(), info.rotation(), scale); + host->GetAcceleratedWidget(), info.GetActiveRotation(), scale); #endif #endif scoped_ptr<RootWindowTransformer> transformer( @@ -160,8 +160,7 @@ host->compositor()->ScheduleFullRedraw(); } -void ClearDisplayPropertiesOnHost(AshWindowTreeHost* ash_host, - const gfx::Display& display) { +void ClearDisplayPropertiesOnHost(AshWindowTreeHost* ash_host) { #if defined(OS_CHROMEOS) && defined(USE_OZONE) aura::WindowTreeHost* host = ash_host->AsWindowTreeHost(); ui::CursorController::GetInstance()->ClearCursorConfigForWindow( @@ -181,12 +180,11 @@ class FocusActivationStore { public: FocusActivationStore() - : activation_client_(NULL), - capture_client_(NULL), - focus_client_(NULL), - focused_(NULL), - active_(NULL) { - } + : activation_client_(nullptr), + capture_client_(nullptr), + focus_client_(nullptr), + focused_(nullptr), + active_(nullptr) {} void Store(bool clear_focus) { if (!activation_client_) { @@ -207,13 +205,13 @@ activation_client_->DeactivateWindow(active_); // Release capture if any. - capture_client_->SetCapture(NULL); + capture_client_->SetCapture(nullptr); // Clear the focused window if any. This is necessary because a // window may be deleted when losing focus (fullscreen flash for // example). If the focused window is still alive after move, it'll // be re-focused below. if (clear_focus) - focus_client_->FocusWindow(NULL); + focus_client_->FocusWindow(nullptr); } void Restore() { @@ -227,8 +225,8 @@ tracker_.Remove(focused_); if (active_) tracker_.Remove(active_); - focused_ = NULL; - active_ = NULL; + focused_ = nullptr; + active_ = nullptr; } private: @@ -263,7 +261,7 @@ // DisplayController DisplayController::DisplayController() - : primary_tree_host_for_replace_(NULL), + : primary_tree_host_for_replace_(nullptr), focus_activation_store_(new FocusActivationStore()), cursor_window_controller_(new CursorWindowController()), mirror_window_controller_(new MirrorWindowController()), @@ -289,7 +287,7 @@ void DisplayController::Shutdown() { // Unset the display manager's delegate here because // DisplayManager outlives DisplayController. - Shell::GetInstance()->display_manager()->set_delegate(NULL); + Shell::GetInstance()->display_manager()->set_delegate(nullptr); cursor_window_controller_.reset(); mirror_window_controller_.reset(); @@ -302,7 +300,7 @@ // delete the primary root window controller. aura::Window::Windows root_windows = DisplayController::GetAllRootWindows(); std::vector<RootWindowController*> to_delete; - RootWindowController* primary_rwc = NULL; + RootWindowController* primary_rwc = nullptr; for (aura::Window::Windows::iterator iter = root_windows.begin(); iter != root_windows.end(); ++iter) { @@ -330,7 +328,6 @@ void DisplayController::InitDisplays() { RootWindowController::CreateForPrimaryDisplay( window_tree_hosts_[primary_display_id]); - DisplayManager* display_manager = GetDisplayManager(); for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { const gfx::Display& display = display_manager->GetDisplayAt(i); @@ -363,12 +360,17 @@ } aura::Window* DisplayController::GetRootWindowForDisplayId(int64 id) { - CHECK_EQ(1u, window_tree_hosts_.count(id)); - AshWindowTreeHost* host = window_tree_hosts_[id]; + AshWindowTreeHost* host = GetAshWindowTreeHostForDisplayId(id); CHECK(host); return GetWindow(host); } +AshWindowTreeHost* DisplayController::GetAshWindowTreeHostForDisplayId( + int64 id) { + CHECK_EQ(1u, window_tree_hosts_.count(id)); + return window_tree_hosts_[id]; +} + void DisplayController::CloseChildWindows() { for (WindowTreeHostMap::const_iterator it = window_tree_hosts_.begin(); it != window_tree_hosts_.end(); @@ -546,7 +548,7 @@ int64 closest_distance_squared = -1; DisplayManager* display_manager = GetDisplayManager(); - aura::Window* dst_root_window = NULL; + aura::Window* dst_root_window = nullptr; for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { const gfx::Display& display = display_manager->GetDisplayAt(i); const DisplayInfo display_info = @@ -629,13 +631,30 @@ } void DisplayController::OnDisplayAdded(const gfx::Display& display) { - if (primary_tree_host_for_replace_) { + if (GetDisplayManager()->IsInUnifiedMode()) { + if (primary_display_id == gfx::Display::kInvalidDisplayID) + primary_display_id = display.id(); + AshWindowTreeHost* ash_host = + AddWindowTreeHostForDisplay(display, AshWindowTreeHostInitParams()); + RootWindowController::CreateForSecondaryDisplay(ash_host); + + if (primary_tree_host_for_replace_) { + AshWindowTreeHost* to_delete = primary_tree_host_for_replace_; + primary_tree_host_for_replace_ = nullptr; + DeleteHost(to_delete); + // the host has already been removed from the window_tree_host_. + } + } + // TODO(oshima): It should be possible to consolidate logic for + // unified and non unified, but I'm keeping them separated to minimize + // the risk in M44. I'll consolidate this in M45. + else if (primary_tree_host_for_replace_) { DCHECK(window_tree_hosts_.empty()); primary_display_id = display.id(); window_tree_hosts_[display.id()] = primary_tree_host_for_replace_; GetRootWindowSettings(GetWindow(primary_tree_host_for_replace_)) ->display_id = display.id(); - primary_tree_host_for_replace_ = NULL; + primary_tree_host_for_replace_ = nullptr; const DisplayInfo& display_info = GetDisplayManager()->GetDisplayInfo(display.id()); AshWindowTreeHost* ash_host = window_tree_hosts_[display.id()]; @@ -645,12 +664,24 @@ if (primary_display_id == gfx::Display::kInvalidDisplayID) primary_display_id = display.id(); DCHECK(!window_tree_hosts_.empty()); - AshWindowTreeHost* ash_host = AddWindowTreeHostForDisplay( - display, AshWindowTreeHostInitParams()); + AshWindowTreeHost* ash_host = + AddWindowTreeHostForDisplay(display, AshWindowTreeHostInitParams()); RootWindowController::CreateForSecondaryDisplay(ash_host); } } +void DisplayController::DeleteHost(AshWindowTreeHost* host_to_delete) { + ClearDisplayPropertiesOnHost(host_to_delete); + RootWindowController* controller = + GetRootWindowController(GetWindow(host_to_delete)); + DCHECK(controller); + controller->MoveWindowsTo(GetPrimaryRootWindow()); + // Delete most of root window related objects, but don't delete + // root window itself yet because the stack may be using it. + controller->Shutdown(); + base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller); +} + void DisplayController::OnDisplayRemoved(const gfx::Display& display) { AshWindowTreeHost* host_to_delete = window_tree_hosts_[display.id()]; CHECK(host_to_delete) << display.ToString(); @@ -690,15 +721,8 @@ GetDisplayManager()->GetDisplayForId(primary_display_id), DISPLAY_METRIC_BOUNDS); } - ClearDisplayPropertiesOnHost(host_to_delete, display); - RootWindowController* controller = - GetRootWindowController(GetWindow(host_to_delete)); - DCHECK(controller); - controller->MoveWindowsTo(GetPrimaryRootWindow()); - // Delete most of root window related objects, but don't delete - // root window itself yet because the stack may be using it. - controller->Shutdown(); - base::MessageLoop::current()->DeleteSoon(FROM_HERE, controller); + + DeleteHost(host_to_delete); // The window tree host should be erased at last because some handlers can // access to the host through GetRootWindowForDisplayId() during @@ -731,10 +755,11 @@ } void DisplayController::CreateOrUpdateMirroringDisplay( - const DisplayInfo& info) { - switch (GetDisplayManager()->second_display_mode()) { + const DisplayInfoList& info_list) { + switch (GetDisplayManager()->multi_display_mode()) { case DisplayManager::MIRRORING: - mirror_window_controller_->UpdateWindow(info); + case DisplayManager::UNIFIED: + mirror_window_controller_->UpdateWindow(info_list); cursor_window_controller_->UpdateContainer(); break; case DisplayManager::EXTENDED: @@ -780,9 +805,9 @@ if (display_manager->num_connected_displays() > 1) { DisplayIdPair pair = display_manager->GetCurrentDisplayIdPair(); layout_store->UpdateMirrorStatus(pair, display_manager->IsInMirrorMode()); - DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair); if (Shell::GetScreen()->GetNumDisplays() > 1 ) { + DisplayLayout layout = layout_store->GetRegisteredDisplayLayout(pair); int64 primary_id = layout.primary_id; SetPrimaryDisplayId( primary_id == gfx::Display::kInvalidDisplayID ? @@ -807,10 +832,14 @@ GetDisplayManager()->GetDisplayInfo(display.id()); AshWindowTreeHostInitParams params_with_bounds(init_params); params_with_bounds.initial_bounds = display_info.bounds_in_native(); + params_with_bounds.offscreen = + display.id() == DisplayManager::kUnifiedDisplayId; AshWindowTreeHost* ash_host = AshWindowTreeHost::Create(params_with_bounds); aura::WindowTreeHost* host = ash_host->AsWindowTreeHost(); - host->window()->SetName(base::StringPrintf("RootWindow-%d", host_count++)); + host->window()->SetName(base::StringPrintf( + "%sRootWindow-%d", params_with_bounds.offscreen ? "Offscreen" : "", + host_count++)); host->window()->SetTitle(base::UTF8ToUTF16(display_info.name())); host->compositor()->SetBackgroundColor(SK_ColorBLACK); // No need to remove our observer observer because the DisplayController @@ -823,10 +852,7 @@ SetDisplayPropertiesOnHost(ash_host, display); #if defined(OS_CHROMEOS) - static bool force_constrain_pointer_to_root = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshConstrainPointerToRoot); - if (base::SysInfo::IsRunningOnChromeOS() || force_constrain_pointer_to_root) + if (switches::ConstrainPointerToRoot()) ash_host->ConfineCursorToRootWindow(); #endif return ash_host;
diff --git a/ash/display/display_controller.h b/ash/display/display_controller.h index 3dc8189..a46b8d1 100644 --- a/ash/display/display_controller.h +++ b/ash/display/display_controller.h
@@ -106,6 +106,10 @@ // Returns the root window for |display_id|. aura::Window* GetRootWindowForDisplayId(int64 id); + // Returns AshWTH for given display |id|. Call results in CHECK failure + // if the WTH does not exist. + AshWindowTreeHost* GetAshWindowTreeHostForDisplayId(int64 id); + // Toggle mirror mode. void ToggleMirrorMode(); @@ -153,7 +157,8 @@ void OnHostResized(const aura::WindowTreeHost* host) override; // aura::DisplayManager::Delegate overrides: - void CreateOrUpdateMirroringDisplay(const DisplayInfo& info) override; + void CreateOrUpdateMirroringDisplay( + const DisplayInfoList& info_list) override; void CloseMirroringDisplay() override; void PreDisplayConfigurationChange(bool clear_focus) override; void PostDisplayConfigurationChange() override; @@ -174,6 +179,10 @@ void SetMirrorModeAfterAnimation(bool mirror); + // Delete the AsWindowTreeHost. This does not remove the entry from + // |window_tree_hosts_|. Caller has to explicitly remove it. + void DeleteHost(AshWindowTreeHost* host_to_delete); + class DisplayChangeLimiter { public: DisplayChangeLimiter();
diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc index 6b9e056..273b461 100644 --- a/ash/display/display_controller_unittest.cc +++ b/ash/display/display_controller_unittest.cc
@@ -346,10 +346,6 @@ DISALLOW_COPY_AND_ASSIGN(TestEventHandler); }; -gfx::Display::Rotation GetStoredRotation(int64 id) { - return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation(); -} - float GetStoredUIScale(int64 id) { return Shell::GetInstance()->display_manager()->GetDisplayInfo(id). GetEffectiveUIScale(); @@ -534,7 +530,7 @@ gfx::Display::Rotation rotation) { DisplayInfo info(id, "", false); info.SetBounds(gfx::Rect(0, y, 500, 500)); - info.set_rotation(rotation); + info.SetRotation(rotation, gfx::Display::ROTATION_SOURCE_ACTIVE); return info; } @@ -663,12 +659,14 @@ // Rotation observer.GetRotationChangedCountAndReset(); // we only want to reset. int64 primary_id = GetPrimaryDisplay().id(); - display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90); + display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_ACTIVE); EXPECT_EQ(1, observer.GetRotationChangedCountAndReset()); EXPECT_EQ(1, observer.CountAndReset()); EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); - display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90); + display_manager->SetDisplayRotation(primary_id, gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_ACTIVE); EXPECT_EQ(0, observer.GetRotationChangedCountAndReset()); EXPECT_EQ(0, observer.CountAndReset()); EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); @@ -1023,20 +1021,20 @@ ScreenUtil::GetSecondaryDisplay().bounds().ToString()); generator1.MoveMouseToInHost(50, 40); EXPECT_EQ("50,40", event_handler.GetLocationAndReset()); - EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id())); - EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id)); + EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display1.id())); + EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display2_id)); EXPECT_EQ(0, observer.GetRotationChangedCountAndReset()); - display_manager->SetDisplayRotation(display1.id(), - gfx::Display::ROTATE_90); + display_manager->SetDisplayRotation(display1.id(), gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_ACTIVE); EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); EXPECT_EQ("200,0 150x200", ScreenUtil::GetSecondaryDisplay().bounds().ToString()); generator1.MoveMouseToInHost(50, 40); EXPECT_EQ("40,69", event_handler.GetLocationAndReset()); - EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id())); - EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id)); + EXPECT_EQ(gfx::Display::ROTATE_90, GetActiveDisplayRotation(display1.id())); + EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display2_id)); EXPECT_EQ(1, observer.GetRotationChangedCountAndReset()); DisplayLayout display_layout(DisplayLayout::BOTTOM, 50); @@ -1044,30 +1042,30 @@ EXPECT_EQ("50,120 150x200", ScreenUtil::GetSecondaryDisplay().bounds().ToString()); - display_manager->SetDisplayRotation(display2_id, - gfx::Display::ROTATE_270); + display_manager->SetDisplayRotation(display2_id, gfx::Display::ROTATE_270, + gfx::Display::ROTATION_SOURCE_ACTIVE); EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); EXPECT_EQ("50,120 200x150", ScreenUtil::GetSecondaryDisplay().bounds().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id())); - EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id)); + EXPECT_EQ(gfx::Display::ROTATE_90, GetActiveDisplayRotation(display1.id())); + EXPECT_EQ(gfx::Display::ROTATE_270, GetActiveDisplayRotation(display2_id)); EXPECT_EQ(1, observer.GetRotationChangedCountAndReset()); #if !defined(OS_WIN) ui::test::EventGenerator generator2(root_windows[1]); generator2.MoveMouseToInHost(50, 40); EXPECT_EQ("179,25", event_handler.GetLocationAndReset()); - display_manager->SetDisplayRotation(display1.id(), - gfx::Display::ROTATE_180); + display_manager->SetDisplayRotation(display1.id(), gfx::Display::ROTATE_180, + gfx::Display::ROTATION_SOURCE_ACTIVE); EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); // Dislay must share at least 100, so the x's offset becomes 20. EXPECT_EQ("20,200 200x150", ScreenUtil::GetSecondaryDisplay().bounds().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id())); - EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id)); + EXPECT_EQ(gfx::Display::ROTATE_180, GetActiveDisplayRotation(display1.id())); + EXPECT_EQ(gfx::Display::ROTATE_270, GetActiveDisplayRotation(display2_id)); EXPECT_EQ(1, observer.GetRotationChangedCountAndReset()); generator1.MoveMouseToInHost(50, 40);
diff --git a/ash/display/display_info.cc b/ash/display/display_info.cc index e812633b..e58b51a 100644 --- a/ash/display/display_info.cc +++ b/ash/display/display_info.cc
@@ -207,7 +207,7 @@ DisplayInfo display_info( id, base::StringPrintf("Display-%d", static_cast<int>(id)), has_overscan); display_info.set_device_scale_factor(device_scale_factor); - display_info.set_rotation(rotation); + display_info.SetRotation(rotation, gfx::Display::ROTATION_SOURCE_ACTIVE); display_info.set_configured_ui_scale(ui_scale); display_info.SetBounds(bounds_in_native); display_info.SetDisplayModes(display_modes); @@ -228,7 +228,6 @@ DisplayInfo::DisplayInfo() : id_(gfx::Display::kInvalidDisplayID), has_overscan_(false), - rotation_(gfx::Display::ROTATE_0), touch_support_(gfx::Display::TOUCH_SUPPORT_UNKNOWN), touch_device_id_(0), device_scale_factor_(1.0f), @@ -246,7 +245,6 @@ : id_(id), name_(name), has_overscan_(has_overscan), - rotation_(gfx::Display::ROTATE_0), touch_support_(gfx::Display::TOUCH_SUPPORT_UNKNOWN), touch_device_id_(0), device_scale_factor_(1.0f), @@ -261,6 +259,23 @@ DisplayInfo::~DisplayInfo() { } +void DisplayInfo::SetRotation(gfx::Display::Rotation rotation, + gfx::Display::RotationSource source) { + rotations_[source] = rotation; + rotations_[gfx::Display::ROTATION_SOURCE_ACTIVE] = rotation; +} + +gfx::Display::Rotation DisplayInfo::GetActiveRotation() const { + return GetRotation(gfx::Display::ROTATION_SOURCE_ACTIVE); +} + +gfx::Display::Rotation DisplayInfo::GetRotation( + gfx::Display::RotationSource source) const { + if (rotations_.find(source) == rotations_.end()) + return gfx::Display::ROTATE_0; + return rotations_.at(source); +} + void DisplayInfo::Copy(const DisplayInfo& native_info) { DCHECK(id_ == native_info.id_); name_ = native_info.name_; @@ -287,7 +302,7 @@ else if (!native_info.overscan_insets_in_dip_.empty()) overscan_insets_in_dip_ = native_info.overscan_insets_in_dip_; - rotation_ = native_info.rotation_; + rotations_ = native_info.rotations_; configured_ui_scale_ = native_info.configured_ui_scale_; color_profile_ = native_info.color_profile(); } @@ -325,9 +340,10 @@ overscan_insets_in_dip_.Set(0, 0, 0, 0); } - if (rotation_ == gfx::Display::ROTATE_90 || - rotation_ == gfx::Display::ROTATE_270) + if (GetActiveRotation() == gfx::Display::ROTATE_90 || + GetActiveRotation() == gfx::Display::ROTATE_270) { size_in_pixel_.SetSize(size_in_pixel_.height(), size_in_pixel_.width()); + } gfx::SizeF size_f(size_in_pixel_); size_f.Scale(GetEffectiveUIScale()); size_in_pixel_ = gfx::ToFlooredSize(size_f); @@ -358,7 +374,7 @@ } std::string DisplayInfo::ToString() const { - int rotation_degree = static_cast<int>(rotation_) * 90; + int rotation_degree = static_cast<int>(GetActiveRotation()) * 90; return base::StringPrintf( "DisplayInfo[%lld] native bounds=%s, size=%s, scale=%f, " "overscan=%s, rotation=%d, ui-scale=%f, touchscreen=%s, "
diff --git a/ash/display/display_info.h b/ash/display/display_info.h index 427355b8..34f2299 100644 --- a/ash/display/display_info.h +++ b/ash/display/display_info.h
@@ -5,6 +5,7 @@ #ifndef ASH_DISPLAY_DISPLAY_INFO_H_ #define ASH_DISPLAY_DISPLAY_INFO_H_ +#include <map> #include <string> #include <vector> @@ -103,9 +104,6 @@ // actual overscan automatically, but used in the message. bool has_overscan() const { return has_overscan_; } - void set_rotation(gfx::Display::Rotation rotation) { rotation_ = rotation; } - gfx::Display::Rotation rotation() const { return rotation_; } - void set_touch_support(gfx::Display::TouchSupport support) { touch_support_ = support; } @@ -139,6 +137,17 @@ float configured_ui_scale() const { return configured_ui_scale_; } void set_configured_ui_scale(float scale) { configured_ui_scale_ = scale; } + // Sets the rotation for the given |source|. Setting a new rotation will also + // have it become the active rotation. + void SetRotation(gfx::Display::Rotation rotation, + gfx::Display::RotationSource source); + + // Returns the currently active rotation for this display. + gfx::Display::Rotation GetActiveRotation() const; + + // Returns the rotation set by a given |source|. + gfx::Display::Rotation GetRotation(gfx::Display::RotationSource source) const; + // Returns the ui scale and device scale factor actually used to create // display that chrome sees. This can be different from one obtained // from dispaly or one specified by a user in following situation. @@ -231,7 +240,7 @@ int64 id_; std::string name_; bool has_overscan_; - gfx::Display::Rotation rotation_; + std::map<gfx::Display::RotationSource, gfx::Display::Rotation> rotations_; gfx::Display::TouchSupport touch_support_; // If the display is also a touch device, it will have a positive
diff --git a/ash/display/display_info_unittest.cc b/ash/display/display_info_unittest.cc index 01362b43..7c5da69 100644 --- a/ash/display/display_info_unittest.cc +++ b/ash/display/display_info_unittest.cc
@@ -29,32 +29,32 @@ EXPECT_EQ(10, info.id()); EXPECT_EQ("0,0 200x100", info.bounds_in_native().ToString()); EXPECT_EQ("200x100", info.size_in_pixel().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_0, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, info.GetActiveRotation()); EXPECT_EQ("0,0,0,0", info.overscan_insets_in_dip().ToString()); EXPECT_EQ(1.0f, info.configured_ui_scale()); info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/o", 10); EXPECT_EQ("10,20 300x400", info.bounds_in_native().ToString()); EXPECT_EQ("288x380", info.size_in_pixel().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_0, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, info.GetActiveRotation()); EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString()); info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/ob", 10); EXPECT_EQ("10,20 300x400", info.bounds_in_native().ToString()); EXPECT_EQ("288x380", info.size_in_pixel().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_0, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, info.GetActiveRotation()); EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString()); info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/or", 10); EXPECT_EQ("10,20 300x400", info.bounds_in_native().ToString()); EXPECT_EQ("380x288", info.size_in_pixel().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_90, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, info.GetActiveRotation()); // TODO(oshima): This should be rotated too. Fix this. EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString()); info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/l@1.5", 10); EXPECT_EQ("10,20 300x400", info.bounds_in_native().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_270, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_270, info.GetActiveRotation()); EXPECT_EQ(1.5f, info.configured_ui_scale()); info = DisplayInfo::CreateFromSpecWithID(
diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc index d40917ac6..aaee9238 100644 --- a/ash/display/display_manager.cc +++ b/ash/display/display_manager.cc
@@ -13,6 +13,8 @@ #include "ash/ash_switches.h" #include "ash/display/display_layout_store.h" #include "ash/display/display_util.h" +#include "ash/display/extended_mouse_warp_controller.h" +#include "ash/display/null_mouse_warp_controller.h" #include "ash/display/screen_ash.h" #include "ash/screen_util.h" #include "ash/shell.h" @@ -47,6 +49,8 @@ #include "base/win/windows_version.h" #endif +#include "base/debug/stack_trace.h" + namespace ash { typedef std::vector<gfx::Display> DisplayList; typedef std::vector<DisplayInfo> DisplayInfoList; @@ -113,6 +117,9 @@ using std::string; using std::vector; +// static +int64 DisplayManager::kUnifiedDisplayId = -10; + DisplayManager::DisplayManager() : delegate_(NULL), screen_(new ScreenAsh), @@ -121,7 +128,8 @@ num_connected_displays_(0), force_bounds_changed_(false), change_display_upon_host_resize_(false), - second_display_mode_(EXTENDED), + multi_display_mode_(EXTENDED), + default_multi_display_mode_(EXTENDED), mirroring_display_id_(gfx::Display::kInvalidDisplayID), registered_internal_display_rotation_lock_(false), registered_internal_display_rotation_(gfx::Display::ROTATE_0), @@ -131,6 +139,9 @@ if (base::SysInfo::IsRunningOnChromeOS()) DisplayInfo::SetUse125DSFForUIScaling(true); + if (switches::UnifiedDesktopEnabled()) + multi_display_mode_ = default_multi_display_mode_ = UNIFIED; + change_display_upon_host_resize_ = !base::SysInfo::IsRunningOnChromeOS(); #endif gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_ALTERNATE, screen_.get()); @@ -168,7 +179,7 @@ MaybeInitInternalDisplay(&info_list[0]); if (info_list.size() > 1 && command_line->HasSwitch(switches::kAshEnableSoftwareMirroring)) { - SetSecondDisplayMode(MIRRORING); + SetMultiDisplayMode(MIRRORING); } OnNativeDisplaysChanged(info_list); return true; @@ -217,7 +228,10 @@ } DisplayIdPair DisplayManager::GetCurrentDisplayIdPair() const { - if (IsInMirrorMode()) { + if (IsInUnifiedMode()) { + return std::make_pair(software_mirroring_display_list_[0].id(), + software_mirroring_display_list_[1].id()); + } else if (IsInMirrorMode()) { if (software_mirroring_enabled()) { CHECK_EQ(2u, num_connected_displays()); // This comment is to make it easy to distinguish the crash @@ -325,14 +339,17 @@ } void DisplayManager::SetDisplayRotation(int64 display_id, - gfx::Display::Rotation rotation) { + gfx::Display::Rotation rotation, + gfx::Display::RotationSource source) { DisplayInfoList display_info_list; for (const auto& display : active_display_list_) { DisplayInfo info = GetDisplayInfo(display.id()); if (info.id() == display_id) { - if (info.rotation() == rotation) + if (info.GetRotation(source) == rotation && + info.GetActiveRotation() == rotation) { return; - info.set_rotation(rotation); + } + info.SetRotation(rotation, source); } display_info_list.push_back(info); } @@ -448,7 +465,8 @@ if (display_info_.find(display_id) == display_info_.end()) display_info_[display_id] = DisplayInfo(display_id, std::string(), false); - display_info_[display_id].set_rotation(rotation); + display_info_[display_id].SetRotation(rotation, + gfx::Display::ROTATION_SOURCE_ACTIVE); display_info_[display_id].SetColorProfile(color_profile); // Just in case the preference file was corrupted. // TODO(mukai): register |display_modes_| here as well, so the lookup for the @@ -587,7 +605,7 @@ bool internal_display_connected = false; num_connected_displays_ = updated_displays.size(); mirroring_display_id_ = gfx::Display::kInvalidDisplayID; - software_mirroring_display_ = gfx::Display(); + software_mirroring_display_list_.clear(); DisplayInfoList new_display_info_list; for (DisplayInfoList::const_iterator iter = updated_displays.begin(); iter != updated_displays.end(); @@ -662,8 +680,7 @@ if (delegate_) delegate_->CloseMirroringDisplay(); - if (second_display_mode_ == MIRRORING && new_display_info_list.size() == 2) - CreateSoftwareMirroringDisplay(&new_display_info_list); + CreateSoftwareMirroringDisplay(&new_display_info_list); DisplayList new_displays; DisplayList removed_displays; @@ -864,6 +881,11 @@ return mirroring_display_id_ != gfx::Display::kInvalidDisplayID; } +bool DisplayManager::IsInUnifiedMode() const { + return multi_display_mode_ == UNIFIED && + !software_mirroring_display_list_.empty(); +} + const DisplayInfo& DisplayManager::GetDisplayInfo(int64 display_id) const { DCHECK_NE(gfx::Display::kInvalidDisplayID, display_id); @@ -873,6 +895,17 @@ return iter->second; } +const gfx::Display DisplayManager::GetMirroringDisplayById( + int64 display_id) const { + auto iter = std::find_if(software_mirroring_display_list_.begin(), + software_mirroring_display_list_.end(), + [display_id](const gfx::Display& display) { + return display.id() == display_id; + }); + return iter == software_mirroring_display_list_.end() ? gfx::Display() + : *iter; +} + std::string DisplayManager::GetDisplayNameForId(int64 id) { if (id == gfx::Display::kInvalidDisplayID) return l10n_util::GetStringUTF8(IDS_ASH_STATUS_TRAY_UNKNOWN_DISPLAY_NAME); @@ -893,30 +926,37 @@ return display_id; } -void DisplayManager::SetMirrorMode(bool mirrored) { +void DisplayManager::SetMirrorMode(bool mirror) { +#if defined(OS_CHROMEOS) if (num_connected_displays() <= 1) return; -#if defined(OS_CHROMEOS) if (base::SysInfo::IsRunningOnChromeOS()) { ui::MultipleDisplayState new_state = - mirrored ? ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR : - ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED; + mirror ? ui::MULTIPLE_DISPLAY_STATE_DUAL_MIRROR + : ui::MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED; Shell::GetInstance()->display_configurator()->SetDisplayMode(new_state); return; } -#endif + // This is fallback path to emulate mirroroing on desktop. - SetSecondDisplayMode(mirrored ? MIRRORING : EXTENDED); DisplayInfoList display_info_list; - int count = 0; - for (std::map<int64, DisplayInfo>::const_iterator iter = - display_info_.begin(); - count < 2; ++iter, ++count) { - display_info_list.push_back(GetDisplayInfo(iter->second.id())); + for (DisplayList::const_iterator iter = active_display_list_.begin(); + (display_info_list.size() < 2 && iter != active_display_list_.end()); + ++iter) { + if (iter->id() == kUnifiedDisplayId) + continue; + display_info_list.push_back(GetDisplayInfo(iter->id())); } + for (auto iter = software_mirroring_display_list_.begin(); + (display_info_list.size() < 2 && + iter != software_mirroring_display_list_.end()); + ++iter) { + display_info_list.push_back(GetDisplayInfo(iter->id())); + } + + SetSoftwareMirroring(mirror); UpdateDisplays(display_info_list); -#if defined(OS_CHROMEOS) if (Shell::GetInstance()->display_configurator_animation()) { Shell::GetInstance()->display_configurator_animation()-> StartFadeInAnimation(); @@ -928,7 +968,9 @@ DCHECK(!active_display_list_.empty()); std::vector<DisplayInfo> new_display_info_list; const DisplayInfo& first_display = - GetDisplayInfo(active_display_list_[0].id()); + IsInUnifiedMode() + ? GetDisplayInfo(software_mirroring_display_list_[0].id()) + : GetDisplayInfo(active_display_list_[0].id()); new_display_info_list.push_back(first_display); // Add if there is only one display connected. if (num_connected_displays() == 1) { @@ -940,7 +982,7 @@ } num_connected_displays_ = new_display_info_list.size(); mirroring_display_id_ = gfx::Display::kInvalidDisplayID; - software_mirroring_display_ = gfx::Display(); + software_mirroring_display_list_.clear(); UpdateDisplays(new_display_info_list); } @@ -960,7 +1002,7 @@ #if defined(OS_CHROMEOS) void DisplayManager::SetSoftwareMirroring(bool enabled) { - SetSecondDisplayMode(enabled ? MIRRORING : EXTENDED); + SetMultiDisplayMode(enabled ? MIRRORING : default_multi_display_mode_); } bool DisplayManager::SoftwareMirroringEnabled() const { @@ -968,10 +1010,17 @@ } #endif -void DisplayManager::SetSecondDisplayMode(SecondDisplayMode mode) { - second_display_mode_ = mode; +void DisplayManager::SetMultiDisplayMode(MultiDisplayMode mode) { + multi_display_mode_ = mode; mirroring_display_id_ = gfx::Display::kInvalidDisplayID; - software_mirroring_display_ = gfx::Display(); + software_mirroring_display_list_.clear(); +} + +void DisplayManager::SetDefaultMultiDisplayMode(MultiDisplayMode mode) { + // TODO(oshima): Remove this constrain. + DCHECK_EQ(default_multi_display_mode_, EXTENDED); + DCHECK_EQ(mode, UNIFIED); + default_multi_display_mode_ = mode; } bool DisplayManager::UpdateDisplayBounds(int64 display_id, @@ -994,7 +1043,7 @@ // Do not post a task if the software mirroring doesn't exist, or // during initialization when compositor's init task isn't posted yet. // ash::Shell::Init() will call this after the compositor is initialized. - if (!software_mirroring_display_.is_valid() || !delegate_) + if (software_mirroring_display_list_.empty() || !delegate_) return; base::MessageLoopForUI::current()->PostTask( FROM_HERE, @@ -1002,6 +1051,15 @@ weak_ptr_factory_.GetWeakPtr())); } +scoped_ptr<MouseWarpController> DisplayManager::CreateMouseWarpController( + aura::Window* drag_source) const { + // Extra check for |num_connected_displays()| is for SystemDisplayApiTest + // that injects MockScreen. + if (GetNumDisplays() < 2 || num_connected_displays() < 2) + return make_scoped_ptr(new NullMouseWarpController()); + return make_scoped_ptr(new ExtendedMouseWarpController(drag_source)); +} + void DisplayManager::CreateScreenForShutdown() const { bool native_is_ash = gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_NATIVE) == screen_.get(); @@ -1028,23 +1086,54 @@ // the root window so that it matches the external display's // resolution. This is necessary in order for scaling to work while // mirrored. - bool zero_is_source = - first_display_id_ == (*display_info_list)[0].id() || - gfx::Display::InternalDisplayId() == (*display_info_list)[0].id(); - DCHECK_EQ(MIRRORING, second_display_mode_); - mirroring_display_id_ = (*display_info_list)[zero_is_source ? 1 : 0].id(); - int64 display_id = mirroring_display_id_; - auto iter = std::find_if(display_info_list->begin(), display_info_list->end(), - [display_id](const DisplayInfo& info) { - return info.id() == display_id; - }); - DCHECK(iter != display_info_list->end()); - DisplayInfo info = *iter; - info.SetOverscanInsets(gfx::Insets()); - InsertAndUpdateDisplayInfo(info); - software_mirroring_display_ = - CreateDisplayFromDisplayInfoById(mirroring_display_id_); - display_info_list->erase(iter); + // int64 mirroring_display_id = gfx::Display::kInvalidDisplayID; + if (display_info_list->size() == 2) { + switch (multi_display_mode_) { + case MIRRORING: { + bool zero_is_source = + first_display_id_ == (*display_info_list)[0].id() || + gfx::Display::InternalDisplayId() == (*display_info_list)[0].id(); + DCHECK_EQ(MIRRORING, multi_display_mode_); + mirroring_display_id_ = + (*display_info_list)[zero_is_source ? 1 : 0].id(); + + int64 display_id = mirroring_display_id_; + auto iter = + std::find_if(display_info_list->begin(), display_info_list->end(), + [display_id](const DisplayInfo& info) { + return info.id() == display_id; + }); + DCHECK(iter != display_info_list->end()); + + DisplayInfo info = *iter; + info.SetOverscanInsets(gfx::Insets()); + InsertAndUpdateDisplayInfo(info); + software_mirroring_display_list_.push_back( + CreateDisplayFromDisplayInfoById(mirroring_display_id_)); + display_info_list->erase(iter); + break; + } + case UNIFIED: { + // TODO(oshima): Suport displays that have different heights. + gfx::Rect unified_bounds; + software_mirroring_display_list_.clear(); + for (auto& info : *display_info_list) { + InsertAndUpdateDisplayInfo(info); + software_mirroring_display_list_.push_back( + CreateDisplayFromDisplayInfoById(info.id())); + gfx::Point origin(unified_bounds.right(), 0); + unified_bounds.Union(gfx::Rect(origin, info.size_in_pixel())); + } + DisplayInfo info(kUnifiedDisplayId, "Unified Desktop", false); + info.SetBounds(unified_bounds); + display_info_list->clear(); + display_info_list->push_back(info); + break; + } + case EXTENDED: + break; + } + } } gfx::Display* DisplayManager::FindDisplayForId(int64 id) { @@ -1053,7 +1142,10 @@ [id](const gfx::Display& display) { return display.id() == id; }); if (iter != active_display_list_.end()) return &(*iter); - DLOG(WARNING) << "Could not find display:" << id; + // TODO(oshima): This happens when a windows in unified desktop have + // been moved to normal window. Fix this. + if (id != kUnifiedDisplayId) + DLOG(WARNING) << "Could not find display:" << id; return NULL; } @@ -1087,7 +1179,7 @@ } gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) { - DCHECK(display_info_.find(id) != display_info_.end()); + DCHECK(display_info_.find(id) != display_info_.end()) << "id=" << id; const DisplayInfo& display_info = display_info_[id]; gfx::Display new_display(display_info.id()); @@ -1099,7 +1191,7 @@ // in |UpdateNonPrimaryDisplayBoundsForLayout| called in |UpdateDisplay|. new_display.SetScaleAndBounds( device_scale_factor, gfx::Rect(bounds_in_native.size())); - new_display.set_rotation(display_info.rotation()); + new_display.set_rotation(display_info.GetActiveRotation()); new_display.set_touch_support(display_info.touch_support()); return new_display; } @@ -1161,10 +1253,12 @@ } void DisplayManager::CreateMirrorWindowIfAny() { - if (software_mirroring_display_.is_valid() && delegate_) { - DisplayInfo display_info = GetDisplayInfo(software_mirroring_display_.id()); - delegate_->CreateOrUpdateMirroringDisplay(display_info); - } + if (software_mirroring_display_list_.empty() || !delegate_) + return; + DisplayInfoList list; + for (auto& display : software_mirroring_display_list_) + list.push_back(GetDisplayInfo(display.id())); + delegate_->CreateOrUpdateMirroringDisplay(list); } // static @@ -1215,7 +1309,7 @@ } void DisplayManager::RunPendingTasksForTest() { - if (software_mirroring_display_.is_valid()) + if (!software_mirroring_display_list_.empty()) base::RunLoop().RunUntilIdle(); }
diff --git a/ash/display/display_manager.h b/ash/display/display_manager.h index 9aa686c..3b0bd6a2 100644 --- a/ash/display/display_manager.h +++ b/ash/display/display_manager.h
@@ -21,6 +21,10 @@ #include "ui/display/chromeos/display_configurator.h" #endif +namespace aura { +class Window; +} + namespace gfx { class Display; class Insets; @@ -32,8 +36,11 @@ class AcceleratorControllerTest; class DisplayController; class DisplayLayoutStore; +class MouseWarpController; class ScreenAsh; +typedef std::vector<DisplayInfo> DisplayInfoList; + namespace test { class AshTestBase; class DisplayManagerTestApi; @@ -54,9 +61,9 @@ public: virtual ~Delegate() {} - // Create or updates the mirroring window with |display_info|. + // Create or updates the mirroring window with |display_info_list|. virtual void CreateOrUpdateMirroringDisplay( - const DisplayInfo& display_info) = 0; + const DisplayInfoList& display_info_list) = 0; // Closes the mirror window if exists. virtual void CloseMirroringDisplay() = 0; @@ -74,11 +81,16 @@ // 1) EXTENDED mode extends the desktop to the second dislpay. // 2) MIRRORING mode copies the content of the primary display to // the 2nd display. (Software Mirroring). - enum SecondDisplayMode { + // 3) UNIFIED mode creates single desktop across multiple displays. + enum MultiDisplayMode { EXTENDED, - MIRRORING + MIRRORING, + UNIFIED, }; + // The display ID for a virtual display assigned to a unified desktop. + static int64 kUnifiedDisplayId; + DisplayManager(); #if defined(OS_CHROMEOS) ~DisplayManager() override; @@ -141,8 +153,11 @@ // display's bounds change. void SetOverscanInsets(int64 display_id, const gfx::Insets& insets_in_dip); - // Sets the display's rotation. - void SetDisplayRotation(int64 display_id, gfx::Display::Rotation rotation); + // Sets the display's rotation for the given |source|. The new |rotation| will + // also become active. + void SetDisplayRotation(int64 display_id, + gfx::Display::Rotation rotation, + gfx::Display::RotationSource source); // Sets the display's ui scale. Returns true if it's successful, or // false otherwise. TODO(mukai): remove this and merge into @@ -239,10 +254,11 @@ bool IsInMirrorMode() const; int64 mirroring_display_id() const { return mirroring_display_id_; } - // Returns the display used for software mirrroring. - const gfx::Display& software_mirroring_display() const { - return software_mirroring_display_; - } + bool IsInUnifiedMode() const; + + // Returns the display used for software mirrroring. Returns invalid + // display if not found. + const gfx::Display GetMirroringDisplayById(int64 id) const; // Retuns the display info associated with |display_id|. const DisplayInfo& GetDisplayInfo(int64 display_id) const; @@ -270,13 +286,17 @@ bool SoftwareMirroringEnabled() const override; #endif bool software_mirroring_enabled() const { - return second_display_mode_ == MIRRORING; + return multi_display_mode_ == MIRRORING; }; - // Sets/gets second display mode. - void SetSecondDisplayMode(SecondDisplayMode mode); - SecondDisplayMode second_display_mode() const { - return second_display_mode_; + // Sets/gets multi display mode. + void SetMultiDisplayMode(MultiDisplayMode mode); + MultiDisplayMode multi_display_mode() const { return multi_display_mode_; } + + // Sets/gets default multi display mode. + void SetDefaultMultiDisplayMode(MultiDisplayMode mode); + MultiDisplayMode default_multi_display_mode() const { + return default_multi_display_mode_; } // Update the bounds of the display given by |display_id|. @@ -287,6 +307,12 @@ // is enabled. void CreateMirrorWindowAsyncIfAny(); + // Creates a MouseWarpController for the current display + // configuration. |drag_source| is the window where dragging + // started, or nullptr otherwise. + scoped_ptr<MouseWarpController> CreateMouseWarpController( + aura::Window* drag_source) const; + // Create a screen instance to be used during shutdown. void CreateScreenForShutdown() const; @@ -383,9 +409,11 @@ // on device as well as during the unit tests. bool change_display_upon_host_resize_; - SecondDisplayMode second_display_mode_; + MultiDisplayMode multi_display_mode_; + MultiDisplayMode default_multi_display_mode_; + int64 mirroring_display_id_; - gfx::Display software_mirroring_display_; + DisplayList software_mirroring_display_list_; // User preference for rotation lock of the internal display. bool registered_internal_display_rotation_lock_;
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index 9ed1039..00e2f10 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc
@@ -121,8 +121,12 @@ // aura::WindowObserver overrides: void OnWindowDestroying(aura::Window* window) override { - ASSERT_EQ(Shell::GetPrimaryRootWindow(), window); - root_window_destroyed_ = true; + // TODO(oshima): When moving between unified desktop, the + // primary root window can be deleted. + if (!display_manager()->IsInUnifiedMode()) { + ASSERT_EQ(Shell::GetPrimaryRootWindow(), window); + root_window_destroyed_ = true; + } } private: @@ -1207,7 +1211,7 @@ Shell::GetScreen()->AddObserver(&display_observer); DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); display_manager->UpdateDisplays(); RunAllPendingInMessageLoop(); EXPECT_TRUE(display_observer.changed_and_reset()); @@ -1265,7 +1269,7 @@ UpdateDisplay("600x400"); DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); UpdateDisplay("600x400,600x400"); EXPECT_TRUE(display_manager->IsInMirrorMode()); @@ -1458,6 +1462,34 @@ EXPECT_EQ("200x300", host1->GetBounds().size().ToString()); } +#if !defined(OS_WIN) && defined(USE_X11) + +TEST_F(DisplayManagerTest, UnifiedDesktopBasic) { + display_manager()->SetDefaultMultiDisplayMode(DisplayManager::UNIFIED); + display_manager()->SetMultiDisplayMode(DisplayManager::UNIFIED); + UpdateDisplay("300x200,400x500"); + + gfx::Screen* screen = + gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE); + EXPECT_EQ("700x500", screen->GetPrimaryDisplay().size().ToString()); + + display_manager()->SetMirrorMode(true); + EXPECT_EQ("300x200", screen->GetPrimaryDisplay().size().ToString()); + + display_manager()->SetMirrorMode(false); + EXPECT_EQ("700x500", screen->GetPrimaryDisplay().size().ToString()); + + // Swithc to single desktop. + UpdateDisplay("500x300"); + EXPECT_EQ("500x300", screen->GetPrimaryDisplay().size().ToString()); + + // Swithc to unified desktop. + UpdateDisplay("500x300,400x500"); + EXPECT_EQ("900x500", screen->GetPrimaryDisplay().size().ToString()); +} + +#endif + class ScreenShutdownTest : public test::AshTestBase { public: ScreenShutdownTest() {
diff --git a/ash/display/extended_mouse_warp_controller.cc b/ash/display/extended_mouse_warp_controller.cc new file mode 100644 index 0000000..c07b125b6 --- /dev/null +++ b/ash/display/extended_mouse_warp_controller.cc
@@ -0,0 +1,339 @@ +// 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 "ash/display/extended_mouse_warp_controller.h" + +#include <cmath> + +#include "ash/display/cursor_window_controller.h" +#include "ash/display/display_controller.h" +#include "ash/display/display_manager.h" +#include "ash/display/shared_display_edge_indicator.h" +#include "ash/host/ash_window_tree_host.h" +#include "ash/root_window_controller.h" +#include "ash/screen_util.h" +#include "ash/shell.h" +#include "ash/wm/window_util.h" +#include "ui/aura/env.h" +#include "ui/aura/window.h" +#include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_tree_host.h" +#include "ui/base/layout.h" +#include "ui/compositor/dip_util.h" +#include "ui/events/event.h" +#include "ui/events/event_utils.h" +#include "ui/gfx/screen.h" +#include "ui/wm/core/coordinate_conversion.h" + +namespace ash { + +namespace { + +// Maximum size on the display edge that initiate snapping phantom window, +// from the corner of the display. +const int kMaximumSnapHeight = 16; + +// Minimum height of an indicator on the display edge that allows +// dragging a window. If two displays shares the edge smaller than +// this, entire edge will be used as a draggable space. +const int kMinimumIndicatorHeight = 200; + +const int kIndicatorThickness = 1; + +void ConvertPointFromScreenToNative(const aura::Window* root_window, + gfx::Point* point) { + ::wm::ConvertPointFromScreen(root_window, point); + root_window->GetHost()->ConvertPointToNativeScreen(point); +} + +gfx::Rect GetNativeEdgeBounds(const aura::Window* root_window, + gfx::Point start, + gfx::Point end) { + gfx::Rect native_bounds = root_window->GetHost()->GetBounds(); + native_bounds.Inset( + GetRootWindowController(root_window)->ash_host()->GetHostInsets()); + + ConvertPointFromScreenToNative(root_window, &start); + ConvertPointFromScreenToNative(root_window, &end); + if (start.x() == end.x()) { + // vertical in native + int x = std::abs(native_bounds.x() - start.x()) < + std::abs(native_bounds.right() - start.x()) + ? native_bounds.x() + : native_bounds.right() - 1; + return gfx::Rect(x, std::min(start.y(), end.y()), 1, + std::abs(start.y() - end.y())); + } else { + // horizontal in native + int y = std::abs(native_bounds.y() - start.y()) < + std::abs(native_bounds.bottom() - start.y()) + ? native_bounds.y() + : native_bounds.bottom() - 1; + return gfx::Rect(std::min(start.x(), end.x()), y, + std::abs(start.x() - end.x()), 1); + } +} + +// Creates edge bounds from indicator bounds that fits the edge +// of the native window for |root_window|. +gfx::Rect CreateVerticalEdgeBoundsInNative(const aura::Window* root_window, + const gfx::Rect& indicator_bounds) { + gfx::Point start = indicator_bounds.origin(); + gfx::Point end = start; + end.set_y(indicator_bounds.bottom()); + return GetNativeEdgeBounds(root_window, start, end); +} + +gfx::Rect CreateHorizontalEdgeBoundsInNative( + const aura::Window* root_window, + const gfx::Rect& indicator_bounds) { + gfx::Point start = indicator_bounds.origin(); + gfx::Point end = start; + end.set_x(indicator_bounds.right()); + return GetNativeEdgeBounds(root_window, start, end); +} + +void MovePointInside(const gfx::Rect& native_bounds, + gfx::Point* point_in_native) { + if (native_bounds.x() > point_in_native->x()) + point_in_native->set_x(native_bounds.x()); + if (native_bounds.right() < point_in_native->x()) + point_in_native->set_x(native_bounds.right()); + + if (native_bounds.y() > point_in_native->y()) + point_in_native->set_y(native_bounds.y()); + if (native_bounds.bottom() < point_in_native->y()) + point_in_native->set_y(native_bounds.bottom()); +} + +// Moves the cursor to the point inside the root that is closest to +// the point_in_screen, which is outside of the root window. +void MoveCursorTo(aura::Window* root, + const gfx::Point& point_in_screen, + bool update_last_location_now) { + gfx::Point point_in_native = point_in_screen; + ::wm::ConvertPointFromScreen(root, &point_in_native); + root->GetHost()->ConvertPointToNativeScreen(&point_in_native); + + // now fit the point inside the native bounds. + gfx::Rect native_bounds = root->GetHost()->GetBounds(); + gfx::Point native_origin = native_bounds.origin(); + native_bounds.Inset( + GetRootWindowController(root)->ash_host()->GetHostInsets()); + // Shrink further so that the mouse doesn't warp on the + // edge. The right/bottom needs to be shrink by 2 to subtract + // the 1 px from width/height value. + native_bounds.Inset(1, 1, 2, 2); + + MovePointInside(native_bounds, &point_in_native); + gfx::Point point_in_host = point_in_native; + + point_in_host.Offset(-native_origin.x(), -native_origin.y()); + root->GetHost()->MoveCursorToHostLocation(point_in_host); + + if (update_last_location_now) { + gfx::Point new_point_in_screen = point_in_native; + root->GetHost()->ConvertPointFromNativeScreen(&new_point_in_screen); + ::wm::ConvertPointToScreen(root, &new_point_in_screen); + aura::Env::GetInstance()->set_last_mouse_location(new_point_in_screen); + } +} + +} // namespace + +ExtendedMouseWarpController::ExtendedMouseWarpController( + aura::Window* drag_source) + : drag_source_root_(drag_source), + shared_display_edge_indicator_(new SharedDisplayEdgeIndicator), + allow_non_native_event_(false) { + DisplayLayout::Position position = Shell::GetInstance() + ->display_manager() + ->GetCurrentDisplayLayout() + .position; + if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) + UpdateHorizontalEdgeBounds(); + else + UpdateVerticalEdgeBounds(); + if (drag_source) { + shared_display_edge_indicator_->Show(src_indicator_bounds_, + dst_indicator_bounds_); + } +} + +ExtendedMouseWarpController::~ExtendedMouseWarpController() { +} + +bool ExtendedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) { + if (Shell::GetScreen()->GetNumDisplays() <= 1) + return false; + + aura::Window* target = static_cast<aura::Window*>(event->target()); + gfx::Point point_in_screen = event->location(); + ::wm::ConvertPointToScreen(target, &point_in_screen); + + // A native event may not exist in unit test. Generate the native point + // from the screen point instead. + if (!event->HasNativeEvent()) { + if (!allow_non_native_event_) + return false; + aura::Window* target_root = target->GetRootWindow(); + gfx::Point point_in_native = point_in_screen; + ::wm::ConvertPointFromScreen(target_root, &point_in_native); + target_root->GetHost()->ConvertPointToNativeScreen(&point_in_native); + return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, + true); + } + + gfx::Point point_in_native = + ui::EventSystemLocationFromNative(event->native_event()); + +#if defined(USE_OZONE) + // TODO(dnicoara): crbug.com/415680 Move cursor warping into Ozone once Ozone + // has access to the logical display layout. + // Native events in Ozone are in the native window coordinate system. We need + // to translate them to get the global position. + point_in_native.Offset(target->GetHost()->GetBounds().x(), + target->GetHost()->GetBounds().y()); +#endif + + return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, false); +} + +bool ExtendedMouseWarpController::WarpMouseCursorInNativeCoords( + const gfx::Point& point_in_native, + const gfx::Point& point_in_screen, + bool update_mouse_location_now) { + bool in_src_edge = src_edge_bounds_in_native_.Contains(point_in_native); + bool in_dst_edge = dst_edge_bounds_in_native_.Contains(point_in_native); + if (!in_src_edge && !in_dst_edge) + return false; + + // The mouse must move. + aura::Window* src_root = NULL; + aura::Window* dst_root = NULL; + GetSrcAndDstRootWindows(&src_root, &dst_root); + + if (in_src_edge) + MoveCursorTo(dst_root, point_in_screen, update_mouse_location_now); + else + MoveCursorTo(src_root, point_in_screen, update_mouse_location_now); + return true; +} + +void ExtendedMouseWarpController::UpdateHorizontalEdgeBounds() { + bool from_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; + // GetPrimaryDisplay returns an object on stack, so copy the bounds + // instead of using reference. + const gfx::Rect primary_bounds = + Shell::GetScreen()->GetPrimaryDisplay().bounds(); + const gfx::Rect secondary_bounds = ScreenUtil::GetSecondaryDisplay().bounds(); + DisplayLayout::Position position = Shell::GetInstance() + ->display_manager() + ->GetCurrentDisplayLayout() + .position; + + src_indicator_bounds_.set_x( + std::max(primary_bounds.x(), secondary_bounds.x())); + src_indicator_bounds_.set_width( + std::min(primary_bounds.right(), secondary_bounds.right()) - + src_indicator_bounds_.x()); + src_indicator_bounds_.set_height(kIndicatorThickness); + src_indicator_bounds_.set_y( + position == DisplayLayout::TOP + ? primary_bounds.y() - (from_primary ? 0 : kIndicatorThickness) + : primary_bounds.bottom() - (from_primary ? kIndicatorThickness : 0)); + + dst_indicator_bounds_ = src_indicator_bounds_; + dst_indicator_bounds_.set_height(kIndicatorThickness); + dst_indicator_bounds_.set_y( + position == DisplayLayout::TOP + ? primary_bounds.y() - (from_primary ? kIndicatorThickness : 0) + : primary_bounds.bottom() - (from_primary ? 0 : kIndicatorThickness)); + + aura::Window* src_root = NULL; + aura::Window* dst_root = NULL; + GetSrcAndDstRootWindows(&src_root, &dst_root); + + src_edge_bounds_in_native_ = + CreateHorizontalEdgeBoundsInNative(src_root, src_indicator_bounds_); + dst_edge_bounds_in_native_ = + CreateHorizontalEdgeBoundsInNative(dst_root, dst_indicator_bounds_); +} + +void ExtendedMouseWarpController::UpdateVerticalEdgeBounds() { + int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0; + bool in_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; + // GetPrimaryDisplay returns an object on stack, so copy the bounds + // instead of using reference. + const gfx::Rect primary_bounds = + Shell::GetScreen()->GetPrimaryDisplay().bounds(); + const gfx::Rect secondary_bounds = ScreenUtil::GetSecondaryDisplay().bounds(); + DisplayLayout::Position position = Shell::GetInstance() + ->display_manager() + ->GetCurrentDisplayLayout() + .position; + + int upper_shared_y = std::max(primary_bounds.y(), secondary_bounds.y()); + int lower_shared_y = + std::min(primary_bounds.bottom(), secondary_bounds.bottom()); + int shared_height = lower_shared_y - upper_shared_y; + + int dst_x = + position == DisplayLayout::LEFT + ? primary_bounds.x() - (in_primary ? kIndicatorThickness : 0) + : primary_bounds.right() - (in_primary ? 0 : kIndicatorThickness); + dst_indicator_bounds_.SetRect(dst_x, upper_shared_y, kIndicatorThickness, + shared_height); + + // The indicator on the source display. + src_indicator_bounds_.set_width(kIndicatorThickness); + src_indicator_bounds_.set_x( + position == DisplayLayout::LEFT + ? primary_bounds.x() - (in_primary ? 0 : kIndicatorThickness) + : primary_bounds.right() - (in_primary ? kIndicatorThickness : 0)); + + const gfx::Rect& source_bounds = + in_primary ? primary_bounds : secondary_bounds; + int upper_indicator_y = source_bounds.y() + snap_height; + int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y); + + // This gives a hight that can be used without sacrifying the snap space. + int available_space = + lower_indicator_y - std::max(upper_shared_y, upper_indicator_y); + + if (shared_height < kMinimumIndicatorHeight) { + // If the shared height is smaller than minimum height, use the + // entire height. + upper_indicator_y = upper_shared_y; + } else if (available_space < kMinimumIndicatorHeight) { + // Snap to the bottom. + upper_indicator_y = + std::max(upper_shared_y, lower_indicator_y + kMinimumIndicatorHeight); + } else { + upper_indicator_y = std::max(upper_indicator_y, upper_shared_y); + } + src_indicator_bounds_.set_y(upper_indicator_y); + src_indicator_bounds_.set_height(lower_indicator_y - upper_indicator_y); + + aura::Window* src_root = NULL; + aura::Window* dst_root = NULL; + GetSrcAndDstRootWindows(&src_root, &dst_root); + + // Native + src_edge_bounds_in_native_ = + CreateVerticalEdgeBoundsInNative(src_root, src_indicator_bounds_); + dst_edge_bounds_in_native_ = + CreateVerticalEdgeBoundsInNative(dst_root, dst_indicator_bounds_); +} + +void ExtendedMouseWarpController::GetSrcAndDstRootWindows( + aura::Window** src_root, + aura::Window** dst_root) { + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + *src_root = drag_source_root_ ? drag_source_root_ + : Shell::GetInstance()->GetPrimaryRootWindow(); + *dst_root = root_windows[0] == *src_root ? root_windows[1] : root_windows[0]; +} + +} // namespace ash
diff --git a/ash/display/extended_mouse_warp_controller.h b/ash/display/extended_mouse_warp_controller.h new file mode 100644 index 0000000..28300dd1 --- /dev/null +++ b/ash/display/extended_mouse_warp_controller.h
@@ -0,0 +1,91 @@ +// 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 ASH_DISPLAY_EXTENDED_MOUSE_WARP_CONTROLLER_H +#define ASH_DISPLAY_EXTENDED_MOUSE_WARP_CONTROLLER_H + +#include "ash/display/mouse_warp_controller.h" + +#include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" +#include "ui/gfx/geometry/rect.h" + +namespace aura { +class Window; +} + +namespace gfx { +class Point; +} + +namespace ash { +namespace test { +class DisplayManagerTestApi; +} +class SharedDisplayEdgeIndicator; + +// A MouseWarpController used in extended display mode. +class ASH_EXPORT ExtendedMouseWarpController : public MouseWarpController { + public: + explicit ExtendedMouseWarpController(aura::Window* drag_source); + ~ExtendedMouseWarpController() override; + + // MouseWarpController: + bool WarpMouseCursor(ui::MouseEvent* event) override; + + private: + friend class test::DisplayManagerTestApi; + FRIEND_TEST_ALL_PREFIXES(ExtendedMouseWarpControllerTest, + IndicatorBoundsTestOnRight); + FRIEND_TEST_ALL_PREFIXES(ExtendedMouseWarpControllerTest, + IndicatorBoundsTestOnLeft); + FRIEND_TEST_ALL_PREFIXES(ExtendedMouseWarpControllerTest, + IndicatorBoundsTestOnTopBottom); + + // Warps the mouse cursor to an alternate root window when the + // mouse location in |event|, hits the edge of the event target's root and + // the mouse cursor is considered to be in an alternate display. + // If |update_mouse_location_now| is true, + // Returns true if/ the cursor was moved. + bool WarpMouseCursorInNativeCoords(const gfx::Point& point_in_native, + const gfx::Point& point_in_screen, + bool update_mouse_location_now); + + // Update the edge/indicator bounds based on the current + // display configuration. + void UpdateHorizontalEdgeBounds(); + void UpdateVerticalEdgeBounds(); + + // Returns the source and destination window. When |src_window| is + // |drag_soruce_root_| when it is set. Otherwise, the |src_window| + // is always the primary root window, because there is no difference + // between moving src to dst and moving dst to src. + void GetSrcAndDstRootWindows(aura::Window** src_window, + aura::Window** dst_window); + + void allow_non_native_event_for_test() { allow_non_native_event_ = true; } + + // The bounds for warp hole windows. |dst_indicator_bounds_| is kept + // in the instance for testing. + gfx::Rect src_indicator_bounds_; + gfx::Rect dst_indicator_bounds_; + + gfx::Rect src_edge_bounds_in_native_; + gfx::Rect dst_edge_bounds_in_native_; + + // The root window in which the dragging started. + aura::Window* drag_source_root_; + + // Shows the area where a window can be dragged in to/out from + // another display. + scoped_ptr<SharedDisplayEdgeIndicator> shared_display_edge_indicator_; + + bool allow_non_native_event_; + + DISALLOW_COPY_AND_ASSIGN(ExtendedMouseWarpController); +}; + +} // namespace ash + +#endif // ASH_DISPLAY_EXTENDED_MOUSE_WARP_CONTROLLER_H
diff --git a/ash/display/extended_mouse_warp_controller_unittest.cc b/ash/display/extended_mouse_warp_controller_unittest.cc new file mode 100644 index 0000000..b3a0fe90 --- /dev/null +++ b/ash/display/extended_mouse_warp_controller_unittest.cc
@@ -0,0 +1,196 @@ +// 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 "ash/display/extended_mouse_warp_controller.h" + +#include "ash/display/display_layout_store.h" +#include "ash/display/display_manager.h" +#include "ash/display/mouse_cursor_event_filter.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "ui/events/test/event_generator.h" +#include "ui/gfx/display.h" +#include "ui/gfx/screen.h" + +namespace ash { + +class ExtendedMouseWarpControllerTest : public test::AshTestBase { + public: + ExtendedMouseWarpControllerTest() {} + ~ExtendedMouseWarpControllerTest() override {} + + protected: + MouseCursorEventFilter* event_filter() { + return Shell::GetInstance()->mouse_cursor_filter(); + } + + ExtendedMouseWarpController* mouse_warp_controller() { + return static_cast<ExtendedMouseWarpController*>( + event_filter()->mouse_warp_controller_for_test()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ExtendedMouseWarpControllerTest); +}; + +// Verifies if MouseCursorEventFilter's bounds calculation works correctly. +TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnRight) { + if (!SupportsMultipleDisplays()) + return; + + UpdateDisplay("360x360,700x700"); + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + DisplayLayout layout(DisplayLayout::RIGHT, 0); + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + EXPECT_EQ("359,16 1x344", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("360,0 1x360", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + EXPECT_EQ("360,16 1x344", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("359,0 1x360", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + + // Move 2nd display downwards a bit. + layout.offset = 5; + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + // This is same as before because the 2nd display's y is above + // the indicator's x. + EXPECT_EQ("359,16 1x344", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("360,5 1x355", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + EXPECT_EQ("360,21 1x339", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("359,5 1x355", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + + // Move it down further so that the shared edge is shorter than + // minimum hole size (160). + layout.offset = 200; + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + EXPECT_EQ("359,200 1x160", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("360,200 1x160", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + EXPECT_EQ("360,200 1x160", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("359,200 1x160", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + + // Now move 2nd display upwards + layout.offset = -5; + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + EXPECT_EQ("359,16 1x344", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("360,0 1x360", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + // 16 px are reserved on 2nd display from top, so y must be + // (16 - 5) = 11 + EXPECT_EQ("360,11 1x349", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("359,0 1x360", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + + event_filter()->HideSharedEdgeIndicator(); +} + +TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnLeft) { + if (!SupportsMultipleDisplays()) + return; + + UpdateDisplay("360x360,700x700"); + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + DisplayLayout layout(DisplayLayout::LEFT, 0); + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + EXPECT_EQ("0,16 1x344", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("-1,0 1x360", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + EXPECT_EQ("-1,16 1x344", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("0,0 1x360", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + + layout.offset = 250; + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + EXPECT_EQ("0,250 1x110", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("-1,250 1x110", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + EXPECT_EQ("-1,250 1x110", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("0,250 1x110", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->HideSharedEdgeIndicator(); +} + +TEST_F(ExtendedMouseWarpControllerTest, IndicatorBoundsTestOnTopBottom) { + if (!SupportsMultipleDisplays()) + return; + + UpdateDisplay("360x360,700x700"); + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + DisplayLayout layout(DisplayLayout::TOP, 0); + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + EXPECT_EQ("0,0 360x1", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("0,-1 360x1", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + EXPECT_EQ("0,-1 360x1", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("0,0 360x1", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + + layout.offset = 250; + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + EXPECT_EQ("250,0 110x1", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("250,-1 110x1", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + EXPECT_EQ("250,-1 110x1", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("250,0 110x1", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + + layout.position = DisplayLayout::BOTTOM; + layout.offset = 0; + display_manager->SetLayoutForCurrentDisplays(layout); + event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); + EXPECT_EQ("0,359 360x1", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("0,360 360x1", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); + EXPECT_EQ("0,360 360x1", + mouse_warp_controller()->src_indicator_bounds_.ToString()); + EXPECT_EQ("0,359 360x1", + mouse_warp_controller()->dst_indicator_bounds_.ToString()); + + event_filter()->HideSharedEdgeIndicator(); +} + +} // namespace ash
diff --git a/ash/display/mirror_window_controller.cc b/ash/display/mirror_window_controller.cc index c7e5acf0..8fb7767 100644 --- a/ash/display/mirror_window_controller.cc +++ b/ash/display/mirror_window_controller.cc
@@ -76,6 +76,11 @@ } // namespace +MirrorWindowController::MirroringHostInfo::MirroringHostInfo() { +} +MirrorWindowController::MirroringHostInfo::~MirroringHostInfo() { +} + MirrorWindowController::MirrorWindowController() {} MirrorWindowController::~MirrorWindowController() { @@ -83,93 +88,187 @@ Close(); } -void MirrorWindowController::UpdateWindow(const DisplayInfo& display_info) { +void MirrorWindowController::UpdateWindow( + const std::vector<DisplayInfo>& display_info_list) { static int mirror_host_count = 0; - if (!ash_host_.get()) { - AshWindowTreeHostInitParams init_params; - init_params.initial_bounds = display_info.bounds_in_native(); - ash_host_.reset(AshWindowTreeHost::Create(init_params)); - aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); - host->window()->SetName( - base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++)); - host->compositor()->SetBackgroundColor(SK_ColorBLACK); - // No need to remove the observer because the DisplayController outlives the - // host. - host->AddObserver(Shell::GetInstance()->display_controller()); - host->AddObserver(this); - // TODO(oshima): TouchHUD is using idkey. - InitRootWindowSettings(host->window())->display_id = display_info.id(); - host->InitHost(); + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + const gfx::Display& primary = Shell::GetScreen()->GetPrimaryDisplay(); + const DisplayInfo& source_display_info = + display_manager->GetDisplayInfo(primary.id()); + + gfx::Point mirroring_origin; + for (const DisplayInfo& display_info : display_info_list) { + if (mirroring_host_info_map_.find(display_info.id()) == + mirroring_host_info_map_.end()) { + AshWindowTreeHostInitParams init_params; + init_params.initial_bounds = display_info.bounds_in_native(); + MirroringHostInfo* host_info = new MirroringHostInfo; + host_info->ash_host.reset(AshWindowTreeHost::Create(init_params)); + mirroring_host_info_map_[display_info.id()] = host_info; + + aura::WindowTreeHost* host = host_info->ash_host->AsWindowTreeHost(); + host->window()->SetName( + base::StringPrintf("MirrorRootWindow-%d", mirror_host_count++)); + host->compositor()->SetBackgroundColor(SK_ColorBLACK); + // No need to remove the observer because the DisplayController outlives + // the + // host. + host->AddObserver(Shell::GetInstance()->display_controller()); + host->AddObserver(this); + // TODO(oshima): TouchHUD is using idkey. + InitRootWindowSettings(host->window())->display_id = display_info.id(); + host->InitHost(); #if defined(USE_X11) - DisableInput(host->GetAcceleratedWidget()); + if (display_manager->multi_display_mode() != DisplayManager::UNIFIED) + DisableInput(host->GetAcceleratedWidget()); #endif - aura::client::SetCaptureClient(host->window(), new NoneCaptureClient()); - host->Show(); +#if defined(OS_CHROMEOS) + if (display_manager->multi_display_mode() == DisplayManager::UNIFIED) { + host_info->ash_host->ConfineCursorToRootWindow(); + AshWindowTreeHost* unified_ash_host = + Shell::GetInstance() + ->display_controller() + ->GetAshWindowTreeHostForDisplayId( + Shell::GetScreen()->GetPrimaryDisplay().id()); + unified_ash_host->RegisterMirroringHost(host_info->ash_host.get()); + } +#endif - // TODO(oshima): Start mirroring. - aura::Window* mirror_window = new aura::Window(NULL); - mirror_window->Init(ui::LAYER_SOLID_COLOR); - host->window()->AddChild(mirror_window); - mirror_window->SetBounds(host->window()->bounds()); - mirror_window->Show(); - reflector_ = aura::Env::GetInstance()->context_factory()->CreateReflector( - Shell::GetPrimaryRootWindow()->GetHost()->compositor(), - mirror_window->layer()); - } else { - aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); - GetRootWindowSettings(host->window())->display_id = display_info.id(); - host->SetBounds(display_info.bounds_in_native()); + aura::client::SetCaptureClient(host->window(), new NoneCaptureClient()); + host->Show(); + + aura::Window* mirror_window = host_info->mirror_window = + new aura::Window(nullptr); + mirror_window->Init(ui::LAYER_SOLID_COLOR); + host->window()->AddChild(mirror_window); + mirror_window->SetBounds(host->window()->bounds()); + mirror_window->Show(); + if (reflector_) { + // TODO(oshima): Enable this once reflect change is landed. + // reflector_->AddMirroringLayer(mirror_window->layer()); + } else { + reflector_ = + aura::Env::GetInstance()->context_factory()->CreateReflector( + Shell::GetPrimaryRootWindow()->GetHost()->compositor(), + mirror_window->layer()); + } + } else { + aura::WindowTreeHost* host = mirroring_host_info_map_[display_info.id()] + ->ash_host->AsWindowTreeHost(); + GetRootWindowSettings(host->window())->display_id = display_info.id(); + host->SetBounds(display_info.bounds_in_native()); + } + + AshWindowTreeHost* mirroring_ash_host = + mirroring_host_info_map_[display_info.id()]->ash_host.get(); + switch (display_manager->multi_display_mode()) { + case DisplayManager::MIRRORING: { + scoped_ptr<RootWindowTransformer> transformer( + CreateRootWindowTransformerForMirroredDisplay(source_display_info, + display_info)); + mirroring_ash_host->SetRootWindowTransformer(transformer.Pass()); + break; + } + case DisplayManager::UNIFIED: { + gfx::Display display; + display.SetScaleAndBounds( + 1.0f, gfx::Rect(mirroring_origin, + display_info.bounds_in_native().size())); + mirroring_origin.SetPoint(display.bounds().right(), 0); + scoped_ptr<RootWindowTransformer> transformer( + CreateRootWindowTransformerForUnifiedDesktop(primary.bounds(), + display)); + mirroring_ash_host->SetRootWindowTransformer(transformer.Pass()); + break; + } + case DisplayManager::EXTENDED: + NOTREACHED(); + } } - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - const DisplayInfo& source_display_info = display_manager->GetDisplayInfo( - Shell::GetScreen()->GetPrimaryDisplay().id()); - DCHECK(display_manager->IsInMirrorMode()); - scoped_ptr<RootWindowTransformer> transformer( - CreateRootWindowTransformerForMirroredDisplay(source_display_info, - display_info)); - ash_host_->SetRootWindowTransformer(transformer.Pass()); + // Deleting WTHs for disconnected displays. + if (mirroring_host_info_map_.size() > display_info_list.size()) { + for (MirroringHostInfoMap::iterator iter = mirroring_host_info_map_.begin(); + iter != mirroring_host_info_map_.end();) { + if (std::find_if(display_info_list.begin(), display_info_list.end(), + [iter](const DisplayInfo& info) { + return info.id() == iter->first; + }) == display_info_list.end()) { + CloseAndDeleteHost(iter->second); + iter = mirroring_host_info_map_.erase(iter); + } else { + ++iter; + } + } + } } void MirrorWindowController::UpdateWindow() { - if (ash_host_.get()) { - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - const DisplayInfo& mirror_display_info = display_manager->GetDisplayInfo( - display_manager->mirroring_display_id()); - UpdateWindow(mirror_display_info); - } + if (!mirroring_host_info_map_.size()) + return; + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + std::vector<DisplayInfo> display_info_list; + for (auto& pair : mirroring_host_info_map_) + display_info_list.push_back(display_manager->GetDisplayInfo(pair.first)); + UpdateWindow(display_info_list); } void MirrorWindowController::Close() { - if (ash_host_.get()) { - aura::WindowTreeHost* host = ash_host_->AsWindowTreeHost(); + for (auto& info : mirroring_host_info_map_) { + CloseAndDeleteHost(info.second); + } + mirroring_host_info_map_.clear(); + if (reflector_) { aura::Env::GetInstance()->context_factory()->RemoveReflector( reflector_.get()); - reflector_ = nullptr; - NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( - aura::client::GetCaptureClient(host->window())); - aura::client::SetCaptureClient(host->window(), NULL); - delete capture_client; - - host->RemoveObserver(Shell::GetInstance()->display_controller()); - host->RemoveObserver(this); - ash_host_.reset(); + reflector_.reset(); } } void MirrorWindowController::OnHostResized(const aura::WindowTreeHost* host) { - if (mirror_window_host_size_ == host->GetBounds().size()) - return; - mirror_window_host_size_ = host->GetBounds().size(); - reflector_->OnMirroringCompositorResized(); - ash_host_->SetRootWindowTransformer(CreateRootWindowTransformer().Pass()); - Shell::GetInstance()->display_controller()->cursor_window_controller()-> - UpdateLocation(); + for (auto& pair : mirroring_host_info_map_) { + MirroringHostInfo* info = pair.second; + if (info->ash_host->AsWindowTreeHost() == host) { + if (info->mirror_window_host_size == host->GetBounds().size()) + return; + info->mirror_window_host_size = host->GetBounds().size(); + reflector_->OnMirroringCompositorResized(); + info->ash_host->SetRootWindowTransformer( + CreateRootWindowTransformer().Pass()); + Shell::GetInstance() + ->display_controller() + ->cursor_window_controller() + ->UpdateLocation(); + return; + } + } } aura::Window* MirrorWindowController::GetWindow() { - return ash_host_.get() ? ash_host_->AsWindowTreeHost()->window() : NULL; + DisplayManager* display_manager = Shell::GetInstance()->display_manager(); + if (display_manager->multi_display_mode() != DisplayManager::MIRRORING || + mirroring_host_info_map_.empty()) { + return nullptr; + } + + DCHECK_EQ(1U, mirroring_host_info_map_.size()); + return mirroring_host_info_map_.begin() + ->second->ash_host->AsWindowTreeHost() + ->window(); +} + +void MirrorWindowController::CloseAndDeleteHost(MirroringHostInfo* host_info) { + aura::WindowTreeHost* host = host_info->ash_host->AsWindowTreeHost(); + NoneCaptureClient* capture_client = static_cast<NoneCaptureClient*>( + aura::client::GetCaptureClient(host->window())); + aura::client::SetCaptureClient(host->window(), NULL); + delete capture_client; + + host->RemoveObserver(Shell::GetInstance()->display_controller()); + host->RemoveObserver(this); + // reflector_->RemoveMirroringLayer(host_info->mirror_window->layer()); + delete host_info; } scoped_ptr<RootWindowTransformer>
diff --git a/ash/display/mirror_window_controller.h b/ash/display/mirror_window_controller.h index 5b24cc6..39adef51 100644 --- a/ash/display/mirror_window_controller.h +++ b/ash/display/mirror_window_controller.h
@@ -5,6 +5,9 @@ #ifndef ASH_DISPLAY_MIRROR_WINDOW_CONTROLLER_H_ #define ASH_DISPLAY_MIRROR_WINDOW_CONTROLLER_H_ +#include <map> +#include <vector> + #include "ash/ash_export.h" #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" @@ -40,7 +43,7 @@ // Updates the root window's bounds using |display_info|. // Creates the new root window if one doesn't exist. - void UpdateWindow(const DisplayInfo& display_info); + void UpdateWindow(const std::vector<DisplayInfo>& display_info); // Same as above, but using existing display info // for the mirrored display. @@ -59,12 +62,23 @@ private: friend class test::MirrorWindowTestApi; + struct MirroringHostInfo { + MirroringHostInfo(); + ~MirroringHostInfo(); + scoped_ptr<AshWindowTreeHost> ash_host; + gfx::Size mirror_window_host_size; + aura::Window* mirror_window = nullptr; + }; + + void CloseAndDeleteHost(MirroringHostInfo* host_info); + // Creates a RootWindowTransformer for current display // configuration. scoped_ptr<RootWindowTransformer> CreateRootWindowTransformer() const; - scoped_ptr<AshWindowTreeHost> ash_host_; - gfx::Size mirror_window_host_size_; + typedef std::map<int64_t, MirroringHostInfo*> MirroringHostInfoMap; + MirroringHostInfoMap mirroring_host_info_map_; + scoped_ptr<ui::Reflector> reflector_; DISALLOW_COPY_AND_ASSIGN(MirrorWindowController);
diff --git a/ash/display/mirror_window_controller_unittest.cc b/ash/display/mirror_window_controller_unittest.cc index c1fe0cb..822f4f8 100644 --- a/ash/display/mirror_window_controller_unittest.cc +++ b/ash/display/mirror_window_controller_unittest.cc
@@ -77,7 +77,7 @@ test_window_delegate.set_window_component(HTTOP); DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); UpdateDisplay("400x400,400x400"); aura::Window* root = Shell::GetInstance()->GetPrimaryRootWindow(); scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate( @@ -127,7 +127,7 @@ test_window_delegate.set_window_component(HTTOP); DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); UpdateDisplay("400x400,400x400"); aura::Window* root = Shell::GetInstance()->GetPrimaryRootWindow(); scoped_ptr<aura::Window> window(aura::test::CreateTestWindowWithDelegate( @@ -182,7 +182,7 @@ TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorLocations) { test::MirrorWindowTestApi test_api; DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); // Test with device scale factor. UpdateDisplay("400x600*2,400x600"); @@ -236,7 +236,7 @@ EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); EXPECT_EQ(gfx::Display::ROTATE_0, cursor_test_api.GetCurrentCursorRotation()); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); UpdateDisplay("400x400*2/r,400x400"); // Entering mirror mode should have centered the cursor on the primary display @@ -271,7 +271,7 @@ CreateDisplayInfo(external_id, gfx::Rect(1, 1, 100, 100)); std::vector<DisplayInfo> display_info_list; - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); // software mirroring. display_info_list.push_back(internal_display_info); @@ -289,7 +289,7 @@ // dock mode. display_info_list.clear(); display_info_list.push_back(external_display_info); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); display_manager->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager->GetNumDisplays()); EXPECT_FALSE(display_manager->IsInMirrorMode()); @@ -298,7 +298,7 @@ display_info_list.clear(); display_info_list.push_back(internal_display_info); display_info_list.push_back(external_display_info); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); display_manager->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager->GetNumDisplays()); EXPECT_TRUE(display_manager->IsInMirrorMode());
diff --git a/ash/display/mouse_cursor_event_filter.cc b/ash/display/mouse_cursor_event_filter.cc index e904881..c043c7ca 100644 --- a/ash/display/mouse_cursor_event_filter.cc +++ b/ash/display/mouse_cursor_event_filter.cc
@@ -7,142 +7,28 @@ #include <cmath> #include "ash/display/cursor_window_controller.h" -#include "ash/display/display_controller.h" #include "ash/display/display_manager.h" -#include "ash/display/shared_display_edge_indicator.h" -#include "ash/host/ash_window_tree_host.h" -#include "ash/root_window_controller.h" -#include "ash/screen_util.h" +#include "ash/display/mouse_warp_controller.h" #include "ash/shell.h" -#include "ash/wm/window_util.h" -#include "ui/aura/env.h" -#include "ui/aura/window.h" -#include "ui/aura/window_event_dispatcher.h" -#include "ui/aura/window_tree_host.h" -#include "ui/base/layout.h" -#include "ui/compositor/dip_util.h" -#include "ui/events/event.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/screen.h" -#include "ui/wm/core/coordinate_conversion.h" namespace ash { -namespace { -// Maximum size on the display edge that initiate snapping phantom window, -// from the corner of the display. -const int kMaximumSnapHeight = 16; - -// Minimum height of an indicator on the display edge that allows -// dragging a window. If two displays shares the edge smaller than -// this, entire edge will be used as a draggable space. -const int kMinimumIndicatorHeight = 200; - -const int kIndicatorThickness = 1; - -void ConvertPointFromScreenToNative(const aura::Window* root_window, - gfx::Point* point) { - ::wm::ConvertPointFromScreen(root_window, point); - root_window->GetHost()->ConvertPointToNativeScreen(point); -} - -gfx::Rect GetNativeEdgeBounds(const aura::Window* root_window, - gfx::Point start, - gfx::Point end) { - gfx::Rect native_bounds = root_window->GetHost()->GetBounds(); - native_bounds.Inset( - GetRootWindowController(root_window)->ash_host()->GetHostInsets()); - - ConvertPointFromScreenToNative(root_window, &start); - ConvertPointFromScreenToNative(root_window, &end); - if (start.x() == end.x()) { - // vertical in native - int x = std::abs(native_bounds.x() - start.x()) < - std::abs(native_bounds.right() - start.x()) - ? native_bounds.x() - : native_bounds.right() - 1; - return gfx::Rect( - x, std::min(start.y(), end.y()), 1, std::abs(start.y() - end.y())); - } else { - // horizontal in native - int y = std::abs(native_bounds.y() - start.y()) < - std::abs(native_bounds.bottom() - start.y()) - ? native_bounds.y() - : native_bounds.bottom() - 1; - return gfx::Rect( - std::min(start.x(), end.x()), y, std::abs(start.x() - end.x()), 1); - } -} - -// Creates edge bounds from indicator bounds that fits the edge -// of the native window for |root_window|. -gfx::Rect CreateVerticalEdgeBoundsInNative(const aura::Window* root_window, - const gfx::Rect& indicator_bounds) { - gfx::Point start = indicator_bounds.origin(); - gfx::Point end = start; - end.set_y(indicator_bounds.bottom()); - return GetNativeEdgeBounds(root_window, start, end); -} - -gfx::Rect CreateHorizontalEdgeBoundsInNative( - const aura::Window* root_window, - const gfx::Rect& indicator_bounds) { - gfx::Point start = indicator_bounds.origin(); - gfx::Point end = start; - end.set_x(indicator_bounds.right()); - return GetNativeEdgeBounds(root_window, start, end); -} - -void MovePointInside(const gfx::Rect& native_bounds, - gfx::Point* point_in_native) { - if (native_bounds.x() > point_in_native->x()) - point_in_native->set_x(native_bounds.x()); - if (native_bounds.right() < point_in_native->x()) - point_in_native->set_x(native_bounds.right()); - - if (native_bounds.y() > point_in_native->y()) - point_in_native->set_y(native_bounds.y()); - if (native_bounds.bottom() < point_in_native->y()) - point_in_native->set_y(native_bounds.bottom()); -} - -} // namespace - -MouseCursorEventFilter::MouseCursorEventFilter() - : mouse_warp_enabled_(true), - drag_source_root_(NULL), - shared_display_edge_indicator_(new SharedDisplayEdgeIndicator) { +MouseCursorEventFilter::MouseCursorEventFilter() : mouse_warp_enabled_(true) { Shell::GetInstance()->display_controller()->AddObserver(this); } MouseCursorEventFilter::~MouseCursorEventFilter() { - HideSharedEdgeIndicator(); Shell::GetInstance()->display_controller()->RemoveObserver(this); } void MouseCursorEventFilter::ShowSharedEdgeIndicator(aura::Window* from) { - HideSharedEdgeIndicator(); - if (Shell::GetScreen()->GetNumDisplays() <= 1 || from == NULL) { - src_indicator_bounds_.SetRect(0, 0, 0, 0); - dst_indicator_bounds_.SetRect(0, 0, 0, 0); - drag_source_root_ = NULL; - return; - } - drag_source_root_ = from; - - DisplayLayout::Position position = Shell::GetInstance()-> - display_manager()->GetCurrentDisplayLayout().position; - if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) - UpdateHorizontalEdgeBounds(); - else - UpdateVerticalEdgeBounds(); - - shared_display_edge_indicator_->Show(src_indicator_bounds_, - dst_indicator_bounds_); + mouse_warp_controller_ = Shell::GetInstance() + ->display_manager() + ->CreateMouseWarpController(from) + .Pass(); } void MouseCursorEventFilter::HideSharedEdgeIndicator() { - shared_display_edge_indicator_->Hide(); OnDisplayConfigurationChanged(); } @@ -151,25 +37,10 @@ } void MouseCursorEventFilter::OnDisplayConfigurationChanged() { - // Extra check for |num_connected_displays()| is for SystemDisplayApiTest - // that injects MockScreen. - if (Shell::GetScreen()->GetNumDisplays() <= 1 || - Shell::GetInstance()->display_manager()->num_connected_displays() <= 1) { - src_edge_bounds_in_native_.SetRect(0, 0, 0, 0); - dst_edge_bounds_in_native_.SetRect(0, 0, 0, 0); - return; - } - - drag_source_root_ = NULL; - DisplayLayout::Position position = Shell::GetInstance() - ->display_manager() - ->GetCurrentDisplayLayout() - .position; - - if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) - UpdateHorizontalEdgeBounds(); - else - UpdateVerticalEdgeBounds(); + mouse_warp_controller_ = Shell::GetInstance() + ->display_manager() + ->CreateMouseWarpController(nullptr) + .Pass(); } void MouseCursorEventFilter::OnMouseEvent(ui::MouseEvent* event) { @@ -184,196 +55,8 @@ Shell::GetInstance()->display_controller()-> cursor_window_controller()->UpdateLocation(); - if (WarpMouseCursorIfNecessary(event)) + if (mouse_warp_enabled_ && mouse_warp_controller_->WarpMouseCursor(event)) event->StopPropagation(); } -// static -void MouseCursorEventFilter::MoveCursorTo(aura::Window* root, - const gfx::Point& point_in_screen) { - gfx::Point point_in_native = point_in_screen; - ::wm::ConvertPointFromScreen(root, &point_in_native); - root->GetHost()->ConvertPointToNativeScreen(&point_in_native); - - // now fit the point inside the native bounds. - gfx::Rect native_bounds = root->GetHost()->GetBounds(); - gfx::Point native_origin = native_bounds.origin(); - native_bounds.Inset( - GetRootWindowController(root)->ash_host()->GetHostInsets()); - // Shrink further so that the mouse doesn't warp on the - // edge. The right/bottom needs to be shrink by 2 to subtract - // the 1 px from width/height value. - native_bounds.Inset(1, 1, 2, 2); - - MovePointInside(native_bounds, &point_in_native); - gfx::Point point_in_host = point_in_native; - - point_in_host.Offset(-native_origin.x(), -native_origin.y()); - root->GetHost()->MoveCursorToHostLocation(point_in_host); -} - -bool MouseCursorEventFilter::WarpMouseCursorIfNecessary(ui::MouseEvent* event) { - if (!event->HasNativeEvent()) - return false; - - gfx::Point point_in_native = - ui::EventSystemLocationFromNative(event->native_event()); - - aura::Window* target = static_cast<aura::Window*>(event->target()); -#if defined(USE_OZONE) - // TODO(dnicoara): crbug.com/415680 Move cursor warping into Ozone once Ozone - // has access to the logical display layout. - // Native events in Ozone are in the native window coordinate system. We need - // to translate them to get the global position. - point_in_native.Offset(target->GetHost()->GetBounds().x(), - target->GetHost()->GetBounds().y()); -#endif - gfx::Point point_in_screen = event->location(); - ::wm::ConvertPointToScreen(target, &point_in_screen); - - return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen); -} - -bool MouseCursorEventFilter::WarpMouseCursorInNativeCoords( - const gfx::Point& point_in_native, - const gfx::Point& point_in_screen) { - if (Shell::GetScreen()->GetNumDisplays() <= 1 || !mouse_warp_enabled_) - return false; - - bool in_src_edge = src_edge_bounds_in_native_.Contains(point_in_native); - bool in_dst_edge = dst_edge_bounds_in_native_.Contains(point_in_native); - if (!in_src_edge && !in_dst_edge) - return false; - - // The mouse must move. - aura::Window* src_root = NULL; - aura::Window* dst_root = NULL; - GetSrcAndDstRootWindows(&src_root, &dst_root); - - if (in_src_edge) - MoveCursorTo(dst_root, point_in_screen); - else - MoveCursorTo(src_root, point_in_screen); - - return true; -} - -void MouseCursorEventFilter::UpdateHorizontalEdgeBounds() { - bool from_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; - // GetPrimaryDisplay returns an object on stack, so copy the bounds - // instead of using reference. - const gfx::Rect primary_bounds = - Shell::GetScreen()->GetPrimaryDisplay().bounds(); - const gfx::Rect secondary_bounds = ScreenUtil::GetSecondaryDisplay().bounds(); - DisplayLayout::Position position = Shell::GetInstance()-> - display_manager()->GetCurrentDisplayLayout().position; - - src_indicator_bounds_.set_x( - std::max(primary_bounds.x(), secondary_bounds.x())); - src_indicator_bounds_.set_width( - std::min(primary_bounds.right(), secondary_bounds.right()) - - src_indicator_bounds_.x()); - src_indicator_bounds_.set_height(kIndicatorThickness); - src_indicator_bounds_.set_y( - position == DisplayLayout::TOP ? - primary_bounds.y() - (from_primary ? 0 : kIndicatorThickness) : - primary_bounds.bottom() - (from_primary ? kIndicatorThickness : 0)); - - dst_indicator_bounds_ = src_indicator_bounds_; - dst_indicator_bounds_.set_height(kIndicatorThickness); - dst_indicator_bounds_.set_y( - position == DisplayLayout::TOP ? - primary_bounds.y() - (from_primary ? kIndicatorThickness : 0) : - primary_bounds.bottom() - (from_primary ? 0 : kIndicatorThickness)); - - aura::Window* src_root = NULL; - aura::Window* dst_root = NULL; - GetSrcAndDstRootWindows(&src_root, &dst_root); - - src_edge_bounds_in_native_ = - CreateHorizontalEdgeBoundsInNative(src_root, src_indicator_bounds_); - dst_edge_bounds_in_native_ = - CreateHorizontalEdgeBoundsInNative(dst_root, dst_indicator_bounds_); -} - -void MouseCursorEventFilter::UpdateVerticalEdgeBounds() { - int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0; - bool in_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; - // GetPrimaryDisplay returns an object on stack, so copy the bounds - // instead of using reference. - const gfx::Rect primary_bounds = - Shell::GetScreen()->GetPrimaryDisplay().bounds(); - const gfx::Rect secondary_bounds = ScreenUtil::GetSecondaryDisplay().bounds(); - DisplayLayout::Position position = Shell::GetInstance()-> - display_manager()->GetCurrentDisplayLayout().position; - - int upper_shared_y = std::max(primary_bounds.y(), secondary_bounds.y()); - int lower_shared_y = std::min(primary_bounds.bottom(), - secondary_bounds.bottom()); - int shared_height = lower_shared_y - upper_shared_y; - - int dst_x = position == DisplayLayout::LEFT ? - primary_bounds.x() - (in_primary ? kIndicatorThickness : 0) : - primary_bounds.right() - (in_primary ? 0 : kIndicatorThickness); - dst_indicator_bounds_.SetRect( - dst_x, upper_shared_y, kIndicatorThickness, shared_height); - - // The indicator on the source display. - src_indicator_bounds_.set_width(kIndicatorThickness); - src_indicator_bounds_.set_x( - position == DisplayLayout::LEFT ? - primary_bounds.x() - (in_primary ? 0 : kIndicatorThickness) : - primary_bounds.right() - (in_primary ? kIndicatorThickness : 0)); - - const gfx::Rect& source_bounds = - in_primary ? primary_bounds : secondary_bounds; - int upper_indicator_y = source_bounds.y() + snap_height; - int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y); - - // This gives a hight that can be used without sacrifying the snap space. - int available_space = lower_indicator_y - - std::max(upper_shared_y, upper_indicator_y); - - if (shared_height < kMinimumIndicatorHeight) { - // If the shared height is smaller than minimum height, use the - // entire height. - upper_indicator_y = upper_shared_y; - } else if (available_space < kMinimumIndicatorHeight) { - // Snap to the bottom. - upper_indicator_y = - std::max(upper_shared_y, lower_indicator_y + kMinimumIndicatorHeight); - } else { - upper_indicator_y = std::max(upper_indicator_y, upper_shared_y); - } - src_indicator_bounds_.set_y(upper_indicator_y); - src_indicator_bounds_.set_height(lower_indicator_y - upper_indicator_y); - - aura::Window* src_root = NULL; - aura::Window* dst_root = NULL; - GetSrcAndDstRootWindows(&src_root, &dst_root); - - // Native - src_edge_bounds_in_native_ = - CreateVerticalEdgeBoundsInNative(src_root, src_indicator_bounds_); - dst_edge_bounds_in_native_ = - CreateVerticalEdgeBoundsInNative(dst_root, dst_indicator_bounds_); -} - -void MouseCursorEventFilter::GetSrcAndDstRootWindows(aura::Window** src_root, - aura::Window** dst_root) { - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - *src_root = drag_source_root_ ? drag_source_root_ - : Shell::GetInstance()->GetPrimaryRootWindow(); - *dst_root = root_windows[0] == *src_root ? root_windows[1] : root_windows[0]; -} - -bool MouseCursorEventFilter::WarpMouseCursorIfNecessaryForTest( - aura::Window* target_root, - const gfx::Point& point_in_screen) { - gfx::Point native = point_in_screen; - ::wm::ConvertPointFromScreen(target_root, &native); - target_root->GetHost()->ConvertPointToNativeScreen(&native); - return WarpMouseCursorInNativeCoords(native, point_in_screen); -} - } // namespace ash
diff --git a/ash/display/mouse_cursor_event_filter.h b/ash/display/mouse_cursor_event_filter.h index 44496cf..eafcd2e 100644 --- a/ash/display/mouse_cursor_event_filter.h +++ b/ash/display/mouse_cursor_event_filter.h
@@ -19,7 +19,7 @@ } namespace ash { -class SharedDisplayEdgeIndicator; +class DisplayEdgeController; // An event filter that controls mouse location in extended desktop // environment. @@ -44,66 +44,22 @@ void OnMouseEvent(ui::MouseEvent* event) override; private: - friend class DragWindowResizerTest; + friend class test::DisplayManagerTestApi; + friend class ExtendedMouseWarpControllerTest; friend class MouseCursorEventFilterTest; FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest, DoNotWarpTwice); FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest, SetMouseWarpModeFlag); FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest, - IndicatorBoundsTestOnRight); - FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest, - IndicatorBoundsTestOnLeft); - FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest, - IndicatorBoundsTestOnTopBottom); - FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplaysInNative); - FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, WarpMousePointer); - // Moves the cursor to the point inside the root that is closest to - // the point_in_screen, which is outside of the root window. - static void MoveCursorTo(aura::Window* root, - const gfx::Point& point_in_screen); - - // Warps the mouse cursor to an alternate root window when the - // mouse location in |event|, hits the edge of the event target's root and - // the mouse cursor is considered to be in an alternate display. - // Returns true if/ the cursor was moved. - bool WarpMouseCursorIfNecessary(ui::MouseEvent* event); - - bool WarpMouseCursorInNativeCoords(const gfx::Point& point_in_native, - const gfx::Point& point_in_screen); - - // Update the edge/indicator bounds based on the current - // display configuration. - void UpdateHorizontalEdgeBounds(); - void UpdateVerticalEdgeBounds(); - - // Returns the source and destination window. When |src_window| is - // |drag_soruce_root_| when it is set. Otherwise, the |src_window| - // is always the primary root window, because there is no difference - // between moving src to dst and moving dst to src. - void GetSrcAndDstRootWindows(aura::Window** src_window, - aura::Window** dst_window); - - bool WarpMouseCursorIfNecessaryForTest(aura::Window* target_root, - const gfx::Point& point_in_screen); + MouseWarpController* mouse_warp_controller_for_test() { + return mouse_warp_controller_.get(); + } bool mouse_warp_enabled_; - // The bounds for warp hole windows. |dst_indicator_bounds_| is kept - // in the instance for testing. - gfx::Rect src_indicator_bounds_; - gfx::Rect dst_indicator_bounds_; - - gfx::Rect src_edge_bounds_in_native_; - gfx::Rect dst_edge_bounds_in_native_; - - // The root window in which the dragging started. - aura::Window* drag_source_root_; - - // Shows the area where a window can be dragged in to/out from - // another display. - scoped_ptr<SharedDisplayEdgeIndicator> shared_display_edge_indicator_; + scoped_ptr<MouseWarpController> mouse_warp_controller_; DISALLOW_COPY_AND_ASSIGN(MouseCursorEventFilter); };
diff --git a/ash/display/mouse_cursor_event_filter_unittest.cc b/ash/display/mouse_cursor_event_filter_unittest.cc index 58a1a0f..fe0554ab 100644 --- a/ash/display/mouse_cursor_event_filter_unittest.cc +++ b/ash/display/mouse_cursor_event_filter_unittest.cc
@@ -4,16 +4,14 @@ #include "ash/display/mouse_cursor_event_filter.h" +#include "ash/display/display_layout_store.h" +#include "ash/display/display_manager.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/test/cursor_manager_test_api.h" -#include "ash/display/display_layout_store.h" -#include "ash/display/display_manager.h" +#include "ash/test/display_manager_test_api.h" #include "ui/aura/env.h" -#include "ui/aura/window_event_dispatcher.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/display.h" -#include "ui/gfx/screen.h" +#include "ui/events/test/event_generator.h" namespace ash { @@ -27,30 +25,9 @@ return Shell::GetInstance()->mouse_cursor_filter(); } - bool WarpMouseCursorIfNecessary(aura::Window* target_root, - gfx::Point point_in_screen) { - bool is_warped = event_filter()->WarpMouseCursorIfNecessaryForTest( - target_root, point_in_screen); - return is_warped; - } - - bool WarpMouseCursorIfNecessaryWithDragRoot( - aura::Window* drag_source_root, - aura::Window* target_root, - gfx::Point point_in_screen) { - gfx::Point location = drag_source_root->bounds().CenterPoint(); - ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, location, location, - ui::EventTimeForNow(), 0, 0); - ui::Event::DispatcherApi(&pressed).set_target(drag_source_root); - event_filter()->OnMouseEvent(&pressed); - bool is_warped = event_filter()->WarpMouseCursorIfNecessaryForTest( - target_root, point_in_screen); - - ui::MouseEvent released(ui::ET_MOUSE_RELEASED, location, location, - ui::EventTimeForNow(), 0, 0); - ui::Event::DispatcherApi(&released).set_target(drag_source_root); - event_filter()->OnMouseEvent(&released); - return is_warped; + bool TestIfMouseWarpsAt(const gfx::Point& point_in_screen) { + return test::DisplayManagerTestApi::TestIfMouseWarpsAt(GetEventGenerator(), + point_in_screen); } private: @@ -70,35 +47,30 @@ Shell::GetInstance()->display_manager()->layout_store()-> default_display_layout().position); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(11, 11))); - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(11, 11))); + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(11, 11))); // Touch the right edge of the primary root window. Pointer should warp. - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(499, 11))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(499, 11))); EXPECT_EQ("501,11", // by 2px. aura::Env::GetInstance()->last_mouse_location().ToString()); // Touch the left edge of the secondary root window. Pointer should warp. - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(500, 11))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(500, 11))); EXPECT_EQ("498,11", // by 2px. aura::Env::GetInstance()->last_mouse_location().ToString()); // Touch the left edge of the primary root window. - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(0, 11))); + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(0, 11))); // Touch the top edge of the primary root window. - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(11, 0))); + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(11, 0))); // Touch the bottom edge of the primary root window. - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(11, 499))); + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(11, 499))); // Touch the right edge of the secondary root window. - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1], - gfx::Point(999, 11))); + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(999, 11))); // Touch the top edge of the secondary root window. - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(11, 0))); + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(11, 0))); // Touch the bottom edge of the secondary root window. - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1], - gfx::Point(11, 499))); + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(11, 499))); } // Verifies if the mouse pointer correctly moves to another display even when @@ -114,19 +86,15 @@ Shell::GetInstance()->display_manager()-> GetCurrentDisplayLayout().position); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(623, 123)); - // Touch the left edge of the secondary root window. Pointer should NOT warp // because 1px left of (0, 500) is outside the primary root window. - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(0, 500))); - EXPECT_EQ("623,123", // by 2px. + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(501, 500))); + EXPECT_EQ("501,500", aura::Env::GetInstance()->last_mouse_location().ToString()); // Touch the left edge of the secondary root window. Pointer should warp // because 1px left of (0, 480) is inside the primary root window. - EXPECT_TRUE( - WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(500, 480))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(500, 480))); EXPECT_EQ("498,480", // by 2px. aura::Env::GetInstance()->last_mouse_location().ToString()); } @@ -146,166 +114,39 @@ ->GetCurrentDisplayLayout() .position); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(900, 123)); - EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest( - root_windows[0], gfx::Point(499, 123))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(499, 123))); EXPECT_EQ("500,123", aura::Env::GetInstance()->last_mouse_location().ToString()); - // Touch the edge of 2nd display again and make sure it warps to // 1st dislay. - EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest( - root_windows[1], gfx::Point(500, 123))); - EXPECT_EQ("498,123", + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(500, 123))); + // TODO(oshima): Due to a bug in EventGenerator, the screen coordinates + // is shrinked by dsf once. Fix this. + EXPECT_EQ("498,61", aura::Env::GetInstance()->last_mouse_location().ToString()); } -// Verifies if MouseCursorEventFilter::set_mouse_warp_mode() works as expected. +// Verifies if MouseCursorEventFilter::set_mouse_warp_enabled() works as +// expected. TEST_F(MouseCursorEventFilterTest, SetMouseWarpModeFlag) { if (!SupportsMultipleDisplays()) return; UpdateDisplay("500x500,500x500"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(1, 1)); - event_filter()->set_mouse_warp_enabled(false); - EXPECT_FALSE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(499, 11))); - EXPECT_EQ("1,1", + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(499, 11))); + EXPECT_EQ("499,11", aura::Env::GetInstance()->last_mouse_location().ToString()); + event_filter()->set_mouse_warp_enabled(true); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(499, 11))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(499, 11))); EXPECT_EQ("501,11", aura::Env::GetInstance()->last_mouse_location().ToString()); } -// Verifies if MouseCursorEventFilter's bounds calculation works correctly. -TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnRight) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("360x360,700x700"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - DisplayLayout layout(DisplayLayout::RIGHT, 0); - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("360,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - EXPECT_EQ("360,16 1x344", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("359,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); - - // Move 2nd display downwards a bit. - layout.offset = 5; - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - // This is same as before because the 2nd display's y is above - // the indicator's x. - EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("360,5 1x355", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - EXPECT_EQ("360,21 1x339", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("359,5 1x355", event_filter()->dst_indicator_bounds_.ToString()); - - // Move it down further so that the shared edge is shorter than - // minimum hole size (160). - layout.offset = 200; - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - EXPECT_EQ("359,200 1x160", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("360,200 1x160", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - EXPECT_EQ("360,200 1x160", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("359,200 1x160", event_filter()->dst_indicator_bounds_.ToString()); - - // Now move 2nd display upwards - layout.offset = -5; - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - EXPECT_EQ("359,16 1x344", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("360,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - // 16 px are reserved on 2nd display from top, so y must be - // (16 - 5) = 11 - EXPECT_EQ("360,11 1x349", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("359,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); - - event_filter()->HideSharedEdgeIndicator(); -} - -TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnLeft) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("360x360,700x700"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - DisplayLayout layout(DisplayLayout::LEFT, 0); - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - EXPECT_EQ("0,16 1x344", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("-1,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - EXPECT_EQ("-1,16 1x344", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("0,0 1x360", event_filter()->dst_indicator_bounds_.ToString()); - - layout.offset = 250; - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - EXPECT_EQ("0,250 1x110", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("-1,250 1x110", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - EXPECT_EQ("-1,250 1x110", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("0,250 1x110", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->HideSharedEdgeIndicator(); -} - -TEST_F(MouseCursorEventFilterTest, IndicatorBoundsTestOnTopBottom) { - if (!SupportsMultipleDisplays()) - return; - - UpdateDisplay("360x360,700x700"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - DisplayLayout layout(DisplayLayout::TOP, 0); - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - EXPECT_EQ("0,0 360x1", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("0,-1 360x1", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - EXPECT_EQ("0,-1 360x1", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("0,0 360x1", event_filter()->dst_indicator_bounds_.ToString()); - - layout.offset = 250; - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - EXPECT_EQ("250,0 110x1", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("250,-1 110x1", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - EXPECT_EQ("250,-1 110x1", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("250,0 110x1", event_filter()->dst_indicator_bounds_.ToString()); - - layout.position = DisplayLayout::BOTTOM; - layout.offset = 0; - display_manager->SetLayoutForCurrentDisplays(layout); - event_filter()->ShowSharedEdgeIndicator(root_windows[0] /* primary */); - EXPECT_EQ("0,359 360x1", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("0,360 360x1", event_filter()->dst_indicator_bounds_.ToString()); - event_filter()->ShowSharedEdgeIndicator(root_windows[1] /* secondary */); - EXPECT_EQ("0,360 360x1", event_filter()->src_indicator_bounds_.ToString()); - EXPECT_EQ("0,359 360x1", event_filter()->dst_indicator_bounds_.ToString()); - - event_filter()->HideSharedEdgeIndicator(); -} - // Verifies cursor's device scale factor is updated when a cursor has moved // across root windows with different device scale factors // (http://crbug.com/154183). @@ -317,15 +158,13 @@ DisplayManager* display_manager = Shell::GetInstance()->display_manager(); display_manager->SetLayoutForCurrentDisplays( DisplayLayout(DisplayLayout::RIGHT, 0)); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - ASSERT_EQ(2U, root_windows.size()); test::CursorManagerTestApi cursor_test_api( Shell::GetInstance()->cursor_manager()); EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); - WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200)); + TestIfMouseWarpsAt(gfx::Point(399, 200)); EXPECT_EQ(2.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); - WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200)); + TestIfMouseWarpsAt(gfx::Point(400, 200)); EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); }
diff --git a/ash/display/mouse_warp_controller.h b/ash/display/mouse_warp_controller.h new file mode 100644 index 0000000..19ba9ac --- /dev/null +++ b/ash/display/mouse_warp_controller.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 ASH_DISPLAY_MOUSE_WARP_CONTROLLER_H +#define ASH_DISPLAY_MOUSE_WARP_CONTROLLER_H + +#include "ash/ash_export.h" +#include "base/macros.h" + +namespace ui { +class MouseEvent; +} + +namespace ash { + +// MouseWarpController implements the mouse warp behavior for +// different display modes and platforms. +class ASH_EXPORT MouseWarpController { + public: + virtual ~MouseWarpController() {} + + // An implementaion may warp the mouse cursor to another display + // when necessary. Returns true if the mouse cursor has been + // moved to another display, or false otherwise. + virtual bool WarpMouseCursor(ui::MouseEvent* event) = 0; +}; + +} // namespace ash + +#endif // ASH_DISPLAY_MOUSE_WARP_CONTROLLER_H
diff --git a/ash/display/null_mouse_warp_controller.cc b/ash/display/null_mouse_warp_controller.cc new file mode 100644 index 0000000..efe6b88 --- /dev/null +++ b/ash/display/null_mouse_warp_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 "ash/display/null_mouse_warp_controller.h" + +namespace ash { + +bool NullMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) { + return false; +} + +} // namespace ash
diff --git a/ash/display/null_mouse_warp_controller.h b/ash/display/null_mouse_warp_controller.h new file mode 100644 index 0000000..3b3789c --- /dev/null +++ b/ash/display/null_mouse_warp_controller.h
@@ -0,0 +1,27 @@ +// 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 ASH_DISPLAY_NULL_MOUSE_WARP_CONTROLLER_H +#define ASH_DISPLAY_NULL_MOUSE_WARP_CONTROLLER_H + +#include "ash/display/mouse_warp_controller.h" + +namespace ash { + +// A MouseWarpController when there is one desktop display +// (in single display or mirror mode). +class NullMouseWarpController : public MouseWarpController { + public: + NullMouseWarpController() {} + + // MouseWarpController: + bool WarpMouseCursor(ui::MouseEvent* event) override; + + private: + DISALLOW_COPY_AND_ASSIGN(NullMouseWarpController); +}; + +} // namespace ash + +#endif // ASH_DISPLAY_MOUSE_WARP_CONTROLLER_H
diff --git a/ash/display/root_window_transformers.cc b/ash/display/root_window_transformers.cc index 509bb8e..6a9eea3 100644 --- a/ash/display/root_window_transformers.cc +++ b/ash/display/root_window_transformers.cc
@@ -62,16 +62,18 @@ // updating the transform results in incorrectly resizing // the root window. Don't apply the transform unless // necessary so that unit tests pass on win8 bots. - if (info.rotation() == root_window->GetProperty(kRotationPropertyKey)) + if (info.GetActiveRotation() == + root_window->GetProperty(kRotationPropertyKey)) { return gfx::Transform(); - root_window->SetProperty(kRotationPropertyKey, info.rotation()); + } + root_window->SetProperty(kRotationPropertyKey, info.GetActiveRotation()); #endif gfx::Transform rotate; // The origin is (0, 0), so the translate width/height must be reduced by // 1 pixel. float one_pixel = 1.0f / display.device_scale_factor(); - switch (info.rotation()) { + switch (info.GetActiveRotation()) { case gfx::Display::ROTATE_0: break; case gfx::Display::ROTATE_90: @@ -273,6 +275,37 @@ DISALLOW_COPY_AND_ASSIGN(MirrorRootWindowTransformer); }; +class PartialBoundsRootWindowTransformer : public RootWindowTransformer { + public: + PartialBoundsRootWindowTransformer(const gfx::Rect& screen_bounds, + const gfx::Display& display) { + gfx::SizeF root_size(display.bounds().size()); + root_size.Scale(display.device_scale_factor()); + root_bounds_ = gfx::Rect(gfx::ToFlooredSize(root_size)); + + transform_.Translate(-SkIntToMScalar(display.bounds().x()), + -SkIntToMScalar(display.bounds().y())); + } + + // RootWindowTransformer: + gfx::Transform GetTransform() const override { return transform_; } + gfx::Transform GetInverseTransform() const override { + gfx::Transform invert; + CHECK(transform_.GetInverse(&invert)); + return invert; + } + gfx::Rect GetRootWindowBounds(const gfx::Size& host_size) const override { + return root_bounds_; + } + gfx::Insets GetHostInsets() const override { return gfx::Insets(); } + + private: + gfx::Transform transform_; + gfx::Rect root_bounds_; + + DISALLOW_COPY_AND_ASSIGN(PartialBoundsRootWindowTransformer); +}; + } // namespace RootWindowTransformer* CreateRootWindowTransformerForDisplay( @@ -288,4 +321,10 @@ mirror_display_info); } +RootWindowTransformer* CreateRootWindowTransformerForUnifiedDesktop( + const gfx::Rect& screen_bounds, + const gfx::Display& display) { + return new PartialBoundsRootWindowTransformer(screen_bounds, display); +} + } // namespace ash
diff --git a/ash/display/root_window_transformers.h b/ash/display/root_window_transformers.h index b41ccdf..61ccea7f 100644 --- a/ash/display/root_window_transformers.h +++ b/ash/display/root_window_transformers.h
@@ -13,6 +13,7 @@ namespace gfx { class Display; +class Rect; class Transform; } @@ -32,6 +33,13 @@ const DisplayInfo& source_display_info, const DisplayInfo& mirror_display_info); +// Creates a RootWindowTransformers for unified desktop mode. +// |screen_bounds| specifies the unified desktop's bounds and +// |display| specifies the display used to mirror the unified desktop. +ASH_EXPORT RootWindowTransformer* CreateRootWindowTransformerForUnifiedDesktop( + const gfx::Rect& screen_bounds, + const gfx::Display& display); + } // namespace ash #endif // ASH_DISPLAY_ROOT_WINDOW_TRANSFORMERS_H_
diff --git a/ash/display/root_window_transformers_unittest.cc b/ash/display/root_window_transformers_unittest.cc index 17c8b36..1036b318 100644 --- a/ash/display/root_window_transformers_unittest.cc +++ b/ash/display/root_window_transformers_unittest.cc
@@ -107,10 +107,6 @@ DISALLOW_COPY_AND_ASSIGN(TestEventHandler); }; -gfx::Display::Rotation GetStoredRotation(int64 id) { - return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation(); -} - float GetStoredUIScale(int64 id) { return Shell::GetInstance()->display_manager()->GetDisplayInfo(id). GetEffectiveUIScale(); @@ -158,12 +154,12 @@ EXPECT_EQ("50,90", event_handler.GetLocationAndReset()); EXPECT_EQ("50,90", aura::Env::GetInstance()->last_mouse_location().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id())); - EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id)); + EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display1.id())); + EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display2_id)); magnifier->SetEnabled(false); - display_manager->SetDisplayRotation(display1.id(), - gfx::Display::ROTATE_90); + display_manager->SetDisplayRotation(display1.id(), gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_ACTIVE); // Move the cursor to the center of the first root window. generator1.MoveMouseToInHost(59, 100); @@ -177,8 +173,8 @@ EXPECT_EQ("110,70", event_handler.GetLocationAndReset()); EXPECT_EQ("110,70", aura::Env::GetInstance()->last_mouse_location().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id())); - EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id)); + EXPECT_EQ(gfx::Display::ROTATE_90, GetActiveDisplayRotation(display1.id())); + EXPECT_EQ(gfx::Display::ROTATE_0, GetActiveDisplayRotation(display2_id)); magnifier->SetEnabled(false); DisplayLayout display_layout(DisplayLayout::BOTTOM, 50); @@ -186,8 +182,8 @@ EXPECT_EQ("50,120 150x200", ScreenUtil::GetSecondaryDisplay().bounds().ToString()); - display_manager->SetDisplayRotation(display2_id, - gfx::Display::ROTATE_270); + display_manager->SetDisplayRotation(display2_id, gfx::Display::ROTATE_270, + gfx::Display::ROTATION_SOURCE_ACTIVE); // Move the cursor to the center of the second root window. generator2.MoveMouseToInHost(151, 199); @@ -200,12 +196,12 @@ EXPECT_EQ("95,80", event_handler.GetLocationAndReset()); EXPECT_EQ("145,200", aura::Env::GetInstance()->last_mouse_location().ToString()); - EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id())); - EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id)); + EXPECT_EQ(gfx::Display::ROTATE_90, GetActiveDisplayRotation(display1.id())); + EXPECT_EQ(gfx::Display::ROTATE_270, GetActiveDisplayRotation(display2_id)); magnifier->SetEnabled(false); - display_manager->SetDisplayRotation(display1.id(), - gfx::Display::ROTATE_180); + display_manager->SetDisplayRotation(display1.id(), gfx::Display::ROTATE_180, + gfx::Display::ROTATION_SOURCE_ACTIVE); // Move the cursor to the center of the first root window. generator1.MoveMouseToInHost(59, 99); @@ -217,8 +213,8 @@ ScreenUtil::GetSecondaryDisplay().bounds().ToString()); generator1.MoveMouseToInHost(39, 59); EXPECT_EQ("70,120", event_handler.GetLocationAndReset()); - EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id())); - EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id)); + EXPECT_EQ(gfx::Display::ROTATE_180, GetActiveDisplayRotation(display1.id())); + EXPECT_EQ(gfx::Display::ROTATE_270, GetActiveDisplayRotation(display2_id)); magnifier->SetEnabled(false); Shell::GetInstance()->RemovePreTargetHandler(&event_handler); @@ -397,7 +393,7 @@ return; test::MirrorWindowTestApi test_api; DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); UpdateDisplay("400x200,500x500"); scoped_ptr<RootWindowTransformer> transformer( test_api.CreateCurrentRootWindowTransformer());
diff --git a/ash/display/screen_ash.cc b/ash/display/screen_ash.cc index 700abe6..5941bcc 100644 --- a/ash/display/screen_ash.cc +++ b/ash/display/screen_ash.cc
@@ -165,8 +165,9 @@ DisplayManager* display_manager = GetDisplayManager(); // RootWindow needs Display to determine its device scale factor // for non desktop display. - if (display_manager->software_mirroring_display().id() == id) - return display_manager->software_mirroring_display(); + gfx::Display mirroring_display = display_manager->GetMirroringDisplayById(id); + if (mirroring_display.is_valid()) + return mirroring_display; return display_manager->GetDisplayForId(id); }
diff --git a/ash/drag_drop/OWNERS b/ash/drag_drop/OWNERS index 5762b1c..d231d19d 100644 --- a/ash/drag_drop/OWNERS +++ b/ash/drag_drop/OWNERS
@@ -1 +1 @@ -varunjain@chromium.org +mfomitchev@chromium.org
diff --git a/ash/host/ash_window_tree_host.h b/ash/host/ash_window_tree_host.h index 321ee25..fab7afd 100644 --- a/ash/host/ash_window_tree_host.h +++ b/ash/host/ash_window_tree_host.h
@@ -55,6 +55,8 @@ // Stop listening for events in preparation for shutdown. virtual void PrepareForShutdown() {} + virtual void RegisterMirroringHost(AshWindowTreeHost* mirroring_ash_host) {} + protected: // Translates the native mouse location into screen coordinates. void TranslateLocatedEvent(ui::LocatedEvent* event);
diff --git a/ash/host/ash_window_tree_host_init_params.cc b/ash/host/ash_window_tree_host_init_params.cc index 55d15c03..ae1f58e 100644 --- a/ash/host/ash_window_tree_host_init_params.cc +++ b/ash/host/ash_window_tree_host_init_params.cc
@@ -6,11 +6,13 @@ namespace ash { +AshWindowTreeHostInitParams::AshWindowTreeHostInitParams() + : offscreen(false) #if defined(OS_WIN) -AshWindowTreeHostInitParams::AshWindowTreeHostInitParams() : remote_hwnd(NULL) { -#else -AshWindowTreeHostInitParams::AshWindowTreeHostInitParams() { + , + remote_hwnd(NULL) #endif +{ } AshWindowTreeHostInitParams::~AshWindowTreeHostInitParams() {
diff --git a/ash/host/ash_window_tree_host_init_params.h b/ash/host/ash_window_tree_host_init_params.h index d9bb7de..bc584d8 100644 --- a/ash/host/ash_window_tree_host_init_params.h +++ b/ash/host/ash_window_tree_host_init_params.h
@@ -22,6 +22,8 @@ gfx::Rect initial_bounds; + bool offscreen; + #if defined(OS_WIN) HWND remote_hwnd; #endif
diff --git a/ash/host/ash_window_tree_host_ozone.cc b/ash/host/ash_window_tree_host_ozone.cc index cb2ec66..e45bf5d 100644 --- a/ash/host/ash_window_tree_host_ozone.cc +++ b/ash/host/ash_window_tree_host_ozone.cc
@@ -5,6 +5,7 @@ #include "ash/host/ash_window_tree_host.h" #include "ash/host/ash_window_tree_host_init_params.h" +#include "ash/host/ash_window_tree_host_unified.h" #include "ash/host/root_window_transformer.h" #include "ash/host/transformer_helper.h" #include "base/command_line.h" @@ -144,6 +145,8 @@ AshWindowTreeHost* AshWindowTreeHost::Create( const AshWindowTreeHostInitParams& init_params) { + if (init_params.offscreen) + return new AshWindowTreeHostUnified(init_params.initial_bounds); return new AshWindowTreeHostOzone(init_params.initial_bounds); }
diff --git a/ash/host/ash_window_tree_host_unified.cc b/ash/host/ash_window_tree_host_unified.cc new file mode 100644 index 0000000..4317365f --- /dev/null +++ b/ash/host/ash_window_tree_host_unified.cc
@@ -0,0 +1,164 @@ +// 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 "ash/host/ash_window_tree_host_unified.h" +#include "ash/host/root_window_transformer.h" +#include "base/logging.h" +#include "ui/aura/window.h" +#include "ui/aura/window_event_dispatcher.h" +#include "ui/aura/window_targeter.h" +#include "ui/compositor/compositor.h" +#include "ui/events/event_processor.h" +#include "ui/gfx/geometry/insets.h" + +namespace ash { + +class UnifiedEventTargeter : public aura::WindowTargeter { + public: + UnifiedEventTargeter(aura::Window* src_root, aura::Window* dst_root) + : src_root_(src_root), dst_root_(dst_root) {} + + ui::EventTarget* FindTargetForEvent(ui::EventTarget* root, + ui::Event* event) override { + if (root == src_root_ && !event->target()) { + if (event->IsLocatedEvent()) { + ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event); + located_event->ConvertLocationToTarget( + static_cast<aura::Window*>(nullptr), dst_root_); + located_event->UpdateForRootTransform( + dst_root_->GetHost()->GetRootTransform()); + } + ignore_result( + dst_root_->GetHost()->event_processor()->OnEventFromSource(event)); + return nullptr; + } else { + LOG(ERROR) << "Handling Event:" << event->type(); + return aura::WindowTargeter::FindTargetForEvent(root, event); + } + } + + aura::Window* src_root_; + aura::Window* dst_root_; + + DISALLOW_COPY_AND_ASSIGN(UnifiedEventTargeter); +}; + +AshWindowTreeHostUnified::AshWindowTreeHostUnified( + const gfx::Rect& initial_bounds) + : bounds_(gfx::Rect(initial_bounds.size())) { + CreateCompositor(GetAcceleratedWidget()); +} + +AshWindowTreeHostUnified::~AshWindowTreeHostUnified() { + DestroyCompositor(); + DestroyDispatcher(); +} + +void AshWindowTreeHostUnified::PrepareForShutdown() { + for (auto host : mirroring_hosts_) + host->PrepareForShutdown(); +} + +void AshWindowTreeHostUnified::RegisterMirroringHost( + AshWindowTreeHost* mirroring_ash_host) { + aura::Window* src_root = mirroring_ash_host->AsWindowTreeHost()->window(); + src_root->SetEventTargeter( + make_scoped_ptr(new UnifiedEventTargeter(src_root, window()))); + DCHECK(std::find(mirroring_hosts_.begin(), mirroring_hosts_.end(), + mirroring_ash_host) == mirroring_hosts_.end()); + mirroring_hosts_.push_back(mirroring_ash_host); + mirroring_ash_host->AsWindowTreeHost()->window()->AddObserver(this); +} + +void AshWindowTreeHostUnified::ToggleFullScreen() { +} + +bool AshWindowTreeHostUnified::ConfineCursorToRootWindow() { + return true; +} + +void AshWindowTreeHostUnified::UnConfineCursor() { +} + +void AshWindowTreeHostUnified::SetRootWindowTransformer( + scoped_ptr<RootWindowTransformer> transformer) { + // TODO(oshima): Find out if this is neceessary. + NOTIMPLEMENTED(); +} + +gfx::Insets AshWindowTreeHostUnified::GetHostInsets() const { + return gfx::Insets(); +} + +aura::WindowTreeHost* AshWindowTreeHostUnified::AsWindowTreeHost() { + return this; +} + +ui::EventSource* AshWindowTreeHostUnified::GetEventSource() { + return this; +} + +gfx::AcceleratedWidget AshWindowTreeHostUnified::GetAcceleratedWidget() { + // TODO(oshima): Enable offscreen compositor. + return gfx::kNullAcceleratedWidget; +} + +void AshWindowTreeHostUnified::Show() { +} + +void AshWindowTreeHostUnified::Hide() { +} + +gfx::Rect AshWindowTreeHostUnified::GetBounds() const { + return bounds_; +} + +void AshWindowTreeHostUnified::SetBounds(const gfx::Rect& bounds) { + if (bounds_.size() == bounds.size()) + return; + bounds_.set_size(bounds.size()); + OnHostResized(bounds_.size()); +} + +void AshWindowTreeHostUnified::SetCapture() { +} + +void AshWindowTreeHostUnified::ReleaseCapture() { +} + +gfx::Point AshWindowTreeHostUnified::GetLocationOnNativeScreen() const { + return gfx::Point(); +} + +void AshWindowTreeHostUnified::SetCursorNative(gfx::NativeCursor cursor) { + for (auto host : mirroring_hosts_) + host->AsWindowTreeHost()->SetCursor(cursor); +} + +void AshWindowTreeHostUnified::MoveCursorToNative(const gfx::Point& location) { + // TODO(oshima): Find out if this is neceessary. + NOTIMPLEMENTED(); +} + +void AshWindowTreeHostUnified::OnCursorVisibilityChangedNative(bool show) { + for (auto host : mirroring_hosts_) + host->AsWindowTreeHost()->OnCursorVisibilityChanged(show); +} + +void AshWindowTreeHostUnified::OnWindowDestroying(aura::Window* window) { + auto iter = + std::find_if(mirroring_hosts_.begin(), mirroring_hosts_.end(), + [window](AshWindowTreeHost* ash_host) { + return ash_host->AsWindowTreeHost()->window() == window; + }); + DCHECK(iter != mirroring_hosts_.end()); + window->RemoveObserver(this); + mirroring_hosts_.erase(iter); +} + +ui::EventProcessor* AshWindowTreeHostUnified::GetEventProcessor() { + return dispatcher(); +} + +} // namespace ash
diff --git a/ash/host/ash_window_tree_host_unified.h b/ash/host/ash_window_tree_host_unified.h new file mode 100644 index 0000000..024b8dfd --- /dev/null +++ b/ash/host/ash_window_tree_host_unified.h
@@ -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. + +#ifndef ASH_HOST_ASH_WINDOW_TREE_HOST_UNIFIED_H_ +#define ASH_HOST_ASH_WINDOW_TREE_HOST_UNIFIED_H_ + +#include <vector> + +#include "ash/host/ash_window_tree_host.h" +#include "ui/aura/window_observer.h" +#include "ui/aura/window_tree_host.h" +#include "ui/events/event_source.h" +#include "ui/gfx/geometry/rect.h" + +namespace ui { +class Reflector; +} + +namespace ash { +class DisplayInfo; + +// A WTH used for unified desktop mode. This creates an offscreen +// compositor whose texture will be copied into each displays' +// compositor. +class AshWindowTreeHostUnified : public AshWindowTreeHost, + public aura::WindowTreeHost, + public aura::WindowObserver, + public ui::EventSource { + public: + explicit AshWindowTreeHostUnified(const gfx::Rect& initial_bounds); + ~AshWindowTreeHostUnified() override; + + private: + // AshWindowTreeHost: + void ToggleFullScreen() override; + bool ConfineCursorToRootWindow() override; + void UnConfineCursor() override; + void SetRootWindowTransformer( + scoped_ptr<RootWindowTransformer> transformer) override; + gfx::Insets GetHostInsets() const override; + aura::WindowTreeHost* AsWindowTreeHost() override; + void PrepareForShutdown() override; + void RegisterMirroringHost(AshWindowTreeHost* mirroring_ash_host) override; + + // aura::WindowTreeHost: + ui::EventSource* GetEventSource() override; + gfx::AcceleratedWidget GetAcceleratedWidget() override; + void Show() override; + void Hide() override; + gfx::Rect GetBounds() const override; + void SetBounds(const gfx::Rect& bounds) override; + void SetCapture() override; + void ReleaseCapture() override; + gfx::Point GetLocationOnNativeScreen() const override; + void SetCursorNative(gfx::NativeCursor cursor) override; + void MoveCursorToNative(const gfx::Point& location) override; + void OnCursorVisibilityChangedNative(bool show) override; + + // aura::WindowObserver: + void OnWindowDestroying(aura::Window* window) override; + + // ui::EventSource: + ui::EventProcessor* GetEventProcessor() override; + + std::vector<AshWindowTreeHost*> mirroring_hosts_; + + gfx::Rect bounds_; + + DISALLOW_COPY_AND_ASSIGN(AshWindowTreeHostUnified); +}; + +} // namespace ash + +#endif // ASH_HOST_ASH_WINDOW_TREE_HOST_UNIFIED_H_
diff --git a/ash/host/ash_window_tree_host_x11.cc b/ash/host/ash_window_tree_host_x11.cc index 882ef13..c82d9154 100644 --- a/ash/host/ash_window_tree_host_x11.cc +++ b/ash/host/ash_window_tree_host_x11.cc
@@ -13,6 +13,7 @@ #include <vector> #include "ash/host/ash_window_tree_host_init_params.h" +#include "ash/host/ash_window_tree_host_unified.h" #include "ash/host/root_window_transformer.h" #include "base/basictypes.h" #include "base/sys_info.h" @@ -280,6 +281,8 @@ AshWindowTreeHost* AshWindowTreeHost::Create( const AshWindowTreeHostInitParams& init_params) { + if (init_params.offscreen) + return new AshWindowTreeHostUnified(init_params.initial_bounds); return new AshWindowTreeHostX11(init_params.initial_bounds); }
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc index ccdcb8f4..f7e1f42 100644 --- a/ash/metrics/user_metrics_recorder.cc +++ b/ash/metrics/user_metrics_recorder.cc
@@ -4,11 +4,13 @@ #include "ash/metrics/user_metrics_recorder.h" +#include "ash/session/session_state_delegate.h" #include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_view.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/shell_window_ids.h" +#include "ash/system/tray/system_tray_delegate.h" #include "ash/wm/window_state.h" #include "base/metrics/histogram.h" #include "base/metrics/user_metrics.h" @@ -64,6 +66,31 @@ return active_window_state_type; } +// Returns true if kiosk mode is active. +bool IsKioskModeActive() { + return Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus() == + user::LOGGED_IN_KIOSK_APP; +} + +// Returns true if there is an active user and their session isn't currently +// locked. +bool IsUserActive() { + switch (Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus()) { + case user::LOGGED_IN_NONE: + case user::LOGGED_IN_LOCKED: + return false; + case user::LOGGED_IN_USER: + case user::LOGGED_IN_OWNER: + case user::LOGGED_IN_GUEST: + case user::LOGGED_IN_PUBLIC: + case user::LOGGED_IN_SUPERVISED: + case user::LOGGED_IN_KIOSK_APP: + return true; + } + NOTREACHED(); + return false; +} + // Array of window container ids that contain visible windows to be counted for // UMA statistics. Note the containers are ordered from top most visible // container to the lowest to allow the |GetNumVisibleWindows| method to short @@ -124,10 +151,12 @@ } // namespace UserMetricsRecorder::UserMetricsRecorder() { - timer_.Start(FROM_HERE, - base::TimeDelta::FromSeconds(kAshPeriodicMetricsTimeInSeconds), - this, - &UserMetricsRecorder::RecordPeriodicMetrics); + StartTimer(); +} + +UserMetricsRecorder::UserMetricsRecorder(bool record_periodic_metrics) { + if (record_periodic_metrics) + StartTimer(); } UserMetricsRecorder::~UserMetricsRecorder() { @@ -203,6 +232,9 @@ case ash::UMA_LAUNCHER_LAUNCH_TASK: base::RecordAction(base::UserMetricsAction("Launcher_LaunchTask")); break; + case ash::UMA_LAUNCHER_MINIMIZE_TASK: + base::RecordAction(base::UserMetricsAction("Launcher_MinimizeTask")); + break; case ash::UMA_LAUNCHER_SWITCH_TASK: base::RecordAction(base::UserMetricsAction("Launcher_SwitchTask")); break; @@ -522,7 +554,10 @@ void UserMetricsRecorder::RecordPeriodicMetrics() { ShelfLayoutManager* manager = ShelfLayoutManager::ForShelf(Shell::GetPrimaryRootWindow()); + // TODO(bruthig): Investigating whether the check for |manager| is necessary + // and add tests if it is. if (manager) { + // TODO(bruthig): Consider tracking the time spent in each alignment. UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentOverTime", manager->SelectValueForShelfAlignment( SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM, @@ -532,12 +567,28 @@ SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT); } - UMA_HISTOGRAM_COUNTS_100("Ash.NumberOfVisibleWindowsInPrimaryDisplay", - GetNumVisibleWindowsInPrimaryDisplay()); + if (IsUserInActiveDesktopEnvironment()) { + UMA_HISTOGRAM_COUNTS_100("Ash.NumberOfVisibleWindowsInPrimaryDisplay", + GetNumVisibleWindowsInPrimaryDisplay()); + } + // TODO(bruthig): Find out if this should only be logged when the user is + // active. + // TODO(bruthig): Consider tracking how long a particular type of window is + // active at a time. UMA_HISTOGRAM_ENUMERATION("Ash.ActiveWindowShowTypeOverTime", GetActiveWindowState(), ACTIVE_WINDOW_STATE_TYPE_COUNT); } +bool UserMetricsRecorder::IsUserInActiveDesktopEnvironment() const { + return IsUserActive() && !IsKioskModeActive(); +} + +void UserMetricsRecorder::StartTimer() { + timer_.Start(FROM_HERE, + base::TimeDelta::FromSeconds(kAshPeriodicMetricsTimeInSeconds), + this, &UserMetricsRecorder::RecordPeriodicMetrics); +} + } // namespace ash
diff --git a/ash/metrics/user_metrics_recorder.h b/ash/metrics/user_metrics_recorder.h index 7c27326..a2f5fb1 100644 --- a/ash/metrics/user_metrics_recorder.h +++ b/ash/metrics/user_metrics_recorder.h
@@ -10,6 +10,10 @@ namespace ash { +namespace test { +class UserMetricsRecorderTestAPI; +} + enum UserMetricsAction { UMA_ACCEL_EXIT_FIRST_Q, UMA_ACCEL_EXIT_SECOND_Q, @@ -30,6 +34,7 @@ UMA_LAUNCHER_CLICK_ON_APP, UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON, UMA_LAUNCHER_LAUNCH_TASK, + UMA_LAUNCHER_MINIMIZE_TASK, UMA_LAUNCHER_SWITCH_TASK, UMA_MAXIMIZE_MODE_DISABLED, UMA_MAXIMIZE_MODE_ENABLED, @@ -128,14 +133,40 @@ // (RecordUserMetricsAction) are passed through the UserMetricsRecorder. class ASH_EXPORT UserMetricsRecorder { public: + // Creates a UserMetricsRecorder that records metrics periodically. Equivalent + // to calling UserMetricsRecorder(true). UserMetricsRecorder(); - ~UserMetricsRecorder(); + virtual ~UserMetricsRecorder(); + + // Records an Ash owned user action. void RecordUserMetricsAction(ash::UserMetricsAction action); + private: + friend class test::UserMetricsRecorderTestAPI; + + // Creates a UserMetricsRecorder and will only record periodic metrics if + // |record_periodic_metrics| is true. This is used by tests that do not want + // the timer to be started. + // TODO(bruthig): Add a constructor that accepts a base::RepeatingTimer so + // that tests can inject a test double that can be controlled by the test. The + // missing piece is a suitable base::RepeatingTimer test double. + explicit UserMetricsRecorder(bool record_periodic_metrics); + + // Records UMA metrics. Invoked periodically by the |timer_|. void RecordPeriodicMetrics(); + // Returns true if the user's session is active and they are in a desktop + // environment. + bool IsUserInActiveDesktopEnvironment() const; + + // Starts the |timer_| and binds it to |RecordPeriodicMetrics|. + void StartTimer(); + + // The periodic timer that triggers metrics to be recorded. base::RepeatingTimer<UserMetricsRecorder> timer_; + + DISALLOW_COPY_AND_ASSIGN(UserMetricsRecorder); }; } // namespace ash
diff --git a/ash/metrics/user_metrics_recorder_unittest.cc b/ash/metrics/user_metrics_recorder_unittest.cc new file mode 100644 index 0000000..04cbd1cd --- /dev/null +++ b/ash/metrics/user_metrics_recorder_unittest.cc
@@ -0,0 +1,162 @@ +// 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 "ash/metrics/user_metrics_recorder.h" + +#include "ash/shell.h" +#include "ash/system/user/login_status.h" +#include "ash/test/ash_test_base.h" +#include "ash/test/test_system_tray_delegate.h" +#include "ash/test/user_metrics_recorder_test_api.h" +#include "base/memory/scoped_ptr.h" +#include "base/test/histogram_tester.h" +#include "ui/aura/window.h" + +namespace ash { +namespace { + +const char kAsh_NumberOfVisibleWindowsInPrimaryDisplay[] = + "Ash.NumberOfVisibleWindowsInPrimaryDisplay"; + +const char kAsh_ActiveWindowShowTypeOverTime[] = + "Ash.ActiveWindowShowTypeOverTime"; + +} // namespace + +// Test fixture for the UserMetricsRecorder class. +class UserMetricsRecorderTest : public test::AshTestBase { + public: + UserMetricsRecorderTest(); + ~UserMetricsRecorderTest() override; + + // test::AshTestBase: + void SetUp() override; + void TearDown() override; + + // Sets the user login status. + void SetLoginStatus(user::LoginStatus login_status); + + // Sets the current user session to be active or inactive in a desktop + // environment. + void SetUserInActiveDesktopEnvironment(bool is_active); + + test::UserMetricsRecorderTestAPI* user_metrics_recorder_test_api() { + return user_metrics_recorder_test_api_.get(); + } + + base::HistogramTester& histograms() { return histograms_; } + + private: + // Test API to access private members of the test target. + scoped_ptr<test::UserMetricsRecorderTestAPI> user_metrics_recorder_test_api_; + + // Histogram value verifier. + base::HistogramTester histograms_; + + // The active SystemTrayDelegate. Not owned. + test::TestSystemTrayDelegate* test_system_tray_delegate_; + + DISALLOW_COPY_AND_ASSIGN(UserMetricsRecorderTest); +}; + +UserMetricsRecorderTest::UserMetricsRecorderTest() { +} + +UserMetricsRecorderTest::~UserMetricsRecorderTest() { +} + +void UserMetricsRecorderTest::SetUp() { + test::AshTestBase::SetUp(); + user_metrics_recorder_test_api_.reset(new test::UserMetricsRecorderTestAPI()); + test_system_tray_delegate_ = GetSystemTrayDelegate(); +} + +void UserMetricsRecorderTest::TearDown() { + test_system_tray_delegate_ = nullptr; + test::AshTestBase::TearDown(); +} + +void UserMetricsRecorderTest::SetLoginStatus(user::LoginStatus login_status) { + test_system_tray_delegate_->SetLoginStatus(login_status); +} + +void UserMetricsRecorderTest::SetUserInActiveDesktopEnvironment( + bool is_active) { + if (is_active) { + SetLoginStatus(user::LOGGED_IN_USER); + ASSERT_TRUE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + } else { + SetLoginStatus(user::LOGGED_IN_LOCKED); + ASSERT_FALSE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + } +} + +// Verifies the return value of IsUserInActiveDesktopEnvironment() for the +// different login status values. +TEST_F(UserMetricsRecorderTest, VerifyIsUserInActiveDesktopEnvironmentValues) { + SetLoginStatus(user::LOGGED_IN_NONE); + EXPECT_FALSE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + + SetLoginStatus(user::LOGGED_IN_LOCKED); + EXPECT_FALSE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + + SetLoginStatus(user::LOGGED_IN_USER); + EXPECT_TRUE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + + SetLoginStatus(user::LOGGED_IN_OWNER); + EXPECT_TRUE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + + SetLoginStatus(user::LOGGED_IN_GUEST); + EXPECT_TRUE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + + SetLoginStatus(user::LOGGED_IN_PUBLIC); + EXPECT_TRUE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + + SetLoginStatus(user::LOGGED_IN_SUPERVISED); + EXPECT_TRUE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); + + SetLoginStatus(user::LOGGED_IN_KIOSK_APP); + EXPECT_FALSE( + user_metrics_recorder_test_api()->IsUserInActiveDesktopEnvironment()); +} + +// Verifies that the IsUserInActiveDesktopEnvironment() dependent stats are not +// recorded when a user is not active in a desktop environment. +TEST_F(UserMetricsRecorderTest, + VerifyStatsRecordedWhenUserNotInActiveDesktopEnvironment) { + SetUserInActiveDesktopEnvironment(false); + user_metrics_recorder_test_api()->RecordPeriodicMetrics(); + + histograms().ExpectTotalCount(kAsh_NumberOfVisibleWindowsInPrimaryDisplay, 0); +} + +// Verifies that the IsUserInActiveDesktopEnvironment() dependent stats are +// recorded when a user is active in a desktop environment. +TEST_F(UserMetricsRecorderTest, + VerifyStatsRecordedWhenUserInActiveDesktopEnvironment) { + SetUserInActiveDesktopEnvironment(true); + user_metrics_recorder_test_api()->RecordPeriodicMetrics(); + + histograms().ExpectTotalCount(kAsh_NumberOfVisibleWindowsInPrimaryDisplay, 1); +} + +// Verifies recording of stats which are always recorded by +// RecordPeriodicMetrics. +TEST_F(UserMetricsRecorderTest, VerifyStatsRecordedByRecordPeriodicMetrics) { + SetUserInActiveDesktopEnvironment(true); + user_metrics_recorder_test_api()->RecordPeriodicMetrics(); + + histograms().ExpectTotalCount(kAsh_ActiveWindowShowTypeOverTime, 1); +} + +} // namespace ash
diff --git a/ash/rotator/screen_rotation_animator.cc b/ash/rotator/screen_rotation_animator.cc index ed37b7f..9b746b68 100644 --- a/ash/rotator/screen_rotation_animator.cc +++ b/ash/rotator/screen_rotation_animator.cc
@@ -67,7 +67,7 @@ return Shell::GetInstance() ->display_manager() ->GetDisplayInfo(display_id) - .rotation(); + .GetActiveRotation(); } // Returns true if the rotation between |initial_rotation| and |new_rotation| is @@ -103,6 +103,10 @@ void OnDetachedFromSequence(ui::LayerAnimationSequence* sequence) override; private: + // Aborts the active animations of the layer, and recurses upon its child + // layers. + void AbortAnimations(ui::Layer* layer); + // The owned layer tree. scoped_ptr<ui::LayerTreeOwner> layer_tree_owner_; @@ -123,6 +127,7 @@ // RequiresNotificationWhenAnimatorDestroyed. if (sequence_) sequence_->RemoveObserver(this); + AbortAnimations(layer_tree_owner_->root()); } ui::Layer* LayerCleanupObserver::GetRootLayer() { @@ -150,10 +155,17 @@ sequence_ = nullptr; } +void LayerCleanupObserver::AbortAnimations(ui::Layer* layer) { + for (ui::Layer* child_layer : layer->children()) + AbortAnimations(child_layer); + layer->GetAnimator()->AbortAllAnimations(); +} + // Set the screen orientation for the given |display| to |new_rotation| and // animate the change. void RotateScreen(int64 display_id, gfx::Display::Rotation new_rotation, + gfx::Display::RotationSource source, base::TimeDelta duration, int rotation_degrees, int rotation_degree_offset, @@ -181,8 +193,8 @@ scoped_ptr<LayerCleanupObserver> layer_cleanup_observer( new LayerCleanupObserver(old_layer_tree.Pass())); - Shell::GetInstance()->display_manager()->SetDisplayRotation(display_id, - new_rotation); + Shell::GetInstance()->display_manager()->SetDisplayRotation( + display_id, new_rotation, source); const gfx::RectF rotated_screen_bounds = root_window->GetTargetBounds(); const gfx::Point pivot = gfx::Point(rotated_screen_bounds.width() / 2, @@ -267,7 +279,15 @@ ScreenRotationAnimator::~ScreenRotationAnimator() { } -void ScreenRotationAnimator::Rotate(gfx::Display::Rotation new_rotation) { +bool ScreenRotationAnimator::CanAnimate() const { + return Shell::GetInstance() + ->display_manager() + ->GetDisplayForId(display_id_) + .is_valid(); +} + +void ScreenRotationAnimator::Rotate(gfx::Display::Rotation new_rotation, + gfx::Display::RotationSource source) { const gfx::Display::Rotation current_rotation = GetCurrentRotation(display_id_); @@ -279,8 +299,8 @@ switches::kAshEnableScreenRotationAnimation); if (switch_value == kRotationAnimation_None) { - Shell::GetInstance()->display_manager()->SetDisplayRotation(display_id_, - new_rotation); + Shell::GetInstance()->display_manager()->SetDisplayRotation( + display_id_, new_rotation, source); } else if (kRotationAnimation_Default == switch_value || kRotationAnimation_Partial == switch_value) { const int rotation_degree_offset = @@ -288,7 +308,7 @@ ? 180 - kPartialRotationDegrees : 90 - kPartialRotationDegrees; - RotateScreen(display_id_, new_rotation, + RotateScreen(display_id_, new_rotation, source, base::TimeDelta::FromMilliseconds(kRotationDurationInMs), kPartialRotationDegrees, rotation_degree_offset, gfx::Tween::FAST_OUT_LINEAR_IN, false /* should_scale */); @@ -296,7 +316,7 @@ const int rotation_degrees = Is180DegreeFlip(current_rotation, new_rotation) ? 180 : 90; - RotateScreen(display_id_, new_rotation, + RotateScreen(display_id_, new_rotation, source, base::TimeDelta::FromMilliseconds(kRotationDurationInMs), rotation_degrees, 0 /* rotation_degree_offset */, gfx::Tween::FAST_OUT_LINEAR_IN, true /* should_scale */);
diff --git a/ash/rotator/screen_rotation_animator.h b/ash/rotator/screen_rotation_animator.h index 055e755906..6aff4327 100644 --- a/ash/rotator/screen_rotation_animator.h +++ b/ash/rotator/screen_rotation_animator.h
@@ -17,8 +17,18 @@ explicit ScreenRotationAnimator(int64 display_id); ~ScreenRotationAnimator(); - // Rotates |display_| to the |new_rotation| orientation. - void Rotate(gfx::Display::Rotation new_rotation); + // Returns true if the screen rotation animation can be completed + // successfully. For example an animation is not possible if |display_id_| + // specifies a gfx::Display that is not currently active. See + // www.crbug.com/479503. + bool CanAnimate() const; + + // Rotates the gfx::Display specified by |display_id_| to the |new_rotation| + // orientation, for the given |source|. The rotation will also become active. + // Clients should only call |Rotate(gfx::Display::Rotation)| if |CanAnimate()| + // returns true. + void Rotate(gfx::Display::Rotation new_rotation, + gfx::Display::RotationSource source); private: // The id of the display to rotate.
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 06d6dd4..f46233c 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -1768,7 +1768,6 @@ ShelfItemDelegate::PerformedAction performed_action) { switch (performed_action) { case ShelfItemDelegate::kNoAction: - case ShelfItemDelegate::kExistingWindowMinimized: case ShelfItemDelegate::kAppListMenuShown: break; case ShelfItemDelegate::kNewWindowCreated: @@ -1779,6 +1778,10 @@ Shell::GetInstance()->metrics()->RecordUserMetricsAction( UMA_LAUNCHER_SWITCH_TASK); break; + case ShelfItemDelegate::kExistingWindowMinimized: + Shell::GetInstance()->metrics()->RecordUserMetricsAction( + UMA_LAUNCHER_MINIMIZE_TASK); + break; } }
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index beb6620..640a5c5 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -1841,6 +1841,15 @@ EXPECT_EQ(1, user_action_tester.GetActionCount("Launcher_LaunchTask")); } +// Verifies that a Launcher_MinimizeTask UMA user action is recorded when +// selecting an icon causes an existing window to be minimized. +TEST_F(ShelfViewTest, Launcher_MinimizeTaskIsRecordedWhenWindowIsMinimized) { + base::UserActionTester user_action_tester; + test_api_->RecordIconActivatedAction( + ShelfItemDelegate::kExistingWindowMinimized); + EXPECT_EQ(1, user_action_tester.GetActionCount("Launcher_MinimizeTask")); +} + // Verifies that a Launcher_SwitchTask UMA user action is recorded when // selecting an icon causes an existing window to be activated. TEST_F(ShelfViewTest,
diff --git a/ash/shell.cc b/ash/shell.cc index 6bf50fe0..024c87d 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -485,9 +485,11 @@ #if defined(OS_CHROMEOS) bool Shell::ShouldSaveDisplaySettings() { + // TODO(oshima): Allow saving the settings even in unified desktop mode. return !(screen_orientation_controller_ ->ignore_display_configuration_updates() || - resolution_notification_controller_->DoesNotificationTimeout()); + resolution_notification_controller_->DoesNotificationTimeout()) && + !switches::UnifiedDesktopEnabled(); } #endif
diff --git a/ash/system/audio/tray_audio.cc b/ash/system/audio/tray_audio.cc index 21c2163..7260fc0 100644 --- a/ash/system/audio/tray_audio.cc +++ b/ash/system/audio/tray_audio.cc
@@ -167,7 +167,7 @@ const DisplayInfo& display_info = Shell::GetInstance()->display_manager()->GetDisplayInfo( gfx::Display::InternalDisplayId()); - if (display_info.rotation() == gfx::Display::ROTATE_180) + if (display_info.GetActiveRotation() == gfx::Display::ROTATE_180) channel_mode = system::TrayAudioDelegate::LEFT_RIGHT_SWAPPED; }
diff --git a/ash/system/chromeos/tray_display.cc b/ash/system/chromeos/tray_display.cc index aaeead2..0fd314e0 100644 --- a/ash/system/chromeos/tray_display.cc +++ b/ash/system/chromeos/tray_display.cc
@@ -207,7 +207,7 @@ base::string16 name = GetDisplayName(external_id); const DisplayInfo& display_info = display_manager->GetDisplayInfo(external_id); - if (display_info.rotation() != gfx::Display::ROTATE_0 || + if (display_info.GetActiveRotation() != gfx::Display::ROTATE_0 || display_info.configured_ui_scale() != 1.0f || !display_info.overscan_insets_in_dip().empty()) { name = l10n_util::GetStringFUTF16( @@ -263,10 +263,10 @@ bool ShouldShowFirstDisplayInfo() const { const DisplayInfo& display_info = GetDisplayManager()->GetDisplayInfo( GetDisplayManager()->first_display_id()); - return display_info.rotation() != gfx::Display::ROTATE_0 || - display_info.configured_ui_scale() != 1.0f || - !display_info.overscan_insets_in_dip().empty() || - display_info.has_overscan(); + return display_info.GetActiveRotation() != gfx::Display::ROTATE_0 || + display_info.configured_ui_scale() != 1.0f || + !display_info.overscan_insets_in_dip().empty() || + display_info.has_overscan(); } // Overridden from ActionableView. @@ -334,15 +334,15 @@ if (iter->second.configured_ui_scale() != old_iter->second.configured_ui_scale()) { - *message_out = l10n_util::GetStringFUTF16( + *additional_message_out = l10n_util::GetStringFUTF16( IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, - GetDisplayName(iter->first), - GetDisplaySize(iter->first)); + GetDisplayName(iter->first), GetDisplaySize(iter->first)); return true; } - if (iter->second.rotation() != old_iter->second.rotation()) { + if (iter->second.GetActiveRotation() != + old_iter->second.GetActiveRotation()) { int rotation_text_id = 0; - switch (iter->second.rotation()) { + switch (iter->second.GetActiveRotation()) { case gfx::Display::ROTATE_0: rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION; break; @@ -356,9 +356,8 @@ rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270; break; } - *message_out = l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, - GetDisplayName(iter->first), + *additional_message_out = l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter->first), l10n_util::GetStringUTF16(rotation_text_id)); return true; } @@ -376,7 +375,7 @@ message_center::MessageCenter::Get()->RemoveNotification( kNotificationId, false /* by_user */); - if (message.empty()) + if (message.empty() && additional_message.empty()) return; // Don't display notifications for accelerometer triggered screen rotations.
diff --git a/ash/system/chromeos/tray_display_unittest.cc b/ash/system/chromeos/tray_display_unittest.cc index e289fa24..fe761f4 100644 --- a/ash/system/chromeos/tray_display_unittest.cc +++ b/ash/system/chromeos/tray_display_unittest.cc
@@ -423,43 +423,39 @@ // rotation. UpdateDisplay("400x400/r"); - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(), - l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), - GetDisplayNotificationText()); - EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(), + l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), + GetDisplayNotificationAdditionalText()); + EXPECT_TRUE(GetDisplayNotificationText().empty()); CloseNotification(); UpdateDisplay("400x400"); - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(), - l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION)), - GetDisplayNotificationText()); - EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(), + l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION)), + GetDisplayNotificationAdditionalText()); + EXPECT_TRUE(GetDisplayNotificationText().empty()); // UI-scale CloseNotification(); UpdateDisplay("400x400@1.5"); - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, - GetFirstDisplayName(), base::UTF8ToUTF16("600x600")), - GetDisplayNotificationText()); - EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, + GetFirstDisplayName(), base::UTF8ToUTF16("600x600")), + GetDisplayNotificationAdditionalText()); + EXPECT_TRUE(GetDisplayNotificationText().empty()); // UI-scale to 1.0 CloseNotification(); UpdateDisplay("400x400"); - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, - GetFirstDisplayName(), base::UTF8ToUTF16("400x400")), - GetDisplayNotificationText()); - EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, + GetFirstDisplayName(), base::UTF8ToUTF16("400x400")), + GetDisplayNotificationAdditionalText()); + EXPECT_TRUE(GetDisplayNotificationText().empty()); // No-update CloseNotification(); @@ -497,23 +493,20 @@ // Resize the first display. UpdateDisplay("400x400@1.5,200x200"); - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, - GetFirstDisplayName(), base::UTF8ToUTF16("600x600")), - GetDisplayNotificationText()); - EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, + GetFirstDisplayName(), base::UTF8ToUTF16("600x600")), + GetDisplayNotificationAdditionalText()); + EXPECT_TRUE(GetDisplayNotificationText().empty()); // Rotate the second. UpdateDisplay("400x400@1.5,200x200/r"); - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, - GetSecondDisplayName(), - l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), - GetDisplayNotificationText()); - EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetSecondDisplayName(), + l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), + GetDisplayNotificationAdditionalText()); + EXPECT_TRUE(GetDisplayNotificationText().empty()); // Enters closed lid mode. UpdateDisplay("400x400@1.5,200x200"); @@ -563,13 +556,11 @@ // rotate the second. UpdateDisplay("400x400,200x200/r"); - EXPECT_EQ( - l10n_util::GetStringFUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, - GetSecondDisplayName(), - l10n_util::GetStringUTF16( - IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), - GetDisplayNotificationText()); + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetSecondDisplayName(), + l10n_util::GetStringUTF16( + IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), + GetDisplayNotificationAdditionalText()); } } // namespace ash
diff --git a/ash/system/date/date_default_view.cc b/ash/system/date/date_default_view.cc index ca64a1ef..35b4d36 100644 --- a/ash/system/date/date_default_view.cc +++ b/ash/system/date/date_default_view.cc
@@ -13,6 +13,7 @@ #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_popup_header_button.h" #include "ash/wm/lock_state_controller.h" +#include "base/i18n/rtl.h" #include "grit/ash_resources.h" #include "grit/ash_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -23,6 +24,10 @@ namespace { +// The ISO-639 code for the Hebrew locale. The help icon asset is a '?' which is +// not mirrored in this locale. +const char kHebrewLocale[] = "he"; + const int kPaddingVertical = 19; } // namespace @@ -58,6 +63,13 @@ this, IDR_AURA_UBER_TRAY_HELP, IDR_AURA_UBER_TRAY_HELP, IDR_AURA_UBER_TRAY_HELP_HOVER, IDR_AURA_UBER_TRAY_HELP_HOVER, IDS_ASH_STATUS_TRAY_HELP); + if (base::i18n::IsRTL() && + base::i18n::GetConfiguredLocale() == kHebrewLocale) { + // The asset for the help button is a question mark '?'. Normally this asset + // is flipped in RTL locales, however Hebrew uses the LTR '?'. So the + // flipping must be disabled. (crbug.com/475237) + help_button_->EnableCanvasFlippingForRTLUI(false); + } help_button_->SetTooltipText( l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_HELP)); view->AddButton(help_button_);
diff --git a/ash/system/overview/overview_button_tray_unittest.cc b/ash/system/overview/overview_button_tray_unittest.cc index 516a5ba..3268b7b 100644 --- a/ash/system/overview/overview_button_tray_unittest.cc +++ b/ash/system/overview/overview_button_tray_unittest.cc
@@ -189,7 +189,7 @@ new ui::ScopedAnimationDurationScaleMode( ui::ScopedAnimationDurationScaleMode::ZERO_DURATION)); ash::ScreenRotationAnimator(gfx::Display::InternalDisplayId()) - .Rotate(gfx::Display::ROTATE_270); + .Rotate(gfx::Display::ROTATE_270, gfx::Display::ROTATION_SOURCE_ACTIVE); RunAllPendingInMessageLoop(); EXPECT_FALSE(GetTray()->visible());
diff --git a/ash/system/web_notification/web_notification_tray_unittest.cc b/ash/system/web_notification/web_notification_tray_unittest.cc index 20e6893..6cf8cb1 100644 --- a/ash/system/web_notification/web_notification_tray_unittest.cc +++ b/ash/system/web_notification/web_notification_tray_unittest.cc
@@ -290,12 +290,12 @@ // http://crbug.com/263664 DisplayManager* display_manager = Shell::GetInstance()->display_manager(); - display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + display_manager->SetMultiDisplayMode(DisplayManager::MIRRORING); UpdateDisplay("400x400,200x200"); EXPECT_TRUE(GetTray()->IsPopupVisible()); EXPECT_FALSE(GetSecondaryTray()); - display_manager->SetSecondDisplayMode(DisplayManager::EXTENDED); + display_manager->SetMultiDisplayMode(DisplayManager::EXTENDED); UpdateDisplay("400x400,200x200"); EXPECT_TRUE(GetTray()->IsPopupVisible()); secondary_tray = GetSecondaryTray();
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index 6e6f78d..ffb63306 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc
@@ -202,6 +202,17 @@ return *event_generator_.get(); } +gfx::Display::Rotation AshTestBase::GetActiveDisplayRotation(int64 id) { + return Shell::GetInstance() + ->display_manager() + ->GetDisplayInfo(id) + .GetActiveRotation(); +} + +gfx::Display::Rotation AshTestBase::GetCurrentInternalDisplayRotation() { + return GetActiveDisplayRotation(gfx::Display::InternalDisplayId()); +} + bool AshTestBase::SupportsMultipleDisplays() { return AshTestHelper::SupportsMultipleDisplays(); }
diff --git a/ash/test/ash_test_base.h b/ash/test/ash_test_base.h index e877eec..bc59cbc9 100644 --- a/ash/test/ash_test_base.h +++ b/ash/test/ash_test_base.h
@@ -13,6 +13,7 @@ #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/display.h" #include "ui/wm/public/window_types.h" #if defined(OS_WIN) @@ -99,6 +100,12 @@ NUMBER_OF_BLOCK_REASONS }; + // Returns the rotation currentl active for the display |id|. + static gfx::Display::Rotation GetActiveDisplayRotation(int64 id); + + // Returns the rotation currently active for the internal display. + static gfx::Display::Rotation GetCurrentInternalDisplayRotation(); + // Proxy to AshTestHelper::SupportsMultipleDisplays(). static bool SupportsMultipleDisplays();
diff --git a/ash/test/display_manager_test_api.cc b/ash/test/display_manager_test_api.cc index 87326ee..bf5fa77 100644 --- a/ash/test/display_manager_test_api.cc +++ b/ash/test/display_manager_test_api.cc
@@ -8,9 +8,13 @@ #include "ash/display/display_info.h" #include "ash/display/display_manager.h" +#include "ash/display/extended_mouse_warp_controller.h" +#include "ash/display/mouse_cursor_event_filter.h" #include "ash/shell.h" #include "base/strings/string_split.h" +#include "ui/aura/env.h" #include "ui/aura/window_event_dispatcher.h" +#include "ui/events/test/event_generator.h" #include "ui/gfx/display.h" namespace ash { @@ -41,6 +45,27 @@ } // namespace +// static +bool DisplayManagerTestApi::TestIfMouseWarpsAt( + ui::test::EventGenerator& event_generator, + const gfx::Point& point_in_screen) { + aura::Window* context = Shell::GetAllRootWindows()[0]; + ExtendedMouseWarpController* warp_controller = + static_cast<ExtendedMouseWarpController*>( + Shell::GetInstance() + ->mouse_cursor_filter() + ->mouse_warp_controller_for_test()); + warp_controller->allow_non_native_event_for_test(); + + gfx::Screen* screen = gfx::Screen::GetScreenFor(context); + gfx::Display original_display = + screen->GetDisplayNearestPoint(point_in_screen); + event_generator.MoveMouseTo(point_in_screen); + return original_display.id() != + screen->GetDisplayNearestPoint( + aura::Env::GetInstance()->last_mouse_location()).id(); +} + DisplayManagerTestApi::DisplayManagerTestApi(DisplayManager* display_manager) : display_manager_(display_manager) {}
diff --git a/ash/test/display_manager_test_api.h b/ash/test/display_manager_test_api.h index f9f5c41..afbfd431 100644 --- a/ash/test/display_manager_test_api.h +++ b/ash/test/display_manager_test_api.h
@@ -11,6 +11,16 @@ #include "base/basictypes.h" #include "ui/display/types/display_constants.h" +namespace gfx { +class Point; +} + +namespace ui { +namespace test { +class EventGenerator; +} +} + namespace ash { class DisplayManager; @@ -18,6 +28,11 @@ class DisplayManagerTestApi { public: + // Test if moving a mouse to |point_in_screen| warps it to another + // display. + static bool TestIfMouseWarpsAt(ui::test::EventGenerator& event_generator, + const gfx::Point& point_in_screen); + explicit DisplayManagerTestApi(DisplayManager* display_manager); virtual ~DisplayManagerTestApi();
diff --git a/ash/test/user_metrics_recorder_test_api.cc b/ash/test/user_metrics_recorder_test_api.cc new file mode 100644 index 0000000..b9a5eac --- /dev/null +++ b/ash/test/user_metrics_recorder_test_api.cc
@@ -0,0 +1,26 @@ +// 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 "ash/test/user_metrics_recorder_test_api.h" + +namespace ash { +namespace test { + +UserMetricsRecorderTestAPI::UserMetricsRecorderTestAPI() + : user_metrics_recorder_(false) { +} + +UserMetricsRecorderTestAPI::~UserMetricsRecorderTestAPI() { +} + +void UserMetricsRecorderTestAPI::RecordPeriodicMetrics() { + user_metrics_recorder_.RecordPeriodicMetrics(); +} + +bool UserMetricsRecorderTestAPI::IsUserInActiveDesktopEnvironment() const { + return user_metrics_recorder_.IsUserInActiveDesktopEnvironment(); +} + +} // namespace test +} // namespace ash
diff --git a/ash/test/user_metrics_recorder_test_api.h b/ash/test/user_metrics_recorder_test_api.h new file mode 100644 index 0000000..e52ef0b --- /dev/null +++ b/ash/test/user_metrics_recorder_test_api.h
@@ -0,0 +1,37 @@ +// 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 ASH_TEST_USER_METRICS_RECORDER_TEST_API_H_ +#define ASH_TEST_USER_METRICS_RECORDER_TEST_API_H_ + +#include "ash/metrics/user_metrics_recorder.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" + +namespace ash { +namespace test { + +// Test API to access internals of the UserMetricsRecorder class. +class UserMetricsRecorderTestAPI { + public: + UserMetricsRecorderTestAPI(); + ~UserMetricsRecorderTestAPI(); + + // Accessor to UserMetricsRecorder::RecordPeriodicMetrics(). + void RecordPeriodicMetrics(); + + // Accessor to UserMetricsRecorder::IsUserInActiveDesktopEnvironment(). + bool IsUserInActiveDesktopEnvironment() const; + + private: + // The UserMetricsRecorder that |this| is providing internal access to. + UserMetricsRecorder user_metrics_recorder_; + + DISALLOW_COPY_AND_ASSIGN(UserMetricsRecorderTestAPI); +}; + +} // namespace test +} // namespace ash + +#endif // ASH_TEST_USER_METRICS_RECORDER_TEST_API_H_
diff --git a/ash/touch/touch_transformer_controller.cc b/ash/touch/touch_transformer_controller.cc index d2582c0..269450e 100644 --- a/ash/touch/touch_transformer_controller.cc +++ b/ash/touch/touch_transformer_controller.cc
@@ -142,7 +142,8 @@ DisplayManager* display_manager = GetDisplayManager(); if (display_manager->num_connected_displays() == 0) { return; - } else if (display_manager->num_connected_displays() == 1) { + } else if (display_manager->num_connected_displays() == 1 || + display_manager->multi_display_mode() == DisplayManager::UNIFIED) { single_display_id = display_manager->first_display_id(); DCHECK(single_display_id != gfx::Display::kInvalidDisplayID); single_display = display_manager->GetDisplayInfo(single_display_id);
diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc index c5c5be5e..ef2cc208 100644 --- a/ash/wm/drag_window_resizer_unittest.cc +++ b/ash/wm/drag_window_resizer_unittest.cc
@@ -11,18 +11,18 @@ #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ash/test/cursor_manager_test_api.h" +#include "ash/test/display_manager_test_api.h" #include "ash/wm/drag_window_controller.h" #include "ash/wm/window_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/env.h" #include "ui/aura/test/test_window_delegate.h" -#include "ui/aura/window_event_dispatcher.h" #include "ui/base/hit_test.h" #include "ui/base/ui_base_types.h" #include "ui/compositor/layer_tree_owner.h" #include "ui/gfx/geometry/insets.h" -#include "ui/gfx/screen.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/window_util.h" @@ -121,13 +121,9 @@ aura::client::WINDOW_MOVE_SOURCE_MOUSE).release(); } - bool WarpMouseCursorIfNecessary(aura::Window* target_root, - const gfx::Point& point_in_screen) { - MouseCursorEventFilter* event_filter = - Shell::GetInstance()->mouse_cursor_filter(); - bool is_warped = event_filter->WarpMouseCursorIfNecessaryForTest( - target_root, point_in_screen); - return is_warped; + bool TestIfMouseWarpsAt(const gfx::Point& point_in_screen) { + return test::DisplayManagerTestApi::TestIfMouseWarpsAt(GetEventGenerator(), + point_in_screen); } aura::test::TestWindowDelegate delegate_; @@ -489,7 +485,7 @@ EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200)); + TestIfMouseWarpsAt(gfx::Point(399, 200)); EXPECT_EQ(2.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); resizer->CompleteDrag(); EXPECT_EQ(2.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); @@ -513,7 +509,7 @@ EXPECT_EQ(2.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, -200, 200), 0); - WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200)); + TestIfMouseWarpsAt(gfx::Point(400, 200)); EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); resizer->CompleteDrag(); EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); @@ -542,8 +538,9 @@ window, gfx::Point(), HTCAPTION)); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(399, 200))); + EXPECT_EQ("401,200", + aura::Env::GetInstance()->last_mouse_location().ToString()); resizer->CompleteDrag(); } @@ -557,8 +554,9 @@ window, gfx::Point(), HTCAPTION)); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(399, 200))); + EXPECT_EQ("401,200", + aura::Env::GetInstance()->last_mouse_location().ToString()); resizer->CompleteDrag(); } @@ -567,13 +565,15 @@ aura::Window* window = system_modal_window_.get(); window->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60), Shell::GetScreen()->GetPrimaryDisplay()); + aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(0, 0)); // Grab (0, 0) of the window. scoped_ptr<WindowResizer> resizer(CreateDragWindowResizer( window, gfx::Point(), HTCAPTION)); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(399, 200))); + EXPECT_EQ("401,200", + aura::Env::GetInstance()->last_mouse_location().ToString()); resizer->CompleteDrag(); } @@ -587,9 +587,9 @@ window, gfx::Point(), HTCAPTION)); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_FALSE(WarpMouseCursorIfNecessary( - root_windows[0], - gfx::Point(399, 200))); + EXPECT_FALSE(TestIfMouseWarpsAt(gfx::Point(399, 200))); + EXPECT_EQ("399,200", + aura::Env::GetInstance()->last_mouse_location().ToString()); resizer->CompleteDrag(); } @@ -603,8 +603,9 @@ window, gfx::Point(), HTCAPTION)); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(399, 200))); + EXPECT_EQ("401,200", + aura::Env::GetInstance()->last_mouse_location().ToString()); resizer->CompleteDrag(); } @@ -618,8 +619,9 @@ window, gfx::Point(), HTCAPTION)); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); - EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[0], - gfx::Point(399, 200))); + EXPECT_TRUE(TestIfMouseWarpsAt(gfx::Point(399, 200))); + EXPECT_EQ("401,200", + aura::Env::GetInstance()->last_mouse_location().ToString()); resizer->CompleteDrag(); } }
diff --git a/ash/wm/lock_layout_manager_unittest.cc b/ash/wm/lock_layout_manager_unittest.cc index 96ce1a84..a210a9b6 100644 --- a/ash/wm/lock_layout_manager_unittest.cc +++ b/ash/wm/lock_layout_manager_unittest.cc
@@ -212,12 +212,14 @@ ash::DisplayManager* display_manager = Shell::GetInstance()->display_manager(); display_manager->SetDisplayRotation(primary_display.id(), - gfx::Display::ROTATE_90); + gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_ACTIVE); primary_display = Shell::GetScreen()->GetPrimaryDisplay(); screen_bounds = primary_display.bounds(); EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString()); display_manager->SetDisplayRotation(primary_display.id(), - gfx::Display::ROTATE_0); + gfx::Display::ROTATE_0, + gfx::Display::ROTATION_SOURCE_ACTIVE); // When virtual keyboard overscroll is disabled keyboard bounds do // affect window bounds.
diff --git a/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc b/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc index 3c098f36..6153984 100644 --- a/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc +++ b/ash/wm/maximize_mode/maximize_mode_controller_unittest.cc
@@ -112,16 +112,6 @@ return maximize_mode_controller()->IsMaximizeModeWindowManagerEnabled(); } - gfx::Display::Rotation GetInternalDisplayRotation() const { - return Shell::GetInstance()->display_manager()->GetDisplayInfo( - gfx::Display::InternalDisplayId()).rotation(); - } - - void SetInternalDisplayRotation(gfx::Display::Rotation rotation) const { - Shell::GetInstance()->display_manager()-> - SetDisplayRotation(gfx::Display::InternalDisplayId(), rotation); - } - // Attaches a SimpleTestTickClock to the MaximizeModeController with a non // null value initial value. void AttachTickClockForTest() {
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc index a03966a..47087c3 100644 --- a/ash/wm/overview/window_grid.cc +++ b/ash/wm/overview/window_grid.cc
@@ -27,6 +27,7 @@ #include "ui/gfx/animation/tween.h" #include "ui/gfx/geometry/vector2d.h" #include "ui/views/background.h" +#include "ui/views/border.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/window_animations.h" @@ -92,8 +93,9 @@ const int kOverviewSelectorTransitionMilliseconds = 100; // The color and opacity of the overview selector. -const SkColor kWindowOverviewSelectionColor = SK_ColorBLACK; -const unsigned char kWindowOverviewSelectorOpacity = 128; +const SkColor kWindowSelectionColor = SkColorSetARGB(128, 0, 0, 0); +const SkColor kWindowSelectionBorderColor = SkColorSetARGB(38, 255, 255, 255); +const int kWindowSelectionBorderThickness = 2; // The minimum amount of spacing between the bottom of the text filtering // text field and the top of the selection widget on the first row of items. @@ -368,7 +370,9 @@ views::View* content_view = new views::View; content_view->set_background( - views::Background::CreateSolidBackground(kWindowOverviewSelectionColor)); + views::Background::CreateSolidBackground(kWindowSelectionColor)); + content_view->SetBorder(views::Border::CreateSolidBorder( + kWindowSelectionBorderThickness, kWindowSelectionBorderColor)); selection_widget_->SetContentsView(content_view); selection_widget_->GetNativeWindow()->parent()->StackChildAtBottom( selection_widget_->GetNativeWindow()); @@ -438,11 +442,11 @@ animation_settings.SetPreemptionStrategy( ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); selection_widget_->SetBounds(SelectedWindow()->target_bounds()); - selection_widget_->SetOpacity(kWindowOverviewSelectorOpacity); + selection_widget_->SetOpacity(255); return; } selection_widget_->SetBounds(SelectedWindow()->target_bounds()); - selection_widget_->SetOpacity(kWindowOverviewSelectorOpacity); + selection_widget_->SetOpacity(255); } } // namespace ash
diff --git a/base/BUILD.gn b/base/BUILD.gn index 7750eeec..f1b0bb8 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -233,7 +233,6 @@ "files/scoped_file.h", "files/scoped_temp_dir.cc", "files/scoped_temp_dir.h", - "float_util.h", "format_macros.h", "gtest_prod_util.h", "guid.cc", @@ -1042,17 +1041,6 @@ ] } -# TODO(pasko): Remove this target when crbug.com/424562 is fixed. -source_set("protect_file_posix") { - sources = [ - "files/protect_file_posix.cc", - ] - - deps = [ - "//base", - ] -} - if (is_win) { # Target to manually rebuild pe_image_test.dll which is checked into # base/test/data/pe_image. @@ -1460,10 +1448,20 @@ android_library("base_java_test_support") { deps = [ ":base_java", + "//testing/android/reporter:reporter_java", ] DEPRECATED_java_in_dir = "test/android/javatests/src" } + # GYP: //base.gyp:base_junit_tests + junit_binary("base_junit_tests") { + java_files = [ "android/junit/src/org/chromium/base/LogTest.java" ] + deps = [ + ":base_java", + ":base_java_test_support", + ] + } + # GYP: //base.gyp:base_java_application_state # GYP: //base.gyp:base_java_library_load_from_apk_status_codes # GYP: //base.gyp:base_java_library_process_type
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java index 40cb0359..3df7b92 100644 --- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java +++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -375,4 +375,16 @@ return res.getDrawable(id); } } + + /** + * @see android.content.res.Resources#getDrawableForDensity(int id, int density). + */ + @SuppressWarnings("deprecation") + public static Drawable getDrawableForDensity(Resources res, int id, int density) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + return res.getDrawableForDensity(id, density, null); + } else { + return res.getDrawableForDensity(id, density); + } + } }
diff --git a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java index 8f7d39d..2946f6f 100644 --- a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java +++ b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java
@@ -8,6 +8,7 @@ import android.app.Application; import android.content.Context; import android.os.Bundle; +import android.view.KeyEvent; import android.view.Window; /** @@ -47,6 +48,17 @@ listener.onWindowFocusChanged(activity, hasFocus); } } + + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + // TODO(aurimas): remove this once AppCompatDelegateImpl no longer steals + // KEYCODE_MENU. (see b/20529185) + if (event.getKeyCode() == KeyEvent.KEYCODE_MENU + && activity.dispatchKeyEvent(event)) { + return true; + } + return super.dispatchKeyEvent(event); + } }); }
diff --git a/base/android/java/src/org/chromium/base/OWNERS b/base/android/java/src/org/chromium/base/OWNERS new file mode 100644 index 0000000..d99aec1 --- /dev/null +++ b/base/android/java/src/org/chromium/base/OWNERS
@@ -0,0 +1,2 @@ +per-file ApiCompatibilityUtils.java=aurimas@chromium.org +per-file ApiCompatibilityUtils.java=newt@chromium.org
diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java index 2a8deeb..c0b9172 100644 --- a/base/android/java/src/org/chromium/base/ThreadUtils.java +++ b/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -176,6 +176,7 @@ * @param task The Runnable to run * @param delayMillis The delay in milliseconds until the Runnable will be run */ + @VisibleForTesting public static void postOnUiThreadDelayed(Runnable task, long delayMillis) { getUiThreadHandler().postDelayed(task, delayMillis); }
diff --git a/base/android/junit/src/org/chromium/base/LogTest.java b/base/android/junit/src/org/chromium/base/LogTest.java new file mode 100644 index 0000000..14726fe --- /dev/null +++ b/base/android/junit/src/org/chromium/base/LogTest.java
@@ -0,0 +1,93 @@ +// 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. + +package org.chromium.base; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.chromium.testing.local.LocalRobolectricTestRunner; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.Implementation; +import org.robolectric.annotation.Implements; +import org.robolectric.shadows.ShadowLog; + +import java.util.List; + +/** Unit tests for {@link Log}. */ +@RunWith(LocalRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {LogTest.PermissiveShadowLog.class}) +public class LogTest { + /** Test method for {@link Log#makeTag(String)} */ + @Test + public void testMakeTag() { + assertEquals("chromium.Foo", Log.makeTag("Foo")); + assertEquals("chromium", Log.makeTag(null)); + assertEquals("chromium", Log.makeTag("")); + } + + /** Tests that the computed call origin is the correct one. */ + @Test + public void callOriginTest() { + Log.d("Foo", "Bar"); + + List<ShadowLog.LogItem> logs = ShadowLog.getLogs(); + assertEquals("Only one log should be written", 1, logs.size()); + + assertTrue("The origin of the log message (" + logs.get(0).msg + ") looks wrong.", + logs.get(0).msg.matches("\\[LogTest.java:\\d+\\].*")); + } + + /** Tests that exceptions provided to the log functions are properly recognized and printed. */ + @Test + public void exceptionLoggingTest() { + Throwable t = new Throwable() { + @Override + public String toString() { + return "MyThrowable"; + } + }; + + Throwable t2 = new Throwable() { + @Override + public String toString() { + return "MyOtherThrowable"; + } + }; + + List<ShadowLog.LogItem> logs = ShadowLog.getLogs(); + + // The throwable gets printed out + Log.i("Foo", "Bar", t); + assertEquals(t, logs.get(logs.size() - 1).throwable); + assertEquals("Bar", logs.get(logs.size() - 1).msg); + + // The throwable can be both added to the message itself and printed out + Log.i("Foo", "Bar %s", t); + assertEquals(t, logs.get(logs.size() - 1).throwable); + assertEquals("Bar MyThrowable", logs.get(logs.size() - 1).msg); + + // Non throwable are properly identified + Log.i("Foo", "Bar %s", t, "Baz"); + assertNull(logs.get(logs.size() - 1).throwable); + assertEquals("Bar MyThrowable", logs.get(logs.size() - 1).msg); + + // The last throwable is the one used that is going to be printed out + Log.i("Foo", "Bar %s %s", t, t2); + assertEquals(t2, logs.get(logs.size() - 1).throwable); + assertEquals("Bar MyThrowable MyOtherThrowable", logs.get(logs.size() - 1).msg); + } + + /** Needed to allow debug/verbose logging that is disabled by default. */ + @Implements(android.util.Log.class) + public static class PermissiveShadowLog extends ShadowLog { + @Implementation + public static boolean isLoggable(String tag, int level) { + return true; + } + } +}
diff --git a/base/base.gyp b/base/base.gyp index 325210f..35f883cb 100644 --- a/base/base.gyp +++ b/base/base.gyp
@@ -376,24 +376,6 @@ ], }, { - # TODO(pasko): Remove this target when crbug.com/424562 is fixed. - # GN: //base:protect_file_posix - 'target_name': 'protect_file_posix', - 'conditions': [ - ['os_posix == 1', { - 'type': 'static_library', - 'dependencies': [ - 'base', - ], - 'sources': [ - 'files/protect_file_posix.cc', - ], - }, { - 'type': 'none', - }], - ], - }, - { 'target_name': 'base_prefs_test_support', 'type': 'static_library', 'dependencies': [ @@ -803,14 +785,6 @@ '../third_party/icu/icu.gyp:icudata', ], }], - ['incremental_chrome_dll', { - 'defines': [ - # Used only to workaround a linker bug, do not use this - # otherwise, and don't make it broader scope. See - # http://crbug.com/251251. - 'INCREMENTAL_LINKING', - ], - }], ], }, { # OS != "win" 'dependencies': [ @@ -1502,6 +1476,7 @@ 'type': 'none', 'dependencies': [ 'base_java', + '../testing/android/on_device_instrumentation.gyp:reporter_java', ], 'variables': { 'java_in_dir': '../base/test/android/javatests', @@ -1509,6 +1484,23 @@ 'includes': [ '../build/java.gypi' ], }, { + # GN: //base:base_junit_tests + 'target_name': 'base_junit_tests', + 'type': 'none', + 'dependencies': [ + 'base_java', + 'base_java_test_support', + '../testing/android/junit/junit_test.gyp:junit_test_support', + ], + 'variables': { + 'main_class': 'org.chromium.testing.local.JunitTestMain', + 'src_paths': [ + '../base/android/junit/', + ], + }, + 'includes': [ '../build/host_jar.gypi' ], + }, + { # GN: //base:base_javatests 'target_name': 'base_javatests', 'type': 'none',
diff --git a/base/base.gypi b/base/base.gypi index a45a387..bbc3f60f 100644 --- a/base/base.gypi +++ b/base/base.gypi
@@ -227,7 +227,6 @@ 'files/scoped_file.h', 'files/scoped_temp_dir.cc', 'files/scoped_temp_dir.h', - 'float_util.h', 'format_macros.h', 'gtest_prod_util.h', 'guid.cc',
diff --git a/base/files/file.cc b/base/files/file.cc index 86fdbc9..8030bf1 100644 --- a/base/files/file.cc +++ b/base/files/file.cc
@@ -7,10 +7,6 @@ #include "base/metrics/histogram.h" #include "base/timer/elapsed_timer.h" -#if defined(OS_POSIX) -#include "base/files/file_posix_hooks_internal.h" -#endif - namespace base { File::Info::Info() @@ -44,8 +40,6 @@ async_(false) { #if defined(OS_POSIX) DCHECK_GE(platform_file, -1); - if (IsValid()) - ProtectFileDescriptor(platform_file); #endif } @@ -60,10 +54,6 @@ error_details_(other.object->error_details()), created_(other.object->created()), async_(other.object->async_) { -#if defined(OS_POSIX) - if (IsValid()) - ProtectFileDescriptor(GetPlatformFile()); -#endif } File::~File() { @@ -88,7 +78,7 @@ error_details_ = FILE_ERROR_ACCESS_DENIED; return; } - InitializeUnsafe(name, flags); + DoInitialize(name, flags); } #endif
diff --git a/base/files/file.h b/base/files/file.h index 49ffb92..89077b4 100644 --- a/base/files/file.h +++ b/base/files/file.h
@@ -150,13 +150,13 @@ bool is_symbolic_link; // The last modified time of a file. - base::Time last_modified; + Time last_modified; // The last accessed time of a file. - base::Time last_accessed; + Time last_accessed; // The creation time of a file. - base::Time creation_time; + Time creation_time; }; File(); @@ -182,10 +182,6 @@ // Creates or opens the given file. void Initialize(const FilePath& name, uint32 flags); - // Creates or opens the given file, allowing paths with traversal ('..') - // components. Use only with extreme care. - void InitializeUnsafe(const FilePath& name, uint32 flags); - bool IsValid() const; // Returns true if a new file was created (or an old one truncated to zero @@ -354,6 +350,10 @@ }; #endif + // Creates or opens the given file. Only called if |name| has no traversal + // ('..') components. + void DoInitialize(const FilePath& name, uint32 flags); + // TODO(tnagel): Reintegrate into Flush() once histogram isn't needed anymore, // cf. issue 473337. bool DoFlush();
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc index b74fb4b..4c79057 100644 --- a/base/files/file_posix.cc +++ b/base/files/file_posix.cc
@@ -10,7 +10,6 @@ #include <unistd.h> #include "base/files/file_path.h" -#include "base/files/file_posix_hooks_internal.h" #include "base/logging.h" #include "base/metrics/sparse_histogram.h" #include "base/posix/eintr_wrapper.h" @@ -32,12 +31,12 @@ #if defined(OS_BSD) || defined(OS_MACOSX) || defined(OS_NACL) static int CallFstat(int fd, stat_wrapper_t *sb) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); return fstat(fd, sb); } #else static int CallFstat(int fd, stat_wrapper_t *sb) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); return fstat64(fd, sb); } #endif @@ -158,104 +157,6 @@ Time::kNanosecondsPerMicrosecond); } -// Default implementations of Protect/Unprotect hooks defined as weak symbols -// where possible. -void ProtectFileDescriptor(int fd) { -} - -void UnprotectFileDescriptor(int fd) { -} - -// NaCl doesn't implement system calls to open files directly. -#if !defined(OS_NACL) -// TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? -void File::InitializeUnsafe(const FilePath& name, uint32 flags) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(!IsValid()); - - int open_flags = 0; - if (flags & FLAG_CREATE) - open_flags = O_CREAT | O_EXCL; - - created_ = false; - - if (flags & FLAG_CREATE_ALWAYS) { - DCHECK(!open_flags); - DCHECK(flags & FLAG_WRITE); - open_flags = O_CREAT | O_TRUNC; - } - - if (flags & FLAG_OPEN_TRUNCATED) { - DCHECK(!open_flags); - DCHECK(flags & FLAG_WRITE); - open_flags = O_TRUNC; - } - - if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) { - NOTREACHED(); - errno = EOPNOTSUPP; - error_details_ = FILE_ERROR_FAILED; - return; - } - - if (flags & FLAG_WRITE && flags & FLAG_READ) { - open_flags |= O_RDWR; - } else if (flags & FLAG_WRITE) { - open_flags |= O_WRONLY; - } else if (!(flags & FLAG_READ) && - !(flags & FLAG_WRITE_ATTRIBUTES) && - !(flags & FLAG_APPEND) && - !(flags & FLAG_OPEN_ALWAYS)) { - NOTREACHED(); - } - - if (flags & FLAG_TERMINAL_DEVICE) - open_flags |= O_NOCTTY | O_NDELAY; - - if (flags & FLAG_APPEND && flags & FLAG_READ) - open_flags |= O_APPEND | O_RDWR; - else if (flags & FLAG_APPEND) - open_flags |= O_APPEND | O_WRONLY; - - COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero); - - int mode = S_IRUSR | S_IWUSR; -#if defined(OS_CHROMEOS) - mode |= S_IRGRP | S_IROTH; -#endif - - int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); - - if (flags & FLAG_OPEN_ALWAYS) { - if (descriptor < 0) { - open_flags |= O_CREAT; - if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE) - open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW - - descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); - if (descriptor >= 0) - created_ = true; - } - } - - if (descriptor < 0) { - error_details_ = File::OSErrorToFileError(errno); - return; - } - - if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE)) - created_ = true; - - if (flags & FLAG_DELETE_ON_CLOSE) - unlink(name.value().c_str()); - - async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC); - error_details_ = FILE_OK; - file_.reset(descriptor); - ProtectFileDescriptor(descriptor); -} -#endif // !defined(OS_NACL) - bool File::IsValid() const { return file_.is_valid(); } @@ -265,8 +166,6 @@ } PlatformFile File::TakePlatformFile() { - if (IsValid()) - UnprotectFileDescriptor(GetPlatformFile()); return file_.release(); } @@ -274,13 +173,12 @@ if (!IsValid()) return; - base::ThreadRestrictions::AssertIOAllowed(); - UnprotectFileDescriptor(GetPlatformFile()); + ThreadRestrictions::AssertIOAllowed(); file_.reset(); } int64 File::Seek(Whence whence, int64 offset) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); #if defined(OS_ANDROID) @@ -295,7 +193,7 @@ } int File::Read(int64 offset, char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); if (size < 0) return -1; @@ -315,7 +213,7 @@ } int File::ReadAtCurrentPos(char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); if (size < 0) return -1; @@ -334,14 +232,14 @@ } int File::ReadNoBestEffort(int64 offset, char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); return HANDLE_EINTR(pread(file_.get(), data, size, offset)); } int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); if (size < 0) return -1; @@ -350,7 +248,7 @@ } int File::Write(int64 offset, const char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); if (IsOpenAppend(file_.get())) return WriteAtCurrentPos(data, size); @@ -374,7 +272,7 @@ } int File::WriteAtCurrentPos(const char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); if (size < 0) return -1; @@ -394,7 +292,7 @@ } int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); if (size < 0) return -1; @@ -413,13 +311,13 @@ } bool File::SetLength(int64 length) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); return !CallFtruncate(file_.get(), length); } bool File::SetTimes(Time last_access_time, Time last_modified_time) { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); timeval times[2]; @@ -541,8 +439,97 @@ ComputeMemoryChecksum(&file_memory_checksum_); } +// NaCl doesn't implement system calls to open files directly. +#if !defined(OS_NACL) +// TODO(erikkay): does it make sense to support FLAG_EXCLUSIVE_* here? +void File::DoInitialize(const FilePath& name, uint32 flags) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(!IsValid()); + + int open_flags = 0; + if (flags & FLAG_CREATE) + open_flags = O_CREAT | O_EXCL; + + created_ = false; + + if (flags & FLAG_CREATE_ALWAYS) { + DCHECK(!open_flags); + DCHECK(flags & FLAG_WRITE); + open_flags = O_CREAT | O_TRUNC; + } + + if (flags & FLAG_OPEN_TRUNCATED) { + DCHECK(!open_flags); + DCHECK(flags & FLAG_WRITE); + open_flags = O_TRUNC; + } + + if (!open_flags && !(flags & FLAG_OPEN) && !(flags & FLAG_OPEN_ALWAYS)) { + NOTREACHED(); + errno = EOPNOTSUPP; + error_details_ = FILE_ERROR_FAILED; + return; + } + + if (flags & FLAG_WRITE && flags & FLAG_READ) { + open_flags |= O_RDWR; + } else if (flags & FLAG_WRITE) { + open_flags |= O_WRONLY; + } else if (!(flags & FLAG_READ) && + !(flags & FLAG_WRITE_ATTRIBUTES) && + !(flags & FLAG_APPEND) && + !(flags & FLAG_OPEN_ALWAYS)) { + NOTREACHED(); + } + + if (flags & FLAG_TERMINAL_DEVICE) + open_flags |= O_NOCTTY | O_NDELAY; + + if (flags & FLAG_APPEND && flags & FLAG_READ) + open_flags |= O_APPEND | O_RDWR; + else if (flags & FLAG_APPEND) + open_flags |= O_APPEND | O_WRONLY; + + COMPILE_ASSERT(O_RDONLY == 0, O_RDONLY_must_equal_zero); + + int mode = S_IRUSR | S_IWUSR; +#if defined(OS_CHROMEOS) + mode |= S_IRGRP | S_IROTH; +#endif + + int descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); + + if (flags & FLAG_OPEN_ALWAYS) { + if (descriptor < 0) { + open_flags |= O_CREAT; + if (flags & FLAG_EXCLUSIVE_READ || flags & FLAG_EXCLUSIVE_WRITE) + open_flags |= O_EXCL; // together with O_CREAT implies O_NOFOLLOW + + descriptor = HANDLE_EINTR(open(name.value().c_str(), open_flags, mode)); + if (descriptor >= 0) + created_ = true; + } + } + + if (descriptor < 0) { + error_details_ = File::OSErrorToFileError(errno); + return; + } + + if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE)) + created_ = true; + + if (flags & FLAG_DELETE_ON_CLOSE) + unlink(name.value().c_str()); + + async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC); + error_details_ = FILE_OK; + file_.reset(descriptor); +} +#endif // !defined(OS_NACL) + bool File::DoFlush() { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); #if defined(OS_NACL) NOTIMPLEMENTED(); // NaCl doesn't implement fsync. @@ -555,10 +542,8 @@ } void File::SetPlatformFile(PlatformFile file) { - CHECK(!file_.is_valid()); + DCHECK(!file_.is_valid()); file_.reset(file); - if (file_.is_valid()) - ProtectFileDescriptor(GetPlatformFile()); } } // namespace base
diff --git a/base/files/file_posix_hooks_internal.h b/base/files/file_posix_hooks_internal.h deleted file mode 100644 index 1137b487..0000000 --- a/base/files/file_posix_hooks_internal.h +++ /dev/null
@@ -1,31 +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 BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_ -#define BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_ - -#include "base/base_export.h" - -namespace base { - -// Define empty hooks for blacklisting file descriptors used in base::File. -// These functions should be declared 'weak', i.e. the functions declared in -// a default way would have precedence over the weak ones at link time. This -// works for both static and dynamic linking. -// TODO(pasko): Remove these hooks when crbug.com/424562 is fixed. -// -// With compilers other than GCC/Clang define strong no-op symbols for -// simplicity. -#if defined(COMPILER_GCC) -#define ATTRIBUTE_WEAK __attribute__ ((weak)) -#else -#define ATTRIBUTE_WEAK -#endif -BASE_EXPORT void ProtectFileDescriptor(int fd) ATTRIBUTE_WEAK; -BASE_EXPORT void UnprotectFileDescriptor(int fd) ATTRIBUTE_WEAK; -#undef ATTRIBUTE_WEAK - -} // namespace base - -#endif // BASE_FILES_FILE_POSIX_HOOKS_INTERNAL_H_
diff --git a/base/files/file_win.cc b/base/files/file_win.cc index 08d6612..200ea29 100644 --- a/base/files/file_win.cc +++ b/base/files/file_win.cc
@@ -18,8 +18,268 @@ File::FROM_CURRENT == FILE_CURRENT && File::FROM_END == FILE_END, whence_matches_system); -void File::InitializeUnsafe(const FilePath& name, uint32 flags) { - base::ThreadRestrictions::AssertIOAllowed(); +bool File::IsValid() const { + return file_.IsValid(); +} + +PlatformFile File::GetPlatformFile() const { + return file_.Get(); +} + +PlatformFile File::TakePlatformFile() { + return file_.Take(); +} + +void File::Close() { + if (file_.IsValid()) { + ThreadRestrictions::AssertIOAllowed(); + file_.Close(); + } +} + +int64 File::Seek(Whence whence, int64 offset) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + + LARGE_INTEGER distance, res; + distance.QuadPart = offset; + DWORD move_method = static_cast<DWORD>(whence); + if (!SetFilePointerEx(file_.Get(), distance, &res, move_method)) + return -1; + return res.QuadPart; +} + +int File::Read(int64 offset, char* data, int size) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + DCHECK(!async_); + if (size < 0) + return -1; + + LARGE_INTEGER offset_li; + offset_li.QuadPart = offset; + + OVERLAPPED overlapped = {0}; + overlapped.Offset = offset_li.LowPart; + overlapped.OffsetHigh = offset_li.HighPart; + + DWORD bytes_read; + if (::ReadFile(file_.Get(), data, size, &bytes_read, &overlapped)) + return bytes_read; + if (ERROR_HANDLE_EOF == GetLastError()) + return 0; + + return -1; +} + +int File::ReadAtCurrentPos(char* data, int size) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + DCHECK(!async_); + if (size < 0) + return -1; + + DWORD bytes_read; + if (::ReadFile(file_.Get(), data, size, &bytes_read, NULL)) + return bytes_read; + if (ERROR_HANDLE_EOF == GetLastError()) + return 0; + + return -1; +} + +int File::ReadNoBestEffort(int64 offset, char* data, int size) { + return Read(offset, data, size); +} + +int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { + return ReadAtCurrentPos(data, size); +} + +int File::Write(int64 offset, const char* data, int size) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + DCHECK(!async_); + + LARGE_INTEGER offset_li; + offset_li.QuadPart = offset; + + OVERLAPPED overlapped = {0}; + overlapped.Offset = offset_li.LowPart; + overlapped.OffsetHigh = offset_li.HighPart; + + DWORD bytes_written; + if (::WriteFile(file_.Get(), data, size, &bytes_written, &overlapped)) + return bytes_written; + + return -1; +} + +int File::WriteAtCurrentPos(const char* data, int size) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + DCHECK(!async_); + if (size < 0) + return -1; + + DWORD bytes_written; + if (::WriteFile(file_.Get(), data, size, &bytes_written, NULL)) + return bytes_written; + + return -1; +} + +int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { + return WriteAtCurrentPos(data, size); +} + +int64 File::GetLength() { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + LARGE_INTEGER size; + if (!::GetFileSizeEx(file_.Get(), &size)) + return -1; + + return static_cast<int64>(size.QuadPart); +} + +bool File::SetLength(int64 length) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + + // Get the current file pointer. + LARGE_INTEGER file_pointer; + LARGE_INTEGER zero; + zero.QuadPart = 0; + if (!::SetFilePointerEx(file_.Get(), zero, &file_pointer, FILE_CURRENT)) + return false; + + LARGE_INTEGER length_li; + length_li.QuadPart = length; + // If length > file size, SetFilePointerEx() should extend the file + // with zeroes on all Windows standard file systems (NTFS, FATxx). + if (!::SetFilePointerEx(file_.Get(), length_li, NULL, FILE_BEGIN)) + return false; + + // Set the new file length and move the file pointer to its old position. + // This is consistent with ftruncate()'s behavior, even when the file + // pointer points to a location beyond the end of the file. + // TODO(rvargas): Emulating ftruncate details seem suspicious and it is not + // promised by the interface (nor was promised by PlatformFile). See if this + // implementation detail can be removed. + return ((::SetEndOfFile(file_.Get()) != FALSE) && + (::SetFilePointerEx(file_.Get(), file_pointer, NULL, FILE_BEGIN) != + FALSE)); +} + +bool File::SetTimes(Time last_access_time, Time last_modified_time) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + + FILETIME last_access_filetime = last_access_time.ToFileTime(); + FILETIME last_modified_filetime = last_modified_time.ToFileTime(); + return (::SetFileTime(file_.Get(), NULL, &last_access_filetime, + &last_modified_filetime) != FALSE); +} + +bool File::GetInfo(Info* info) { + ThreadRestrictions::AssertIOAllowed(); + DCHECK(IsValid()); + + BY_HANDLE_FILE_INFORMATION file_info; + if (!GetFileInformationByHandle(file_.Get(), &file_info)) + return false; + + LARGE_INTEGER size; + size.HighPart = file_info.nFileSizeHigh; + size.LowPart = file_info.nFileSizeLow; + info->size = size.QuadPart; + info->is_directory = + (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; + info->is_symbolic_link = false; // Windows doesn't have symbolic links. + info->last_modified = Time::FromFileTime(file_info.ftLastWriteTime); + info->last_accessed = Time::FromFileTime(file_info.ftLastAccessTime); + info->creation_time = Time::FromFileTime(file_info.ftCreationTime); + return true; +} + +File::Error File::Lock() { + DCHECK(IsValid()); + BOOL result = LockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD); + if (!result) + return OSErrorToFileError(GetLastError()); + return FILE_OK; +} + +File::Error File::Unlock() { + DCHECK(IsValid()); + BOOL result = UnlockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD); + if (!result) + return OSErrorToFileError(GetLastError()); + return FILE_OK; +} + +File File::Duplicate() { + if (!IsValid()) + return File(); + + HANDLE other_handle = nullptr; + + if (!::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle + GetPlatformFile(), + GetCurrentProcess(), // hTargetProcessHandle + &other_handle, + 0, // dwDesiredAccess ignored due to SAME_ACCESS + FALSE, // !bInheritHandle + DUPLICATE_SAME_ACCESS)) { + return File(OSErrorToFileError(GetLastError())); + } + + File other(other_handle); + if (async()) + other.async_ = true; + return other.Pass(); +} + +// Static. +File::Error File::OSErrorToFileError(DWORD last_error) { + switch (last_error) { + case ERROR_SHARING_VIOLATION: + return FILE_ERROR_IN_USE; + case ERROR_FILE_EXISTS: + return FILE_ERROR_EXISTS; + case ERROR_FILE_NOT_FOUND: + case ERROR_PATH_NOT_FOUND: + return FILE_ERROR_NOT_FOUND; + case ERROR_ACCESS_DENIED: + return FILE_ERROR_ACCESS_DENIED; + case ERROR_TOO_MANY_OPEN_FILES: + return FILE_ERROR_TOO_MANY_OPENED; + case ERROR_OUTOFMEMORY: + case ERROR_NOT_ENOUGH_MEMORY: + return FILE_ERROR_NO_MEMORY; + case ERROR_HANDLE_DISK_FULL: + case ERROR_DISK_FULL: + case ERROR_DISK_RESOURCES_EXHAUSTED: + return FILE_ERROR_NO_SPACE; + case ERROR_USER_MAPPED_FILE: + return FILE_ERROR_INVALID_OPERATION; + case ERROR_NOT_READY: + case ERROR_SECTOR_NOT_FOUND: + case ERROR_DEV_NOT_EXIST: + case ERROR_IO_DEVICE: + case ERROR_FILE_CORRUPT: + case ERROR_DISK_CORRUPT: + return FILE_ERROR_IO; + default: + UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows", + last_error); + return FILE_ERROR_FAILED; + } +} + +void File::DoInitialize(const FilePath& name, uint32 flags) { + ThreadRestrictions::AssertIOAllowed(); DCHECK(!IsValid()); DWORD disposition = 0; @@ -102,268 +362,8 @@ } } -bool File::IsValid() const { - return file_.IsValid(); -} - -PlatformFile File::GetPlatformFile() const { - return file_.Get(); -} - -PlatformFile File::TakePlatformFile() { - return file_.Take(); -} - -void File::Close() { - if (file_.IsValid()) { - base::ThreadRestrictions::AssertIOAllowed(); - file_.Close(); - } -} - -int64 File::Seek(Whence whence, int64 offset) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - - LARGE_INTEGER distance, res; - distance.QuadPart = offset; - DWORD move_method = static_cast<DWORD>(whence); - if (!SetFilePointerEx(file_.Get(), distance, &res, move_method)) - return -1; - return res.QuadPart; -} - -int File::Read(int64 offset, char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - DCHECK(!async_); - if (size < 0) - return -1; - - LARGE_INTEGER offset_li; - offset_li.QuadPart = offset; - - OVERLAPPED overlapped = {0}; - overlapped.Offset = offset_li.LowPart; - overlapped.OffsetHigh = offset_li.HighPart; - - DWORD bytes_read; - if (::ReadFile(file_.Get(), data, size, &bytes_read, &overlapped)) - return bytes_read; - if (ERROR_HANDLE_EOF == GetLastError()) - return 0; - - return -1; -} - -int File::ReadAtCurrentPos(char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - DCHECK(!async_); - if (size < 0) - return -1; - - DWORD bytes_read; - if (::ReadFile(file_.Get(), data, size, &bytes_read, NULL)) - return bytes_read; - if (ERROR_HANDLE_EOF == GetLastError()) - return 0; - - return -1; -} - -int File::ReadNoBestEffort(int64 offset, char* data, int size) { - return Read(offset, data, size); -} - -int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { - return ReadAtCurrentPos(data, size); -} - -int File::Write(int64 offset, const char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - DCHECK(!async_); - - LARGE_INTEGER offset_li; - offset_li.QuadPart = offset; - - OVERLAPPED overlapped = {0}; - overlapped.Offset = offset_li.LowPart; - overlapped.OffsetHigh = offset_li.HighPart; - - DWORD bytes_written; - if (::WriteFile(file_.Get(), data, size, &bytes_written, &overlapped)) - return bytes_written; - - return -1; -} - -int File::WriteAtCurrentPos(const char* data, int size) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - DCHECK(!async_); - if (size < 0) - return -1; - - DWORD bytes_written; - if (::WriteFile(file_.Get(), data, size, &bytes_written, NULL)) - return bytes_written; - - return -1; -} - -int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { - return WriteAtCurrentPos(data, size); -} - -int64 File::GetLength() { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - LARGE_INTEGER size; - if (!::GetFileSizeEx(file_.Get(), &size)) - return -1; - - return static_cast<int64>(size.QuadPart); -} - -bool File::SetLength(int64 length) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - - // Get the current file pointer. - LARGE_INTEGER file_pointer; - LARGE_INTEGER zero; - zero.QuadPart = 0; - if (!::SetFilePointerEx(file_.Get(), zero, &file_pointer, FILE_CURRENT)) - return false; - - LARGE_INTEGER length_li; - length_li.QuadPart = length; - // If length > file size, SetFilePointerEx() should extend the file - // with zeroes on all Windows standard file systems (NTFS, FATxx). - if (!::SetFilePointerEx(file_.Get(), length_li, NULL, FILE_BEGIN)) - return false; - - // Set the new file length and move the file pointer to its old position. - // This is consistent with ftruncate()'s behavior, even when the file - // pointer points to a location beyond the end of the file. - // TODO(rvargas): Emulating ftruncate details seem suspicious and it is not - // promised by the interface (nor was promised by PlatformFile). See if this - // implementation detail can be removed. - return ((::SetEndOfFile(file_.Get()) != FALSE) && - (::SetFilePointerEx(file_.Get(), file_pointer, NULL, FILE_BEGIN) != - FALSE)); -} - -bool File::SetTimes(Time last_access_time, Time last_modified_time) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - - FILETIME last_access_filetime = last_access_time.ToFileTime(); - FILETIME last_modified_filetime = last_modified_time.ToFileTime(); - return (::SetFileTime(file_.Get(), NULL, &last_access_filetime, - &last_modified_filetime) != FALSE); -} - -bool File::GetInfo(Info* info) { - base::ThreadRestrictions::AssertIOAllowed(); - DCHECK(IsValid()); - - BY_HANDLE_FILE_INFORMATION file_info; - if (!GetFileInformationByHandle(file_.Get(), &file_info)) - return false; - - LARGE_INTEGER size; - size.HighPart = file_info.nFileSizeHigh; - size.LowPart = file_info.nFileSizeLow; - info->size = size.QuadPart; - info->is_directory = - (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; - info->is_symbolic_link = false; // Windows doesn't have symbolic links. - info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime); - info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime); - info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime); - return true; -} - -File::Error base::File::Lock() { - DCHECK(IsValid()); - BOOL result = LockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD); - if (!result) - return OSErrorToFileError(GetLastError()); - return FILE_OK; -} - -File::Error File::Unlock() { - DCHECK(IsValid()); - BOOL result = UnlockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD); - if (!result) - return OSErrorToFileError(GetLastError()); - return FILE_OK; -} - -File File::Duplicate() { - if (!IsValid()) - return File(); - - HANDLE other_handle = nullptr; - - if (!::DuplicateHandle(GetCurrentProcess(), // hSourceProcessHandle - GetPlatformFile(), - GetCurrentProcess(), // hTargetProcessHandle - &other_handle, - 0, // dwDesiredAccess ignored due to SAME_ACCESS - FALSE, // !bInheritHandle - DUPLICATE_SAME_ACCESS)) { - return File(OSErrorToFileError(GetLastError())); - } - - File other(other_handle); - if (async()) - other.async_ = true; - return other.Pass(); -} - -// Static. -File::Error File::OSErrorToFileError(DWORD last_error) { - switch (last_error) { - case ERROR_SHARING_VIOLATION: - return FILE_ERROR_IN_USE; - case ERROR_FILE_EXISTS: - return FILE_ERROR_EXISTS; - case ERROR_FILE_NOT_FOUND: - case ERROR_PATH_NOT_FOUND: - return FILE_ERROR_NOT_FOUND; - case ERROR_ACCESS_DENIED: - return FILE_ERROR_ACCESS_DENIED; - case ERROR_TOO_MANY_OPEN_FILES: - return FILE_ERROR_TOO_MANY_OPENED; - case ERROR_OUTOFMEMORY: - case ERROR_NOT_ENOUGH_MEMORY: - return FILE_ERROR_NO_MEMORY; - case ERROR_HANDLE_DISK_FULL: - case ERROR_DISK_FULL: - case ERROR_DISK_RESOURCES_EXHAUSTED: - return FILE_ERROR_NO_SPACE; - case ERROR_USER_MAPPED_FILE: - return FILE_ERROR_INVALID_OPERATION; - case ERROR_NOT_READY: - case ERROR_SECTOR_NOT_FOUND: - case ERROR_DEV_NOT_EXIST: - case ERROR_IO_DEVICE: - case ERROR_FILE_CORRUPT: - case ERROR_DISK_CORRUPT: - return FILE_ERROR_IO; - default: - UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows", - last_error); - return FILE_ERROR_FAILED; - } -} - bool File::DoFlush() { - base::ThreadRestrictions::AssertIOAllowed(); + ThreadRestrictions::AssertIOAllowed(); DCHECK(IsValid()); return ::FlushFileBuffers(file_.Get()) != FALSE; }
diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc index 47b0b09e..f49790cd 100644 --- a/base/files/important_file_writer.cc +++ b/base/files/important_file_writer.cc
@@ -51,6 +51,12 @@ << " : " << message; } +// Helper function to call WriteFileAtomically() with a scoped_ptr<std::string>. +bool WriteScopedStringToFileAtomically(const FilePath& path, + scoped_ptr<std::string> data) { + return ImportantFileWriter::WriteFileAtomically(path, *data); +} + } // namespace // static @@ -139,9 +145,9 @@ return timer_.IsRunning(); } -void ImportantFileWriter::WriteNow(const std::string& data) { +void ImportantFileWriter::WriteNow(scoped_ptr<std::string> data) { DCHECK(CalledOnValidThread()); - if (data.length() > static_cast<size_t>(kint32max)) { + if (data->length() > static_cast<size_t>(kint32max)) { NOTREACHED(); return; } @@ -149,13 +155,14 @@ if (HasPendingWrite()) timer_.Stop(); - if (!PostWriteTask(data)) { + auto task = Bind(&WriteScopedStringToFileAtomically, path_, Passed(&data)); + if (!PostWriteTask(task)) { // Posting the task to background message loop is not expected // to fail, but if it does, avoid losing data and just hit the disk // on the current thread. NOTREACHED(); - WriteFileAtomically(path_, data); + task.Run(); } } @@ -173,9 +180,9 @@ void ImportantFileWriter::DoScheduledWrite() { DCHECK(serializer_); - std::string data; - if (serializer_->SerializeData(&data)) { - WriteNow(data); + scoped_ptr<std::string> data(new std::string); + if (serializer_->SerializeData(data.get())) { + WriteNow(data.Pass()); } else { DLOG(WARNING) << "failed to serialize data to be saved in " << path_.value().c_str(); @@ -189,7 +196,7 @@ on_next_successful_write_ = on_next_successful_write; } -bool ImportantFileWriter::PostWriteTask(const std::string& data) { +bool ImportantFileWriter::PostWriteTask(const Callback<bool()>& task) { // TODO(gab): This code could always use PostTaskAndReplyWithResult and let // ForwardSuccessfulWrite() no-op if |on_next_successful_write_| is null, but // PostTaskAndReply causes memory leaks in tests (crbug.com/371974) and @@ -199,16 +206,13 @@ return base::PostTaskAndReplyWithResult( task_runner_.get(), FROM_HERE, - MakeCriticalClosure( - Bind(&ImportantFileWriter::WriteFileAtomically, path_, data)), + MakeCriticalClosure(task), Bind(&ImportantFileWriter::ForwardSuccessfulWrite, weak_factory_.GetWeakPtr())); } return task_runner_->PostTask( FROM_HERE, - MakeCriticalClosure( - Bind(IgnoreResult(&ImportantFileWriter::WriteFileAtomically), - path_, data))); + MakeCriticalClosure(base::Bind(IgnoreResult(task)))); } void ImportantFileWriter::ForwardSuccessfulWrite(bool result) {
diff --git a/base/files/important_file_writer.h b/base/files/important_file_writer.h index 9ead9c1..99f1a7c6 100644 --- a/base/files/important_file_writer.h +++ b/base/files/important_file_writer.h
@@ -78,7 +78,7 @@ // Save |data| to target filename. Does not block. If there is a pending write // scheduled by ScheduleWrite, it is cancelled. - void WriteNow(const std::string& data); + void WriteNow(scoped_ptr<std::string> data); // Schedule a save to target filename. Data will be serialized and saved // to disk after the commit interval. If another ScheduleWrite is issued @@ -106,7 +106,7 @@ private: // Helper method for WriteNow(). - bool PostWriteTask(const std::string& data); + bool PostWriteTask(const Callback<bool()>& task); // If |result| is true and |on_next_successful_write_| is set, invokes // |on_successful_write_| and then resets it; no-ops otherwise.
diff --git a/base/files/important_file_writer_unittest.cc b/base/files/important_file_writer_unittest.cc index 98eaee8..170c2b2 100644 --- a/base/files/important_file_writer_unittest.cc +++ b/base/files/important_file_writer_unittest.cc
@@ -100,7 +100,7 @@ ImportantFileWriter writer(file_, MessageLoopProxy::current().get()); EXPECT_FALSE(PathExists(writer.path())); EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); - writer.WriteNow("foo"); + writer.WriteNow(make_scoped_ptr(new std::string("foo"))); RunLoop().RunUntilIdle(); EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); @@ -113,7 +113,7 @@ EXPECT_FALSE(PathExists(writer.path())); EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); successful_write_observer_.ObserveNextSuccessfulWrite(&writer); - writer.WriteNow("foo"); + writer.WriteNow(make_scoped_ptr(new std::string("foo"))); RunLoop().RunUntilIdle(); // Confirm that the observer is invoked. @@ -124,7 +124,7 @@ // Confirm that re-installing the observer works for another write. EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); successful_write_observer_.ObserveNextSuccessfulWrite(&writer); - writer.WriteNow("bar"); + writer.WriteNow(make_scoped_ptr(new std::string("bar"))); RunLoop().RunUntilIdle(); EXPECT_TRUE(successful_write_observer_.GetAndResetObservationState()); @@ -134,7 +134,7 @@ // Confirm that writing again without re-installing the observer doesn't // result in a notification. EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState()); - writer.WriteNow("baz"); + writer.WriteNow(make_scoped_ptr(new std::string("baz"))); RunLoop().RunUntilIdle(); EXPECT_FALSE(successful_write_observer_.GetAndResetObservationState());
diff --git a/base/files/protect_file_posix.cc b/base/files/protect_file_posix.cc deleted file mode 100644 index e4753c4..0000000 --- a/base/files/protect_file_posix.cc +++ /dev/null
@@ -1,106 +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 "base/containers/hash_tables.h" -#include "base/files/file.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/posix/eintr_wrapper.h" -#include "base/synchronization/lock.h" - -// These hooks provided for base::File perform additional sanity checks when -// files are closed. These extra checks are hard to understand and maintain, -// hence they are temporary. TODO(pasko): Remove these extra checks as soon as -// crbug.com/424562 is fixed. -// -// Background: -// 1. The browser process crashes if a call to close() provided by the C -// library (i.e. close(3)) fails. This is done for security purposes. See -// base/files/scoped_file.cc. When a crash like this happens, there is not -// enough context in the minidump to triage the problem. -// 2. base::File provides a good abstraction to prevent closing incorrect -// file descriptors or double-closing. Closing non-owned file descriptors -// would more likely happen from outside base::File and base::ScopedFD. -// -// These hooks intercept base::File operations to 'protect' file handles / -// descriptors from accidental close(3) by other portions of the code being -// linked into the browser. Also, this file provides an interceptor for the -// close(3) itself, and requires to be linked with cooperation of -// --Wl,--wrap=close (i.e. linker wrapping). -// -// Wrapping close(3) on all libraries can lead to confusion, particularly for -// the libraries that do not use ::base (I am also looking at you, -// crazy_linker). Instead two hooks are added to base::File, which are -// implemented as no-op by default. This file should be linked into the Chrome -// native binary(-ies) for a whitelist of targets where "file descriptor -// protection" is useful. - -// With compilers other than GCC/Clang the wrapper is trivial. This is to avoid -// overexercising mechanisms for overriding weak symbols. -#if !defined(COMPILER_GCC) -extern "C" { - -int __real_close(int fd); - -BASE_EXPORT int __wrap_close(int fd) { - return __real_close(fd); -} - -} // extern "C" - -#else // defined(COMPILER_GCC) - -namespace { - -// Protects the |g_protected_fd_set|. -base::LazyInstance<base::Lock>::Leaky g_lock = LAZY_INSTANCE_INITIALIZER; - -// Holds the set of all 'protected' file descriptors. -base::LazyInstance<base::hash_set<int> >::Leaky g_protected_fd_set = - LAZY_INSTANCE_INITIALIZER; - -bool IsFileDescriptorProtected(int fd) { - base::AutoLock lock(*g_lock.Pointer()); - return g_protected_fd_set.Get().count(fd) != 0; -} - -} // namespace - -namespace base { - -BASE_EXPORT void ProtectFileDescriptor(int fd) { - base::AutoLock lock(g_lock.Get()); - CHECK(!g_protected_fd_set.Get().count(fd)) << "fd: " << fd; - g_protected_fd_set.Get().insert(fd); -} - -BASE_EXPORT void UnprotectFileDescriptor(int fd) { - base::AutoLock lock(*g_lock.Pointer()); - CHECK(g_protected_fd_set.Get().erase(fd)) << "fd: " << fd; -} - -} // namespace base - -extern "C" { - -int __real_close(int fd); - -BASE_EXPORT int __wrap_close(int fd) { - // The crash happens here if a protected file descriptor was attempted to be - // closed without first being unprotected. Unprotection happens only in - // base::File. In other words this is an "early crash" as compared to the one - // happening in scoped_file.cc. - // - // Getting an earlier crash provides a more useful stack trace (minidump) - // allowing to debug deeper into the thread that freed the wrong resource. - CHECK(!IsFileDescriptorProtected(fd)) << "fd: " << fd; - - // Crash by the same reason as in scoped_file.cc. - PCHECK(0 == IGNORE_EINTR(__real_close(fd))); - return 0; -} - -} // extern "C" - -#endif // defined(COMPILER_GCC)
diff --git a/base/files/protect_file_posix.gypi b/base/files/protect_file_posix.gypi deleted file mode 100644 index 017fd875..0000000 --- a/base/files/protect_file_posix.gypi +++ /dev/null
@@ -1,31 +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. - -# Provides sanity-checks and early crashes on some improper use of posix file -# descriptors. See protect_file_posix.cc for details. -# -# Usage: -# { -# 'target_name': 'libsomething', -# 'type': 'shared_library', // Do *not* use it for static libraries. -# 'includes': [ -# 'base/files/protect_file_posix.gypi', -# ], -# ... -# } -{ - 'conditions': [ - # In the component build the interceptors have to be declared with - # non-hidden visibility, which is not desirable for the release build. - # Disable the extra checks for the component build for simplicity. - ['component != "shared_library"', { - 'ldflags': [ - '-Wl,--wrap=close', - ], - 'dependencies': [ - '<(DEPTH)/base/base.gyp:protect_file_posix', - ], - }], - ], -}
diff --git a/base/float_util.h b/base/float_util.h deleted file mode 100644 index 90273106..0000000 --- a/base/float_util.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_FLOAT_UTIL_H_ -#define BASE_FLOAT_UTIL_H_ - -#include "build/build_config.h" - -#include <float.h> - -#include <cmath> - -namespace base { - -template <typename Float> -inline bool IsFinite(const Float& number) { -#if defined(OS_POSIX) - return std::isfinite(number) != 0; -#elif defined(OS_WIN) - return _finite(number) != 0; -#endif -} - -template <typename Float> -inline bool IsNaN(const Float& number) { -#if defined(OS_POSIX) - return std::isnan(number) != 0; -#elif defined(OS_WIN) - return _isnan(number) != 0; -#endif -} - -} // namespace base - -#endif // BASE_FLOAT_UTIL_H_
diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc index 8bbbc04..76eaa62 100644 --- a/base/i18n/icu_util.cc +++ b/base/i18n/icu_util.cc
@@ -10,6 +10,7 @@ #include <string> +#include "base/debug/alias.h" #include "base/files/file_path.h" #include "base/files/memory_mapped_file.h" #include "base/logging.h" @@ -130,6 +131,10 @@ #if defined(OS_WIN) // The data file will be in the same directory as the current module. bool path_ok = PathService::Get(base::DIR_MODULE, &data_path); + wchar_t tmp_buffer[_MAX_PATH] = {0}; + wcscpy_s(tmp_buffer, data_path.value().c_str()); + base::debug::Alias(tmp_buffer); + CHECK(path_ok); // TODO(scottmg): http://crbug.com/445616 #elif defined(OS_ANDROID) bool path_ok = PathService::Get(base::DIR_ANDROID_APP_DATA, &data_path); #else @@ -140,6 +145,14 @@ #endif DCHECK(path_ok); data_path = data_path.AppendASCII(kIcuDataFileName); + +#if defined(OS_WIN) + // TODO(scottmg): http://crbug.com/445616 + wchar_t tmp_buffer2[_MAX_PATH] = {0}; + wcscpy_s(tmp_buffer2, data_path.value().c_str()); + base::debug::Alias(tmp_buffer2); +#endif + #else // Assume it is in the framework bundle's Resources directory. base::ScopedCFTypeRef<CFStringRef> data_file_name( @@ -152,12 +165,18 @@ } #endif // OS check if (!mapped_file.Initialize(data_path)) { +#if defined(OS_WIN) + CHECK(false); // TODO(scottmg): http://crbug.com/445616 +#endif LOG(ERROR) << "Couldn't mmap " << data_path.AsUTF8Unsafe(); return false; } } UErrorCode err = U_ZERO_ERROR; udata_setCommonData(const_cast<uint8*>(mapped_file.data()), &err); +#if defined(OS_WIN) + CHECK(err == U_ZERO_ERROR); // TODO(scottmg): http://crbug.com/445616 +#endif return err == U_ZERO_ERROR; #endif }
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc index d42b1a3..e9a27bc 100644 --- a/base/json/json_parser.cc +++ b/base/json/json_parser.cc
@@ -4,7 +4,8 @@ #include "base/json/json_parser.h" -#include "base/float_util.h" +#include <cmath> + #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_number_conversions.h" @@ -872,7 +873,7 @@ double num_double; if (base::StringToDouble(num_string.as_string(), &num_double) && - IsFinite(num_double)) { + std::isfinite(num_double)) { return new FundamentalValue(num_double); }
diff --git a/base/md5.cc b/base/md5.cc index 9709a86..72c774d3 100644 --- a/base/md5.cc +++ b/base/md5.cc
@@ -37,11 +37,12 @@ * Note: this code is harmless on little-endian machines. */ void byteReverse(uint8_t* buf, unsigned longs) { - uint32_t t; do { - t = (uint32_t)((unsigned)buf[3] << 8 | buf[2]) << 16 | - ((unsigned)buf[1] << 8 | buf[0]); - *(uint32_t*)buf = t; + uint32_t temp = static_cast<uint32_t>( + static_cast<unsigned>(buf[3]) << 8 | + buf[2]) << 16 | + (static_cast<unsigned>(buf[1]) << 8 | buf[0]); + *reinterpret_cast<uint32_t*>(buf) = temp; buf += 4; } while (--longs); } @@ -154,7 +155,7 @@ * initialization constants. */ void MD5Init(MD5Context* context) { - struct Context* ctx = (struct Context*)context; + struct Context* ctx = reinterpret_cast<struct Context*>(context); ctx->buf[0] = 0x67452301; ctx->buf[1] = 0xefcdab89; ctx->buf[2] = 0x98badcfe; @@ -168,14 +169,14 @@ * of bytes. */ void MD5Update(MD5Context* context, const StringPiece& data) { - struct Context* ctx = (struct Context*)context; - const uint8_t* buf = (const uint8_t*)data.data(); + struct Context* ctx = reinterpret_cast<struct Context*>(context); + const uint8_t* buf = reinterpret_cast<const uint8_t*>(data.data()); size_t len = data.size(); /* Update bitcount */ uint32_t t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32_t)len << 3)) < t) + if ((ctx->bits[0] = t + (static_cast<uint32_t>(len) << 3)) < t) ctx->bits[1]++; /* Carry from low to high */ ctx->bits[1] += static_cast<uint32_t>(len >> 29); @@ -184,7 +185,7 @@ /* Handle any leading odd-sized chunks */ if (t) { - uint8_t* p = (uint8_t*)ctx->in + t; + uint8_t* p = static_cast<uint8_t*>(ctx->in + t); t = 64 - t; if (len < t) { @@ -193,7 +194,7 @@ } memcpy(p, buf, t); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t*)ctx->in); + MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in)); buf += t; len -= t; } @@ -203,7 +204,7 @@ while (len >= 64) { memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t*)ctx->in); + MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in)); buf += 64; len -= 64; } @@ -218,7 +219,7 @@ * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Final(MD5Digest* digest, MD5Context* context) { - struct Context* ctx = (struct Context*)context; + struct Context* ctx = reinterpret_cast<struct Context*>(context); unsigned count; uint8_t* p; @@ -238,7 +239,7 @@ /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32_t*)ctx->in); + MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in)); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); @@ -254,8 +255,8 @@ memcpy(&ctx->in[15 * sizeof(ctx->bits[1])], &ctx->bits[1], sizeof(ctx->bits[1])); - MD5Transform(ctx->buf, (uint32_t*)ctx->in); - byteReverse((uint8_t*)ctx->buf, 4); + MD5Transform(ctx->buf, reinterpret_cast<uint32_t*>(ctx->in)); + byteReverse(reinterpret_cast<uint8_t*>(ctx->buf), 4); memcpy(digest->a, ctx->buf, 16); memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ }
diff --git a/base/message_loop/message_pump_libevent.cc b/base/message_loop/message_pump_libevent.cc index 743b4f74..b5b1fb7e 100644 --- a/base/message_loop/message_pump_libevent.cc +++ b/base/message_loop/message_pump_libevent.cc
@@ -15,6 +15,7 @@ #include "base/observer_list.h" #include "base/posix/eintr_wrapper.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "third_party/libevent/event.h" #if defined(OS_MACOSX) @@ -344,6 +345,8 @@ WeakPtr<FileDescriptorWatcher> controller = static_cast<FileDescriptorWatcher*>(context)->weak_factory_.GetWeakPtr(); DCHECK(controller.get()); + TRACE_EVENT1("toplevel", "MessagePumpLibevent::OnLibeventNotification", + "fd", fd); MessagePumpLibevent* pump = controller->pump(); pump->processed_io_events_ = true;
diff --git a/base/observer_list.h b/base/observer_list.h index e473b32..9ea344d 100644 --- a/base/observer_list.h +++ b/base/observer_list.h
@@ -143,13 +143,13 @@ template <class ObserverType> ObserverType* ObserverListBase<ObserverType>::Iterator::GetNext() { if (!list_.get()) - return NULL; + return nullptr; ListType& observers = list_->observers_; // Advance if the current element is null size_t max_index = std::min(max_index_, observers.size()); while (index_ < max_index && !observers[index_]) ++index_; - return index_ < max_index ? observers[index_++] : NULL; + return index_ < max_index ? observers[index_++] : nullptr; } template <class ObserverType> @@ -170,7 +170,7 @@ std::find(observers_.begin(), observers_.end(), obs); if (it != observers_.end()) { if (notify_depth_) { - *it = 0; + *it = nullptr; } else { observers_.erase(it); } @@ -192,7 +192,7 @@ if (notify_depth_) { for (typename ListType::iterator it = observers_.begin(); it != observers_.end(); ++it) { - *it = 0; + *it = nullptr; } } else { observers_.clear(); @@ -202,8 +202,8 @@ template <class ObserverType> void ObserverListBase<ObserverType>::Compact() { observers_.erase( - std::remove(observers_.begin(), observers_.end(), - static_cast<ObserverType*>(NULL)), observers_.end()); + std::remove(observers_.begin(), observers_.end(), nullptr), + observers_.end()); } template <class ObserverType, bool check_empty = false> @@ -235,7 +235,7 @@ ObserverListBase<ObserverType>::Iterator it_inside_observer_macro( \ &observer_list); \ ObserverType* obs; \ - while ((obs = it_inside_observer_macro.GetNext()) != NULL) \ + while ((obs = it_inside_observer_macro.GetNext()) != nullptr) \ obs->func; \ } \ } while (0)
diff --git a/base/observer_list_threadsafe.h b/base/observer_list_threadsafe.h index 46ce880..5205a5a 100644 --- a/base/observer_list_threadsafe.h +++ b/base/observer_list_threadsafe.h
@@ -111,7 +111,7 @@ if (!base::MessageLoop::current()) return; - ObserverList<ObserverType>* list = NULL; + ObserverList<ObserverType>* list = nullptr; base::PlatformThreadId thread_id = base::PlatformThread::CurrentId(); { base::AutoLock lock(list_lock_); @@ -128,8 +128,8 @@ // If the observer to be removed is in the list, RemoveObserver MUST // be called from the same thread which called AddObserver. void RemoveObserver(ObserverType* obs) { - ObserverListContext* context = NULL; - ObserverList<ObserverType>* list = NULL; + ObserverListContext* context = nullptr; + ObserverList<ObserverType>* list = nullptr; base::PlatformThreadId thread_id = base::PlatformThread::CurrentId(); { base::AutoLock lock(list_lock_); @@ -230,7 +230,7 @@ { typename ObserverList<ObserverType>::Iterator it(&context->list); ObserverType* obs; - while ((obs = it.GetNext()) != NULL) + while ((obs = it.GetNext()) != nullptr) method.Run(obs); }
diff --git a/base/observer_list_unittest.cc b/base/observer_list_unittest.cc index 46b350b..ea916b1 100644 --- a/base/observer_list_unittest.cc +++ b/base/observer_list_unittest.cc
@@ -94,7 +94,7 @@ public: AddRemoveThread(ObserverListThreadSafe<Foo>* list, bool notify) : list_(list), - loop_(NULL), + loop_(nullptr), in_list_(false), start_(Time::Now()), count_observes_(0),
diff --git a/base/prefs/pref_registry.cc b/base/prefs/pref_registry.cc index 69f0494..74f4b52 100644 --- a/base/prefs/pref_registry.cc +++ b/base/prefs/pref_registry.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/prefs/default_pref_store.h" #include "base/prefs/pref_store.h" +#include "base/stl_util.h" #include "base/values.h" PrefRegistry::PrefRegistry() @@ -16,6 +17,13 @@ PrefRegistry::~PrefRegistry() { } +uint32 PrefRegistry::GetRegistrationFlags(const std::string& pref_name) const { + const auto& it = registration_flags_.find(pref_name); + if (it == registration_flags_.end()) + return NO_REGISTRATION_FLAGS; + return it->second; +} + scoped_refptr<PrefStore> PrefRegistry::defaults() { return defaults_.get(); } @@ -41,13 +49,18 @@ } void PrefRegistry::RegisterPreference(const std::string& path, - base::Value* default_value) { + base::Value* default_value, + uint32 flags) { base::Value::Type orig_type = default_value->GetType(); DCHECK(orig_type != base::Value::TYPE_NULL && orig_type != base::Value::TYPE_BINARY) << "invalid preference type: " << orig_type; DCHECK(!defaults_->GetValue(path, NULL)) << "Trying to register a previously registered pref: " << path; + DCHECK(!ContainsKey(registration_flags_, path)) << + "Trying to register a previously registered pref: " << path; defaults_->SetDefaultValue(path, make_scoped_ptr(default_value)); + if (flags != NO_REGISTRATION_FLAGS) + registration_flags_[path] = flags; }
diff --git a/base/prefs/pref_registry.h b/base/prefs/pref_registry.h index a500b6e..cc5804e 100644 --- a/base/prefs/pref_registry.h +++ b/base/prefs/pref_registry.h
@@ -5,6 +5,7 @@ #ifndef BASE_PREFS_PREF_REGISTRY_H_ #define BASE_PREFS_PREF_REGISTRY_H_ +#include "base/containers/hash_tables.h" #include "base/memory/ref_counted.h" #include "base/prefs/base_prefs_export.h" #include "base/prefs/pref_value_map.h" @@ -27,10 +28,26 @@ // also work, but this is being deprecated. class BASE_PREFS_EXPORT PrefRegistry : public base::RefCounted<PrefRegistry> { public: + // Registration flags that can be specified which impact how the pref will + // behave or be stored. This will be passed in a bitmask when the pref is + // registered. Subclasses of PrefRegistry can specify their own flags. Care + // must be taken to ensure none of these overlap with the flags below. + enum PrefRegistrationFlags { + // No flags are specified. + NO_REGISTRATION_FLAGS = 0, + + // The first 8 bits are reserved for subclasses of PrefRegistry to use. + }; + typedef PrefValueMap::const_iterator const_iterator; + typedef base::hash_map<std::string, uint32> PrefRegistrationFlagsMap; PrefRegistry(); + // Retrieve the set of registration flags for the given preference. The return + // value is a bitmask of PrefRegistrationFlags. + uint32 GetRegistrationFlags(const std::string& pref_name) const; + // Gets the registered defaults. scoped_refptr<PrefStore> defaults(); @@ -47,11 +64,17 @@ friend class base::RefCounted<PrefRegistry>; virtual ~PrefRegistry(); - // Used by subclasses to register a default value for a preference. - void RegisterPreference(const std::string& path, base::Value* default_value); + // Used by subclasses to register a default value and registration flags for + // a preference. |flags| is a bitmask of |PrefRegistrationFlags|. + void RegisterPreference(const std::string& path, + base::Value* default_value, + uint32 flags); scoped_refptr<DefaultPrefStore> defaults_; + // A map of pref name to a bitmask of PrefRegistrationFlags. + PrefRegistrationFlagsMap registration_flags_; + private: DISALLOW_COPY_AND_ASSIGN(PrefRegistry); };
diff --git a/base/prefs/pref_registry_simple.cc b/base/prefs/pref_registry_simple.cc index fa679dc9..93c2686 100644 --- a/base/prefs/pref_registry_simple.cc +++ b/base/prefs/pref_registry_simple.cc
@@ -16,51 +16,146 @@ void PrefRegistrySimple::RegisterBooleanPref(const std::string& path, bool default_value) { - RegisterPreference(path, new base::FundamentalValue(default_value)); + RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), + NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterIntegerPref(const std::string& path, int default_value) { - RegisterPreference(path, new base::FundamentalValue(default_value)); + RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), + NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterDoublePref(const std::string& path, double default_value) { - RegisterPreference(path, new base::FundamentalValue(default_value)); + RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), + NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterStringPref(const std::string& path, const std::string& default_value) { - RegisterPreference(path, new base::StringValue(default_value)); + RegisterPrefAndNotify(path, new base::StringValue(default_value), + NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterFilePathPref( const std::string& path, const base::FilePath& default_value) { - RegisterPreference(path, new base::StringValue(default_value.value())); + RegisterPrefAndNotify(path, new base::StringValue(default_value.value()), + NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterListPref(const std::string& path) { - RegisterPreference(path, new base::ListValue()); + RegisterPrefAndNotify(path, new base::ListValue(), NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterListPref(const std::string& path, base::ListValue* default_value) { - RegisterPreference(path, default_value); + RegisterPrefAndNotify(path, default_value, NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterDictionaryPref(const std::string& path) { - RegisterPreference(path, new base::DictionaryValue()); + RegisterPrefAndNotify(path, new base::DictionaryValue(), + NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterDictionaryPref( const std::string& path, base::DictionaryValue* default_value) { - RegisterPreference(path, default_value); + RegisterPrefAndNotify(path, default_value, NO_REGISTRATION_FLAGS); } void PrefRegistrySimple::RegisterInt64Pref(const std::string& path, int64 default_value) { - RegisterPreference( - path, new base::StringValue(base::Int64ToString(default_value))); + RegisterPrefAndNotify( + path, new base::StringValue(base::Int64ToString(default_value)), + NO_REGISTRATION_FLAGS); +} + +void PrefRegistrySimple::RegisterUint64Pref(const std::string& path, + uint64 default_value) { + RegisterPrefAndNotify( + path, new base::StringValue(base::Uint64ToString(default_value)), + NO_REGISTRATION_FLAGS); +} + +void PrefRegistrySimple::RegisterBooleanPref(const std::string& path, + bool default_value, + uint32 flags) { + RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags); +} + +void PrefRegistrySimple::RegisterIntegerPref(const std::string& path, + int default_value, + uint32 flags) { + RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags); +} + +void PrefRegistrySimple::RegisterDoublePref(const std::string& path, + double default_value, + uint32 flags) { + RegisterPrefAndNotify(path, new base::FundamentalValue(default_value), flags); +} + +void PrefRegistrySimple::RegisterStringPref(const std::string& path, + const std::string& default_value, + uint32 flags) { + RegisterPrefAndNotify(path, new base::StringValue(default_value), flags); +} + +void PrefRegistrySimple::RegisterFilePathPref( + const std::string& path, + const base::FilePath& default_value, + uint32 flags) { + RegisterPrefAndNotify(path, new base::StringValue(default_value.value()), + flags); +} + +void PrefRegistrySimple::RegisterListPref(const std::string& path, + uint32 flags) { + RegisterPrefAndNotify(path, new base::ListValue(), flags); +} + +void PrefRegistrySimple::RegisterListPref(const std::string& path, + base::ListValue* default_value, + uint32 flags) { + RegisterPrefAndNotify(path, default_value, flags); +} + +void PrefRegistrySimple::RegisterDictionaryPref(const std::string& path, + uint32 flags) { + RegisterPrefAndNotify(path, new base::DictionaryValue(), flags); +} + +void PrefRegistrySimple::RegisterDictionaryPref( + const std::string& path, + base::DictionaryValue* default_value, + uint32 flags) { + RegisterPrefAndNotify(path, default_value, flags); +} + +void PrefRegistrySimple::RegisterInt64Pref(const std::string& path, + int64 default_value, + uint32 flags) { + RegisterPrefAndNotify( + path, new base::StringValue(base::Int64ToString(default_value)), flags); +} + +void PrefRegistrySimple::RegisterUint64Pref(const std::string& path, + uint64 default_value, + uint32 flags) { + RegisterPrefAndNotify( + path, new base::StringValue(base::Uint64ToString(default_value)), flags); +} + +void PrefRegistrySimple::OnPrefRegistered(const std::string& path, + base::Value* default_value, + uint32 flags) { +} + +void PrefRegistrySimple::RegisterPrefAndNotify(const std::string& path, + base::Value* default_value, + uint32 flags) { + RegisterPreference(path, default_value, flags); + OnPrefRegistered(path, default_value, flags); }
diff --git a/base/prefs/pref_registry_simple.h b/base/prefs/pref_registry_simple.h index 73ae216..6b69e30c 100644 --- a/base/prefs/pref_registry_simple.h +++ b/base/prefs/pref_registry_simple.h
@@ -35,9 +35,48 @@ void RegisterDictionaryPref(const std::string& path, base::DictionaryValue* default_value); void RegisterInt64Pref(const std::string& path, int64 default_value); + void RegisterUint64Pref(const std::string&, uint64 default_value); + + // Versions of registration functions that accept PrefRegistrationFlags. + // |flags| is a bitmask of PrefRegistrationFlags. + void RegisterBooleanPref(const std::string&, + bool default_value, + uint32 flags); + void RegisterIntegerPref(const std::string&, int default_value, uint32 flags); + void RegisterDoublePref(const std::string&, + double default_value, + uint32 flags); + void RegisterStringPref(const std::string&, + const std::string& default_value, + uint32 flags); + void RegisterFilePathPref(const std::string&, + const base::FilePath& default_value, + uint32 flags); + void RegisterListPref(const std::string&, uint32 flags); + void RegisterDictionaryPref(const std::string&, uint32 flags); + void RegisterListPref(const std::string&, + base::ListValue* default_value, + uint32 flags); + void RegisterDictionaryPref(const std::string&, + base::DictionaryValue* default_value, + uint32 flags); + void RegisterInt64Pref(const std::string&, int64 default_value, uint32 flags); + void RegisterUint64Pref(const std::string&, + uint64 default_value, + uint32 flags); + + protected: + ~PrefRegistrySimple() override; + + // Allows subclasses to hook into pref registration. + virtual void OnPrefRegistered(const std::string&, + base::Value* default_value, + uint32 flags); private: - ~PrefRegistrySimple() override; + void RegisterPrefAndNotify(const std::string&, + base::Value* default_value, + uint32 flags); DISALLOW_COPY_AND_ASSIGN(PrefRegistrySimple); };
diff --git a/base/prefs/pref_value_map.cc b/base/prefs/pref_value_map.cc index cafc1d8b..5f2dc506b 100644 --- a/base/prefs/pref_value_map.cc +++ b/base/prefs/pref_value_map.cc
@@ -4,6 +4,8 @@ #include "base/prefs/pref_value_map.h" +#include <map> + #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/stl_util.h" @@ -18,51 +20,49 @@ bool PrefValueMap::GetValue(const std::string& key, const base::Value** value) const { const Map::const_iterator entry = prefs_.find(key); - if (entry != prefs_.end()) { - if (value) - *value = entry->second; - return true; - } + if (entry == prefs_.end()) + return false; - return false; + if (value) + *value = entry->second; + return true; } bool PrefValueMap::GetValue(const std::string& key, base::Value** value) { const Map::const_iterator entry = prefs_.find(key); - if (entry != prefs_.end()) { - if (value) - *value = entry->second; - return true; - } + if (entry == prefs_.end()) + return false; - return false; + if (value) + *value = entry->second; + return true; } bool PrefValueMap::SetValue(const std::string& key, base::Value* value) { DCHECK(value); + auto result = prefs_.insert(std::make_pair(key, value)); + if (result.second) + return true; + scoped_ptr<base::Value> value_ptr(value); - const Map::iterator entry = prefs_.find(key); - if (entry != prefs_.end()) { - if (base::Value::Equals(entry->second, value)) - return false; - delete entry->second; - entry->second = value_ptr.release(); - } else { - prefs_[key] = value_ptr.release(); - } + const Map::iterator& entry = result.first; + if (base::Value::Equals(entry->second, value)) + return false; + + delete entry->second; + entry->second = value_ptr.release(); return true; } bool PrefValueMap::RemoveValue(const std::string& key) { const Map::iterator entry = prefs_.find(key); - if (entry != prefs_.end()) { - delete entry->second; - prefs_.erase(entry); - return true; - } + if (entry == prefs_.end()) + return false; - return false; + delete entry->second; + prefs_.erase(entry); + return true; } void PrefValueMap::Clear() { @@ -91,7 +91,7 @@ bool PrefValueMap::GetBoolean(const std::string& key, bool* value) const { - const base::Value* stored_value = NULL; + const base::Value* stored_value = nullptr; return GetValue(key, &stored_value) && stored_value->GetAsBoolean(value); } @@ -101,7 +101,7 @@ bool PrefValueMap::GetString(const std::string& key, std::string* value) const { - const base::Value* stored_value = NULL; + const base::Value* stored_value = nullptr; return GetValue(key, &stored_value) && stored_value->GetAsString(value); } @@ -111,7 +111,7 @@ } bool PrefValueMap::GetInteger(const std::string& key, int* value) const { - const base::Value* stored_value = NULL; + const base::Value* stored_value = nullptr; return GetValue(key, &stored_value) && stored_value->GetAsInteger(value); } @@ -128,10 +128,15 @@ std::vector<std::string>* differing_keys) const { differing_keys->clear(); + // Put everything into ordered maps. + std::map<std::string, base::Value*> this_prefs(prefs_.begin(), prefs_.end()); + std::map<std::string, base::Value*> other_prefs(other->prefs_.begin(), + other->prefs_.end()); + // Walk over the maps in lockstep, adding everything that is different. - Map::const_iterator this_pref(prefs_.begin()); - Map::const_iterator other_pref(other->prefs_.begin()); - while (this_pref != prefs_.end() && other_pref != other->prefs_.end()) { + auto this_pref(this_prefs.begin()); + auto other_pref(other_prefs.begin()); + while (this_pref != this_prefs.end() && other_pref != other_prefs.end()) { const int diff = this_pref->first.compare(other_pref->first); if (diff == 0) { if (!this_pref->second->Equals(other_pref->second)) @@ -148,8 +153,8 @@ } // Add the remaining entries. - for ( ; this_pref != prefs_.end(); ++this_pref) + for ( ; this_pref != this_prefs.end(); ++this_pref) differing_keys->push_back(this_pref->first); - for ( ; other_pref != other->prefs_.end(); ++other_pref) + for ( ; other_pref != other_prefs.end(); ++other_pref) differing_keys->push_back(other_pref->first); }
diff --git a/base/prefs/pref_value_map.h b/base/prefs/pref_value_map.h index 2db18ab2..12b30c697 100644 --- a/base/prefs/pref_value_map.h +++ b/base/prefs/pref_value_map.h
@@ -5,11 +5,11 @@ #ifndef BASE_PREFS_PREF_VALUE_MAP_H_ #define BASE_PREFS_PREF_VALUE_MAP_H_ -#include <map> #include <string> #include <vector> #include "base/basictypes.h" +#include "base/containers/hash_tables.h" #include "base/prefs/base_prefs_export.h" namespace base { @@ -19,8 +19,9 @@ // A generic string to value map used by the PrefStore implementations. class BASE_PREFS_EXPORT PrefValueMap { public: - typedef std::map<std::string, base::Value*>::iterator iterator; - typedef std::map<std::string, base::Value*>::const_iterator const_iterator; + using Map = base::hash_map<std::string, base::Value*>; + using iterator = Map::iterator; + using const_iterator = Map::const_iterator; PrefValueMap(); virtual ~PrefValueMap(); @@ -81,8 +82,6 @@ std::vector<std::string>* differing_keys) const; private: - typedef std::map<std::string, base::Value*> Map; - Map prefs_; DISALLOW_COPY_AND_ASSIGN(PrefValueMap);
diff --git a/base/profiler/scoped_profile.h b/base/profiler/scoped_profile.h index c1e28302..6b0c800 100644 --- a/base/profiler/scoped_profile.h +++ b/base/profiler/scoped_profile.h
@@ -30,6 +30,14 @@ FROM_HERE_WITH_EXPLICIT_FUNCTION(#dispatch_function_name), \ ::tracked_objects::ScopedProfile::ENABLED) +// Same as TRACK_RUN_IN_THIS_SCOPED_REGION except that there's an extra param +// which is concatenated with the function name for better filtering. +#define TRACK_SCOPED_REGION(category_name, dispatch_function_name) \ + ::tracked_objects::ScopedProfile LINE_BASED_VARIABLE_NAME_FOR_PROFILING( \ + FROM_HERE_WITH_EXPLICIT_FUNCTION( \ + "[" category_name "]" dispatch_function_name), \ + ::tracked_objects::ScopedProfile::ENABLED) + namespace tracked_objects { class Births;
diff --git a/base/sys_info_chromeos.cc b/base/sys_info_chromeos.cc index ef5f1fe..9915055 100644 --- a/base/sys_info_chromeos.cc +++ b/base/sys_info_chromeos.cc
@@ -109,7 +109,7 @@ // Parse and cache lsb_release key pairs. There should only be a handful // of entries so the overhead for this will be small, and it can be // useful for debugging. - std::vector<std::pair<std::string, std::string> > pairs; + base::StringPairs pairs; SplitStringIntoKeyValuePairs(lsb_release, '=', '\n', &pairs); for (size_t i = 0; i < pairs.size(); ++i) { std::string key, value;
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java index a104831d..8a3395a 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java
@@ -14,10 +14,12 @@ import junit.framework.TestResult; import org.chromium.base.test.util.MinAndroidSdkLevel; +import org.chromium.test.reporter.TestStatusListener; import java.util.ArrayList; import java.util.List; +// TODO(jbudorick): Add support for on-device handling of timeouts. /** * An Instrumentation test runner that checks SDK level for tests with specific requirements. */ @@ -88,7 +90,7 @@ @Override protected AndroidTestRunner getAndroidTestRunner() { - return new AndroidTestRunner() { + AndroidTestRunner runner = new AndroidTestRunner() { @Override protected TestResult createTestResult() { SkippingTestResult r = new SkippingTestResult(); @@ -96,6 +98,8 @@ return r; } }; + runner.addTestListener(new TestStatusListener(getContext())); + return runner; } /**
diff --git a/base/test/test_suite.cc b/base/test/test_suite.cc index ee135e53..6c766eb 100644 --- a/base/test/test_suite.cc +++ b/base/test/test_suite.cc
@@ -51,6 +51,8 @@ #include "base/test/test_support_ios.h" #endif +namespace base { + namespace { class MaybeTestDisabler : public testing::EmptyTestEventListener { @@ -66,35 +68,31 @@ class TestClientInitializer : public testing::EmptyTestEventListener { public: TestClientInitializer() - : old_command_line_(base::CommandLine::NO_PROGRAM) { + : old_command_line_(CommandLine::NO_PROGRAM) { } void OnTestStart(const testing::TestInfo& test_info) override { - old_command_line_ = *base::CommandLine::ForCurrentProcess(); + old_command_line_ = *CommandLine::ForCurrentProcess(); } void OnTestEnd(const testing::TestInfo& test_info) override { - *base::CommandLine::ForCurrentProcess() = old_command_line_; + *CommandLine::ForCurrentProcess() = old_command_line_; } private: - base::CommandLine old_command_line_; + CommandLine old_command_line_; DISALLOW_COPY_AND_ASSIGN(TestClientInitializer); }; } // namespace -namespace base { - int RunUnitTestsUsingBaseTestSuite(int argc, char **argv) { TestSuite test_suite(argc, argv); - return base::LaunchUnitTests( - argc, argv, Bind(&TestSuite::Run, Unretained(&test_suite))); + return LaunchUnitTests(argc, argv, + Bind(&TestSuite::Run, Unretained(&test_suite))); } -} // namespace base - TestSuite::TestSuite(int argc, char** argv) : initialized_command_line_(false) { PreInitialize(true); InitializeFromCommandLine(argc, argv); @@ -116,11 +114,11 @@ TestSuite::~TestSuite() { if (initialized_command_line_) - base::CommandLine::Reset(); + CommandLine::Reset(); } void TestSuite::InitializeFromCommandLine(int argc, char** argv) { - initialized_command_line_ = base::CommandLine::Init(argc, argv); + initialized_command_line_ = CommandLine::Init(argc, argv); testing::InitGoogleTest(&argc, argv); testing::InitGoogleMock(&argc, argv); @@ -132,7 +130,7 @@ #if defined(OS_WIN) void TestSuite::InitializeFromCommandLine(int argc, wchar_t** argv) { // Windows CommandLine::Init ignores argv anyway. - initialized_command_line_ = base::CommandLine::Init(argc, NULL); + initialized_command_line_ = CommandLine::Init(argc, NULL); testing::InitGoogleTest(&argc, argv); testing::InitGoogleMock(&argc, argv); } @@ -142,7 +140,7 @@ #if defined(OS_WIN) testing::GTEST_FLAG(catch_exceptions) = false; #endif - base::EnableTerminationOnHeapCorruption(); + EnableTerminationOnHeapCorruption(); #if defined(OS_LINUX) && defined(USE_AURA) // When calling native char conversion functions (e.g wrctomb) we need to // have the locale set. In the absence of such a call the "C" locale is the @@ -154,7 +152,7 @@ // testing/android/native_test_wrapper.cc before main() is called. #if !defined(OS_ANDROID) if (create_at_exit_manager) - at_exit_manager_.reset(new base::AtExitManager); + at_exit_manager_.reset(new AtExitManager); #endif // Don't add additional code to this function. Instead add it to @@ -181,13 +179,13 @@ void TestSuite::AddTestLauncherResultPrinter() { // Only add the custom printer if requested. - if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + if (!CommandLine::ForCurrentProcess()->HasSwitch( switches::kTestLauncherOutput)) { return; } - FilePath output_path(base::CommandLine::ForCurrentProcess()-> - GetSwitchValuePath(switches::kTestLauncherOutput)); + FilePath output_path(CommandLine::ForCurrentProcess()->GetSwitchValuePath( + switches::kTestLauncherOutput)); // Do not add the result printer if output path already exists. It's an // indicator there is a process printing to that file, and we're likely @@ -213,19 +211,19 @@ #endif #if defined(OS_MACOSX) - base::mac::ScopedNSAutoreleasePool scoped_pool; + mac::ScopedNSAutoreleasePool scoped_pool; #endif Initialize(); std::string client_func = - base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kTestChildProcess); // Check to see if we are being run as a client process. if (!client_func.empty()) return multi_process_function_list::InvokeChildProcessTest(client_func); #if defined(OS_IOS) - base::test_listener_ios::RegisterTestEndListener(); + test_listener_ios::RegisterTestEndListener(); #endif int result = RUN_ALL_TESTS(); @@ -285,9 +283,8 @@ void TestSuite::Initialize() { #if !defined(OS_IOS) - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kWaitForDebugger)) { - base::debug::WaitForDebugger(60, true); + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kWaitForDebugger)) { + debug::WaitForDebugger(60, true); } #endif @@ -299,9 +296,9 @@ InitAndroidTest(); #else // Initialize logging. - base::FilePath exe; - PathService::Get(base::FILE_EXE, &exe); - base::FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log")); + FilePath exe; + PathService::Get(FILE_EXE, &exe); + FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log")); logging::LoggingSettings settings; settings.logging_dest = logging::LOG_TO_ALL; settings.log_file = log_filename.value().c_str(); @@ -312,23 +309,22 @@ logging::SetLogItems(true, true, true, true); #endif // else defined(OS_ANDROID) - CHECK(base::debug::EnableInProcessStackDumping()); + CHECK(debug::EnableInProcessStackDumping()); #if defined(OS_WIN) // Make sure we run with high resolution timer to minimize differences // between production code and test code. - base::Time::EnableHighResolutionTimer(true); + Time::EnableHighResolutionTimer(true); #endif // defined(OS_WIN) // In some cases, we do not want to see standard error dialogs. - if (!base::debug::BeingDebugged() && - !base::CommandLine::ForCurrentProcess()->HasSwitch( - "show-error-dialogs")) { + if (!debug::BeingDebugged() && + !CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) { SuppressErrorDialogs(); - base::debug::SetSuppressDebugUI(true); + debug::SetSuppressDebugUI(true); logging::SetLogAssertHandler(UnitTestAssertHandler); } - base::i18n::InitializeICU(); + i18n::InitializeICU(); // On the Mac OS X command line, the default locale is *_POSIX. In Chromium, // the locale is set via an OS X locale API and is never *_POSIX. // Some tests (such as those involving word break iterator) will behave @@ -338,11 +334,11 @@ // TODO(jshin): Should we set the locale via an OS X locale API here? #if !defined(OS_WIN) #if defined(OS_IOS) - base::i18n::SetICUDefaultLocale("en_US"); + i18n::SetICUDefaultLocale("en_US"); #else std::string default_locale(uloc_getDefault()); if (EndsWith(default_locale, "POSIX", false)) - base::i18n::SetICUDefaultLocale("en_US"); + i18n::SetICUDefaultLocale("en_US"); #endif #endif @@ -357,3 +353,5 @@ void TestSuite::Shutdown() { } + +} // namespace base
diff --git a/base/test/test_suite.h b/base/test/test_suite.h index fa0ab6c4..cf0dd3ae 100644 --- a/base/test/test_suite.h +++ b/base/test/test_suite.h
@@ -90,8 +90,4 @@ } // namespace base -// TODO(brettw) remove this. This is a temporary hack to allow WebKit to compile -// until we can update it to use "base::" (preventing a two-sided patch). -using base::TestSuite; - #endif // BASE_TEST_TEST_SUITE_H_
diff --git a/base/threading/thread_local_storage_unittest.cc b/base/threading/thread_local_storage_unittest.cc index b53f577..bcc1d1b 100644 --- a/base/threading/thread_local_storage_unittest.cc +++ b/base/threading/thread_local_storage_unittest.cc
@@ -79,17 +79,16 @@ EXPECT_EQ(value, 123); } -#if defined(THREAD_SANITIZER) || \ - (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && \ - defined(INCREMENTAL_LINKING)) +#if defined(THREAD_SANITIZER) || \ + (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && !defined(NDEBUG)) // Do not run the test under ThreadSanitizer. Because this test iterates its // own TSD destructor for the maximum possible number of times, TSan can't jump // in after the last destructor invocation, therefore the destructor remains // unsynchronized with the following users of the same TSD slot. This results // in race reports between the destructor and functions in other tests. // -// It is disabled on Win x64 with incremental linking pending resolution of -// http://crbug.com/251251. +// It is disabled on Win x64 with incremental linking (i.e. "Debug") pending +// resolution of http://crbug.com/251251. #define MAYBE_TLSDestructors DISABLED_TLSDestructors #else #define MAYBE_TLSDestructors TLSDestructors
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index 75d8925..54f50eb 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -42,6 +42,7 @@ class NestedMessagePumpAndroid; class RenderWidgetResizeHelper; class ScopedAllowWaitForAndroidLayoutTests; +class ScopedAllowWaitForDebugURL; class TextInputClientMac; } // namespace content namespace dbus { @@ -175,6 +176,7 @@ friend class content::NestedMessagePumpAndroid; friend class content::RenderWidgetResizeHelper; friend class content::ScopedAllowWaitForAndroidLayoutTests; + friend class content::ScopedAllowWaitForDebugURL; friend class ::HistogramSynchronizer; friend class ::ScopedAllowWaitForLegacyWebViewApi; friend class cc::CompletionEvent;
diff --git a/base/time/time.cc b/base/time/time.cc index 321323b7..bf6c998 100644 --- a/base/time/time.cc +++ b/base/time/time.cc
@@ -4,12 +4,12 @@ #include "base/time/time.h" +#include <cmath> #include <ios> #include <limits> #include <ostream> #include <sstream> -#include "base/float_util.h" #include "base/lazy_instance.h" #include "base/logging.h" #include "base/strings/stringprintf.h" @@ -161,7 +161,7 @@ // static Time Time::FromDoubleT(double dt) { - if (dt == 0 || IsNaN(dt)) + if (dt == 0 || std::isnan(dt)) return Time(); // Preserve 0 so we can tell it doesn't exist. if (dt == std::numeric_limits<double>::infinity()) return Max();
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn index db5509e2..4f3819d 100644 --- a/base/trace_event/BUILD.gn +++ b/base/trace_event/BUILD.gn
@@ -4,6 +4,8 @@ source_set("trace_event") { sources = [ + "java_heap_dump_provider_android.cc", + "java_heap_dump_provider_android.h", "memory_allocator_attributes_type_info.cc", "memory_allocator_attributes_type_info.h", "memory_allocator_dump.cc", @@ -42,6 +44,8 @@ "trace_event_system_stats_monitor.h", "trace_event_win.cc", "trace_event_win.h", + "winheap_dump_provider_win.cc", + "winheap_dump_provider_win.h", ] if (is_nacl) { @@ -95,6 +99,7 @@ "trace_event_system_stats_monitor_unittest.cc", "trace_event_unittest.cc", "trace_event_win_unittest.cc", + "winheap_dump_provider_win_unittest.cc", ] deps = [
diff --git a/base/trace_event/OWNERS b/base/trace_event/OWNERS index 3932776..aa1d675 100644 --- a/base/trace_event/OWNERS +++ b/base/trace_event/OWNERS
@@ -1,3 +1,4 @@ nduca@chromium.org dsinclair@chromium.org +primiano@chromium.org per-file trace_event_android.cc=wangxianzhu@chromium.org
diff --git a/base/trace_event/java_heap_dump_provider_android.cc b/base/trace_event/java_heap_dump_provider_android.cc new file mode 100644 index 0000000..aa193ab7 --- /dev/null +++ b/base/trace_event/java_heap_dump_provider_android.cc
@@ -0,0 +1,53 @@ +// 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/trace_event/java_heap_dump_provider_android.h" + +#include "base/android/java_runtime.h" +#include "base/trace_event/process_memory_dump.h" + +namespace base { +namespace trace_event { + +namespace { + +const char kDumperFriendlyName[] = "JavaHeap"; +const char kDumperName[] = "java_heap"; + +} // namespace + +// static +JavaHeapDumpProvider* JavaHeapDumpProvider::GetInstance() { + return Singleton<JavaHeapDumpProvider, + LeakySingletonTraits<JavaHeapDumpProvider>>::get(); +} + +JavaHeapDumpProvider::JavaHeapDumpProvider() { +} + +JavaHeapDumpProvider::~JavaHeapDumpProvider() { +} + +// Called at trace dump point time. Creates a snapshot with the memory counters +// for the current process. +bool JavaHeapDumpProvider::DumpInto(ProcessMemoryDump* pmd) { + MemoryAllocatorDump* dump = + pmd->CreateAllocatorDump(kDumperName, MemoryAllocatorDump::kRootHeap); + + // These numbers come from java.lang.Runtime stats. + long total_heap_size = 0; + long free_heap_size = 0; + android::JavaRuntime::GetMemoryUsage(&total_heap_size, &free_heap_size); + dump->set_physical_size_in_bytes(total_heap_size); + dump->set_allocated_objects_count(0); + dump->set_allocated_objects_size_in_bytes(total_heap_size - free_heap_size); + return true; +} + +const char* JavaHeapDumpProvider::GetFriendlyName() const { + return kDumperFriendlyName; +} + +} // namespace trace_event +} // namespace base
diff --git a/base/trace_event/java_heap_dump_provider_android.h b/base/trace_event/java_heap_dump_provider_android.h new file mode 100644 index 0000000..8280751 --- /dev/null +++ b/base/trace_event/java_heap_dump_provider_android.h
@@ -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. + +#ifndef BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_ +#define BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_ + +#include "base/memory/singleton.h" +#include "base/trace_event/memory_dump_provider.h" + +namespace base { +namespace trace_event { + +// Dump provider which collects process-wide memory stats. +class JavaHeapDumpProvider : public MemoryDumpProvider { + public: + static JavaHeapDumpProvider* GetInstance(); + + // MemoryDumpProvider implementation. + bool DumpInto(ProcessMemoryDump* pmd) override; + const char* GetFriendlyName() const override; + + private: + friend struct DefaultSingletonTraits<JavaHeapDumpProvider>; + + JavaHeapDumpProvider(); + ~JavaHeapDumpProvider() override; + + DISALLOW_COPY_AND_ASSIGN(JavaHeapDumpProvider); +}; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_JAVA_HEAP_DUMP_PROVIDER_ANDROID_H_
diff --git a/base/trace_event/memory_allocator_dump.cc b/base/trace_event/memory_allocator_dump.cc index 13f5dcb..1d2fb3f 100644 --- a/base/trace_event/memory_allocator_dump.cc +++ b/base/trace_event/memory_allocator_dump.cc
@@ -74,16 +74,31 @@ static const char kHexFmt[] = "%" PRIx64; value->BeginDictionary(GetAbsoluteName().c_str()); + value->BeginDictionary("attrs"); - value->SetString("physical_size_in_bytes", - StringPrintf(kHexFmt, physical_size_in_bytes_)); - value->SetString("allocated_objects_count", - StringPrintf(kHexFmt, allocated_objects_count_)); - value->SetString("allocated_objects_size_in_bytes", + // TODO(primiano): these hard-coded types are temporary to transition to the + // new generalized attribute format. This code will be refactored by the end + // of May 2015. + value->BeginDictionary("outer_size"); + value->SetString("type", "scalar"); + value->SetString("units", "bytes"); + value->SetString("value", StringPrintf(kHexFmt, physical_size_in_bytes_)); + value->EndDictionary(); + + value->BeginDictionary("inner_size"); + value->SetString("type", "scalar"); + value->SetString("units", "bytes"); + value->SetString("value", StringPrintf(kHexFmt, allocated_objects_size_in_bytes_)); + value->EndDictionary(); + + value->BeginDictionary("objects_count"); + value->SetString("type", "scalar"); + value->SetString("units", "objects"); + value->SetString("value", StringPrintf(kHexFmt, allocated_objects_count_)); + value->EndDictionary(); // Copy all the extra attributes. - value->BeginDictionary("args"); for (DictionaryValue::Iterator it(attributes_values_); !it.IsAtEnd(); it.Advance()) { const std::string& attr_name = it.key(); @@ -91,17 +106,16 @@ value->BeginDictionary(attr_name.c_str()); value->SetValue("value", attr_value.DeepCopy()); - // TODO(primiano): the "type" should be dumped just once, not repeated on - // on every event. The ability of doing so depends on crbug.com/466121. const std::string& attr_type = GetAttributesTypeInfo().Get(allocator_name_, attr_name); DCHECK(!attr_type.empty()); - value->SetString("type", attr_type); + value->SetString("type", "scalar"); + value->SetString("units", attr_type); value->EndDictionary(); // "arg_name": { "type": "...", "value": "..." } } - value->EndDictionary(); // "args": { ... } + value->EndDictionary(); // "attrs": { ... } value->EndDictionary(); // "allocator_name/heap_subheap": { ... } }
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc index 63d91bb4..859e8e0 100644 --- a/base/trace_event/memory_dump_manager.cc +++ b/base/trace_event/memory_dump_manager.cc
@@ -17,6 +17,8 @@ #include "base/trace_event/malloc_dump_provider.h" #include "base/trace_event/process_memory_maps_dump_provider.h" #include "base/trace_event/process_memory_totals_dump_provider.h" +#elif defined(OS_WIN) +#include "base/trace_event/winheap_dump_provider_win.h" #endif namespace base { @@ -165,6 +167,8 @@ RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance()); RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance()); RegisterDumpProvider(MallocDumpProvider::GetInstance()); +#elif defined(OS_WIN) + RegisterDumpProvider(WinHeapDumpProvider::GetInstance()); #endif }
diff --git a/base/trace_event/trace_event.gypi b/base/trace_event/trace_event.gypi index 5cd8ca43..9bbd172 100644 --- a/base/trace_event/trace_event.gypi +++ b/base/trace_event/trace_event.gypi
@@ -4,6 +4,8 @@ { 'variables': { 'trace_event_sources' : [ + 'trace_event/java_heap_dump_provider_android.cc', + 'trace_event/java_heap_dump_provider_android.h', 'trace_event/memory_allocator_attributes_type_info.cc', 'trace_event/memory_allocator_attributes_type_info.h', 'trace_event/memory_allocator_dump.cc', @@ -42,6 +44,8 @@ 'trace_event/trace_event_system_stats_monitor.h', 'trace_event/trace_event_win.cc', 'trace_event/trace_event_win.h', + 'trace_event/winheap_dump_provider_win.cc', + 'trace_event/winheap_dump_provider_win.h', ], 'conditions': [ ['OS == "linux" or OS == "android"', { @@ -63,6 +67,7 @@ 'trace_event/trace_event_system_stats_monitor_unittest.cc', 'trace_event/trace_event_unittest.cc', 'trace_event/trace_event_win_unittest.cc', + 'trace_event/winheap_dump_provider_win_unittest.cc', ], }, }
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc index 12f9598a..cbeeeabb 100644 --- a/base/trace_event/trace_event_impl.cc +++ b/base/trace_event/trace_event_impl.cc
@@ -5,12 +5,12 @@ #include "base/trace_event/trace_event_impl.h" #include <algorithm> +#include <cmath> #include "base/base_switches.h" #include "base/bind.h" #include "base/command_line.h" #include "base/debug/leak_annotations.h" -#include "base/float_util.h" #include "base/format_macros.h" #include "base/json/string_escape.h" #include "base/lazy_instance.h" @@ -647,7 +647,7 @@ // should be made into a common method. std::string real; double val = value.as_double; - if (IsFinite(val)) { + if (std::isfinite(val)) { real = DoubleToString(val); // Ensure that the number has a .0 if there's no decimal or 'e'. This // makes sure that when we read the JSON back, it's interpreted as a @@ -665,7 +665,7 @@ // "-.1" bad "-0.1" good real.insert(1, "0"); } - } else if (IsNaN(val)){ + } else if (std::isnan(val)){ // The JSON spec doesn't allow NaN and Infinity (since these are // objects in EcmaScript). Use strings instead. real = "\"NaN\"";
diff --git a/base/trace_event/winheap_dump_provider_win.cc b/base/trace_event/winheap_dump_provider_win.cc new file mode 100644 index 0000000..3a4fd870 --- /dev/null +++ b/base/trace_event/winheap_dump_provider_win.cc
@@ -0,0 +1,103 @@ +// 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/trace_event/winheap_dump_provider_win.h" + +#include <windows.h> + +#include "base/trace_event/process_memory_dump.h" + +namespace base { +namespace trace_event { + +namespace { + +const char kDumperFriendlyName[] = "winheap"; + +// Report a heap dump to a process memory dump. The |heap_info| structure +// contains the information about this heap, and |heap_name| will be used to +// represent it in the report. +bool ReportHeapDump(ProcessMemoryDump* pmd, + const WinHeapInfo& heap_info, + const std::string& heap_name) { + MemoryAllocatorDump* dump = + pmd->CreateAllocatorDump(kDumperFriendlyName, heap_name); + if (!dump) + return false; + dump->set_physical_size_in_bytes(heap_info.committed_size); + dump->set_allocated_objects_count(heap_info.block_count); + dump->set_allocated_objects_size_in_bytes(heap_info.allocated_size); + return true; +} + +} // namespace + +WinHeapDumpProvider* WinHeapDumpProvider::GetInstance() { + return Singleton<WinHeapDumpProvider, + LeakySingletonTraits<WinHeapDumpProvider>>::get(); +} + +bool WinHeapDumpProvider::DumpInto(ProcessMemoryDump* pmd) { + // Retrieves the number of heaps in the current process. + DWORD number_of_heaps = ::GetProcessHeaps(0, NULL); + WinHeapInfo all_heap_info = {0}; + + // Try to retrieve a handle to all the heaps owned by this process. Returns + // false if the number of heaps has changed. + // + // This is inherently racy as is, but it's not something that we observe a lot + // in Chrome, the heaps tend to be created at startup only. + scoped_ptr<HANDLE[]> all_heaps(new HANDLE[number_of_heaps]); + if (::GetProcessHeaps(number_of_heaps, all_heaps.get()) != number_of_heaps) + return false; + + // Skip the pointer to the heap array to avoid accounting the memory used by + // this dump provider. + std::set<void*> block_to_skip; + block_to_skip.insert(all_heaps.get()); + + // Retrieves some metrics about each heap. + for (size_t i = 0; i < number_of_heaps; ++i) { + WinHeapInfo heap_info = {0}; + heap_info.heap_id = all_heaps[i]; + GetHeapInformation(&heap_info, block_to_skip); + + all_heap_info.allocated_size += heap_info.allocated_size; + all_heap_info.committed_size += heap_info.committed_size; + all_heap_info.block_count += heap_info.block_count; + } + // Report the heap dump. + if (!ReportHeapDump(pmd, all_heap_info, MemoryAllocatorDump::kRootHeap)) + return false; + + return true; +} + +const char* WinHeapDumpProvider::GetFriendlyName() const { + return kDumperFriendlyName; +} + +bool WinHeapDumpProvider::GetHeapInformation( + WinHeapInfo* heap_info, + const std::set<void*>& block_to_skip) { + CHECK(::HeapLock(heap_info->heap_id) == TRUE); + PROCESS_HEAP_ENTRY heap_entry; + heap_entry.lpData = nullptr; + // Walk over all the entries in this heap. + while (::HeapWalk(heap_info->heap_id, &heap_entry) != FALSE) { + if (block_to_skip.count(heap_entry.lpData) == 1) + continue; + if ((heap_entry.wFlags & PROCESS_HEAP_ENTRY_BUSY) != 0) { + heap_info->allocated_size += heap_entry.cbData; + heap_info->block_count++; + } else if ((heap_entry.wFlags & PROCESS_HEAP_REGION) != 0) { + heap_info->committed_size += heap_entry.Region.dwCommittedSize; + } + } + CHECK(::HeapUnlock(heap_info->heap_id) == TRUE); + return true; +} + +} // namespace trace_event +} // namespace base
diff --git a/base/trace_event/winheap_dump_provider_win.h b/base/trace_event/winheap_dump_provider_win.h new file mode 100644 index 0000000..8abac47 --- /dev/null +++ b/base/trace_event/winheap_dump_provider_win.h
@@ -0,0 +1,53 @@ +// 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 BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_ +#define BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_ + +#include <set> + +#include "base/memory/singleton.h" +#include "base/trace_event/memory_dump_provider.h" + +namespace base { +namespace trace_event { + +// A structure containing some information about a given heap. +struct WinHeapInfo { + HANDLE heap_id; + size_t committed_size; + size_t allocated_size; + size_t block_count; +}; + +// Dump provider which collects process-wide heap memory stats. This provider +// iterates over all the heaps of the current process to gather some metrics +// about them. +class BASE_EXPORT WinHeapDumpProvider : public MemoryDumpProvider { + public: + static WinHeapDumpProvider* GetInstance(); + + // MemoryDumpProvider implementation. + bool DumpInto(ProcessMemoryDump* pmd) override; + const char* GetFriendlyName() const override; + + private: + friend struct DefaultSingletonTraits<WinHeapDumpProvider>; + + // Retrieves the information about given heap. The |heap_info| should contain + // a valid handle to an existing heap. The blocks contained in the + // |block_to_skip| set will be ignored. + bool GetHeapInformation(WinHeapInfo* heap_info, + const std::set<void*>& block_to_skip); + + WinHeapDumpProvider() {} + ~WinHeapDumpProvider() override {} + + DISALLOW_COPY_AND_ASSIGN(WinHeapDumpProvider); +}; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_WINHEAP_DUMP_PROVIDER_WIN_H_
diff --git a/base/trace_event/winheap_dump_provider_win_unittest.cc b/base/trace_event/winheap_dump_provider_win_unittest.cc new file mode 100644 index 0000000..99da18a --- /dev/null +++ b/base/trace_event/winheap_dump_provider_win_unittest.cc
@@ -0,0 +1,27 @@ +// 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/trace_event/winheap_dump_provider_win.h" + +#include <windows.h> + +#include "base/trace_event/memory_dump_session_state.h" +#include "base/trace_event/process_memory_dump.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace trace_event { + +TEST(WinHeapDumpProviderTest, DumpInto) { + ProcessMemoryDump pmd(make_scoped_refptr(new MemoryDumpSessionState())); + + WinHeapDumpProvider* winheap_dump_provider = + WinHeapDumpProvider::GetInstance(); + ASSERT_NE(static_cast<WinHeapDumpProvider*>(nullptr), winheap_dump_provider); + + ASSERT_TRUE(winheap_dump_provider->DumpInto(&pmd)); +} + +} // namespace trace_event +} // namespace base
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc index a60e260..5747458 100644 --- a/base/tracked_objects.cc +++ b/base/tracked_objects.cc
@@ -37,7 +37,7 @@ // record all of the startup-time tasks, or should we start up DEACTIVATED, so // that we only record after parsing the command line flag --enable-tracking. // Note that the flag may force either state, so this really controls only the -// period of time up until that flag is parsed. If there is no flag seen, then +// period of time up until that flag is parsed. If there is no flag seen, then // this state may prevail for much or all of the process lifetime. const ThreadData::Status kInitialStartupState = ThreadData::PROFILING_CHILDREN_ACTIVE; @@ -61,9 +61,10 @@ // State of the profiler timing enabledness. base::subtle::Atomic32 g_profiler_timing_enabled = UNDEFINED_TIMING; -// Returns whether profiler timing is enabled. The default is true, but this may -// be overridden by a command-line flag. Some platforms may programmatically set -// this command-line flag to the "off" value if it's not specified. +// Returns whether profiler timing is enabled. The default is true, but this +// may be overridden by a command-line flag. Some platforms may +// programmatically set this command-line flag to the "off" value if it's not +// specified. // This in turn can be overridden by explicitly calling // ThreadData::EnableProfilerTiming, say, based on a field trial. inline bool IsProfilerTimingEnabled() { @@ -92,13 +93,40 @@ //------------------------------------------------------------------------------ // DeathData tallies durations when a death takes place. -DeathData::DeathData() { - Clear(); +DeathData::DeathData() + : count_(0), + sample_probability_count_(0), + run_duration_sum_(0), + queue_duration_sum_(0), + run_duration_max_(0), + queue_duration_max_(0), + run_duration_sample_(0), + queue_duration_sample_(0), + last_phase_snapshot_(nullptr) { } -DeathData::DeathData(int count) { - Clear(); - count_ = count; +DeathData::DeathData(const DeathData& other) + : count_(other.count_), + sample_probability_count_(other.sample_probability_count_), + run_duration_sum_(other.run_duration_sum_), + queue_duration_sum_(other.queue_duration_sum_), + run_duration_max_(other.run_duration_max_), + queue_duration_max_(other.queue_duration_max_), + run_duration_sample_(other.run_duration_sample_), + queue_duration_sample_(other.queue_duration_sample_), + last_phase_snapshot_(nullptr) { + // This constructor will be used by std::map when adding new DeathData values + // to the map. At that point, last_phase_snapshot_ is still NULL, so we don't + // need to worry about ownership transfer. + DCHECK(other.last_phase_snapshot_ == nullptr); +} + +DeathData::~DeathData() { + while (last_phase_snapshot_) { + const DeathDataPhaseSnapshot* snapshot = last_phase_snapshot_; + last_phase_snapshot_ = snapshot->prev; + delete snapshot; + } } // TODO(jar): I need to see if this macro to optimize branching is worth using. @@ -117,6 +145,12 @@ // We'll just clamp at INT_MAX, but we should note this in the UI as such. if (count_ < INT_MAX) ++count_; + + int sample_probability_count = sample_probability_count_; + if (sample_probability_count < INT_MAX) + ++sample_probability_count; + sample_probability_count_ = sample_probability_count; + queue_duration_sum_ += queue_duration; run_duration_sum_ += run_duration; @@ -125,14 +159,16 @@ if (run_duration_max_ < run_duration) run_duration_max_ = run_duration; - // Take a uniformly distributed sample over all durations ever supplied. - // The probability that we (instead) use this new sample is 1/count_. This - // results in a completely uniform selection of the sample (at least when we - // don't clamp count_... but that should be inconsequentially likely). - // We ignore the fact that we correlated our selection of a sample to the run - // and queue times (i.e., we used them to generate random_number). - CHECK_GT(count_, 0); - if (0 == (random_number % count_)) { + // Take a uniformly distributed sample over all durations ever supplied during + // the current profiling phase. + // The probability that we (instead) use this new sample is + // 1/sample_probability_count_. This results in a completely uniform selection + // of the sample (at least when we don't clamp sample_probability_count_... + // but that should be inconsequentially likely). We ignore the fact that we + // correlated our selection of a sample to the run and queue times (i.e., we + // used them to generate random_number). + CHECK_GT(sample_probability_count, 0); + if (0 == (random_number % sample_probability_count)) { queue_duration_sample_ = queue_duration; run_duration_sample_ = run_duration; } @@ -160,14 +196,43 @@ return queue_duration_sample_; } -void DeathData::Clear() { - count_ = 0; - run_duration_sum_ = 0; +const DeathDataPhaseSnapshot* DeathData::last_phase_snapshot() const { + return last_phase_snapshot_; +} + +void DeathData::OnProfilingPhaseCompleted(int profiling_phase) { + // Snapshotting and storing current state. + last_phase_snapshot_ = new DeathDataPhaseSnapshot( + profiling_phase, count_, run_duration_sum_, run_duration_max_, + run_duration_sample_, queue_duration_sum_, queue_duration_max_, + queue_duration_sample_, last_phase_snapshot_); + + // Not touching fields for which a delta can be computed by comparing with a + // snapshot from the previous phase. Resetting other fields. Sample values + // will be reset upon next death recording because sample_probability_count_ + // is set to 0. + // We avoid resetting to 0 in favor of deltas whenever possible. The reason + // is that for incrementable fields, resetting to 0 from the snapshot thread + // potentially in parallel with incrementing in the death thread may result in + // significant data corruption that has a potential to grow with time. Not + // resetting incrementable fields and using deltas will cause any + // off-by-little corruptions to be likely fixed at the next snapshot. + // The max values are not incrementable, and cannot be deduced using deltas + // for a given phase. Hence, we have to reset them to 0. But the potential + // damage is limited to getting the previous phase's max to apply for the next + // phase, and the error doesn't have a potential to keep growing with new + // resets. + // sample_probability_count_ is incrementable, but must be reset to 0 at the + // phase end, so that we start a new uniformly randomized sample selection + // after the reset. Corruptions due to race conditions are possible, but the + // damage is limited to selecting a wrong sample, which is not something that + // can cause accumulating or cascading effects. + // If there were no corruptions caused by race conditions, we never send a + // sample for the previous phase in the next phase's snapshot because + // ThreadData::SnapshotExecutedTasks doesn't send deltas with 0 count. + sample_probability_count_ = 0; run_duration_max_ = 0; - run_duration_sample_ = 0; - queue_duration_sum_ = 0; queue_duration_max_ = 0; - queue_duration_sample_ = 0; } //------------------------------------------------------------------------------ @@ -181,20 +246,34 @@ queue_duration_sample(-1) { } -DeathDataSnapshot::DeathDataSnapshot( - const tracked_objects::DeathData& death_data) - : count(death_data.count()), - run_duration_sum(death_data.run_duration_sum()), - run_duration_max(death_data.run_duration_max()), - run_duration_sample(death_data.run_duration_sample()), - queue_duration_sum(death_data.queue_duration_sum()), - queue_duration_max(death_data.queue_duration_max()), - queue_duration_sample(death_data.queue_duration_sample()) { +DeathDataSnapshot::DeathDataSnapshot(int count, + int32 run_duration_sum, + int32 run_duration_max, + int32 run_duration_sample, + int32 queue_duration_sum, + int32 queue_duration_max, + int32 queue_duration_sample) + : count(count), + run_duration_sum(run_duration_sum), + run_duration_max(run_duration_max), + run_duration_sample(run_duration_sample), + queue_duration_sum(queue_duration_sum), + queue_duration_max(queue_duration_max), + queue_duration_sample(queue_duration_sample) { } DeathDataSnapshot::~DeathDataSnapshot() { } +DeathDataSnapshot DeathDataSnapshot::Delta( + const DeathDataSnapshot& older) const { + return DeathDataSnapshot(count - older.count, + run_duration_sum - older.run_duration_sum, + run_duration_max, run_duration_sample, + queue_duration_sum - older.queue_duration_sum, + queue_duration_max, queue_duration_sample); +} + //------------------------------------------------------------------------------ BirthOnThread::BirthOnThread(const Location& location, const ThreadData& current) @@ -206,8 +285,7 @@ BirthOnThreadSnapshot::BirthOnThreadSnapshot() { } -BirthOnThreadSnapshot::BirthOnThreadSnapshot( - const tracked_objects::BirthOnThread& birth) +BirthOnThreadSnapshot::BirthOnThreadSnapshot(const BirthOnThread& birth) : location(birth.location()), thread_name(birth.birth_thread()->thread_name()) { } @@ -238,9 +316,9 @@ // static bool ThreadData::now_function_is_time_ = false; -// A TLS slot which points to the ThreadData instance for the current thread. We -// do a fake initialization here (zeroing out data), and then the real in-place -// construction happens when we call tls_index_.Initialize(). +// A TLS slot which points to the ThreadData instance for the current thread. +// We do a fake initialization here (zeroing out data), and then the real +// in-place construction happens when we call tls_index_.Initialize(). // static base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER; @@ -288,7 +366,8 @@ PushToHeadOfList(); // Which sets real incarnation_count_for_pool_. } -ThreadData::~ThreadData() {} +ThreadData::~ThreadData() { +} void ThreadData::PushToHeadOfList() { // Toss in a hint of randomness (atop the uniniitalized value). @@ -361,7 +440,7 @@ // static void ThreadData::OnThreadTermination(void* thread_data) { DCHECK(thread_data); // TLS should *never* call us with a NULL. - // We must NOT do any allocations during this callback. There is a chance + // We must NOT do any allocations during this callback. There is a chance // that the allocator is no longer active on this thread. reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup(); } @@ -385,9 +464,54 @@ } // static -void ThreadData::Snapshot(ProcessDataSnapshot* process_data_snapshot) { - ThreadData::SnapshotCurrentPhase( - &process_data_snapshot->phased_process_data_snapshots[0]); +void ThreadData::Snapshot(int current_profiling_phase, + ProcessDataSnapshot* process_data_snapshot) { + // Get an unchanging copy of a ThreadData list. + ThreadData* my_list = ThreadData::first(); + + // Gather data serially. + // This hackish approach *can* get some slightly corrupt tallies, as we are + // grabbing values without the protection of a lock, but it has the advantage + // of working even with threads that don't have message loops. If a user + // sees any strangeness, they can always just run their stats gathering a + // second time. + BirthCountMap birth_counts; + for (ThreadData* thread_data = my_list; thread_data; + thread_data = thread_data->next()) { + thread_data->SnapshotExecutedTasks(current_profiling_phase, + &process_data_snapshot->phased_snapshots, + &birth_counts); + } + + // Add births that are still active -- i.e. objects that have tallied a birth, + // but have not yet tallied a matching death, and hence must be either + // running, queued up, or being held in limbo for future posting. + auto* current_phase_tasks = + &process_data_snapshot->phased_snapshots[current_profiling_phase].tasks; + for (const auto& birth_count : birth_counts) { + if (birth_count.second > 0) { + current_phase_tasks->push_back( + TaskSnapshot(BirthOnThreadSnapshot(*birth_count.first), + DeathDataSnapshot(birth_count.second, 0, 0, 0, 0, 0, 0), + "Still_Alive")); + } + } +} + +// static +void ThreadData::OnProfilingPhaseCompleted(int profiling_phase) { + // Get an unchanging copy of a ThreadData list. + ThreadData* my_list = ThreadData::first(); + + // Add snapshots for all instances of death data in all threads serially. + // This hackish approach *can* get some slightly corrupt tallies, as we are + // grabbing values without the protection of a lock, but it has the advantage + // of working even with threads that don't have message loops. Any corruption + // shouldn't cause "cascading damage" to anything else (in later phases). + for (ThreadData* thread_data = my_list; thread_data; + thread_data = thread_data->next()) { + thread_data->OnProfilingPhaseCompletedOnThread(profiling_phase); + } } Births* ThreadData::TallyABirth(const Location& location) { @@ -419,7 +543,7 @@ return child; } -void ThreadData::TallyADeath(const Births& birth, +void ThreadData::TallyADeath(const Births& births, int32 queue_duration, const TaskStopwatch& stopwatch) { int32 run_duration = stopwatch.RunDurationMs(); @@ -428,9 +552,9 @@ const uint32 kSomePrimeNumber = 2147483647; random_number_ += queue_duration + run_duration + kSomePrimeNumber; // An address is going to have some randomness to it as well ;-). - random_number_ ^= static_cast<uint32>(&birth - reinterpret_cast<Births*>(0)); + random_number_ ^= static_cast<uint32>(&births - reinterpret_cast<Births*>(0)); - // We don't have queue durations without OS timer. OS timer is automatically + // We don't have queue durations without OS timer. OS timer is automatically // used for task-post-timing, so the use of an alternate timer implies all // queue times are invalid, unless it was explicitly said that we can trust // the alternate timer. @@ -440,20 +564,20 @@ queue_duration = 0; } - DeathMap::iterator it = death_map_.find(&birth); + DeathMap::iterator it = death_map_.find(&births); DeathData* death_data; if (it != death_map_.end()) { death_data = &it->second; } else { base::AutoLock lock(map_lock_); // Lock as the map may get relocated now. - death_data = &death_map_[&birth]; + death_data = &death_map_[&births]; } // Release lock ASAP. death_data->RecordDeath(queue_duration, run_duration, random_number_); if (!kTrackParentChildLinks) return; if (!parent_stack_.empty()) { // We might get turned off. - DCHECK_EQ(parent_stack_.top(), &birth); + DCHECK_EQ(parent_stack_.top(), &births); parent_stack_.pop(); } } @@ -475,8 +599,8 @@ // Even if we have been DEACTIVATED, we will process any pending births so // that our data structures (which counted the outstanding births) remain // consistent. - const Births* birth = completed_task.birth_tally; - if (!birth) + const Births* births = completed_task.birth_tally; + if (!births) return; ThreadData* current_thread_data = stopwatch.GetThreadData(); if (!current_thread_data) @@ -485,7 +609,7 @@ // Watch out for a race where status_ is changing, and hence one or both // of start_of_run or end_of_run is zero. In that case, we didn't bother to // get a time value since we "weren't tracking" and we were trying to be - // efficient by not calling for a genuine time value. For simplicity, we'll + // efficient by not calling for a genuine time value. For simplicity, we'll // use a default zero duration when we can't calculate a true value. TrackedTime start_of_run = stopwatch.StartTime(); int32 queue_duration = 0; @@ -493,18 +617,18 @@ queue_duration = (start_of_run - completed_task.EffectiveTimePosted()) .InMilliseconds(); } - current_thread_data->TallyADeath(*birth, queue_duration, stopwatch); + current_thread_data->TallyADeath(*births, queue_duration, stopwatch); } // static void ThreadData::TallyRunOnWorkerThreadIfTracking( - const Births* birth, + const Births* births, const TrackedTime& time_posted, const TaskStopwatch& stopwatch) { // Even if we have been DEACTIVATED, we will process any pending births so // that our data structures (which counted the outstanding births) remain // consistent. - if (!birth) + if (!births) return; // TODO(jar): Support the option to coalesce all worker-thread activity under @@ -512,7 +636,7 @@ // reduce memory (making it provably bounded), but run incrementally slower // (since we'll use locks on TallyABirth and TallyADeath). The good news is // that the locks on TallyADeath will be *after* the worker thread has run, - // and hence nothing will be waiting for the completion (... besides some + // and hence nothing will be waiting for the completion (... besides some // other thread that might like to run). Also, the worker threads tasks are // generally longer, and hence the cost of the lock may perchance be amortized // over the long task's lifetime. @@ -525,17 +649,17 @@ if (!start_of_run.is_null()) { queue_duration = (start_of_run - time_posted).InMilliseconds(); } - current_thread_data->TallyADeath(*birth, queue_duration, stopwatch); + current_thread_data->TallyADeath(*births, queue_duration, stopwatch); } // static void ThreadData::TallyRunInAScopedRegionIfTracking( - const Births* birth, + const Births* births, const TaskStopwatch& stopwatch) { // Even if we have been DEACTIVATED, we will process any pending births so // that our data structures (which counted the outstanding births) remain // consistent. - if (!birth) + if (!births) return; ThreadData* current_thread_data = stopwatch.GetThreadData(); @@ -543,87 +667,68 @@ return; int32 queue_duration = 0; - current_thread_data->TallyADeath(*birth, queue_duration, stopwatch); -} - -// static -void ThreadData::SnapshotAllExecutedTasks( - ProcessDataPhaseSnapshot* process_data_phase, - BirthCountMap* birth_counts) { - // Get an unchanging copy of a ThreadData list. - ThreadData* my_list = ThreadData::first(); - - // Gather data serially. - // This hackish approach *can* get some slighly corrupt tallies, as we are - // grabbing values without the protection of a lock, but it has the advantage - // of working even with threads that don't have message loops. If a user - // sees any strangeness, they can always just run their stats gathering a - // second time. - for (ThreadData* thread_data = my_list; - thread_data; - thread_data = thread_data->next()) { - thread_data->SnapshotExecutedTasks(process_data_phase, birth_counts); - } -} - -// static -void ThreadData::SnapshotCurrentPhase( - ProcessDataPhaseSnapshot* process_data_phase) { - // Add births that have run to completion to |collected_data|. - // |birth_counts| tracks the total number of births recorded at each location - // for which we have not seen a death count. - BirthCountMap birth_counts; - ThreadData::SnapshotAllExecutedTasks(process_data_phase, &birth_counts); - - // Add births that are still active -- i.e. objects that have tallied a birth, - // but have not yet tallied a matching death, and hence must be either - // running, queued up, or being held in limbo for future posting. - for (const auto& birth_count : birth_counts) { - if (birth_count.second > 0) { - process_data_phase->tasks.push_back(TaskSnapshot( - *birth_count.first, DeathData(birth_count.second), "Still_Alive")); - } - } + current_thread_data->TallyADeath(*births, queue_duration, stopwatch); } void ThreadData::SnapshotExecutedTasks( - ProcessDataPhaseSnapshot* process_data_phase, + int current_profiling_phase, + PhasedProcessDataSnapshotMap* phased_snapshots, BirthCountMap* birth_counts) { // Get copy of data, so that the data will not change during the iterations // and processing. - ThreadData::BirthMap birth_map; - ThreadData::DeathMap death_map; - ThreadData::ParentChildSet parent_child_set; - SnapshotMaps(&birth_map, &death_map, &parent_child_set); - - for (const auto& death : death_map) { - process_data_phase->tasks.push_back( - TaskSnapshot(*death.first, death.second, thread_name())); - (*birth_counts)[death.first] -= death.first->birth_count(); - } + BirthMap birth_map; + DeathsSnapshot deaths; + ParentChildSet parent_child_set; + SnapshotMaps(current_profiling_phase, &birth_map, &deaths, &parent_child_set); for (const auto& birth : birth_map) { (*birth_counts)[birth.second] += birth.second->birth_count(); } - if (!kTrackParentChildLinks) - return; + for (const auto& death : deaths) { + (*birth_counts)[death.first] -= death.first->birth_count(); - for (const auto& parent_child : parent_child_set) { - process_data_phase->descendants.push_back( - ParentChildPairSnapshot(parent_child)); + // For the current death data, walk through all its snapshots, starting from + // the current one, then from the previous profiling phase etc., and for + // each snapshot calculate the delta between the snapshot and the previous + // phase, if any. Store the deltas in the result. + for (const DeathDataPhaseSnapshot* phase = &death.second; phase; + phase = phase->prev) { + const DeathDataSnapshot& death_data = + phase->prev ? phase->death_data.Delta(phase->prev->death_data) + : phase->death_data; + + if (death_data.count > 0) { + (*phased_snapshots)[phase->profiling_phase].tasks.push_back( + TaskSnapshot(BirthOnThreadSnapshot(*death.first), death_data, + thread_name())); + } + } } } // This may be called from another thread. -void ThreadData::SnapshotMaps(BirthMap* birth_map, - DeathMap* death_map, +void ThreadData::SnapshotMaps(int profiling_phase, + BirthMap* birth_map, + DeathsSnapshot* deaths, ParentChildSet* parent_child_set) { base::AutoLock lock(map_lock_); + for (const auto& birth : birth_map_) (*birth_map)[birth.first] = birth.second; - for (const auto& death : death_map_) - (*death_map)[death.first] = death.second; + + for (const auto& death : death_map_) { + deaths->push_back(std::make_pair( + death.first, + DeathDataPhaseSnapshot(profiling_phase, death.second.count(), + death.second.run_duration_sum(), + death.second.run_duration_max(), + death.second.run_duration_sample(), + death.second.queue_duration_sum(), + death.second.queue_duration_max(), + death.second.queue_duration_sample(), + death.second.last_phase_snapshot()))); + } if (!kTrackParentChildLinks) return; @@ -632,6 +737,14 @@ parent_child_set->insert(parent_child); } +void ThreadData::OnProfilingPhaseCompletedOnThread(int profiling_phase) { + base::AutoLock lock(map_lock_); + + for (auto& death : death_map_) { + death.second.OnProfilingPhaseCompleted(profiling_phase); + } +} + static void OptionallyInitializeAlternateTimer() { NowFunction* alternate_time_source = GetAlternateTimeSource(); if (alternate_time_source) @@ -674,7 +787,7 @@ // never again change in this process. ++incarnation_counter_; - // The lock is not critical for setting status_, but it doesn't hurt. It also + // The lock is not critical for setting status_, but it doesn't hurt. It also // ensures that if we have a racy initialization, that we'll bail as soon as // we get the lock earlier in this method. status_ = kInitialStartupState; @@ -909,11 +1022,37 @@ } //------------------------------------------------------------------------------ +// DeathDataPhaseSnapshot + +DeathDataPhaseSnapshot::DeathDataPhaseSnapshot( + int profiling_phase, + int count, + int32 run_duration_sum, + int32 run_duration_max, + int32 run_duration_sample, + int32 queue_duration_sum, + int32 queue_duration_max, + int32 queue_duration_sample, + const DeathDataPhaseSnapshot* prev) + : profiling_phase(profiling_phase), + death_data(count, + run_duration_sum, + run_duration_max, + run_duration_sample, + queue_duration_sum, + queue_duration_max, + queue_duration_sample), + prev(prev) { +} + +//------------------------------------------------------------------------------ +// TaskSnapshot + TaskSnapshot::TaskSnapshot() { } -TaskSnapshot::TaskSnapshot(const BirthOnThread& birth, - const DeathData& death_data, +TaskSnapshot::TaskSnapshot(const BirthOnThreadSnapshot& birth, + const DeathDataSnapshot& death_data, const std::string& death_thread_name) : birth(birth), death_data(death_data),
diff --git a/base/tracked_objects.h b/base/tracked_objects.h index 9643265..0f55a079 100644 --- a/base/tracked_objects.h +++ b/base/tracked_objects.h
@@ -22,6 +22,7 @@ #include "base/profiler/alternate_timer.h" #include "base/profiler/tracked_time.h" #include "base/synchronization/lock.h" +#include "base/threading/thread_checker.h" #include "base/threading/thread_local_storage.h" namespace base { @@ -85,7 +86,7 @@ // threads there are, and how many Locations of construction there are. // Fortunately, we don't use memory that is the product of those two counts, but // rather we only need one Births instance for each thread that constructs an -// instance at a Location. In many cases, instances are only created on one +// instance at a Location. In many cases, instances are only created on one // thread, so the memory utilization is actually fairly restrained. // // Lastly, when an instance is deleted, the final tallies of statistics are @@ -106,14 +107,14 @@ // Each thread maintains a list of data items specific to that thread in a // ThreadData instance (for that specific thread only). The two critical items // are lists of DeathData and Births instances. These lists are maintained in -// STL maps, which are indexed by Location. As noted earlier, we can compare +// STL maps, which are indexed by Location. As noted earlier, we can compare // locations very efficiently as we consider the underlying data (file, // function, line) to be atoms, and hence pointer comparison is used rather than // (slow) string comparisons. // // To provide a mechanism for iterating over all "known threads," which means // threads that have recorded a birth or a death, we create a singly linked list -// of ThreadData instances. Each such instance maintains a pointer to the next +// of ThreadData instances. Each such instance maintains a pointer to the next // one. A static member of ThreadData provides a pointer to the first item on // this global list, and access via that all_thread_data_list_head_ item // requires the use of the list_lock_. @@ -148,13 +149,13 @@ // TaskSnapshot instances, so that such instances can be sorted and // aggregated (and remain frozen during our processing). // -// Profiling consists of phases. The concrete phase in the sequence of phases is -// identified by its 0-based index. +// Profiling consists of phases. The concrete phase in the sequence of phases +// is identified by its 0-based index. // // The ProcessDataPhaseSnapshot struct is a serialized representation of the -// list of ThreadData objects for a process for a concrete profiling phase. It +// list of ThreadData objects for a process for a concrete profiling phase. It // holds a set of TaskSnapshots and tracks parent/child relationships for the -// executed tasks. The statistics in a snapshot are gathered asynhcronously +// executed tasks. The statistics in a snapshot are gathered asynhcronously // relative to their ongoing updates. // It is possible, though highly unlikely, that stats could be incorrectly // recorded by this process (all data is held in 32 bit ints, but we are not @@ -254,64 +255,29 @@ }; //------------------------------------------------------------------------------ -// Basic info summarizing multiple destructions of a tracked object with a -// single birthplace (fixed Location). Used both on specific threads, and also -// in snapshots when integrating assembled data. - -class BASE_EXPORT DeathData { - public: - // Default initializer. - DeathData(); - - // When deaths have not yet taken place, and we gather data from all the - // threads, we create DeathData stats that tally the number of births without - // a corresponding death. - explicit DeathData(int count); - - // Update stats for a task destruction (death) that had a Run() time of - // |duration|, and has had a queueing delay of |queue_duration|. - void RecordDeath(const int32 queue_duration, - const int32 run_duration, - const uint32 random_number); - - // Metrics accessors, used only for serialization and in tests. - int count() const; - int32 run_duration_sum() const; - int32 run_duration_max() const; - int32 run_duration_sample() const; - int32 queue_duration_sum() const; - int32 queue_duration_max() const; - int32 queue_duration_sample() const; - - // Reset all tallies to zero. This is used as a hack on realtime data. - void Clear(); - - private: - // Members are ordered from most regularly read and updated, to least - // frequently used. This might help a bit with cache lines. - // Number of runs seen (divisor for calculating averages). - int count_; - // Basic tallies, used to compute averages. - int32 run_duration_sum_; - int32 queue_duration_sum_; - // Max values, used by local visualization routines. These are often read, - // but rarely updated. - int32 run_duration_max_; - int32 queue_duration_max_; - // Samples, used by crowd sourcing gatherers. These are almost never read, - // and rarely updated. - int32 run_duration_sample_; - int32 queue_duration_sample_; -}; - -//------------------------------------------------------------------------------ // A "snapshotted" representation of the DeathData class. struct BASE_EXPORT DeathDataSnapshot { DeathDataSnapshot(); - explicit DeathDataSnapshot(const DeathData& death_data); + + // Constructs the snapshot from individual values. + // The alternative would be taking a DeathData parameter, but this would + // create a loop since DeathData indirectly refers DeathDataSnapshot. Passing + // a wrapper structure as a param or using an empty constructor for + // snapshotting DeathData would be less efficient. + DeathDataSnapshot(int count, + int32 run_duration_sum, + int32 run_duration_max, + int32 run_duration_sample, + int32 queue_duration_sum, + int32 queue_duration_max, + int32 queue_duration_sample); ~DeathDataSnapshot(); + // Calculates and returns the delta between this snapshot and an earlier + // snapshot of the same task |older|. + DeathDataSnapshot Delta(const DeathDataSnapshot& older) const; + int count; int32 run_duration_sum; int32 run_duration_max; @@ -322,6 +288,107 @@ }; //------------------------------------------------------------------------------ +// A "snapshotted" representation of the DeathData for a particular profiling +// phase. Used as an element of the list of phase snapshots owned by DeathData. + +struct DeathDataPhaseSnapshot { + DeathDataPhaseSnapshot(int profiling_phase, + int count, + int32 run_duration_sum, + int32 run_duration_max, + int32 run_duration_sample, + int32 queue_duration_sum, + int32 queue_duration_max, + int32 queue_duration_sample, + const DeathDataPhaseSnapshot* prev); + + // Profiling phase at which completion this snapshot was taken. + int profiling_phase; + + // Death data snapshot. + DeathDataSnapshot death_data; + + // Pointer to a snapshot from the previous phase. + const DeathDataPhaseSnapshot* prev; +}; + +//------------------------------------------------------------------------------ +// Information about deaths of a task on a given thread, called "death thread". +// Access to members of this class is never protected by a lock. The fields +// are accessed in such a way that corruptions resulting from race conditions +// are not significant, and don't accumulate as a result of multiple accesses. +// All invocations of DeathData::OnProfilingPhaseCompleted and +// ThreadData::SnapshotMaps (which takes DeathData snapshot) in a given process +// must be called from the same thread. It doesn't matter what thread it is, but +// it's important the same thread is used as a snapshot thread during the whole +// process lifetime. All fields except sample_probability_count_ can be +// snapshotted. + +class BASE_EXPORT DeathData { + public: + DeathData(); + DeathData(const DeathData& other); + ~DeathData(); + + // Update stats for a task destruction (death) that had a Run() time of + // |duration|, and has had a queueing delay of |queue_duration|. + void RecordDeath(const int32 queue_duration, + const int32 run_duration, + const uint32 random_number); + + // Metrics and past snapshots accessors, used only for serialization and in + // tests. + int count() const; + int32 run_duration_sum() const; + int32 run_duration_max() const; + int32 run_duration_sample() const; + int32 queue_duration_sum() const; + int32 queue_duration_max() const; + int32 queue_duration_sample() const; + const DeathDataPhaseSnapshot* last_phase_snapshot() const; + + // Called when the current profiling phase, identified by |profiling_phase|, + // ends. + // Must be called only on the snapshot thread. + void OnProfilingPhaseCompleted(int profiling_phase); + + private: + // Members are ordered from most regularly read and updated, to least + // frequently used. This might help a bit with cache lines. + // Number of runs seen (divisor for calculating averages). + // Can be incremented only on the death thread. + int count_; + + // Count used in determining probability of selecting exec/queue times from a + // recorded death as samples. + // Gets incremented only on the death thread, but can be set to 0 by + // OnProfilingPhaseCompleted() on the snapshot thread. + int sample_probability_count_; + + // Basic tallies, used to compute averages. Can be incremented only on the + // death thread. + int32 run_duration_sum_; + int32 queue_duration_sum_; + // Max values, used by local visualization routines. These are often read, + // but rarely updated. The max values get assigned only on the death thread, + // but these fields can be set to 0 by OnProfilingPhaseCompleted() on the + // snapshot thread. + int32 run_duration_max_; + int32 queue_duration_max_; + // Samples, used by crowd sourcing gatherers. These are almost never read, + // and rarely updated. They can be modified only on the death thread. + int32 run_duration_sample_; + int32 queue_duration_sample_; + + // Snapshot of this death data made at the last profiling phase completion, if + // any. DeathData owns the whole list starting with this pointer. + // Can be accessed only on the snapshot thread. + const DeathDataPhaseSnapshot* last_phase_snapshot_; + + DISALLOW_ASSIGN(DeathData); +}; + +//------------------------------------------------------------------------------ // A temporary collection of data that can be sorted and summarized. It is // gathered (carefully) from many threads. Instances are held in arrays and // processed, filtered, and rendered. @@ -330,12 +397,14 @@ struct BASE_EXPORT TaskSnapshot { TaskSnapshot(); - TaskSnapshot(const BirthOnThread& birth, - const DeathData& death_data, + TaskSnapshot(const BirthOnThreadSnapshot& birth, + const DeathDataSnapshot& death_data, const std::string& death_thread_name); ~TaskSnapshot(); BirthOnThreadSnapshot birth; + // Delta between death data for a thread for a certain profiling phase and the + // snapshot for the pervious phase, if any. Otherwise, just a snapshot. DeathDataSnapshot death_data; std::string death_thread_name; }; @@ -388,8 +457,21 @@ static ThreadData* Get(); // Fills |process_data_snapshot| with phased snapshots of all profiling - // phases, including the current one. - static void Snapshot(ProcessDataSnapshot* process_data_snapshot); + // phases, including the current one, identified by |current_profiling_phase|. + // |current_profiling_phase| is necessary because a child process can start + // after several phase-changing events, so it needs to receive the current + // phase number from the browser process to fill the correct entry for the + // current phase in the |process_data_snapshot| map. + static void Snapshot(int current_profiling_phase, + ProcessDataSnapshot* process_data_snapshot); + + // Called when the current profiling phase, identified by |profiling_phase|, + // ends. + // |profiling_phase| is necessary because a child process can start after + // several phase-changing events, so it needs to receive the phase number from + // the browser process to fill the correct entry in the + // completed_phases_snapshots_ map. + static void OnProfilingPhaseCompleted(int profiling_phase); // Finds (or creates) a place to count births from the given location in this // thread, and increment that tally. @@ -403,7 +485,7 @@ // delayed tasks, and it indicates when the task should have run (i.e., when // it should have posted out of the timer queue, and into the work queue. // The |end_of_run| was just obtained by a call to Now() (just after the task - // finished). It is provided as an argument to help with testing. + // finished). It is provided as an argument to help with testing. static void TallyRunOnNamedThreadIfTracking( const base::TrackingInfo& completed_task, const TaskStopwatch& stopwatch); @@ -415,19 +497,19 @@ // the task. // The |end_of_run| was just obtained by a call to Now() (just after the task // finished). - static void TallyRunOnWorkerThreadIfTracking(const Births* birth, + static void TallyRunOnWorkerThreadIfTracking(const Births* births, const TrackedTime& time_posted, const TaskStopwatch& stopwatch); // Record the end of execution in region, generally corresponding to a scope // being exited. - static void TallyRunInAScopedRegionIfTracking(const Births* birth, + static void TallyRunInAScopedRegionIfTracking(const Births* births, const TaskStopwatch& stopwatch); const std::string& thread_name() const { return thread_name_; } // Initializes all statics if needed (this initialization call should be made - // while we are single threaded). Returns false if unable to initialize. + // while we are single threaded). Returns false if unable to initialize. static bool Initialize(); // Sets internal status_. @@ -452,7 +534,7 @@ // on. This is currently a compiled option, atop TrackingStatus(). static bool TrackingParentChildStatus(); - // Marks a start of a tracked run. It's super fast when tracking is disabled, + // Marks a start of a tracked run. It's super fast when tracking is disabled, // and has some internal side effects when we are tracking, so that we can // deduce the amount of time accumulated outside of execution of tracked runs. // The task that will be tracked is passed in as |parent| so that parent-child @@ -493,6 +575,9 @@ typedef std::map<const BirthOnThread*, int> BirthCountMap; + typedef std::vector<std::pair<const Births*, DeathDataPhaseSnapshot>> + DeathsSnapshot; + // Worker thread construction creates a name since there is none. explicit ThreadData(int thread_number); @@ -517,37 +602,33 @@ Births* TallyABirth(const Location& location); // Find a place to record a death on this thread. - void TallyADeath(const Births& birth, + void TallyADeath(const Births& births, int32 queue_duration, const TaskStopwatch& stopwatch); - // Snapshot (under a lock) the profiled data for the tasks in each ThreadData - // instance. Also updates the |birth_counts| tally for each task to keep - // track of the number of living instances of the task. - static void SnapshotAllExecutedTasks( - ProcessDataPhaseSnapshot* process_data_phase, - BirthCountMap* birth_counts); - - // Fills |process_data_phase| with all the recursive results in our process. - static void SnapshotCurrentPhase( - ProcessDataPhaseSnapshot* process_data_phase); - // Snapshots (under a lock) the profiled data for the tasks for this thread - // and writes all of the executed tasks' data -- i.e. the data for the tasks - // with with entries in the death_map_ -- into |process_data_phase|. Also - // updates the |birth_counts| tally for each task to keep track of the number - // of living instances of the task -- that is, each task maps to the number of - // births for the task that have not yet been balanced by a death. - void SnapshotExecutedTasks(ProcessDataPhaseSnapshot* process_data_phase, + // and writes all of the executed tasks' data -- i.e. the data for all + // profiling phases (including the current one: |current_profiling_phase|) for + // the tasks with with entries in the death_map_ -- into |phased_snapshots|. + // Also updates the |birth_counts| tally for each task to keep track of the + // number of living instances of the task -- that is, each task maps to the + // number of births for the task that have not yet been balanced by a death. + void SnapshotExecutedTasks(int current_profiling_phase, + PhasedProcessDataSnapshotMap* phased_snapshots, BirthCountMap* birth_counts); // Using our lock, make a copy of the specified maps. This call may be made // on non-local threads, which necessitate the use of the lock to prevent // the map(s) from being reallocated while they are copied. - void SnapshotMaps(BirthMap* birth_map, - DeathMap* death_map, + void SnapshotMaps(int profiling_phase, + BirthMap* birth_map, + DeathsSnapshot* deaths, ParentChildSet* parent_child_set); + // Called for this thread when the current profiling phase, identified by + // |profiling_phase|, ends. + void OnProfilingPhaseCompletedOnThread(int profiling_phase); + // This method is called by the TLS system when a thread terminates. // The argument may be NULL if this thread has never tracked a birth or death. static void OnThreadTermination(void* thread_data); @@ -578,7 +659,7 @@ // We use thread local store to identify which ThreadData to interact with. static base::ThreadLocalStorage::StaticSlot tls_index_; - // List of ThreadData instances for use with worker threads. When a worker + // List of ThreadData instances for use with worker threads. When a worker // thread is done (terminated), we push it onto this list. When a new worker // thread is created, we first try to re-use a ThreadData instance from the // list, and if none are available, construct a new one. @@ -595,7 +676,7 @@ static int worker_thread_data_creation_count_; // The number of times TLS has called us back to cleanup a ThreadData - // instance. This is only accessed while list_lock_ is held. + // instance. This is only accessed while list_lock_ is held. static int cleanup_count_; // Incarnation sequence number, indicating how many times (during unittests) @@ -612,7 +693,7 @@ // We set status_ to SHUTDOWN when we shut down the tracking service. static Status status_; - // Link to next instance (null terminated list). Used to globally track all + // Link to next instance (null terminated list). Used to globally track all // registered instances (corresponds to all registered threads where we keep // data). ThreadData* next_; @@ -644,7 +725,7 @@ // locking before reading it. DeathMap death_map_; - // A set of parents that created children tasks on this thread. Each pair + // A set of parents that created children tasks on this thread. Each pair // corresponds to potentially non-local Births (location and thread), and a // local Births (that took place on this thread). ParentChildSet parent_child_set_; @@ -657,7 +738,7 @@ // writing is only done from this thread. mutable base::Lock map_lock_; - // The stack of parents that are currently being profiled. This includes only + // The stack of parents that are currently being profiled. This includes only // tasks that have started a timer recently via PrepareForStartOfRun(), but // not yet concluded with a NowForEndOfRun(). Usually this stack is one deep, // but if a scoped region is profiled, or <sigh> a task runs a nested-message @@ -688,7 +769,7 @@ //------------------------------------------------------------------------------ // Stopwatch to measure task run time or simply create a time interval that will -// be subtracted from the current most nested task's run time. Stopwatches +// be subtracted from the current most nested task's run time. Stopwatches // coordinate with the stopwatches in which they are nested to avoid // double-counting nested tasks run times. @@ -736,12 +817,12 @@ TaskStopwatch* parent_; #if DCHECK_IS_ON() - // State of the stopwatch. Stopwatch is first constructed in a created state + // State of the stopwatch. Stopwatch is first constructed in a created state // state, then is optionally started/stopped, then destructed. enum { CREATED, RUNNING, STOPPED } state_; // Currently running stopwatch that is directly nested in this one, if such - // stopwatch exists. NULL otherwise. + // stopwatch exists. NULL otherwise. TaskStopwatch* child_; #endif }; @@ -783,7 +864,7 @@ ProcessDataSnapshot(); ~ProcessDataSnapshot(); - PhasedProcessDataSnapshotMap phased_process_data_snapshots; + PhasedProcessDataSnapshotMap phased_snapshots; base::ProcessId process_id; };
diff --git a/base/tracked_objects_unittest.cc b/base/tracked_objects_unittest.cc index 5455fef..81f464c 100644 --- a/base/tracked_objects_unittest.cc +++ b/base/tracked_objects_unittest.cc
@@ -71,9 +71,9 @@ int count, int run_ms, int queue_ms) { - ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size()); - auto it = process_data.phased_process_data_snapshots.find(0); - ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end()); + ASSERT_EQ(1u, process_data.phased_snapshots.size()); + auto it = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it != process_data.phased_snapshots.end()); const ProcessDataPhaseSnapshot& process_data_phase = it->second; ASSERT_EQ(1u, process_data_phase.tasks.size()); @@ -123,6 +123,7 @@ TEST_F(TrackedObjectsTest, TaskStopwatchNoStartStop) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -135,6 +136,7 @@ // Minimal test doesn't even create any tasks. if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -145,11 +147,11 @@ EXPECT_FALSE(data->next()); EXPECT_EQ(data, ThreadData::Get()); ThreadData::BirthMap birth_map; - ThreadData::DeathMap death_map; + ThreadData::DeathsSnapshot deaths; ThreadData::ParentChildSet parent_child_set; - data->SnapshotMaps(&birth_map, &death_map, &parent_child_set); + data->SnapshotMaps(0, &birth_map, &deaths, &parent_child_set); EXPECT_EQ(0u, birth_map.size()); - EXPECT_EQ(0u, death_map.size()); + EXPECT_EQ(0u, deaths.size()); EXPECT_EQ(0u, parent_child_set.size()); // Clean up with no leaking. @@ -165,17 +167,18 @@ EXPECT_FALSE(data->next()); EXPECT_EQ(data, ThreadData::Get()); birth_map.clear(); - death_map.clear(); + deaths.clear(); parent_child_set.clear(); - data->SnapshotMaps(&birth_map, &death_map, &parent_child_set); + data->SnapshotMaps(0, &birth_map, &deaths, &parent_child_set); EXPECT_EQ(0u, birth_map.size()); - EXPECT_EQ(0u, death_map.size()); + EXPECT_EQ(0u, deaths.size()); EXPECT_EQ(0u, parent_child_set.size()); } TEST_F(TrackedObjectsTest, TinyStartupShutdown) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -189,12 +192,12 @@ EXPECT_FALSE(data->next()); EXPECT_EQ(data, ThreadData::Get()); ThreadData::BirthMap birth_map; - ThreadData::DeathMap death_map; + ThreadData::DeathsSnapshot deaths; ThreadData::ParentChildSet parent_child_set; - data->SnapshotMaps(&birth_map, &death_map, &parent_child_set); + data->SnapshotMaps(0, &birth_map, &deaths, &parent_child_set); EXPECT_EQ(1u, birth_map.size()); // 1 birth location. EXPECT_EQ(1, birth_map.begin()->second->birth_count()); // 1 birth. - EXPECT_EQ(0u, death_map.size()); // No deaths. + EXPECT_EQ(0u, deaths.size()); // No deaths. EXPECT_EQ(0u, parent_child_set.size()); // No children. @@ -218,13 +221,13 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); birth_map.clear(); - death_map.clear(); + deaths.clear(); parent_child_set.clear(); - data->SnapshotMaps(&birth_map, &death_map, &parent_child_set); + data->SnapshotMaps(0, &birth_map, &deaths, &parent_child_set); EXPECT_EQ(1u, birth_map.size()); // 1 birth location. EXPECT_EQ(2, birth_map.begin()->second->birth_count()); // 2 births. - EXPECT_EQ(1u, death_map.size()); // 1 location. - EXPECT_EQ(1, death_map.begin()->second.count()); // 1 death. + EXPECT_EQ(1u, deaths.size()); // 1 location. + EXPECT_EQ(1, deaths.begin()->second.death_data.count); // 1 death. if (ThreadData::TrackingParentChildStatus()) { EXPECT_EQ(1u, parent_child_set.size()); // 1 child. EXPECT_EQ(parent_child_set.begin()->first, @@ -234,14 +237,14 @@ } // The births were at the same location as the one known death. - EXPECT_EQ(birth_map.begin()->second, death_map.begin()->first); + EXPECT_EQ(birth_map.begin()->second, deaths.begin()->first); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); - ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size()); - auto it = process_data.phased_process_data_snapshots.find(0); - ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end()); + ASSERT_EQ(1u, process_data.phased_snapshots.size()); + auto it = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it != process_data.phased_snapshots.end()); const ProcessDataPhaseSnapshot& process_data_phase = it->second; ASSERT_EQ(1u, process_data_phase.tasks.size()); EXPECT_EQ(kFile, process_data_phase.tasks[0].birth.location.file_name); @@ -285,19 +288,23 @@ } } -TEST_F(TrackedObjectsTest, DeathDataTest) { +TEST_F(TrackedObjectsTest, DeathDataTestRecordDeath) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } scoped_ptr<DeathData> data(new DeathData()); ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL)); EXPECT_EQ(data->run_duration_sum(), 0); + EXPECT_EQ(data->run_duration_max(), 0); EXPECT_EQ(data->run_duration_sample(), 0); EXPECT_EQ(data->queue_duration_sum(), 0); + EXPECT_EQ(data->queue_duration_max(), 0); EXPECT_EQ(data->queue_duration_sample(), 0); EXPECT_EQ(data->count(), 0); + EXPECT_EQ(nullptr, data->last_phase_snapshot()); int32 run_ms = 42; int32 queue_ms = 8; @@ -305,31 +312,133 @@ const int kUnrandomInt = 0; // Fake random int that ensure we sample data. data->RecordDeath(queue_ms, run_ms, kUnrandomInt); EXPECT_EQ(data->run_duration_sum(), run_ms); + EXPECT_EQ(data->run_duration_max(), run_ms); EXPECT_EQ(data->run_duration_sample(), run_ms); EXPECT_EQ(data->queue_duration_sum(), queue_ms); + EXPECT_EQ(data->queue_duration_max(), queue_ms); EXPECT_EQ(data->queue_duration_sample(), queue_ms); EXPECT_EQ(data->count(), 1); + EXPECT_EQ(nullptr, data->last_phase_snapshot()); data->RecordDeath(queue_ms, run_ms, kUnrandomInt); EXPECT_EQ(data->run_duration_sum(), run_ms + run_ms); + EXPECT_EQ(data->run_duration_max(), run_ms); EXPECT_EQ(data->run_duration_sample(), run_ms); EXPECT_EQ(data->queue_duration_sum(), queue_ms + queue_ms); + EXPECT_EQ(data->queue_duration_max(), queue_ms); EXPECT_EQ(data->queue_duration_sample(), queue_ms); EXPECT_EQ(data->count(), 2); + EXPECT_EQ(nullptr, data->last_phase_snapshot()); +} - DeathDataSnapshot snapshot(*data); - EXPECT_EQ(2, snapshot.count); - EXPECT_EQ(2 * run_ms, snapshot.run_duration_sum); - EXPECT_EQ(run_ms, snapshot.run_duration_max); - EXPECT_EQ(run_ms, snapshot.run_duration_sample); - EXPECT_EQ(2 * queue_ms, snapshot.queue_duration_sum); - EXPECT_EQ(queue_ms, snapshot.queue_duration_max); - EXPECT_EQ(queue_ms, snapshot.queue_duration_sample); +TEST_F(TrackedObjectsTest, DeathDataTest2Phases) { + if (!ThreadData::InitializeAndSetTrackingStatus( + ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. + return; + } + + scoped_ptr<DeathData> data(new DeathData()); + ASSERT_NE(data, reinterpret_cast<DeathData*>(NULL)); + + int32 run_ms = 42; + int32 queue_ms = 8; + + const int kUnrandomInt = 0; // Fake random int that ensure we sample data. + data->RecordDeath(queue_ms, run_ms, kUnrandomInt); + data->RecordDeath(queue_ms, run_ms, kUnrandomInt); + + data->OnProfilingPhaseCompleted(123); + EXPECT_EQ(data->run_duration_sum(), run_ms + run_ms); + EXPECT_EQ(data->run_duration_max(), 0); + EXPECT_EQ(data->run_duration_sample(), run_ms); + EXPECT_EQ(data->queue_duration_sum(), queue_ms + queue_ms); + EXPECT_EQ(data->queue_duration_max(), 0); + EXPECT_EQ(data->queue_duration_sample(), queue_ms); + EXPECT_EQ(data->count(), 2); + ASSERT_NE(nullptr, data->last_phase_snapshot()); + EXPECT_EQ(123, data->last_phase_snapshot()->profiling_phase); + EXPECT_EQ(2, data->last_phase_snapshot()->death_data.count); + EXPECT_EQ(2 * run_ms, + data->last_phase_snapshot()->death_data.run_duration_sum); + EXPECT_EQ(run_ms, data->last_phase_snapshot()->death_data.run_duration_max); + EXPECT_EQ(run_ms, + data->last_phase_snapshot()->death_data.run_duration_sample); + EXPECT_EQ(2 * queue_ms, + data->last_phase_snapshot()->death_data.queue_duration_sum); + EXPECT_EQ(queue_ms, + data->last_phase_snapshot()->death_data.queue_duration_max); + EXPECT_EQ(queue_ms, + data->last_phase_snapshot()->death_data.queue_duration_sample); + EXPECT_EQ(nullptr, data->last_phase_snapshot()->prev); + + int32 run_ms1 = 21; + int32 queue_ms1 = 4; + + data->RecordDeath(queue_ms1, run_ms1, kUnrandomInt); + EXPECT_EQ(data->run_duration_sum(), run_ms + run_ms + run_ms1); + EXPECT_EQ(data->run_duration_max(), run_ms1); + EXPECT_EQ(data->run_duration_sample(), run_ms1); + EXPECT_EQ(data->queue_duration_sum(), queue_ms + queue_ms + queue_ms1); + EXPECT_EQ(data->queue_duration_max(), queue_ms1); + EXPECT_EQ(data->queue_duration_sample(), queue_ms1); + EXPECT_EQ(data->count(), 3); + ASSERT_NE(nullptr, data->last_phase_snapshot()); + EXPECT_EQ(123, data->last_phase_snapshot()->profiling_phase); + EXPECT_EQ(2, data->last_phase_snapshot()->death_data.count); + EXPECT_EQ(2 * run_ms, + data->last_phase_snapshot()->death_data.run_duration_sum); + EXPECT_EQ(run_ms, data->last_phase_snapshot()->death_data.run_duration_max); + EXPECT_EQ(run_ms, + data->last_phase_snapshot()->death_data.run_duration_sample); + EXPECT_EQ(2 * queue_ms, + data->last_phase_snapshot()->death_data.queue_duration_sum); + EXPECT_EQ(queue_ms, + data->last_phase_snapshot()->death_data.queue_duration_max); + EXPECT_EQ(queue_ms, + data->last_phase_snapshot()->death_data.queue_duration_sample); + EXPECT_EQ(nullptr, data->last_phase_snapshot()->prev); +} + +TEST_F(TrackedObjectsTest, Delta) { + if (!ThreadData::InitializeAndSetTrackingStatus( + ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. + return; + } + + DeathDataSnapshot snapshot; + snapshot.count = 10; + snapshot.run_duration_sum = 100; + snapshot.run_duration_max = 50; + snapshot.run_duration_sample = 25; + snapshot.queue_duration_sum = 200; + snapshot.queue_duration_max = 101; + snapshot.queue_duration_sample = 26; + + DeathDataSnapshot older_snapshot; + older_snapshot.count = 2; + older_snapshot.run_duration_sum = 95; + older_snapshot.run_duration_max = 48; + older_snapshot.run_duration_sample = 22; + older_snapshot.queue_duration_sum = 190; + older_snapshot.queue_duration_max = 99; + older_snapshot.queue_duration_sample = 21; + + const DeathDataSnapshot& delta = snapshot.Delta(older_snapshot); + EXPECT_EQ(8, delta.count); + EXPECT_EQ(5, delta.run_duration_sum); + EXPECT_EQ(50, delta.run_duration_max); + EXPECT_EQ(25, delta.run_duration_sample); + EXPECT_EQ(10, delta.queue_duration_sum); + EXPECT_EQ(101, delta.queue_duration_max); + EXPECT_EQ(26, delta.queue_duration_sample); } TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToSnapshotWorkerThread) { // Start in the deactivated state. if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -338,21 +447,23 @@ TallyABirth(location, std::string()); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); - ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size()); - auto it = process_data.phased_process_data_snapshots.find(0); - ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end()); + ASSERT_EQ(1u, process_data.phased_snapshots.size()); + + auto it = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it != process_data.phased_snapshots.end()); const ProcessDataPhaseSnapshot& process_data_phase = it->second; - EXPECT_EQ(0u, process_data_phase.tasks.size()); - EXPECT_EQ(0u, process_data_phase.descendants.size()); + ASSERT_EQ(0u, process_data_phase.tasks.size()); + EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); } TEST_F(TrackedObjectsTest, DeactivatedBirthOnlyToSnapshotMainThread) { // Start in the deactivated state. if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -361,21 +472,23 @@ TallyABirth(location, kMainThreadName); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); - ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size()); - auto it = process_data.phased_process_data_snapshots.find(0); - ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end()); + ASSERT_EQ(1u, process_data.phased_snapshots.size()); + + auto it = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it != process_data.phased_snapshots.end()); const ProcessDataPhaseSnapshot& process_data_phase = it->second; - EXPECT_EQ(0u, process_data_phase.tasks.size()); - EXPECT_EQ(0u, process_data_phase.descendants.size()); + ASSERT_EQ(0u, process_data_phase.tasks.size()); + EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); } TEST_F(TrackedObjectsTest, BirthOnlyToSnapshotWorkerThread) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -384,7 +497,7 @@ TallyABirth(location, std::string()); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); ExpectSimpleProcessData(process_data, kFunction, kWorkerThreadName, kStillAlive, 1, 0, 0); } @@ -392,6 +505,7 @@ TEST_F(TrackedObjectsTest, BirthOnlyToSnapshotMainThread) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -400,7 +514,7 @@ TallyABirth(location, kMainThreadName); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kStillAlive, 1, 0, 0); } @@ -408,6 +522,7 @@ TEST_F(TrackedObjectsTest, LifeCycleToSnapshotMainThread) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -432,11 +547,399 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 1, 2, 4); } +TEST_F(TrackedObjectsTest, TwoPhases) { + if (!ThreadData::InitializeAndSetTrackingStatus( + ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. + return; + } + + const char kFunction[] = "TwoPhases"; + Location location(kFunction, kFile, kLineNumber, NULL); + TallyABirth(location, kMainThreadName); + + const TrackedTime kTimePosted = TrackedTime::FromMilliseconds(1); + const base::TimeTicks kDelayedStartTime = base::TimeTicks(); + // TrackingInfo will call TallyABirth() during construction. + base::TrackingInfo pending_task(location, kDelayedStartTime); + pending_task.time_posted = kTimePosted; // Overwrite implied Now(). + + const unsigned int kStartOfRun = 5; + const unsigned int kEndOfRun = 7; + SetTestTime(kStartOfRun); + TaskStopwatch stopwatch; + stopwatch.Start(); + SetTestTime(kEndOfRun); + stopwatch.Stop(); + + ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); + + ThreadData::OnProfilingPhaseCompleted(0); + + TallyABirth(location, kMainThreadName); + + const TrackedTime kTimePosted1 = TrackedTime::FromMilliseconds(9); + const base::TimeTicks kDelayedStartTime1 = base::TimeTicks(); + // TrackingInfo will call TallyABirth() during construction. + base::TrackingInfo pending_task1(location, kDelayedStartTime1); + pending_task1.time_posted = kTimePosted1; // Overwrite implied Now(). + + const unsigned int kStartOfRun1 = 11; + const unsigned int kEndOfRun1 = 21; + SetTestTime(kStartOfRun1); + TaskStopwatch stopwatch1; + stopwatch1.Start(); + SetTestTime(kEndOfRun1); + stopwatch1.Stop(); + + ThreadData::TallyRunOnNamedThreadIfTracking(pending_task1, stopwatch1); + + ProcessDataSnapshot process_data; + ThreadData::Snapshot(1, &process_data); + + ASSERT_EQ(2u, process_data.phased_snapshots.size()); + + auto it0 = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it0 != process_data.phased_snapshots.end()); + const ProcessDataPhaseSnapshot& process_data_phase0 = it0->second; + + ASSERT_EQ(1u, process_data_phase0.tasks.size()); + + EXPECT_EQ(kFile, process_data_phase0.tasks[0].birth.location.file_name); + EXPECT_EQ(kFunction, + process_data_phase0.tasks[0].birth.location.function_name); + EXPECT_EQ(kLineNumber, + process_data_phase0.tasks[0].birth.location.line_number); + + EXPECT_EQ(kMainThreadName, process_data_phase0.tasks[0].birth.thread_name); + + EXPECT_EQ(1, process_data_phase0.tasks[0].death_data.count); + EXPECT_EQ(2, process_data_phase0.tasks[0].death_data.run_duration_sum); + EXPECT_EQ(2, process_data_phase0.tasks[0].death_data.run_duration_max); + EXPECT_EQ(2, process_data_phase0.tasks[0].death_data.run_duration_sample); + EXPECT_EQ(4, process_data_phase0.tasks[0].death_data.queue_duration_sum); + EXPECT_EQ(4, process_data_phase0.tasks[0].death_data.queue_duration_max); + EXPECT_EQ(4, process_data_phase0.tasks[0].death_data.queue_duration_sample); + + EXPECT_EQ(kMainThreadName, process_data_phase0.tasks[0].death_thread_name); + + EXPECT_EQ(0u, process_data_phase0.descendants.size()); + + auto it1 = process_data.phased_snapshots.find(1); + ASSERT_TRUE(it1 != process_data.phased_snapshots.end()); + const ProcessDataPhaseSnapshot& process_data_phase1 = it1->second; + + ASSERT_EQ(1u, process_data_phase1.tasks.size()); + + EXPECT_EQ(kFile, process_data_phase1.tasks[0].birth.location.file_name); + EXPECT_EQ(kFunction, + process_data_phase1.tasks[0].birth.location.function_name); + EXPECT_EQ(kLineNumber, + process_data_phase1.tasks[0].birth.location.line_number); + + EXPECT_EQ(kMainThreadName, process_data_phase1.tasks[0].birth.thread_name); + + EXPECT_EQ(1, process_data_phase1.tasks[0].death_data.count); + EXPECT_EQ(10, process_data_phase1.tasks[0].death_data.run_duration_sum); + EXPECT_EQ(10, process_data_phase1.tasks[0].death_data.run_duration_max); + EXPECT_EQ(10, process_data_phase1.tasks[0].death_data.run_duration_sample); + EXPECT_EQ(2, process_data_phase1.tasks[0].death_data.queue_duration_sum); + EXPECT_EQ(2, process_data_phase1.tasks[0].death_data.queue_duration_max); + EXPECT_EQ(2, process_data_phase1.tasks[0].death_data.queue_duration_sample); + + EXPECT_EQ(kMainThreadName, process_data_phase1.tasks[0].death_thread_name); + + EXPECT_EQ(0u, process_data_phase1.descendants.size()); + + EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); +} + +TEST_F(TrackedObjectsTest, ThreePhases) { + if (!ThreadData::InitializeAndSetTrackingStatus( + ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. + return; + } + + const char kFunction[] = "ThreePhases"; + Location location(kFunction, kFile, kLineNumber, NULL); + + // Phase 0 + { + TallyABirth(location, kMainThreadName); + + // TrackingInfo will call TallyABirth() during construction. + SetTestTime(10); + base::TrackingInfo pending_task(location, base::TimeTicks()); + + SetTestTime(17); + TaskStopwatch stopwatch; + stopwatch.Start(); + SetTestTime(23); + stopwatch.Stop(); + + ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); + } + + ThreadData::OnProfilingPhaseCompleted(0); + + // Phase 1 + { + TallyABirth(location, kMainThreadName); + + SetTestTime(30); + base::TrackingInfo pending_task(location, base::TimeTicks()); + + SetTestTime(35); + TaskStopwatch stopwatch; + stopwatch.Start(); + SetTestTime(39); + stopwatch.Stop(); + + ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); + } + + ThreadData::OnProfilingPhaseCompleted(1); + + // Phase 2 + { + TallyABirth(location, kMainThreadName); + + // TrackingInfo will call TallyABirth() during construction. + SetTestTime(40); + base::TrackingInfo pending_task(location, base::TimeTicks()); + + SetTestTime(43); + TaskStopwatch stopwatch; + stopwatch.Start(); + SetTestTime(45); + stopwatch.Stop(); + + ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); + } + + // Snapshot and check results. + ProcessDataSnapshot process_data; + ThreadData::Snapshot(2, &process_data); + + ASSERT_EQ(3u, process_data.phased_snapshots.size()); + + auto it0 = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it0 != process_data.phased_snapshots.end()); + const ProcessDataPhaseSnapshot& process_data_phase0 = it0->second; + + ASSERT_EQ(1u, process_data_phase0.tasks.size()); + + EXPECT_EQ(kFile, process_data_phase0.tasks[0].birth.location.file_name); + EXPECT_EQ(kFunction, + process_data_phase0.tasks[0].birth.location.function_name); + EXPECT_EQ(kLineNumber, + process_data_phase0.tasks[0].birth.location.line_number); + + EXPECT_EQ(kMainThreadName, process_data_phase0.tasks[0].birth.thread_name); + + EXPECT_EQ(1, process_data_phase0.tasks[0].death_data.count); + EXPECT_EQ(6, process_data_phase0.tasks[0].death_data.run_duration_sum); + EXPECT_EQ(6, process_data_phase0.tasks[0].death_data.run_duration_max); + EXPECT_EQ(6, process_data_phase0.tasks[0].death_data.run_duration_sample); + EXPECT_EQ(7, process_data_phase0.tasks[0].death_data.queue_duration_sum); + EXPECT_EQ(7, process_data_phase0.tasks[0].death_data.queue_duration_max); + EXPECT_EQ(7, process_data_phase0.tasks[0].death_data.queue_duration_sample); + + EXPECT_EQ(kMainThreadName, process_data_phase0.tasks[0].death_thread_name); + + EXPECT_EQ(0u, process_data_phase0.descendants.size()); + + auto it1 = process_data.phased_snapshots.find(1); + ASSERT_TRUE(it1 != process_data.phased_snapshots.end()); + const ProcessDataPhaseSnapshot& process_data_phase1 = it1->second; + + ASSERT_EQ(1u, process_data_phase1.tasks.size()); + + EXPECT_EQ(kFile, process_data_phase1.tasks[0].birth.location.file_name); + EXPECT_EQ(kFunction, + process_data_phase1.tasks[0].birth.location.function_name); + EXPECT_EQ(kLineNumber, + process_data_phase1.tasks[0].birth.location.line_number); + + EXPECT_EQ(kMainThreadName, process_data_phase1.tasks[0].birth.thread_name); + + EXPECT_EQ(1, process_data_phase1.tasks[0].death_data.count); + EXPECT_EQ(4, process_data_phase1.tasks[0].death_data.run_duration_sum); + EXPECT_EQ(4, process_data_phase1.tasks[0].death_data.run_duration_max); + EXPECT_EQ(4, process_data_phase1.tasks[0].death_data.run_duration_sample); + EXPECT_EQ(5, process_data_phase1.tasks[0].death_data.queue_duration_sum); + EXPECT_EQ(5, process_data_phase1.tasks[0].death_data.queue_duration_max); + EXPECT_EQ(5, process_data_phase1.tasks[0].death_data.queue_duration_sample); + + EXPECT_EQ(kMainThreadName, process_data_phase1.tasks[0].death_thread_name); + + EXPECT_EQ(0u, process_data_phase1.descendants.size()); + + auto it2 = process_data.phased_snapshots.find(2); + ASSERT_TRUE(it2 != process_data.phased_snapshots.end()); + const ProcessDataPhaseSnapshot& process_data_phase2 = it2->second; + + ASSERT_EQ(1u, process_data_phase2.tasks.size()); + + EXPECT_EQ(kFile, process_data_phase2.tasks[0].birth.location.file_name); + EXPECT_EQ(kFunction, + process_data_phase2.tasks[0].birth.location.function_name); + EXPECT_EQ(kLineNumber, + process_data_phase2.tasks[0].birth.location.line_number); + + EXPECT_EQ(kMainThreadName, process_data_phase2.tasks[0].birth.thread_name); + + EXPECT_EQ(1, process_data_phase2.tasks[0].death_data.count); + EXPECT_EQ(2, process_data_phase2.tasks[0].death_data.run_duration_sum); + EXPECT_EQ(2, process_data_phase2.tasks[0].death_data.run_duration_max); + EXPECT_EQ(2, process_data_phase2.tasks[0].death_data.run_duration_sample); + EXPECT_EQ(3, process_data_phase2.tasks[0].death_data.queue_duration_sum); + EXPECT_EQ(3, process_data_phase2.tasks[0].death_data.queue_duration_max); + EXPECT_EQ(3, process_data_phase2.tasks[0].death_data.queue_duration_sample); + + EXPECT_EQ(kMainThreadName, process_data_phase2.tasks[0].death_thread_name); + + EXPECT_EQ(0u, process_data_phase2.descendants.size()); + + EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); +} + +TEST_F(TrackedObjectsTest, TwoPhasesSecondEmpty) { + if (!ThreadData::InitializeAndSetTrackingStatus( + ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. + return; + } + + const char kFunction[] = "TwoPhasesSecondEmpty"; + Location location(kFunction, kFile, kLineNumber, NULL); + ThreadData::InitializeThreadContext(kMainThreadName); + + const TrackedTime kTimePosted = TrackedTime::FromMilliseconds(1); + const base::TimeTicks kDelayedStartTime = base::TimeTicks(); + // TrackingInfo will call TallyABirth() during construction. + base::TrackingInfo pending_task(location, kDelayedStartTime); + pending_task.time_posted = kTimePosted; // Overwrite implied Now(). + + const unsigned int kStartOfRun = 5; + const unsigned int kEndOfRun = 7; + SetTestTime(kStartOfRun); + TaskStopwatch stopwatch; + stopwatch.Start(); + SetTestTime(kEndOfRun); + stopwatch.Stop(); + + ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); + + ThreadData::OnProfilingPhaseCompleted(0); + + ProcessDataSnapshot process_data; + ThreadData::Snapshot(1, &process_data); + + ASSERT_EQ(2u, process_data.phased_snapshots.size()); + + auto it0 = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it0 != process_data.phased_snapshots.end()); + const ProcessDataPhaseSnapshot& process_data_phase0 = it0->second; + + ASSERT_EQ(1u, process_data_phase0.tasks.size()); + + EXPECT_EQ(kFile, process_data_phase0.tasks[0].birth.location.file_name); + EXPECT_EQ(kFunction, + process_data_phase0.tasks[0].birth.location.function_name); + EXPECT_EQ(kLineNumber, + process_data_phase0.tasks[0].birth.location.line_number); + + EXPECT_EQ(kMainThreadName, process_data_phase0.tasks[0].birth.thread_name); + + EXPECT_EQ(1, process_data_phase0.tasks[0].death_data.count); + EXPECT_EQ(2, process_data_phase0.tasks[0].death_data.run_duration_sum); + EXPECT_EQ(2, process_data_phase0.tasks[0].death_data.run_duration_max); + EXPECT_EQ(2, process_data_phase0.tasks[0].death_data.run_duration_sample); + EXPECT_EQ(4, process_data_phase0.tasks[0].death_data.queue_duration_sum); + EXPECT_EQ(4, process_data_phase0.tasks[0].death_data.queue_duration_max); + EXPECT_EQ(4, process_data_phase0.tasks[0].death_data.queue_duration_sample); + + EXPECT_EQ(kMainThreadName, process_data_phase0.tasks[0].death_thread_name); + + auto it1 = process_data.phased_snapshots.find(1); + ASSERT_TRUE(it1 != process_data.phased_snapshots.end()); + const ProcessDataPhaseSnapshot& process_data_phase1 = it1->second; + + ASSERT_EQ(0u, process_data_phase1.tasks.size()); + + EXPECT_EQ(0u, process_data_phase0.descendants.size()); + + EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); +} + +TEST_F(TrackedObjectsTest, TwoPhasesFirstEmpty) { + if (!ThreadData::InitializeAndSetTrackingStatus( + ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. + return; + } + + ThreadData::OnProfilingPhaseCompleted(0); + + const char kFunction[] = "TwoPhasesSecondEmpty"; + Location location(kFunction, kFile, kLineNumber, NULL); + ThreadData::InitializeThreadContext(kMainThreadName); + + const TrackedTime kTimePosted = TrackedTime::FromMilliseconds(1); + const base::TimeTicks kDelayedStartTime = base::TimeTicks(); + // TrackingInfo will call TallyABirth() during construction. + base::TrackingInfo pending_task(location, kDelayedStartTime); + pending_task.time_posted = kTimePosted; // Overwrite implied Now(). + + const unsigned int kStartOfRun = 5; + const unsigned int kEndOfRun = 7; + SetTestTime(kStartOfRun); + TaskStopwatch stopwatch; + stopwatch.Start(); + SetTestTime(kEndOfRun); + stopwatch.Stop(); + + ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); + + ProcessDataSnapshot process_data; + ThreadData::Snapshot(1, &process_data); + + ASSERT_EQ(1u, process_data.phased_snapshots.size()); + + auto it1 = process_data.phased_snapshots.find(1); + ASSERT_TRUE(it1 != process_data.phased_snapshots.end()); + const ProcessDataPhaseSnapshot& process_data_phase1 = it1->second; + + ASSERT_EQ(1u, process_data_phase1.tasks.size()); + + EXPECT_EQ(kFile, process_data_phase1.tasks[0].birth.location.file_name); + EXPECT_EQ(kFunction, + process_data_phase1.tasks[0].birth.location.function_name); + EXPECT_EQ(kLineNumber, + process_data_phase1.tasks[0].birth.location.line_number); + + EXPECT_EQ(kMainThreadName, process_data_phase1.tasks[0].birth.thread_name); + + EXPECT_EQ(1, process_data_phase1.tasks[0].death_data.count); + EXPECT_EQ(2, process_data_phase1.tasks[0].death_data.run_duration_sum); + EXPECT_EQ(2, process_data_phase1.tasks[0].death_data.run_duration_max); + EXPECT_EQ(2, process_data_phase1.tasks[0].death_data.run_duration_sample); + EXPECT_EQ(4, process_data_phase1.tasks[0].death_data.queue_duration_sum); + EXPECT_EQ(4, process_data_phase1.tasks[0].death_data.queue_duration_max); + EXPECT_EQ(4, process_data_phase1.tasks[0].death_data.queue_duration_sample); + + EXPECT_EQ(kMainThreadName, process_data_phase1.tasks[0].death_thread_name); + + EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); +} + // We will deactivate tracking after the birth, and before the death, and // demonstrate that the lifecycle is completely tallied. This ensures that // our tallied births are matched by tallied deaths (except for when the @@ -444,6 +947,7 @@ TEST_F(TrackedObjectsTest, LifeCycleMidDeactivatedToSnapshotMainThread) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -472,7 +976,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 1, 2, 4); } @@ -482,6 +986,7 @@ TEST_F(TrackedObjectsTest, LifeCyclePreDeactivatedToSnapshotMainThread) { // Start in the deactivated state. if (!ThreadData::InitializeAndSetTrackingStatus(ThreadData::DEACTIVATED)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -506,21 +1011,23 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); - ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size()); - auto it = process_data.phased_process_data_snapshots.find(0); - ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end()); + ASSERT_EQ(1u, process_data.phased_snapshots.size()); + + auto it = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it != process_data.phased_snapshots.end()); const ProcessDataPhaseSnapshot& process_data_phase = it->second; - EXPECT_EQ(0u, process_data_phase.tasks.size()); - EXPECT_EQ(0u, process_data_phase.descendants.size()); + ASSERT_EQ(0u, process_data_phase.tasks.size()); + EXPECT_EQ(base::GetCurrentProcId(), process_data.process_id); } TEST_F(TrackedObjectsTest, TwoLives) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -556,7 +1063,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task2, stopwatch2); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 2, 2, 4); } @@ -564,6 +1071,7 @@ TEST_F(TrackedObjectsTest, DifferentLives) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -596,11 +1104,11 @@ pending_task2.time_posted = kTimePosted; // Overwrite implied Now(). ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); - ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size()); - auto it = process_data.phased_process_data_snapshots.find(0); - ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end()); + ASSERT_EQ(1u, process_data.phased_snapshots.size()); + auto it = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it != process_data.phased_snapshots.end()); const ProcessDataPhaseSnapshot& process_data_phase = it->second; ASSERT_EQ(2u, process_data_phase.tasks.size()); @@ -640,6 +1148,7 @@ TEST_F(TrackedObjectsTest, TaskWithNestedExclusion) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -669,7 +1178,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 1, 6, 4); } @@ -677,6 +1186,7 @@ TEST_F(TrackedObjectsTest, TaskWith2NestedExclusions) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -712,7 +1222,7 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); ExpectSimpleProcessData(process_data, kFunction, kMainThreadName, kMainThreadName, 1, 13, 4); } @@ -720,6 +1230,7 @@ TEST_F(TrackedObjectsTest, TaskWithNestedExclusionWithNestedTask) { if (!ThreadData::InitializeAndSetTrackingStatus( ThreadData::PROFILING_CHILDREN_ACTIVE)) { + // Don't run the test if task tracking is not compiled in. return; } @@ -765,11 +1276,11 @@ ThreadData::TallyRunOnNamedThreadIfTracking(pending_task, task_stopwatch); ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(0, &process_data); - ASSERT_EQ(1u, process_data.phased_process_data_snapshots.size()); - auto it = process_data.phased_process_data_snapshots.find(0); - ASSERT_TRUE(it != process_data.phased_process_data_snapshots.end()); + ASSERT_EQ(1u, process_data.phased_snapshots.size()); + auto it = process_data.phased_snapshots.find(0); + ASSERT_TRUE(it != process_data.phased_snapshots.end()); const ProcessDataPhaseSnapshot& process_data_phase = it->second; // The order in which the two task follow is platform-dependent.
diff --git a/base/values.cc b/base/values.cc index 52876cf..0e1e2b1 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -7,9 +7,9 @@ #include <string.h> #include <algorithm> +#include <cmath> #include <ostream> -#include "base/float_util.h" #include "base/json/json_writer.h" #include "base/logging.h" #include "base/move.h" @@ -175,7 +175,7 @@ FundamentalValue::FundamentalValue(double in_value) : Value(TYPE_DOUBLE), double_value_(in_value) { - if (!IsFinite(double_value_)) { + if (!std::isfinite(double_value_)) { NOTREACHED() << "Non-finite (i.e. NaN or positive/negative infinity) " << "values cannot be represented in JSON"; double_value_ = 0.0;
diff --git a/base/win/scoped_process_information.cc b/base/win/scoped_process_information.cc index bb246377..634a538 100644 --- a/base/win/scoped_process_information.cc +++ b/base/win/scoped_process_information.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" namespace base { namespace win { @@ -20,11 +21,49 @@ return true; HANDLE temp = NULL; - if (!::DuplicateHandle(::GetCurrentProcess(), source, - ::GetCurrentProcess(), &temp, 0, FALSE, - DUPLICATE_SAME_ACCESS)) { - DPLOG(ERROR) << "Failed to duplicate a handle."; - return false; + + // TODO(shrikant): Remove following code as soon as we gather some + // information regarding AppContainer related DuplicateHandle failures that + // only seem to happen on certain machine and only random launches (normally + // renderer launches seem to succeed even on those machines.) + if (base::win::GetVersion() == base::win::VERSION_WIN8 || + base::win::GetVersion() == base::win::VERSION_WIN8_1) { + typedef LONG (WINAPI *NtDuplicateObject)( + IN HANDLE SourceProcess, + IN HANDLE SourceHandle, + IN HANDLE TargetProcess, + OUT PHANDLE TargetHandle, + IN ACCESS_MASK DesiredAccess, + IN ULONG Attributes, + IN ULONG Options); + + typedef ULONG (WINAPI *RtlNtStatusToDosError)(IN LONG Status); + + NtDuplicateObject nt_duplicate_object = + reinterpret_cast<NtDuplicateObject>(::GetProcAddress( + GetModuleHandle(L"ntdll.dll"), "NtDuplicateObject")); + if (nt_duplicate_object != NULL) { + LONG status = nt_duplicate_object(::GetCurrentProcess(), source, + ::GetCurrentProcess(), &temp, + 0, FALSE, DUPLICATE_SAME_ACCESS); + if (status < 0) { + DPLOG(ERROR) << "Failed to duplicate a handle."; + RtlNtStatusToDosError ntstatus_to_doserror = + reinterpret_cast<RtlNtStatusToDosError>(::GetProcAddress( + GetModuleHandle(L"ntdll.dll"), "RtlNtStatusToDosError")); + if (ntstatus_to_doserror != NULL) { + ::SetLastError(ntstatus_to_doserror(status)); + } + return false; + } + } + } else { + if (!::DuplicateHandle(::GetCurrentProcess(), source, + ::GetCurrentProcess(), &temp, 0, FALSE, + DUPLICATE_SAME_ACCESS)) { + DPLOG(ERROR) << "Failed to duplicate a handle."; + return false; + } } target->Set(temp); return true;
diff --git a/base/win/shortcut.cc b/base/win/shortcut.cc index eb26ceaa..207fdbe0 100644 --- a/base/win/shortcut.cc +++ b/base/win/shortcut.cc
@@ -42,6 +42,13 @@ } // namespace +ShortcutProperties::ShortcutProperties() + : icon_index(-1), dual_mode(false), options(0U) { +} + +ShortcutProperties::~ShortcutProperties() { +} + bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path, const ShortcutProperties& properties, ShortcutOperation operation) {
diff --git a/base/win/shortcut.h b/base/win/shortcut.h index 2feb4c3..6f7d10c8 100644 --- a/base/win/shortcut.h +++ b/base/win/shortcut.h
@@ -7,6 +7,7 @@ #include <windows.h> +#include "base/base_export.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/strings/string16.h" @@ -29,7 +30,7 @@ // creation/update, others will be ignored. // Callers are encouraged to use the setters provided which take care of // setting |options| as desired. -struct ShortcutProperties { +struct BASE_EXPORT ShortcutProperties { enum IndividualProperties { PROPERTIES_TARGET = 1U << 0, PROPERTIES_WORKING_DIR = 1U << 1, @@ -48,7 +49,8 @@ PROPERTIES_ALL = PROPERTIES_BASIC | PROPERTIES_WIN7 }; - ShortcutProperties() : icon_index(-1), dual_mode(false), options(0U) {} + ShortcutProperties(); + ~ShortcutProperties(); void set_target(const FilePath& target_in) { target = target_in;
diff --git a/base/win/startup_information.h b/base/win/startup_information.h index e7e21cb1..73d9f3e7 100644 --- a/base/win/startup_information.h +++ b/base/win/startup_information.h
@@ -24,6 +24,8 @@ bool InitializeProcThreadAttributeList(DWORD attribute_count); // Sets one entry in the initialized attribute list. + // |value| needs to live at least as long as the StartupInformation object + // this is called on. bool UpdateProcThreadAttribute(DWORD_PTR attribute, void* value, size_t size);
diff --git a/build/android/adb_install_apk.py b/build/android/adb_install_apk.py index b6da19e..7bc634c7 100755 --- a/build/android/adb_install_apk.py +++ b/build/android/adb_install_apk.py
@@ -11,8 +11,6 @@ import sys from pylib import constants -from pylib.device import adb_wrapper -from pylib.device import device_filter from pylib.device import device_utils @@ -72,13 +70,13 @@ constants.SetBuildType(options.build_type) ValidateInstallAPKOption(parser, options, args) - devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) + devices = device_utils.DeviceUtils.HealthyDevices() if options.device: - if options.device not in [d.GetDeviceSerial() for d in devices]: + device_serials = [d.adb.GetDeviceSerial() for d in devices] + if options.device not in device_serials: raise Exception('Error: %s not in attached devices %s' % (options.device, - ','.join(devices))) + ','.join(device_serials))) devices = [options.device] if not devices:
diff --git a/build/android/adb_reverse_forwarder.py b/build/android/adb_reverse_forwarder.py index b2da6a758..6cae0cf 100755 --- a/build/android/adb_reverse_forwarder.py +++ b/build/android/adb_reverse_forwarder.py
@@ -19,7 +19,6 @@ from pylib import constants from pylib import forwarder from pylib.device import adb_wrapper -from pylib.device import device_filter from pylib.device import device_utils from pylib.utils import run_tests_helper @@ -54,11 +53,10 @@ parser.error('Bad port number') sys.exit(1) - devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) + devices = device_utils.DeviceUtils.HealthyDevices() if options.device: - if options.device not in [d.GetDeviceSerial() for d in devices]: + if options.device not in [str(d) for d in devices]: raise Exception('Error: %s not in attached devices %s' % (options.device, ','.join(devices))) devices = [options.device] @@ -67,7 +65,7 @@ raise Exception('Error: no connected devices') logging.info('No device specified. Defaulting to %s', devices[0]) - device = device_utils.DeviceUtils(devices[0]) + device = devices[0] constants.SetBuildType(options.build_type) try: forwarder.Forwarder.Map(port_pairs, device)
diff --git a/build/android/buildbot/bb_device_steps.py b/build/android/buildbot/bb_device_steps.py index 0ea6dd2..e5df563 100755 --- a/build/android/buildbot/bb_device_steps.py +++ b/build/android/buildbot/bb_device_steps.py
@@ -94,9 +94,10 @@ 'ChromeDriverWebViewShell.apk', 'org.chromium.chromedriver_webview_shell')])) -VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'gpu', - 'telemetry_unittests', 'telemetry_perf_unittests', 'ui', - 'unit', 'webkit', 'webkit_layout', 'python_unittests']) +VALID_TESTS = set(['chromedriver', 'chrome_proxy', 'components_browsertests', + 'gpu', 'python_unittests', 'telemetry_unittests', + 'telemetry_perf_unittests', 'ui', 'unit', 'webkit', + 'webkit_layout']) RunCmd = bb_utils.RunCmd @@ -172,7 +173,7 @@ bb_annotations.PrintNamedStep(suite) cmd = [suite] + args cmd += suites_options.get(suite, []) - if suite == 'content_browsertests': + if suite == 'content_browsertests' or suite == 'components_browsertests': cmd.append('--num_retries=1') _RunTest(options, cmd, suite) @@ -557,6 +558,8 @@ return [ ('chromedriver', RunChromeDriverTests), ('chrome_proxy', RunChromeProxyTests), + ('components_browsertests', + lambda options: RunTestSuites(options, ['components_browsertests'])), ('gpu', RunGPUTests), ('python_unittests', RunPythonUnitTests), ('telemetry_unittests', RunTelemetryUnitTests),
diff --git a/build/android/buildbot/bb_run_bot.py b/build/android/buildbot/bb_run_bot.py index 4682aeaa..a6afb86 100755 --- a/build/android/buildbot/bb_run_bot.py +++ b/build/android/buildbot/bb_run_bot.py
@@ -174,7 +174,7 @@ '--coverage-bucket', CHROMIUM_COVERAGE_BUCKET, '--cleanup'])), B('user-build-fyi-tests-dbg', H(std_test_steps), - T(telemetry_tests_user_build)), + T(telemetry_tests_user_build + ['components_browsertests'])), B('fyi-component-builder-tests-dbg', H(compile_step, extra_gyp='component=shared_library'), T(std_tests, ['--experimental', flakiness_server])),
diff --git a/build/android/gyp/process_resources.py b/build/android/gyp/process_resources.py index 52cf143..4e6c27d 100755 --- a/build/android/gyp/process_resources.py +++ b/build/android/gyp/process_resources.py
@@ -10,6 +10,7 @@ (see generate_v14_compatible_resources.py). """ +import codecs import optparse import os import re @@ -112,14 +113,15 @@ if len(java_files) != 1: return r_java_file = java_files[0] - r_java_contents = open(r_java_file).read() + r_java_contents = codecs.open(r_java_file, encoding='utf-8').read() for package in extra_packages: package_r_java_dir = os.path.join(r_dir, *package.split('.')) build_utils.MakeDirectory(package_r_java_dir) package_r_java_path = os.path.join(package_r_java_dir, 'R.java') - open(package_r_java_path, 'w').write( - re.sub(r'package [.\w]*;', 'package %s;' % package, r_java_contents)) + new_r_java = re.sub(r'package [.\w]*;', u'package %s;' % package, + r_java_contents) + codecs.open(package_r_java_path, 'w', encoding='utf-8').write(new_r_java) # TODO(cjhopman): These extra package's R.java files should be filtered to # only contain the resources listed in their R.txt files. At this point, we # have already compiled those other libraries, so doing this would only
diff --git a/build/android/gyp/write_build_config.py b/build/android/gyp/write_build_config.py index d8f2d74..1b4379d 100755 --- a/build/android/gyp/write_build_config.py +++ b/build/android/gyp/write_build_config.py
@@ -29,11 +29,43 @@ import optparse import os import sys +import xml.dom.minidom from util import build_utils import write_ordered_libraries +class AndroidManifest(object): + def __init__(self, path): + self.path = path + dom = xml.dom.minidom.parse(path) + manifests = dom.getElementsByTagName('manifest') + assert len(manifests) == 1 + self.manifest = manifests[0] + + def GetInstrumentation(self): + instrumentation_els = self.manifest.getElementsByTagName('instrumentation') + if len(instrumentation_els) == 0: + return None + if len(instrumentation_els) != 1: + raise Exception( + 'More than one <instrumentation> element found in %s' % self.path) + return instrumentation_els[0] + + def CheckInstrumentation(self, expected_package): + instr = self.GetInstrumentation() + if not instr: + raise Exception('No <instrumentation> elements found in %s' % self.path) + instrumented_package = instr.getAttributeNS( + 'http://schemas.android.com/apk/res/android', 'targetPackage') + if instrumented_package != expected_package: + raise Exception( + 'Wrong instrumented package. Expected %s, got %s' + % (expected_package, instrumented_package)) + + def GetPackageName(self): + return self.manifest.getAttribute('package') + dep_config_cache = {} def GetDepConfig(path): @@ -158,7 +190,6 @@ } deps_info = config['deps_info'] - if options.type == 'java_library' and not options.bypass_platform_checks: deps_info['requires_android'] = options.requires_android deps_info['supports_android'] = options.supports_android @@ -176,7 +207,6 @@ raise Exception('Not all deps support the Android platform: ' + str(deps_not_support_android)) - if options.type in ['java_library', 'android_apk']: javac_classpath = [c['jar_path'] for c in direct_library_deps] java_full_classpath = [c['jar_path'] for c in all_library_deps] @@ -220,8 +250,9 @@ config['resources']['extra_package_names'] = [ c['package_name'] for c in all_resources_deps if 'package_name' in c] + if options.type in ['android_apk', 'deps_dex']: + deps_dex_files = [c['dex_path'] for c in all_library_deps] - deps_dex_files = [c['dex_path'] for c in all_library_deps] # An instrumentation test apk should exclude the dex files that are in the apk # under test. if options.type == 'android_apk' and options.tested_apk_config: @@ -233,6 +264,10 @@ deps_dex_files = [ p for p in deps_dex_files if not p in tested_apk_deps_dex_files] + tested_apk_config = GetDepConfig(options.tested_apk_config) + expected_tested_package = tested_apk_config['package_name'] + AndroidManifest(options.android_manifest).CheckInstrumentation( + expected_tested_package) # Dependencies for the final dex file of an apk or a 'deps_dex'. if options.type in ['android_apk', 'deps_dex']: @@ -241,13 +276,17 @@ # TODO(cjhopman): proguard version dex_config['dependency_dex_files'] = deps_dex_files - if options.type == 'android_apk': config['dist_jar'] = { 'dependency_jars': [ c['jar_path'] for c in all_library_deps ] } + manifest = AndroidManifest(options.android_manifest) + deps_info['package_name'] = manifest.GetPackageName() + if not options.tested_apk_config and manifest.GetInstrumentation(): + # This must then have instrumentation only for itself. + manifest.CheckInstrumentation(manifest.GetPackageName()) library_paths = [] java_libraries_list = []
diff --git a/build/android/host_heartbeat.py b/build/android/host_heartbeat.py index 11421ce7..6a7cdd1 100755 --- a/build/android/host_heartbeat.py +++ b/build/android/host_heartbeat.py
@@ -12,8 +12,6 @@ import sys import time -from pylib.device import adb_wrapper -from pylib.device import device_filter from pylib.device import device_utils PULSE_PERIOD = 20 @@ -21,11 +19,10 @@ def main(): while True: try: - devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) + devices = device_utils.DeviceUtils.HealthyDevices() for d in devices: - device_utils.DeviceUtils(d).RunShellCommand( - ['touch', '/sdcard/host_heartbeat'], check_return=True) + d.RunShellCommand(['touch', '/sdcard/host_heartbeat'], + check_return=True) except: # Keep the heatbeat running bypassing all errors. pass
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py index e4517b6..ee52c71 100755 --- a/build/android/provision_devices.py +++ b/build/android/provision_devices.py
@@ -21,11 +21,9 @@ from pylib import constants from pylib import device_settings -from pylib.device import adb_wrapper from pylib.device import battery_utils from pylib.device import device_blacklist from pylib.device import device_errors -from pylib.device import device_filter from pylib.device import device_utils from pylib.utils import run_tests_helper from pylib.utils import timeout_retry @@ -55,8 +53,7 @@ if options.device is not None: devices = [options.device] else: - devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) + devices = device_utils.DeviceUtils.HealthyDevices() parallel_devices = device_utils.DeviceUtils.parallel(devices) parallel_devices.pMap(ProvisionDevice, options)
diff --git a/build/android/pylib/device/adb_wrapper.py b/build/android/pylib/device/adb_wrapper.py index fa430f55..20787c1 100644 --- a/build/android/pylib/device/adb_wrapper.py +++ b/build/android/pylib/device/adb_wrapper.py
@@ -12,18 +12,22 @@ import errno import logging import os +import re from pylib import cmd_helper from pylib import constants from pylib.device import decorators from pylib.device import device_errors -from pylib.device import device_filter from pylib.utils import timeout_retry _DEFAULT_TIMEOUT = 30 _DEFAULT_RETRIES = 2 +_EMULATOR_RE = re.compile(r'^emulator-[0-9]+$') + +_READY_STATE = 'device' + def _VerifyLocalFileExists(path): """Verifies a local file exists. @@ -160,22 +164,17 @@ cpu_affinity=0) @classmethod - def GetDevices(cls, filters=None, timeout=_DEFAULT_TIMEOUT, - retries=_DEFAULT_RETRIES): + def GetDevices(cls, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES): """DEPRECATED. Refer to Devices(...) below.""" # TODO(jbudorick): Remove this function once no more clients are using it. - return cls.Devices(filters=filters, timeout=timeout, retries=retries) + return cls.Devices(timeout=timeout, retries=retries) @classmethod - def Devices(cls, filters=None, timeout=_DEFAULT_TIMEOUT, + def Devices(cls, is_ready=True, timeout=_DEFAULT_TIMEOUT, retries=_DEFAULT_RETRIES): """Get the list of active attached devices. Args: - filters: (optional) A list of binary functions that take an AdbWrapper - instance and a string description. Any device for which all provided - filter functions do not return True will not be included in the - returned list. timeout: (optional) Timeout per try in seconds. retries: (optional) Number of retries to attempt. @@ -184,17 +183,8 @@ """ output = cls._RunAdbCmd(['devices'], timeout=timeout, retries=retries) lines = (line.split() for line in output.splitlines()) - devices = (AdbWrapper(line[0]) for line in lines if len(line) == 2) - - def matches_all_filters(device): - for f in filters or (): - if not f(device): - logging.info('Device %s failed filter %s', device.GetDeviceSerial(), - f.__name__) - return False - return True - - return [d for d in devices if matches_all_filters(d)] + return [AdbWrapper(line[0]) for line in lines + if len(line) == 2 and (not is_ready or line[1] == _READY_STATE)] def GetDeviceSerial(self): """Gets the device serial number associated with this object. @@ -551,3 +541,15 @@ if 'cannot' in output: raise device_errors.AdbCommandFailedError( ['root'], output, device_serial=self._device_serial) + + @property + def is_emulator(self): + return _EMULATOR_RE.match(self._device_serial) + + @property + def is_ready(self): + try: + return self.GetState() == _READY_STATE + except device_errors.CommandFailedError: + return False +
diff --git a/build/android/pylib/device/device_filter.py b/build/android/pylib/device/device_filter.py deleted file mode 100644 index 8e54b25..0000000 --- a/build/android/pylib/device/device_filter.py +++ /dev/null
@@ -1,53 +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. - -from pylib.device import device_blacklist -from pylib.device import device_errors - - -def DefaultFilters(): - """Returns a list of the most commonly-used device filters. - - These filters match devices that: - - are in a "device" state (as opposed to, e.g., "unauthorized" or - "emulator") - - are not blacklisted. - - Returns: - A list of the most commonly-used device filters. - """ - return [DeviceFilter, BlacklistFilter()] - - -def BlacklistFilter(): - """Returns a filter that matches devices that are not blacklisted. - - Note that this function is not the filter. It creates one when called using - the blacklist at that time and returns that. - - Returns: - A filter function that matches devices that are not blacklisted. - """ - blacklist = set(device_blacklist.ReadBlacklist()) - def f(adb): - return adb.GetDeviceSerial() not in blacklist - - return f - - -def DeviceFilter(adb): - """A filter that matches devices in a "device" state. - - (Basically, this is adb get-state == "device") - - Args: - adb: An instance of AdbWrapper. - Returns: - True if the device is in a "device" state. - """ - try: - return adb.GetState() == 'device' - except device_errors.CommandFailedError: - return False -
diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py index ddda017..46aec6f 100644 --- a/build/android/pylib/device/device_utils.py +++ b/build/android/pylib/device/device_utils.py
@@ -30,7 +30,6 @@ from pylib.device import decorators from pylib.device import device_blacklist from pylib.device import device_errors -from pylib.device import device_filter from pylib.device import intent from pylib.device import logcat_monitor from pylib.device.commands import install_commands @@ -854,29 +853,27 @@ if not real_device_path: return [(host_path, device_path)] - host_hash_tuples = md5sum.CalculateHostMd5Sums([real_host_path]) + host_checksums = md5sum.CalculateHostMd5Sums([real_host_path]) device_paths_to_md5 = ( real_device_path if os.path.isfile(real_host_path) else ('%s/%s' % (real_device_path, os.path.relpath(p, real_host_path)) - for _, p in host_hash_tuples)) - device_hash_tuples = md5sum.CalculateDeviceMd5Sums( + for p in host_checksums.iterkeys())) + device_checksums = md5sum.CalculateDeviceMd5Sums( device_paths_to_md5, self) if os.path.isfile(host_path): - if (not device_hash_tuples - or device_hash_tuples[0].hash != host_hash_tuples[0].hash): + host_checksum = host_checksums.get(real_host_path) + device_checksum = device_checksums.get(real_device_path) + if host_checksum != device_checksum: return [(host_path, device_path)] else: return [] else: - device_tuple_dict = dict((d.path, d.hash) for d in device_hash_tuples) to_push = [] - for host_hash, host_abs_path in ( - (h.hash, h.path) for h in host_hash_tuples): + for host_abs_path, host_checksum in host_checksums.iteritems(): device_abs_path = '%s/%s' % ( real_device_path, os.path.relpath(host_abs_path, real_host_path)) - if (device_abs_path not in device_tuple_dict - or device_tuple_dict[device_abs_path] != host_hash): + if (device_checksums.get(device_abs_path) != host_checksum): to_push.append((host_abs_path, device_abs_path)) return to_push @@ -1542,6 +1539,18 @@ return self._cache['run_pie'] + def GetClientCache(self, client_name): + """Returns client cache.""" + if client_name not in self._client_caches: + self._client_caches[client_name] = {} + return self._client_caches[client_name] + + def _ClearCache(self): + """Clears all caches.""" + for client in self._client_caches: + self._client_caches[client].clear() + self._cache.clear() + @classmethod def parallel(cls, devices=None, async=False): """Creates a Parallelizer to operate over the provided list of devices. @@ -1560,8 +1569,7 @@ A Parallelizer operating over |devices|. """ if not devices: - devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) + devices = cls.HealthyDevices() if not devices: raise device_errors.NoDevicesError() @@ -1571,14 +1579,15 @@ else: return parallelizer.SyncParallelizer(devices) - def GetClientCache(self, client_name): - """Returns client cache.""" - if client_name not in self._client_caches: - self._client_caches[client_name] = {} - return self._client_caches[client_name] + @classmethod + def HealthyDevices(cls): + blacklist = device_blacklist.ReadBlacklist() + def blacklisted(adb): + if adb.GetDeviceSerial() in blacklist: + logging.warning('Device %s is blacklisted.', adb.GetDeviceSerial()) + return True + return False - def _ClearCache(self): - """Clears all caches.""" - for client in self._client_caches: - self._client_caches[client].clear() - self._cache.clear() + return [cls(adb) for adb in adb_wrapper.AdbWrapper.Devices() + if not blacklisted(adb)] +
diff --git a/build/android/pylib/device/device_utils_test.py b/build/android/pylib/device/device_utils_test.py index 3806e26..4301e9d9 100755 --- a/build/android/pylib/device/device_utils_test.py +++ b/build/android/pylib/device/device_utils_test.py
@@ -1547,30 +1547,6 @@ self.assertEqual('0123456789abcdef', str(self.device)) -class DeviceUtilsParallelTest(mock_calls.TestCase): - - def testParallel_default(self): - test_serials = ['0123456789abcdef', 'fedcba9876543210'] - with self.assertCalls( - (mock.call.pylib.device.device_filter.DefaultFilters(), None), - (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(filters=None), - [_AdbWrapperMock(serial) for serial in test_serials])): - parallel_devices = device_utils.DeviceUtils.parallel() - for serial, device in zip(test_serials, parallel_devices.pGet(None)): - self.assertTrue( - isinstance(device, device_utils.DeviceUtils) - and serial == str(device), - 'Expected a DeviceUtils object with serial %s' % serial) - - def testParallel_noDevices(self): - with self.assertCalls( - (mock.call.pylib.device.device_filter.DefaultFilters(), None), - (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(filters=None), - [])): - with self.assertRaises(device_errors.NoDevicesError): - device_utils.DeviceUtils.parallel() - - class DeviceUtilsClientCache(DeviceUtilsTest): def testClientCache_twoCaches(self): @@ -1597,6 +1573,57 @@ self.assertEqual(client_cache_one, {}) self.assertEqual(client_cache_two, {}) + +class DeviceUtilsParallelTest(mock_calls.TestCase): + + def testParallel_default(self): + test_serials = ['0123456789abcdef', 'fedcba9876543210'] + with self.assertCall( + mock.call.pylib.device.device_utils.DeviceUtils.HealthyDevices(), + [device_utils.DeviceUtils(s) for s in test_serials]): + parallel_devices = device_utils.DeviceUtils.parallel() + for serial, device in zip(test_serials, parallel_devices.pGet(None)): + self.assertTrue(isinstance(device, device_utils.DeviceUtils)) + self.assertEquals(serial, device.adb.GetDeviceSerial()) + + def testParallel_noDevices(self): + with self.assertCall( + mock.call.pylib.device.device_utils.DeviceUtils.HealthyDevices(), []): + with self.assertRaises(device_errors.NoDevicesError): + device_utils.DeviceUtils.parallel() + + +class DeviceUtilsHealthyDevicesTest(mock_calls.TestCase): + + def _createAdbWrapperMock(self, serial, is_ready=True): + adb = _AdbWrapperMock(serial) + adb.is_ready = is_ready + return adb + + def testHealthyDevices_default(self): + test_serials = ['0123456789abcdef', 'fedcba9876543210'] + with self.assertCalls( + (mock.call.pylib.device.device_blacklist.ReadBlacklist(), []), + (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(), + [self._createAdbWrapperMock(s) for s in test_serials])): + devices = device_utils.DeviceUtils.HealthyDevices() + for serial, device in zip(test_serials, devices): + self.assertTrue(isinstance(device, device_utils.DeviceUtils)) + self.assertEquals(serial, device.adb.GetDeviceSerial()) + + def testHealthyDevices_blacklisted(self): + test_serials = ['0123456789abcdef', 'fedcba9876543210'] + with self.assertCalls( + (mock.call.pylib.device.device_blacklist.ReadBlacklist(), + ['fedcba9876543210']), + (mock.call.pylib.device.adb_wrapper.AdbWrapper.Devices(), + [self._createAdbWrapperMock(s) for s in test_serials])): + devices = device_utils.DeviceUtils.HealthyDevices() + self.assertEquals(1, len(devices)) + self.assertTrue(isinstance(devices[0], device_utils.DeviceUtils)) + self.assertEquals('0123456789abcdef', devices[0].adb.GetDeviceSerial()) + + if __name__ == '__main__': logging.getLogger().setLevel(logging.DEBUG) unittest.main(verbosity=2)
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py index 3f56e6d..0633f14 100644 --- a/build/android/pylib/instrumentation/instrumentation_test_instance.py +++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -30,6 +30,17 @@ _DEFAULT_ANNOTATIONS = [ 'Smoke', 'SmallTest', 'MediumTest', 'LargeTest', 'EnormousTest', 'IntegrationTest'] +_EXTRA_ENABLE_HTTP_SERVER = ( + 'org.chromium.chrome.test.ChromeInstrumentationTestRunner.' + + 'EnableTestHttpServer') +_EXTRA_DRIVER_TEST_LIST = ( + 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList') +_EXTRA_DRIVER_TEST_LIST_FILE = ( + 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestListFile') +_EXTRA_DRIVER_TARGET_PACKAGE = ( + 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage') +_EXTRA_DRIVER_TARGET_CLASS = ( + 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass') _NATIVE_CRASH_RE = re.compile('native crash', re.IGNORECASE) _PICKLE_FORMAT_VERSION = 10 @@ -130,29 +141,35 @@ self._apk_under_test = None self._package_info = None + self._suite = None self._test_apk = None self._test_jar = None self._test_package = None self._test_runner = None self._test_support_apk = None - self.__initializeApkAttributes(args, error_func) + self._initializeApkAttributes(args, error_func) self._data_deps = None self._isolate_abs_path = None self._isolate_delegate = None self._isolated_abs_path = None self._test_data = None - self.__initializeDataDependencyAttributes(args, isolate_delegate) + self._initializeDataDependencyAttributes(args, isolate_delegate) self._annotations = None self._excluded_annotations = None self._test_filter = None - self.__initializeTestFilterAttributes(args) + self._initializeTestFilterAttributes(args) self._flags = None - self.__initializeFlagAttributes(args) + self._initializeFlagAttributes(args) - def __initializeApkAttributes(self, args, error_func): + self._driver_apk = None + self._driver_package = None + self._driver_name = None + self._initializeDriverAttributes() + + def _initializeApkAttributes(self, args, error_func): if args.apk_under_test.endswith('.apk'): self._apk_under_test = args.apk_under_test else: @@ -164,20 +181,20 @@ error_func('Unable to find APK under test: %s' % self._apk_under_test) if args.test_apk.endswith('.apk'): - test_apk_root = os.path.splitext(os.path.basename(args.test_apk))[0] + self._suite = os.path.splitext(os.path.basename(args.test_apk))[0] self._test_apk = args.test_apk else: - test_apk_root = args.test_apk + self._suite = args.test_apk self._test_apk = os.path.join( constants.GetOutDirectory(), constants.SDK_BUILD_APKS_DIR, '%s.apk' % args.test_apk) self._test_jar = os.path.join( constants.GetOutDirectory(), constants.SDK_BUILD_TEST_JAVALIB_DIR, - '%s.jar' % test_apk_root) + '%s.jar' % self._suite) self._test_support_apk = os.path.join( constants.GetOutDirectory(), constants.SDK_BUILD_TEST_JAVALIB_DIR, - '%sSupport.apk' % test_apk_root) + '%sSupport.apk' % self._suite) if not os.path.exists(self._test_apk): error_func('Unable to find test APK: %s' % self._test_apk) @@ -194,7 +211,7 @@ if not self._package_info: logging.warning('Unable to find package info for %s', self._test_package) - def __initializeDataDependencyAttributes(self, args, isolate_delegate): + def _initializeDataDependencyAttributes(self, args, isolate_delegate): self._data_deps = [] if args.isolate_file_path: self._isolate_abs_path = os.path.abspath(args.isolate_file_path) @@ -215,7 +232,7 @@ if not self._isolate_delegate and not self._test_data: logging.warning('No data dependencies will be pushed.') - def __initializeTestFilterAttributes(self, args): + def _initializeTestFilterAttributes(self, args): self._test_filter = args.test_filter def annotation_dict_element(a): @@ -240,7 +257,7 @@ else: self._excluded_annotations = {} - def __initializeFlagAttributes(self, args): + def _initializeFlagAttributes(self, args): self._flags = ['--disable-fre', '--enable-test-intents'] # TODO(jbudorick): Transition "--device-flags" to "--device-flags-file" if hasattr(args, 'device_flags') and args.device_flags: @@ -252,9 +269,17 @@ stripped_lines = (l.strip() for l in device_flags_file) self._flags.extend([flag for flag in stripped_lines if flag]) - @property - def suite(self): - return 'instrumentation' + def _initializeDriverAttributes(self): + self._driver_apk = os.path.join( + constants.GetOutDirectory(), constants.SDK_BUILD_APKS_DIR, + 'OnDeviceInstrumentationDriver.apk') + if os.path.exists(self._driver_apk): + self._driver_package = apk_helper.GetPackageName( + self._driver_apk) + self._driver_name = apk_helper.GetInstrumentationName( + self._driver_apk) + else: + self._driver_apk = None @property def apk_under_test(self): @@ -265,10 +290,26 @@ return self._flags @property + def driver_apk(self): + return self._driver_apk + + @property + def driver_package(self): + return self._driver_package + + @property + def driver_name(self): + return self._driver_name + + @property def package_info(self): return self._package_info @property + def suite(self): + return self._suite + + @property def test_apk(self): return self._test_apk @@ -335,7 +376,7 @@ with open(pickle_path, 'r') as pickle_file: pickle_data = pickle.loads(pickle_file.read()) - jar_md5, _ = md5sum.CalculateHostMd5Sums(jar_path)[0] + jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path] try: if pickle_data['VERSION'] != _PICKLE_FORMAT_VERSION: @@ -377,7 +418,7 @@ if is_test_class(c)] def _SaveTestsToPickle(self, pickle_path, jar_path, tests): - jar_md5, _ = md5sum.CalculateHostMd5Sums(jar_path)[0] + jar_md5 = md5sum.CalculateHostMd5Sums(jar_path)[jar_path] pickle_data = { 'VERSION': _PICKLE_FORMAT_VERSION, 'JAR_MD5SUM': jar_md5, @@ -446,6 +487,28 @@ return inflated_tests @staticmethod + def GetHttpServerEnvironmentVars(): + return { + _EXTRA_ENABLE_HTTP_SERVER: None, + } + + def GetDriverEnvironmentVars( + self, test_list=None, test_list_file_path=None): + env = { + _EXTRA_DRIVER_TARGET_PACKAGE: self.test_package, + _EXTRA_DRIVER_TARGET_CLASS: self.test_runner, + } + + if test_list: + env[_EXTRA_DRIVER_TEST_LIST] = ','.join(test_list) + + if test_list_file_path: + env[_EXTRA_DRIVER_TEST_LIST_FILE] = ( + os.path.basename(test_list_file_path)) + + return env + + @staticmethod def ParseAmInstrumentRawOutput(raw_output): return ParseAmInstrumentRawOutput(raw_output)
diff --git a/build/android/pylib/instrumentation/test_jar.py b/build/android/pylib/instrumentation/test_jar.py index c3faef3..9c38510d 100644 --- a/build/android/pylib/instrumentation/test_jar.py +++ b/build/android/pylib/instrumentation/test_jar.py
@@ -65,7 +65,7 @@ try: with open(self._pickled_proguard_name, 'r') as r: d = pickle.loads(r.read()) - jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash + jar_md5 = md5sum.CalculateHostMd5Sums(self._jar_path)[self._jar_path] if (d['JAR_MD5SUM'] == jar_md5 and d['VERSION'] == PICKLE_FORMAT_VERSION): self._test_methods = d['TEST_METHODS'] @@ -105,7 +105,8 @@ logging.info('Storing proguard output to %s', self._pickled_proguard_name) d = {'VERSION': PICKLE_FORMAT_VERSION, 'TEST_METHODS': self._test_methods, - 'JAR_MD5SUM': md5sum.CalculateHostMd5Sums(self._jar_path)[0].hash} + 'JAR_MD5SUM': + md5sum.CalculateHostMd5Sums(self._jar_path)[self._jar_path]} with open(self._pickled_proguard_name, 'w') as f: f.write(pickle.dumps(d))
diff --git a/build/android/pylib/local/device/local_device_environment.py b/build/android/pylib/local/device/local_device_environment.py index 8346762..0d02ca3 100644 --- a/build/android/pylib/local/device/local_device_environment.py +++ b/build/android/pylib/local/device/local_device_environment.py
@@ -5,7 +5,6 @@ from pylib.base import environment from pylib.device import adb_wrapper from pylib.device import device_errors -from pylib.device import device_filter from pylib.device import device_utils from pylib.utils import parallelizer @@ -14,26 +13,24 @@ def __init__(self, args, _error_func): super(LocalDeviceEnvironment, self).__init__() - self._device = args.test_device + self._device_serial = args.test_device self._devices = [] self._max_tries = 1 + args.num_retries self._tool_name = args.tool #override def SetUp(self): - available_devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) + available_devices = device_utils.DeviceUtils.HealthyDevices() if not available_devices: raise device_errors.NoDevicesError - if self._device: - if self._device not in available_devices: + if self._device_serial: + self._devices = [d for d in available_devices + if d.adb.GetDeviceSerial == self._device_serial] + if not self._devices: raise device_errors.DeviceUnreachableError( - 'Could not find device %r' % self._device) - self._devices = [device_utils.DeviceUtils(self._device)] + 'Could not find device %r' % self._device_serial) else: - self._devices = [ - device_utils.DeviceUtils(s) - for s in available_devices] + self._devices = available_devices @property def devices(self):
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py index 1dc3ed4..e388fce 100644 --- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py +++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -48,8 +48,11 @@ def _DismissCrashDialog(device): + # TODO(jbudorick): Try to grep the output on the device instead of using + # large_output if/when DeviceUtils exposes a public interface for piped + # shell command handling. for l in device.RunShellCommand( - ['dumpsys', 'window', 'windows'], check_return=True): + ['dumpsys', 'window', 'windows'], check_return=True, large_output=True): m = re.match(_CURRENT_FOCUS_CRASH_RE, l) if m: device.SendKeyEvent(keyevent.KEYCODE_DPAD_RIGHT) @@ -127,22 +130,41 @@ #override def _RunTest(self, device, test): - test_name = self._GetTestName(test) - logging.info('preparing to run %s: %s' % (test_name, test)) + extras = self._test_instance.GetHttpServerEnvironmentVars() - extras = { - 'class': test_name, - 'org.chromium.chrome.test.ChromeInstrumentationTestRunner' - '.EnableTestHttpServer': '', - } - timeout = self._GetTimeoutFromAnnotations(test['annotations'], test_name) + if isinstance(test, list): + if not self._test_instance.driver_apk: + raise Exception('driver_apk does not exist. ' + 'Please build it and try again.') + + def name_and_timeout(t): + n = self._GetTestName(t) + i = self._GetTimeoutFromAnnotations(t['annotations'], n) + return (n, i) + + test_names, timeouts = zip(*(name_and_timeout(t) for t in test)) + + test_name = ','.join(test_names) + target = '%s/%s' % ( + self._test_instance.driver_package, + self._test_instance.driver_name) + extras.update( + self._test_instance.GetDriverEnvironmentVars( + test_list=test_names)) + timeout = sum(timeouts) + else: + test_name = self._GetTestName(test) + target = '%s/%s' % ( + self._test_instance.test_package, self._test_instance.test_runner) + extras['class'] = test_name + timeout = self._GetTimeoutFromAnnotations(test['annotations'], test_name) + + logging.info('preparing to run %s: %s' % (test_name, test)) time_ms = lambda: int(time.time() * 1e3) start_ms = time_ms() output = device.StartInstrumentation( - '%s/%s' % (self._test_instance.test_package, - self._test_instance.test_runner), - raw=True, extras=extras, timeout=timeout, retries=0) + target, raw=True, extras=extras, timeout=timeout, retries=0) duration_ms = time_ms() - start_ms # TODO(jbudorick): Make instrumentation tests output a JSON so this
diff --git a/build/android/pylib/remote/device/remote_device_helper.py b/build/android/pylib/remote/device/remote_device_helper.py index 5b1411e..896ae99 100644 --- a/build/android/pylib/remote/device/remote_device_helper.py +++ b/build/android/pylib/remote/device/remote_device_helper.py
@@ -20,4 +20,5 @@ error_msg: Error message to display if bad response is seen. """ if response.status_code != 200: - raise RemoteDeviceError(error_msg) + raise RemoteDeviceError( + '%s (%d: %s)' % (error_msg, response.status_code, response.reason))
diff --git a/build/android/pylib/remote/device/remote_device_instrumentation_test_run.py b/build/android/pylib/remote/device/remote_device_instrumentation_test_run.py index fe173a40..bcdb90c 100644 --- a/build/android/pylib/remote/device/remote_device_instrumentation_test_run.py +++ b/build/android/pylib/remote/device/remote_device_instrumentation_test_run.py
@@ -8,6 +8,7 @@ import os import tempfile +from pylib import constants from pylib.base import base_test_result from pylib.remote.device import remote_device_test_run from pylib.utils import apk_helper @@ -25,9 +26,33 @@ def _TriggerSetUp(self): """Set up the triggering of a test run.""" logging.info('Triggering test run.') - self._AmInstrumentTestSetup( - self._test_instance._apk_under_test, self._test_instance.test_apk, - self._test_instance.test_runner, environment_variables={}) + + with tempfile.NamedTemporaryFile(suffix='.txt') as test_list_file: + tests = self._test_instance.GetTests() + logging.debug('preparing to run %d instrumentation tests remotely:', + len(tests)) + for t in tests: + test_name = '%s#%s' % (t['class'], t['method']) + logging.debug(' %s', test_name) + test_list_file.write('%s\n' % test_name) + test_list_file.flush() + self._test_instance._data_deps.append( + (os.path.abspath(test_list_file.name), None)) + + env_vars = self._test_instance.GetDriverEnvironmentVars( + test_list_file_path=test_list_file.name) + env_vars.update(self._test_instance.GetHttpServerEnvironmentVars()) + + logging.debug('extras:') + for k, v in env_vars.iteritems(): + logging.debug(' %s: %s', k, v) + + self._AmInstrumentTestSetup( + self._test_instance.apk_under_test, + self._test_instance.driver_apk, + self._test_instance.driver_name, + environment_variables=env_vars, + extra_apks=[self._test_instance.test_apk]) #override def _ParseTestResults(self):
diff --git a/build/android/pylib/remote/device/remote_device_test_run.py b/build/android/pylib/remote/device/remote_device_test_run.py index 7aa91ae..3808836 100644 --- a/build/android/pylib/remote/device/remote_device_test_run.py +++ b/build/android/pylib/remote/device/remote_device_test_run.py
@@ -201,7 +201,7 @@ return self._results['status'] def _AmInstrumentTestSetup(self, app_path, test_path, runner_package, - environment_variables): + environment_variables, extra_apks=None): config = {'runner': runner_package} if environment_variables: config['environment_vars'] = ','.join( @@ -213,6 +213,7 @@ if data_deps: with tempfile.NamedTemporaryFile(suffix='.zip') as test_with_deps: sdcard_files = [] + additional_apks = [] host_test = os.path.basename(test_path) with zipfile.ZipFile(test_with_deps.name, 'w') as zip_file: zip_file.write(test_path, host_test, zipfile.ZIP_DEFLATED) @@ -223,8 +224,14 @@ else: zip_utils.WriteToZipFile(zip_file, h, os.path.basename(h)) sdcard_files.append(os.path.basename(h)) + for a in extra_apks or (): + zip_utils.WriteToZipFile(zip_file, a, os.path.basename(a)); + additional_apks.append(os.path.basename(a)) + config['sdcard_files'] = ','.join(sdcard_files) config['host_test'] = host_test + if additional_apks: + config['additional_apks'] = ','.join(additional_apks) self._test_id = self._UploadTestToDevice( 'robotium', test_with_deps.name, app_id=self._app_id) else: @@ -238,7 +245,8 @@ def _UploadAppToDevice(self, app_path): """Upload app to device.""" - logging.info('Uploading %s to remote service.', app_path) + logging.info('Uploading %s to remote service as %s.', app_path, + self._test_instance.suite) with open(app_path, 'rb') as apk_src: with appurify_sanitized.SanitizeLogging(self._env.verbose_count, logging.WARNING): @@ -297,4 +305,4 @@ config_response = appurify_sanitized.api.config_upload( self._env.token, config, self._test_id) remote_device_helper.TestHttpResponse( - config_response, 'Unable to upload test config.') \ No newline at end of file + config_response, 'Unable to upload test config.')
diff --git a/build/android/pylib/utils/md5sum.py b/build/android/pylib/utils/md5sum.py index da3cd15c..4d7d0b0 100644 --- a/build/android/pylib/utils/md5sum.py +++ b/build/android/pylib/utils/md5sum.py
@@ -5,6 +5,7 @@ import collections import logging import os +import re import tempfile import types @@ -12,8 +13,6 @@ from pylib import constants from pylib.utils import device_temp_file -HashAndPath = collections.namedtuple('HashAndPath', ['hash', 'path']) - MD5SUM_DEVICE_LIB_PATH = '/data/local/tmp/md5sum/' MD5SUM_DEVICE_BIN_PATH = MD5SUM_DEVICE_LIB_PATH + 'md5sum_bin' @@ -21,6 +20,8 @@ 'test -f {path} -o -d {path} ' '&& LD_LIBRARY_PATH={md5sum_lib} {device_pie_wrapper} {md5sum_bin} {path}') +_STARTS_WITH_CHECKSUM_RE = re.compile(r'^\s*[0-9a-fA-f]{32}\s+') + def CalculateHostMd5Sums(paths): """Calculates the MD5 sum value for all items in |paths|. @@ -28,7 +29,7 @@ Args: paths: A list of host paths to md5sum. Returns: - A list of named tuples with 'hash' and 'path' attributes. + A dict mapping paths to their respective md5sum checksums. """ if isinstance(paths, basestring): paths = [paths] @@ -36,7 +37,8 @@ out = cmd_helper.GetCmdOutput( [os.path.join(constants.GetOutDirectory(), 'md5sum_bin_host')] + [p for p in paths]) - return [HashAndPath(*l.split(None, 1)) for l in out.splitlines()] + + return _ParseMd5SumOutput(out.splitlines()) def CalculateDeviceMd5Sums(paths, device): @@ -45,7 +47,7 @@ Args: paths: A list of device paths to md5sum. Returns: - A list of named tuples with 'hash' and 'path' attributes. + A dict mapping paths to their respective md5sum checksums. """ if isinstance(paths, basestring): paths = [paths] @@ -72,5 +74,11 @@ device.adb.Push(md5sum_script_file.name, md5sum_device_script_file.name) out = device.RunShellCommand(['sh', md5sum_device_script_file.name]) - return [HashAndPath(*l.split(None, 1)) for l in out if l] + return _ParseMd5SumOutput(out) + + +def _ParseMd5SumOutput(out): + hash_and_path = (l.split(None, 1) for l in out + if l and _STARTS_WITH_CHECKSUM_RE.match(l)) + return dict((p, h) for h, p in hash_and_path)
diff --git a/build/android/pylib/utils/md5sum_test.py b/build/android/pylib/utils/md5sum_test.py index 6c689fbd..de9cd357 100755 --- a/build/android/pylib/utils/md5sum_test.py +++ b/build/android/pylib/utils/md5sum_test.py
@@ -39,8 +39,9 @@ with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output): out = md5sum.CalculateHostMd5Sums(test_path) self.assertEquals(1, len(out)) - self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash) - self.assertEquals('/test/host/file.dat', out[0].path) + self.assertTrue('/test/host/file.dat' in out) + self.assertEquals('0123456789abcdeffedcba9876543210', + out['/test/host/file.dat']) mock_get_cmd_output.assert_called_once_with( [HOST_MD5_EXECUTABLE, '/test/host/file.dat']) @@ -52,10 +53,12 @@ with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output): out = md5sum.CalculateHostMd5Sums(test_paths) self.assertEquals(2, len(out)) - self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash) - self.assertEquals('/test/host/file0.dat', out[0].path) - self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash) - self.assertEquals('/test/host/file1.dat', out[1].path) + self.assertTrue('/test/host/file0.dat' in out) + self.assertEquals('0123456789abcdeffedcba9876543210', + out['/test/host/file0.dat']) + self.assertTrue('/test/host/file1.dat' in out) + self.assertEquals('123456789abcdef00fedcba987654321', + out['/test/host/file1.dat']) mock_get_cmd_output.assert_called_once_with( [HOST_MD5_EXECUTABLE, '/test/host/file0.dat', '/test/host/file1.dat']) @@ -68,10 +71,12 @@ with mock.patch('pylib.cmd_helper.GetCmdOutput', new=mock_get_cmd_output): out = md5sum.CalculateHostMd5Sums(test_paths) self.assertEquals(2, len(out)) - self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash) - self.assertEquals('/test/host/file0.dat', out[0].path) - self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash) - self.assertEquals('/test/host/file1.dat', out[1].path) + self.assertTrue('/test/host/file0.dat' in out) + self.assertEquals('0123456789abcdeffedcba9876543210', + out['/test/host/file0.dat']) + self.assertTrue('/test/host/file1.dat' in out) + self.assertEquals('123456789abcdef00fedcba987654321', + out['/test/host/file1.dat']) mock_get_cmd_output.assert_called_once_with( [HOST_MD5_EXECUTABLE, '/test/host/file0.dat', '/test/host/file1.dat']) @@ -99,8 +104,9 @@ new=mock_device_temp_file)): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(1, len(out)) - self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash) - self.assertEquals('/storage/emulated/legacy/test/file.dat', out[0].path) + self.assertTrue('/storage/emulated/legacy/test/file.dat' in out) + self.assertEquals('0123456789abcdeffedcba9876543210', + out['/storage/emulated/legacy/test/file.dat']) device.adb.Push.assert_called_once_with( '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh') device.RunShellCommand.assert_called_once_with( @@ -132,10 +138,12 @@ new=mock_device_temp_file)): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(2, len(out)) - self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash) - self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path) - self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash) - self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path) + self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out) + self.assertEquals('0123456789abcdeffedcba9876543210', + out['/storage/emulated/legacy/test/file0.dat']) + self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out) + self.assertEquals('123456789abcdef00fedcba987654321', + out['/storage/emulated/legacy/test/file1.dat']) device.adb.Push.assert_called_once_with( '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh') device.RunShellCommand.assert_called_once_with( @@ -168,10 +176,47 @@ new=mock_device_temp_file)): out = md5sum.CalculateDeviceMd5Sums(test_path, device) self.assertEquals(2, len(out)) - self.assertEquals('0123456789abcdeffedcba9876543210', out[0].hash) - self.assertEquals('/storage/emulated/legacy/test/file0.dat', out[0].path) - self.assertEquals('123456789abcdef00fedcba987654321', out[1].hash) - self.assertEquals('/storage/emulated/legacy/test/file1.dat', out[1].path) + self.assertTrue('/storage/emulated/legacy/test/file0.dat' in out) + self.assertEquals('0123456789abcdeffedcba9876543210', + out['/storage/emulated/legacy/test/file0.dat']) + self.assertTrue('/storage/emulated/legacy/test/file1.dat' in out) + self.assertEquals('123456789abcdef00fedcba987654321', + out['/storage/emulated/legacy/test/file1.dat']) + device.adb.Push.assert_called_once_with( + '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh') + device.RunShellCommand.assert_called_once_with( + ['sh', '/data/local/tmp/test/script/file.sh']) + + def testCalculateDeviceMd5Sums_singlePath_linkerWarning(self): + # See crbug/479966 + test_path = '/storage/emulated/legacy/test/file.dat' + + device = mock.NonCallableMock() + device.adb = mock.NonCallableMock() + device.adb.Push = mock.Mock() + device_md5sum_output = [ + 'WARNING: linker: /data/local/tmp/md5sum/md5sum_bin: ' + 'unused DT entry: type 0x1d arg 0x15db', + '0123456789abcdeffedcba9876543210 ' + '/storage/emulated/legacy/test/file.dat', + ] + device.RunShellCommand = mock.Mock(return_value=device_md5sum_output) + + mock_temp_file = mock.mock_open() + mock_temp_file.return_value.name = '/tmp/test/script/file.sh' + + mock_device_temp_file = mock.mock_open() + mock_device_temp_file.return_value.name = ( + '/data/local/tmp/test/script/file.sh') + + with mock.patch('tempfile.NamedTemporaryFile', new=mock_temp_file), ( + mock.patch('pylib.utils.device_temp_file.DeviceTempFile', + new=mock_device_temp_file)): + out = md5sum.CalculateDeviceMd5Sums(test_path, device) + self.assertEquals(1, len(out)) + self.assertTrue('/storage/emulated/legacy/test/file.dat' in out) + self.assertEquals('0123456789abcdeffedcba9876543210', + out['/storage/emulated/legacy/test/file.dat']) device.adb.Push.assert_called_once_with( '/tmp/test/script/file.sh', '/data/local/tmp/test/script/file.sh') device.RunShellCommand.assert_called_once_with(
diff --git a/build/android/screenshot.py b/build/android/screenshot.py index 4c1e247..c48a255 100755 --- a/build/android/screenshot.py +++ b/build/android/screenshot.py
@@ -12,8 +12,7 @@ import sys from pylib import screenshot -from pylib.device import adb_wrapper -from pylib.device import device_filter +from pylib.device import device_errors from pylib.device import device_utils def _PrintMessage(heading, eol='\n'): @@ -67,22 +66,25 @@ (options, args) = parser.parse_args() - if options.verbose: - logging.getLogger().setLevel(logging.DEBUG) - - devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) - - if not options.device and len(devices) > 1: - parser.error('Multiple devices are attached. ' - 'Please specify device serial number with --device.') - elif not options.device and len(devices) == 1: - options.device = devices[0] - if len(args) > 1: parser.error('Too many positional arguments.') host_file = args[0] if args else options.file - device = device_utils.DeviceUtils(options.device) + + if options.verbose: + logging.getLogger().setLevel(logging.DEBUG) + + devices = device_utils.DeviceUtils.HealthyDevices() + + if not options.device: + if len(devices) > 1: + parser.error('Multiple devices are attached. ' + 'Please specify device serial number with --device.') + elif len(devices) == 1: + device = devices[0] + else: + raise device_errors.NoDevicesError() + else: + device = device_utils.DeviceUtils(options.device) if options.video: _CaptureVideo(device, host_file, options)
diff --git a/build/android/tombstones.py b/build/android/tombstones.py index 3f35086..c83a5848 100755 --- a/build/android/tombstones.py +++ b/build/android/tombstones.py
@@ -21,7 +21,6 @@ from pylib.device import adb_wrapper from pylib.device import device_errors -from pylib.device import device_filter from pylib.device import device_utils from pylib.utils import run_tests_helper @@ -234,20 +233,19 @@ options, _ = parser.parse_args() if options.device: - devices = [options.device] + devices = [device_utils.DeviceUtils(options.device)] else: - devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) + devices = device_utils.DeviceUtils.HealthyDevices() # This must be done serially because strptime can hit a race condition if # used for the first time in a multithreaded environment. # http://bugs.python.org/issue7980 tombstones = [] - for adb in devices: - device = device_utils.DeviceUtils(adb) + for device in devices: tombstones += _GetTombstonesForDevice(device, options) _ResolveTombstones(options.jobs, tombstones) + if __name__ == '__main__': sys.exit(main())
diff --git a/build/android/update_verification.py b/build/android/update_verification.py index 29589f3..45c6e98 100755 --- a/build/android/update_verification.py +++ b/build/android/update_verification.py
@@ -12,8 +12,6 @@ import sys import time -from pylib.device import adb_wrapper -from pylib.device import device_filter from pylib.device import device_utils def _SaveAppData(device, package_name, from_apk=None, data_dir=None): @@ -109,11 +107,10 @@ parser.print_help(sys.stderr) parser.error('Unknown arguments: %s.' % args) - devices = adb_wrapper.AdbWrapper.Devices( - filters=device_filter.DefaultFilters()) + devices = device_utils.DeviceUtils.HealthyDevices() if len(devices) != 1: parser.error('Exactly 1 device must be attached.') - device = device_utils.DeviceUtils(devices[0]) + device = devices[0] if options.from_apk: assert os.path.isfile(options.from_apk)
diff --git a/build/apk_test.gypi b/build/apk_test.gypi index 792d92ca..3a66e3bf 100644 --- a/build/apk_test.gypi +++ b/build/apk_test.gypi
@@ -22,6 +22,7 @@ '<(DEPTH)/base/base.gyp:base_java', '<(DEPTH)/build/android/pylib/device/commands/commands.gyp:chromium_commands', '<(DEPTH)/build/android/pylib/remote/device/dummy/dummy.gyp:remote_device_dummy_apk', + '<(DEPTH)/testing/android/appurify_support.gyp:appurify_support_java', '<(DEPTH)/tools/android/android_tools.gyp:android_tools', ], 'conditions': [
diff --git a/build/common.gypi b/build/common.gypi index e43adfd..2f72ec6 100644 --- a/build/common.gypi +++ b/build/common.gypi
@@ -149,6 +149,7 @@ 'enable_hidpi%': '<(enable_hidpi)', 'buildtype%': '<(buildtype)', 'branding%': '<(branding)', + 'branding_path_component%': '<(branding)', 'host_arch%': '<(host_arch)', 'target_arch%': '<(target_arch)', @@ -188,6 +189,14 @@ 'mips_dsp_rev%': 0, 'conditions': [ + ['branding == "Chrome"', { + 'branding_path_component%': 'google_chrome', + }], + + ['branding == "Chromium"', { + 'branding_path_component%': 'chromium', + }], + # Ash needs Aura. ['use_aura==0', { 'use_ash%': 0, @@ -295,6 +304,7 @@ 'use_default_render_theme%': '<(use_default_render_theme)', 'buildtype%': '<(buildtype)', 'branding%': '<(branding)', + 'branding_path_component%': '<(branding_path_component)', 'arm_version%': '<(arm_version)', 'sysroot%': '<(sysroot)', 'chroot_cmd%': '<(chroot_cmd)', @@ -1066,6 +1076,7 @@ # Copy conditionally-set variables out one scope. 'branding%': '<(branding)', + 'branding_path_component%': '<(branding_path_component)', 'buildtype%': '<(buildtype)', 'target_arch%': '<(target_arch)', 'target_subarch%': '<(target_subarch)', @@ -3745,9 +3756,17 @@ ], }], ['OS=="android"', { - 'variables': { - 'release_optimize%': 's', - }, + 'conditions': [ + ['clang==1', { + 'variables': { + 'release_optimize%': 'z', + }, + }, { + 'variables': { + 'release_optimize%': 's', + }, + }], + ], }], ['profiling==1', { 'cflags': [ @@ -5108,6 +5127,22 @@ }], ], }, + 'configurations': { + 'Release_Base': { + 'conditions': [ + ['branding=="Chrome" and buildtype=="Official"', { + 'xcode_settings': { + 'OTHER_CFLAGS': [ + # The Google Chrome Framework dSYM generated by dsymutil has + # grown larger than 4GB, which dsymutil can't handle. Reduce + # the amount of debug symbols. + '-gline-tables-only', # See http://crbug.com/479841 + ] + }, + }], + ], + }, # configuration "Release" + }, # configurations 'xcode_settings': { 'GCC_DYNAMIC_NO_PIC': 'NO', # No -mdynamic-no-pic # (Equivalent to -fPIC) @@ -5208,15 +5243,6 @@ }, { # asan != 0 'STRIPFLAGS': '-S', }], - ['branding=="Chrome" and buildtype=="Official"', { - 'OTHER_CFLAGS': [ - # The Google Chrome Framework dSYM generated by - # dsymutil has grown larger than 4GB, which - # dsymutil can't handle. Reduce the amount of debug - # symbols. - '-gline-tables-only', # See http://crbug.com/479841 - ] - }], ], }, # xcode_settings }, # configuration "Release"
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index a093879c..ab773ea 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -314,6 +314,8 @@ "--android-manifest", rebase_path(invoker.android_manifest, root_build_dir), ] + } else { + assert(!is_apk, "apk build configs require an android_manifest") } if (defined(invoker.custom_package)) { args += [
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 7a49a5e..ddd58ee3 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1194,6 +1194,7 @@ } assert(defined(invoker.final_apk_path) || defined(invoker.apk_name)) + assert(defined(invoker.android_manifest)) gen_dir = "$target_gen_dir/$target_name" base_path = "$gen_dir/$target_name" _build_config = "$target_gen_dir/$target_name.build_config" @@ -1279,6 +1280,7 @@ } } + _android_manifest = invoker.android_manifest _rebased_build_config = rebase_path(_build_config, root_build_dir) write_build_config("${_template_name}__build_config") { @@ -1286,6 +1288,7 @@ dex_path = final_dex_path resources_zip = resources_zip_path build_config = _build_config + android_manifest = _android_manifest if (defined(invoker.deps)) { deps = invoker.deps @@ -1303,7 +1306,7 @@ final_deps += [ ":${_template_name}__process_resources" ] process_resources("${_template_name}__process_resources") { srcjar_path = "${target_gen_dir}/${target_name}.srcjar" - android_manifest = invoker.android_manifest + android_manifest = _android_manifest resource_dirs = [ "//build/android/ant/empty/res" ] zip_path = resources_zip_path generate_constant_ids = true @@ -1349,7 +1352,7 @@ supports_android = true requires_android = true override_build_config = _build_config - android_manifest = invoker.android_manifest + android_manifest = _android_manifest chromium_code = true if (defined(invoker.java_files)) { java_files = invoker.java_files @@ -1457,7 +1460,7 @@ final_deps += [ ":${_template_name}__create" ] create_apk("${_template_name}__create") { apk_path = _final_apk_path - android_manifest = invoker.android_manifest + android_manifest = _android_manifest resources_zip = all_resources_zip_path dex_path = final_dex_path load_library_from_apk = _load_library_from_apk @@ -1550,8 +1553,7 @@ } android_apk(target_name) { - _apk_name = apk_name - final_apk_path = "$root_build_dir/${_apk_name}_apk/${_apk_name}-debug.apk" + final_apk_path = "$root_build_dir/${apk_name}_apk/${apk_name}-debug.apk" java_files = [ "//testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestActivity.java", "//testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java", @@ -1564,6 +1566,7 @@ deps = [ "//base:base_java", "//build/android/pylib/remote/device/dummy:remote_device_dummy_apk", + "//testing/android/appurify_support:appurify_support_java", ] if (defined(invoker.deps)) { deps += invoker.deps
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index ca7fe6d..8b0910f 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -97,11 +97,21 @@ # Subsystem -------------------------------------------------------------------- +# This is appended to the subsystem to specify a minimum version. +if (current_cpu == "x64") { + # The number after the comma is the minimum required OS version. + # 5.02 = Windows Server 2003. + subsystem_version_suffix = ",5.02" +} else { + # Don't specify a min version on x86. + subsystem_version_suffix = "" +} + config("console") { - ldflags = [ "/SUBSYSTEM:CONSOLE" ] + ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ] } config("windowed") { - ldflags = [ "/SUBSYSTEM:WINDOWS" ] + ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ] } # Incremental linking ----------------------------------------------------------
diff --git a/build/gn_migration.gypi b/build/gn_migration.gypi index 76d3b59a..58e7ff5 100644 --- a/build/gn_migration.gypi +++ b/build/gn_migration.gypi
@@ -39,7 +39,6 @@ '../base/base.gyp:base_unittests', '../base/base.gyp:build_utf8_validator_tables#host', '../base/base.gyp:check_example', - '../base/base.gyp:protect_file_posix', '../cc/cc_tests.gyp:cc_perftests', '../cc/cc_tests.gyp:cc_unittests', '../cc/blink/cc_blink_tests.gyp:cc_blink_unittests',
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt index 3e8ad45..18239b7a 100644 --- a/build/ios/grit_whitelist.txt +++ b/build/ios/grit_whitelist.txt
@@ -770,8 +770,6 @@ IDS_NUMBERED_PROFILE_NAME IDS_OK IDS_OMNIBOX_EMPTY_HINT -IDS_OMNIBOX_EMPTY_HINT_NO_DEFAULT_SEARCH_PROVIDER -IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER IDS_ONE_CLICK_SIGNIN_CONFIRM_EMAIL_DIALOG_CANCEL_BUTTON IDS_OPEN_TABS_NOTYETSYNCED IDS_OPEN_TABS_PROMOCOMPUTER @@ -991,6 +989,7 @@ IDS_SAFE_BROWSING_PRIVACY_POLICY_PAGE_V2 IDS_SAFE_BROWSING_PRIVACY_POLICY_URL IDS_SAVE +IDS_SEARCH_BOX_EMPTY_HINT IDS_SECURE_CONNECTION_EV IDS_SESSION_CRASHED_VIEW_MESSAGE IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON
diff --git a/build/linux/system.gyp b/build/linux/system.gyp index cc6e81b..476476e 100644 --- a/build/linux/system.gyp +++ b/build/linux/system.gyp
@@ -1124,6 +1124,7 @@ 'spd_set_synthesis_voice', 'spd_list_modules', 'spd_set_output_module', + 'spd_set_language', ], 'message': 'Generating libspeechd library loader', 'process_outputs_as_sources': 1,
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index 352b41f..ac502cf 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -295,9 +295,6 @@ // https://crbug.com/430533 "race:TileTaskGraphRunner::Run\n" -// https://crbug.com/437044 -"race:SkEventTracer\n" - // https://crbug.com/448203 "race:blink::RemoteFrame::detach\n"
diff --git a/build/secondary/tools/grit/grit_rule.gni b/build/secondary/tools/grit/grit_rule.gni index 64cfd77a..09a04c1 100644 --- a/build/secondary/tools/grit/grit_rule.gni +++ b/build/secondary/tools/grit/grit_rule.gni
@@ -204,6 +204,12 @@ "enable_extensions", ] } +if (enable_media_router) { + grit_defines += [ + "-D", + "enable_media_router", + ] +} if (enable_plugins) { grit_defines += [ "-D",
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn index 95c2d9f3..05406c3 100644 --- a/build/toolchain/win/BUILD.gn +++ b/build/toolchain/win/BUILD.gn
@@ -101,7 +101,7 @@ outputs = [ "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", ] - rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_c}}" + rspfile_content = "{{defines}} {{include_dirs}} {{cflags}} {{cflags_cc}}" } tool("rc") {
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index b35560a..c0987c8 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn
@@ -98,6 +98,7 @@ "input/page_scale_animation.h", "input/scroll_elasticity_helper.cc", "input/scroll_elasticity_helper.h", + "input/selection.h", "input/selection_bound_type.h", "input/top_controls_manager.cc", "input/top_controls_manager.h",
diff --git a/cc/base/histograms.cc b/cc/base/histograms.cc index af1ea66..8b284d9 100644 --- a/cc/base/histograms.cc +++ b/cc/base/histograms.cc
@@ -5,9 +5,9 @@ #include "cc/base/histograms.h" #include <algorithm> +#include <cmath> #include <limits> -#include "base/float_util.h" #include "base/numerics/safe_conversions.h" namespace cc { @@ -38,7 +38,7 @@ elapsed = std::max( elapsed, base::TimeDelta::FromMicroseconds(kMinimumTimeMicroseconds)); double area_per_time = area / elapsed.InMillisecondsF(); - DCHECK(!base::IsNaN(area_per_time)); + DCHECK(!std::isnan(area_per_time)); *time_microseconds = base::saturated_cast<Sample>(elapsed.InMicroseconds()); *pixels_per_ms = base::saturated_cast<Sample>(area_per_time); }
diff --git a/cc/blink/web_content_layer_impl.cc b/cc/blink/web_content_layer_impl.cc index 90d7f9b9..a480a06 100644 --- a/cc/blink/web_content_layer_impl.cc +++ b/cc/blink/web_content_layer_impl.cc
@@ -29,6 +29,8 @@ return blink::WebContentLayerClient::DisplayListConstructionDisabled; case cc::ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED: return blink::WebContentLayerClient::DisplayListCachingDisabled; + case cc::ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED: + return blink::WebContentLayerClient::DisplayListPaintingDisabled; } NOTREACHED(); return blink::WebContentLayerClient::PaintDefaultBehavior;
diff --git a/cc/cc.gyp b/cc/cc.gyp index aeea018..96001ef 100644 --- a/cc/cc.gyp +++ b/cc/cc.gyp
@@ -153,6 +153,7 @@ 'input/scroll_elasticity_helper.cc', 'input/scroll_elasticity_helper.h', 'input/selection_bound_type.h', + 'input/selection.h', 'input/top_controls_manager.cc', 'input/top_controls_manager.h', 'input/top_controls_manager_client.h',
diff --git a/cc/debug/rasterize_and_record_benchmark.cc b/cc/debug/rasterize_and_record_benchmark.cc index f9a48c9..4b98dfa 100644 --- a/cc/debug/rasterize_and_record_benchmark.cc +++ b/cc/debug/rasterize_and_record_benchmark.cc
@@ -34,8 +34,12 @@ const int kWarmupRuns = 0; const int kTimeCheckInterval = 1; -const char* kModeSuffixes[RecordingSource::RECORDING_MODE_COUNT] = - {"", "_sk_null_canvas", "_painting_disabled", "_caching_disabled"}; +const char* kModeSuffixes[RecordingSource::RECORDING_MODE_COUNT] = { + "", + "_sk_null_canvas", + "_painting_disabled", + "_caching_disabled", + "_construction_disabled"}; } // namespace @@ -129,6 +133,11 @@ mode_index++) { RecordingSource::RecordingMode mode = static_cast<RecordingSource::RecordingMode>(mode_index); + + // Not supported for SkPicture recording. + if (mode == RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED) + continue; + base::TimeDelta min_time = base::TimeDelta::Max(); size_t memory_used = 0; @@ -182,15 +191,18 @@ // Already setup for normal recording. break; case RecordingSource::RECORD_WITH_SK_NULL_CANVAS: - // TODO(schenney): Remove this when DisplayList recording is the only - // option. For now, fall through and disable construction. + // Not supported for Display List recording. + continue; case RecordingSource::RECORD_WITH_PAINTING_DISABLED: - painting_control = - ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED; + painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED; break; case RecordingSource::RECORD_WITH_CACHING_DISABLED: painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; break; + case RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED: + painting_control = + ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED; + break; default: NOTREACHED(); }
diff --git a/cc/input/layer_selection_bound.h b/cc/input/layer_selection_bound.h index 21d52849..10b14d9 100644 --- a/cc/input/layer_selection_bound.h +++ b/cc/input/layer_selection_bound.h
@@ -6,6 +6,7 @@ #define CC_INPUT_LAYER_SELECTION_BOUND_H_ #include "cc/base/cc_export.h" +#include "cc/input/selection.h" #include "cc/input/selection_bound_type.h" #include "ui/gfx/geometry/point_f.h" @@ -25,6 +26,8 @@ bool operator==(const LayerSelectionBound& lhs, const LayerSelectionBound& rhs); bool operator!=(const LayerSelectionBound& lhs, const LayerSelectionBound& rhs); +typedef Selection<LayerSelectionBound> LayerSelection; + } // namespace cc #endif // CC_INPUT_LAYER_SELECTION_BOUND_H_
diff --git a/cc/input/selection.h b/cc/input/selection.h new file mode 100644 index 0000000..1f3c6eb --- /dev/null +++ b/cc/input/selection.h
@@ -0,0 +1,38 @@ +// 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 CC_INPUT_SELECTION_H_ +#define CC_INPUT_SELECTION_H_ + +#include "cc/base/cc_export.h" + +namespace cc { + +template <typename BoundType> +struct CC_EXPORT Selection { + Selection() : is_editable(false), is_empty_text_form_control(false) {} + ~Selection() {} + + BoundType start, end; + bool is_editable; + bool is_empty_text_form_control; +}; + +template <typename BoundType> +inline bool operator==(const Selection<BoundType>& lhs, + const Selection<BoundType>& rhs) { + return lhs.start == rhs.start && lhs.end == rhs.end && + lhs.is_editable == rhs.is_editable && + lhs.is_empty_text_form_control == rhs.is_empty_text_form_control; +} + +template <typename BoundType> +inline bool operator!=(const Selection<BoundType>& lhs, + const Selection<BoundType>& rhs) { + return !(lhs == rhs); +} + +} // namespace cc + +#endif // CC_INPUT_SELECTION_H_
diff --git a/cc/layers/content_layer_client.h b/cc/layers/content_layer_client.h index 3a821369..86b5264 100644 --- a/cc/layers/content_layer_client.h +++ b/cc/layers/content_layer_client.h
@@ -22,7 +22,8 @@ enum PaintingControlSetting { PAINTING_BEHAVIOR_NORMAL, DISPLAY_LIST_CONSTRUCTION_DISABLED, - DISPLAY_LIST_CACHING_DISABLED + DISPLAY_LIST_CACHING_DISABLED, + DISPLAY_LIST_PAINTING_DISABLED }; virtual void PaintContents(SkCanvas* canvas,
diff --git a/cc/layers/contents_scaling_layer.cc b/cc/layers/contents_scaling_layer.cc index 733bac09..b44830f 100644 --- a/cc/layers/contents_scaling_layer.cc +++ b/cc/layers/contents_scaling_layer.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/layers/contents_scaling_layer.h" +#include "cc/trees/layer_tree_host.h" #include "ui/gfx/geometry/size_conversions.h" namespace cc { @@ -25,11 +26,23 @@ float* contents_scale_x, float* contents_scale_y, gfx::Size* content_bounds) { + float old_contents_scale_x = *contents_scale_x; + float old_contents_scale_y = *contents_scale_y; + gfx::Size old_content_bounds = *content_bounds; *contents_scale_x = ideal_contents_scale; *contents_scale_y = ideal_contents_scale; *content_bounds = ComputeContentBoundsForScale( ideal_contents_scale, ideal_contents_scale); + + if (!layer_tree_host()) + return; + + if (old_contents_scale_x != *contents_scale_x || + old_contents_scale_y != *contents_scale_y || + old_content_bounds != *content_bounds) { + layer_tree_host()->property_trees()->needs_rebuild = true; + } } bool ContentsScalingLayer::Update(ResourceUpdateQueue* queue,
diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc index aa16beb..7037038 100644 --- a/cc/layers/delegated_renderer_layer_impl.cc +++ b/cc/layers/delegated_renderer_layer_impl.cc
@@ -408,14 +408,6 @@ } } -// TODO(danakj): crbug.com/455931 -static ResourceProvider::ResourceId ValidateResource( - ResourceProvider* provider, - ResourceProvider::ResourceId id) { - provider->ValidateResource(id); - return id; -} - void DelegatedRendererLayerImpl::AppendRenderPassQuads( RenderPass* render_pass, const RenderPass* delegated_render_pass, @@ -487,9 +479,7 @@ DrawQuad* output_quad = render_pass->CopyFromAndAppendDrawQuad( delegated_quad, output_shared_quad_state); output_quad->visible_rect = quad_visible_rect; - // TODO(danakj): crbug.com/455931 - output_quad->IterateResources(base::Bind( - &ValidateResource, layer_tree_impl()->resource_provider())); + ValidateQuadResources(output_quad); } else { RenderPassId delegated_contributing_render_pass_id = RenderPassDrawQuad::MaterialCast(delegated_quad)->render_pass_id; @@ -507,9 +497,7 @@ RenderPassDrawQuad::MaterialCast(delegated_quad), output_shared_quad_state, output_contributing_render_pass_id); output_quad->visible_rect = quad_visible_rect; - // TODO(danakj): crbug.com/455931 - output_quad->IterateResources(base::Bind( - &ValidateResource, layer_tree_impl()->resource_provider())); + ValidateQuadResources(output_quad); } } }
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index 3eacbbd..7d449b7 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -159,9 +159,6 @@ bool nearest_neighbor = false; TextureDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - resources_.back()->id()); quad->SetNew(shared_quad_state, quad_rect, opaque_rect, @@ -174,6 +171,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } void HeadsUpDisplayLayerImpl::UpdateHudTexture(
diff --git a/cc/layers/io_surface_layer_impl.cc b/cc/layers/io_surface_layer_impl.cc index f9acc683..a7da986 100644 --- a/cc/layers/io_surface_layer_impl.cc +++ b/cc/layers/io_surface_layer_impl.cc
@@ -77,9 +77,6 @@ if (visible_quad_rect.IsEmpty()) return; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - io_surface_resource_id_); IOSurfaceDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<IOSurfaceDrawQuad>(); quad->SetNew(shared_quad_state, @@ -89,6 +86,7 @@ io_surface_size_, io_surface_resource_id_, IOSurfaceDrawQuad::FLIPPED); + ValidateQuadResources(quad); } void IOSurfaceLayerImpl::ReleaseResources() {
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 13e788e..c47e50c 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -352,6 +352,8 @@ float fill_width = width * 3; gfx::Rect fill_rect = quad_rect; fill_rect.Inset(fill_width / 2.f, fill_width / 2.f); + if (fill_rect.IsEmpty()) + return; gfx::Rect visible_fill_rect = gfx::IntersectRects(visible_quad_rect, fill_rect); DebugBorderDrawQuad* fill_quad = @@ -744,6 +746,23 @@ SetNeedsPushProperties(); } +#if DCHECK_IS_ON() +// Verify that the resource id is valid. +static ResourceProvider::ResourceId ValidateResource( + const ResourceProvider* provider, + ResourceProvider::ResourceId id) { + provider->ValidateResource(id); + return id; +} +#endif + +void LayerImpl::ValidateQuadResourcesInternal(DrawQuad* quad) const { +#if DCHECK_IS_ON() + quad->IterateResources( + base::Bind(&ValidateResource, layer_tree_impl_->resource_provider())); +#endif +} + const char* LayerImpl::LayerTypeAsString() const { return "cc::LayerImpl"; }
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 730b188e..f3eb4ce 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -247,6 +247,13 @@ AppendQuadsData* append_quads_data) {} virtual void DidDraw(ResourceProvider* resource_provider); + // Verify that the resource ids in the quad are valid. + void ValidateQuadResources(DrawQuad* quad) const { +#if DCHECK_IS_ON() + ValidateQuadResourcesInternal(quad); +#endif + } + virtual void GetContentsResourceId(ResourceProvider::ResourceId* resource_id, gfx::Size* resource_size) const; @@ -669,6 +676,8 @@ gfx::Rect GetScaledEnclosingRectInTargetSpace(float scale) const; private: + void ValidateQuadResourcesInternal(DrawQuad* quad) const; + void PushScrollOffset(const gfx::ScrollOffset* scroll_offset); // If the new scroll offset is assigned from the root scroll offset delegate, // LayerImpl won't inform the root scroll offset delegate about the scroll
diff --git a/cc/layers/nine_patch_layer_impl.cc b/cc/layers/nine_patch_layer_impl.cc index 898e6b5f..fc2f457 100644 --- a/cc/layers/nine_patch_layer_impl.cc +++ b/cc/layers/nine_patch_layer_impl.cc
@@ -100,9 +100,6 @@ if (!resource) return; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource(resource); - static const bool flipped = false; static const bool nearest_neighbor = false; static const bool premultiplied_alpha = true; @@ -234,6 +231,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } visible_rect = @@ -255,6 +253,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } visible_rect = @@ -276,6 +275,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } visible_rect = @@ -297,6 +297,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } visible_rect = @@ -318,6 +319,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } visible_rect = @@ -339,6 +341,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } visible_rect = @@ -360,6 +363,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } visible_rect = @@ -381,6 +385,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } if (fill_center_) { @@ -403,6 +408,7 @@ vertex_opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } } }
diff --git a/cc/layers/painted_scrollbar_layer_impl.cc b/cc/layers/painted_scrollbar_layer_impl.cc index ad98c4f..005e087 100644 --- a/cc/layers/painted_scrollbar_layer_impl.cc +++ b/cc/layers/painted_scrollbar_layer_impl.cc
@@ -103,14 +103,13 @@ if (thumb_resource_id && !visible_thumb_quad_rect.IsEmpty()) { gfx::Rect opaque_rect; const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource(thumb_resource_id); TextureDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); quad->SetNew(shared_quad_state, scaled_thumb_quad_rect, opaque_rect, scaled_visible_thumb_quad_rect, thumb_resource_id, premultipled_alpha, uv_top_left, uv_bottom_right, SK_ColorTRANSPARENT, opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } gfx::Rect track_quad_rect(bounds()); @@ -124,14 +123,13 @@ gfx::Rect opaque_rect(contents_opaque() ? scaled_track_quad_rect : gfx::Rect()); const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource(track_resource_id); TextureDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); quad->SetNew(shared_quad_state, scaled_track_quad_rect, opaque_rect, scaled_visible_track_quad_rect, track_resource_id, premultipled_alpha, uv_top_left, uv_bottom_right, SK_ColorTRANSPARENT, opacity, flipped, nearest_neighbor); + ValidateQuadResources(quad); } }
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 3fb0256..34a7599 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -208,6 +208,7 @@ visible_geometry_rect, texture_rect, texture_size, nearest_neighbor_, RGBA_8888, quad_content_rect, max_contents_scale, raster_source_); + ValidateQuadResources(quad); return; } @@ -305,15 +306,13 @@ append_quads_data->num_incomplete_tiles++; } - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - draw_info.resource_id()); TileDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>(); quad->SetNew(shared_quad_state, geometry_rect, opaque_rect, visible_geometry_rect, draw_info.resource_id(), texture_rect, draw_info.resource_size(), draw_info.contents_swizzled(), nearest_neighbor_); + ValidateQuadResources(quad); has_draw_quad = true; break; } @@ -322,6 +321,7 @@ render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>(); quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect, draw_info.solid_color(), false); + ValidateQuadResources(quad); has_draw_quad = true; break; } @@ -346,6 +346,7 @@ visible_geometry_rect, color, false); + ValidateQuadResources(quad); } if (geometry_rect.Intersects(scaled_viewport_for_tile_priority)) {
diff --git a/cc/layers/texture_layer_impl.cc b/cc/layers/texture_layer_impl.cc index 5df00b8e..a7775c90 100644 --- a/cc/layers/texture_layer_impl.cc +++ b/cc/layers/texture_layer_impl.cc
@@ -167,8 +167,6 @@ render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); ResourceProvider::ResourceId id = valid_texture_copy_ ? texture_copy_->id() : external_texture_resource_; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource(id); quad->SetNew(shared_quad_state, quad_rect, opaque_rect, @@ -181,6 +179,7 @@ vertex_opacity_, flipped_, nearest_neighbor_); + ValidateQuadResources(quad); } SimpleEnclosedRegion TextureLayerImpl::VisibleContentOpaqueRegion() const {
diff --git a/cc/layers/tiled_layer_impl.cc b/cc/layers/tiled_layer_impl.cc index f2b2b00..85b1115 100644 --- a/cc/layers/tiled_layer_impl.cc +++ b/cc/layers/tiled_layer_impl.cc
@@ -260,9 +260,6 @@ float tile_height = static_cast<float>(tiler_->tile_size().height()); gfx::Size texture_size(tile_width, tile_height); - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - tile->resource_id()); TileDrawQuad* quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>(); quad->SetNew(shared_quad_state, tile_rect, @@ -273,6 +270,7 @@ texture_size, tile->contents_swizzled(), false); + ValidateQuadResources(quad); } } }
diff --git a/cc/layers/ui_resource_layer_impl.cc b/cc/layers/ui_resource_layer_impl.cc index 5986bec..582ea9eb 100644 --- a/cc/layers/ui_resource_layer_impl.cc +++ b/cc/layers/ui_resource_layer_impl.cc
@@ -110,9 +110,6 @@ if (!resource) return; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource(resource); - static const bool flipped = false; static const bool nearest_neighbor = false; static const bool premultiplied_alpha = true; @@ -144,6 +141,7 @@ vertex_opacity_, flipped, nearest_neighbor); + ValidateQuadResources(quad); } const char* UIResourceLayerImpl::LayerTypeAsString() const {
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc index 5c36e99..5171971 100644 --- a/cc/layers/video_layer_impl.cc +++ b/cc/layers/video_layer_impl.cc
@@ -202,9 +202,6 @@ float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; bool flipped = false; bool nearest_neighbor = false; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - software_resources_[0]); TextureDrawQuad* texture_quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); texture_quad->SetNew(shared_quad_state, @@ -219,6 +216,7 @@ opacity, flipped, nearest_neighbor); + ValidateQuadResources(texture_quad); break; } case VideoFrameExternalResources::YUV_RESOURCE: { @@ -244,17 +242,6 @@ frame_->format(), media::VideoFrame::kAPlane, coded_size)); } - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - frame_resources_[0]); - layer_tree_impl()->resource_provider()->ValidateResource( - frame_resources_[1]); - layer_tree_impl()->resource_provider()->ValidateResource( - frame_resources_[2]); - if (frame_resources_.size() > 3) { - layer_tree_impl()->resource_provider()->ValidateResource( - frame_resources_[3]); - } gfx::RectF tex_coord_rect( tex_x_offset, tex_y_offset, tex_width_scale, tex_height_scale); YUVVideoDrawQuad* yuv_video_quad = @@ -264,6 +251,7 @@ tex_coord_rect, ya_tex_size, uv_tex_size, frame_resources_[0], frame_resources_[1], frame_resources_[2], frame_resources_.size() > 3 ? frame_resources_[3] : 0, color_space); + ValidateQuadResources(yuv_video_quad); break; } case VideoFrameExternalResources::RGB_RESOURCE: { @@ -276,9 +264,6 @@ float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; bool flipped = false; bool nearest_neighbor = false; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - frame_resources_[0]); TextureDrawQuad* texture_quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); texture_quad->SetNew(shared_quad_state, @@ -293,15 +278,13 @@ opacity, flipped, nearest_neighbor); + ValidateQuadResources(texture_quad); break; } case VideoFrameExternalResources::STREAM_TEXTURE_RESOURCE: { DCHECK_EQ(frame_resources_.size(), 1u); if (frame_resources_.size() < 1u) break; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - frame_resources_[0]); gfx::Transform scale; scale.Scale(tex_width_scale, tex_height_scale); StreamVideoDrawQuad* stream_video_quad = @@ -310,15 +293,13 @@ shared_quad_state, quad_rect, opaque_rect, visible_quad_rect, frame_resources_[0], scale * provider_client_impl_->StreamTextureMatrix()); + ValidateQuadResources(stream_video_quad); break; } case VideoFrameExternalResources::IO_SURFACE: { DCHECK_EQ(frame_resources_.size(), 1u); if (frame_resources_.size() < 1u) break; - // TODO(danakj): crbug.com/455931 - layer_tree_impl()->resource_provider()->ValidateResource( - frame_resources_[0]); IOSurfaceDrawQuad* io_surface_quad = render_pass->CreateAndAppendDrawQuad<IOSurfaceDrawQuad>(); io_surface_quad->SetNew(shared_quad_state, @@ -328,6 +309,7 @@ visible_rect.size(), frame_resources_[0], IOSurfaceDrawQuad::UNFLIPPED); + ValidateQuadResources(io_surface_quad); break; } #if defined(VIDEO_HOLE)
diff --git a/cc/output/compositor_frame_metadata.h b/cc/output/compositor_frame_metadata.h index e92a84d..999a6b4 100644 --- a/cc/output/compositor_frame_metadata.h +++ b/cc/output/compositor_frame_metadata.h
@@ -44,8 +44,7 @@ // Provides selection region updates relative to the current viewport. If the // selection is empty or otherwise unused, the bound types will indicate such. - ViewportSelectionBound selection_start; - ViewportSelectionBound selection_end; + ViewportSelection selection; std::vector<ui::LatencyInfo> latency_info;
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc index bfad4ba0c..269ec585 100644 --- a/cc/output/renderer_pixeltest.cc +++ b/cc/output/renderer_pixeltest.cc
@@ -1337,10 +1337,11 @@ pass_list.push_back(child_pass.Pass()); pass_list.push_back(root_pass.Pass()); + // This test blends slightly differently with the software renderer vs. the gl + // renderer so use a fuzzy comparator. EXPECT_TRUE(this->RunPixelTest( - &pass_list, - base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")), - ExactPixelComparator(true))); + &pass_list, base::FilePath(FILE_PATH_LITERAL("blue_yellow_alpha.png")), + FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false))); } TYPED_TEST(RendererPixelTest, FastPassFilterChain) { @@ -1408,10 +1409,12 @@ pass_list.push_back(child_pass.Pass()); pass_list.push_back(root_pass.Pass()); + // This test blends slightly differently with the software renderer vs. the gl + // renderer so use a fuzzy comparator. EXPECT_TRUE(this->RunPixelTest( &pass_list, base::FilePath(FILE_PATH_LITERAL("blue_yellow_filter_chain.png")), - ExactPixelComparator(true))); + FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false))); } TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) {
diff --git a/cc/output/viewport_selection_bound.h b/cc/output/viewport_selection_bound.h index 77298e7..2e4fe3c 100644 --- a/cc/output/viewport_selection_bound.h +++ b/cc/output/viewport_selection_bound.h
@@ -6,12 +6,14 @@ #define CC_OUTPUT_VIEWPORT_SELECTION_BOUND_H_ #include "cc/base/cc_export.h" +#include "cc/input/selection.h" #include "cc/input/selection_bound_type.h" #include "ui/gfx/geometry/point_f.h" namespace cc { // Marker for a selection end-point in (DIP) viewport coordinates. +// TODO(jdduke): Move this to ui/gfx and merge with ui::SelectionBound. struct CC_EXPORT ViewportSelectionBound { ViewportSelectionBound(); ~ViewportSelectionBound(); @@ -27,6 +29,8 @@ CC_EXPORT bool operator!=(const ViewportSelectionBound& lhs, const ViewportSelectionBound& rhs); +typedef Selection<ViewportSelectionBound> ViewportSelection; + } // namespace cc #endif // CC_OUTPUT_VIEWPORT_SELECTION_BOUND_H_
diff --git a/cc/resources/display_list_recording_source.cc b/cc/resources/display_list_recording_source.cc index 701db9bf..1c16aca2 100644 --- a/cc/resources/display_list_recording_source.cc +++ b/cc/resources/display_list_recording_source.cc
@@ -97,26 +97,24 @@ case RECORD_NORMALLY: // Already setup for normal recording. break; - case RECORD_WITH_SK_NULL_CANVAS: - // TODO(schenney): Remove this when DisplayList recording is the only - // option. For now, fall through and disable construction. case RECORD_WITH_PAINTING_DISABLED: - painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED; + painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED; break; case RECORD_WITH_CACHING_DISABLED: painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; break; + case RECORD_WITH_CONSTRUCTION_DISABLED: + painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED; + break; default: + // case RecordingSource::RECORD_WITH_SK_NULL_CANVAS should not be reached NOTREACHED(); } int repeat_count = 1; if (slow_down_raster_scale_factor_for_debug_ > 1) { repeat_count = slow_down_raster_scale_factor_for_debug_; - if (painting_control != - ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED) { - painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; - } + painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; } for (int i = 0; i < repeat_count; ++i) { const bool use_cached_picture = true;
diff --git a/cc/resources/drawing_display_item.cc b/cc/resources/drawing_display_item.cc index 91ab3fb..a37729f 100644 --- a/cc/resources/drawing_display_item.cc +++ b/cc/resources/drawing_display_item.cc
@@ -62,4 +62,8 @@ array->EndDictionary(); } +scoped_ptr<DrawingDisplayItem> DrawingDisplayItem::Clone() { + return Create(picture_); +} + } // namespace cc
diff --git a/cc/resources/drawing_display_item.h b/cc/resources/drawing_display_item.h index a3eef771..da302d8 100644 --- a/cc/resources/drawing_display_item.h +++ b/cc/resources/drawing_display_item.h
@@ -33,6 +33,8 @@ size_t PictureMemoryUsage() const override; void AsValueInto(base::trace_event::TracedValue* array) const override; + scoped_ptr<DrawingDisplayItem> Clone(); + protected: explicit DrawingDisplayItem(skia::RefPtr<SkPicture> picture);
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc index 9375d7e..cd46505 100644 --- a/cc/resources/picture.cc +++ b/cc/resources/picture.cc
@@ -199,13 +199,15 @@ // prevent the Blink GraphicsContext object from consuming any compute // time. canvas = skia::AdoptRef(SkCreateNullCanvas()); - painting_control = ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED; + painting_control = ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED; break; case RecordingSource::RECORD_WITH_CACHING_DISABLED: // This mode should give the same results as RECORD_NORMALLY. painting_control = ContentLayerClient::DISPLAY_LIST_CACHING_DISABLED; break; default: + // case RecordingSource::RECORD_WITH_CONSTRUCTION_DISABLED should + // not be reached NOTREACHED(); }
diff --git a/cc/resources/picture_unittest.cc b/cc/resources/picture_unittest.cc index b53765c..488d7bf 100644 --- a/cc/resources/picture_unittest.cc +++ b/cc/resources/picture_unittest.cc
@@ -160,7 +160,7 @@ Picture::Create(layer_rect, &content_layer_client, tile_grid_size, false, RecordingSource::RECORD_WITH_PAINTING_DISABLED); EXPECT_TRUE(content_layer_client.last_canvas() != NULL); - EXPECT_EQ(ContentLayerClient::DISPLAY_LIST_CONSTRUCTION_DISABLED, + EXPECT_EQ(ContentLayerClient::DISPLAY_LIST_PAINTING_DISABLED, content_layer_client.last_painting_control()); EXPECT_TRUE(picture.get()); @@ -172,7 +172,9 @@ content_layer_client.last_painting_control()); EXPECT_TRUE(picture.get()); - EXPECT_EQ(4, RecordingSource::RECORDING_MODE_COUNT); + // RECORD_WITH_CONSTRUCTION_DISABLED is not supported for Picture. + + EXPECT_EQ(5, RecordingSource::RECORDING_MODE_COUNT); } } // namespace
diff --git a/cc/resources/recording_source.h b/cc/resources/recording_source.h index ef8c0334..a95ba73a 100644 --- a/cc/resources/recording_source.h +++ b/cc/resources/recording_source.h
@@ -18,11 +18,14 @@ class CC_EXPORT RecordingSource { public: + // TODO(schenney) Remove RECORD_WITH_SK_NULL_CANVAS when we no longer + // support a non-Slimming Paint path. enum RecordingMode { RECORD_NORMALLY, RECORD_WITH_SK_NULL_CANVAS, RECORD_WITH_PAINTING_DISABLED, RECORD_WITH_CACHING_DISABLED, + RECORD_WITH_CONSTRUCTION_DISABLED, RECORDING_MODE_COUNT, // Must be the last entry. };
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc index 7987f81..522150cf 100644 --- a/cc/resources/resource_provider.cc +++ b/cc/resources/resource_provider.cc
@@ -863,10 +863,9 @@ ResourceProvider::Resource* ResourceProvider::GetResource(ResourceId id) { DCHECK(thread_checker_.CalledOnValidThread()); - // TODO(danakj): crbug.com/455931 - CHECK(id); + DCHECK(id); ResourceMap::iterator it = resources_.find(id); - CHECK(it != resources_.end()); + DCHECK(it != resources_.end()); return &it->second; } @@ -2044,11 +2043,10 @@ return active_unit; } -void ResourceProvider::ValidateResource(ResourceId id) { +void ResourceProvider::ValidateResource(ResourceId id) const { DCHECK(thread_checker_.CalledOnValidThread()); - CHECK(id); - ResourceMap::iterator it = resources_.find(id); - CHECK(it != resources_.end()); + DCHECK(id); + DCHECK(resources_.find(id) != resources_.end()); } GLES2Interface* ResourceProvider::ContextGL() const {
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h index 70b7fc7..ea9588a2 100644 --- a/cc/resources/resource_provider.h +++ b/cc/resources/resource_provider.h
@@ -434,7 +434,7 @@ OutputSurface* output_surface() { return output_surface_; } - void ValidateResource(ResourceId id); + void ValidateResource(ResourceId id) const; private: struct Resource {
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc index 2288169e..5ffd59c0 100644 --- a/cc/scheduler/scheduler.cc +++ b/cc/scheduler/scheduler.cc
@@ -493,7 +493,26 @@ } void Scheduler::BeginImplFrameWithDeadline(const BeginFrameArgs& args) { - BeginImplFrame(args); + bool main_thread_is_in_high_latency_mode = + state_machine_.MainThreadIsInHighLatencyMode(); + TRACE_EVENT2("cc,benchmark", "Scheduler::BeginImplFrame", "args", + args.AsValue(), "main_thread_is_high_latency", + main_thread_is_in_high_latency_mode); + TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), + "MainThreadLatency", main_thread_is_in_high_latency_mode); + + advance_commit_state_task_.Cancel(); + + begin_impl_frame_args_ = args; + begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); + + if (!state_machine_.impl_latency_takes_priority() && + main_thread_is_in_high_latency_mode && + CanCommitAndActivateBeforeDeadline()) { + state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); + } + + BeginImplFrame(); // The deadline will be scheduled in ProcessScheduledActions. state_machine_.OnBeginImplFrameDeadlinePending(); @@ -501,7 +520,10 @@ } void Scheduler::BeginImplFrameSynchronous(const BeginFrameArgs& args) { - BeginImplFrame(args); + TRACE_EVENT1("cc,benchmark", "Scheduler::BeginImplFrame", "args", + args.AsValue()); + begin_impl_frame_args_ = args; + BeginImplFrame(); FinishImplFrame(); } @@ -516,33 +538,12 @@ // BeginImplFrame starts a compositor frame that will wait up until a deadline // for a BeginMainFrame+activation to complete before it times out and draws // any asynchronous animation and scroll/pinch updates. -void Scheduler::BeginImplFrame(const BeginFrameArgs& args) { - bool main_thread_is_in_high_latency_mode = - state_machine_.MainThreadIsInHighLatencyMode(); - TRACE_EVENT2("cc,benchmark", - "Scheduler::BeginImplFrame", - "args", - args.AsValue(), - "main_thread_is_high_latency", - main_thread_is_in_high_latency_mode); - TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"), - "MainThreadLatency", - main_thread_is_in_high_latency_mode); +void Scheduler::BeginImplFrame() { DCHECK_EQ(state_machine_.begin_impl_frame_state(), SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE); DCHECK(!BeginImplFrameDeadlinePending()); DCHECK(state_machine_.HasInitializedOutputSurface()); - - advance_commit_state_task_.Cancel(); - - begin_impl_frame_args_ = args; - begin_impl_frame_args_.deadline -= client_->DrawDurationEstimate(); - - if (!state_machine_.impl_latency_takes_priority() && - main_thread_is_in_high_latency_mode && - CanCommitAndActivateBeforeDeadline()) { - state_machine_.SetSkipNextBeginMainFrameToReduceLatency(); - } + DCHECK(advance_commit_state_task_.IsCancelled()); state_machine_.OnBeginImplFrame(); devtools_instrumentation::DidBeginFrame(layer_tree_host_id_);
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h index 4307b21..0076b4ab4 100644 --- a/cc/scheduler/scheduler.h +++ b/cc/scheduler/scheduler.h
@@ -236,7 +236,7 @@ void BeginRetroFrame(); void BeginImplFrameWithDeadline(const BeginFrameArgs& args); void BeginImplFrameSynchronous(const BeginFrameArgs& args); - void BeginImplFrame(const BeginFrameArgs& args); + void BeginImplFrame(); void FinishImplFrame(); void OnBeginImplFrameDeadline(); void PollToAdvanceCommitState();
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc index 1a444c9..54b78ddd 100644 --- a/cc/scheduler/scheduler_state_machine.cc +++ b/cc/scheduler/scheduler_state_machine.cc
@@ -388,10 +388,6 @@ } bool SchedulerStateMachine::CouldSendBeginMainFrame() const { - // Do not send begin main frame too many times in a single frame. - if (send_begin_main_frame_funnel_) - return false; - if (!needs_commit_) return false; @@ -410,6 +406,10 @@ if (!CouldSendBeginMainFrame()) return false; + // Do not send begin main frame too many times in a single frame. + if (send_begin_main_frame_funnel_) + return false; + // Only send BeginMainFrame when there isn't another commit pending already. if (commit_state_ != COMMIT_STATE_IDLE) return false; @@ -713,6 +713,11 @@ invalidate_output_surface_funnel_ = true; last_frame_number_invalidate_output_surface_performed_ = current_frame_number_; + + // The synchronous compositor makes no guarantees about a draw coming in after + // an invalidate so clear any flags that would cause the compositor's pipeline + // to stall. + active_tree_needs_first_draw_ = false; // blocks commit if true } void SchedulerStateMachine::SetSkipNextBeginMainFrameToReduceLatency() {
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc index c643726..c03c79b 100644 --- a/cc/scheduler/scheduler_unittest.cc +++ b/cc/scheduler/scheduler_unittest.cc
@@ -2405,14 +2405,12 @@ client_->Reset(); } -TEST_F(SchedulerTest, UsingSynchronousCompositor) { +TEST_F(SchedulerTest, SynchronousCompositorAnimation) { scheduler_settings_.using_synchronous_renderer_compositor = true; scheduler_settings_.use_external_begin_frame_source = true; scheduler_settings_.impl_side_painting = true; SetUpScheduler(true); - // Compositor thread initiated input/animation. - // -------------------------------------------- scheduler_->SetNeedsAnimate(); EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); client_->Reset(); @@ -2458,9 +2456,14 @@ EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); +} - // Android onDraw after idle. - // -------------------------- +TEST_F(SchedulerTest, SynchronousCompositorOnDrawDuringIdle) { + scheduler_settings_.using_synchronous_renderer_compositor = true; + scheduler_settings_.use_external_begin_frame_source = true; + scheduler_settings_.impl_side_painting = true; + SetUpScheduler(true); + scheduler_->SetNeedsRedraw(); scheduler_->OnDrawForOutputSurface(); EXPECT_ACTION("SetNeedsBeginFrames(true)", client_, 0, 3); @@ -2476,9 +2479,14 @@ EXPECT_ACTION("SendBeginMainFrameNotExpectedSoon", client_, 2, 3); EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); client_->Reset(); +} - // Main thread initiated activity. - // ------------------------------- +TEST_F(SchedulerTest, SynchronousCompositorCommit) { + scheduler_settings_.using_synchronous_renderer_compositor = true; + scheduler_settings_.use_external_begin_frame_source = true; + scheduler_settings_.impl_side_painting = true; + SetUpScheduler(true); + scheduler_->SetNeedsCommit(); EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); client_->Reset(); @@ -2531,6 +2539,54 @@ client_->Reset(); } +TEST_F(SchedulerTest, SynchronousCompositorDoubleCommitWithoutDraw) { + scheduler_settings_.using_synchronous_renderer_compositor = true; + scheduler_settings_.use_external_begin_frame_source = true; + scheduler_settings_.impl_side_painting = true; + SetUpScheduler(true); + + scheduler_->SetNeedsCommit(); + EXPECT_SINGLE_ACTION("SetNeedsBeginFrames(true)", client_); + client_->Reset(); + + // Next vsync. + AdvanceFrame(); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 2); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 1, 2); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + client_->Reset(); + + scheduler_->NotifyBeginMainFrameStarted(); + EXPECT_NO_ACTION(client_); + + scheduler_->NotifyReadyToCommit(); + EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); + client_->Reset(); + + scheduler_->NotifyReadyToActivate(); + EXPECT_SINGLE_ACTION("ScheduledActionActivateSyncTree", client_); + client_->Reset(); + + // Ask for another commit. + scheduler_->SetNeedsCommit(); + + AdvanceFrame(); + EXPECT_ACTION("WillBeginImplFrame", client_, 0, 4); + EXPECT_ACTION("ScheduledActionAnimate", client_, 1, 4); + EXPECT_ACTION("ScheduledActionSendBeginMainFrame", client_, 2, 4); + EXPECT_ACTION("ScheduledActionInvalidateOutputSurface", client_, 3, 4); + EXPECT_FALSE(scheduler_->BeginImplFrameDeadlinePending()); + client_->Reset(); + + scheduler_->NotifyBeginMainFrameStarted(); + EXPECT_NO_ACTION(client_); + + // Allow new commit even though previous commit hasn't been drawn. + scheduler_->NotifyReadyToCommit(); + EXPECT_SINGLE_ACTION("ScheduledActionCommit", client_); + client_->Reset(); +} + TEST_F(SchedulerTest, AuthoritativeVSyncInterval) { SetUpScheduler(true);
diff --git a/cc/test/fake_picture_layer_tiling_client.cc b/cc/test/fake_picture_layer_tiling_client.cc index cc308e5..41f27c5 100644 --- a/cc/test/fake_picture_layer_tiling_client.cc +++ b/cc/test/fake_picture_layer_tiling_client.cc
@@ -17,20 +17,21 @@ twin_set_(nullptr), twin_tiling_(nullptr), recycled_twin_tiling_(nullptr), - max_tile_priority_bin_(TilePriority::NOW) { + max_tile_priority_bin_(TilePriority::NOW), + tree_(ACTIVE_TREE) { } FakePictureLayerTilingClient::FakePictureLayerTilingClient( ResourceProvider* resource_provider) - : resource_pool_( - ResourcePool::Create(resource_provider, GL_TEXTURE_2D)), - tile_manager_(new FakeTileManager( - &tile_manager_client_, resource_pool_.get())), + : resource_pool_(ResourcePool::Create(resource_provider, GL_TEXTURE_2D)), + tile_manager_( + new FakeTileManager(&tile_manager_client_, resource_pool_.get())), pile_(FakePicturePileImpl::CreateInfiniteFilledPile()), twin_set_(nullptr), twin_tiling_(nullptr), recycled_twin_tiling_(nullptr), - max_tile_priority_bin_(TilePriority::NOW) { + max_tile_priority_bin_(TilePriority::NOW), + tree_(ACTIVE_TREE) { } FakePictureLayerTilingClient::~FakePictureLayerTilingClient() {
diff --git a/cc/trees/draw_property_utils.cc b/cc/trees/draw_property_utils.cc index 83b91f4..50b91cb3 100644 --- a/cc/trees/draw_property_utils.cc +++ b/cc/trees/draw_property_utils.cc
@@ -9,6 +9,7 @@ #include "cc/base/math_util.h" #include "cc/layers/layer.h" #include "cc/layers/layer_impl.h" +#include "cc/trees/layer_tree_impl.h" #include "cc/trees/property_tree.h" #include "cc/trees/property_tree_builder.h" #include "ui/gfx/geometry/rect_conversions.h" @@ -157,48 +158,25 @@ } template <typename LayerType> -static bool IsLayerBackFaceExposed(LayerType* layer, - const TransformTree& tree) { - if (!TransformToScreenIsKnown(layer, tree)) - return false; - if (LayerIsInExisting3DRenderingContext(layer)) - return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible(); - return layer->transform().IsBackFaceVisible(); -} - -template <typename LayerType> -static bool IsSurfaceBackFaceExposed(LayerType* layer, - const TransformTree& tree) { - if (!TransformToScreenIsKnown(layer, tree)) - return false; - if (LayerIsInExisting3DRenderingContext(layer)) - return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible(); - - if (IsRootLayerOfNewRenderingContext(layer)) - return layer->transform().IsBackFaceVisible(); - - // If the render_surface is not part of a new or existing rendering context, - // then the layers that contribute to this surface will decide back-face - // visibility for themselves. - return false; -} - -template <typename LayerType> static bool HasSingularTransform(LayerType* layer, const TransformTree& tree) { const TransformNode* node = tree.Node(layer->transform_tree_index()); return !node->data.is_invertible || !node->data.ancestors_are_invertible; } template <typename LayerType> -static bool IsBackFaceInvisible(LayerType* layer, const TransformTree& tree) { - LayerType* backface_test_layer = layer; - if (layer->use_parent_backface_visibility()) { - DCHECK(layer->parent()); - DCHECK(!layer->parent()->use_parent_backface_visibility()); - backface_test_layer = layer->parent(); - } - return !backface_test_layer->double_sided() && - IsLayerBackFaceExposed(backface_test_layer, tree); +static bool IsLayerBackFaceVisible(LayerType* layer, + const TransformTree& tree) { + // The current W3C spec on CSS transforms says that backface visibility should + // be determined differently depending on whether the layer is in a "3d + // rendering context" or not. For Chromium code, we can determine whether we + // are in a 3d rendering context by checking if the parent preserves 3d. + + if (LayerIsInExisting3DRenderingContext(layer)) + return DrawTransformFromPropertyTrees(layer, tree).IsBackFaceVisible(); + + // In this case, either the layer establishes a new 3d rendering context, or + // is not in a 3d rendering context at all. + return layer->transform().IsBackFaceVisible(); } template <typename LayerType> @@ -208,21 +186,126 @@ return node->data.to_screen_is_animated; } -template <typename LayerType> -static bool IsInvisibleDueToTransform(LayerType* layer, - const TransformTree& tree) { - if (IsAnimatingTransformToScreen(layer, tree)) - return false; - return HasSingularTransform(layer, tree) || IsBackFaceInvisible(layer, tree); +static inline bool TransformToScreenIsKnown(Layer* layer, + const TransformTree& tree) { + return !IsAnimatingTransformToScreen(layer, tree); } -bool LayerIsInvisible(const Layer* layer) { +static inline bool TransformToScreenIsKnown(LayerImpl* layer, + const TransformTree& tree) { + return true; +} + +template <typename LayerType> +static bool HasInvertibleOrAnimatedTransform(LayerType* layer) { + return layer->transform_is_invertible() || layer->TransformIsAnimating(); +} + +static inline bool SubtreeShouldBeSkipped(LayerImpl* layer, + bool layer_is_drawn) { + // If the layer transform is not invertible, it should not be drawn. + // TODO(ajuma): Correctly process subtrees with singular transform for the + // case where we may animate to a non-singular transform and wish to + // pre-raster. + if (!HasInvertibleOrAnimatedTransform(layer)) + return true; + + // When we need to do a readback/copy of a layer's output, we can not skip + // it or any of its ancestors. + if (layer->draw_properties().layer_or_descendant_has_copy_request) + return false; + + // We cannot skip the the subtree if a descendant has a wheel or touch handler + // or the hit testing code will break (it requires fresh transforms, etc). + if (layer->draw_properties().layer_or_descendant_has_input_handler) + return false; + + // If the layer is not drawn, then skip it and its subtree. + if (!layer_is_drawn) + return true; + + // If layer is on the pending tree and opacity is being animated then + // this subtree can't be skipped as we need to create, prioritize and + // include tiles for this layer when deciding if tree can be activated. + if (layer->layer_tree_impl()->IsPendingTree() && layer->OpacityIsAnimating()) + return false; + + // The opacity of a layer always applies to its children (either implicitly + // via a render surface or explicitly if the parent preserves 3D), so the + // entire subtree can be skipped if this layer is fully transparent. + return !layer->opacity(); +} + +static inline bool SubtreeShouldBeSkipped(Layer* layer, bool layer_is_drawn) { + // If the layer transform is not invertible, it should not be drawn. + if (!layer->transform_is_invertible() && !layer->TransformIsAnimating()) + return true; + + // When we need to do a readback/copy of a layer's output, we can not skip + // it or any of its ancestors. + if (layer->draw_properties().layer_or_descendant_has_copy_request) + return false; + + // We cannot skip the the subtree if a descendant has a wheel or touch handler + // or the hit testing code will break (it requires fresh transforms, etc). + if (layer->draw_properties().layer_or_descendant_has_input_handler) + return false; + + // If the layer is not drawn, then skip it and its subtree. + if (!layer_is_drawn) + return true; + + // If the opacity is being animated then the opacity on the main thread is + // unreliable (since the impl thread may be using a different opacity), so it + // should not be trusted. + // In particular, it should not cause the subtree to be skipped. + // Similarly, for layers that might animate opacity using an impl-only + // animation, their subtree should also not be skipped. return !layer->opacity() && !layer->OpacityIsAnimating() && !layer->OpacityCanAnimateOnImplThread(); } -bool LayerIsInvisible(const LayerImpl* layer) { - return !layer->opacity() && !layer->OpacityIsAnimating(); +template <typename LayerType> +static bool LayerShouldBeSkipped(LayerType* layer, + bool layer_is_drawn, + const TransformTree& tree) { + // Layers can be skipped if any of these conditions are met. + // - is not drawn due to it or one of its ancestors being hidden (or having + // no copy requests). + // - does not draw content. + // - is transparent. + // - has empty bounds + // - the layer is not double-sided, but its back face is visible. + // + // Some additional conditions need to be computed at a later point after the + // recursion is finished. + // - the intersection of render_surface content and layer clip_rect is empty + // - the visible_content_rect is empty + // + // Note, if the layer should not have been drawn due to being fully + // transparent, we would have skipped the entire subtree and never made it + // into this function, so it is safe to omit this check here. + if (!layer_is_drawn) + return true; + + if (!layer->DrawsContent() || layer->bounds().IsEmpty()) + return true; + + LayerType* backface_test_layer = layer; + if (layer->use_parent_backface_visibility()) { + DCHECK(layer->parent()); + DCHECK(!layer->parent()->use_parent_backface_visibility()); + backface_test_layer = layer->parent(); + } + + // The layer should not be drawn if (1) it is not double-sided and (2) the + // back of the layer is known to be facing the screen. + if (!backface_test_layer->double_sided() && + TransformToScreenIsKnown(backface_test_layer, tree) && + IsLayerBackFaceVisible(backface_test_layer, tree)) + return true; + + return false; } template <typename LayerType> @@ -230,24 +313,15 @@ const TransformTree& tree, bool subtree_is_visible_from_ancestor, std::vector<LayerType*>* layers_to_update) { - const bool layer_is_invisible = LayerIsInvisible(layer); - const bool layer_is_backfacing = - (layer->has_render_surface() && !layer->double_sided() && - IsSurfaceBackFaceExposed(layer, tree)); - - const bool subtree_is_invisble = layer_is_invisible || layer_is_backfacing; - if (subtree_is_invisble) - return; - bool layer_is_drawn = layer->HasCopyRequest() || (subtree_is_visible_from_ancestor && !layer->hide_layer_and_subtree()); - if (layer_is_drawn && layer->DrawsContent()) { - const bool visible = !IsInvisibleDueToTransform(layer, tree); - if (visible) - layers_to_update->push_back(layer); - } + if (layer->parent() && SubtreeShouldBeSkipped(layer, layer_is_drawn)) + return; + + if (!LayerShouldBeSkipped(layer, layer_is_drawn, tree)) + layers_to_update->push_back(layer); for (size_t i = 0; i < layer->children().size(); ++i) { FindLayersThatNeedVisibleRects(layer->child_at(i), tree, layer_is_drawn,
diff --git a/cc/trees/latency_info_swap_promise_monitor.cc b/cc/trees/latency_info_swap_promise_monitor.cc index 2b56f68c..c63ac5b 100644 --- a/cc/trees/latency_info_swap_promise_monitor.cc +++ b/cc/trees/latency_info_swap_promise_monitor.cc
@@ -83,7 +83,7 @@ return; ui::LatencyInfo new_latency; new_latency.AddLatencyNumberWithTraceName( - ui::INPUT_EVENT_LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT, 0, + ui::LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT, 0, new_sequence_number, "ScrollUpdate"); new_latency.CopyLatencyFrom( *latency_,
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 6dc3e96..53aea757 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -325,7 +325,7 @@ sync_tree->ClearViewportLayers(); } - sync_tree->RegisterSelection(selection_start_, selection_end_); + sync_tree->RegisterSelection(selection_); sync_tree->PushPageScaleFromMainThread( page_scale_factor_, min_page_scale_factor_, max_page_scale_factor_); @@ -1222,13 +1222,11 @@ outer_viewport_scroll_layer_ = outer_viewport_scroll_layer; } -void LayerTreeHost::RegisterSelection(const LayerSelectionBound& start, - const LayerSelectionBound& end) { - if (selection_start_ == start && selection_end_ == end) +void LayerTreeHost::RegisterSelection(const LayerSelection& selection) { + if (selection_ == selection) return; - selection_start_ = start; - selection_end_ = end; + selection_ = selection; SetNeedsCommit(); }
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 742578a..bd53413 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -182,8 +182,7 @@ return outer_viewport_scroll_layer_.get(); } - void RegisterSelection(const LayerSelectionBound& start, - const LayerSelectionBound& end); + void RegisterSelection(const LayerSelection& selection); const LayerTreeSettings& settings() const { return settings_; } @@ -444,8 +443,7 @@ scoped_refptr<Layer> inner_viewport_scroll_layer_; scoped_refptr<Layer> outer_viewport_scroll_layer_; - LayerSelectionBound selection_start_; - LayerSelectionBound selection_end_; + LayerSelection selection_; SharedBitmapManager* shared_bitmap_manager_; gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
diff --git a/cc/trees/layer_tree_host_common.cc b/cc/trees/layer_tree_host_common.cc index 31f64d6..6b2c5b6 100644 --- a/cc/trees/layer_tree_host_common.cc +++ b/cc/trees/layer_tree_host_common.cc
@@ -2480,7 +2480,7 @@ for (int row = 0; row < 4; row++) { for (int col = 0; col < 4; col++) { - static const float delta = + const float delta = std::abs(a.matrix().get(row, col) - b.matrix().get(row, col)); const float tolerance = col == 3 && row < 3 ? translation_tolerance : component_tolerance;
diff --git a/cc/trees/layer_tree_host_common.h b/cc/trees/layer_tree_host_common.h index 2d50b0a..111c3cc 100644 --- a/cc/trees/layer_tree_host_common.h +++ b/cc/trees/layer_tree_host_common.h
@@ -73,7 +73,7 @@ LayerType* root_layer; gfx::Size device_viewport_size; - const gfx::Transform& device_transform; + gfx::Transform device_transform; float device_scale_factor; float page_scale_factor; const LayerType* page_scale_application_layer; @@ -104,7 +104,6 @@ RenderSurfaceLayerListType* render_surface_layer_list); private: - const gfx::Transform identity_transform_; PropertyTrees temporary_property_trees; }; @@ -280,7 +279,7 @@ : CalcDrawPropsInputs<LayerType, RenderSurfaceLayerListType>( root_layer, device_viewport_size, - identity_transform_, + gfx::Transform(), 1.f, 1.f, NULL,
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc index e484b42..43aa410 100644 --- a/cc/trees/layer_tree_host_common_unittest.cc +++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -21,6 +21,9 @@ #include "cc/output/copy_output_request.h" #include "cc/output/copy_output_result.h" #include "cc/test/animation_test_common.h" +#include "cc/test/fake_content_layer.h" +#include "cc/test/fake_content_layer_client.h" +#include "cc/test/fake_content_layer_impl.h" #include "cc/test/fake_impl_proxy.h" #include "cc/test/fake_layer_tree_host.h" #include "cc/test/fake_layer_tree_host_impl.h" @@ -9221,5 +9224,250 @@ EXPECT_EQ(gfx::Rect(5, 5, 5, 5), child->visible_rect_from_property_trees()); } +TEST_F(LayerTreeHostCommonTest, UpdateScrollChildPosition) { + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<LayerWithForcedDrawsContent> scroll_parent = + make_scoped_refptr(new LayerWithForcedDrawsContent); + scoped_refptr<LayerWithForcedDrawsContent> scroll_child = + make_scoped_refptr(new LayerWithForcedDrawsContent); + + root->AddChild(scroll_child); + root->AddChild(scroll_parent); + scroll_child->SetScrollParent(scroll_parent.get()); + scroll_parent->SetScrollClipLayerId(root->id()); + + scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); + host->SetRootLayer(root); + + gfx::Transform identity_transform; + gfx::Transform scale; + scale.Scale(2.f, 2.f); + SetLayerPropertiesForTesting(root.get(), identity_transform, gfx::Point3F(), + gfx::PointF(), gfx::Size(50, 50), true, false); + SetLayerPropertiesForTesting(scroll_child.get(), scale, gfx::Point3F(), + gfx::PointF(), gfx::Size(40, 40), true, false); + SetLayerPropertiesForTesting(scroll_parent.get(), identity_transform, + gfx::Point3F(), gfx::PointF(), gfx::Size(30, 30), + true, false); + + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(25, 25), + scroll_child->visible_rect_from_property_trees()); + + scroll_child->SetPosition(gfx::PointF(0, -10.f)); + scroll_parent->SetScrollOffset(gfx::ScrollOffset(0.f, 10.f)); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 5, 25, 25), + scroll_child->visible_rect_from_property_trees()); +} + +static void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) { +} + +TEST_F(LayerTreeHostCommonTest, SkippingSubtreeMain) { + gfx::Transform identity; + FakeContentLayerClient client; + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<LayerWithForcedDrawsContent> child = + make_scoped_refptr(new LayerWithForcedDrawsContent()); + scoped_refptr<LayerWithForcedDrawsContent> grandchild = + make_scoped_refptr(new LayerWithForcedDrawsContent()); + scoped_refptr<FakeContentLayer> greatgrandchild( + FakeContentLayer::Create(&client)); + SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), true, false); + SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false); + SetLayerPropertiesForTesting(grandchild.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false); + SetLayerPropertiesForTesting(greatgrandchild.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false); + + root->AddChild(child); + child->AddChild(grandchild); + grandchild->AddChild(greatgrandchild); + + scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); + host->SetRootLayer(root); + + // Check the non-skipped case. + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees()); + + // Now we will reset the visible rect from property trees for the grandchild, + // and we will configure |child| in several ways that should force the subtree + // to be skipped. The visible content rect for |grandchild| should, therefore, + // remain empty. + grandchild->set_visible_rect_from_property_trees(gfx::Rect()); + gfx::Transform singular; + singular.matrix().set(0, 0, 0); + + child->SetTransform(singular); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees()); + child->SetTransform(identity); + + child->SetHideLayerAndSubtree(true); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees()); + child->SetHideLayerAndSubtree(false); + + child->SetOpacity(0.f); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees()); + + // Now, even though child has zero opacity, we will configure |grandchild| and + // |greatgrandchild| in several ways that should force the subtree to be + // processed anyhow. + grandchild->SetTouchEventHandlerRegion(Region(gfx::Rect(0, 0, 10, 10))); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees()); + grandchild->set_visible_rect_from_property_trees(gfx::Rect()); + grandchild->SetTouchEventHandlerRegion(Region()); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), grandchild->visible_rect_from_property_trees()); + grandchild->set_visible_rect_from_property_trees(gfx::Rect()); + + greatgrandchild->RequestCopyOfOutput( + CopyOutputRequest::CreateBitmapRequest(base::Bind(&CopyOutputCallback))); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(10, 10), grandchild->visible_rect_from_property_trees()); +} + +TEST_F(LayerTreeHostCommonTest, SkippingSubtreeImpl) { + FakeImplProxy proxy; + TestSharedBitmapManager shared_bitmap_manager; + FakeLayerTreeHostImpl host_impl(&proxy, &shared_bitmap_manager, nullptr); + + gfx::Transform identity; + scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl.active_tree(), 1); + scoped_ptr<LayerImpl> child = LayerImpl::Create(host_impl.active_tree(), 2); + scoped_ptr<LayerImpl> grandchild = + LayerImpl::Create(host_impl.active_tree(), 3); + + scoped_ptr<FakeContentLayerImpl> greatgrandchild( + FakeContentLayerImpl::Create(host_impl.active_tree(), 4)); + + child->SetDrawsContent(true); + grandchild->SetDrawsContent(true); + greatgrandchild->SetDrawsContent(true); + + SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), true, false, + true); + SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false, + false); + SetLayerPropertiesForTesting(grandchild.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false, + false); + SetLayerPropertiesForTesting(greatgrandchild.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false, + true); + + LayerImpl* child_ptr = child.get(); + LayerImpl* grandchild_ptr = grandchild.get(); + LayerImpl* greatgrandchild_ptr = greatgrandchild.get(); + + grandchild->AddChild(greatgrandchild.Pass()); + child->AddChild(grandchild.Pass()); + root->AddChild(child.Pass()); + + // Check the non-skipped case. + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(10, 10), + grandchild_ptr->visible_rect_from_property_trees()); + + // Now we will reset the visible rect from property trees for the grandchild, + // and we will configure |child| in several ways that should force the subtree + // to be skipped. The visible content rect for |grandchild| should, therefore, + // remain empty. + grandchild_ptr->set_visible_rect_from_property_trees(gfx::Rect()); + gfx::Transform singular; + singular.matrix().set(0, 0, 0); + + child_ptr->SetTransform(singular); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), + grandchild_ptr->visible_rect_from_property_trees()); + child_ptr->SetTransform(identity); + + child_ptr->SetHideLayerAndSubtree(true); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), + grandchild_ptr->visible_rect_from_property_trees()); + child_ptr->SetHideLayerAndSubtree(false); + + child_ptr->SetOpacity(0.f); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), + grandchild_ptr->visible_rect_from_property_trees()); + + // Now, even though child has zero opacity, we will configure |grandchild| and + // |greatgrandchild| in several ways that should force the subtree to be + // processed anyhow. + grandchild_ptr->SetTouchEventHandlerRegion(Region(gfx::Rect(0, 0, 10, 10))); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(10, 10), + grandchild_ptr->visible_rect_from_property_trees()); + grandchild_ptr->set_visible_rect_from_property_trees(gfx::Rect()); + grandchild_ptr->SetTouchEventHandlerRegion(Region()); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), + grandchild_ptr->visible_rect_from_property_trees()); + grandchild_ptr->set_visible_rect_from_property_trees(gfx::Rect()); + + ScopedPtrVector<CopyOutputRequest> requests; + requests.push_back(CopyOutputRequest::CreateEmptyRequest()); + + greatgrandchild_ptr->PassCopyRequests(&requests); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(10, 10), + grandchild_ptr->visible_rect_from_property_trees()); +} + +TEST_F(LayerTreeHostCommonTest, SkippingLayer) { + gfx::Transform identity; + FakeContentLayerClient client; + scoped_refptr<Layer> root = Layer::Create(); + scoped_refptr<LayerWithForcedDrawsContent> child = + make_scoped_refptr(new LayerWithForcedDrawsContent()); + SetLayerPropertiesForTesting(root.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(100, 100), true, false); + SetLayerPropertiesForTesting(child.get(), identity, gfx::Point3F(), + gfx::PointF(), gfx::Size(10, 10), true, false); + root->AddChild(child); + + scoped_ptr<FakeLayerTreeHost> host(CreateFakeLayerTreeHost()); + host->SetRootLayer(root); + + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(10, 10), child->visible_rect_from_property_trees()); + child->set_visible_rect_from_property_trees(gfx::Rect()); + + child->SetHideLayerAndSubtree(true); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), child->visible_rect_from_property_trees()); + child->SetHideLayerAndSubtree(false); + + child->SetBounds(gfx::Size()); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), child->visible_rect_from_property_trees()); + child->SetBounds(gfx::Size(10, 10)); + + gfx::Transform rotate; + child->SetDoubleSided(false); + rotate.RotateAboutXAxis(180.f); + child->SetTransform(rotate); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), child->visible_rect_from_property_trees()); + child->SetDoubleSided(true); + child->SetTransform(identity); + + child->SetOpacity(0.f); + ExecuteCalculateDrawProperties(root.get()); + EXPECT_EQ(gfx::Rect(0, 0), child->visible_rect_from_property_trees()); +} + } // namespace } // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 7f40c98..1b1f6fc 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -1435,8 +1435,7 @@ metadata.location_bar_content_translation = gfx::Vector2dF(0.f, top_controls_manager_->ContentTopOffset()); - active_tree_->GetViewportSelection(&metadata.selection_start, - &metadata.selection_end); + active_tree_->GetViewportSelection(&metadata.selection); LayerImpl* root_layer_for_overflow = OuterViewportScrollLayer() ? OuterViewportScrollLayer()
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index be18719..073d5ae 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -6525,23 +6525,21 @@ // Ensure the default frame selection bounds are empty. FakeOutputSurface* fake_output_surface = static_cast<FakeOutputSurface*>(host_impl_->output_surface()); - const ViewportSelectionBound& selection_start_before = - fake_output_surface->last_sent_frame().metadata.selection_start; - const ViewportSelectionBound& selection_end_before = - fake_output_surface->last_sent_frame().metadata.selection_end; - EXPECT_EQ(ViewportSelectionBound(), selection_start_before); - EXPECT_EQ(ViewportSelectionBound(), selection_end_before); + const ViewportSelection& selection_before = + fake_output_surface->last_sent_frame().metadata.selection; + EXPECT_EQ(ViewportSelectionBound(), selection_before.start); + EXPECT_EQ(ViewportSelectionBound(), selection_before.end); // Plumb the layer-local selection bounds. gfx::PointF selection_top(5, 0); gfx::PointF selection_bottom(5, 5); - LayerSelectionBound start, end; - start.type = SELECTION_BOUND_CENTER; - start.layer_id = root_layer_id; - start.edge_bottom = selection_bottom; - start.edge_top = selection_top; - end = start; - host_impl_->active_tree()->RegisterSelection(start, end); + LayerSelection selection; + selection.start.type = SELECTION_BOUND_CENTER; + selection.start.layer_id = root_layer_id; + selection.start.edge_bottom = selection_bottom; + selection.start.edge_top = selection_top; + selection.end = selection.start; + host_impl_->active_tree()->RegisterSelection(selection); // Trigger a draw-swap sequence. host_impl_->SetNeedsRedraw(); @@ -6554,16 +6552,14 @@ EXPECT_TRUE(host_impl_->SwapBuffers(frame)); // Ensure the selection bounds have propagated to the frame metadata. - const ViewportSelectionBound& selection_start_after = - fake_output_surface->last_sent_frame().metadata.selection_start; - const ViewportSelectionBound& selection_end_after = - fake_output_surface->last_sent_frame().metadata.selection_end; - EXPECT_EQ(start.type, selection_start_after.type); - EXPECT_EQ(end.type, selection_end_after.type); - EXPECT_EQ(selection_bottom, selection_start_after.edge_bottom); - EXPECT_EQ(selection_top, selection_start_after.edge_top); - EXPECT_TRUE(selection_start_after.visible); - EXPECT_TRUE(selection_start_after.visible); + const ViewportSelection& selection_after = + fake_output_surface->last_sent_frame().metadata.selection; + EXPECT_EQ(selection.start.type, selection_after.start.type); + EXPECT_EQ(selection.end.type, selection_after.end.type); + EXPECT_EQ(selection_bottom, selection_after.start.edge_bottom); + EXPECT_EQ(selection_top, selection_after.start.edge_top); + EXPECT_TRUE(selection_after.start.visible); + EXPECT_TRUE(selection_after.start.visible); } class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 7843fb4..be879af 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -86,6 +86,46 @@ PrioritizedResourceManager* contents_texture_manager_; }; +class LayerTreeHostTestSetNeedsCommitInsideLayout : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void Layout() override { + // This shouldn't cause a second commit to happen. + layer_tree_host()->SetNeedsCommit(); + } + + void DidCommit() override { + EXPECT_EQ(1, layer_tree_host()->source_frame_number()); + EndTest(); + } + + void AfterTest() override {} +}; + +SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( + LayerTreeHostTestSetNeedsCommitInsideLayout); + +class LayerTreeHostTestSetNeedsUpdateInsideLayout : public LayerTreeHostTest { + protected: + void BeginTest() override { PostSetNeedsCommitToMainThread(); } + + void Layout() override { + // This shouldn't cause a second commit to happen. + layer_tree_host()->SetNeedsUpdateLayers(); + } + + void DidCommit() override { + EXPECT_EQ(1, layer_tree_host()->source_frame_number()); + EndTest(); + } + + void AfterTest() override {} +}; + +SINGLE_AND_MULTI_THREAD_IMPL_TEST_F( + LayerTreeHostTestSetNeedsUpdateInsideLayout); + // Test if the LTHI receives ReadyToActivate notifications from the TileManager // when no raster tasks get scheduled. class LayerTreeHostTestReadyToActivateEmpty : public LayerTreeHostTest {
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 7721976..25f48d6 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -226,7 +226,7 @@ target_tree->ClearViewportLayers(); } - target_tree->RegisterSelection(selection_start_, selection_end_); + target_tree->RegisterSelection(selection_); // This should match the property synchronization in // LayerTreeHost::finishCommitOnImplThread(). @@ -1473,13 +1473,11 @@ return data_for_recursion.closest_match; } -void LayerTreeImpl::RegisterSelection(const LayerSelectionBound& start, - const LayerSelectionBound& end) { - selection_start_ = start; - selection_end_ = end; +void LayerTreeImpl::RegisterSelection(const LayerSelection& selection) { + selection_ = selection; } -static ViewportSelectionBound ComputeViewportSelection( +static ViewportSelectionBound ComputeViewportSelectionBound( const LayerSelectionBound& layer_bound, LayerImpl* layer, float device_scale_factor) { @@ -1526,22 +1524,22 @@ return viewport_bound; } -void LayerTreeImpl::GetViewportSelection(ViewportSelectionBound* start, - ViewportSelectionBound* end) { - DCHECK(start); - DCHECK(end); +void LayerTreeImpl::GetViewportSelection(ViewportSelection* selection) { + DCHECK(selection); - *start = ComputeViewportSelection( - selection_start_, - selection_start_.layer_id ? LayerById(selection_start_.layer_id) : NULL, + selection->start = ComputeViewportSelectionBound( + selection_.start, + selection_.start.layer_id ? LayerById(selection_.start.layer_id) : NULL, device_scale_factor()); - if (start->type == SELECTION_BOUND_CENTER || - start->type == SELECTION_BOUND_EMPTY) { - *end = *start; + selection->is_editable = selection_.is_editable; + selection->is_empty_text_form_control = selection_.is_empty_text_form_control; + if (selection->start.type == SELECTION_BOUND_CENTER || + selection->start.type == SELECTION_BOUND_EMPTY) { + selection->end = selection->start; } else { - *end = ComputeViewportSelection( - selection_end_, - selection_end_.layer_id ? LayerById(selection_end_.layer_id) : NULL, + selection->end = ComputeViewportSelectionBound( + selection_.end, + selection_.end.layer_id ? LayerById(selection_.end.layer_id) : NULL, device_scale_factor()); } }
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index d51c042..76911e15 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -51,7 +51,6 @@ class VideoFrameControllerClient; struct PendingPageScaleAnimation; struct RendererCapabilities; -struct SelectionHandle; typedef std::vector<UIResourceRequest> UIResourceRequestQueue; typedef SyncedProperty<AdditionGroup<float>> SyncedTopControls; @@ -317,13 +316,11 @@ LayerImpl* FindLayerThatIsHitByPointInTouchHandlerRegion( const gfx::PointF& screen_space_point); - void RegisterSelection(const LayerSelectionBound& start, - const LayerSelectionBound& end); + void RegisterSelection(const LayerSelection& selection); // Compute the current selection handle location and visbility with respect to // the viewport. - void GetViewportSelection(ViewportSelectionBound* start, - ViewportSelectionBound* end); + void GetViewportSelection(ViewportSelection* selection); void set_top_controls_shrink_blink_size(bool shrink); bool top_controls_shrink_blink_size() const { @@ -376,8 +373,7 @@ LayerImpl* inner_viewport_scroll_layer_; LayerImpl* outer_viewport_scroll_layer_; - LayerSelectionBound selection_start_; - LayerSelectionBound selection_end_; + LayerSelection selection_; scoped_refptr<SyncedProperty<ScaleGroup>> page_scale_factor_; float min_page_scale_factor_;
diff --git a/cc/trees/layer_tree_impl_unittest.cc b/cc/trees/layer_tree_impl_unittest.cc index c4abd52..04c108f 100644 --- a/cc/trees/layer_tree_impl_unittest.cc +++ b/cc/trees/layer_tree_impl_unittest.cc
@@ -1910,51 +1910,59 @@ ASSERT_EQ(1u, RenderSurfaceLayerList().size()); ASSERT_EQ(1u, root_layer()->render_surface()->layer_list().size()); - LayerSelectionBound left_input; - left_input.type = SELECTION_BOUND_LEFT; - left_input.edge_top = gfx::PointF(10, 10); - left_input.edge_bottom = gfx::PointF(10, 20); - left_input.layer_id = root_layer_id; + LayerSelection input; - LayerSelectionBound right_input; - right_input.type = SELECTION_BOUND_RIGHT; - right_input.edge_top = gfx::PointF(50, 10); - right_input.edge_bottom = gfx::PointF(50, 30); - right_input.layer_id = root_layer_id; + input.start.type = SELECTION_BOUND_LEFT; + input.start.edge_top = gfx::PointF(10, 10); + input.start.edge_bottom = gfx::PointF(10, 20); + input.start.layer_id = root_layer_id; - ViewportSelectionBound left_output, right_output; + input.end.type = SELECTION_BOUND_RIGHT; + input.end.edge_top = gfx::PointF(50, 10); + input.end.edge_bottom = gfx::PointF(50, 30); + input.end.layer_id = root_layer_id; + + ViewportSelection output; // Empty input bounds should produce empty output bounds. - host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); - EXPECT_EQ(ViewportSelectionBound(), left_output); - EXPECT_EQ(ViewportSelectionBound(), right_output); + host_impl().active_tree()->GetViewportSelection(&output); + EXPECT_EQ(ViewportSelectionBound(), output.start); + EXPECT_EQ(ViewportSelectionBound(), output.end); // Selection bounds should produce distinct left and right bounds. - host_impl().active_tree()->RegisterSelection(left_input, right_input); - host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); - EXPECT_EQ(left_input.type, left_output.type); - EXPECT_EQ(left_input.edge_bottom, left_output.edge_bottom); - EXPECT_EQ(left_input.edge_top, left_output.edge_top); - EXPECT_TRUE(left_output.visible); - EXPECT_EQ(right_input.type, right_output.type); - EXPECT_EQ(right_input.edge_bottom, right_output.edge_bottom); - EXPECT_EQ(right_input.edge_top, right_output.edge_top); - EXPECT_TRUE(right_output.visible); + host_impl().active_tree()->RegisterSelection(input); + host_impl().active_tree()->GetViewportSelection(&output); + EXPECT_EQ(input.start.type, output.start.type); + EXPECT_EQ(input.start.edge_bottom, output.start.edge_bottom); + EXPECT_EQ(input.start.edge_top, output.start.edge_top); + EXPECT_TRUE(output.start.visible); + EXPECT_EQ(input.end.type, output.end.type); + EXPECT_EQ(input.end.edge_bottom, output.end.edge_bottom); + EXPECT_EQ(input.end.edge_top, output.end.edge_top); + EXPECT_TRUE(output.end.visible); + EXPECT_EQ(input.is_editable, output.is_editable); + EXPECT_EQ(input.is_empty_text_form_control, + output.is_empty_text_form_control); // Insertion bounds should produce identical left and right bounds. - LayerSelectionBound insertion_input; - insertion_input.type = SELECTION_BOUND_CENTER; - insertion_input.edge_top = gfx::PointF(15, 10); - insertion_input.edge_bottom = gfx::PointF(15, 30); - insertion_input.layer_id = root_layer_id; - host_impl().active_tree()->RegisterSelection(insertion_input, - LayerSelectionBound()); - host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); - EXPECT_EQ(insertion_input.type, left_output.type); - EXPECT_EQ(insertion_input.edge_bottom, left_output.edge_bottom); - EXPECT_EQ(insertion_input.edge_top, left_output.edge_top); - EXPECT_TRUE(left_output.visible); - EXPECT_EQ(left_output, right_output); + LayerSelection insertion_input; + insertion_input.start.type = SELECTION_BOUND_CENTER; + insertion_input.start.edge_top = gfx::PointF(15, 10); + insertion_input.start.edge_bottom = gfx::PointF(15, 30); + insertion_input.start.layer_id = root_layer_id; + insertion_input.is_editable = true; + insertion_input.is_empty_text_form_control = true; + insertion_input.end = insertion_input.start; + host_impl().active_tree()->RegisterSelection(insertion_input); + host_impl().active_tree()->GetViewportSelection(&output); + EXPECT_EQ(insertion_input.start.type, output.start.type); + EXPECT_EQ(insertion_input.start.edge_bottom, output.start.edge_bottom); + EXPECT_EQ(insertion_input.start.edge_top, output.start.edge_top); + EXPECT_EQ(insertion_input.is_editable, output.is_editable); + EXPECT_EQ(insertion_input.is_empty_text_form_control, + output.is_empty_text_form_control); + EXPECT_TRUE(output.start.visible); + EXPECT_EQ(output.start, output.end); } TEST_F(LayerTreeImplTest, SelectionBoundsForPartialOccludedLayers) { @@ -2003,58 +2011,57 @@ // Sanity check the scenario we just created. ASSERT_EQ(1u, RenderSurfaceLayerList().size()); - LayerSelectionBound left_input; - left_input.type = SELECTION_BOUND_LEFT; - left_input.edge_top = gfx::PointF(25, 10); - left_input.edge_bottom = gfx::PointF(25, 30); - left_input.layer_id = clipped_layer_id; + LayerSelection input; + input.start.type = SELECTION_BOUND_LEFT; + input.start.edge_top = gfx::PointF(25, 10); + input.start.edge_bottom = gfx::PointF(25, 30); + input.start.layer_id = clipped_layer_id; - LayerSelectionBound right_input; - right_input.type = SELECTION_BOUND_RIGHT; - right_input.edge_top = gfx::PointF(75, 10); - right_input.edge_bottom = gfx::PointF(75, 30); - right_input.layer_id = clipped_layer_id; - host_impl().active_tree()->RegisterSelection(left_input, right_input); + input.end.type = SELECTION_BOUND_RIGHT; + input.end.edge_top = gfx::PointF(75, 10); + input.end.edge_bottom = gfx::PointF(75, 30); + input.end.layer_id = clipped_layer_id; + host_impl().active_tree()->RegisterSelection(input); // The left bound should be occluded by the clip layer. - ViewportSelectionBound left_output, right_output; - host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); - EXPECT_EQ(left_input.type, left_output.type); - gfx::PointF expected_left_output_top = left_input.edge_top; - gfx::PointF expected_left_output_bottom = left_input.edge_bottom; - expected_left_output_top.Offset(clipping_offset.x(), clipping_offset.y()); - expected_left_output_bottom.Offset(clipping_offset.x(), clipping_offset.y()); - EXPECT_EQ(expected_left_output_top, left_output.edge_top); - EXPECT_EQ(expected_left_output_bottom, left_output.edge_bottom); - EXPECT_TRUE(left_output.visible); - EXPECT_EQ(right_input.type, right_output.type); - gfx::PointF expected_right_output_top = right_input.edge_top; - gfx::PointF expected_right_output_bottom = right_input.edge_bottom; - expected_right_output_bottom.Offset(clipping_offset.x(), clipping_offset.y()); - expected_right_output_top.Offset(clipping_offset.x(), clipping_offset.y()); - EXPECT_EQ(expected_right_output_top, right_output.edge_top); - EXPECT_EQ(expected_right_output_bottom, right_output.edge_bottom); - EXPECT_FALSE(right_output.visible); + ViewportSelection output; + host_impl().active_tree()->GetViewportSelection(&output); + EXPECT_EQ(input.start.type, output.start.type); + gfx::PointF expected_output_start_top = input.start.edge_top; + gfx::PointF expected_output_edge_botom = input.start.edge_bottom; + expected_output_start_top.Offset(clipping_offset.x(), clipping_offset.y()); + expected_output_edge_botom.Offset(clipping_offset.x(), clipping_offset.y()); + EXPECT_EQ(expected_output_start_top, output.start.edge_top); + EXPECT_EQ(expected_output_edge_botom, output.start.edge_bottom); + EXPECT_TRUE(output.start.visible); + EXPECT_EQ(input.end.type, output.end.type); + gfx::PointF expected_output_end_top = input.end.edge_top; + gfx::PointF expected_output_end_bottom = input.end.edge_bottom; + expected_output_end_bottom.Offset(clipping_offset.x(), clipping_offset.y()); + expected_output_end_top.Offset(clipping_offset.x(), clipping_offset.y()); + EXPECT_EQ(expected_output_end_top, output.end.edge_top); + EXPECT_EQ(expected_output_end_bottom, output.end.edge_bottom); + EXPECT_FALSE(output.end.visible); // Handles outside the viewport bounds should be marked invisible. - left_input.edge_top = gfx::PointF(-25, 0); - left_input.edge_bottom = gfx::PointF(-25, 20); - host_impl().active_tree()->RegisterSelection(left_input, right_input); - host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); - EXPECT_FALSE(left_output.visible); + input.start.edge_top = gfx::PointF(-25, 0); + input.start.edge_bottom = gfx::PointF(-25, 20); + host_impl().active_tree()->RegisterSelection(input); + host_impl().active_tree()->GetViewportSelection(&output); + EXPECT_FALSE(output.start.visible); - left_input.edge_top = gfx::PointF(0, -25); - left_input.edge_bottom = gfx::PointF(0, -5); - host_impl().active_tree()->RegisterSelection(left_input, right_input); - host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); - EXPECT_FALSE(left_output.visible); + input.start.edge_top = gfx::PointF(0, -25); + input.start.edge_bottom = gfx::PointF(0, -5); + host_impl().active_tree()->RegisterSelection(input); + host_impl().active_tree()->GetViewportSelection(&output); + EXPECT_FALSE(output.start.visible); // If the handle bottom is partially visible, the handle is marked visible. - left_input.edge_top = gfx::PointF(0, -20); - left_input.edge_bottom = gfx::PointF(0, 1); - host_impl().active_tree()->RegisterSelection(left_input, right_input); - host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); - EXPECT_TRUE(left_output.visible); + input.start.edge_top = gfx::PointF(0, -20); + input.start.edge_bottom = gfx::PointF(0, 1); + host_impl().active_tree()->RegisterSelection(input); + host_impl().active_tree()->GetViewportSelection(&output); + EXPECT_TRUE(output.start.visible); } TEST_F(LayerTreeImplTest, SelectionBoundsForScaledLayers) { @@ -2102,43 +2109,41 @@ // Sanity check the scenario we just created. ASSERT_EQ(1u, RenderSurfaceLayerList().size()); - LayerSelectionBound left_input; - left_input.type = SELECTION_BOUND_LEFT; - left_input.edge_top = gfx::PointF(10, 10); - left_input.edge_bottom = gfx::PointF(10, 30); - left_input.layer_id = root_layer_id; + LayerSelection input; + input.start.type = SELECTION_BOUND_LEFT; + input.start.edge_top = gfx::PointF(10, 10); + input.start.edge_bottom = gfx::PointF(10, 30); + input.start.layer_id = root_layer_id; - LayerSelectionBound right_input; - right_input.type = SELECTION_BOUND_RIGHT; - right_input.edge_top = gfx::PointF(0, 0); - right_input.edge_bottom = gfx::PointF(0, 20); - right_input.layer_id = sub_layer_id; - host_impl().active_tree()->RegisterSelection(left_input, right_input); + input.end.type = SELECTION_BOUND_RIGHT; + input.end.edge_top = gfx::PointF(0, 0); + input.end.edge_bottom = gfx::PointF(0, 20); + input.end.layer_id = sub_layer_id; + host_impl().active_tree()->RegisterSelection(input); // The viewport bounds should be properly scaled by the page scale, but should // remain in DIP coordinates. - ViewportSelectionBound left_output, right_output; - host_impl().active_tree()->GetViewportSelection(&left_output, &right_output); - EXPECT_EQ(left_input.type, left_output.type); - gfx::PointF expected_left_output_top = left_input.edge_top; - gfx::PointF expected_left_output_bottom = left_input.edge_bottom; - expected_left_output_top.Scale(page_scale_factor); - expected_left_output_bottom.Scale(page_scale_factor); - EXPECT_EQ(left_input.edge_top, left_output.edge_top); - EXPECT_EQ(left_input.edge_bottom, left_output.edge_bottom); - EXPECT_TRUE(left_output.visible); - EXPECT_EQ(right_input.type, right_output.type); + ViewportSelection output; + host_impl().active_tree()->GetViewportSelection(&output); + EXPECT_EQ(input.start.type, output.start.type); + gfx::PointF expected_output_start_top = input.start.edge_top; + gfx::PointF expected_output_edge_botom = input.start.edge_bottom; + expected_output_start_top.Scale(page_scale_factor); + expected_output_edge_botom.Scale(page_scale_factor); + EXPECT_EQ(input.start.edge_top, output.start.edge_top); + EXPECT_EQ(input.start.edge_bottom, output.start.edge_bottom); + EXPECT_TRUE(output.start.visible); + EXPECT_EQ(input.end.type, output.end.type); - gfx::PointF expected_right_output_top = right_input.edge_top; - gfx::PointF expected_right_output_bottom = right_input.edge_bottom; - expected_right_output_top.Offset(sub_layer_offset.x(), sub_layer_offset.y()); - expected_right_output_bottom.Offset(sub_layer_offset.x(), - sub_layer_offset.y()); - expected_right_output_top.Scale(page_scale_factor); - expected_right_output_bottom.Scale(page_scale_factor); - EXPECT_EQ(expected_right_output_top, right_output.edge_top); - EXPECT_EQ(expected_right_output_bottom, right_output.edge_bottom); - EXPECT_TRUE(right_output.visible); + gfx::PointF expected_output_end_top = input.end.edge_top; + gfx::PointF expected_output_end_bottom = input.end.edge_bottom; + expected_output_end_top.Offset(sub_layer_offset.x(), sub_layer_offset.y()); + expected_output_end_bottom.Offset(sub_layer_offset.x(), sub_layer_offset.y()); + expected_output_end_top.Scale(page_scale_factor); + expected_output_end_bottom.Scale(page_scale_factor); + EXPECT_EQ(expected_output_end_top, output.end.edge_top); + EXPECT_EQ(expected_output_end_bottom, output.end.edge_bottom); + EXPECT_TRUE(output.end.visible); } TEST_F(LayerTreeImplTest, NumLayersTestOne) {
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 7f384456..d9b7081 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -48,6 +48,7 @@ TransformNodeData::TransformNodeData() : target_id(-1), content_target_id(-1), + source_node_id(-1), needs_local_transform_update(true), is_invertible(true), ancestors_are_invertible(true), @@ -76,8 +77,8 @@ post_local.MakeIdentity(); post_local.Scale(post_local_scale_factor, post_local_scale_factor); post_local.Translate3d( - position.x() + parent_offset.x() + transform_origin.x(), - position.y() + parent_offset.y() + transform_origin.y(), + position.x() + source_offset.x() + transform_origin.x(), + position.y() + source_offset.y() + transform_origin.y(), transform_origin.z()); } @@ -141,7 +142,8 @@ TransformNode* node = Node(id); TransformNode* parent_node = parent(node); TransformNode* target_node = Node(node->data.target_id); - if (node->data.needs_local_transform_update) + if (node->data.needs_local_transform_update || + node->parent_id != node->data.source_node_id) UpdateLocalTransform(node); UpdateScreenSpaceTransform(node, parent_node, target_node); UpdateSublayerScale(node); @@ -249,8 +251,14 @@ void TransformTree::UpdateLocalTransform(TransformNode* node) { gfx::Transform transform = node->data.post_local; - transform.Translate(-node->data.scroll_offset.x(), - -node->data.scroll_offset.y()); + gfx::Vector2dF source_to_parent; + if (node->parent_id != node->data.source_node_id) { + gfx::Transform to_parent; + ComputeTransform(node->data.source_node_id, node->parent_id, &to_parent); + source_to_parent = to_parent.To2dTranslation(); + } + transform.Translate(source_to_parent.x() - node->data.scroll_offset.x(), + source_to_parent.y() - node->data.scroll_offset.y()); transform.PreconcatTransform(node->data.local); transform.PreconcatTransform(node->data.pre_local); node->data.set_to_parent(transform);
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 42e2e169..c0796cf 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -60,6 +60,12 @@ // with this transform node. int content_target_id; + // This is the node with respect to which source_offset is defined. This will + // not be needed once layerization moves to cc, but is needed in order to + // efficiently update the transform tree for changes to position in the layer + // tree. + int source_node_id; + // TODO(vollick): will be moved when accelerated effects are implemented. bool needs_local_transform_update; @@ -98,7 +104,7 @@ gfx::Vector2dF scroll_snap; // TODO(vollick): will be moved when accelerated effects are implemented. - gfx::Vector2dF parent_offset; + gfx::Vector2dF source_offset; void set_to_parent(const gfx::Transform& transform) { to_parent = transform;
diff --git a/cc/trees/property_tree_builder.cc b/cc/trees/property_tree_builder.cc index 269a71e..064a094 100644 --- a/cc/trees/property_tree_builder.cc +++ b/cc/trees/property_tree_builder.cc
@@ -185,33 +185,29 @@ LayerType* transform_parent = GetTransformParent(data_from_ancestor, layer); - gfx::Vector2dF parent_offset; + int parent_index = 0; + if (transform_parent) + parent_index = transform_parent->transform_tree_index(); + + int source_index = parent_index; + + gfx::Vector2dF source_offset; if (transform_parent) { if (layer->scroll_parent()) { - gfx::Transform to_parent; LayerType* source = layer->parent(); - parent_offset += source->offset_to_transform_parent(); - data_from_ancestor.transform_tree->ComputeTransform( - source->transform_tree_index(), - transform_parent->transform_tree_index(), &to_parent); - parent_offset += to_parent.To2dTranslation(); + source_offset += source->offset_to_transform_parent(); + source_index = source->transform_tree_index(); } else if (!is_fixed) { - parent_offset = transform_parent->offset_to_transform_parent(); + source_offset = transform_parent->offset_to_transform_parent(); } else { if (data_from_ancestor.transform_tree_parent != data_from_ancestor.transform_fixed_parent) { - gfx::Vector2dF fixed_offset = data_from_ancestor.transform_tree_parent - ->offset_to_transform_parent(); - gfx::Transform parent_to_parent; - data_from_ancestor.transform_tree->ComputeTransform( - data_from_ancestor.transform_tree_parent->transform_tree_index(), - data_from_ancestor.transform_fixed_parent->transform_tree_index(), - &parent_to_parent); - - fixed_offset += parent_to_parent.To2dTranslation(); - parent_offset += fixed_offset; + source_offset = data_from_ancestor.transform_tree_parent + ->offset_to_transform_parent(); + source_index = + data_from_ancestor.transform_tree_parent->transform_tree_index(); } - parent_offset += data_from_ancestor.scroll_compensation_adjustment; + source_offset += data_from_ancestor.scroll_compensation_adjustment; } } @@ -226,17 +222,21 @@ data_for_children->should_flatten |= layer->should_flatten_transform(); gfx::Vector2dF local_offset = layer->position().OffsetFromOrigin() + layer->transform().To2dTranslation(); - layer->set_offset_to_transform_parent(parent_offset + local_offset); + gfx::Vector2dF source_to_parent; + if (source_index != parent_index) { + gfx::Transform to_parent; + data_from_ancestor.transform_tree->ComputeTransform( + source_index, parent_index, &to_parent); + source_to_parent = to_parent.To2dTranslation(); + } + layer->set_offset_to_transform_parent(source_offset + source_to_parent + + local_offset); layer->set_should_flatten_transform_from_property_tree( data_from_ancestor.should_flatten); - layer->set_transform_tree_index(transform_parent->transform_tree_index()); + layer->set_transform_tree_index(parent_index); return false; } - int parent_index = 0; - if (transform_parent) - parent_index = transform_parent->transform_tree_index(); - data_for_children->transform_tree->Insert(TransformNode(), parent_index); TransformNode* node = data_for_children->transform_tree->back(); @@ -276,7 +276,8 @@ post_local_scale_factor); } else { node->data.post_local_scale_factor = post_local_scale_factor; - node->data.parent_offset = parent_offset; + node->data.source_offset = source_offset; + node->data.source_node_id = source_index; node->data.update_post_local_transform(layer->position(), layer->transform_origin()); }
diff --git a/cc/trees/property_tree_unittest.cc b/cc/trees/property_tree_unittest.cc index d8ee10e..2248286 100644 --- a/cc/trees/property_tree_unittest.cc +++ b/cc/trees/property_tree_unittest.cc
@@ -47,6 +47,7 @@ TransformNode child; child.data.local.Translate(3, 3); child.data.target_id = 0; + child.data.source_node_id = 0; tree.Insert(child, 0); tree.UpdateTransforms(1); @@ -87,6 +88,7 @@ int grand_parent = tree.Insert(TransformNode(), 0); tree.Node(grand_parent)->data.content_target_id = grand_parent; tree.Node(grand_parent)->data.target_id = grand_parent; + tree.Node(grand_parent)->data.source_node_id = 0; gfx::Transform rotation_about_x; rotation_about_x.RotateAboutXAxis(15); @@ -95,17 +97,20 @@ tree.Node(parent)->data.needs_sublayer_scale = true; tree.Node(parent)->data.target_id = grand_parent; tree.Node(parent)->data.content_target_id = parent; + tree.Node(parent)->data.source_node_id = grand_parent; tree.Node(parent)->data.local = rotation_about_x; int child = tree.Insert(TransformNode(), parent); tree.Node(child)->data.target_id = parent; tree.Node(child)->data.content_target_id = parent; + tree.Node(child)->data.source_node_id = parent; tree.Node(child)->data.flattens_inherited_transform = true; tree.Node(child)->data.local = rotation_about_x; int grand_child = tree.Insert(TransformNode(), child); tree.Node(grand_child)->data.target_id = parent; tree.Node(grand_child)->data.content_target_id = parent; + tree.Node(grand_child)->data.source_node_id = child; tree.Node(grand_child)->data.flattens_inherited_transform = true; tree.Node(grand_child)->data.local = rotation_about_x; @@ -162,6 +167,7 @@ TransformNode child; child.data.local.Scale(2, 2); child.data.target_id = 0; + child.data.source_node_id = 0; tree.Insert(child, 0); tree.UpdateTransforms(1); @@ -194,6 +200,7 @@ TransformNode child; child.data.local.Scale(0, 0); child.data.target_id = 0; + child.data.source_node_id = 0; tree.Insert(child, 0); tree.UpdateTransforms(1); @@ -223,6 +230,7 @@ TransformNode grand_parent; grand_parent.data.local.Scale(2.f, 2.f); grand_parent.data.target_id = 0; + grand_parent.data.source_node_id = 0; grand_parent.data.needs_sublayer_scale = true; int grand_parent_id = tree.Insert(grand_parent, 0); tree.UpdateTransforms(grand_parent_id); @@ -230,18 +238,21 @@ TransformNode parent; parent.data.local.Translate(15.f, 15.f); parent.data.target_id = grand_parent_id; + parent.data.source_node_id = grand_parent_id; int parent_id = tree.Insert(parent, grand_parent_id); tree.UpdateTransforms(parent_id); TransformNode child; child.data.local.Scale(3.f, 3.f); child.data.target_id = grand_parent_id; + child.data.source_node_id = parent_id; int child_id = tree.Insert(child, parent_id); tree.UpdateTransforms(child_id); TransformNode grand_child; grand_child.data.local.Scale(5.f, 5.f); grand_child.data.target_id = grand_parent_id; + grand_child.data.source_node_id = child_id; grand_child.data.needs_sublayer_scale = true; int grand_child_id = tree.Insert(grand_child, child_id); tree.UpdateTransforms(grand_child_id); @@ -327,6 +338,7 @@ int parent = tree.Insert(TransformNode(), 0); tree.Node(parent)->data.content_target_id = parent; tree.Node(parent)->data.target_id = parent; + tree.Node(parent)->data.source_node_id = 0; tree.Node(parent)->data.local.Translate(2, 2); gfx::Transform rotation_about_x; @@ -335,12 +347,14 @@ int child = tree.Insert(TransformNode(), parent); tree.Node(child)->data.content_target_id = child; tree.Node(child)->data.target_id = child; + tree.Node(child)->data.source_node_id = parent; tree.Node(child)->data.local = rotation_about_x; int grand_child = tree.Insert(TransformNode(), child); tree.Node(grand_child)->data.content_target_id = grand_child; tree.Node(grand_child)->data.target_id = grand_child; + tree.Node(grand_child)->data.source_node_id = child; tree.Node(grand_child)->data.flattens_inherited_transform = true; tree.set_needs_update(true);
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc index c25ed4d..b9f6a484 100644 --- a/cc/trees/single_thread_proxy.cc +++ b/cc/trees/single_thread_proxy.cc
@@ -50,11 +50,21 @@ commit_requested_(false), inside_synchronous_composite_(false), output_surface_creation_requested_(false), - external_begin_frame_source_(external_begin_frame_source.Pass()), weak_factory_(this) { TRACE_EVENT0("cc", "SingleThreadProxy::SingleThreadProxy"); DCHECK(Proxy::IsMainThread()); DCHECK(layer_tree_host); + + if (layer_tree_host->settings().single_thread_proxy_scheduler && + !scheduler_on_impl_thread_) { + SchedulerSettings scheduler_settings( + layer_tree_host->settings().ToSchedulerSettings()); + // SingleThreadProxy should run in main thread low latency mode. + scheduler_settings.main_thread_should_always_be_low_latency = true; + scheduler_on_impl_thread_ = Scheduler::Create( + this, scheduler_settings, layer_tree_host_->id(), + MainThreadTaskRunner(), external_begin_frame_source.Pass()); + } } void SingleThreadProxy::Start() { @@ -95,18 +105,7 @@ // nothing to do. DCHECK(Proxy::IsMainThread()); DebugScopedSetImplThread impl(this); - if (layer_tree_host_->settings().single_thread_proxy_scheduler && - !scheduler_on_impl_thread_) { - SchedulerSettings scheduler_settings( - layer_tree_host_->settings().ToSchedulerSettings()); - // SingleThreadProxy should run in main thread low latency mode. - scheduler_settings.main_thread_should_always_be_low_latency = true; - scheduler_on_impl_thread_ = - Scheduler::Create(this, - scheduler_settings, - layer_tree_host_->id(), - MainThreadTaskRunner(), - external_begin_frame_source_.Pass()); + if (scheduler_on_impl_thread_) { scheduler_on_impl_thread_->SetCanStart(); scheduler_on_impl_thread_->SetVisible(layer_tree_host_impl_->visible()); } @@ -214,7 +213,6 @@ // fixed. tracked_objects::ScopedTracker tracking_profile1( FROM_HERE_WITH_EXPLICIT_FUNCTION("461509 SingleThreadProxy::DoCommit1")); - commit_requested_ = false; layer_tree_host_->WillCommit(); devtools_instrumentation::ScopedCommitTrace commit_task( layer_tree_host_->id()); @@ -334,8 +332,10 @@ void SingleThreadProxy::SetNeedsCommit() { DCHECK(Proxy::IsMainThread()); - DebugScopedSetImplThread impl(this); client_->ScheduleComposite(); + if (commit_requested_) + return; + DebugScopedSetImplThread impl(this); if (scheduler_on_impl_thread_) scheduler_on_impl_thread_->SetNeedsCommit(); commit_requested_ = true; @@ -766,7 +766,11 @@ } bool SingleThreadProxy::MainFrameWillHappenForTesting() { - return false; + if (layer_tree_host_->output_surface_lost()) + return false; + if (!scheduler_on_impl_thread_) + return false; + return scheduler_on_impl_thread_->MainFrameForTestingWillHappen(); } void SingleThreadProxy::SetChildrenNeedBeginFrames( @@ -804,6 +808,8 @@ } void SingleThreadProxy::BeginMainFrame() { + commit_requested_ = false; + if (defer_commits_) { TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit", TRACE_EVENT_SCOPE_THREAD); @@ -831,6 +837,9 @@ return; } + // Prevent new commits from being requested inside DoBeginMainFrame. + commit_requested_ = true; + const BeginFrameArgs& begin_frame_args = layer_tree_host_impl_->CurrentBeginFrameArgs(); DoBeginMainFrame(begin_frame_args); @@ -855,6 +864,9 @@ DCHECK(!queue_for_commit_); queue_for_commit_ = make_scoped_ptr(new ResourceUpdateQueue); + // New commits requested inside UpdateLayers should be respected. + commit_requested_ = false; + layer_tree_host_->UpdateLayers(queue_for_commit_.get()); timing_history_.DidBeginMainFrame();
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h index 0ff637a..3ac80cc 100644 --- a/cc/trees/single_thread_proxy.h +++ b/cc/trees/single_thread_proxy.h
@@ -172,8 +172,6 @@ // This is the callback for the scheduled RequestNewOutputSurface. base::CancelableClosure output_surface_creation_callback_; - scoped_ptr<BeginFrameSource> external_begin_frame_source_; - base::WeakPtrFactory<SingleThreadProxy> weak_factory_; DISALLOW_COPY_AND_ASSIGN(SingleThreadProxy);
diff --git a/chrome/VERSION b/chrome/VERSION index 721243e..66ad392 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=44 MINOR=0 -BUILD=2379 +BUILD=2385 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 8642838..a3292c8 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -192,14 +192,6 @@ deps = [ ":chrome_shell_base", ] - - # GYP: via base/files/protect_file_posix.gypi - # TODO(pasko): Remove this non-trivial linker wrapping as soon as - # crbug.com/424562 is fixed. - if (!is_component_build) { - ldflags = [ "-Wl,--wrap=close" ] - deps += [ "//base:protect_file_posix" ] - } } # GYP: //chrome/chrome_shell.gypi:libchromesyncshell @@ -236,6 +228,7 @@ ":chrome_java", "//base:base_java", "//content/public/android:content_java", + "//components/dom_distiller/android:dom_distiller_content_java", "//components/dom_distiller/android:dom_distiller_core_java", "//components/service_tab_launcher:service_tab_launcher_java", "//components/web_contents_delegate_android:web_contents_delegate_android_java", @@ -451,24 +444,34 @@ # GYP: //chrome/chrome_tests.gypi:chrome_shell_test_apk android_apk("chrome_shell_test_apk") { testonly = true + apk_under_test = ":chrome_shell_apk" deps = [ ":chrome_javatests", ":chrome_shell_test_java", "//sync/android:sync_javatests", + "//testing/android/broker:broker_java", "//ui/android:ui_javatests", ] + datadeps = [ + "//testing/android/driver:driver_apk", + ] apk_name = "ChromeShellTest" android_manifest = "shell/javatests/AndroidManifest.xml" } # GYP: //chrome/chrome_tests.gypi:chrome_junit_tests junit_binary("chrome_junit_tests") { - java_files = - [ "junit/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java" ] + java_files = [ + "junit/src/org/chromium/chrome/browser/omaha/ResponseParserTest.java", + "junit/src/org/chromium/chrome/browser/media/remote/MediaUrlResolverTest.java", + "junit/src/org/chromium/chrome/browser/media/remote/RemoteVideoInfoTest.java", + "junit/src/org/chromium/chrome/browser/media/remote/TransportControlTest.java", + ] deps = [ ":chrome_java", "//base:base_java", "//base:base_java_test_support", + "//third_party/junit:hamcrest", ] } @@ -477,6 +480,7 @@ # TODO(GYP): We need sync/sync_tests.gypi:test_support_sync_proto_java to be ported. # crbug.com/475612 android_apk("chrome_sync_shell_test_apk") { + apk_under_test = ":chrome_sync_shell_apk" testonly = true deps = [ ":chrome_java",
diff --git a/chrome/android/java/res/drawable-hdpi/permission_media.png b/chrome/android/java/res/drawable-hdpi/permission_camera.png similarity index 100% rename from chrome/android/java/res/drawable-hdpi/permission_media.png rename to chrome/android/java/res/drawable-hdpi/permission_camera.png Binary files differ
diff --git a/chrome/android/java/res/drawable-mdpi/permission_media.png b/chrome/android/java/res/drawable-mdpi/permission_camera.png similarity index 100% rename from chrome/android/java/res/drawable-mdpi/permission_media.png rename to chrome/android/java/res/drawable-mdpi/permission_camera.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/permission_media.png b/chrome/android/java/res/drawable-xhdpi/permission_camera.png similarity index 100% rename from chrome/android/java/res/drawable-xhdpi/permission_media.png rename to chrome/android/java/res/drawable-xhdpi/permission_camera.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxhdpi/permission_media.png b/chrome/android/java/res/drawable-xxhdpi/permission_camera.png similarity index 100% rename from chrome/android/java/res/drawable-xxhdpi/permission_media.png rename to chrome/android/java/res/drawable-xxhdpi/permission_camera.png Binary files differ
diff --git a/chrome/android/java/res/drawable-xxxhdpi/permission_media.png b/chrome/android/java/res/drawable-xxxhdpi/permission_camera.png similarity index 100% rename from chrome/android/java/res/drawable-xxxhdpi/permission_media.png rename to chrome/android/java/res/drawable-xxxhdpi/permission_camera.png Binary files differ
diff --git a/chrome/android/java/res/drawable/website_voice_and_video_capture.xml b/chrome/android/java/res/drawable/website_voice_and_video_capture.xml deleted file mode 100644 index ef32940..0000000 --- a/chrome/android/java/res/drawable/website_voice_and_video_capture.xml +++ /dev/null
@@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. --> - -<level-list xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- video and/or voice allowed icon --> - <item android:maxLevel="1" android:drawable="@drawable/webrtc_video_settings" /> - <!-- video and/or voice denied icon --> - <item android:maxLevel="2" android:drawable="@drawable/webrtc_video_settings_denied" /> - <!-- voice allowed icon --> - <item android:maxLevel="3" android:drawable="@drawable/webrtc_audio_settings" /> - <!-- voice denied icon --> - <item android:maxLevel="4" android:drawable="@drawable/webrtc_audio_settings_denied" /> -</level-list> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/dom_distiller_feedback_reporting_view.xml b/chrome/android/java/res/layout/dom_distiller_feedback_reporting_view.xml deleted file mode 100644 index a20a4925..0000000 --- a/chrome/android/java/res/layout/dom_distiller_feedback_reporting_view.xml +++ /dev/null
@@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- 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. ---> - -<org.chromium.chrome.browser.dom_distiller.DomDistillerFeedbackReportingView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:chrome="http://schemas.android.com/apk/res-auto" - android:id="@+id/feedback_reporting_view" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:background="#656565"> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:gravity="center"> - - <LinearLayout - android:baselineAligned="false" - android:layout_width="match_parent" - android:layout_height="15dp" - android:orientation="horizontal"> - - <View - android:background="#4285F4" - android:layout_height="match_parent" - android:layout_width="0dp" - android:layout_weight="1" /> - - <View - android:background="#DB4437" - android:layout_height="match_parent" - android:layout_width="0dp" - android:layout_weight="1" /> - - <View - android:background="#F4B400" - android:layout_height="match_parent" - android:layout_width="0dp" - android:layout_weight="1" /> - - <View - android:background="#0F9D58" - android:layout_height="match_parent" - android:layout_width="0dp" - android:layout_weight="1" /> - </LinearLayout> - - <TextView - android:id="@+id/distillation_quality_question" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center" - android:padding="10dp" - android:text="@string/distillation_quality_question" - android:textSize="20sp" - android:textColor="@android:color/white" - android:textStyle="bold" - android:fontFamily="sans-serif" /> - - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingTop="10dp" - android:paddingBottom="10dp" - android:clipToPadding="false" - android:orientation="horizontal"> - - <org.chromium.chrome.browser.widget.ButtonCompat - android:id="@+id/distillation_quality_answer_no" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_margin="8dp" - android:text="@string/distillation_quality_answer_no" - android:textColor="#fff" - chrome:buttonColor="#DB4437" /> - - <org.chromium.chrome.browser.widget.ButtonCompat - android:id="@+id/distillation_quality_answer_yes" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_margin="8dp" - android:text="@string/distillation_quality_answer_yes" - android:textColor="#fff" - chrome:buttonColor="#0F9D58" /> - - </LinearLayout> - </LinearLayout> - -</org.chromium.chrome.browser.dom_distiller.DomDistillerFeedbackReportingView> \ No newline at end of file
diff --git a/chrome/android/java/res/layout/website_features.xml b/chrome/android/java/res/layout/website_features.xml index 5c143eb5..99971572 100644 --- a/chrome/android/java/res/layout/website_features.xml +++ b/chrome/android/java/res/layout/website_features.xml
@@ -17,11 +17,4 @@ android:layout_height="wrap_content" android:visibility="gone" android:contentDescription="@null" /> - - <ImageView android:id="@+id/voice_and_video_capture_icon" - android:layout_width="32dp" - android:layout_height="32dp" - android:visibility="gone" - android:contentDescription="@null" - android:src="@drawable/website_voice_and_video_capture" /> </LinearLayout>
diff --git a/chrome/android/java/res/xml/content_preferences.xml b/chrome/android/java/res/xml/content_preferences.xml index 7a85047a..d59950b 100644 --- a/chrome/android/java/res/xml/content_preferences.xml +++ b/chrome/android/java/res/xml/content_preferences.xml
@@ -18,10 +18,14 @@ <Preference android:fragment="org.chromium.chrome.browser.preferences.website.WebsitePreferences" android:key="device_location" /> - <!-- Media --> + <!-- Camera --> <Preference android:fragment="org.chromium.chrome.browser.preferences.website.WebsitePreferences" - android:key="use_camera_or_mic" /> + android:key="camera" /> + <!-- Microphone --> + <Preference + android:fragment="org.chromium.chrome.browser.preferences.website.WebsitePreferences" + android:key="microphone" /> <!-- Notifications --> <Preference android:fragment="org.chromium.chrome.browser.preferences.website.WebsitePreferences"
diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml index c08e9bb..1af3ede 100644 --- a/chrome/android/java/res/xml/privacy_preferences.xml +++ b/chrome/android/java/res/xml/privacy_preferences.xml
@@ -45,6 +45,10 @@ android:key="crash_dump_upload_no_cellular" android:title="@string/crash_dump_upload_title" android:defaultValue="false" /> + <Preference + android:key="usage_and_crash_reports" + android:title="@string/usage_and_crash_reports_title" + android:fragment="org.chromium.chrome.browser.preferences.privacy.UsageAndCrashReportsPreferenceFragment" /> <Preference android:fragment="org.chromium.chrome.browser.preferences.privacy.DoNotTrackPreference"
diff --git a/chrome/android/java/res/xml/single_website_preferences.xml b/chrome/android/java/res/xml/single_website_preferences.xml index 4d0ee85..46a9dc92 100644 --- a/chrome/android/java/res/xml/single_website_preferences.xml +++ b/chrome/android/java/res/xml/single_website_preferences.xml
@@ -25,7 +25,9 @@ <org.chromium.chrome.browser.preferences.ChromeBaseListPreference android:key="cookies_permission_list" /> <org.chromium.chrome.browser.preferences.ChromeBaseListPreference - android:key="voice_and_video_capture_permission_list" /> + android:key="camera_permission_list" /> + <org.chromium.chrome.browser.preferences.ChromeBaseListPreference + android:key="microphone_permission_list" /> <org.chromium.chrome.browser.preferences.ChromeBaseListPreference android:key="popup_permission_list" /> <org.chromium.chrome.browser.preferences.ChromeBaseListPreference
diff --git a/chrome/android/java/res/xml/usage_and_crash_reports_preferences.xml b/chrome/android/java/res/xml/usage_and_crash_reports_preferences.xml new file mode 100644 index 0000000..a9831905 --- /dev/null +++ b/chrome/android/java/res/xml/usage_and_crash_reports_preferences.xml
@@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<PreferenceScreen + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:chrome="http://schemas.android.com/apk/res-auto"> + + <org.chromium.chrome.browser.preferences.ChromeSwitchPreference + android:key="usage_and_crash_reports_switch" + android:summaryOn="@string/text_on" + android:summaryOff="@string/text_off"/> + + <org.chromium.chrome.browser.preferences.TextMessagePreference + android:title="@string/usage_and_crash_reports_description"/> + + <org.chromium.chrome.browser.preferences.HyperlinkPreference + android:key="usage_and_crash_reports_learn_more" + android:title="@string/learn_more" + chrome:url="@string/usage_and_crash_reports_learn_more_url" + chrome:imitateWebLink="true" /> + +</PreferenceScreen>
diff --git a/chrome/android/java/src/org/chromium/chrome/ChromeSwitches.java b/chrome/android/java/src/org/chromium/chrome/ChromeSwitches.java index 7cc1286..75cc3c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/ChromeSwitches.java +++ b/chrome/android/java/src/org/chromium/chrome/ChromeSwitches.java
@@ -129,6 +129,13 @@ */ public static final String GOOGLE_BASE_URL = "google-base-url"; + /** + * Use fake device for Media Stream to replace actual camera and microphone. + * Native switch - switches::kUseFakeDeviceForMediaStream. + */ + public static final String USE_FAKE_DEVICE_FOR_MEDIA_STREAM = + "use-fake-device-for-media-stream"; + // Prevent instantiation. private ChromeSwitches() {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AccessibilityUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/AccessibilityUtil.java index 40e69ab..f0234bf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/AccessibilityUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/AccessibilityUtil.java
@@ -10,7 +10,6 @@ import android.content.DialogInterface; import android.content.Intent; import android.net.Uri; -import android.os.Build; import android.view.accessibility.AccessibilityManager; import org.chromium.base.CalledByNative; @@ -78,7 +77,6 @@ if (!isTalkbackRunning) return false; if (PackageUtils.getPackageVersion(context, TALKBACK_PACKAGE_NAME) < MIN_TALKBACK_VERSION - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && !sOldTalkBackVersionAlertShown) { showOldTalkbackVersionAlertOnce(context); return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/BookmarkUtils.java index 13f0a5ee..20dfcddf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/BookmarkUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/BookmarkUtils.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser; -import android.annotation.TargetApi; import android.app.ActivityManager; import android.content.Context; import android.content.Intent; @@ -22,7 +21,6 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.os.Build; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; @@ -153,14 +151,9 @@ return bitmap; } - @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) private static Bitmap getBitmapFromResourceId(Context context, int id, int density) { - Drawable drawable = null; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { - drawable = context.getResources().getDrawableForDensity(id, density); - } else { - drawable = ApiCompatibilityUtils.getDrawable(context.getResources(), id); - } + Drawable drawable = ApiCompatibilityUtils.getDrawableForDensity( + context.getResources(), id, density); if (drawable instanceof BitmapDrawable) { BitmapDrawable bd = (BitmapDrawable) drawable;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java index 26dcb5a..601a5a5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java
@@ -85,9 +85,7 @@ mAccessibilityRefreshString = contentViewCore.getContext().getResources().getString(resId); } - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { - mSwipeRefreshLayout.announceForAccessibility(mAccessibilityRefreshString); - } + mSwipeRefreshLayout.announceForAccessibility(mAccessibilityRefreshString); contentViewCore.getWebContents().getNavigationController().reload(true); } });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java index db202ccd..7806061a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
@@ -36,7 +36,6 @@ import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; import org.chromium.chrome.browser.contextmenu.ContextMenuPopulatorWrapper; import org.chromium.chrome.browser.contextmenu.EmptyChromeContextMenuItemDelegate; -import org.chromium.chrome.browser.dom_distiller.DomDistillerFeedbackReporter; import org.chromium.chrome.browser.fullscreen.FullscreenManager; import org.chromium.chrome.browser.infobar.InfoBarContainer; import org.chromium.chrome.browser.metrics.UmaSessionStats; @@ -181,7 +180,6 @@ private ContentViewClient mContentViewClient; private WebContentsObserver mWebContentsObserver; private TabChromeWebContentsDelegateAndroid mWebContentsDelegate; - private DomDistillerFeedbackReporter mDomDistillerFeedbackReporter; /** * If this tab was opened from another tab, store the id of the tab that @@ -1215,6 +1213,13 @@ } /** + * Called on the foreground tab when the Activity is stopped. + */ + public void onActivityStop() { + hide(); + } + + /** * Prepares the tab to be shown. This method is supposed to be called before the tab is * displayed. It restores the ContentView if it is not available after the cold start and * reloads the tab if its renderer has crashed. @@ -1597,9 +1602,7 @@ if (mInfoBarContainer == null) { // The InfoBarContainer needs to be created after the ContentView has been natively // initialized. - WebContents webContents = mContentViewCore.getWebContents(); - mInfoBarContainer = new InfoBarContainer( - mContext, getId(), mContentViewParent, webContents, this); + mInfoBarContainer = new InfoBarContainer(mContext, getId(), mContentViewParent, this); } else { mInfoBarContainer.onParentViewChanged(getId(), mContentViewParent); } @@ -1608,10 +1611,6 @@ mSwipeRefreshHandler = new SwipeRefreshHandler(mContext); mSwipeRefreshHandler.setContentViewCore(mContentViewCore); - if (DomDistillerFeedbackReporter.isEnabled() && mDomDistillerFeedbackReporter == null) { - mDomDistillerFeedbackReporter = new DomDistillerFeedbackReporter(this); - } - for (TabObserver observer : mObservers) observer.onContentChanged(this); // For browser tabs, we want to set accessibility focus to the page @@ -2157,8 +2156,9 @@ } /** This is currently called when committing a pre-rendered page. */ + @VisibleForTesting @CalledByNative - private void swapWebContents( + public void swapWebContents( WebContents webContents, boolean didStartLoad, boolean didFinishLoad) { ContentViewCore cvc = new ContentViewCore(mContext); ContentView cv = new ContentView(mContext, cvc); @@ -2219,11 +2219,6 @@ mNativeTabAndroid = nativePtr; } - @CalledByNative - private long getNativeInfoBarContainer() { - return getInfoBarContainer().getNative(); - } - /** * @return Whether the TabState representing this Tab has been updated. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java b/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java index 599420e..5f7bf580 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/WebsiteSettingsPopup.java
@@ -412,7 +412,7 @@ case ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION: return R.drawable.permission_location; case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: - return R.drawable.permission_media; + return R.drawable.permission_camera; case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: return R.drawable.permission_mic; case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java index 608b0b49..2e6df63 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenu.java
@@ -11,7 +11,6 @@ import android.content.res.Resources; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.os.Build; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; @@ -222,8 +221,7 @@ } // Don't animate the menu items for low end devices. - if (!SysUtils.isLowEndDevice() - && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (!SysUtils.isLowEndDevice()) { mPopup.getListView().addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java index e390e20..3735335 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java
@@ -205,6 +205,13 @@ } } + /** + * @return the ContentViewCore that this View is monitoring. + */ + protected ContentViewCore getContentViewCore() { + return mContentViewCore; + } + public void addToParentView(ViewGroup parentView) { if (parentView != null && parentView.indexOfChild(this) == -1) { parentView.addView(this, createLayoutParams()); @@ -646,7 +653,7 @@ PropertyValuesHolder.ofFloat("translationY", getTranslationY(), y)); mCurrentAnimation = new AnimatorSet(); - mCurrentAnimation.setDuration(duration); + mCurrentAnimation.setDuration(Math.max(duration, 0)); mCurrentAnimation.playTogether(alphaAnimator, translationXAnimator, translationYAnimator); mCurrentAnimation.addListener(mAnimatorListenerAdapter); mCurrentAnimation.setInterpolator(mInterpolator);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java index c75d3e7..ab25498 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -6,7 +6,6 @@ import android.content.Context; import android.net.MailTo; -import android.os.Build; import android.text.TextUtils; import android.view.ContextMenu; import android.view.MenuInflater; @@ -101,9 +100,6 @@ TemplateUrlService.getInstance() .getDefaultSearchEngineTemplateUrl().getShortName())); } - - menu.findItem(R.id.contextmenu_copy_image).setVisible( - Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerFeedbackReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerFeedbackReporter.java index f1a27a15..9af5839 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerFeedbackReporter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerFeedbackReporter.java
@@ -8,22 +8,13 @@ import org.chromium.base.CalledByNative; import org.chromium.base.JNINamespace; -import org.chromium.chrome.browser.ChromeVersionInfo; -import org.chromium.chrome.browser.EmptyTabObserver; -import org.chromium.chrome.browser.Tab; -import org.chromium.chrome.browser.TabObserver; -import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; -import org.chromium.content.browser.ContentViewCore; -import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.WindowAndroid; /** - * Java implementation of dom_distiller::android::FeedbackReporterAndroid. + * Java implementation of dom_distiller::android::ExternalFeedbackReporterAndroid. */ @JNINamespace("dom_distiller::android") -public final class DomDistillerFeedbackReporter implements - DomDistillerFeedbackReportingView.FeedbackObserver { - +public final class DomDistillerFeedbackReporter { private static ExternalFeedbackReporter sExternalFeedbackReporter = new NoOpExternalFeedbackReporter(); @@ -37,116 +28,6 @@ } } - private final long mNativePointer; - private final Tab mTab; - - private ContentViewCore mContentViewCore; - private DomDistillerFeedbackReportingView mReportingView; - - /** - * @return whether the DOM Distiller feature is enabled. - */ - public static boolean isEnabled() { - return (ChromeVersionInfo.isLocalBuild() || ChromeVersionInfo.isDevBuild()) - && nativeIsEnabled(); - } - - /** - * Creates the FeedbackReporter, adds itself as a TabObserver, and ensures - * references to ContentView and WebContents are up to date. - * - * @param tab the tab where the overlay should be displayed. - */ - public DomDistillerFeedbackReporter(Tab tab) { - mNativePointer = nativeInit(); - mTab = tab; - mTab.addObserver(createTabObserver()); - updatePointers(); - } - - @Override - public void onYesPressed(DomDistillerFeedbackReportingView view) { - if (view != mReportingView) return; - recordQuality(true); - dismissOverlay(); - } - - @Override - public void onNoPressed(DomDistillerFeedbackReportingView view) { - if (view != mReportingView) return; - recordQuality(false); - dismissOverlay(); - } - - /** - * Records feedback for the distilled content. - * - * @param good whether the perceived quality of the distillation of a web page was good. - */ - private void recordQuality(boolean good) { - nativeReportQuality(good); - if (!good) { - Activity activity = mTab.getWindowAndroid().getActivity().get(); - String url = DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl( - mContentViewCore.getWebContents().getUrl()); - sExternalFeedbackReporter.reportFeedback(activity, url, good); - } - } - - /** - * Start showing the overlay. - */ - @CalledByNative - private void showOverlay() { - mReportingView = DomDistillerFeedbackReportingView.create(mContentViewCore, this); - } - - /** - * Dismiss the overlay which is currently being displayed. - */ - @CalledByNative - private void dismissOverlay() { - if (mReportingView != null) { - mReportingView.dismiss(true); - mReportingView = null; - } - } - - /** - * Updates which ContentViewCore and WebContents the FeedbackReporter is monitoring. - */ - private void updatePointers() { - mContentViewCore = mTab.getContentViewCore(); - nativeReplaceWebContents(mNativePointer, mTab.getWebContents()); - } - - /** - * Creates a TabObserver for monitoring a Tab, used to react to changes in the ContentViewCore - * or to trigger its own destruction. - * - * @return TabObserver that can be used to monitor a Tab. - */ - private TabObserver createTabObserver() { - return new EmptyTabObserver() { - @Override - public void onWebContentsSwapped(Tab tab, boolean didStartLoad, - boolean didFinishLoad) { - updatePointers(); - } - - @Override - public void onContentChanged(Tab tab) { - updatePointers(); - } - - @Override - public void onDestroyed(Tab tab) { - nativeDestroy(mNativePointer); - mContentViewCore = null; - } - }; - } - /** * A static method for native code to call to call the external feedback form. * @param window WindowAndroid object to get an activity from. @@ -157,15 +38,4 @@ public static void reportFeedbackWithWindow(WindowAndroid window, String url, boolean good) { sExternalFeedbackReporter.reportFeedback(window.getActivity().get(), url, good); } - - private static native boolean nativeIsEnabled(); - - private static native void nativeReportQuality(boolean good); - - private native long nativeInit(); - - private native void nativeDestroy(long nativeFeedbackReporterAndroid); - - private native void nativeReplaceWebContents( - long nativeFeedbackReporterAndroid, WebContents webContents); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerFeedbackReportingView.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerFeedbackReportingView.java deleted file mode 100644 index 69c8a80c0..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerFeedbackReportingView.java +++ /dev/null
@@ -1,144 +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. - -package org.chromium.chrome.browser.dom_distiller; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; - -import org.chromium.chrome.R; -import org.chromium.chrome.browser.banners.SwipableOverlayView; -import org.chromium.chrome.browser.widget.ButtonCompat; -import org.chromium.content.browser.ContentViewCore; - -/** - * A view which displays a question to the user about the quality of distillation, where the user - * is given the option to respond. - * - * <p>The observer is called when the user makes a choice. After this point, it is not possible to - * interact with the view, and it is ready for dismissal. The selected option stays visibly - * selected. - */ -public class DomDistillerFeedbackReportingView extends SwipableOverlayView { - // XML layout for the BannerView. - private static final int VIEW_LAYOUT = R.layout.dom_distiller_feedback_reporting_view; - - // Class to alert about DomDistillerFeedbackReportingView events. - private FeedbackObserver mFeedbackObserver; - - // The button to click for selecting 'No'. - private ButtonCompat mNoButton; - - // The button to click for selecting 'Yes'. - private ButtonCompat mYesButton; - - // Whether a selection has already been made, which means new events should be ignored. - private boolean mSelectionMade; - - /** - * Called when the user makes a choice. After the call, it is not possible to interact further - * with the view. - */ - interface FeedbackObserver { - void onYesPressed(DomDistillerFeedbackReportingView view); - - void onNoPressed(DomDistillerFeedbackReportingView view); - } - - /** - * Creates a DomDistillerFeedbackReportingView and adds it to the given ContentViewCore. - * - * @param contentView ContentViewCore to display the DomDistillerFeedbackReportingView for. - * @param feedbackObserver Class that is alerted for DomDistillerFeedbackReportingView events. - * @return The created banner. - */ - public static DomDistillerFeedbackReportingView create(ContentViewCore contentViewCore, - FeedbackObserver feedbackObserver) { - Context context = contentViewCore.getContext(); - DomDistillerFeedbackReportingView view = - (DomDistillerFeedbackReportingView) LayoutInflater.from(context) - .inflate(VIEW_LAYOUT, null); - view.initialize(feedbackObserver); - view.setContentViewCore(contentViewCore); - view.addToParentView(contentViewCore.getContainerView()); - return view; - } - - /** - * Creates a DomDistillerFeedbackReportingView. - * - * @param context Context for acquiring resources. - * @param attrs Attributes from the XML layout inflation. - */ - public DomDistillerFeedbackReportingView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - private void initialize(FeedbackObserver feedbackObserver) { - mFeedbackObserver = feedbackObserver; - mNoButton = (ButtonCompat) findViewById(R.id.distillation_quality_answer_no); - mYesButton = (ButtonCompat) findViewById(R.id.distillation_quality_answer_yes); - mNoButton.setClickable(true); - mYesButton.setClickable(true); - mNoButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (mSelectionMade) return; - mSelectionMade = true; - disableUI(); - if (mFeedbackObserver != null) { - mFeedbackObserver.onNoPressed(DomDistillerFeedbackReportingView.this); - } - } - }); - mYesButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (mSelectionMade) return; - mSelectionMade = true; - disableUI(); - if (mFeedbackObserver != null) { - mFeedbackObserver.onYesPressed(DomDistillerFeedbackReportingView.this); - } - } - }); - } - - private void disableUI() { - // Clear OnClickListener to assure no more calls and that everything is cleaned up. - mNoButton.setOnClickListener(null); - mYesButton.setOnClickListener(null); - - // Disable the buttons, so the images for highlighted/non-highlighted will not change if the - // user continues to tap the buttons while it is dismissing. - mNoButton.setEnabled(false); - mYesButton.setEnabled(false); - } - - /** - * This is overridden since the method visibility is protected in the parent - * {@link SwipableOverlayView}. The {@link DomDistillerFeedbackReporter} needs to be able to - * dismiss this {@link DomDistillerFeedbackReportingView}, so by overriding this method in this - * class, it is callable from {@link DomDistillerFeedbackReporter}. - */ - @Override - protected boolean dismiss(boolean horizontally) { - return super.dismiss(horizontally); - } - - @Override - protected void onViewClicked() { - } - - @Override - protected void onViewPressed(MotionEvent event) { - } - - @Override - protected void onViewSwipedAway() { - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java index eb6776f..114f708 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -9,7 +9,7 @@ import android.content.Intent; import android.os.Bundle; import android.support.v4.view.ViewPager; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; @@ -36,7 +36,7 @@ * [Sign-in page] * The activity might be run more than once, e.g. 1) for ToS and sign-in, and 2) for intro. */ -public class FirstRunActivity extends ActionBarActivity implements FirstRunPageDelegate { +public class FirstRunActivity extends AppCompatActivity implements FirstRunPageDelegate { protected static final String TAG = "FirstRunActivity"; // Incoming parameters:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java index 73e7ef0..ba1021c6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -9,7 +9,6 @@ import android.animation.ObjectAnimator; import android.app.Activity; import android.content.res.Resources; -import android.os.Build; import android.os.Handler; import android.os.Message; import android.os.SystemClock; @@ -51,8 +50,7 @@ // Maximum length of the slide in/out animation of the toolbar (in ms). private static final long MAX_ANIMATION_DURATION_MS = 500; - private static final int MSG_ID_CONTROLS_REQUEST_LAYOUT = 1; - private static final int MSG_ID_HIDE_CONTROLS = 2; + private static final int MSG_ID_HIDE_CONTROLS = 1; private final HashSet<Integer> mPersistentControlTokens = new HashSet<Integer>(); @@ -166,9 +164,6 @@ ChromeFullscreenManager chromeFullscreenManager = mChromeFullscreenManager.get(); if (chromeFullscreenManager == null) return; switch (msg.what) { - case MSG_ID_CONTROLS_REQUEST_LAYOUT: - chromeFullscreenManager.mControlContainer.requestLayout(); - break; case MSG_ID_HIDE_CONTROLS: chromeFullscreenManager.update(false); break; @@ -505,14 +500,6 @@ scheduleVisibilityUpdate(); if (shouldShowAndroidControls()) mControlContainer.setTranslationY(getControlOffset()); - // In ICS, the toolbar can appear clipped when compositor content is not being drawn - // beneath it (at the top of the page, during side swipe). Requesting a layout clears - // up the issue (see crbug.com/172631). - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - if (!mHandler.hasMessages(MSG_ID_CONTROLS_REQUEST_LAYOUT)) { - mHandler.sendEmptyMessage(MSG_ID_CONTROLS_REQUEST_LAYOUT); - } - } for (int i = 0; i < mListeners.size(); i++) { mListeners.get(i).onVisibleContentOffsetChanged(getVisibleContentOffset()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AnimationHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AnimationHelper.java index af325f8..24cc0c9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AnimationHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AnimationHelper.java
@@ -9,8 +9,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; -import android.annotation.TargetApi; -import android.os.Build; import android.view.View; import android.view.ViewTreeObserver; import android.view.animation.AccelerateDecelerateInterpolator; @@ -217,15 +215,13 @@ mTargetWrapperView.startTransition(); } - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void onAnimationEnd(Animator animation) { mTargetWrapperView.finishTransition(); mContainer.finishTransition(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && mToShow != null - && (mAnimationType == ANIMATION_TYPE_SHOW - || mAnimationType == ANIMATION_TYPE_SWAP)) { + if (mToShow != null && (mAnimationType == ANIMATION_TYPE_SHOW + || mAnimationType == ANIMATION_TYPE_SWAP)) { TextView messageView = (TextView) mToShow.findViewById(R.id.infobar_message); if (messageView != null) { mToShow.announceForAccessibility(messageView.getText());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java index a87967e..45efdf3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarContainer.java
@@ -20,6 +20,7 @@ import org.chromium.chrome.browser.Tab; import org.chromium.chrome.browser.TabObserver; import org.chromium.chrome.browser.banners.SwipableOverlayView; +import org.chromium.content.browser.ContentViewCore; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.DeviceFormFactor; @@ -110,8 +111,7 @@ private Paint mTopBorderPaint; - public InfoBarContainer( - Context context, int tabId, ViewGroup parentView, WebContents webContents, Tab tab) { + public InfoBarContainer(Context context, int tabId, ViewGroup parentView, Tab tab) { super(context, null); tab.addObserver(getTabObserver()); setIsSwipable(false); @@ -144,7 +144,15 @@ // Chromium's InfoBarContainer may add an InfoBar immediately during this initialization // call, so make sure everything in the InfoBarContainer is completely ready beforehand. - mNativeInfoBarContainer = nativeInit(webContents); + mNativeInfoBarContainer = nativeInit(); + } + + @Override + public void setContentViewCore(ContentViewCore contentViewCore) { + super.setContentViewCore(contentViewCore); + if (getContentViewCore() != null) { + nativeSetWebContents(mNativeInfoBarContainer, contentViewCore.getWebContents()); + } } @Override @@ -519,10 +527,6 @@ return null; } - public long getNative() { - return mNativeInfoBarContainer; - } - /** * Sets whether the InfoBarContainer is allowed to auto-hide when the user scrolls the page. * Expected to be called when Touch Exploration is enabled. @@ -552,6 +556,8 @@ assert false; } - private native long nativeInit(WebContents webContents); + private native long nativeInit(); + private native void nativeSetWebContents( + long nativeInfoBarContainerAndroid, WebContents webContents); private native void nativeDestroy(long nativeInfoBarContainerAndroid); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java index efefcd61..a7404376 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
@@ -10,7 +10,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnPreDrawListener; @@ -29,7 +29,7 @@ /** * An activity that talks with application and activity level delegates for async initialization. */ -public abstract class AsyncInitializationActivity extends ActionBarActivity implements +public abstract class AsyncInitializationActivity extends AppCompatActivity implements ChromeActivityNativeDelegate, BrowserParts { private static final LaunchHistogram sBadIntentMetric = new LaunchHistogram("Launch.InvalidIntent");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControl.java b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControl.java index 196976fe..ab0bffa74 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/remote/LockScreenTransportControl.java
@@ -7,6 +7,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.os.Build; import android.util.Log; import android.view.KeyEvent; @@ -106,7 +107,7 @@ // wallpaper (which we set to the poster of the current video) when the phone is // locked. Also, once the minSdkVersion is updated in the manifest, get rid of the // code for older SDK versions. - if (android.os.Build.VERSION.SDK_INT < 18) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) { sInstance = new LockScreenTransportControlV16(context); } else { sInstance = new LockScreenTransportControlV18(context);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/MemoryUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/MemoryUma.java index 5deefaad..f52502f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/MemoryUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/MemoryUma.java
@@ -12,7 +12,6 @@ import static android.content.ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE; import static android.content.ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; -import android.os.Build; import android.os.SystemClock; import org.chromium.base.metrics.RecordHistogram; @@ -75,8 +74,6 @@ private static void memoryNotificationForeground(int notification) { assert notification >= 0 && notification < FOREGROUND_MAX; - // Before Jelly Bean we have only LowMemory foreground notification. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return; RecordHistogram.recordEnumeratedHistogram("MemoryAndroid.NotificationForeground", notification, FOREGROUND_MAX); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java index e3de19b..b5e8134 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java
@@ -8,15 +8,18 @@ import android.content.ComponentCallbacks; import android.content.Context; import android.content.res.Configuration; +import android.text.TextUtils; import org.chromium.base.ActivityState; import org.chromium.base.ApplicationStatus; import org.chromium.chrome.browser.Tab; +import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.privacy.CrashReportingPermissionManager; import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; +import org.chromium.components.variations.VariationsAssociatedData; import org.chromium.content_public.browser.WebContents; import org.chromium.net.NetworkChangeNotifier; @@ -102,6 +105,7 @@ nativeUmaResumeSession(sNativeUmaSessionStats); NetworkChangeNotifier.addConnectionTypeObserver(this); + updatePreferences(); updateMetricsServiceState(); } @@ -159,6 +163,32 @@ nativeUpdateMetricsServiceState(mayRecordStats, mayUploadStats); } + /** + * Updating Android preferences according to equivalent native preferences so that the values + * can be retrieved while native preferences are not accessible. + */ + private void updatePreferences() { + // Update cellular experiment preference. + PrivacyPreferencesManager prefManager = PrivacyPreferencesManager.getInstance(mContext); + boolean cellularExperiment = TextUtils.equals("true", + VariationsAssociatedData.getVariationParamValue( + "UMA_EnableCellularLogUpload", "Enabled")); + prefManager.setCellularExperiment(cellularExperiment); + + // Update metrics reporting preference. + if (cellularExperiment) { + PrefServiceBridge prefBridge = PrefServiceBridge.getInstance(); + // If the native preference metrics reporting has not been set, then initialize it + // based on the older android preference. + if (!prefBridge.hasSetMetricsReporting()) { + prefBridge.setMetricsReportingEnabled(prefManager.isUploadCrashDumpEnabled()); + } + + // Set new Android preference for usage and crash reporting. + prefManager.setUsageAndCrashReporting(prefBridge.isMetricsReportingEnabled()); + } + } + @Override public void onConnectionTypeChanged(int connectionType) { updateMetricsServiceState();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java index d336d84..6d2d8c5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
@@ -721,32 +721,61 @@ } /** - * @return Whether the camera/microphone permission is enabled. + * @return Whether the camera permission is enabled. */ - public boolean isCameraMicEnabled() { - return nativeGetCameraMicEnabled(); + public boolean isCameraEnabled() { + return nativeGetCameraEnabled(); } /** - * Sets the preferences on whether to enable/disable camera and microphone + * Sets the preferences on whether to enable/disable camera. */ - public void setCameraMicEnabled(boolean enabled) { - nativeSetCameraMicEnabled(enabled); + public void setCameraEnabled(boolean enabled) { + nativeSetCameraEnabled(enabled); } /** * @return Whether the camera/microphone permission is managed * by the custodian of the supervised account. */ - public boolean isCameraMicManagedByCustodian() { - return nativeGetCameraMicManagedByCustodian(); + public boolean isCameraManagedByCustodian() { + return nativeGetCameraManagedByCustodian(); } /** - * @return Whether the camera/microphone permission is editable by the user. + * @return Whether the camera permission is editable by the user. */ - public boolean isCameraMicUserModifiable() { - return nativeGetCameraMicUserModifiable(); + public boolean isCameraUserModifiable() { + return nativeGetCameraUserModifiable(); + } + + /** + * @return Whether the microphone permission is enabled. + */ + public boolean isMicEnabled() { + return nativeGetMicEnabled(); + } + + /** + * Sets the preferences on whether to enable/disable microphone. + */ + public void setMicEnabled(boolean enabled) { + nativeSetMicEnabled(enabled); + } + + /** + * @return Whether the microphone permission is managed by the custodian of + * the supervised account. + */ + public boolean isMicManagedByCustodian() { + return nativeGetMicManagedByCustodian(); + } + + /** + * @return Whether the microphone permission is editable by the user. + */ + public boolean isMicUserModifiable() { + return nativeGetMicUserModifiable(); } /** @@ -863,6 +892,28 @@ int contentSettingsType, List<ContentSettingException> list); public native void nativeSetContentSettingForPattern( int contentSettingType, String pattern, int setting); + + /** + * @return whether Metrics reporting is enabled. + */ + public boolean isMetricsReportingEnabled() { + return nativeGetMetricsReportingEnabled(); + } + + /** + * Sets whether the metrics reporting should be enabled. + */ + public void setMetricsReportingEnabled(boolean enabled) { + nativeSetMetricsReportingEnabled(enabled); + } + + /** + * @return whether the metrics reporting preference has been set by user. + */ + public boolean hasSetMetricsReporting() { + return nativeHasSetMetricsReporting(); + } + private native boolean nativeGetAcceptCookiesEnabled(); private native boolean nativeGetAcceptCookiesManaged(); private native boolean nativeGetBlockThirdPartyCookiesEnabled(); @@ -877,8 +928,14 @@ private native boolean nativeGetDoNotTrackEnabled(); private native boolean nativeGetPasswordEchoEnabled(); private native boolean nativeGetFirstRunEulaAccepted(); - private native boolean nativeGetCameraMicUserModifiable(); - private native boolean nativeGetCameraMicManagedByCustodian(); + private native boolean nativeGetCameraEnabled(); + private native void nativeSetCameraEnabled(boolean allow); + private native boolean nativeGetCameraUserModifiable(); + private native boolean nativeGetCameraManagedByCustodian(); + private native boolean nativeGetMicEnabled(); + private native void nativeSetMicEnabled(boolean allow); + private native boolean nativeGetMicUserModifiable(); + private native boolean nativeGetMicManagedByCustodian(); private native boolean nativeGetFullscreenAllowed(); private native boolean nativeGetFullscreenManaged(); private native boolean nativeGetTranslateEnabled(); @@ -911,11 +968,9 @@ private native boolean nativeGetAllowLocationEnabled(); private native boolean nativeGetPushNotificationsEnabled(); private native void nativeSetAllowLocationEnabled(boolean allow); - private native void nativeSetCameraMicEnabled(boolean allow); private native void nativeSetPushNotificationsEnabled(boolean allow); private native void nativeSetPasswordEchoEnabled(boolean enabled); private native void nativeSetPopupException(String pattern, int setting); - private native boolean nativeGetCameraMicEnabled(); private native boolean nativeGetAutologinEnabled(); private native void nativeSetAutologinEnabled(boolean autologinEnabled); private native void nativeSetCrashReporting(boolean reporting); @@ -945,4 +1000,7 @@ private native String nativeGetSupervisedUserSecondCustodianName(); private native String nativeGetSupervisedUserSecondCustodianEmail(); private native String nativeGetSupervisedUserSecondCustodianProfileImageURL(); + private native boolean nativeGetMetricsReportingEnabled(); + private native void nativeSetMetricsReportingEnabled(boolean enabled); + private native boolean nativeHasSetMetricsReporting(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/Preferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/Preferences.java index 5263580..5a96a317 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/Preferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/Preferences.java
@@ -18,7 +18,7 @@ import android.preference.PreferenceFragment; import android.preference.PreferenceFragment.OnPreferenceStartFragmentCallback; import android.support.v4.view.ViewCompat; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -37,7 +37,7 @@ * may freely modify its activity's action bar or title. This mimics the behavior of * android.preference.PreferenceActivity. */ -public abstract class Preferences extends ActionBarActivity implements +public abstract class Preferences extends AppCompatActivity implements OnPreferenceStartFragmentCallback { public static final String EXTRA_SHOW_FRAGMENT = "show_fragment";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferences.java index 289fdcc..9e6e7e74 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferences.java
@@ -10,6 +10,7 @@ import android.preference.Preference.OnPreferenceChangeListener; import android.preference.Preference.OnPreferenceClickListener; import android.preference.PreferenceFragment; +import android.preference.PreferenceScreen; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -46,6 +47,7 @@ "crash_dump_upload_no_cellular"; private static final String PREF_DO_NOT_TRACK = "do_not_track"; private static final String PREF_CLEAR_BROWSING_DATA = "clear_browsing_data"; + private static final String PREF_USAGE_AND_CRASH_REPORTING = "usage_and_crash_reports"; private ClearBrowsingDataDialogFragment mClearBrowsingDataDialogFragment; private ManagedPreferenceDelegate mManagedPreferenceDelegate; @@ -53,7 +55,9 @@ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - PrivacyPreferencesManager.getInstance(getActivity()).migrateNetworkPredictionPreferences(); + PrivacyPreferencesManager privacyPrefManager = + PrivacyPreferencesManager.getInstance(getActivity()); + privacyPrefManager.migrateNetworkPredictionPreferences(); addPreferencesFromResource(R.xml.privacy_preferences); getActivity().setTitle(R.string.prefs_privacy); setHasOptionsMenu(true); @@ -67,15 +71,15 @@ NetworkPredictionOptions networkPredictionOptions = PrefServiceBridge.getInstance() .getNetworkPredictionOptions(); - boolean isMobileNetworkCapable = - PrivacyPreferencesManager.getInstance(getActivity()).isMobileNetworkCapable(); + PreferenceScreen preferenceScreen = getPreferenceScreen(); + boolean isMobileNetworkCapable = privacyPrefManager.isMobileNetworkCapable(); if (isMobileNetworkCapable) { - getPreferenceScreen().removePreference(networkPredictionNoCellularPref); + preferenceScreen.removePreference(networkPredictionNoCellularPref); networkPredictionPref.setValue(networkPredictionOptions.enumToString()); networkPredictionPref.setOnPreferenceChangeListener(this); networkPredictionPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate); } else { - getPreferenceScreen().removePreference(networkPredictionPref); + preferenceScreen.removePreference(networkPredictionPref); networkPredictionNoCellularPref.setChecked( networkPredictionOptions != NetworkPredictionOptions.NETWORK_PREDICTION_NEVER); networkPredictionNoCellularPref.setOnPreferenceChangeListener(this); @@ -83,19 +87,28 @@ mManagedPreferenceDelegate); } + // Display the correct settings fragment according to the user experiment group and to type + // of the device, by removing not applicable preference fragments. CrashDumpUploadPreference uploadCrashDumpPref = (CrashDumpUploadPreference) findPreference(PREF_CRASH_DUMP_UPLOAD); ChromeBaseCheckBoxPreference uploadCrashDumpNoCellularPref = (ChromeBaseCheckBoxPreference) findPreference(PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR); - if (isMobileNetworkCapable) { - getPreferenceScreen().removePreference(uploadCrashDumpNoCellularPref); - uploadCrashDumpPref.setOnPreferenceChangeListener(this); - uploadCrashDumpPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate); + if (privacyPrefManager.isCellularExperimentEnabled()) { + preferenceScreen.removePreference(uploadCrashDumpNoCellularPref); + preferenceScreen.removePreference(uploadCrashDumpPref); } else { - getPreferenceScreen().removePreference(uploadCrashDumpPref); - uploadCrashDumpNoCellularPref.setOnPreferenceChangeListener(this); - uploadCrashDumpNoCellularPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate); + preferenceScreen.removePreference(findPreference(PREF_USAGE_AND_CRASH_REPORTING)); + if (isMobileNetworkCapable) { + preferenceScreen.removePreference(uploadCrashDumpNoCellularPref); + uploadCrashDumpPref.setOnPreferenceChangeListener(this); + uploadCrashDumpPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate); + } else { + preferenceScreen.removePreference(uploadCrashDumpPref); + uploadCrashDumpNoCellularPref.setOnPreferenceChangeListener(this); + uploadCrashDumpNoCellularPref.setManagedPreferenceDelegate( + mManagedPreferenceDelegate); + } } ChromeBaseCheckBoxPreference navigationErrorPref = @@ -109,7 +122,7 @@ searchSuggestionsPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate); if (!((Preferences) getActivity()).isContextualSearchEnabled()) { - getPreferenceScreen().removePreference(findPreference(PREF_CONTEXTUAL_SEARCH)); + preferenceScreen.removePreference(findPreference(PREF_CONTEXTUAL_SEARCH)); } ButtonPreference clearBrowsingData =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java index 10156b16..8d8bc99c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java
@@ -29,6 +29,8 @@ private static final String PREF_NETWORK_PREDICTIONS = "network_predictions"; private static final String PREF_BANDWIDTH_OLD = "prefetch_bandwidth"; private static final String PREF_BANDWIDTH_NO_CELLULAR_OLD = "prefetch_bandwidth_no_cellular"; + private static final String PREF_METRICS_REPORTING = "metrics_reporting"; + private static final String PREF_CELLULAR_EXPERIMENT = "cellular_experiment"; private static final String ALLOW_PRERENDER_OLD = "allow_prefetch"; private static PrivacyPreferencesManager sInstance; @@ -204,20 +206,65 @@ } /** - * Check whether to allow uploading crash dump. The option should be either - * "always upload", or "wifi only" with current connection being wifi/ethernet. + * Check whether to allow uploading usage and crash reporting. The option should be either + * "always upload", or "wifi only" with current connection being wifi/ethernet for the + * three-choice pref or ON for the new two-choice pref. * - * @return boolean to whether to allow uploading crash dump. + * @return boolean whether to allow uploading crash dump. */ private boolean allowUploadCrashDump() { - if (!isMobileNetworkCapable()) { - return mSharedPreferences.getBoolean(PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR, false); - } else { + if (isCellularExperimentEnabled()) return isUsageAndCrashReportingEnabled(); + + if (isMobileNetworkCapable()) { String option = mSharedPreferences.getString(PREF_CRASH_DUMP_UPLOAD, mCrashDumpNeverUpload); return option.equals(mCrashDumpAlwaysUpload) || (option.equals(mCrashDumpWifiOnlyUpload) && isWiFiOrEthernetNetwork()); } + + return mSharedPreferences.getBoolean(PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR, false); + } + + /** + * Check whether usage and crash reporting set to ON. Also initializes the new pref if + * necessary. + * + * @return boolean whether usage and crash reporting set to ON. + */ + public boolean isUsageAndCrashReportingEnabled() { + // If the preference is not set initialize it based on the old preference value. + if (!mSharedPreferences.contains(PREF_METRICS_REPORTING)) { + setUsageAndCrashReporting(isUploadCrashDumpEnabled()); + } + + return mSharedPreferences.getBoolean(PREF_METRICS_REPORTING, false); + } + + /** + * Sets the usage and crash reporting preference ON or OFF. + * + * @param enabled A boolean corresponding whether usage and crash reports uploads are allowed. + */ + public void setUsageAndCrashReporting(boolean enabled) { + mSharedPreferences.edit().putBoolean(PREF_METRICS_REPORTING, enabled).apply(); + } + + /** + * Sets whether cellular experiment is enabled or not. + */ + @VisibleForTesting + public void setCellularExperiment(boolean enabled) { + mSharedPreferences.edit().putBoolean(PREF_CELLULAR_EXPERIMENT, enabled).apply(); + } + + /** + * Checks whether user is assigned to experimental group for enabling new cellular uploads + * functionality. + * + * @return boolean whether user is assigned to experimental group. + */ + public boolean isCellularExperimentEnabled() { + return mSharedPreferences.getBoolean(PREF_CELLULAR_EXPERIMENT, false); } /** @@ -242,19 +289,27 @@ } /** - * Check whether crash dump upload preference is set to NEVER only. + * Check whether crash dump upload preference is disabled according to corresponding preference. * - * @return boolean {@code true} if the option is set to NEVER + * @return boolean {@code true} if the option is set to not send. */ public boolean isNeverUploadCrashDump() { - boolean option; + if (isCellularExperimentEnabled()) return !isUsageAndCrashReportingEnabled(); + return !isUploadCrashDumpEnabled(); + } + + /** + * Check whether crash dump upload preference is set to NEVER only. + * + * @return boolean {@code true} if the option is set to NEVER. + */ + public boolean isUploadCrashDumpEnabled() { if (isMobileNetworkCapable()) { - option = mSharedPreferences.getString(PREF_CRASH_DUMP_UPLOAD, mCrashDumpNeverUpload) - .equals(mCrashDumpNeverUpload); - } else { - option = !mSharedPreferences.getBoolean(PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR, false); + return !mSharedPreferences.getString(PREF_CRASH_DUMP_UPLOAD, mCrashDumpNeverUpload) + .equals(mCrashDumpNeverUpload); } - return option; + + return mSharedPreferences.getBoolean(PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR, false); } /** @@ -282,6 +337,9 @@ * {@link #allowUploadCrashDump()} should return {@code true}, * and the network should be connected as well. * + * This function should not result in a native call as it can be called in circumstances where + * natives are not guaranteed to be loaded. + * * @return boolean to whether to allow uploading crash dump now. */ @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/UsageAndCrashReportsPreferenceFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/UsageAndCrashReportsPreferenceFragment.java new file mode 100644 index 0000000..e414c5b --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/UsageAndCrashReportsPreferenceFragment.java
@@ -0,0 +1,65 @@ +// 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. + +package org.chromium.chrome.browser.preferences.privacy; + +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceFragment; + +import org.chromium.chrome.R; +import org.chromium.chrome.browser.preferences.ChromeSwitchPreference; +import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegate; +import org.chromium.chrome.browser.preferences.PrefServiceBridge; + +/** + * Fragment to manage the Usage and crash reports preference and to explain to + * the user what it does. + */ +public class UsageAndCrashReportsPreferenceFragment extends PreferenceFragment { + private static final String PREF_USAGE_AND_CRASH_REPORTS_SWITCH = + "usage_and_crash_reports_switch"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.usage_and_crash_reports_preferences); + getActivity().setTitle(R.string.usage_and_crash_reports_title); + initUsageAndCrashReportsSwitch(); + } + + private void initUsageAndCrashReportsSwitch() { + ChromeSwitchPreference usageAndCrashReportsSwitch = + (ChromeSwitchPreference) findPreference(PREF_USAGE_AND_CRASH_REPORTS_SWITCH); + boolean enabled = PrivacyPreferencesManager.getInstance(getActivity()) + .isUsageAndCrashReportingEnabled(); + usageAndCrashReportsSwitch.setChecked(enabled); + + usageAndCrashReportsSwitch.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + boolean enabled = (boolean) newValue; + PrivacyPreferencesManager privacyManager = + PrivacyPreferencesManager.getInstance(getActivity()); + + // Update new two-choice android and chromium preferences. + PrefServiceBridge.getInstance().setMetricsReportingEnabled(enabled); + privacyManager.setUsageAndCrashReporting(enabled); + + // Update old three-choice android and chromium preference. + PrefServiceBridge.getInstance().setCrashReporting(enabled); + privacyManager.initCrashUploadPreference(enabled); + return true; + } + }); + + usageAndCrashReportsSwitch.setManagedPreferenceDelegate(new ManagedPreferenceDelegate() { + @Override + public boolean isPreferenceControlledByPolicy(Preference preference) { + return PrefServiceBridge.getInstance().isCrashReportManaged(); + } + }); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/CameraInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/CameraInfo.java new file mode 100644 index 0000000..a720114 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/CameraInfo.java
@@ -0,0 +1,25 @@ +// 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. + +package org.chromium.chrome.browser.preferences.website; + +/** + * Camera information for a given origin. + */ +public class CameraInfo extends PermissionInfo { + public CameraInfo(String origin, String embedder) { + super(origin, embedder); + } + + protected int getNativePreferenceValue(String origin, String embedder) { + return WebsitePreferenceBridge.nativeGetCameraSettingForOrigin( + origin, embedder); + } + + protected void setNativePreferenceValue( + String origin, String embedder, int value) { + WebsitePreferenceBridge.nativeSetCameraSettingForOrigin( + origin, embedder, value); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentPreferences.java index 7eda61b0..06c96637 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentPreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentPreferences.java
@@ -25,11 +25,12 @@ implements OnPreferenceClickListener { // The keys for each category shown on the Site Settings page. static final String ALL_SITES_KEY = "website_settings"; + static final String CAMERA_KEY = "camera"; static final String COOKIES_KEY = "cookies"; static final String FULLSCREEN_KEY = "fullscreen"; static final String IMAGES_KEY = "images"; static final String LOCATION_KEY = "device_location"; - static final String CAMERA_AND_MIC_KEY = "use_camera_or_mic"; + static final String MICROPHONE_KEY = "microphone"; static final String JAVASCRIPT_KEY = "javascript"; static final String BLOCK_POPUPS_KEY = "block_popups"; static final String PUSH_NOTIFICATIONS_KEY = "push_notifications"; @@ -52,14 +53,16 @@ } private int keyToContentSettingsType(String key) { - if (COOKIES_KEY.equals(key)) { + if (CAMERA_KEY.equals(key)) { + return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA; + } else if (COOKIES_KEY.equals(key)) { return ContentSettingsType.CONTENT_SETTINGS_TYPE_COOKIES; } else if (FULLSCREEN_KEY.equals(key)) { return ContentSettingsType.CONTENT_SETTINGS_TYPE_FULLSCREEN; } else if (LOCATION_KEY.equals(key)) { return ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION; - } else if (CAMERA_AND_MIC_KEY.equals(key)) { - return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM; + } else if (MICROPHONE_KEY.equals(key)) { + return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC; } else if (IMAGES_KEY.equals(key)) { return ContentSettingsType.CONTENT_SETTINGS_TYPE_IMAGES; } else if (JAVASCRIPT_KEY.equals(key)) { @@ -90,10 +93,11 @@ websitePrefs.add(PROTECTED_CONTENT_KEY); } websitePrefs.add(COOKIES_KEY); - websitePrefs.add(CAMERA_AND_MIC_KEY); + websitePrefs.add(CAMERA_KEY); websitePrefs.add(FULLSCREEN_KEY); websitePrefs.add(IMAGES_KEY); websitePrefs.add(JAVASCRIPT_KEY); + websitePrefs.add(MICROPHONE_KEY); websitePrefs.add(PUSH_NOTIFICATIONS_KEY); websitePrefs.add(POPUPS_KEY); // Initialize the summary and icon for all preferences that have an @@ -103,12 +107,14 @@ boolean checked = false; if (LOCATION_KEY.equals(prefName)) { checked = LocationSettings.getInstance().areAllLocationSettingsEnabled(); - } else if (CAMERA_AND_MIC_KEY.equals(prefName)) { - checked = PrefServiceBridge.getInstance().isCameraMicEnabled(); + } else if (CAMERA_KEY.equals(prefName)) { + checked = PrefServiceBridge.getInstance().isCameraEnabled(); } else if (JAVASCRIPT_KEY.equals(prefName)) { checked = PrefServiceBridge.getInstance().javaScriptEnabled(); } else if (IMAGES_KEY.equals(prefName)) { checked = PrefServiceBridge.getInstance().imagesEnabled(); + } else if (MICROPHONE_KEY.equals(prefName)) { + checked = PrefServiceBridge.getInstance().isMicEnabled(); } else if (PROTECTED_CONTENT_KEY.equals(prefName)) { checked = PrefServiceBridge.getInstance().isProtectedMediaIdentifierEnabled(); } else if (COOKIES_KEY.equals(prefName)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java index 9f17a973..05e686fe6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/ContentSettingsResources.java
@@ -27,8 +27,10 @@ return R.drawable.permission_images; case ContentSettingsType.CONTENT_SETTINGS_TYPE_JAVASCRIPT: return R.drawable.permission_javascript; - case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM: - return R.drawable.permission_media; + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: + return R.drawable.permission_camera; + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: + return R.drawable.permission_mic; case ContentSettingsType.CONTENT_SETTINGS_TYPE_MIDI_SYSEX: return R.drawable.permission_midi; case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS: @@ -58,8 +60,10 @@ return R.string.images_permission_title; case ContentSettingsType.CONTENT_SETTINGS_TYPE_JAVASCRIPT: return R.string.javascript_permission_title; - case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM: - return R.string.website_settings_use_camera_or_mic; + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: + return R.string.website_settings_use_camera; + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: + return R.string.website_settings_use_mic; case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS: return R.string.push_notifications_permission_title; case ContentSettingsType.CONTENT_SETTINGS_TYPE_POPUPS: @@ -87,6 +91,10 @@ return R.string.images_permission_title; case ContentSettingsType.CONTENT_SETTINGS_TYPE_JAVASCRIPT: return R.string.javascript_permission_title; + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: + return R.string.camera_permission_title; + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: + return R.string.mic_permission_title; case ContentSettingsType.CONTENT_SETTINGS_TYPE_MIDI_SYSEX: return R.string.midi_sysex_permission_title; case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS: @@ -112,7 +120,8 @@ case ContentSettingsType.CONTENT_SETTINGS_TYPE_POPUPS: return ContentSetting.ALLOW; case ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION: - case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM: + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS: case ContentSettingsType.CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: return ContentSetting.ASK; @@ -134,7 +143,8 @@ case ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION: case ContentSettingsType.CONTENT_SETTINGS_TYPE_IMAGES: case ContentSettingsType.CONTENT_SETTINGS_TYPE_JAVASCRIPT: - case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM: + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS: case ContentSettingsType.CONTENT_SETTINGS_TYPE_POPUPS: case ContentSettingsType.CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER: @@ -195,8 +205,10 @@ return R.string.website_settings_category_cookie_allowed; case ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION: return R.string.website_settings_category_ask_before_accessing; - case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM: - return R.string.website_settings_category_ask_before_accessing_camera_mic; + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: + return R.string.website_settings_category_ask_before_accessing_camera; + case ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: + return R.string.website_settings_category_ask_before_accessing_mic; case ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS: return R.string.website_settings_category_ask_before_sending; default:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/MicrophoneInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/MicrophoneInfo.java new file mode 100644 index 0000000..d29c081a --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/MicrophoneInfo.java
@@ -0,0 +1,25 @@ +// 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. + +package org.chromium.chrome.browser.preferences.website; + +/** + * Microphone information for a given origin. + */ +public class MicrophoneInfo extends PermissionInfo { + public MicrophoneInfo(String origin, String embedder) { + super(origin, embedder); + } + + protected int getNativePreferenceValue(String origin, String embedder) { + return WebsitePreferenceBridge.nativeGetMicrophoneSettingForOrigin( + origin, embedder); + } + + protected void setNativePreferenceValue( + String origin, String embedder, int value) { + WebsitePreferenceBridge.nativeSetMicrophoneSettingForOrigin( + origin, embedder, value); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java index 807fb6e..31bd7c0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleWebsitePreferences.java
@@ -52,33 +52,34 @@ // Buttons: public static final String PREF_RESET_SITE = "reset_site_button"; // Website permissions (if adding new, see hasPermissionsPreferences and resetSite below): + public static final String PREF_CAMERA_CAPTURE_PERMISSION = "camera_permission_list"; public static final String PREF_COOKIES_PERMISSION = "cookies_permission_list"; public static final String PREF_FULLSCREEN_PERMISSION = "fullscreen_permission_list"; public static final String PREF_IMAGES_PERMISSION = "images_permission_list"; public static final String PREF_JAVASCRIPT_PERMISSION = "javascript_permission_list"; public static final String PREF_LOCATION_ACCESS = "location_access_list"; + public static final String PREF_MIC_CAPTURE_PERMISSION = "microphone_permission_list"; public static final String PREF_MIDI_SYSEX_PERMISSION = "midi_sysex_permission_list"; public static final String PREF_POPUP_PERMISSION = "popup_permission_list"; public static final String PREF_PROTECTED_MEDIA_IDENTIFIER_PERMISSION = "protected_media_identifier_permission_list"; public static final String PREF_PUSH_NOTIFICATIONS_PERMISSION = "push_notifications_list"; - public static final String PREF_VOICE_AND_VIDEO_CAPTURE_PERMISSION = - "voice_and_video_capture_permission_list"; // All permissions from the permissions preference category must be listed here. // TODO(mvanouwerkerk): Use this array in more places to reduce verbosity. private static final String[] PERMISSION_PREFERENCE_KEYS = { + PREF_CAMERA_CAPTURE_PERMISSION, PREF_COOKIES_PERMISSION, PREF_FULLSCREEN_PERMISSION, PREF_IMAGES_PERMISSION, PREF_JAVASCRIPT_PERMISSION, PREF_LOCATION_ACCESS, + PREF_MIC_CAPTURE_PERMISSION, PREF_MIDI_SYSEX_PERMISSION, PREF_POPUP_PERMISSION, PREF_PROTECTED_MEDIA_IDENTIFIER_PERMISSION, PREF_PUSH_NOTIFICATIONS_PERMISSION, - PREF_VOICE_AND_VIDEO_CAPTURE_PERMISSION }; // The website this page is displaying details about. @@ -195,13 +196,18 @@ other.getPushNotificationInfo(), origin)) { merged.setPushNotificationInfo(other.getPushNotificationInfo()); } - if (merged.getVoiceAndVideoCaptureInfo() == null - && other.getVoiceAndVideoCaptureInfo() != null) { - if (origin.equals(other.getVoiceAndVideoCaptureInfo().getOrigin()) - && (origin.equals(other.getVoiceAndVideoCaptureInfo().getEmbedderSafe()) - || "*".equals(other.getVoiceAndVideoCaptureInfo() - .getEmbedderSafe()))) { - merged.setVoiceAndVideoCaptureInfo(other.getVoiceAndVideoCaptureInfo()); + if (merged.getCameraInfo() == null && other.getCameraInfo() != null) { + if (origin.equals(other.getCameraInfo().getOrigin()) + && (origin.equals(other.getCameraInfo().getEmbedderSafe()) + || "*".equals(other.getCameraInfo().getEmbedderSafe()))) { + merged.setCameraInfo(other.getCameraInfo()); + } + } + if (merged.getMicrophoneInfo() == null && other.getMicrophoneInfo() != null) { + if (origin.equals(other.getMicrophoneInfo().getOrigin()) + && (origin.equals(other.getMicrophoneInfo().getEmbedderSafe()) + || "*".equals(other.getMicrophoneInfo().getEmbedderSafe()))) { + merged.setMicrophoneInfo(other.getMicrophoneInfo()); } } if (merged.getLocalStorageInfo() == null @@ -259,6 +265,8 @@ } } else if (PREF_RESET_SITE.equals(preference.getKey())) { preference.setOnPreferenceClickListener(this); + } else if (PREF_CAMERA_CAPTURE_PERMISSION.equals(preference.getKey())) { + setUpListPreference(preference, mSite.getCameraPermission()); } else if (PREF_COOKIES_PERMISSION.equals(preference.getKey())) { setUpListPreference(preference, mSite.getCookiePermission()); } else if (PREF_FULLSCREEN_PERMISSION.equals(preference.getKey())) { @@ -269,6 +277,8 @@ setUpListPreference(preference, mSite.getJavaScriptPermission()); } else if (PREF_LOCATION_ACCESS.equals(preference.getKey())) { setUpListPreference(preference, mSite.getGeolocationPermission()); + } else if (PREF_MIC_CAPTURE_PERMISSION.equals(preference.getKey())) { + setUpListPreference(preference, mSite.getMicrophonePermission()); } else if (PREF_MIDI_SYSEX_PERMISSION.equals(preference.getKey())) { setUpListPreference(preference, mSite.getMidiPermission()); } else if (PREF_POPUP_PERMISSION.equals(preference.getKey())) { @@ -277,8 +287,6 @@ setUpListPreference(preference, mSite.getProtectedMediaIdentifierPermission()); } else if (PREF_PUSH_NOTIFICATIONS_PERMISSION.equals(preference.getKey())) { setUpListPreference(preference, mSite.getPushNotificationPermission()); - } else if (PREF_VOICE_AND_VIDEO_CAPTURE_PERMISSION.equals(preference.getKey())) { - configureVoiceAndVideoPreference(preference); } } @@ -346,6 +354,8 @@ private int getContentSettingsTypeFromPreferenceKey(String preferenceKey) { switch (preferenceKey) { + case PREF_CAMERA_CAPTURE_PERMISSION: + return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA; case PREF_COOKIES_PERMISSION: return ContentSettingsType.CONTENT_SETTINGS_TYPE_COOKIES; case PREF_FULLSCREEN_PERMISSION: @@ -356,6 +366,8 @@ return ContentSettingsType.CONTENT_SETTINGS_TYPE_JAVASCRIPT; case PREF_LOCATION_ACCESS: return ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION; + case PREF_MIC_CAPTURE_PERMISSION: + return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC; case PREF_MIDI_SYSEX_PERMISSION: return ContentSettingsType.CONTENT_SETTINGS_TYPE_MIDI_SYSEX; case PREF_POPUP_PERMISSION: @@ -364,53 +376,11 @@ return ContentSettingsType.CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER; case PREF_PUSH_NOTIFICATIONS_PERMISSION: return ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS; - case PREF_VOICE_AND_VIDEO_CAPTURE_PERMISSION: - return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM; default: return 0; } } - /** - * Based on the type of media allowed or denied for this website, the title and summary - * of the CheckBoxPreference will change. If this website has no media related permission, then - * the preference will be removed. - * @param preference CheckboxPreference whose title and summary will be set. - */ - private void configureVoiceAndVideoPreference(Preference preference) { - ContentSetting voice = mSite.getVoiceCapturePermission(); - ContentSetting video = mSite.getVideoCapturePermission(); - if (voice == null && video == null) { - getPreferenceScreen().removePreference(preference); - return; - } - - int mediaAccessType = mSite.getMediaAccessType(); - switch (mediaAccessType) { - case Website.CAMERA_ACCESS_ALLOWED: - case Website.CAMERA_ACCESS_DENIED: - preference.setTitle(R.string.video_permission_title); - break; - case Website.MICROPHONE_ACCESS_ALLOWED: - case Website.MICROPHONE_ACCESS_DENIED: - preference.setTitle(R.string.voice_permission_title); - break; - case Website.MICROPHONE_AND_CAMERA_ACCESS_ALLOWED: - case Website.MICROPHONE_AND_CAMERA_ACCESS_DENIED: - preference.setTitle(R.string.voice_and_video_permission_title); - break; - case Website.INVALID_CAMERA_OR_MICROPHONE_ACCESS: - default: - getPreferenceScreen().removePreference(preference); - } - setUpListPreference( - preference, mediaAccessType == Website.CAMERA_ACCESS_ALLOWED - || mediaAccessType == Website.MICROPHONE_ACCESS_ALLOWED - || mediaAccessType == Website.MICROPHONE_AND_CAMERA_ACCESS_ALLOWED - ? ContentSetting.ALLOW : - ContentSetting.BLOCK); - } - @Override public void onClick(DialogInterface dialog, int which) { clearStoredData(); @@ -439,46 +409,13 @@ } } - private void setVoiceAndVideoCaptureSetting(ContentSetting value) { - int mediaAccessType = mSite.getMediaAccessType(); - if (value == ContentSetting.ALLOW) { - switch (mediaAccessType) { - case Website.CAMERA_ACCESS_DENIED: - mSite.setVideoCapturePermission(ContentSetting.ALLOW); - break; - case Website.MICROPHONE_ACCESS_DENIED: - mSite.setVoiceCapturePermission(ContentSetting.ALLOW); - break; - case Website.MICROPHONE_AND_CAMERA_ACCESS_DENIED: - mSite.setVideoCapturePermission(ContentSetting.ALLOW); - mSite.setVoiceCapturePermission(ContentSetting.ALLOW); - break; - default: - assert false; - } - } else { - switch (mediaAccessType) { - case Website.CAMERA_ACCESS_ALLOWED: - mSite.setVideoCapturePermission(ContentSetting.BLOCK); - break; - case Website.MICROPHONE_ACCESS_ALLOWED: - mSite.setVoiceCapturePermission(ContentSetting.BLOCK); - break; - case Website.MICROPHONE_AND_CAMERA_ACCESS_ALLOWED: - mSite.setVideoCapturePermission(ContentSetting.BLOCK); - mSite.setVoiceCapturePermission(ContentSetting.BLOCK); - break; - default: - assert false; - } - } - } - @Override public boolean onPreferenceChange(Preference preference, Object newValue) { ContentSetting permission = ContentSetting.fromString((String) newValue); - if (PREF_COOKIES_PERMISSION.equals(preference.getKey())) { + if (PREF_CAMERA_CAPTURE_PERMISSION.equals(preference.getKey())) { + mSite.setCameraPermission(permission); + } else if (PREF_COOKIES_PERMISSION.equals(preference.getKey())) { mSite.setCookiePermission(permission); } else if (PREF_FULLSCREEN_PERMISSION.equals(preference.getKey())) { mSite.setFullscreenPermission(permission); @@ -488,6 +425,8 @@ mSite.setJavaScriptPermission(permission); } else if (PREF_LOCATION_ACCESS.equals(preference.getKey())) { mSite.setGeolocationPermission(permission); + } else if (PREF_MIC_CAPTURE_PERMISSION.equals(preference.getKey())) { + mSite.setMicrophonePermission(permission); } else if (PREF_MIDI_SYSEX_PERMISSION.equals(preference.getKey())) { mSite.setMidiPermission(permission); } else if (PREF_POPUP_PERMISSION.equals(preference.getKey())) { @@ -496,8 +435,6 @@ mSite.setProtectedMediaIdentifierPermission(permission); } else if (PREF_PUSH_NOTIFICATIONS_PERMISSION.equals(preference.getKey())) { mSite.setPushNotificationPermission(permission); - } else if (PREF_VOICE_AND_VIDEO_CAPTURE_PERMISSION.equals(preference.getKey())) { - setVoiceAndVideoCaptureSetting(permission); } else { return true; } @@ -536,18 +473,18 @@ } // Clear the permissions. + mSite.setCameraPermission(null); mSite.setCookiePermission(null); WebsitePreferenceBridge.nativeClearCookieData(mSite.getAddress().getOrigin()); mSite.setFullscreenPermission(null); mSite.setGeolocationPermission(null); mSite.setImagesPermission(null); mSite.setJavaScriptPermission(null); + mSite.setMicrophonePermission(null); mSite.setMidiPermission(null); mSite.setPopupPermission(null); mSite.setProtectedMediaIdentifierPermission(null); mSite.setPushNotificationPermission(null); - mSite.setVideoCapturePermission(null); - mSite.setVoiceCapturePermission(null); // Clear the storage and finish the activity if necessary. if (mSite.getTotalUsage() > 0) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/VoiceAndVideoCaptureInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/VoiceAndVideoCaptureInfo.java deleted file mode 100644 index 1725d1c..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/VoiceAndVideoCaptureInfo.java +++ /dev/null
@@ -1,84 +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. - -package org.chromium.chrome.browser.preferences.website; - -import java.io.Serializable; - -/** - * This class represents voice and video capture permission information for requesting - * frame origin and embedding frame origin. - */ -public class VoiceAndVideoCaptureInfo implements Serializable { - - private final String mOrigin; - private final String mEmbedder; - - /** - * @param origin Requesting frame URL's origin for voice and video capture permission. - * @param embedder Embedding (top frame) frame URL's origin for voice and video capture - * permission. - */ - public VoiceAndVideoCaptureInfo(String origin, String embedder) { - mOrigin = origin; - mEmbedder = embedder; - } - - /** - * @return Requesting frame URL's origin for voice and video capture permission. - */ - public String getOrigin() { - return mOrigin; - } - - /** - * @return embedding frame URL's origin for voice and video capture permission. - */ - public String getEmbedder() { - return mEmbedder; - } - - /** - * @return Embedding frame origin for this permission. It it's null, returns origin. - */ - public String getEmbedderSafe() { - return mEmbedder != null ? mEmbedder : mOrigin; - } - - /** - * @return Whether audio is being captured. - */ - public ContentSetting getVoiceCapturePermission() { - return ContentSetting.fromInt( - WebsitePreferenceBridge.nativeGetVoiceCaptureSettingForOrigin( - mOrigin, getEmbedderSafe())); - } - - /** - * @return Whether video is being captured. - */ - public ContentSetting getVideoCapturePermission() { - return ContentSetting.fromInt( - WebsitePreferenceBridge.nativeGetVideoCaptureSettingForOrigin( - mOrigin, getEmbedderSafe())); - } - - /** - * Sets voice capture permission. - * @param value ALLOW to allow voice capture, BLOCK otherwise. - */ - public void setVoiceCapturePermission(ContentSetting value) { - WebsitePreferenceBridge.nativeSetVoiceCaptureSettingForOrigin( - mOrigin, getEmbedderSafe(), ContentSetting.toInt(value)); - } - - /** - * Sets video capture permission. - * @param value ALLOW to allow video capture, BLOCK otherwise. - */ - public void setVideoCapturePermission(ContentSetting value) { - WebsitePreferenceBridge.nativeSetVideoCaptureSettingForOrigin( - mOrigin, getEmbedderSafe(), ContentSetting.toInt(value)); - } -}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/Website.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/Website.java index 8f5bc2b..7eb3cca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/Website.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/Website.java
@@ -24,15 +24,16 @@ private final WebsiteAddress mAddress; private final String mTitle; private String mSummary; + private CameraInfo mCameraInfo; private CookieInfo mCookieInfo; private GeolocationInfo mGeolocationInfo; + private MicrophoneInfo mMicrophoneInfo; private MidiInfo mMidiInfo; private ContentSettingException mImagesException; private ContentSettingException mJavaScriptException; private ContentSettingException mPopupException; private ProtectedMediaIdentifierInfo mProtectedMediaIdentifierInfo; private PushNotificationInfo mPushNotificationInfo; - private VoiceAndVideoCaptureInfo mVoiceAndVideoCaptureInfo; private LocalStorageInfo mLocalStorageInfo; private final List<StorageInfo> mStorageInfo = new ArrayList<StorageInfo>(); private int mStorageInfoCallbacksLeft; @@ -296,85 +297,61 @@ } /** - * Sets voice and video capture info class. + * Sets camera capture info class. */ - public void setVoiceAndVideoCaptureInfo(VoiceAndVideoCaptureInfo info) { - mVoiceAndVideoCaptureInfo = info; + public void setCameraInfo(CameraInfo info) { + mCameraInfo = info; WebsiteAddress embedder = WebsiteAddress.create(info.getEmbedder()); if (embedder != null) { mSummary = embedder.getTitle(); } } - public VoiceAndVideoCaptureInfo getVoiceAndVideoCaptureInfo() { - return mVoiceAndVideoCaptureInfo; + public CameraInfo getCameraInfo() { + return mCameraInfo; } /** - * Returns what setting governs voice capture access. + * Sets microphone capture info class. */ - public ContentSetting getVoiceCapturePermission() { - return mVoiceAndVideoCaptureInfo != null - ? mVoiceAndVideoCaptureInfo.getVoiceCapturePermission() : null; - } - - /** - * Returns what setting governs video capture access. - */ - public ContentSetting getVideoCapturePermission() { - return mVoiceAndVideoCaptureInfo != null - ? mVoiceAndVideoCaptureInfo.getVideoCapturePermission() : null; - } - - /** - * Configure voice capture setting for this site. - */ - public void setVoiceCapturePermission(ContentSetting value) { - if (mVoiceAndVideoCaptureInfo != null) { - mVoiceAndVideoCaptureInfo.setVoiceCapturePermission(value); + public void setMicrophoneInfo(MicrophoneInfo info) { + mMicrophoneInfo = info; + WebsiteAddress embedder = WebsiteAddress.create(info.getEmbedder()); + if (embedder != null) { + mSummary = embedder.getTitle(); } } - /** - * Configure video capture setting for this site. - */ - public void setVideoCapturePermission(ContentSetting value) { - if (mVoiceAndVideoCaptureInfo != null) { - mVoiceAndVideoCaptureInfo.setVideoCapturePermission(value); - } + public MicrophoneInfo getMicrophoneInfo() { + return mMicrophoneInfo; } /** - * Returns the type of media that is being captured (audio/video/both). + * Returns what setting governs microphone capture access. */ - public int getMediaAccessType() { - ContentSetting voice = getVoiceCapturePermission(); - ContentSetting video = getVideoCapturePermission(); - if (video != null) { - if (voice == null) { - if (video == ContentSetting.ALLOW) { - return CAMERA_ACCESS_ALLOWED; - } else { - return CAMERA_ACCESS_DENIED; - } - } else { - if (video != voice) { - return INVALID_CAMERA_OR_MICROPHONE_ACCESS; - } - if (video == ContentSetting.ALLOW && voice == ContentSetting.ALLOW) { - return MICROPHONE_AND_CAMERA_ACCESS_ALLOWED; - } else { - return MICROPHONE_AND_CAMERA_ACCESS_DENIED; - } - } - } else { - if (voice == null) return INVALID_CAMERA_OR_MICROPHONE_ACCESS; - if (voice == ContentSetting.ALLOW) { - return MICROPHONE_ACCESS_ALLOWED; - } else { - return MICROPHONE_ACCESS_DENIED; - } - } + public ContentSetting getMicrophonePermission() { + return mMicrophoneInfo != null ? mMicrophoneInfo.getContentSetting() : null; + } + + /** + * Returns what setting governs camera capture access. + */ + public ContentSetting getCameraPermission() { + return mCameraInfo != null ? mCameraInfo.getContentSetting() : null; + } + + /** + * Configure microphone capture setting for this site. + */ + public void setMicrophonePermission(ContentSetting value) { + if (mMicrophoneInfo != null) mMicrophoneInfo.setContentSetting(value); + } + + /** + * Configure camera capture setting for this site. + */ + public void setCameraPermission(ContentSetting value) { + if (mCameraInfo != null) mCameraInfo.setContentSetting(value); } public void setLocalStorageInfo(LocalStorageInfo info) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java index ea0a665..34d7a1d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePermissionsFetcher.java
@@ -78,8 +78,10 @@ queue.add(new ProtectedMediaIdentifierInfoFetcher()); // Push notification permission is per-origin and per-embedder. queue.add(new PushNotificationInfoFetcher()); - // Voice and Video capture permission is per-origin and per-embedder. - queue.add(new VoiceAndVideoCaptureInfoFetcher()); + // Camera capture permission is per-origin and per-embedder. + queue.add(new CameraCaptureInfoFetcher()); + // Micropohone capture permission is per-origin and per-embedder. + queue.add(new MicrophoneCaptureInfoFetcher()); queue.add(new PermissionsAvailableCallbackRunner()); queue.next(); } @@ -112,9 +114,12 @@ } else if (filterHelper.showFullscreenSites(filter)) { // Local storage info is per-origin. queue.add(new FullscreenInfoFetcher()); - } else if (filterHelper.showCameraMicSites(filter)) { - // Voice and Video capture permission is per-origin and per-embedder. - queue.add(new VoiceAndVideoCaptureInfoFetcher()); + } else if (filterHelper.showCameraSites(filter)) { + // Camera capture permission is per-origin and per-embedder. + queue.add(new CameraCaptureInfoFetcher()); + } else if (filterHelper.showMicrophoneSites(filter)) { + // Micropohone capture permission is per-origin and per-embedder. + queue.add(new MicrophoneCaptureInfoFetcher()); } else if (filterHelper.showPopupSites(filter)) { // Popup exceptions are host-based patterns (unless we start // synchronizing popup exceptions with desktop Chrome.) @@ -364,14 +369,25 @@ } } - private class VoiceAndVideoCaptureInfoFetcher implements Task { + private class CameraCaptureInfoFetcher implements Task { @Override public void run(TaskQueue queue) { - for (VoiceAndVideoCaptureInfo info : - WebsitePreferenceBridge.getVoiceAndVideoCaptureInfo()) { + for (CameraInfo info : WebsitePreferenceBridge.getCameraInfo()) { WebsiteAddress address = WebsiteAddress.create(info.getOrigin()); if (address == null) continue; - createSiteByOriginAndHost(address).setVoiceAndVideoCaptureInfo(info); + createSiteByOriginAndHost(address).setCameraInfo(info); + } + queue.next(); + } + } + + private class MicrophoneCaptureInfoFetcher implements Task { + @Override + public void run(TaskQueue queue) { + for (MicrophoneInfo info : WebsitePreferenceBridge.getMicrophoneInfo()) { + WebsiteAddress address = WebsiteAddress.create(info.getOrigin()); + if (address == null) continue; + createSiteByOriginAndHost(address).setMicrophoneInfo(info); } queue.next(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreference.java index d4d0016..ab2f00f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreference.java
@@ -13,7 +13,6 @@ import android.preference.Preference; import android.text.format.Formatter; import android.view.View; -import android.widget.ImageView; import android.widget.TextView; import org.chromium.base.annotations.SuppressFBWarnings; @@ -147,17 +146,6 @@ } } - ImageView mediaCaptureIcon = (ImageView) view.findViewById( - R.id.voice_and_video_capture_icon); - mediaCaptureIcon.setVisibility(View.GONE); - if (mFilter.showCameraMicSites(mCategoryFilter)) { - int level = determineMediaIconToDisplay(mSite.getMediaAccessType()); - if (level > 0) { - mediaCaptureIcon.setImageLevel(level); - mediaCaptureIcon.setVisibility(View.VISIBLE); - } - } - float density = getContext().getResources().getDisplayMetrics().density; if (!mFaviconFetched) { // Start the favicon fetching. Will respond in onFaviconAvailable. @@ -177,30 +165,4 @@ View iconView = view.findViewById(android.R.id.icon); iconView.setPadding(iconPadding, iconPadding, iconPadding, iconPadding); } - - /** - * Converts type of media captured into level 0..4 to display the appropriate media icon. - * This level is used in the drawable website_voice_and_video_capture.xml to display the icon. - * 0 - Invalid - * 1 - Voice and video/only video allowed - display camera allowed icon - * 2 - Voice and video/only video denied - display camera denied icon - * 3 - Only voice allowed - display mic allowed icon - * 4 - Only voice denied - display mic denied icon - */ - private static int determineMediaIconToDisplay(int mediaAccessType) { - switch (mediaAccessType) { - case Website.CAMERA_ACCESS_ALLOWED: - case Website.MICROPHONE_AND_CAMERA_ACCESS_ALLOWED: - return 1; - case Website.CAMERA_ACCESS_DENIED: - case Website.MICROPHONE_AND_CAMERA_ACCESS_DENIED: - return 2; - case Website.MICROPHONE_ACCESS_ALLOWED: - return 3; - case Website.MICROPHONE_ACCESS_DENIED: - return 4; - default: - return 0; - } - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java index 3baa5e10..ceb7b6f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferenceBridge.java
@@ -137,30 +137,53 @@ } /** - * @return List of all the origin/embedder combinations of voice and video capture - * permissions. + * @return List of all the origin/embedder combinations of camera permissions. */ @SuppressWarnings("unchecked") - public static List<VoiceAndVideoCaptureInfo> getVoiceAndVideoCaptureInfo() { - ArrayList<VoiceAndVideoCaptureInfo> list = - new ArrayList<VoiceAndVideoCaptureInfo>(); - // Camera and Microphone can be managed by the custodian of a supervised account or - // by enterprise policy. - boolean managedOnly = !PrefServiceBridge.getInstance().isCameraMicUserModifiable(); - nativeGetVoiceAndVideoCaptureOrigins(list, managedOnly); + public static List<CameraInfo> getCameraInfo() { + ArrayList<CameraInfo> list = new ArrayList<CameraInfo>(); + // Camera can be managed by the custodian of a supervised account or by enterprise policy. + boolean managedOnly = !PrefServiceBridge.getInstance().isCameraUserModifiable(); + nativeGetCameraOrigins(list, managedOnly); return list; } @CalledByNative - private static void insertVoiceAndVideoCaptureInfoIntoList( - ArrayList<VoiceAndVideoCaptureInfo> list, String origin, String embedder) { + private static void insertCameraInfoIntoList( + ArrayList<CameraInfo> list, String origin, String embedder) { for (int i = 0; i < list.size(); i++) { if (list.get(i).getOrigin().equals(origin) && list.get(i).getEmbedder().equals(embedder)) { return; } } - list.add(new VoiceAndVideoCaptureInfo(origin, embedder)); + list.add(new CameraInfo(origin, embedder)); + } + + /** + * @return List of all the origin/embedder combinations of microphone permissions. + */ + @SuppressWarnings("unchecked") + public static List<MicrophoneInfo> getMicrophoneInfo() { + ArrayList<MicrophoneInfo> list = + new ArrayList<MicrophoneInfo>(); + // Microphone can be managed by the custodian of a supervised account or by enterprise + // policy. + boolean managedOnly = !PrefServiceBridge.getInstance().isMicUserModifiable(); + nativeGetMicrophoneOrigins(list, managedOnly); + return list; + } + + @CalledByNative + private static void insertMicrophoneInfoIntoList( + ArrayList<MicrophoneInfo> list, String origin, String embedder) { + for (int i = 0; i < list.size(); i++) { + if (list.get(i).getOrigin().equals(origin) + && list.get(i).getEmbedder().equals(embedder)) { + return; + } + } + list.add(new MicrophoneInfo(origin, embedder)); } public static List<ContentSettingException> getContentSettingsExceptions( @@ -226,13 +249,13 @@ String embedder); static native void nativeSetProtectedMediaIdentifierSettingForOrigin(String origin, String embedder, int value); - private static native void nativeGetVoiceAndVideoCaptureOrigins( - Object list, boolean managedOnly); - static native int nativeGetVoiceCaptureSettingForOrigin(String origin, String embedder); - static native int nativeGetVideoCaptureSettingForOrigin(String origin, String embedder); - static native void nativeSetVoiceCaptureSettingForOrigin(String origin, String embedder, + private static native void nativeGetCameraOrigins(Object list, boolean managedOnly); + private static native void nativeGetMicrophoneOrigins(Object list, boolean managedOnly); + static native int nativeGetMicrophoneSettingForOrigin(String origin, String embedder); + static native int nativeGetCameraSettingForOrigin(String origin, String embedder); + static native void nativeSetMicrophoneSettingForOrigin(String origin, String embedder, int value); - static native void nativeSetVideoCaptureSettingForOrigin(String origin, String embedder, + static native void nativeSetCameraSettingForOrigin(String origin, String embedder, int value); private static native void nativeGetCookieOrigins(Object list, boolean managedOnly); static native int nativeGetCookieSettingForOrigin(String origin, String embedder);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferences.java index cd4fdb59..bd32358 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsitePreferences.java
@@ -202,9 +202,8 @@ private boolean isOnBlockList(WebsitePreference website) { if (mFilter.showCookiesSites(mCategoryFilter)) { return website.site().getCookiePermission() == ContentSetting.BLOCK; - } else if (mFilter.showCameraMicSites(mCategoryFilter)) { - return website.site().getVoiceCapturePermission() == ContentSetting.BLOCK - || website.site().getVideoCapturePermission() == ContentSetting.BLOCK; + } else if (mFilter.showCameraSites(mCategoryFilter)) { + return website.site().getCameraPermission() == ContentSetting.BLOCK; } else if (mFilter.showFullscreenSites(mCategoryFilter)) { return website.site().getFullscreenPermission() == ContentSetting.ASK; } else if (mFilter.showGeolocationSites(mCategoryFilter)) { @@ -213,6 +212,8 @@ return website.site().getImagesPermission() == ContentSetting.BLOCK; } else if (mFilter.showJavaScriptSites(mCategoryFilter)) { return website.site().getJavaScriptPermission() == ContentSetting.BLOCK; + } else if (mFilter.showMicrophoneSites(mCategoryFilter)) { + return website.site().getMicrophonePermission() == ContentSetting.BLOCK; } else if (mFilter.showPopupSites(mCategoryFilter)) { return website.site().getPopupPermission() == ContentSetting.BLOCK; } else if (mFilter.showPushNotificationsSites(mCategoryFilter)) { @@ -355,14 +356,16 @@ } else if (mFilter.showCookiesSites(mCategoryFilter)) { PrefServiceBridge.getInstance().setAllowCookiesEnabled((boolean) newValue); updateThirdPartyCookiesCheckBox(); - } else if (mFilter.showCameraMicSites(mCategoryFilter)) { - PrefServiceBridge.getInstance().setCameraMicEnabled((boolean) newValue); + } else if (mFilter.showCameraSites(mCategoryFilter)) { + PrefServiceBridge.getInstance().setCameraEnabled((boolean) newValue); } else if (mFilter.showFullscreenSites(mCategoryFilter)) { PrefServiceBridge.getInstance().setFullscreenAllowed((boolean) newValue); } else if (mFilter.showImagesSites(mCategoryFilter)) { PrefServiceBridge.getInstance().setImagesEnabled((boolean) newValue); } else if (mFilter.showJavaScriptSites(mCategoryFilter)) { PrefServiceBridge.getInstance().setJavaScriptEnabled((boolean) newValue); + } else if (mFilter.showMicrophoneSites(mCategoryFilter)) { + PrefServiceBridge.getInstance().setMicEnabled((boolean) newValue); } else if (mFilter.showPopupSites(mCategoryFilter)) { PrefServiceBridge.getInstance().setAllowPopupsEnabled((boolean) newValue); } else if (mFilter.showPushNotificationsSites(mCategoryFilter)) { @@ -446,7 +449,7 @@ */ private boolean isCategoryManaged() { PrefServiceBridge prefs = PrefServiceBridge.getInstance(); - if (mFilter.showCameraMicSites(mCategoryFilter)) return !prefs.isCameraMicUserModifiable(); + if (mFilter.showCameraSites(mCategoryFilter)) return !prefs.isCameraUserModifiable(); if (mFilter.showCookiesSites(mCategoryFilter)) return prefs.isAcceptCookiesManaged(); if (mFilter.showFullscreenSites(mCategoryFilter)) return prefs.isFullscreenManaged(); if (mFilter.showGeolocationSites(mCategoryFilter)) { @@ -454,6 +457,7 @@ } if (mFilter.showImagesSites(mCategoryFilter)) return prefs.imagesManaged(); if (mFilter.showJavaScriptSites(mCategoryFilter)) return prefs.javaScriptManaged(); + if (mFilter.showMicrophoneSites(mCategoryFilter)) return !prefs.isMicUserModifiable(); if (mFilter.showPopupSites(mCategoryFilter)) return prefs.isPopupsManaged(); return false; } @@ -467,8 +471,11 @@ if (mFilter.showGeolocationSites(mCategoryFilter)) { return prefs.isAllowLocationManagedByCustodian(); } - if (mFilter.showCameraMicSites(mCategoryFilter)) { - return prefs.isCameraMicManagedByCustodian(); + if (mFilter.showCameraSites(mCategoryFilter)) { + return prefs.isCameraManagedByCustodian(); + } + if (mFilter.showMicrophoneSites(mCategoryFilter)) { + return prefs.isMicManagedByCustodian(); } return false; } @@ -570,11 +577,11 @@ if (isCategoryManaged() && !isCategoryManagedByCustodian()) { globalToggle.setIcon(R.drawable.controlled_setting_mandatory); } - if (mFilter.showGeolocationSites(mCategoryFilter)) { + if (mFilter.showCameraSites(mCategoryFilter)) { + globalToggle.setChecked(PrefServiceBridge.getInstance().isCameraEnabled()); + } else if (mFilter.showGeolocationSites(mCategoryFilter)) { globalToggle.setChecked( LocationSettings.getInstance().isChromeLocationSettingEnabled()); - } else if (mFilter.showCameraMicSites(mCategoryFilter)) { - globalToggle.setChecked(PrefServiceBridge.getInstance().isCameraMicEnabled()); } else if (mFilter.showCookiesSites(mCategoryFilter)) { globalToggle.setChecked( PrefServiceBridge.getInstance().isAcceptCookiesEnabled()); @@ -586,6 +593,8 @@ PrefServiceBridge.getInstance().imagesEnabled()); } else if (mFilter.showJavaScriptSites(mCategoryFilter)) { globalToggle.setChecked(PrefServiceBridge.getInstance().javaScriptEnabled()); + } else if (mFilter.showMicrophoneSites(mCategoryFilter)) { + globalToggle.setChecked(PrefServiceBridge.getInstance().isMicEnabled()); } else if (mFilter.showPopupSites(mCategoryFilter)) { globalToggle.setChecked(PrefServiceBridge.getInstance().popupsEnabled()); } else if (mFilter.showPushNotificationsSites(mCategoryFilter)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsiteSettingsCategoryFilter.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsiteSettingsCategoryFilter.java index b0b1bda..d47e251 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsiteSettingsCategoryFilter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/WebsiteSettingsCategoryFilter.java
@@ -12,15 +12,16 @@ public class WebsiteSettingsCategoryFilter { // The actual values for the keys for the category filter. private static final String FILTER_ALL_SITES = "all_sites"; + private static final String FILTER_CAMERA = "camera"; private static final String FILTER_COOKIES = "cookies"; - private static final String FILTER_CAMERA_MIC = "use_camera_or_mic"; - private static final String FILTER_JAVASCRIPT = "javascript"; private static final String FILTER_IMAGES = "images"; + private static final String FILTER_JAVASCRIPT = "javascript"; private static final String FILTER_DEVICE_LOCATION = "device_location"; private static final String FILTER_FULLSCREEN = "fullscreen"; - private static final String FILTER_USE_STORAGE = "use_storage"; + private static final String FILTER_MICROPHONE = "microphone"; private static final String FILTER_POPUPS = "popups"; public static final String FILTER_PUSH_NOTIFICATIONS = "push_notifications"; + private static final String FILTER_USE_STORAGE = "use_storage"; public WebsiteSettingsCategoryFilter() { } @@ -29,22 +30,24 @@ * Converts a category filter key (see above) to content settings enum. */ public int toContentSettingsType(String key) { - if (showCookiesSites(key)) { + if (showCameraSites(key)) { + return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA; + } else if (showCookiesSites(key)) { return ContentSettingsType.CONTENT_SETTINGS_TYPE_COOKIES; - } else if (showCameraMicSites(key)) { - return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM; - } else if (showPopupSites(key)) { - return ContentSettingsType.CONTENT_SETTINGS_TYPE_POPUPS; + } else if (showFullscreenSites(key)) { + return ContentSettingsType.CONTENT_SETTINGS_TYPE_FULLSCREEN; } else if (showGeolocationSites(key)) { return ContentSettingsType.CONTENT_SETTINGS_TYPE_GEOLOCATION; } else if (showImagesSites(key)) { return ContentSettingsType.CONTENT_SETTINGS_TYPE_IMAGES; - } else if (showPushNotificationsSites(key)) { - return ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS; } else if (showJavaScriptSites(key)) { return ContentSettingsType.CONTENT_SETTINGS_TYPE_JAVASCRIPT; - } else if (showFullscreenSites(key)) { - return ContentSettingsType.CONTENT_SETTINGS_TYPE_FULLSCREEN; + } else if (showMicrophoneSites(key)) { + return ContentSettingsType.CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC; + } else if (showPopupSites(key)) { + return ContentSettingsType.CONTENT_SETTINGS_TYPE_POPUPS; + } else if (showPushNotificationsSites(key)) { + return ContentSettingsType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS; } return -1; } @@ -59,18 +62,10 @@ /** * @param filterValue A category value. - * @return Whether the category passed is the cookies category. + * @return Whether the category passed is the camera category. */ - public boolean showCookiesSites(String filterValue) { - return filterValue.equals(FILTER_COOKIES); - } - - /** - * @param filterValue A category value. - * @return Whether the category passed is the camera/mic category. - */ - public boolean showCameraMicSites(String filterValue) { - return filterValue.equals(FILTER_CAMERA_MIC); + public boolean showCameraSites(String filterValue) { + return filterValue.equals(FILTER_CAMERA); } /** @@ -83,10 +78,10 @@ /** * @param filterValue A category value. - * @return Whether the category passed is the javascript category. + * @return Whether the category passed is the cookies category. */ - public boolean showJavaScriptSites(String filterValue) { - return filterValue.equals(FILTER_JAVASCRIPT); + public boolean showCookiesSites(String filterValue) { + return filterValue.equals(FILTER_COOKIES); } /** @@ -107,10 +102,18 @@ /** * @param filterValue A category value. - * @return Whether the category passed is the storage category. + * @return Whether the category passed is the javascript category. */ - public boolean showStorageSites(String filterValue) { - return filterValue.equals(FILTER_USE_STORAGE); + public boolean showJavaScriptSites(String filterValue) { + return filterValue.equals(FILTER_JAVASCRIPT); + } + + /** + * @param filterValue A category value. + * @return Whether the category passed is the microphone category. + */ + public boolean showMicrophoneSites(String filterValue) { + return filterValue.equals(FILTER_MICROPHONE); } /** @@ -128,4 +131,12 @@ public boolean showPushNotificationsSites(String filterValue) { return filterValue.equals(FILTER_PUSH_NOTIFICATIONS); } + + /** + * @param filterValue A category value. + * @return Whether the category passed is the storage category. + */ + public boolean showStorageSites(String filterValue) { + return filterValue.equals(FILTER_USE_STORAGE); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java index b7476118..b71fcfc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -6,6 +6,7 @@ import android.app.Activity; import android.app.AlertDialog; +import android.content.ClipData; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -253,6 +254,10 @@ intent.putExtra(Intent.EXTRA_TEXT, url); if (screenshotUri != null) { intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + // To give read access to an Intent target, we need to put |screenshotUri| in clipData + // because adding Intent.FLAG_GRANT_READ_URI_PERMISSION doesn't work for + // EXTRA_SHARE_SCREENSHOT_AS_STREAM. + intent.setClipData(ClipData.newRawUri("", screenshotUri)); intent.putExtra(EXTRA_SHARE_SCREENSHOT_AS_STREAM, screenshotUri); } return intent;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java index 6b59276..1c102ff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/AccountManagementFragment.java
@@ -502,15 +502,7 @@ } if (profileSyncService.isPassphraseRequiredForDecryption()) { - switch (profileSyncService.getPassphraseType()) { - case IMPLICIT_PASSPHRASE: - return res.getString(R.string.sync_need_password); - case FROZEN_IMPLICIT_PASSPHRASE: // Falling through intentionally. - case CUSTOM_PASSPHRASE: - return res.getString(R.string.sync_need_passphrase); - default: - break; - } + return res.getString(R.string.sync_need_passphrase); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java index 1e74bb8..2b78f53 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -280,9 +280,10 @@ */ public void startSignIn(Activity activity, final Account account, boolean passive, final SignInFlowObserver observer) { - assert mSignInActivity == null; - assert mSignInAccount == null; - assert mSignInFlowObserver == null; + if (mSignInAccount != null) { + Log.w(TAG, "Ignoring sign-in request as another sign-in request is pending."); + return; + } if (mFirstRunCheckIsPending) { Log.w(TAG, "Ignoring sign-in request until the First Run check completes."); @@ -395,6 +396,11 @@ } private void finishSignIn(AccountIdsAndNames accountIdsAndNames) { + if (mSignInAccount == null) { + Log.w(TAG, "Sign in request was canceled; aborting finishSignIn()."); + return; + } + // Cache the signed-in account name. ChromeSigninController.get(mContext).setSignedInAccountName(mSignInAccount.name);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java index b5268517..5bb26901 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
@@ -72,10 +72,7 @@ } else if (mProfileSyncService.isSyncInitialized() && mProfileSyncService.isPassphraseRequiredForDecryption()) { switch (mProfileSyncService.getPassphraseType()) { - case IMPLICIT_PASSPHRASE: - message = R.string.sync_need_password; - intent = createPasswordIntent(); - break; + case IMPLICIT_PASSPHRASE: // Falling through intentionally. case FROZEN_IMPLICIT_PASSPHRASE: // Falling through intentionally. case CUSTOM_PASSPHRASE: message = R.string.sync_need_passphrase;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java index 3277df8..284b3ec 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
@@ -76,63 +76,56 @@ LayoutInflater inflater = getActivity().getLayoutInflater(); View v = inflater.inflate(R.layout.sync_enter_passphrase, null); - boolean isGaia = getArguments().getBoolean(ARG_IS_GAIA); TextView promptText = (TextView) v.findViewById(R.id.prompt_text); final EditText passphrase = (EditText) v.findViewById(R.id.passphrase); final Context context = passphrase.getContext(); TextView resetText = (TextView) v.findViewById(R.id.reset_text); ProfileSyncService profileSyncService = ProfileSyncService.get(context); String accountName = profileSyncService.getCurrentSignedInAccountText() + "\n\n"; - if (isGaia) { - promptText.setText(accountName + context.getText( - R.string.sync_enter_google_passphrase)); - passphrase.setHint(R.string.sync_enter_google_passphrase_hint); - } else { - if (profileSyncService.hasExplicitPassphraseTime()) { - resetText.setText(SpanApplier.applySpans( - context.getString(R.string.sync_passphrase_reset_instructions), - new SpanInfo("<link>", "</link>", new ClickableSpan() { - @Override - public void onClick(View view) { - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse( - context.getText(R.string.sync_dashboard_url).toString())); - intent.putExtra(Browser.EXTRA_APPLICATION_ID, - context.getPackageName()); - intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); - intent.setPackage(context.getPackageName()); - context.startActivity(intent); - Activity activity = getActivity(); - if (activity != null) activity.finish(); - } - }))); - resetText.setMovementMethod(LinkMovementMethod.getInstance()); - resetText.setVisibility(View.VISIBLE); - PassphraseType passphraseType = profileSyncService.getPassphraseType(); - switch (passphraseType) { - case FROZEN_IMPLICIT_PASSPHRASE: - promptText.setText(accountName + profileSyncService - .getSyncEnterGooglePassphraseBodyWithDateText()); - break; - case CUSTOM_PASSPHRASE: - promptText.setText(accountName + profileSyncService - .getSyncEnterCustomPassphraseBodyWithDateText()); - break; - case IMPLICIT_PASSPHRASE: // Falling through intentionally. - case KEYSTORE_PASSPHRASE: // Falling through intentionally. - default: - Log.w(TAG, "Found incorrect passphrase type " - + passphraseType - + ". Falling back to default string."); - promptText.setText(accountName - + profileSyncService.getSyncEnterCustomPassphraseBodyText()); - break; - } - } else { - promptText.setText(accountName - + profileSyncService.getSyncEnterCustomPassphraseBodyText()); + resetText.setText(SpanApplier.applySpans( + context.getString(R.string.sync_passphrase_reset_instructions), + new SpanInfo("<link>", "</link>", new ClickableSpan() { + @Override + public void onClick(View view) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse( + context.getText(R.string.sync_dashboard_url).toString())); + intent.putExtra(Browser.EXTRA_APPLICATION_ID, + context.getPackageName()); + intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); + intent.setPackage(context.getPackageName()); + context.startActivity(intent); + Activity activity = getActivity(); + if (activity != null) activity.finish(); + } + }))); + resetText.setMovementMethod(LinkMovementMethod.getInstance()); + resetText.setVisibility(View.VISIBLE); + PassphraseType passphraseType = profileSyncService.getPassphraseType(); + if (profileSyncService.hasExplicitPassphraseTime()) { + switch (passphraseType) { + case FROZEN_IMPLICIT_PASSPHRASE: + promptText.setText(accountName + profileSyncService + .getSyncEnterGooglePassphraseBodyWithDateText()); + break; + case CUSTOM_PASSPHRASE: + promptText.setText(accountName + profileSyncService + .getSyncEnterCustomPassphraseBodyWithDateText()); + break; + case IMPLICIT_PASSPHRASE: // Falling through intentionally. + case KEYSTORE_PASSPHRASE: // Falling through intentionally. + default: + Log.w(TAG, "Found incorrect passphrase type " + + passphraseType + + ". Falling back to default string."); + promptText.setText(accountName + + profileSyncService.getSyncEnterCustomPassphraseBodyText()); + break; } - passphrase.setHint(R.string.sync_enter_custom_passphrase_hint); + } else { + promptText.setText(accountName + + profileSyncService.getSyncEnterCustomPassphraseBodyText()); } + passphrase.setHint(R.string.sync_enter_custom_passphrase_hint); passphrase.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java index d3f8549c..bf3117e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/SyncCustomizationFragment.java
@@ -292,13 +292,8 @@ return; } if (mProfileSyncService.isPassphraseRequiredForDecryption() && isAdded()) { - if (mProfileSyncService.isUsingSecondaryPassphrase()) { - mSyncEncryption.setSummary( - errorSummary(getString(R.string.sync_need_passphrase))); - } else { - mSyncEncryption.setSummary( - errorSummary(getString(R.string.sync_need_password))); - } + mSyncEncryption.setSummary( + errorSummary(getString(R.string.sync_need_passphrase))); } } @@ -434,11 +429,7 @@ @Override public void onPassphraseEntered(String passphrase, boolean isGaia, boolean isUpdate) { if (isUpdate) { - if (isGaia) { - handleEncryptWithGaia(passphrase); - } else { - handleEncryptWithCustomPassphrase(passphrase); - } + handleEncryptWithCustomPassphrase(passphrase); } else { handleDecryption(passphrase); } @@ -467,25 +458,13 @@ @Override public void onPassphraseTypeSelected(PassphraseType type) { boolean isAllDataEncrypted = mProfileSyncService.isEncryptEverythingEnabled(); - boolean isPassphraseGaia = !mProfileSyncService.isUsingSecondaryPassphrase(); + boolean isUsingSecondaryPassphrase = mProfileSyncService.isUsingSecondaryPassphrase(); - if (type == PassphraseType.IMPLICIT_PASSPHRASE) { - // custom passphrase -> gaia is not allowed - assert (isPassphraseGaia); - boolean isGaia = true; - boolean isUpdate = !isAllDataEncrypted; - displayPasswordDialog(isGaia, isUpdate); - } else if (type == PassphraseType.CUSTOM_PASSPHRASE) { - if (isPassphraseGaia) { - displayCustomPasswordDialog(); - } else { - // Now using the existing custom passphrase to encrypt - // everything. - boolean isGaia = false; - boolean isUpdate = false; - displayPasswordDialog(isGaia, isUpdate); - } - } + // The passphrase type should only ever be selected if the account doesn't have + // full encryption enabled. Otherwise both options should be disabled. + assert !isAllDataEncrypted; + assert !isUsingSecondaryPassphrase; + displayCustomPasswordDialog(); } /** @@ -500,7 +479,7 @@ } if (preference == mSyncEncryption && mProfileSyncService.isSyncInitialized()) { if (mProfileSyncService.isPassphraseRequiredForDecryption()) { - displayPasswordDialog(!mProfileSyncService.isUsingSecondaryPassphrase(), false); + displayPasswordDialog(false, false); } else { displayPasswordTypeDialog(); return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/ActivityDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/ActivityDelegate.java index e2ed4771..1274d25 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/ActivityDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/ActivityDelegate.java
@@ -91,8 +91,9 @@ if (!isValidActivity(isIncognito, intent)) continue; int tabId = getTabIdFromIntent(intent); + if (tabId == Tab.INVALID_TAB_ID) continue; + String initialUrl = getInitialUrlForDocument(intent); - if (tabId == Tab.INVALID_TAB_ID || initialUrl == null) continue; entries.add(new Entry(tabId, initialUrl)); } return entries;
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 69491e8..a31aa19 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -384,6 +384,17 @@ <message name="IDS_CAN_NOT_CLEAR_BROWSING_HISTORY_TOAST" desc="Message on the toast explaining that child account users can not clear their browsing history."> Browsing history can't be cleared with accounts for kids </message> + <message name="IDS_USAGE_AND_CRASH_REPORTS_TITLE" desc="Title for 'Usage and crash reports' preference"> + Usage and crash reports + </message> + <message name="IDS_USAGE_AND_CRASH_REPORTS_DESCRIPTION" desc="Description for 'Usage and crash reports' preference"> + Help us prioritize the features and improvements we should work on by sending Google information about the files, applications, and services running whenever you experience a crash. + + Usage statistics include information such as preferences, button clicks, and memory usage. They do not include webpage URLs or any personal information. Crash reports contain system information at the time of the crash, and may contain web page URLs or personal information, depending on what was happening at the time of the crash. + </message> + <message name="IDS_USAGE_AND_CRASH_REPORTS_LEARN_MORE_URL" desc="URL for learning more about 'Usage and crash reports' preference" translateable="false"> + https://support.google.com/chrome/answer/96817 + </message> <!-- Accessibility preferences --> <message name="IDS_PREFS_ACCESSIBILITY" desc="Title of Accessibility settings, which allows the user to change webpage font sizes. [CHAR-LIMIT=32]"> @@ -505,8 +516,11 @@ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_ASK_BEFORE_ACCESSING" desc="Summary text explaining that permission will be requested before accessing something, like location."> Ask before accessing (recommended) </message> - <message name="IDS_WEBSITE_SETTINGS_CATEGORY_ASK_BEFORE_ACCESSING_CAMERA_MIC" desc="Summary text explaining that permission will be requested before accessing the camera and microphone."> - Ask before accessing camera and microphone (recommended) + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_ASK_BEFORE_ACCESSING_CAMERA" desc="Summary text explaining that permission will be requested before accessing the camera."> + Ask before accessing camera (recommended) + </message> + <message name="IDS_WEBSITE_SETTINGS_CATEGORY_ASK_BEFORE_ACCESSING_MIC" desc="Summary text explaining that permission will be requested before accessing the microphone."> + Ask before accessing microphone (recommended) </message> <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_ALLOWED" desc="Summary text explaining that sites are allowed to use cookies and that it is the recommended setting."> Allow sites to save and read cookie data (recommended) @@ -559,13 +573,16 @@ </message> <!-- Camera and microphone preferences --> - <message name="IDS_WEBSITE_SETTINGS_USE_CAMERA_OR_MIC" desc="The category filter 'Camera/Mic' for content settings."> - Camera or microphone + <message name="IDS_WEBSITE_SETTINGS_USE_CAMERA" desc="The category filter 'Camera' for content settings."> + Camera </message> - <message name="IDS_VIDEO_PERMISSION_TITLE" desc="Title text to be shown when the user has allowed/denied video access for the website [CHAR-LIMIT=32]"> + <message name="IDS_WEBSITE_SETTINGS_USE_MIC" desc="The category filter 'Mic' for content settings."> + Microphone + </message> + <message name="IDS_CAMERA_PERMISSION_TITLE" desc="Title text to be shown when the user has allowed/denied video access for the website [CHAR-LIMIT=32]"> Access your camera </message> - <message name="IDS_VOICE_PERMISSION_TITLE" desc="Title text to be shown when the user has allowed/denied voice access for the website [CHAR-LIMIT=32]"> + <message name="IDS_MIC_PERMISSION_TITLE" desc="Title text to be shown when the user has allowed/denied voice access for the website [CHAR-LIMIT=32]"> Access your microphone </message> <message name="IDS_VOICE_AND_VIDEO_PERMISSION_TITLE" desc="Title text to be shown when the user has allowed/denied voice and video access for the website [CHAR-LIMIT=32]"> @@ -1212,15 +1229,6 @@ </message> <!-- DOM Distiller strings --> - <message name="IDS_DISTILLATION_QUALITY_QUESTION" desc="Question to ask the user about whether the text from a web page was extracted correctly."> - Was the text extracted correctly? - </message> - <message name="IDS_DISTILLATION_QUALITY_ANSWER_YES" desc="Text for the answering whether the text from a web page was extracted correctly and the answer is yes."> - Yes - </message> - <message name="IDS_DISTILLATION_QUALITY_ANSWER_NO" desc="Text for the answering whether the text from a web page was extracted correctly and the answer is no."> - No - </message> <message name="IDS_DARK_MODE" desc="Title of button that will change theme of distilled pages to dark mode."> Dark </message>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java index 84797e1..19bee2c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -35,10 +35,10 @@ @CommandLineFlags.Add(ChromeSwitches.ENABLE_APP_INSTALL_ALERTS) public class AppBannerManagerTest extends ChromeShellTestBase { private static final String NATIVE_APP_URL = - TestHttpServerClient.getUrl("chrome/test/data/android/banners/native_app_test.html"); + TestHttpServerClient.getUrl("chrome/test/data/banners/play_app_test_page.html"); private static final String NATIVE_ICON_URL = - TestHttpServerClient.getUrl("chrome/test/data/android/banners/native_app_test.png"); + TestHttpServerClient.getUrl("chrome/test/data/banners/launcher-icon-1x.png"); private static final String NATIVE_APP_TITLE = "Mock app title";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java index 4aa6745..8f827fe 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -7,7 +7,6 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; -import android.os.Build; import android.test.FlakyTest; import android.test.suitebuilder.annotation.MediumTest; import android.view.ContextMenu; @@ -96,8 +95,6 @@ // @MediumTest @Feature({"Browser"}) public void testCopyImageToClipboard() throws InterruptedException, TimeoutException { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return; - Tab tab = getActivity().getActiveTab(); ContextMenuUtils.selectContextMenuItem(this, tab, "testImage", R.id.contextmenu_copy_image);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java index 25b784f..1622226 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/infobar/InfoBarTest.java
@@ -9,8 +9,10 @@ import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.Smoke; +import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.UrlUtils; +import org.chromium.chrome.browser.ContentViewUtil; import org.chromium.chrome.browser.location.LocationSettingsTestUtil; import org.chromium.chrome.shell.ChromeShellTestBase; import org.chromium.chrome.test.util.InfoBarTestAnimationListener; @@ -18,9 +20,11 @@ import org.chromium.chrome.test.util.TestHttpServerClient; import org.chromium.content.browser.test.util.Criteria; import org.chromium.content.browser.test.util.CriteriaHelper; +import org.chromium.content_public.browser.WebContents; import java.util.List; +/** Tests for the InfoBars. */ public class InfoBarTest extends ChromeShellTestBase { private static final long MAX_TIMEOUT = scaleTimeout(2000); private static final int CHECK_INTERVAL = 500; @@ -41,6 +45,14 @@ super.setUp(); // Register for animation notifications + assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { + @Override + public boolean isSatisfied() { + if (getActivity().getActiveTab() == null) return false; + if (getActivity().getActiveTab().getInfoBarContainer() == null) return false; + return true; + } + })); InfoBarContainer container = getActivity().getActiveTab().getInfoBarContainer(); mListener = new InfoBarTestAnimationListener(); container.setAnimationListener(mListener); @@ -128,4 +140,41 @@ MAX_TIMEOUT, CHECK_INTERVAL); assertTrue("InfoBar not removed.", mListener.removeInfoBarAnimationFinished()); } + + /** + * Verify InfoBarContainers swap the WebContents they are monitoring properly. + */ + @MediumTest + @Feature({"Browser", "Main"}) + public void testInfoBarContainerSwapsWebContents() throws InterruptedException { + // Add an infobar. + LocationSettingsTestUtil.setSystemLocationSettingEnabled(true); + loadUrlWithSanitization(TestHttpServerClient.getUrl(GEOLOCATION_PAGE)); + assertTrue("InfoBar not added", mListener.addInfoBarAnimationFinished()); + List<InfoBar> infoBars = getActivity().getActiveTab().getInfoBarContainer().getInfoBars(); + assertEquals("Wrong infobar count", 1, infoBars.size()); + + // Swap out the WebContents and send the user somewhere so that the InfoBar gets removed. + InfoBarTestAnimationListener removeListener = new InfoBarTestAnimationListener(); + getActivity().getActiveTab().getInfoBarContainer().setAnimationListener(removeListener); + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + WebContents newContents = ContentViewUtil.createWebContents(false, false); + getActivity().getActiveTab().swapWebContents(newContents, false, false); + } + }); + loadUrlWithSanitization(HELLO_WORLD_URL); + assertTrue("InfoBar not removed.", removeListener.removeInfoBarAnimationFinished()); + infoBars = getActivity().getActiveTab().getInfoBarContainer().getInfoBars(); + assertEquals("Wrong infobar count", 0, infoBars.size()); + + // Revisiting the original page should make the InfoBar reappear. + InfoBarTestAnimationListener addListener = new InfoBarTestAnimationListener(); + getActivity().getActiveTab().getInfoBarContainer().setAnimationListener(addListener); + loadUrlWithSanitization(TestHttpServerClient.getUrl(GEOLOCATION_PAGE)); + assertTrue("InfoBar not added", addListener.addInfoBarAnimationFinished()); + infoBars = getActivity().getActiveTab().getInfoBarContainer().getInfoBars(); + assertEquals("Wrong infobar count", 1, infoBars.size()); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationUIManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationUIManagerTest.java index 7e14a0c5..b6534171 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationUIManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/notifications/NotificationUIManagerTest.java
@@ -16,7 +16,6 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.preferences.website.ContentSetting; import org.chromium.chrome.browser.preferences.website.PushNotificationInfo; import org.chromium.chrome.browser.widget.RoundedIconGenerator; @@ -36,7 +35,6 @@ * * Web Notifications are only supported on Android JellyBean and beyond. */ -@MinAndroidSdkLevel(Build.VERSION_CODES.JELLY_BEAN) public class NotificationUIManagerTest extends ChromeShellTestBase { private static final String NOTIFICATION_TEST_PAGE = TestHttpServerClient.getUrl("chrome/test/data/notifications/android_test.html");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManagerTest.java index 8bdaf3b1..99a2f43 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManagerTest.java
@@ -34,6 +34,13 @@ private static final UserUploadPreference UPLOAD_WIFI_ONLY = UserUploadPreference.WIFI_ONLY; private static final UserUploadPreference UPLOAD_NEVER = UserUploadPreference.NEVER; + private static final boolean EXPERIMENT_ENABLED = true; + private static final boolean EXPERIMENT_DISABLED = false; + private static final boolean METRIC_REPORTING_SET = true; + private static final boolean METRIC_REPORTING_NOT_SET = false; + private static final boolean METRIC_REPORTING_ENABLED = true; + private static final boolean METRIC_REPORTING_DISABLED = false; + // Perform the same test a few times to make sure any sort of // caching still works. private static final int REPS = 3; @@ -66,20 +73,50 @@ @UiThreadTest public void testAllowCrashDumpUploadNowCellDev() { CommandLine.init(null); - runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, UPLOAD_OK); - runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, DISCONNECTED, WIFI_ON, UPLOAD_NOT_PERMITTED); - runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_OFF, UPLOAD_OK); - runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, DISCONNECTED, WIFI_OFF, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_OK); + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, DISCONNECTED, WIFI_ON, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_OFF, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_OK); + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, DISCONNECTED, WIFI_OFF, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); - runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, CONNECTED, WIFI_ON, UPLOAD_OK); - runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, DISCONNECTED, WIFI_ON, UPLOAD_NOT_PERMITTED); - runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, CONNECTED, WIFI_OFF, UPLOAD_NOT_PERMITTED); - runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, DISCONNECTED, WIFI_OFF, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, CONNECTED, WIFI_ON, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_OK); + runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, DISCONNECTED, WIFI_ON, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, CONNECTED, WIFI_OFF, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, DISCONNECTED, WIFI_OFF, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); - runTest(CELLULAR_DEVICE, UPLOAD_NEVER, CONNECTED, WIFI_ON, UPLOAD_NOT_PERMITTED); - runTest(CELLULAR_DEVICE, UPLOAD_NEVER, DISCONNECTED, WIFI_ON, UPLOAD_NOT_PERMITTED); - runTest(CELLULAR_DEVICE, UPLOAD_NEVER, CONNECTED, WIFI_OFF, UPLOAD_NOT_PERMITTED); - runTest(CELLULAR_DEVICE, UPLOAD_NEVER, DISCONNECTED, WIFI_OFF, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_NEVER, CONNECTED, WIFI_ON, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_NEVER, DISCONNECTED, WIFI_ON, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_NEVER, CONNECTED, WIFI_OFF, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_NEVER, DISCONNECTED, WIFI_OFF, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_DISABLED, UPLOAD_OK); + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, DISCONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_DISABLED, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_WIFI_ONLY, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_DISABLED, UPLOAD_OK); + runTest(CELLULAR_DEVICE, UPLOAD_NEVER, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_SET, METRIC_REPORTING_ENABLED, UPLOAD_OK); + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_OFF, EXPERIMENT_ENABLED, + METRIC_REPORTING_SET, METRIC_REPORTING_ENABLED, UPLOAD_OK); + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_SET, METRIC_REPORTING_DISABLED, UPLOAD_NOT_PERMITTED); + runTest(CELLULAR_DEVICE, UPLOAD_ALWAYS, DISCONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); } @SmallTest @@ -87,24 +124,44 @@ @UiThreadTest public void testAllowCrashDumpUploadNowWifiDev() { CommandLine.init(null); - runTest(WIFI_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, UPLOAD_OK); - runTest(WIFI_DEVICE, UPLOAD_ALWAYS, DISCONNECTED, WIFI_OFF, UPLOAD_NOT_PERMITTED); + runTest(WIFI_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_OK); + runTest(WIFI_DEVICE, UPLOAD_ALWAYS, DISCONNECTED, WIFI_OFF, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); - runTest(WIFI_DEVICE, UPLOAD_NEVER, CONNECTED, WIFI_ON, UPLOAD_NOT_PERMITTED); - runTest(WIFI_DEVICE, UPLOAD_NEVER, DISCONNECTED, WIFI_OFF, UPLOAD_NOT_PERMITTED); + runTest(WIFI_DEVICE, UPLOAD_NEVER, CONNECTED, WIFI_ON, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + runTest(WIFI_DEVICE, UPLOAD_NEVER, DISCONNECTED, WIFI_OFF, EXPERIMENT_DISABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + + runTest(WIFI_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_OK); + runTest(WIFI_DEVICE, UPLOAD_NEVER, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_NOT_SET, METRIC_REPORTING_ENABLED, UPLOAD_NOT_PERMITTED); + + runTest(WIFI_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_SET, METRIC_REPORTING_ENABLED, UPLOAD_OK); + runTest(WIFI_DEVICE, UPLOAD_ALWAYS, CONNECTED, WIFI_ON, EXPERIMENT_ENABLED, + METRIC_REPORTING_SET, METRIC_REPORTING_DISABLED, UPLOAD_NOT_PERMITTED); } private void runTest(boolean mobileCapable, UserUploadPreference userPreference, - boolean isConnected, boolean wifiOn, boolean uploadPermitted) { + boolean isConnected, boolean wifiOn, boolean experimentEnabled, + boolean hasSetMetricsReporting, boolean isMetricsReportinEnabled, + boolean uploadPermitted) { PermissionContext context = new PermissionContext(getInstrumentation().getTargetContext()); PrivacyPreferencesManager preferenceManager = - new MockPrivacyPreferencesManager(context, mobileCapable, isConnected, wifiOn); + new MockPrivacyPreferencesManager(context, mobileCapable, isConnected, wifiOn, + hasSetMetricsReporting, isMetricsReportinEnabled); + preferenceManager.setCellularExperiment(experimentEnabled); for (int i = 0; i < REPS; i++) { setUpUserPreferences(context, userPreference); - String state = String.format( - "[cellular = %b, preference = %b, connected = %b, wifi = %b]", - mobileCapable, userPreference.toBooleanValue(), isConnected, wifiOn); + String state = + String.format("[cellular = %b, preference = %b, connected = %b, wifi = %b," + + "experiment = %b, reporting_set = %b, reporting = %b]", + mobileCapable, userPreference.toBooleanValue(), isConnected, wifiOn, + experimentEnabled, hasSetMetricsReporting, isMetricsReportinEnabled); boolean res = preferenceManager.isUploadPermitted(); if (uploadPermitted) { assertTrue("Upload should be permitted for " + state, res); @@ -130,11 +187,13 @@ private final boolean mIsWifi; MockPrivacyPreferencesManager(Context context, boolean isMobileCapable, boolean isConnected, - boolean isWifi) { + boolean isWifi, boolean hasSetMetricsReporting, boolean isMetricsReportinEnabled) { super(context); mIsMobileCapable = isMobileCapable; mIsConnected = isConnected; mIsWifi = isWifi; + + if (hasSetMetricsReporting) setUsageAndCrashReporting(isMetricsReportinEnabled); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/ContentPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/ContentPreferencesTest.java index 5422f59c..969df3f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/ContentPreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/ContentPreferencesTest.java
@@ -9,7 +9,9 @@ import android.test.suitebuilder.annotation.SmallTest; import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; +import org.chromium.chrome.ChromeSwitches; import org.chromium.chrome.browser.infobar.InfoBar; import org.chromium.chrome.browser.infobar.InfoBarContainer; import org.chromium.chrome.browser.location.LocationSettingsTestUtil; @@ -198,9 +200,9 @@ preferenceActivity.finish(); } - private void setEnableCameraMic(final boolean enabled) { + private void setEnableCamera(final boolean enabled) { final Preferences preferenceActivity = - startContentSettingsCategory(ContentPreferences.CAMERA_AND_MIC_KEY); + startContentSettingsCategory(ContentPreferences.CAMERA_KEY); ThreadUtils.runOnUiThread(new Runnable() { @Override @@ -210,13 +212,31 @@ ChromeSwitchPreference toggle = (ChromeSwitchPreference) websitePreferences.findPreference(WebsitePreferences.READ_WRITE_TOGGLE_KEY); websitePreferences.onPreferenceChange(toggle, enabled); - assertEquals("Camera/Mic should be " + (enabled ? "allowed" : "blocked"), - enabled, PrefServiceBridge.getInstance().isCameraMicEnabled()); + assertEquals("Camera should be " + (enabled ? "allowed" : "blocked"), + enabled, PrefServiceBridge.getInstance().isCameraEnabled()); } }); preferenceActivity.finish(); } + private void setEnableMic(final boolean enabled) { + final Preferences preferenceActivity = + startContentSettingsCategory(ContentPreferences.MICROPHONE_KEY); + + ThreadUtils.runOnUiThread(new Runnable() { + @Override + public void run() { + WebsitePreferences websitePreferences = + (WebsitePreferences) preferenceActivity.getFragmentForTest(); + ChromeSwitchPreference toggle = (ChromeSwitchPreference) + websitePreferences.findPreference(WebsitePreferences.READ_WRITE_TOGGLE_KEY); + websitePreferences.onPreferenceChange(toggle, enabled); + assertEquals("Mic should be " + (enabled ? "allowed" : "blocked"), + enabled, PrefServiceBridge.getInstance().isMicEnabled()); + } + }); + preferenceActivity.finish(); + } /** * Tests that disabling cookies turns off the third-party cookie toggle. * @throws Exception @@ -342,36 +362,76 @@ } /** - * Sets Allow Camera/Mic Enabled to be false and make sure it is set correctly. + * Sets Allow Camera Enabled to be false and make sure it is set correctly. * @throws Exception */ @SmallTest @Feature({"Preferences"}) - public void testCameraMicBlocked() throws Exception { - setEnableCameraMic(false); + @CommandLineFlags.Add(ChromeSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM) + public void testCameraBlocked() throws Exception { + setEnableCamera(false); // Test that the camera permission doesn't get requested. loadUrl(TestHttpServerClient.getUrl("content/test/data/media/getusermedia.html")); - runJavaScriptCodeInCurrentTab("getUserMediaAndStop({video: true, audio: true});"); + runJavaScriptCodeInCurrentTab("getUserMediaAndStop({video: true, audio: false});"); // No infobars are expected. assertTrue(getInfoBars().isEmpty()); } /** - * Sets Allow Camera/Mic Enabled to be true and make sure it is set correctly. + * Sets Allow Mic Enabled to be false and make sure it is set correctly. * @throws Exception */ @SmallTest @Feature({"Preferences"}) - public void testCameraMicNotBlocked() throws Exception { - setEnableCameraMic(true); + @CommandLineFlags.Add(ChromeSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM) + public void testMicBlocked() throws Exception { + setEnableMic(false); + + // Test that the microphone permission doesn't get requested. + loadUrl(TestHttpServerClient.getUrl("content/test/data/media/getusermedia.html")); + runJavaScriptCodeInCurrentTab("getUserMediaAndStop({video: false, audio: true});"); + + // No infobars are expected. + assertTrue(getInfoBars().isEmpty()); + } + + /** + * Sets Allow Camera Enabled to be true and make sure it is set correctly. + * @throws Exception + */ + @SmallTest + @Feature({"Preferences"}) + @CommandLineFlags.Add(ChromeSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM) + public void testCameraNotBlocked() throws Exception { + setEnableCamera(true); InfoBarTestAnimationListener listener = setInfoBarAnimationListener(); - // Launch a page that use geolocation and make sure an infobar shows up. + // Launch a page that uses camera and make sure an infobar shows up. loadUrl(TestHttpServerClient.getUrl("content/test/data/media/getusermedia.html")); - runJavaScriptCodeInCurrentTab("getUserMediaAndStop({video: true, audio: true});"); + runJavaScriptCodeInCurrentTab("getUserMediaAndStop({video: true, audio: false});"); + + assertTrue("InfoBar not added.", listener.addInfoBarAnimationFinished()); + assertEquals("Wrong infobar count", 1, getInfoBars().size()); + } + + /** + * Sets Allow Mic Enabled to be true and make sure it is set correctly. + * @throws Exception + */ + @SmallTest + @Feature({"Preferences"}) + @CommandLineFlags.Add(ChromeSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM) + public void testMicNotBlocked() throws Exception { + setEnableCamera(true); + + InfoBarTestAnimationListener listener = setInfoBarAnimationListener(); + + // Launch a page that uses the microphone and make sure an infobar shows up. + loadUrl(TestHttpServerClient.getUrl("content/test/data/media/getusermedia.html")); + runJavaScriptCodeInCurrentTab("getUserMediaAndStop({video: false, audio: true});"); assertTrue("InfoBar not added.", listener.addInfoBarAnimationFinished()); assertEquals("Wrong infobar count", 1, getInfoBars().size());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/WebsiteAddressTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/WebsiteAddressTest.java index 1d875d8..0ed68ca 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/WebsiteAddressTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/website/WebsiteAddressTest.java
@@ -4,21 +4,16 @@ package org.chromium.chrome.browser.preferences.website; -import android.os.Build; import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.Smoke; import org.chromium.base.CommandLine; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.content.browser.test.NativeLibraryTestBase; /** * Tests for WebsiteAddress. - * loadNativeLibraryAndInitBrowserProcess seems to be flaky on ICS. - * http://crbug.com/431717 */ -@MinAndroidSdkLevel(Build.VERSION_CODES.JELLY_BEAN) public class WebsiteAddressTest extends NativeLibraryTestBase { @Smoke
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/printing/PrintingControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/printing/PrintingControllerTest.java index 8c906c6..74258a1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/printing/PrintingControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/printing/PrintingControllerTest.java
@@ -196,7 +196,6 @@ } } - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) private void callLayoutOnUiThread( final PrintingControllerImpl controller, final PrintAttributes oldAttributes,
diff --git a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java index d167e5d1..b17e47a 100644 --- a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java +++ b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java
@@ -10,7 +10,7 @@ import android.content.Intent; import android.os.Bundle; import android.provider.Browser; -import android.support.v7.app.ActionBarActivity; +import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; @@ -32,6 +32,7 @@ import org.chromium.chrome.browser.DevToolsServer; import org.chromium.chrome.browser.FileProviderHelper; import org.chromium.chrome.browser.Tab; +import org.chromium.chrome.browser.WarmupManager; import org.chromium.chrome.browser.WebsiteSettingsPopup; import org.chromium.chrome.browser.appmenu.AppMenuHandler; import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate; @@ -65,7 +66,7 @@ /** * The {@link android.app.Activity} component of a basic test shell to test Chrome features. */ -public class ChromeShellActivity extends ActionBarActivity implements AppMenuPropertiesDelegate { +public class ChromeShellActivity extends AppCompatActivity implements AppMenuPropertiesDelegate { private static final String TAG = "ChromeShellActivity"; /** @@ -82,8 +83,7 @@ new ActivityWindowAndroidFactory() { @Override public ActivityWindowAndroid getActivityWindowAndroid(Activity activity) { - final boolean listenToActivityState = true; - return new ActivityWindowAndroid(activity, listenToActivityState); + return new ActivityWindowAndroid(activity); } }; @@ -125,6 +125,11 @@ DeviceUtils.addDeviceSpecificUserAgentSwitch(this); + String url = getUrlFromIntent(getIntent()); + if (url != null) { + WarmupManager.getInstance().maybePrefetchDnsForUrlInBackground(this, url); + } + BrowserStartupController.StartupCallback callback = new BrowserStartupController.StartupCallback() { @Override @@ -273,6 +278,9 @@ super.onStop(); if (mToolbar != null) mToolbar.hideSuggestions(); + + Tab activeTab = getActiveTab(); + if (activeTab != null) activeTab.onActivityStop(); } @Override
diff --git a/chrome/android/shell/java/src/org/chromium/chrome/shell/TabManager.java b/chrome/android/shell/java/src/org/chromium/chrome/shell/TabManager.java index 54afde0..0ebb99f 100644 --- a/chrome/android/shell/java/src/org/chromium/chrome/shell/TabManager.java +++ b/chrome/android/shell/java/src/org/chromium/chrome/shell/TabManager.java
@@ -175,6 +175,11 @@ public void onToggleFullscreenMode(Tab tab, boolean enable) { mToolbar.setVisibility(enable ? GONE : VISIBLE); } + + @Override + public void onContentChanged(Tab tab) { + setupContent(); + } }); return tab; }
diff --git a/chrome/android/shell/javatests/AndroidManifest.xml b/chrome/android/shell/javatests/AndroidManifest.xml index b36520a9..8bdb6446 100644 --- a/chrome/android/shell/javatests/AndroidManifest.xml +++ b/chrome/android/shell/javatests/AndroidManifest.xml
@@ -17,6 +17,9 @@ <provider android:name="org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsDelayedProvider" android:authorities="org.chromium.chrome.test.partnercustomizations.TestPartnerBrowserCustomizationsDelayedProvider" /> + <activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker" + android:exported="true"/> + <activity android:name="org.chromium.sync.test.util.MockGrantCredentialsPermissionActivity" android:exported="false"> <intent-filter>
diff --git a/chrome/app/chrome_crash_reporter_client.h b/chrome/app/chrome_crash_reporter_client.h index 667f22e..ebc1dd9 100644 --- a/chrome/app/chrome_crash_reporter_client.h +++ b/chrome/app/chrome_crash_reporter_client.h
@@ -27,25 +27,24 @@ const std::string& client_guid) override; #endif #if defined(OS_WIN) - virtual bool GetAlternativeCrashDumpLocation(base::FilePath* crash_dir) - override; - virtual void GetProductNameAndVersion(const base::FilePath& exe_path, - base::string16* product_name, - base::string16* version, - base::string16* special_build, - base::string16* channel_name) override; - virtual bool ShouldShowRestartDialog(base::string16* title, - base::string16* message, - bool* is_rtl_locale) override; - virtual bool AboutToRestart() override; - virtual bool GetDeferredUploadsSupported(bool is_per_user_install) override; - virtual bool GetIsPerUserInstall(const base::FilePath& exe_path) override; - virtual bool GetShouldDumpLargerDumps(bool is_per_user_install) override; - virtual int GetResultCodeRespawnFailed() override; - virtual void InitBrowserCrashDumpsRegKey() override; - virtual void RecordCrashDumpAttempt(bool is_real_crash) override; - virtual void RecordCrashDumpAttemptResult(bool is_real_crash, - bool succeeded) override; + bool GetAlternativeCrashDumpLocation(base::FilePath* crash_dir) override; + void GetProductNameAndVersion(const base::FilePath& exe_path, + base::string16* product_name, + base::string16* version, + base::string16* special_build, + base::string16* channel_name) override; + bool ShouldShowRestartDialog(base::string16* title, + base::string16* message, + bool* is_rtl_locale) override; + bool AboutToRestart() override; + bool GetDeferredUploadsSupported(bool is_per_user_install) override; + bool GetIsPerUserInstall(const base::FilePath& exe_path) override; + bool GetShouldDumpLargerDumps(bool is_per_user_install) override; + int GetResultCodeRespawnFailed() override; + void InitBrowserCrashDumpsRegKey() override; + void RecordCrashDumpAttempt(bool is_real_crash) override; + void RecordCrashDumpAttemptResult(bool is_real_crash, + bool succeeded) override; #endif #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 3b458688..94e1efc 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -1541,7 +1541,7 @@ <message name="IDS_LOGIN_PASSWORD_CHANGED_MORE_INFO" desc="Additional information on the password changed dialog"> Because <ph name="IDS_SHORT_PRODUCT_OS_NAME">$1<ex>Chrome OS</ex></ph> securely encrypts all your local data, you must enter the old password now to unlock that data. </message> - <message name="IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT" desc="Old password field hint on the password changed dialog"> + <message name="IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT" desc="Old password field hint on the password changed dialog."> Enter old password </message> <message name="IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD" desc="Error that is shown when incorrect old password was supplied for user cryptohome migration."> @@ -1556,7 +1556,7 @@ <message name="IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY" desc="Button to proceed without providing old password on the password changed dialog"> If you cannot remember your password, you may proceed but local data will be lost. Only synced settings and data will be retrieved. </message> - <message name="IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON" desc="Button to proceed without providing old password on the password changed dialog"> + <message name="IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON" desc="Button to proceed without providing old password on the password changed dialog."> Proceed anyway </message> <message name="IDS_LOGIN_PASSWORD_CHANGED_RESET" desc="Reset option of the password changed dialog"> @@ -1566,6 +1566,18 @@ Migrate all Chrome OS data to the new password (requires previous password) </message> + <message name="IDS_LOGIN_NEWGAIA_PASSWORD_CHANGED_TITLE" desc="Title for the password changed dialog box"> + To unlock and restore your local data, please enter your old <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> password. + </message> + <message name="IDS_LOGIN_NEWGAIA_PASSWORD_CHANGED_FORGOT_PASSWORD" desc="Text of the link that lets user skip old password input on the password changed dialog in the newgaia flow"> + Forgot your old password? + </message> + <message name="IDS_LOGIN_NEWGAIA_PASSWORD_CHANGED_PROCEED_ANYWAY" desc="Button to proceed without providing old password on the password changed dialog in the newgaia flow"> + You may proceed, but only your synced data and settings will be restored. All local data will be lost. + </message> + <message name="IDS_LOGIN_NEWGAIA_PASSWORD_CHANGED_TRY_AGAIN" desc="Label for the retry button on the proceed anyway step in the newgaia password changed flow"> + Try again + </message> <message name="IDS_LOGIN_PREVIOUS_PASSWORD" desc="Password field text on the password changed dialog"> Previous password </message> @@ -5951,6 +5963,9 @@ <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_USER" desc="Error message to show when the user used to re-enroll the device does not belong to the domain that the device was originally enrolled into."> This user account does not belong to the domain that the device is enrolled to. If you want to enroll to a different domain you need to go through device recovery first. </message> + <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_MODE" desc="Error message to show upon attempting to re-enroll a device that is locked to a different operational mode."> + This device is locked in a mode that prevents enterprise enrollment. If you want to enroll the device you need to go through device recovery first. + </message> <message name="IDS_ENTERPRISE_ENROLLMENT_STATUS_STORE_ERROR" desc="Error message shown on the enrollment screen when the installation of the policy on the device fails."> Failed to install policy settings on the device: <ph name="VALIDATION_ERROR">$1<ex>Policy parsing failed</ex></ph>. </message>
diff --git a/chrome/app/client_util.cc b/chrome/app/client_util.cc index 6cbca1a..87b8163 100644 --- a/chrome/app/client_util.cc +++ b/chrome/app/client_util.cc
@@ -206,6 +206,9 @@ if (!PathService::Get(chrome::DIR_WATCHER_DATA, &watcher_data_directory)) return chrome::RESULT_CODE_MISSING_DATA; + base::string16 channel_name = GoogleUpdateSettings::GetChromeChannel( + !InstallUtil::IsPerUserInstall(cmd_line.GetProgram())); + // Intentionally leaked. HMODULE watcher_dll = Load(&version, &file); if (!watcher_dll) @@ -217,7 +220,7 @@ return watcher_main(chrome::kBrowserExitCodesRegistryPath, parent_process.Take(), on_initialized_event.Take(), watcher_data_directory.value().c_str(), - message_window_name.c_str()); + message_window_name.c_str(), channel_name.c_str()); } // Initialize the sandbox services.
diff --git a/chrome/app/delay_load_hook_unittest_win.cc b/chrome/app/delay_load_hook_unittest_win.cc index ed2adf8d..8ef56b6 100644 --- a/chrome/app/delay_load_hook_unittest_win.cc +++ b/chrome/app/delay_load_hook_unittest_win.cc
@@ -18,7 +18,7 @@ ChromeDelayLoadHookTest() : proc_ptr_(NULL) { } - virtual void SetUp() override { + void SetUp() override { SetupInfo("kernel32.dll"); }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 0c3901e..8922cec 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -270,7 +270,9 @@ </if> <!-- Media Router specific strings --> - <part file="media_router_strings.grdp" /> + <if expr="enable_media_router"> + <part file="media_router_strings.grdp" /> + </if> <!-- TODO add all of your "string table" messages here. Remember to change nontranslateable parts of the messages into placeholders (using the @@ -4598,6 +4600,12 @@ <message name="IDS_EXTENSION_PROMPT_WARNING_SETTINGS_PRIVATE" desc="Permission string for access to settings."> Read and change user and device settings </message> + <message name="IDS_EXTENSION_PROMPT_WARNING_SEARCH_ENGINES_PRIVATE" desc="Permission string for access to search engines."> + Read and change default and custom search engines + </message> + <message name="IDS_EXTENSION_PROMPT_WARNING_AUTOFILL_PRIVATE" desc="Permission string for access to autofill settings."> + Read and change autofill settings + </message> <!-- Extension/App error messages --> <message name="IDS_EXTENSION_CANT_GET_ABSOLUTE_PATH" desc="Warning displayed in pack dialog when the absolute path to the extension directory can not be found."> @@ -5868,6 +5876,18 @@ <message name="IDS_FLAGS_ENABLE_TOUCH_EDITING_DESCRIPTION" desc="Description of the flag to enable touch based text editing."> Touch editing can be initiated by tapping on a textfield or a selected text. </message> + <message name="IDS_FLAGS_TOUCH_SELECTION_STRATEGY_NAME" desc="Name of the flag that controls touch based text selection strategy."> + Touch text selection strategy + </message> + <message name="IDS_FLAGS_TOUCH_SELECTION_STRATEGY_DESCRIPTION" desc="Description of the flag that controls touch based text selection strategy."> + Controls how text selection granularity changes when touch text selection handles are dragged. Non-default behavior is experimental. + </message> + <message name="IDS_TOUCH_SELECTION_STRATEGY_CHARACTER" desc="Description for the touch text selection strategy which always uses character granularity."> + Character + </message> + <message name="IDS_TOUCH_SELECTION_STRATEGY_DIRECTION" desc="Description for the touch text selection strategy which is based on the direction in which the handle is dragged."> + Direction + </message> <message name="IDS_FLAGS_WALLET_SERVICE_USE_SANDBOX_NAME" desc="Title for the flag to use the Online Wallet sandbox servers (instead of production)."> Use Wallet sandbox servers </message> @@ -7381,12 +7401,9 @@ <message name="IDS_OMNIBOX_KEYWORD_TEXT" desc="Text shown in the search button at the front of the omnibox when the user has selected a keyword"> Search <ph name="SITE_NAME">$1<ex>google.com</ex></ph>: </message> - <message name="IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER" desc="The text displayed in the omnibox when it is empty, which includes the name of the default search provider."> + <message name="IDS_SEARCH_BOX_EMPTY_HINT" desc="The text displayed in the fakebox when it is empty, which includes the name of the default search provider."> Search <ph name="ENGINE">$1<ex>Google</ex></ph> or type URL </message> - <message name="IDS_OMNIBOX_EMPTY_HINT_NO_DEFAULT_SEARCH_PROVIDER" desc="The text displayed in the omnibox when it is empty, if the default search provider cannot be determined."> - Type URL - </message> <if expr="is_ios"> <message name="IDS_OMNIBOX_EMPTY_HINT" desc="The text displayed in the omnibox when it is empty."> Search or type URL
diff --git a/chrome/app/media_router_strings.grdp b/chrome/app/media_router_strings.grdp index 7c91a2ea..cee8974 100644 --- a/chrome/app/media_router_strings.grdp +++ b/chrome/app/media_router_strings.grdp
@@ -1,7 +1,45 @@ <?xml version="1.0" encoding="utf-8"?> <!-- Media Router-specific strings (included from generated_resources.grd). --> <grit-part> + <!-- General --> <message name="IDS_MEDIA_ROUTER_TITLE" desc="Title for media router"> Media Router </message> + + <!-- Cast Modes --> + <message name="IDS_MEDIA_ROUTER_DEFAULT_CAST_MODE" desc="Message for default cast mode."> + Cast <ph name="HOST_NAME">$1<ex>google.com</ex></ph> + </message> + <message name="IDS_MEDIA_ROUTER_DEFAULT_CAST_MODE_TITLE" desc="Title for default cast mode."> + Cast <ph name="HOST_NAME">$1<ex>google.com</ex></ph> to... + </message> + <message name="IDS_MEDIA_ROUTER_DESKTOP_OR_WINDOW_MIRROR_CAST_MODE" desc="Message for desktop/window mirror cast mode."> + Cast desktop or window + </message> + <message name="IDS_MEDIA_ROUTER_DESKTOP_OR_WINDOW_MIRROR_CAST_MODE_TITLE" desc="Title for desktop/window mirror cast mode."> + Cast desktop or window to... + </message> + <message name="IDS_MEDIA_ROUTER_SOUND_OPTIMIZED_TAB_MIRROR_CAST_MODE" desc="Message for default cast mode."> + Cast this tab (optimized for audio) + </message> + <message name="IDS_MEDIA_ROUTER_SOUND_OPTIMIZED_TAB_MIRROR_CAST_MODE_TITLE" desc="Title for sound optimized tab mirror cast mode."> + Cast this tab (optimized for audio) to... + </message> + <message name="IDS_MEDIA_ROUTER_TAB_MIRROR_CAST_MODE" desc="Message for tab mirror cast mode."> + Cast this tab + </message> + <message name="IDS_MEDIA_ROUTER_TAB_MIRROR_CAST_MODE_TITLE" desc="Title for tab mirror cast mode."> + Cast this tab to... + </message> + + <!-- Route Details --> + <message name="IDS_MEDIA_ROUTER_BACK_TO_SINK_PICKER" desc="Label of back to sink picker button."> + Back to device list + </message> + <message name="IDS_MEDIA_ROUTER_CASTING_ACTIVITY_STATUS" desc="Label of activity status."> + Casting to <ph name="sinkName">$1<ex>Living Room TV</ex></ph> + </message> + <message name="IDS_MEDIA_ROUTER_STOP_CASTING_BUTTON" desc="Text of Stop casting button."> + Stop casting + </message> </grit-part>
diff --git a/chrome/app/nibs/ExtensionInstallPromptBundle.xib b/chrome/app/nibs/ExtensionInstallPromptBundle.xib index 1c254801..541670b 100644 --- a/chrome/app/nibs/ExtensionInstallPromptBundle.xib +++ b/chrome/app/nibs/ExtensionInstallPromptBundle.xib
@@ -16,6 +16,8 @@ <string>NSButtonCell</string> <string>NSCustomObject</string> <string>NSCustomView</string> + <string>NSImageCell</string> + <string>NSImageView</string> <string>NSOutlineView</string> <string>NSScrollView</string> <string>NSScroller</string> @@ -210,29 +212,44 @@ <double key="NSMaxMagnification">4</double> <double key="NSMagnification">1</double> </object> - <object class="NSTextField" id="674425416"> + <object class="NSView" id="674425416"> <reference key="NSNextResponder" ref="727455624"/> <int key="NSvFlags">268</int> - <string key="NSFrame">{{19, 107}, {430, 17}}</string> + <string key="NSFrame">{{19, 115}, {357, 6}}</string> <reference key="NSSuperview" ref="727455624"/> <reference key="NSWindow"/> <reference key="NSNextKeyView" ref="255067549"/> - <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="415453281"> - <int key="NSCellFlags">67108864</int> - <int key="NSCellFlags2">272629760</int> - <string key="NSContents"/> - <reference key="NSSupport" ref="236266328"/> - <reference key="NSControlView" ref="674425416"/> - <object class="NSColor" key="NSBackgroundColor" id="106251383"> - <int key="NSColorSpace">6</int> - <string key="NSCatalogName">System</string> - <string key="NSColorName">controlColor</string> - <reference key="NSColor" ref="305211941"/> + </object> + <object class="NSImageView" id="111827522"> + <reference key="NSNextResponder" ref="727455624"/> + <int key="NSvFlags">265</int> + <object class="NSMutableSet" key="NSDragTypes"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="set.sortedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>Apple PDF pasteboard type</string> + <string>Apple PICT pasteboard type</string> + <string>Apple PNG pasteboard type</string> + <string>NSFilenamesPboardType</string> + <string>NeXT Encapsulated PostScript v1.2 pasteboard type</string> + <string>NeXT TIFF v4.0 pasteboard type</string> </object> - <reference key="NSTextColor" ref="684741680"/> + </object> + <string key="NSFrame">{{380, 74}, {64, 64}}</string> + <reference key="NSSuperview" ref="727455624"/> + <reference key="NSWindow"/> + <reference key="NSNextKeyView" ref="78143092"/> + <bool key="NSEnabled">YES</bool> + <object class="NSImageCell" key="NSCell" id="565316756"> + <int key="NSCellFlags">134217728</int> + <int key="NSCellFlags2">33554432</int> + <int key="NSAlign">0</int> + <int key="NSScale">0</int> + <int key="NSStyle">0</int> + <bool key="NSAnimates">NO</bool> </object> <bool key="NSAllowsLogicalLayoutDirection">NO</bool> + <bool key="NSEditable">YES</bool> </object> <object class="NSButton" id="78143092"> <reference key="NSNextResponder" ref="727455624"/> @@ -305,7 +322,7 @@ <object class="NSTextField" id="116161706"> <reference key="NSNextResponder" ref="727455624"/> <int key="NSvFlags">268</int> - <string key="NSFrame">{{19, 128}, {430, 17}}</string> + <string key="NSFrame">{{19, 128}, {357, 17}}</string> <reference key="NSSuperview" ref="727455624"/> <reference key="NSWindow"/> <reference key="NSNextKeyView" ref="674425416"/> @@ -320,7 +337,12 @@ <int key="NSfFlags">16</int> </object> <reference key="NSControlView" ref="116161706"/> - <reference key="NSBackgroundColor" ref="106251383"/> + <object class="NSColor" key="NSBackgroundColor" id="106251383"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlColor</string> + <reference key="NSColor" ref="305211941"/> + </object> <reference key="NSTextColor" ref="684741680"/> </object> <bool key="NSAllowsLogicalLayoutDirection">NO</bool> @@ -346,6 +368,14 @@ <int key="connectionID">144</int> </object> <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">iconView_</string> + <reference key="source" ref="762632889"/> + <reference key="destination" ref="111827522"/> + </object> + <int key="connectionID">188</int> + </object> + <object class="IBConnectionRecord"> <object class="IBActionConnection" key="connection"> <string key="label">ok:</string> <reference key="source" ref="762632889"/> @@ -483,10 +513,20 @@ <reference ref="78143092"/> <reference ref="116161706"/> <reference ref="658209583"/> + <reference ref="111827522"/> </object> <reference key="parent" ref="0"/> </object> <object class="IBObjectRecord"> + <int key="objectID">171</int> + <reference key="object" ref="111827522"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="565316756"/> + </object> + <reference key="parent" ref="727455624"/> + </object> + <object class="IBObjectRecord"> <int key="objectID">118</int> <reference key="object" ref="116161706"/> <object class="NSMutableArray" key="children"> @@ -531,18 +571,9 @@ <object class="IBObjectRecord"> <int key="objectID">154</int> <reference key="object" ref="674425416"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="415453281"/> - </object> <reference key="parent" ref="727455624"/> </object> <object class="IBObjectRecord"> - <int key="objectID">155</int> - <reference key="object" ref="415453281"/> - <reference key="parent" ref="674425416"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">159</int> <reference key="object" ref="255067549"/> <object class="NSMutableArray" key="children"> @@ -657,7 +688,7 @@ <reference key="dict.values" ref="0"/> </object> <nil key="sourceID"/> - <int key="maxID">170</int> + <int key="maxID">171</int> </object> <object class="IBClassDescriber" key="IBDocument.Classes"> <object class="NSMutableArray" key="referencedPartialClassDescriptions"> @@ -748,7 +779,7 @@ <bool key="EncodedWithXMLCoder">YES</bool> <string>NSButton</string> <string>NSImageView</string> - <string>NSTextField</string> + <string>NSView</string> <string>NSButton</string> <string>NSOutlineView</string> <string>NSTextField</string> @@ -787,7 +818,7 @@ </object> <object class="IBToOneOutletInfo"> <string key="name">itemsField_</string> - <string key="candidateClassName">NSTextField</string> + <string key="candidateClassName">NSView</string> </object> <object class="IBToOneOutletInfo"> <string key="name">okButton_</string>
diff --git a/chrome/app/nibs/ExtensionInstalledBubbleBundle.xib b/chrome/app/nibs/ExtensionInstalledBubbleBundle.xib index 5b4243b..3ded7bb 100644 --- a/chrome/app/nibs/ExtensionInstalledBubbleBundle.xib +++ b/chrome/app/nibs/ExtensionInstalledBubbleBundle.xib
@@ -113,42 +113,20 @@ </object> <bool key="NSAllowsLogicalLayoutDirection">NO</bool> </object> - <object class="NSTextField" id="665888286"> + <object class="NSView" id="665888286"> <reference key="NSNextResponder" ref="914312036"/> <int key="NSvFlags">-2147483380</int> <string key="NSFrame">{{12, 38}, {314, 17}}</string> <reference key="NSSuperview" ref="914312036"/> <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="85879595"> - <int key="NSCellFlags">67108864</int> - <int key="NSCellFlags2">272662528</int> - <string key="NSContents">Installed items</string> - <object class="NSFont" key="NSSupport" id="472995141"> - <string key="NSName">LucidaGrande</string> - <double key="NSSize">13</double> - <int key="NSfFlags">1044</int> - </object> - <reference key="NSControlView" ref="665888286"/> - <reference key="NSBackgroundColor" ref="951604798"/> - <reference key="NSTextColor" ref="121031723"/> - </object> <bool key="NSAllowsLogicalLayoutDirection">NO</bool> </object> - <object class="NSTextField" id="531091173"> + <object class="NSView" id="531091173"> <reference key="NSNextResponder" ref="914312036"/> <int key="NSvFlags">-2147483380</int> <string key="NSFrame">{{12, 88}, {314, 17}}</string> <reference key="NSSuperview" ref="914312036"/> <bool key="NSEnabled">YES</bool> - <object class="NSTextFieldCell" key="NSCell" id="226927715"> - <int key="NSCellFlags">67108864</int> - <int key="NSCellFlags2">272662528</int> - <string key="NSContents">Installed items</string> - <reference key="NSSupport" ref="472995141"/> - <reference key="NSControlView" ref="531091173"/> - <reference key="NSBackgroundColor" ref="951604798"/> - <reference key="NSTextColor" ref="121031723"/> - </object> <bool key="NSAllowsLogicalLayoutDirection">NO</bool> </object> <object class="NSButton" id="433090690"> @@ -161,7 +139,11 @@ <int key="NSCellFlags">67108864</int> <int key="NSCellFlags2">134250496</int> <string key="NSContents"/> - <reference key="NSSupport" ref="472995141"/> + <object class="NSFont" key="NSSupport" id="472995141"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">13</double> + <int key="NSfFlags">1044</int> + </object> <reference key="NSControlView" ref="433090690"/> <int key="NSButtonFlags">139214848</int> <int key="NSButtonFlags2">6</int> @@ -215,7 +197,7 @@ </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> - <string key="label">installedItemsMsg_</string> + <string key="label">installedItemsView_</string> <reference key="source" ref="1001"/> <reference key="destination" ref="531091173"/> </object> @@ -231,7 +213,7 @@ </object> <object class="IBConnectionRecord"> <object class="IBOutletConnection" key="connection"> - <string key="label">failedItemsMsg_</string> + <string key="label">failedItemsView_</string> <reference key="source" ref="1001"/> <reference key="destination" ref="665888286"/> </object> @@ -339,18 +321,9 @@ <object class="IBObjectRecord"> <int key="objectID">35</int> <reference key="object" ref="531091173"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="226927715"/> - </object> <reference key="parent" ref="914312036"/> </object> <object class="IBObjectRecord"> - <int key="objectID">36</int> - <reference key="object" ref="226927715"/> - <reference key="parent" ref="531091173"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">15</int> <reference key="object" ref="433090690"/> <object class="NSMutableArray" key="children"> @@ -367,18 +340,9 @@ <object class="IBObjectRecord"> <int key="objectID">48</int> <reference key="object" ref="665888286"/> - <object class="NSMutableArray" key="children"> - <bool key="EncodedWithXMLCoder">YES</bool> - <reference ref="85879595"/> - </object> <reference key="parent" ref="914312036"/> </object> <object class="IBObjectRecord"> - <int key="objectID">49</int> - <reference key="object" ref="85879595"/> - <reference key="parent" ref="665888286"/> - </object> - <object class="IBObjectRecord"> <int key="objectID">56</int> <reference key="object" ref="14720802"/> <object class="NSMutableArray" key="children">
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 1680a39a..1376ca80 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -89,4 +89,25 @@ <message name="IDS_SETTINGS_INTERNET_PAGE_TITLE" desc="Name of the settings page which displays internet preferences."> Internet Connection </message> + + <!-- Search Page --> + <message name="IDS_SETTINGS_SEARCH_PAGE_TITLE" desc="Name of the settings page which displays search engine preferences."> + Search + </message> + <message name="IDS_SETTINGS_SEARCH_EXPLANATION" desc="Explanation for the search engine dropdown setting."> + Set which search engine is used when searching from the omnibox. + </message> + <message name="IDS_SETTINGS_SEARCH_MANAGE_BUTTON_LABEL" desc="Label for the Manage Search Engines button."> + Manage Search Engines + </message> + <message name="IDS_SETTINGS_SEARCH_OK_GOOGLE_LABEL" desc="Label for the checkbox which enables the OK Google hotword."> + Enable "Ok Google" to start a voice search. + </message> + <message name="IDS_SETTINGS_SEARCH_OK_GOOGLE_LEARN_MORE_LINK" desc="Link which opens page to learn more about the OK Google hotword."> + Learn more + </message> + <message name="IDS_SETTINGS_SEARCH_OK_GOOGLE_DESCRIPTION_LABEL" desc="Label describing when the OK Google hotword may be used."> + Say "Ok Google" in a new tab and google.com + </message> + </grit-part>
diff --git a/chrome/app_installer/BUILD.gn b/chrome/app_installer/BUILD.gn new file mode 100644 index 0000000..f371e40 --- /dev/null +++ b/chrome/app_installer/BUILD.gn
@@ -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. + +import("//testing/test.gni") + +assert(is_win) + +executable("app_installer") { + sources = [ + "/win/app_installer_main.cc" + ] + + configs -= [ "//build/config/win:console" ] + configs += [ "//build/config/win:windowed" ] + + deps = [ + ":util", + "//base", + ] + + # TODO(GYP) manifest. +} + +source_set("util") { + sources = [ + "win/app_installer_util.cc", + "win/app_installer_util.h", + ] + + deps = [ + "//base", + "//chrome/common", + "//chrome/common:constants", + "//chrome/installer/launcher_support", + "//chrome/installer/util", + "//chrome/installer/util:strings", + "//content/public/common", + "//net", + "//third_party/omaha:extractor", + ] +} + +test("app_installer_unittests") { + sources = [ + "win/app_installer_util_unittest.cc", + ] + + deps = [ + ":util", + "//base", + "//base/test:run_all_unittests", + "//net:test_support", + "//testing/gtest", + ] + + # TODO(GYP) manifest +}
diff --git a/chrome/app_installer/app_installer.gypi b/chrome/app_installer/app_installer.gypi index 8bc96fe..ac382b5 100644 --- a/chrome/app_installer/app_installer.gypi +++ b/chrome/app_installer/app_installer.gypi
@@ -7,6 +7,7 @@ ['OS=="win"', { 'targets': [ { + # GN version: //chrome/app_installer:util 'target_name': 'app_installer_util', 'type': 'static_library', 'dependencies': [ @@ -32,6 +33,7 @@ # TODO(jackhou): Add a version resource (using # version_resource_rules.gypi). { + # GN version: //chrome/app_installer 'target_name': 'app_installer', 'type': 'executable', 'dependencies': [ @@ -57,6 +59,7 @@ }, }, { + # GN version: //chrome/installer/app_installer:app_installer_unittests 'target_name': 'app_installer_unittests', 'type': 'executable', 'dependencies': [
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index c6925c3..709fd0c 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -948,10 +948,10 @@ "sessions/session_restore_test_helper.h", "sessions/session_service_test_helper.cc", "sessions/session_service_test_helper.h", - "signin/fake_account_reconcilor.cc", - "signin/fake_account_reconcilor.h", "signin/fake_account_tracker_service.cc", "signin/fake_account_tracker_service.h", + "signin/fake_gaia_cookie_manager_service.cc", + "signin/fake_gaia_cookie_manager_service.h", "signin/fake_profile_oauth2_token_service.cc", "signin/fake_profile_oauth2_token_service.h", "signin/fake_profile_oauth2_token_service_builder.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index f8e446e..9aae179 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -180,6 +180,16 @@ }; #endif +const Experiment::Choice kTouchTextSelectionStrategyChoices[] = { + { IDS_GENERIC_EXPERIMENT_CHOICE_DEFAULT, "", "" }, + { IDS_TOUCH_SELECTION_STRATEGY_CHARACTER, + switches::kTouchTextSelectionStrategy, + "character" }, + { IDS_TOUCH_SELECTION_STRATEGY_DIRECTION, + switches::kTouchTextSelectionStrategy, + "direction" } +}; + #if !defined(DISABLE_NACL) const Experiment::Choice kNaClDebugMaskChoices[] = { // Secure shell can be used on ChromeOS for forwarding the TCP port opened by @@ -1219,6 +1229,13 @@ switches::kDisableTouchEditing) }, { + "touch-selection-strategy", + IDS_FLAGS_TOUCH_SELECTION_STRATEGY_NAME, + IDS_FLAGS_TOUCH_SELECTION_STRATEGY_DESCRIPTION, + kOsAndroid, // TODO(mfomitchev): Add CrOS/Win/Linux support soon. + MULTI_VALUE_TYPE(kTouchTextSelectionStrategyChoices) + }, + { "enable-stale-while-revalidate", IDS_FLAGS_ENABLE_STALE_WHILE_REVALIDATE_NAME, IDS_FLAGS_ENABLE_STALE_WHILE_REVALIDATE_DESCRIPTION,
diff --git a/chrome/browser/accessibility/animation_policy_prefs.cc b/chrome/browser/accessibility/animation_policy_prefs.cc index 45b795a..6974c40 100644 --- a/chrome/browser/accessibility/animation_policy_prefs.cc +++ b/chrome/browser/accessibility/animation_policy_prefs.cc
@@ -12,8 +12,6 @@ const char kAnimationPolicyNone[] = "none"; void RegisterAnimationPolicyPrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kAnimationPolicy, - kAnimationPolicyAllowed, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kAnimationPolicy, + kAnimationPolicyAllowed); }
diff --git a/chrome/browser/accessibility/invert_bubble_prefs.cc b/chrome/browser/accessibility/invert_bubble_prefs.cc index 3570c19..2bccd156 100644 --- a/chrome/browser/accessibility/invert_bubble_prefs.cc +++ b/chrome/browser/accessibility/invert_bubble_prefs.cc
@@ -10,10 +10,7 @@ namespace chrome { void RegisterInvertBubbleUserPrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kInvertNotificationShown, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kInvertNotificationShown, false); } } // namespace chrome
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_shim.cc b/chrome/browser/android/bookmarks/partner_bookmarks_shim.cc index 433b0ca..c113377 100644 --- a/chrome/browser/android/bookmarks/partner_bookmarks_shim.cc +++ b/chrome/browser/android/bookmarks/partner_bookmarks_shim.cc
@@ -69,9 +69,7 @@ // static void PartnerBookmarksShim::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref( - prefs::kPartnerBookmarkMappings, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kPartnerBookmarkMappings); } // static
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc index eecce76f..3cb80b2 100644 --- a/chrome/browser/android/chrome_jni_registrar.cc +++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -23,7 +23,7 @@ #include "chrome/browser/android/content_view_util.h" #include "chrome/browser/android/cookies/cookies_fetcher.h" #include "chrome/browser/android/dev_tools_server.h" -#include "chrome/browser/android/dom_distiller/feedback_reporter_android.h" +#include "chrome/browser/android/dom_distiller/external_feedback_reporter_android.h" #include "chrome/browser/android/download/chrome_download_delegate.h" #include "chrome/browser/android/favicon_helper.h" #include "chrome/browser/android/feature_utilities.h"
diff --git a/chrome/browser/android/compositor/scene_layer/scene_layer.h b/chrome/browser/android/compositor/scene_layer/scene_layer.h index a0cd867..92cbf58 100644 --- a/chrome/browser/android/compositor/scene_layer/scene_layer.h +++ b/chrome/browser/android/compositor/scene_layer/scene_layer.h
@@ -11,12 +11,9 @@ #include "base/android/scoped_java_ref.h" #include "base/basictypes.h" #include "base/memory/ref_counted.h" +#include "cc/layers/layer.h" #include "third_party/skia/include/core/SkColor.h" -namespace cc { -class Layer; -} - namespace chrome { namespace android {
diff --git a/chrome/browser/android/dom_distiller/external_feedback_reporter_android.cc b/chrome/browser/android/dom_distiller/external_feedback_reporter_android.cc index 8a3eae5..04cf18a 100644 --- a/chrome/browser/android/dom_distiller/external_feedback_reporter_android.cc +++ b/chrome/browser/android/dom_distiller/external_feedback_reporter_android.cc
@@ -4,8 +4,13 @@ #include "chrome/browser/android/dom_distiller/external_feedback_reporter_android.h" -#include "chrome/browser/android/dom_distiller/feedback_reporter_android.h" +#include "base/android/jni_string.h" +#include "chrome/browser/ui/android/window_android_helper.h" +#include "components/dom_distiller/core/url_utils.h" #include "content/public/browser/web_contents.h" +#include "jni/DomDistillerFeedbackReporter_jni.h" +#include "ui/android/window_android.h" +#include "url/gurl.h" namespace dom_distiller { @@ -16,7 +21,27 @@ content::WebContents* web_contents, const GURL& url, const bool good) { - ReportDomDistillerExternalFeedback(web_contents, url, good); + if (!web_contents) + return; + WindowAndroidHelper* helper = + content::WebContentsUserData<WindowAndroidHelper>::FromWebContents( + web_contents); + DCHECK(helper); + + ui::WindowAndroid* window = helper->GetWindowAndroid(); + DCHECK(window); + + JNIEnv* env = base::android::AttachCurrentThread(); + ScopedJavaLocalRef<jstring> jurl = base::android::ConvertUTF8ToJavaString( + env, url_utils::GetOriginalUrlFromDistillerUrl(url).spec()); + + Java_DomDistillerFeedbackReporter_reportFeedbackWithWindow( + env, window->GetJavaObject().obj(), jurl.obj(), good); +} + +// static +bool RegisterFeedbackReporter(JNIEnv* env) { + return RegisterNativesImpl(env); } } // namespace android
diff --git a/chrome/browser/android/dom_distiller/external_feedback_reporter_android.h b/chrome/browser/android/dom_distiller/external_feedback_reporter_android.h index 4590988..6cce524 100644 --- a/chrome/browser/android/dom_distiller/external_feedback_reporter_android.h +++ b/chrome/browser/android/dom_distiller/external_feedback_reporter_android.h
@@ -26,6 +26,9 @@ DISALLOW_COPY_AND_ASSIGN(ExternalFeedbackReporterAndroid); }; +// Registers the FeedbackReporter's native methods through JNI. +bool RegisterFeedbackReporter(JNIEnv* env); + } // namespace android } // namespace dom_distiller
diff --git a/chrome/browser/android/dom_distiller/feedback_reporter_android.cc b/chrome/browser/android/dom_distiller/feedback_reporter_android.cc deleted file mode 100644 index 5b1f8b4..0000000 --- a/chrome/browser/android/dom_distiller/feedback_reporter_android.cc +++ /dev/null
@@ -1,97 +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 "chrome/browser/android/dom_distiller/feedback_reporter_android.h" - -#include "base/android/jni_string.h" -#include "base/command_line.h" -#include "chrome/browser/ui/android/window_android_helper.h" -#include "chrome/common/chrome_switches.h" -#include "components/dom_distiller/core/feedback_reporter.h" -#include "components/dom_distiller/core/url_utils.h" -#include "content/public/browser/navigation_details.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/common/frame_navigate_params.h" -#include "jni/DomDistillerFeedbackReporter_jni.h" -#include "ui/android/window_android.h" -#include "url/gurl.h" - -namespace dom_distiller { - -namespace android { - -// static -jboolean IsEnabled(JNIEnv* env, jclass clazz) { - // TODO(mdjones): Remove android-view version of feedback overlay. - return false; -} - -// static -void ReportQuality(JNIEnv* env, jclass clazz, jboolean j_good) { - FeedbackReporter::ReportQuality(j_good); -} - -FeedbackReporterAndroid::FeedbackReporterAndroid(JNIEnv* env, jobject obj) - : weak_java_feedback_reporter_(env, obj) {} - -FeedbackReporterAndroid::~FeedbackReporterAndroid() {} - -void FeedbackReporterAndroid::Destroy(JNIEnv* env, jobject obj) { delete this; } - -void FeedbackReporterAndroid::ReplaceWebContents(JNIEnv* env, - jobject obj, - jobject jweb_contents) { - content::WebContents* web_contents = - content::WebContents::FromJavaWebContents(jweb_contents); - Observe(web_contents); -} - -void FeedbackReporterAndroid::DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) { - JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef<jobject> jobj = weak_java_feedback_reporter_.get(env); - if (jobj.is_null()) - return; - Java_DomDistillerFeedbackReporter_dismissOverlay(env, jobj.obj()); - GURL url = details.entry->GetURL(); - if (dom_distiller::url_utils::IsDistilledPage(url)) { - Java_DomDistillerFeedbackReporter_showOverlay(env, jobj.obj()); - } -} - -jlong Init(JNIEnv* env, jobject obj) { - FeedbackReporterAndroid* reporter = new FeedbackReporterAndroid(env, obj); - return reinterpret_cast<intptr_t>(reporter); -} - -// static -void ReportDomDistillerExternalFeedback(content::WebContents* web_contents, - const GURL& url, - const bool good) { - if (!web_contents) - return; - WindowAndroidHelper* helper = - content::WebContentsUserData<WindowAndroidHelper>::FromWebContents( - web_contents); - DCHECK(helper); - - ui::WindowAndroid* window = helper->GetWindowAndroid(); - DCHECK(window); - - JNIEnv* env = base::android::AttachCurrentThread(); - ScopedJavaLocalRef<jstring> jurl = base::android::ConvertUTF8ToJavaString( - env, url_utils::GetOriginalUrlFromDistillerUrl(url).spec()); - - Java_DomDistillerFeedbackReporter_reportFeedbackWithWindow( - env, window->GetJavaObject().obj(), jurl.obj(), good); -} - -// static -bool RegisterFeedbackReporter(JNIEnv* env) { return RegisterNativesImpl(env); } - -} // namespace android - -} // namespace dom_distiller
diff --git a/chrome/browser/android/dom_distiller/feedback_reporter_android.h b/chrome/browser/android/dom_distiller/feedback_reporter_android.h deleted file mode 100644 index a6235a48..0000000 --- a/chrome/browser/android/dom_distiller/feedback_reporter_android.h +++ /dev/null
@@ -1,58 +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 CHROME_BROWSER_ANDROID_DOM_DISTILLER_FEEDBACK_REPORTER_ANDROID_H_ -#define CHROME_BROWSER_ANDROID_DOM_DISTILLER_FEEDBACK_REPORTER_ANDROID_H_ - -#include <jni.h> - -#include "base/android/jni_weak_ref.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_contents_observer.h" - -namespace content { -struct FrameNavigateParams; -struct LoadCommittedDetails; -} // namespace content - -namespace dom_distiller { - -namespace android { - -class FeedbackReporterAndroid : content::WebContentsObserver { - public: - FeedbackReporterAndroid(JNIEnv* env, jobject obj); - ~FeedbackReporterAndroid() override; - - // Destroys the FeedbackReporterAndroid. - void Destroy(JNIEnv* env, jobject obj); - - // Observes a new WebContents, if necessary. - void ReplaceWebContents(JNIEnv* env, jobject obj, jobject jweb_contents); - - // WebContentsObserver implementation: - void DidNavigateMainFrame( - const content::LoadCommittedDetails& details, - const content::FrameNavigateParams& params) override; - - private: - // FeedbackReporterAndroid on the Java side. - JavaObjectWeakGlobalRef weak_java_feedback_reporter_; - - DISALLOW_COPY_AND_ASSIGN(FeedbackReporterAndroid); -}; - -// Load the external feedback form for distiller. -void ReportDomDistillerExternalFeedback(content::WebContents* web_contents, - const GURL& url, - const bool good); - -// Registers the FeedbackReporter's native methods through JNI. -bool RegisterFeedbackReporter(JNIEnv* env); - -} // namespace android - -} // namespace dom_distiller - -#endif // CHROME_BROWSER_ANDROID_DOM_DISTILLER_FEEDBACK_REPORTER_ANDROID_H_
diff --git a/chrome/browser/android/new_tab_page_prefs.cc b/chrome/browser/android/new_tab_page_prefs.cc index 616beb00..7d2eb229 100644 --- a/chrome/browser/android/new_tab_page_prefs.cc +++ b/chrome/browser/android/new_tab_page_prefs.cc
@@ -108,28 +108,12 @@ // static void NewTabPagePrefs::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kNtpCollapsedCurrentlyOpenTabs, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kNtpCollapsedSnapshotDocument, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kNtpCollapsedRecentlyClosedTabs, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kNtpCollapsedSyncPromo, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kNtpCollapsedForeignSessions, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kNtpMostVisitedURLsBlacklist, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kNtpCollapsedCurrentlyOpenTabs, false); + registry->RegisterBooleanPref(prefs::kNtpCollapsedSnapshotDocument, false); + registry->RegisterBooleanPref(prefs::kNtpCollapsedRecentlyClosedTabs, false); + registry->RegisterBooleanPref(prefs::kNtpCollapsedSyncPromo, false); + registry->RegisterDictionaryPref(prefs::kNtpCollapsedForeignSessions); + registry->RegisterDictionaryPref(prefs::kNtpMostVisitedURLsBlacklist); } // static
diff --git a/chrome/browser/android/preferences/pref_service_bridge.cc b/chrome/browser/android/preferences/pref_service_bridge.cc index 189bab0..ca8810f 100644 --- a/chrome/browser/android/preferences/pref_service_bridge.cc +++ b/chrome/browser/android/preferences/pref_service_bridge.cc
@@ -380,6 +380,23 @@ CONTENT_SETTINGS_TYPE_FULLSCREEN, NULL) == CONTENT_SETTING_ALLOW; } +static jboolean GetMetricsReportingEnabled(JNIEnv* env, jobject obj) { + PrefService* local_state = g_browser_process->local_state(); + return local_state->GetBoolean(prefs::kMetricsReportingEnabled); +} + +static void SetMetricsReportingEnabled(JNIEnv* env, + jobject obj, + jboolean enabled) { + PrefService* local_state = g_browser_process->local_state(); + local_state->SetBoolean(prefs::kMetricsReportingEnabled, enabled); +} + +static jboolean HasSetMetricsReporting(JNIEnv* env, jobject obj) { + PrefService* local_state = g_browser_process->local_state(); + return local_state->HasPrefPath(prefs::kMetricsReportingEnabled); +} + namespace { // Redirects a BrowsingDataRemover completion callback back into Java. @@ -488,15 +505,20 @@ is_enabled ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK); } -static void SetCameraMicEnabled(JNIEnv* env, jobject obj, jboolean allow) { +static void SetCameraEnabled(JNIEnv* env, jobject obj, jboolean allow) { + HostContentSettingsMap* host_content_settings_map = + GetOriginalProfile()->GetHostContentSettingsMap(); + host_content_settings_map->SetDefaultContentSetting( + CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, + allow ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK); +} + +static void SetMicEnabled(JNIEnv* env, jobject obj, jboolean allow) { HostContentSettingsMap* host_content_settings_map = GetOriginalProfile()->GetHostContentSettingsMap(); host_content_settings_map->SetDefaultContentSetting( CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, allow ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK); - host_content_settings_map->SetDefaultContentSetting( - CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, - allow ? CONTENT_SETTING_ASK : CONTENT_SETTING_BLOCK); } static void SetFullscreenAllowed(JNIEnv* env, jobject obj, jboolean allow) { @@ -598,26 +620,34 @@ passwordEchoEnabled); } - -static jboolean GetCameraMicEnabled(JNIEnv* env, jobject obj) { - return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) && - GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); +static jboolean GetCameraEnabled(JNIEnv* env, jobject obj) { + return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); } -static jboolean GetCameraMicUserModifiable(JNIEnv* env, jobject obj) { +static jboolean GetCameraUserModifiable(JNIEnv* env, jobject obj) { return IsContentSettingUserModifiable( - CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) && - IsContentSettingUserModifiable( CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); } -static jboolean GetCameraMicManagedByCustodian(JNIEnv* env, jobject obj) { +static jboolean GetCameraManagedByCustodian(JNIEnv* env, jobject obj) { return IsContentSettingManagedByCustodian( - CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) && - IsContentSettingManagedByCustodian( CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); } +static jboolean GetMicEnabled(JNIEnv* env, jobject obj) { + return GetBooleanForContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); +} + +static jboolean GetMicUserModifiable(JNIEnv* env, jobject obj) { + return IsContentSettingUserModifiable( + CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); +} + +static jboolean GetMicManagedByCustodian(JNIEnv* env, jobject obj) { + return IsContentSettingManagedByCustodian( + CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); +} + static jboolean GetAutologinEnabled(JNIEnv* env, jobject obj) { return GetPrefService()->GetBoolean(prefs::kAutologinEnabled); }
diff --git a/chrome/browser/android/preferences/website_preference_bridge.cc b/chrome/browser/android/preferences/website_preference_bridge.cc index a82ee751..feba405 100644 --- a/chrome/browser/android/preferences/website_preference_bridge.cc +++ b/chrome/browser/android/preferences/website_preference_bridge.cc
@@ -91,8 +91,11 @@ jembedder = ConvertUTF8ToJavaString(env, embedder); switch (content_type) { case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: + Java_WebsitePreferenceBridge_insertMicrophoneInfoIntoList( + env, list, jorigin.obj(), jembedder.obj()); + break; case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: - Java_WebsitePreferenceBridge_insertVoiceAndVideoCaptureInfoIntoList( + Java_WebsitePreferenceBridge_insertCameraInfoIntoList( env, list, jorigin.obj(), jembedder.obj()); break; case CONTENT_SETTINGS_TYPE_GEOLOCATION: @@ -277,33 +280,39 @@ CONTENT_SETTINGS_TYPE_NOTIFICATIONS, setting); } -static void GetVoiceAndVideoCaptureOrigins(JNIEnv* env, - jclass clazz, - jobject list, - jboolean managedOnly) { - GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, list, managedOnly); +static void GetCameraOrigins(JNIEnv* env, + jclass clazz, + jobject list, + jboolean managedOnly) { GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, list, managedOnly); } -static jint GetVoiceCaptureSettingForOrigin(JNIEnv* env, jclass clazz, +static void GetMicrophoneOrigins(JNIEnv* env, + jclass clazz, + jobject list, + jboolean managedOnly) { + GetOrigins(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, list, managedOnly); +} + +static jint GetMicrophoneSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin, jstring embedder) { return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, origin, embedder); } -static jint GetVideoCaptureSettingForOrigin(JNIEnv* env, jclass clazz, +static jint GetCameraSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin, jstring embedder) { return GetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, origin, embedder); } -static void SetVoiceCaptureSettingForOrigin(JNIEnv* env, jclass clazz, +static void SetMicrophoneSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin, jstring embedder, jint value) { SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, origin, ContentSettingsPattern::Wildcard(), value); } -static void SetVideoCaptureSettingForOrigin(JNIEnv* env, jclass clazz, +static void SetCameraSettingForOrigin(JNIEnv* env, jclass clazz, jstring origin, jstring embedder, jint value) { SetSettingForOrigin(env, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, origin, ContentSettingsPattern::Wildcard(), value);
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc index afbe27f..7ea7eb6 100644 --- a/chrome/browser/android/tab_android.cc +++ b/chrome/browser/android/tab_android.cc
@@ -294,17 +294,6 @@ bool did_start_load, bool did_finish_load) { JNIEnv* env = base::android::AttachCurrentThread(); - - // We need to notify the native InfobarContainer so infobars can be swapped. - InfoBarContainerAndroid* infobar_container = - reinterpret_cast<InfoBarContainerAndroid*>( - Java_Tab_getNativeInfoBarContainer( - env, - weak_java_tab_.get(env).obj())); - InfoBarService* new_infobar_service = - new_contents ? InfoBarService::FromWebContents(new_contents) : NULL; - infobar_container->ChangeInfoBarManager(new_infobar_service); - Java_Tab_swapWebContents( env, weak_java_tab_.get(env).obj(),
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h index 53f5be6f..8c69929c 100644 --- a/chrome/browser/app_controller_mac.h +++ b/chrome/browser/app_controller_mac.h
@@ -157,6 +157,7 @@ - (const std::vector<GURL>&)startupUrls; - (BookmarkMenuBridge*)bookmarkMenuBridge; +- (HistoryMenuBridge*)historyMenuBridge; // Subscribes/unsubscribes from the work area change notification. - (void)addObserverForWorkAreaChange:(ui::WorkAreaWatcherObserver*)observer;
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index e888d39..91ae9320 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -893,8 +893,13 @@ // to the old profile. // In a browser test, the application is not brought to the front, so // |lastProfile_| might be null. - if (!lastProfile_ || profilePath == lastProfile_->GetPath()) - lastProfile_ = g_browser_process->profile_manager()->GetLastUsedProfile(); + if (!lastProfile_ || profilePath == lastProfile_->GetPath()) { + // Force windowChangedToProfile: to set the lastProfile_ and also update the + // relevant menuBridge objects. + lastProfile_ = nullptr; + [self windowChangedToProfile:g_browser_process->profile_manager()-> + GetLastUsedProfile()]; + } auto it = profileBookmarkMenuBridgeMap_.find(profilePath); if (it != profileBookmarkMenuBridgeMap_.end()) { @@ -1549,6 +1554,10 @@ return bookmarkMenuBridge_; } +- (HistoryMenuBridge*)historyMenuBridge { + return historyMenuBridge_.get(); +} + - (void)addObserverForWorkAreaChange:(ui::WorkAreaWatcherObserver*)observer { workAreaChangeObservers_.AddObserver(observer); }
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm index 52fa358b..4b3d9586 100644 --- a/chrome/browser/app_controller_mac_browsertest.mm +++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -22,11 +22,13 @@ #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/cocoa/bookmarks/bookmark_menu_bridge.h" +#include "chrome/browser/ui/cocoa/history_menu_bridge.h" #include "chrome/browser/ui/host_desktop.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/user_manager.h" @@ -79,6 +81,13 @@ method_invoke(controller, get_url, shortcut_event, NULL); } +void RunClosureWhenProfileInitialized(const base::Closure& closure, + Profile* profile, + Profile::CreateStatus status) { + if (status == Profile::CREATE_STATUS_INITIALIZED) + closure.Run(); +} + } // namespace @interface TestOpenShortcutOnStartup : NSObject @@ -427,6 +436,71 @@ }; IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest, + HistoryMenuResetAfterProfileDeletion) { + ProfileManager* profile_manager = g_browser_process->profile_manager(); + AppController* ac = [NSApp delegate]; + + // Use the existing profile as profile 1. + Profile* profile1 = browser()->profile(); + + // Create profile 2. + base::FilePath profile2_path = + profile_manager->GenerateNextProfileDirectoryPath(); + base::RunLoop run_loop; + profile_manager->CreateProfileAsync( + profile2_path, + base::Bind(&RunClosureWhenProfileInitialized, + run_loop.QuitClosure()), + base::string16(), + base::string16(), + std::string()); + run_loop.Run(); + Profile* profile2 = profile_manager->GetProfileByPath(profile2_path); + ASSERT_TRUE(profile2); + + // Switch the controller to profile1. + [ac windowChangedToProfile:profile1]; + base::RunLoop().RunUntilIdle(); + + // Verify the controller's History Menu corresponds to profile1. + EXPECT_TRUE([ac historyMenuBridge]->service()); + EXPECT_EQ([ac historyMenuBridge]->service(), + HistoryServiceFactory::GetForProfile(profile1, + ServiceAccessType::EXPLICIT_ACCESS)); + + // Load profile2's History Service backend so it will be assigned to the + // HistoryMenuBridge when windowChangedToProfile is called, or else this test + // will fail flaky. + ui_test_utils::WaitForHistoryToLoad( + HistoryServiceFactory::GetForProfile(profile2, + ServiceAccessType::EXPLICIT_ACCESS)); + // Switch the controller to profile2. + [ac windowChangedToProfile:profile2]; + base::RunLoop().RunUntilIdle(); + + // Verify the controller's History Menu has changed. + EXPECT_TRUE([ac historyMenuBridge]->service()); + EXPECT_EQ([ac historyMenuBridge]->service(), + HistoryServiceFactory::GetForProfile(profile2, + ServiceAccessType::EXPLICIT_ACCESS)); + EXPECT_NE( + HistoryServiceFactory::GetForProfile(profile1, + ServiceAccessType::EXPLICIT_ACCESS), + HistoryServiceFactory::GetForProfile(profile2, + ServiceAccessType::EXPLICIT_ACCESS)); + + // Delete profile2. + profile_manager->ScheduleProfileForDeletion( + profile2->GetPath(), ProfileManager::CreateCallback()); + base::RunLoop().RunUntilIdle(); + + // Verify the controller's history is back to profile1. + EXPECT_EQ([ac historyMenuBridge]->service(), + HistoryServiceFactory::GetForProfile(profile1, + ServiceAccessType::EXPLICIT_ACCESS)); +} + +IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest, BookmarksMenuIsRestoredAfterProfileSwitch) { ProfileManager* profile_manager = g_browser_process->profile_manager(); base::scoped_nsobject<AppController> ac([[AppController alloc] init]);
diff --git a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc index 913c9c81..f361b7a 100644 --- a/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc +++ b/chrome/browser/apps/app_shim/extension_app_shim_handler_mac_unittest.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/test/base/testing_profile.h" #include "content/public/browser/notification_service.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/common/extension.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -116,16 +117,16 @@ MOCK_METHOD1(OnAppLaunchComplete, void(AppShimLaunchResult)); - virtual void OnAppClosed() override { + void OnAppClosed() override { handler_->OnShimClose(this); ++close_count_; } - virtual void OnAppHide() override {} - virtual void OnAppRequestUserAttention(AppShimAttentionType type) override {} - virtual base::FilePath GetProfilePath() const override { + void OnAppHide() override {} + void OnAppRequestUserAttention(AppShimAttentionType type) override {} + base::FilePath GetProfilePath() const override { return profile_path_; } - virtual std::string GetAppId() const override { return app_id_; } + std::string GetAppId() const override { return app_id_; } int close_count() { return close_count_; } @@ -200,6 +201,7 @@ std::vector<base::FilePath>()); } + content::TestBrowserThreadBundle thread_bundle_; MockDelegate* delegate_; scoped_ptr<TestingExtensionAppShimHandler> handler_; base::FilePath profile_path_a_;
diff --git a/chrome/browser/apps/drive/drive_app_mapping.cc b/chrome/browser/apps/drive/drive_app_mapping.cc index 8456fcd..78058f4 100644 --- a/chrome/browser/apps/drive/drive_app_mapping.cc +++ b/chrome/browser/apps/drive/drive_app_mapping.cc
@@ -43,12 +43,8 @@ // static void DriveAppMapping::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kAppLauncherDriveAppMapping, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref( - prefs::kAppLauncherUninstalledDriveApps, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kAppLauncherDriveAppMapping); + registry->RegisterListPref(prefs::kAppLauncherUninstalledDriveApps); } void DriveAppMapping::Add(const std::string& drive_app_id,
diff --git a/chrome/browser/apps/ephemeral_app_service.cc b/chrome/browser/apps/ephemeral_app_service.cc index 6eb8da8..d5ff5b4 100644 --- a/chrome/browser/apps/ephemeral_app_service.cc +++ b/chrome/browser/apps/ephemeral_app_service.cc
@@ -8,22 +8,18 @@ #include "base/command_line.h" #include "base/message_loop/message_loop.h" #include "chrome/browser/apps/ephemeral_app_service_factory.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_switches.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_source.h" -#include "content/public/browser/notification_types.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/extension_util.h" -#include "extensions/browser/notification_types.h" #include "extensions/browser/uninstall_reason.h" #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" +#include "extensions/common/one_shot_event.h" using extensions::Extension; using extensions::ExtensionPrefs; @@ -71,9 +67,9 @@ ephemeral_app_count_(-1), disable_idle_app_delay_(kDefaultDisableAppDelay), weak_ptr_factory_(this) { - registrar_.Add(this, - extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, - content::Source<Profile>(profile_)); + ExtensionSystem::Get(profile_)->ready().Post( + FROM_HERE, + base::Bind(&EphemeralAppService::Init, weak_ptr_factory_.GetWeakPtr())); } EphemeralAppService::~EphemeralAppService() { @@ -115,20 +111,6 @@ } } -void EphemeralAppService::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - switch (type) { - case extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED: { - Init(); - break; - } - default: - NOTREACHED(); - } -} - void EphemeralAppService::OnExtensionWillBeInstalled( content::BrowserContext* browser_context, const extensions::Extension* extension,
diff --git a/chrome/browser/apps/ephemeral_app_service.h b/chrome/browser/apps/ephemeral_app_service.h index cf8c879..76a7213f 100644 --- a/chrome/browser/apps/ephemeral_app_service.h +++ b/chrome/browser/apps/ephemeral_app_service.h
@@ -5,7 +5,6 @@ #ifndef CHROME_BROWSER_APPS_EPHEMERAL_APP_SERVICE_H_ #define CHROME_BROWSER_APPS_EPHEMERAL_APP_SERVICE_H_ -#include <map> #include <set> #include "apps/app_lifetime_monitor.h" @@ -13,8 +12,6 @@ #include "base/scoped_observer.h" #include "base/timer/timer.h" #include "components/keyed_service/core/keyed_service.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" #include "extensions/browser/extension_registry_observer.h" class Profile; @@ -26,7 +23,6 @@ // Performs the background garbage collection of ephemeral apps. class EphemeralAppService : public KeyedService, - public content::NotificationObserver, public extensions::ExtensionRegistryObserver, public apps::AppLifetimeMonitor::Observer { public: @@ -60,11 +56,6 @@ // A map used to order the ephemeral apps by their last launch time. typedef std::multimap<base::Time, std::string> LaunchTimeAppMap; - // content::NotificationObserver implementation. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - // extensions::ExtensionRegistryObserver. void OnExtensionWillBeInstalled(content::BrowserContext* browser_context, const extensions::Extension* extension, @@ -96,7 +87,6 @@ Profile* profile_; - content::NotificationRegistrar registrar_; ScopedObserver<extensions::ExtensionRegistry, extensions::ExtensionRegistryObserver> extension_registry_observer_;
diff --git a/chrome/browser/apps/guest_view/app_view_browsertest.cc b/chrome/browser/apps/guest_view/app_view_browsertest.cc index 8ddc15d7..9a6ba6b 100644 --- a/chrome/browser/apps/guest_view/app_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/app_view_browsertest.cc
@@ -10,83 +10,19 @@ #include "content/public/test/test_utils.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" +#include "extensions/browser/guest_view/test_guest_view_manager.h" #include "extensions/common/switches.h" #include "extensions/test/extension_test_message_listener.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" -namespace { - -class TestGuestViewManager : public extensions::GuestViewManager { - public: - explicit TestGuestViewManager(content::BrowserContext* context) : - extensions::GuestViewManager(context), - web_contents_(NULL) {} - - content::WebContents* WaitForGuestCreated() { - if (web_contents_) - return web_contents_; - - message_loop_runner_ = new content::MessageLoopRunner; - message_loop_runner_->Run(); - return web_contents_; - } - - private: - // GuestViewManager override: - void AddGuest(int guest_instance_id, - content::WebContents* guest_web_contents) override { - extensions::GuestViewManager::AddGuest( - guest_instance_id, guest_web_contents); - web_contents_ = guest_web_contents; - - if (message_loop_runner_.get()) - message_loop_runner_->Quit(); - } - - content::WebContents* web_contents_; - scoped_refptr<content::MessageLoopRunner> message_loop_runner_; -}; - -// Test factory for creating test instances of GuestViewManager. -class TestGuestViewManagerFactory : public extensions::GuestViewManagerFactory { - public: - TestGuestViewManagerFactory() : - test_guest_view_manager_(NULL) {} - - ~TestGuestViewManagerFactory() override {} - - extensions::GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) override { - return GetManager(context); - } - - TestGuestViewManager* GetManager(content::BrowserContext* context) { - if (!test_guest_view_manager_) { - test_guest_view_manager_ = new TestGuestViewManager(context); - } - return test_guest_view_manager_; - } - - private: - TestGuestViewManager* test_guest_view_manager_; - - DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory); -}; - -} // namespace - class AppViewTest : public extensions::PlatformAppBrowserTest { public: AppViewTest() { extensions::GuestViewManager::set_factory_for_testing(&factory_); } - TestGuestViewManager* GetGuestViewManager() { - return factory_.GetManager(browser()->profile()); - } - enum TestServer { NEEDS_TEST_SERVER, NO_TEST_SERVER @@ -134,7 +70,7 @@ extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line); } - TestGuestViewManagerFactory factory_; + extensions::TestGuestViewManagerFactory factory_; }; // Tests that <appview> is able to navigate to another installed app.
diff --git a/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc b/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc index f539220..22c64a4 100644 --- a/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/extension_view/extension_view_browsertest.cc
@@ -6,68 +6,15 @@ #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test_utils.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" +#include "extensions/browser/guest_view/test_guest_view_manager.h" #include "extensions/test/extension_test_message_listener.h" -namespace { - -class TestGuestViewManager : public extensions::GuestViewManager { - public: - explicit TestGuestViewManager(content::BrowserContext* context) - : extensions::GuestViewManager(context), web_contents_(NULL) {} - - content::WebContents* WaitForGuestCreated() { - if (web_contents_) - return web_contents_; - - message_loop_runner_ = new content::MessageLoopRunner; - message_loop_runner_->Run(); - return web_contents_; - } - - private: - // GuestViewManager override. - void AddGuest(int guest_instance_id, - content::WebContents* guest_web_contents) override { - extensions::GuestViewManager::AddGuest(guest_instance_id, - guest_web_contents); - web_contents_ = guest_web_contents; - - if (message_loop_runner_.get()) - message_loop_runner_->Quit(); - } - - content::WebContents* web_contents_; - scoped_refptr<content::MessageLoopRunner> message_loop_runner_; -}; - -// Test factory for creating test instances of GuestViewManager. -class TestGuestViewManagerFactory : public extensions::GuestViewManagerFactory { - public: - TestGuestViewManagerFactory() : test_guest_view_manager_(NULL) {} - - ~TestGuestViewManagerFactory() override {} - - extensions::GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) override { - return GetManager(context); - } - - TestGuestViewManager* GetManager(content::BrowserContext* context) { - if (!test_guest_view_manager_) { - test_guest_view_manager_ = new TestGuestViewManager(context); - } - return test_guest_view_manager_; - } - - private: - TestGuestViewManager* test_guest_view_manager_; - - DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory); -}; - -} // namespace +using extensions::ExtensionsGuestViewManagerDelegate; +using extensions::GuestViewManager; +using extensions::TestGuestViewManager; class ExtensionViewTest : public extensions::PlatformAppBrowserTest { public: @@ -75,8 +22,20 @@ extensions::GuestViewManager::set_factory_for_testing(&factory_); } - TestGuestViewManager* GetGuestViewManager() { - return factory_.GetManager(browser()->profile()); + extensions::TestGuestViewManager* GetGuestViewManager() { + TestGuestViewManager* manager = static_cast<TestGuestViewManager*>( + TestGuestViewManager::FromBrowserContext(browser()->profile())); + // TestGuestViewManager::WaitForSingleGuestCreated may and will get called + // before a guest is created. + if (!manager) { + manager = static_cast<TestGuestViewManager*>( + GuestViewManager::CreateWithDelegate( + browser()->profile(), + scoped_ptr<guestview::GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate( + browser()->profile())))); + } + return manager; } void TestHelper(const std::string& test_name, @@ -111,7 +70,7 @@ extensions::PlatformAppBrowserTest::SetUpCommandLine(command_line); } - TestGuestViewManagerFactory factory_; + extensions::TestGuestViewManagerFactory factory_; }; // Tests that <extensionview> can be created and added to the DOM.
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index 7318ef8..cc42984 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -36,6 +36,7 @@ #include "extensions/browser/api/declarative/test_rules_registry.h" #include "extensions/browser/api/declarative_webrequest/webrequest_constants.h" #include "extensions/browser/app_window/native_app_window.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" #include "extensions/browser/guest_view/test_guest_view_manager.h" @@ -67,6 +68,9 @@ #endif using extensions::ContextMenuMatcher; +using extensions::ExtensionsGuestViewManagerDelegate; +using extensions::GuestViewManager; +using extensions::TestGuestViewManager; using extensions::MenuItem; using prerender::PrerenderLinkManager; using prerender::PrerenderLinkManagerFactory; @@ -85,6 +89,7 @@ const char kEmptyResponsePath[] = "/close-socket"; const char kRedirectResponsePath[] = "/server-redirect"; const char kUserAgentRedirectResponsePath[] = "/detect-user-agent"; +const char kCacheResponsePath[] = "/cache-control-response"; const char kRedirectResponseFullPath[] = "/extensions/platform_apps/web_view/shim/guest_redirect.html"; @@ -252,40 +257,6 @@ DISALLOW_COPY_AND_ASSIGN(MockWebContentsDelegate); }; -class MockWebViewGuestDelegate : public extensions::WebViewGuestDelegate { - public: - explicit MockWebViewGuestDelegate(extensions::WebViewGuest* web_view_guest) - : web_view_guest_(web_view_guest), clear_cache_called_(false) {} - ~MockWebViewGuestDelegate() override {} - - // WebViewGuestDelegate implementation. - void ClearCache(base::Time remove_since, - const base::Closure& callback) override { - clear_cache_called_ = true; - base::MessageLoop::current()->PostTask(FROM_HERE, callback); - } - bool HandleContextMenu(const content::ContextMenuParams& params) override { - return false; - } - void OnAttachWebViewHelpers(content::WebContents* contents) override {} - void OnDidCommitProvisionalLoadForFrame(bool is_main_frame) override {} - void OnDidInitialize() override {} - void OnDocumentLoadedInFrame( - content::RenderFrameHost* render_frame_host) override {} - void OnGuestDestroyed() override {} - void OnShowContextMenu( - int request_id, - const WebViewGuestDelegate::MenuItemVector* items) override {} - - bool clear_cache_called() { return clear_cache_called_; } - - private: - extensions::WebViewGuest* web_view_guest_; - bool clear_cache_called_; - - DISALLOW_COPY_AND_ASSIGN(MockWebViewGuestDelegate); -}; - // This class intercepts download request from the guest. class MockDownloadWebContentsDelegate : public content::WebContentsDelegate { public: @@ -604,14 +575,27 @@ static scoped_ptr<net::test_server::HttpResponse> EmptyResponseHandler( const std::string& path, const net::test_server::HttpRequest& request) { - if (StartsWithASCII(path, request.relative_url, true)) { - return scoped_ptr<net::test_server::HttpResponse>( - new EmptyHttpResponse); - } + if (StartsWithASCII(path, request.relative_url, true)) + return scoped_ptr<net::test_server::HttpResponse>(new EmptyHttpResponse); return scoped_ptr<net::test_server::HttpResponse>(); } + // Handles |request| by serving cache-able response. + static scoped_ptr<net::test_server::HttpResponse> CacheControlResponseHandler( + const std::string& path, + const net::test_server::HttpRequest& request) { + if (!StartsWithASCII(path, request.relative_url, true)) + return scoped_ptr<net::test_server::HttpResponse>(); + + scoped_ptr<net::test_server::BasicHttpResponse> http_response( + new net::test_server::BasicHttpResponse); + http_response->AddCustomHeader("Cache-control", "max-age=3600"); + http_response->set_content_type("text/plain"); + http_response->set_content("dummy text"); + return http_response.Pass(); + } + // Shortcut to return the current MenuManager. extensions::MenuManager* menu_manager() { return extensions::MenuManager::Get(browser()->profile()); @@ -658,6 +642,9 @@ &WebViewTest::UserAgentResponseHandler, kUserAgentRedirectResponsePath, embedded_test_server()->GetURL(kRedirectResponseFullPath))); + + embedded_test_server()->RegisterRequestHandler(base::Bind( + &WebViewTest::CacheControlResponseHandler, kCacheResponsePath)); } LoadAndLaunchPlatformApp(app_location.c_str(), "Launched"); @@ -816,10 +803,20 @@ return embedder_web_contents_; } - extensions::TestGuestViewManager* GetGuestViewManager() { - return static_cast<extensions::TestGuestViewManager*>( - extensions::TestGuestViewManager::FromBrowserContext( - browser()->profile())); + TestGuestViewManager* GetGuestViewManager() { + TestGuestViewManager* manager = static_cast<TestGuestViewManager*>( + TestGuestViewManager::FromBrowserContext(browser()->profile())); + // TestGuestViewManager::WaitForSingleGuestCreated may and will get called + // before a guest is created. + if (!manager) { + manager = static_cast<TestGuestViewManager*>( + GuestViewManager::CreateWithDelegate( + browser()->profile(), + scoped_ptr<guestview::GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate( + browser()->profile())))); + } + return manager; } WebViewTest() : guest_web_contents_(NULL), @@ -1153,6 +1150,11 @@ NEEDS_TEST_SERVER); } +IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAddContentScriptWithCode) { + TestHelper("testAddContentScriptWithCode", "web_view/shim", + NEEDS_TEST_SERVER); +} + IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestExecuteScriptFail) { #if defined(OS_WIN) // Flaky on XP bot http://crbug.com/266185 @@ -2420,25 +2422,7 @@ } IN_PROC_BROWSER_TEST_F(WebViewTest, ClearDataCache) { - LoadAppWithGuest("web_view/clear_data_cache"); - content::WebContents* guest_web_contents = GetGuestWebContents(); - auto guest = extensions::WebViewGuest::FromWebContents(guest_web_contents); - ASSERT_TRUE(guest); - scoped_ptr<extensions::WebViewGuestDelegate> mock_web_view_guest_delegate( - new MockWebViewGuestDelegate(guest)); - scoped_ptr<extensions::WebViewGuestDelegate> orig_web_view_guest_delegate = - guest->SetDelegateForTesting(mock_web_view_guest_delegate.Pass()); - - ASSERT_TRUE(GetEmbedderWebContents()); - ExtensionTestMessageListener clear_data_done_listener( - "WebViewTest.CLEAR_DATA_DONE", false); - EXPECT_TRUE(content::ExecuteScript( - GetEmbedderWebContents(), base::StringPrintf("testClearDataCache()"))); - EXPECT_TRUE(clear_data_done_listener.WaitUntilSatisfied()); - - // Reset delegate back to original once we're done mocking. - mock_web_view_guest_delegate = - guest->SetDelegateForTesting(orig_web_view_guest_delegate.Pass()); + TestHelper("testClearCache", "web_view/clear_data_cache", NEEDS_TEST_SERVER); } // This test is disabled on Win due to being flaky. http://crbug.com/294592
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc index 89a6099..bb24c916 100644 --- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -23,9 +23,11 @@ #include "content/public/test/browser_test_utils.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_base.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" +#include "extensions/browser/guest_view/test_guest_view_manager.h" #include "extensions/test/extension_test_message_listener.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "ui/base/ime/composition_text.h" @@ -34,88 +36,9 @@ #include "ui/events/keycodes/keyboard_codes.h" using extensions::AppWindow; - -class TestGuestViewManager : public extensions::GuestViewManager { - public: - explicit TestGuestViewManager(content::BrowserContext* context) - : GuestViewManager(context), - guest_add_count_(0), - guest_remove_count_(0), - web_contents_(NULL) {} - - content::WebContents* WaitForGuestAdded() { - if (web_contents_) - return web_contents_; - - add_message_loop_runner_ = new content::MessageLoopRunner; - add_message_loop_runner_->Run(); - return web_contents_; - } - - // Waits so that at least |expected_remove_count| guests' creation - // has been seen by this manager. - void WaitForGuestRemoved(size_t expected_remove_count) { - if (guest_remove_count_ >= expected_remove_count) - return; - - remove_message_loop_runner_ = new content::MessageLoopRunner; - remove_message_loop_runner_->Run(); - } - - size_t guest_add_count() { return guest_add_count_; } - - private: - // GuestViewManager override: - void AddGuest(int guest_instance_id, - content::WebContents* guest_web_contents) override { - GuestViewManager::AddGuest(guest_instance_id, guest_web_contents); - web_contents_ = guest_web_contents; - ++guest_add_count_; - - if (add_message_loop_runner_.get()) - add_message_loop_runner_->Quit(); - } - - void RemoveGuest(int guest_instance_id) override { - GuestViewManager::RemoveGuest(guest_instance_id); - ++guest_remove_count_; - - if (remove_message_loop_runner_.get()) - remove_message_loop_runner_->Quit(); - } - - size_t guest_add_count_; - size_t guest_remove_count_; - content::WebContents* web_contents_; - scoped_refptr<content::MessageLoopRunner> add_message_loop_runner_; - scoped_refptr<content::MessageLoopRunner> remove_message_loop_runner_; -}; - -// Test factory for creating test instances of GuestViewManager. -class TestGuestViewManagerFactory : public extensions::GuestViewManagerFactory { - public: - TestGuestViewManagerFactory() : - test_guest_view_manager_(NULL) {} - - ~TestGuestViewManagerFactory() override {} - - extensions::GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) override { - return GetManager(context); - } - - TestGuestViewManager* GetManager(content::BrowserContext* context) { - if (!test_guest_view_manager_) { - test_guest_view_manager_ = new TestGuestViewManager(context); - } - return test_guest_view_manager_; - } - - private: - TestGuestViewManager* test_guest_view_manager_; - - DISALLOW_COPY_AND_ASSIGN(TestGuestViewManagerFactory); -}; +using extensions::ExtensionsGuestViewManagerDelegate; +using extensions::GuestViewManager; +using extensions::TestGuestViewManager; class WebViewInteractiveTest : public extensions::PlatformAppBrowserTest { @@ -130,7 +53,19 @@ } TestGuestViewManager* GetGuestViewManager() { - return factory_.GetManager(browser()->profile()); + TestGuestViewManager* manager = static_cast<TestGuestViewManager*>( + TestGuestViewManager::FromBrowserContext(browser()->profile())); + // TestGuestViewManager::WaitForSingleGuestCreated may and will get called + // before a guest is created. + if (!manager) { + manager = static_cast<TestGuestViewManager*>( + GuestViewManager::CreateWithDelegate( + browser()->profile(), + scoped_ptr<guestview::GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate( + browser()->profile())))); + } + return manager; } void MoveMouseInsideWindowWithListener(gfx::Point point, @@ -284,11 +219,9 @@ ASSERT_TRUE(done_listener); ASSERT_TRUE(done_listener->WaitUntilSatisfied()); - guest_web_contents_ = GetGuestViewManager()->WaitForGuestAdded(); + guest_web_contents_ = GetGuestViewManager()->WaitForSingleGuestCreated(); } - void RunTest(const std::string& app_name) { - } void SetupTest(const std::string& app_name, const std::string& guest_url_spec) { ASSERT_TRUE(StartEmbeddedTestServer()); @@ -547,7 +480,7 @@ } protected: - TestGuestViewManagerFactory factory_; + extensions::TestGuestViewManagerFactory factory_; content::WebContents* guest_web_contents_; content::WebContents* embedder_web_contents_; gfx::Point corner_; @@ -900,13 +833,13 @@ TestHelper("testNewWindowOpenerDestroyedWhileUnattached", "web_view/newwindow", NEEDS_TEST_SERVER); - ASSERT_EQ(2u, GetGuestViewManager()->guest_add_count()); + ASSERT_EQ(2, GetGuestViewManager()->num_guests_created()); // We have two guests in this test, one is the intial one, the other // is the newwindow one. // Before the embedder goes away, both the guests should go away. // This ensures that unattached guests are gone if opener is gone. - GetGuestViewManager()->WaitForGuestRemoved(2u); + GetGuestViewManager()->WaitForAllGuestsDeleted(); } IN_PROC_BROWSER_TEST_F(WebViewInteractiveTest, ExecuteCode) {
diff --git a/chrome/browser/apps/shortcut_manager.cc b/chrome/browser/apps/shortcut_manager.cc index be1533a..819df61 100644 --- a/chrome/browser/apps/shortcut_manager.cc +++ b/chrome/browser/apps/shortcut_manager.cc
@@ -75,9 +75,7 @@ void AppShortcutManager::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { // Indicates whether app shortcuts have been created. - registry->RegisterIntegerPref( - prefs::kAppShortcutsVersion, 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kAppShortcutsVersion, 0); } AppShortcutManager::AppShortcutManager(Profile* profile)
diff --git a/chrome/browser/autocomplete/autocomplete_controller.h b/chrome/browser/autocomplete/autocomplete_controller.h index 8096137..6ca35cb 100644 --- a/chrome/browser/autocomplete/autocomplete_controller.h +++ b/chrome/browser/autocomplete/autocomplete_controller.h
@@ -57,7 +57,7 @@ TemplateURLService* template_url_service, AutocompleteControllerDelegate* delegate, int provider_types); - ~AutocompleteController(); + ~AutocompleteController() override; // Starts an autocomplete query, which continues until all providers are // done or the query is Stop()ed. It is safe to Start() a new query without @@ -96,7 +96,7 @@ void ExpireCopiedEntries(); // AutocompleteProviderListener: - virtual void OnProviderUpdate(bool updated_matches) override; + void OnProviderUpdate(bool updated_matches) override; // Called when an omnibox event log entry is generated. // Populates provider_info with diagnostic information about the status
diff --git a/chrome/browser/autocomplete/autocomplete_provider_unittest.cc b/chrome/browser/autocomplete/autocomplete_provider_unittest.cc index 6db865f..56099092 100644 --- a/chrome/browser/autocomplete/autocomplete_provider_unittest.cc +++ b/chrome/browser/autocomplete/autocomplete_provider_unittest.cc
@@ -7,7 +7,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/strings/string16.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -30,6 +29,7 @@ #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_source.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" static std::ostream& operator<<(std::ostream& os, @@ -234,7 +234,7 @@ const content::NotificationSource& source, const content::NotificationDetails& details) override; - base::MessageLoopForUI message_loop_; + content::TestBrowserThreadBundle thread_bundle_; content::NotificationRegistrar registrar_; TestingProfile profile_; scoped_ptr<AutocompleteController> controller_;
diff --git a/chrome/browser/autocomplete/bookmark_provider_unittest.cc b/chrome/browser/autocomplete/bookmark_provider_unittest.cc index 4afa6be..e9ba234a 100644 --- a/chrome/browser/autocomplete/bookmark_provider_unittest.cc +++ b/chrome/browser/autocomplete/bookmark_provider_unittest.cc
@@ -21,6 +21,7 @@ #include "components/bookmarks/test/test_bookmark_client.h" #include "components/metrics/proto/omnibox_event.pb.h" #include "components/omnibox/autocomplete_provider.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" using bookmarks::BookmarkMatch; @@ -74,6 +75,7 @@ protected: void SetUp() override; + content::TestBrowserThreadBundle thread_bundle_; bookmarks::TestBookmarkClient client_; scoped_ptr<TestingProfile> profile_; scoped_ptr<BookmarkModel> model_;
diff --git a/chrome/browser/autocomplete/history_url_provider.h b/chrome/browser/autocomplete/history_url_provider.h index 4a43e2d..6a97dff 100644 --- a/chrome/browser/autocomplete/history_url_provider.h +++ b/chrome/browser/autocomplete/history_url_provider.h
@@ -193,11 +193,10 @@ HistoryURLProvider(AutocompleteProviderListener* listener, Profile* profile); // HistoryProvider: - virtual void Start(const AutocompleteInput& input, - bool minimal_changes, - bool called_due_to_focus) override; - virtual void Stop(bool clear_cached_results, - bool due_to_user_inactivity) override; + void Start(const AutocompleteInput& input, + bool minimal_changes, + bool called_due_to_focus) override; + void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; // Returns a match representing a navigation to |destination_url| given user // input of |text|. |trim_http| controls whether the match's |fill_into_edit| @@ -229,7 +228,7 @@ }; class VisitClassifier; - ~HistoryURLProvider(); + ~HistoryURLProvider() override; // Determines the relevance for a match, given its type. If |match_type| is // NORMAL, |match_number| is a number indicating the relevance of the match
diff --git a/chrome/browser/autocomplete/in_memory_url_index.cc b/chrome/browser/autocomplete/in_memory_url_index.cc index 6533014..62236ae 100644 --- a/chrome/browser/autocomplete/in_memory_url_index.cc +++ b/chrome/browser/autocomplete/in_memory_url_index.cc
@@ -16,7 +16,7 @@ using in_memory_url_index::InMemoryURLIndexCacheItem; // Called by DoSaveToCacheFile to delete any old cache file at |path| when -// there is no private data to save. Runs on the FILE thread. +// there is no private data to save. Runs on the blocking pool. void DeleteCacheFile(const base::FilePath& path) { DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); base::DeleteFile(path, false); @@ -90,6 +90,9 @@ private_data_(new URLIndexPrivateData), restore_cache_observer_(NULL), save_cache_observer_(NULL), + task_runner_( + content::BrowserThread::GetBlockingPool()->GetSequencedTaskRunner( + content::BrowserThread::GetBlockingPool()->GetSequenceToken())), shutdown_(false), restored_(false), needs_to_be_cached_(false), @@ -191,10 +194,8 @@ // in it (URLs visited after user deleted some URLs from history), which // would be odd and confusing. It's better to force a rebuild. base::FilePath path; - if (needs_to_be_cached_ && GetCacheFilePath(&path)) { - content::BrowserThread::PostBlockingPoolTask( - FROM_HERE, base::Bind(DeleteCacheFile, path)); - } + if (needs_to_be_cached_ && GetCacheFilePath(&path)) + task_runner_->PostTask(FROM_HERE, base::Bind(DeleteCacheFile, path)); } void InMemoryURLIndex::OnHistoryServiceLoaded( @@ -218,9 +219,9 @@ return; } - content::BrowserThread::PostTaskAndReplyWithResult - <scoped_refptr<URLIndexPrivateData> >( - content::BrowserThread::FILE, FROM_HERE, + base::PostTaskAndReplyWithResult( + task_runner_.get(), + FROM_HERE, base::Bind(&URLIndexPrivateData::RestoreFromFile, path, languages_), base::Bind(&InMemoryURLIndex::OnCacheLoadDone, AsWeakPtr())); } @@ -240,8 +241,7 @@ base::FilePath path; if (!GetCacheFilePath(&path) || shutdown_) return; - content::BrowserThread::PostBlockingPoolTask( - FROM_HERE, base::Bind(DeleteCacheFile, path)); + task_runner_->PostTask(FROM_HERE, base::Bind(DeleteCacheFile, path)); if (history_service_->backend_loaded()) { ScheduleRebuildFromHistory(); } else { @@ -263,7 +263,12 @@ if (!GetCacheFilePath(&path)) return; private_data_tracker_.TryCancelAll(); - URLIndexPrivateData::WritePrivateDataToCacheFileTask(private_data_, path); + task_runner_->PostTask( + FROM_HERE, + base::Bind( + base::IgnoreResult( + &URLIndexPrivateData::WritePrivateDataToCacheFileTask), + private_data_, path)); needs_to_be_cached_ = false; } @@ -317,16 +322,15 @@ // completion closure below. scoped_refptr<URLIndexPrivateData> private_data_copy = private_data_->Duplicate(); - content::BrowserThread::PostTaskAndReplyWithResult<bool>( - content::BrowserThread::FILE, FROM_HERE, + base::PostTaskAndReplyWithResult( + task_runner_.get(), + FROM_HERE, base::Bind(&URLIndexPrivateData::WritePrivateDataToCacheFileTask, private_data_copy, path), base::Bind(&InMemoryURLIndex::OnCacheSaveDone, AsWeakPtr())); } else { // If there is no data in our index then delete any existing cache file. - content::BrowserThread::PostBlockingPoolTask( - FROM_HERE, - base::Bind(DeleteCacheFile, path)); + task_runner_->PostTask(FROM_HERE, base::Bind(DeleteCacheFile, path)); } }
diff --git a/chrome/browser/autocomplete/in_memory_url_index.h b/chrome/browser/autocomplete/in_memory_url_index.h index d5818d8..2b3199cf 100644 --- a/chrome/browser/autocomplete/in_memory_url_index.h +++ b/chrome/browser/autocomplete/in_memory_url_index.h
@@ -27,6 +27,7 @@ class HistoryQuickProviderTest; namespace base { +class SequencedTaskRunner; class Time; } @@ -287,6 +288,10 @@ RestoreCacheObserver* restore_cache_observer_; SaveCacheObserver* save_cache_observer_; + // Task runner from the worker pool, used for operations which require disk + // access. + scoped_refptr<base::SequencedTaskRunner> task_runner_; + base::CancelableTaskTracker private_data_tracker_; base::CancelableTaskTracker cache_reader_tracker_;
diff --git a/chrome/browser/autocomplete/shortcuts_backend.cc b/chrome/browser/autocomplete/shortcuts_backend.cc index 4da4f902..003be70 100644 --- a/chrome/browser/autocomplete/shortcuts_backend.cc +++ b/chrome/browser/autocomplete/shortcuts_backend.cc
@@ -146,6 +146,13 @@ } ShortcutsBackend::~ShortcutsBackend() { + if (db_) { + auto* db = db_.get(); + db->AddRef(); + db_ = nullptr; + if (!BrowserThread::ReleaseSoon(BrowserThread::DB, FROM_HERE, db)) + db->Release(); + } } // static
diff --git a/chrome/browser/autocomplete/shortcuts_backend_unittest.cc b/chrome/browser/autocomplete/shortcuts_backend_unittest.cc index 9e8233a..e10692e3 100644 --- a/chrome/browser/autocomplete/shortcuts_backend_unittest.cc +++ b/chrome/browser/autocomplete/shortcuts_backend_unittest.cc
@@ -54,14 +54,16 @@ bool DeleteShortcutsWithIDs( const ShortcutsDatabase::ShortcutIDs& deleted_ids); + private: + base::MessageLoopForUI ui_message_loop_; + content::TestBrowserThread ui_thread_; + content::TestBrowserThread db_thread_; + protected: TestingProfile profile_; private: scoped_refptr<ShortcutsBackend> backend_; - base::MessageLoopForUI ui_message_loop_; - content::TestBrowserThread ui_thread_; - content::TestBrowserThread db_thread_; bool load_notified_; bool changed_notified_;
diff --git a/chrome/browser/autocomplete/shortcuts_database_unittest.cc b/chrome/browser/autocomplete/shortcuts_database_unittest.cc index 5c744cd..756752a 100644 --- a/chrome/browser/autocomplete/shortcuts_database_unittest.cc +++ b/chrome/browser/autocomplete/shortcuts_database_unittest.cc
@@ -14,6 +14,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/test/base/testing_profile.h" #include "components/omnibox/autocomplete_match_type.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "sql/statement.h" #include "sql/test/test_helpers.h" #include "testing/gtest/include/gtest/gtest.h" @@ -87,6 +88,7 @@ void AddAll(); + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<TestingProfile> profile_; scoped_refptr<ShortcutsDatabase> db_; };
diff --git a/chrome/browser/autocomplete/zero_suggest_provider.cc b/chrome/browser/autocomplete/zero_suggest_provider.cc index ed00030..bb9f460 100644 --- a/chrome/browser/autocomplete/zero_suggest_provider.cc +++ b/chrome/browser/autocomplete/zero_suggest_provider.cc
@@ -85,10 +85,7 @@ // static void ZeroSuggestProvider::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kZeroSuggestCachedResults, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kZeroSuggestCachedResults, std::string()); } void ZeroSuggestProvider::Start(const AutocompleteInput& input,
diff --git a/chrome/browser/autocomplete/zero_suggest_provider_unittest.cc b/chrome/browser/autocomplete/zero_suggest_provider_unittest.cc index 96c9f59..e15c471 100644 --- a/chrome/browser/autocomplete/zero_suggest_provider_unittest.cc +++ b/chrome/browser/autocomplete/zero_suggest_provider_unittest.cc
@@ -90,6 +90,7 @@ bool AddForcedURL(const GURL& url, const base::Time& time) override { return false; } + void OnNavigationCommitted(const GURL& url) override {} // RefcountedKeyedService: void ShutdownOnUIThread() override {}
diff --git a/chrome/browser/autofill/autofill_cc_infobar_delegate_unittest.cc b/chrome/browser/autofill/autofill_cc_infobar_delegate_unittest.cc index adc41d3f..50f86423 100644 --- a/chrome/browser/autofill/autofill_cc_infobar_delegate_unittest.cc +++ b/chrome/browser/autofill/autofill_cc_infobar_delegate_unittest.cc
@@ -29,8 +29,8 @@ using PersonalDataManager::SetPrefService; // Overridden to avoid a trip to the database. - virtual void LoadProfiles() override {} - virtual void LoadCreditCards() override {} + void LoadProfiles() override {} + void LoadCreditCards() override {} MOCK_METHOD1(SaveImportedCreditCard, std::string(const CreditCard& imported_credit_card));
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc index 90a5107..406411b 100644 --- a/chrome/browser/background/background_contents_service.cc +++ b/chrome/browser/background/background_contents_service.cc
@@ -67,6 +67,7 @@ namespace { const char kNotificationPrefix[] = "app.background.crashed."; +bool g_disable_close_balloon_for_testing = false; void CloseBalloon(const std::string& balloon_id, ProfileID profile_id) { NotificationUIManager* notification_ui_manager = @@ -84,7 +85,7 @@ // Closes the crash notification balloon for the app/extension with this id. void ScheduleCloseBalloon(const std::string& extension_id, Profile* profile) { - if (!base::MessageLoop::current()) // For unit_tests + if (g_disable_close_balloon_for_testing) return; base::MessageLoop::current()->PostTask( FROM_HERE, @@ -293,6 +294,12 @@ ShowBalloon(extension, profile); } +// static +void BackgroundContentsService::DisableCloseBalloonForTesting( + bool disable_close_balloon_for_testing) { + g_disable_close_balloon_for_testing = disable_close_balloon_for_testing; +} + std::vector<BackgroundContents*> BackgroundContentsService::GetBackgroundContents() const {
diff --git a/chrome/browser/background/background_contents_service.h b/chrome/browser/background/background_contents_service.h index 380982b..1448af6 100644 --- a/chrome/browser/background/background_contents_service.h +++ b/chrome/browser/background/background_contents_service.h
@@ -75,6 +75,10 @@ static void ShowBalloonForTesting(const extensions::Extension* extension, Profile* profile); + // Disable closing the crash notification balloon for tests. + static void DisableCloseBalloonForTesting( + bool disable_close_balloon_for_testing); + // Returns the BackgroundContents associated with the passed application id, // or NULL if none. BackgroundContents* GetAppBackgroundContents(const base::string16& appid);
diff --git a/chrome/browser/background/background_contents_service_factory.cc b/chrome/browser/background/background_contents_service_factory.cc index e15f860..de469a4 100644 --- a/chrome/browser/background/background_contents_service_factory.cc +++ b/chrome/browser/background/background_contents_service_factory.cc
@@ -45,9 +45,7 @@ void BackgroundContentsServiceFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* user_prefs) { - user_prefs->RegisterDictionaryPref( - prefs::kRegisteredBackgroundContents, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + user_prefs->RegisterDictionaryPref(prefs::kRegisteredBackgroundContents); } content::BrowserContext*
diff --git a/chrome/browser/background/background_contents_service_unittest.cc b/chrome/browser/background/background_contents_service_unittest.cc index 4b23a0d1..6d726f01 100644 --- a/chrome/browser/background/background_contents_service_unittest.cc +++ b/chrome/browser/background/background_contents_service_unittest.cc
@@ -7,7 +7,6 @@ #include "base/basictypes.h" #include "base/command_line.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "base/prefs/pref_service.h" #include "base/prefs/scoped_user_pref_update.h" #include "base/run_loop.h" @@ -25,6 +24,7 @@ #include "chrome/test/base/testing_profile_manager.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/common/extension.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -44,6 +44,11 @@ ~BackgroundContentsServiceTest() override {} void SetUp() override { command_line_.reset(new base::CommandLine(base::CommandLine::NO_PROGRAM)); + BackgroundContentsService::DisableCloseBalloonForTesting(true); + } + + void TearDown() override { + BackgroundContentsService::DisableCloseBalloonForTesting(false); } const base::DictionaryValue* GetPrefs(Profile* profile) { @@ -62,6 +67,7 @@ return url; } + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<base::CommandLine> command_line_; };
diff --git a/chrome/browser/background/background_mode_manager_unittest.cc b/chrome/browser/background/background_mode_manager_unittest.cc index 7b58503..8551a7d 100644 --- a/chrome/browser/background/background_mode_manager_unittest.cc +++ b/chrome/browser/background/background_mode_manager_unittest.cc
@@ -7,6 +7,8 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/test_simple_task_runner.h" +#include "base/thread_task_runner_handle.h" #include "chrome/browser/background/background_mode_manager.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/extensions/extension_function_test_utils.h" @@ -44,6 +46,13 @@ namespace { +scoped_ptr<TestingProfileManager> CreateTestingProfileManager() { + scoped_ptr<TestingProfileManager> profile_manager( + new TestingProfileManager(TestingBrowserProcess::GetGlobal())); + EXPECT_TRUE(profile_manager->SetUp()); + return profile_manager.Pass(); +} + // Helper class that tracks state transitions in BackgroundModeManager and // exposes them via getters (or gmock for EnableLaunchOnStartup). class TestBackgroundModeManager : public StrictMock<BackgroundModeManager> { @@ -153,28 +162,19 @@ command_line_.reset(new base::CommandLine(base::CommandLine::NO_PROGRAM)); profile_manager_ = CreateTestingProfileManager(); profile_ = profile_manager_->CreateTestingProfile("p1"); + chrome::DisableShutdownForTesting(true); + } + + void TearDown() override { + // Don't allow the browser to be closed because the shutdown procedure will + // attempt to access objects that we haven't created (e.g., MessageCenter). + browser_shutdown::SetTryingToQuit(true); + chrome::DisableShutdownForTesting(false); + browser_shutdown::SetTryingToQuit(false); } protected: - scoped_refptr<extensions::Extension> CreateExtension( - extensions::Manifest::Location location, - const std::string& data, - const std::string& id) { - scoped_ptr<base::DictionaryValue> parsed_manifest( - extensions::api_test_utils::ParseDictionary(data)); - return extensions::api_test_utils::CreateExtension( - location, parsed_manifest.get(), id); - } - - // From views::MenuModelAdapter::IsCommandEnabled with modification. - bool IsCommandEnabled(ui::MenuModel* model, int id) const { - int index = 0; - if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) - return model->IsEnabledAt(index); - - return false; - } - + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<base::CommandLine> command_line_; scoped_ptr<TestingProfileManager> profile_manager_; @@ -182,24 +182,18 @@ TestingProfile* profile_; private: - scoped_ptr<TestingProfileManager> CreateTestingProfileManager() { - scoped_ptr<TestingProfileManager> profile_manager - (new TestingProfileManager(TestingBrowserProcess::GetGlobal())); - EXPECT_TRUE(profile_manager->SetUp()); - return profile_manager.Pass(); - } - DISALLOW_COPY_AND_ASSIGN(BackgroundModeManagerTest); }; -class BackgroundModeManagerWithExtensionsTest - : public BackgroundModeManagerTest { +class BackgroundModeManagerWithExtensionsTest : public testing::Test { public: BackgroundModeManagerWithExtensionsTest() {} ~BackgroundModeManagerWithExtensionsTest() override {} void SetUp() override { - BackgroundModeManagerTest::SetUp(); + command_line_.reset(new base::CommandLine(base::CommandLine::NO_PROGRAM)); + profile_manager_ = CreateTestingProfileManager(); + profile_ = profile_manager_->CreateTestingProfile("p1"); // Aura clears notifications from the message center at shutdown. message_center::MessageCenter::Initialize(); @@ -266,6 +260,25 @@ } protected: + scoped_refptr<extensions::Extension> CreateExtension( + extensions::Manifest::Location location, + const std::string& data, + const std::string& id) { + scoped_ptr<base::DictionaryValue> parsed_manifest( + extensions::api_test_utils::ParseDictionary(data)); + return extensions::api_test_utils::CreateExtension( + location, parsed_manifest.get(), id); + } + + // From views::MenuModelAdapter::IsCommandEnabled with modification. + bool IsCommandEnabled(ui::MenuModel* model, int id) const { + int index = 0; + if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index)) + return model->IsEnabledAt(index); + + return false; + } + void AddEphemeralApp(const extensions::Extension* extension, ExtensionService* service) { extensions::ExtensionPrefs* prefs = @@ -282,6 +295,12 @@ scoped_ptr<TestBackgroundModeManager> manager_; + scoped_ptr<base::CommandLine> command_line_; + + scoped_ptr<TestingProfileManager> profile_manager_; + // Test profile used by all tests - this is owned by profile_manager_. + TestingProfile* profile_; + private: // Required for extension service. content::TestBrowserThreadBundle thread_bundle_;
diff --git a/chrome/browser/bookmarks/bookmark_model_factory.cc b/chrome/browser/bookmarks/bookmark_model_factory.cc index e0f7e80..e031858 100644 --- a/chrome/browser/bookmarks/bookmark_model_factory.cc +++ b/chrome/browser/bookmarks/bookmark_model_factory.cc
@@ -88,14 +88,9 @@ // want to sync the expanded state of folders, it should be part of // bookmark sync itself (i.e., a property of the sync folder nodes). registry->RegisterListPref(bookmarks::prefs::kBookmarkEditorExpandedNodes, - new base::ListValue, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref( - bookmarks::prefs::kManagedBookmarks, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref( - bookmarks::prefs::kSupervisedBookmarks, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + new base::ListValue); + registry->RegisterListPref(bookmarks::prefs::kManagedBookmarks); + registry->RegisterListPref(bookmarks::prefs::kSupervisedBookmarks); } content::BrowserContext* BookmarkModelFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/browser_about_handler_unittest.cc b/chrome/browser/browser_about_handler_unittest.cc index 2448653..b904287 100644 --- a/chrome/browser/browser_about_handler_unittest.cc +++ b/chrome/browser/browser_about_handler_unittest.cc
@@ -12,6 +12,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/common/referrer.h" #include "content/public/test/test_browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -20,7 +21,9 @@ using content::NavigationEntry; using content::Referrer; -typedef testing::Test BrowserAboutHandlerTest; +class BrowserAboutHandlerTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; TEST_F(BrowserAboutHandlerTest, WillHandleBrowserAboutURL) { std::string chrome_prefix(content::kChromeUIScheme); @@ -70,8 +73,6 @@ GURL(chrome_prefix + "host/path?query#ref"), } }; - base::MessageLoopForUI message_loop; - content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); TestingProfile profile; for (size_t i = 0; i < arraysize(test_data); ++i) {
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index a5b6d0a..f41e589a 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -135,7 +135,7 @@ #endif #if !defined(DISABLE_NACL) -#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h" +#include "chrome/browser/component_updater/pnacl_component_installer.h" #endif #if defined(ENABLE_PLUGIN_INSTALLATION)
diff --git a/chrome/browser/browser_process_platform_part_aurawin.h b/chrome/browser/browser_process_platform_part_aurawin.h index 9cf6dc4..8063f26 100644 --- a/chrome/browser/browser_process_platform_part_aurawin.h +++ b/chrome/browser/browser_process_platform_part_aurawin.h
@@ -17,19 +17,19 @@ public content::NotificationObserver { public: BrowserProcessPlatformPart(); - virtual ~BrowserProcessPlatformPart(); + ~BrowserProcessPlatformPart() override; // Invoked when the ASH metro viewer process on Windows 8 exits. void OnMetroViewerProcessTerminated(); // Overridden from BrowserProcessPlatformPartBase: - virtual void PlatformSpecificCommandLineProcessing( + void PlatformSpecificCommandLineProcessing( const base::CommandLine& command_line) override; // content::NotificationObserver method: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; private: // Hosts the channel for the Windows 8 metro viewer process which runs in
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc index e9e2a51a..f8a68da 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -15,12 +15,15 @@ #include "base/guid.h" #include "base/message_loop/message_loop.h" #include "base/prefs/testing_pref_service.h" +#include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/task/cancelable_task_tracker.h" #include "chrome/browser/autofill/personal_data_manager_factory.h" +#include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_remover_test_util.h" #include "chrome/browser/domain_reliability/service_factory.h" +#include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/common/pref_names.h" @@ -31,9 +34,12 @@ #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/personal_data_manager_observer.h" +#include "components/bookmarks/browser/bookmark_model.h" +#include "components/bookmarks/test/bookmark_test_helpers.h" #include "components/domain_reliability/clear_mode.h" #include "components/domain_reliability/monitor.h" #include "components/domain_reliability/service.h" +#include "components/favicon/core/favicon_service.h" #include "components/history/core/browser/history_service.h" #include "content/public/browser/cookie_store_factory.h" #include "content/public/browser/dom_storage_context.h" @@ -50,6 +56,8 @@ #include "net/url_request/url_request_context_getter.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/favicon_size.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/users/mock_user_manager.h" @@ -431,6 +439,96 @@ DISALLOW_COPY_AND_ASSIGN(RemoveHistoryTester); }; +class RemoveFaviconTester { + public: + RemoveFaviconTester() + : got_favicon_(false), + got_expired_favicon_(false), + history_service_(nullptr), + favicon_service_(nullptr) {} + + bool Init(TestingProfile* profile) WARN_UNUSED_RESULT { + // Create the history service if it has not been created yet. + history_service_ = HistoryServiceFactory::GetForProfile( + profile, ServiceAccessType::EXPLICIT_ACCESS); + if (!history_service_) { + if (!profile->CreateHistoryService(true, false)) + return false; + history_service_ = HistoryServiceFactory::GetForProfile( + profile, ServiceAccessType::EXPLICIT_ACCESS); + } + + profile->CreateFaviconService(); + favicon_service_ = FaviconServiceFactory::GetForProfile( + profile, ServiceAccessType::EXPLICIT_ACCESS); + return true; + } + + // Returns true if there is a favicon stored for |page_url| in the favicon + // database. + bool HasFaviconForPageURL(const GURL& page_url) { + RequestFaviconSyncForPageURL(page_url); + return got_favicon_; + } + + // Returns true if: + // - There is a favicon stored for |page_url| in the favicon database. + // - The stored favicon is expired. + bool HasExpiredFaviconForPageURL(const GURL& page_url) { + RequestFaviconSyncForPageURL(page_url); + return got_expired_favicon_; + } + + // Adds a visit to history and stores an arbitrary favicon bitmap for + // |page_url|. + void VisitAndAddFavicon(const GURL& page_url) { + history_service_->AddPage(page_url, base::Time::Now(), nullptr, 0, GURL(), + history::RedirectList(), ui::PAGE_TRANSITION_LINK, + history::SOURCE_BROWSED, false); + + SkBitmap bitmap; + bitmap.allocN32Pixels(gfx::kFaviconSize, gfx::kFaviconSize); + bitmap.eraseColor(SK_ColorBLUE); + favicon_service_->SetFavicons(page_url, page_url, favicon_base::FAVICON, + gfx::Image::CreateFrom1xBitmap(bitmap)); + } + + private: + // Synchronously requests the favicon for |page_url| from the favicon + // database. + void RequestFaviconSyncForPageURL(const GURL& page_url) { + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + favicon_service_->GetRawFaviconForPageURL( + page_url, + favicon_base::FAVICON, + gfx::kFaviconSize, + base::Bind(&RemoveFaviconTester::SaveResultAndQuit, + base::Unretained(this)), + &tracker_); + run_loop.Run(); + } + + // Callback for HistoryService::QueryURL. + void SaveResultAndQuit(const favicon_base::FaviconRawBitmapResult& result) { + got_favicon_ = result.is_valid(); + got_expired_favicon_ = result.is_valid() && result.expired; + quit_closure_.Run(); + } + + // For favicon requests. + base::CancelableTaskTracker tracker_; + bool got_favicon_; + bool got_expired_favicon_; + base::Closure quit_closure_; + + // Owned by TestingProfile. + history::HistoryService* history_service_; + favicon::FaviconService* favicon_service_; + + DISALLOW_COPY_AND_ASSIGN(RemoveFaviconTester); +}; + class RemoveAutofillTester : public autofill::PersonalDataManagerObserver { public: explicit RemoveAutofillTester(TestingProfile* profile) @@ -1192,6 +1290,48 @@ } #endif +// Test that clearing history deletes favicons not associated with bookmarks. +TEST_F(BrowsingDataRemoverTest, RemoveFaviconsForever) { + GURL page_url("http://a"); + + RemoveFaviconTester favicon_tester; + ASSERT_TRUE(favicon_tester.Init(GetProfile())); + favicon_tester.VisitAndAddFavicon(page_url); + ASSERT_TRUE(favicon_tester.HasFaviconForPageURL(page_url)); + + BlockUntilBrowsingDataRemoved(BrowsingDataRemover::EVERYTHING, + BrowsingDataRemover::REMOVE_HISTORY, false); + EXPECT_EQ(BrowsingDataRemover::REMOVE_HISTORY, GetRemovalMask()); + EXPECT_FALSE(favicon_tester.HasFaviconForPageURL(page_url)); +} + +// Test that a bookmark's favicon is expired and not deleted when clearing +// history. Expiring the favicon causes the bookmark's favicon to be updated +// when the user next visits the bookmarked page. Expiring the bookmark's +// favicon is useful when the bookmark's favicon becomes incorrect (See +// crbug.com/474421 for a sample bug which causes this). +TEST_F(BrowsingDataRemoverTest, ExpireBookmarkFavicons) { + GURL bookmarked_page("http://a"); + + TestingProfile* profile = GetProfile(); + profile->CreateBookmarkModel(true); + bookmarks::BookmarkModel* bookmark_model = + BookmarkModelFactory::GetForProfile(profile); + bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model); + bookmark_model->AddURL(bookmark_model->bookmark_bar_node(), 0, + base::ASCIIToUTF16("a"), bookmarked_page); + + RemoveFaviconTester favicon_tester; + ASSERT_TRUE(favicon_tester.Init(GetProfile())); + favicon_tester.VisitAndAddFavicon(bookmarked_page); + ASSERT_TRUE(favicon_tester.HasFaviconForPageURL(bookmarked_page)); + + BlockUntilBrowsingDataRemoved(BrowsingDataRemover::EVERYTHING, + BrowsingDataRemover::REMOVE_HISTORY, false); + EXPECT_EQ(BrowsingDataRemover::REMOVE_HISTORY, GetRemovalMask()); + EXPECT_TRUE(favicon_tester.HasExpiredFaviconForPageURL(bookmarked_page)); +} + TEST_F(BrowsingDataRemoverTest, RemoveQuotaManagedDataForeverBoth) { BlockUntilBrowsingDataRemoved(BrowsingDataRemover::EVERYTHING, BrowsingDataRemover::REMOVE_FILE_SYSTEMS |
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index a8c1b1f..ab69bfe 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -24,6 +24,7 @@ #include "base/prefs/pref_value_store.h" #include "base/prefs/scoped_user_pref_update.h" #include "base/process/process_info.h" +#include "base/profiler/scoped_profile.h" #include "base/profiler/scoped_tracker.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" @@ -33,6 +34,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/sys_info.h" #include "base/threading/platform_thread.h" +#include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "base/values.h" @@ -197,7 +199,7 @@ #endif // !defined(OS_IOS) #if !defined(DISABLE_NACL) -#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h" +#include "chrome/browser/component_updater/pnacl_component_installer.h" #include "components/nacl/browser/nacl_process_host.h" #endif // !defined(DISABLE_NACL) @@ -333,6 +335,9 @@ const base::FilePath& user_data_dir, const base::CommandLine& parsed_command_line) { TRACE_EVENT0("startup", "ChromeBrowserMainParts::CreateProfile") + TRACK_SCOPED_REGION( + "Startup", "ChromeBrowserMainParts::CreatePrimaryProfile"); + base::Time start = base::Time::Now(); if (profiles::IsMultipleProfilesEnabled() && parsed_command_line.HasSwitch(switches::kProfileDirectory)) { @@ -989,8 +994,8 @@ #endif // defined(OS_LINUX) || defined(OS_OPENBSD) || defined(OS_MACOSX) // Initialize tracking synchronizer system. - tracking_synchronizer_ = - new metrics::TrackingSynchronizer(base::TimeTicks::Now()); + tracking_synchronizer_ = new metrics::TrackingSynchronizer( + make_scoped_ptr(new base::DefaultTickClock())); #if defined(OS_MACOSX) // Get the Keychain API to register for distributed notifications on the main @@ -1021,6 +1026,9 @@ void ChromeBrowserMainParts::PreMainMessageLoopRun() { TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreMainMessageLoopRun"); + TRACK_SCOPED_REGION( + "Startup", "ChromeBrowserMainParts::PreMainMessageLoopRun"); + result_code_ = PreMainMessageLoopRunImpl(); for (size_t i = 0; i < chrome_extra_parts_.size(); ++i) @@ -1126,6 +1134,9 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreMainMessageLoopRunImpl"); + TRACK_SCOPED_REGION( + "Startup", "ChromeBrowserMainParts::PreMainMessageLoopRunImpl"); + SCOPED_UMA_HISTOGRAM_LONG_TIMER("Startup.PreMainMessageLoopRunImplLongTime"); const base::TimeTicks start_time_step1 = base::TimeTicks::Now();
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm index e37d3a5..f48fe74 100644 --- a/chrome/browser/chrome_browser_main_mac.mm +++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -136,14 +136,7 @@ // in the window server, which is the default when not not using the // 10.9 SDK. // TODO: Remove this when we build with the 10.9 SDK. - @"NSWindowHostsLayersInWindowServer": - @(base::mac::IsOSMavericksOrLater()), - // This setting prevents views from ditching their layers when the view - // gets removed from the view hierarchy. It defaults to YES for - // applications linked against an OSX 10.8+ SDK. In Yosemite, failing to - // set this to YES causes an AppKit crash. http://crbug.com/428977 - // TODO(erikchen): Remove this when we build with an OSX 10.8+ SDK. - @"NSViewKeepLayersAround": @(YES) + @"NSWindowHostsLayersInWindowServer": @(base::mac::IsOSMavericksOrLater()) }]; }
diff --git a/chrome/browser/chrome_browser_main_win.h b/chrome/browser/chrome_browser_main_win.h index e5b08831..2662b7b 100644 --- a/chrome/browser/chrome_browser_main_win.h +++ b/chrome/browser/chrome_browser_main_win.h
@@ -26,17 +26,17 @@ explicit ChromeBrowserMainPartsWin( const content::MainFunctionParams& parameters); - virtual ~ChromeBrowserMainPartsWin(); + ~ChromeBrowserMainPartsWin() override; // BrowserParts overrides. - virtual void ToolkitInitialized() override; - virtual void PreMainMessageLoopStart() override; - virtual int PreCreateThreads() override; + void ToolkitInitialized() override; + void PreMainMessageLoopStart() override; + int PreCreateThreads() override; // ChromeBrowserMainParts overrides. - virtual void ShowMissingLocaleMessageBox() override; - virtual void PostProfileInit() override; - virtual void PostBrowserStart() override; + void ShowMissingLocaleMessageBox() override; + void PostProfileInit() override; + void PostBrowserStart() override; // Prepares the localized strings that are going to be displayed to // the user if the browser process dies. These strings are stored in the
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 2617765..f1cb6e4e 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -641,17 +641,9 @@ // static void ChromeContentBrowserClient::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kDisable3DAPIs, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kEnableHyperlinkAuditing, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref( - prefs::kEnableDeprecatedWebPlatformFeatures, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kDisable3DAPIs, false); + registry->RegisterBooleanPref(prefs::kEnableHyperlinkAuditing, true); + registry->RegisterListPref(prefs::kEnableDeprecatedWebPlatformFeatures); } // static
diff --git a/chrome/browser/chrome_elf_init_unittest_win.cc b/chrome/browser/chrome_elf_init_unittest_win.cc index 1bc9e4d8..1960aa54 100644 --- a/chrome/browser/chrome_elf_init_unittest_win.cc +++ b/chrome/browser/chrome_elf_init_unittest_win.cc
@@ -24,9 +24,9 @@ class ChromeBlacklistTrialTest : public testing::Test { protected: ChromeBlacklistTrialTest() {} - virtual ~ChromeBlacklistTrialTest() {} + ~ChromeBlacklistTrialTest() override {} - virtual void SetUp() override { + void SetUp() override { testing::Test::SetUp(); override_manager_.OverrideRegistry(HKEY_CURRENT_USER);
diff --git a/chrome/browser/chrome_select_file_dialog_factory_win.h b/chrome/browser/chrome_select_file_dialog_factory_win.h index 1846da8..6dd9fe7 100644 --- a/chrome/browser/chrome_select_file_dialog_factory_win.h +++ b/chrome/browser/chrome_select_file_dialog_factory_win.h
@@ -23,11 +23,11 @@ // Uses |blocking_task_runner| to perform IPC with the utility process. explicit ChromeSelectFileDialogFactory( const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner); - virtual ~ChromeSelectFileDialogFactory(); + ~ChromeSelectFileDialogFactory() override; // ui::SelectFileDialogFactory implementation - virtual ui::SelectFileDialog* Create(ui::SelectFileDialog::Listener* listener, - ui::SelectFilePolicy* policy) override; + ui::SelectFileDialog* Create(ui::SelectFileDialog::Listener* listener, + ui::SelectFilePolicy* policy) override; private: scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
diff --git a/chrome/browser/chromeos/customization/customization_document.cc b/chrome/browser/chromeos/customization/customization_document.cc index 9aae363e..368908b 100644 --- a/chrome/browser/chromeos/customization/customization_document.cc +++ b/chrome/browser/chromeos/customization/customization_document.cc
@@ -440,9 +440,7 @@ // static void ServicesCustomizationDocument::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - kServicesCustomizationKey, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kServicesCustomizationKey); } // static
diff --git a/chrome/browser/chromeos/dbus/printer_service_provider_unittest.cc b/chrome/browser/chromeos/dbus/printer_service_provider_unittest.cc index 7dd3e99..a39b68f 100644 --- a/chrome/browser/chromeos/dbus/printer_service_provider_unittest.cc +++ b/chrome/browser/chromeos/dbus/printer_service_provider_unittest.cc
@@ -15,6 +15,7 @@ #include "chromeos/chromeos_switches.h" #include "chromeos/dbus/services/service_provider_test_helper.h" #include "components/user_manager/fake_user_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "dbus/message.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension_builder.h" @@ -130,6 +131,7 @@ .Build(); } + content::TestBrowserThreadBundle thread_bundle_; StubNotificationUIManager notification_ui_manager_; TestingProfile profile_; user_manager::FakeUserManager* user_manager_;
diff --git a/chrome/browser/chromeos/display/display_preferences.cc b/chrome/browser/chromeos/display/display_preferences.cc index dca2e5a2..18e054b 100644 --- a/chrome/browser/chromeos/display/display_preferences.cc +++ b/chrome/browser/chromeos/display/display_preferences.cc
@@ -225,14 +225,16 @@ } void StoreCurrentDisplayLayoutPrefs() { + ash::DisplayManager* display_manager = GetDisplayManager(); if (!UserCanSaveDisplayPreference() || - GetDisplayManager()->num_connected_displays() < 2) { + display_manager->num_connected_displays() < 2 || + display_manager->IsInUnifiedMode()) { return; } - ash::DisplayIdPair pair = GetDisplayManager()->GetCurrentDisplayIdPair(); + ash::DisplayIdPair pair = display_manager->GetCurrentDisplayIdPair(); ash::DisplayLayout display_layout = - GetDisplayManager()->layout_store()->GetRegisteredDisplayLayout(pair); + display_manager->layout_store()->GetRegisteredDisplayLayout(pair); StoreDisplayLayoutPref(pair, display_layout); } @@ -251,7 +253,9 @@ scoped_ptr<base::DictionaryValue> property_value( new base::DictionaryValue()); - property_value->SetInteger("rotation", static_cast<int>(info.rotation())); + property_value->SetInteger( + "rotation", + static_cast<int>(info.GetRotation(gfx::Display::ROTATION_SOURCE_USER))); property_value->SetInteger( "ui-scale", static_cast<int>(info.configured_ui_scale() * 1000)); @@ -358,7 +362,7 @@ gfx::Display::Rotation rotation = GetDisplayManager() ->GetDisplayInfo(gfx::Display::InternalDisplayId()) - .rotation(); + .GetRotation(gfx::Display::ROTATION_SOURCE_ACCELEROMETER); pref_data->SetInteger("orientation", static_cast<int>(rotation)); }
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc index d38e572..96c08ad7 100644 --- a/chrome/browser/chromeos/display/display_preferences_unittest.cc +++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -245,7 +245,8 @@ EXPECT_NE(dummy_id, ash::Shell::GetScreen()->GetPrimaryDisplay().id()); display_controller->SetOverscanInsets(id1, gfx::Insets(10, 11, 12, 13)); - display_manager->SetDisplayRotation(id1, gfx::Display::ROTATE_90); + display_manager->SetDisplayRotation(id1, gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_USER); EXPECT_TRUE(display_manager->SetDisplayUIScale(id1, 1.25f)); EXPECT_FALSE(display_manager->SetDisplayUIScale(id2, 1.25f)); @@ -576,7 +577,8 @@ display_controller->SetOverscanInsets( new_primary, gfx::Insets(10, 11, 12, 13)); - display_manager->SetDisplayRotation(new_primary, gfx::Display::ROTATE_90); + display_manager->SetDisplayRotation(new_primary, gfx::Display::ROTATE_90, + gfx::Display::ROTATION_SOURCE_USER); // Does not store the preferences locally. EXPECT_FALSE(local_state()->FindPreference( @@ -599,7 +601,7 @@ const ash::DisplayInfo& info_primary = display_manager->GetDisplayInfo(new_primary); - EXPECT_EQ(gfx::Display::ROTATE_90, info_primary.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, info_primary.GetActiveRotation()); EXPECT_EQ(1.0f, info_primary.configured_ui_scale()); } @@ -669,10 +671,12 @@ LoggedInAsUser(); // Populate the properties. display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(), - gfx::Display::ROTATE_180); + gfx::Display::ROTATE_180, + gfx::Display::ROTATION_SOURCE_USER); // Reset property to avoid rotation lock display_manager->SetDisplayRotation(gfx::Display::InternalDisplayId(), - gfx::Display::ROTATE_0); + gfx::Display::ROTATE_0, + gfx::Display::ROTATION_SOURCE_USER); // Open up 270 degrees to trigger maximize mode scoped_refptr<chromeos::AccelerometerUpdate> update( @@ -690,8 +694,7 @@ update->Set(chromeos::ACCELEROMETER_SOURCE_SCREEN, -kMeanGravity, 0.0f, 0.0f); controller->OnAccelerometerUpdated(update); shell->screen_orientation_controller()->OnAccelerometerUpdated(update); - EXPECT_EQ(gfx::Display::ROTATE_90, display_manager-> - GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, GetCurrentInternalDisplayRotation()); const base::DictionaryValue* properties = local_state()->GetDictionary(prefs::kDisplayProperties); @@ -701,6 +704,17 @@ int rotation = -1; EXPECT_TRUE(property->GetInteger("rotation", &rotation)); EXPECT_EQ(gfx::Display::ROTATE_0, rotation); + + // Trigger a save, the acceleration rotation should not be saved as the user + // rotation. + StoreDisplayPrefs(); + properties = local_state()->GetDictionary(prefs::kDisplayProperties); + property = NULL; + EXPECT_TRUE(properties->GetDictionary( + base::Int64ToString(gfx::Display::InternalDisplayId()), &property)); + rotation = -1; + EXPECT_TRUE(property->GetInteger("rotation", &rotation)); + EXPECT_EQ(gfx::Display::ROTATE_0, rotation); } // Tests that the rotation state is saved without a user being logged in. @@ -720,9 +734,7 @@ EXPECT_EQ(current_rotation_lock, rotation_lock); int orientation; - gfx::Display::Rotation current_rotation = ash::Shell::GetInstance()-> - display_manager()-> - GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); + gfx::Display::Rotation current_rotation = GetCurrentInternalDisplayRotation(); EXPECT_TRUE(properties->GetInteger("orientation", &orientation)); EXPECT_EQ(current_rotation, orientation); } @@ -745,9 +757,7 @@ EXPECT_EQ(current_rotation_lock, rotation_lock); int orientation; - gfx::Display::Rotation current_rotation = ash::Shell::GetInstance()-> - display_manager()-> - GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); + gfx::Display::Rotation current_rotation = GetCurrentInternalDisplayRotation(); EXPECT_TRUE(properties->GetInteger("orientation", &orientation)); EXPECT_EQ(current_rotation, orientation); } @@ -770,9 +780,7 @@ EXPECT_EQ(current_rotation_lock, rotation_lock); int orientation; - gfx::Display::Rotation current_rotation = ash::Shell::GetInstance()-> - display_manager()-> - GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); + gfx::Display::Rotation current_rotation = GetCurrentInternalDisplayRotation(); EXPECT_TRUE(properties->GetInteger("orientation", &orientation)); EXPECT_EQ(current_rotation, orientation); } @@ -788,8 +796,7 @@ bool initial_rotation_lock = IsRotationLocked(); ASSERT_FALSE(initial_rotation_lock); ash::DisplayManager* display_manager = shell->display_manager(); - gfx::Display::Rotation initial_rotation = display_manager-> - GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); + gfx::Display::Rotation initial_rotation = GetCurrentInternalDisplayRotation(); ASSERT_EQ(gfx::Display::ROTATE_0, initial_rotation); StoreDisplayRotationPrefs(initial_rotation_lock); @@ -806,8 +813,8 @@ EXPECT_EQ(gfx::Display::ROTATE_90, display_rotation); bool rotation_lock = IsRotationLocked(); - gfx::Display::Rotation before_maximize_mode_rotation = display_manager-> - GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); + gfx::Display::Rotation before_maximize_mode_rotation = + GetCurrentInternalDisplayRotation(); // Settings should not be applied until maximize mode activates EXPECT_FALSE(rotation_lock); @@ -824,8 +831,8 @@ maximize_mode_controller->OnAccelerometerUpdated(update); EXPECT_TRUE(maximize_mode_controller->IsMaximizeModeWindowManagerEnabled()); bool screen_orientation_rotation_lock = IsRotationLocked(); - gfx::Display::Rotation maximize_mode_rotation = display_manager-> - GetDisplayInfo(gfx::Display::InternalDisplayId()).rotation(); + gfx::Display::Rotation maximize_mode_rotation = + GetCurrentInternalDisplayRotation(); EXPECT_TRUE(screen_orientation_rotation_lock); EXPECT_EQ(gfx::Display::ROTATE_90, maximize_mode_rotation); }
diff --git a/chrome/browser/chromeos/drive/file_system_util_unittest.cc b/chrome/browser/chromeos/drive/file_system_util_unittest.cc index 500ac52..7bbbe0a 100644 --- a/chrome/browser/chromeos/drive/file_system_util_unittest.cc +++ b/chrome/browser/chromeos/drive/file_system_util_unittest.cc
@@ -9,7 +9,6 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/test/base/testing_browser_process.h" @@ -77,7 +76,11 @@ base::FilePath::FromUTF8Unsafe("/special/non-drive-path"))); } -TEST(FileSystemUtilTest, IsUnderDriveMountPoint) { +class FileSystemUtilTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(FileSystemUtilTest, IsUnderDriveMountPoint) { EXPECT_FALSE(IsUnderDriveMountPoint( base::FilePath::FromUTF8Unsafe("/wherever/foo.txt"))); EXPECT_FALSE(IsUnderDriveMountPoint( @@ -95,7 +98,7 @@ base::FilePath::FromUTF8Unsafe("/special/drive-xxx/foo.txt"))); } -TEST(FileSystemUtilTest, ExtractDrivePath) { +TEST_F(FileSystemUtilTest, ExtractDrivePath) { EXPECT_EQ(base::FilePath(), ExtractDrivePath( base::FilePath::FromUTF8Unsafe("/wherever/foo.txt"))); @@ -117,14 +120,13 @@ base::FilePath::FromUTF8Unsafe("/special/drive-xxx/foo.txt"))); } -TEST(FileSystemUtilTest, ExtractDrivePathFromFileSystemUrl) { +TEST_F(FileSystemUtilTest, ExtractDrivePathFromFileSystemUrl) { TestingProfile profile; // Set up file system context for testing. base::ScopedTempDir temp_dir_; ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - base::MessageLoop message_loop; scoped_refptr<storage::ExternalMountPoints> mount_points = storage::ExternalMountPoints::CreateRefCounted(); scoped_refptr<storage::FileSystemContext> context( @@ -188,7 +190,7 @@ isolated_id + "/" + isolated_name)))); } -TEST(FileSystemUtilTest, EscapeUnescapeCacheFileName) { +TEST_F(FileSystemUtilTest, EscapeUnescapeCacheFileName) { const std::string kUnescapedFileName( "tmp:`~!@#$%^&*()-_=+[{|]}\\\\;\',<.>/?"); const std::string kEscapedFileName( @@ -197,7 +199,7 @@ EXPECT_EQ(kUnescapedFileName, UnescapeCacheFileName(kEscapedFileName)); } -TEST(FileSystemUtilTest, NormalizeFileName) { +TEST_F(FileSystemUtilTest, NormalizeFileName) { EXPECT_EQ("", NormalizeFileName("")); EXPECT_EQ("foo", NormalizeFileName("foo")); // Slash @@ -213,14 +215,14 @@ EXPECT_EQ("._", NormalizeFileName("./")); } -TEST(FileSystemUtilTest, GetCacheRootPath) { +TEST_F(FileSystemUtilTest, GetCacheRootPath) { TestingProfile profile; base::FilePath profile_path = profile.GetPath(); EXPECT_EQ(profile_path.AppendASCII("GCache/v1"), util::GetCacheRootPath(&profile)); } -TEST(FileSystemUtilTest, GDocFile) { +TEST_F(FileSystemUtilTest, GDocFile) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc index 8b38af923..60e86dcb 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -1034,9 +1034,10 @@ return; } - download_url_ = - google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction + - entry->resource_id(); + DriveApiUrlGenerator url_generator( + (GURL(google_apis::DriveApiUrlGenerator::kBaseUrlForProduction)), + (GURL(google_apis::DriveApiUrlGenerator::kBaseDownloadUrlForProduction))); + download_url_ = url_generator.GenerateDownloadFileUrl(entry->resource_id()); ProfileOAuth2TokenService* oauth2_token_service = ProfileOAuth2TokenServiceFactory::GetForProfile(GetProfile()); @@ -1065,7 +1066,8 @@ return; } - const std::string url = download_url_ + "?access_token=" + access_token; + const std::string url = + download_url_.Resolve("?access_token=" + access_token).spec(); SetResult(new base::StringValue(url)); SendResponse(true);
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h index af9b20d..da203c6 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
@@ -240,7 +240,7 @@ const std::string& access_token); private: - std::string download_url_; + GURL download_url_; scoped_ptr<google_apis::AuthService> auth_service_; };
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 8c9d28a..8e1d1185 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -1040,10 +1040,14 @@ TestParameter(NOT_IN_GUEST_MODE, "traverseDrive"))); // Slow tests are disabled on debug build. http://crbug.com/327719 -// Disabled under MSAN, ASAN, and LSAN as well. http://crbug.com/479757. -// Flakes often: http://crbug.com/479757 +// Disabled under MSAN as well. http://crbug.com/468980. +#if !defined(NDEBUG) || defined(MEMORY_SANITIZER) +#define MAYBE_SuggestAppDialog DISABLED_SuggestAppDialog +#else +#define MAYBE_SuggestAppDialog SuggestAppDialog +#endif WRAPPED_INSTANTIATE_TEST_CASE_P( - DISABLED_SuggestAppDialog, + MAYBE_SuggestAppDialog, FileManagerBrowserTest, ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "suggestAppDialog"))); @@ -1156,14 +1160,23 @@ ::testing::Values(TestParameter(NOT_IN_GUEST_MODE, "tabindexFocusDirectorySelected"))); +// http://crbug.com/480491 INSTANTIATE_TEST_CASE_P( - TabindexOpenDialog, + DISABLED_TabindexOpenDialog, FileManagerBrowserTest, ::testing::Values( TestParameter(NOT_IN_GUEST_MODE, "tabindexOpenDialogDrive"), TestParameter(NOT_IN_GUEST_MODE, "tabindexOpenDialogDownloads"), TestParameter(IN_GUEST_MODE, "tabindexOpenDialogDownloads"))); +INSTANTIATE_TEST_CASE_P( + TabindexSaveFileDialog, + FileManagerBrowserTest, + ::testing::Values( + TestParameter(NOT_IN_GUEST_MODE, "tabindexSaveFileDialogDrive"), + TestParameter(NOT_IN_GUEST_MODE, "tabindexSaveFileDialogDownloads"), + TestParameter(IN_GUEST_MODE, "tabindexSaveFileDialogDownloads"))); + // Fails on official build. http://crbug.com/429294 // Disabled under MSAN as well. http://crbug.com/468980. #if !defined(NDEBUG) || defined(OFFICIAL_BUILD) || defined(MEMORY_SANITIZER) @@ -1354,13 +1367,13 @@ template<GuestMode M> class GalleryBrowserTestBase : public FileManagerBrowserTestBase { public: - virtual GuestMode GetGuestModeParam() const override { return M; } - virtual const char* GetTestCaseNameParam() const override { + GuestMode GetGuestModeParam() const override { return M; } + const char* GetTestCaseNameParam() const override { return test_case_name_.c_str(); } protected: - virtual const char* GetTestManifestName() const override { + const char* GetTestManifestName() const override { return "gallery_test_manifest.json"; } @@ -1507,19 +1520,19 @@ template<GuestMode M> class VideoPlayerBrowserTestBase : public FileManagerBrowserTestBase { public: - virtual GuestMode GetGuestModeParam() const override { return M; } - virtual const char* GetTestCaseNameParam() const override { + GuestMode GetGuestModeParam() const override { return M; } + const char* GetTestCaseNameParam() const override { return test_case_name_.c_str(); } protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitch( chromeos::switches::kEnableVideoPlayerChromecastSupport); FileManagerBrowserTestBase::SetUpCommandLine(command_line); } - virtual const char* GetTestManifestName() const override { + const char* GetTestManifestName() const override { return "video_player_test_manifest.json"; }
diff --git a/chrome/browser/chromeos/file_system_provider/registry.cc b/chrome/browser/chromeos/file_system_provider/registry.cc index f3b3cd7..d6d6404 100644 --- a/chrome/browser/chromeos/file_system_provider/registry.cc +++ b/chrome/browser/chromeos/file_system_provider/registry.cc
@@ -36,9 +36,7 @@ const char kPrefKeyOpenedFilesLimit[] = "opened-files-limit"; void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kFileSystemProviderMounted, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kFileSystemProviderMounted); } std::string SourceToString(Source source) {
diff --git a/chrome/browser/chromeos/input_method/input_method_syncer.cc b/chrome/browser/chromeos/input_method/input_method_syncer.cc index 1c82be7..b76080cd 100644 --- a/chrome/browser/chromeos/input_method/input_method_syncer.cc +++ b/chrome/browser/chromeos/input_method/input_method_syncer.cc
@@ -140,10 +140,7 @@ prefs::kLanguageEnabledExtensionImesSyncable, "", user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kLanguageShouldMergeInputMethods, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kLanguageShouldMergeInputMethods, false); } void InputMethodSyncer::Initialize() {
diff --git a/chrome/browser/chromeos/login/app_launch_signin_screen.cc b/chrome/browser/chromeos/login/app_launch_signin_screen.cc index d98d51b..e13afed 100644 --- a/chrome/browser/chromeos/login/app_launch_signin_screen.cc +++ b/chrome/browser/chromeos/login/app_launch_signin_screen.cc
@@ -8,10 +8,10 @@ #include "chrome/browser/chromeos/login/help_app_launcher.h" #include "chrome/browser/chromeos/login/screens/user_selection_screen.h" #include "chrome/browser/chromeos/login/session/user_session_manager.h" -#include "chrome/browser/signin/screenlock_bridge.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" #include "chrome/grit/generated_resources.h" #include "chromeos/login/auth/user_context.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_ui.h" @@ -199,10 +199,10 @@ for (user_manager::UserList::const_iterator it = users.begin(); it != users.end(); ++it) { - ScreenlockBridge::LockHandler::AuthType initial_auth_type = + proximity_auth::ScreenlockBridge::LockHandler::AuthType initial_auth_type = UserSelectionScreen::ShouldForceOnlineSignIn(*it) - ? ScreenlockBridge::LockHandler::ONLINE_SIGN_IN - : ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; + ? proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN + : proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; base::DictionaryValue* user_dict = new base::DictionaryValue(); UserSelectionScreen::FillUserDictionary( *it,
diff --git a/chrome/browser/chromeos/login/app_launch_signin_screen.h b/chrome/browser/chromeos/login/app_launch_signin_screen.h index bc560bb1..7a9bb77 100644 --- a/chrome/browser/chromeos/login/app_launch_signin_screen.h +++ b/chrome/browser/chromeos/login/app_launch_signin_screen.h
@@ -8,10 +8,10 @@ #include <string> #include "base/memory/ref_counted.h" -#include "chrome/browser/signin/screenlock_bridge.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" #include "chromeos/login/auth/auth_status_consumer.h" #include "chromeos/login/auth/authenticator.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/chromeos/login/auth/online_attempt_unittest.cc b/chrome/browser/chromeos/login/auth/online_attempt_unittest.cc index 8ba68a3..66839404 100644 --- a/chrome/browser/chromeos/login/auth/online_attempt_unittest.cc +++ b/chrome/browser/chromeos/login/auth/online_attempt_unittest.cc
@@ -16,6 +16,7 @@ #include "chromeos/login/auth/online_attempt.h" #include "chromeos/login/auth/test_attempt_state.h" #include "chromeos/login/auth/user_context.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "google_apis/gaia/gaia_auth_consumer.h" #include "google_apis/gaia/mock_url_fetcher_factory.h" #include "net/url_request/url_request_context.h" @@ -84,9 +85,9 @@ auth->weak_factory_.GetWeakPtr())); } + content::TestBrowserThreadBundle thread_bundle_; scoped_refptr<base::MessageLoopProxy> message_loop_; scoped_refptr<net::URLRequestContextGetter> request_context_; - base::MessageLoop loop_; TestAttemptState state_; MockAuthAttemptStateResolver resolver_; scoped_ptr<OnlineAttempt> attempt_;
diff --git a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.cc b/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.cc index 1c55068..64a6b33a 100644 --- a/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.cc +++ b/chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/signin/easy_unlock_service.h" #include "chrome/browser/signin/easy_unlock_service_regular.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "components/proximity_auth/screenlock_bridge.h" namespace chromeos {
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.cc index 1882dcb..f56fbbb 100644 --- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.cc +++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.cc
@@ -7,12 +7,13 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.h" #include "chrome/browser/chromeos/login/lock/screen_locker.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/grit/generated_resources.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/session_manager_client.h" #include "chromeos/login/auth/auth_status_consumer.h" #include "chromeos/login/auth/user_context.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -74,8 +75,9 @@ screen_locker->SetLoginStatusConsumer(this); // Show tooltip explaining reauth. - ScreenlockBridge::UserPodCustomIconOptions icon_options; - icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE); + proximity_auth::ScreenlockBridge::UserPodCustomIconOptions icon_options; + icon_options.SetIcon( + proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE); icon_options.SetTooltip( l10n_util::GetStringUTF16( IDS_SMART_LOCK_SCREENLOCK_TOOLTIP_HARDLOCK_REAUTH_USER), @@ -83,7 +85,7 @@ const user_manager::UserList& lock_users = screen_locker->users(); DCHECK(lock_users.size() == 1); - ScreenlockBridge::Get()->lock_handler()->ShowUserPodCustomIcon( + GetScreenlockBridgeInstance()->lock_handler()->ShowUserPodCustomIcon( lock_users[0]->email(), icon_options); }
diff --git a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc index ce77bf3..9cdf43e 100644 --- a/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc +++ b/chrome/browser/chromeos/login/enrollment/enterprise_enrollment_helper_impl.cc
@@ -401,6 +401,9 @@ case policy::EnterpriseInstallAttributes::LOCK_WRONG_DOMAIN: UMA(policy::kMetricEnrollmentLockDomainMismatch); break; + case policy::EnterpriseInstallAttributes::LOCK_WRONG_MODE: + UMA(policy::kMetricEnrollmentLockModeMismatch); + break; } break; case policy::EnrollmentStatus::STATUS_ROBOT_AUTH_FETCH_FAILED:
diff --git a/chrome/browser/chromeos/login/enrollment/mock_auto_enrollment_check_screen.h b/chrome/browser/chromeos/login/enrollment/mock_auto_enrollment_check_screen.h index cbcada8..b6dd5e1 100644 --- a/chrome/browser/chromeos/login/enrollment/mock_auto_enrollment_check_screen.h +++ b/chrome/browser/chromeos/login/enrollment/mock_auto_enrollment_check_screen.h
@@ -22,9 +22,9 @@ : public AutoEnrollmentCheckScreenActor { public: MockAutoEnrollmentCheckScreenActor(); - virtual ~MockAutoEnrollmentCheckScreenActor(); + ~MockAutoEnrollmentCheckScreenActor() override; - virtual void SetDelegate(Delegate* screen) override; + void SetDelegate(Delegate* screen) override; MOCK_METHOD1(MockSetDelegate, void(Delegate* screen)); MOCK_METHOD0(Show, void());
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc index ce08f36..4cb37534 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.cc +++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -29,6 +29,7 @@ #include "chrome/browser/chromeos/login/easy_unlock/bootstrap_user_flow.h" #include "chrome/browser/chromeos/login/helper.h" #include "chrome/browser/chromeos/login/session/user_session_manager.h" +#include "chrome/browser/chromeos/login/signin/oauth2_token_initializer.h" #include "chrome/browser/chromeos/login/signin_specifics.h" #include "chrome/browser/chromeos/login/startup_utils.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" @@ -596,7 +597,7 @@ // Bootstrap experiment F N/A const bool has_auth_cookies = login_performer_->auth_mode() == LoginPerformer::AUTH_MODE_EXTENSION && - (user_context.GetAuthCode().empty() || + (user_context.GetAccessToken().empty() || user_context.GetAuthFlow() == UserContext::AUTH_FLOW_GAIA_WITH_SAML) && user_context.GetAuthFlow() != UserContext::AUTH_FLOW_EASY_BOOTSTRAP; @@ -679,7 +680,8 @@ // us to recover from a lost owner password/homedir. // TODO(gspencer): We shouldn't have to erase stateful data when // doing this. See http://crosbug.com/9115 http://crosbug.com/7792 - login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error); + login_display_->ShowPasswordChangedDialog(show_invalid_old_password_error, + display_email_); if (auth_status_consumer_) auth_status_consumer_->OnPasswordChangeDetected(); @@ -1122,6 +1124,17 @@ return; } + // Fetch OAuth2 tokens if we have an auth code and are not using SAML. + // SAML uses cookies to get tokens. + if (user_context.GetAuthFlow() == UserContext::AUTH_FLOW_GAIA_WITHOUT_SAML && + !user_context.GetAuthCode().empty()) { + oauth2_token_initializer_.reset(new OAuth2TokenInitializer); + oauth2_token_initializer_->Start( + user_context, base::Bind(&ExistingUserController::OnOAuth2TokensFetched, + weak_factory_.GetWeakPtr())); + return; + } + PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION); } @@ -1199,4 +1212,15 @@ PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION); } +void ExistingUserController::OnOAuth2TokensFetched( + bool success, + const UserContext& user_context) { + if (!success) { + LOG(ERROR) << "OAuth2 token fetch failed."; + OnAuthFailure(AuthFailure(AuthFailure::NETWORK_AUTH_FAILED)); + return; + } + PerformLogin(user_context, LoginPerformer::AUTH_MODE_EXTENSION); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h index c7953818d..0eb01b89 100644 --- a/chrome/browser/chromeos/login/existing_user_controller.h +++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -38,6 +38,7 @@ class BootstrapUserContextInitializer; class CrosSettings; class LoginDisplayHost; +class OAuth2TokenInitializer; namespace login { class NetworkStateHelper; @@ -238,6 +239,9 @@ void OnBootstrapUserContextInitialized(bool success, const UserContext& user_context); + // Callback invoked when |oauth2_token_initializer_| has finished. + void OnOAuth2TokensFetched(bool success, const UserContext& user_context); + // Public session auto-login timer. scoped_ptr<base::OneShotTimer<ExistingUserController> > auto_login_timer_; @@ -325,6 +329,8 @@ scoped_ptr<BootstrapUserContextInitializer> bootstrap_user_context_initializer_; + scoped_ptr<OAuth2TokenInitializer> oauth2_token_initializer_; + FRIEND_TEST_ALL_PREFIXES(ExistingUserControllerTest, ExistingUserLogin); // Factory of callbacks.
diff --git a/chrome/browser/chromeos/login/helper.cc b/chrome/browser/chromeos/login/helper.cc index a0177c5d..afdd7417 100644 --- a/chrome/browser/chromeos/login/helper.cc +++ b/chrome/browser/chromeos/login/helper.cc
@@ -66,7 +66,7 @@ content::StoragePartition* GetPartition(content::WebContents* embedder, const std::string& partition_name) { extensions::GuestViewManager* manager = - extensions::GuestViewManager::FromBrowserContextIfAvailable( + extensions::GuestViewManager::FromBrowserContext( embedder->GetBrowserContext()); if (!manager) return nullptr;
diff --git a/chrome/browser/chromeos/login/login_browsertest.cc b/chrome/browser/chromeos/login/login_browsertest.cc index fa8574b..46db1d8 100644 --- a/chrome/browser/chromeos/login/login_browsertest.cc +++ b/chrome/browser/chromeos/login/login_browsertest.cc
@@ -133,9 +133,11 @@ } while (message != "\"offlineLoaded\""); } - void SubmitGaiaAuthOfflineForm(const std::string& user_email, - const std::string& password) { + void SubmitOldGaiaAuthOfflineForm(const std::string& user_email, + const std::string& password) { // Note the input elements must match gaia_auth/offline.html. + JSExpect("document.querySelector('#offline-gaia').hidden"); + JSExpect("!document.querySelector('#signin-frame').hidden"); std::string js = "(function(){" "document.getElementsByName('email')[0].value = '$Email';" @@ -146,6 +148,66 @@ ReplaceSubstringsAfterOffset(&js, 0, "$Password", password); ExecuteJsInGaiaAuthFrame(js); } + + void SubmitGaiaAuthOfflineForm(const std::string& user_email, + const std::string& password) { + const std::string animated_pages = + "document.querySelector('#offline-gaia /deep/ " + "#animatedPages')"; + const std::string email_input = + "document.querySelector('#offline-gaia /deep/ #emailInput')"; + const std::string email_next_button = + "document.querySelector('#offline-gaia /deep/ #emailInput " + "/deep/ .blue-button')"; + const std::string password_input = + "document.querySelector('#offline-gaia /deep/ " + "#passwordInput')"; + const std::string password_next_button = + "document.querySelector('#offline-gaia /deep/ #passwordInput" + " /deep/ .blue-button')"; + + content::DOMMessageQueue message_queue; + JSExpect("!document.querySelector('#offline-gaia').hidden"); + JSExpect("document.querySelector('#signin-frame').hidden"); + const std::string js = + animated_pages + + ".addEventListener('core-animated-pages-transition-end'," + "function() {" + "window.domAutomationController.setAutomationId(0);" + "window.domAutomationController.send('switchToPassword');" + "})"; + ASSERT_TRUE(content::ExecuteScript(web_contents(), js)); + std::string set_email = email_input + ".inputValue = '$Email'"; + ReplaceSubstringsAfterOffset(&set_email, 0, "$Email", user_email); + ASSERT_TRUE(content::ExecuteScript(web_contents(), set_email)); + ASSERT_TRUE(content::ExecuteScript(web_contents(), + email_next_button + ".fire('tap')")); + std::string message; + do { + ASSERT_TRUE(message_queue.WaitForMessage(&message)); + LOG(ERROR) << message; + } while (message != "\"switchToPassword\""); + + std::string set_password = password_input + ".inputValue = '$Password'"; + ReplaceSubstringsAfterOffset(&set_password, 0, "$Password", password); + ASSERT_TRUE(content::ExecuteScript(web_contents(), set_password)); + ASSERT_TRUE(content::ExecuteScript(web_contents(), + password_next_button + ".fire('tap')")); + } + + void PrepareOfflineLogin() { + bool show_user; + ASSERT_TRUE(chromeos::CrosSettings::Get()->GetBoolean( + chromeos::kAccountsPrefShowUserNamesOnSignIn, &show_user)); + ASSERT_FALSE(show_user); + + StartGaiaAuthOffline(); + + chromeos::UserContext user_context(kTestUser); + user_context.SetGaiaID(kGaiaId); + user_context.SetKey(chromeos::Key(kPassword)); + SetExpectedCredentials(user_context); + } }; class LoginOfflineTest : public LoginTest { @@ -247,26 +309,33 @@ ASSERT_TRUE(tracing::EndTracing(&json_events)); } -IN_PROC_BROWSER_TEST_F(LoginOfflineTest, PRE_GaiaAuthOffline) { +IN_PROC_BROWSER_TEST_F(LoginOfflineTest, PRE_OldGaiaAuthOffline) { RegisterUser(kTestUser); chromeos::StartupUtils::MarkOobeCompleted(); chromeos::CrosSettings::Get()->SetBoolean( chromeos::kAccountsPrefShowUserNamesOnSignIn, false); } -IN_PROC_BROWSER_TEST_F(LoginOfflineTest, GaiaAuthOffline) { - bool show_user; - ASSERT_TRUE(chromeos::CrosSettings::Get()->GetBoolean( - chromeos::kAccountsPrefShowUserNamesOnSignIn, &show_user)); - ASSERT_FALSE(show_user); +IN_PROC_BROWSER_TEST_F(LoginOfflineTest, OldGaiaAuthOffline) { + PrepareOfflineLogin(); + content::WindowedNotificationObserver session_start_waiter( + chrome::NOTIFICATION_SESSION_STARTED, + content::NotificationService::AllSources()); + SubmitOldGaiaAuthOfflineForm(kTestUser, kPassword); + session_start_waiter.Wait(); - StartGaiaAuthOffline(); + TestSystemTrayIsVisible(); +} - chromeos::UserContext user_context(kTestUser); - user_context.SetGaiaID(kGaiaId); - user_context.SetKey(chromeos::Key(kPassword)); - SetExpectedCredentials(user_context); +IN_PROC_BROWSER_TEST_F(LoginTest, PRE_GaiaAuthOffline) { + RegisterUser(kTestUser); + chromeos::StartupUtils::MarkOobeCompleted(); + chromeos::CrosSettings::Get()->SetBoolean( + chromeos::kAccountsPrefShowUserNamesOnSignIn, false); +} +IN_PROC_BROWSER_TEST_F(LoginTest, GaiaAuthOffline) { + PrepareOfflineLogin(); content::WindowedNotificationObserver session_start_waiter( chrome::NOTIFICATION_SESSION_STARTED, content::NotificationService::AllSources());
diff --git a/chrome/browser/chromeos/login/proxy_auth_dialog_browsertest.cc b/chrome/browser/chromeos/login/proxy_auth_dialog_browsertest.cc index 9fb5726..5fc1fc1 100644 --- a/chrome/browser/chromeos/login/proxy_auth_dialog_browsertest.cc +++ b/chrome/browser/chromeos/login/proxy_auth_dialog_browsertest.cc
@@ -126,10 +126,13 @@ } } -// TODO(paulmeyer): Re-enable webview version of this test -// (once http://crbug.com/452452 is fixed. INSTANTIATE_TEST_CASE_P(ProxyAuthOnUserBoardScreenTestSuite, ProxyAuthOnUserBoardScreenTest, +// Times out under MSan: https://crbug.com/481651 +#if defined(MEMORY_SANITIZER) testing::Values(false)); +#else + testing::Bool()); +#endif } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/resource_loader_browsertest.cc b/chrome/browser/chromeos/login/resource_loader_browsertest.cc index 3041775..2053e46 100644 --- a/chrome/browser/chromeos/login/resource_loader_browsertest.cc +++ b/chrome/browser/chromeos/login/resource_loader_browsertest.cc
@@ -33,12 +33,12 @@ ResourceLoaderBrowserTest() {} protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { // Needed to load file:// URLs in XHRs. command_line->AppendSwitch(switches::kDisableWebSecurity); } - virtual void SetUpOnMainThread() override { + void SetUpOnMainThread() override { // Create the root page containing resource_loader.js. std::string root_page = "<html>"
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc index ce4d3c0f..7c8af714 100644 --- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc +++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -51,6 +51,7 @@ #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_session_manager_client.h" #include "chromeos/dbus/session_manager_client.h" +#include "chromeos/dbus/shill_manager_client.h" #include "chromeos/settings/cros_settings_names.h" #include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" @@ -112,6 +113,9 @@ const char kNonSAMLUserEmail[] = "dan@example.com"; const char kDifferentDomainSAMLUserEmail[] = "eve@example.test"; +const char kIdPHost[] = "login.example.com"; +const char kAdditionalIdPHost[] = "login2.example.com"; + const char kSAMLIdPCookieName[] = "saml"; const char kSAMLIdPCookieValue1[] = "value-1"; const char kSAMLIdPCookieValue2[] = "value-2"; @@ -263,7 +267,7 @@ // iframe (false) GAIA sign in. class SamlTest : public OobeBaseTest, public testing::WithParamInterface<bool> { public: - SamlTest() : saml_load_injected_(false) { + SamlTest() { set_use_webview(GetParam()); set_initialize_fake_merge_session(false); } @@ -272,8 +276,8 @@ void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitch(switches::kOobeSkipPostLogin); - const GURL gaia_url = gaia_https_forwarder_->GetURL(""); - const GURL saml_idp_url = saml_https_forwarder_->GetURL("SAML"); + const GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost(""); + const GURL saml_idp_url = saml_https_forwarder_.GetURLForSSLHost("SAML"); fake_saml_idp_.SetUp(saml_idp_url.path(), gaia_url); fake_gaia_->RegisterSamlUser(kFirstSAMLUserEmail, saml_idp_url); fake_gaia_->RegisterSamlUser(kSecondSAMLUserEmail, saml_idp_url); @@ -295,21 +299,23 @@ OobeBaseTest::SetUpOnMainThread(); } + void SetupAuthFlowChangeListener() { + ASSERT_TRUE(content::ExecuteScript( + GetLoginUI()->GetWebContents(), + "$('gaia-signin').gaiaAuthHost_.addEventListener('authFlowChange'," + "function f() {" + "$('gaia-signin').gaiaAuthHost_.removeEventListener(" + "'authFlowChange', f);" + "window.domAutomationController.setAutomationId(0);" + "window.domAutomationController.send(" + "$('gaia-signin').isSAML() ? 'SamlLoaded' : 'GaiaLoaded');" + "});")); + } + virtual void StartSamlAndWaitForIdpPageLoad(const std::string& gaia_email) { WaitForSigninScreen(); - if (!saml_load_injected_) { - saml_load_injected_ = true; - - ASSERT_TRUE(content::ExecuteScript( - GetLoginUI()->GetWebContents(), - "$('gaia-signin').gaiaAuthHost_.addEventListener('authFlowChange'," - "function() {" - "window.domAutomationController.setAutomationId(0);" - "window.domAutomationController.send(" - "$('gaia-signin').isSAML() ? 'SamlLoaded' : 'GaiaLoaded');" - "});")); - } + SetupAuthFlowChangeListener(); content::DOMMessageQueue message_queue; // Start observe before SAML. GetLoginDisplay()->ShowSigninScreenForCreds(gaia_email, ""); @@ -344,20 +350,16 @@ protected: void InitHttpsForwarders() override { - saml_https_forwarder_.reset( - new HTTPSForwarder(embedded_test_server()->base_url())); - ASSERT_TRUE(saml_https_forwarder_->Start()); - + ASSERT_TRUE(saml_https_forwarder_.Initialize( + kIdPHost, embedded_test_server()->base_url())); OobeBaseTest::InitHttpsForwarders(); } - scoped_ptr<HTTPSForwarder> saml_https_forwarder_; + HTTPSForwarder saml_https_forwarder_; private: FakeSamlIdp fake_saml_idp_; - bool saml_load_injected_; - DISALLOW_COPY_AND_ASSIGN(SamlTest); }; @@ -370,10 +372,16 @@ // Saml flow UI expectations. JsExpect("$('gaia-signin').classList.contains('full-width')"); + JsExpect("!$('saml-notice-container').hidden"); + std::string js = "$('saml-notice-message').textContent.indexOf('$Host') > -1"; + ReplaceSubstringsAfterOffset(&js, 0, "$Host", kIdPHost); + JsExpect(js); if (!use_webview()) { JsExpect("!$('cancel-add-user-button').hidden"); } + SetupAuthFlowChangeListener(); + // Click on 'cancel'. content::DOMMessageQueue message_queue; // Observe before 'cancel'. if (use_webview()) { @@ -398,13 +406,6 @@ // Tests the sign-in flow when the credentials passing API is used. IN_PROC_BROWSER_TEST_P(SamlTest, CredentialPassingAPI) { - // Disabled for webview because the script is injected using - // webview.executeScript and there is no way to control the injection time. - // As a result, this test is flaky and fails about 20% of the time. - // TODO(xiyuan): Re-enable when webview.addContentScript API is ready. - if (use_webview()) - return; - fake_saml_idp()->SetLoginHTMLTemplate("saml_api_login.html"); fake_saml_idp()->SetLoginAuthHTMLTemplate("saml_api_login_auth.html"); StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail); @@ -587,6 +588,54 @@ WaitForAndGetFatalErrorMessage()); } +// Verifies that when the login flow redirects from one host to another, the +// notice shown to the user is updated. This guards against regressions of +// http://crbug.com/447818. +IN_PROC_BROWSER_TEST_P(SamlTest, NoticeUpdatedOnRedirect) { + // Start another https server at |kAdditionalIdPHost|. + HTTPSForwarder saml_https_forwarder_2; + ASSERT_TRUE(saml_https_forwarder_2.Initialize( + kAdditionalIdPHost, embedded_test_server()->base_url())); + + // Make the login flow redirect to |kAdditionalIdPHost|. + fake_saml_idp()->SetLoginHTMLTemplate("saml_login_instant_meta_refresh.html"); + fake_saml_idp()->SetRefreshURL( + saml_https_forwarder_2.GetURLForSSLHost("simple.html")); + StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail); + + // Wait until the notice shown to the user is updated to contain + // |kAdditionalIdPHost|. + std::string js = + "var sendIfHostFound = function() {" + " var found =" + " $('saml-notice-message').textContent.indexOf('$Host') > -1;" + " if (found)" + " window.domAutomationController.send(true);" + " return found;" + "};" + "var processEventsAndSendIfHostFound = function() {" + " window.setTimeout(function() {" + " if (sendIfHostFound()) {" + " $('gaia-signin').gaiaAuthHost_.removeEventListener(" + " 'authDomainChange'," + " processEventsAndSendIfHostFound);" + " }" + " }, 0);" + "};" + "if (!sendIfHostFound()) {" + " $('gaia-signin').gaiaAuthHost_.addEventListener(" + " 'authDomainChange'," + " processEventsAndSendIfHostFound);" + "}"; + ReplaceSubstringsAfterOffset(&js, 0, "$Host", kAdditionalIdPHost); + bool dummy; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + GetLoginUI()->GetWebContents(), js, &dummy)); + + // Verify that the notice is visible. + JsExpect("!$('saml-notice-container').hidden"); +} + // Verifies that when GAIA attempts to redirect to a SAML IdP served over http, // not https, the redirect is blocked and an error message is shown. IN_PROC_BROWSER_TEST_P(SamlTest, HTTPRedirectDisallowed) { @@ -728,8 +777,8 @@ return; const GURL origin = validated_url.GetOrigin(); - if (origin != gaia_https_forwarder_->GetURL("") && - origin != saml_https_forwarder_->GetURL("")) { + if (origin != gaia_https_forwarder_.GetURLForSSLHost(std::string()) && + origin != saml_https_forwarder_.GetURLForSSLHost(std::string())) { return; } @@ -873,6 +922,12 @@ user_manager::UserManager::Get()->SaveUserOAuthStatus( kDifferentDomainSAMLUserEmail, user_manager::User::OAUTH2_TOKEN_STATUS_VALID); + + // Set up fake networks. + DBusThreadManager::Get() + ->GetShillManagerClient() + ->GetTestInterface() + ->SetupDefaultEnvironment(); } void SAMLPolicyTest::SetSAMLOfflineSigninTimeLimitPolicy(int limit) {
diff --git a/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.cc b/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.cc index b5639d39..ba92b40f 100644 --- a/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.cc +++ b/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.cc
@@ -31,14 +31,9 @@ // static void SAMLOfflineSigninLimiter::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kSAMLOfflineSigninTimeLimit, - kDefaultSAMLOfflineSigninTimeLimit, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kSAMLLastGAIASignInTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kSAMLOfflineSigninTimeLimit, + kDefaultSAMLOfflineSigninTimeLimit); + registry->RegisterInt64Pref(prefs::kSAMLLastGAIASignInTime, 0); } void SAMLOfflineSigninLimiter::SignedIn(UserContext::AuthFlow auth_flow) {
diff --git a/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_unittest.cc b/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_unittest.cc index 7969589..beaf843 100644 --- a/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_unittest.cc +++ b/chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_unittest.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/pref_registry/pref_registry_syncable.h" #include "testing/gmock/include/gmock/gmock.h" @@ -23,6 +24,7 @@ using testing::Mock; using testing::ReturnRef; using testing::Sequence; +using testing::_; namespace chromeos { @@ -68,6 +70,9 @@ DestroyLimiter(); Mock::VerifyAndClearExpectations(user_manager_); EXPECT_CALL(*user_manager_, Shutdown()).Times(1); + EXPECT_CALL(*user_manager_, RemoveSessionStateObserver(_)).Times(1); + profile_.reset(); + TestingBrowserProcess::DeleteInstance(); } void SAMLOfflineSigninLimiterTest::DestroyLimiter() {
diff --git a/chrome/browser/chromeos/login/screens/core_oobe_actor.h b/chrome/browser/chromeos/login/screens/core_oobe_actor.h index cfd3c7e..6a491d2c 100644 --- a/chrome/browser/chromeos/login/screens/core_oobe_actor.h +++ b/chrome/browser/chromeos/login/screens/core_oobe_actor.h
@@ -32,7 +32,8 @@ virtual void ResetSignInUI(bool force_online) = 0; virtual void ClearUserPodPassword() = 0; virtual void RefocusCurrentPod() = 0; - virtual void ShowPasswordChangedScreen(bool show_password_error) = 0; + virtual void ShowPasswordChangedScreen(bool show_password_error, + const std::string& email) = 0; virtual void SetUsageStats(bool checked) = 0; virtual void SetOemEulaUrl(const std::string& oem_eula_url) = 0; virtual void SetTpmPassword(const std::string& tmp_password) = 0;
diff --git a/chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h b/chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h index 235d2de..85ec708 100644 --- a/chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h +++ b/chrome/browser/chromeos/login/screens/mock_enable_debugging_screen.h
@@ -23,15 +23,14 @@ : public EnableDebuggingScreenActor { public: MockEnableDebuggingScreenActor(); - virtual ~MockEnableDebuggingScreenActor(); + ~MockEnableDebuggingScreenActor() override; MOCK_METHOD0(PrepareToShow, void()); MOCK_METHOD0(Show, void()); MOCK_METHOD0(Hide, void()); MOCK_METHOD1(MockSetDelegate, void(Delegate* delegate)); - virtual void SetDelegate( - EnableDebuggingScreenActor::Delegate* delegate) override; + void SetDelegate(EnableDebuggingScreenActor::Delegate* delegate) override; private: Delegate* delegate_;
diff --git a/chrome/browser/chromeos/login/screens/mock_eula_screen.h b/chrome/browser/chromeos/login/screens/mock_eula_screen.h index 36a015d..2186750 100644 --- a/chrome/browser/chromeos/login/screens/mock_eula_screen.h +++ b/chrome/browser/chromeos/login/screens/mock_eula_screen.h
@@ -23,10 +23,10 @@ class MockEulaView : public EulaView { public: MockEulaView(); - virtual ~MockEulaView(); + ~MockEulaView() override; - virtual void Bind(EulaModel& model) override; - virtual void Unbind() override; + void Bind(EulaModel& model) override; + void Unbind() override; MOCK_METHOD0(PrepareToShow, void()); MOCK_METHOD0(Show, void());
diff --git a/chrome/browser/chromeos/login/screens/mock_network_screen.h b/chrome/browser/chromeos/login/screens/mock_network_screen.h index bcb4f900..9ccae6bd 100644 --- a/chrome/browser/chromeos/login/screens/mock_network_screen.h +++ b/chrome/browser/chromeos/login/screens/mock_network_screen.h
@@ -17,7 +17,7 @@ MockNetworkScreen(BaseScreenDelegate* base_screen_delegate, Delegate* delegate, NetworkView* view); - virtual ~MockNetworkScreen(); + ~MockNetworkScreen() override; MOCK_METHOD0(Show, void()); MOCK_METHOD0(Hide, void()); @@ -26,10 +26,10 @@ class MockNetworkView : public NetworkView { public: MockNetworkView(); - virtual ~MockNetworkView(); + ~MockNetworkView() override; - virtual void Bind(NetworkModel& model) override; - virtual void Unbind() override; + void Bind(NetworkModel& model) override; + void Unbind() override; MOCK_METHOD1(MockBind, void(NetworkModel& model)); MOCK_METHOD0(MockUnbind, void());
diff --git a/chrome/browser/chromeos/login/screens/mock_wrong_hwid_screen.h b/chrome/browser/chromeos/login/screens/mock_wrong_hwid_screen.h index 6a9ba39..067ce4b 100644 --- a/chrome/browser/chromeos/login/screens/mock_wrong_hwid_screen.h +++ b/chrome/browser/chromeos/login/screens/mock_wrong_hwid_screen.h
@@ -23,9 +23,9 @@ class MockWrongHWIDScreenActor : public WrongHWIDScreenActor { public: MockWrongHWIDScreenActor(); - virtual ~MockWrongHWIDScreenActor(); + ~MockWrongHWIDScreenActor() override; - virtual void SetDelegate(Delegate* delegate) override; + void SetDelegate(Delegate* delegate) override; MOCK_METHOD0(PrepareToShow, void()); MOCK_METHOD0(Show, void());
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.cc b/chrome/browser/chromeos/login/screens/user_selection_screen.cc index 2156e875..9bcb404 100644 --- a/chrome/browser/chromeos/login/screens/user_selection_screen.cc +++ b/chrome/browser/chromeos/login/screens/user_selection_screen.cc
@@ -18,9 +18,10 @@ #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/signin/easy_unlock_service.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/user_manager/user_id.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_type.h" @@ -118,14 +119,14 @@ } UserSelectionScreen::~UserSelectionScreen() { - ScreenlockBridge::Get()->SetLockHandler(nullptr); + GetScreenlockBridgeInstance()->SetLockHandler(nullptr); ui::UserActivityDetector* activity_detector = ui::UserActivityDetector::Get(); if (activity_detector->HasObserver(this)) activity_detector->RemoveObserver(this); } void UserSelectionScreen::InitEasyUnlock() { - ScreenlockBridge::Get()->SetLockHandler(this); + GetScreenlockBridgeInstance()->SetLockHandler(this); } void UserSelectionScreen::SetLoginDisplayDelegate( @@ -445,15 +446,15 @@ view_->SetAuthType(user_id, auth_type, initial_value); } -ScreenlockBridge::LockHandler::AuthType UserSelectionScreen::GetAuthType( - const std::string& username) const { +proximity_auth::ScreenlockBridge::LockHandler::AuthType +UserSelectionScreen::GetAuthType(const std::string& username) const { if (user_auth_type_map_.find(username) == user_auth_type_map_.end()) return OFFLINE_PASSWORD; return user_auth_type_map_.find(username)->second; } -ScreenlockBridge::LockHandler::ScreenType UserSelectionScreen::GetScreenType() - const { +proximity_auth::ScreenlockBridge::LockHandler::ScreenType +UserSelectionScreen::GetScreenType() const { if (display_type_ == OobeUI::kLockDisplay) return LOCK_SCREEN; @@ -469,7 +470,8 @@ void UserSelectionScreen::ShowUserPodCustomIcon( const std::string& user_id, - const ScreenlockBridge::UserPodCustomIconOptions& icon_options) { + const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions& + icon_options) { scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue(); if (!icon || icon->empty()) return;
diff --git a/chrome/browser/chromeos/login/screens/user_selection_screen.h b/chrome/browser/chromeos/login/screens/user_selection_screen.h index 74eab73..7b9c684 100644 --- a/chrome/browser/chromeos/login/screens/user_selection_screen.h +++ b/chrome/browser/chromeos/login/screens/user_selection_screen.h
@@ -15,7 +15,7 @@ #include "chrome/browser/chromeos/login/signin/token_handle_util.h" #include "chrome/browser/chromeos/login/ui/login_display.h" #include "chrome/browser/chromeos/login/ui/models/user_board_model.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/user_manager/user.h" #include "components/user_manager/user_id.h" #include "ui/base/user_activity/user_activity_observer.h" @@ -28,9 +28,10 @@ class UserBoardView; // This class represents User Selection screen: user pod-based login screen. -class UserSelectionScreen : public ui::UserActivityObserver, - public ScreenlockBridge::LockHandler, - public UserBoardModel { +class UserSelectionScreen + : public ui::UserActivityObserver, + public proximity_auth::ScreenlockBridge::LockHandler, + public UserBoardModel { public: explicit UserSelectionScreen(const std::string& display_type); ~UserSelectionScreen() override; @@ -61,11 +62,12 @@ void InitEasyUnlock(); - // ScreenlockBridge::LockHandler implementation: + // proximity_auth::ScreenlockBridge::LockHandler implementation: void ShowBannerMessage(const base::string16& message) override; void ShowUserPodCustomIcon( const std::string& user_email, - const ScreenlockBridge::UserPodCustomIconOptions& icon) override; + const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions& icon) + override; void HideUserPodCustomIcon(const std::string& user_email) override; void EnableInput() override; @@ -135,7 +137,7 @@ // Map of usernames to their current authentication type. If a user is not // contained in the map, it is using the default authentication type. - std::map<std::string, ScreenlockBridge::LockHandler::AuthType> + std::map<std::string, proximity_auth::ScreenlockBridge::LockHandler::AuthType> user_auth_type_map_; // Timer for measuring idle state duration before password clear.
diff --git a/chrome/browser/chromeos/login/session/user_session_manager.cc b/chrome/browser/chromeos/login/session/user_session_manager.cc index 1fbb3d8..871233e 100644 --- a/chrome/browser/chromeos/login/session/user_session_manager.cc +++ b/chrome/browser/chromeos/login/session/user_session_manager.cc
@@ -1218,8 +1218,6 @@ if (has_auth_cookies_) { session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_COOKIE_JAR; - } else if (!user_context_.GetAuthCode().empty()) { - session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_AUTH_CODE; } else if (!user_context_.GetRefreshToken().empty()) { session_restore_strategy_ = OAuth2LoginManager::RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN; @@ -1267,7 +1265,7 @@ } login_manager->RestoreSession(auth_request_context, session_restore_strategy_, user_context_.GetRefreshToken(), - user_context_.GetAuthCode()); + user_context_.GetAccessToken()); } void UserSessionManager::InitRlzImpl(Profile* profile, bool disabled) {
diff --git a/chrome/browser/chromeos/login/signin/merge_session_load_page_unittest.cc b/chrome/browser/chromeos/login/signin/merge_session_load_page_unittest.cc index 31572465..0ff4379c 100644 --- a/chrome/browser/chromeos/login/signin/merge_session_load_page_unittest.cc +++ b/chrome/browser/chromeos/login/signin/merge_session_load_page_unittest.cc
@@ -13,6 +13,7 @@ #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "content/public/browser/interstitial_page.h" #include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" #include "content/public/test/web_contents_tester.h" @@ -64,10 +65,14 @@ ChromeRenderViewHostTestHarness::TearDown(); } - void Navigate(const char* url, int page_id) { - WebContentsTester::For(web_contents())->TestDidNavigate( - web_contents()->GetMainFrame(), page_id, GURL(url), - ui::PAGE_TRANSITION_TYPED); + void Navigate(const char* url, + int page_id, + int nav_entry_id, + bool did_create_new_entry) { + WebContentsTester::For(web_contents()) + ->TestDidNavigate(web_contents()->GetMainFrame(), page_id, nav_entry_id, + did_create_new_entry, GURL(url), + ui::PAGE_TRANSITION_TYPED); } void ShowInterstitial(const char* url) { @@ -117,7 +122,7 @@ TEST_F(MergeSessionLoadPageTest, MergeSessionPageNotShown) { SetMergeSessionState(OAuth2LoginManager::SESSION_RESTORE_DONE); // Start a load. - Navigate(kURL1, 1); + Navigate(kURL1, 1, 0, true); // Load next page. controller().LoadURL(GURL(kURL2), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); @@ -135,7 +140,7 @@ base::TimeDelta::FromSeconds(kSessionMergeTimeout + 1)); // Start a load. - Navigate(kURL1, 1); + Navigate(kURL1, 1, 0, true); // Load next page. controller().LoadURL(GURL(kURL2), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); @@ -150,10 +155,11 @@ SetMergeSessionState(OAuth2LoginManager::SESSION_RESTORE_IN_PROGRESS); // Start a load. - Navigate(kURL1, 1); + Navigate(kURL1, 1, 0, true); // Load next page. controller().LoadURL(GURL(kURL2), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int pending_id = controller().GetPendingEntry()->GetUniqueID(); // Simulate the load causing an merge session interstitial page // to be shown. @@ -170,7 +176,7 @@ EXPECT_EQ(kURL2, web_contents()->GetVisibleURL().spec()); // Commit navigation and the interstitial page is gone. - Navigate(kURL2, 2); + Navigate(kURL2, 2, pending_id, true); EXPECT_FALSE(GetMergeSessionLoadPage()); }
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc index 61023ea..9d2989af 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc +++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.cc
@@ -74,21 +74,19 @@ net::URLRequestContextGetter* auth_request_context, SessionRestoreStrategy restore_strategy, const std::string& oauth2_refresh_token, - const std::string& auth_code) { + const std::string& oauth2_access_token) { DCHECK(user_profile_); auth_request_context_ = auth_request_context; restore_strategy_ = restore_strategy; refresh_token_ = oauth2_refresh_token; - oauthlogin_access_token_ = std::string(); - auth_code_ = auth_code; + oauthlogin_access_token_ = oauth2_access_token; session_restore_start_ = base::Time::Now(); SetSessionRestoreState(OAuth2LoginManager::SESSION_RESTORE_PREPARING); ContinueSessionRestore(); } void OAuth2LoginManager::ContinueSessionRestore() { - if (restore_strategy_ == RESTORE_FROM_COOKIE_JAR || - restore_strategy_ == RESTORE_FROM_AUTH_CODE) { + if (restore_strategy_ == RESTORE_FROM_COOKIE_JAR) { FetchOAuth2Tokens(); return; } @@ -239,28 +237,23 @@ void OAuth2LoginManager::FetchOAuth2Tokens() { DCHECK(auth_request_context_.get()); + if (restore_strategy_ != RESTORE_FROM_COOKIE_JAR) { + NOTREACHED(); + SetSessionRestoreState(SESSION_RESTORE_FAILED); + return; + } + // If we have authenticated cookie jar, get OAuth1 token first, then fetch // SID/LSID cookies through OAuthLogin call. - if (restore_strategy_ == RESTORE_FROM_COOKIE_JAR) { - SigninClient* signin_client = - ChromeSigninClientFactory::GetForProfile(user_profile_); - std::string signin_scoped_device_id = - signin_client->GetSigninScopedDeviceId(); + SigninClient* signin_client = + ChromeSigninClientFactory::GetForProfile(user_profile_); + std::string signin_scoped_device_id = + signin_client->GetSigninScopedDeviceId(); - oauth2_token_fetcher_.reset( - new OAuth2TokenFetcher(this, auth_request_context_.get())); - oauth2_token_fetcher_->StartExchangeFromCookies(std::string(), - signin_scoped_device_id); - } else if (restore_strategy_ == RESTORE_FROM_AUTH_CODE) { - DCHECK(!auth_code_.empty()); - oauth2_token_fetcher_.reset( - new OAuth2TokenFetcher(this, - g_browser_process->system_request_context())); - oauth2_token_fetcher_->StartExchangeFromAuthCode(auth_code_); - } else { - NOTREACHED(); - SetSessionRestoreState(OAuth2LoginManager::SESSION_RESTORE_FAILED); - } + oauth2_token_fetcher_.reset( + new OAuth2TokenFetcher(this, auth_request_context_.get())); + oauth2_token_fetcher_->StartExchangeFromCookies(std::string(), + signin_scoped_device_id); } void OAuth2LoginManager::OnOAuth2TokensAvailable(
diff --git a/chrome/browser/chromeos/login/signin/oauth2_login_manager.h b/chrome/browser/chromeos/login/signin/oauth2_login_manager.h index 15b3473..a197d8c5 100644 --- a/chrome/browser/chromeos/login/signin/oauth2_login_manager.h +++ b/chrome/browser/chromeos/login/signin/oauth2_login_manager.h
@@ -58,8 +58,6 @@ RESTORE_FROM_SAVED_OAUTH2_REFRESH_TOKEN, // Restore session from OAuth2 refresh token passed via command line. RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN, - // Restore session from authentication code passed via command line. - RESTORE_FROM_AUTH_CODE, }; class Observer { @@ -84,24 +82,20 @@ void AddObserver(OAuth2LoginManager::Observer* observer); void RemoveObserver(OAuth2LoginManager::Observer* observer); - // Restores and verifies OAuth tokens either following specified - // |restore_strategy|. For |restore_strategy| with values - // RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN or - // RESTORE_FROM_AUTH_CODE, respectively - // parameters |oauth2_refresh_token| or |auth_code| need to have non-empty - // value. - // For |restore_strategy| with values RESTORE_FROM_COOKIE_JAR or - // RESTORE_FROM_AUTH_CODE |auth_request_context| must be initialized. - void RestoreSession( - net::URLRequestContextGetter* auth_request_context, - SessionRestoreStrategy restore_strategy, - const std::string& oauth2_refresh_token, - const std::string& auth_code); + // Restores and verifies OAuth tokens following specified |restore_strategy|. + // For |restore_strategy| RESTORE_FROM_PASSED_OAUTH2_REFRESH_TOKEN, parameter + // |oauth2_refresh_token| needs to have a non-empty value. + // For |restore_strategy| RESTORE_FROM_COOKIE_JAR |auth_request_context| must + // be initialized. + void RestoreSession(net::URLRequestContextGetter* auth_request_context, + SessionRestoreStrategy restore_strategy, + const std::string& oauth2_refresh_token, + const std::string& oauth2_access_token); // Continues session restore after transient network errors. void ContinueSessionRestore(); - // Start resporting session from saved OAuth2 refresh token. + // Start restoring session from saved OAuth2 refresh token. void RestoreSessionFromSavedTokens(); // Stops all background authentication requests. @@ -152,7 +146,7 @@ // gaia::GaiaOAuthClient::Delegate overrides. void OnRefreshTokenResponse(const std::string& access_token, - int expires_in_seconds) override; + int expires_in_seconds) override; void OnGetUserInfoResponse( scoped_ptr<base::DictionaryValue> user_info) override; void OnOAuthError() override; @@ -250,9 +244,6 @@ // OAuthLogin scoped access token. std::string oauthlogin_access_token_; - // Authorization code for fetching OAuth2 tokens. - std::string auth_code_; - // Session restore start time. base::Time session_restore_start_;
diff --git a/chrome/browser/chromeos/login/signin/oauth2_token_initializer.cc b/chrome/browser/chromeos/login/signin/oauth2_token_initializer.cc new file mode 100644 index 0000000..c0bcbc9 --- /dev/null +++ b/chrome/browser/chromeos/login/signin/oauth2_token_initializer.cc
@@ -0,0 +1,41 @@ +// 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/chromeos/login/signin/oauth2_token_initializer.h" + +#include "chrome/browser/browser_process.h" + +namespace chromeos { + +OAuth2TokenInitializer::OAuth2TokenInitializer() { +} + +OAuth2TokenInitializer::~OAuth2TokenInitializer() { +} + +void OAuth2TokenInitializer::Start(const UserContext& user_context, + const FetchOAuth2TokensCallback& callback) { + DCHECK(!user_context.GetAuthCode().empty()); + callback_ = callback; + user_context_ = user_context; + oauth2_token_fetcher_.reset(new OAuth2TokenFetcher( + this, g_browser_process->system_request_context())); + oauth2_token_fetcher_->StartExchangeFromAuthCode(user_context.GetAuthCode()); +} + +void OAuth2TokenInitializer::OnOAuth2TokensAvailable( + const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) { + VLOG(1) << "OAuth2 tokens fetched"; + user_context_.SetAuthCode(std::string()); + user_context_.SetRefreshToken(oauth2_tokens.refresh_token); + user_context_.SetAccessToken(oauth2_tokens.access_token); + callback_.Run(true, user_context_); +} + +void OAuth2TokenInitializer::OnOAuth2TokensFetchFailed() { + LOG(WARNING) << "OAuth2TokenInitializer - OAuth2 token fetch failed"; + callback_.Run(false, user_context_); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/signin/oauth2_token_initializer.h b/chrome/browser/chromeos/login/signin/oauth2_token_initializer.h new file mode 100644 index 0000000..b583ffd --- /dev/null +++ b/chrome/browser/chromeos/login/signin/oauth2_token_initializer.h
@@ -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. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_OAUTH2_TOKEN_INITIALIZER_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_OAUTH2_TOKEN_INITIALIZER_H_ + +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/chromeos/login/signin/oauth2_token_fetcher.h" +#include "chromeos/login/auth/user_context.h" + +namespace chromeos { + +// Performs initial fetch of OAuth2 Tokens. +class OAuth2TokenInitializer final : public OAuth2TokenFetcher::Delegate { + public: + // Callback to be invoked after initialization is done. + using FetchOAuth2TokensCallback = + base::Callback<void(bool success, const UserContext& user_context)>; + + OAuth2TokenInitializer(); + ~OAuth2TokenInitializer() override; + + // Fetch OAuth2 tokens. + void Start(const UserContext& context, + const FetchOAuth2TokensCallback& callback); + + private: + // OAuth2TokenFetcher::Delegate overrides. + void OnOAuth2TokensAvailable( + const GaiaAuthConsumer::ClientOAuthResult& oauth2_tokens) override; + void OnOAuth2TokensFetchFailed() override; + + UserContext user_context_; + FetchOAuth2TokensCallback callback_; + scoped_ptr<OAuth2TokenFetcher> oauth2_token_fetcher_; + + DISALLOW_COPY_AND_ASSIGN(OAuth2TokenInitializer); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_SIGNIN_OAUTH2_TOKEN_INITIALIZER_H_
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_authentication.cc b/chrome/browser/chromeos/login/supervised/supervised_user_authentication.cc index c2ea24d..b4a64a3 100644 --- a/chrome/browser/chromeos/login/supervised/supervised_user_authentication.cc +++ b/chrome/browser/chromeos/login/supervised/supervised_user_authentication.cc
@@ -287,9 +287,11 @@ base::FilePath profile_path = ProfileHelper::GetProfilePathByUserIdHash(user->username_hash()); PostTaskAndReplyWithResult( - content::BrowserThread::GetBlockingPool(), - FROM_HERE, - base::Bind(&LoadPasswordData, profile_path), + content::BrowserThread::GetBlockingPool() + ->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN) + .get(), + FROM_HERE, base::Bind(&LoadPasswordData, profile_path), base::Bind(&OnPasswordDataLoaded, success_callback, failure_callback)); }
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_controller_new.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_controller_new.cc index cfd798e3..0e512ff 100644 --- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_controller_new.cc +++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_controller_new.cc
@@ -347,10 +347,12 @@ creation_context_->token = token; PostTaskAndReplyWithResult( - content::BrowserThread::GetBlockingPool(), + content::BrowserThread::GetBlockingPool() + ->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN) + .get(), FROM_HERE, - base::Bind(&StoreSupervisedUserFiles, - creation_context_->token, + base::Bind(&StoreSupervisedUserFiles, creation_context_->token, ProfileHelper::GetProfilePathByUserIdHash( creation_context_->mount_hash)), base::Bind(
diff --git a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc index 041be37..1cfd624 100644 --- a/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc +++ b/chrome/browser/chromeos/login/supervised/supervised_user_creation_screen.cc
@@ -156,7 +156,8 @@ if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) { get_base_screen_delegate()->HideErrorScreen(this); histogram_helper_->OnErrorHide(); - } else { + } else if (state.status != + NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN) { on_error_screen_ = true; ErrorScreen* screen = get_base_screen_delegate()->GetErrorScreen(); ConfigureErrorScreen(screen, network, state.status);
diff --git a/chrome/browser/chromeos/login/test/https_forwarder.cc b/chrome/browser/chromeos/login/test/https_forwarder.cc index 118488ab..4101476 100644 --- a/chrome/browser/chromeos/login/test/https_forwarder.cc +++ b/chrome/browser/chromeos/login/test/https_forwarder.cc
@@ -4,25 +4,71 @@ #include "chrome/browser/chromeos/login/test/https_forwarder.h" +#include <cstring> + #include "base/base_paths.h" #include "base/files/file_path.h" +#include "base/logging.h" #include "base/path_service.h" #include "base/values.h" +#include "net/cert/test_root_certs.h" +#include "net/cert/x509_certificate.h" #include "net/test/python_utils.h" +#include "net/test/spawned_test_server/base_test_server.h" +#include "net/test/spawned_test_server/local_test_server.h" +#include "url/third_party/mozilla/url_parse.h" +#include "url/url_canon.h" namespace chromeos { -HTTPSForwarder::HTTPSForwarder(const GURL& forward_target) +namespace { + +// The root certificate used by net/tools/testserver/minica.py. +const char kMinicaRootCert[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIB0TCCATqgAwIBAgIBATANBgkqhkiG9w0BAQUFADAVMRMwEQYDVQQDEwpUZXN0aW5nIENBMB" + "4XDTEwMDEwMTA2MDAwMFoXDTMyMTIwMTA2MDAwMFowFTETMBEGA1UEAxMKVGVzdGluZyBDQTCB" + "nTANBgkqhkiG9w0BAQEFAAOBiwAwgYcCgYEApxmY8pML/nPQMah/Ez0vN47u7tUqd+RND8n/bw" + "f/Msvz2pmd5O1lgyr8sIB/mHh1BlOdJYoM48LHeWdlMJmpA0qbEVqHbDmoxOTtSs0MZAlZRvs5" + "7utHoHBNuwGKz0jDocS4lfxAn7SjQKmGsa/EVRmrnspHwwGFx3HGSqXs8H0CAQOjMzAxMBIGA1" + "UdEwEB/wQIMAYBAf8CAQAwGwYDVR0gAQEABBEwDzANBgsrBgEEAdZ5AgHODzANBgkqhkiG9w0B" + "AQUFAAOBgQA/STb40A6D+93jMfLGQzXc997IsaJZdoPt7tYa8PqGJBL62EiTj+erd/H5pDZx/2" + "/bcpOG4m9J56ygwOohbllw2TM+oeEd8syzV6X+1SIPnGI56JRrm3UXcHYx1Rq5loM9WKAiz/Wm" + "IWmskljsEQ7+542pq0pkHjs8nuXovSkUYA==\n" + "-----END CERTIFICATE-----"; + +} // namespace + +// A net::LocalTestServer that handles the actual forwarding to another server. +// Requires that the root certificate used by minica.py be marked as trusted +// before it is used. +class ForwardingServer : public net::LocalTestServer { + public: + ForwardingServer(const std::string& ssl_host, const GURL& forward_target); + + // net::LocalTestServer: + bool SetPythonPath() const override; + bool GetTestServerPath(base::FilePath* testserver_path) const override; + bool GenerateAdditionalArguments( + base::DictionaryValue* arguments) const override; + + private: + const std::string ssl_host_; + const GURL forward_target_; + + DISALLOW_COPY_AND_ASSIGN(ForwardingServer); +}; + +ForwardingServer::ForwardingServer(const std::string& ssl_host, + const GURL& forward_target) : net::LocalTestServer(net::LocalTestServer::TYPE_HTTPS, - net::LocalTestServer::kLocalhost, + SSLOptions(SSLOptions::CERT_AUTO), base::FilePath()), + ssl_host_(ssl_host), forward_target_(forward_target) { } -HTTPSForwarder::~HTTPSForwarder() { -} - -bool HTTPSForwarder::SetPythonPath() const { +bool ForwardingServer::SetPythonPath() const { if (!net::LocalTestServer::SetPythonPath()) return false; @@ -34,7 +80,8 @@ return true; } -bool HTTPSForwarder::GetTestServerPath(base::FilePath* testserver_path) const { +bool ForwardingServer::GetTestServerPath( + base::FilePath* testserver_path) const { base::FilePath source_root_dir; if (!PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir)) return false; @@ -48,15 +95,51 @@ return true; } -bool HTTPSForwarder::GenerateAdditionalArguments( +bool ForwardingServer::GenerateAdditionalArguments( base::DictionaryValue* arguments) const { base::FilePath source_root_dir; if (!net::LocalTestServer::GenerateAdditionalArguments(arguments) || !PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir)) return false; + arguments->SetString("ssl-host", ssl_host_); arguments->SetString("forward-target", forward_target_.spec()); + return true; } +HTTPSForwarder::HTTPSForwarder() { +} + +HTTPSForwarder::~HTTPSForwarder() { +} + +GURL HTTPSForwarder::GetURLForSSLHost(const std::string& path) const { + CHECK(forwarding_server_); + url::Replacements<char> replacements; + replacements.SetHost(ssl_host_.c_str(), url::Component(0, ssl_host_.size())); + return forwarding_server_->GetURL(path).ReplaceComponents(replacements); +} + +bool HTTPSForwarder::Initialize(const std::string& ssl_host, + const GURL& forward_target) { + // Mark the root certificate used by minica.py as trusted. This will be used + // by the Python part of the HTTPSForwarder to generate a certificate for + // |ssl_host_|. + net::TestRootCerts* root_certs = net::TestRootCerts::GetInstance(); + if (!root_certs) + return false; + net::CertificateList certs = + net::X509Certificate::CreateCertificateListFromBytes( + kMinicaRootCert, strlen(kMinicaRootCert), + net::X509Certificate::FORMAT_AUTO); + if (certs.size() != 1) + return false; + root_certs->Add(certs.front().get()); + + ssl_host_ = ssl_host; + forwarding_server_.reset(new ForwardingServer(ssl_host, forward_target)); + return forwarding_server_->Start(); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/https_forwarder.h b/chrome/browser/chromeos/login/test/https_forwarder.h index 060b24c..c054ae71 100644 --- a/chrome/browser/chromeos/login/test/https_forwarder.h +++ b/chrome/browser/chromeos/login/test/https_forwarder.h
@@ -5,28 +5,37 @@ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_TEST_HTTPS_FORWARDER_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_HTTPS_FORWARDER_H_ -#include "base/basictypes.h" +#include <string> + #include "base/compiler_specific.h" -#include "net/test/spawned_test_server/local_test_server.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" #include "url/gurl.h" namespace chromeos { +class ForwardingServer; + // An https test server that forwards all requests to another server. This // allows a server that supports http only to be accessed over https. -class HTTPSForwarder : public net::LocalTestServer { +// +// The server will bind to |127.0.0.1| but will present a certificate issued to +// |ssl_host|. +class HTTPSForwarder { public: - explicit HTTPSForwarder(const GURL& forward_target); - ~HTTPSForwarder() override; + HTTPSForwarder(); + ~HTTPSForwarder(); - // net::LocalTestServer: - bool SetPythonPath() const override; - bool GetTestServerPath(base::FilePath* testserver_path) const override; - bool GenerateAdditionalArguments( - base::DictionaryValue* arguments) const override; + // Returns a URL that uses |ssl_host_| as the host. + GURL GetURLForSSLHost(const std::string& path) const; + + bool Initialize(const std::string& ssl_host, + const GURL& forward_target) WARN_UNUSED_RESULT; private: - GURL forward_target_; + std::string ssl_host_; + + scoped_ptr<ForwardingServer> forwarding_server_; DISALLOW_COPY_AND_ASSIGN(HTTPSForwarder); };
diff --git a/chrome/browser/chromeos/login/test/https_forwarder.py b/chrome/browser/chromeos/login/test/https_forwarder.py index 6e7157b..5bde110 100644 --- a/chrome/browser/chromeos/login/test/https_forwarder.py +++ b/chrome/browser/chromeos/login/test/https_forwarder.py
@@ -7,7 +7,7 @@ """ import BaseHTTPServer -import os +import minica import SocketServer import sys import urllib2 @@ -144,14 +144,15 @@ Returns: The started server. """ + # The server binds to |host:port| but the certificate is issued to + # |ssl_host| instead. port = self.options.port host = self.options.host + ssl_host = self.options.ssl_host - if not os.path.isfile(self.options.cert_and_key_file): - raise testserver_base.OptionError( - 'Specified server cert file not found: ' + - self.options.cert_and_key_file) - pem_cert_and_key = open(self.options.cert_and_key_file).read() + (pem_cert_and_key, ocsp_der) = minica.GenerateCertKeyAndOCSP( + subject = self.options.ssl_host, + ocsp_url = None) server = MultiThreadedHTTPSServer((host, port), RequestForwarder, @@ -174,9 +175,10 @@ self.option_parser.add_option('--https', action='store_true', help='Ignored (provided for compatibility ' 'only).') - self.option_parser.add_option('--cert-and-key-file', help='The path to the ' - 'file containing the certificate and private ' - 'key for the server in PEM format.') + self.option_parser.add_option('--ocsp', help='Ignored (provided for' + 'compatibility only).') + self.option_parser.add_option('--ssl-host', help='The host name that the ' + 'certificate should be issued to.') self.option_parser.add_option('--forward-target', help='The URL prefix to ' 'which requests will be forwarded.')
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc index 1851974e..dd823a8d 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.cc +++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -33,6 +33,10 @@ namespace chromeos { +namespace { +const char kGAIAHost[] = "accounts.google.com"; +} + // static const char OobeBaseTest::kFakeUserEmail[] = "fake-email@gmail.com"; const char OobeBaseTest::kFakeUserPassword[] = "fake-password"; @@ -146,7 +150,7 @@ command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user"); - GURL gaia_url = gaia_https_forwarder_->GetURL(std::string()); + GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost(std::string()); command_line->AppendSwitchASCII(::switches::kGaiaUrl, gaia_url.spec()); command_line->AppendSwitchASCII(::switches::kLsoUrl, gaia_url.spec()); command_line->AppendSwitchASCII(::switches::kGoogleApisUrl, @@ -157,9 +161,8 @@ } void OobeBaseTest::InitHttpsForwarders() { - gaia_https_forwarder_.reset( - new HTTPSForwarder(embedded_test_server()->base_url())); - ASSERT_TRUE(gaia_https_forwarder_->Start()); + ASSERT_TRUE(gaia_https_forwarder_.Initialize( + kGAIAHost, embedded_test_server()->base_url())); } void OobeBaseTest::RegisterAdditionalRequestHandlers() {
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.h b/chrome/browser/chromeos/login/test/oobe_base_test.h index 7c2f592..f93ef88a 100644 --- a/chrome/browser/chromeos/login/test/oobe_base_test.h +++ b/chrome/browser/chromeos/login/test/oobe_base_test.h
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/command_line.h" +#include "chrome/browser/chromeos/login/test/https_forwarder.h" #include "chrome/browser/chromeos/login/ui/login_display_host_impl.h" #include "chrome/browser/chromeos/login/ui/webui_login_display.h" #include "chrome/browser/extensions/extension_apitest.h" @@ -28,7 +29,6 @@ namespace chromeos { -class HTTPSForwarder; class NetworkPortalDetectorTestImpl; // Base class for OOBE, login, SAML and Kiosk tests. @@ -104,7 +104,7 @@ scoped_ptr<content::WindowedNotificationObserver> login_screen_load_observer_; scoped_ptr<extensions::ScopedCurrentChannel> scoped_channel_; - scoped_ptr<HTTPSForwarder> gaia_https_forwarder_; + HTTPSForwarder gaia_https_forwarder_; std::string gaia_frame_parent_; bool use_webview_; bool initialize_fake_merge_session_;
diff --git a/chrome/browser/chromeos/login/ui/login_display.h b/chrome/browser/chromeos/login/ui/login_display.h index d6c70c5..6512bcf8 100644 --- a/chrome/browser/chromeos/login/ui/login_display.h +++ b/chrome/browser/chromeos/login/ui/login_display.h
@@ -133,7 +133,8 @@ // Show password changed dialog. If |show_password_error| is not null // user already tried to enter old password but it turned out to be incorrect. - virtual void ShowPasswordChangedDialog(bool show_password_error) = 0; + virtual void ShowPasswordChangedDialog(bool show_password_error, + const std::string& email) = 0; // Shows signin UI with specified email. virtual void ShowSigninUI(const std::string& email) = 0;
diff --git a/chrome/browser/chromeos/login/ui/mock_login_display.h b/chrome/browser/chromeos/login/ui/mock_login_display.h index 79f1a88..dca85a1 100644 --- a/chrome/browser/chromeos/login/ui/mock_login_display.h +++ b/chrome/browser/chromeos/login/ui/mock_login_display.h
@@ -24,7 +24,7 @@ MOCK_METHOD3(ShowError, void(int, int, HelpAppLauncher::HelpTopic)); MOCK_METHOD1(ShowErrorScreen, void(LoginDisplay::SigninError)); MOCK_METHOD1(ShowGaiaPasswordChanged, void(const std::string&)); - MOCK_METHOD1(ShowPasswordChangedDialog, void(bool)); + MOCK_METHOD2(ShowPasswordChangedDialog, void(bool, const std::string&)); MOCK_METHOD1(ShowSigninUI, void(const std::string&)); MOCK_METHOD0(ShowWhitelistCheckFailedError, void(void)); MOCK_METHOD1(OnBeforeUserRemoved, void(const std::string&));
diff --git a/chrome/browser/chromeos/login/ui/views/user_board_view.h b/chrome/browser/chromeos/login/ui/views/user_board_view.h index dae7a7d..30fe63f 100644 --- a/chrome/browser/chromeos/login/ui/views/user_board_view.h +++ b/chrome/browser/chromeos/login/ui/views/user_board_view.h
@@ -10,7 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "base/values.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "components/proximity_auth/screenlock_bridge.h" namespace chromeos { @@ -35,9 +35,10 @@ virtual void ShowUserPodCustomIcon(const std::string& user_id, const base::DictionaryValue& icon) = 0; virtual void HideUserPodCustomIcon(const std::string& user_id) = 0; - virtual void SetAuthType(const std::string& user_id, - ScreenlockBridge::LockHandler::AuthType auth_type, - const base::string16& initial_value) = 0; + virtual void SetAuthType( + const std::string& user_id, + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type, + const base::string16& initial_value) = 0; }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/webui_login_display.cc b/chrome/browser/chromeos/login/ui/webui_login_display.cc index cd0817d2..264ef14 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_display.cc +++ b/chrome/browser/chromeos/login/ui/webui_login_display.cc
@@ -185,9 +185,10 @@ webui_handler_->ShowGaiaPasswordChanged(username); } -void WebUILoginDisplay::ShowPasswordChangedDialog(bool show_password_error) { +void WebUILoginDisplay::ShowPasswordChangedDialog(bool show_password_error, + const std::string& email) { if (webui_handler_) - webui_handler_->ShowPasswordChangedDialog(show_password_error); + webui_handler_->ShowPasswordChangedDialog(show_password_error, email); } void WebUILoginDisplay::ShowSigninUI(const std::string& email) {
diff --git a/chrome/browser/chromeos/login/ui/webui_login_display.h b/chrome/browser/chromeos/login/ui/webui_login_display.h index 7005afc..6cc25fb 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_display.h +++ b/chrome/browser/chromeos/login/ui/webui_login_display.h
@@ -42,7 +42,8 @@ HelpAppLauncher::HelpTopic help_topic_id) override; void ShowErrorScreen(LoginDisplay::SigninError error_id) override; void ShowGaiaPasswordChanged(const std::string& username) override; - void ShowPasswordChangedDialog(bool show_password_error) override; + void ShowPasswordChangedDialog(bool show_password_error, + const std::string& email) override; void ShowSigninUI(const std::string& email) override; void ShowWhitelistCheckFailedError() override;
diff --git a/chrome/browser/chromeos/login/users/mock_user_manager.h b/chrome/browser/chromeos/login/users/mock_user_manager.h index 78a6ef9..c7545bc 100644 --- a/chrome/browser/chromeos/login/users/mock_user_manager.h +++ b/chrome/browser/chromeos/login/users/mock_user_manager.h
@@ -98,25 +98,24 @@ // You can't mock these functions easily because nobody can create // User objects but the ChromeUserManager and us. - virtual const user_manager::UserList& GetUsers() const override; - virtual const user_manager::User* GetLoggedInUser() const override; - virtual user_manager::UserList GetUnlockUsers() const override; - virtual const std::string& GetOwnerEmail() const override; - virtual user_manager::User* GetLoggedInUser() override; - virtual const user_manager::User* GetActiveUser() const override; - virtual user_manager::User* GetActiveUser() override; - virtual const user_manager::User* GetPrimaryUser() const override; + const user_manager::UserList& GetUsers() const override; + const user_manager::User* GetLoggedInUser() const override; + user_manager::UserList GetUnlockUsers() const override; + const std::string& GetOwnerEmail() const override; + user_manager::User* GetLoggedInUser() override; + const user_manager::User* GetActiveUser() const override; + user_manager::User* GetActiveUser() override; + const user_manager::User* GetPrimaryUser() const override; // ChromeUserManager overrides: - virtual BootstrapManager* GetBootstrapManager() override; - virtual MultiProfileUserController* GetMultiProfileUserController() override; - virtual UserImageManager* GetUserImageManager( - const std::string& user_id) override; - virtual SupervisedUserManager* GetSupervisedUserManager() override; + BootstrapManager* GetBootstrapManager() override; + MultiProfileUserController* GetMultiProfileUserController() override; + UserImageManager* GetUserImageManager(const std::string& user_id) override; + SupervisedUserManager* GetSupervisedUserManager() override; MOCK_METHOD2(SetUserFlow, void(const std::string&, UserFlow*)); MOCK_METHOD1(ResetUserFlow, void(const std::string&)); - virtual UserFlow* GetCurrentUserFlow() const override; - virtual UserFlow* GetUserFlow(const std::string&) const override; + UserFlow* GetCurrentUserFlow() const override; + UserFlow* GetUserFlow(const std::string&) const override; // Sets a new User instance. Users previously created by this MockUserManager // become invalid.
diff --git a/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc b/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc index 6a3a1c8b..e1733004 100644 --- a/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc +++ b/chrome/browser/chromeos/login/users/multi_profile_user_controller.cc
@@ -73,10 +73,8 @@ // static void MultiProfileUserController::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kMultiProfileUserBehavior, - kBehaviorUnrestricted, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kMultiProfileUserBehavior, + kBehaviorUnrestricted); registry->RegisterBooleanPref( prefs::kMultiProfileNeverShowIntro, false,
diff --git a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc index 9339c1f..0668465 100644 --- a/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc +++ b/chrome/browser/chromeos/login/users/supervised_user_manager_impl.cc
@@ -512,10 +512,11 @@ base::FilePath profile_dir = ProfileHelper::GetProfilePathByUserIdHash( ProfileHelper::Get()->GetUserByProfile(profile)->username_hash()); PostTaskAndReplyWithResult( - content::BrowserThread::GetBlockingPool(), - FROM_HERE, - base::Bind(&LoadSyncToken, profile_dir), - callback); + content::BrowserThread::GetBlockingPool() + ->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN) + .get(), + FROM_HERE, base::Bind(&LoadSyncToken, profile_dir), callback); } void SupervisedUserManagerImpl::ConfigureSyncWithToken(
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc index 1d6f75ad..6f7280a1a 100644 --- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc +++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -1039,11 +1039,9 @@ auth_needed_waiter.Wait(); } -// TODO(paulmeyer): Re-enable webview version of this test -// (drop this condition) once http://crbug.com/452452 is fixed. INSTANTIATE_TEST_CASE_P(WizardControllerProxyAuthOnSigninSuite, WizardControllerProxyAuthOnSigninTest, - testing::Values(false)); + testing::Bool()); class WizardControllerKioskFlowTest : public WizardControllerFlowTest { protected:
diff --git a/chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc b/chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc index be4621e2..59f6a5b3 100644 --- a/chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc +++ b/chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc
@@ -40,6 +40,7 @@ int CertVerifyProcChromeOS::VerifyInternal( net::X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, net::CRLSet* crl_set, const net::CertificateList& additional_trust_anchors, @@ -52,12 +53,8 @@ chain_verify_callback.isChainValidArg = static_cast<void*>(&chain_verify_args); - return VerifyInternalImpl(cert, - hostname, - flags, - crl_set, - additional_trust_anchors, - &chain_verify_callback, + return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set, + additional_trust_anchors, &chain_verify_callback, verify_result); }
diff --git a/chrome/browser/chromeos/net/cert_verify_proc_chromeos.h b/chrome/browser/chromeos/net/cert_verify_proc_chromeos.h index b79ac8a..346642f 100644 --- a/chrome/browser/chromeos/net/cert_verify_proc_chromeos.h +++ b/chrome/browser/chromeos/net/cert_verify_proc_chromeos.h
@@ -34,6 +34,7 @@ // net::CertVerifyProcNSS implementation: int VerifyInternal(net::X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, net::CRLSet* crl_set, const net::CertificateList& additional_trust_anchors,
diff --git a/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc b/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc index f7deba815..dc65814 100644 --- a/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc +++ b/chrome/browser/chromeos/net/cert_verify_proc_chromeos_unittest.cc
@@ -80,12 +80,9 @@ std::string* root_subject_name) { int flags = 0; net::CertVerifyResult verify_result; - int error = verify_proc->Verify(cert, - "127.0.0.1", - flags, - NULL, - additional_trust_anchors, - &verify_result); + int error = + verify_proc->Verify(cert, "127.0.0.1", std::string(), flags, NULL, + additional_trust_anchors, &verify_result); if (verify_result.verified_cert.get() && !verify_result.verified_cert->GetIntermediateCertificates().empty()) { net::X509Certificate::OSCertHandle root =
diff --git a/chrome/browser/chromeos/net/proxy_config_handler.cc b/chrome/browser/chromeos/net/proxy_config_handler.cc index 782b035..4fa3d662 100644 --- a/chrome/browser/chromeos/net/proxy_config_handler.cc +++ b/chrome/browser/chromeos/net/proxy_config_handler.cc
@@ -130,13 +130,9 @@ } void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kUseSharedProxies, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kUseSharedProxies, false); - registry->RegisterListPref(prefs::kOpenNetworkConfiguration, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kOpenNetworkConfiguration); } } // namespace proxy_config
diff --git a/chrome/browser/chromeos/offline/offline_load_page_unittest.cc b/chrome/browser/chromeos/offline/offline_load_page_unittest.cc index 6261d3cc..8bf9a98 100644 --- a/chrome/browser/chromeos/offline/offline_load_page_unittest.cc +++ b/chrome/browser/chromeos/offline/offline_load_page_unittest.cc
@@ -61,10 +61,14 @@ user_response_ = CANCEL; } - void Navigate(const char* url, int page_id) { - WebContentsTester::For(web_contents())->TestDidNavigate( - web_contents()->GetMainFrame(), page_id, GURL(url), - ui::PAGE_TRANSITION_TYPED); + void Navigate(const char* url, + int page_id, + int nav_entry_id, + bool did_create_new_entry) { + WebContentsTester::For(web_contents()) + ->TestDidNavigate(web_contents()->GetMainFrame(), page_id, nav_entry_id, + did_create_new_entry, GURL(url), + ui::PAGE_TRANSITION_TYPED); } void ShowInterstitial(const char* url) { @@ -91,7 +95,7 @@ TEST_F(OfflineLoadPageTest, OfflinePageProceed) { // Start a load. - Navigate(kURL1, 1); + Navigate(kURL1, 1, 0, true); // Load next page. controller().LoadURL(GURL(kURL2), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); @@ -113,14 +117,14 @@ EXPECT_EQ(kURL2, web_contents()->GetVisibleURL().spec()); // Commit navigation and the interstitial page is gone. - Navigate(kURL2, 2); + Navigate(kURL2, 2, 0, true); EXPECT_FALSE(GetOfflineLoadPage()); } // Tests showing an offline page and not proceeding. TEST_F(OfflineLoadPageTest, OfflinePageDontProceed) { // Start a load. - Navigate(kURL1, 1); + Navigate(kURL1, 1, 0, true); controller().LoadURL(GURL(kURL2), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
diff --git a/chrome/browser/chromeos/policy/consumer_enrollment_handler_factory_unittest.cc b/chrome/browser/chromeos/policy/consumer_enrollment_handler_factory_unittest.cc index 8e56c19..b1c209d 100644 --- a/chrome/browser/chromeos/policy/consumer_enrollment_handler_factory_unittest.cc +++ b/chrome/browser/chromeos/policy/consumer_enrollment_handler_factory_unittest.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/chromeos/policy/fake_consumer_management_service.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -52,6 +53,7 @@ ASSERT_TRUE(testing_profile_manager_->SetUp()); } + content::TestBrowserThreadBundle thread_bundle_; FakeConsumerManagementService* fake_service_; chromeos::FakeChromeUserManager* fake_user_manager_; chromeos::ScopedUserManagerEnabler scoped_user_manager_enabler_;
diff --git a/chrome/browser/chromeos/policy/consumer_management_notifier_factory_unittest.cc b/chrome/browser/chromeos/policy/consumer_management_notifier_factory_unittest.cc index ca78a43d..5963c82 100644 --- a/chrome/browser/chromeos/policy/consumer_management_notifier_factory_unittest.cc +++ b/chrome/browser/chromeos/policy/consumer_management_notifier_factory_unittest.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/chromeos/policy/fake_consumer_management_service.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -52,6 +53,7 @@ ASSERT_TRUE(testing_profile_manager_->SetUp()); } + content::TestBrowserThreadBundle thread_bundle_; FakeConsumerManagementService* fake_service_; chromeos::FakeChromeUserManager* fake_user_manager_; chromeos::ScopedUserManagerEnabler scoped_user_manager_enabler_;
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc index 1355846..f9800ab 100644 --- a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc +++ b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
@@ -115,8 +115,8 @@ protected: DeviceLocalAccountPolicyServiceTest(); - virtual void SetUp() override; - virtual void TearDown() override; + void SetUp() override; + void TearDown() override; void InstallDevicePolicy() override;
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc index cf9c94b2..be98336f 100644 --- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc +++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -436,6 +436,7 @@ case EnterpriseInstallAttributes::LOCK_FINALIZE_ERROR: case EnterpriseInstallAttributes::LOCK_READBACK_ERROR: case EnterpriseInstallAttributes::LOCK_WRONG_DOMAIN: + case EnterpriseInstallAttributes::LOCK_WRONG_MODE: ReportResult(EnrollmentStatus::ForLockError(lock_result)); break; }
diff --git a/chrome/browser/chromeos/policy/enterprise_install_attributes.cc b/chrome/browser/chromeos/policy/enterprise_install_attributes.cc index 9b58583..3fbbc8d 100644 --- a/chrome/browser/chromeos/policy/enterprise_install_attributes.cc +++ b/chrome/browser/chromeos/policy/enterprise_install_attributes.cc
@@ -154,15 +154,35 @@ // Check for existing lock first. if (device_locked_) { - if (device_mode == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) { - callback.Run((registration_mode_ == device_mode) ? LOCK_SUCCESS : - LOCK_NOT_READY); - } else { - std::string domain = gaia::ExtractDomainName(user); - callback.Run( - (!registration_domain_.empty() && domain == registration_domain_) ? - LOCK_SUCCESS : LOCK_WRONG_DOMAIN); + if (device_mode != registration_mode_) { + callback.Run(LOCK_WRONG_MODE); + return; } + + switch (registration_mode_) { + case DEVICE_MODE_ENTERPRISE: + case DEVICE_MODE_LEGACY_RETAIL_MODE: { + // Check domain match for enterprise devices. + std::string domain = gaia::ExtractDomainName(user); + if (registration_domain_.empty() || domain != registration_domain_) { + callback.Run(LOCK_WRONG_DOMAIN); + return; + } + break; + } + case DEVICE_MODE_NOT_SET: + case DEVICE_MODE_PENDING: + // This case can't happen due to the CHECK_NE asserts above. + NOTREACHED(); + break; + case DEVICE_MODE_CONSUMER: + case DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH: + // The user parameter is ignored for consumer devices. + break; + } + + // Already locked in the right mode, signal success. + callback.Run(LOCK_SUCCESS); return; }
diff --git a/chrome/browser/chromeos/policy/enterprise_install_attributes.h b/chrome/browser/chromeos/policy/enterprise_install_attributes.h index ec1f07f6..bb9a681 100644 --- a/chrome/browser/chromeos/policy/enterprise_install_attributes.h +++ b/chrome/browser/chromeos/policy/enterprise_install_attributes.h
@@ -38,6 +38,7 @@ LOCK_FINALIZE_ERROR = 6, // Backend failed to lock. LOCK_READBACK_ERROR = 7, // Inconsistency reading back registration data. LOCK_WRONG_DOMAIN = 8, // Device already registered to another domain. + LOCK_WRONG_MODE = 9, // Device already locked to a different mode. }; // A callback to handle responses of methods returning a LockResult value.
diff --git a/chrome/browser/chromeos/policy/enterprise_install_attributes_unittest.cc b/chrome/browser/chromeos/policy/enterprise_install_attributes_unittest.cc index b2cf71d..1e6a8ec 100644 --- a/chrome/browser/chromeos/policy/enterprise_install_attributes_unittest.cc +++ b/chrome/browser/chromeos/policy/enterprise_install_attributes_unittest.cc
@@ -91,28 +91,28 @@ TEST_F(EnterpriseInstallAttributesTest, Lock) { EXPECT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS, - LockDeviceAndWaitForResult( - kTestUser, - DEVICE_MODE_ENTERPRISE, - kTestDeviceId)); + LockDeviceAndWaitForResult(kTestUser, DEVICE_MODE_ENTERPRISE, + kTestDeviceId)); + // Locking an already locked device should succeed if the parameters match. EXPECT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS, - LockDeviceAndWaitForResult( - kTestUser, - DEVICE_MODE_ENTERPRISE, - kTestDeviceId)); + LockDeviceAndWaitForResult(kTestUser, DEVICE_MODE_ENTERPRISE, + kTestDeviceId)); + // Another user from the same domain should also succeed. EXPECT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS, - LockDeviceAndWaitForResult( - "test1@example.com", - DEVICE_MODE_ENTERPRISE, - kTestDeviceId)); + LockDeviceAndWaitForResult("test1@example.com", + DEVICE_MODE_ENTERPRISE, kTestDeviceId)); + // But another domain should fail. EXPECT_EQ(EnterpriseInstallAttributes::LOCK_WRONG_DOMAIN, - LockDeviceAndWaitForResult( - "test@bluebears.com", - DEVICE_MODE_ENTERPRISE, - kTestDeviceId)); + LockDeviceAndWaitForResult("test@bluebears.com", + DEVICE_MODE_ENTERPRISE, kTestDeviceId)); + + // A non-matching mode should fail as well. + EXPECT_EQ(EnterpriseInstallAttributes::LOCK_WRONG_MODE, + LockDeviceAndWaitForResult(kTestUser, DEVICE_MODE_CONSUMER, + kTestDeviceId)); } TEST_F(EnterpriseInstallAttributesTest, LockCanonicalize) {
diff --git a/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc b/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc index da4a95c..9b770a0 100644 --- a/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc +++ b/chrome/browser/chromeos/policy/network_configuration_updater_unittest.cc
@@ -201,7 +201,7 @@ protected: NetworkConfigurationUpdaterTest() : certificate_importer_(NULL) {} - virtual void SetUp() override { + void SetUp() override { EXPECT_CALL(provider_, IsInitializationComplete(_)) .WillRepeatedly(Return(false)); provider_.Init(); @@ -231,7 +231,7 @@ certificate_importer_owned_.reset(certificate_importer_); } - virtual void TearDown() override { + void TearDown() override { network_configuration_updater_.reset(); provider_.Shutdown(); base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/chromeos/policy/policy_cert_service_factory.cc b/chrome/browser/chromeos/policy/policy_cert_service_factory.cc index 4955bc0..52a69f3 100644 --- a/chrome/browser/chromeos/policy/policy_cert_service_factory.cc +++ b/chrome/browser/chromeos/policy/policy_cert_service_factory.cc
@@ -140,10 +140,7 @@ user_prefs::PrefRegistrySyncable* registry) { // TODO(joaodasilva): this is used for backwards compatibility. // Remove once it's not necessary anymore. - registry->RegisterBooleanPref( - prefs::kUsedPolicyCertificatesOnce, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kUsedPolicyCertificatesOnce, false); } bool PolicyCertServiceFactory::ServiceIsNULLWhileTesting() const {
diff --git a/chrome/browser/chromeos/policy/policy_cert_verifier.cc b/chrome/browser/chromeos/policy/policy_cert_verifier.cc index cca86b06..d3abda8e 100644 --- a/chrome/browser/chromeos/policy/policy_cert_verifier.cc +++ b/chrome/browser/chromeos/policy/policy_cert_verifier.cc
@@ -71,6 +71,7 @@ int PolicyCertVerifier::Verify( net::X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, net::CRLSet* crl_set, net::CertVerifyResult* verify_result, @@ -84,8 +85,9 @@ anchor_used_callback_, completion_callback, verify_result); - int error = delegate_->Verify(cert, hostname, flags, crl_set, verify_result, - wrapped_callback, out_req, net_log); + int error = + delegate_->Verify(cert, hostname, ocsp_response, flags, crl_set, + verify_result, wrapped_callback, out_req, net_log); MaybeSignalAnchorUse(error, anchor_used_callback_, *verify_result); return error; } @@ -95,6 +97,11 @@ delegate_->CancelRequest(req); } +bool PolicyCertVerifier::SupportsOCSPStapling() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + return delegate_->SupportsOCSPStapling(); +} + const net::CertificateList& PolicyCertVerifier::GetAdditionalTrustAnchors() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); return trust_anchors_;
diff --git a/chrome/browser/chromeos/policy/policy_cert_verifier.h b/chrome/browser/chromeos/policy/policy_cert_verifier.h index 11060cc..774b36b5 100644 --- a/chrome/browser/chromeos/policy/policy_cert_verifier.h +++ b/chrome/browser/chromeos/policy/policy_cert_verifier.h
@@ -49,6 +49,7 @@ // Note: |callback| can be null. int Verify(net::X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, net::CRLSet* crl_set, net::CertVerifyResult* verify_result, @@ -58,6 +59,8 @@ void CancelRequest(RequestHandle req) override; + bool SupportsOCSPStapling() override; + // CertTrustAnchorProvider: const net::CertificateList& GetAdditionalTrustAnchors() override;
diff --git a/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc b/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc index 4d6bff1..aeb626e0 100644 --- a/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc +++ b/chrome/browser/chromeos/policy/policy_cert_verifier_browsertest.cc
@@ -67,13 +67,9 @@ int VerifyTestServerCert(const net::TestCompletionCallback& test_callback, net::CertVerifyResult* verify_result, net::CertVerifier::RequestHandle* request_handle) { - return cert_verifier_->Verify(test_server_cert_.get(), - "127.0.0.1", - 0, - NULL, - verify_result, - test_callback.callback(), - request_handle, + return cert_verifier_->Verify(test_server_cert_.get(), "127.0.0.1", + std::string(), 0, NULL, verify_result, + test_callback.callback(), request_handle, net::BoundNetLog()); }
diff --git a/chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.cc b/chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.cc index f21b96fb..2815759 100644 --- a/chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.cc +++ b/chrome/browser/chromeos/policy/remote_commands/device_command_reboot_job.cc
@@ -9,7 +9,9 @@ #include "base/bind.h" #include "base/location.h" #include "base/logging.h" +#include "base/single_thread_task_runner.h" #include "base/sys_info.h" +#include "base/thread_task_runner_handle.h" #include "base/time/time.h" #include "chromeos/dbus/power_manager_client.h" #include "policy/proto/device_management_backend.pb.h" @@ -62,7 +64,8 @@ // performed and we invoke it. |kMinimumUptimeInMinutes| defines a lower limit // on the uptime to avoid uninterruptable reboot loops. if (delta > base::TimeDelta()) { - succeeded_callback.Run(nullptr); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(succeeded_callback, nullptr)); return; }
diff --git a/chrome/browser/chromeos/power/power_prefs.cc b/chrome/browser/chromeos/power/power_prefs.cc index 9b7b8643..5dc80f9f 100644 --- a/chrome/browser/chromeos/power/power_prefs.cc +++ b/chrome/browser/chromeos/power/power_prefs.cc
@@ -50,14 +50,10 @@ user_prefs::PrefRegistrySyncable* registry) { RegisterProfilePrefs(registry); - registry->RegisterIntegerPref( - prefs::kPowerBatteryIdleAction, - PowerPolicyController::ACTION_SUSPEND, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerLidClosedAction, - PowerPolicyController::ACTION_SUSPEND, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kPowerBatteryIdleAction, + PowerPolicyController::ACTION_SUSPEND); + registry->RegisterIntegerPref(prefs::kPowerLidClosedAction, + PowerPolicyController::ACTION_SUSPEND); } // static @@ -65,14 +61,10 @@ user_prefs::PrefRegistrySyncable* registry) { RegisterProfilePrefs(registry); - registry->RegisterIntegerPref( - prefs::kPowerBatteryIdleAction, - PowerPolicyController::ACTION_SHUT_DOWN, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerLidClosedAction, - PowerPolicyController::ACTION_SHUT_DOWN, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kPowerBatteryIdleAction, + PowerPolicyController::ACTION_SHUT_DOWN); + registry->RegisterIntegerPref(prefs::kPowerLidClosedAction, + PowerPolicyController::ACTION_SHUT_DOWN); } void PowerPrefs::Observe(int type, @@ -170,90 +162,34 @@ // static void PowerPrefs::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kPowerAcScreenDimDelayMs, - 420000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerAcScreenOffDelayMs, - 480000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerAcScreenLockDelayMs, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerAcIdleWarningDelayMs, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerAcIdleDelayMs, - 1800000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerBatteryScreenDimDelayMs, - 300000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerBatteryScreenOffDelayMs, - 360000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerBatteryScreenLockDelayMs, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerBatteryIdleWarningDelayMs, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerBatteryIdleDelayMs, - 600000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerLockScreenDimDelayMs, - 30000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerLockScreenOffDelayMs, - 40000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kPowerAcIdleAction, - PowerPolicyController::ACTION_SUSPEND, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kPowerUseAudioActivity, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kPowerUseVideoActivity, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kPowerAllowScreenWakeLocks, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kPowerAcScreenDimDelayMs, 420000); + registry->RegisterIntegerPref(prefs::kPowerAcScreenOffDelayMs, 480000); + registry->RegisterIntegerPref(prefs::kPowerAcScreenLockDelayMs, 0); + registry->RegisterIntegerPref(prefs::kPowerAcIdleWarningDelayMs, 0); + registry->RegisterIntegerPref(prefs::kPowerAcIdleDelayMs, 1800000); + registry->RegisterIntegerPref(prefs::kPowerBatteryScreenDimDelayMs, 300000); + registry->RegisterIntegerPref(prefs::kPowerBatteryScreenOffDelayMs, 360000); + registry->RegisterIntegerPref(prefs::kPowerBatteryScreenLockDelayMs, 0); + registry->RegisterIntegerPref(prefs::kPowerBatteryIdleWarningDelayMs, 0); + registry->RegisterIntegerPref(prefs::kPowerBatteryIdleDelayMs, 600000); + registry->RegisterIntegerPref(prefs::kPowerLockScreenDimDelayMs, 30000); + registry->RegisterIntegerPref(prefs::kPowerLockScreenOffDelayMs, 40000); + registry->RegisterIntegerPref(prefs::kPowerAcIdleAction, + PowerPolicyController::ACTION_SUSPEND); + registry->RegisterBooleanPref(prefs::kPowerUseAudioActivity, true); + registry->RegisterBooleanPref(prefs::kPowerUseVideoActivity, true); + registry->RegisterBooleanPref(prefs::kPowerAllowScreenWakeLocks, true); registry->RegisterBooleanPref( prefs::kEnableAutoScreenLock, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterDoublePref( - prefs::kPowerPresentationScreenDimDelayFactor, - 2.0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDoublePref( - prefs::kPowerUserActivityScreenDimDelayFactor, - 2.0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDoublePref(prefs::kPowerPresentationScreenDimDelayFactor, + 2.0); + registry->RegisterDoublePref(prefs::kPowerUserActivityScreenDimDelayFactor, + 2.0); + registry->RegisterBooleanPref(prefs::kPowerWaitForInitialUserActivity, false); registry->RegisterBooleanPref( - prefs::kPowerWaitForInitialUserActivity, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kPowerForceNonzeroBrightnessForUserActivity, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kPowerForceNonzeroBrightnessForUserActivity, true); } void PowerPrefs::SetProfile(Profile* profile) {
diff --git a/chrome/browser/chromeos/power/power_prefs_unittest.cc b/chrome/browser/chromeos/power/power_prefs_unittest.cc index 9bf1e9c57..dbf34ea 100644 --- a/chrome/browser/chromeos/power/power_prefs_unittest.cc +++ b/chrome/browser/chromeos/power/power_prefs_unittest.cc
@@ -32,6 +32,7 @@ #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos { @@ -60,6 +61,7 @@ bool GetExpectedAllowScreenWakeLocksForProfile(Profile* profile) const; bool GetCurrentAllowScreenWakeLocks() const; + content::TestBrowserThreadBundle thread_bundle_; TestingProfileManager profile_manager_; PowerPolicyController* power_policy_controller_; // Not owned. scoped_ptr<FakePowerManagerClient> fake_power_manager_client_;
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index ba4f242fba..26bdbd9ff 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -107,10 +107,7 @@ hardware_keyboard_id = "xkb:us::eng"; // only for testing. } - registry->RegisterBooleanPref( - prefs::kPerformanceTracingEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kPerformanceTracingEnabled, false); registry->RegisterBooleanPref( prefs::kTapToClickEnabled, @@ -120,10 +117,7 @@ prefs::kTapDraggingEnabled, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); - registry->RegisterBooleanPref( - prefs::kEnableTouchpadThreeFingerClick, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kEnableTouchpadThreeFingerClick, false); registry->RegisterBooleanPref( prefs::kNaturalScroll, base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kNaturalScrollDefault), @@ -132,14 +126,8 @@ prefs::kPrimaryMouseButtonRight, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); - registry->RegisterBooleanPref( - prefs::kLabsMediaplayerEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kLabsAdvancedFilesystemEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kLabsMediaplayerEnabled, false); + registry->RegisterBooleanPref(prefs::kLabsAdvancedFilesystemEnabled, false); registry->RegisterBooleanPref( prefs::kAccessibilityStickyKeysEnabled, false, @@ -148,10 +136,8 @@ prefs::kAccessibilityLargeCursorEnabled, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kAccessibilitySpokenFeedbackEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kAccessibilitySpokenFeedbackEnabled, + false); registry->RegisterBooleanPref( prefs::kAccessibilityHighContrastEnabled, false, @@ -164,10 +150,8 @@ prefs::kAccessibilityScreenMagnifierType, ui::kDefaultMagnifierType, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterDoublePref( - prefs::kAccessibilityScreenMagnifierScale, - std::numeric_limits<double>::min(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDoublePref(prefs::kAccessibilityScreenMagnifierScale, + std::numeric_limits<double>::min()); registry->RegisterBooleanPref( prefs::kAccessibilityAutoclickEnabled, false, @@ -210,26 +194,13 @@ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); // We don't sync prefs::kLanguageCurrentInputMethod and PreviousInputMethod // because they're just used to track the logout state of the device. - registry->RegisterStringPref( - prefs::kLanguageCurrentInputMethod, - "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kLanguagePreviousInputMethod, - "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kLanguagePreferredLanguages, - kFallbackInputMethodLocale, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kLanguagePreloadEngines, - hardware_keyboard_id, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kLanguageEnabledExtensionImes, - "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kLanguageCurrentInputMethod, ""); + registry->RegisterStringPref(prefs::kLanguagePreviousInputMethod, ""); + registry->RegisterStringPref(prefs::kLanguagePreferredLanguages, + kFallbackInputMethodLocale); + registry->RegisterStringPref(prefs::kLanguagePreloadEngines, + hardware_keyboard_id); + registry->RegisterStringPref(prefs::kLanguageEnabledExtensionImes, ""); registry->RegisterIntegerPref( prefs::kLanguageRemapSearchKeyTo, @@ -246,10 +217,8 @@ // We don't sync the CapsLock remapping pref, since the UI hides this pref // on certain devices, so syncing a non-default value to a device that // doesn't allow changing the pref would be odd. http://crbug.com/167237 - registry->RegisterIntegerPref( - prefs::kLanguageRemapCapsLockKeyTo, - input_method::kCapsLockKey, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kLanguageRemapCapsLockKeyTo, + input_method::kCapsLockKey); registry->RegisterIntegerPref( prefs::kLanguageRemapDiamondKeyTo, input_method::kControlKey, @@ -257,10 +226,7 @@ // The following pref isn't synced since the user may desire a different value // depending on whether an external keyboard is attached to a particular // device. - registry->RegisterBooleanPref( - prefs::kLanguageSendFunctionKeys, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kLanguageSendFunctionKeys, false); registry->RegisterBooleanPref( prefs::kLanguageXkbAutoRepeatEnabled, true, @@ -275,10 +241,7 @@ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); // We don't sync wake-on-wifi related prefs because they are device specific. - registry->RegisterBooleanPref( - prefs::kWakeOnWifiSsid, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kWakeOnWifiSsid, true); // Mobile plan notifications default to on. registry->RegisterBooleanPref( @@ -287,16 +250,10 @@ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); // 3G first-time usage promo will be shown at least once. - registry->RegisterBooleanPref( - prefs::kShow3gPromoNotification, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kShow3gPromoNotification, true); // Number of times Data Saver prompt has been shown on 3G data network. - registry->RegisterIntegerPref( - prefs::kDataSaverPromptsShown, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kDataSaverPromptsShown, 0); // Initially all existing users would see "What's new" for current version // after update. @@ -304,25 +261,13 @@ "0.0.0.0", user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kExternalStorageDisabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kExternalStorageDisabled, false); - registry->RegisterStringPref( - prefs::kTermsOfServiceURL, - "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kTermsOfServiceURL, ""); - registry->RegisterBooleanPref( - prefs::kTouchHudProjectionEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kTouchHudProjectionEnabled, false); - registry->RegisterBooleanPref( - prefs::kTouchVirtualKeyboardEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kTouchVirtualKeyboardEnabled, false); input_method::InputMethodSyncer::RegisterProfilePrefs(registry); @@ -330,13 +275,10 @@ prefs::kResolveTimezoneByGeolocation, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kCaptivePortalAuthenticationIgnoresProxy, true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kCaptivePortalAuthenticationIgnoresProxy, + true); - registry->RegisterBooleanPref( - prefs::kForceMaximizeOnFirstRun, false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kForceMaximizeOnFirstRun, false); } void Preferences::InitUserPrefs(PrefServiceSyncable* prefs) {
diff --git a/chrome/browser/chromeos/preferences_unittest.cc b/chrome/browser/chromeos/preferences_unittest.cc index b58fb5d2..60a4829 100644 --- a/chrome/browser/chromeos/preferences_unittest.cc +++ b/chrome/browser/chromeos/preferences_unittest.cc
@@ -193,6 +193,7 @@ prefs_->SetInputMethodListForTesting(); } + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<TestingProfileManager> profile_manager_; scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_; scoped_ptr<Preferences> prefs_; @@ -352,7 +353,6 @@ StringPrefMember preload_engines_syncable_; StringPrefMember enabled_extension_imes_; StringPrefMember enabled_extension_imes_syncable_; - content::TestBrowserThreadBundle thread_bundle_; private: DISALLOW_COPY_AND_ASSIGN(InputMethodPreferencesTest);
diff --git a/chrome/browser/chromeos/profiles/profile_list_chromeos_unittest.cc b/chrome/browser/chromeos/profiles/profile_list_chromeos_unittest.cc index 2d37fa45..3365bf4 100644 --- a/chrome/browser/chromeos/profiles/profile_list_chromeos_unittest.cc +++ b/chrome/browser/chromeos/profiles/profile_list_chromeos_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" using base::ASCIIToUTF16; @@ -106,6 +107,7 @@ int change_count() const { return mock_observer_->change_count(); } private: + content::TestBrowserThreadBundle thread_bundle_; TestingProfileManager manager_; scoped_ptr<MockObserver> mock_observer_; scoped_ptr<ScopedUserManagerEnabler> user_manager_enabler_;
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc index 5451f0d..56ff9d9 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -52,7 +52,7 @@ : local_state_(TestingBrowserProcess::GetGlobal()), user_data_dir_override_(chrome::DIR_USER_DATA) {} - virtual void SetUp() override { + void SetUp() override { DeviceSettingsTestBase::SetUp(); EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber()); @@ -64,9 +64,7 @@ Mock::VerifyAndClearExpectations(this); } - virtual void TearDown() override { - DeviceSettingsTestBase::TearDown(); - } + void TearDown() override { DeviceSettingsTestBase::TearDown(); } // Helper routine to enable/disable all reporting settings in policy. void SetReportingSettings(bool enable_reporting, int frequency) {
diff --git a/chrome/browser/chromeos/settings/session_manager_operation_unittest.cc b/chrome/browser/chromeos/settings/session_manager_operation_unittest.cc index 9eda36b..5a63d61e 100644 --- a/chrome/browser/chromeos/settings/session_manager_operation_unittest.cc +++ b/chrome/browser/chromeos/settings/session_manager_operation_unittest.cc
@@ -52,7 +52,7 @@ ->SetOwnerKeyUtilForTesting(owner_key_util_); } - virtual void SetUp() override { + void SetUp() override { policy_.payload().mutable_user_whitelist()->add_user_whitelist( "fake-whitelist"); policy_.Build();
diff --git a/chrome/browser/chromeos/system/device_disabling_manager_unittest.cc b/chrome/browser/chromeos/system/device_disabling_manager_unittest.cc index 771b719..d01d4dd 100644 --- a/chrome/browser/chromeos/system/device_disabling_manager_unittest.cc +++ b/chrome/browser/chromeos/system/device_disabling_manager_unittest.cc
@@ -136,6 +136,7 @@ TestingPrefServiceSimple local_state_; + content::TestBrowserThreadBundle thread_bundle_; base::RunLoop run_loop_; bool device_disabled_;
diff --git a/chrome/browser/component_updater/chrome_component_updater_configurator_unittest.cc b/chrome/browser/component_updater/chrome_component_updater_configurator_unittest.cc new file mode 100644 index 0000000..5a7589e --- /dev/null +++ b/chrome/browser/component_updater/chrome_component_updater_configurator_unittest.cc
@@ -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. + +#include <string> +#include <vector> + +#include "base/command_line.h" +#include "base/memory/ref_counted.h" +#include "chrome/browser/component_updater/chrome_component_updater_configurator.h" +#include "components/component_updater/component_updater_switches.h" +#include "components/update_client/configurator.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace component_updater { + +TEST(ChromeComponentUpdaterConfiguratorTest, TestDisablePings) { + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + cmdline->AppendSwitchASCII(switches::kComponentUpdater, "disable-pings"); + + const auto config(MakeChromeComponentUpdaterConfigurator(cmdline, NULL)); + + const std::vector<GURL> pingUrls = config->PingUrl(); + EXPECT_TRUE(pingUrls.empty()); +} + +TEST(ChromeComponentUpdaterConfiguratorTest, TestFastUpdate) { + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + cmdline->AppendSwitchASCII(switches::kComponentUpdater, "fast-update"); + + const auto config(MakeChromeComponentUpdaterConfigurator(cmdline, NULL)); + + ASSERT_EQ(1, config->InitialDelay()); +} + +TEST(ChromeComponentUpdaterConfiguratorTest, TestOverrideUrl) { + const char overrideUrl[] = "http://0.0.0.0/"; + + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + std::string val = "url-source"; + val.append("="); + val.append(overrideUrl); + cmdline->AppendSwitchASCII(switches::kComponentUpdater, val.c_str()); + + const auto config(MakeChromeComponentUpdaterConfigurator(cmdline, NULL)); + + const std::vector<GURL> urls = config->UpdateUrl(); + + ASSERT_EQ(1U, urls.size()); + ASSERT_EQ(overrideUrl, urls.at(0).possibly_invalid_spec()); +} + +TEST(ChromeComponentUpdaterConfiguratorTest, TestSwitchRequestParam) { + base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + cmdline->AppendSwitchASCII(switches::kComponentUpdater, "test-request"); + + const auto config(MakeChromeComponentUpdaterConfigurator(cmdline, NULL)); + + EXPECT_FALSE(config->ExtraRequestParams().empty()); +} + +} // namespace component_updater
diff --git a/chrome/browser/component_updater/cld_component_installer_unittest.cc b/chrome/browser/component_updater/cld_component_installer_unittest.cc new file mode 100644 index 0000000..fe1efcd9 --- /dev/null +++ b/chrome/browser/component_updater/cld_component_installer_unittest.cc
@@ -0,0 +1,134 @@ +// 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 <stdint.h> +#include <vector> + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "base/version.h" +#include "chrome/browser/component_updater/cld_component_installer.h" +#include "components/translate/content/browser/browser_cld_data_provider.h" +#include "components/translate/content/common/cld_data_source.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +using component_updater::CldComponentInstallerTraits; + +namespace { + +// This has to match what's in cld_component_installer.cc. +const base::FilePath::CharType kTestCldDataFileName[] = + FILE_PATH_LITERAL("cld2_data.bin"); + +} // namespace + +namespace component_updater { + +class CldComponentInstallerTest : public PlatformTest { + public: + CldComponentInstallerTest() {} + void SetUp() override { + PlatformTest::SetUp(); + translate::CldDataSource::DisableSanityChecksForTest(); + + // ScopedTempDir automatically does a recursive delete on the entire + // directory in its destructor, so no cleanup is required in TearDown. + // Note that all files created by this test case are created within the + // directory that is created here, so even though they are not explicitly + // created *as temp files*, they will still get cleaned up automagically. + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + + // The "latest CLD data file" is a static piece of information, and thus + // for correctness we empty it before each test. + CldComponentInstallerTraits::SetLatestCldDataFile(base::FilePath()); + base::FilePath path_now = + CldComponentInstallerTraits::GetLatestCldDataFile(); + ASSERT_TRUE(path_now.empty()); + } + + void TearDown() override { + // Restore sanity checks. + translate::CldDataSource::EnableSanityChecksForTest(); + } + + protected: + base::ScopedTempDir temp_dir_; + CldComponentInstallerTraits traits_; + + private: + DISALLOW_COPY_AND_ASSIGN(CldComponentInstallerTest); +}; + +TEST_F(CldComponentInstallerTest, SetLatestCldDataFile) { + const base::FilePath expected(FILE_PATH_LITERAL("test/foo.test")); + CldComponentInstallerTraits::SetLatestCldDataFile(expected); + base::FilePath result = CldComponentInstallerTraits::GetLatestCldDataFile(); + ASSERT_EQ(expected, result); +} + +TEST_F(CldComponentInstallerTest, VerifyInstallation) { + // All files are created within a ScopedTempDir, which deletes all + // children when its destructor is called (at the end of each test). + const base::DictionaryValue manifest; + ASSERT_FALSE(traits_.VerifyInstallation(manifest, temp_dir_.path())); + const base::FilePath data_file_dir = + temp_dir_.path() + .Append(FILE_PATH_LITERAL("_platform_specific")) + .Append(FILE_PATH_LITERAL("all")); + ASSERT_TRUE(base::CreateDirectory(data_file_dir)); + const base::FilePath data_file = data_file_dir.Append(kTestCldDataFileName); + const std::string test_data("fake cld2 data file content here :)"); + ASSERT_EQ(static_cast<int32>(test_data.length()), + base::WriteFile(data_file, test_data.c_str(), test_data.length())); + ASSERT_TRUE(traits_.VerifyInstallation(manifest, temp_dir_.path())); +} + +TEST_F(CldComponentInstallerTest, OnCustomInstall) { + const base::DictionaryValue manifest; + const base::FilePath install_dir; + // Sanity: shouldn't crash. + ASSERT_TRUE(traits_.OnCustomInstall(manifest, install_dir)); +} + +TEST_F(CldComponentInstallerTest, GetInstalledPath) { + const base::FilePath base_dir; + const base::FilePath result = + CldComponentInstallerTraits::GetInstalledPath(base_dir); + ASSERT_TRUE(EndsWith(result.value(), kTestCldDataFileName, true)); +} + +TEST_F(CldComponentInstallerTest, GetBaseDirectory) { + const base::FilePath result = traits_.GetBaseDirectory(); + ASSERT_FALSE(result.empty()); +} + +TEST_F(CldComponentInstallerTest, GetHash) { + std::vector<uint8_t> hash; + traits_.GetHash(&hash); + ASSERT_EQ(static_cast<size_t>(32), hash.size()); +} + +TEST_F(CldComponentInstallerTest, GetName) { + ASSERT_FALSE(traits_.GetName().empty()); +} + +TEST_F(CldComponentInstallerTest, ComponentReady) { + scoped_ptr<base::DictionaryValue> manifest; + const base::FilePath install_dir(FILE_PATH_LITERAL("/foo")); + const base::Version version("1.2.3.4"); + traits_.ComponentReady(version, install_dir, manifest.Pass()); + base::FilePath result = CldComponentInstallerTraits::GetLatestCldDataFile(); + ASSERT_TRUE( + StartsWith(result.AsUTF16Unsafe(), install_dir.AsUTF16Unsafe(), true)); + ASSERT_TRUE(EndsWith(result.value(), kTestCldDataFileName, true)); +} + +} // namespace component_updater
diff --git a/chrome/browser/component_updater/component_installers_unittest.cc b/chrome/browser/component_updater/component_installers_unittest.cc new file mode 100644 index 0000000..10c5834 --- /dev/null +++ b/chrome/browser/component_updater/component_installers_unittest.cc
@@ -0,0 +1,88 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/json/json_file_value_serializer.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "base/version.h" +#include "build/build_config.h" +#include "chrome/browser/component_updater/flash_component_installer.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/pepper_flash.h" +#include "content/public/test/test_browser_thread.h" +#include "ppapi/shared_impl/test_globals.h" + +#include "testing/gtest/include/gtest/gtest.h" + +using content::BrowserThread; + +namespace component_updater { + +namespace { +// File name of the Pepper Flash plugin on different platforms. +const base::FilePath::CharType kDataPath[] = +#if defined(OS_MACOSX) +#if defined(ARCH_CPU_X86) + FILE_PATH_LITERAL("components/flapper/mac"); +#elif defined(ARCH_CPU_X86_64) + FILE_PATH_LITERAL("components/flapper/mac_x64"); +#else + FILE_PATH_LITERAL("components/flapper/NONEXISTENT"); +#endif +#elif defined(OS_WIN) +#if defined(ARCH_CPU_X86) + FILE_PATH_LITERAL("components\\flapper\\windows"); +#elif defined(ARCH_CPU_X86_64) + FILE_PATH_LITERAL("components\\flapper\\windows_x64"); +#else + FILE_PATH_LITERAL("components\\flapper\\NONEXISTENT"); +#endif +#else // OS_LINUX, etc. +#if defined(ARCH_CPU_X86) + FILE_PATH_LITERAL("components/flapper/linux"); +#elif defined(ARCH_CPU_X86_64) + FILE_PATH_LITERAL("components/flapper/linux_x64"); +#else + FILE_PATH_LITERAL("components/flapper/NONEXISTENT"); +#endif +#endif +} // namespace + +// TODO(viettrungluu): Separate out into two separate tests; use a test fixture. +TEST(ComponentInstallerTest, PepperFlashCheck) { + base::MessageLoop message_loop; + content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); + + ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test; + ppapi::TestGlobals test_globals(per_thread_for_test); + ppapi::PpapiGlobals::SetPpapiGlobalsOnThreadForTest(&test_globals); + + // The test directory is chrome/test/data/components/flapper. + base::FilePath manifest; + PathService::Get(chrome::DIR_TEST_DATA, &manifest); + manifest = manifest.Append(kDataPath); + manifest = manifest.AppendASCII("manifest.json"); + + if (!base::PathExists(manifest)) { + LOG(WARNING) << "No test manifest available. Skipping."; + return; + } + + JSONFileValueDeserializer deserializer(manifest); + std::string error; + scoped_ptr<base::DictionaryValue> root(static_cast<base::DictionaryValue*>( + deserializer.Deserialize(NULL, &error))); + ASSERT_TRUE(root); + ASSERT_TRUE(root->IsType(base::Value::TYPE_DICTIONARY)); + + // This checks that the whole manifest is compatible. + Version version; + EXPECT_TRUE(chrome::CheckPepperFlashManifest(*root, &version)); + EXPECT_TRUE(version.IsValid()); +} + +} // namespace component_updater
diff --git a/chrome/browser/component_updater/component_updater_service_unittest.cc b/chrome/browser/component_updater/component_updater_service_unittest.cc new file mode 100644 index 0000000..49d86bd --- /dev/null +++ b/chrome/browser/component_updater/component_updater_service_unittest.cc
@@ -0,0 +1,1398 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/component_updater/component_updater_service_unittest.h" + +#include <vector> + +#include "base/files/file_util.h" +#include "base/memory/scoped_ptr.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/values.h" +#include "chrome/browser/component_updater/component_updater_resource_throttle.h" +#include "chrome/common/chrome_paths.h" +#include "components/update_client/test_configurator.h" +#include "components/update_client/test_installer.h" +#include "components/update_client/url_request_post_interceptor.h" +#include "components/update_client/utils.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/resource_controller.h" +#include "content/public/browser/resource_request_info.h" +#include "content/public/browser/resource_throttle.h" +#include "libxml/globals.h" +#include "net/base/upload_bytes_element_reader.h" +#include "net/url_request/test_url_request_interceptor.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_test_util.h" +#include "url/gurl.h" + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::InSequence; +using ::testing::Mock; + +using content::BrowserThread; + +using std::string; + +using update_client::CrxComponent; +using update_client::PartialMatch; +using update_client::InterceptorFactory; +using update_client::TestConfigurator; +using update_client::TestInstaller; +using update_client::URLRequestPostInterceptor; +using update_client::VersionedTestInstaller; + +using update_client::abag_hash; +using update_client::ihfo_hash; +using update_client::jebg_hash; + +using Events = component_updater::ServiceObserver::Events; +using Status = component_updater::ComponentUpdateService::Status; + +namespace component_updater { + +MockServiceObserver::MockServiceObserver() { +} + +MockServiceObserver::~MockServiceObserver() { +} + +ComponentUpdaterTest::ComponentUpdaterTest() + : post_interceptor_(NULL), + thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), + test_config_(NULL) { + // The component updater instance under test. + test_config_ = new TestConfigurator( + BrowserThread::GetBlockingPool() + ->GetSequencedTaskRunnerWithShutdownBehavior( + BrowserThread::GetBlockingPool()->GetSequenceToken(), + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); + component_updater_.reset( + ComponentUpdateServiceFactory(test_config_).release()); +} + +ComponentUpdaterTest::~ComponentUpdaterTest() { +} + +void ComponentUpdaterTest::SetUp() { + get_interceptor_.reset(new GetInterceptor( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); + interceptor_factory_.reset(new InterceptorFactory( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); + post_interceptor_ = interceptor_factory_->CreateInterceptor(); + EXPECT_TRUE(post_interceptor_); +} + +void ComponentUpdaterTest::TearDown() { + interceptor_factory_.reset(); + get_interceptor_.reset(); + xmlCleanupGlobals(); +} + +ComponentUpdateService* ComponentUpdaterTest::component_updater() { + return component_updater_.get(); +} + +// Makes the full path to a component updater test file. +const base::FilePath ComponentUpdaterTest::test_file(const char* file) { + base::FilePath path; + PathService::Get(base::DIR_SOURCE_ROOT, &path); + return path.AppendASCII("components") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("update_client") + .AppendASCII(file); +} + +scoped_refptr<update_client::TestConfigurator> +ComponentUpdaterTest::test_configurator() { + return test_config_; +} + +ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent( + CrxComponent* com, + TestComponents component, + const Version& version, + const scoped_refptr<TestInstaller>& installer) { + switch (component) { + case kTestComponent_abag: { + com->name = "test_abag"; + com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); + break; + } + case kTestComponent_jebg: { + com->name = "test_jebg"; + com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + break; + } + case kTestComponent_ihfo: { + com->name = "test_ihfo"; + com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); + break; + } + } + com->version = version; + com->installer = installer; + return component_updater_->RegisterComponent(*com); +} + +void ComponentUpdaterTest::RunThreads() { + base::RunLoop runloop; + test_configurator()->SetQuitClosure(runloop.QuitClosure()); + runloop.Run(); + + // Since some tests need to drain currently enqueued tasks such as network + // intercepts on the IO thread, run the threads until they are + // idle. The component updater service won't loop again until the loop count + // is set and the service is started. + RunThreadsUntilIdle(); +} + +void ComponentUpdaterTest::RunThreadsUntilIdle() { + base::RunLoop().RunUntilIdle(); +} + +ComponentUpdateService::Status OnDemandTester::OnDemand( + ComponentUpdateService* cus, + const std::string& component_id) { + return cus->GetOnDemandUpdater().OnDemandUpdate(component_id); +} + +// Verify that our test fixture work and the component updater can +// be created and destroyed with no side effects. +TEST_F(ComponentUpdaterTest, VerifyFixture) { + EXPECT_TRUE(component_updater() != NULL); +} + +// Verify that the component updater can be caught in a quick +// start-shutdown situation. Failure of this test will be a crash. +TEST_F(ComponentUpdaterTest, StartStop) { + component_updater()->Start(); + RunThreadsUntilIdle(); + component_updater()->Stop(); +} + +// Verify that when the server has no updates, we go back to sleep and +// the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications +// are generated. No pings are sent. +TEST_F(ComponentUpdaterTest, CheckCrxSleep) { + MockServiceObserver observer; + + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(2); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(2); + + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + scoped_refptr<TestInstaller> installer(new TestInstaller); + CrxComponent com; + component_updater()->AddObserver(&observer); + EXPECT_EQ(Status::kOk, RegisterComponent(&com, kTestComponent_abag, + Version("1.1"), installer)); + + // We loop twice, but there are no updates so we expect two sleep messages. + test_configurator()->SetLoopCount(2); + component_updater()->Start(); + RunThreads(); + + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(0, installer->install_count()); + + // Expect to see the two update check requests and no other requests, + // including pings. + EXPECT_EQ(2, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(2, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[1].find( + "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + + component_updater()->Stop(); + + // Loop twice again but this case we simulate a server error by returning + // an empty file. Expect the behavior of the service to be the same as before. + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(2); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(2); + + post_interceptor_->Reset(); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty"))); + + test_configurator()->SetLoopCount(2); + component_updater()->Start(); + RunThreads(); + + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(0, installer->install_count()); + + EXPECT_EQ(2, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(2, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[1].find( + "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + + component_updater()->Stop(); +} + +// Verify that we can check for updates and install one component. Besides +// the notifications above COMPONENT_UPDATE_FOUND and COMPONENT_UPDATE_READY +// should have been fired. We do two loops so the second time around there +// should be nothing left to do. +// We also check that the following network requests are issued: +// 1- update check +// 2- download crx +// 3- ping +// 4- second update check. +TEST_F(ComponentUpdaterTest, InstallCrx) { + MockServiceObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(AnyNumber()); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + get_interceptor_->SetResponse( + GURL(expected_crx_url), + test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); + + component_updater()->AddObserver(&observer); + + scoped_refptr<TestInstaller> installer1(new TestInstaller); + CrxComponent com1; + RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), installer1); + scoped_refptr<TestInstaller> installer2(new TestInstaller); + CrxComponent com2; + RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), installer2); + + test_configurator()->SetLoopCount(2); + component_updater()->Start(); + RunThreads(); + + EXPECT_EQ(0, installer1->error()); + EXPECT_EQ(1, installer1->install_count()); + EXPECT_EQ(0, installer2->error()); + EXPECT_EQ(0, installer2->install_count()); + + // Expect three request in total: two update checks and one ping. + EXPECT_EQ(3, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(3, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + // Expect one component download. + EXPECT_EQ(1, get_interceptor_->GetHitCount()); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " + "version=\"0.9\" nextversion=\"1.0\">" + "<event eventtype=\"3\" eventresult=\"1\"/>")) + << post_interceptor_->GetRequestsAsString(); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[2].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">" + "<updatecheck /></app>")); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[2].find( + "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + + // Test the protocol version is correct and the extra request attributes + // are included in the request. + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( + "request protocol=\"3.0\" extra=\"foo\"")) + << post_interceptor_->GetRequestsAsString(); + + // Tokenize the request string to look for specific attributes, which + // are important for backward compatibility with the version v2 of the update + // protocol. In this case, inspect the <request>, which is the first element + // after the xml declaration of the update request body. + // Expect to find the |os|, |arch|, |prodchannel|, and |prodversion| + // attributes: + // <?xml version="1.0" encoding="UTF-8"?> + // <request... os=... arch=... prodchannel=... prodversion=...> + // ... + // </request> + const std::string update_request(post_interceptor_->GetRequests()[0]); + std::vector<base::StringPiece> elements; + Tokenize(update_request, "<>", &elements); + EXPECT_NE(string::npos, elements[1].find(" os=")); + EXPECT_NE(string::npos, elements[1].find(" arch=")); + EXPECT_NE(string::npos, elements[1].find(" prodchannel=")); + EXPECT_NE(string::npos, elements[1].find(" prodversion=")); + + // Look for additional attributes of the request, such as |version|, + // |requestid|, |lang|, and |nacl_arch|. + EXPECT_NE(string::npos, elements[1].find(" version=")); + EXPECT_NE(string::npos, elements[1].find(" requestid=")); + EXPECT_NE(string::npos, elements[1].find(" lang=")); + EXPECT_NE(string::npos, elements[1].find(" nacl_arch=")); + + component_updater()->Stop(); +} + +// This test checks that the "prodversionmin" value is handled correctly. In +// particular there should not be an install because the minimum product +// version is much higher than of chrome. +TEST_F(ComponentUpdaterTest, ProdVersionCheck) { + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_2.xml"))); + + get_interceptor_->SetResponse( + GURL(expected_crx_url), + test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); + + scoped_refptr<TestInstaller> installer(new TestInstaller); + CrxComponent com; + RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), installer); + + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + RunThreads(); + + // Expect one update check and no ping. + EXPECT_EQ(1, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + // Expect no download to occur. + EXPECT_EQ(0, get_interceptor_->GetHitCount()); + + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(0, installer->install_count()); + + component_updater()->Stop(); +} + +// Test that a update check due to an on demand call can cause installs. +// Here is the timeline: +// - First loop: we return a reply that indicates no update, so +// nothing happens. +// - We make an on demand call. +// - This triggers a second loop, which has a reply that triggers an install. +#if defined(OS_LINUX) +// http://crbug.com/396488 +#define MAYBE_OnDemandUpdate DISABLED_OnDemandUpdate +#else +#define MAYBE_OnDemandUpdate OnDemandUpdate +#endif +TEST_F(ComponentUpdaterTest, MAYBE_OnDemandUpdate) { + MockServiceObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(AnyNumber()); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty"))); + + get_interceptor_->SetResponse( + GURL(expected_crx_url), + test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); + + component_updater()->AddObserver(&observer); + + scoped_refptr<TestInstaller> installer1(new TestInstaller); + CrxComponent com1; + RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), installer1); + scoped_refptr<TestInstaller> installer2(new TestInstaller); + CrxComponent com2; + RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), installer2); + + // No update normally. + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + RunThreads(); + component_updater()->Stop(); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + EXPECT_EQ(0, get_interceptor_->GetHitCount()); + + // Update after an on-demand check is issued. + post_interceptor_->Reset(); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + + EXPECT_EQ(Status::kOk, OnDemandTester::OnDemand(component_updater(), + GetCrxComponentID(com2))); + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + RunThreads(); + + EXPECT_EQ(0, installer1->error()); + EXPECT_EQ(0, installer1->install_count()); + EXPECT_EQ(0, installer2->error()); + EXPECT_EQ(1, installer2->install_count()); + + EXPECT_EQ(2, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(2, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + EXPECT_EQ(1, get_interceptor_->GetHitCount()); + + // Expect the update check to contain an "ondemand" request for the + // second component (com2) and a normal request for the other component. + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( + "<app appid=\"abagagagagagagagagagagagagagagag\" " + "version=\"2.2\"><updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " + "version=\"0.9\" installsource=\"ondemand\"><updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " + "version=\"0.9\" nextversion=\"1.0\">" + "<event eventtype=\"3\" eventresult=\"1\"/>")) + << post_interceptor_->GetRequestsAsString(); + + // Also check what happens if previous check too soon. It works, since this + // direct OnDemand call does not implement a cooldown. + test_configurator()->SetOnDemandTime(60 * 60); + EXPECT_EQ(Status::kOk, OnDemandTester::OnDemand(component_updater(), + GetCrxComponentID(com2))); + // Okay, now reset to 0 for the other tests. + test_configurator()->SetOnDemandTime(0); + component_updater()->Stop(); + + // Test a few error cases. NOTE: We don't have callbacks for + // when the updates failed yet. + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer)); + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + // No update: error from no server response + post_interceptor_->Reset(); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty"))); + + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + EXPECT_EQ(Status::kOk, OnDemandTester::OnDemand(component_updater(), + GetCrxComponentID(com2))); + RunThreads(); + component_updater()->Stop(); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + // No update: already updated to 1.0 so nothing new + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer)); + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + post_interceptor_->Reset(); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + EXPECT_EQ(Status::kOk, OnDemandTester::OnDemand(component_updater(), + GetCrxComponentID(com2))); + RunThreads(); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + component_updater()->Stop(); +} + +// Verify that a previously registered component can get re-registered +// with a different version. +TEST_F(ComponentUpdaterTest, CheckReRegistration) { + MockServiceObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "jebgalgnebhfojomionfpkfelancnnkf")) + .Times(AnyNumber()); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + get_interceptor_->SetResponse( + GURL(expected_crx_url), + test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); + + component_updater()->AddObserver(&observer); + + scoped_refptr<TestInstaller> installer1(new TestInstaller); + CrxComponent com1; + RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), installer1); + scoped_refptr<TestInstaller> installer2(new TestInstaller); + CrxComponent com2; + RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), installer2); + + // Loop twice to issue two checks: (1) with original 0.9 version, update to + // 1.0, and do the second check (2) with the updated 1.0 version. + test_configurator()->SetLoopCount(2); + component_updater()->Start(); + RunThreads(); + + EXPECT_EQ(0, installer1->error()); + EXPECT_EQ(1, installer1->install_count()); + EXPECT_EQ(0, installer2->error()); + EXPECT_EQ(0, installer2->install_count()); + + EXPECT_EQ(3, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, get_interceptor_->GetHitCount()); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " + "version=\"0.9\" nextversion=\"1.0\">" + "<event eventtype=\"3\" eventresult=\"1\"/>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[2].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + + component_updater()->Stop(); + + // Now re-register, pretending to be an even newer version (2.2) + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer)); + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + post_interceptor_->Reset(); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + scoped_refptr<TestInstaller> installer3(new TestInstaller); + EXPECT_EQ(Status::kReplaced, RegisterComponent(&com1, kTestComponent_jebg, + Version("2.2"), installer3)); + + // Loop once just to notice the check happening with the re-register version. + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + RunThreads(); + + // We created a new installer, so the counts go back to 0. + EXPECT_EQ(0, installer3->error()); + EXPECT_EQ(0, installer3->install_count()); + EXPECT_EQ(0, installer2->error()); + EXPECT_EQ(0, installer2->install_count()); + + // One update check and no additional pings are expected. + EXPECT_EQ(1, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"2.2\">" + "<updatecheck /></app>")); + + component_updater()->Stop(); +} + +// Verify that we can download and install a component and a differential +// update to that component. We do three loops; the final loop should do +// nothing. +// We also check that exactly 5 non-ping network requests are issued: +// 1- update check (response: v1 available) +// 2- download crx (v1) +// 3- update check (response: v2 available) +// 4- download differential crx (v1 to v2) +// 5- update check (response: no further update available) +// There should be two pings, one for each update. The second will bear a +// diffresult=1, while the first will not. +TEST_F(ComponentUpdaterTest, DifferentialUpdate) { + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_diff_reply_1.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_diff_reply_2.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_diff_reply_3.xml"))); + + get_interceptor_->SetResponse( + GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), + test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); + get_interceptor_->SetResponse( + GURL( + "http://localhost/download/" + "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), + test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx")); + + scoped_refptr<TestInstaller> installer(new VersionedTestInstaller); + CrxComponent com; + RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), installer); + + test_configurator()->SetLoopCount(3); + component_updater()->Start(); + RunThreads(); + + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(2, installer->install_count()); + + EXPECT_EQ(5, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(5, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(2, get_interceptor_->GetHitCount()); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, + post_interceptor_->GetRequests()[1].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " + "version=\"0.0\" nextversion=\"1.0\">" + "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[2].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" + "<updatecheck /><packages><package fp=\"1\"/></packages></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, + post_interceptor_->GetRequests()[3].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " + "version=\"1.0\" nextversion=\"2.0\">" + "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"1\" " + "previousfp=\"1\" nextfp=\"22\"/>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[4].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" + "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) + << post_interceptor_->GetRequestsAsString(); + component_updater()->Stop(); +} + +// Verify that component installation falls back to downloading and installing +// a full update if the differential update fails (in this case, because the +// installer does not know about the existing files). We do two loops; the final +// loop should do nothing. +// We also check that exactly 4 non-ping network requests are issued: +// 1- update check (loop 1) +// 2- download differential crx +// 3- download full crx +// 4- update check (loop 2 - no update available) +// There should be one ping for the first attempted update. +// This test is flaky on Android. crbug.com/329883 +#if defined(OS_ANDROID) +#define MAYBE_DifferentialUpdateFails DISABLED_DifferentialUpdateFails +#else +#define MAYBE_DifferentialUpdateFails DifferentialUpdateFails +#endif +TEST_F(ComponentUpdaterTest, MAYBE_DifferentialUpdateFails) { + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_diff_reply_2.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_diff_reply_3.xml"))); + + get_interceptor_->SetResponse( + GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), + test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); + get_interceptor_->SetResponse( + GURL( + "http://localhost/download/" + "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), + test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx")); + get_interceptor_->SetResponse( + GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), + test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx")); + + scoped_refptr<TestInstaller> installer(new TestInstaller); + CrxComponent com; + RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), installer); + + test_configurator()->SetLoopCount(2); + component_updater()->Start(); + RunThreads(); + + // A failed differential update does not count as a failed install. + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(1, installer->install_count()); + + EXPECT_EQ(3, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(3, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(2, get_interceptor_->GetHitCount()); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, + post_interceptor_->GetRequests()[1].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " + "version=\"1.0\" nextversion=\"2.0\">" + "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"0\" " + "differrorcat=\"2\" differrorcode=\"16\" nextfp=\"22\"/>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[2].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" + "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) + << post_interceptor_->GetRequestsAsString(); + + component_updater()->Stop(); +} + +// Test is flakey on Android bots. See crbug.com/331420. +#if defined(OS_ANDROID) +#define MAYBE_CheckFailedInstallPing DISABLED_CheckFailedInstallPing +#else +#define MAYBE_CheckFailedInstallPing CheckFailedInstallPing +#endif +// Verify that a failed installation causes an install failure ping. +TEST_F(ComponentUpdaterTest, MAYBE_CheckFailedInstallPing) { + // This test installer reports installation failure. + class FailingTestInstaller : public TestInstaller { + bool Install(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) override { + ++install_count_; + base::DeleteFile(unpack_path, true); + return false; + } + + private: + ~FailingTestInstaller() override {} + }; + scoped_refptr<FailingTestInstaller> installer(new FailingTestInstaller); + + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + get_interceptor_->SetResponse( + GURL(expected_crx_url), + test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); + + // Start with 0.9, and attempt update to 1.0. + // Loop twice to issue two checks: (1) with original 0.9 version + // and (2), which should retry with 0.9. + CrxComponent com; + RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), installer); + + test_configurator()->SetLoopCount(2); + component_updater()->Start(); + RunThreads(); + + EXPECT_EQ(4, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(2, get_interceptor_->GetHitCount()); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[1].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " + "version=\"0.9\" nextversion=\"1.0\">" + "<event eventtype=\"3\" eventresult=\"0\" " + "errorcat=\"3\" errorcode=\"9\"/>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[2].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " + "version=\"0.9\" nextversion=\"1.0\">" + "<event eventtype=\"3\" eventresult=\"0\" " + "errorcat=\"3\" errorcode=\"9\"/>")) + << post_interceptor_->GetRequestsAsString(); + + // Loop once more, but expect no ping because a noupdate response is issued. + // This is necessary to clear out the fire-and-forget ping from the previous + // iteration. + post_interceptor_->Reset(); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_reply_noupdate.xml"))); + + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + RunThreads(); + + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(2, installer->install_count()); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + + component_updater()->Stop(); +} + +// Verify that we successfully propagate a patcher error. +// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect +// patching instruction that should fail. +TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) { + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_diff_reply_1.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_diff_reply_2.xml"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), + test_file("updatecheck_diff_reply_3.xml"))); + + get_interceptor_->SetResponse( + GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), + test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); + // This intercept returns a different file than what is specified in the + // update check response and requested in the download. The file that is + // actually dowloaded contains a patching error, an therefore, an error + // is injected at the time of patching. + get_interceptor_->SetResponse( + GURL( + "http://localhost/download/" + "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), + test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx")); + get_interceptor_->SetResponse( + GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), + test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx")); + + scoped_refptr<TestInstaller> installer(new VersionedTestInstaller); + CrxComponent com; + RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), installer); + + test_configurator()->SetLoopCount(3); + component_updater()->Start(); + RunThreads(); + component_updater()->Stop(); + + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(2, installer->install_count()); + + EXPECT_EQ(5, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(5, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(3, get_interceptor_->GetHitCount()); + + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">" + "<updatecheck /></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, + post_interceptor_->GetRequests()[1].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " + "version=\"0.0\" nextversion=\"1.0\">" + "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[2].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" + "<updatecheck /><packages><package fp=\"1\"/></packages></app>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[3].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " + "version=\"1.0\" nextversion=\"2.0\">" + "<event eventtype=\"3\" eventresult=\"1\" " + "diffresult=\"0\" differrorcat=\"2\" " + "differrorcode=\"14\" diffextracode1=\"305\" " + "previousfp=\"1\" nextfp=\"22\"/>")) + << post_interceptor_->GetRequestsAsString(); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[4].find( + "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" + "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) + << post_interceptor_->GetRequestsAsString(); +} + +class TestResourceController : public content::ResourceController { + public: + virtual void SetThrottle(content::ResourceThrottle* throttle) {} +}; + +content::ResourceThrottle* RequestTestResourceThrottle( + ComponentUpdateService* cus, + TestResourceController* controller, + const char* crx_id) { + net::TestURLRequestContext context; + scoped_ptr<net::URLRequest> url_request(context.CreateRequest( + GURL("http://foo.example.com/thing.bin"), net::DEFAULT_PRIORITY, NULL)); + + content::ResourceThrottle* rt = GetOnDemandResourceThrottle(cus, crx_id); + rt->set_controller_for_testing(controller); + controller->SetThrottle(rt); + return rt; +} + +void RequestAndDeleteResourceThrottle(ComponentUpdateService* cus, + const char* crx_id) { + // By requesting a throttle and deleting it immediately we ensure that we + // hit the case where the component updater tries to use the weak + // pointer to a dead Resource throttle. + class NoCallResourceController : public TestResourceController { + public: + ~NoCallResourceController() override {} + void Cancel() override { CHECK(false); } + void CancelAndIgnore() override { CHECK(false); } + void CancelWithError(int error_code) override { CHECK(false); } + void Resume() override { CHECK(false); } + } controller; + + delete RequestTestResourceThrottle(cus, &controller, crx_id); +} + +TEST_F(ComponentUpdaterTest, ResourceThrottleDeletedNoUpdate) { + MockServiceObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + scoped_refptr<TestInstaller> installer(new TestInstaller); + CrxComponent com; + component_updater()->AddObserver(&observer); + EXPECT_EQ(Status::kOk, RegisterComponent(&com, kTestComponent_abag, + Version("1.1"), installer)); + // The following two calls ensure that we don't do an update check via the + // timer, so the only update check should be the on-demand one. + test_configurator()->SetInitialDelay(1000000); + test_configurator()->SetRecheckTime(1000000); + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + + RunThreadsUntilIdle(); + + EXPECT_EQ(0, post_interceptor_->GetHitCount()); + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&RequestAndDeleteResourceThrottle, component_updater(), + "abagagagagagagagagagagagagagagag")); + + RunThreads(); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()); + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(0, installer->install_count()); + + component_updater()->Stop(); +} + +class CancelResourceController : public TestResourceController { + public: + CancelResourceController() : throttle_(NULL), resume_called_(0) {} + ~CancelResourceController() override { + // Check that the throttle has been resumed by the time we + // exit the test. + CHECK_EQ(1, resume_called_); + delete throttle_; + } + void Cancel() override { CHECK(false); } + void CancelAndIgnore() override { CHECK(false); } + void CancelWithError(int error_code) override { CHECK(false); } + void Resume() override { + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&CancelResourceController::ResumeCalled, + base::Unretained(this))); + } + void SetThrottle(content::ResourceThrottle* throttle) override { + throttle_ = throttle; + bool defer = false; + // Initially the throttle is blocked. The CUS needs to run a + // task on the UI thread to decide if it should unblock. + throttle_->WillStartRequest(&defer); + CHECK(defer); + } + + private: + void ResumeCalled() { ++resume_called_; } + + content::ResourceThrottle* throttle_; + int resume_called_; +}; + +// Tests the on-demand update with resource throttle, including the +// cooldown interval between calls. +TEST_F(ComponentUpdaterTest, ResourceThrottleLiveNoUpdate) { + MockServiceObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + } + + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + scoped_refptr<TestInstaller> installer(new TestInstaller); + CrxComponent com; + component_updater()->AddObserver(&observer); + EXPECT_EQ(Status::kOk, RegisterComponent(&com, kTestComponent_abag, + Version("1.1"), installer)); + // The following two calls ensure that we don't do an update check via the + // timer, so the only update check should be the on-demand one. + test_configurator()->SetInitialDelay(1000000); + test_configurator()->SetRecheckTime(1000000); + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + + RunThreadsUntilIdle(); + + EXPECT_EQ(0, post_interceptor_->GetHitCount()); + + { + // First on-demand update check is expected to succeeded. + CancelResourceController controller; + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(base::IgnoreResult(&RequestTestResourceThrottle), + component_updater(), &controller, + "abagagagagagagagagagagagagagagag")); + + RunThreads(); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()); + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(0, installer->install_count()); + + component_updater()->Stop(); + } + + { + // Second on-demand update check is expected to succeed as well, since there + // is no cooldown interval between calls, due to calling SetOnDemandTime. + test_configurator()->SetOnDemandTime(0); + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + + CancelResourceController controller; + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(base::IgnoreResult(&RequestTestResourceThrottle), + component_updater(), &controller, + "abagagagagagagagagagagagagagagag")); + + RunThreads(); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()); + EXPECT_EQ(0, installer->error()); + EXPECT_EQ(0, installer->install_count()); + + component_updater()->Stop(); + } + + { + // This on-demand call is expected not to trigger a component update check. + test_configurator()->SetOnDemandTime(1000000); + component_updater()->Start(); + + CancelResourceController controller; + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(base::IgnoreResult(&RequestTestResourceThrottle), + component_updater(), &controller, + "abagagagagagagagagagagagagagagag")); + RunThreadsUntilIdle(); + } +} + +// Tests adding and removing observers. +TEST_F(ComponentUpdaterTest, Observer) { + MockServiceObserver observer1, observer2; + + // Expect that two observers see the events. + { + InSequence seq; + EXPECT_CALL(observer1, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer1, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")) + .Times(1); + EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")) + .Times(1); + EXPECT_CALL(observer1, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + component_updater()->AddObserver(&observer1); + component_updater()->AddObserver(&observer2); + + scoped_refptr<TestInstaller> installer(new TestInstaller); + CrxComponent com; + EXPECT_EQ(Status::kOk, RegisterComponent(&com, kTestComponent_abag, + Version("1.1"), installer)); + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + RunThreads(); + + // After removing the first observer, it's only the second observer that + // gets the events. + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); + { + InSequence seq; + EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) + .Times(1); + EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")) + .Times(1); + EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) + .Times(1); + } + + component_updater()->RemoveObserver(&observer1); + + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + RunThreads(); + + // Both observers are removed and no one gets the events. + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); + EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); + component_updater()->RemoveObserver(&observer2); + + test_configurator()->SetLoopCount(1); + component_updater()->Start(); + RunThreads(); + + component_updater()->Stop(); +} + +} // namespace component_updater
diff --git a/chrome/browser/component_updater/component_updater_service_unittest.h b/chrome/browser/component_updater/component_updater_service_unittest.h new file mode 100644 index 0000000..e0d1c41 --- /dev/null +++ b/chrome/browser/component_updater/component_updater_service_unittest.h
@@ -0,0 +1,102 @@ +// Copyright 2013 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 CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UPDATER_SERVICE_UNITTEST_H_ +#define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UPDATER_SERVICE_UNITTEST_H_ + +#include <string> + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "components/component_updater/component_updater_service.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { +class LocalHostTestURLRequestInterceptor; +} + +namespace update_client { +struct CrxComponent; +class InterceptorFactory; +class TestConfigurator; +class TestInstaller; +class URLRequestPostInterceptor; +} + +namespace component_updater { + +// Intercepts HTTP GET requests sent to "localhost". +typedef net::LocalHostTestURLRequestInterceptor GetInterceptor; + +class ComponentUpdaterTest : public testing::Test { + public: + enum TestComponents { + kTestComponent_abag, + kTestComponent_jebg, + kTestComponent_ihfo, + }; + + ComponentUpdaterTest(); + + ~ComponentUpdaterTest() override; + + void SetUp() override; + + void TearDown() override; + + ComponentUpdateService* component_updater(); + + // Makes the full path to a component updater test file. + const base::FilePath test_file(const char* file); + + scoped_refptr<update_client::TestConfigurator> test_configurator(); + + ComponentUpdateService::Status RegisterComponent( + update_client::CrxComponent* com, + TestComponents component, + const Version& version, + const scoped_refptr<update_client::TestInstaller>& installer); + + protected: + void RunThreads(); + void RunThreadsUntilIdle(); + + scoped_ptr<update_client::InterceptorFactory> interceptor_factory_; + + // Owned by the factory. + update_client::URLRequestPostInterceptor* post_interceptor_; + + scoped_ptr<GetInterceptor> get_interceptor_; + + private: + content::TestBrowserThreadBundle thread_bundle_; + scoped_refptr<update_client::TestConfigurator> test_config_; + scoped_ptr<ComponentUpdateService> component_updater_; +}; + +const char expected_crx_url[] = + "http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"; + +class MockServiceObserver : public ServiceObserver { + public: + MockServiceObserver(); + ~MockServiceObserver(); + MOCK_METHOD2(OnEvent, void(Events event, const std::string&)); +}; + +class OnDemandTester { + public: + static ComponentUpdateService::Status OnDemand( + ComponentUpdateService* cus, + const std::string& component_id); +}; + +} // namespace component_updater + +#endif // CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_UPDATER_SERVICE_UNITTEST_H_
diff --git a/chrome/browser/component_updater/pnacl/OWNERS b/chrome/browser/component_updater/pnacl/OWNERS deleted file mode 100644 index 1891ea9..0000000 --- a/chrome/browser/component_updater/pnacl/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -dschuff@chromium.org -jvoung@chromium.org -sehr@chromium.org
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc b/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc deleted file mode 100644 index 84e59a57..0000000 --- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.cc +++ /dev/null
@@ -1,388 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h" - -#include <stdint.h> -#include <string> -#include <vector> - -#include "base/atomicops.h" -#include "base/base_paths.h" -#include "base/bind.h" -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/files/file_enumerator.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/json/json_file_value_serializer.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "base/strings/string_util.h" -#include "base/values.h" -#include "base/version.h" -#include "base/win/windows_version.h" -#include "build/build_config.h" -#include "chrome/browser/browser_process.h" -#include "chrome/common/chrome_paths.h" -#include "components/component_updater/component_updater_service.h" -#include "components/nacl/common/nacl_switches.h" -#include "components/update_client/update_query_params.h" -#include "content/public/browser/browser_thread.h" - -using content::BrowserThread; -using update_client::CrxComponent; -using update_client::UpdateQueryParams; - -namespace component_updater { - -namespace { - -// Name of the Pnacl component specified in the manifest. -const char kPnaclManifestName[] = "PNaCl Translator"; - -// Sanitize characters from Pnacl Arch value so that they can be used -// in path names. This should only be characters in the set: [a-z0-9_]. -// Keep in sync with chrome/browser/nacl_host/nacl_file_host. -std::string SanitizeForPath(const std::string& input) { - std::string result; - base::ReplaceChars(input, "-", "_", &result); - return result; -} - -// Set the component's hash to the multi-CRX PNaCl package. -void SetPnaclHash(CrxComponent* component) { - static const uint8_t sha256_hash[32] = { - // This corresponds to AppID: hnimpnehoodheedghdeeijklkeaacbdc - 0x7d, 0x8c, 0xfd, 0x47, 0xee, 0x37, 0x44, 0x36, - 0x73, 0x44, 0x89, 0xab, 0xa4, 0x00, 0x21, 0x32, - 0x4a, 0x06, 0x06, 0xf1, 0x51, 0x3c, 0x51, 0xba, - 0x31, 0x2f, 0xbc, 0xb3, 0x99, 0x07, 0xdc, 0x9c - }; - - component->pk_hash.assign(sha256_hash, &sha256_hash[arraysize(sha256_hash)]); -} - -// If we don't have Pnacl installed, this is the version we claim. -const char kNullVersion[] = "0.0.0.0"; -const char kMinPnaclVersion[] = "0.2.0.86"; - -// Initially say that we do not need OnDemand updates. This should be -// updated by CheckVersionCompatiblity(), before doing any URLRequests -// that depend on PNaCl. -volatile base::subtle::Atomic32 needs_on_demand_update = 0; - -void CheckVersionCompatiblity(const base::Version& current_version) { - // Using NoBarrier, since needs_on_demand_update is standalone and does - // not have other associated data. - base::subtle::NoBarrier_Store(&needs_on_demand_update, - current_version.IsOlderThan(kMinPnaclVersion)); -} - -// PNaCl is packaged as a multi-CRX. This returns the platform-specific -// subdirectory that is part of that multi-CRX. -base::FilePath GetPlatformDir(const base::FilePath& base_path) { - std::string arch = SanitizeForPath(UpdateQueryParams::GetNaclArch()); - return base_path.AppendASCII("_platform_specific").AppendASCII(arch); -} - -// Tell the rest of the world where to find the platform-specific PNaCl files. -void OverrideDirPnaclComponent(const base::FilePath& base_path) { - PathService::Override(chrome::DIR_PNACL_COMPONENT, GetPlatformDir(base_path)); -} - -bool GetLatestPnaclDirectory(const scoped_refptr<PnaclComponentInstaller>& pci, - base::FilePath* latest_dir, - Version* latest_version, - std::vector<base::FilePath>* older_dirs) { - // Enumerate all versions starting from the base directory. - base::FilePath base_dir = pci->GetPnaclBaseDirectory(); - bool found = false; - base::FileEnumerator file_enumerator( - base_dir, false, base::FileEnumerator::DIRECTORIES); - for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); - path = file_enumerator.Next()) { - Version version(path.BaseName().MaybeAsASCII()); - if (!version.IsValid()) - continue; - if (found) { - if (version.CompareTo(*latest_version) > 0) { - older_dirs->push_back(*latest_dir); - *latest_dir = path; - *latest_version = version; - } else { - older_dirs->push_back(path); - } - } else { - *latest_version = version; - *latest_dir = path; - found = true; - } - } - return found; -} - -// Read a manifest file in. -base::DictionaryValue* ReadJSONManifest(const base::FilePath& manifest_path) { - JSONFileValueDeserializer deserializer(manifest_path); - std::string error; - scoped_ptr<base::Value> root(deserializer.Deserialize(NULL, &error)); - if (!root.get()) - return NULL; - if (!root->IsType(base::Value::TYPE_DICTIONARY)) - return NULL; - return static_cast<base::DictionaryValue*>(root.release()); -} - -// Read the PNaCl specific manifest. -base::DictionaryValue* ReadPnaclManifest(const base::FilePath& unpack_path) { - base::FilePath manifest_path = - GetPlatformDir(unpack_path).AppendASCII("pnacl_public_pnacl_json"); - if (!base::PathExists(manifest_path)) - return NULL; - return ReadJSONManifest(manifest_path); -} - -// Read the component's manifest.json. -base::DictionaryValue* ReadComponentManifest( - const base::FilePath& unpack_path) { - base::FilePath manifest_path = - unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); - if (!base::PathExists(manifest_path)) - return NULL; - return ReadJSONManifest(manifest_path); -} - -// Check that the component's manifest is for PNaCl, and check the -// PNaCl manifest indicates this is the correct arch-specific package. -bool CheckPnaclComponentManifest(const base::DictionaryValue& manifest, - const base::DictionaryValue& pnacl_manifest, - Version* version_out) { - // Make sure we have the right |manifest| file. - std::string name; - if (!manifest.GetStringASCII("name", &name)) { - LOG(WARNING) << "'name' field is missing from manifest!"; - return false; - } - // For the webstore, we've given different names to each of the - // architecture specific packages (and test/QA vs not test/QA) - // so only part of it is the same. - if (name.find(kPnaclManifestName) == std::string::npos) { - LOG(WARNING) << "'name' field in manifest is invalid (" << name - << ") -- missing (" << kPnaclManifestName << ")"; - return false; - } - - std::string proposed_version; - if (!manifest.GetStringASCII("version", &proposed_version)) { - LOG(WARNING) << "'version' field is missing from manifest!"; - return false; - } - Version version(proposed_version.c_str()); - if (!version.IsValid()) { - LOG(WARNING) << "'version' field in manifest is invalid " - << version.GetString(); - return false; - } - - // Now check the |pnacl_manifest|. - std::string arch; - if (!pnacl_manifest.GetStringASCII("pnacl-arch", &arch)) { - LOG(WARNING) << "'pnacl-arch' field is missing from pnacl-manifest!"; - return false; - } - if (arch.compare(UpdateQueryParams::GetNaclArch()) != 0) { - LOG(WARNING) << "'pnacl-arch' field in manifest is invalid (" << arch - << " vs " << UpdateQueryParams::GetNaclArch() << ")"; - return false; - } - - *version_out = version; - return true; -} - -} // namespace - -PnaclComponentInstaller::PnaclComponentInstaller() : cus_(NULL) { -} - -PnaclComponentInstaller::~PnaclComponentInstaller() { -} - -void PnaclComponentInstaller::OnUpdateError(int error) { - NOTREACHED() << "Pnacl update error: " << error; -} - -// Pnacl components have the version encoded in the path itself: -// <profile>\AppData\Local\Google\Chrome\User Data\pnacl\0.1.2.3\. -// and the base directory will be: -// <profile>\AppData\Local\Google\Chrome\User Data\pnacl\. -base::FilePath PnaclComponentInstaller::GetPnaclBaseDirectory() { - base::FilePath result; - CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result)); - return result; -} - -bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) { - scoped_ptr<base::DictionaryValue> pnacl_manifest( - ReadPnaclManifest(unpack_path)); - if (pnacl_manifest == NULL) { - LOG(WARNING) << "Failed to read pnacl manifest."; - return false; - } - - Version version; - if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { - LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; - return false; - } - - // Don't install if the current version is actually newer. - if (current_version().CompareTo(version) > 0) { - return false; - } - - // Passed the basic tests. Time to install it. - base::FilePath path = - GetPnaclBaseDirectory().AppendASCII(version.GetString()); - if (base::PathExists(path)) { - if (!base::DeleteFile(path, true)) - return false; - } - if (!base::Move(unpack_path, path)) { - LOG(WARNING) << "Move failed, not installing."; - return false; - } - - // Installation is done. Now tell the rest of chrome. - // - The path service. - // - Callbacks that requested an update. - set_current_version(version); - CheckVersionCompatiblity(version); - OverrideDirPnaclComponent(path); - return true; -} - -// Given |file|, which can be a path like "_platform_specific/arm/pnacl_foo", -// returns the assumed install path. The path separator in |file| is '/' -// for all platforms. Caller is responsible for checking that the -// |installed_file| actually exists. -bool PnaclComponentInstaller::GetInstalledFile(const std::string& file, - base::FilePath* installed_file) { - if (current_version().Equals(Version(kNullVersion))) - return false; - - *installed_file = GetPnaclBaseDirectory() - .AppendASCII(current_version().GetString()) - .AppendASCII(file); - return true; -} - -bool PnaclComponentInstaller::Uninstall() { - return false; -} - -CrxComponent PnaclComponentInstaller::GetCrxComponent() { - CrxComponent pnacl_component; - pnacl_component.version = current_version(); - pnacl_component.name = "pnacl"; - pnacl_component.installer = this; - pnacl_component.fingerprint = current_fingerprint(); - SetPnaclHash(&pnacl_component); - - return pnacl_component; -} - -namespace { - -void FinishPnaclUpdateRegistration( - const Version& current_version, - const std::string& current_fingerprint, - const scoped_refptr<PnaclComponentInstaller>& pci) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - pci->set_current_version(current_version); - CheckVersionCompatiblity(current_version); - pci->set_current_fingerprint(current_fingerprint); - CrxComponent pnacl_component = pci->GetCrxComponent(); - - ComponentUpdateService::Status status = - pci->cus()->RegisterComponent(pnacl_component); - if (status != ComponentUpdateService::Status::kOk && - status != ComponentUpdateService::Status::kReplaced) { - NOTREACHED() << "Pnacl component registration failed."; - } -} - -// Check if there is an existing version on disk first to know when -// a hosted version is actually newer. -void StartPnaclUpdateRegistration( - const scoped_refptr<PnaclComponentInstaller>& pci) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - base::FilePath path = pci->GetPnaclBaseDirectory(); - if (!base::PathExists(path)) { - if (!base::CreateDirectory(path)) { - NOTREACHED() << "Could not create base Pnacl directory."; - return; - } - } - - Version current_version(kNullVersion); - std::string current_fingerprint; - std::vector<base::FilePath> older_dirs; - if (GetLatestPnaclDirectory(pci, &path, ¤t_version, &older_dirs)) { - scoped_ptr<base::DictionaryValue> manifest(ReadComponentManifest(path)); - scoped_ptr<base::DictionaryValue> pnacl_manifest(ReadPnaclManifest(path)); - Version manifest_version; - // Check that the component manifest and PNaCl manifest files - // are legit, and that the indicated version matches the one - // encoded within the path name. - if (manifest == NULL || pnacl_manifest == NULL || - !CheckPnaclComponentManifest(*manifest, - *pnacl_manifest, - &manifest_version) || - !current_version.Equals(manifest_version)) { - current_version = Version(kNullVersion); - } else { - OverrideDirPnaclComponent(path); - base::ReadFileToString(path.AppendASCII("manifest.fingerprint"), - ¤t_fingerprint); - } - } - - BrowserThread::PostTask(BrowserThread::UI, - FROM_HERE, - base::Bind(&FinishPnaclUpdateRegistration, - current_version, - current_fingerprint, - pci)); - - // Remove older versions of PNaCl. - for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); - iter != older_dirs.end(); - ++iter) { - base::DeleteFile(*iter, true); - } -} - -} // namespace - -void PnaclComponentInstaller::RegisterPnaclComponent( - ComponentUpdateService* cus) { - cus_ = cus; - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&StartPnaclUpdateRegistration, make_scoped_refptr(this))); -} - -} // namespace component_updater - -namespace pnacl { - -bool NeedsOnDemandUpdate() { - return base::subtle::NoBarrier_Load( - &component_updater::needs_on_demand_update) != 0; -} - -} // namespace pnacl
diff --git a/chrome/browser/component_updater/pnacl/pnacl_component_installer.h b/chrome/browser/component_updater/pnacl/pnacl_component_installer.h deleted file mode 100644 index 08f46e1..0000000 --- a/chrome/browser/component_updater/pnacl/pnacl_component_installer.h +++ /dev/null
@@ -1,86 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_COMPONENT_INSTALLER_H_ -#define CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_COMPONENT_INSTALLER_H_ - -#include <list> -#include <string> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/version.h" -#include "components/update_client/update_client.h" - -namespace base { -class DictionaryValue; -} - -namespace pnacl { -// Returns true if PNaCl actually needs an on-demand component update. -// E.g., if PNaCl is not yet installed and the user is loading a PNaCl app, -// or the current version is behind chrome's version, and is ABI incompatible -// with chrome. If not necessary, returns false. -// May conservatively return false before PNaCl is registered, but -// should return the right answer after it is registered. -bool NeedsOnDemandUpdate(); -} - -namespace component_updater { - -class ComponentUpdateService; - -// Component installer responsible for Portable Native Client files. -// Files can be installed to a shared location, or be installed to -// a per-user location. -class PnaclComponentInstaller : public update_client::CrxInstaller { - public: - PnaclComponentInstaller(); - - // ComponentInstaller implementation: - void OnUpdateError(int error) override; - bool Install(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) override; - bool GetInstalledFile(const std::string& file, - base::FilePath* installed_file) override; - bool Uninstall() override; - - // Register a PNaCl component for the first time. - void RegisterPnaclComponent(ComponentUpdateService* cus); - - update_client::CrxComponent GetCrxComponent(); - - // Determine the base directory for storing each version of PNaCl. - base::FilePath GetPnaclBaseDirectory(); - - base::Version current_version() const { return current_version_; } - - void set_current_version(const base::Version& current_version) { - current_version_ = current_version; - } - - std::string current_fingerprint() const { return current_fingerprint_; } - - void set_current_fingerprint(const std::string& current_fingerprint) { - current_fingerprint_ = current_fingerprint; - } - - ComponentUpdateService* cus() const { return cus_; } - - private: - ~PnaclComponentInstaller() override; - - base::Version current_version_; - std::string current_fingerprint_; - ComponentUpdateService* cus_; - - DISALLOW_COPY_AND_ASSIGN(PnaclComponentInstaller); -}; - -} // namespace component_updater - -#endif // CHROME_BROWSER_COMPONENT_UPDATER_PNACL_PNACL_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/component_updater/pnacl_component_installer.cc b/chrome/browser/component_updater/pnacl_component_installer.cc new file mode 100644 index 0000000..57d1475 --- /dev/null +++ b/chrome/browser/component_updater/pnacl_component_installer.cc
@@ -0,0 +1,388 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/component_updater/pnacl_component_installer.h" + +#include <stdint.h> +#include <string> +#include <vector> + +#include "base/atomicops.h" +#include "base/base_paths.h" +#include "base/bind.h" +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/json/json_file_value_serializer.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/values.h" +#include "base/version.h" +#include "base/win/windows_version.h" +#include "build/build_config.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/chrome_paths.h" +#include "components/component_updater/component_updater_service.h" +#include "components/nacl/common/nacl_switches.h" +#include "components/update_client/update_query_params.h" +#include "content/public/browser/browser_thread.h" + +using content::BrowserThread; +using update_client::CrxComponent; +using update_client::UpdateQueryParams; + +namespace component_updater { + +namespace { + +// Name of the Pnacl component specified in the manifest. +const char kPnaclManifestName[] = "PNaCl Translator"; + +// Sanitize characters from Pnacl Arch value so that they can be used +// in path names. This should only be characters in the set: [a-z0-9_]. +// Keep in sync with chrome/browser/nacl_host/nacl_file_host. +std::string SanitizeForPath(const std::string& input) { + std::string result; + base::ReplaceChars(input, "-", "_", &result); + return result; +} + +// Set the component's hash to the multi-CRX PNaCl package. +void SetPnaclHash(CrxComponent* component) { + static const uint8_t sha256_hash[32] = { + // This corresponds to AppID: hnimpnehoodheedghdeeijklkeaacbdc + 0x7d, 0x8c, 0xfd, 0x47, 0xee, 0x37, 0x44, 0x36, + 0x73, 0x44, 0x89, 0xab, 0xa4, 0x00, 0x21, 0x32, + 0x4a, 0x06, 0x06, 0xf1, 0x51, 0x3c, 0x51, 0xba, + 0x31, 0x2f, 0xbc, 0xb3, 0x99, 0x07, 0xdc, 0x9c + }; + + component->pk_hash.assign(sha256_hash, &sha256_hash[arraysize(sha256_hash)]); +} + +// If we don't have Pnacl installed, this is the version we claim. +const char kNullVersion[] = "0.0.0.0"; +const char kMinPnaclVersion[] = "0.2.0.86"; + +// Initially say that we do not need OnDemand updates. This should be +// updated by CheckVersionCompatiblity(), before doing any URLRequests +// that depend on PNaCl. +volatile base::subtle::Atomic32 needs_on_demand_update = 0; + +void CheckVersionCompatiblity(const base::Version& current_version) { + // Using NoBarrier, since needs_on_demand_update is standalone and does + // not have other associated data. + base::subtle::NoBarrier_Store(&needs_on_demand_update, + current_version.IsOlderThan(kMinPnaclVersion)); +} + +// PNaCl is packaged as a multi-CRX. This returns the platform-specific +// subdirectory that is part of that multi-CRX. +base::FilePath GetPlatformDir(const base::FilePath& base_path) { + std::string arch = SanitizeForPath(UpdateQueryParams::GetNaclArch()); + return base_path.AppendASCII("_platform_specific").AppendASCII(arch); +} + +// Tell the rest of the world where to find the platform-specific PNaCl files. +void OverrideDirPnaclComponent(const base::FilePath& base_path) { + PathService::Override(chrome::DIR_PNACL_COMPONENT, GetPlatformDir(base_path)); +} + +bool GetLatestPnaclDirectory(const scoped_refptr<PnaclComponentInstaller>& pci, + base::FilePath* latest_dir, + Version* latest_version, + std::vector<base::FilePath>* older_dirs) { + // Enumerate all versions starting from the base directory. + base::FilePath base_dir = pci->GetPnaclBaseDirectory(); + bool found = false; + base::FileEnumerator file_enumerator( + base_dir, false, base::FileEnumerator::DIRECTORIES); + for (base::FilePath path = file_enumerator.Next(); !path.value().empty(); + path = file_enumerator.Next()) { + Version version(path.BaseName().MaybeAsASCII()); + if (!version.IsValid()) + continue; + if (found) { + if (version.CompareTo(*latest_version) > 0) { + older_dirs->push_back(*latest_dir); + *latest_dir = path; + *latest_version = version; + } else { + older_dirs->push_back(path); + } + } else { + *latest_version = version; + *latest_dir = path; + found = true; + } + } + return found; +} + +// Read a manifest file in. +base::DictionaryValue* ReadJSONManifest(const base::FilePath& manifest_path) { + JSONFileValueDeserializer deserializer(manifest_path); + std::string error; + scoped_ptr<base::Value> root(deserializer.Deserialize(NULL, &error)); + if (!root.get()) + return NULL; + if (!root->IsType(base::Value::TYPE_DICTIONARY)) + return NULL; + return static_cast<base::DictionaryValue*>(root.release()); +} + +// Read the PNaCl specific manifest. +base::DictionaryValue* ReadPnaclManifest(const base::FilePath& unpack_path) { + base::FilePath manifest_path = + GetPlatformDir(unpack_path).AppendASCII("pnacl_public_pnacl_json"); + if (!base::PathExists(manifest_path)) + return NULL; + return ReadJSONManifest(manifest_path); +} + +// Read the component's manifest.json. +base::DictionaryValue* ReadComponentManifest( + const base::FilePath& unpack_path) { + base::FilePath manifest_path = + unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); + if (!base::PathExists(manifest_path)) + return NULL; + return ReadJSONManifest(manifest_path); +} + +// Check that the component's manifest is for PNaCl, and check the +// PNaCl manifest indicates this is the correct arch-specific package. +bool CheckPnaclComponentManifest(const base::DictionaryValue& manifest, + const base::DictionaryValue& pnacl_manifest, + Version* version_out) { + // Make sure we have the right |manifest| file. + std::string name; + if (!manifest.GetStringASCII("name", &name)) { + LOG(WARNING) << "'name' field is missing from manifest!"; + return false; + } + // For the webstore, we've given different names to each of the + // architecture specific packages (and test/QA vs not test/QA) + // so only part of it is the same. + if (name.find(kPnaclManifestName) == std::string::npos) { + LOG(WARNING) << "'name' field in manifest is invalid (" << name + << ") -- missing (" << kPnaclManifestName << ")"; + return false; + } + + std::string proposed_version; + if (!manifest.GetStringASCII("version", &proposed_version)) { + LOG(WARNING) << "'version' field is missing from manifest!"; + return false; + } + Version version(proposed_version.c_str()); + if (!version.IsValid()) { + LOG(WARNING) << "'version' field in manifest is invalid " + << version.GetString(); + return false; + } + + // Now check the |pnacl_manifest|. + std::string arch; + if (!pnacl_manifest.GetStringASCII("pnacl-arch", &arch)) { + LOG(WARNING) << "'pnacl-arch' field is missing from pnacl-manifest!"; + return false; + } + if (arch.compare(UpdateQueryParams::GetNaclArch()) != 0) { + LOG(WARNING) << "'pnacl-arch' field in manifest is invalid (" << arch + << " vs " << UpdateQueryParams::GetNaclArch() << ")"; + return false; + } + + *version_out = version; + return true; +} + +} // namespace + +PnaclComponentInstaller::PnaclComponentInstaller() : cus_(NULL) { +} + +PnaclComponentInstaller::~PnaclComponentInstaller() { +} + +void PnaclComponentInstaller::OnUpdateError(int error) { + NOTREACHED() << "Pnacl update error: " << error; +} + +// Pnacl components have the version encoded in the path itself: +// <profile>\AppData\Local\Google\Chrome\User Data\pnacl\0.1.2.3\. +// and the base directory will be: +// <profile>\AppData\Local\Google\Chrome\User Data\pnacl\. +base::FilePath PnaclComponentInstaller::GetPnaclBaseDirectory() { + base::FilePath result; + CHECK(PathService::Get(chrome::DIR_PNACL_BASE, &result)); + return result; +} + +bool PnaclComponentInstaller::Install(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) { + scoped_ptr<base::DictionaryValue> pnacl_manifest( + ReadPnaclManifest(unpack_path)); + if (pnacl_manifest == NULL) { + LOG(WARNING) << "Failed to read pnacl manifest."; + return false; + } + + Version version; + if (!CheckPnaclComponentManifest(manifest, *pnacl_manifest, &version)) { + LOG(WARNING) << "CheckPnaclComponentManifest failed, not installing."; + return false; + } + + // Don't install if the current version is actually newer. + if (current_version().CompareTo(version) > 0) { + return false; + } + + // Passed the basic tests. Time to install it. + base::FilePath path = + GetPnaclBaseDirectory().AppendASCII(version.GetString()); + if (base::PathExists(path)) { + if (!base::DeleteFile(path, true)) + return false; + } + if (!base::Move(unpack_path, path)) { + LOG(WARNING) << "Move failed, not installing."; + return false; + } + + // Installation is done. Now tell the rest of chrome. + // - The path service. + // - Callbacks that requested an update. + set_current_version(version); + CheckVersionCompatiblity(version); + OverrideDirPnaclComponent(path); + return true; +} + +// Given |file|, which can be a path like "_platform_specific/arm/pnacl_foo", +// returns the assumed install path. The path separator in |file| is '/' +// for all platforms. Caller is responsible for checking that the +// |installed_file| actually exists. +bool PnaclComponentInstaller::GetInstalledFile(const std::string& file, + base::FilePath* installed_file) { + if (current_version().Equals(Version(kNullVersion))) + return false; + + *installed_file = GetPnaclBaseDirectory() + .AppendASCII(current_version().GetString()) + .AppendASCII(file); + return true; +} + +bool PnaclComponentInstaller::Uninstall() { + return false; +} + +CrxComponent PnaclComponentInstaller::GetCrxComponent() { + CrxComponent pnacl_component; + pnacl_component.version = current_version(); + pnacl_component.name = "pnacl"; + pnacl_component.installer = this; + pnacl_component.fingerprint = current_fingerprint(); + SetPnaclHash(&pnacl_component); + + return pnacl_component; +} + +namespace { + +void FinishPnaclUpdateRegistration( + const Version& current_version, + const std::string& current_fingerprint, + const scoped_refptr<PnaclComponentInstaller>& pci) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + pci->set_current_version(current_version); + CheckVersionCompatiblity(current_version); + pci->set_current_fingerprint(current_fingerprint); + CrxComponent pnacl_component = pci->GetCrxComponent(); + + ComponentUpdateService::Status status = + pci->cus()->RegisterComponent(pnacl_component); + if (status != ComponentUpdateService::Status::kOk && + status != ComponentUpdateService::Status::kReplaced) { + NOTREACHED() << "Pnacl component registration failed."; + } +} + +// Check if there is an existing version on disk first to know when +// a hosted version is actually newer. +void StartPnaclUpdateRegistration( + const scoped_refptr<PnaclComponentInstaller>& pci) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + base::FilePath path = pci->GetPnaclBaseDirectory(); + if (!base::PathExists(path)) { + if (!base::CreateDirectory(path)) { + NOTREACHED() << "Could not create base Pnacl directory."; + return; + } + } + + Version current_version(kNullVersion); + std::string current_fingerprint; + std::vector<base::FilePath> older_dirs; + if (GetLatestPnaclDirectory(pci, &path, ¤t_version, &older_dirs)) { + scoped_ptr<base::DictionaryValue> manifest(ReadComponentManifest(path)); + scoped_ptr<base::DictionaryValue> pnacl_manifest(ReadPnaclManifest(path)); + Version manifest_version; + // Check that the component manifest and PNaCl manifest files + // are legit, and that the indicated version matches the one + // encoded within the path name. + if (manifest == NULL || pnacl_manifest == NULL || + !CheckPnaclComponentManifest(*manifest, + *pnacl_manifest, + &manifest_version) || + !current_version.Equals(manifest_version)) { + current_version = Version(kNullVersion); + } else { + OverrideDirPnaclComponent(path); + base::ReadFileToString(path.AppendASCII("manifest.fingerprint"), + ¤t_fingerprint); + } + } + + BrowserThread::PostTask(BrowserThread::UI, + FROM_HERE, + base::Bind(&FinishPnaclUpdateRegistration, + current_version, + current_fingerprint, + pci)); + + // Remove older versions of PNaCl. + for (std::vector<base::FilePath>::iterator iter = older_dirs.begin(); + iter != older_dirs.end(); + ++iter) { + base::DeleteFile(*iter, true); + } +} + +} // namespace + +void PnaclComponentInstaller::RegisterPnaclComponent( + ComponentUpdateService* cus) { + cus_ = cus; + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&StartPnaclUpdateRegistration, make_scoped_refptr(this))); +} + +} // namespace component_updater + +namespace pnacl { + +bool NeedsOnDemandUpdate() { + return base::subtle::NoBarrier_Load( + &component_updater::needs_on_demand_update) != 0; +} + +} // namespace pnacl
diff --git a/chrome/browser/component_updater/pnacl_component_installer.h b/chrome/browser/component_updater/pnacl_component_installer.h new file mode 100644 index 0000000..5b7e3cd --- /dev/null +++ b/chrome/browser/component_updater/pnacl_component_installer.h
@@ -0,0 +1,86 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COMPONENT_UPDATER_PNACL_COMPONENT_INSTALLER_H_ +#define CHROME_BROWSER_COMPONENT_UPDATER_PNACL_COMPONENT_INSTALLER_H_ + +#include <list> +#include <string> + +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/version.h" +#include "components/update_client/update_client.h" + +namespace base { +class DictionaryValue; +} + +namespace pnacl { +// Returns true if PNaCl actually needs an on-demand component update. +// E.g., if PNaCl is not yet installed and the user is loading a PNaCl app, +// or the current version is behind chrome's version, and is ABI incompatible +// with chrome. If not necessary, returns false. +// May conservatively return false before PNaCl is registered, but +// should return the right answer after it is registered. +bool NeedsOnDemandUpdate(); +} + +namespace component_updater { + +class ComponentUpdateService; + +// Component installer responsible for Portable Native Client files. +// Files can be installed to a shared location, or be installed to +// a per-user location. +class PnaclComponentInstaller : public update_client::CrxInstaller { + public: + PnaclComponentInstaller(); + + // ComponentInstaller implementation: + void OnUpdateError(int error) override; + bool Install(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) override; + bool GetInstalledFile(const std::string& file, + base::FilePath* installed_file) override; + bool Uninstall() override; + + // Register a PNaCl component for the first time. + void RegisterPnaclComponent(ComponentUpdateService* cus); + + update_client::CrxComponent GetCrxComponent(); + + // Determine the base directory for storing each version of PNaCl. + base::FilePath GetPnaclBaseDirectory(); + + base::Version current_version() const { return current_version_; } + + void set_current_version(const base::Version& current_version) { + current_version_ = current_version; + } + + std::string current_fingerprint() const { return current_fingerprint_; } + + void set_current_fingerprint(const std::string& current_fingerprint) { + current_fingerprint_ = current_fingerprint; + } + + ComponentUpdateService* cus() const { return cus_; } + + private: + ~PnaclComponentInstaller() override; + + base::Version current_version_; + std::string current_fingerprint_; + ComponentUpdateService* cus_; + + DISALLOW_COPY_AND_ASSIGN(PnaclComponentInstaller); +}; + +} // namespace component_updater + +#endif // CHROME_BROWSER_COMPONENT_UPDATER_PNACL_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/component_updater/test/supervised_user_whitelist_installer_unittest.cc b/chrome/browser/component_updater/supervised_user_whitelist_installer_unittest.cc similarity index 100% rename from chrome/browser/component_updater/test/supervised_user_whitelist_installer_unittest.cc rename to chrome/browser/component_updater/supervised_user_whitelist_installer_unittest.cc
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.cc b/chrome/browser/component_updater/sw_reporter_installer_win.cc index 603a2d2b..3ba5527 100644 --- a/chrome/browser/component_updater/sw_reporter_installer_win.cc +++ b/chrome/browser/component_updater/sw_reporter_installer_win.cc
@@ -474,17 +474,11 @@ void RegisterProfilePrefsForSwReporter( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kSwReporterPromptReason, -1, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kSwReporterPromptReason, -1); - registry->RegisterStringPref( - prefs::kSwReporterPromptVersion, "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kSwReporterPromptVersion, ""); - registry->RegisterStringPref( - prefs::kSwReporterPromptSeed, "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kSwReporterPromptSeed, ""); } } // namespace component_updater
diff --git a/chrome/browser/component_updater/test/chrome_component_updater_configurator_unittest.cc b/chrome/browser/component_updater/test/chrome_component_updater_configurator_unittest.cc deleted file mode 100644 index ddb9fdd..0000000 --- a/chrome/browser/component_updater/test/chrome_component_updater_configurator_unittest.cc +++ /dev/null
@@ -1,60 +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 "base/command_line.h" -#include "base/memory/ref_counted.h" -#include "chrome/browser/component_updater/chrome_component_updater_configurator.h" -#include "components/component_updater/component_updater_switches.h" -#include "components/update_client/configurator.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace component_updater { - -TEST(ChromeComponentUpdaterConfiguratorTest, TestDisablePings) { - base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - cmdline->AppendSwitchASCII(switches::kComponentUpdater, "disable-pings"); - - const auto config(MakeChromeComponentUpdaterConfigurator(cmdline, NULL)); - - const std::vector<GURL> pingUrls = config->PingUrl(); - EXPECT_TRUE(pingUrls.empty()); -} - -TEST(ChromeComponentUpdaterConfiguratorTest, TestFastUpdate) { - base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - cmdline->AppendSwitchASCII(switches::kComponentUpdater, "fast-update"); - - const auto config(MakeChromeComponentUpdaterConfigurator(cmdline, NULL)); - - ASSERT_EQ(1, config->InitialDelay()); -} - -TEST(ChromeComponentUpdaterConfiguratorTest, TestOverrideUrl) { - const char overrideUrl[] = "http://0.0.0.0/"; - - base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - std::string val = "url-source"; - val.append("="); - val.append(overrideUrl); - cmdline->AppendSwitchASCII(switches::kComponentUpdater, val.c_str()); - - const auto config(MakeChromeComponentUpdaterConfigurator(cmdline, NULL)); - - const std::vector<GURL> urls = config->UpdateUrl(); - - ASSERT_EQ(1U, urls.size()); - ASSERT_EQ(overrideUrl, urls.at(0).possibly_invalid_spec()); -} - -TEST(ChromeComponentUpdaterConfiguratorTest, TestSwitchRequestParam) { - base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - cmdline->AppendSwitchASCII(switches::kComponentUpdater, "test-request"); - - const auto config(MakeChromeComponentUpdaterConfigurator(cmdline, NULL)); - - EXPECT_FALSE(config->ExtraRequestParams().empty()); -} - -} // namespace component_updater
diff --git a/chrome/browser/component_updater/test/cld_component_installer_unittest.cc b/chrome/browser/component_updater/test/cld_component_installer_unittest.cc deleted file mode 100644 index 3d39ef72c..0000000 --- a/chrome/browser/component_updater/test/cld_component_installer_unittest.cc +++ /dev/null
@@ -1,134 +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 <stdint.h> -#include <vector> - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "base/version.h" -#include "chrome/browser/component_updater/cld_component_installer.h" -#include "components/translate/content/browser/browser_cld_data_provider.h" -#include "components/translate/content/common/cld_data_source.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/platform_test.h" - -using component_updater::CldComponentInstallerTraits; - -namespace { -// This has to match what's in cld_component_installer.cc. -const base::FilePath::CharType kTestCldDataFileName[] = - FILE_PATH_LITERAL("cld2_data.bin"); - -} // namespace - -namespace component_updater { - -class CldComponentInstallerTest : public PlatformTest { - public: - CldComponentInstallerTest() {} - void SetUp() override { - PlatformTest::SetUp(); - translate::CldDataSource::DisableSanityChecksForTest(); - - // ScopedTempDir automatically does a recursive delete on the entire - // directory in its destructor, so no cleanup is required in TearDown. - // Note that all files created by this test case are created within the - // directory that is created here, so even though they are not explicitly - // created *as temp files*, they will still get cleaned up automagically. - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - // The "latest CLD data file" is a static piece of information, and thus - // for correctness we empty it before each test. - CldComponentInstallerTraits::SetLatestCldDataFile(base::FilePath()); - base::FilePath path_now = - CldComponentInstallerTraits::GetLatestCldDataFile(); - ASSERT_TRUE(path_now.empty()); - } - - void TearDown() override { - // Restore sanity checks. - translate::CldDataSource::EnableSanityChecksForTest(); - } - protected: - base::ScopedTempDir temp_dir_; - CldComponentInstallerTraits traits_; - - private: - DISALLOW_COPY_AND_ASSIGN(CldComponentInstallerTest); -}; - -TEST_F(CldComponentInstallerTest, SetLatestCldDataFile) { - const base::FilePath expected(FILE_PATH_LITERAL("test/foo.test")); - CldComponentInstallerTraits::SetLatestCldDataFile(expected); - base::FilePath result = - CldComponentInstallerTraits::GetLatestCldDataFile(); - ASSERT_EQ(expected, result); -} - -TEST_F(CldComponentInstallerTest, VerifyInstallation) { - // All files are created within a ScopedTempDir, which deletes all - // children when its destructor is called (at the end of each test). - const base::DictionaryValue manifest; - ASSERT_FALSE(traits_.VerifyInstallation(manifest, temp_dir_.path())); - const base::FilePath data_file_dir = - temp_dir_.path().Append(FILE_PATH_LITERAL("_platform_specific")).Append( - FILE_PATH_LITERAL("all")); - ASSERT_TRUE(base::CreateDirectory(data_file_dir)); - const base::FilePath data_file = data_file_dir.Append(kTestCldDataFileName); - const std::string test_data("fake cld2 data file content here :)"); - ASSERT_EQ(static_cast<int32>(test_data.length()), - base::WriteFile(data_file, test_data.c_str(), test_data.length())); - ASSERT_TRUE(traits_.VerifyInstallation(manifest, temp_dir_.path())); -} - -TEST_F(CldComponentInstallerTest, OnCustomInstall) { - const base::DictionaryValue manifest; - const base::FilePath install_dir; - // Sanity: shouldn't crash. - ASSERT_TRUE(traits_.OnCustomInstall(manifest, install_dir)); -} - -TEST_F(CldComponentInstallerTest, GetInstalledPath) { - const base::FilePath base_dir; - const base::FilePath result = - CldComponentInstallerTraits::GetInstalledPath(base_dir); - ASSERT_TRUE(EndsWith(result.value(), kTestCldDataFileName, true)); -} - -TEST_F(CldComponentInstallerTest, GetBaseDirectory) { - const base::FilePath result = traits_.GetBaseDirectory(); - ASSERT_FALSE(result.empty()); -} - -TEST_F(CldComponentInstallerTest, GetHash) { - std::vector<uint8_t> hash; - traits_.GetHash(&hash); - ASSERT_EQ(static_cast<size_t>(32), hash.size()); -} - -TEST_F(CldComponentInstallerTest, GetName) { - ASSERT_FALSE(traits_.GetName().empty()); -} - -TEST_F(CldComponentInstallerTest, ComponentReady) { - scoped_ptr<base::DictionaryValue> manifest; - const base::FilePath install_dir(FILE_PATH_LITERAL("/foo")); - const base::Version version("1.2.3.4"); - traits_.ComponentReady(version, install_dir, manifest.Pass()); - base::FilePath result = - CldComponentInstallerTraits::GetLatestCldDataFile(); - ASSERT_TRUE(StartsWith(result.AsUTF16Unsafe(), - install_dir.AsUTF16Unsafe(), - true)); - ASSERT_TRUE(EndsWith(result.value(), kTestCldDataFileName, true)); -} - -} // namespace component_updater
diff --git a/chrome/browser/component_updater/test/component_installers_unittest.cc b/chrome/browser/component_updater/test/component_installers_unittest.cc deleted file mode 100644 index 8cb58d0c..0000000 --- a/chrome/browser/component_updater/test/component_installers_unittest.cc +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/component_updater/flash_component_installer.h" - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/json/json_file_value_serializer.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/version.h" -#include "build/build_config.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/pepper_flash.h" -#include "content/public/test/test_browser_thread.h" -#include "ppapi/shared_impl/test_globals.h" - -#include "testing/gtest/include/gtest/gtest.h" - -using content::BrowserThread; - -namespace component_updater { - -namespace { -// File name of the Pepper Flash plugin on different platforms. -const base::FilePath::CharType kDataPath[] = -#if defined(OS_MACOSX) -#if defined(ARCH_CPU_X86) - FILE_PATH_LITERAL("components/flapper/mac"); -#elif defined(ARCH_CPU_X86_64) - FILE_PATH_LITERAL("components/flapper/mac_x64"); -#else - FILE_PATH_LITERAL("components/flapper/NONEXISTENT"); -#endif -#elif defined(OS_WIN) -#if defined(ARCH_CPU_X86) - FILE_PATH_LITERAL("components\\flapper\\windows"); -#elif defined(ARCH_CPU_X86_64) - FILE_PATH_LITERAL("components\\flapper\\windows_x64"); -#else - FILE_PATH_LITERAL("components\\flapper\\NONEXISTENT"); -#endif -#else // OS_LINUX, etc. -#if defined(ARCH_CPU_X86) - FILE_PATH_LITERAL("components/flapper/linux"); -#elif defined(ARCH_CPU_X86_64) - FILE_PATH_LITERAL("components/flapper/linux_x64"); -#else - FILE_PATH_LITERAL("components/flapper/NONEXISTENT"); -#endif -#endif -} // namespace - -// TODO(viettrungluu): Separate out into two separate tests; use a test fixture. -TEST(ComponentInstallerTest, PepperFlashCheck) { - base::MessageLoop message_loop; - content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); - - ppapi::PpapiGlobals::PerThreadForTest per_thread_for_test; - ppapi::TestGlobals test_globals(per_thread_for_test); - ppapi::PpapiGlobals::SetPpapiGlobalsOnThreadForTest(&test_globals); - - // The test directory is chrome/test/data/components/flapper. - base::FilePath manifest; - PathService::Get(chrome::DIR_TEST_DATA, &manifest); - manifest = manifest.Append(kDataPath); - manifest = manifest.AppendASCII("manifest.json"); - - if (!base::PathExists(manifest)) { - LOG(WARNING) << "No test manifest available. Skipping."; - return; - } - - JSONFileValueDeserializer deserializer(manifest); - std::string error; - scoped_ptr<base::DictionaryValue> root(static_cast<base::DictionaryValue*>( - deserializer.Deserialize(NULL, &error))); - ASSERT_TRUE(root); - ASSERT_TRUE(root->IsType(base::Value::TYPE_DICTIONARY)); - - // This checks that the whole manifest is compatible. - Version version; - EXPECT_TRUE(chrome::CheckPepperFlashManifest(*root, &version)); - EXPECT_TRUE(version.IsValid()); -} - -} // namespace component_updater
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.cc b/chrome/browser/component_updater/test/component_updater_service_unittest.cc deleted file mode 100644 index e0d02eaf..0000000 --- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc +++ /dev/null
@@ -1,1424 +0,0 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/component_updater/test/component_updater_service_unittest.h" - -#include <vector> - -#include "base/files/file_util.h" -#include "base/memory/scoped_ptr.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/values.h" -#include "chrome/browser/component_updater/component_updater_resource_throttle.h" -#include "chrome/common/chrome_paths.h" -#include "components/update_client/test/test_configurator.h" -#include "components/update_client/test/test_installer.h" -#include "components/update_client/test/url_request_post_interceptor.h" -#include "components/update_client/utils.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/resource_controller.h" -#include "content/public/browser/resource_request_info.h" -#include "content/public/browser/resource_throttle.h" -#include "libxml/globals.h" -#include "net/base/upload_bytes_element_reader.h" -#include "net/url_request/test_url_request_interceptor.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_test_util.h" -#include "url/gurl.h" - -using ::testing::_; -using ::testing::AnyNumber; -using ::testing::InSequence; -using ::testing::Mock; - -using content::BrowserThread; - -using std::string; - -using update_client::CrxComponent; -using update_client::PartialMatch; -using update_client::InterceptorFactory; -using update_client::TestConfigurator; -using update_client::TestInstaller; -using update_client::URLRequestPostInterceptor; -using update_client::VersionedTestInstaller; - -using update_client::abag_hash; -using update_client::ihfo_hash; -using update_client::jebg_hash; - -using Events = component_updater::ServiceObserver::Events; -using Status = component_updater::ComponentUpdateService::Status; - -namespace component_updater { - -MockServiceObserver::MockServiceObserver() { -} - -MockServiceObserver::~MockServiceObserver() { -} - -ComponentUpdaterTest::ComponentUpdaterTest() - : post_interceptor_(NULL), - thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), - test_config_(NULL) { - // The component updater instance under test. - test_config_ = new TestConfigurator( - BrowserThread::GetBlockingPool() - ->GetSequencedTaskRunnerWithShutdownBehavior( - BrowserThread::GetBlockingPool()->GetSequenceToken(), - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)); - component_updater_.reset( - ComponentUpdateServiceFactory(test_config_).release()); -} - -ComponentUpdaterTest::~ComponentUpdaterTest() { -} - -void ComponentUpdaterTest::SetUp() { - get_interceptor_.reset(new GetInterceptor( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), - BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN))); - interceptor_factory_.reset(new InterceptorFactory( - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); - post_interceptor_ = interceptor_factory_->CreateInterceptor(); - EXPECT_TRUE(post_interceptor_); -} - -void ComponentUpdaterTest::TearDown() { - interceptor_factory_.reset(); - get_interceptor_.reset(); - xmlCleanupGlobals(); -} - -ComponentUpdateService* ComponentUpdaterTest::component_updater() { - return component_updater_.get(); -} - -// Makes the full path to a component updater test file. -const base::FilePath ComponentUpdaterTest::test_file(const char* file) { - base::FilePath path; - PathService::Get(base::DIR_SOURCE_ROOT, &path); - return path.AppendASCII("components") - .AppendASCII("test") - .AppendASCII("data") - .AppendASCII("update_client") - .AppendASCII(file); -} - -scoped_refptr<update_client::TestConfigurator> -ComponentUpdaterTest::test_configurator() { - return test_config_; -} - -ComponentUpdateService::Status ComponentUpdaterTest::RegisterComponent( - CrxComponent* com, - TestComponents component, - const Version& version, - const scoped_refptr<TestInstaller>& installer) { - switch (component) { - case kTestComponent_abag: { - com->name = "test_abag"; - com->pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); - break; - } - case kTestComponent_jebg: { - com->name = "test_jebg"; - com->pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); - break; - } - case kTestComponent_ihfo: { - com->name = "test_ihfo"; - com->pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); - break; - } - } - com->version = version; - com->installer = installer; - return component_updater_->RegisterComponent(*com); -} - -void ComponentUpdaterTest::RunThreads() { - base::RunLoop runloop; - test_configurator()->SetQuitClosure(runloop.QuitClosure()); - runloop.Run(); - - // Since some tests need to drain currently enqueued tasks such as network - // intercepts on the IO thread, run the threads until they are - // idle. The component updater service won't loop again until the loop count - // is set and the service is started. - RunThreadsUntilIdle(); -} - -void ComponentUpdaterTest::RunThreadsUntilIdle() { - base::RunLoop().RunUntilIdle(); -} - -ComponentUpdateService::Status OnDemandTester::OnDemand( - ComponentUpdateService* cus, - const std::string& component_id) { - return cus->GetOnDemandUpdater().OnDemandUpdate(component_id); -} - -// Verify that our test fixture work and the component updater can -// be created and destroyed with no side effects. -TEST_F(ComponentUpdaterTest, VerifyFixture) { - EXPECT_TRUE(component_updater() != NULL); -} - -// Verify that the component updater can be caught in a quick -// start-shutdown situation. Failure of this test will be a crash. -TEST_F(ComponentUpdaterTest, StartStop) { - component_updater()->Start(); - RunThreadsUntilIdle(); - component_updater()->Stop(); -} - -// Verify that when the server has no updates, we go back to sleep and -// the COMPONENT_UPDATER_STARTED and COMPONENT_UPDATER_SLEEPING notifications -// are generated. No pings are sent. -TEST_F(ComponentUpdaterTest, CheckCrxSleep) { - MockServiceObserver observer; - - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(2); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(2); - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - scoped_refptr<TestInstaller> installer(new TestInstaller); - CrxComponent com; - component_updater()->AddObserver(&observer); - EXPECT_EQ(Status::kOk, RegisterComponent(&com, kTestComponent_abag, - Version("1.1"), installer)); - - // We loop twice, but there are no updates so we expect two sleep messages. - test_configurator()->SetLoopCount(2); - component_updater()->Start(); - RunThreads(); - - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(0, installer->install_count()); - - // Expect to see the two update check requests and no other requests, - // including pings. - EXPECT_EQ(2, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(2, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - - component_updater()->Stop(); - - // Loop twice again but this case we simulate a server error by returning - // an empty file. Expect the behavior of the service to be the same as before. - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(2); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(2); - - post_interceptor_->Reset(); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty"))); - - test_configurator()->SetLoopCount(2); - component_updater()->Start(); - RunThreads(); - - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(0, installer->install_count()); - - EXPECT_EQ(2, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(2, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"1.1\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - - component_updater()->Stop(); -} - -// Verify that we can check for updates and install one component. Besides -// the notifications above COMPONENT_UPDATE_FOUND and COMPONENT_UPDATE_READY -// should have been fired. We do two loops so the second time around there -// should be nothing left to do. -// We also check that the following network requests are issued: -// 1- update check -// 2- download crx -// 3- ping -// 4- second update check. -TEST_F(ComponentUpdaterTest, InstallCrx) { - MockServiceObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "jebgalgnebhfojomionfpkfelancnnkf")) - .Times(AnyNumber()); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - get_interceptor_->SetResponse( - GURL(expected_crx_url), - test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); - - component_updater()->AddObserver(&observer); - - scoped_refptr<TestInstaller> installer1(new TestInstaller); - CrxComponent com1; - RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), installer1); - scoped_refptr<TestInstaller> installer2(new TestInstaller); - CrxComponent com2; - RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), installer2); - - test_configurator()->SetLoopCount(2); - component_updater()->Start(); - RunThreads(); - - EXPECT_EQ(0, installer1->error()); - EXPECT_EQ(1, installer1->install_count()); - EXPECT_EQ(0, installer2->error()); - EXPECT_EQ(0, installer2->install_count()); - - // Expect three request in total: two update checks and one ping. - EXPECT_EQ(3, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(3, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - // Expect one component download. - EXPECT_EQ(1, get_interceptor_->GetHitCount()); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " - "version=\"0.9\" nextversion=\"1.0\">" - "<event eventtype=\"3\" eventresult=\"1\"/>")) - << post_interceptor_->GetRequestsAsString(); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[2].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">" - "<updatecheck /></app>")); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[2].find( - "<app appid=\"abagagagagagagagagagagagagagagag\" version=\"2.2\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - - // Test the protocol version is correct and the extra request attributes - // are included in the request. - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "request protocol=\"3.0\" extra=\"foo\"")) - << post_interceptor_->GetRequestsAsString(); - - // Tokenize the request string to look for specific attributes, which - // are important for backward compatibility with the version v2 of the update - // protocol. In this case, inspect the <request>, which is the first element - // after the xml declaration of the update request body. - // Expect to find the |os|, |arch|, |prodchannel|, and |prodversion| - // attributes: - // <?xml version="1.0" encoding="UTF-8"?> - // <request... os=... arch=... prodchannel=... prodversion=...> - // ... - // </request> - const std::string update_request(post_interceptor_->GetRequests()[0]); - std::vector<base::StringPiece> elements; - Tokenize(update_request, "<>", &elements); - EXPECT_NE(string::npos, elements[1].find(" os=")); - EXPECT_NE(string::npos, elements[1].find(" arch=")); - EXPECT_NE(string::npos, elements[1].find(" prodchannel=")); - EXPECT_NE(string::npos, elements[1].find(" prodversion=")); - - // Look for additional attributes of the request, such as |version|, - // |requestid|, |lang|, and |nacl_arch|. - EXPECT_NE(string::npos, elements[1].find(" version=")); - EXPECT_NE(string::npos, elements[1].find(" requestid=")); - EXPECT_NE(string::npos, elements[1].find(" lang=")); - EXPECT_NE(string::npos, elements[1].find(" nacl_arch=")); - - component_updater()->Stop(); -} - -// This test checks that the "prodversionmin" value is handled correctly. In -// particular there should not be an install because the minimum product -// version is much higher than of chrome. -TEST_F(ComponentUpdaterTest, ProdVersionCheck) { - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_2.xml"))); - - get_interceptor_->SetResponse( - GURL(expected_crx_url), - test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); - - scoped_refptr<TestInstaller> installer(new TestInstaller); - CrxComponent com; - RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), installer); - - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - RunThreads(); - - // Expect one update check and no ping. - EXPECT_EQ(1, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - // Expect no download to occur. - EXPECT_EQ(0, get_interceptor_->GetHitCount()); - - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(0, installer->install_count()); - - component_updater()->Stop(); -} - -// Test that a update check due to an on demand call can cause installs. -// Here is the timeline: -// - First loop: we return a reply that indicates no update, so -// nothing happens. -// - We make an on demand call. -// - This triggers a second loop, which has a reply that triggers an install. -#if defined(OS_LINUX) -// http://crbug.com/396488 -#define MAYBE_OnDemandUpdate DISABLED_OnDemandUpdate -#else -#define MAYBE_OnDemandUpdate OnDemandUpdate -#endif -TEST_F(ComponentUpdaterTest, MAYBE_OnDemandUpdate) { - MockServiceObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "jebgalgnebhfojomionfpkfelancnnkf")) - .Times(AnyNumber()); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty"))); - - get_interceptor_->SetResponse( - GURL(expected_crx_url), - test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); - - component_updater()->AddObserver(&observer); - - scoped_refptr<TestInstaller> installer1(new TestInstaller); - CrxComponent com1; - RegisterComponent(&com1, kTestComponent_abag, Version("2.2"), installer1); - scoped_refptr<TestInstaller> installer2(new TestInstaller); - CrxComponent com2; - RegisterComponent(&com2, kTestComponent_jebg, Version("0.9"), installer2); - - // No update normally. - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - RunThreads(); - component_updater()->Stop(); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - EXPECT_EQ(0, get_interceptor_->GetHitCount()); - - // Update after an on-demand check is issued. - post_interceptor_->Reset(); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - - EXPECT_EQ(Status::kOk, OnDemandTester::OnDemand(component_updater(), - GetCrxComponentID(com2))); - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - RunThreads(); - - EXPECT_EQ(0, installer1->error()); - EXPECT_EQ(0, installer1->install_count()); - EXPECT_EQ(0, installer2->error()); - EXPECT_EQ(1, installer2->install_count()); - - EXPECT_EQ(2, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(2, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - EXPECT_EQ(1, get_interceptor_->GetHitCount()); - - // Expect the update check to contain an "ondemand" request for the - // second component (com2) and a normal request for the other component. - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"abagagagagagagagagagagagagagagag\" " - "version=\"2.2\"><updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " - "version=\"0.9\" installsource=\"ondemand\"><updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " - "version=\"0.9\" nextversion=\"1.0\">" - "<event eventtype=\"3\" eventresult=\"1\"/>")) - << post_interceptor_->GetRequestsAsString(); - - // Also check what happens if previous check too soon. It works, since this - // direct OnDemand call does not implement a cooldown. - test_configurator()->SetOnDemandTime(60 * 60); - EXPECT_EQ(Status::kOk, OnDemandTester::OnDemand(component_updater(), - GetCrxComponentID(com2))); - // Okay, now reset to 0 for the other tests. - test_configurator()->SetOnDemandTime(0); - component_updater()->Stop(); - - // Test a few error cases. NOTE: We don't have callbacks for - // when the updates failed yet. - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer)); - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - // No update: error from no server response - post_interceptor_->Reset(); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_empty"))); - - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - EXPECT_EQ(Status::kOk, OnDemandTester::OnDemand(component_updater(), - GetCrxComponentID(com2))); - RunThreads(); - component_updater()->Stop(); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - // No update: already updated to 1.0 so nothing new - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer)); - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - post_interceptor_->Reset(); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - EXPECT_EQ(Status::kOk, OnDemandTester::OnDemand(component_updater(), - GetCrxComponentID(com2))); - RunThreads(); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - component_updater()->Stop(); -} - -// Verify that a previously registered component can get re-registered -// with a different version. -TEST_F(ComponentUpdaterTest, CheckReRegistration) { - MockServiceObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "jebgalgnebhfojomionfpkfelancnnkf")) - .Times(AnyNumber()); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - get_interceptor_->SetResponse( - GURL(expected_crx_url), - test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); - - component_updater()->AddObserver(&observer); - - scoped_refptr<TestInstaller> installer1(new TestInstaller); - CrxComponent com1; - RegisterComponent(&com1, kTestComponent_jebg, Version("0.9"), installer1); - scoped_refptr<TestInstaller> installer2(new TestInstaller); - CrxComponent com2; - RegisterComponent(&com2, kTestComponent_abag, Version("2.2"), installer2); - - // Loop twice to issue two checks: (1) with original 0.9 version, update to - // 1.0, and do the second check (2) with the updated 1.0 version. - test_configurator()->SetLoopCount(2); - component_updater()->Start(); - RunThreads(); - - EXPECT_EQ(0, installer1->error()); - EXPECT_EQ(1, installer1->install_count()); - EXPECT_EQ(0, installer2->error()); - EXPECT_EQ(0, installer2->install_count()); - - EXPECT_EQ(3, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, get_interceptor_->GetHitCount()); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " - "version=\"0.9\" nextversion=\"1.0\">" - "<event eventtype=\"3\" eventresult=\"1\"/>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[2].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"1.0\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - - component_updater()->Stop(); - - // Now re-register, pretending to be an even newer version (2.2) - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer)); - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - post_interceptor_->Reset(); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - scoped_refptr<TestInstaller> installer3(new TestInstaller); - EXPECT_EQ(Status::kReplaced, RegisterComponent(&com1, kTestComponent_jebg, - Version("2.2"), installer3)); - - // Loop once just to notice the check happening with the re-register version. - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - RunThreads(); - - // We created a new installer, so the counts go back to 0. - EXPECT_EQ(0, installer3->error()); - EXPECT_EQ(0, installer3->install_count()); - EXPECT_EQ(0, installer2->error()); - EXPECT_EQ(0, installer2->install_count()); - - // One update check and no additional pings are expected. - EXPECT_EQ(1, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"2.2\">" - "<updatecheck /></app>")); - - component_updater()->Stop(); -} - -// Verify that we can download and install a component and a differential -// update to that component. We do three loops; the final loop should do -// nothing. -// We also check that exactly 5 non-ping network requests are issued: -// 1- update check (response: v1 available) -// 2- download crx (v1) -// 3- update check (response: v2 available) -// 4- download differential crx (v1 to v2) -// 5- update check (response: no further update available) -// There should be two pings, one for each update. The second will bear a -// diffresult=1, while the first will not. -TEST_F(ComponentUpdaterTest, DifferentialUpdate) { - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_diff_reply_1.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_diff_reply_2.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_diff_reply_3.xml"))); - - get_interceptor_->SetResponse( - GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), - test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); - get_interceptor_->SetResponse( - GURL("http://localhost/download/" - "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), - test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx")); - - scoped_refptr<TestInstaller> installer(new VersionedTestInstaller); - CrxComponent com; - RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), installer); - - test_configurator()->SetLoopCount(3); - component_updater()->Start(); - RunThreads(); - - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(2, installer->install_count()); - - EXPECT_EQ(5, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(5, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(2, get_interceptor_->GetHitCount()); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " - "version=\"0.0\" nextversion=\"1.0\">" - "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[2].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" - "<updatecheck /><packages><package fp=\"1\"/></packages></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[3].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " - "version=\"1.0\" nextversion=\"2.0\">" - "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"1\" " - "previousfp=\"1\" nextfp=\"22\"/>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[4].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" - "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) - << post_interceptor_->GetRequestsAsString(); - component_updater()->Stop(); -} - -// Verify that component installation falls back to downloading and installing -// a full update if the differential update fails (in this case, because the -// installer does not know about the existing files). We do two loops; the final -// loop should do nothing. -// We also check that exactly 4 non-ping network requests are issued: -// 1- update check (loop 1) -// 2- download differential crx -// 3- download full crx -// 4- update check (loop 2 - no update available) -// There should be one ping for the first attempted update. -// This test is flaky on Android. crbug.com/329883 -#if defined(OS_ANDROID) -#define MAYBE_DifferentialUpdateFails DISABLED_DifferentialUpdateFails -#else -#define MAYBE_DifferentialUpdateFails DifferentialUpdateFails -#endif -TEST_F(ComponentUpdaterTest, MAYBE_DifferentialUpdateFails) { - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_diff_reply_2.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_diff_reply_3.xml"))); - - get_interceptor_->SetResponse( - GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), - test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); - get_interceptor_->SetResponse( - GURL("http://localhost/download/" - "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), - test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx")); - get_interceptor_->SetResponse( - GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), - test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx")); - - scoped_refptr<TestInstaller> installer(new TestInstaller); - CrxComponent com; - RegisterComponent(&com, kTestComponent_ihfo, Version("1.0"), installer); - - test_configurator()->SetLoopCount(2); - component_updater()->Start(); - RunThreads(); - - // A failed differential update does not count as a failed install. - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(1, installer->install_count()); - - EXPECT_EQ(3, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(3, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(2, get_interceptor_->GetHitCount()); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " - "version=\"1.0\" nextversion=\"2.0\">" - "<event eventtype=\"3\" eventresult=\"1\" diffresult=\"0\" " - "differrorcat=\"2\" differrorcode=\"16\" nextfp=\"22\"/>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[2].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" - "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) - << post_interceptor_->GetRequestsAsString(); - - component_updater()->Stop(); -} - -// Test is flakey on Android bots. See crbug.com/331420. -#if defined(OS_ANDROID) -#define MAYBE_CheckFailedInstallPing DISABLED_CheckFailedInstallPing -#else -#define MAYBE_CheckFailedInstallPing CheckFailedInstallPing -#endif -// Verify that a failed installation causes an install failure ping. -TEST_F(ComponentUpdaterTest, MAYBE_CheckFailedInstallPing) { - // This test installer reports installation failure. - class FailingTestInstaller : public TestInstaller { - bool Install(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) override { - ++install_count_; - base::DeleteFile(unpack_path, true); - return false; - } - private: - ~FailingTestInstaller() override {} - }; - scoped_refptr<FailingTestInstaller> installer(new FailingTestInstaller); - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - get_interceptor_->SetResponse( - GURL(expected_crx_url), - test_file("jebgalgnebhfojomionfpkfelancnnkf.crx")); - - // Start with 0.9, and attempt update to 1.0. - // Loop twice to issue two checks: (1) with original 0.9 version - // and (2), which should retry with 0.9. - CrxComponent com; - RegisterComponent(&com, kTestComponent_jebg, Version("0.9"), installer); - - test_configurator()->SetLoopCount(2); - component_updater()->Start(); - RunThreads(); - - EXPECT_EQ(4, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(2, get_interceptor_->GetHitCount()); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " - "version=\"0.9\" nextversion=\"1.0\">" - "<event eventtype=\"3\" eventresult=\"0\" " - "errorcat=\"3\" errorcode=\"9\"/>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[2].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[3].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" " - "version=\"0.9\" nextversion=\"1.0\">" - "<event eventtype=\"3\" eventresult=\"0\" " - "errorcat=\"3\" errorcode=\"9\"/>")) - << post_interceptor_->GetRequestsAsString(); - - // Loop once more, but expect no ping because a noupdate response is issued. - // This is necessary to clear out the fire-and-forget ping from the previous - // iteration. - post_interceptor_->Reset(); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_reply_noupdate.xml"))); - - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - RunThreads(); - - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(2, installer->install_count()); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - - component_updater()->Stop(); -} - -// Verify that we successfully propagate a patcher error. -// ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx contains an incorrect -// patching instruction that should fail. -TEST_F(ComponentUpdaterTest, DifferentialUpdateFailErrorcode) { - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_diff_reply_1.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_diff_reply_2.xml"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest(new PartialMatch("event"))); - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), - test_file("updatecheck_diff_reply_3.xml"))); - - get_interceptor_->SetResponse( - GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), - test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx")); - // This intercept returns a different file than what is specified in the - // update check response and requested in the download. The file that is - // actually dowloaded contains a patching error, an therefore, an error - // is injected at the time of patching. - get_interceptor_->SetResponse( - GURL("http://localhost/download/" - "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), - test_file("ihfokbkgjpifnbbojhneepfflplebdkc_1to2_bad.crx")); - get_interceptor_->SetResponse( - GURL("http://localhost/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), - test_file("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx")); - - scoped_refptr<TestInstaller> installer(new VersionedTestInstaller); - CrxComponent com; - RegisterComponent(&com, kTestComponent_ihfo, Version("0.0"), installer); - - test_configurator()->SetLoopCount(3); - component_updater()->Start(); - RunThreads(); - component_updater()->Stop(); - - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(2, installer->install_count()); - - EXPECT_EQ(5, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(5, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(3, get_interceptor_->GetHitCount()); - - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"0.0\">" - "<updatecheck /></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[1].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " - "version=\"0.0\" nextversion=\"1.0\">" - "<event eventtype=\"3\" eventresult=\"1\" nextfp=\"1\"/>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[2].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"1.0\">" - "<updatecheck /><packages><package fp=\"1\"/></packages></app>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[3].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" " - "version=\"1.0\" nextversion=\"2.0\">" - "<event eventtype=\"3\" eventresult=\"1\" " - "diffresult=\"0\" differrorcat=\"2\" " - "differrorcode=\"14\" diffextracode1=\"305\" " - "previousfp=\"1\" nextfp=\"22\"/>")) - << post_interceptor_->GetRequestsAsString(); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[4].find( - "<app appid=\"ihfokbkgjpifnbbojhneepfflplebdkc\" version=\"2.0\">" - "<updatecheck /><packages><package fp=\"22\"/></packages></app>")) - << post_interceptor_->GetRequestsAsString(); -} - -class TestResourceController : public content::ResourceController { - public: - virtual void SetThrottle(content::ResourceThrottle* throttle) {} -}; - -content::ResourceThrottle* RequestTestResourceThrottle( - ComponentUpdateService* cus, - TestResourceController* controller, - const char* crx_id) { - net::TestURLRequestContext context; - scoped_ptr<net::URLRequest> url_request(context.CreateRequest( - GURL("http://foo.example.com/thing.bin"), - net::DEFAULT_PRIORITY, - NULL)); - - content::ResourceThrottle* rt = GetOnDemandResourceThrottle(cus, crx_id); - rt->set_controller_for_testing(controller); - controller->SetThrottle(rt); - return rt; -} - -void RequestAndDeleteResourceThrottle(ComponentUpdateService* cus, - const char* crx_id) { - // By requesting a throttle and deleting it immediately we ensure that we - // hit the case where the component updater tries to use the weak - // pointer to a dead Resource throttle. - class NoCallResourceController : public TestResourceController { - public: - ~NoCallResourceController() override {} - void Cancel() override { CHECK(false); } - void CancelAndIgnore() override { CHECK(false); } - void CancelWithError(int error_code) override { CHECK(false); } - void Resume() override { CHECK(false); } - } controller; - - delete RequestTestResourceThrottle(cus, &controller, crx_id); -} - -TEST_F(ComponentUpdaterTest, ResourceThrottleDeletedNoUpdate) { - MockServiceObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - scoped_refptr<TestInstaller> installer(new TestInstaller); - CrxComponent com; - component_updater()->AddObserver(&observer); - EXPECT_EQ(Status::kOk, RegisterComponent(&com, kTestComponent_abag, - Version("1.1"), installer)); - // The following two calls ensure that we don't do an update check via the - // timer, so the only update check should be the on-demand one. - test_configurator()->SetInitialDelay(1000000); - test_configurator()->SetRecheckTime(1000000); - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - - RunThreadsUntilIdle(); - - EXPECT_EQ(0, post_interceptor_->GetHitCount()); - - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, - base::Bind(&RequestAndDeleteResourceThrottle, - component_updater(), - "abagagagagagagagagagagagagagagag")); - - RunThreads(); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()); - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(0, installer->install_count()); - - component_updater()->Stop(); -} - -class CancelResourceController : public TestResourceController { - public: - CancelResourceController() : throttle_(NULL), resume_called_(0) {} - ~CancelResourceController() override { - // Check that the throttle has been resumed by the time we - // exit the test. - CHECK_EQ(1, resume_called_); - delete throttle_; - } - void Cancel() override { CHECK(false); } - void CancelAndIgnore() override { CHECK(false); } - void CancelWithError(int error_code) override { CHECK(false); } - void Resume() override { - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, - base::Bind(&CancelResourceController::ResumeCalled, - base::Unretained(this))); - } - void SetThrottle(content::ResourceThrottle* throttle) override { - throttle_ = throttle; - bool defer = false; - // Initially the throttle is blocked. The CUS needs to run a - // task on the UI thread to decide if it should unblock. - throttle_->WillStartRequest(&defer); - CHECK(defer); - } - - private: - void ResumeCalled() { ++resume_called_; } - - content::ResourceThrottle* throttle_; - int resume_called_; -}; - -// Tests the on-demand update with resource throttle, including the -// cooldown interval between calls. -TEST_F(ComponentUpdaterTest, ResourceThrottleLiveNoUpdate) { - MockServiceObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - } - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - scoped_refptr<TestInstaller> installer(new TestInstaller); - CrxComponent com; - component_updater()->AddObserver(&observer); - EXPECT_EQ(Status::kOk, RegisterComponent(&com, kTestComponent_abag, - Version("1.1"), installer)); - // The following two calls ensure that we don't do an update check via the - // timer, so the only update check should be the on-demand one. - test_configurator()->SetInitialDelay(1000000); - test_configurator()->SetRecheckTime(1000000); - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - - RunThreadsUntilIdle(); - - EXPECT_EQ(0, post_interceptor_->GetHitCount()); - - { - // First on-demand update check is expected to succeeded. - CancelResourceController controller; - - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(base::IgnoreResult(&RequestTestResourceThrottle), - component_updater(), - &controller, - "abagagagagagagagagagagagagagagag")); - - RunThreads(); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()); - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(0, installer->install_count()); - - component_updater()->Stop(); - } - - { - // Second on-demand update check is expected to succeed as well, since there - // is no cooldown interval between calls, due to calling SetOnDemandTime. - test_configurator()->SetOnDemandTime(0); - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - - CancelResourceController controller; - - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(base::IgnoreResult(&RequestTestResourceThrottle), - component_updater(), - &controller, - "abagagagagagagagagagagagagagagag")); - - RunThreads(); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()); - EXPECT_EQ(0, installer->error()); - EXPECT_EQ(0, installer->install_count()); - - component_updater()->Stop(); - } - - { - // This on-demand call is expected not to trigger a component update check. - test_configurator()->SetOnDemandTime(1000000); - component_updater()->Start(); - - CancelResourceController controller; - - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(base::IgnoreResult(&RequestTestResourceThrottle), - component_updater(), - &controller, - "abagagagagagagagagagagagagagagag")); - RunThreadsUntilIdle(); - } -} - -// Tests adding and removing observers. -TEST_F(ComponentUpdaterTest, Observer) { - MockServiceObserver observer1, observer2; - - // Expect that two observers see the events. - { - InSequence seq; - EXPECT_CALL(observer1, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer1, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")) - .Times(1); - EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")) - .Times(1); - EXPECT_CALL(observer1, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - component_updater()->AddObserver(&observer1); - component_updater()->AddObserver(&observer2); - - scoped_refptr<TestInstaller> installer(new TestInstaller); - CrxComponent com; - EXPECT_EQ(Status::kOk, RegisterComponent(&com, kTestComponent_abag, - Version("1.1"), installer)); - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - RunThreads(); - - // After removing the first observer, it's only the second observer that - // gets the events. - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); - { - InSequence seq; - EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_UPDATER_STARTED, "")) - .Times(1); - EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")) - .Times(1); - EXPECT_CALL(observer2, OnEvent(Events::COMPONENT_UPDATER_SLEEPING, "")) - .Times(1); - } - - component_updater()->RemoveObserver(&observer1); - - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - RunThreads(); - - // Both observers are removed and no one gets the events. - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer1)); - EXPECT_TRUE(Mock::VerifyAndClearExpectations(&observer2)); - component_updater()->RemoveObserver(&observer2); - - test_configurator()->SetLoopCount(1); - component_updater()->Start(); - RunThreads(); - - component_updater()->Stop(); -} - -} // namespace component_updater
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.h b/chrome/browser/component_updater/test/component_updater_service_unittest.h deleted file mode 100644 index 3052824..0000000 --- a/chrome/browser/component_updater/test/component_updater_service_unittest.h +++ /dev/null
@@ -1,102 +0,0 @@ -// Copyright 2013 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 CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_UPDATER_SERVICE_UNITTEST_H_ -#define CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_UPDATER_SERVICE_UNITTEST_H_ - -#include <string> - -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "components/component_updater/component_updater_service.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace net { -class LocalHostTestURLRequestInterceptor; -} - -namespace update_client { -struct CrxComponent; -class InterceptorFactory; -class TestConfigurator; -class TestInstaller; -class URLRequestPostInterceptor; -} - -namespace component_updater { - -// Intercepts HTTP GET requests sent to "localhost". -typedef net::LocalHostTestURLRequestInterceptor GetInterceptor; - -class ComponentUpdaterTest : public testing::Test { - public: - enum TestComponents { - kTestComponent_abag, - kTestComponent_jebg, - kTestComponent_ihfo, - }; - - ComponentUpdaterTest(); - - ~ComponentUpdaterTest() override; - - void SetUp() override; - - void TearDown() override; - - ComponentUpdateService* component_updater(); - - // Makes the full path to a component updater test file. - const base::FilePath test_file(const char* file); - - scoped_refptr<update_client::TestConfigurator> test_configurator(); - - ComponentUpdateService::Status RegisterComponent( - update_client::CrxComponent* com, - TestComponents component, - const Version& version, - const scoped_refptr<update_client::TestInstaller>& installer); - - protected: - void RunThreads(); - void RunThreadsUntilIdle(); - - scoped_ptr<update_client::InterceptorFactory> interceptor_factory_; - - // Owned by the factory. - update_client::URLRequestPostInterceptor* post_interceptor_; - - scoped_ptr<GetInterceptor> get_interceptor_; - - private: - content::TestBrowserThreadBundle thread_bundle_; - scoped_refptr<update_client::TestConfigurator> test_config_; - scoped_ptr<ComponentUpdateService> component_updater_; -}; - -const char expected_crx_url[] = - "http://localhost/download/jebgalgnebhfojomionfpkfelancnnkf.crx"; - -class MockServiceObserver : public ServiceObserver { - public: - MockServiceObserver(); - ~MockServiceObserver(); - MOCK_METHOD2(OnEvent, void(Events event, const std::string&)); -}; - -class OnDemandTester { - public: - static ComponentUpdateService::Status OnDemand( - ComponentUpdateService* cus, - const std::string& component_id); -}; - -} // namespace component_updater - -#endif // CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_UPDATER_SERVICE_UNITTEST_H_
diff --git a/chrome/browser/content_settings/content_settings_default_provider_unittest.cc b/chrome/browser/content_settings/content_settings_default_provider_unittest.cc index c477a00..7a9b35e 100644 --- a/chrome/browser/content_settings/content_settings_default_provider_unittest.cc +++ b/chrome/browser/content_settings/content_settings_default_provider_unittest.cc
@@ -13,6 +13,7 @@ #include "components/content_settings/core/browser/content_settings_default_provider.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/test/content_settings_test_utils.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -26,6 +27,7 @@ ~DefaultProviderTest() override { provider_.ShutdownOnUIThread(); } protected: + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; content_settings::DefaultProvider provider_; };
diff --git a/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc b/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc index 0bf6e4d..ff861bd 100644 --- a/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc +++ b/chrome/browser/content_settings/content_settings_policy_provider_unittest.cc
@@ -20,6 +20,7 @@ #include "components/content_settings/core/browser/content_settings_rule.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/test/content_settings_test_utils.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -29,7 +30,11 @@ typedef std::vector<Rule> Rules; -TEST(PolicyProviderTest, DefaultGeolocationContentSetting) { +class PolicyProviderTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(PolicyProviderTest, DefaultGeolocationContentSetting) { TestingProfile profile; TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService(); PolicyProvider provider(prefs); @@ -63,7 +68,7 @@ provider.ShutdownOnUIThread(); } -TEST(PolicyProviderTest, ManagedDefaultContentSettings) { +TEST_F(PolicyProviderTest, ManagedDefaultContentSettings) { TestingProfile profile; TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService(); PolicyProvider provider(prefs); @@ -90,7 +95,7 @@ // When a default-content-setting is set to a managed setting a // CONTENT_SETTINGS_CHANGED notification should be fired. The same should happen // if the managed setting is removed. -TEST(PolicyProviderTest, ObserveManagedSettingsChange) { +TEST_F(PolicyProviderTest, ObserveManagedSettingsChange) { TestingProfile profile; TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService(); PolicyProvider provider(prefs); @@ -117,7 +122,7 @@ provider.ShutdownOnUIThread(); } -TEST(PolicyProviderTest, GettingManagedContentSettings) { +TEST_F(PolicyProviderTest, GettingManagedContentSettings) { TestingProfile profile; TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService(); @@ -189,7 +194,7 @@ provider.ShutdownOnUIThread(); } -TEST(PolicyProviderTest, ResourceIdentifier) { +TEST_F(PolicyProviderTest, ResourceIdentifier) { TestingProfile profile; TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService(); @@ -226,7 +231,7 @@ provider.ShutdownOnUIThread(); } -TEST(PolicyProviderTest, AutoSelectCertificateList) { +TEST_F(PolicyProviderTest, AutoSelectCertificateList) { TestingProfile profile; TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService();
diff --git a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc index e502981..6386a75 100644 --- a/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc +++ b/chrome/browser/content_settings/content_settings_pref_provider_unittest.cc
@@ -31,6 +31,7 @@ #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/test/content_settings_test_utils.h" #include "components/pref_registry/pref_registry_syncable.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -90,7 +91,11 @@ DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerObserver); }; -TEST(PrefProviderTest, Observer) { +class PrefProviderTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(PrefProviderTest, Observer) { TestingProfile profile; PrefProvider pref_content_settings_provider(profile.GetPrefs(), false); @@ -117,7 +122,7 @@ // Test for regression in which the PrefProvider modified the user pref store // of the OTR unintentionally: http://crbug.com/74466. -TEST(PrefProviderTest, Incognito) { +TEST_F(PrefProviderTest, Incognito) { PersistentPrefStore* user_prefs = new TestingPrefStore(); OverlayUserPrefStore* otr_user_prefs = new OverlayUserPrefStore(user_prefs); @@ -184,7 +189,7 @@ pref_content_settings_provider_incognito.ShutdownOnUIThread(); } -TEST(PrefProviderTest, GetContentSettingsValue) { +TEST_F(PrefProviderTest, GetContentSettingsValue) { TestingProfile testing_profile; PrefProvider provider(testing_profile.GetPrefs(), false); @@ -246,7 +251,7 @@ provider.ShutdownOnUIThread(); } -TEST(PrefProviderTest, Patterns) { +TEST_F(PrefProviderTest, Patterns) { TestingProfile testing_profile; PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(), false); @@ -335,7 +340,7 @@ pref_content_settings_provider.ShutdownOnUIThread(); } -TEST(PrefProviderTest, ResourceIdentifier) { +TEST_F(PrefProviderTest, ResourceIdentifier) { TestingProfile testing_profile; PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(), false); @@ -371,7 +376,7 @@ pref_content_settings_provider.ShutdownOnUIThread(); } -TEST(PrefProviderTest, AutoSubmitCertificateContentSetting) { +TEST_F(PrefProviderTest, AutoSubmitCertificateContentSetting) { TestingProfile profile; TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService(); GURL primary_url("https://www.example.com"); @@ -405,7 +410,7 @@ } // http://crosbug.com/17760 -TEST(PrefProviderTest, Deadlock) { +TEST_F(PrefProviderTest, Deadlock) { TestingPrefServiceSyncable prefs; PrefProvider::RegisterProfilePrefs(prefs.registry()); @@ -428,7 +433,7 @@ provider.ShutdownOnUIThread(); } -TEST(PrefProviderTest, LastUsage) { +TEST_F(PrefProviderTest, LastUsage) { TestingProfile testing_profile; PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(), false); @@ -468,7 +473,7 @@ // aggregate dictionary preferences for all content settings types and the new // dictionary preferences for individual types. Remove this when the migration // period is over. -TEST(PrefProviderTest, SyncingOldToNew) { +TEST_F(PrefProviderTest, SyncingOldToNew) { TestingPrefServiceSyncable prefs; PrefProvider::RegisterProfilePrefs(prefs.registry()); PrefProvider provider(&prefs, false); @@ -554,7 +559,7 @@ provider.ShutdownOnUIThread(); } -TEST(PrefProviderTest, SyncingNewToOld) { +TEST_F(PrefProviderTest, SyncingNewToOld) { TestingPrefServiceSyncable prefs; PrefProvider::RegisterProfilePrefs(prefs.registry()); PrefProvider provider(&prefs, false); @@ -643,7 +648,7 @@ } #if defined(OS_CHROMEOS) || defined(OS_ANDROID) -TEST(PrefProviderTest, PMIMigrateOnlyAllow) { +TEST_F(PrefProviderTest, PMIMigrateOnlyAllow) { TestingPrefServiceSyncable prefs; PrefProvider::RegisterProfilePrefs(prefs.registry()); @@ -684,7 +689,7 @@ } #endif -TEST(PrefProviderTest, PrefsMigrateVerbatim) { +TEST_F(PrefProviderTest, PrefsMigrateVerbatim) { TestingPrefServiceSyncable prefs; PrefProvider::RegisterProfilePrefs(prefs.registry()); @@ -735,7 +740,7 @@ provider.ShutdownOnUIThread(); } -TEST(PrefProviderTest, IncognitoInheritsValueMap) { +TEST_F(PrefProviderTest, IncognitoInheritsValueMap) { TestingPrefServiceSyncable prefs; PrefProvider::RegisterProfilePrefs(prefs.registry()); @@ -802,7 +807,7 @@ normal_provider.ShutdownOnUIThread(); } -TEST(PrefProviderTest, ClearAllContentSettingsRules) { +TEST_F(PrefProviderTest, ClearAllContentSettingsRules) { TestingPrefServiceSyncable prefs; PrefProvider::RegisterProfilePrefs(prefs.registry());
diff --git a/chrome/browser/content_settings/permission_context_base.cc b/chrome/browser/content_settings/permission_context_base.cc index ede79e3..60b7438 100644 --- a/chrome/browser/content_settings/permission_context_base.cc +++ b/chrome/browser/content_settings/permission_context_base.cc
@@ -11,13 +11,13 @@ #include "chrome/browser/content_settings/permission_queue_controller.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" -#include "chrome/common/origin_util.h" #include "chrome/common/pref_names.h" #include "components/content_settings/core/browser/content_settings_utils.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/permission_request_id.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/origin_util.h" PermissionContextBase::PermissionContextBase( Profile* profile, @@ -107,7 +107,7 @@ // The Web MIDI SYSEX API is only available to secure origins. if (permission_type_ == CONTENT_SETTINGS_TYPE_MIDI_SYSEX && - !IsOriginSecure(requesting_origin)) { + !content::IsOriginSecure(requesting_origin)) { NotifyPermissionSet(id, requesting_origin, embedding_origin, callback, false /* persist */, CONTENT_SETTING_BLOCK); return;
diff --git a/chrome/browser/crash_upload_list_win.h b/chrome/browser/crash_upload_list_win.h index 8e1393a0..28e99cab 100644 --- a/chrome/browser/crash_upload_list_win.h +++ b/chrome/browser/crash_upload_list_win.h
@@ -16,7 +16,7 @@ protected: // Loads the list of crashes from the Windows Event Log. - virtual void LoadUploadList() override; + void LoadUploadList() override; private: // Returns whether the event record is likely a Chrome crash log.
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.cc b/chrome/browser/custom_handlers/protocol_handler_registry.cc index 88a20e35..43b1b20 100644 --- a/chrome/browser/custom_handlers/protocol_handler_registry.cc +++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc
@@ -727,18 +727,11 @@ // static void ProtocolHandlerRegistry::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(prefs::kRegisteredProtocolHandlers, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kIgnoredProtocolHandlers, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kPolicyRegisteredProtocolHandlers, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kPolicyIgnoredProtocolHandlers, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kCustomHandlersEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kRegisteredProtocolHandlers); + registry->RegisterListPref(prefs::kIgnoredProtocolHandlers); + registry->RegisterListPref(prefs::kPolicyRegisteredProtocolHandlers); + registry->RegisterListPref(prefs::kPolicyIgnoredProtocolHandlers); + registry->RegisterBooleanPref(prefs::kCustomHandlersEnabled, true); } ProtocolHandlerRegistry::~ProtocolHandlerRegistry() {
diff --git a/chrome/browser/devtools/device/port_forwarding_controller.cc b/chrome/browser/devtools/device/port_forwarding_controller.cc index cd7dc34..521be62 100644 --- a/chrome/browser/devtools/device/port_forwarding_controller.cc +++ b/chrome/browser/devtools/device/port_forwarding_controller.cc
@@ -39,7 +39,6 @@ kStatusDisconnecting = -2, kStatusConnecting = -1, kStatusOK = 0, - // Positive values are used to count open connections. }; namespace tethering = ::chrome::devtools::Tethering; @@ -48,40 +47,29 @@ class SocketTunnel : public base::NonThreadSafe { public: - typedef base::Callback<void(int)> CounterCallback; - static void StartTunnel(const std::string& host, int port, - const CounterCallback& callback, int result, scoped_ptr<net::StreamSocket> socket) { - if (result < 0) - return; - SocketTunnel* tunnel = new SocketTunnel(callback); - tunnel->Start(socket.Pass(), host, port); + if (result == net::OK) + new SocketTunnel(socket.Pass(), host, port); } private: - explicit SocketTunnel(const CounterCallback& callback) - : pending_writes_(0), - pending_destruction_(false), - callback_(callback), - about_to_destroy_(false) { - callback_.Run(1); - } - - void Start(scoped_ptr<net::StreamSocket> socket, - const std::string& host, int port) { - remote_socket_.swap(socket); - - host_resolver_ = net::HostResolver::CreateDefaultResolver(NULL); + SocketTunnel(scoped_ptr<net::StreamSocket> socket, + const std::string& host, + int port) + : remote_socket_(socket.Pass()), + pending_writes_(0), + pending_destruction_(false) { + host_resolver_ = net::HostResolver::CreateDefaultResolver(nullptr); net::HostResolver::RequestInfo request_info(net::HostPortPair(host, port)); int result = host_resolver_->Resolve( request_info, net::DEFAULT_PRIORITY, &address_list_, base::Bind(&SocketTunnel::OnResolved, base::Unretained(this)), - NULL, + nullptr, net::BoundNetLog()); if (result != net::ERR_IO_PENDING) OnResolved(result); @@ -93,7 +81,7 @@ return; } - host_socket_.reset(new net::TCPClientSocket(address_list_, NULL, + host_socket_.reset(new net::TCPClientSocket(address_list_, nullptr, net::NetLog::Source())); result = host_socket_->Connect(base::Bind(&SocketTunnel::OnConnected, base::Unretained(this))); @@ -101,15 +89,6 @@ OnConnected(result); } - ~SocketTunnel() { - about_to_destroy_ = true; - if (host_socket_) - host_socket_->Disconnect(); - if (remote_socket_) - remote_socket_->Disconnect(); - callback_.Run(-1); - } - void OnConnected(int result) { if (result < 0) { SelfDestruct(); @@ -195,11 +174,6 @@ } void SelfDestruct() { - // In case one of the connections closes, we could get here - // from another one due to Disconnect firing back on all - // read callbacks. - if (about_to_destroy_) - return; if (pending_writes_ > 0) { pending_destruction_ = true; return; @@ -213,8 +187,6 @@ net::AddressList address_list_; int pending_writes_; bool pending_destruction_; - CounterCallback callback_; - bool about_to_destroy_; }; } // namespace @@ -254,10 +226,6 @@ void ProcessBindResponse(int port, PortStatus status); void ProcessUnbindResponse(int port, PortStatus status); - static void UpdateSocketCountOnHandlerThread( - base::WeakPtr<Connection> weak_connection, int port, int increment); - void UpdateSocketCount(int port, int increment); - // DevToolsAndroidBridge::AndroidWebSocket::Delegate implementation: void OnSocketOpened() override; void OnFrameRead(const std::string& message) override; @@ -271,7 +239,6 @@ ForwardingMap forwarding_map_; CommandCallbackMap pending_responses_; PortStatusMap port_status_; - base::WeakPtrFactory<Connection> weak_factory_; DISALLOW_COPY_AND_ASSIGN(Connection); }; @@ -284,8 +251,7 @@ browser_(browser), command_id_(0), connected_(false), - forwarding_map_(forwarding_map), - weak_factory_(this) { + forwarding_map_(forwarding_map) { DCHECK_CURRENTLY_ON(BrowserThread::UI); controller_->registry_[browser->serial()] = this; scoped_refptr<AndroidDeviceManager::Device> device( @@ -403,27 +369,6 @@ port_status_.erase(it); } -// static -void PortForwardingController::Connection::UpdateSocketCountOnHandlerThread( - base::WeakPtr<Connection> weak_connection, int port, int increment) { - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(&Connection::UpdateSocketCount, - weak_connection, port, increment)); -} - -void PortForwardingController::Connection::UpdateSocketCount( - int port, int increment) { -#if defined(DEBUG_DEVTOOLS) - DCHECK_CURRENTLY_ON(BrowserThread::UI); - PortStatusMap::iterator it = port_status_.find(port); - if (it == port_status_.end()) - return; - if (it->second < 0 || (it->second == 0 && increment < 0)) - return; - it->second += increment; -#endif // defined(DEBUG_DEVTOOLS) -} - const PortForwardingController::PortStatusMap& PortForwardingController::Connection::GetPortStatusMap() { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -473,10 +418,6 @@ return; std::string destination_host = tokens[0]; - SocketTunnel::CounterCallback callback = - base::Bind(&Connection::UpdateSocketCountOnHandlerThread, - weak_factory_.GetWeakPtr(), port); - scoped_refptr<AndroidDeviceManager::Device> device( controller_->bridge_->FindDevice(browser_->serial())); DCHECK(device.get()); @@ -484,8 +425,7 @@ connection_id.c_str(), base::Bind(&SocketTunnel::StartTunnel, destination_host, - destination_port, - callback)); + destination_port)); } PortForwardingController::PortForwardingController(
diff --git a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc index 1eab6e8..035c39b 100644 --- a/chrome/browser/devtools/device/usb/android_usb_browsertest.cc +++ b/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -120,11 +120,11 @@ broken_(false) { } - virtual scoped_refptr<UsbDevice> GetDevice() const override { + scoped_refptr<UsbDevice> GetDevice() const override { return device_; } - virtual void Close() override { device_ = nullptr; } + void Close() override { device_ = nullptr; } void SetConfiguration(int configuration_value, const ResultCallback& callback) override {
diff --git a/chrome/browser/devtools/devtools_network_controller_unittest.cc b/chrome/browser/devtools/devtools_network_controller_unittest.cc index 3046e9b..de428fc0 100644 --- a/chrome/browser/devtools/devtools_network_controller_unittest.cc +++ b/chrome/browser/devtools/devtools_network_controller_unittest.cc
@@ -18,6 +18,12 @@ namespace test { +using net::kSimpleGET_Transaction; +using net::MockHttpRequest; +using net::MockNetworkLayer; +using net::MockTransaction; +using net::TEST_MODE_SYNC_NET_START; + const char kClientId[] = "42"; const char kAnotherClientId[] = "24";
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 3f751d3..9e134e3b 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -773,7 +773,7 @@ void DevToolsUIBindings::RecordEnumeratedHistogram(const std::string& name, int sample, int boundary_value) { - if (!(boundary_value >= 0 && boundary_value < 100 && sample >= 0 && + if (!(boundary_value >= 0 && boundary_value <= 100 && sample >= 0 && sample < boundary_value)) { frontend_host_->BadMessageRecieved(); return;
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index 5706f4a..d069412 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc
@@ -304,34 +304,17 @@ // static void DevToolsWindow::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kDevToolsEditedFiles, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kDevToolsFileSystemPaths, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDevToolsAdbKey, std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kDevToolsEditedFiles); + registry->RegisterDictionaryPref(prefs::kDevToolsFileSystemPaths); + registry->RegisterStringPref(prefs::kDevToolsAdbKey, std::string()); - registry->RegisterBooleanPref( - prefs::kDevToolsDiscoverUsbDevicesEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDevToolsPortForwardingEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDevToolsPortForwardingDefaultSet, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kDevToolsPortForwardingConfig, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kDevToolsPreferences, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kDevToolsDiscoverUsbDevicesEnabled, + true); + registry->RegisterBooleanPref(prefs::kDevToolsPortForwardingEnabled, false); + registry->RegisterBooleanPref(prefs::kDevToolsPortForwardingDefaultSet, + false); + registry->RegisterDictionaryPref(prefs::kDevToolsPortForwardingConfig); + registry->RegisterDictionaryPref(prefs::kDevToolsPreferences); } // static
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc index ad2b94ba..b1bae98 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.cc +++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -213,7 +213,7 @@ } void ChromeDownloadManagerDelegate::SetNextId(uint32 next_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!profile_->IsOffTheRecord()); DCHECK_NE(content::DownloadItem::kInvalidId, next_id); next_download_id_ = next_id; @@ -228,7 +228,7 @@ void ChromeDownloadManagerDelegate::GetNextId( const content::DownloadIdCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (profile_->IsOffTheRecord()) { content::BrowserContext::GetDownloadManager( profile_->GetOriginalProfile())->GetDelegate()->GetNextId(callback); @@ -243,7 +243,7 @@ void ChromeDownloadManagerDelegate::ReturnNextId( const content::DownloadIdCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!profile_->IsOffTheRecord()); DCHECK_NE(content::DownloadItem::kInvalidId, next_download_id_); callback.Run(next_download_id_++); @@ -268,7 +268,7 @@ bool ChromeDownloadManagerDelegate::ShouldOpenFileBasedOnExtension( const base::FilePath& path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (path.Extension().empty()) return false; #if defined(ENABLE_EXTENSIONS) @@ -283,7 +283,7 @@ // static void ChromeDownloadManagerDelegate::DisableSafeBrowsing(DownloadItem* item) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(FULL_SAFE_BROWSING) SafeBrowsingState* state = static_cast<SafeBrowsingState*>( item->GetUserData(&kSafeBrowsingUserDataKey)); @@ -298,7 +298,7 @@ bool ChromeDownloadManagerDelegate::IsDownloadReadyForCompletion( DownloadItem* item, const base::Closure& internal_complete_callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(FULL_SAFE_BROWSING) SafeBrowsingState* state = static_cast<SafeBrowsingState*>( item->GetUserData(&kSafeBrowsingUserDataKey)); @@ -516,7 +516,7 @@ DownloadProtectionService* ChromeDownloadManagerDelegate::GetDownloadProtectionService() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(FULL_SAFE_BROWSING) SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); if (sb_service && sb_service->download_protection_service() && @@ -531,7 +531,7 @@ DownloadItem* download, const base::FilePath& virtual_path, const NotifyExtensionsCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(ENABLE_EXTENSIONS) extensions::ExtensionDownloadsEventRouter* router = DownloadServiceFactory::GetForBrowserContext(profile_) @@ -555,7 +555,7 @@ bool create_directory, DownloadPathReservationTracker::FilenameConflictAction conflict_action, const DownloadTargetDeterminerDelegate::ReservedPathCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path.empty()); #if defined(OS_CHROMEOS) // TODO(asanka): Handle path reservations for virtual paths as well. @@ -578,7 +578,7 @@ DownloadItem* download, const base::FilePath& suggested_path, const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(OS_ANDROID) chrome::android::ChromeDownloadManagerOverwriteInfoBarDelegate::Create( InfoBarService::FromWebContents(download->GetWebContents()), @@ -592,7 +592,7 @@ DownloadItem* download, const base::FilePath& virtual_path, const DownloadTargetDeterminerDelegate::LocalPathCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(OS_CHROMEOS) drive::DownloadHandler* drive_download_handler = drive::DownloadHandler::GetForProfile(profile_); @@ -609,7 +609,7 @@ DownloadItem* download, const base::FilePath& suggested_path, const CheckDownloadUrlCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(FULL_SAFE_BROWSING) safe_browsing::DownloadProtectionService* service = @@ -632,7 +632,7 @@ void ChromeDownloadManagerDelegate::GetFileMimeType( const base::FilePath& path, const GetFileMimeTypeCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); base::PostTaskAndReplyWithResult(BrowserThread::GetBlockingPool(), FROM_HERE, base::Bind(&GetMimeType, path), @@ -712,7 +712,7 @@ int32 download_id, const content::DownloadTargetCallback& callback, scoped_ptr<DownloadTargetInfo> target_info) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DownloadItem* item = download_manager_->GetDownload(download_id); if (item) { if (!target_info->target_path.empty() &&
diff --git a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc index fdda636..913612e 100644 --- a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc +++ b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
@@ -74,22 +74,21 @@ : ChromeDownloadManagerDelegate(profile) { } - virtual ~TestChromeDownloadManagerDelegate() {} + ~TestChromeDownloadManagerDelegate() override {} - virtual safe_browsing::DownloadProtectionService* + safe_browsing::DownloadProtectionService* GetDownloadProtectionService() override { return NULL; } - virtual void NotifyExtensions( - content::DownloadItem* download, - const base::FilePath& suggested_virtual_path, - const NotifyExtensionsCallback& callback) override { + void NotifyExtensions(content::DownloadItem* download, + const base::FilePath& suggested_virtual_path, + const NotifyExtensionsCallback& callback) override { callback.Run(base::FilePath(), DownloadPathReservationTracker::UNIQUIFY); } - virtual void ReserveVirtualPath( + void ReserveVirtualPath( content::DownloadItem* download, const base::FilePath& virtual_path, bool create_directory, @@ -102,7 +101,7 @@ FROM_HERE, base::Bind(callback, virtual_path, true)); } - virtual void PromptUserForDownloadPath( + void PromptUserForDownloadPath( DownloadItem* download, const base::FilePath& suggested_path, const DownloadTargetDeterminerDelegate::FileSelectedCallback& callback)
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index cc4bb59..39caea3 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -3427,9 +3427,9 @@ final_state_seen_(false) { Init(); } - virtual ~DisableSafeBrowsingOnInProgressDownload() {} + ~DisableSafeBrowsingOnInProgressDownload() override {} - virtual bool IsDownloadInFinalState(DownloadItem* download) override { + bool IsDownloadInFinalState(DownloadItem* download) override { if (download->GetState() != DownloadItem::IN_PROGRESS || download->GetTargetFilePath().empty()) return false;
diff --git a/chrome/browser/download/download_crx_util.cc b/chrome/browser/download/download_crx_util.cc index 28ba4ab..6a2ed63 100644 --- a/chrome/browser/download/download_crx_util.cc +++ b/chrome/browser/download/download_crx_util.cc
@@ -94,7 +94,7 @@ scoped_refptr<extensions::CrxInstaller> OpenChromeExtension( Profile* profile, const DownloadItem& download_item) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); scoped_refptr<extensions::CrxInstaller> installer( CreateCrxInstaller(profile, download_item));
diff --git a/chrome/browser/download/download_history.cc b/chrome/browser/download/download_history.cc index 05c5a5d7..becc0e5 100644 --- a/chrome/browser/download/download_history.cc +++ b/chrome/browser/download/download_history.cc
@@ -212,7 +212,7 @@ loading_id_(content::DownloadItem::kInvalidId), history_size_(0), weak_ptr_factory_(this) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::DownloadManager::DownloadVector items; notifier_.GetManager()->GetAllDownloads(&items); for (content::DownloadManager::DownloadVector::const_iterator @@ -224,24 +224,24 @@ } DownloadHistory::~DownloadHistory() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); FOR_EACH_OBSERVER(Observer, observers_, OnDownloadHistoryDestroyed()); observers_.Clear(); } void DownloadHistory::AddObserver(DownloadHistory::Observer* observer) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); observers_.AddObserver(observer); } void DownloadHistory::RemoveObserver(DownloadHistory::Observer* observer) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); observers_.RemoveObserver(observer); } bool DownloadHistory::WasRestoredFromHistory( const content::DownloadItem* download) const { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const DownloadHistoryData* data = DownloadHistoryData::Get(download); // The OnDownloadCreated handler sets the was_restored_from_history flag when @@ -253,7 +253,7 @@ } void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // ManagerGoingDown() may have happened before the history loaded. if (!notifier_.GetManager()) return; @@ -293,7 +293,7 @@ } void DownloadHistory::MaybeAddToHistory(content::DownloadItem* item) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); uint32 download_id = item->GetId(); DownloadHistoryData* data = DownloadHistoryData::Get(item); @@ -371,7 +371,7 @@ void DownloadHistory::OnDownloadCreated( content::DownloadManager* manager, content::DownloadItem* item) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // All downloads should pass through OnDownloadCreated exactly once. CHECK(!DownloadHistoryData::Get(item)); @@ -389,7 +389,7 @@ void DownloadHistory::OnDownloadUpdated( content::DownloadManager* manager, content::DownloadItem* item) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DownloadHistoryData* data = DownloadHistoryData::Get(item); if (data->state() == DownloadHistoryData::NOT_PERSISTED) { @@ -424,7 +424,7 @@ void DownloadHistory::OnDownloadRemoved( content::DownloadManager* manager, content::DownloadItem* item) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DownloadHistoryData* data = DownloadHistoryData::Get(item); if (data->state() != DownloadHistoryData::PERSISTED) { @@ -445,7 +445,7 @@ } void DownloadHistory::ScheduleRemoveDownload(uint32 download_id) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // For database efficiency, batch removals together if they happen all at // once. @@ -458,7 +458,7 @@ } void DownloadHistory::RemoveDownloadsBatch() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); IdSet remove_ids; removing_ids_.swap(remove_ids); history_->RemoveDownloads(remove_ids);
diff --git a/chrome/browser/download/download_history_unittest.cc b/chrome/browser/download/download_history_unittest.cc index 2ffdb948..db441ed 100644 --- a/chrome/browser/download/download_history_unittest.cc +++ b/chrome/browser/download/download_history_unittest.cc
@@ -75,7 +75,7 @@ void QueryDownloads( const history::HistoryService::DownloadQueryCallback& callback) override { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, base::Bind(&FakeHistoryAdapter::QueryDownloadsDone, base::Unretained(this), callback)); @@ -83,7 +83,7 @@ void QueryDownloadsDone( const history::HistoryService::DownloadQueryCallback& callback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); CHECK(expect_query_downloads_.get()); callback.Run(expect_query_downloads_.Pass()); } @@ -93,7 +93,7 @@ void CreateDownload(const history::DownloadRow& info, const history::HistoryService::DownloadCreateCallback& callback) override { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); create_download_info_ = info; // Must not call CreateDownload() again before FinishCreateDownload()! DCHECK(create_download_callback_.is_null()); @@ -104,18 +104,18 @@ } void FinishCreateDownload() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); create_download_callback_.Run(); create_download_callback_.Reset(); } void UpdateDownload(const history::DownloadRow& info) override { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); update_download_ = info; } void RemoveDownloads(const IdSet& ids) override { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); for (IdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) { remove_downloads_.insert(*it); @@ -123,55 +123,55 @@ } void ExpectWillQueryDownloads(scoped_ptr<InfoVector> infos) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); expect_query_downloads_ = infos.Pass(); } void ExpectQueryDownloadsDone() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); EXPECT_TRUE(NULL == expect_query_downloads_.get()); } void FailCreateDownload() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); fail_create_download_ = true; } void ExpectDownloadCreated( const history::DownloadRow& info) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::RunAllPendingInMessageLoop(content::BrowserThread::UI); CheckInfoEqual(info, create_download_info_); create_download_info_ = history::DownloadRow(); } void ExpectNoDownloadCreated() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::RunAllPendingInMessageLoop(content::BrowserThread::UI); CheckInfoEqual(history::DownloadRow(), create_download_info_); } void ExpectDownloadUpdated(const history::DownloadRow& info) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::RunAllPendingInMessageLoop(content::BrowserThread::UI); CheckInfoEqual(update_download_, info); update_download_ = history::DownloadRow(); } void ExpectNoDownloadUpdated() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::RunAllPendingInMessageLoop(content::BrowserThread::UI); CheckInfoEqual(history::DownloadRow(), update_download_); } void ExpectNoDownloadsRemoved() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::RunAllPendingInMessageLoop(content::BrowserThread::UI); EXPECT_EQ(0, static_cast<int>(remove_downloads_.size())); } void ExpectDownloadsRemoved(const IdSet& ids) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::RunAllPendingInMessageLoop(content::BrowserThread::UI); IdSet differences = base::STLSetDifference<IdSet>(ids, remove_downloads_); for (IdSet::const_iterator different = differences.begin(); @@ -222,7 +222,7 @@ } void CreateDownloadHistory(scoped_ptr<InfoVector> infos) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); CHECK(infos.get()); EXPECT_CALL(manager(), AddObserver(_)).WillOnce(WithArg<0>(Invoke( this, &DownloadHistoryTest::SetManagerObserver))); @@ -265,7 +265,7 @@ } void CallOnDownloadCreated(size_t index) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!pre_on_create_handler_.is_null()) pre_on_create_handler_.Run(&item(index)); manager_observer()->OnDownloadCreated(&manager(), &item(index)); @@ -274,60 +274,60 @@ } void CallOnDownloadCreatedInOrder() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Gmock doesn't appear to support something like InvokeWithTheseArgs. Maybe // gmock needs to learn about base::Callback. CallOnDownloadCreated(download_created_index_++); } void set_slow_create_download(bool slow) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->set_slow_create_download(slow); } void FinishCreateDownload() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->FinishCreateDownload(); } void FailCreateDownload() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->FailCreateDownload(); } void ExpectDownloadCreated( const history::DownloadRow& info) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->ExpectDownloadCreated(info); } void ExpectNoDownloadCreated() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->ExpectNoDownloadCreated(); } void ExpectDownloadUpdated(const history::DownloadRow& info) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->ExpectDownloadUpdated(info); } void ExpectNoDownloadUpdated() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->ExpectNoDownloadUpdated(); } void ExpectNoDownloadsRemoved() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->ExpectNoDownloadsRemoved(); } void ExpectDownloadsRemoved(const IdSet& ids) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); history_->ExpectDownloadsRemoved(ids); } void ExpectDownloadsRestoredFromHistory(bool expected_value) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); pre_on_create_handler_ = base::Bind(&DownloadHistoryTest::CheckDownloadWasRestoredFromHistory, base::Unretained(this), @@ -389,7 +389,7 @@ const std::string& by_extension_id, const std::string& by_extension_name, history::DownloadRow* info) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); size_t index = items_.size(); StrictMockDownloadItem* mock_item = new StrictMockDownloadItem();
diff --git a/chrome/browser/download/download_path_reservation_tracker.cc b/chrome/browser/download/download_path_reservation_tracker.cc index 8ced0eee..8492b85 100644 --- a/chrome/browser/download/download_path_reservation_tracker.cc +++ b/chrome/browser/download/download_path_reservation_tracker.cc
@@ -70,7 +70,7 @@ // Returns true if the given path is in use by a path reservation. bool IsPathReserved(const base::FilePath& path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); // No reservation map => no reservations. if (g_reservation_map == NULL) return false; @@ -89,7 +89,7 @@ // Returns true if the given path is in use by any path reservation or the // file system. Called on the FILE thread. bool IsPathInUse(const base::FilePath& path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); // If there is a reservation, then the path is in use. if (IsPathReserved(path)) return true; @@ -155,7 +155,7 @@ bool create_directory, DownloadPathReservationTracker::FilenameConflictAction conflict_action, base::FilePath* reserved_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); DCHECK(suggested_path.IsAbsolute()); // Create a reservation map if one doesn't exist. It will be automatically @@ -249,7 +249,7 @@ // Called on the FILE thread to update the path of the reservation associated // with |key| to |new_path|. void UpdateReservation(ReservationKey key, const base::FilePath& new_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); DCHECK(g_reservation_map != NULL); ReservationMap::iterator iter = g_reservation_map->find(key); if (iter != g_reservation_map->end()) { @@ -265,7 +265,7 @@ // Called on the FILE thread to remove the path reservation associated with // |key|. void RevokeReservation(ReservationKey key) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); DCHECK(g_reservation_map != NULL); DCHECK(ContainsKey(*g_reservation_map, key)); g_reservation_map->erase(key); @@ -280,14 +280,14 @@ const DownloadPathReservationTracker::ReservedPathCallback& callback, const base::FilePath* reserved_path, bool verified) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); callback.Run(*reserved_path, verified); } DownloadItemObserver::DownloadItemObserver(DownloadItem* download_item) : download_item_(download_item), last_target_path_(download_item->GetTargetFilePath()) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); download_item_->AddObserver(this); } @@ -350,7 +350,7 @@ bool create_directory, FilenameConflictAction conflict_action, const ReservedPathCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Attach an observer to the download item so that we know when the target // path changes and/or the download is no longer active. new DownloadItemObserver(download_item);
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index 9597aac..19fc13e5 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc
@@ -183,34 +183,19 @@ prefs::kPromptForDownload, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDownloadExtensionsToOpen, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDownloadDirUpgraded, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kSaveFileType, - content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kDownloadExtensionsToOpen, std::string()); + registry->RegisterBooleanPref(prefs::kDownloadDirUpgraded, false); + registry->RegisterIntegerPref(prefs::kSaveFileType, + content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML); const base::FilePath& default_download_path = GetDefaultDownloadDirectory(); - registry->RegisterFilePathPref( - prefs::kDownloadDefaultDirectory, - default_download_path, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterFilePathPref( - prefs::kSaveFileDefaultDirectory, - default_download_path, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterFilePathPref(prefs::kDownloadDefaultDirectory, + default_download_path); + registry->RegisterFilePathPref(prefs::kSaveFileDefaultDirectory, + default_download_path); #if defined(OS_WIN) || defined(OS_LINUX) || \ (defined(OS_MACOSX) && !defined(OS_IOS)) - registry->RegisterBooleanPref( - prefs::kOpenPdfDownloadInSystemReader, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kOpenPdfDownloadInSystemReader, false); #endif }
diff --git a/chrome/browser/download/download_request_limiter.cc b/chrome/browser/download/download_request_limiter.cc index 9d2117d6..39e3cd0a 100644 --- a/chrome/browser/download/download_request_limiter.cc +++ b/chrome/browser/download/download_request_limiter.cc
@@ -287,7 +287,7 @@ const Callback& callback) { // This is invoked on the IO thread. Schedule the task to run on the UI // thread so that we can query UI state. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(&DownloadRequestLimiter::CanDownload, this, @@ -319,7 +319,7 @@ const GURL& url, const std::string& request_method, const Callback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); content::WebContents* originating_contents = tab_util::GetWebContentsByID(render_process_host_id, render_view_id); @@ -357,7 +357,7 @@ int render_view_id, const std::string& request_method, const Callback& orig_callback, bool allow) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); content::WebContents* originating_contents = tab_util::GetWebContentsByID(render_process_host_id, render_view_id); if (!originating_contents || !allow) {
diff --git a/chrome/browser/download/download_request_limiter_unittest.cc b/chrome/browser/download/download_request_limiter_unittest.cc index 4cfc555..46c4243 100644 --- a/chrome/browser/download/download_request_limiter_unittest.cc +++ b/chrome/browser/download/download_request_limiter_unittest.cc
@@ -66,6 +66,7 @@ void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); + profile_.reset(new TestingProfile()); InfoBarService::CreateForWebContents(web_contents()); PermissionBubbleManager::CreateForWebContents(web_contents()); @@ -80,7 +81,7 @@ &DownloadRequestLimiterTest::FakeCreate, base::Unretained(this)); DownloadRequestInfoBarDelegate::SetCallbackForTesting( &fake_create_callback_); - content_settings_ = new HostContentSettingsMap(profile_.GetPrefs(), false); + content_settings_ = new HostContentSettingsMap(profile_->GetPrefs(), false); DownloadRequestLimiter::SetContentSettingsForTesting( content_settings_.get()); } @@ -198,7 +199,7 @@ private: DownloadRequestInfoBarDelegate::FakeCreateCallback fake_create_callback_; - TestingProfile profile_; + scoped_ptr<TestingProfile> profile_; scoped_ptr<FakePermissionBubbleView> view_; };
diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc index ee41e0a0..7a7dfb8 100644 --- a/chrome/browser/download/download_target_determiner.cc +++ b/chrome/browser/download/download_target_determiner.cc
@@ -100,7 +100,7 @@ delegate_(delegate), completion_callback_(callback), weak_ptr_factory_(this) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(download_); DCHECK(delegate); download_->AddObserver(this); @@ -109,7 +109,7 @@ } DownloadTargetDeterminer::~DownloadTargetDeterminer() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(download_); DCHECK(completion_callback_.is_null()); download_->RemoveObserver(this); @@ -170,7 +170,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoGenerateTargetPath() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(local_path_.empty()); DCHECK(!should_prompt_); DCHECK(!should_notify_extensions_); @@ -240,7 +240,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoNotifyExtensions() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty()); next_state_ = STATE_RESERVE_VIRTUAL_PATH; @@ -257,7 +257,7 @@ void DownloadTargetDeterminer::NotifyExtensionsDone( const base::FilePath& suggested_path, DownloadPathReservationTracker::FilenameConflictAction conflict_action) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe(); // Extensions should not call back here more than once. @@ -289,7 +289,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoReserveVirtualPath() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty()); next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH; @@ -303,7 +303,7 @@ void DownloadTargetDeterminer::ReserveVirtualPathDone( const base::FilePath& path, bool verified) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe() << " Verified:" << verified; DCHECK_EQ(STATE_PROMPT_USER_FOR_DOWNLOAD_PATH, next_state_); @@ -315,7 +315,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoPromptUserForDownloadPath() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty()); next_state_ = STATE_DETERMINE_LOCAL_PATH; @@ -333,7 +333,7 @@ void DownloadTargetDeterminer::PromptUserForDownloadPathDone( const base::FilePath& virtual_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(20) << "User selected path:" << virtual_path.AsUTF8Unsafe(); if (virtual_path.empty()) { CancelOnFailureAndDeleteSelf(); @@ -348,7 +348,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoDetermineLocalPath() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty()); DCHECK(local_path_.empty()); @@ -364,7 +364,7 @@ void DownloadTargetDeterminer::DetermineLocalPathDone( const base::FilePath& local_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe(); if (local_path.empty()) { // Path subsitution failed. @@ -379,7 +379,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoDetermineMimeType() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty()); DCHECK(!local_path_.empty()); DCHECK(mime_type_.empty()); @@ -398,7 +398,7 @@ void DownloadTargetDeterminer::DetermineMimeTypeDone( const std::string& mime_type) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(20) << "MIME type: " << mime_type; DCHECK_EQ(STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER, next_state_); @@ -427,7 +427,7 @@ const std::string& mime_type, ActionOnStalePluginList stale_plugin_action, const base::Callback<void(bool)>& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!mime_type.empty()); using content::WebPluginInfo; @@ -461,7 +461,8 @@ bool is_handled_safely = plugin_found && (plugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS || - plugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS); + plugin_info.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS || + plugin_info.type == WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(callback, is_handled_safely)); } @@ -471,7 +472,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoDetermineIfHandledSafely() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty()); DCHECK(!local_path_.empty()); DCHECK(!is_filetype_handled_safely_); @@ -507,7 +508,7 @@ #if defined(ENABLE_PLUGINS) void DownloadTargetDeterminer::DetermineIfHandledSafelyDone( bool is_handled_safely) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(20) << "Is file type handled safely: " << is_filetype_handled_safely_; DCHECK_EQ(STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE, next_state_); is_filetype_handled_safely_ = is_handled_safely; @@ -517,7 +518,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoDetermineIfAdobeReaderUpToDate() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); next_state_ = STATE_CHECK_DOWNLOAD_URL; @@ -544,7 +545,7 @@ #if defined(OS_WIN) void DownloadTargetDeterminer::DetermineIfAdobeReaderUpToDateDone( bool adobe_reader_up_to_date) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(20) << "Is Adobe Reader Up To Date: " << adobe_reader_up_to_date; DCHECK_EQ(STATE_CHECK_DOWNLOAD_URL, next_state_); g_is_adobe_reader_up_to_date_ = adobe_reader_up_to_date; @@ -554,7 +555,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoCheckDownloadUrl() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty()); next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE; delegate_->CheckDownloadUrl( @@ -567,7 +568,7 @@ void DownloadTargetDeterminer::CheckDownloadUrlDone( content::DownloadDangerType danger_type) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(20) << "URL Check Result:" << danger_type; DCHECK_EQ(STATE_CHECK_VISITED_REFERRER_BEFORE, next_state_); danger_type_ = danger_type; @@ -576,7 +577,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH; @@ -624,7 +625,7 @@ void DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone( bool visited_referrer_before) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(STATE_DETERMINE_INTERMEDIATE_PATH, next_state_); if (IsDangerousFile(visited_referrer_before ? VISITED_REFERRER : NO_VISITS_TO_REFERRER)) { @@ -637,7 +638,7 @@ DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoDetermineIntermediatePath() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!virtual_path_.empty()); DCHECK(!local_path_.empty()); DCHECK(intermediate_path_.empty()); @@ -809,7 +810,7 @@ } bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // If the user has has been prompted or will be, assume that the user has // approved the download. A programmatic download is considered safe unless it @@ -868,7 +869,7 @@ void DownloadTargetDeterminer::OnDownloadDestroyed( DownloadItem* download) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(download_, download); CancelOnFailureAndDeleteSelf(); }
diff --git a/chrome/browser/download/download_target_determiner_unittest.cc b/chrome/browser/download/download_target_determiner_unittest.cc index a0b8cde..ca91bc3 100644 --- a/chrome/browser/download/download_target_determiner_unittest.cc +++ b/chrome/browser/download/download_target_determiner_unittest.cc
@@ -194,8 +194,8 @@ class DownloadTargetDeterminerTest : public ChromeRenderViewHostTestHarness { public: // ::testing::Test - virtual void SetUp() override; - virtual void TearDown() override; + void SetUp() override; + void TearDown() override; // Creates MockDownloadItem and sets up default expectations. content::MockDownloadItem* CreateActiveDownloadItem( @@ -1952,17 +1952,17 @@ public: MOCK_METHOD1(MockPluginAvailable, bool(const base::FilePath&)); - virtual bool IsPluginAvailable(int render_process_id, - int render_view_id, - const void* context, - const GURL& url, - const GURL& policy_url, - content::WebPluginInfo* plugin) override { + bool IsPluginAvailable(int render_process_id, + int render_view_id, + const void* context, + const GURL& url, + const GURL& policy_url, + content::WebPluginInfo* plugin) override { return MockPluginAvailable(plugin->path); } - virtual bool CanLoadPlugin(int render_process_id, - const base::FilePath& path) override { + bool CanLoadPlugin(int render_process_id, + const base::FilePath& path) override { return true; } }; @@ -2014,17 +2014,17 @@ DownloadTargetDeterminerTestWithPlugin() : old_plugin_service_filter_(NULL) {} - virtual void SetUp() override { + void SetUp() override { + DownloadTargetDeterminerTest::SetUp(); content::PluginService* plugin_service = content::PluginService::GetInstance(); plugin_service->Init(); plugin_service->DisablePluginsDiscoveryForTesting(); old_plugin_service_filter_ = plugin_service->GetFilter(); plugin_service->SetFilter(&mock_plugin_filter_); - DownloadTargetDeterminerTest::SetUp(); } - virtual void TearDown() override { + void TearDown() override { content::PluginService::GetInstance()->SetFilter( old_plugin_service_filter_); DownloadTargetDeterminerTest::TearDown(); @@ -2106,6 +2106,75 @@ EXPECT_FALSE(target_info->is_filetype_handled_safely); } +// Check if secure handling of filetypes is determined correctly for +// BrowserPlugins. +TEST_F(DownloadTargetDeterminerTestWithPlugin, + TargetDeterminer_CheckForSecureHandling_BrowserPlugin) { + // All test cases run with GetPathInDownloadDir(kInitialPath) as the inital + // path. + const base::FilePath::CharType kInitialPath[] = + FILE_PATH_LITERAL("some_path/bar.txt"); + const char kTestMIMEType[] = "application/x-example-should-not-exist"; + + DownloadTestCase kSecureHandlingTestCase = { + AUTOMATIC, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + "http://example.com/foo.fakeext", "", + FILE_PATH_LITERAL(""), + + FILE_PATH_LITERAL("foo.fakeext"), + DownloadItem::TARGET_DISPOSITION_OVERWRITE, + + EXPECT_CRDOWNLOAD + }; + + content::PluginService* plugin_service = + content::PluginService::GetInstance(); + + // Verify our test assumptions. + { + ForceRefreshOfPlugins(); + std::vector<content::WebPluginInfo> info; + ASSERT_FALSE(plugin_service->GetPluginInfoArray( + GURL(), kTestMIMEType, false, &info, NULL)); + ASSERT_EQ(0u, info.size()) + << "Name: " << info[0].name << ", Path: " << info[0].path.value(); + } + + ON_CALL(*delegate(), GetFileMimeType( + GetPathInDownloadDir(FILE_PATH_LITERAL("foo.fakeext")), _)) + .WillByDefault(WithArg<1>( + ScheduleCallback(kTestMIMEType))); + scoped_ptr<content::MockDownloadItem> item( + CreateActiveDownloadItem(1, kSecureHandlingTestCase)); + scoped_ptr<DownloadTargetInfo> target_info = + RunDownloadTargetDeterminer(GetPathInDownloadDir(kInitialPath), + item.get()); + EXPECT_FALSE(target_info->is_filetype_handled_safely); + + // Register a BrowserPlugin. This should count as handling the filetype + // securely. + ScopedRegisterInternalPlugin browser_plugin( + plugin_service, + content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN, + test_download_dir().AppendASCII("browser_plugin"), + kTestMIMEType, + "fakeext"); + EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(browser_plugin.path())) + .WillRepeatedly(Return(true)); + + target_info = RunDownloadTargetDeterminer( + GetPathInDownloadDir(kInitialPath), item.get()); + EXPECT_TRUE(target_info->is_filetype_handled_safely); + + // Try disabling the plugin. Handling should no longer be considered secure. + EXPECT_CALL(mock_plugin_filter_, MockPluginAvailable(browser_plugin.path())) + .WillRepeatedly(Return(false)); + target_info = RunDownloadTargetDeterminer( + GetPathInDownloadDir(kInitialPath), item.get()); + EXPECT_FALSE(target_info->is_filetype_handled_safely); +} + // Check if secure handling of filetypes is determined correctly for NPAPI // plugins. TEST_F(DownloadTargetDeterminerTestWithPlugin,
diff --git a/chrome/browser/download/notification/download_notification_browsertest.cc b/chrome/browser/download/notification/download_notification_browsertest.cc new file mode 100644 index 0000000..287bbbd4 --- /dev/null +++ b/chrome/browser/download/notification/download_notification_browsertest.cc
@@ -0,0 +1,501 @@ +// 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/command_line.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/download/chrome_download_manager_delegate.h" +#include "chrome/browser/download/download_service.h" +#include "chrome/browser/download/download_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "chromeos/chromeos_switches.h" +#include "components/signin/core/browser/signin_manager_base.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/download_item.h" +#include "content/public/browser/download_manager.h" +#include "grit/theme_resources.h" +#include "net/test/url_request/url_request_slow_download_job.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/message_center/message_center.h" +#include "ui/message_center/message_center_observer.h" +#include "url/gurl.h" + +namespace { + +enum { + DUMMY_ACCOUNT_INDEX = 0, + PRIMARY_ACCOUNT_INDEX = 1, + SECONDARY_ACCOUNT_INDEX_START = 2, +}; + +// Structure to describe an account info. +struct TestAccountInfo { + const char* const email; + const char* const gaia_id; + const char* const hash; + const char* const display_name; +}; + +// Accounts for multi profile test. +static const TestAccountInfo kTestAccounts[] = { + {"__dummy__@invalid.domain", "10000", "hashdummy", "Dummy Account"}, + {"alice@invalid.domain", "10001", "hashalice", "Alice"}, + {"bob@invalid.domain", "10002", "hashbobbo", "Bob"}, + {"charlie@invalid.domain", "10003", "hashcharl", "Charlie"}, +}; + +// Base class observing notification events. +class MessageCenterChangeObserver + : public message_center::MessageCenterObserver { + public: + MessageCenterChangeObserver() { + message_center::MessageCenter::Get()->AddObserver(this); + } + + ~MessageCenterChangeObserver() override { + message_center::MessageCenter::Get()->RemoveObserver(this); + } + + protected: + void RunLoop() { + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); + run_loop_.Run(); + } + + void QuitRunLoop() { + run_loop_.Quit(); + } + + private: + base::RunLoop run_loop_; + + DISALLOW_COPY_AND_ASSIGN(MessageCenterChangeObserver); +}; + +// Class observing of "ADD" notification events. +class NotificationAddObserver : public MessageCenterChangeObserver { + public: + NotificationAddObserver() : count_(1) { + MessageCenterChangeObserver(); + } + explicit NotificationAddObserver(int count) : count_(count) { + MessageCenterChangeObserver(); + } + ~NotificationAddObserver() override {} + + bool Wait() { + if (count_ <= 0) + return count_ == 0; + + waiting_ = true; + RunLoop(); + waiting_ = false; + return count_ == 0; + } + + // message_center::MessageCenterObserver: + void OnNotificationAdded(const std::string& notification_id) override { + count_--; + + if (notification_id_.empty()) + notification_id_ = notification_id; + + if (waiting_) + QuitRunLoop(); + } + + std::string notification_id() { return notification_id_; } + + private: + std::string notification_id_; + bool waiting_ = false; + int count_; + + DISALLOW_COPY_AND_ASSIGN(NotificationAddObserver); +}; + +// Class observing of "UPDATE" notification events. +class NotificationUpdateObserver : public MessageCenterChangeObserver { + public: + NotificationUpdateObserver() : waiting_(false) { + MessageCenterChangeObserver(); + } + ~NotificationUpdateObserver() override {} + + std::string Wait() { + if (!notification_id_.empty()) + return notification_id_; + + waiting_ = true; + RunLoop(); + waiting_ = false; + return notification_id_; + } + + void OnNotificationUpdated(const std::string& notification_id) override { + if (notification_id_.empty()) { + notification_id_ = notification_id; + + if (waiting_) + QuitRunLoop(); + } + } + + private: + std::string notification_id_; + bool waiting_; + + DISALLOW_COPY_AND_ASSIGN(NotificationUpdateObserver); +}; + +class TestChromeDownloadManagerDelegate : public ChromeDownloadManagerDelegate { + public: + explicit TestChromeDownloadManagerDelegate(Profile* profile) + : ChromeDownloadManagerDelegate(profile), opened_(false) {} + ~TestChromeDownloadManagerDelegate() override {} + + // ChromeDownloadManagerDelegate override: + void OpenDownload(content::DownloadItem* item) override { opened_ = true; } + + // Return if the download is opened. + bool opened() const { return opened_; } + + private: + bool opened_; +}; + +// Utility method to retrieve a message center. +message_center::MessageCenter* GetMessageCenter() { + return message_center::MessageCenter::Get(); +} + +// Utility method to retrieve a notification object by id. +message_center::Notification* GetNotification(const std::string& id) { + return GetMessageCenter()->FindVisibleNotificationById(id); +} + +} // anonnymous namespace + +// Base class for tests +class DownloadNotificationTestBase : public InProcessBrowserTest { + public: + ~DownloadNotificationTestBase() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + // TODO(yoshiki): Remove this after the download notification launches. + command_line->AppendSwitch(switches::kEnableDownloadNotification); + } + + void SetUpOnMainThread() override { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler)); + } + + content::DownloadManager* GetDownloadManager(Browser* browser) { + return content::BrowserContext::GetDownloadManager(browser->profile()); + } +}; + +////////////////////////////////////////////////// +// Test with a single profile +////////////////////////////////////////////////// + +class DownloadNotificationTest : public DownloadNotificationTestBase { + public: + ~DownloadNotificationTest() override {} + + void SetUpOnMainThread() override { + Profile* profile = browser()->profile(); + + scoped_ptr<TestChromeDownloadManagerDelegate> test_delegate; + test_delegate.reset(new TestChromeDownloadManagerDelegate(profile)); + test_delegate->GetDownloadIdReceiverCallback().Run( + content::DownloadItem::kInvalidId + 1); + + DownloadServiceFactory::GetForBrowserContext(profile) + ->SetDownloadManagerDelegateForTesting(test_delegate.Pass()); + + DownloadNotificationTestBase::SetUpOnMainThread(); + } + + TestChromeDownloadManagerDelegate* GetDownloadManagerDelegate() const { + return static_cast<TestChromeDownloadManagerDelegate*>( + DownloadServiceFactory::GetForBrowserContext(browser()->profile()) + ->GetDownloadManagerDelegate()); + } +}; + +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadFile) { + GURL url(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); + + // Starts a download. + NotificationAddObserver download_start_notification_observer; + ui_test_utils::NavigateToURL(browser(), url); + EXPECT_TRUE(download_start_notification_observer.Wait()); + + // Confirms that a notification is created. + std::string notification_id = + download_start_notification_observer.notification_id(); + EXPECT_FALSE(notification_id.empty()); + + // Confirms that a download is also started. + std::vector<content::DownloadItem*> downloads; + GetDownloadManager(browser())->GetAllDownloads(&downloads); + EXPECT_EQ(1u, downloads.size()); + content::DownloadItem* download = downloads[0]; + + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_STATUS_IN_PROGRESS_TITLE, + download->GetFileNameToReportUser().LossyDisplayName()), + GetNotification(notification_id)->title()); + EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, + GetNotification(notification_id)->type()); + + // Requests to complete the download. + ui_test_utils::NavigateToURL( + browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); + + // Waits for download completion. + while (download->GetState() != content::DownloadItem::COMPLETE) { + NotificationUpdateObserver download_change_notification_observer; + download_change_notification_observer.Wait(); + } + + EXPECT_EQ(l10n_util::GetStringFUTF16( + IDS_DOWNLOAD_STATUS_DOWNLOADED_TITLE, + download->GetFileNameToReportUser().LossyDisplayName()), + GetNotification(notification_id)->title()); + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, + GetNotification(notification_id)->type()); + + // Try to open the downloaded item by clicking the notification. + EXPECT_FALSE(GetDownloadManagerDelegate()->opened()); + GetMessageCenter()->ClickOnNotification(notification_id); + EXPECT_TRUE(GetDownloadManagerDelegate()->opened()); + + EXPECT_FALSE(GetNotification(notification_id)); +} + +IN_PROC_BROWSER_TEST_F(DownloadNotificationTest, DownloadMultipleFiles) { + GURL url1(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); + GURL url2(net::URLRequestSlowDownloadJob::kKnownSizeUrl); + + // Starts the 1st download. + NotificationAddObserver download_start_notification_observer1; + ui_test_utils::NavigateToURL(browser(), url1); + EXPECT_TRUE(download_start_notification_observer1.Wait()); + std::string notification_id1 = + download_start_notification_observer1.notification_id(); + EXPECT_FALSE(notification_id1.empty()); + + // Confirms that there is a download. + std::vector<content::DownloadItem*> downloads; + GetDownloadManager(browser())->GetAllDownloads(&downloads); + EXPECT_EQ(1u, downloads.size()); + content::DownloadItem* download1or2 = downloads[0]; + + // Starts the 2nd download. + NotificationAddObserver download_start_notification_observer2; + ui_test_utils::NavigateToURL(browser(), url2); + EXPECT_TRUE(download_start_notification_observer2.Wait()); + std::string notification_id2 = + download_start_notification_observer2.notification_id(); + EXPECT_FALSE(notification_id2.empty()); + + // Confirms that there are 2 downloads. + downloads.clear(); + GetDownloadManager(browser())->GetAllDownloads(&downloads); + content::DownloadItem* download1 = downloads[0]; + content::DownloadItem* download2 = downloads[1]; + EXPECT_EQ(2u, downloads.size()); + EXPECT_NE(download1, download2); + EXPECT_TRUE(download1 == download1or2 || download2 == download1or2); + + // Confirms the types of download notifications are correct. + EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, + GetNotification(notification_id1)->type()); + EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, + GetNotification(notification_id2)->type()); + + // Requests to complete the downloads. + ui_test_utils::NavigateToURL( + browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); + + // Waits for the completion of downloads. + while (download1->GetState() != content::DownloadItem::COMPLETE || + download2->GetState() != content::DownloadItem::COMPLETE) { + NotificationUpdateObserver download_change_notification_observer; + download_change_notification_observer.Wait(); + } + + // Confirms the types of download notifications are correct. + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, + GetNotification(notification_id1)->type()); + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, + GetNotification(notification_id2)->type()); +} + +////////////////////////////////////////////////// +// Test with multi profiles +////////////////////////////////////////////////// + +class MultiProfileDownloadNotificationTest + : public DownloadNotificationTestBase { + public: + ~MultiProfileDownloadNotificationTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + DownloadNotificationTestBase::SetUpCommandLine(command_line); + + // Logs in to a dummy profile. + command_line->AppendSwitchASCII(chromeos::switches::kLoginUser, + kTestAccounts[DUMMY_ACCOUNT_INDEX].email); + command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, + kTestAccounts[DUMMY_ACCOUNT_INDEX].hash); + } + + // Logs in to the primary profile. + void SetUpOnMainThread() override { + const TestAccountInfo& info = kTestAccounts[PRIMARY_ACCOUNT_INDEX]; + + AddUser(info, true); + DownloadNotificationTestBase::SetUpOnMainThread(); + } + + // Loads all users to the current session and sets up necessary fields. + // This is used for preparing all accounts in PRE_ test setup, and for testing + // actual login behavior. + void AddAllUsers() { + for (size_t i = 0; i < arraysize(kTestAccounts); ++i) + AddUser(kTestAccounts[i], i >= SECONDARY_ACCOUNT_INDEX_START); + } + + Profile* GetProfileByIndex(int index) { + return chromeos::ProfileHelper::GetProfileByUserIdHash( + kTestAccounts[index].hash); + } + + // Adds a new user for testing to the current session. + void AddUser(const TestAccountInfo& info, bool log_in) { + user_manager::UserManager* const user_manager = + user_manager::UserManager::Get(); + if (log_in) + user_manager->UserLoggedIn(info.email, info.hash, false); + user_manager->SaveUserDisplayName(info.email, + base::UTF8ToUTF16(info.display_name)); + SigninManagerFactory::GetForProfile( + chromeos::ProfileHelper::GetProfileByUserIdHash(info.hash)) + ->SetAuthenticatedAccountInfo(info.gaia_id, info.email); + } +}; + +IN_PROC_BROWSER_TEST_F(MultiProfileDownloadNotificationTest, + PRE_DownloadMultipleFiles) { + AddAllUsers(); +} + +IN_PROC_BROWSER_TEST_F(MultiProfileDownloadNotificationTest, + DownloadMultipleFiles) { + AddAllUsers(); + + GURL url(net::URLRequestSlowDownloadJob::kUnknownSizeUrl); + + Profile* profile1 = GetProfileByIndex(1); + Profile* profile2 = GetProfileByIndex(2); + Browser* browser1 = CreateBrowser(profile1); + Browser* browser2 = CreateBrowser(profile2); + EXPECT_NE(browser1, browser2); + + // First user starts a download. + NotificationAddObserver download_start_notification_observer1; + ui_test_utils::NavigateToURL(browser1, url); + download_start_notification_observer1.Wait(); + + // Confirms that the download is started. + std::vector<content::DownloadItem*> downloads; + GetDownloadManager(browser1)->GetAllDownloads(&downloads); + EXPECT_EQ(1u, downloads.size()); + content::DownloadItem* download1 = downloads[0]; + + // Confirms that a download notification is generated. + std::string notification_id1 = + download_start_notification_observer1.notification_id(); + EXPECT_FALSE(notification_id1.empty()); + + // Second user starts a download. + NotificationAddObserver download_start_notification_observer2; + ui_test_utils::NavigateToURL(browser2, url); + download_start_notification_observer2.Wait(); + std::string notification_id2 = + download_start_notification_observer2.notification_id(); + EXPECT_FALSE(notification_id2.empty()); + + // Confirms that the second user has only 1 download. + downloads.clear(); + GetDownloadManager(browser2)->GetAllDownloads(&downloads); + ASSERT_EQ(1u, downloads.size()); + + // Second user starts another download. + NotificationAddObserver download_start_notification_observer3; + ui_test_utils::NavigateToURL(browser2, url); + download_start_notification_observer3.Wait(); + std::string notification_id3 = + download_start_notification_observer3.notification_id(); + EXPECT_FALSE(notification_id3.empty()); + + // Confirms that the second user has 2 downloads. + downloads.clear(); + GetDownloadManager(browser2)->GetAllDownloads(&downloads); + ASSERT_EQ(2u, downloads.size()); + content::DownloadItem* download2 = downloads[0]; + content::DownloadItem* download3 = downloads[1]; + EXPECT_NE(download1, download2); + EXPECT_NE(download1, download3); + EXPECT_NE(download2, download3); + + // Confirms that the first user still has only 1 download. + downloads.clear(); + GetDownloadManager(browser1)->GetAllDownloads(&downloads); + ASSERT_EQ(1u, downloads.size()); + EXPECT_EQ(download1, downloads[0]); + + // Confirms the types of download notifications are correct. + EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, + GetNotification(notification_id1)->type()); + EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, + GetNotification(notification_id2)->type()); + EXPECT_EQ(message_center::NOTIFICATION_TYPE_PROGRESS, + GetNotification(notification_id3)->type()); + + // Requests to complete the downloads. + ui_test_utils::NavigateToURL( + browser(), GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl)); + + // Waits for the completion of downloads. + while (download1->GetState() != content::DownloadItem::COMPLETE || + download2->GetState() != content::DownloadItem::COMPLETE || + download3->GetState() != content::DownloadItem::COMPLETE) { + NotificationUpdateObserver download_change_notification_observer; + download_change_notification_observer.Wait(); + } + + // Confirms the types of download notifications are correct. + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, + GetNotification(notification_id1)->type()); + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, + GetNotification(notification_id2)->type()); + EXPECT_EQ(message_center::NOTIFICATION_TYPE_SIMPLE, + GetNotification(notification_id3)->type()); +}
diff --git a/chrome/browser/drive/drive_api_util.cc b/chrome/browser/drive/drive_api_util.cc index 5d07e1e..bd9ba99 100644 --- a/chrome/browser/drive/drive_api_util.cc +++ b/chrome/browser/drive/drive_api_util.cc
@@ -168,7 +168,7 @@ base::MD5Digest digest; base::MD5Final(&digest, &context); - return MD5DigestToBase16(digest); + return base::MD5DigestToBase16(digest); } FileStreamMd5Digester::FileStreamMd5Digester() @@ -207,7 +207,7 @@ // EOF. base::MD5Digest digest; base::MD5Final(&digest, &md5_context_); - std::string result = MD5DigestToBase16(digest); + std::string result = base::MD5DigestToBase16(digest); callback.Run(result); return; }
diff --git a/chrome/browser/drive/drive_api_util_unittest.cc b/chrome/browser/drive/drive_api_util_unittest.cc index 179e5b7..60730d4 100644 --- a/chrome/browser/drive/drive_api_util_unittest.cc +++ b/chrome/browser/drive/drive_api_util_unittest.cc
@@ -52,7 +52,7 @@ EXPECT_EQ("fullText contains 'dog'", TranslateQuery("\"\" dog \"\"")); } -TEST(FileSystemUtilTest, CanonicalizeResourceId) { +TEST(DriveAPIUtilTest, CanonicalizeResourceId) { std::string resource_id("1YsCnrMxxgp7LDdtlFDt-WdtEIth89vA9inrILtvK-Ug"); // New style ID is unchanged.
diff --git a/chrome/browser/enhanced_bookmarks/android/bookmark_image_service_android.cc b/chrome/browser/enhanced_bookmarks/android/bookmark_image_service_android.cc index c783f9c9..1d8c5667 100644 --- a/chrome/browser/enhanced_bookmarks/android/bookmark_image_service_android.cc +++ b/chrome/browser/enhanced_bookmarks/android/bookmark_image_service_android.cc
@@ -89,7 +89,7 @@ content::RenderFrameHost* render_frame_host, const GURL& page_url, bool update_bookmark) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (IsPageUrlInProgress(page_url)) return; // A request for this URL is already in progress. @@ -259,7 +259,7 @@ void BookmarkImageServiceAndroid::BitmapFetcherHandler::OnFetchComplete( const GURL& url, const SkBitmap* bitmap) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); scoped_ptr<gfx::Image> image; if (bitmap) {
diff --git a/chrome/browser/enhanced_bookmarks/android/enhanced_bookmarks_bridge.cc b/chrome/browser/enhanced_bookmarks/android/enhanced_bookmarks_bridge.cc index 6cd7c65b..96c2f5b 100644 --- a/chrome/browser/enhanced_bookmarks/android/enhanced_bookmarks_bridge.cc +++ b/chrome/browser/enhanced_bookmarks/android/enhanced_bookmarks_bridge.cc
@@ -213,7 +213,7 @@ jobject obj, jobject j_bookmark_id_obj, jobject j_parent_id_obj) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(enhanced_bookmark_model_->loaded()); long bookmark_id = JavaBookmarkIdGetId(env, j_bookmark_id_obj);
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc index 1fad43a..059fd3e5 100644 --- a/chrome/browser/extensions/activity_log/activity_log.cc +++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -512,10 +512,7 @@ // static void ActivityLog::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kWatchdogExtensionActive, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kWatchdogExtensionActive, false); } // LOG ACTIONS. ----------------------------------------------------------------
diff --git a/chrome/browser/extensions/activity_log/uma_policy_unittest.cc b/chrome/browser/extensions/activity_log/uma_policy_unittest.cc index 86f57f83..e7ba9242 100644 --- a/chrome/browser/extensions/activity_log/uma_policy_unittest.cc +++ b/chrome/browser/extensions/activity_log/uma_policy_unittest.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/extensions/activity_log/activity_action_constants.h" #include "chrome/browser/extensions/activity_log/uma_policy.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/common/dom_action_types.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,6 +19,7 @@ } protected: + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<TestingProfile> profile_; };
diff --git a/chrome/browser/extensions/api/autofill_private/OWNERS b/chrome/browser/extensions/api/autofill_private/OWNERS new file mode 100644 index 0000000..1100e97 --- /dev/null +++ b/chrome/browser/extensions/api/autofill_private/OWNERS
@@ -0,0 +1,2 @@ +khorimoto@chromium.org +stevenjb@chromium.org
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc new file mode 100644 index 0000000..6dcd5eaa --- /dev/null +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -0,0 +1,109 @@ +// 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/extensions/api/autofill_private/autofill_private_api.h" + +#include "base/values.h" +#include "chrome/common/extensions/api/autofill_private.h" +#include "extensions/browser/extension_function_registry.h" + +namespace extensions { + +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivateSaveAddressFunction + +AutofillPrivateSaveAddressFunction::~AutofillPrivateSaveAddressFunction() {} + +ExtensionFunction::ResponseAction AutofillPrivateSaveAddressFunction::Run() { + scoped_ptr<api::autofill_private::SaveAddress::Params> parameters = + api::autofill_private::SaveAddress::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters.get()); + + // TODO(khorimoto): Implement. + + return RespondNow(NoArguments()); +} + +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivate*Function + +AutofillPrivateGetAddressComponentsFunction:: + ~AutofillPrivateGetAddressComponentsFunction() {} + +ExtensionFunction::ResponseAction + AutofillPrivateGetAddressComponentsFunction::Run() { + scoped_ptr<api::autofill_private::GetAddressComponents::Params> parameters = + api::autofill_private::GetAddressComponents::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters.get()); + + // TODO(khorimoto): Implement. + + return RespondNow(NoArguments()); +} + +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivateSaveCreditCardFunction + +AutofillPrivateSaveCreditCardFunction:: + ~AutofillPrivateSaveCreditCardFunction() {} + +ExtensionFunction::ResponseAction AutofillPrivateSaveCreditCardFunction::Run() { + scoped_ptr<api::autofill_private::SaveCreditCard::Params> parameters = + api::autofill_private::SaveCreditCard::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters.get()); + + // TODO(khorimoto): Implement. + + return RespondNow(NoArguments()); +} + +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivateRemoveEntryFunction + +AutofillPrivateRemoveEntryFunction::~AutofillPrivateRemoveEntryFunction() {} + +ExtensionFunction::ResponseAction AutofillPrivateRemoveEntryFunction::Run() { + scoped_ptr<api::autofill_private::RemoveEntry::Params> parameters = + api::autofill_private::RemoveEntry::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters.get()); + + // TODO(khorimoto): Implement. + + return RespondNow(NoArguments()); +} + +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivateValidatePhoneNumbersFunction + +AutofillPrivateValidatePhoneNumbersFunction:: + ~AutofillPrivateValidatePhoneNumbersFunction() {} + +ExtensionFunction::ResponseAction + AutofillPrivateValidatePhoneNumbersFunction::Run() { + scoped_ptr<api::autofill_private::ValidatePhoneNumbers::Params> parameters = + api::autofill_private::ValidatePhoneNumbers::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters.get()); + + // TODO(khorimoto): Implement. + + return RespondNow(NoArguments()); +} + +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivateMaskCreditCardFunction + +AutofillPrivateMaskCreditCardFunction:: + ~AutofillPrivateMaskCreditCardFunction() {} + +ExtensionFunction::ResponseAction AutofillPrivateMaskCreditCardFunction::Run() { + scoped_ptr<api::autofill_private::MaskCreditCard::Params> parameters = + api::autofill_private::MaskCreditCard::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters.get()); + + // TODO(khorimoto): Implement. + + return RespondNow(NoArguments()); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h new file mode 100644 index 0000000..776bd3a --- /dev/null +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
@@ -0,0 +1,115 @@ +// 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 CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_PRIVATE_AUTOFILL_PRIVATE_API_H_ +#define CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_PRIVATE_AUTOFILL_PRIVATE_API_H_ + +#include <string> + +#include "base/macros.h" +#include "extensions/browser/extension_function.h" + +namespace extensions { + +class AutofillPrivateSaveAddressFunction : public UIThreadExtensionFunction { + public: + AutofillPrivateSaveAddressFunction() {} + DECLARE_EXTENSION_FUNCTION("autofillPrivate.saveAddress", + AUTOFILLPRIVATE_SAVEADDRESS); + + protected: + ~AutofillPrivateSaveAddressFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillPrivateSaveAddressFunction); +}; + +class AutofillPrivateGetAddressComponentsFunction : + public UIThreadExtensionFunction { + public: + AutofillPrivateGetAddressComponentsFunction() {} + DECLARE_EXTENSION_FUNCTION("autofillPrivate.getAddressComponents", + AUTOFILLPRIVATE_GETADDRESSCOMPONENTS); + + protected: + ~AutofillPrivateGetAddressComponentsFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetAddressComponentsFunction); +}; + +class AutofillPrivateSaveCreditCardFunction : public UIThreadExtensionFunction { + public: + AutofillPrivateSaveCreditCardFunction() {} + DECLARE_EXTENSION_FUNCTION("autofillPrivate.saveCreditCard", + AUTOFILLPRIVATE_SAVECREDITCARD); + + protected: + ~AutofillPrivateSaveCreditCardFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillPrivateSaveCreditCardFunction); +}; + +class AutofillPrivateRemoveEntryFunction : public UIThreadExtensionFunction { + public: + AutofillPrivateRemoveEntryFunction() {} + DECLARE_EXTENSION_FUNCTION("autofillPrivate.removeEntry", + AUTOFILLPRIVATE_REMOVEENTRY); + + protected: + ~AutofillPrivateRemoveEntryFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillPrivateRemoveEntryFunction); +}; + +class AutofillPrivateValidatePhoneNumbersFunction : + public UIThreadExtensionFunction { + public: + AutofillPrivateValidatePhoneNumbersFunction() {} + DECLARE_EXTENSION_FUNCTION("autofillPrivate.validatePhoneNumbers", + AUTOFILLPRIVATE_VALIDATEPHONENUMBERS); + + protected: + ~AutofillPrivateValidatePhoneNumbersFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillPrivateValidatePhoneNumbersFunction); +}; + +class AutofillPrivateMaskCreditCardFunction : public UIThreadExtensionFunction { + public: + AutofillPrivateMaskCreditCardFunction() {} + DECLARE_EXTENSION_FUNCTION("autofillPrivate.maskCreditCard", + AUTOFILLPRIVATE_MASKCREDITCARD); + + protected: + ~AutofillPrivateMaskCreditCardFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + DISALLOW_COPY_AND_ASSIGN(AutofillPrivateMaskCreditCardFunction); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_PRIVATE_AUTOFILL_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc index 3a7769c3..4310f03 100644 --- a/chrome/browser/extensions/api/automation/automation_apitest.cc +++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -64,7 +64,7 @@ } public: - virtual void SetUpInProcessBrowserTestFixture() override { + void SetUpInProcessBrowserTestFixture() override { ExtensionApiTest::SetUpInProcessBrowserTestFixture(); } };
diff --git a/chrome/browser/extensions/api/declarative_content/content_action.h b/chrome/browser/extensions/api/declarative_content/content_action.h index 27a6d3a..acc13e07 100644 --- a/chrome/browser/extensions/api/declarative_content/content_action.h +++ b/chrome/browser/extensions/api/declarative_content/content_action.h
@@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "extensions/browser/api/declarative/declarative_rule.h" #include "extensions/browser/declarative_user_script_master.h" +#include "extensions/common/user_script.h" namespace base { class Time;
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc index d581e5f2..353f715b 100644 --- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc +++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
@@ -91,6 +91,10 @@ // executable for http://clients1.google.com. void CheckActionNeedsAllUrls(const char* action, RequestStage stage); + private: + content::TestBrowserThreadBundle thread_bundle_; + + protected: net::TestURLRequestContext context_; // An extension with *.com host permissions and the DWR permission. @@ -98,9 +102,6 @@ // An extension with host permissions for all URLs and the DWR permission. scoped_refptr<Extension> extension_all_urls_; scoped_refptr<InfoMap> extension_info_map_; - - private: - content::TestBrowserThreadBundle thread_bundle_; }; void WebRequestActionWithThreadsTest::SetUp() {
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index 47e5e93..0c1ab7e 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/extensions/api/developer_private/developer_private_api.h" -#include "base/base64.h" #include "base/bind.h" #include "base/files/file_util.h" #include "base/lazy_instance.h" @@ -61,12 +60,10 @@ #include "extensions/browser/notification_types.h" #include "extensions/browser/warning_service.h" #include "extensions/common/constants.h" -#include "extensions/common/extension_resource.h" #include "extensions/common/extension_set.h" #include "extensions/common/feature_switch.h" #include "extensions/common/install_warning.h" #include "extensions/common/manifest.h" -#include "extensions/common/manifest_handlers/icons_handler.h" #include "extensions/common/manifest_handlers/options_page_info.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/grit/extensions_browser_resources.h" @@ -76,11 +73,10 @@ #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/fileapi/isolated_context.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" namespace extensions { -namespace developer_private = api::developer_private; +namespace developer = api::developer_private; namespace { @@ -111,60 +107,6 @@ return ExtensionSystem::Get(context)->extension_service(); } -GURL GetImageURLFromData(const std::string& contents) { - std::string contents_base64; - base::Base64Encode(contents, &contents_base64); - - // TODO(dvh): make use of content::kDataScheme. Filed as crbug/297301. - const char kDataURLPrefix[] = "data:;base64,"; - return GURL(kDataURLPrefix + contents_base64); -} - -GURL GetDefaultImageURL(developer_private::ItemType type) { - int icon_resource_id; - switch (type) { - case developer::ITEM_TYPE_LEGACY_PACKAGED_APP: - case developer::ITEM_TYPE_HOSTED_APP: - case developer::ITEM_TYPE_PACKAGED_APP: - icon_resource_id = IDR_APP_DEFAULT_ICON; - break; - default: - icon_resource_id = IDR_EXTENSION_DEFAULT_ICON; - break; - } - - return GetImageURLFromData( - ResourceBundle::GetSharedInstance().GetRawDataResourceForScale( - icon_resource_id, ui::SCALE_FACTOR_100P).as_string()); -} - -// TODO(dvh): This code should be refactored and moved to -// extensions::ImageLoader. Also a resize should be performed to avoid -// potential huge URLs: crbug/297298. -GURL ToDataURL(const base::FilePath& path, developer_private::ItemType type) { - std::string contents; - if (path.empty() || !base::ReadFileToString(path, &contents)) - return GetDefaultImageURL(type); - - return GetImageURLFromData(contents); -} - -void BroadcastItemStateChanged(content::BrowserContext* browser_context, - developer::EventType event_type, - const std::string& item_id) { - developer::EventData event_data; - event_data.event_type = event_type; - event_data.item_id = item_id; - event_data.extension_info = - ExtensionInfoGenerator(browser_context).CreateExtensionInfo(item_id); - - scoped_ptr<base::ListValue> args(new base::ListValue()); - args->Append(event_data.ToValue().release()); - scoped_ptr<Event> event(new Event( - developer_private::OnItemStateChanged::kEventName, args.Pass())); - EventRouter::Get(browser_context)->BroadcastEvent(event.Pass()); -} - std::string ReadFileToString(const base::FilePath& path) { std::string data; ignore_result(base::ReadFileToString(path, &data)); @@ -246,7 +188,9 @@ process_manager_observer_(this), app_window_registry_observer_(this), extension_action_api_observer_(this), - profile_(profile) { + profile_(profile), + event_router_(EventRouter::Get(profile_)), + weak_factory_(this) { extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); error_console_observer_.Add(ErrorConsole::Get(profile)); process_manager_observer_.Add(ProcessManager::Get(profile)); @@ -271,8 +215,7 @@ content::BrowserContext* browser_context, const Extension* extension) { DCHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context))); - BroadcastItemStateChanged( - browser_context, developer::EVENT_TYPE_LOADED, extension->id()); + BroadcastItemStateChanged(developer::EVENT_TYPE_LOADED, extension->id()); } void DeveloperPrivateEventRouter::OnExtensionUnloaded( @@ -280,19 +223,15 @@ const Extension* extension, UnloadedExtensionInfo::Reason reason) { DCHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context))); - BroadcastItemStateChanged( - browser_context, developer::EVENT_TYPE_UNLOADED, extension->id()); + BroadcastItemStateChanged(developer::EVENT_TYPE_UNLOADED, extension->id()); } -void DeveloperPrivateEventRouter::OnExtensionWillBeInstalled( +void DeveloperPrivateEventRouter::OnExtensionInstalled( content::BrowserContext* browser_context, const Extension* extension, - bool is_update, - bool from_ephemeral, - const std::string& old_name) { + bool is_update) { DCHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context))); - BroadcastItemStateChanged( - browser_context, developer::EVENT_TYPE_INSTALLED, extension->id()); + BroadcastItemStateChanged(developer::EVENT_TYPE_INSTALLED, extension->id()); } void DeveloperPrivateEventRouter::OnExtensionUninstalled( @@ -300,8 +239,7 @@ const Extension* extension, extensions::UninstallReason reason) { DCHECK(profile_->IsSameProfile(Profile::FromBrowserContext(browser_context))); - BroadcastItemStateChanged( - browser_context, developer::EVENT_TYPE_UNINSTALLED, extension->id()); + BroadcastItemStateChanged(developer::EVENT_TYPE_UNINSTALLED, extension->id()); } void DeveloperPrivateEventRouter::OnErrorAdded(const ExtensionError* error) { @@ -311,40 +249,81 @@ if (extension_ids_.find(error->extension_id()) != extension_ids_.end()) return; - BroadcastItemStateChanged( - profile_, developer::EVENT_TYPE_ERROR_ADDED, error->extension_id()); + BroadcastItemStateChanged(developer::EVENT_TYPE_ERROR_ADDED, + error->extension_id()); } void DeveloperPrivateEventRouter::OnExtensionFrameRegistered( const std::string& extension_id, content::RenderFrameHost* render_frame_host) { - BroadcastItemStateChanged( - profile_, developer::EVENT_TYPE_VIEW_REGISTERED, extension_id); + BroadcastItemStateChanged(developer::EVENT_TYPE_VIEW_REGISTERED, + extension_id); } void DeveloperPrivateEventRouter::OnExtensionFrameUnregistered( const std::string& extension_id, content::RenderFrameHost* render_frame_host) { - BroadcastItemStateChanged( - profile_, developer::EVENT_TYPE_VIEW_UNREGISTERED, extension_id); + BroadcastItemStateChanged(developer::EVENT_TYPE_VIEW_UNREGISTERED, + extension_id); } void DeveloperPrivateEventRouter::OnAppWindowAdded(AppWindow* window) { - BroadcastItemStateChanged( - profile_, developer::EVENT_TYPE_VIEW_REGISTERED, window->extension_id()); + BroadcastItemStateChanged(developer::EVENT_TYPE_VIEW_REGISTERED, + window->extension_id()); } void DeveloperPrivateEventRouter::OnAppWindowRemoved(AppWindow* window) { - BroadcastItemStateChanged(profile_, - developer::EVENT_TYPE_VIEW_UNREGISTERED, + BroadcastItemStateChanged(developer::EVENT_TYPE_VIEW_UNREGISTERED, window->extension_id()); } void DeveloperPrivateEventRouter::OnExtensionActionVisibilityChanged( const std::string& extension_id, bool is_now_visible) { - BroadcastItemStateChanged( - profile_, developer::EVENT_TYPE_PREFS_CHANGED, extension_id); + BroadcastItemStateChanged(developer::EVENT_TYPE_PREFS_CHANGED, extension_id); +} + +void DeveloperPrivateEventRouter::BroadcastItemStateChanged( + developer::EventType event_type, + const std::string& extension_id) { + scoped_ptr<ExtensionInfoGenerator> info_generator( + new ExtensionInfoGenerator(profile_)); + ExtensionInfoGenerator* info_generator_weak = info_generator.get(); + info_generator_weak->CreateExtensionInfo( + extension_id, + base::Bind(&DeveloperPrivateEventRouter::BroadcastItemStateChangedHelper, + weak_factory_.GetWeakPtr(), + event_type, + extension_id, + base::Passed(info_generator.Pass()))); +} + +void DeveloperPrivateEventRouter::BroadcastItemStateChangedHelper( + developer::EventType event_type, + const std::string& extension_id, + scoped_ptr<ExtensionInfoGenerator> info_generator, + const ExtensionInfoGenerator::ExtensionInfoList& infos) { + DCHECK_LE(infos.size(), 1u); + + developer::EventData event_data; + event_data.event_type = event_type; + event_data.item_id = extension_id; + scoped_ptr<base::DictionaryValue> dict = event_data.ToValue(); + + if (!infos.empty()) { + // Hack: Ideally, we would use event_data.extension_info to set the + // extension info, but since it's an optional field, it's implemented as a + // scoped ptr, and so ownership between that and the vector of linked ptrs + // here is, well, messy. Easier to just set it like this. + dict->SetWithoutPathExpansion("extensionInfo", + infos[0]->ToValue().release()); + } + + scoped_ptr<base::ListValue> args(new base::ListValue()); + args->Append(dict.release()); + scoped_ptr<Event> event(new Event( + developer::OnItemStateChanged::kEventName, args.Pass())); + event_router_->BroadcastEvent(event.Pass()); } void DeveloperPrivateAPI::SetLastUnpackedDirectory(const base::FilePath& path) { @@ -353,7 +332,7 @@ void DeveloperPrivateAPI::RegisterNotifications() { EventRouter::Get(profile_)->RegisterObserver( - this, developer_private::OnItemStateChanged::kEventName); + this, developer::OnItemStateChanged::kEventName); } DeveloperPrivateAPI::~DeveloperPrivateAPI() {} @@ -373,7 +352,7 @@ void DeveloperPrivateAPI::OnListenerRemoved( const EventListenerInfo& details) { if (!EventRouter::Get(profile_)->HasEventListener( - developer_private::OnItemStateChanged::kEventName)) { + developer::OnItemStateChanged::kEventName)) { developer_private_event_router_.reset(NULL); } else { developer_private_event_router_->RemoveExtensionId(details.extension_id); @@ -411,6 +390,10 @@ } DeveloperPrivateGetExtensionsInfoFunction:: +DeveloperPrivateGetExtensionsInfoFunction() { +} + +DeveloperPrivateGetExtensionsInfoFunction:: ~DeveloperPrivateGetExtensionsInfoFunction() { } @@ -429,12 +412,23 @@ include_terminated = *params->options->include_terminated; } - std::vector<linked_ptr<developer::ExtensionInfo>> list = - ExtensionInfoGenerator(browser_context()). - CreateExtensionsInfo(include_disabled, include_terminated); + info_generator_.reset(new ExtensionInfoGenerator(browser_context())); + info_generator_->CreateExtensionsInfo( + include_disabled, + include_terminated, + base::Bind(&DeveloperPrivateGetExtensionsInfoFunction::OnInfosGenerated, + this /* refcounted */)); - return RespondNow(ArgumentList( - developer::GetExtensionsInfo::Results::Create(list))); + return RespondLater(); +} + +void DeveloperPrivateGetExtensionsInfoFunction::OnInfosGenerated( + const ExtensionInfoGenerator::ExtensionInfoList& list) { + Respond(ArgumentList(developer::GetExtensionsInfo::Results::Create(list))); +} + +DeveloperPrivateGetExtensionInfoFunction:: +DeveloperPrivateGetExtensionInfoFunction() { } DeveloperPrivateGetExtensionInfoFunction:: @@ -447,13 +441,21 @@ developer::GetExtensionInfo::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); - scoped_ptr<developer::ExtensionInfo> info = - ExtensionInfoGenerator(browser_context()).CreateExtensionInfo(params->id); + info_generator_.reset(new ExtensionInfoGenerator(browser_context())); + info_generator_->CreateExtensionInfo( + params->id, + base::Bind(&DeveloperPrivateGetExtensionInfoFunction::OnInfosGenerated, + this /* refcounted */)); - if (!info) - return RespondNow(Error(kNoSuchExtensionError)); + return RespondLater(); +} - return RespondNow(OneArgument(info->ToValue().release())); +void DeveloperPrivateGetExtensionInfoFunction::OnInfosGenerated( + const ExtensionInfoGenerator::ExtensionInfoList& list) { + DCHECK_EQ(1u, list.size()); + const linked_ptr<developer::ExtensionInfo>& info = list[0]; + Respond(info.get() ? OneArgument(info->ToValue()) : + Error(kNoSuchExtensionError)); } DeveloperPrivateGetItemsInfoFunction::DeveloperPrivateGetItemsInfoFunction() {} @@ -464,63 +466,23 @@ developer::GetItemsInfo::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); - ExtensionSet items; - ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context()); - items.InsertAll(registry->enabled_extensions()); - - if (params->include_disabled) - items.InsertAll(registry->disabled_extensions()); - if (params->include_terminated) - items.InsertAll(registry->terminated_extensions()); - - std::map<std::string, ExtensionResource> resource_map; - for (const scoped_refptr<const Extension>& item : items) { - // Don't show component extensions and invisible apps. - if (ui_util::ShouldDisplayInExtensionSettings(item.get(), - browser_context())) { - resource_map[item->id()] = - IconsInfo::GetIconResource(item.get(), - extension_misc::EXTENSION_ICON_MEDIUM, - ExtensionIconSet::MATCH_BIGGER); - } - } - - std::vector<linked_ptr<developer::ExtensionInfo>> list = - ExtensionInfoGenerator(browser_context()). - CreateExtensionsInfo(params->include_disabled, - params->include_terminated); - - for (const linked_ptr<developer::ExtensionInfo>& info : list) - item_list_.push_back(developer_private_mangle::MangleExtensionInfo(*info)); - - content::BrowserThread::PostTask( - content::BrowserThread::FILE, - FROM_HERE, - base::Bind(&DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread, - this, - resource_map)); + info_generator_.reset(new ExtensionInfoGenerator(browser_context())); + info_generator_->CreateExtensionsInfo( + params->include_disabled, + params->include_terminated, + base::Bind(&DeveloperPrivateGetItemsInfoFunction::OnInfosGenerated, + this /* refcounted */)); return RespondLater(); } -void DeveloperPrivateGetItemsInfoFunction::GetIconsOnFileThread( - const std::map<std::string, ExtensionResource> resource_map) { - for (const linked_ptr<developer::ItemInfo>& item : item_list_) { - auto resource = resource_map.find(item->id); - if (resource != resource_map.end()) { - item->icon_url = ToDataURL(resource->second.GetFilePath(), - item->type).spec(); - } - } +void DeveloperPrivateGetItemsInfoFunction::OnInfosGenerated( + const ExtensionInfoGenerator::ExtensionInfoList& list) { + std::vector<linked_ptr<developer::ItemInfo>> item_list; + for (const linked_ptr<developer::ExtensionInfo>& info : list) + item_list.push_back(developer_private_mangle::MangleExtensionInfo(*info)); - content::BrowserThread::PostTask( - content::BrowserThread::UI, - FROM_HERE, - base::Bind(&DeveloperPrivateGetItemsInfoFunction::Finish, this)); -} - -void DeveloperPrivateGetItemsInfoFunction::Finish() { - Respond(ArgumentList(developer::GetItemsInfo::Results::Create(item_list_))); + Respond(ArgumentList(developer::GetItemsInfo::Results::Create(item_list))); } DeveloperPrivateGetProfileConfigurationFunction:: @@ -685,8 +647,8 @@ } ExtensionFunction::ResponseAction DeveloperPrivateLoadUnpackedFunction::Run() { - scoped_ptr<developer_private::LoadUnpacked::Params> params( - developer_private::LoadUnpacked::Params::Create(*args_)); + scoped_ptr<developer::LoadUnpacked::Params> params( + developer::LoadUnpacked::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); if (!ShowPicker( @@ -766,7 +728,7 @@ response.message = base::UTF16ToUTF8( PackExtensionJob::StandardSuccessMessage(crx_file, pem_file)); response.status = developer::PACK_STATUS_SUCCESS; - Respond(OneArgument(response.ToValue().release())); + Respond(OneArgument(response.ToValue())); Release(); // Balanced in Run(). } @@ -783,7 +745,7 @@ } else { response.status = developer::PACK_STATUS_ERROR; } - Respond(OneArgument(response.ToValue().release())); + Respond(OneArgument(response.ToValue())); Release(); // Balanced in Run(). } @@ -811,14 +773,14 @@ IDS_EXTENSION_PACK_DIALOG_ERROR_ROOT_INVALID); response.status = developer::PACK_STATUS_ERROR; - return RespondNow(OneArgument(response.ToValue().release())); + return RespondNow(OneArgument(response.ToValue())); } if (!key_path_str_.empty() && key_file.empty()) { response.message = l10n_util::GetStringUTF8( IDS_EXTENSION_PACK_DIALOG_ERROR_KEY_INVALID); response.status = developer::PACK_STATUS_ERROR; - return RespondNow(OneArgument(response.ToValue().release())); + return RespondNow(OneArgument(response.ToValue())); } AddRef(); // Balanced in OnPackSuccess / OnPackFailure. @@ -1205,7 +1167,7 @@ response.highlight = highlighter->GetFeature(); response.after_highlight = highlighter->GetAfterFeature(); - Respond(OneArgument(response.ToValue().release())); + Respond(OneArgument(response.ToValue())); } DeveloperPrivateOpenDevToolsFunction::DeveloperPrivateOpenDevToolsFunction() {}
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chrome/browser/extensions/api/developer_private/developer_private_api.h index 8e2e013a..f2131c8 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.h +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -8,6 +8,7 @@ #include <set> #include "base/files/file.h" +#include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" #include "chrome/browser/extensions/api/developer_private/entry_picker.h" #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" @@ -16,6 +17,7 @@ #include "chrome/browser/extensions/error_console/error_console.h" #include "chrome/browser/extensions/extension_uninstall_dialog.h" #include "chrome/browser/extensions/pack_extension_job.h" +#include "chrome/common/extensions/api/developer_private.h" #include "chrome/common/extensions/webstore_install_result.h" #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/browser_context_keyed_api_factory.h" @@ -30,7 +32,9 @@ namespace extensions { +class EventRouter; class ExtensionError; +class ExtensionInfoGenerator; class ExtensionRegistry; class ExtensionSystem; class ManagementPolicy; @@ -42,27 +46,8 @@ class EntryPicker; class EntryPickerClient; -namespace developer_private { - -struct ItemInfo; -struct ItemInspectView; -struct ProjectInfo; - -namespace RequestFileSource { -struct Params; -} - -} // namespace developer_private - } // namespace api -namespace developer = api::developer_private; - -typedef std::vector<linked_ptr<developer::ItemInfo> > ItemInfoList; -typedef std::vector<linked_ptr<developer::ProjectInfo> > ProjectInfoList; -typedef std::vector<linked_ptr<developer::ItemInspectView> > - ItemInspectViewList; - class DeveloperPrivateEventRouter : public ExtensionRegistryObserver, public ErrorConsole::Observer, public ProcessManagerObserver, @@ -83,11 +68,9 @@ void OnExtensionUnloaded(content::BrowserContext* browser_context, const Extension* extension, UnloadedExtensionInfo::Reason reason) override; - void OnExtensionWillBeInstalled(content::BrowserContext* browser_context, - const Extension* extension, - bool is_update, - bool from_ephemeral, - const std::string& old_name) override; + void OnExtensionInstalled(content::BrowserContext* browser_context, + const Extension* extension, + bool is_update) override; void OnExtensionUninstalled(content::BrowserContext* browser_context, const Extension* extension, extensions::UninstallReason reason) override; @@ -111,6 +94,16 @@ void OnExtensionActionVisibilityChanged(const std::string& extension_id, bool is_now_visible) override; + // Broadcasts an event to all listeners. + void BroadcastItemStateChanged(api::developer_private::EventType event_type, + const std::string& id); + void BroadcastItemStateChangedHelper( + api::developer_private::EventType event_type, + const std::string& extension_id, + scoped_ptr<ExtensionInfoGenerator> info_generator, + const std::vector<linked_ptr<api::developer_private::ExtensionInfo>>& + infos); + ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> extension_registry_observer_; ScopedObserver<ErrorConsole, ErrorConsole::Observer> error_console_observer_; @@ -123,6 +116,8 @@ Profile* profile_; + EventRouter* event_router_; + // The set of IDs of the Extensions that have subscribed to DeveloperPrivate // events. Since the only consumer of the DeveloperPrivate API is currently // the Apps Developer Tool (which replaces the chrome://extensions page), we @@ -131,6 +126,8 @@ // when, e.g., the Apps Developer Tool throws an error. std::set<std::string> extension_ids_; + base::WeakPtrFactory<DeveloperPrivateEventRouter> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateEventRouter); }; @@ -218,33 +215,53 @@ ~DeveloperPrivateGetItemsInfoFunction() override; ResponseAction Run() override; - void GetIconsOnFileThread( - std::map<std::string, ExtensionResource> resource_map); - void Finish(); + void OnInfosGenerated( + const std::vector<linked_ptr<api::developer_private::ExtensionInfo>>& + infos); - ItemInfoList item_list_; + scoped_ptr<ExtensionInfoGenerator> info_generator_; + + DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateGetItemsInfoFunction); }; class DeveloperPrivateGetExtensionsInfoFunction : public DeveloperPrivateAPIFunction { public: + DeveloperPrivateGetExtensionsInfoFunction(); DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionsInfo", DEVELOPERPRIVATE_GETEXTENSIONSINFO); private: ~DeveloperPrivateGetExtensionsInfoFunction() override; ResponseAction Run() override; + + void OnInfosGenerated( + const std::vector<linked_ptr<api::developer_private::ExtensionInfo>>& + infos); + + scoped_ptr<ExtensionInfoGenerator> info_generator_; + + DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateGetExtensionsInfoFunction); }; class DeveloperPrivateGetExtensionInfoFunction : public DeveloperPrivateAPIFunction { public: + DeveloperPrivateGetExtensionInfoFunction(); DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionInfo", DEVELOPERPRIVATE_GETEXTENSIONINFO); private: ~DeveloperPrivateGetExtensionInfoFunction() override; ResponseAction Run() override; + + void OnInfosGenerated( + const std::vector<linked_ptr<api::developer_private::ExtensionInfo>>& + infos); + + scoped_ptr<ExtensionInfoGenerator> info_generator_; + + DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateGetExtensionInfoFunction); }; class DeveloperPrivateGetProfileConfigurationFunction
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_mangle.cc b/chrome/browser/extensions/api/developer_private/developer_private_mangle.cc index aa1bcdb..073df5b 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_mangle.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_mangle.cc
@@ -51,8 +51,10 @@ default: NOTREACHED(); } - result->allow_file_access = info.file_access.is_enabled; - result->wants_file_access = info.file_access.is_active; + result->allow_file_access = info.file_access.is_active; + result->wants_file_access = info.file_access.is_enabled; + + result->icon_url = info.icon_url; result->incognito_enabled = info.incognito_access.is_active; result->allow_incognito = info.incognito_access.is_enabled;
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc index 9ac1c43..fd91759 100644 --- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc +++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/extensions/api/developer_private/extension_info_generator.h" +#include "base/base64.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/api/developer_private/inspectable_views_finder.h" #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" @@ -22,17 +23,25 @@ #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" +#include "extensions/browser/image_loader.h" #include "extensions/browser/warning_service.h" #include "extensions/common/extension_set.h" #include "extensions/common/feature_switch.h" #include "extensions/common/install_warning.h" #include "extensions/common/manifest.h" #include "extensions/common/manifest_handlers/background_info.h" +#include "extensions/common/manifest_handlers/icons_handler.h" #include "extensions/common/manifest_handlers/offline_enabled_info.h" #include "extensions/common/manifest_handlers/options_page_info.h" #include "extensions/common/manifest_url_handlers.h" #include "extensions/common/permissions/permissions_data.h" +#include "extensions/grit/extensions_browser_resources.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/color_utils.h" +#include "ui/gfx/image/image.h" +#include "ui/gfx/skbitmap_operations.h" namespace extensions { @@ -142,15 +151,83 @@ extension_prefs_(ExtensionPrefs::Get(browser_context)), extension_action_api_(ExtensionActionAPI::Get(browser_context)), warning_service_(WarningService::Get(browser_context)), - error_console_(ErrorConsole::Get(browser_context)) { + error_console_(ErrorConsole::Get(browser_context)), + image_loader_(ImageLoader::Get(browser_context)), + pending_image_loads_(0u), + weak_factory_(this) { } ExtensionInfoGenerator::~ExtensionInfoGenerator() { } -scoped_ptr<developer::ExtensionInfo> -ExtensionInfoGenerator::CreateExtensionInfo(const Extension& extension, - developer::ExtensionState state) { +void ExtensionInfoGenerator::CreateExtensionInfo( + const std::string& id, + const ExtensionInfosCallback& callback) { + DCHECK(callback_.is_null() && list_.empty()) << + "Only a single generation can be running at a time!"; + ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); + + developer::ExtensionState state = developer::EXTENSION_STATE_NONE; + const Extension* ext = nullptr; + if ((ext = registry->enabled_extensions().GetByID(id)) != nullptr) + state = developer::EXTENSION_STATE_ENABLED; + else if ((ext = registry->disabled_extensions().GetByID(id)) != nullptr) + state = developer::EXTENSION_STATE_DISABLED; + else if ((ext = registry->terminated_extensions().GetByID(id)) != nullptr) + state = developer::EXTENSION_STATE_TERMINATED; + + if (ext && ui_util::ShouldDisplayInExtensionSettings(ext, browser_context_)) + CreateExtensionInfoHelper(*ext, state); + + if (pending_image_loads_ == 0) { + // Don't call the callback re-entrantly. + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, list_)); + list_.clear(); + } else { + callback_ = callback; + } +} + +void ExtensionInfoGenerator::CreateExtensionsInfo( + bool include_disabled, + bool include_terminated, + const ExtensionInfosCallback& callback) { + auto add_to_list = [this](const ExtensionSet& extensions, + developer::ExtensionState state) { + for (const scoped_refptr<const Extension>& extension : extensions) { + if (ui_util::ShouldDisplayInExtensionSettings(extension.get(), + browser_context_)) { + CreateExtensionInfoHelper(*extension, state); + } + } + }; + + ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); + add_to_list(registry->enabled_extensions(), + developer::EXTENSION_STATE_ENABLED); + if (include_disabled) { + add_to_list(registry->disabled_extensions(), + developer::EXTENSION_STATE_DISABLED); + } + if (include_terminated) { + add_to_list(registry->terminated_extensions(), + developer::EXTENSION_STATE_TERMINATED); + } + + if (pending_image_loads_ == 0) { + // Don't call the callback re-entrantly. + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, list_)); + list_.clear(); + } else { + callback_ = callback; + } +} + +void ExtensionInfoGenerator::CreateExtensionInfoHelper( + const Extension& extension, + developer::ExtensionState state) { scoped_ptr<developer::ExtensionInfo> info(new developer::ExtensionInfo()); // Don't consider the button hidden with the redesign, because "hidden" @@ -217,17 +294,6 @@ info->home_page.url = ManifestURL::GetHomepageURL(&extension).spec(); info->home_page.specified = ManifestURL::SpecifiedHomepageURL(&extension); - bool is_enabled = state == developer::EXTENSION_STATE_ENABLED; - - // TODO(devlin): This won't work with apps (CORS). We should convert to data - // urls. - info->icon_url = - ExtensionIconSource::GetIconURL(&extension, - extension_misc::EXTENSION_ICON_MEDIUM, - ExtensionIconSet::MATCH_BIGGER, - !is_enabled, - nullptr).spec(); - info->id = extension.id(); // Incognito access. @@ -357,68 +423,98 @@ info->version = extension.GetVersionForDisplay(); + bool is_enabled = state == developer::EXTENSION_STATE_ENABLED; if (state != developer::EXTENSION_STATE_TERMINATED) { info->views = InspectableViewsFinder(profile). GetViewsForExtension(extension, is_enabled); } - return info.Pass(); + + // The icon. + ExtensionResource icon = + IconsInfo::GetIconResource(&extension, + extension_misc::EXTENSION_ICON_MEDIUM, + ExtensionIconSet::MATCH_BIGGER); + if (icon.empty()) { + info->icon_url = GetDefaultIconUrl(extension.is_app(), !is_enabled); + list_.push_back(make_linked_ptr(info.release())); + } else { + ++pending_image_loads_; + // Max size of 128x128 is a random guess at a nice balance between being + // overly eager to resize and sending across gigantic data urls. (The icon + // used by the url is 48x48). + gfx::Size max_size(128, 128); + image_loader_->LoadImageAsync( + &extension, + icon, + max_size, + base::Bind(&ExtensionInfoGenerator::OnImageLoaded, + weak_factory_.GetWeakPtr(), + base::Passed(info.Pass()))); + } } -scoped_ptr<api::developer_private::ExtensionInfo> -ExtensionInfoGenerator::CreateExtensionInfo(const std::string& id) { - ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); - - const Extension* enabled = registry->enabled_extensions().GetByID(id); - if (enabled && - ui_util::ShouldDisplayInExtensionSettings(enabled, browser_context_)) { - return CreateExtensionInfo(*enabled, developer::EXTENSION_STATE_ENABLED); +const std::string& ExtensionInfoGenerator::GetDefaultIconUrl( + bool is_app, + bool is_greyscale) { + std::string* str; + if (is_app) { + str = is_greyscale ? &default_disabled_app_icon_url_ : + &default_app_icon_url_; + } else { + str = is_greyscale ? &default_disabled_extension_icon_url_ : + &default_extension_icon_url_; } - const Extension* disabled = registry->disabled_extensions().GetByID(id); - if (disabled && - ui_util::ShouldDisplayInExtensionSettings(disabled, browser_context_)) { - return CreateExtensionInfo(*disabled, developer::EXTENSION_STATE_DISABLED); + if (str->empty()) { + *str = GetIconUrlFromImage( + ui::ResourceBundle::GetSharedInstance().GetImageNamed( + is_app ? IDR_APP_DEFAULT_ICON : IDR_EXTENSION_DEFAULT_ICON), + is_greyscale); } - const Extension* terminated = registry->terminated_extensions().GetByID(id); - if (terminated && - ui_util::ShouldDisplayInExtensionSettings(terminated, browser_context_)) { - return CreateExtensionInfo(*terminated, - developer::EXTENSION_STATE_TERMINATED); - } - - return scoped_ptr<api::developer_private::ExtensionInfo>(); + return *str; } -ExtensionInfoGenerator::ExtensionInfoList -ExtensionInfoGenerator::CreateExtensionsInfo(bool include_disabled, - bool include_terminated) { - std::vector<linked_ptr<developer::ExtensionInfo>> list; - auto add_to_list = [this, &list](const ExtensionSet& extensions, - developer::ExtensionState state) { - for (const scoped_refptr<const Extension>& extension : extensions) { - if (ui_util::ShouldDisplayInExtensionSettings(extension.get(), - browser_context_)) { - scoped_ptr<developer::ExtensionInfo> info = - CreateExtensionInfo(*extension, state); - list.push_back(make_linked_ptr(info.release())); - } - } - }; - - ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); - add_to_list(registry->enabled_extensions(), - developer::EXTENSION_STATE_ENABLED); - if (include_disabled) { - add_to_list(registry->disabled_extensions(), - developer::EXTENSION_STATE_DISABLED); - } - if (include_terminated) { - add_to_list(registry->terminated_extensions(), - developer::EXTENSION_STATE_TERMINATED); +std::string ExtensionInfoGenerator::GetIconUrlFromImage( + const gfx::Image& image, + bool should_greyscale) { + scoped_refptr<base::RefCountedMemory> data; + if (should_greyscale) { + color_utils::HSL shift = {-1, 0, 0.6}; + SkBitmap bitmap = + SkBitmapOperations::CreateHSLShiftedBitmap(*image.ToSkBitmap(), shift); + scoped_refptr<base::RefCountedBytes> image_bytes( + new base::RefCountedBytes()); + gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &image_bytes->data()); + data = image_bytes; + } else { + data = image.As1xPNGBytes(); } - return list; + std::string base_64; + base::Base64Encode(std::string(data->front_as<char>(), data->size()), + &base_64); + const char kDataUrlPrefix[] = "data:image/png;base64,"; + return GURL(kDataUrlPrefix + base_64).spec(); +} + +void ExtensionInfoGenerator::OnImageLoaded( + scoped_ptr<developer::ExtensionInfo> info, + const gfx::Image& icon) { + info->icon_url = GetIconUrlFromImage( + icon, info->state != developer::EXTENSION_STATE_ENABLED); + list_.push_back(make_linked_ptr(info.release())); + + --pending_image_loads_; + + if (pending_image_loads_ == 0) { // All done! + // We assign to a temporary and Reset() so that at the end of the method, + // any stored refs are destroyed. + ExtensionInfosCallback callback = callback_; + callback_.Reset(); + callback.Run(list_); + list_.clear(); + } } } // namespace extensions
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.h b/chrome/browser/extensions/api/developer_private/extension_info_generator.h index 29dc73ea..63ad3e69 100644 --- a/chrome/browser/extensions/api/developer_private/extension_info_generator.h +++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.h
@@ -5,44 +5,68 @@ #ifndef CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_EXTENSION_INFO_GENERATOR_H_ #define CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_EXTENSION_INFO_GENERATOR_H_ +#include "base/callback.h" +#include "base/memory/weak_ptr.h" #include "chrome/common/extensions/api/developer_private.h" namespace content { class BrowserContext; } +namespace gfx { +class Image; +} + namespace extensions { class ErrorConsole; class Extension; class ExtensionActionAPI; class ExtensionPrefs; class ExtensionSystem; +class ImageLoader; class WarningService; // Generates the developerPrivate api's specification for ExtensionInfo. +// This class is designed to only have one generation running at a time! class ExtensionInfoGenerator { public: using ExtensionInfoList = std::vector<linked_ptr<api::developer_private::ExtensionInfo>>; + using ExtensionInfosCallback = base::Callback<void(const ExtensionInfoList&)>; + explicit ExtensionInfoGenerator(content::BrowserContext* context); ~ExtensionInfoGenerator(); - // Returns the ExtensionInfo for a given |extension| and |state|. - scoped_ptr<api::developer_private::ExtensionInfo> CreateExtensionInfo( - const Extension& extension, - api::developer_private::ExtensionState state); - // Returns an ExtensionInfo for the given |extension_id|, if the extension - // can be found. - scoped_ptr<api::developer_private::ExtensionInfo> CreateExtensionInfo( - const std::string& id); + // Creates and asynchronously returns an ExtensionInfo for the given + // |extension_id|, if the extension can be found. + // If the extension cannot be found, an empty vector is passed to |callback|. + void CreateExtensionInfo(const std::string& id, + const ExtensionInfosCallback& callback); - // Returns a collection of ExtensionInfos, optionally including disabled and - // terminated. - ExtensionInfoList CreateExtensionsInfo(bool include_disabled, - bool include_terminated); + // Creates and asynchronously returns a collection of ExtensionInfos, + // optionally including disabled and terminated. + void CreateExtensionsInfo(bool include_disabled, + bool include_terminated, + const ExtensionInfosCallback& callback); private: + // Creates an ExtensionInfo for the given |extension| and |state|, and + // asynchronously adds it to the |list|. + void CreateExtensionInfoHelper(const Extension& extension, + api::developer_private::ExtensionState state); + + // Callback for the asynchronous image loading. + void OnImageLoaded(scoped_ptr<api::developer_private::ExtensionInfo> info, + const gfx::Image& image); + + // Returns the icon url for the default icon to use. + const std::string& GetDefaultIconUrl(bool is_app, bool is_disabled); + + // Returns an icon url from the given image, optionally applying a greyscale. + std::string GetIconUrlFromImage(const gfx::Image& image, + bool should_greyscale); + // Various systems, cached for convenience. content::BrowserContext* browser_context_; ExtensionSystem* extension_system_; @@ -50,6 +74,24 @@ ExtensionActionAPI* extension_action_api_; WarningService* warning_service_; ErrorConsole* error_console_; + ImageLoader* image_loader_; + + // The number of pending image loads. + size_t pending_image_loads_; + + // Default icons, cached and lazily initialized. + std::string default_app_icon_url_; + std::string default_extension_icon_url_; + std::string default_disabled_app_icon_url_; + std::string default_disabled_extension_icon_url_; + + // The list of extension infos that have been generated. + ExtensionInfoList list_; + + // The callback to run once all infos have been created. + ExtensionInfosCallback callback_; + + base::WeakPtrFactory<ExtensionInfoGenerator> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ExtensionInfoGenerator); };
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc index eece9df..3b7d50d9 100644 --- a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc +++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -55,6 +55,31 @@ InitializeEmptyExtensionService(); } + void OnInfosGenerated(linked_ptr<developer::ExtensionInfo>* info_out, + const ExtensionInfoGenerator::ExtensionInfoList& list) { + EXPECT_EQ(1u, list.size()); + if (!list.empty()) + *info_out = list[0]; + quit_closure_.Run(); + quit_closure_.Reset(); + } + + scoped_ptr<developer::ExtensionInfo> GenerateExtensionInfo( + const std::string& extension_id) { + linked_ptr<developer::ExtensionInfo> info; + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + scoped_ptr<ExtensionInfoGenerator> generator( + new ExtensionInfoGenerator(browser_context())); + generator->CreateExtensionInfo( + extension_id, + base::Bind(&ExtensionInfoGeneratorUnitTest::OnInfosGenerated, + base::Unretained(this), + base::Unretained(&info))); + run_loop.Run(); + return make_scoped_ptr(info.release()); + } + const scoped_refptr<const Extension> CreateExtension( const std::string& name, ListBuilder& permissions) { @@ -90,11 +115,10 @@ extension_path, location, *extension_data, Extension::REQUIRE_KEY, &error)); CHECK(extension.get()); + service()->AddExtension(extension.get()); EXPECT_EQ(std::string(), error); - return ExtensionInfoGenerator(browser_context()).CreateExtensionInfo( - *extension, - api::developer_private::EXTENSION_STATE_ENABLED); + return GenerateExtensionInfo(extension->id()); } void CompareExpectedAndActualOutput( @@ -136,6 +160,11 @@ } } } + + private: + base::Closure quit_closure_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionInfoGeneratorUnitTest); }; // Test some of the basic fields. @@ -148,7 +177,7 @@ const char kName[] = "extension name"; const char kVersion[] = "1.0.0.1"; - std::string id = crx_file::id_util::GenerateId(kName); + std::string id = crx_file::id_util::GenerateId("alpha"); scoped_ptr<base::DictionaryValue> manifest = DictionaryBuilder().Set("name", kName) .Set("version", kVersion) @@ -203,9 +232,8 @@ // a duplication of the logic in the method itself. Instead, test a handful // of fields for sanity. scoped_ptr<api::developer_private::ExtensionInfo> info = - ExtensionInfoGenerator(browser_context()).CreateExtensionInfo( - *extension, developer::EXTENSION_STATE_ENABLED); - ASSERT_TRUE(info); + GenerateExtensionInfo(extension->id()); + ASSERT_TRUE(info.get()); EXPECT_EQ(kName, info->name); EXPECT_EQ(id, info->id); EXPECT_EQ(kVersion, info->version); @@ -238,12 +266,13 @@ // Test an extension that isn't unpacked. manifest_copy->SetString("update_url", "https://clients2.google.com/service/update2/crx"); + id = crx_file::id_util::GenerateId("beta"); extension = ExtensionBuilder().SetManifest(manifest_copy.Pass()) .SetLocation(Manifest::EXTERNAL_PREF) .SetID(id) .Build(); - info = ExtensionInfoGenerator(browser_context()).CreateExtensionInfo( - *extension, developer::EXTENSION_STATE_ENABLED); + service()->AddExtension(extension.get()); + info = GenerateExtensionInfo(extension->id()); EXPECT_EQ(developer::LOCATION_THIRD_PARTY, info->location); EXPECT_FALSE(info->path); } @@ -322,11 +351,8 @@ scoped_refptr<const Extension> no_urls_extension = CreateExtension("no urls", ListBuilder().Pass()); - ExtensionInfoGenerator generator(browser_context()); scoped_ptr<developer::ExtensionInfo> info = - generator.CreateExtensionInfo( - *all_urls_extension, - api::developer_private::EXTENSION_STATE_ENABLED); + GenerateExtensionInfo(all_urls_extension->id()); // The extension should want all urls, but not currently have it. EXPECT_TRUE(info->run_on_all_urls.is_enabled); @@ -336,14 +362,12 @@ util::SetAllowedScriptingOnAllUrls(all_urls_extension->id(), profile(), true); // Now the extension should both want and have all urls. - info = generator.CreateExtensionInfo(*all_urls_extension, - developer::EXTENSION_STATE_ENABLED); + info = GenerateExtensionInfo(all_urls_extension->id()); EXPECT_TRUE(info->run_on_all_urls.is_enabled); EXPECT_TRUE(info->run_on_all_urls.is_active); // The other extension should neither want nor have all urls. - info = generator.CreateExtensionInfo(*no_urls_extension, - developer::EXTENSION_STATE_ENABLED); + info = GenerateExtensionInfo(no_urls_extension->id()); EXPECT_FALSE(info->run_on_all_urls.is_enabled); EXPECT_FALSE(info->run_on_all_urls.is_active); @@ -357,16 +381,14 @@ // Since the extension doesn't have access to all urls (but normally would), // the extension should have the "want" flag even with the switch off. - info = generator.CreateExtensionInfo(*all_urls_extension, - developer::EXTENSION_STATE_ENABLED); + info = GenerateExtensionInfo(all_urls_extension->id()); EXPECT_TRUE(info->run_on_all_urls.is_enabled); EXPECT_FALSE(info->run_on_all_urls.is_active); // If we grant the extension all urls, then the checkbox should still be // there, since it has an explicitly-set user preference. util::SetAllowedScriptingOnAllUrls(all_urls_extension->id(), profile(), true); - info = generator.CreateExtensionInfo(*all_urls_extension, - developer::EXTENSION_STATE_ENABLED); + info = GenerateExtensionInfo(all_urls_extension->id()); EXPECT_TRUE(info->run_on_all_urls.is_enabled); EXPECT_TRUE(info->run_on_all_urls.is_active); @@ -376,8 +398,7 @@ // Even though the extension has all_urls permission, the checkbox shouldn't // show up without the switch. - info = generator.CreateExtensionInfo(*all_urls_extension, - developer::EXTENSION_STATE_ENABLED); + info = GenerateExtensionInfo(all_urls_extension->id()); EXPECT_FALSE(info->run_on_all_urls.is_enabled); EXPECT_TRUE(info->run_on_all_urls.is_active); }
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 578592240..8844619 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
@@ -17,12 +17,12 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/easy_unlock_screenlock_state_handler.h" #include "chrome/browser/signin/easy_unlock_service.h" -#include "chrome/browser/signin/screenlock_bridge.h" #include "chrome/browser/ui/proximity_auth/proximity_auth_error_bubble.h" #include "chrome/common/extensions/api/easy_unlock_private.h" #include "chrome/grit/generated_resources.h" #include "components/proximity_auth/bluetooth_util.h" #include "components/proximity_auth/cryptauth/cryptauth_enrollment_utils.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/proximity_auth/switches.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc index f4b8f745..9c5e57d 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
@@ -64,7 +64,7 @@ void EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey( const std::string& public_key_der, const std::string& error_message) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (error_message.empty()) { Respond(ArgumentList(api_epki::GenerateKey::Results::Create( std::vector<char>(public_key_der.begin(), public_key_der.end())))); @@ -98,7 +98,7 @@ void EnterprisePlatformKeysGetCertificatesFunction::OnGotCertificates( scoped_ptr<net::CertificateList> certs, const std::string& error_message) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!error_message.empty()) { Respond(Error(error_message)); return; @@ -151,7 +151,7 @@ void EnterprisePlatformKeysImportCertificateFunction::OnImportedCertificate( const std::string& error_message) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (error_message.empty()) Respond(NoArguments()); else @@ -190,7 +190,7 @@ void EnterprisePlatformKeysRemoveCertificateFunction::OnRemovedCertificate( const std::string& error_message) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (error_message.empty()) Respond(NoArguments()); else @@ -215,7 +215,7 @@ void EnterprisePlatformKeysInternalGetTokensFunction::OnGotTokens( scoped_ptr<std::vector<std::string> > platform_keys_token_ids, const std::string& error_message) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!error_message.empty()) { Respond(Error(error_message)); return;
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc index 7c653e7..8db319d9 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
@@ -408,12 +408,8 @@ void EPKPChallengeUserKey::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kAttestationEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kAttestationExtensionWhitelist, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kAttestationEnabled, false); + registry->RegisterListPref(prefs::kAttestationExtensionWhitelist); } bool EPKPChallengeUserKey::RunAsync() {
diff --git a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc index 3f64a3f..08f01f03 100644 --- a/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc +++ b/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -168,7 +168,7 @@ settings_helper_.SetBoolean(chromeos::kDeviceAttestationEnabled, true); } - virtual void SetUp() override { + void SetUp() override { BrowserWithTestWindowTest::SetUp(); // Set the user preferences.
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc index 46f29431..6322c6a 100644 --- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc +++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -73,8 +73,10 @@ ~BrowserActionApiTest() override {} protected: - BrowserActionTestUtil GetBrowserActionsBar() { - return BrowserActionTestUtil(browser()); + BrowserActionTestUtil* GetBrowserActionsBar() { + if (!browser_action_test_util_) + browser_action_test_util_.reset(new BrowserActionTestUtil(browser())); + return browser_action_test_util_.get(); } bool OpenPopup(int index) { @@ -82,16 +84,21 @@ content::WindowedNotificationObserver popup_observer( content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, content::NotificationService::AllSources()); - GetBrowserActionsBar().Press(index); + GetBrowserActionsBar()->Press(index); popup_observer.Wait(); EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); - return GetBrowserActionsBar().HasPopup(); + return GetBrowserActionsBar()->HasPopup(); } ExtensionAction* GetBrowserAction(const Extension& extension) { return ExtensionActionManager::Get(browser()->profile())-> GetBrowserAction(extension); } + + private: + scoped_ptr<BrowserActionTestUtil> browser_action_test_util_; + + DISALLOW_COPY_AND_ASSIGN(BrowserActionApiTest); }; IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, Basic) { @@ -101,7 +108,7 @@ ASSERT_TRUE(extension) << message_; // Test that there is a browser action in the toolbar. - ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); + ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); // Tell the extension to update the browser action state. ResultCatcher catcher; @@ -148,8 +155,8 @@ GetBrowserAction(*extension), NULL); // Test that there is a browser action in the toolbar. - ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); - EXPECT_TRUE(GetBrowserActionsBar().HasIcon(0)); + ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); + EXPECT_TRUE(GetBrowserActionsBar()->HasIcon(0)); gfx::Image action_icon = icon_factory.GetIcon(0); uint32_t action_icon_last_id = action_icon.ToSkBitmap()->getGenerationID(); @@ -163,7 +170,7 @@ ResultCatcher catcher; // Tell the extension to update the icon using ImageData object. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); action_icon = icon_factory.GetIcon(0); @@ -176,11 +183,11 @@ EXPECT_TRUE( ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()), - *GetBrowserActionsBar().GetIcon(0).ToImageSkia(), + *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(), 1.0f)); // Tell the extension to update the icon using path. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); action_icon = icon_factory.GetIcon(0); @@ -194,12 +201,12 @@ EXPECT_TRUE( ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()), - *GetBrowserActionsBar().GetIcon(0).ToImageSkia(), + *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(), 1.0f)); // Tell the extension to update the icon using dictionary of ImageData // objects. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); action_icon = icon_factory.GetIcon(0); @@ -212,11 +219,11 @@ EXPECT_TRUE( ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()), - *GetBrowserActionsBar().GetIcon(0).ToImageSkia(), + *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(), 1.0f)); // Tell the extension to update the icon using dictionary of paths. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); action_icon = icon_factory.GetIcon(0); @@ -229,12 +236,12 @@ EXPECT_TRUE( ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()), - *GetBrowserActionsBar().GetIcon(0).ToImageSkia(), + *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(), 1.0f)); // Tell the extension to update the icon using dictionary of ImageData // objects, but setting only size 19. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); action_icon = icon_factory.GetIcon(0); @@ -247,12 +254,12 @@ EXPECT_TRUE( ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()), - *GetBrowserActionsBar().GetIcon(0).ToImageSkia(), + *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(), 1.0f)); // Tell the extension to update the icon using dictionary of paths, but // setting only size 19. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); action_icon = icon_factory.GetIcon(0); @@ -265,12 +272,12 @@ EXPECT_TRUE( ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()), - *GetBrowserActionsBar().GetIcon(0).ToImageSkia(), + *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(), 1.0f)); // Tell the extension to update the icon using dictionary of ImageData // objects, but setting only size 38. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); action_icon = icon_factory.GetIcon(0); @@ -290,16 +297,16 @@ EXPECT_TRUE( ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon_skia), - *GetBrowserActionsBar().GetIcon(0).ToImageSkia(), + *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(), 2.0f)); // Try setting icon with empty dictionary of ImageData objects. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_FALSE(catcher.GetNextResult()); EXPECT_EQ(kEmptyImageDataError, catcher.message()); // Try setting icon with empty dictionary of path objects. - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_FALSE(catcher.GetNextResult()); EXPECT_EQ(kEmptyPathError, catcher.message()); } @@ -311,26 +318,26 @@ ASSERT_TRUE(extension) << message_; // Test that there is a browser action in the toolbar and that it has an icon. - ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); - EXPECT_TRUE(GetBrowserActionsBar().HasIcon(0)); + ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); + EXPECT_TRUE(GetBrowserActionsBar()->HasIcon(0)); // Execute the action, its title should change. ResultCatcher catcher; - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); - EXPECT_EQ("Showing icon 2", GetBrowserActionsBar().GetTooltip(0)); + EXPECT_EQ("Showing icon 2", GetBrowserActionsBar()->GetTooltip(0)); // Open a new tab, the title should go back. chrome::NewTab(browser()); - EXPECT_EQ("hi!", GetBrowserActionsBar().GetTooltip(0)); + EXPECT_EQ("hi!", GetBrowserActionsBar()->GetTooltip(0)); // Go back to first tab, changed title should reappear. browser()->tab_strip_model()->ActivateTabAt(0, true); - EXPECT_EQ("Showing icon 2", GetBrowserActionsBar().GetTooltip(0)); + EXPECT_EQ("Showing icon 2", GetBrowserActionsBar()->GetTooltip(0)); // Reload that tab, default title should come back. ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); - EXPECT_EQ("hi!", GetBrowserActionsBar().GetTooltip(0)); + EXPECT_EQ("hi!", GetBrowserActionsBar()->GetTooltip(0)); } // http://code.google.com/p/chromium/issues/detail?id=70829 @@ -338,7 +345,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, DISABLED_BrowserActionPopup) { ASSERT_TRUE( LoadExtension(test_data_dir_.AppendASCII("browser_action/popup"))); - BrowserActionTestUtil actions_bar = GetBrowserActionsBar(); + BrowserActionTestUtil* actions_bar = GetBrowserActionsBar(); const Extension* extension = GetSingleLoadedExtension(); ASSERT_TRUE(extension) << message_; @@ -355,17 +362,17 @@ // Simulate a click on the browser action and verify the size of the resulting // popup. The first one tries to be 0x0, so it should be the min values. ASSERT_TRUE(OpenPopup(0)); - EXPECT_EQ(minSize, actions_bar.GetPopupSize()); - EXPECT_TRUE(actions_bar.HidePopup()); + EXPECT_EQ(minSize, actions_bar->GetPopupSize()); + EXPECT_TRUE(actions_bar->HidePopup()); ASSERT_TRUE(OpenPopup(0)); - EXPECT_EQ(middleSize, actions_bar.GetPopupSize()); - EXPECT_TRUE(actions_bar.HidePopup()); + EXPECT_EQ(middleSize, actions_bar->GetPopupSize()); + EXPECT_TRUE(actions_bar->HidePopup()); // One more time, but this time it should be constrained by the max values. ASSERT_TRUE(OpenPopup(0)); - EXPECT_EQ(maxSize, actions_bar.GetPopupSize()); - EXPECT_TRUE(actions_bar.HidePopup()); + EXPECT_EQ(maxSize, actions_bar->GetPopupSize()); + EXPECT_TRUE(actions_bar->HidePopup()); } // Test that calling chrome.browserAction.setPopup() can enable and change @@ -389,7 +396,7 @@ // will add a popup. { ResultCatcher catcher; - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); ASSERT_TRUE(catcher.GetNextResult()); } @@ -467,7 +474,7 @@ ASSERT_TRUE(extension) << message_; // Test that there is a browser action in the toolbar. - ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); + ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); // Open an incognito window and test that the browser action isn't there by // default. @@ -568,7 +575,7 @@ ASSERT_TRUE(extension) << message_; // Test that there is a browser action in the toolbar. - ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); + ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); // Test that CSS values (#FF0000) set color correctly. ExtensionAction* action = GetBrowserAction(*extension); @@ -600,7 +607,7 @@ ASSERT_TRUE(extension) << message_; // Test that there is a browser action in the toolbar. - ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); + ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); // Test the getters for defaults. ResultCatcher catcher; @@ -623,7 +630,7 @@ ASSERT_TRUE(extension) << message_; // Test that there is a browser action in the toolbar. - ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions()); + ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); ui_test_utils::NavigateToURL( browser(), @@ -635,7 +642,7 @@ // Simulate a click on the browser action icon. { ResultCatcher catcher; - GetBrowserActionsBar().Press(0); + GetBrowserActionsBar()->Press(0); EXPECT_TRUE(catcher.GetNextResult()); }
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc index 35de0e5..9d8c45c 100644 --- a/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc +++ b/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
@@ -80,7 +80,7 @@ if (!ShouldRunPopupTest()) return; - BrowserActionTestUtil browserActionBar = BrowserActionTestUtil(browser()); + BrowserActionTestUtil browserActionBar(browser()); // Setup extension message listener to wait for javascript to finish running. ExtensionTestMessageListener listener("ready", true); {
diff --git a/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc b/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc index 35355e84..46db5da9 100644 --- a/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc +++ b/chrome/browser/extensions/api/gcd_private/gcd_private_api.cc
@@ -636,37 +636,6 @@ SendResponse(true); } -GcdPrivateEstablishSessionFunction::GcdPrivateEstablishSessionFunction() { -} - -GcdPrivateEstablishSessionFunction::~GcdPrivateEstablishSessionFunction() { -} - -bool GcdPrivateEstablishSessionFunction::RunAsync() { - scoped_ptr<gcd_private::EstablishSession::Params> params = - gcd_private::EstablishSession::Params::Create(*args_); - - if (!params) - return false; - - GcdPrivateAPIImpl* gcd_api = GcdPrivateAPIImpl::Get(GetProfile()); - - GcdPrivateAPIImpl::EstablishSessionCallback callback = base::Bind( - &GcdPrivateEstablishSessionFunction::OnSessionInitialized, this); - gcd_api->EstablishSession(params->ip_address, params->port, callback); - - return true; -} - -void GcdPrivateEstablishSessionFunction::OnSessionInitialized( - int session_id, - api::gcd_private::Status status, - const std::vector<api::gcd_private::PairingType>& pairing_types) { - results_ = gcd_private::EstablishSession::Results::Create(session_id, status, - pairing_types); - SendResponse(true); -} - GcdPrivateCreateSessionFunction::GcdPrivateCreateSessionFunction() { } @@ -693,8 +662,8 @@ int session_id, api::gcd_private::Status status, const std::vector<api::gcd_private::PairingType>& pairing_types) { - results_ = gcd_private::EstablishSession::Results::Create(session_id, status, - pairing_types); + results_ = gcd_private::CreateSession::Results::Create(session_id, status, + pairing_types); SendResponse(true); }
diff --git a/chrome/browser/extensions/api/gcd_private/gcd_private_api.h b/chrome/browser/extensions/api/gcd_private/gcd_private_api.h index 370261f..f29f357 100644 --- a/chrome/browser/extensions/api/gcd_private/gcd_private_api.h +++ b/chrome/browser/extensions/api/gcd_private/gcd_private_api.h
@@ -123,26 +123,6 @@ bool RunSync() override; }; -class GcdPrivateEstablishSessionFunction : public ChromeAsyncExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("gcdPrivate.establishSession", - GCDPRIVATE_ESTABLISHSESSION) - - GcdPrivateEstablishSessionFunction(); - - protected: - ~GcdPrivateEstablishSessionFunction() override; - - // AsyncExtensionFunction overrides. - bool RunAsync() override; - - private: - void OnSessionInitialized( - int session_id, - api::gcd_private::Status status, - const std::vector<api::gcd_private::PairingType>& pairing_types); -}; - class GcdPrivateCreateSessionFunction : public ChromeAsyncExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("gcdPrivate.createSession",
diff --git a/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc b/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc index 82ab7914..931225ad 100644 --- a/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc +++ b/chrome/browser/extensions/api/gcd_private/gcd_private_apitest.cc
@@ -59,6 +59,8 @@ " \"maxRole\": \"owner\"" " }}]}"; +#if defined(ENABLE_MDNS) + const char kPrivetInfoResponse[] = "{\"version\":\"3.0\"," "\"endpoints\":{\"httpsPort\": 443}," @@ -68,8 +70,6 @@ " \"crypto\":[\"p224_spake2\"]" "}}"; -#if defined(ENABLE_MDNS) - const uint8 kAnnouncePacket[] = { // Header 0x00, 0x00, // ID is zeroed out @@ -283,16 +283,17 @@ EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "get_cloud_list.html")); } +#if defined(ENABLE_MDNS) IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, Session) { - url_fetcher_factory_.SetFakeResponse(GURL("http://1.2.3.4:9090/privet/info"), + test_service_discovery_client_->SimulateReceive(kAnnouncePacket, + sizeof(kAnnouncePacket)); + url_fetcher_factory_.SetFakeResponse(GURL("http://1.2.3.4:8888/privet/info"), kPrivetInfoResponse, net::HTTP_OK, net::URLRequestStatus::SUCCESS); EXPECT_TRUE(RunExtensionSubtest("gcd_private/api", "session.html")); } -#if defined(ENABLE_MDNS) - IN_PROC_BROWSER_TEST_F(GcdPrivateAPITest, AddBefore) { test_service_discovery_client_->SimulateReceive(kAnnouncePacket, sizeof(kAnnouncePacket));
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc index 1d4ba1e..2debe5b0 100644 --- a/chrome/browser/extensions/api/identity/identity_apitest.cc +++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -19,12 +19,12 @@ #include "chrome/browser/extensions/extension_function_test_utils.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/account_reconcilor_factory.h" #include "chrome/browser/signin/account_tracker_service_factory.h" -#include "chrome/browser/signin/fake_account_reconcilor.h" +#include "chrome/browser/signin/fake_gaia_cookie_manager_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" #include "chrome/browser/signin/fake_signin_manager.h" +#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/browser.h" @@ -555,8 +555,8 @@ context, &FakeSigninManagerBase::Build); ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory( context, &BuildFakeProfileOAuth2TokenService); - AccountReconcilorFactory::GetInstance()->SetTestingFactory( - context, &FakeAccountReconcilor::Build); + GaiaCookieManagerServiceFactory::GetInstance()->SetTestingFactory( + context, &FakeGaiaCookieManagerService::Build); } void SetUpOnMainThread() override { @@ -570,6 +570,8 @@ ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile( profile())); ASSERT_TRUE(token_service_); + GaiaCookieManagerServiceFactory::GetInstance()->GetForProfile(profile()) + ->Init(); } protected:
diff --git a/chrome/browser/extensions/api/instance_id/OWNERS b/chrome/browser/extensions/api/instance_id/OWNERS new file mode 100644 index 0000000..e8e7e8b --- /dev/null +++ b/chrome/browser/extensions/api/instance_id/OWNERS
@@ -0,0 +1,2 @@ +fgorski@chromium.org +jianli@chromium.org \ No newline at end of file
diff --git a/chrome/browser/extensions/api/instance_id/instance_id_api.cc b/chrome/browser/extensions/api/instance_id/instance_id_api.cc new file mode 100644 index 0000000..fc76fa9 --- /dev/null +++ b/chrome/browser/extensions/api/instance_id/instance_id_api.cc
@@ -0,0 +1,57 @@ +// 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/extensions/api/instance_id/instance_id_api.h" + +#include "base/logging.h" +#include "extensions/common/extension.h" + +namespace extensions { + +InstanceIDGetIDFunction::InstanceIDGetIDFunction() {} + +InstanceIDGetIDFunction::~InstanceIDGetIDFunction() {} + +ExtensionFunction::ResponseAction InstanceIDGetIDFunction::Run() { + NOTIMPLEMENTED(); + return RespondLater(); +} + +InstanceIDGetCreationTimeFunction::InstanceIDGetCreationTimeFunction() {} + +InstanceIDGetCreationTimeFunction::~InstanceIDGetCreationTimeFunction() {} + +ExtensionFunction::ResponseAction InstanceIDGetCreationTimeFunction::Run() { + NOTIMPLEMENTED(); + return RespondLater(); +} + +InstanceIDGetTokenFunction::InstanceIDGetTokenFunction() {} + +InstanceIDGetTokenFunction::~InstanceIDGetTokenFunction() {} + +ExtensionFunction::ResponseAction InstanceIDGetTokenFunction::Run() { + NOTIMPLEMENTED(); + return RespondLater(); +} + +InstanceIDDeleteTokenFunction::InstanceIDDeleteTokenFunction() {} + +InstanceIDDeleteTokenFunction::~InstanceIDDeleteTokenFunction() {} + +ExtensionFunction::ResponseAction InstanceIDDeleteTokenFunction::Run() { + NOTIMPLEMENTED(); + return RespondLater(); +} + +InstanceIDDeleteIDFunction::InstanceIDDeleteIDFunction() {} + +InstanceIDDeleteIDFunction::~InstanceIDDeleteIDFunction() {} + +ExtensionFunction::ResponseAction InstanceIDDeleteIDFunction::Run() { + NOTIMPLEMENTED(); + return RespondLater(); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/instance_id/instance_id_api.h b/chrome/browser/extensions/api/instance_id/instance_id_api.h new file mode 100644 index 0000000..c7530ebb --- /dev/null +++ b/chrome/browser/extensions/api/instance_id/instance_id_api.h
@@ -0,0 +1,83 @@ +// 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 CHROME_BROWSER_EXTENSIONS_API_INSTANCE_ID_INSTANCE_ID_API_H_ +#define CHROME_BROWSER_EXTENSIONS_API_INSTANCE_ID_INSTANCE_ID_API_H_ + +#include "extensions/browser/extension_function.h" + +class Profile; + +namespace extensions { + +class InstanceIDGetIDFunction : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("instanceID.getID", INSTANCEID_GETID); + + InstanceIDGetIDFunction(); + + protected: + ~InstanceIDGetIDFunction() override; + + // ExtensionFunction: + ResponseAction Run() override; +}; + +class InstanceIDGetCreationTimeFunction : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("instanceID.getCreationTime", + INSTANCEID_GETCREATIONTIME); + + InstanceIDGetCreationTimeFunction(); + + protected: + ~InstanceIDGetCreationTimeFunction() override; + + // ExtensionFunction: + ResponseAction Run() override; +}; + +class InstanceIDGetTokenFunction : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("instanceID.getToken", INSTANCEID_GETTOKEN); + + InstanceIDGetTokenFunction(); + + protected: + ~InstanceIDGetTokenFunction() override; + + // ExtensionFunction: + ResponseAction Run() override; +}; + +class InstanceIDDeleteTokenFunction : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("instanceID.DeleteToken", INSTANCEID_DELETETOKEN); + + InstanceIDDeleteTokenFunction(); + + protected: + ~InstanceIDDeleteTokenFunction() override; + + // ExtensionFunction: + ResponseAction Run() override; +}; + +class InstanceIDDeleteIDFunction : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("instanceID.deleteID", + INSTANCEID_DELETEID); + + InstanceIDDeleteIDFunction(); + + protected: + ~InstanceIDDeleteIDFunction() override; + + // ExtensionFunction: + ResponseAction Run() override; +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_INSTANCE_ID_INSTANCE_ID_API_H_
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc index 11761873..487b92e 100644 --- a/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
@@ -177,7 +177,7 @@ void PlatformKeysInternalSelectClientCertificatesFunction:: OnSelectedCertificates(scoped_ptr<net::CertificateList> matches, const std::string& error_message) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!error_message.empty()) { Respond(Error(error_message)); return; @@ -266,7 +266,7 @@ void PlatformKeysInternalSignFunction::OnSigned( const std::string& signature, const std::string& error_message) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (error_message.empty()) Respond(ArgumentList(api_pki::Sign::Results::Create( std::vector<char>(signature.begin(), signature.end()))));
diff --git a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc index 2c51e27b..01ff012 100644 --- a/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc +++ b/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
@@ -162,7 +162,7 @@ void SetUpTestSystemSlotOnIO(content::ResourceContext* context, const base::Closure& done_callback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); test_system_slot_.reset(new crypto::ScopedTestSystemNSSKeySlot()); ASSERT_TRUE(test_system_slot_->ConstructedSuccessfully()); @@ -171,7 +171,7 @@ } void TearDownTestSystemSlotOnIO(const base::Closure& done_callback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); test_system_slot_.reset(); content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
diff --git a/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc b/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc index 86d6a5d..1ffe795 100644 --- a/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc +++ b/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc
@@ -109,14 +109,10 @@ void ExtensionControlledPrefsTest::RegisterPreferences( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - kPref1, kDefaultPref1, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - kPref2, kDefaultPref2, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - kPref3, kDefaultPref3, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - kPref4, kDefaultPref4, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(kPref1, kDefaultPref1); + registry->RegisterStringPref(kPref2, kDefaultPref2); + registry->RegisterStringPref(kPref3, kDefaultPref3); + registry->RegisterStringPref(kPref4, kDefaultPref4); } void ExtensionControlledPrefsTest::InstallExtensionControlledPref(
diff --git a/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc b/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc index 78d1c49..283c569 100644 --- a/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc +++ b/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.cc
@@ -8,6 +8,7 @@ #include "base/values.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/easy_unlock_service.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/common/extensions/api/screenlock_private.h" #include "chrome/common/extensions/extension_constants.h" #include "extensions/browser/app_window/app_window_registry.h" @@ -20,23 +21,23 @@ namespace { screenlock::AuthType FromLockHandlerAuthType( - ScreenlockBridge::LockHandler::AuthType auth_type) { + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type) { switch (auth_type) { - case ScreenlockBridge::LockHandler::OFFLINE_PASSWORD: + case proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD: return screenlock::AUTH_TYPE_OFFLINEPASSWORD; - case ScreenlockBridge::LockHandler::NUMERIC_PIN: + case proximity_auth::ScreenlockBridge::LockHandler::NUMERIC_PIN: return screenlock::AUTH_TYPE_NUMERICPIN; - case ScreenlockBridge::LockHandler::USER_CLICK: + case proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK: return screenlock::AUTH_TYPE_USERCLICK; - case ScreenlockBridge::LockHandler::ONLINE_SIGN_IN: + case proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN: // Apps should treat forced online sign in same as system password. return screenlock::AUTH_TYPE_OFFLINEPASSWORD; - case ScreenlockBridge::LockHandler::EXPAND_THEN_USER_CLICK: + case proximity_auth::ScreenlockBridge::LockHandler::EXPAND_THEN_USER_CLICK: // This type is used for public sessions, which do not support screen // locking. NOTREACHED(); return screenlock::AUTH_TYPE_NONE; - case ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD: + case proximity_auth::ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD: return screenlock::AUTH_TYPE_OFFLINEPASSWORD; } NOTREACHED(); @@ -50,7 +51,8 @@ ScreenlockPrivateGetLockedFunction::~ScreenlockPrivateGetLockedFunction() {} bool ScreenlockPrivateGetLockedFunction::RunAsync() { - SetResult(new base::FundamentalValue(ScreenlockBridge::Get()->IsLocked())); + SetResult( + new base::FundamentalValue(GetScreenlockBridgeInstance()->IsLocked())); SendResponse(error_.empty()); return true; } @@ -75,9 +77,9 @@ if (service) service->SetTrialRun(); } - ScreenlockBridge::Get()->Lock(GetProfile()); + GetScreenlockBridgeInstance()->Lock(GetProfile()); } else { - ScreenlockBridge::Get()->Unlock(GetProfile()); + GetScreenlockBridgeInstance()->Unlock(GetProfile()); } SendResponse(error_.empty()); return true; @@ -104,19 +106,19 @@ ScreenlockPrivateEventRouter::ScreenlockPrivateEventRouter( content::BrowserContext* context) : browser_context_(context) { - ScreenlockBridge::Get()->AddObserver(this); + GetScreenlockBridgeInstance()->AddObserver(this); } ScreenlockPrivateEventRouter::~ScreenlockPrivateEventRouter() {} void ScreenlockPrivateEventRouter::OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { DispatchEvent(screenlock::OnChanged::kEventName, new base::FundamentalValue(true)); } void ScreenlockPrivateEventRouter::OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { DispatchEvent(screenlock::OnChanged::kEventName, new base::FundamentalValue(false)); } @@ -146,11 +148,11 @@ } void ScreenlockPrivateEventRouter::Shutdown() { - ScreenlockBridge::Get()->RemoveObserver(this); + GetScreenlockBridgeInstance()->RemoveObserver(this); } bool ScreenlockPrivateEventRouter::OnAuthAttempted( - ScreenlockBridge::LockHandler::AuthType auth_type, + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type, const std::string& value) { extensions::EventRouter* router = extensions::EventRouter::Get(browser_context_);
diff --git a/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h b/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h index fb87f12..d120c46e 100644 --- a/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h +++ b/chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h
@@ -8,7 +8,7 @@ #include <string> #include "chrome/browser/extensions/chrome_extension_function.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "extensions/browser/browser_context_keyed_api_factory.h" namespace extensions { @@ -50,14 +50,16 @@ DISALLOW_COPY_AND_ASSIGN(ScreenlockPrivateAcceptAuthAttemptFunction); }; -class ScreenlockPrivateEventRouter : public extensions::BrowserContextKeyedAPI, - public ScreenlockBridge::Observer { +class ScreenlockPrivateEventRouter + : public extensions::BrowserContextKeyedAPI, + public proximity_auth::ScreenlockBridge::Observer { public: explicit ScreenlockPrivateEventRouter(content::BrowserContext* context); ~ScreenlockPrivateEventRouter() override; - bool OnAuthAttempted(ScreenlockBridge::LockHandler::AuthType auth_type, - const std::string& value); + bool OnAuthAttempted( + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type, + const std::string& value); // BrowserContextKeyedAPI static extensions::BrowserContextKeyedAPIFactory< @@ -65,11 +67,12 @@ GetFactoryInstance(); void Shutdown() override; - // ScreenlockBridge::Observer - void OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; + // proximity_auth::ScreenlockBridge::Observer + void OnScreenDidLock(proximity_auth::ScreenlockBridge::LockHandler::ScreenType + screen_type) override; void OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) + override; void OnFocusedUserChanged(const std::string& user_id) override; private:
diff --git a/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc b/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc index cf59938..3bc8d57c 100644 --- a/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc +++ b/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/easy_unlock_service.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/common/profile_management_switches.h" @@ -75,9 +76,8 @@ const content::NotificationDetails& details) override { const std::string& content = *content::Details<std::string>(details).ptr(); if (content == kAttemptClickAuthMessage) { - ScreenlockBridge::Get()->lock_handler()->SetAuthType( - kTestUser, - ScreenlockBridge::LockHandler::USER_CLICK, + GetScreenlockBridgeInstance()->lock_handler()->SetAuthType( + kTestUser, proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, base::string16()); EasyUnlockService::Get(profile())->AttemptAuth(kTestUser); }
diff --git a/chrome/browser/extensions/api/search_engines_private/OWNERS b/chrome/browser/extensions/api/search_engines_private/OWNERS new file mode 100644 index 0000000..52a8bf8 --- /dev/null +++ b/chrome/browser/extensions/api/search_engines_private/OWNERS
@@ -0,0 +1,3 @@ +jlklein@chromium.org +orenb@chromium.org +stevenjb@chromium.org
diff --git a/chrome/browser/extensions/api/search_engines_private/search_engines_private_api.cc b/chrome/browser/extensions/api/search_engines_private/search_engines_private_api.cc new file mode 100644 index 0000000..6fc7e43bd --- /dev/null +++ b/chrome/browser/extensions/api/search_engines_private/search_engines_private_api.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 "chrome/browser/extensions/api/search_engines_private/search_engines_private_api.h" + +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/extensions/chrome_extension_function.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" +#include "chrome/common/extensions/api/search_engines_private.h" +#include "components/search_engines/template_url_service.h" +#include "extensions/browser/extension_function_registry.h" + +namespace extensions { + +//////////////////////////////////////////////////////////////////////////////// +// SearchEnginesPrivateGetDefaultSearchEnginesFunction + +SearchEnginesPrivateGetDefaultSearchEnginesFunction:: + SearchEnginesPrivateGetDefaultSearchEnginesFunction() + : chrome_details_(this) { +} + +SearchEnginesPrivateGetDefaultSearchEnginesFunction:: + ~SearchEnginesPrivateGetDefaultSearchEnginesFunction() { +} + +ExtensionFunction::ResponseAction +SearchEnginesPrivateGetDefaultSearchEnginesFunction::Run() { + TemplateURLService* template_url_service = + TemplateURLServiceFactory::GetForProfile(chrome_details_.GetProfile()); + base::ListValue* engines = new base::ListValue(); + + const TemplateURL* default_url = + template_url_service->GetDefaultSearchProvider(); + std::vector<TemplateURL*> urls = template_url_service->GetTemplateURLs(); + for (size_t i = 0; i < urls.size(); i++) { + api::search_engines_private::SearchEngine engine; + engine.guid = urls[i]->sync_guid(); + engine.name = base::UTF16ToASCII(urls[i]->short_name()); + if (urls[i] == default_url) + engine.is_selected = scoped_ptr<bool>(new bool(true)); + + engines->Append(engine.ToValue().release()); + } + + return RespondNow(OneArgument(engines)); +} + +//////////////////////////////////////////////////////////////////////////////// +// SearchEnginesPrivateSetSelectedSearchEngineFunction + +SearchEnginesPrivateSetSelectedSearchEngineFunction:: + SearchEnginesPrivateSetSelectedSearchEngineFunction() + : chrome_details_(this) { +} + +SearchEnginesPrivateSetSelectedSearchEngineFunction:: + ~SearchEnginesPrivateSetSelectedSearchEngineFunction() { +} + +ExtensionFunction::ResponseAction +SearchEnginesPrivateSetSelectedSearchEngineFunction::Run() { + scoped_ptr<api::search_engines_private::SetSelectedSearchEngine::Params> + parameters = + api::search_engines_private::SetSelectedSearchEngine::Params::Create( + *args_); + EXTENSION_FUNCTION_VALIDATE(parameters.get()); + + TemplateURLService* template_url_service = + TemplateURLServiceFactory::GetForProfile(chrome_details_.GetProfile()); + template_url_service->SetUserSelectedDefaultSearchProvider( + template_url_service->GetTemplateURLForGUID(parameters->guid)); + return RespondNow(NoArguments()); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/search_engines_private/search_engines_private_api.h b/chrome/browser/extensions/api/search_engines_private/search_engines_private_api.h new file mode 100644 index 0000000..9965ef5 --- /dev/null +++ b/chrome/browser/extensions/api/search_engines_private/search_engines_private_api.h
@@ -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. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_API_H_ +#define CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_API_H_ + +#include <string> + +#include "base/macros.h" +#include "chrome/browser/extensions/chrome_extension_function_details.h" +#include "extensions/browser/extension_function.h" + +namespace extensions { + +// Implements the chrome.searchEnginesPrivate.getDefaultSearchEngines method. +class SearchEnginesPrivateGetDefaultSearchEnginesFunction + : public UIThreadExtensionFunction { + public: + SearchEnginesPrivateGetDefaultSearchEnginesFunction(); + DECLARE_EXTENSION_FUNCTION("searchEnginesPrivate.getDefaultSearchEngines", + SEARCHENGINESPRIVATE_GETDEFAULTSEARCHENGINES); + + protected: + ~SearchEnginesPrivateGetDefaultSearchEnginesFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + ChromeExtensionFunctionDetails chrome_details_; + + DISALLOW_COPY_AND_ASSIGN(SearchEnginesPrivateGetDefaultSearchEnginesFunction); +}; + +// Implements the chrome.searchEnginesPrivate.setSelectedSearchEngine method. +class SearchEnginesPrivateSetSelectedSearchEngineFunction + : public UIThreadExtensionFunction { + public: + SearchEnginesPrivateSetSelectedSearchEngineFunction(); + DECLARE_EXTENSION_FUNCTION("searchEnginesPrivate.setSelectedSearchEngine", + SEARCHENGINESPRIVATE_SETSELECTEDSEARCHENGINE); + + protected: + ~SearchEnginesPrivateSetSelectedSearchEngineFunction() override; + + // AsyncExtensionFunction overrides. + ResponseAction Run() override; + + private: + ChromeExtensionFunctionDetails chrome_details_; + + DISALLOW_COPY_AND_ASSIGN(SearchEnginesPrivateSetSelectedSearchEngineFunction); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/search_engines_private/search_engines_private_apitest.cc b/chrome/browser/extensions/api/search_engines_private/search_engines_private_apitest.cc new file mode 100644 index 0000000..6f6feda --- /dev/null +++ b/chrome/browser/extensions/api/search_engines_private/search_engines_private_apitest.cc
@@ -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. + +#include "base/command_line.h" +#include "base/values.h" +#include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/common/extensions/api/search_engines_private.h" +#include "components/keyed_service/core/keyed_service.h" +#include "content/public/test/test_utils.h" +#include "extensions/common/switches.h" + +namespace extensions { + +namespace { + +class SearchEnginesPrivateApiTest : public ExtensionApiTest { + public: + SearchEnginesPrivateApiTest() {} + ~SearchEnginesPrivateApiTest() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + ExtensionApiTest::SetUpCommandLine(command_line); + } + + void SetUpOnMainThread() override { + ExtensionApiTest::SetUpOnMainThread(); + content::RunAllPendingInMessageLoop(); + } + + protected: + bool RunSearchEnginesSubtest(const std::string& subtest) { + return RunExtensionSubtest("search_engines_private", + "main.html?" + subtest, + kFlagLoadAsComponent); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SearchEnginesPrivateApiTest); +}; + +} // namespace + +IN_PROC_BROWSER_TEST_F(SearchEnginesPrivateApiTest, SetSelectedSearchEngine) { + EXPECT_TRUE(RunSearchEnginesSubtest("setSelectedSearchEngine")) << message_; +} + +IN_PROC_BROWSER_TEST_F(SearchEnginesPrivateApiTest, + OnDefaultSearchEnginesChanged) { + EXPECT_TRUE(RunSearchEnginesSubtest("onDefaultSearchEnginesChanged")) + << message_; +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router.cc b/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router.cc new file mode 100644 index 0000000..ac62389 --- /dev/null +++ b/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router.cc
@@ -0,0 +1,122 @@ +// 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/extensions/api/search_engines_private/search_engines_private_event_router.h" + +#include <vector> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" +#include "chrome/common/extensions/api/search_engines_private.h" +#include "content/public/browser/browser_context.h" + +namespace extensions { + +SearchEnginesPrivateEventRouter::SearchEnginesPrivateEventRouter( + content::BrowserContext* context) + : template_url_service_(nullptr), + context_(context), + listening_(false) { + // Register with the event router so we know when renderers are listening to + // our events. We first check and see if there *is* an event router, because + // some unit tests try to create all context services, but don't initialize + // the event router first. + EventRouter* event_router = EventRouter::Get(context_); + if (!event_router) + return; + + event_router->RegisterObserver( + this, + api::search_engines_private::OnDefaultSearchEnginesChanged::kEventName); + template_url_service_ = TemplateURLServiceFactory::GetForProfile( + Profile::FromBrowserContext(context_)); + StartOrStopListeningForSearchEnginesChanges(); +} + +SearchEnginesPrivateEventRouter::~SearchEnginesPrivateEventRouter() { + DCHECK(!listening_); +} + +void SearchEnginesPrivateEventRouter::Shutdown() { + // Unregister with the event router. We first check and see if there *is* an + // event router, because some unit tests try to shutdown all context services, + // but didn't initialize the event router first. + EventRouter* event_router = EventRouter::Get(context_); + if (event_router) + event_router->UnregisterObserver(this); + + if (listening_) + template_url_service_->RemoveObserver(this); + + listening_ = false; +} + +void SearchEnginesPrivateEventRouter::OnListenerAdded( + const EventListenerInfo& details) { + // Start listening to search engines change events. + StartOrStopListeningForSearchEnginesChanges(); +} + +void SearchEnginesPrivateEventRouter::OnListenerRemoved( + const EventListenerInfo& details) { + // Stop listening to events if there are no more listeners. + StartOrStopListeningForSearchEnginesChanges(); +} + +void SearchEnginesPrivateEventRouter::OnTemplateURLServiceChanged() { + if (!template_url_service_ || !template_url_service_->loaded()) + return; + + const TemplateURL* default_url = + template_url_service_->GetDefaultSearchProvider(); + std::vector<TemplateURL*> urls = template_url_service_->GetTemplateURLs(); + + std::vector<linked_ptr<api::search_engines_private::SearchEngine>> engines; + for (TemplateURL* url : urls) { + api::search_engines_private::SearchEngine* engine = + new api::search_engines_private::SearchEngine(); + engine->guid = url->sync_guid(); + engine->name = base::UTF16ToASCII(url->short_name()); + if (url == default_url) + engine->is_selected = scoped_ptr<bool>(new bool(true)); + + engines.push_back( + linked_ptr<api::search_engines_private::SearchEngine>(engine)); + } + + scoped_ptr<base::ListValue> args( + api::search_engines_private::OnDefaultSearchEnginesChanged::Create( + engines)); + + scoped_ptr<Event> extension_event(new Event( + api::search_engines_private::OnDefaultSearchEnginesChanged::kEventName, + args.Pass())); + EventRouter::Get(context_)->BroadcastEvent(extension_event.Pass()); +} + +void SearchEnginesPrivateEventRouter:: + StartOrStopListeningForSearchEnginesChanges() { + EventRouter* event_router = EventRouter::Get(context_); + bool should_listen = event_router->HasEventListener( + api::search_engines_private::OnDefaultSearchEnginesChanged::kEventName); + + if (should_listen && !listening_) { + template_url_service_->Load(); + template_url_service_->AddObserver(this); + } else if (!should_listen && listening_) { + template_url_service_->RemoveObserver(this); + } + listening_ = should_listen; +} + +SearchEnginesPrivateEventRouter* SearchEnginesPrivateEventRouter::Create( + content::BrowserContext* context) { + return new SearchEnginesPrivateEventRouter(context); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router.h b/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router.h new file mode 100644 index 0000000..af62d221 --- /dev/null +++ b/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router.h
@@ -0,0 +1,62 @@ +// 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 CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_EVENT_ROUTER_H_ +#define CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_EVENT_ROUTER_H_ + +#include "components/keyed_service/core/keyed_service.h" +#include "components/search_engines/template_url_service.h" +#include "components/search_engines/template_url_service_observer.h" +#include "extensions/browser/event_router.h" + +namespace content { +class BrowserContext; +} + +namespace extensions { + +class SearchEnginesPrivateDelegate; + +// This is an event router that will observe changes to the available and +// selected search engines via the TemplateURLService, and notify listeners to +// events on the searchEnginesPrivate API of changes. +class SearchEnginesPrivateEventRouter : public KeyedService, + public EventRouter::Observer, + public TemplateURLServiceObserver { + public: + static SearchEnginesPrivateEventRouter* Create( + content::BrowserContext* browser_context); + ~SearchEnginesPrivateEventRouter() override; + + // TemplateURLServiceObserver implementation. + void OnTemplateURLServiceChanged() override; + + protected: + explicit SearchEnginesPrivateEventRouter(content::BrowserContext* context); + + // KeyedService overrides: + void Shutdown() override; + + // EventRouter::Observer overrides: + void OnListenerAdded(const EventListenerInfo& details) override; + void OnListenerRemoved(const EventListenerInfo& details) override; + + TemplateURLService* template_url_service_; + + private: + // Decide if we should listen for search engines changes or not. If there are + // any JavaScript listeners registered for the onDefaultSearchEnginesChanged + // event, then we want to register for change notifications. + // Otherwise, we want to unregister and not be listening for changes. + void StartOrStopListeningForSearchEnginesChanges(); + + content::BrowserContext* context_; + bool listening_; + + DISALLOW_COPY_AND_ASSIGN(SearchEnginesPrivateEventRouter); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_EVENT_ROUTER_H_
diff --git a/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.cc b/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.cc new file mode 100644 index 0000000..1571fcc --- /dev/null +++ b/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.cc
@@ -0,0 +1,59 @@ +// 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/extensions/api/search_engines_private/search_engines_private_event_router.h" +#include "chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "content/public/browser/browser_context.h" +#include "extensions/browser/extension_system_provider.h" +#include "extensions/browser/extensions_browser_client.h" + +namespace extensions { + +// static +SearchEnginesPrivateEventRouter* +SearchEnginesPrivateEventRouterFactory::GetForProfile( + content::BrowserContext* context) { + return static_cast<SearchEnginesPrivateEventRouter*>( + GetInstance()->GetServiceForBrowserContext(context, true)); +} + +// static +SearchEnginesPrivateEventRouterFactory* +SearchEnginesPrivateEventRouterFactory::GetInstance() { + return Singleton<SearchEnginesPrivateEventRouterFactory>::get(); +} + +SearchEnginesPrivateEventRouterFactory::SearchEnginesPrivateEventRouterFactory() + : BrowserContextKeyedServiceFactory( + "SearchEnginesPrivateEventRouter", + BrowserContextDependencyManager::GetInstance()) { + DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); +} + +SearchEnginesPrivateEventRouterFactory:: + ~SearchEnginesPrivateEventRouterFactory() { +} + +KeyedService* SearchEnginesPrivateEventRouterFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return SearchEnginesPrivateEventRouter::Create(context); +} + +content::BrowserContext* +SearchEnginesPrivateEventRouterFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return ExtensionsBrowserClient::Get()->GetOriginalContext(context); +} + +bool SearchEnginesPrivateEventRouterFactory:: + ServiceIsCreatedWithBrowserContext() const { + return true; +} + +bool SearchEnginesPrivateEventRouterFactory::ServiceIsNULLWhileTesting() const { + return false; +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.h b/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.h new file mode 100644 index 0000000..b214255a --- /dev/null +++ b/chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.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 CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_EVENT_ROUTER_FACTORY_H_ +#define CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_EVENT_ROUTER_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace extensions { + +class SearchEnginesPrivateEventRouter; + +// This is a factory class used by the BrowserContextDependencyManager +// to instantiate the searchEnginesPrivate event router per profile (since the +// extension event router is per profile). +class SearchEnginesPrivateEventRouterFactory + : public BrowserContextKeyedServiceFactory { + public: + // Returns the SearchEnginesPrivateEventRouter for |profile|, creating it if + // it is not yet created. + static SearchEnginesPrivateEventRouter* GetForProfile( + content::BrowserContext* context); + + // Returns the SearchEnginesPrivateEventRouterFactory instance. + static SearchEnginesPrivateEventRouterFactory* GetInstance(); + + protected: + // BrowserContextKeyedBaseFactory overrides: + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + bool ServiceIsCreatedWithBrowserContext() const override; + bool ServiceIsNULLWhileTesting() const override; + + private: + friend struct DefaultSingletonTraits<SearchEnginesPrivateEventRouterFactory>; + + SearchEnginesPrivateEventRouterFactory(); + ~SearchEnginesPrivateEventRouterFactory() override; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* profile) const override; + + DISALLOW_COPY_AND_ASSIGN(SearchEnginesPrivateEventRouterFactory); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_SEARCH_ENGINES_PRIVATE_SEARCH_ENGINES_PRIVATE_EVENT_ROUTER_FACTORY_H_
diff --git a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc index 6f6d5e9..1cb5733 100644 --- a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc +++ b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc
@@ -7,8 +7,8 @@ #include <vector> #include "base/guid.h" -#include "base/message_loop/message_loop.h" #include "base/prefs/pref_service.h" +#include "base/thread_task_runner_handle.h" #include "base/values.h" #include "chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h" #include "chrome/browser/extensions/extension_api_unittest.h" @@ -17,6 +17,7 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/profile_sync_service_mock.h" #include "components/sync_driver/device_info.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/common/extension.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -72,11 +73,10 @@ }; TEST(SignedInDevicesAPITest, GetSignedInDevices) { + content::TestBrowserThreadBundle thread_bundle; TestingProfile profile; MockDeviceInfoTracker device_tracker; - base::MessageLoop message_loop_; - TestExtensionPrefs extension_prefs( - message_loop_.message_loop_proxy().get()); + TestExtensionPrefs extension_prefs(base::ThreadTaskRunnerHandle::Get().get()); // Add a couple of devices and make sure we get back public ids for them. std::string extension_name = "test";
diff --git a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager_unittest.cc b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager_unittest.cc index 708bb4a..322ef96 100644 --- a/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager_unittest.cc +++ b/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_manager_unittest.cc
@@ -12,6 +12,7 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/signin/core/browser/signin_manager.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/event_router.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -26,6 +27,7 @@ // Adds a listener and removes it. TEST(SignedInDevicesManager, UpdateListener) { + content::TestBrowserThreadBundle thread_bundle; scoped_ptr<TestingProfile> profile(new TestingProfile()); SigninManagerFactory::GetForProfile(profile.get())-> SetAuthenticatedAccountInfo("gaia_id", "foo");
diff --git a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc index 91f9b74..e372f00e 100644 --- a/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc +++ b/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
@@ -33,7 +33,7 @@ const net::CompletionCallback& callback)); MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay)); MOCK_METHOD1(SetNoDelay, bool(bool no_delay)); - virtual bool IsConnected() const override { + bool IsConnected() const override { return true; }
diff --git a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc index a0c9cdee..adebfbf9 100644 --- a/chrome/browser/extensions/api/socket/tls_socket_unittest.cc +++ b/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
@@ -61,12 +61,12 @@ unsigned int)); MOCK_METHOD1(GetTLSUniqueChannelBinding, int(std::string*)); MOCK_METHOD1(GetSSLCertRequestInfo, void(net::SSLCertRequestInfo*)); - MOCK_METHOD1(GetNextProto, - net::SSLClientSocket::NextProtoStatus(std::string*)); + MOCK_CONST_METHOD1(GetNextProto, + net::SSLClientSocket::NextProtoStatus(std::string*)); MOCK_CONST_METHOD0(GetUnverifiedServerCertificateChain, scoped_refptr<net::X509Certificate>()); MOCK_CONST_METHOD0(GetChannelIDService, net::ChannelIDService*()); - virtual bool IsConnected() const override { return true; } + bool IsConnected() const override { return true; } private: DISALLOW_COPY_AND_ASSIGN(MockSSLClientSocket); @@ -88,7 +88,7 @@ MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay)); MOCK_METHOD1(SetNoDelay, bool(bool no_delay)); - virtual bool IsConnected() const override { return true; } + bool IsConnected() const override { return true; } private: DISALLOW_COPY_AND_ASSIGN(MockTCPSocket);
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chrome/browser/extensions/api/streams_private/streams_private_api.cc index 5929da0..922a978 100644 --- a/chrome/browser/extensions/api/streams_private/streams_private_api.cc +++ b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -152,7 +152,7 @@ } ExtensionFunction::ResponseAction StreamsPrivateAbortFunction::Run() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &stream_url_)); StreamsPrivateAPI::Get(browser_context())->AbortStream( extension_id(), GURL(stream_url_), base::Bind( @@ -161,7 +161,7 @@ } void StreamsPrivateAbortFunction::OnClose() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); Respond(NoArguments()); }
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc index 3bcf3db..dce6c5b7 100644 --- a/chrome/browser/extensions/api/tabs/tabs_api.cc +++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -198,6 +198,35 @@ return ui::SHOW_STATE_DEFAULT; } +bool IsValidStateForWindowsCreateFunction( + const windows::Create::Params::CreateData* create_data) { + if (!create_data) + return true; + + bool has_bound = create_data->left || create_data->top || + create_data->width || create_data->height; + bool is_panel = + create_data->type == windows::CreateType::CREATE_TYPE_PANEL || + create_data->type == windows::CreateType::CREATE_TYPE_DETACHED_PANEL; + + switch (create_data->state) { + case windows::WINDOW_STATE_MINIMIZED: + // If minimised, default focused state should be unfocused. + return !(create_data->focused && *create_data->focused) && !has_bound && + !is_panel; + case windows::WINDOW_STATE_MAXIMIZED: + case windows::WINDOW_STATE_FULLSCREEN: + // If maximised/fullscreen, default focused state should be focused. + return !(create_data->focused && !*create_data->focused) && !has_bound && + !is_panel; + case windows::WINDOW_STATE_NORMAL: + case windows::WINDOW_STATE_NONE: + return true; + } + NOTREACHED(); + return true; +} + } // namespace void ZoomModeToZoomSettings(ZoomController::ZoomMode zoom_mode, @@ -421,6 +450,11 @@ return false; } + if (!IsValidStateForWindowsCreateFunction(create_data)) { + error_ = keys::kInvalidWindowStateError; + return false; + } + Profile* window_profile = GetProfile(); Browser::Type window_type = Browser::TYPE_TABBED; bool create_panel = false; @@ -1599,10 +1633,7 @@ void TabsCaptureVisibleTabFunction::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kDisableScreenshots, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kDisableScreenshots, false); } bool TabsDetectLanguageFunction::RunAsync() {
diff --git a/chrome/browser/extensions/api/tabs/tabs_test.cc b/chrome/browser/extensions/api/tabs/tabs_test.cc index b606a0a..6203ae4 100644 --- a/chrome/browser/extensions/api/tabs/tabs_test.cc +++ b/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -42,8 +42,19 @@ namespace { using ExtensionTabsTest = InProcessBrowserTest; -using ExtensionWindowCreateTest = InProcessBrowserTest; -} + +class ExtensionWindowCreateTest : public InProcessBrowserTest { + public: + // Runs chrome.windows.create(), expecting an error. + std::string RunCreateWindowExpectError(const std::string& args) { + scoped_refptr<WindowsCreateFunction> function(new WindowsCreateFunction); + function->set_extension(test_util::CreateEmptyExtension().get()); + return api_test_utils::RunFunctionAndReturnError(function.get(), args, + browser()->profile()); + } +}; + +} // namespace IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetWindow) { int window_id = ExtensionTabUtil::GetWindowId(browser()); @@ -594,6 +605,42 @@ #endif } +IN_PROC_BROWSER_TEST_F(ExtensionWindowCreateTest, ValidateCreateWindowState) { + EXPECT_TRUE( + MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"fullscreen\", \"type\": \"panel\"}]"), + keys::kInvalidWindowStateError)); + EXPECT_TRUE( + MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"maximized\", \"type\": \"panel\"}]"), + keys::kInvalidWindowStateError)); + EXPECT_TRUE( + MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"minimized\", \"type\": \"panel\"}]"), + keys::kInvalidWindowStateError)); + EXPECT_TRUE( + MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"minimized\", \"focused\": true}]"), + keys::kInvalidWindowStateError)); + EXPECT_TRUE( + MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"maximized\", \"focused\": false}]"), + keys::kInvalidWindowStateError)); + EXPECT_TRUE( + MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"fullscreen\", \"focused\": false}]"), + keys::kInvalidWindowStateError)); + EXPECT_TRUE(MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"minimized\", \"width\": 500}]"), + keys::kInvalidWindowStateError)); + EXPECT_TRUE(MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"maximized\", \"width\": 500}]"), + keys::kInvalidWindowStateError)); + EXPECT_TRUE(MatchPattern(RunCreateWindowExpectError( + "[{\"state\": \"fullscreen\", \"width\": 500}]"), + keys::kInvalidWindowStateError)); +} + IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DuplicateTab) { content::OpenURLParams params(GURL(url::kAboutBlankURL), content::Referrer(),
diff --git a/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc b/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc index 998a2755..16ba40e 100644 --- a/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc +++ b/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc
@@ -53,7 +53,7 @@ const GURL& url, const std::string& api_call, scoped_ptr<base::DictionaryValue> details) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext( browser_context)) return;
diff --git a/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc index af510af..e77c585 100644 --- a/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
@@ -31,6 +31,9 @@ protected: void SetUp() override; + private: + content::TestBrowserThreadBundle thread_bundle_; + protected: net::TestURLRequestContext context; @@ -39,9 +42,6 @@ // This extension has Web Request permissions, and *.com a host permission. scoped_refptr<Extension> com_extension_; scoped_refptr<extensions::InfoMap> extension_info_map_; - - private: - content::TestBrowserThreadBundle thread_bundle_; }; void ExtensionWebRequestHelpersTestWithThreadsTest::SetUp() {
diff --git a/chrome/browser/extensions/app_data_migrator.cc b/chrome/browser/extensions/app_data_migrator.cc index 4f32035..c2734c1 100644 --- a/chrome/browser/extensions/app_data_migrator.cc +++ b/chrome/browser/extensions/app_data_migrator.cc
@@ -80,7 +80,7 @@ StoragePartition* current_partition, const extensions::Extension* extension, const base::Closure& reply) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Since this method is static and it's being run as a closure task, check to // make sure the calling object is still around. @@ -107,7 +107,7 @@ StoragePartition* current_partition, const extensions::Extension* extension, const base::Closure& reply) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); IndexedDBContext* indexed_db_context = current_partition->GetIndexedDBContext(); @@ -149,7 +149,7 @@ void AppDataMigrator::DoMigrationAndReply(const Extension* old, const Extension* extension, const base::Closure& reply) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(NeedsMigration(old, extension)); // This should retrieve the general storage partition.
diff --git a/chrome/browser/extensions/browser_action_test_util.h b/chrome/browser/extensions/browser_action_test_util.h index 2ac46985..bbad3e2 100644 --- a/chrome/browser/extensions/browser_action_test_util.h +++ b/chrome/browser/extensions/browser_action_test_util.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/memory/scoped_ptr.h" #include "ui/gfx/native_widget_types.h" class Browser; @@ -19,18 +20,25 @@ class Size; } // namespace gfx +// A class that creates and owns the platform-specific views for the browser +// actions container. Specific implementations are in the .cc/.mm files. +class TestToolbarActionsBarHelper { + public: + virtual ~TestToolbarActionsBarHelper() {} +}; + class BrowserActionTestUtil { public: // Constructs a BrowserActionTestUtil that uses the |browser|'s default // browser action container. - explicit BrowserActionTestUtil(Browser* browser) - : browser_(browser), bar_delegate_(nullptr) {} + explicit BrowserActionTestUtil(Browser* browser); - // Constructs a BrowserActionTestUtil that will use the |bar_delegate| as the - // browser action container to test. - BrowserActionTestUtil(Browser* browser, - ToolbarActionsBarDelegate* bar_delegate) - : browser_(browser), bar_delegate_(bar_delegate) {} + // Constructs a BrowserActionTestUtil which, if |is_real_window| is false, + // will create its own browser actions container. This is useful in unit + // tests, when the |browser|'s window doesn't create platform-specific views. + BrowserActionTestUtil(Browser* browser, bool is_real_window); + + ~BrowserActionTestUtil(); // Returns the number of browser action buttons in the window toolbar. int NumberOfBrowserActions(); @@ -85,6 +93,10 @@ // Returns the ToolbarActionsBar. ToolbarActionsBar* GetToolbarActionsBar(); + // Creates and returns a BrowserActionTestUtil with an "overflow" container, + // with this object's container as the main bar. + scoped_ptr<BrowserActionTestUtil> CreateOverflowBar(); + // Returns the minimum allowed size of an extension popup. static gfx::Size GetMinPopupSize(); @@ -92,11 +104,16 @@ static gfx::Size GetMaxPopupSize(); private: + // A private constructor to create an overflow version. + BrowserActionTestUtil(Browser* browser, BrowserActionTestUtil* main_bar); + Browser* browser_; // weak - // If non-null, this is a set view to test with, rather than using the - // |browser|'s default container. - ToolbarActionsBarDelegate* bar_delegate_; // weak + // Our test helper, which constructs and owns the views if we don't have a + // real browser window, or if this is an overflow version. + scoped_ptr<TestToolbarActionsBarHelper> test_helper_; + + DISALLOW_COPY_AND_ASSIGN(BrowserActionTestUtil); }; #endif // CHROME_BROWSER_EXTENSIONS_BROWSER_ACTION_TEST_UTIL_H_
diff --git a/chrome/browser/extensions/browser_context_keyed_service_factories.cc b/chrome/browser/extensions/browser_context_keyed_service_factories.cc index bf5ecc4..4f55a320 100644 --- a/chrome/browser/extensions/browser_context_keyed_service_factories.cc +++ b/chrome/browser/extensions/browser_context_keyed_service_factories.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/extensions/api/preference/preference_api.h" #include "chrome/browser/extensions/api/processes/processes_api.h" #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h" +#include "chrome/browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.h" #include "chrome/browser/extensions/api/sessions/sessions_api.h" #include "chrome/browser/extensions/api/settings_overrides/settings_overrides_api.h" #include "chrome/browser/extensions/api/settings_private/settings_private_event_router_factory.h" @@ -125,6 +126,7 @@ extensions::PreferenceAPI::GetFactoryInstance(); extensions::ProcessesAPI::GetFactoryInstance(); extensions::ScreenlockPrivateEventRouter::GetFactoryInstance(); + extensions::SearchEnginesPrivateEventRouterFactory::GetInstance(); extensions::SessionsAPI::GetFactoryInstance(); extensions::SettingsPrivateEventRouterFactory::GetInstance(); extensions::SettingsOverridesAPI::GetFactoryInstance();
diff --git a/chrome/browser/extensions/bundle_installer.cc b/chrome/browser/extensions/bundle_installer.cc index 898bb23..133215ca 100644 --- a/chrome/browser/extensions/bundle_installer.cc +++ b/chrome/browser/extensions/bundle_installer.cc
@@ -93,7 +93,7 @@ base::string16 BundleInstaller::Item::GetNameForDisplay() const { base::string16 name = base::UTF8ToUTF16(localized_name); base::i18n::AdjustStringForLocaleDirection(&name); - return l10n_util::GetStringFUTF16(IDS_EXTENSION_PERMISSION_LINE, name); + return name; } BundleInstaller::BundleInstaller(Browser* browser, @@ -277,7 +277,7 @@ if (browser) web_contents = browser->tab_strip_model()->GetActiveWebContents(); install_ui_.reset(new ExtensionInstallPrompt(web_contents)); - install_ui_->ConfirmBundleInstall(this, permissions.get()); + install_ui_->ConfirmBundleInstall(this, &icon_, permissions.get()); } }
diff --git a/chrome/browser/extensions/chrome_app_sorting.cc b/chrome/browser/extensions/chrome_app_sorting.cc index 5f05f47..a11e1a2 100644 --- a/chrome/browser/extensions/chrome_app_sorting.cc +++ b/chrome/browser/extensions/chrome_app_sorting.cc
@@ -60,6 +60,10 @@ extension_scoped_prefs_ = prefs; } +void ChromeAppSorting::CheckExtensionScopedPrefs() const { + CHECK(extension_scoped_prefs_); +} + void ChromeAppSorting::SetExtensionSyncService( ExtensionSyncService* extension_sync_service) { extension_sync_service_ = extension_sync_service; @@ -67,6 +71,7 @@ void ChromeAppSorting::Initialize( const extensions::ExtensionIdList& extension_ids) { + CHECK(extension_scoped_prefs_); InitializePageOrdinalMap(extension_ids); MigrateAppIndex(extension_ids); @@ -470,6 +475,9 @@ void ChromeAppSorting::InitializePageOrdinalMap( const extensions::ExtensionIdList& extension_ids) { + // TODO(mgiuca): Added this CHECK to try and diagnose http://crbug.com/476648. + // Remove it after the investigation is concluded. + CHECK(extension_scoped_prefs_); for (extensions::ExtensionIdList::const_iterator ext_it = extension_ids.begin(); ext_it != extension_ids.end(); ++ext_it) { AddOrdinalMapping(*ext_it,
diff --git a/chrome/browser/extensions/chrome_app_sorting.h b/chrome/browser/extensions/chrome_app_sorting.h index 14b76f0..d185dee 100644 --- a/chrome/browser/extensions/chrome_app_sorting.h +++ b/chrome/browser/extensions/chrome_app_sorting.h
@@ -29,6 +29,7 @@ // AppSorting implementation: void SetExtensionScopedPrefs(ExtensionScopedPrefs* prefs) override; + void CheckExtensionScopedPrefs() const override; void SetExtensionSyncService( ExtensionSyncService* extension_sync_service) override; void Initialize(const extensions::ExtensionIdList& extension_ids) override;
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index 2362e12..cafc772 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -12,6 +12,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" #include "base/path_service.h" +#include "base/profiler/scoped_profile.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "chrome/browser/extensions/extension_service.h" @@ -133,6 +134,7 @@ void ComponentLoader::LoadAll() { TRACE_EVENT0("browser,startup", "ComponentLoader::LoadAll"); + TRACK_SCOPED_REGION("Startup", "ComponentLoader::LoadAll"); SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllComponentTime"); for (RegisteredComponentExtensions::iterator it =
diff --git a/chrome/browser/extensions/default_apps.cc b/chrome/browser/extensions/default_apps.cc index 7b9c560..3b42e97 100644 --- a/chrome/browser/extensions/default_apps.cc +++ b/chrome/browser/extensions/default_apps.cc
@@ -49,10 +49,7 @@ namespace default_apps { void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kDefaultAppsInstallState, - kUnknown, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kDefaultAppsInstallState, kUnknown); } bool Provider::ShouldInstallInProfile() {
diff --git a/chrome/browser/extensions/display_info_provider_chromeos.cc b/chrome/browser/extensions/display_info_provider_chromeos.cc index fda4b63..673a15a 100644 --- a/chrome/browser/extensions/display_info_provider_chromeos.cc +++ b/chrome/browser/extensions/display_info_provider_chromeos.cc
@@ -334,7 +334,8 @@ // Process 'rotation' parameter. if (info.rotation) { display_manager->SetDisplayRotation(display_id, - DegreesToRotation(*info.rotation)); + DegreesToRotation(*info.rotation), + gfx::Display::ROTATION_SOURCE_ACTIVE); } // Process new display origin parameters.
diff --git a/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc b/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc index 28d3eab..3df2766 100644 --- a/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc +++ b/chrome/browser/extensions/display_info_provider_chromeos_unittest.cc
@@ -121,7 +121,8 @@ EXPECT_EQ("0,0 600x500", SystemInfoDisplayBoundsToString(result[0]->bounds)); EXPECT_EQ(90, result[0]->rotation); - GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_270); + GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_270, + gfx::Display::ROTATION_SOURCE_ACTIVE); result = DisplayInfoProvider::Get()->GetAllDisplaysInfo(); @@ -131,7 +132,8 @@ EXPECT_EQ("0,0 600x500", SystemInfoDisplayBoundsToString(result[0]->bounds)); EXPECT_EQ(270, result[0]->rotation); - GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_180); + GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_180, + gfx::Display::ROTATION_SOURCE_ACTIVE); result = DisplayInfoProvider::Get()->GetAllDisplaysInfo(); @@ -141,7 +143,8 @@ EXPECT_EQ("0,0 500x600", SystemInfoDisplayBoundsToString(result[0]->bounds)); EXPECT_EQ(180, result[0]->rotation); - GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_0); + GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_0, + gfx::Display::ROTATION_SOURCE_ACTIVE); result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
diff --git a/chrome/browser/extensions/display_info_provider_win.h b/chrome/browser/extensions/display_info_provider_win.h index e61b081..9db5fff 100644 --- a/chrome/browser/extensions/display_info_provider_win.h +++ b/chrome/browser/extensions/display_info_provider_win.h
@@ -12,16 +12,16 @@ class DisplayInfoProviderWin : public DisplayInfoProvider { public: DisplayInfoProviderWin(); - virtual ~DisplayInfoProviderWin(); + ~DisplayInfoProviderWin() override; // DisplayInfoProvider implementation. - virtual bool SetInfo(const std::string& display_id, - const core_api::system_display::DisplayProperties& info, - std::string* error) override; - virtual void UpdateDisplayUnitInfoForPlatform( + bool SetInfo(const std::string& display_id, + const core_api::system_display::DisplayProperties& info, + std::string* error) override; + void UpdateDisplayUnitInfoForPlatform( const gfx::Display& display, core_api::system_display::DisplayUnitInfo* unit) override; - virtual gfx::Screen* GetActiveScreen() override; + gfx::Screen* GetActiveScreen() override; private: DISALLOW_COPY_AND_ASSIGN(DisplayInfoProviderWin);
diff --git a/chrome/browser/extensions/error_console/error_console_unittest.cc b/chrome/browser/extensions/error_console/error_console_unittest.cc index 08cf532..ce686dd 100644 --- a/chrome/browser/extensions/error_console/error_console_unittest.cc +++ b/chrome/browser/extensions/error_console/error_console_unittest.cc
@@ -13,6 +13,7 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/crx_file/id_util.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/extension_error.h" #include "extensions/browser/extension_error_test_util.h" #include "extensions/browser/extension_registry.h" @@ -45,6 +46,7 @@ } protected: + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<TestingProfile> profile_; ErrorConsole* error_console_; };
diff --git a/chrome/browser/extensions/extension_action_manager_unittest.cc b/chrome/browser/extensions/extension_action_manager_unittest.cc index 2240125..b29328e 100644 --- a/chrome/browser/extensions/extension_action_manager_unittest.cc +++ b/chrome/browser/extensions/extension_action_manager_unittest.cc
@@ -7,6 +7,7 @@ #include "base/strings/string_number_conversions.h" #include "chrome/browser/extensions/extension_action.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension_builder.h" #include "extensions/common/manifest_handlers/icons_handler.h" @@ -55,6 +56,7 @@ ExtensionActionManager* manager() { return manager_; } private: + content::TestBrowserThreadBundle thread_bundle_; ExtensionRegistry* registry_; int curr_id_; ExtensionActionManager* manager_;
diff --git a/chrome/browser/extensions/extension_fullscreen_apitest.cc b/chrome/browser/extensions/extension_fullscreen_apitest.cc index f05b2ef..9abe3c3 100644 --- a/chrome/browser/extensions/extension_fullscreen_apitest.cc +++ b/chrome/browser/extensions/extension_fullscreen_apitest.cc
@@ -37,3 +37,15 @@ ASSERT_TRUE(RunExtensionTest("window_update/sizing")) << message_; ASSERT_FALSE(browser()->window()->IsFullscreen()); } + +#if defined(OS_MACOSX) +// Fails on MAC: http://crbug.com/480370 +#define MAYBE_DisplayModeWindowIsInFullscreen DISABLED_DisplayModeWindowIsInFullscreen +#else +#define MAYBE_DisplayModeWindowIsInFullscreen DisplayModeWindowIsInFullscreen +#endif // defined(OS_MACOSX) + +IN_PROC_BROWSER_TEST_F(ExtensionApiTest, + MAYBE_DisplayModeWindowIsInFullscreen) { + ASSERT_TRUE(RunPlatformAppTest("fullscreen/mq_display_mode")) << message_; +}
diff --git a/chrome/browser/extensions/extension_garbage_collector.cc b/chrome/browser/extensions/extension_garbage_collector.cc index fd55f22..12877296 100644 --- a/chrome/browser/extensions/extension_garbage_collector.cc +++ b/chrome/browser/extensions/extension_garbage_collector.cc
@@ -159,7 +159,7 @@ } void ExtensionGarbageCollector::GarbageCollectExtensions() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(context_); DCHECK(extension_prefs); @@ -205,7 +205,7 @@ } void ExtensionGarbageCollector::GarbageCollectIsolatedStorageIfNeeded() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(context_); DCHECK(extension_prefs);
diff --git a/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc b/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc index d5d8f89..5355ee0 100644 --- a/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc +++ b/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc
@@ -98,13 +98,13 @@ private: void PumpIOLoopCompleted() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); SignalCompleted(); } void OnIOLoopPump() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); content::BrowserThread::PostTask( content::BrowserThread::IO, @@ -113,7 +113,7 @@ } void OnIOLoopPumpCompleted() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); content::BrowserThread::PostTask( content::BrowserThread::UI,
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc index 1f44cb5..6ad43587 100644 --- a/chrome/browser/extensions/extension_install_prompt.cc +++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -665,6 +665,7 @@ void ExtensionInstallPrompt::ConfirmBundleInstall( extensions::BundleInstaller* bundle, + const SkBitmap* icon, const PermissionSet* permissions) { DCHECK(ui_loop_ == base::MessageLoop::current()); bundle_ = bundle; @@ -672,6 +673,7 @@ delegate_ = bundle; prompt_ = new Prompt(BUNDLE_INSTALL_PROMPT); + SetIcon(icon); ShowConfirmation(); } @@ -831,7 +833,8 @@ // Let's set default icon bitmap whose size is equal to the default icon's // pixel size under maximal supported scale factor. If the bitmap is larger // than the one we need, it will be scaled down by the ui code. - icon_ = GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app()); + icon_ = GetDefaultIconBitmapForMaxScaleFactor( + extension_ ? extension_->is_app() : false); } } @@ -926,7 +929,6 @@ case REPAIR_PROMPT: case DELEGATED_PERMISSIONS_PROMPT: { prompt_->set_extension(extension_); - prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_)); prompt_->set_delegated_username(delegated_username_); break; } @@ -938,6 +940,7 @@ NOTREACHED() << "Unknown message"; return; } + prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_)); g_last_prompt_type_for_tests = prompt_->type();
diff --git a/chrome/browser/extensions/extension_install_prompt.h b/chrome/browser/extensions/extension_install_prompt.h index 7387ff18..da1dd30 100644 --- a/chrome/browser/extensions/extension_install_prompt.h +++ b/chrome/browser/extensions/extension_install_prompt.h
@@ -317,6 +317,7 @@ // We *MUST* eventually call either Proceed() or Abort() on |delegate|. virtual void ConfirmBundleInstall( extensions::BundleInstaller* bundle, + const SkBitmap* icon, const extensions::PermissionSet* permissions); // This is called by the standalone installer to verify whether the install
diff --git a/chrome/browser/extensions/extension_keybinding_apitest.cc b/chrome/browser/extensions/extension_keybinding_apitest.cc index a58db86..6985b54 100644 --- a/chrome/browser/extensions/extension_keybinding_apitest.cc +++ b/chrome/browser/extensions/extension_keybinding_apitest.cc
@@ -133,10 +133,6 @@ ~CommandsApiTest() override {} protected: - BrowserActionTestUtil GetBrowserActionsBar() { - return BrowserActionTestUtil(browser()); - } - bool IsGrantedForTab(const Extension* extension, const content::WebContents* web_contents) { return extension->permissions_data()->HasAPIPermissionForTab( @@ -187,8 +183,9 @@ // immaterial to this test). ASSERT_TRUE(RunExtensionTest("keybinding/conflicting")) << message_; + BrowserActionTestUtil browser_actions_bar(browser()); // Test that there are two browser actions in the toolbar. - ASSERT_EQ(2, GetBrowserActionsBar().NumberOfBrowserActions()); + ASSERT_EQ(2, browser_actions_bar.NumberOfBrowserActions()); ui_test_utils::NavigateToURL( browser(), test_server()->GetURL("files/extensions/test_file.txt"));
diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc index 4d3adbc..bd995e5 100644 --- a/chrome/browser/extensions/extension_management.cc +++ b/chrome/browser/extensions/extension_management.cc
@@ -493,9 +493,7 @@ void ExtensionManagementFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* user_prefs) { - user_prefs->RegisterDictionaryPref( - pref_names::kExtensionManagement, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + user_prefs->RegisterDictionaryPref(pref_names::kExtensionManagement); } } // namespace extensions
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 5cd1701ae..32d434fc 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -10,6 +10,7 @@ #include "base/command_line.h" #include "base/metrics/histogram_macros.h" +#include "base/profiler/scoped_profile.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -397,6 +398,7 @@ void ExtensionService::Init() { CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); TRACE_EVENT0("browser,startup", "ExtensionService::Init"); + TRACK_SCOPED_REGION("Startup", "ExtensionService::Init"); SCOPED_UMA_HISTOGRAM_TIMER("Extensions.ExtensionServiceInitTime"); DCHECK(!is_ready()); // Can't redo init. @@ -1433,6 +1435,8 @@ void ExtensionService::SetReadyAndNotifyListeners() { TRACE_EVENT0("browser,startup", "ExtensionService::SetReadyAndNotifyListeners"); + TRACK_SCOPED_REGION( + "Startup", "ExtensionService::SetReadyAndNotifyListeners"); SCOPED_UMA_HISTOGRAM_TIMER( "Extensions.ExtensionServiceNotifyReadyListenersTime");
diff --git a/chrome/browser/extensions/extension_service_test_base.cc b/chrome/browser/extensions/extension_service_test_base.cc index cb0e914..10f16f3 100644 --- a/chrome/browser/extensions/extension_service_test_base.cc +++ b/chrome/browser/extensions/extension_service_test_base.cc
@@ -73,9 +73,9 @@ } ExtensionServiceTestBase::ExtensionServiceTestBase() - : service_(NULL), + : thread_bundle_(new content::TestBrowserThreadBundle(kThreadOptions)), + service_(NULL), testing_local_state_(TestingBrowserProcess::GetGlobal()), - thread_bundle_(new content::TestBrowserThreadBundle(kThreadOptions)), did_reset_thread_bundle_(false), registry_(NULL) { base::FilePath test_data_dir;
diff --git a/chrome/browser/extensions/extension_service_test_base.h b/chrome/browser/extensions/extension_service_test_base.h index ab48634..85b4d3c4 100644 --- a/chrome/browser/extensions/extension_service_test_base.h +++ b/chrome/browser/extensions/extension_service_test_base.h
@@ -103,6 +103,13 @@ const base::FilePath& data_dir() const { return data_dir_; } const base::ScopedTempDir& temp_dir() const { return temp_dir_; } + private: + // Destroying at_exit_manager_ will delete all LazyInstances, so it must come + // after thread_bundle_ in the destruction order. + base::ShadowingAtExitManager at_exit_manager_; + scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_; + + protected: // It's unfortunate that these are exposed to subclasses (rather than used // through the accessor methods above), but too many tests already use them // directly. @@ -122,11 +129,6 @@ // directory. base::ScopedTempDir temp_dir_; - // Destroying at_exit_manager_ will delete all LazyInstances, so it must come - // after thread_bundle_ in the destruction order. - base::ShadowingAtExitManager at_exit_manager_; - scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_; - // Whether or not the thread bundle was reset in the test. bool did_reset_thread_bundle_;
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 5911845..4352ffa 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -84,6 +84,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/content_constants.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_utils.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" @@ -5598,7 +5599,11 @@ // // Also tests that we always fire EXTENSIONS_READY, no matter whether we are // enabled or not. -TEST(ExtensionServiceTestSimple, Enabledness) { +class ExtensionServiceTestSimple : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(ExtensionServiceTestSimple, Enabledness) { // Make sure the PluginService singleton is destroyed at the end of the test. base::ShadowingAtExitManager at_exit_manager; #if defined(ENABLE_PLUGINS) @@ -5609,7 +5614,6 @@ ExtensionErrorReporter::Init(false); // no noisy errors ExtensionsReadyRecorder recorder; scoped_ptr<TestingProfile> profile(new TestingProfile()); - content::TestBrowserThreadBundle thread_bundle_; #if defined OS_CHROMEOS chromeos::ScopedTestDeviceSettingsService device_settings_service; chromeos::ScopedTestCrosSettings cros_settings;
diff --git a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc b/chrome/browser/extensions/extension_special_storage_policy_unittest.cc index d62eb47..25598326 100644 --- a/chrome/browser/extensions/extension_special_storage_policy_unittest.cc +++ b/chrome/browser/extensions/extension_special_storage_policy_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/message_loop/message_loop.h" #include "base/values.h" #include "chrome/browser/content_settings/cookie_settings.h" #include "chrome/browser/extensions/extension_special_storage_policy.h" @@ -10,6 +9,7 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "content/public/test/test_browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" #include "extensions/common/manifest.h" @@ -172,6 +172,7 @@ } } + content::TestBrowserThreadBundle thread_bundle_; scoped_refptr<ExtensionSpecialStoragePolicy> policy_; }; @@ -309,9 +310,6 @@ } TEST_F(ExtensionSpecialStoragePolicyTest, HasSessionOnlyOrigins) { - base::MessageLoop message_loop; - content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); - TestingProfile profile; CookieSettings* cookie_settings = CookieSettings::Factory::GetForProfile(&profile).get(); @@ -344,10 +342,6 @@ } TEST_F(ExtensionSpecialStoragePolicyTest, NotificationTest) { - base::MessageLoop message_loop; - content::TestBrowserThread ui_thread(BrowserThread::UI, &message_loop); - content::TestBrowserThread io_thread(BrowserThread::IO, &message_loop); - PolicyChangeObserver observer; policy_->AddObserver(&observer); @@ -368,14 +362,14 @@ SCOPED_TRACE(testing::Message() << "i: " << i); observer.ExpectGrant(apps[i]->id(), change_flags[i]); policy_->GrantRightsForExtension(apps[i].get(), NULL); - message_loop.RunUntilIdle(); + base::MessageLoop::current()->RunUntilIdle(); EXPECT_TRUE(observer.IsCompleted()); } for (size_t i = 0; i < arraysize(apps); ++i) { SCOPED_TRACE(testing::Message() << "i: " << i); policy_->GrantRightsForExtension(apps[i].get(), NULL); - message_loop.RunUntilIdle(); + base::MessageLoop::current()->RunUntilIdle(); EXPECT_TRUE(observer.IsCompleted()); } @@ -383,20 +377,20 @@ SCOPED_TRACE(testing::Message() << "i: " << i); observer.ExpectRevoke(apps[i]->id(), change_flags[i]); policy_->RevokeRightsForExtension(apps[i].get()); - message_loop.RunUntilIdle(); + base::MessageLoop::current()->RunUntilIdle(); EXPECT_TRUE(observer.IsCompleted()); } for (size_t i = 0; i < arraysize(apps); ++i) { SCOPED_TRACE(testing::Message() << "i: " << i); policy_->RevokeRightsForExtension(apps[i].get()); - message_loop.RunUntilIdle(); + base::MessageLoop::current()->RunUntilIdle(); EXPECT_TRUE(observer.IsCompleted()); } observer.ExpectClear(); policy_->RevokeRightsForAllExtensions(); - message_loop.RunUntilIdle(); + base::MessageLoop::current()->RunUntilIdle(); EXPECT_TRUE(observer.IsCompleted()); policy_->RemoveObserver(&observer);
diff --git a/chrome/browser/extensions/extension_storage_monitor.cc b/chrome/browser/extensions/extension_storage_monitor.cc index 654d8433..48f1ac2 100644 --- a/chrome/browser/extensions/extension_storage_monitor.cc +++ b/chrome/browser/extensions/extension_storage_monitor.cc
@@ -122,7 +122,7 @@ int64 next_threshold, const base::TimeDelta& rate, bool should_uma) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(quota_manager.get()); GURL origin = site_url.GetOrigin(); @@ -147,7 +147,7 @@ // Updates the threshold for an extension already being monitored. void UpdateThresholdForExtension(const std::string& extension_id, int64 next_threshold) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); it != origin_state_map_.end(); @@ -161,7 +161,7 @@ // Deregister as an observer for the extension's storage events. void StopObservingForExtension(const std::string& extension_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); it != origin_state_map_.end(); ) { @@ -186,7 +186,7 @@ // Stop observing all storage events. Called during shutdown. void StopObserving() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); for (OriginStorageStateMap::iterator it = origin_state_map_.begin(); it != origin_state_map_.end(); ++it) { @@ -401,7 +401,7 @@ const std::string& extension_id, int64 next_threshold, int64 current_usage) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); const Extension* extension = GetExtensionById(context_, extension_id); if (!extension)
diff --git a/chrome/browser/extensions/extension_tabs_apitest.cc b/chrome/browser/extensions/extension_tabs_apitest.cc index 4709c98..36003da 100644 --- a/chrome/browser/extensions/extension_tabs_apitest.cc +++ b/chrome/browser/extensions/extension_tabs_apitest.cc
@@ -254,6 +254,6 @@ << message_; } -// Adding a new test? Awesome. But API tests are the old hotness. The -// new hotness is extension_test_utils. See tabs_test.cc for an example. +// Adding a new test? Awesome. But API tests are the old hotness. The new +// hotness is extension_function_test_utils. See tabs_test.cc for an example. // We are trying to phase out many uses of API tests as they tend to be flaky.
diff --git a/chrome/browser/extensions/extension_web_ui.cc b/chrome/browser/extensions/extension_web_ui.cc index 54ccc8b..ebb22a7b 100644 --- a/chrome/browser/extensions/extension_web_ui.cc +++ b/chrome/browser/extensions/extension_web_ui.cc
@@ -187,9 +187,7 @@ // static void ExtensionWebUI::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - kExtensionURLOverrides, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kExtensionURLOverrides); } // static
diff --git a/chrome/browser/extensions/external_registry_loader_win.h b/chrome/browser/extensions/external_registry_loader_win.h index 27526d85..f621734 100644 --- a/chrome/browser/extensions/external_registry_loader_win.h +++ b/chrome/browser/extensions/external_registry_loader_win.h
@@ -15,12 +15,12 @@ ExternalRegistryLoader() {} protected: - virtual void StartLoading() override; + void StartLoading() override; private: friend class base::RefCountedThreadSafe<ExternalLoader>; - virtual ~ExternalRegistryLoader() {} + ~ExternalRegistryLoader() override {} void LoadOnFileThread();
diff --git a/chrome/browser/extensions/global_shortcut_listener_win.h b/chrome/browser/extensions/global_shortcut_listener_win.h index a155d8f..9bca78c5 100644 --- a/chrome/browser/extensions/global_shortcut_listener_win.h +++ b/chrome/browser/extensions/global_shortcut_listener_win.h
@@ -19,22 +19,20 @@ public gfx::SingletonHwnd::Observer { public: GlobalShortcutListenerWin(); - virtual ~GlobalShortcutListenerWin(); + ~GlobalShortcutListenerWin() override; private: // The implementation of our Window Proc, called by SingletonHwnd. - virtual void OnWndProc(HWND hwnd, - UINT message, - WPARAM wparam, - LPARAM lparam) override; + void OnWndProc(HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) override; // GlobalShortcutListener implementation. - virtual void StartListening() override; - virtual void StopListening() override; - virtual bool RegisterAcceleratorImpl( - const ui::Accelerator& accelerator) override; - virtual void UnregisterAcceleratorImpl( - const ui::Accelerator& accelerator) override; + void StartListening() override; + void StopListening() override; + bool RegisterAcceleratorImpl(const ui::Accelerator& accelerator) override; + void UnregisterAcceleratorImpl(const ui::Accelerator& accelerator) override; // Whether this object is listening for global shortcuts. bool is_listening_;
diff --git a/chrome/browser/extensions/install_tracker_unittest.cc b/chrome/browser/extensions/install_tracker_unittest.cc index 4e6cc6f..e02400f 100644 --- a/chrome/browser/extensions/install_tracker_unittest.cc +++ b/chrome/browser/extensions/install_tracker_unittest.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/extensions/active_install_data.h" #include "chrome/browser/extensions/install_tracker.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/extension.h" #include "extensions/common/manifest_constants.h" @@ -64,6 +65,7 @@ EXPECT_EQ(original.percent_downloaded, retrieved.percent_downloaded); } + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<TestingProfile> profile_; scoped_ptr<InstallTracker> tracker_; };
diff --git a/chrome/browser/extensions/installed_loader.cc b/chrome/browser/extensions/installed_loader.cc index f8e321c..e34f732 100644 --- a/chrome/browser/extensions/installed_loader.cc +++ b/chrome/browser/extensions/installed_loader.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_switches.h" -#include "chrome/common/extensions/api/supervised_user_private/supervised_user_handler.h" #include "chrome/common/extensions/chrome_manifest_url_handlers.h" #include "components/crx_file/id_util.h" #include "content/public/browser/browser_thread.h" @@ -322,7 +321,6 @@ int legacy_packaged_app_count = 0; int platform_app_count = 0; int user_script_count = 0; - int content_pack_count = 0; int extension_user_count = 0; int extension_external_count = 0; int theme_count = 0; @@ -498,9 +496,6 @@ if (extension_action_manager->GetBrowserAction(*extension)) ++browser_action_count; - if (SupervisedUserInfo::IsContentPack(extension)) - ++content_pack_count; - RecordCreationFlags(extension); ExtensionService::RecordPermissionMessagesHistogram( @@ -590,7 +585,6 @@ page_action_count); UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction", browser_action_count); - UMA_HISTOGRAM_COUNTS_100("Extensions.LoadContentPack", content_pack_count); UMA_HISTOGRAM_COUNTS_100("Extensions.DisabledForPermissions", disabled_for_permissions_count); UMA_HISTOGRAM_COUNTS_100("Extensions.NonWebStoreNewTabPageOverrides",
diff --git a/chrome/browser/extensions/launch_util.cc b/chrome/browser/extensions/launch_util.cc index 3def8978..1f8dcc7 100644 --- a/chrome/browser/extensions/launch_util.cc +++ b/chrome/browser/extensions/launch_util.cc
@@ -34,10 +34,8 @@ // static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - pref_names::kBookmarkAppCreationLaunchType, - LAUNCH_TYPE_REGULAR, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(pref_names::kBookmarkAppCreationLaunchType, + LAUNCH_TYPE_REGULAR); } } // namespace launch_util
diff --git a/chrome/browser/extensions/token_cache/token_cache_service_unittest.cc b/chrome/browser/extensions/token_cache/token_cache_service_unittest.cc index 510efd2..f1c6d9b 100644 --- a/chrome/browser/extensions/token_cache/token_cache_service_unittest.cc +++ b/chrome/browser/extensions/token_cache/token_cache_service_unittest.cc
@@ -7,6 +7,7 @@ #include "base/time/time.h" #include "chrome/browser/extensions/token_cache/token_cache_service.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" using base::Time; @@ -44,6 +45,7 @@ } protected: + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; TokenCacheService cache_; };
diff --git a/chrome/browser/extensions/warning_badge_service_unittest.cc b/chrome/browser/extensions/warning_badge_service_unittest.cc index 168c494e..f01b25be 100644 --- a/chrome/browser/extensions/warning_badge_service_unittest.cc +++ b/chrome/browser/extensions/warning_badge_service_unittest.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/global_error/global_error_service.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/warning_service.h" #include "extensions/browser/warning_set.h" #include "testing/gtest/include/gtest/gtest.h" @@ -59,6 +60,7 @@ // Check that no badge appears if it has been suppressed for a specific // warning. TEST(WarningBadgeServiceTest, SuppressBadgeForCurrentWarnings) { + content::TestBrowserThreadBundle thread_bundle; TestingProfile profile; TestExtensionWarningSet warnings(&profile); TestWarningBadgeService badge_service(&profile, &warnings);
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc index ef7a8c3..89318f2f 100644 --- a/chrome/browser/extensions/webstore_installer.cc +++ b/chrome/browser/extensions/webstore_installer.cc
@@ -698,7 +698,7 @@ } void WebstoreInstaller::StartCrxInstaller(const DownloadItem& download) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!crx_installer_.get()); // The clock may be backward, e.g. daylight savings time just happenned.
diff --git a/chrome/browser/extensions/window_open_interactive_apitest.cc b/chrome/browser/extensions/window_open_interactive_apitest.cc index 67d7205..912f1ab 100644 --- a/chrome/browser/extensions/window_open_interactive_apitest.cc +++ b/chrome/browser/extensions/window_open_interactive_apitest.cc
@@ -14,7 +14,7 @@ }; // http://crbug.com/253417 for NDEBUG -#if defined(OS_WIN) || (defined(OS_MACOSX) && defined(NDEBUG)) +#if (defined(OS_WIN) || defined(OS_MACOSX)) && defined(NDEBUG) // Focus test fails if there is no window manager on Linux. IN_PROC_BROWSER_TEST_F(WindowOpenPanelTest, WindowOpenFocus) { ASSERT_TRUE(RunExtensionTest("window_open/focus")) << message_;
diff --git a/chrome/browser/extensions/zipfile_installer.cc b/chrome/browser/extensions/zipfile_installer.cc index 6f64b606..aecb2f2 100644 --- a/chrome/browser/extensions/zipfile_installer.cc +++ b/chrome/browser/extensions/zipfile_installer.cc
@@ -34,7 +34,7 @@ } void ZipFileInstaller::LoadFromZipFile(const base::FilePath& path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); zip_path_ = path; BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, @@ -101,7 +101,7 @@ } void ZipFileInstaller::OnUnzipSucceeded(const base::FilePath& unzipped_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, @@ -110,7 +110,7 @@ } void ZipFileInstaller::OnUnzipFailed(const std::string& error) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE,
diff --git a/chrome/browser/feedback/feedback_profile_observer.cc b/chrome/browser/feedback/feedback_profile_observer.cc index 63d5ac7..90415a8 100644 --- a/chrome/browser/feedback/feedback_profile_observer.cc +++ b/chrome/browser/feedback/feedback_profile_observer.cc
@@ -39,7 +39,7 @@ int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(chrome::NOTIFICATION_PROFILE_CREATED, type); Profile* profile = content::Source<Profile>(source).ptr();
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc index c9025969..9b54b99 100644 --- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc +++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
@@ -42,7 +42,7 @@ } void ChromeInternalLogSource::Fetch(const SysLogsSourceCallback& callback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!callback.is_null()); SystemLogsResponse response;
diff --git a/chrome/browser/feedback/system_logs/log_sources/memory_details_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/memory_details_log_source.cc index c44ce22..39ca766e 100644 --- a/chrome/browser/feedback/system_logs/log_sources/memory_details_log_source.cc +++ b/chrome/browser/feedback/system_logs/log_sources/memory_details_log_source.cc
@@ -18,7 +18,7 @@ // Sends the data to the callback. // MemoryDetails override. void OnDetailsAvailable() override { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); scoped_ptr<SystemLogsResponse> response(new SystemLogsResponse); (*response)["mem_usage"] = ToLogString(); @@ -40,7 +40,7 @@ } void MemoryDetailsLogSource::Fetch(const SysLogsSourceCallback& callback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!callback.is_null()); scoped_refptr<SystemLogsMemoryHandler>
diff --git a/chrome/browser/feedback/system_logs/system_logs_fetcher_base.cc b/chrome/browser/feedback/system_logs/system_logs_fetcher_base.cc index 6974cf0..7a0b938 100644 --- a/chrome/browser/feedback/system_logs/system_logs_fetcher_base.cc +++ b/chrome/browser/feedback/system_logs/system_logs_fetcher_base.cc
@@ -27,7 +27,7 @@ SystemLogsFetcherBase::~SystemLogsFetcherBase() {} void SystemLogsFetcherBase::Fetch(const SysLogsFetcherCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(callback_.is_null()); DCHECK(!callback.is_null()); @@ -42,7 +42,7 @@ void SystemLogsFetcherBase::AddResponse(const std::string& source_name, SystemLogsResponse* response) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); VLOG(1) << "Received SystemLogSource: " << source_name;
diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc index 965acfa..22a8fb4a 100644 --- a/chrome/browser/file_select_helper.cc +++ b/chrome/browser/file_select_helper.cc
@@ -191,10 +191,8 @@ scoped_ptr<ActiveDirectoryEnumeration> entry(new ActiveDirectoryEnumeration); entry->rvh_ = render_view_host; entry->delegate_.reset(new DirectoryListerDispatchDelegate(this, request_id)); - entry->lister_.reset(new net::DirectoryLister(path, - true, - net::DirectoryLister::NO_SORT, - entry->delegate_.get())); + entry->lister_.reset(new net::DirectoryLister( + path, net::DirectoryLister::NO_SORT_RECURSIVE, entry->delegate_.get())); if (!entry->lister_->Start()) { if (request_id == kFileSelectEnumerationId) FileSelectionCanceled(NULL);
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc index 0e88b9f..26ef116 100644 --- a/chrome/browser/first_run/first_run.cc +++ b/chrome/browser/first_run/first_run.cc
@@ -620,10 +620,7 @@ } void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - GetPingDelayPrefName().c_str(), - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(GetPingDelayPrefName().c_str(), 0); } bool SetShowFirstRunBubblePref(FirstRunBubbleOptions show_bubble_option) {
diff --git a/chrome/browser/first_run/first_run_browsertest.cc b/chrome/browser/first_run/first_run_browsertest.cc index 0c97f4c2..25897c1 100644 --- a/chrome/browser/first_run/first_run_browsertest.cc +++ b/chrome/browser/first_run/first_run_browsertest.cc
@@ -129,7 +129,7 @@ FirstRunMasterPrefsBrowserTestT() {} protected: - virtual void SetUp() override { + void SetUp() override { SetMasterPreferencesForTest(Text); FirstRunMasterPrefsBrowserTestBase::SetUp(); }
diff --git a/chrome/browser/first_run/try_chrome_dialog_view.h b/chrome/browser/first_run/try_chrome_dialog_view.h index eebe9ce..48ed0583 100644 --- a/chrome/browser/first_run/try_chrome_dialog_view.h +++ b/chrome/browser/first_run/try_chrome_dialog_view.h
@@ -103,13 +103,12 @@ // views::ButtonListener: // We have two buttons and according to what the user clicked we set |result_| // and we should always close and end the modal loop. - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) override; + void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::LinkListener: // If the user selects the link we need to fire off the default browser that // by some convoluted logic should not be chrome. - virtual void LinkClicked(views::Link* source, int event_flags) override; + void LinkClicked(views::Link* source, int event_flags) override; // Controls which flavor of the heading text to use. size_t flavor_;
diff --git a/chrome/browser/font_family_cache_unittest.cc b/chrome/browser/font_family_cache_unittest.cc index b7f8925..0470b274 100644 --- a/chrome/browser/font_family_cache_unittest.cc +++ b/chrome/browser/font_family_cache_unittest.cc
@@ -7,6 +7,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/test/base/testing_pref_service_syncable.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -31,6 +32,7 @@ // Tests that the cache is correctly set and cleared. TEST(FontFamilyCacheTest, Caching) { + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile; TestingFontFamilyCache cache(&profile); TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService(); @@ -43,14 +45,8 @@ std::string pref_name2(map_name + '.' + "adsf"); // Registers 2 preferences, and sets the first one. - prefs->registry()->RegisterStringPref( - pref_name.c_str(), - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->registry()->RegisterStringPref( - pref_name2.c_str(), - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs->registry()->RegisterStringPref(pref_name.c_str(), std::string()); + prefs->registry()->RegisterStringPref(pref_name2.c_str(), std::string()); prefs->SetString(pref_name.c_str(), font1.c_str()); // Check that the right preference is returned.
diff --git a/chrome/browser/geolocation/chrome_access_token_store.cc b/chrome/browser/geolocation/chrome_access_token_store.cc index b0f521b..01cf53b 100644 --- a/chrome/browser/geolocation/chrome_access_token_store.cc +++ b/chrome/browser/geolocation/chrome_access_token_store.cc
@@ -59,7 +59,7 @@ ~TokenLoadingJob() {} void PerformWorkOnUIThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DictionaryPrefUpdate update(g_browser_process->local_state(), prefs::kGeolocationAccessToken); base::DictionaryValue* token_dictionary = update.Get(); @@ -114,7 +114,7 @@ static void SetAccessTokenOnUIThread(const GURL& server_url, const base::string16& token) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DictionaryPrefUpdate update(g_browser_process->local_state(), prefs::kGeolocationAccessToken); base::DictionaryValue* access_token_dictionary = update.Get();
diff --git a/chrome/browser/geolocation/geolocation_permission_context_factory.cc b/chrome/browser/geolocation/geolocation_permission_context_factory.cc index c1259b1..59168c5 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_factory.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_factory.cc
@@ -61,10 +61,7 @@ void GeolocationPermissionContextFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { #if defined(OS_ANDROID) - registry->RegisterBooleanPref( - prefs::kGeolocationEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kGeolocationEnabled, true); #endif }
diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc index 37e84062..6775087 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc
@@ -32,6 +32,7 @@ #include "components/infobars/core/infobar.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" @@ -224,8 +225,9 @@ content::WebContents* new_tab = CreateTestWebContents(); new_tab->GetController().LoadURL( url, content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + content::NavigationEntry* entry = new_tab->GetController().GetPendingEntry(); content::RenderFrameHostTester::For(new_tab->GetMainFrame()) - ->SendNavigate(extra_tabs_.size() + 1, url); + ->SendNavigate(extra_tabs_.size() + 1, entry->GetUniqueID(), true, url); // Set up required helpers, and make this be as "tabby" as the code requires. #if defined(ENABLE_EXTENSIONS)
diff --git a/chrome/browser/google/google_url_tracker_factory.cc b/chrome/browser/google/google_url_tracker_factory.cc index 1ba3e69..81538e8 100644 --- a/chrome/browser/google/google_url_tracker_factory.cc +++ b/chrome/browser/google/google_url_tracker_factory.cc
@@ -54,14 +54,9 @@ void GoogleURLTrackerFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* user_prefs) { - user_prefs->RegisterStringPref( - prefs::kLastKnownGoogleURL, - GoogleURLTracker::kDefaultGoogleHomepage, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - user_prefs->RegisterStringPref( - kLastPromptedGoogleURL, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + user_prefs->RegisterStringPref(prefs::kLastKnownGoogleURL, + GoogleURLTracker::kDefaultGoogleHomepage); + user_prefs->RegisterStringPref(kLastPromptedGoogleURL, std::string()); } content::BrowserContext* GoogleURLTrackerFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc index 7bcf360..ffdb52da 100644 --- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc +++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.cc
@@ -11,10 +11,8 @@ #include "chrome/browser/renderer_context_menu/render_view_context_menu.h" #include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h" #include "chrome/common/chrome_version_info.h" -#include "components/browsing_data/storage_partition_http_cache_data_remover.h" #include "components/pdf/browser/pdf_web_contents_helper.h" #include "components/renderer_context_menu/context_menu_delegate.h" -#include "components/web_cache/browser/web_cache_manager.h" #include "content/public/browser/render_process_host.h" #include "extensions/browser/api/web_request/web_request_api.h" #include "extensions/browser/guest_view/guest_view_event.h" @@ -42,28 +40,6 @@ ChromeWebViewGuestDelegate::~ChromeWebViewGuestDelegate() { } -void ChromeWebViewGuestDelegate::ClearCache( - base::Time remove_since, - const base::Closure& done_callback) { - int render_process_id = guest_web_contents()->GetRenderProcessHost()->GetID(); - // We need to clear renderer cache separately for our process because - // StoragePartitionHttpCacheDataRemover::ClearData() does not clear that. - web_cache::WebCacheManager::GetInstance()->Remove(render_process_id); - web_cache::WebCacheManager::GetInstance()->ClearCacheForProcess( - render_process_id); - - content::StoragePartition* partition = - content::BrowserContext::GetStoragePartition( - guest_web_contents()->GetBrowserContext(), - guest_web_contents()->GetSiteInstance()); - - // StoragePartitionHttpCacheDataRemover removes itself when it is done. - // TODO(lazyboy): Once StoragePartitionHttpCacheDataRemover moves to - // components/, move |ClearCache| to WebViewGuest: http//crbug.com/471287. - browsing_data::StoragePartitionHttpCacheDataRemover::CreateForRange( - partition, remove_since, base::Time::Now())->Remove(done_callback); -} - bool ChromeWebViewGuestDelegate::HandleContextMenu( const content::ContextMenuParams& params) { ContextMenuDelegate* menu_delegate = @@ -132,7 +108,7 @@ MenuManager* menu_manager = MenuManager::Get( Profile::FromBrowserContext(web_view_guest()->browser_context())); menu_manager->RemoveAllContextItems(MenuItem::ExtensionKey( - web_view_guest()->owner_extension_id(), + web_view_guest()->owner_host(), web_view_guest()->view_instance_id())); }
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h index 9cd1722..aae364a 100644 --- a/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h +++ b/chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h
@@ -27,8 +27,6 @@ ~ChromeWebViewGuestDelegate() override; // WebViewGuestDelegate implementation. - void ClearCache(base::Time remove_since, - const base::Closure& done_callback) override; bool HandleContextMenu(const content::ContextMenuParams& params) override; void OnAttachWebViewHelpers(content::WebContents* contents) override; void OnDidCommitProvisionalLoadForFrame(bool is_main_frame) override;
diff --git a/chrome/browser/history/history_backend_unittest.cc b/chrome/browser/history/history_backend_unittest.cc index 771a0fff..308b9fd 100644 --- a/chrome/browser/history/history_backend_unittest.cc +++ b/chrome/browser/history/history_backend_unittest.cc
@@ -2044,7 +2044,7 @@ EXPECT_EQ(icon_url, icon_mappings[0].icon_url); EXPECT_TRUE(GetOnlyFaviconBitmap(icon_mappings[0].icon_id, &favicon_bitmap)); - EXPECT_NE(base::Time(), favicon_bitmap.last_updated); + EXPECT_EQ(base::Time(), favicon_bitmap.last_updated); EXPECT_TRUE(BitmapDataEqual('b', favicon_bitmap.bitmap_data)); EXPECT_EQ(kSmallSize, favicon_bitmap.pixel_size); } @@ -2112,7 +2112,7 @@ EXPECT_EQ(icon_url1, icon_mappings[0].icon_url); EXPECT_TRUE(GetOnlyFaviconBitmap(icon_mappings[0].icon_id, &favicon_bitmap)); - EXPECT_NE(base::Time(), favicon_bitmap.last_updated); + EXPECT_EQ(base::Time(), favicon_bitmap.last_updated); EXPECT_TRUE(BitmapDataEqual('b', favicon_bitmap.bitmap_data)); EXPECT_EQ(kSmallSize, favicon_bitmap.pixel_size); @@ -2230,7 +2230,7 @@ EXPECT_NE(0, favicon_id); EXPECT_TRUE(GetOnlyFaviconBitmap(favicon_id, &favicon_bitmap)); - EXPECT_NE(base::Time(), favicon_bitmap.last_updated); + EXPECT_EQ(base::Time(), favicon_bitmap.last_updated); EXPECT_TRUE(BitmapDataEqual('b', favicon_bitmap.bitmap_data)); EXPECT_EQ(kSmallSize, favicon_bitmap.pixel_size);
diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc index edd9ddfb..df1d2c05 100644 --- a/chrome/browser/history/history_unittest.cc +++ b/chrome/browser/history/history_unittest.cc
@@ -42,10 +42,7 @@ #include "base/task/cancelable_task_tracker.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" -#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" -#include "components/history/content/browser/download_constants_utils.h" -#include "components/history/content/browser/history_database_helper.h" #include "components/history/core/browser/download_constants.h" #include "components/history/core/browser/download_row.h" #include "components/history/core/browser/history_backend.h" @@ -83,7 +80,6 @@ using base::Time; using base::TimeDelta; -using content::DownloadItem; namespace history { class HistoryBackendDBTest; @@ -137,7 +133,7 @@ void CreateBackendAndDatabase() { backend_ = new HistoryBackend(new BackendDelegate(this), nullptr); backend_->Init(std::string(), false, - HistoryDatabaseParamsForPath(history_dir_)); + TestHistoryDatabaseParamsForPath(history_dir_)); db_ = backend_->db_.get(); DCHECK(in_mem_backend_) << "Mem backend should have been set by " "HistoryBackend::Init"; @@ -204,8 +200,7 @@ 512, state, DownloadDangerType::NOT_DANGEROUS, - ToHistoryDownloadInterruptReason( - content::DOWNLOAD_INTERRUPT_REASON_NONE), + kTestDownloadInterruptReasonNone, id, false, "by_ext_id", @@ -263,8 +258,7 @@ EXPECT_EQ(512, downloads[0].total_bytes); EXPECT_EQ(DownloadState::COMPLETE, downloads[0].state); EXPECT_EQ(DownloadDangerType::NOT_DANGEROUS, downloads[0].danger_type); - EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, - downloads[0].interrupt_reason); + EXPECT_EQ(kTestDownloadInterruptReasonNone, downloads[0].interrupt_reason); EXPECT_FALSE(downloads[0].opened); EXPECT_EQ("by_ext_id", downloads[0].by_ext_id); EXPECT_EQ("by_ext_name", downloads[0].by_ext_name); @@ -415,7 +409,7 @@ "FROM downloads ORDER BY id")); EXPECT_TRUE(statement.Step()); EXPECT_EQ(1, statement.ColumnInt64(0)); - EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, + EXPECT_EQ(DownloadInterruptReasonToInt(kTestDownloadInterruptReasonNone), statement.ColumnInt(1)); EXPECT_EQ("", statement.ColumnString(2)); EXPECT_EQ("", statement.ColumnString(3)); @@ -427,7 +421,7 @@ EXPECT_TRUE(statement.Step()); EXPECT_EQ(2, statement.ColumnInt64(0)); - EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, + EXPECT_EQ(DownloadInterruptReasonToInt(kTestDownloadInterruptReasonNone), statement.ColumnInt(1)); EXPECT_EQ("/path/to/some/file", statement.ColumnString(2)); EXPECT_EQ("/path/to/some/file", statement.ColumnString(3)); @@ -781,8 +775,7 @@ 512, DownloadState::COMPLETE, DownloadDangerType::NOT_DANGEROUS, - ToHistoryDownloadInterruptReason( - content::DOWNLOAD_INTERRUPT_REASON_NONE), + kTestDownloadInterruptReasonNone, 1, 0, "by_ext_id", @@ -846,7 +839,8 @@ EXPECT_TRUE(statement1.Step()); EXPECT_EQ(DownloadStateToInt(DownloadState::IN_PROGRESS), statement1.ColumnInt(0)); - EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, statement1.ColumnInt(1)); + EXPECT_EQ(DownloadInterruptReasonToInt(kTestDownloadInterruptReasonNone), + statement1.ColumnInt(1)); EXPECT_FALSE(statement1.Step()); } @@ -857,8 +851,7 @@ db_->QueryDownloads(&results); ASSERT_EQ(1u, results.size()); EXPECT_EQ(DownloadState::INTERRUPTED, results[0].state); - EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_CRASH, - results[0].interrupt_reason); + EXPECT_EQ(kTestDownloadInterruptReasonCrash, results[0].interrupt_reason); // Allow the update to propagate, shut down the DB, and confirm that // the query updated the on disk database as well. @@ -877,7 +870,7 @@ EXPECT_TRUE(statement1.Step()); EXPECT_EQ(DownloadStateToInt(DownloadState::INTERRUPTED), statement1.ColumnInt(0)); - EXPECT_EQ(content::DOWNLOAD_INTERRUPT_REASON_CRASH, + EXPECT_EQ(DownloadInterruptReasonToInt(kTestDownloadInterruptReasonCrash), statement1.ColumnInt(1)); EXPECT_FALSE(statement1.Step()); } @@ -996,8 +989,8 @@ history_dir_ = temp_dir_.path().AppendASCII("HistoryTest"); ASSERT_TRUE(base::CreateDirectory(history_dir_)); history_service_.reset(new history::HistoryService); - if (!history_service_->Init(std::string(), - HistoryDatabaseParamsForPath(history_dir_))) { + if (!history_service_->Init( + std::string(), TestHistoryDatabaseParamsForPath(history_dir_))) { history_service_.reset(); ADD_FAILURE(); }
diff --git a/chrome/browser/history/thumbnail_database_unittest.cc b/chrome/browser/history/thumbnail_database_unittest.cc index 9cca3cd..4b552d237 100644 --- a/chrome/browser/history/thumbnail_database_unittest.cc +++ b/chrome/browser/history/thumbnail_database_unittest.cc
@@ -387,6 +387,31 @@ EXPECT_EQ(original_schema, db.db_.GetSchema()); } +// Test that RetainDataForPageUrls() expires retained favicons. +TEST_F(ThumbnailDatabaseTest, RetainDataForPageUrlsExpiresRetainedFavicons) { + ThumbnailDatabase db(NULL); + ASSERT_EQ(sql::INIT_OK, db.Init(file_name_)); + db.BeginTransaction(); + + scoped_refptr<base::RefCountedStaticMemory> favicon1( + new base::RefCountedStaticMemory(kBlob1, sizeof(kBlob1))); + favicon_base::FaviconID kept_id = db.AddFavicon( + kIconUrl1, favicon_base::FAVICON, favicon1, base::Time::Now(), + gfx::Size()); + db.AddIconMapping(kPageUrl1, kept_id); + + EXPECT_TRUE(db.RetainDataForPageUrls(std::vector<GURL>(1u, kPageUrl1))); + + favicon_base::FaviconID new_favicon_id = db.GetFaviconIDForFaviconURL( + kIconUrl1, favicon_base::FAVICON, nullptr); + ASSERT_NE(0, new_favicon_id); + std::vector<FaviconBitmap> new_favicon_bitmaps; + db.GetFaviconBitmaps(new_favicon_id, &new_favicon_bitmaps); + + ASSERT_EQ(1u, new_favicon_bitmaps.size()); + EXPECT_EQ(0, new_favicon_bitmaps[0].last_updated.ToInternalValue()); +} + // Tests that deleting a favicon deletes the favicon row and favicon bitmap // rows from the database. TEST_F(ThumbnailDatabaseTest, DeleteFavicon) {
diff --git a/chrome/browser/history/top_sites_factory.cc b/chrome/browser/history/top_sites_factory.cc index a2a7db2..a102fcc 100644 --- a/chrome/browser/history/top_sites_factory.cc +++ b/chrome/browser/history/top_sites_factory.cc
@@ -4,14 +4,18 @@ #include "chrome/browser/history/top_sites_factory.h" +#include "base/bind.h" #include "base/macros.h" #include "base/memory/singleton.h" -#include "chrome/browser/history/top_sites_impl.h" +#include "chrome/browser/history/history_service_factory.h" +#include "chrome/browser/history/history_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_constants.h" +#include "chrome/common/pref_names.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/locale_settings.h" +#include "components/history/core/browser/top_sites_impl.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "content/public/browser/browser_thread.h" #include "grit/theme_resources.h" @@ -85,10 +89,27 @@ return Singleton<TopSitesFactory>::get(); } +// static +scoped_refptr<history::TopSites> TopSitesFactory::BuildTopSites( + content::BrowserContext* context, + const std::vector<history::PrepopulatedPage>& prepopulated_page_list) { + Profile* profile = Profile::FromBrowserContext(context); + scoped_refptr<history::TopSitesImpl> top_sites(new history::TopSitesImpl( + profile->GetPrefs(), HistoryServiceFactory::GetForProfile( + profile, ServiceAccessType::EXPLICIT_ACCESS), + prefs::kNtpMostVisitedURLsBlacklist, prepopulated_page_list, + base::Bind(CanAddURLToHistory))); + top_sites->Init(context->GetPath().Append(chrome::kTopSitesFilename), + content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::DB)); + return top_sites; +} + TopSitesFactory::TopSitesFactory() : RefcountedBrowserContextKeyedServiceFactory( "TopSites", BrowserContextDependencyManager::GetInstance()) { + DependsOn(HistoryServiceFactory::GetInstance()); } TopSitesFactory::~TopSitesFactory() { @@ -98,13 +119,7 @@ content::BrowserContext* context) const { history::PrepopulatedPageList prepopulated_pages; InitializePrepopulatedPageList(&prepopulated_pages); - - history::TopSitesImpl* top_sites = new history::TopSitesImpl( - static_cast<Profile*>(context), prepopulated_pages); - top_sites->Init(context->GetPath().Append(chrome::kTopSitesFilename), - content::BrowserThread::GetMessageLoopProxyForThread( - content::BrowserThread::DB)); - return make_scoped_refptr(top_sites); + return BuildTopSites(context, prepopulated_pages); } bool TopSitesFactory::ServiceIsNULLWhileTesting() const {
diff --git a/chrome/browser/history/top_sites_factory.h b/chrome/browser/history/top_sites_factory.h index f867b2d..3978dbe 100644 --- a/chrome/browser/history/top_sites_factory.h +++ b/chrome/browser/history/top_sites_factory.h
@@ -5,19 +5,18 @@ #ifndef CHROME_BROWSER_HISTORY_TOP_SITES_FACTORY_H_ #define CHROME_BROWSER_HISTORY_TOP_SITES_FACTORY_H_ +#include <vector> + #include "base/memory/ref_counted.h" #include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h" class Profile; -namespace history { -class TopSites; -} - template <typename T> struct DefaultSingletonTraits; namespace history { +struct PrepopulatedPage; class TopSites; } @@ -38,6 +37,12 @@ // Get the singleton instance of the factory. static TopSitesFactory* GetInstance(); + // Creates a TopSites service for |context| with |prepopulated_page_list|. + // Public for testing. + static scoped_refptr<history::TopSites> BuildTopSites( + content::BrowserContext* context, + const std::vector<history::PrepopulatedPage>& prepopulated_page_list); + private: friend struct DefaultSingletonTraits<TopSitesFactory>;
diff --git a/chrome/browser/history/top_sites_impl.cc b/chrome/browser/history/top_sites_impl.cc deleted file mode 100644 index e904643e..0000000 --- a/chrome/browser/history/top_sites_impl.cc +++ /dev/null
@@ -1,956 +0,0 @@ -// Copyright (c) 2013 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/history/top_sites_impl.h" - -#include <algorithm> -#include <set> - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/logging.h" -#include "base/md5.h" -#include "base/memory/ref_counted_memory.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/metrics/histogram.h" -#include "base/prefs/pref_service.h" -#include "base/prefs/scoped_user_pref_update.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/task_runner.h" -#include "base/values.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/history/history_utils.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" -#include "components/history/core/browser/history_backend.h" -#include "components/history/core/browser/history_db_task.h" -#include "components/history/core/browser/page_usage_data.h" -#include "components/history/core/browser/top_sites_cache.h" -#include "components/history/core/browser/url_utils.h" -#include "components/history/core/common/thumbnail_score.h" -#include "content/public/browser/navigation_controller.h" -#include "content/public/browser/navigation_details.h" -#include "content/public/browser/navigation_entry.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/web_contents.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/layout.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/image/image_util.h" - -using base::DictionaryValue; -using content::NavigationController; - -namespace history { - -namespace { - -void RunOrPostGetMostVisitedURLsCallback( - base::TaskRunner* task_runner, - bool include_forced_urls, - const TopSitesImpl::GetMostVisitedURLsCallback& callback, - const MostVisitedURLList& all_urls, - const MostVisitedURLList& nonforced_urls) { - const MostVisitedURLList* urls = - include_forced_urls ? &all_urls : &nonforced_urls; - if (task_runner->RunsTasksOnCurrentThread()) - callback.Run(*urls); - else - task_runner->PostTask(FROM_HERE, base::Bind(callback, *urls)); -} - -// Compares two MostVisitedURL having a non-null |last_forced_time|. -bool ForcedURLComparator(const MostVisitedURL& first, - const MostVisitedURL& second) { - DCHECK(!first.last_forced_time.is_null() && - !second.last_forced_time.is_null()); - return first.last_forced_time < second.last_forced_time; -} - -} // namespace - -// How many non-forced top sites to store in the cache. -static const size_t kNonForcedTopSitesNumber = 20; - -// How many forced top sites to store in the cache. -static const size_t kForcedTopSitesNumber = 20; - -// Max number of temporary images we'll cache. See comment above -// temp_images_ for details. -static const size_t kMaxTempTopImages = 8; - -static const int kDaysOfHistory = 90; -// Time from startup to first HistoryService query. -static const int64 kUpdateIntervalSecs = 15; -// Intervals between requests to HistoryService. -static const int64 kMinUpdateIntervalMinutes = 1; -static const int64 kMaxUpdateIntervalMinutes = 60; - -// Use 100 quality (highest quality) because we're very sensitive to -// artifacts for these small sized, highly detailed images. -static const int kTopSitesImageQuality = 100; - -// Initially, histogram is not recorded. -bool TopSitesImpl::histogram_recorded_ = false; - -TopSitesImpl::TopSitesImpl(Profile* profile, - const PrepopulatedPageList& prepopulated_pages) - : backend_(NULL), - cache_(new TopSitesCache()), - thread_safe_cache_(new TopSitesCache()), - profile_(profile), - last_num_urls_changed_(0), - prepopulated_pages_(prepopulated_pages), - loaded_(false), - history_service_observer_(this) { - if (!profile_) - return; - - if (content::NotificationService::current()) { - // Listen for any nav commits. We'll ignore those not related to this - // profile when we get the notification. - registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, - content::NotificationService::AllSources()); - } -} - -void TopSitesImpl::Init( - const base::FilePath& db_name, - const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner) { - // Create the backend here, rather than in the constructor, so that - // unit tests that do not need the backend can run without a problem. - backend_ = new TopSitesBackend(db_task_runner); - backend_->Init(db_name); - backend_->GetMostVisitedThumbnails( - base::Bind(&TopSitesImpl::OnGotMostVisitedThumbnails, - base::Unretained(this)), - &cancelable_task_tracker_); -} - -bool TopSitesImpl::SetPageThumbnail(const GURL& url, - const gfx::Image& thumbnail, - const ThumbnailScore& score) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!loaded_) { - // TODO(sky): I need to cache these and apply them after the load - // completes. - return false; - } - - bool add_temp_thumbnail = false; - if (!IsKnownURL(url)) { - if (!IsNonForcedFull()) { - add_temp_thumbnail = true; - } else { - return false; // This URL is not known to us. - } - } - - if (!CanAddURLToHistory(url)) - return false; // It's not a real webpage. - - scoped_refptr<base::RefCountedBytes> thumbnail_data; - if (!EncodeBitmap(thumbnail, &thumbnail_data)) - return false; - - if (add_temp_thumbnail) { - // Always remove the existing entry and then add it back. That way if we end - // up with too many temp thumbnails we'll prune the oldest first. - RemoveTemporaryThumbnailByURL(url); - AddTemporaryThumbnail(url, thumbnail_data.get(), score); - return true; - } - - return SetPageThumbnailEncoded(url, thumbnail_data.get(), score); -} - -bool TopSitesImpl::SetPageThumbnailToJPEGBytes( - const GURL& url, - const base::RefCountedMemory* memory, - const ThumbnailScore& score) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!loaded_) { - // TODO(sky): I need to cache these and apply them after the load - // completes. - return false; - } - - bool add_temp_thumbnail = false; - if (!IsKnownURL(url)) { - if (!IsNonForcedFull()) { - add_temp_thumbnail = true; - } else { - return false; // This URL is not known to us. - } - } - - if (!CanAddURLToHistory(url)) - return false; // It's not a real webpage. - - if (add_temp_thumbnail) { - // Always remove the existing entry and then add it back. That way if we end - // up with too many temp thumbnails we'll prune the oldest first. - RemoveTemporaryThumbnailByURL(url); - AddTemporaryThumbnail(url, memory, score); - return true; - } - - return SetPageThumbnailEncoded(url, memory, score); -} - -// WARNING: this function may be invoked on any thread. -void TopSitesImpl::GetMostVisitedURLs( - const GetMostVisitedURLsCallback& callback, - bool include_forced_urls) { - MostVisitedURLList filtered_urls; - { - base::AutoLock lock(lock_); - if (!loaded_) { - // A request came in before we finished loading. Store the callback and - // we'll run it on current thread when we finish loading. - pending_callbacks_.push_back( - base::Bind(&RunOrPostGetMostVisitedURLsCallback, - base::MessageLoopProxy::current(), - include_forced_urls, - callback)); - return; - } - if (include_forced_urls) { - filtered_urls = thread_safe_cache_->top_sites(); - } else { - filtered_urls.assign(thread_safe_cache_->top_sites().begin() + - thread_safe_cache_->GetNumForcedURLs(), - thread_safe_cache_->top_sites().end()); - } - } - callback.Run(filtered_urls); -} - -bool TopSitesImpl::GetPageThumbnail( - const GURL& url, - bool prefix_match, - scoped_refptr<base::RefCountedMemory>* bytes) { - // WARNING: this may be invoked on any thread. - // Perform exact match. - { - base::AutoLock lock(lock_); - if (thread_safe_cache_->GetPageThumbnail(url, bytes)) - return true; - } - - // Resource bundle is thread safe. - for (const auto& prepopulated_page : prepopulated_pages_) { - if (url == prepopulated_page.most_visited.url) { - *bytes = - ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( - prepopulated_page.thumbnail_id, ui::SCALE_FACTOR_100P); - return true; - } - } - - if (prefix_match) { - // If http or https, search with |url| first, then try the other one. - std::vector<GURL> url_list; - url_list.push_back(url); - if (url.SchemeIsHTTPOrHTTPS()) - url_list.push_back(ToggleHTTPAndHTTPS(url)); - - for (std::vector<GURL>::iterator it = url_list.begin(); - it != url_list.end(); ++it) { - base::AutoLock lock(lock_); - - GURL canonical_url; - // Test whether any stored URL is a prefix of |url|. - canonical_url = thread_safe_cache_->GetGeneralizedCanonicalURL(*it); - if (!canonical_url.is_empty() && - thread_safe_cache_->GetPageThumbnail(canonical_url, bytes)) { - return true; - } - } - } - - return false; -} - -bool TopSitesImpl::GetPageThumbnailScore(const GURL& url, - ThumbnailScore* score) { - // WARNING: this may be invoked on any thread. - base::AutoLock lock(lock_); - return thread_safe_cache_->GetPageThumbnailScore(url, score); -} - -bool TopSitesImpl::GetTemporaryPageThumbnailScore(const GURL& url, - ThumbnailScore* score) { - for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end(); - ++i) { - if (i->first == url) { - *score = i->second.thumbnail_score; - return true; - } - } - return false; -} - - -// Returns the index of |url| in |urls|, or -1 if not found. -static int IndexOf(const MostVisitedURLList& urls, const GURL& url) { - for (size_t i = 0; i < urls.size(); i++) { - if (urls[i].url == url) - return i; - } - return -1; -} - -void TopSitesImpl::SyncWithHistory() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (loaded_ && temp_images_.size()) { - // If we have temporary thumbnails it means there isn't much data, and most - // likely the user is first running Chrome. During this time we throttle - // updating from history by 30 seconds. If the user creates a new tab page - // during this window of time we force updating from history so that the new - // tab page isn't so far out of date. - timer_.Stop(); - StartQueryForMostVisited(); - } -} - -bool TopSitesImpl::HasBlacklistedItems() const { - const base::DictionaryValue* blacklist = - profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); - return blacklist && !blacklist->empty(); -} - -void TopSitesImpl::AddBlacklistedURL(const GURL& url) { - DCHECK(thread_checker_.CalledOnValidThread()); - - base::Value* dummy = base::Value::CreateNullValue(); - { - DictionaryPrefUpdate update(profile_->GetPrefs(), - prefs::kNtpMostVisitedURLsBlacklist); - base::DictionaryValue* blacklist = update.Get(); - blacklist->SetWithoutPathExpansion(GetURLHash(url), dummy); - } - - ResetThreadSafeCache(); - NotifyTopSitesChanged(); -} - -void TopSitesImpl::RemoveBlacklistedURL(const GURL& url) { - DCHECK(thread_checker_.CalledOnValidThread()); - { - DictionaryPrefUpdate update(profile_->GetPrefs(), - prefs::kNtpMostVisitedURLsBlacklist); - base::DictionaryValue* blacklist = update.Get(); - blacklist->RemoveWithoutPathExpansion(GetURLHash(url), NULL); - } - ResetThreadSafeCache(); - NotifyTopSitesChanged(); -} - -bool TopSitesImpl::IsBlacklisted(const GURL& url) { - DCHECK(thread_checker_.CalledOnValidThread()); - const base::DictionaryValue* blacklist = - profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); - return blacklist && blacklist->HasKey(GetURLHash(url)); -} - -void TopSitesImpl::ClearBlacklistedURLs() { - DCHECK(thread_checker_.CalledOnValidThread()); - { - DictionaryPrefUpdate update(profile_->GetPrefs(), - prefs::kNtpMostVisitedURLsBlacklist); - base::DictionaryValue* blacklist = update.Get(); - blacklist->Clear(); - } - ResetThreadSafeCache(); - NotifyTopSitesChanged(); -} - -void TopSitesImpl::ShutdownOnUIThread() { - profile_ = NULL; - // Cancel all requests so that the service doesn't callback to us after we've - // invoked Shutdown (this could happen if we have a pending request and - // Shutdown is invoked). - cancelable_task_tracker_.TryCancelAll(); - registrar_.RemoveAll(); - if (backend_) - backend_->Shutdown(); -} - -// static -void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, - const MostVisitedURLList& new_list, - TopSitesDelta* delta) { - - // Add all the old URLs for quick lookup. This maps URLs to the corresponding - // index in the input. - std::map<GURL, size_t> all_old_urls; - size_t num_old_forced = 0; - for (size_t i = 0; i < old_list.size(); i++) { - if (!old_list[i].last_forced_time.is_null()) - num_old_forced++; - DCHECK(old_list[i].last_forced_time.is_null() || i < num_old_forced) - << "Forced URLs must all appear before non-forced URLs."; - all_old_urls[old_list[i].url] = i; - } - - // Check all the URLs in the new set to see which ones are new or just moved. - // When we find a match in the old set, we'll reset its index to our special - // marker. This allows us to quickly identify the deleted ones in a later - // pass. - const size_t kAlreadyFoundMarker = static_cast<size_t>(-1); - int rank = -1; // Forced URLs have a rank of -1. - for (size_t i = 0; i < new_list.size(); i++) { - // Increase the rank if we're going through forced URLs. This works because - // non-forced URLs all come after forced URLs. - if (new_list[i].last_forced_time.is_null()) - rank++; - DCHECK(new_list[i].last_forced_time.is_null() == (rank != -1)) - << "Forced URLs must all appear before non-forced URLs."; - std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url); - if (found == all_old_urls.end()) { - MostVisitedURLWithRank added; - added.url = new_list[i]; - added.rank = rank; - delta->added.push_back(added); - } else { - DCHECK(found->second != kAlreadyFoundMarker) - << "Same URL appears twice in the new list."; - int old_rank = found->second >= num_old_forced ? - found->second - num_old_forced : -1; - if (old_rank != rank || - old_list[found->second].last_forced_time != - new_list[i].last_forced_time) { - MostVisitedURLWithRank moved; - moved.url = new_list[i]; - moved.rank = rank; - delta->moved.push_back(moved); - } - found->second = kAlreadyFoundMarker; - } - } - - // Any member without the special marker in the all_old_urls list means that - // there wasn't a "new" URL that mapped to it, so it was deleted. - for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); - i != all_old_urls.end(); ++i) { - if (i->second != kAlreadyFoundMarker) - delta->deleted.push_back(old_list[i->second]); - } -} - -base::CancelableTaskTracker::TaskId TopSitesImpl::StartQueryForMostVisited() { - DCHECK(loaded_); - if (!profile_) - return base::CancelableTaskTracker::kBadTaskId; - - HistoryService* hs = HistoryServiceFactory::GetForProfile( - profile_, ServiceAccessType::EXPLICIT_ACCESS); - // |hs| may be null during unit tests. - if (hs) { - return hs->QueryMostVisitedURLs( - num_results_to_request_from_history(), - kDaysOfHistory, - base::Bind(&TopSitesImpl::OnTopSitesAvailableFromHistory, - base::Unretained(this)), - &cancelable_task_tracker_); - } - return base::CancelableTaskTracker::kBadTaskId; -} - -bool TopSitesImpl::IsKnownURL(const GURL& url) { - return loaded_ && cache_->IsKnownURL(url); -} - -const std::string& TopSitesImpl::GetCanonicalURLString(const GURL& url) const { - return cache_->GetCanonicalURL(url).spec(); -} - -bool TopSitesImpl::IsNonForcedFull() { - return loaded_ && cache_->GetNumNonForcedURLs() >= kNonForcedTopSitesNumber; -} - -bool TopSitesImpl::IsForcedFull() { - return loaded_ && cache_->GetNumForcedURLs() >= kForcedTopSitesNumber; -} - -TopSitesImpl::~TopSitesImpl() { -} - -bool TopSitesImpl::SetPageThumbnailNoDB( - const GURL& url, - const base::RefCountedMemory* thumbnail_data, - const ThumbnailScore& score) { - // This should only be invoked when we know about the url. - DCHECK(cache_->IsKnownURL(url)); - - const MostVisitedURL& most_visited = - cache_->top_sites()[cache_->GetURLIndex(url)]; - Images* image = cache_->GetImage(url); - - // When comparing the thumbnail scores, we need to take into account the - // redirect hops, which are not generated when the thumbnail is because the - // redirects weren't known. We fill that in here since we know the redirects. - ThumbnailScore new_score_with_redirects(score); - new_score_with_redirects.redirect_hops_from_dest = - GetRedirectDistanceForURL(most_visited, url); - - if (!ShouldReplaceThumbnailWith(image->thumbnail_score, - new_score_with_redirects) && - image->thumbnail.get()) - return false; // The one we already have is better. - - image->thumbnail = const_cast<base::RefCountedMemory*>(thumbnail_data); - image->thumbnail_score = new_score_with_redirects; - - ResetThreadSafeImageCache(); - return true; -} - -bool TopSitesImpl::SetPageThumbnailEncoded( - const GURL& url, - const base::RefCountedMemory* thumbnail, - const ThumbnailScore& score) { - if (!SetPageThumbnailNoDB(url, thumbnail, score)) - return false; - - // Update the database. - if (!cache_->IsKnownURL(url)) - return false; - - size_t index = cache_->GetURLIndex(url); - int url_rank = index - cache_->GetNumForcedURLs(); - const MostVisitedURL& most_visited = cache_->top_sites()[index]; - backend_->SetPageThumbnail(most_visited, - url_rank < 0 ? -1 : url_rank, - *(cache_->GetImage(most_visited.url))); - return true; -} - -// static -bool TopSitesImpl::EncodeBitmap(const gfx::Image& bitmap, - scoped_refptr<base::RefCountedBytes>* bytes) { - if (bitmap.IsEmpty()) - return false; - *bytes = new base::RefCountedBytes(); - std::vector<unsigned char> data; - if (!gfx::JPEG1xEncodedDataFromImage(bitmap, kTopSitesImageQuality, &data)) - return false; - - // As we're going to cache this data, make sure the vector is only as big as - // it needs to be, as JPEGCodec::Encode() over-allocates data.capacity(). - // (In a C++0x future, we can just call shrink_to_fit() in Encode()) - (*bytes)->data() = data; - return true; -} - -void TopSitesImpl::RemoveTemporaryThumbnailByURL(const GURL& url) { - for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end(); - ++i) { - if (i->first == url) { - temp_images_.erase(i); - return; - } - } -} - -void TopSitesImpl::AddTemporaryThumbnail( - const GURL& url, - const base::RefCountedMemory* thumbnail, - const ThumbnailScore& score) { - if (temp_images_.size() == kMaxTempTopImages) - temp_images_.erase(temp_images_.begin()); - - TempImage image; - image.first = url; - image.second.thumbnail = const_cast<base::RefCountedMemory*>(thumbnail); - image.second.thumbnail_score = score; - temp_images_.push_back(image); -} - -void TopSitesImpl::TimerFired() { - StartQueryForMostVisited(); -} - -// static -int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited, - const GURL& url) { - for (size_t i = 0; i < most_visited.redirects.size(); i++) { - if (most_visited.redirects[i] == url) - return static_cast<int>(most_visited.redirects.size() - i - 1); - } - NOTREACHED() << "URL should always be found."; - return 0; -} - -PrepopulatedPageList TopSitesImpl::GetPrepopulatedPages() { - return prepopulated_pages_; -} - -bool TopSitesImpl::loaded() const { - return loaded_; -} - -bool TopSitesImpl::AddForcedURL(const GURL& url, const base::Time& time) { - DCHECK(thread_checker_.CalledOnValidThread()); - size_t num_forced = cache_->GetNumForcedURLs(); - MostVisitedURLList new_list(cache_->top_sites()); - MostVisitedURL new_url; - - if (cache_->IsKnownURL(url)) { - size_t index = cache_->GetURLIndex(url); - // Do nothing if we currently have that URL as non-forced. - if (new_list[index].last_forced_time.is_null()) - return false; - - // Update the |last_forced_time| of the already existing URL. Delete it and - // reinsert it at the right location. - new_url = new_list[index]; - new_list.erase(new_list.begin() + index); - num_forced--; - } else { - new_url.url = url; - new_url.redirects.push_back(url); - } - new_url.last_forced_time = time; - // Add forced URLs and sort. Added to the end of the list of forced URLs - // since this is almost always where it needs to go, unless the user's local - // clock is fiddled with. - MostVisitedURLList::iterator mid = new_list.begin() + num_forced; - new_list.insert(mid, new_url); - mid = new_list.begin() + num_forced; // Mid was invalidated. - std::inplace_merge(new_list.begin(), mid, mid + 1, ForcedURLComparator); - SetTopSites(new_list, CALL_LOCATION_FROM_OTHER_PLACES); - return true; -} - -bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, - size_t num_forced_urls) { - bool added = false; - for (const auto& prepopulated_page : prepopulated_pages_) { - if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && - IndexOf(*urls, prepopulated_page.most_visited.url) == -1) { - urls->push_back(prepopulated_page.most_visited); - added = true; - } - } - return added; -} - -size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { - DCHECK(thread_checker_.CalledOnValidThread()); - // Add all the new URLs for quick lookup. Take that opportunity to count the - // number of forced URLs in |new_list|. - std::set<GURL> all_new_urls; - size_t num_forced = 0; - for (size_t i = 0; i < new_list->size(); ++i) { - for (size_t j = 0; j < (*new_list)[i].redirects.size(); j++) { - all_new_urls.insert((*new_list)[i].redirects[j]); - } - if (!(*new_list)[i].last_forced_time.is_null()) - ++num_forced; - } - - // Keep the forced URLs from |cache_| that are not found in |new_list|. - MostVisitedURLList filtered_forced_urls; - for (size_t i = 0; i < cache_->GetNumForcedURLs(); ++i) { - if (all_new_urls.find(cache_->top_sites()[i].url) == all_new_urls.end()) - filtered_forced_urls.push_back(cache_->top_sites()[i]); - } - num_forced += filtered_forced_urls.size(); - - // Prepend forced URLs and sort in order of ascending |last_forced_time|. - new_list->insert(new_list->begin(), filtered_forced_urls.begin(), - filtered_forced_urls.end()); - std::inplace_merge( - new_list->begin(), new_list->begin() + filtered_forced_urls.size(), - new_list->begin() + num_forced, ForcedURLComparator); - - // Drop older forced URLs if the list overflows. Since forced URLs are always - // sort in increasing order of |last_forced_time|, drop the first ones. - if (num_forced > kForcedTopSitesNumber) { - new_list->erase(new_list->begin(), - new_list->begin() + (num_forced - kForcedTopSitesNumber)); - num_forced = kForcedTopSitesNumber; - } - - return num_forced; -} - -void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, - MostVisitedURLList* out) { - // Log the number of times ApplyBlacklist is called so we can compute the - // average number of blacklisted items per user. - const base::DictionaryValue* blacklist = - profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); - UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); - UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", - (blacklist ? blacklist->size() : 0)); - size_t num_non_forced_urls = 0; - size_t num_forced_urls = 0; - for (size_t i = 0; i < urls.size(); ++i) { - if (!IsBlacklisted(urls[i].url)) { - if (urls[i].last_forced_time.is_null()) { - // Non-forced URL. - if (num_non_forced_urls >= kNonForcedTopSitesNumber) - continue; - num_non_forced_urls++; - } else { - // Forced URL. - if (num_forced_urls >= kForcedTopSitesNumber) - continue; - num_forced_urls++; - } - out->push_back(urls[i]); - } - } -} - -std::string TopSitesImpl::GetURLHash(const GURL& url) { - // We don't use canonical URLs here to be able to blacklist only one of - // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. - return base::MD5String(url.spec()); -} - -base::TimeDelta TopSitesImpl::GetUpdateDelay() { - if (cache_->top_sites().size() <= prepopulated_pages_.size()) - return base::TimeDelta::FromSeconds(30); - - int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; - int64 minutes = kMaxUpdateIntervalMinutes - - last_num_urls_changed_ * range / cache_->top_sites().size(); - return base::TimeDelta::FromMinutes(minutes); -} - -void TopSitesImpl::Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_COMMITTED, type); - if (!loaded_) - return; - - NavigationController* controller = - content::Source<NavigationController>(source).ptr(); - Profile* profile = Profile::FromBrowserContext( - controller->GetWebContents()->GetBrowserContext()); - if (profile == profile_ && !IsNonForcedFull()) { - content::LoadCommittedDetails* load_details = - content::Details<content::LoadCommittedDetails>(details).ptr(); - if (!load_details) - return; - const GURL& url = load_details->entry->GetURL(); - if (!cache_->IsKnownURL(url) && CanAddURLToHistory(url)) { - // To avoid slamming history we throttle requests when the url updates. - // To do otherwise negatively impacts perf tests. - RestartQueryForTopSitesTimer(GetUpdateDelay()); - } - } -} - -void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites, - const CallLocation location) { - DCHECK(thread_checker_.CalledOnValidThread()); - - MostVisitedURLList top_sites(new_top_sites); - size_t num_forced_urls = MergeCachedForcedURLs(&top_sites); - AddPrepopulatedPages(&top_sites, num_forced_urls); - - TopSitesDelta delta; - DiffMostVisited(cache_->top_sites(), top_sites, &delta); - - TopSitesBackend::RecordHistogram record_or_not = - TopSitesBackend::RECORD_HISTOGRAM_NO; - - // Record the delta size into a histogram if this function is called from - // function OnGotMostVisitedThumbnails and no histogram value has been - // recorded before. - if (location == CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_THUMBNAILS && - !histogram_recorded_) { - size_t delta_size = - delta.deleted.size() + delta.added.size() + delta.moved.size(); - UMA_HISTOGRAM_COUNTS_100("History.FirstSetTopSitesDeltaSize", delta_size); - // Will be passed to TopSitesBackend to let it record the histogram too. - record_or_not = TopSitesBackend::RECORD_HISTOGRAM_YES; - // Change it to true so that the histogram will not be recorded any more. - histogram_recorded_ = true; - } - - if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) { - backend_->UpdateTopSites(delta, record_or_not); - } - - last_num_urls_changed_ = delta.added.size() + delta.moved.size(); - - // We always do the following steps (setting top sites in cache, and resetting - // thread safe cache ...) as this method is invoked during startup at which - // point the caches haven't been updated yet. - cache_->SetTopSites(top_sites); - - // See if we have any tmp thumbnails for the new sites. - if (!temp_images_.empty()) { - for (size_t i = 0; i < top_sites.size(); ++i) { - const MostVisitedURL& mv = top_sites[i]; - GURL canonical_url = cache_->GetCanonicalURL(mv.url); - // At the time we get the thumbnail redirects aren't known, so we have to - // iterate through all the images. - for (TempImages::iterator it = temp_images_.begin(); - it != temp_images_.end(); ++it) { - if (canonical_url == cache_->GetCanonicalURL(it->first)) { - SetPageThumbnailEncoded( - mv.url, it->second.thumbnail.get(), it->second.thumbnail_score); - temp_images_.erase(it); - break; - } - } - } - } - - if (top_sites.size() - num_forced_urls >= kNonForcedTopSitesNumber) - temp_images_.clear(); - - ResetThreadSafeCache(); - ResetThreadSafeImageCache(); - NotifyTopSitesChanged(); - - // Restart the timer that queries history for top sites. This is done to - // ensure we stay in sync with history. - RestartQueryForTopSitesTimer(GetUpdateDelay()); -} - -int TopSitesImpl::num_results_to_request_from_history() const { - DCHECK(thread_checker_.CalledOnValidThread()); - - const base::DictionaryValue* blacklist = - profile_->GetPrefs()->GetDictionary(prefs::kNtpMostVisitedURLsBlacklist); - return kNonForcedTopSitesNumber + (blacklist ? blacklist->size() : 0); -} - -void TopSitesImpl::MoveStateToLoaded() { - DCHECK(thread_checker_.CalledOnValidThread()); - - MostVisitedURLList filtered_urls_all; - MostVisitedURLList filtered_urls_nonforced; - PendingCallbacks pending_callbacks; - { - base::AutoLock lock(lock_); - - if (loaded_) - return; // Don't do anything if we're already loaded. - loaded_ = true; - - // Now that we're loaded we can service the queued up callbacks. Copy them - // here and service them outside the lock. - if (!pending_callbacks_.empty()) { - // We always filter out forced URLs because callers of GetMostVisitedURLs - // are not interested in them. - filtered_urls_all = thread_safe_cache_->top_sites(); - filtered_urls_nonforced.assign(thread_safe_cache_->top_sites().begin() + - thread_safe_cache_->GetNumForcedURLs(), - thread_safe_cache_->top_sites().end()); - pending_callbacks.swap(pending_callbacks_); - } - } - - for (size_t i = 0; i < pending_callbacks.size(); i++) - pending_callbacks[i].Run(filtered_urls_all, filtered_urls_nonforced); - - HistoryService* hs = HistoryServiceFactory::GetForProfile( - profile_, ServiceAccessType::EXPLICIT_ACCESS); - // |hs| may be null during unit tests. - if (hs) - history_service_observer_.Add(hs); - - NotifyTopSitesLoaded(); -} - -void TopSitesImpl::ResetThreadSafeCache() { - base::AutoLock lock(lock_); - MostVisitedURLList cached; - ApplyBlacklist(cache_->top_sites(), &cached); - thread_safe_cache_->SetTopSites(cached); -} - -void TopSitesImpl::ResetThreadSafeImageCache() { - base::AutoLock lock(lock_); - thread_safe_cache_->SetThumbnails(cache_->images()); -} - -void TopSitesImpl::RestartQueryForTopSitesTimer(base::TimeDelta delta) { - if (timer_.IsRunning() && ((timer_start_time_ + timer_.GetCurrentDelay()) < - (base::TimeTicks::Now() + delta))) { - return; - } - - timer_start_time_ = base::TimeTicks::Now(); - timer_.Stop(); - timer_.Start(FROM_HERE, delta, this, &TopSitesImpl::TimerFired); -} - -void TopSitesImpl::OnGotMostVisitedThumbnails( - const scoped_refptr<MostVisitedThumbnails>& thumbnails) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // Set the top sites directly in the cache so that SetTopSites diffs - // correctly. - cache_->SetTopSites(thumbnails->most_visited); - SetTopSites(thumbnails->most_visited, - CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_THUMBNAILS); - cache_->SetThumbnails(thumbnails->url_to_images_map); - - ResetThreadSafeImageCache(); - - MoveStateToLoaded(); - - // Start a timer that refreshes top sites from history. - RestartQueryForTopSitesTimer( - base::TimeDelta::FromSeconds(kUpdateIntervalSecs)); -} - -void TopSitesImpl::OnTopSitesAvailableFromHistory( - const MostVisitedURLList* pages) { - DCHECK(pages); - SetTopSites(*pages, CALL_LOCATION_FROM_OTHER_PLACES); -} - -void TopSitesImpl::OnURLsDeleted(HistoryService* history_service, - bool all_history, - bool expired, - const URLRows& deleted_rows, - const std::set<GURL>& favicon_urls) { - if (!loaded_) - return; - - if (all_history) { - SetTopSites(MostVisitedURLList(), CALL_LOCATION_FROM_OTHER_PLACES); - backend_->ResetDatabase(); - } else { - std::set<size_t> indices_to_delete; // Indices into top_sites_. - for (const auto& row : deleted_rows) { - if (cache_->IsKnownURL(row.url())) - indices_to_delete.insert(cache_->GetURLIndex(row.url())); - } - - if (indices_to_delete.empty()) - return; - - MostVisitedURLList new_top_sites(cache_->top_sites()); - for (std::set<size_t>::reverse_iterator i = indices_to_delete.rbegin(); - i != indices_to_delete.rend(); i++) { - new_top_sites.erase(new_top_sites.begin() + *i); - } - SetTopSites(new_top_sites, CALL_LOCATION_FROM_OTHER_PLACES); - } - StartQueryForMostVisited(); -} - -void TopSitesImpl::HistoryServiceBeingDeleted(HistoryService* history_service) { - history_service_observer_.Remove(history_service); -} - -} // namespace history
diff --git a/chrome/browser/history/top_sites_impl.h b/chrome/browser/history/top_sites_impl.h deleted file mode 100644 index eb9a6ca8..0000000 --- a/chrome/browser/history/top_sites_impl.h +++ /dev/null
@@ -1,311 +0,0 @@ -// Copyright (c) 2013 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 CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_ -#define CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_ - -#include <list> -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "base/basictypes.h" -#include "base/callback.h" -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" -#include "base/scoped_observer.h" -#include "base/synchronization/lock.h" -#include "base/task/cancelable_task_tracker.h" -#include "base/threading/thread_checker.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "components/history/core/browser/history_service.h" -#include "components/history/core/browser/history_service_observer.h" -#include "components/history/core/browser/history_types.h" -#include "components/history/core/browser/page_usage_data.h" -#include "components/history/core/browser/top_sites.h" -#include "components/history/core/browser/top_sites_backend.h" -#include "components/history/core/common/thumbnail_score.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "third_party/skia/include/core/SkColor.h" -#include "ui/gfx/image/image.h" -#include "url/gurl.h" - -class Profile; - -namespace base { -class FilePath; -class RefCountedBytes; -class RefCountedMemory; -class SingleThreadTaskRunner; -} - -namespace history { - -class TopSitesCache; -class TopSitesImplTest; - -// This class allows requests for most visited urls and thumbnails on any -// thread. All other methods must be invoked on the UI thread. All mutations -// to internal state happen on the UI thread and are scheduled to update the -// db using TopSitesBackend. -class TopSitesImpl : public TopSites, - public HistoryServiceObserver, - public content::NotificationObserver { - public: - TopSitesImpl(Profile* profile, - const PrepopulatedPageList& prepopulated_pages); - - // Initializes TopSitesImpl. - void Init(const base::FilePath& db_name, - const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner); - - bool SetPageThumbnail(const GURL& url, - const gfx::Image& thumbnail, - const ThumbnailScore& score) override; - bool SetPageThumbnailToJPEGBytes(const GURL& url, - const base::RefCountedMemory* memory, - const ThumbnailScore& score) override; - void GetMostVisitedURLs(const GetMostVisitedURLsCallback& callback, - bool include_forced_urls) override; - bool GetPageThumbnail(const GURL& url, - bool prefix_match, - scoped_refptr<base::RefCountedMemory>* bytes) override; - bool GetPageThumbnailScore(const GURL& url, ThumbnailScore* score) override; - bool GetTemporaryPageThumbnailScore(const GURL& url, - ThumbnailScore* score) override; - void SyncWithHistory() override; - bool HasBlacklistedItems() const override; - void AddBlacklistedURL(const GURL& url) override; - void RemoveBlacklistedURL(const GURL& url) override; - bool IsBlacklisted(const GURL& url) override; - void ClearBlacklistedURLs() override; - base::CancelableTaskTracker::TaskId StartQueryForMostVisited() override; - bool IsKnownURL(const GURL& url) override; - const std::string& GetCanonicalURLString(const GURL& url) const override; - bool IsNonForcedFull() override; - bool IsForcedFull() override; - PrepopulatedPageList GetPrepopulatedPages() override; - bool loaded() const override; - bool AddForcedURL(const GURL& url, const base::Time& time) override; - - // RefcountedKeyedService: - void ShutdownOnUIThread() override; - - protected: - ~TopSitesImpl() override; - - private: - // TODO(yiyaoliu): Remove the enums and related code when crbug/223430 is - // fixed. - // An enum representing different situations under which function - // SetTopSites can be initiated. - // This is needed because a histogram is used to record speed related metrics - // when SetTopSites are initiated from OnGotMostVisitedThumbnails, which - // usually happens early and might affect Chrome startup speed. - enum CallLocation { - // SetTopSites is called from function OnGotMostVisitedThumbnails. - CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_THUMBNAILS, - // All other situations. - CALL_LOCATION_FROM_OTHER_PLACES - }; - - friend class TopSitesImplTest; - FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisited); - FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisitedWithForced); - - typedef base::Callback<void(const MostVisitedURLList&, - const MostVisitedURLList&)> PendingCallback; - - typedef std::pair<GURL, Images> TempImage; - typedef std::list<TempImage> TempImages; - typedef std::vector<PendingCallback> PendingCallbacks; - - // Generates the diff of things that happened between "old" and "new." - // - // This treats forced URLs separately than non-forced URLs. - // - // The URLs that are in "new" but not "old" will be have their index into - // "new" put in |added_urls|. The non-forced URLs that are in "old" but not - // "new" will have their index into "old" put into |deleted_urls|. - // - // URLs appearing in both old and new lists but having different indices will - // have their index into "new" be put into |moved_urls|. - static void DiffMostVisited(const MostVisitedURLList& old_list, - const MostVisitedURLList& new_list, - TopSitesDelta* delta); - - // Sets the thumbnail without writing to the database. Useful when - // reading last known top sites from the DB. - // Returns true if the thumbnail was set, false if the existing one is better. - bool SetPageThumbnailNoDB(const GURL& url, - const base::RefCountedMemory* thumbnail_data, - const ThumbnailScore& score); - - // A version of SetPageThumbnail that takes RefCountedBytes as - // returned by HistoryService. - bool SetPageThumbnailEncoded(const GURL& url, - const base::RefCountedMemory* thumbnail, - const ThumbnailScore& score); - - // Encodes the bitmap to bytes for storage to the db. Returns true if the - // bitmap was successfully encoded. - static bool EncodeBitmap(const gfx::Image& bitmap, - scoped_refptr<base::RefCountedBytes>* bytes); - - // Removes the cached thumbnail for url. Does nothing if |url| if not cached - // in |temp_images_|. - void RemoveTemporaryThumbnailByURL(const GURL& url); - - // Add a thumbnail for an unknown url. See temp_thumbnails_map_. - void AddTemporaryThumbnail(const GURL& url, - const base::RefCountedMemory* thumbnail, - const ThumbnailScore& score); - - // Called by our timer. Starts the query for the most visited sites. - void TimerFired(); - - // Finds the given URL in the redirect chain for the given TopSite, and - // returns the distance from the destination in hops that the given URL is. - // The URL is assumed to be in the list. The destination is 0. - static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited, - const GURL& url); - - // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|. - // Returns true if any pages were added. - bool AddPrepopulatedPages(MostVisitedURLList* urls, - size_t num_forced_urls); - - // Add all the forced URLs from |cache_| into |new_list|, making sure not to - // add any URL that's already in |new_list|'s non-forced URLs. The forced URLs - // in |cache_| and |new_list| are assumed to appear at the front of the list - // and be sorted in increasing |last_forced_time|. This will still be true - // after the call. If the list of forced URLs overflows the older ones are - // dropped. Returns the number of forced URLs after the merge. - size_t MergeCachedForcedURLs(MostVisitedURLList* new_list); - - // Takes |urls|, produces it's copy in |out| after removing blacklisted URLs. - // Also ensures we respect the maximum number of forced URLs and non-forced - // URLs. - void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out); - - // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs. - std::string GetURLHash(const GURL& url); - - // Returns the delay until the next update of history is needed. - // Uses num_urls_changed - base::TimeDelta GetUpdateDelay(); - - // Implementation of content::NotificationObserver. - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - // Updates URLs in |cache_| and the db (in the background). - // The non-forced URLs in |new_top_sites| replace those in |cache_|. - // The forced URLs of |new_top_sites| are merged with those in |cache_|, - // if the list of forced URLs overflows, the oldest ones are dropped. - // All mutations to cache_ *must* go through this. Should - // be called from the UI thread. - void SetTopSites(const MostVisitedURLList& new_top_sites, - const CallLocation location); - - // Returns the number of most visited results to request from history. This - // changes depending upon how many urls have been blacklisted. Should be - // called from the UI thread. - int num_results_to_request_from_history() const; - - // Invoked when transitioning to LOADED. Notifies any queued up callbacks. - // Should be called from the UI thread. - void MoveStateToLoaded(); - - void ResetThreadSafeCache(); - - void ResetThreadSafeImageCache(); - - // Stops and starts timer with a delay of |delta|. - void RestartQueryForTopSitesTimer(base::TimeDelta delta); - - // Callback from TopSites with the top sites/thumbnails. Should be called - // from the UI thread. - void OnGotMostVisitedThumbnails( - const scoped_refptr<MostVisitedThumbnails>& thumbnails); - - // Called when history service returns a list of top URLs. - void OnTopSitesAvailableFromHistory(const MostVisitedURLList* data); - - // history::HistoryServiceObserver: - void OnURLsDeleted(HistoryService* history_service, - bool all_history, - bool expired, - const URLRows& deleted_rows, - const std::set<GURL>& favicon_urls) override; - void HistoryServiceBeingDeleted(HistoryService* history_service) override; - - - // Ensures that non thread-safe methods are called on the correct thread. - base::ThreadChecker thread_checker_; - - scoped_refptr<TopSitesBackend> backend_; - - // The top sites data. - scoped_ptr<TopSitesCache> cache_; - - // Copy of the top sites data that may be accessed on any thread (assuming - // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and - // pinned urls applied (|cache_| does not). - scoped_ptr<TopSitesCache> thread_safe_cache_; - - Profile* profile_; - - // Lock used to access |thread_safe_cache_|. - mutable base::Lock lock_; - - // Task tracker for history and backend requests. - base::CancelableTaskTracker cancelable_task_tracker_; - - // Timer that asks history for the top sites. This is used to make sure our - // data stays in sync with history. - base::OneShotTimer<TopSitesImpl> timer_; - - // The time we started |timer_| at. Only valid if |timer_| is running. - base::TimeTicks timer_start_time_; - - content::NotificationRegistrar registrar_; - - // The number of URLs changed on the last update. - size_t last_num_urls_changed_; - - // The pending requests for the top sites list. Can only be non-empty at - // startup. After we read the top sites from the DB, we'll always have a - // cached list and be able to run callbacks immediately. - PendingCallbacks pending_callbacks_; - - // Stores thumbnails for unknown pages. When SetPageThumbnail is - // called, if we don't know about that URL yet and we don't have - // enough Top Sites (new profile), we store it until the next - // SetNonForcedTopSites call. - TempImages temp_images_; - - // URL List of prepopulated page. - PrepopulatedPageList prepopulated_pages_; - - // Are we loaded? - bool loaded_; - - // Have the SetTopSites execution time related histograms been recorded? - // The histogram should only be recorded once for each Chrome execution. - static bool histogram_recorded_; - - ScopedObserver<HistoryService, HistoryServiceObserver> - history_service_observer_; - - DISALLOW_COPY_AND_ASSIGN(TopSitesImpl); -}; - -} // namespace history - -#endif // CHROME_BROWSER_HISTORY_TOP_SITES_IMPL_H_
diff --git a/chrome/browser/history/top_sites_impl_unittest.cc b/chrome/browser/history/top_sites_impl_unittest.cc index 5de85ce..25d36465 100644 --- a/chrome/browser/history/top_sites_impl_unittest.cc +++ b/chrome/browser/history/top_sites_impl_unittest.cc
@@ -9,7 +9,6 @@ #include "base/task/cancelable_task_tracker.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/history/top_sites_factory.h" -#include "chrome/browser/history/top_sites_impl.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/base/testing_profile.h" @@ -17,6 +16,7 @@ #include "components/history/core/browser/history_types.h" #include "components/history/core/browser/top_sites.h" #include "components/history/core/browser/top_sites_cache.h" +#include "components/history/core/browser/top_sites_impl.h" #include "components/history/core/browser/top_sites_observer.h" #include "components/history/core/test/history_unittest_base.h" #include "content/public/test/test_browser_thread.h" @@ -40,13 +40,7 @@ PrepopulatedPageList prepopulated_pages; prepopulated_pages.push_back(PrepopulatedPage(GURL(kPrepopulatedPageURL), base::string16(), -1, -1, 0)); - - scoped_refptr<TopSitesImpl> top_sites = - new TopSitesImpl(static_cast<Profile*>(context), prepopulated_pages); - top_sites->Init( - context->GetPath().Append(chrome::kTopSitesFilename), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)); - return top_sites; + return TopSitesFactory::BuildTopSites(context, prepopulated_pages); } // Used by WaitForHistory, see it for details.
diff --git a/chrome/browser/importer/external_process_importer_host.cc b/chrome/browser/importer/external_process_importer_host.cc index 4700e4b..5f8cfc9 100644 --- a/chrome/browser/importer/external_process_importer_host.cc +++ b/chrome/browser/importer/external_process_importer_host.cc
@@ -84,7 +84,7 @@ } void ExternalProcessImporterHost::NotifyImportEnded() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); firefox_lock_.reset(); if (observer_) observer_->ImportEnded();
diff --git a/chrome/browser/importer/ie_importer_browsertest_win.cc b/chrome/browser/importer/ie_importer_browsertest_win.cc index 6f469da1..828f9d1 100644 --- a/chrome/browser/importer/ie_importer_browsertest_win.cc +++ b/chrome/browser/importer/ie_importer_browsertest_win.cc
@@ -236,10 +236,10 @@ } // importer::ImporterProgressObserver: - virtual void ImportStarted() override {} - virtual void ImportItemStarted(importer::ImportItem item) override {} - virtual void ImportItemEnded(importer::ImportItem item) override {} - virtual void ImportEnded() override { + void ImportStarted() override {} + void ImportItemStarted(importer::ImportItem item) override {} + void ImportItemEnded(importer::ImportItem item) override {} + void ImportEnded() override { base::MessageLoop::current()->Quit(); if (importer_items_ & importer::FAVORITES) { EXPECT_EQ(arraysize(kIEBookmarks), bookmark_count_); @@ -256,16 +256,17 @@ // EXPECT_EQ(1, password_count_); } - virtual bool BookmarkModelIsLoaded() const { + // ProfileWriter: + bool BookmarkModelIsLoaded() const override { // Profile is ready for writing. return true; } - virtual bool TemplateURLServiceIsLoaded() const { + bool TemplateURLServiceIsLoaded() const override { return true; } - virtual void AddPasswordForm(const autofill::PasswordForm& form) { + void AddPasswordForm(const autofill::PasswordForm& form) override { // Importer should obtain this password form only. EXPECT_EQ(GURL("http://localhost:8080/security/index.htm"), form.origin); EXPECT_EQ("http://localhost:8080/", form.signon_realm); @@ -277,8 +278,8 @@ ++password_count_; } - virtual void AddHistoryPage(const history::URLRows& page, - history::VisitSource visit_source) { + void AddHistoryPage(const history::URLRows& page, + history::VisitSource visit_source) override { bool cache_item_found = false; bool history_item_found = false; // Importer should read the specified URL. @@ -301,9 +302,8 @@ EXPECT_EQ(history::SOURCE_IE_IMPORTED, visit_source); } - virtual void AddBookmarks( - const std::vector<ImportedBookmarkEntry>& bookmarks, - const base::string16& top_level_folder_name) override { + void AddBookmarks(const std::vector<ImportedBookmarkEntry>& bookmarks, + const base::string16& top_level_folder_name) override { ASSERT_LE(bookmark_count_ + bookmarks.size(), arraysize(kIEBookmarks)); // Importer should import the IE Favorites folder the same as the list, // in the same order. @@ -323,8 +323,7 @@ STLDeleteContainerPointers(template_url.begin(), template_url.end()); } - virtual void AddFavicons( - const favicon_base::FaviconUsageDataList& usage) override { + void AddFavicons(const favicon_base::FaviconUsageDataList& usage) override { // Importer should group the favicon information for each favicon URL. for (size_t i = 0; i < arraysize(kIEFaviconGroup); ++i) { GURL favicon_url(kIEFaviconGroup[i].favicon_url); @@ -385,25 +384,25 @@ } // importer::ImporterProgressObserver: - virtual void ImportStarted() override {} - virtual void ImportItemStarted(importer::ImportItem item) override {} - virtual void ImportItemEnded(importer::ImportItem item) override {} - virtual void ImportEnded() override { + void ImportStarted() override {} + void ImportItemStarted(importer::ImportItem item) override {} + void ImportItemEnded(importer::ImportItem item) override {} + void ImportEnded() override { base::MessageLoop::current()->Quit(); EXPECT_EQ(arraysize(kIESortedBookmarks), bookmark_count_); } - virtual bool BookmarkModelIsLoaded() const { return true; } - virtual bool TemplateURLServiceIsLoaded() const { return true; } + // ProfileWriter: + bool BookmarkModelIsLoaded() const override { return true; } + bool TemplateURLServiceIsLoaded() const override { return true; } - virtual void AddPasswordForm(const autofill::PasswordForm& form) {} - virtual void AddHistoryPage(const history::URLRows& page, - history::VisitSource visit_source) {} - virtual void AddKeyword(std::vector<TemplateURL*> template_url, - int default_keyword_index) {} - virtual void AddBookmarks( - const std::vector<ImportedBookmarkEntry>& bookmarks, - const base::string16& top_level_folder_name) override { + void AddPasswordForm(const autofill::PasswordForm& form) override {} + void AddHistoryPage(const history::URLRows& page, + history::VisitSource visit_source) override {} + void AddKeywords(ScopedVector<TemplateURL> template_urls, + bool unique_on_host_and_path) override {} + void AddBookmarks(const std::vector<ImportedBookmarkEntry>& bookmarks, + const base::string16& top_level_folder_name) override { ASSERT_LE(bookmark_count_ + bookmarks.size(), arraysize(kIESortedBookmarks)); for (size_t i = 0; i < bookmarks.size(); ++i) { @@ -415,7 +414,7 @@ } private: - ~MalformedFavoritesRegistryTestObserver() {} + ~MalformedFavoritesRegistryTestObserver() override {} size_t bookmark_count_; }; @@ -426,7 +425,7 @@ // import (via ExternalProcessImporterHost) which launches a utility process. class IEImporterBrowserTest : public InProcessBrowserTest { protected: - virtual void SetUp() override { + void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); // This will launch the browser test and thus needs to happen last.
diff --git a/chrome/browser/importer/in_process_importer_bridge.h b/chrome/browser/importer/in_process_importer_bridge.h index 7066d564..ce09946 100644 --- a/chrome/browser/importer/in_process_importer_bridge.h +++ b/chrome/browser/importer/in_process_importer_bridge.h
@@ -40,7 +40,7 @@ void AddHomePage(const GURL& home_page) override; #if defined(OS_WIN) - virtual void AddIE7PasswordInfo( + void AddIE7PasswordInfo( const importer::ImporterIE7PasswordInfo& password_info) override; #endif
diff --git a/chrome/browser/infobars/infobar_responder.cc b/chrome/browser/infobars/infobar_responder.cc new file mode 100644 index 0000000..cddc89b --- /dev/null +++ b/chrome/browser/infobars/infobar_responder.cc
@@ -0,0 +1,41 @@ +// 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/infobars/infobar_responder.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "chrome/browser/infobars/infobar_service.h" +#include "components/infobars/core/confirm_infobar_delegate.h" +#include "components/infobars/core/infobar.h" + +InfoBarResponder::InfoBarResponder(InfoBarService* infobar_service, + bool should_accept) + : infobar_service_(infobar_service), should_accept_(should_accept) { + infobar_service_->AddObserver(this); +} + +InfoBarResponder::~InfoBarResponder() { + // This is safe even if we were already removed as an observer in + // OnInfoBarAdded(). + infobar_service_->RemoveObserver(this); +} + +void InfoBarResponder::OnInfoBarAdded(infobars::InfoBar* infobar) { + infobar_service_->RemoveObserver(this); + ConfirmInfoBarDelegate* delegate = + infobar->delegate()->AsConfirmInfoBarDelegate(); + DCHECK(delegate); + + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&InfoBarResponder::Respond, base::Unretained(this), delegate)); +} + +void InfoBarResponder::Respond(ConfirmInfoBarDelegate* delegate) { + if (should_accept_) + delegate->Accept(); + else + delegate->Cancel(); +}
diff --git a/chrome/browser/infobars/infobar_responder.h b/chrome/browser/infobars/infobar_responder.h new file mode 100644 index 0000000..266a2be --- /dev/null +++ b/chrome/browser/infobars/infobar_responder.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 CHROME_BROWSER_INFOBARS_INFOBAR_RESPONDER_H_ +#define CHROME_BROWSER_INFOBARS_INFOBAR_RESPONDER_H_ + +#include "base/macros.h" +#include "components/infobars/core/infobar_manager.h" + +namespace infobars { +class InfoBar; +} + +class ConfirmInfoBarDelegate; +class InfoBarService; + +// Used by test code to asynchronously respond to the first infobar shown, which +// must have a ConfirmInfoBarDelegate. This can be used to ensure various +// interaction flows work correctly. +// +// The asynchronous response matches how real users will use the infobar. +class InfoBarResponder : public infobars::InfoBarManager::Observer { + public: + // If |should_accept| is true, the responder will asynchronously Accept() the + // infobar; otherwise it will Cancel() it. + InfoBarResponder(InfoBarService* infobar_service, bool should_accept); + ~InfoBarResponder() override; + + // infobars::InfoBarManager::Observer: + void OnInfoBarAdded(infobars::InfoBar* infobar) override; + + private: + void Respond(ConfirmInfoBarDelegate* delegate); + + InfoBarService* infobar_service_; + bool should_accept_; + + DISALLOW_COPY_AND_ASSIGN(InfoBarResponder); +}; + +#endif // CHROME_BROWSER_INFOBARS_INFOBAR_RESPONDER_H_
diff --git a/chrome/browser/install_verification/win/module_verification_test.h b/chrome/browser/install_verification/win/module_verification_test.h index 718212c..517ea36 100644 --- a/chrome/browser/install_verification/win/module_verification_test.h +++ b/chrome/browser/install_verification/win/module_verification_test.h
@@ -14,7 +14,7 @@ class ModuleVerificationTest : public testing::Test { public: - virtual void SetUp() override; + void SetUp() override; protected: bool GetLoadedModuleInfoSet(std::set<ModuleInfo>* loaded_module_info_set);
diff --git a/chrome/browser/interstitials/security_interstitial_page_test_utils.cc b/chrome/browser/interstitials/security_interstitial_page_test_utils.cc index 6e41b1d1..5c224c3 100644 --- a/chrome/browser/interstitials/security_interstitial_page_test_utils.cc +++ b/chrome/browser/interstitials/security_interstitial_page_test_utils.cc
@@ -21,8 +21,9 @@ namespace chrome_browser_interstitials { -bool IsInterstitialDisplayingText(content::InterstitialPage* interstitial, - const std::string& text) { +bool IsInterstitialDisplayingText( + const content::InterstitialPage* const interstitial, + const std::string& text) { // It's valid for |text| to contain "\'", but simply look for "'" instead // since this function is used for searching host names and a predefined // string.
diff --git a/chrome/browser/interstitials/security_interstitial_page_test_utils.h b/chrome/browser/interstitials/security_interstitial_page_test_utils.h index 34c613a..65a82f3 100644 --- a/chrome/browser/interstitials/security_interstitial_page_test_utils.h +++ b/chrome/browser/interstitials/security_interstitial_page_test_utils.h
@@ -20,8 +20,9 @@ namespace chrome_browser_interstitials { -bool IsInterstitialDisplayingText(content::InterstitialPage* interstitial, - const std::string& text); +bool IsInterstitialDisplayingText( + const content::InterstitialPage* const interstitial, + const std::string& text); // This class is used for testing the display of IDN names in security // interstitials.
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 34fe6b88..4948892 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -327,8 +327,6 @@ // "exclude=<host>" : Disables SPDY support for the host <host>. // "no-compress" : Disables SPDY header compression. // "no-alt-protocols : Disables alternate protocol support. -// "force-alt-protocols : Forces an alternate protocol of SPDY/3 -// on port 443. // "init-max-streams=<limit>" : Specifies the maximum number of concurrent // streams for a SPDY session, unless the // specifies a different value via SETTINGS. @@ -1184,8 +1182,8 @@ params->forced_spdy_exclusions = globals.forced_spdy_exclusions; globals.use_alternate_protocols.CopyToIfSet( ¶ms->use_alternate_protocols); - globals.alternate_protocol_probability_threshold.CopyToIfSet( - ¶ms->alternate_protocol_probability_threshold); + globals.alternative_service_probability_threshold.CopyToIfSet( + ¶ms->alternative_service_probability_threshold); globals.enable_quic.CopyToIfSet(¶ms->enable_quic); globals.enable_quic_for_proxies.CopyToIfSet(¶ms->enable_quic_for_proxies); @@ -1380,11 +1378,11 @@ globals->quic_supported_versions.set(supported_versions); } - double threshold = - GetAlternateProtocolProbabilityThreshold(command_line, quic_trial_params); + double threshold = GetAlternativeProtocolProbabilityThreshold( + command_line, quic_trial_params); if (threshold >=0 && threshold <= 1) { - globals->alternate_protocol_probability_threshold.set(threshold); - globals->http_server_properties->SetAlternateProtocolProbabilityThreshold( + globals->alternative_service_probability_threshold.set(threshold); + globals->http_server_properties->SetAlternativeServiceProbabilityThreshold( threshold); } @@ -1472,15 +1470,15 @@ } // static -double IOThread::GetAlternateProtocolProbabilityThreshold( +double IOThread::GetAlternativeProtocolProbabilityThreshold( const base::CommandLine& command_line, const VariationParameters& quic_trial_params) { double value; if (command_line.HasSwitch( - switches::kAlternateProtocolProbabilityThreshold)) { + switches::kAlternativeServiceProbabilityThreshold)) { if (base::StringToDouble( command_line.GetSwitchValueASCII( - switches::kAlternateProtocolProbabilityThreshold), + switches::kAlternativeServiceProbabilityThreshold), &value)) { return value; } @@ -1488,12 +1486,20 @@ if (command_line.HasSwitch(switches::kEnableQuic)) { return 0; } + // TODO(bnc): Remove when new parameter name rolls out and server + // configuration is changed. if (base::StringToDouble( GetVariationParam(quic_trial_params, "alternate_protocol_probability_threshold"), &value)) { return value; } + if (base::StringToDouble( + GetVariationParam(quic_trial_params, + "alternative_service_probability_threshold"), + &value)) { + return value; + } return -1; }
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index 93cfa48..4b604560 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -175,7 +175,7 @@ Optional<std::string> trusted_spdy_proxy; std::set<net::HostPortPair> forced_spdy_exclusions; Optional<bool> use_alternate_protocols; - Optional<double> alternate_protocol_probability_threshold; + Optional<double> alternative_service_probability_threshold; Optional<bool> enable_quic; Optional<bool> enable_quic_for_proxies; @@ -411,9 +411,9 @@ const base::CommandLine& command_line, const VariationParameters& quic_trial_params); - // Returns the alternate protocol probability threshold specified by + // Returns the alternative service probability threshold specified by // any flags in |command_line| or |quic_trial_params|. - static double GetAlternateProtocolProbabilityThreshold( + static double GetAlternativeProtocolProbabilityThreshold( const base::CommandLine& command_line, const VariationParameters& quic_trial_params);
diff --git a/chrome/browser/io_thread_unittest.cc b/chrome/browser/io_thread_unittest.cc index f2820d9..99023156 100644 --- a/chrome/browser/io_thread_unittest.cc +++ b/chrome/browser/io_thread_unittest.cc
@@ -193,7 +193,7 @@ EXPECT_TRUE(params.enable_quic); EXPECT_TRUE(params.enable_quic_for_proxies); EXPECT_EQ(1350u, params.quic_max_packet_length); - EXPECT_EQ(1.0, params.alternate_protocol_probability_threshold); + EXPECT_EQ(1.0, params.alternative_service_probability_threshold); EXPECT_EQ(default_params.quic_supported_versions, params.quic_supported_versions); EXPECT_EQ(net::QuicTagVector(), params.quic_connection_options); @@ -421,36 +421,45 @@ EXPECT_EQ(1048576, params.quic_socket_receive_buffer_size); } -TEST_F(IOThreadTest, - AlternateProtocolProbabilityThresholdFromFlag) { - command_line_.AppendSwitchASCII("alternate-protocol-probability-threshold", - ".5"); +TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromFlag) { + command_line_.AppendSwitchASCII("alternative-service-probability-threshold", + "0.5"); ConfigureQuicGlobals(); net::HttpNetworkSession::Params params; InitializeNetworkSessionParams(¶ms); - EXPECT_EQ(.5, params.alternate_protocol_probability_threshold); + EXPECT_EQ(.5, params.alternative_service_probability_threshold); } -TEST_F(IOThreadTest, - AlternateProtocolProbabilityThresholdFromEnableQuicFlag) { +TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromEnableQuicFlag) { command_line_.AppendSwitch("enable-quic"); ConfigureQuicGlobals(); net::HttpNetworkSession::Params params; InitializeNetworkSessionParams(¶ms); - EXPECT_EQ(0, params.alternate_protocol_probability_threshold); + EXPECT_EQ(0, params.alternative_service_probability_threshold); } -TEST_F(IOThreadTest, - AlternateProtocolProbabilityThresholdFromParams) { +// TODO(bnc): Remove when new parameter name rolls out and server configuration +// is changed. +TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromOldParams) { field_trial_group_ = "Enabled"; field_trial_params_["alternate_protocol_probability_threshold"] = ".5"; ConfigureQuicGlobals(); net::HttpNetworkSession::Params params; InitializeNetworkSessionParams(¶ms); - EXPECT_EQ(.5, params.alternate_protocol_probability_threshold); + EXPECT_EQ(.5, params.alternative_service_probability_threshold); +} + +TEST_F(IOThreadTest, AlternativeServiceProbabilityThresholdFromParams) { + field_trial_group_ = "Enabled"; + field_trial_params_["alternative_service_probability_threshold"] = ".5"; + + ConfigureQuicGlobals(); + net::HttpNetworkSession::Params params; + InitializeNetworkSessionParams(¶ms); + EXPECT_EQ(.5, params.alternative_service_probability_threshold); } } // namespace test
diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime.cc index ac9ff01f..0d80bd11 100644 --- a/chrome/browser/lifetime/application_lifetime.cc +++ b/chrome/browser/lifetime/application_lifetime.cc
@@ -82,6 +82,7 @@ #endif // !defined(OS_ANDROID) int g_keep_alive_count = 0; +bool g_disable_shutdown_for_testing = false; #if defined(OS_CHROMEOS) // Whether chrome should send stop request to a session manager. @@ -319,11 +320,20 @@ ++g_keep_alive_count; } +void CloseAllBrowsersIfNeeded() { + // If there are no browsers open and we aren't already shutting down, + // initiate a shutdown. Also skips shutdown if this is a unit test. + // (MessageLoop::current() == null or explicitly disabled). + if (chrome::GetTotalBrowserCount() == 0 && + !browser_shutdown::IsTryingToQuit() && base::MessageLoop::current() && + !g_disable_shutdown_for_testing) { + CloseAllBrowsers(); + } +} + void DecrementKeepAliveCount() { DCHECK_GT(g_keep_alive_count, 0); --g_keep_alive_count; - - DCHECK(g_browser_process); // Although we should have a browser process, if there is none, // there is nothing to do. if (!g_browser_process) return; @@ -331,14 +341,7 @@ // Allow the app to shutdown again. if (!WillKeepAlive()) { g_browser_process->ReleaseModule(); - // If there are no browsers open and we aren't already shutting down, - // initiate a shutdown. Also skips shutdown if this is a unit test - // (MessageLoop::current() == null). - if (chrome::GetTotalBrowserCount() == 0 && - !browser_shutdown::IsTryingToQuit() && - base::MessageLoop::current()) { - CloseAllBrowsers(); - } + CloseAllBrowsersIfNeeded(); } } @@ -422,4 +425,10 @@ return true; } +void DisableShutdownForTesting(bool disable_shutdown_for_testing) { + g_disable_shutdown_for_testing = disable_shutdown_for_testing; + if (!g_disable_shutdown_for_testing && !WillKeepAlive()) + CloseAllBrowsersIfNeeded(); +} + } // namespace chrome
diff --git a/chrome/browser/lifetime/application_lifetime.h b/chrome/browser/lifetime/application_lifetime.h index 9165754..3cf1854 100644 --- a/chrome/browser/lifetime/application_lifetime.h +++ b/chrome/browser/lifetime/application_lifetime.h
@@ -116,6 +116,9 @@ // last browser window is being closed. bool ShouldStartShutdown(Browser* browser); +// Disable browser shutdown for unit tests. +void DisableShutdownForTesting(bool disable_shutdown_for_testing); + } // namespace chrome #endif // CHROME_BROWSER_LIFETIME_APPLICATION_LIFETIME_H_
diff --git a/chrome/browser/local_discovery/privet_device_lister_unittest.cc b/chrome/browser/local_discovery/privet_device_lister_unittest.cc index 3f7dfa9..a165b718 100644 --- a/chrome/browser/local_discovery/privet_device_lister_unittest.cc +++ b/chrome/browser/local_discovery/privet_device_lister_unittest.cc
@@ -169,10 +169,10 @@ PrivetDeviceListerTest() : mock_client_(&mock_delegate_) { } - virtual ~PrivetDeviceListerTest() { + ~PrivetDeviceListerTest() override { } - virtual void SetUp() override { + void SetUp() override { example_attrs_.push_back("tXtvers=1"); example_attrs_.push_back("ty=My Printer"); example_attrs_.push_back("nOte=This is my Printer");
diff --git a/chrome/browser/local_discovery/privet_http_unittest.cc b/chrome/browser/local_discovery/privet_http_unittest.cc index 66bb7f6c..c77de5ea 100644 --- a/chrome/browser/local_discovery/privet_http_unittest.cc +++ b/chrome/browser/local_discovery/privet_http_unittest.cc
@@ -379,7 +379,7 @@ ~MockRegisterDelegate() { } - virtual void OnPrivetRegisterClaimToken( + void OnPrivetRegisterClaimToken( PrivetRegisterOperation* operation, const std::string& token, const GURL& url) override { @@ -390,7 +390,7 @@ const std::string& token, const GURL& url)); - virtual void OnPrivetRegisterError( + void OnPrivetRegisterError( PrivetRegisterOperation* operation, const std::string& action, PrivetRegisterOperation::FailureReason reason, @@ -405,7 +405,7 @@ PrivetRegisterOperation::FailureReason reason, int printer_http_code)); - virtual void OnPrivetRegisterDone( + void OnPrivetRegisterDone( PrivetRegisterOperation* operation, const std::string& device_id) override { OnPrivetRegisterDoneInternal(device_id); @@ -439,9 +439,9 @@ public: PrivetInfoTest() {} - virtual ~PrivetInfoTest() {} + ~PrivetInfoTest() override {} - virtual void SetUp() override { + void SetUp() override { info_operation_ = privet_client_->CreateInfoOperation( info_callback_.callback()); } @@ -485,10 +485,10 @@ public: PrivetRegisterTest() { } - virtual ~PrivetRegisterTest() { + ~PrivetRegisterTest() override { } - virtual void SetUp() override { + void SetUp() override { info_operation_ = privet_client_->CreateInfoOperation( info_callback_.callback()); register_operation_ = @@ -675,9 +675,9 @@ public: PrivetCapabilitiesTest() {} - virtual ~PrivetCapabilitiesTest() {} + ~PrivetCapabilitiesTest() override {} - virtual void SetUp() override { + void SetUp() override { capabilities_operation_ = privet_client_->CreateCapabilitiesOperation( capabilities_callback_.callback()); } @@ -785,9 +785,9 @@ public: PrivetLocalPrintTest() {} - virtual ~PrivetLocalPrintTest() {} + ~PrivetLocalPrintTest() override {} - virtual void SetUp() override { + void SetUp() override { PrivetURLFetcher::ResetTokenMapForTests(); local_print_operation_ = privet_client_->CreateLocalPrintOperation(
diff --git a/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc b/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc index 2b1daca..467e1d8 100644 --- a/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc +++ b/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc
@@ -28,19 +28,19 @@ MockPrivetURLFetcherDelegate() : raw_mode_(false) { } - virtual ~MockPrivetURLFetcherDelegate() { + ~MockPrivetURLFetcherDelegate() override { } - virtual void OnError(PrivetURLFetcher* fetcher, - PrivetURLFetcher::ErrorType error) override { + void OnError(PrivetURLFetcher* fetcher, + PrivetURLFetcher::ErrorType error) override { OnErrorInternal(error); } MOCK_METHOD1(OnErrorInternal, void(PrivetURLFetcher::ErrorType error)); - virtual void OnParsedJson(PrivetURLFetcher* fetcher, - const base::DictionaryValue& value, - bool has_error) override { + void OnParsedJson(PrivetURLFetcher* fetcher, + const base::DictionaryValue& value, + bool has_error) override { saved_value_.reset(value.DeepCopy()); OnParsedJsonInternal(has_error); }
diff --git a/chrome/browser/local_discovery/privetv3_session_unittest.cc b/chrome/browser/local_discovery/privetv3_session_unittest.cc index 3e9c1a42..8cf8e89e 100644 --- a/chrome/browser/local_discovery/privetv3_session_unittest.cc +++ b/chrome/browser/local_discovery/privetv3_session_unittest.cc
@@ -49,17 +49,17 @@ CreateInfoOperationPtr, PrivetJSONOperation*(const PrivetJSONOperation::ResultCallback&)); - virtual void RefreshPrivetToken( + void RefreshPrivetToken( const PrivetURLFetcher::TokenCallback& callback) override { FAIL(); } - virtual scoped_ptr<PrivetJSONOperation> CreateInfoOperation( + scoped_ptr<PrivetJSONOperation> CreateInfoOperation( const PrivetJSONOperation::ResultCallback& callback) override { return make_scoped_ptr(CreateInfoOperationPtr(callback)); } - virtual scoped_ptr<PrivetURLFetcher> CreateURLFetcher( + scoped_ptr<PrivetURLFetcher> CreateURLFetcher( const GURL& url, net::URLFetcher::RequestType request_type, PrivetURLFetcher::Delegate* delegate) override { @@ -78,7 +78,7 @@ : fetcher_factory_(nullptr), session_(make_scoped_ptr(new MockPrivetHTTPClient())) {} - virtual ~PrivetV3SessionTest() {} + ~PrivetV3SessionTest() override {} MOCK_METHOD2(OnInitialized, void(Result, const std::vector<PairingType>&)); MOCK_METHOD1(OnPairingStarted, void(Result)); @@ -87,7 +87,7 @@ MOCK_METHOD1(OnPostData, void(const base::DictionaryValue& data)); protected: - virtual void SetUp() override { + void SetUp() override { EXPECT_CALL(*this, OnInitialized(_, _)).Times(0); EXPECT_CALL(*this, OnPairingStarted(_)).Times(0); EXPECT_CALL(*this, OnCodeConfirmed(_)).Times(0);
diff --git a/chrome/browser/local_discovery/service_discovery_client_mdns.cc b/chrome/browser/local_discovery/service_discovery_client_mdns.cc index fbd077f9..cfaa3cf0 100644 --- a/chrome/browser/local_discovery/service_discovery_client_mdns.cc +++ b/chrome/browser/local_discovery/service_discovery_client_mdns.cc
@@ -145,15 +145,15 @@ : Proxy(client) { } - virtual ~ProxyBase() { + ~ProxyBase() override { DeleteOnMdnsThread(implementation_.release()); } - virtual bool IsValid() override { + bool IsValid() override { return !!implementation(); } - virtual void OnMdnsDestroy() override { + void OnMdnsDestroy() override { DeleteOnMdnsThread(implementation_.release()); };
diff --git a/chrome/browser/local_discovery/test_service_discovery_client.h b/chrome/browser/local_discovery/test_service_discovery_client.h index 28836d4..caf5eec 100644 --- a/chrome/browser/local_discovery/test_service_discovery_client.h +++ b/chrome/browser/local_discovery/test_service_discovery_client.h
@@ -19,13 +19,13 @@ void Start(); - virtual scoped_ptr<ServiceWatcher> CreateServiceWatcher( + scoped_ptr<ServiceWatcher> CreateServiceWatcher( const std::string& service_type, const ServiceWatcher::UpdatedCallback& callback) override; - virtual scoped_ptr<ServiceResolver> CreateServiceResolver( + scoped_ptr<ServiceResolver> CreateServiceResolver( const std::string& service_name, const ServiceResolver::ResolveCompleteCallback& callback) override; - virtual scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver( + scoped_ptr<LocalDomainResolver> CreateLocalDomainResolver( const std::string& domain, net::AddressFamily address_family, const LocalDomainResolver::IPAddressCallback& callback) override; @@ -35,7 +35,7 @@ void SimulateReceive(const uint8* packet, int size); private: - ~TestServiceDiscoveryClient(); + ~TestServiceDiscoveryClient() override; // Owned by mdns_client_impl_. net::MockMDnsSocketFactory mock_socket_factory_;
diff --git a/chrome/browser/local_discovery/wifi/credential_getter_win.h b/chrome/browser/local_discovery/wifi/credential_getter_win.h index 4b28aca4..7e4ca21 100644 --- a/chrome/browser/local_discovery/wifi/credential_getter_win.h +++ b/chrome/browser/local_discovery/wifi/credential_getter_win.h
@@ -20,16 +20,16 @@ CredentialsCallback; CredentialGetterWin(); - virtual ~CredentialGetterWin(); + ~CredentialGetterWin() override; void StartGetCredentials(const std::string& network_guid, const CredentialsCallback& callback); private: // UtilityProcessHostClient - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void OnProcessCrashed(int exit_code) override; - virtual void OnProcessLaunchFailed() override; + bool OnMessageReceived(const IPC::Message& message) override; + void OnProcessCrashed(int exit_code) override; + void OnProcessLaunchFailed() override; // IPC message handlers. void OnGotCredentials(const std::string& key_data, bool success);
diff --git a/chrome/browser/local_discovery/wifi/mock_wifi_manager.h b/chrome/browser/local_discovery/wifi/mock_wifi_manager.h index 80cecb3fd..acf8296 100644 --- a/chrome/browser/local_discovery/wifi/mock_wifi_manager.h +++ b/chrome/browser/local_discovery/wifi/mock_wifi_manager.h
@@ -16,11 +16,11 @@ class MockWifiManager : public WifiManager { public: MockWifiManager(); - ~MockWifiManager(); + ~MockWifiManager() override; MOCK_METHOD0(Start, void()); - virtual void GetSSIDList(const SSIDListCallback& callback) override; + void GetSSIDList(const SSIDListCallback& callback) override; MOCK_METHOD0(GetSSIDListInternal, void()); @@ -28,7 +28,7 @@ MOCK_METHOD0(RequestScan, void()); - virtual void ConfigureAndConnectNetwork( + void ConfigureAndConnectNetwork( const std::string& ssid, const WifiCredentials& credentials, const SuccessCallback& callback) override; @@ -38,15 +38,15 @@ void CallConfigureAndConnectNetworkCallback(bool success); - virtual void ConnectToNetworkByID(const std::string& internal_id, - const SuccessCallback& callback) override; + void ConnectToNetworkByID(const std::string& internal_id, + const SuccessCallback& callback) override; MOCK_METHOD1(ConnectToNetworkByIDInternal, void(const std::string& internal_id)); void CallConnectToNetworkByIDCallback(bool success); - virtual void RequestNetworkCredentials( + void RequestNetworkCredentials( const std::string& internal_id, const CredentialsCallback& callback) override; @@ -76,9 +76,9 @@ class MockWifiManagerFactory : public WifiManagerFactory { public: MockWifiManagerFactory(); - virtual ~MockWifiManagerFactory(); + ~MockWifiManagerFactory() override; - virtual scoped_ptr<WifiManager> CreateWifiManager() override; + scoped_ptr<WifiManager> CreateWifiManager() override; MockWifiManager* GetLastCreatedWifiManager();
diff --git a/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc b/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc index 88620d3..78d999f9 100644 --- a/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc +++ b/chrome/browser/local_discovery/wifi/wifi_manager_nonchromeos.cc
@@ -122,12 +122,12 @@ scoped_refptr<base::MessageLoopProxy> callback_runner_; - base::WeakPtrFactory<WifiServiceWrapper> weak_factory_; - #if defined(OS_WIN) scoped_refptr<CredentialGetterWin> credential_getter_; #endif // OS_WIN + base::WeakPtrFactory<WifiServiceWrapper> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(WifiServiceWrapper); };
diff --git a/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc b/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc index d06a595e..b307d07 100644 --- a/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc +++ b/chrome/browser/media/chrome_media_stream_infobar_browsertest.cc
@@ -106,7 +106,7 @@ IN_PROC_BROWSER_TEST_F(MediaStreamInfoBarTest, TestAllowingUserMedia) { content::WebContents* tab_contents = LoadTestPageInTab(); - GetUserMediaAndAccept(tab_contents); + EXPECT_TRUE(GetUserMediaAndAccept(tab_contents)); } IN_PROC_BROWSER_TEST_F(MediaStreamInfoBarTest, TestDenyingUserMedia) { @@ -135,7 +135,7 @@ content::WebContents* tab_contents = LoadTestPageInTab(); - GetUserMediaAndAccept(tab_contents); + EXPECT_TRUE(GetUserMediaAndAccept(tab_contents)); GetUserMediaAndDeny(tab_contents); // Should fail with permission denied right away with no infobar popping up. @@ -153,8 +153,8 @@ // If accept were sticky the second call would hang because it hangs if an // infobar does not pop up. - GetUserMediaAndAccept(tab_contents); - GetUserMediaAndAccept(tab_contents); + EXPECT_TRUE(GetUserMediaAndAccept(tab_contents)); + EXPECT_TRUE(GetUserMediaAndAccept(tab_contents)); } IN_PROC_BROWSER_TEST_F(MediaStreamInfoBarTest, TestDismissIsNotSticky) { @@ -198,8 +198,8 @@ // If mic blocking also blocked cameras, the second call here would hang. GetUserMediaWithSpecificConstraintsAndDeny(tab_contents, kAudioOnlyCallConstraints); - GetUserMediaWithSpecificConstraintsAndAccept(tab_contents, - kVideoOnlyCallConstraints); + EXPECT_TRUE(GetUserMediaWithSpecificConstraintsAndAccept( + tab_contents, kVideoOnlyCallConstraints)); } IN_PROC_BROWSER_TEST_F(MediaStreamInfoBarTest, @@ -209,6 +209,6 @@ // If camera blocking also blocked mics, the second call here would hang. GetUserMediaWithSpecificConstraintsAndDeny(tab_contents, kVideoOnlyCallConstraints); - GetUserMediaWithSpecificConstraintsAndAccept(tab_contents, - kAudioOnlyCallConstraints); + EXPECT_TRUE(GetUserMediaWithSpecificConstraintsAndAccept( + tab_contents, kAudioOnlyCallConstraints)); }
diff --git a/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc b/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc index 41b733e..7716245 100644 --- a/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc +++ b/chrome/browser/media/chrome_webrtc_audio_quality_browsertest.cc
@@ -602,11 +602,11 @@ // Sets up a two-way WebRTC call and records its output to |recording|, using // getUserMedia. // -// |reference_file| should have at least two seconds of silence in the +// |reference_file| should have at least five seconds of silence in the // beginning: otherwise all the reference audio will not be picked up by the // recording. Note that the reference file will start playing as soon as the // audio device is up following the getUserMedia call in the left tab. The time -// it takes to negotiate a call isn't deterministic, but two seconds should be +// it takes to negotiate a call isn't deterministic, but five seconds should be // plenty of time. Similarly, the recording time should be enough to catch the // whole reference file. If you then silence-trim the reference file and actual // file, you should end up with two time-synchronized files. @@ -658,7 +658,7 @@ ASSERT_NO_FATAL_FAILURE(SetupAndRecordAudioCall( reference_file, recording, kAudioOnlyCallConstraints, - base::TimeDelta::FromSeconds(25))); + base::TimeDelta::FromSeconds(30))); ComputeAndPrintPesqResults(reference_file, recording, "_getusermedia"); DeleteFileUnlessTestFailed(recording, false); @@ -687,10 +687,10 @@ base::FilePath recording = CreateTemporaryWaveFile(); - // Note: the sound clip is about 13 seconds: record for 20 seconds to get some + // Note: the sound clip is 21.6 seconds: record for 25 seconds to get some // safety margins on each side. AudioRecorder recorder; - ASSERT_TRUE(recorder.StartRecording(base::TimeDelta::FromSeconds(20), + ASSERT_TRUE(recorder.StartRecording(base::TimeDelta::FromSeconds(25), recording)); PlayAudioFileThroughWebAudio(left_tab); @@ -752,7 +752,7 @@ ASSERT_NO_FATAL_FAILURE(SetupAndRecordAudioCall( reference_file, recording, constraints, - base::TimeDelta::FromSeconds(25))); + base::TimeDelta::FromSeconds(30))); base::ScopedTempDir split_ref_files; ASSERT_TRUE(split_ref_files.CreateUniqueTempDir());
diff --git a/chrome/browser/media/chrome_webrtc_getmediadevices_browsertest.cc b/chrome/browser/media/chrome_webrtc_getmediadevices_browsertest.cc index b68e1c3..e7647c4 100644 --- a/chrome/browser/media/chrome_webrtc_getmediadevices_browsertest.cc +++ b/chrome/browser/media/chrome_webrtc_getmediadevices_browsertest.cc
@@ -212,7 +212,7 @@ content::WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - GetUserMediaAndAccept(tab); + EXPECT_TRUE(GetUserMediaAndAccept(tab)); std::vector<MediaDeviceInfo> devices; GetMediaDevices(tab, &devices); @@ -269,7 +269,7 @@ content::WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - GetUserMediaAndAccept(tab); + EXPECT_TRUE(GetUserMediaAndAccept(tab)); std::vector<MediaDeviceInfo> devices; GetMediaDevices(tab, &devices);
diff --git a/chrome/browser/media/chrome_webrtc_webcam_browsertest.cc b/chrome/browser/media/chrome_webrtc_webcam_browsertest.cc index 5f4a3ea..1daff03 100644 --- a/chrome/browser/media/chrome_webrtc_webcam_browsertest.cc +++ b/chrome/browser/media/chrome_webrtc_webcam_browsertest.cc
@@ -55,12 +55,13 @@ std::string GetUserMediaAndGetStreamSize(content::WebContents* tab, const std::string& constraints) { - GetUserMediaWithSpecificConstraintsAndAccept(tab, constraints); - - StartDetectingVideo(tab, "local-view"); - WaitForVideoToPlay(tab); - std::string actual_stream_size = GetStreamSize(tab, "local-view"); - CloseLastLocalStream(tab); + std::string actual_stream_size; + if (GetUserMediaWithSpecificConstraintsAndAccept(tab, constraints)) { + StartDetectingVideo(tab, "local-view"); + if (WaitForVideoToPlay(tab)) + actual_stream_size = GetStreamSize(tab, "local-view"); + CloseLastLocalStream(tab); + } return actual_stream_size; }
diff --git a/chrome/browser/media/desktop_media_list_ash.cc b/chrome/browser/media/desktop_media_list_ash.cc index d24ec21b..be37820 100644 --- a/chrome/browser/media/desktop_media_list_ash.cc +++ b/chrome/browser/media/desktop_media_list_ash.cc
@@ -149,7 +149,7 @@ std::vector<DesktopMediaListAsh::SourceDescription>* sources, aura::Window* root_window, int container_id) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); aura::Window* container = ash::Shell::GetContainer(root_window, container_id); if (!container) @@ -171,7 +171,7 @@ void DesktopMediaListAsh::EnumerateSources( std::vector<DesktopMediaListAsh::SourceDescription>* sources) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
diff --git a/chrome/browser/media/desktop_streams_registry.cc b/chrome/browser/media/desktop_streams_registry.cc index 9f6a0eb..bd21240c 100644 --- a/chrome/browser/media/desktop_streams_registry.cc +++ b/chrome/browser/media/desktop_streams_registry.cc
@@ -36,7 +36,7 @@ const GURL& origin, const content::DesktopMediaID& source, const std::string& extension_name) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::string id = GenerateRandomStreamId(); DCHECK(approved_streams_.find(id) == approved_streams_.end()); @@ -62,7 +62,7 @@ int render_frame_id, const GURL& origin, std::string* extension_name) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); StreamsMap::iterator it = approved_streams_.find(id); @@ -82,7 +82,7 @@ } void DesktopStreamsRegistry::CleanupStream(const std::string& id) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); approved_streams_.erase(id); }
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc index 4bfb4c9..851b456 100644 --- a/chrome/browser/media/media_capture_devices_dispatcher.cc +++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -182,7 +182,7 @@ bool display_notification, const base::string16& application_title, const base::string16& registered_extension_name) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); scoped_ptr<content::MediaStreamUI> ui; // Add selected desktop source to the list. @@ -271,7 +271,7 @@ // UI thread. Otherwise, it will not receive // content::NOTIFICATION_WEB_CONTENTS_DESTROYED, and that will result in // possible use after free. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); notifications_registrar_.Add( this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, content::NotificationService::AllSources()); @@ -290,30 +290,26 @@ void MediaCaptureDevicesDispatcher::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kDefaultAudioCaptureDevice, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultVideoCaptureDevice, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kDefaultAudioCaptureDevice, + std::string()); + registry->RegisterStringPref(prefs::kDefaultVideoCaptureDevice, + std::string()); } void MediaCaptureDevicesDispatcher::AddObserver(Observer* observer) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!observers_.HasObserver(observer)) observers_.AddObserver(observer); } void MediaCaptureDevicesDispatcher::RemoveObserver(Observer* observer) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); observers_.RemoveObserver(observer); } const MediaStreamDevices& MediaCaptureDevicesDispatcher::GetAudioCaptureDevices() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (is_device_enumeration_disabled_ || !test_audio_devices_.empty()) return test_audio_devices_; @@ -322,7 +318,7 @@ const MediaStreamDevices& MediaCaptureDevicesDispatcher::GetVideoCaptureDevices() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (is_device_enumeration_disabled_ || !test_video_devices_.empty()) return test_video_devices_; @@ -333,7 +329,7 @@ int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { content::WebContents* web_contents = content::Source<content::WebContents>(source).ptr(); @@ -346,7 +342,7 @@ const content::MediaStreamRequest& request, const content::MediaResponseCallback& callback, const extensions::Extension* extension) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) { @@ -376,7 +372,7 @@ content::BrowserContext* browser_context, const GURL& security_origin, content::MediaStreamType type) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE || type == content::MEDIA_DEVICE_VIDEO_CAPTURE); @@ -433,7 +429,7 @@ content::WebContents* web_contents, const GURL& security_origin, content::MediaStreamType type) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE || type == content::MEDIA_DEVICE_VIDEO_CAPTURE); @@ -481,7 +477,7 @@ const GURL& security_origin, content::MediaStreamType type, const extensions::Extension* extension) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(type == content::MEDIA_DEVICE_AUDIO_CAPTURE || type == content::MEDIA_DEVICE_VIDEO_CAPTURE); @@ -835,7 +831,7 @@ content::WebContents* web_contents, const content::MediaStreamRequest& request, const content::MediaResponseCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); RequestsQueue& queue = pending_requests_[web_contents]; queue.push_back(PendingAccessRequest(request, callback)); @@ -847,7 +843,7 @@ void MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest( content::WebContents* web_contents) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); std::map<content::WebContents*, RequestsQueue>::iterator it = pending_requests_.find(web_contents); @@ -888,7 +884,7 @@ const content::MediaStreamDevices& devices, content::MediaStreamRequestResult result, scoped_ptr<content::MediaStreamUI> ui) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); std::map<content::WebContents*, RequestsQueue>::iterator it = pending_requests_.find(web_contents); @@ -922,7 +918,7 @@ bool audio, bool video, content::MediaStreamDevices* devices) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(audio || video); PrefService* prefs = profile->GetPrefs(); @@ -951,7 +947,7 @@ const content::MediaStreamDevice* MediaCaptureDevicesDispatcher::GetRequestedAudioDevice( const std::string& requested_audio_device_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); const content::MediaStreamDevices& audio_devices = GetAudioCaptureDevices(); const content::MediaStreamDevice* const device = FindDeviceWithId(audio_devices, requested_audio_device_id); @@ -960,7 +956,7 @@ const content::MediaStreamDevice* MediaCaptureDevicesDispatcher::GetFirstAvailableAudioDevice() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); const content::MediaStreamDevices& audio_devices = GetAudioCaptureDevices(); if (audio_devices.empty()) return NULL; @@ -970,7 +966,7 @@ const content::MediaStreamDevice* MediaCaptureDevicesDispatcher::GetRequestedVideoDevice( const std::string& requested_video_device_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); const content::MediaStreamDevices& video_devices = GetVideoCaptureDevices(); const content::MediaStreamDevice* const device = FindDeviceWithId(video_devices, requested_video_device_id); @@ -979,7 +975,7 @@ const content::MediaStreamDevice* MediaCaptureDevicesDispatcher::GetFirstAvailableVideoDevice() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); const content::MediaStreamDevices& video_devices = GetVideoCaptureDevices(); if (video_devices.empty()) return NULL; @@ -1003,7 +999,7 @@ } void MediaCaptureDevicesDispatcher::OnAudioCaptureDevicesChanged() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( @@ -1012,7 +1008,7 @@ } void MediaCaptureDevicesDispatcher::OnVideoCaptureDevicesChanged() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( @@ -1027,7 +1023,7 @@ const GURL& security_origin, content::MediaStreamType stream_type, content::MediaRequestState state) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( @@ -1039,7 +1035,7 @@ void MediaCaptureDevicesDispatcher::OnCreatingAudioStream( int render_process_id, int render_frame_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind( @@ -1131,13 +1127,13 @@ void MediaCaptureDevicesDispatcher::OnCreatingAudioStreamOnUIThread( int render_process_id, int render_frame_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); FOR_EACH_OBSERVER(Observer, observers_, OnCreatingAudioStream(render_process_id, render_frame_id)); } bool MediaCaptureDevicesDispatcher::IsDesktopCaptureInProgress() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return desktop_capture_sessions_.size() > 0; }
diff --git a/chrome/browser/media/media_device_id_salt.cc b/chrome/browser/media/media_device_id_salt.cc index 27da539..8f2f970 100644 --- a/chrome/browser/media/media_device_id_salt.cc +++ b/chrome/browser/media/media_device_id_salt.cc
@@ -25,7 +25,7 @@ MediaDeviceIDSalt::MediaDeviceIDSalt(PrefService* pref_service, bool incognito) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (incognito) { incognito_salt_ = CreateSalt(); @@ -44,13 +44,13 @@ } void MediaDeviceIDSalt::ShutdownOnUIThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (incognito_salt_.empty()) media_device_id_salt_.Destroy(); } std::string MediaDeviceIDSalt::GetSalt() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (incognito_salt_.size()) return incognito_salt_; return media_device_id_salt_.GetValue(); @@ -58,10 +58,7 @@ void MediaDeviceIDSalt::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kMediaDeviceIdSalt, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kMediaDeviceIdSalt, std::string()); } void MediaDeviceIDSalt::Reset(PrefService* pref_service) {
diff --git a/chrome/browser/media/media_stream_device_permissions.cc b/chrome/browser/media/media_stream_device_permissions.cc index 6ce1c7b..3f5221d 100644 --- a/chrome/browser/media/media_stream_device_permissions.cc +++ b/chrome/browser/media/media_stream_device_permissions.cc
@@ -48,7 +48,7 @@ const GURL& security_origin, const char* policy_name, const char* whitelist_policy_name) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // If the security origin policy matches a value in the whitelist, allow it. // Otherwise, check the |policy_name| master switch for the default behavior.
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc index f6d6ecad..0f08b8c 100644 --- a/chrome/browser/media/media_stream_devices_controller.cc +++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -215,16 +215,10 @@ // static void MediaStreamDevicesController::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* prefs) { - prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true); + prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true); + prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls); + prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls); } // TODO(gbillock): rename? doesn't actually dismiss. More of a 'check profile @@ -592,7 +586,7 @@ } bool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return (profile_->GetHostContentSettingsMap()->GetDefaultContentSetting( CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, NULL) == CONTENT_SETTING_BLOCK && @@ -607,7 +601,7 @@ } void MediaStreamDevicesController::StorePermission(bool allowed) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); ContentSettingsPattern primary_pattern = ContentSettingsPattern::FromURLNoWildcard(request_.security_origin); // Check the pattern is valid or not. When the request is from a file access,
diff --git a/chrome/browser/media/protected_media_identifier_permission_context_factory.cc b/chrome/browser/media/protected_media_identifier_permission_context_factory.cc index b6992826..e6ace58f5 100644 --- a/chrome/browser/media/protected_media_identifier_permission_context_factory.cc +++ b/chrome/browser/media/protected_media_identifier_permission_context_factory.cc
@@ -48,10 +48,7 @@ ProtectedMediaIdentifierPermissionContextFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { #if defined(OS_ANDROID) - registry->RegisterBooleanPref( - prefs::kProtectedMediaIdentifierEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kProtectedMediaIdentifierEnabled, true); #endif }
diff --git a/chrome/browser/media/webrtc_browsertest_base.cc b/chrome/browser/media/webrtc_browsertest_base.cc index 52adbbc..215acf1 100644 --- a/chrome/browser/media/webrtc_browsertest_base.cc +++ b/chrome/browser/media/webrtc_browsertest_base.cc
@@ -100,13 +100,13 @@ } } -void WebRtcTestBase::GetUserMediaAndAccept( +bool WebRtcTestBase::GetUserMediaAndAccept( content::WebContents* tab_contents) const { - GetUserMediaWithSpecificConstraintsAndAccept(tab_contents, - kAudioVideoCallConstraints); + return GetUserMediaWithSpecificConstraintsAndAccept( + tab_contents, kAudioVideoCallConstraints); } -void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAccept( +bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAccept( content::WebContents* tab_contents, const std::string& constraints) const { infobars::InfoBar* infobar = @@ -116,8 +116,8 @@ // Wait for WebRTC to call the success callback. const char kOkGotStream[] = "ok-got-stream"; - EXPECT_TRUE(test::PollingWaitUntil("obtainGetUserMediaResult()", kOkGotStream, - tab_contents)); + return test::PollingWaitUntil("obtainGetUserMediaResult()", kOkGotStream, + tab_contents); } void WebRtcTestBase::GetUserMediaAndDeny(content::WebContents* tab_contents) { @@ -193,7 +193,8 @@ ui_test_utils::NavigateToURL(browser(), url); content::WebContents* new_tab = browser()->tab_strip_model()->GetActiveWebContents(); - GetUserMediaWithSpecificConstraintsAndAccept(new_tab, constraints); + EXPECT_TRUE(GetUserMediaWithSpecificConstraintsAndAccept( + new_tab, constraints)); return new_tab; } @@ -337,10 +338,12 @@ EXPECT_EQ("ok-started", ExecuteJavascript(javascript, tab_contents)); } -void WebRtcTestBase::WaitForVideoToPlay( +bool WebRtcTestBase::WaitForVideoToPlay( content::WebContents* tab_contents) const { - EXPECT_TRUE(test::PollingWaitUntil("isVideoPlaying()", "video-playing", - tab_contents)); + bool is_video_playing = test::PollingWaitUntil( + "isVideoPlaying()", "video-playing", tab_contents); + EXPECT_TRUE(is_video_playing); + return is_video_playing; } std::string WebRtcTestBase::GetStreamSize(
diff --git a/chrome/browser/media/webrtc_browsertest_base.h b/chrome/browser/media/webrtc_browsertest_base.h index 69aa4ba..9cb7ce1 100644 --- a/chrome/browser/media/webrtc_browsertest_base.h +++ b/chrome/browser/media/webrtc_browsertest_base.h
@@ -42,9 +42,11 @@ ~WebRtcTestBase() override; // These all require that the loaded page fulfills the public interface in - // chrome/test/data/webrtc/message_handling.js. - void GetUserMediaAndAccept(content::WebContents* tab_contents) const; - void GetUserMediaWithSpecificConstraintsAndAccept( + // chrome/test/data/webrtc/getusermedia.js. + // If an error is reported back from the getUserMedia call, these functions + // will return false. + bool GetUserMediaAndAccept(content::WebContents* tab_contents) const; + bool GetUserMediaWithSpecificConstraintsAndAccept( content::WebContents* tab_contents, const std::string& constraints) const; void GetUserMediaAndDeny(content::WebContents* tab_contents); @@ -106,7 +108,7 @@ // make that work). Looks at a 320x240 area of the target video tag. void StartDetectingVideo(content::WebContents* tab_contents, const std::string& video_element) const; - void WaitForVideoToPlay(content::WebContents* tab_contents) const; + bool WaitForVideoToPlay(content::WebContents* tab_contents) const; // Returns the stream size as a string on the format <width>x<height>. std::string GetStreamSize(content::WebContents* tab_contents,
diff --git a/chrome/browser/media/webrtc_browsertest_common.cc b/chrome/browser/media/webrtc_browsertest_common.cc index 34298f2..635b818 100644 --- a/chrome/browser/media/webrtc_browsertest_common.cc +++ b/chrome/browser/media/webrtc_browsertest_common.cc
@@ -6,6 +6,7 @@ #include "base/files/file_util.h" #include "base/path_service.h" +#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/test/test_timeouts.h" #include "base/time/time.h" @@ -38,6 +39,10 @@ const int kDefaultPollIntervalMsec = 250; +bool IsErrorResult(const std::string& result) { + return StartsWithASCII(result, "failed-", false); +} + base::FilePath GetReferenceFilesDir() { base::FilePath test_data_dir; PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); @@ -133,8 +138,12 @@ return false; } - if (evaluates_to == result) + if (evaluates_to == result) { return true; + } else if (IsErrorResult(result)) { + LOG(ERROR) << "|" << javascript << "| returned an error: " << result; + return false; + } // Sleep a bit here to keep this loop from spinlocking too badly. if (!SleepInJavascript(tab_contents, poll_interval_msec)) {
diff --git a/chrome/browser/media/webrtc_log_uploader_unittest.cc b/chrome/browser/media/webrtc_log_uploader_unittest.cc index 2994c8b..c3bf518 100644 --- a/chrome/browser/media/webrtc_log_uploader_unittest.cc +++ b/chrome/browser/media/webrtc_log_uploader_unittest.cc
@@ -13,6 +13,8 @@ #include "base/strings/string_split.h" #include "base/time/time.h" #include "chrome/browser/media/webrtc_log_uploader.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" const char kTestTime[] = "time"; @@ -157,6 +159,7 @@ EXPECT_EQ(dump_content, lines[i + 3]); } + content::TestBrowserThreadBundle thread_bundle_; base::FilePath test_list_path_; }; @@ -247,8 +250,13 @@ WebRtcLogUploadDoneData upload_done_data; upload_done_data.log_path = temp_dir.path().AppendASCII("log"); + scoped_ptr<Profile> profile(new TestingProfile()); + scoped_refptr<WebRtcLoggingHandlerHost> host( + new WebRtcLoggingHandlerHost(profile.get())); + upload_done_data.incoming_rtp_dump = incoming_dump; upload_done_data.outgoing_rtp_dump = outgoing_dump; + upload_done_data.host = host.get(); scoped_ptr<WebRtcLogBuffer> log(new WebRtcLogBuffer()); log->SetComplete();
diff --git a/chrome/browser/media/webrtc_log_util.cc b/chrome/browser/media/webrtc_log_util.cc index 7afd9b22..f9d3fbb 100644 --- a/chrome/browser/media/webrtc_log_util.cc +++ b/chrome/browser/media/webrtc_log_util.cc
@@ -44,7 +44,7 @@ void WebRtcLogUtil::DeleteOldAndRecentWebRtcLogFiles( const base::FilePath& log_dir, const base::Time& delete_begin_time) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); if (!base::PathExists(log_dir)) { // This will happen if no logs have been stored or uploaded. @@ -102,7 +102,7 @@ // static void WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ProfileInfoCache& profile_cache = g_browser_process->profile_manager()->GetProfileInfoCache();
diff --git a/chrome/browser/media/webrtc_logging_handler_host.cc b/chrome/browser/media/webrtc_logging_handler_host.cc index c118017..5c1476b 100644 --- a/chrome/browser/media/webrtc_logging_handler_host.cc +++ b/chrome/browser/media/webrtc_logging_handler_host.cc
@@ -105,7 +105,7 @@ const WebRtcLoggingHandlerHost::GenericDoneCallback& callback, bool success, const std::string& error_message) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); content::BrowserThread::PostTask( content::BrowserThread::UI, @@ -169,7 +169,7 @@ void WebRtcLoggingHandlerHost::SetMetaData( scoped_ptr<MetaDataMap> meta_data, const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); std::string error_message; @@ -195,7 +195,7 @@ void WebRtcLoggingHandlerHost::StartLogging( const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); if (logging_state_ != CLOSED) { @@ -210,7 +210,7 @@ void WebRtcLoggingHandlerHost::StopLogging( const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); if (logging_state_ != STARTED) { @@ -224,7 +224,7 @@ } void WebRtcLoggingHandlerHost::UploadLog(const UploadDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); if (logging_state_ != STOPPED) { @@ -246,7 +246,7 @@ void WebRtcLoggingHandlerHost::UploadStoredLog( const std::string& log_id, const UploadDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); content::BrowserThread::PostTask(content::BrowserThread::FILE, @@ -258,7 +258,7 @@ void WebRtcLoggingHandlerHost::UploadStoredLogOnFileThread( const std::string& log_id, const UploadDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); WebRtcLogUploadDoneData upload_data; upload_data.log_path = GetLogDirectoryAndEnsureExists(); @@ -270,12 +270,12 @@ } void WebRtcLoggingHandlerHost::UploadLogDone() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); logging_state_ = CLOSED; } void WebRtcLoggingHandlerHost::DiscardLog(const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); if (logging_state_ != STOPPED) { @@ -295,7 +295,7 @@ void WebRtcLoggingHandlerHost::StoreLog( const std::string& log_id, const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); if (logging_state_ != STOPPED) { @@ -321,7 +321,7 @@ void WebRtcLoggingHandlerHost::StoreLogContinue( const std::string& log_id, const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); scoped_ptr<WebRtcLogPaths> log_paths(new WebRtcLogPaths()); @@ -351,7 +351,7 @@ const GenericDoneCallback& callback, const content::RenderProcessHost::WebRtcStopRtpDumpCallback& stop_callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(stop_rtp_dump_callback_.is_null() || stop_rtp_dump_callback_.Equals(stop_callback)); @@ -376,7 +376,7 @@ void WebRtcLoggingHandlerHost::StopRtpDump( RtpDumpType type, const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); if (!rtp_dump_handler_) { @@ -400,7 +400,7 @@ size_t header_length, size_t packet_length, bool incoming) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask( BrowserThread::IO, @@ -418,7 +418,7 @@ size_t header_length, size_t packet_length, bool incoming) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // |rtp_dump_handler_| could be NULL if we are waiting for the FILE thread to // create/ensure the log directory. @@ -429,7 +429,7 @@ } void WebRtcLoggingHandlerHost::OnChannelClosing() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (logging_state_ == STARTED || logging_state_ == STOPPED) { if (upload_log_on_render_close_) { logging_started_time_ = base::Time(); @@ -453,7 +453,7 @@ } bool WebRtcLoggingHandlerHost::OnMessageReceived(const IPC::Message& message) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); bool handled = true; IPC_BEGIN_MESSAGE_MAP(WebRtcLoggingHandlerHost, message) IPC_MESSAGE_HANDLER(WebRtcLoggingMsg_AddLogMessages, OnAddLogMessages) @@ -467,14 +467,14 @@ void WebRtcLoggingHandlerHost::AddLogMessageFromBrowser( const WebRtcLoggingMessageData& message) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (logging_state_ == STARTED) LogToCircularBuffer(message.Format(logging_started_time_)); } void WebRtcLoggingHandlerHost::OnAddLogMessages( const std::vector<WebRtcLoggingMessageData>& messages) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (logging_state_ == STARTED || logging_state_ == STOPPING) { for (size_t i = 0; i < messages.size(); ++i) { LogToCircularBuffer(messages[i].Format(logging_started_time_)); @@ -483,7 +483,7 @@ } void WebRtcLoggingHandlerHost::OnLoggingStoppedInRenderer() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (logging_state_ != STOPPING) { // If an out-of-order response is received, stop_callback_ may be invalid, // and must not be invoked. @@ -499,7 +499,7 @@ void WebRtcLoggingHandlerHost::StartLoggingIfAllowed( const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( &WebRtcLoggingHandlerHost::DoStartLogging, this, g_browser_process->webrtc_log_uploader()->ApplyForStartLogging(), @@ -509,7 +509,7 @@ void WebRtcLoggingHandlerHost::DoStartLogging( bool permissions_granted, const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (logging_state_ != STARTING) { FireGenericDoneCallback(callback, false, "Logging cancelled."); return; @@ -534,7 +534,7 @@ void WebRtcLoggingHandlerHost::LogInitialInfoOnFileThread( const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); net::NetworkInterfaceList network_list; net::GetNetworkList(&network_list, @@ -548,7 +548,7 @@ void WebRtcLoggingHandlerHost::LogInitialInfoOnIOThread( const net::NetworkInterfaceList& network_list, const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (logging_state_ != STARTING) { FireGenericDoneCallback(callback, false, "Logging cancelled."); return; @@ -637,7 +637,7 @@ void WebRtcLoggingHandlerHost::NotifyLoggingStarted( const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_EQ(logging_state_, STARTING); Send(new WebRtcLoggingMsg_StartLogging()); logging_started_time_ = base::Time::Now(); @@ -646,13 +646,13 @@ } void WebRtcLoggingHandlerHost::LogToCircularBuffer(const std::string& message) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_NE(logging_state_, CLOSED); log_buffer_->Log(message); } base::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); base::FilePath log_dir_path = WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()); base::File::Error error; @@ -666,7 +666,7 @@ void WebRtcLoggingHandlerHost::TriggerUpload( const UploadDoneCallback& callback, const base::FilePath& log_directory) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (rtp_dump_handler_) { BrowserThread::PostTask( @@ -690,7 +690,7 @@ scoped_ptr<WebRtcLogPaths> log_paths, const GenericDoneCallback& done_callback, const base::FilePath& directory) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); log_paths->log_path = directory; log_buffer_->SetComplete(); @@ -706,7 +706,7 @@ void WebRtcLoggingHandlerHost::DoUploadLogAndRtpDumps( const base::FilePath& log_directory, const UploadDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); WebRtcLogUploadDoneData upload_done_data; upload_done_data.log_path = log_directory; @@ -729,7 +729,7 @@ RtpDumpType type, const GenericDoneCallback& callback, const base::FilePath& dump_dir) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // |rtp_dump_handler_| may be non-NULL if StartRtpDump is called again before // GetLogDirectoryAndEnsureExists returns on the FILE thread for a previous @@ -742,7 +742,7 @@ void WebRtcLoggingHandlerHost::DoStartRtpDump( RtpDumpType type, const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(rtp_dump_handler_); std::string error; @@ -751,7 +751,7 @@ } bool WebRtcLoggingHandlerHost::ReleaseRtpDumps(WebRtcLogPaths* log_paths) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(log_paths); if (!rtp_dump_handler_)
diff --git a/chrome/browser/media/webrtc_rtp_dump_handler.cc b/chrome/browser/media/webrtc_rtp_dump_handler.cc index 34f7637..7fb26131 100644 --- a/chrome/browser/media/webrtc_rtp_dump_handler.cc +++ b/chrome/browser/media/webrtc_rtp_dump_handler.cc
@@ -27,7 +27,7 @@ const WebRtcRtpDumpHandler::GenericDoneCallback& callback, bool success, const std::string& error_message) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); content::BrowserThread::PostTask( @@ -51,11 +51,11 @@ incoming_state_(STATE_NONE), outgoing_state_(STATE_NONE), weak_ptr_factory_(this) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); } WebRtcRtpDumpHandler::~WebRtcRtpDumpHandler() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // Reset dump writer first to stop writing. if (dump_writer_) { @@ -82,7 +82,7 @@ bool WebRtcRtpDumpHandler::StartDump(RtpDumpType type, std::string* error_message) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!dump_writer_ && g_ongoing_rtp_dumps >= kMaxOngoingRtpDumpsAllowed) { *error_message = "Max RTP dump limit reached."; @@ -140,7 +140,7 @@ void WebRtcRtpDumpHandler::StopDump(RtpDumpType type, const GenericDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // Returns an error if any type of dump specified by the caller cannot be // stopped. @@ -178,7 +178,7 @@ } bool WebRtcRtpDumpHandler::ReadyToRelease() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); return incoming_state_ != STATE_STARTED && incoming_state_ != STATE_STOPPING && @@ -186,7 +186,7 @@ } WebRtcRtpDumpHandler::ReleasedDumps WebRtcRtpDumpHandler::ReleaseDumps() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(ReadyToRelease()); base::FilePath incoming_dump, outgoing_dump; @@ -211,7 +211,7 @@ size_t header_length, size_t packet_length, bool incoming) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if ((incoming && incoming_state_ != STATE_STARTED) || (!incoming && outgoing_state_ != STATE_STARTED)) { @@ -223,7 +223,7 @@ } void WebRtcRtpDumpHandler::StopOngoingDumps(const base::Closure& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!callback.is_null()); // No ongoing dumps, return directly. @@ -270,7 +270,7 @@ void WebRtcRtpDumpHandler::SetDumpWriterForTesting( scoped_ptr<WebRtcRtpDumpWriter> writer) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); dump_writer_ = writer.Pass(); ++g_ongoing_rtp_dumps; @@ -280,7 +280,7 @@ } void WebRtcRtpDumpHandler::OnMaxDumpSizeReached() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); RtpDumpType type = (incoming_state_ == STATE_STARTED) @@ -294,7 +294,7 @@ RtpDumpType ended_type, bool incoming_success, bool outgoing_success) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (DumpTypeContainsIncoming(ended_type)) { DCHECK_EQ(STATE_STOPPING, incoming_state_);
diff --git a/chrome/browser/media_galleries/fileapi/iapps_finder_impl_win_browsertest.cc b/chrome/browser/media_galleries/fileapi/iapps_finder_impl_win_browsertest.cc index 05424710..9155830c 100644 --- a/chrome/browser/media_galleries/fileapi/iapps_finder_impl_win_browsertest.cc +++ b/chrome/browser/media_galleries/fileapi/iapps_finder_impl_win_browsertest.cc
@@ -37,9 +37,9 @@ public: ITunesFinderWinTest() : test_finder_callback_called_(false) {} - virtual ~ITunesFinderWinTest() {} + ~ITunesFinderWinTest() override {} - virtual void SetUp() override { + void SetUp() override { ASSERT_TRUE(app_data_dir_.CreateUniqueTempDir()); ASSERT_TRUE(music_dir_.CreateUniqueTempDir()); app_data_dir_override_.reset(
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc index 9584bed..79dc4f0d 100644 --- a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc +++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
@@ -54,7 +54,7 @@ const storage::AsyncFileUtil::CreateOrOpenCallback& callback, const scoped_refptr<storage::ShareableFileReference>& file_ref, base::File file) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (!file.IsValid()) { callback.Run(file.Pass(), base::Closure()); return; @@ -104,7 +104,7 @@ const base::File::Info& file_info, const base::FilePath& platform_path, const scoped_refptr<storage::ShareableFileReference>& file_ref) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (result != base::File::FILE_OK) { callback.Run(base::File(), base::Closure()); return;
diff --git a/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h b/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h index 7e5d70cf..0777c64 100644 --- a/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h +++ b/chrome/browser/media_galleries/fileapi/safe_itunes_pref_parser_win.h
@@ -43,7 +43,7 @@ }; // Private because content::UtilityProcessHostClient is ref-counted. - virtual ~SafeITunesPrefParserWin(); + ~SafeITunesPrefParserWin() override; void StartWorkOnIOThread(); @@ -52,8 +52,8 @@ void OnGotITunesDirectory(const base::FilePath& library_file); // UtilityProcessHostClient implementation. - virtual void OnProcessCrashed(int exit_code) override; - virtual bool OnMessageReceived(const IPC::Message& message) override; + void OnProcessCrashed(int exit_code) override; + bool OnMessageReceived(const IPC::Message& message) override; const std::string unsafe_xml_; const ParserCallback callback_;
diff --git a/chrome/browser/media_galleries/media_galleries_preferences.cc b/chrome/browser/media_galleries/media_galleries_preferences.cc index 57aae666..553f736 100644 --- a/chrome/browser/media_galleries/media_galleries_preferences.cc +++ b/chrome/browser/media_galleries/media_galleries_preferences.cc
@@ -1315,16 +1315,11 @@ // static void MediaGalleriesPreferences::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(prefs::kMediaGalleriesRememberedGalleries, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterUint64Pref( - prefs::kMediaGalleriesUniqueId, - kInvalidMediaGalleryPrefId + 1, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kMediaGalleriesLastScanTime, - base::Time().ToInternalValue(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kMediaGalleriesRememberedGalleries); + registry->RegisterUint64Pref(prefs::kMediaGalleriesUniqueId, + kInvalidMediaGalleryPrefId + 1); + registry->RegisterInt64Pref(prefs::kMediaGalleriesLastScanTime, + base::Time().ToInternalValue()); } bool MediaGalleriesPreferences::SetGalleryPermissionInPrefs(
diff --git a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.h b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.h index 11f3205..0be9239 100644 --- a/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.h +++ b/chrome/browser/media_galleries/win/mtp_device_delegate_impl_win.h
@@ -87,34 +87,34 @@ const base::string16& storage_object_id); // Destructed via CancelPendingTasksAndDeleteDelegate(). - virtual ~MTPDeviceDelegateImplWin(); + ~MTPDeviceDelegateImplWin() override; // MTPDeviceAsyncDelegate: - virtual void GetFileInfo(const base::FilePath& file_path, - const GetFileInfoSuccessCallback& success_callback, - const ErrorCallback& error_callback) override; - virtual void CreateDirectory( + void GetFileInfo(const base::FilePath& file_path, + const GetFileInfoSuccessCallback& success_callback, + const ErrorCallback& error_callback) override; + void CreateDirectory( const base::FilePath& directory_path, const bool exclusive, const bool recursive, const CreateDirectorySuccessCallback& success_callback, const ErrorCallback& error_callback) override; - virtual void ReadDirectory( + void ReadDirectory( const base::FilePath& root, const ReadDirectorySuccessCallback& success_callback, const ErrorCallback& error_callback) override; - virtual void CreateSnapshotFile( + void CreateSnapshotFile( const base::FilePath& device_file_path, const base::FilePath& local_path, const CreateSnapshotFileSuccessCallback& success_callback, const ErrorCallback& error_callback) override; - virtual bool IsStreaming() override; - virtual void ReadBytes(const base::FilePath& device_file_path, - const scoped_refptr<net::IOBuffer>& buf, - int64 offset, - int buf_len, - const ReadBytesSuccessCallback& success_callback, - const ErrorCallback& error_callback) override; + bool IsStreaming() override; + void ReadBytes(const base::FilePath& device_file_path, + const scoped_refptr<net::IOBuffer>& buf, + int64 offset, + int buf_len, + const ReadBytesSuccessCallback& success_callback, + const ErrorCallback& error_callback) override; bool IsReadOnly() const override; void CopyFileLocal( const base::FilePath& source_file_path, @@ -151,7 +151,7 @@ const base::FilePath& file_path, const bool recursive, const storage::WatcherManager::StatusCallback& callback) override; - virtual void CancelPendingTasksAndDeleteDelegate() override; + void CancelPendingTasksAndDeleteDelegate() override; // Ensures the device is initialized for communication by doing a // call-and-reply to a blocking pool thread. |task_info.task| runs on a
diff --git a/chrome/browser/media_router_resources.grdp b/chrome/browser/media_router_resources.grdp index 74b9c5ef..a64467b 100644 --- a/chrome/browser/media_router_resources.grdp +++ b/chrome/browser/media_router_resources.grdp
@@ -1,6 +1,10 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> + <!-- General --> <include name="IDR_MEDIA_ROUTER_DATA_JS" file="resources\media_router\media_router_data.js" type="BINDATA" /> + <include name="IDR_MEDIA_ROUTER_HTML" file="resources\media_router\media_router.html" type="BINDATA" /> + + <!-- Polymer --> <include name="IDR_CAST_MODE_PICKER_HTML" file="resources\media_router\elements\cast_mode_picker\cast_mode_picker.html" type="BINDATA" /> <include name="IDR_CAST_MODE_PICKER_CSS" file="resources\media_router\elements\cast_mode_picker\cast_mode_picker.css" type="BINDATA" /> <include name="IDR_CAST_MODE_PICKER_JS" file="resources\media_router\elements\cast_mode_picker\cast_mode_picker.js" type="BINDATA" /> @@ -13,8 +17,10 @@ <include name="IDR_MEDIA_ROUTER_SINK_HTML" file="resources\media_router\elements\media_router_sink\media_router_sink.html" type="BINDATA" /> <include name="IDR_MEDIA_ROUTER_SINK_JS" file="resources\media_router\elements\media_router_sink\media_router_sink.js" type="BINDATA" /> <include name="IDR_MEDIA_ROUTER_SINK_CSS" file="resources\media_router\elements\media_router_sink\media_router_sink.css" type="BINDATA" /> + <include name="IDR_MEDIA_ROUTER_SINK_PICKER_HTML" file="resources\media_router\elements\media_router_sink_picker\media_router_sink_picker.html" type="BINDATA" /> + <include name="IDR_MEDIA_ROUTER_SINK_PICKER_JS" file="resources\media_router\elements\media_router_sink_picker\media_router_sink_picker.js" type="BINDATA" /> - <!-- Icons. --> + <!-- Icons --> <include name="IDR_MEDIA_ROUTER_CHROMECAST_ICON" file="resources\media_router\elements\icon\chromecast-icon.png" type="BINDATA" /> <include name="IDR_MEDIA_ROUTER_CHROMECAST_2X_ICON" file="resources\media_router\elements\icon\chromecast-icon2x.png" type="BINDATA" /> <include name="IDR_CLOSE_GRAY_ICON" file="resources\media_router\elements\icon\close-gray.png" type="BINDATA" />
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc index 589c129..2b6e1e1 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.cc +++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -117,6 +117,7 @@ google_update_metrics_provider_(nullptr), #endif drive_metrics_provider_(nullptr), + start_time_(base::TimeTicks::Now()), weak_ptr_factory_(this) { DCHECK(thread_checker_.CalledOnValidThread()); RecordCommandLineMetrics(); @@ -395,19 +396,14 @@ weak_ptr_factory_.GetWeakPtr()); } -// TODO(vadimt): Consider wrapping params in a struct after the list of params -// to ReceivedProfilerData settles. crbug/456354. void ChromeMetricsServiceClient::ReceivedProfilerData( + const metrics::ProfilerDataAttributes& attributes, const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, - base::ProcessId process_id, - content::ProcessType process_type, - int profiling_phase, - base::TimeDelta phase_start, - base::TimeDelta phase_finish, const metrics::ProfilerEvents& past_events) { profiler_metrics_provider_->RecordProfilerData( - process_data_phase, process_id, process_type, profiling_phase, - phase_start, phase_finish, past_events); + process_data_phase, attributes.process_id, attributes.process_type, + attributes.profiling_phase, attributes.phase_start - start_time_, + attributes.phase_finish - start_time_, past_events); } void ChromeMetricsServiceClient::FinishedReceivingProfilerData() {
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.h b/chrome/browser/metrics/chrome_metrics_service_client.h index 7456d1d..8123823 100644 --- a/chrome/browser/metrics/chrome_metrics_service_client.h +++ b/chrome/browser/metrics/chrome_metrics_service_client.h
@@ -97,12 +97,8 @@ // TrackingSynchronizerObserver: void ReceivedProfilerData( + const metrics::ProfilerDataAttributes& attributes, const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, - base::ProcessId process_id, - content::ProcessType process_type, - int profiling_phase, - base::TimeDelta phase_start, - base::TimeDelta phase_finish, const metrics::ProfilerEvents& past_profiler_events) override; void FinishedReceivingProfilerData() override; @@ -185,6 +181,9 @@ // used. base::Callback<void(bool*)> cellular_callback_; + // Time of this object's creation. + const base::TimeTicks start_time_; + base::WeakPtrFactory<ChromeMetricsServiceClient> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ChromeMetricsServiceClient);
diff --git a/chrome/browser/metrics/chromeos_metrics_provider.cc b/chrome/browser/metrics/chromeos_metrics_provider.cc index 8ea28df..211eec39 100644 --- a/chrome/browser/metrics/chromeos_metrics_provider.cc +++ b/chrome/browser/metrics/chromeos_metrics_provider.cc
@@ -177,7 +177,7 @@ } void ChromeOSMetricsProvider::InitTaskGetHardwareClassOnFileThread() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic( "hardware_class", &hardware_class_); }
diff --git a/chrome/browser/metrics/field_trial_synchronizer.cc b/chrome/browser/metrics/field_trial_synchronizer.cc index cc9775a..43f53ad9 100644 --- a/chrome/browser/metrics/field_trial_synchronizer.cc +++ b/chrome/browser/metrics/field_trial_synchronizer.cc
@@ -38,7 +38,7 @@ const std::string& group_name) { // To iterate over RenderProcessHosts, or to send messages to the hosts, we // need to be on the UI thread. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); for (content::RenderProcessHost::iterator it( content::RenderProcessHost::AllHostsIterator());
diff --git a/chrome/browser/metrics/first_web_contents_profiler.cc b/chrome/browser/metrics/first_web_contents_profiler.cc index ae97bac..0433d25 100644 --- a/chrome/browser/metrics/first_web_contents_profiler.cc +++ b/chrome/browser/metrics/first_web_contents_profiler.cc
@@ -12,6 +12,8 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_iterator.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "components/metrics/profiler/tracking_synchronizer.h" +#include "components/metrics/proto/profiler_event.pb.h" scoped_ptr<FirstWebContentsProfiler> FirstWebContentsProfiler::CreateProfilerForFirstWebContents( @@ -51,6 +53,9 @@ elapsed); } + metrics::TrackingSynchronizer::OnProfilingPhaseCompleted( + metrics::ProfilerEventProto::EVENT_FIRST_NONEMPTY_PAINT); + if (IsFinishedCollectingMetrics()) FinishedCollectingMetrics(); }
diff --git a/chrome/browser/metrics/google_update_metrics_provider_win.h b/chrome/browser/metrics/google_update_metrics_provider_win.h index a898851..171ee794 100644 --- a/chrome/browser/metrics/google_update_metrics_provider_win.h +++ b/chrome/browser/metrics/google_update_metrics_provider_win.h
@@ -16,14 +16,14 @@ class GoogleUpdateMetricsProviderWin : public metrics::MetricsProvider { public: GoogleUpdateMetricsProviderWin(); - virtual ~GoogleUpdateMetricsProviderWin(); + ~GoogleUpdateMetricsProviderWin() override; // Fetches Google Update data asynchronously and calls |done_callback| when // done. void GetGoogleUpdateData(const base::Closure& done_callback); // metrics::MetricsProvider - virtual void ProvideSystemProfileMetrics( + void ProvideSystemProfileMetrics( metrics::SystemProfileProto* system_profile_proto) override; private:
diff --git a/chrome/browser/metrics/thread_watcher.cc b/chrome/browser/metrics/thread_watcher.cc index 27dc825..ec13045 100644 --- a/chrome/browser/metrics/thread_watcher.cc +++ b/chrome/browser/metrics/thread_watcher.cc
@@ -346,7 +346,7 @@ // static void ThreadWatcherList::StartWatchingAll( const base::CommandLine& command_line) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); uint32 unresponsive_threshold; CrashOnHangThreadMap crash_on_hang_threads; ParseCommandLine(command_line,
diff --git a/chrome/browser/metrics/thread_watcher_android.cc b/chrome/browser/metrics/thread_watcher_android.cc index 74aab6a..67b92f0 100644 --- a/chrome/browser/metrics/thread_watcher_android.cc +++ b/chrome/browser/metrics/thread_watcher_android.cc
@@ -24,7 +24,7 @@ void OnApplicationStateChange( base::android::ApplicationState application_state) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (application_state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) { g_application_has_stopped = true;
diff --git a/chrome/browser/metrics/thread_watcher_unittest.cc b/chrome/browser/metrics/thread_watcher_unittest.cc index a53cd490..4b3c457a 100644 --- a/chrome/browser/metrics/thread_watcher_unittest.cc +++ b/chrome/browser/metrics/thread_watcher_unittest.cc
@@ -312,6 +312,7 @@ } private: + base::MessageLoop message_loop_; base::Lock lock_; base::ConditionVariable setup_complete_; bool initialized_;
diff --git a/chrome/browser/metrics/variations/variations_service.cc b/chrome/browser/metrics/variations/variations_service.cc index 3a8c0091..2ad9b02 100644 --- a/chrome/browser/metrics/variations/variations_service.cc +++ b/chrome/browser/metrics/variations/variations_service.cc
@@ -321,7 +321,7 @@ } void VariationsService::StartRepeatedVariationsSeedFetch() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Initialize the Variations server URL. variations_server_url_ = @@ -419,10 +419,8 @@ user_prefs::PrefRegistrySyncable* registry) { // This preference will only be written by the policy service, which will fill // it according to a value stored in the User Policy. - registry->RegisterStringPref( - prefs::kVariationsRestrictParameter, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kVariationsRestrictParameter, + std::string()); } // static @@ -496,7 +494,7 @@ } void VariationsService::FetchVariationsSeed() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const web_resource::ResourceRequestAllowedNotifier::State state = resource_request_allowed_notifier_->GetResourceRequestsAllowedState();
diff --git a/chrome/browser/metrics/variations/variations_service_unittest.cc b/chrome/browser/metrics/variations/variations_service_unittest.cc index 6f67e9cd..90f6dbc 100644 --- a/chrome/browser/metrics/variations/variations_service_unittest.cc +++ b/chrome/browser/metrics/variations/variations_service_unittest.cc
@@ -18,6 +18,7 @@ #include "components/variations/proto/variations_seed.pb.h" #include "components/web_resource/resource_request_allowed_notifier_test_util.h" #include "content/public/test/test_browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "net/base/url_util.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" @@ -221,6 +222,7 @@ VariationsServiceTest() {} private: + content::TestBrowserThreadBundle thread_bundle_; #if defined(OS_CHROMEOS) // Not used directly. Initializes CrosSettings for testing. chromeos::ScopedTestDeviceSettingsService test_device_settings_service_; @@ -266,9 +268,6 @@ } TEST_F(VariationsServiceTest, RequestsInitiallyNotAllowed) { - base::MessageLoopForUI message_loop; - content::TestBrowserThread ui_thread(content::BrowserThread::UI, - &message_loop); TestingPrefServiceSimple prefs; VariationsService::RegisterPrefs(prefs.registry()); @@ -288,9 +287,6 @@ } TEST_F(VariationsServiceTest, RequestsInitiallyAllowed) { - base::MessageLoopForUI message_loop; - content::TestBrowserThread ui_thread(content::BrowserThread::UI, - &message_loop); TestingPrefServiceSimple prefs; VariationsService::RegisterPrefs(prefs.registry()); @@ -306,9 +302,6 @@ } TEST_F(VariationsServiceTest, SeedStoredWhenOKStatus) { - base::MessageLoop message_loop; - content::TestBrowserThread io_thread(content::BrowserThread::IO, - &message_loop); TestingPrefServiceSimple prefs; VariationsService::RegisterPrefs(prefs.registry()); @@ -339,9 +332,6 @@ net::HTTP_SERVICE_UNAVAILABLE, }; - base::MessageLoop message_loop; - content::TestBrowserThread io_thread(content::BrowserThread::IO, - &message_loop); TestingPrefServiceSimple prefs; VariationsService::RegisterPrefs(prefs.registry()); @@ -363,9 +353,6 @@ } TEST_F(VariationsServiceTest, SeedDateUpdatedOn304Status) { - base::MessageLoop message_loop; - content::TestBrowserThread io_thread(content::BrowserThread::IO, - &message_loop); TestingPrefServiceSimple prefs; VariationsService::RegisterPrefs(prefs.registry());
diff --git a/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.h b/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.h index 96be8c50..26fae655 100644 --- a/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.h +++ b/chrome/browser/metro_viewer/chrome_metro_viewer_process_host_aurawin.h
@@ -14,20 +14,19 @@ class ChromeMetroViewerProcessHost : public win8::MetroViewerProcessHost { public: ChromeMetroViewerProcessHost(); - virtual ~ChromeMetroViewerProcessHost(); + ~ChromeMetroViewerProcessHost() override; private: // win8::MetroViewerProcessHost implementation - virtual void OnChannelError() override; + void OnChannelError() override; // IPC::Listener implementation - virtual void OnChannelConnected(int32 peer_pid) override; - virtual void OnSetTargetSurface(gfx::NativeViewId target_surface, - float device_scale) override; - virtual void OnOpenURL(const base::string16& url) override; - virtual void OnHandleSearchRequest( - const base::string16& search_string) override; - virtual void OnWindowSizeChanged(uint32 width, uint32 height) override; + void OnChannelConnected(int32 peer_pid) override; + void OnSetTargetSurface(gfx::NativeViewId target_surface, + float device_scale) override; + void OnOpenURL(const base::string16& url) override; + void OnHandleSearchRequest(const base::string16& search_string) override; + void OnWindowSizeChanged(uint32 width, uint32 height) override; DISALLOW_COPY_AND_ASSIGN(ChromeMetroViewerProcessHost); };
diff --git a/chrome/browser/nacl_host/nacl_browser_delegate_impl.cc b/chrome/browser/nacl_host/nacl_browser_delegate_impl.cc index c2b18ddcc5..1ed15da 100644 --- a/chrome/browser/nacl_host/nacl_browser_delegate_impl.cc +++ b/chrome/browser/nacl_host/nacl_browser_delegate_impl.cc
@@ -4,10 +4,12 @@ #include "chrome/browser/nacl_host/nacl_browser_delegate_impl.h" +#include <vector> + #include "base/path_service.h" #include "base/strings/string_split.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h" +#include "chrome/browser/component_updater/pnacl_component_installer.h" #if defined(ENABLE_EXTENSIONS) #include "chrome/browser/extensions/extension_service.h" #endif @@ -57,11 +59,11 @@ void OnKeepaliveOnUIThread( const content::BrowserPpapiHost::OnKeepaliveInstanceData& instance_data, const base::FilePath& profile_data_directory) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Only one instance will exist for NaCl embeds, even when more than one // embed of the same plugin exists on the same page. - DCHECK(instance_data.size() == 1); + DCHECK_EQ(1U, instance_data.size()); if (instance_data.size() < 1) return;
diff --git a/chrome/browser/net/cert_logger.proto b/chrome/browser/net/cert_logger.proto index b42c5df..7ef828a5 100644 --- a/chrome/browser/net/cert_logger.proto +++ b/chrome/browser/net/cert_logger.proto
@@ -41,6 +41,24 @@ repeated string pin = 5; }; +// A wrapper proto containing an encrypted CertLoggerRequest +message EncryptedCertLoggerRequest { + // An encrypted, serialized CertLoggerRequest + required bytes encrypted_report = 1; + // The server public key version that was used to derive the shared secret. + required uint32 server_public_key_version = 2; + // The client public key that corresponds to the private key that was used + // to derive the shared secret. + required bytes client_public_key = 3; + // The encryption algorithm used to encrypt the report. + enum Algorithm { + UNKNOWN_ALGORITHM = 0; + AEAD_ECDH_AES_128_CTR_HMAC_SHA256 = 1; + } + optional Algorithm algorithm = 4 + [default = AEAD_ECDH_AES_128_CTR_HMAC_SHA256]; +}; + // The response sent back to the user. message CertLoggerResponse { enum ResponseCode { @@ -53,4 +71,3 @@ }; required ResponseCode response = 1; }; -
diff --git a/chrome/browser/net/certificate_error_reporter.cc b/chrome/browser/net/certificate_error_reporter.cc index 279209c..edff489 100644 --- a/chrome/browser/net/certificate_error_reporter.cc +++ b/chrome/browser/net/certificate_error_reporter.cc
@@ -10,6 +10,14 @@ #include "base/stl_util.h" #include "base/time/time.h" #include "chrome/browser/net/cert_logger.pb.h" + +#if defined(USE_OPENSSL) +#include "crypto/aead_openssl.h" +#endif + +#include "crypto/curve25519.h" +#include "crypto/hkdf.h" +#include "crypto/random.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/load_flags.h" #include "net/base/request_priority.h" @@ -18,15 +26,87 @@ #include "net/ssl/ssl_info.h" #include "net/url_request/url_request_context.h" +namespace { + +// Constants used for crypto +static const uint8 kServerPublicKey[] = { + 0x51, 0xcc, 0x52, 0x67, 0x42, 0x47, 0x3b, 0x10, 0xe8, 0x63, 0x18, + 0x3c, 0x61, 0xa7, 0x96, 0x76, 0x86, 0x91, 0x40, 0x71, 0x39, 0x5f, + 0x31, 0x1a, 0x39, 0x5b, 0x76, 0xb1, 0x6b, 0x3d, 0x6a, 0x2b}; +static const uint32 kServerPublicKeyVersion = 1; + +#if defined(USE_OPENSSL) + +static const char kHkdfLabel[] = "certificate report"; + +bool EncryptSerializedReport( + const uint8* server_public_key, + uint32 server_public_key_version, + const std::string& report, + chrome_browser_net::EncryptedCertLoggerRequest* encrypted_report) { + // Generate an ephemeral key pair to generate a shared secret. + uint8 public_key[crypto::curve25519::kBytes]; + uint8 private_key[crypto::curve25519::kScalarBytes]; + uint8 shared_secret[crypto::curve25519::kBytes]; + + crypto::RandBytes(private_key, sizeof(private_key)); + crypto::curve25519::ScalarBaseMult(private_key, public_key); + crypto::curve25519::ScalarMult(private_key, server_public_key, shared_secret); + + crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256); + crypto::HKDF hkdf(std::string((char*)shared_secret, sizeof(shared_secret)), + kHkdfLabel, std::string(), 0, 0, aead.KeyLength()); + + const std::string key(hkdf.subkey_secret().data(), + hkdf.subkey_secret().size()); + aead.Init(&key); + + // Use an all-zero nonce because the key is random per-message. + std::string nonce(aead.NonceLength(), 0); + + std::string ciphertext; + if (!aead.Seal(report, nonce, "", &ciphertext)) { + LOG(ERROR) << "Error sealing certificate report."; + return false; + } + + encrypted_report->set_encrypted_report(ciphertext); + encrypted_report->set_server_public_key_version(server_public_key_version); + encrypted_report->set_client_public_key( + std::string((char*)public_key, sizeof(public_key))); + encrypted_report->set_algorithm( + chrome_browser_net::EncryptedCertLoggerRequest:: + AEAD_ECDH_AES_128_CTR_HMAC_SHA256); + return true; +} +#endif + +} // namespace + namespace chrome_browser_net { CertificateErrorReporter::CertificateErrorReporter( net::URLRequestContext* request_context, const GURL& upload_url, CookiesPreference cookies_preference) + : CertificateErrorReporter(request_context, + upload_url, + cookies_preference, + kServerPublicKey, + kServerPublicKeyVersion) { +} + +CertificateErrorReporter::CertificateErrorReporter( + net::URLRequestContext* request_context, + const GURL& upload_url, + CookiesPreference cookies_preference, + const uint8 server_public_key[32], + const uint32 server_public_key_version) : request_context_(request_context), upload_url_(upload_url), - cookies_preference_(cookies_preference) { + cookies_preference_(cookies_preference), + server_public_key_(server_public_key), + server_public_key_version_(server_public_key_version) { DCHECK(!upload_url.is_empty()); } @@ -38,8 +118,6 @@ const std::string& hostname, const net::SSLInfo& ssl_info) { CertLoggerRequest request; - std::string out; - BuildReport(hostname, ssl_info, &request); switch (type) { @@ -47,9 +125,25 @@ SendCertLoggerRequest(request); break; case REPORT_TYPE_EXTENDED_REPORTING: - // TODO(estark): Encrypt the report if not sending over HTTPS. - DCHECK(upload_url_.SchemeIsCryptographic()); - SendCertLoggerRequest(request); + if (upload_url_.SchemeIsCryptographic()) { + SendCertLoggerRequest(request); + } else { + DCHECK(IsHttpUploadUrlSupported()); +#if defined(USE_OPENSSL) + EncryptedCertLoggerRequest encrypted_report; + std::string serialized_report; + request.SerializeToString(&serialized_report); + if (!EncryptSerializedReport(server_public_key_, + server_public_key_version_, + serialized_report, &encrypted_report)) { + LOG(ERROR) << "Failed to encrypt serialized report."; + return; + } + std::string serialized_encrypted_report; + encrypted_report.SerializeToString(&serialized_encrypted_report); + SendSerializedRequest(serialized_encrypted_report); +#endif + } break; default: NOTREACHED(); @@ -84,11 +178,55 @@ return request.Pass(); } +bool CertificateErrorReporter::IsHttpUploadUrlSupported() { +#if defined(USE_OPENSSL) + return true; +#else + return false; +#endif +} + +// Used only by tests. +#if defined(USE_OPENSSL) +bool CertificateErrorReporter::DecryptCertificateErrorReport( + const uint8 server_private_key[32], + const EncryptedCertLoggerRequest& encrypted_report, + CertLoggerRequest* decrypted_report) { + uint8 shared_secret[crypto::curve25519::kBytes]; + crypto::curve25519::ScalarMult( + server_private_key, (uint8*)encrypted_report.client_public_key().data(), + shared_secret); + + crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256); + crypto::HKDF hkdf(std::string((char*)shared_secret, sizeof(shared_secret)), + kHkdfLabel, std::string(), 0, 0, aead.KeyLength()); + + const std::string key(hkdf.subkey_secret().data(), + hkdf.subkey_secret().size()); + aead.Init(&key); + + // Use an all-zero nonce because the key is random per-message. + std::string nonce(aead.NonceLength(), 0); + + std::string plaintext; + if (!aead.Open(encrypted_report.encrypted_report(), nonce, "", &plaintext)) { + LOG(ERROR) << "Error opening certificate report"; + return false; + } + + return decrypted_report->ParseFromString(plaintext); +} +#endif + void CertificateErrorReporter::SendCertLoggerRequest( const CertLoggerRequest& request) { std::string serialized_request; request.SerializeToString(&serialized_request); + SendSerializedRequest(serialized_request); +} +void CertificateErrorReporter::SendSerializedRequest( + const std::string& serialized_request) { scoped_ptr<net::URLRequest> url_request = CreateURLRequest(request_context_); url_request->set_method("POST");
diff --git a/chrome/browser/net/certificate_error_reporter.h b/chrome/browser/net/certificate_error_reporter.h index 3c20ec1..cba431f 100644 --- a/chrome/browser/net/certificate_error_reporter.h +++ b/chrome/browser/net/certificate_error_reporter.h
@@ -21,6 +21,7 @@ namespace chrome_browser_net { class CertLoggerRequest; +class EncryptedCertLoggerRequest; // Provides functionality for sending reports about invalid SSL // certificate chains to a report collection server. @@ -48,6 +49,13 @@ const GURL& upload_url, CookiesPreference cookies_preference); + // Allows tests to use a server public key with known private key. + CertificateErrorReporter(net::URLRequestContext* request_context, + const GURL& upload_url, + CookiesPreference cookies_preference, + const uint8 server_public_key[32], + const uint32 server_public_key_version); + ~CertificateErrorReporter() override; // Construct, serialize, and send a certificate report to the report @@ -58,6 +66,11 @@ // responsible for enforcing any preconditions (such as obtaining user // opt-in, only sending reports for certain hostnames, checking for // incognito mode, etc.). + // + // On some platforms (but not all), CertificateErrorReporter can use + // an HTTP endpoint to send encrypted extended reporting reports. On + // unsupported platforms, callers must send extended reporting reports + // over SSL. virtual void SendReport(ReportType type, const std::string& hostname, const net::SSLInfo& ssl_info); @@ -66,6 +79,16 @@ void OnResponseStarted(net::URLRequest* request) override; void OnReadCompleted(net::URLRequest* request, int bytes_read) override; + // Callers can use this method to determine if sending reports over + // HTTP is supported. + static bool IsHttpUploadUrlSupported(); + + // Used by tests. + static bool DecryptCertificateErrorReport( + const uint8 server_private_key[32], + const EncryptedCertLoggerRequest& encrypted_report, + CertLoggerRequest* decrypted_report); + private: // Create a URLRequest with which to send a certificate report to the // server. @@ -76,6 +99,8 @@ // collection server. void SendCertLoggerRequest(const CertLoggerRequest& request); + void SendSerializedRequest(const std::string& serialized_request); + // Populate the CertLoggerRequest for a report. static void BuildReport(const std::string& hostname, const net::SSLInfo& ssl_info, @@ -92,6 +117,9 @@ CookiesPreference cookies_preference_; + const uint8* server_public_key_; + const uint32 server_public_key_version_; + DISALLOW_COPY_AND_ASSIGN(CertificateErrorReporter); };
diff --git a/chrome/browser/net/certificate_error_reporter_unittest.cc b/chrome/browser/net/certificate_error_reporter_unittest.cc index cc6fee79..f9054cd 100644 --- a/chrome/browser/net/certificate_error_reporter_unittest.cc +++ b/chrome/browser/net/certificate_error_reporter_unittest.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/net/cert_logger.pb.h" #include "chrome/common/chrome_paths.h" #include "content/public/browser/browser_thread.h" +#include "crypto/curve25519.h" #include "net/base/load_flags.h" #include "net/base/network_delegate_impl.h" #include "net/base/test_data_directory.h" @@ -47,6 +48,7 @@ const char kSecondRequestHostname[] = "test2.mail.google.com"; const char kDummyFailureLog[] = "dummy failure log"; const char kTestCertFilename[] = "test_mail_google_com.pem"; +const uint32 kServerPublicKeyVersion = 1; SSLInfo GetTestSSLInfo() { SSLInfo info; @@ -83,7 +85,9 @@ // |GetTestSSLInfo()|). The hostname sent in the report will be erased // from |expect_hostnames|. void CheckUploadData(URLRequest* request, - std::set<std::string>* expect_hostnames) { + std::set<std::string>* expect_hostnames, + bool encrypted, + const uint8* server_private_key) { const net::UploadDataStream* upload = request->get_upload(); ASSERT_TRUE(upload); ASSERT_TRUE(upload->GetElementReaders()); @@ -93,9 +97,27 @@ (*upload->GetElementReaders())[0]->AsBytesReader(); ASSERT_TRUE(reader); std::string upload_data(reader->bytes(), reader->length()); - chrome_browser_net::CertLoggerRequest uploaded_request; - uploaded_request.ParseFromString(upload_data); + chrome_browser_net::CertLoggerRequest uploaded_request; +#if defined(USE_OPENSSL) + if (encrypted) { + chrome_browser_net::EncryptedCertLoggerRequest encrypted_request; + encrypted_request.ParseFromString(upload_data); + EXPECT_EQ(kServerPublicKeyVersion, + encrypted_request.server_public_key_version()); + EXPECT_EQ(chrome_browser_net::EncryptedCertLoggerRequest:: + AEAD_ECDH_AES_128_CTR_HMAC_SHA256, + encrypted_request.algorithm()); + ASSERT_TRUE( + chrome_browser_net::CertificateErrorReporter:: + DecryptCertificateErrorReport(server_private_key, encrypted_request, + &uploaded_request)); + } else { + ASSERT_TRUE(uploaded_request.ParseFromString(upload_data)); + } +#else + ASSERT_TRUE(uploaded_request.ParseFromString(upload_data)); +#endif EXPECT_EQ(1u, expect_hostnames->count(uploaded_request.hostname())); expect_hostnames->erase(uploaded_request.hostname()); @@ -116,7 +138,11 @@ : url_request_destroyed_callback_(base::Bind(&base::DoNothing)), all_url_requests_destroyed_callback_(base::Bind(&base::DoNothing)), num_requests_(0), - expect_cookies_(false) {} + expect_cookies_(false), + expect_request_encrypted_(false) { + memset(server_private_key_, 1, sizeof(server_private_key_)); + crypto::curve25519::ScalarBaseMult(server_private_key_, server_public_key_); + } ~TestCertificateErrorReporterNetworkDelegate() override {} @@ -145,6 +171,10 @@ expect_cookies_ = expect_cookies; } + void set_expect_request_encrypted(bool expect_request_encrypted) { + expect_request_encrypted_ = expect_request_encrypted; + } + // NetworkDelegateImpl implementation int OnBeforeURLRequest(URLRequest* request, const CompletionCallback& callback, @@ -162,7 +192,8 @@ } std::string uploaded_request_hostname; - CheckUploadData(request, &expect_hostnames_); + CheckUploadData(request, &expect_hostnames_, expect_request_encrypted_, + server_private_key_); expect_hostnames_.erase(uploaded_request_hostname); return net::OK; } @@ -173,6 +204,8 @@ all_url_requests_destroyed_callback_.Run(); } + const uint8* server_public_key() { return server_public_key_; } + private: base::Closure url_request_destroyed_callback_; base::Closure all_url_requests_destroyed_callback_; @@ -180,6 +213,10 @@ GURL expect_url_; std::set<std::string> expect_hostnames_; bool expect_cookies_; + bool expect_request_encrypted_; + + uint8 server_public_key_[32]; + uint8 server_private_key_[32]; DISALLOW_COPY_AND_ASSIGN(TestCertificateErrorReporterNetworkDelegate); }; @@ -237,11 +274,24 @@ } TEST_F(CertificateErrorReporterTest, ExtendedReportingSendReportSendsRequest) { - GURL url = net::URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1); - CertificateErrorReporter reporter( - context(), url, CertificateErrorReporter::DO_NOT_SEND_COOKIES); - SendReport(&reporter, network_delegate(), kHostname, url, 0, + // Data should not be encrypted when sent to an HTTPS URL. + GURL https_url = net::URLRequestMockDataJob::GetMockHttpsUrl("dummy data", 1); + CertificateErrorReporter https_reporter( + context(), https_url, CertificateErrorReporter::DO_NOT_SEND_COOKIES); + network_delegate()->set_expect_request_encrypted(false); + SendReport(&https_reporter, network_delegate(), kHostname, https_url, 0, CertificateErrorReporter::REPORT_TYPE_EXTENDED_REPORTING); + + // Data should be encrypted when sent to an HTTP URL. + if (CertificateErrorReporter::IsHttpUploadUrlSupported()) { + GURL http_url = net::URLRequestMockDataJob::GetMockHttpUrl("dummy data", 1); + CertificateErrorReporter http_reporter( + context(), http_url, CertificateErrorReporter::DO_NOT_SEND_COOKIES, + network_delegate()->server_public_key(), kServerPublicKeyVersion); + network_delegate()->set_expect_request_encrypted(true); + SendReport(&http_reporter, network_delegate(), kHostname, http_url, 1, + CertificateErrorReporter::REPORT_TYPE_EXTENDED_REPORTING); + } } TEST_F(CertificateErrorReporterTest, SendMultipleReportsSequentially) {
diff --git a/chrome/browser/net/chrome_net_log.cc b/chrome/browser/net/chrome_net_log.cc index 674ee64..316d581 100644 --- a/chrome/browser/net/chrome_net_log.cc +++ b/chrome/browser/net/chrome_net_log.cc
@@ -83,14 +83,14 @@ << " for net logging"; } else { scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants()); - net_log_logger_.reset(new net::WriteToFileNetLogObserver()); + write_to_file_observer_.reset(new net::WriteToFileNetLogObserver()); net::NetLogCaptureMode capture_mode = GetCaptureModeFromCommandLine(command_line); - net_log_logger_->set_capture_mode(capture_mode); + write_to_file_observer_->set_capture_mode(capture_mode); - net_log_logger_->StartObserving(this, file.Pass(), constants.get(), - nullptr); + write_to_file_observer_->StartObserving(this, file.Pass(), + constants.get(), nullptr); } } @@ -101,8 +101,8 @@ ChromeNetLog::~ChromeNetLog() { net_log_temp_file_.reset(); // Remove the observers we own before we're destroyed. - if (net_log_logger_) - net_log_logger_->StopObserving(nullptr); + if (write_to_file_observer_) + write_to_file_observer_->StopObserving(nullptr); if (trace_net_log_observer_) trace_net_log_observer_->StopWatchForTraceStart(); }
diff --git a/chrome/browser/net/chrome_net_log.h b/chrome/browser/net/chrome_net_log.h index ad4c4b05..7c4b76e 100644 --- a/chrome/browser/net/chrome_net_log.h +++ b/chrome/browser/net/chrome_net_log.h
@@ -30,7 +30,7 @@ } private: - scoped_ptr<net::WriteToFileNetLogObserver> net_log_logger_; + scoped_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_; scoped_ptr<NetLogTempFile> net_log_temp_file_; scoped_ptr<net::TraceNetLogObserver> trace_net_log_observer_;
diff --git a/chrome/browser/net/dns_probe_service_unittest.cc b/chrome/browser/net/dns_probe_service_unittest.cc index 5e03b053..1579f47f 100644 --- a/chrome/browser/net/dns_probe_service_unittest.cc +++ b/chrome/browser/net/dns_probe_service_unittest.cc
@@ -74,10 +74,10 @@ callback_result_ = result; } + TestBrowserThreadBundle bundle_; DnsProbeService service_; bool callback_called_; DnsProbeStatus callback_result_; - TestBrowserThreadBundle bundle_; }; TEST_F(DnsProbeServiceTest, Probe_OK_OK) {
diff --git a/chrome/browser/net/http_server_properties_manager_factory.cc b/chrome/browser/net/http_server_properties_manager_factory.cc index 72acd43..ecd09e18 100644 --- a/chrome/browser/net/http_server_properties_manager_factory.cc +++ b/chrome/browser/net/http_server_properties_manager_factory.cc
@@ -24,9 +24,7 @@ /* static */ void HttpServerPropertiesManagerFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kHttpServerProperties, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kHttpServerProperties); } } // namespace chrome_browser_net
diff --git a/chrome/browser/net/net_log_temp_file.cc b/chrome/browser/net/net_log_temp_file.cc index 99f29aa..35a170f 100644 --- a/chrome/browser/net/net_log_temp_file.cc +++ b/chrome/browser/net/net_log_temp_file.cc
@@ -22,8 +22,8 @@ } NetLogTempFile::~NetLogTempFile() { - if (net_log_logger_) - net_log_logger_->StopObserving(nullptr); + if (write_to_file_observer_) + write_to_file_observer_->StopObserving(nullptr); } void NetLogTempFile::ProcessCommand(Command command) { @@ -145,10 +145,10 @@ state_ = STATE_LOGGING; scoped_ptr<base::Value> constants(NetInternalsUI::GetConstants()); - net_log_logger_.reset(new net::WriteToFileNetLogObserver()); - net_log_logger_->set_capture_mode(GetCaptureModeForLogType(log_type)); - net_log_logger_->StartObserving(chrome_net_log_, file.Pass(), constants.get(), - nullptr); + write_to_file_observer_.reset(new net::WriteToFileNetLogObserver()); + write_to_file_observer_->set_capture_mode(GetCaptureModeForLogType(log_type)); + write_to_file_observer_->StartObserving(chrome_net_log_, file.Pass(), + constants.get(), nullptr); } void NetLogTempFile::StopNetLog() { @@ -156,8 +156,8 @@ if (state_ != STATE_LOGGING) return; - net_log_logger_->StopObserving(nullptr); - net_log_logger_.reset(); + write_to_file_observer_->StopObserving(nullptr); + write_to_file_observer_.reset(); state_ = STATE_NOT_LOGGING; }
diff --git a/chrome/browser/net/net_log_temp_file.h b/chrome/browser/net/net_log_temp_file.h index 2b96276..0ea28ab 100644 --- a/chrome/browser/net/net_log_temp_file.h +++ b/chrome/browser/net/net_log_temp_file.h
@@ -151,9 +151,9 @@ base::FilePath log_path_; // base::FilePath to the temporary file. - // |net_log_logger_| watches the NetLog event stream, and sends all entries to - // the file created in StartNetLog(). - scoped_ptr<net::WriteToFileNetLogObserver> net_log_logger_; + // |write_to_file_observer_| watches the NetLog event stream, and + // sends all entries to the file created in StartNetLog(). + scoped_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_; // The |chrome_net_log_| is owned by the browser process, cached here to avoid // using global (g_browser_process).
diff --git a/chrome/browser/net/net_pref_observer.cc b/chrome/browser/net/net_pref_observer.cc index 8046e4de..8027bdb 100644 --- a/chrome/browser/net/net_pref_observer.cc +++ b/chrome/browser/net/net_pref_observer.cc
@@ -43,8 +43,5 @@ prefs::kNetworkPredictionEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDisableSpdy, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kDisableSpdy, false); }
diff --git a/chrome/browser/net/predictor.cc b/chrome/browser/net/predictor.cc index b135b2fd..539bf89ba 100644 --- a/chrome/browser/net/predictor.cc +++ b/chrome/browser/net/predictor.cc
@@ -176,10 +176,8 @@ void Predictor::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(prefs::kDnsPrefetchingStartupList, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kDnsPrefetchingHostReferralList, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kDnsPrefetchingStartupList); + registry->RegisterListPref(prefs::kDnsPrefetchingHostReferralList); } // --------------------- Start UI methods. ------------------------------------
diff --git a/chrome/browser/net/pref_proxy_config_tracker_impl.cc b/chrome/browser/net/pref_proxy_config_tracker_impl.cc index 3e969c8..61ae371f 100644 --- a/chrome/browser/net/pref_proxy_config_tracker_impl.cc +++ b/chrome/browser/net/pref_proxy_config_tracker_impl.cc
@@ -212,10 +212,7 @@ user_prefs::PrefRegistrySyncable* pref_service) { base::DictionaryValue* default_settings = ProxyConfigDictionary::CreateSystem(); - pref_service->RegisterDictionaryPref( - prefs::kProxy, - default_settings, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + pref_service->RegisterDictionaryPref(prefs::kProxy, default_settings); } // static
diff --git a/chrome/browser/net/quota_policy_channel_id_store_unittest.cc b/chrome/browser/net/quota_policy_channel_id_store_unittest.cc index f82f6e47..1f1718b0 100644 --- a/chrome/browser/net/quota_policy_channel_id_store_unittest.cc +++ b/chrome/browser/net/quota_policy_channel_id_store_unittest.cc
@@ -140,7 +140,7 @@ ASSERT_EQ(3, foo_channel_id->creation_time().ToInternalValue()); ASSERT_EQ(4, foo_channel_id->expiration_time().ToInternalValue()); - // Now delete the cert and check persistence again. + // Now delete the channel ID and check persistence again. store_->DeleteChannelID(*channel_ids[0]); store_->DeleteChannelID(*channel_ids[1]); store_ = NULL; @@ -152,7 +152,7 @@ base::MessageLoopProxy::current(), NULL); - // Reload and check if the cert has been removed. + // Reload and check if the channel ID has been removed. Load(&channel_ids); ASSERT_EQ(0U, channel_ids.size()); } @@ -160,7 +160,7 @@ // Test if data is stored as expected in the QuotaPolicy database. TEST_F(QuotaPolicyChannelIDStoreTest, TestPolicy) { store_->AddChannelID( - net::DefaultChannelIDStore::ChannelID("foo.com", + net::DefaultChannelIDStore::ChannelID("nonpersistent.com", base::Time::FromInternalValue(3), base::Time::FromInternalValue(4), "c", @@ -173,12 +173,12 @@ store_ = NULL; // Make sure we wait until the destructor has run. base::RunLoop().RunUntilIdle(); - // Specify storage policy that makes "foo.com" session only. + // Specify storage policy that makes "nonpersistent.com" session only. scoped_refptr<content::MockSpecialStoragePolicy> storage_policy = new content::MockSpecialStoragePolicy(); storage_policy->AddSessionOnly( - net::cookie_util::CookieOriginToURL("foo.com", true)); - // Reload store, it should still have both channel ids. + net::cookie_util::CookieOriginToURL("nonpersistent.com", true)); + // Reload store, it should still have both channel IDs. store_ = new QuotaPolicyChannelIDStore( temp_dir_.path().Append(kTestChannelIDFilename), base::MessageLoopProxy::current(), @@ -186,7 +186,20 @@ Load(&channel_ids); ASSERT_EQ(2U, channel_ids.size()); - // Now close the store, and "foo.com" should be deleted according to policy. + // Add another two channel IDs before closing the store. Because additions are + // delayed and committed to disk in batches, these will not be committed until + // the store is destroyed, which is after the policy is applied. The pending + // operation pruning logic should prevent the "nonpersistent.com" ID from + // being committed to disk. + store_->AddChannelID(net::DefaultChannelIDStore::ChannelID( + "nonpersistent.com", base::Time::FromInternalValue(5), + base::Time::FromInternalValue(6), "e", "f")); + store_->AddChannelID(net::DefaultChannelIDStore::ChannelID( + "persistent.com", base::Time::FromInternalValue(7), + base::Time::FromInternalValue(8), "g", "h")); + + // Now close the store, and the nonpersistent.com channel IDs should be + // deleted according to policy. store_ = NULL; // Make sure we wait until the destructor has run. base::RunLoop().RunUntilIdle(); @@ -196,8 +209,10 @@ base::MessageLoopProxy::current(), NULL); - // Reload and check that the "foo.com" cert has been removed. + // Reload and check that the nonpersistent.com channel IDs have been removed. Load(&channel_ids); - ASSERT_EQ(1U, channel_ids.size()); - ASSERT_EQ("google.com", channel_ids[0]->server_identifier()); + ASSERT_EQ(2U, channel_ids.size()); + for (const auto& id : channel_ids) { + ASSERT_NE("nonpersistent.com", id->server_identifier()); + } }
diff --git a/chrome/browser/net/spdyproxy/OWNERS b/chrome/browser/net/spdyproxy/OWNERS index ab34b0e..2a2dace 100644 --- a/chrome/browser/net/spdyproxy/OWNERS +++ b/chrome/browser/net/spdyproxy/OWNERS
@@ -1,4 +1,3 @@ bengr@chromium.org -marq@chromium.org sclittle@chromium.org jeremyim@chromium.org
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc index 319969e9..c70e581 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc
@@ -4,10 +4,12 @@ #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.h" +#include "base/prefs/pref_service.h" #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h" #include "chrome/common/chrome_content_client.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" #if defined(OS_ANDROID) #include "base/android/build_info.h" @@ -49,12 +51,16 @@ } #endif + bool enabled = prefs->GetBoolean( + data_reduction_proxy::prefs::kDataReductionProxyEnabled) || + data_reduction_proxy::DataReductionProxyParams:: + ShouldForceEnableDataReductionProxy(); scoped_ptr<data_reduction_proxy::DataReductionProxyIOData> data_reduction_proxy_io_data( new data_reduction_proxy::DataReductionProxyIOData( DataReductionProxyChromeSettings::GetClient(), flags, net_log, - io_task_runner, ui_task_runner, enable_quic, GetUserAgent())); - data_reduction_proxy_io_data->InitOnUIThread(prefs); + io_task_runner, ui_task_runner, enabled, enable_quic, + GetUserAgent())); #if defined(ENABLE_DATA_REDUCTION_PROXY_DEBUGGING) scoped_ptr<data_reduction_proxy::ContentDataReductionProxyDebugUIService>
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc index 9d0d213..c9de4084 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_unittest.cc
@@ -48,6 +48,7 @@ registry->RegisterDictionaryPref(prefs::kProxy); } + base::MessageLoopForIO message_loop_; scoped_ptr<DataReductionProxyChromeSettings> drp_chrome_settings_; scoped_ptr<base::DictionaryValue> dict_; scoped_ptr<data_reduction_proxy::DataReductionProxyTestContext> test_context_;
diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc index 7c91e9d4..87ef6798 100644 --- a/chrome/browser/notifications/desktop_notification_service.cc +++ b/chrome/browser/notifications/desktop_notification_service.cc
@@ -45,12 +45,8 @@ // static void DesktopNotificationService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref( - prefs::kMessageCenterDisabledExtensionIds, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref( - prefs::kMessageCenterDisabledSystemComponentIds, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kMessageCenterDisabledExtensionIds); + registry->RegisterListPref(prefs::kMessageCenterDisabledSystemComponentIds); } DesktopNotificationService::DesktopNotificationService(Profile* profile)
diff --git a/chrome/browser/notifications/extension_welcome_notification.cc b/chrome/browser/notifications/extension_welcome_notification.cc index 335ebb8..5cb62ca 100644 --- a/chrome/browser/notifications/extension_welcome_notification.cc +++ b/chrome/browser/notifications/extension_welcome_notification.cc
@@ -218,15 +218,10 @@ prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissed, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissedLocal, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs->RegisterBooleanPref(prefs::kWelcomeNotificationDismissedLocal, false); prefs->RegisterBooleanPref(prefs::kWelcomeNotificationPreviouslyPoppedUp, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->RegisterInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + false); + prefs->RegisterInt64Pref(prefs::kWelcomeNotificationExpirationTimestamp, 0); } message_center::MessageCenter*
diff --git a/chrome/browser/notifications/extension_welcome_notification_unittest.cc b/chrome/browser/notifications/extension_welcome_notification_unittest.cc index 8881262..43d9d88 100644 --- a/chrome/browser/notifications/extension_welcome_notification_unittest.cc +++ b/chrome/browser/notifications/extension_welcome_notification_unittest.cc
@@ -14,6 +14,7 @@ #include "base/thread_task_runner_handle.h" #include "chrome/browser/notifications/notification.h" #include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_pref_service_syncable.h" #include "chrome/test/base/testing_profile.h" #include "components/pref_registry/pref_registry_syncable.h" @@ -142,6 +143,7 @@ delegate_ = NULL; welcome_notification_.reset(); profile_.reset(); + TestingBrowserProcess::DeleteInstance(); thread_task_runner_handle_.reset(); task_runner_ = NULL; }
diff --git a/chrome/browser/notifications/message_center_notification_manager.cc b/chrome/browser/notifications/message_center_notification_manager.cc index 5e7802d4..4c755f0 100644 --- a/chrome/browser/notifications/message_center_notification_manager.cc +++ b/chrome/browser/notifications/message_center_notification_manager.cc
@@ -59,12 +59,16 @@ #if defined(OS_WIN) first_run_idle_timeout_( base::TimeDelta::FromSeconds(kFirstRunIdleDelaySeconds)), - weak_factory_(this), #endif settings_provider_(settings_provider.Pass()), system_observer_(this), stats_collector_(message_center), - google_now_stats_collector_(message_center) { + google_now_stats_collector_(message_center) +#if defined(OS_WIN) + , + weak_factory_(this) +#endif +{ #if defined(OS_WIN) first_run_pref_.Init(prefs::kMessageCenterShowedFirstRunBalloon, local_state); #endif
diff --git a/chrome/browser/notifications/message_center_notification_manager.h b/chrome/browser/notifications/message_center_notification_manager.h index 2806ef50..986f9cc1 100644 --- a/chrome/browser/notifications/message_center_notification_manager.h +++ b/chrome/browser/notifications/message_center_notification_manager.h
@@ -138,9 +138,6 @@ // The first-run balloon will be shown |first_run_idle_timeout_| after all // popups go away and the user has notifications in the message center. base::TimeDelta first_run_idle_timeout_; - - // Provides weak pointers for the purpose of the first run timer. - base::WeakPtrFactory<MessageCenterNotificationManager> weak_factory_; #endif scoped_ptr<message_center::NotifierSettingsProvider> settings_provider_; @@ -156,6 +153,11 @@ // Keeps track of notifications specific to Google Now for UMA purposes. GoogleNowNotificationStatsCollector google_now_stats_collector_; +#if defined(OS_WIN) + // Provides weak pointers for the purpose of the first run timer. + base::WeakPtrFactory<MessageCenterNotificationManager> weak_factory_; +#endif + DISALLOW_COPY_AND_ASSIGN(MessageCenterNotificationManager); };
diff --git a/chrome/browser/notifications/platform_notification_service_browsertest.cc b/chrome/browser/notifications/platform_notification_service_browsertest.cc index 0cf8fa1..335e8388 100644 --- a/chrome/browser/notifications/platform_notification_service_browsertest.cc +++ b/chrome/browser/notifications/platform_notification_service_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/path_service.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/infobars/infobar_responder.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/notifications/desktop_notification_profile_util.h" #include "chrome/browser/notifications/desktop_notification_service.h" @@ -19,71 +20,12 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" -#include "components/infobars/core/confirm_infobar_delegate.h" -#include "components/infobars/core/infobar.h" -#include "components/infobars/core/infobar_manager.h" #include "content/public/test/browser_test_utils.h" #include "net/base/filename_util.h" #include "net/test/spawned_test_server/spawned_test_server.h" // ----------------------------------------------------------------------------- -// Accept or rejects the first shown confirm infobar. The infobar will be -// responsed to asynchronously, to imitate the behavior of a user. -// TODO(peter): Generalize this class, as it's commonly useful. -class InfoBarResponder : public infobars::InfoBarManager::Observer { - public: - InfoBarResponder(Browser* browser, bool accept); - ~InfoBarResponder() override; - - // infobars::InfoBarManager::Observer overrides. - void OnInfoBarAdded(infobars::InfoBar* infobar) override; - - private: - void Respond(ConfirmInfoBarDelegate* delegate); - - InfoBarService* infobar_service_; - bool accept_; - bool has_observed_; -}; - -InfoBarResponder::InfoBarResponder(Browser* browser, bool accept) - : infobar_service_(InfoBarService::FromWebContents( - browser->tab_strip_model()->GetActiveWebContents())), - accept_(accept), - has_observed_(false) { - infobar_service_->AddObserver(this); -} - -InfoBarResponder::~InfoBarResponder() { - infobar_service_->RemoveObserver(this); -} - -void InfoBarResponder::OnInfoBarAdded(infobars::InfoBar* infobar) { - if (has_observed_) - return; - - has_observed_ = true; - ConfirmInfoBarDelegate* delegate = - infobar->delegate()->AsConfirmInfoBarDelegate(); - DCHECK(delegate); - - // Respond to the infobar asynchronously, like a person. - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind( - &InfoBarResponder::Respond, base::Unretained(this), delegate)); -} - -void InfoBarResponder::Respond(ConfirmInfoBarDelegate* delegate) { - if (accept_) - delegate->Accept(); - else - delegate->Cancel(); -} - -// ----------------------------------------------------------------------------- - // Dimensions of the icon.png resource in the notification test data directory. const int kIconWidth = 100; const int kIconHeight = 100; @@ -122,6 +64,7 @@ net::HostPortPair ServerHostPort() const; GURL TestPageUrl() const; + InfoBarService* GetInfoBarService(); private: const base::FilePath server_root_; @@ -198,6 +141,11 @@ return https_server_->GetURL(test_page_url_); } +InfoBarService* PlatformNotificationServiceBrowserTest::GetInfoBarService() { + return InfoBarService::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents()); +} + // ----------------------------------------------------------------------------- // TODO(peter): Move PlatformNotificationService-related tests over from @@ -207,7 +155,7 @@ DisplayPersistentNotificationWithoutPermission) { std::string script_result; - InfoBarResponder accepting_responder(browser(), false); + InfoBarResponder cancelling_responder(GetInfoBarService(), false); ASSERT_TRUE(RunScript("RequestPermission()", &script_result)); EXPECT_EQ("denied", script_result); @@ -223,7 +171,7 @@ DisplayPersistentNotificationWithPermission) { std::string script_result; - InfoBarResponder accepting_responder(browser(), true); + InfoBarResponder accepting_responder(GetInfoBarService(), true); ASSERT_TRUE(RunScript("RequestPermission()", &script_result)); EXPECT_EQ("granted", script_result); @@ -248,7 +196,7 @@ // TODO(peter): It doesn't add much value if we use the InfoBarResponder for // each test. Rather, we should just toggle the content setting. - InfoBarResponder accepting_responder(browser(), true); + InfoBarResponder accepting_responder(GetInfoBarService(), true); ASSERT_TRUE(RunScript("RequestPermission()", &script_result)); EXPECT_EQ("granted", script_result); @@ -274,7 +222,7 @@ CloseDisplayedPersistentNotification) { std::string script_result; - InfoBarResponder accepting_responder(browser(), true); + InfoBarResponder accepting_responder(GetInfoBarService(), true); ASSERT_TRUE(RunScript("RequestPermission()", &script_result)); EXPECT_EQ("granted", script_result); @@ -298,7 +246,7 @@ std::string script_result; // Creates a simple notification. - InfoBarResponder accepting_responder(browser(), true); + InfoBarResponder accepting_responder(GetInfoBarService(), true); ASSERT_TRUE(RunScript("RequestPermission()", &script_result)); ASSERT_EQ("granted", script_result); ASSERT_TRUE(RunScript("DisplayPersistentNotification()", &script_result)); @@ -320,7 +268,7 @@ // See crbug.com/402191. std::string script_result; - InfoBarResponder accepting_responder_web(browser(), true); + InfoBarResponder accepting_responder_web(GetInfoBarService(), true); DesktopNotificationService* notification_service = DesktopNotificationServiceFactory::GetForProfile(browser()->profile()); @@ -342,7 +290,7 @@ message_center::NotifierId file_notifier(file_url); EXPECT_FALSE(notification_service->IsNotifierEnabled(file_notifier)); - InfoBarResponder accepting_responder_file(browser(), true); + InfoBarResponder accepting_responder_file(GetInfoBarService(), true); ASSERT_TRUE(RunScript("RequestPermission()", &script_result)); EXPECT_EQ("granted", script_result);
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc index 8d1aa699..3e2fe342 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -73,7 +73,7 @@ public: ChromePasswordManagerClientTest(); - virtual void SetUp() override; + void SetUp() override; TestingPrefServiceSyncable* prefs() { return profile()->GetTestingPrefService();
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc index 198d73f..bae4833 100644 --- a/chrome/browser/password_manager/native_backend_gnome_x.cc +++ b/chrome/browser/password_manager/native_backend_gnome_x.cc
@@ -206,7 +206,7 @@ } else { LOG(WARNING) << "Unable to access password from list element!"; } - forms.push_back(form.release()); + forms.push_back(form.Pass()); } else { LOG(WARNING) << "Could not initialize PasswordForm from attributes!"; }
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.cc b/chrome/browser/password_manager/native_backend_kwallet_x.cc index ae506175..12f5425 100644 --- a/chrome/browser/password_manager/native_backend_kwallet_x.cc +++ b/chrome/browser/password_manager/native_backend_kwallet_x.cc
@@ -226,7 +226,7 @@ generation_upload_status); } - converted_forms.push_back(form.release()); + converted_forms.push_back(form.Pass()); } forms->swap(converted_forms);
diff --git a/chrome/browser/password_manager/native_backend_libsecret.cc b/chrome/browser/password_manager/native_backend_libsecret.cc index 72ecbad..252af3d 100644 --- a/chrome/browser/password_manager/native_backend_libsecret.cc +++ b/chrome/browser/password_manager/native_backend_libsecret.cc
@@ -601,7 +601,7 @@ } else { VLOG(1) << "Unable to access password from list element!"; } - forms.push_back(form.release()); + forms.push_back(form.Pass()); } else { VLOG(1) << "Could not initialize PasswordForm from attributes!"; }
diff --git a/chrome/browser/password_manager/password_generation_interactive_uitest.cc b/chrome/browser/password_manager/password_generation_interactive_uitest.cc index 78702e9..334367e 100644 --- a/chrome/browser/password_manager/password_generation_interactive_uitest.cc +++ b/chrome/browser/password_manager/password_generation_interactive_uitest.cc
@@ -132,25 +132,9 @@ TestPopupObserver observer_; }; -#if defined(USE_AURA) -// Enabled on these platforms. -// Disabled due to flakiness, see http://crbug.com/407998 -#define MAYBE_PopupShownAndPasswordSelected \ - DISABLED_PopupShownAndPasswordSelected -#define MAYBE_PopupShownAndDismissed DISABLED_PopupShownAndDismissed -#define MAYBE_PopupShownAndDismissedByScrolling \ - DISABLED_PopupShownAndDismissedByScrolling -#else -// Popup not enabled for these platforms yet. -#define MAYBE_PopupShownAndPasswordSelected \ - DISABLED_PopupShownAndPasswordSelected -#define MAYBE_PopupShownAndDismissed DISABLED_PopupShownAndDismissed -#define MAYBE_PopupShownAndDismissedByScrolling \ - DISABLED_PopupShownAndDismissedByScrolling -#endif - +// Disabled due to flakiness due to resizes, see http://crbug.com/407998. IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest, - MAYBE_PopupShownAndPasswordSelected) { + DISABLED_PopupShownAndPasswordSelected) { FocusPasswordField(); EXPECT_TRUE(GenerationPopupShowing()); SendKeyToPopup(ui::VKEY_DOWN); @@ -168,8 +152,9 @@ EXPECT_TRUE(EditingPopupShowing()); } +// Disabled due to flakiness due to resizes, see http://crbug.com/407998. IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest, - MAYBE_PopupShownAndDismissed) { + DISABLED_PopupShownAndDismissed) { FocusPasswordField(); EXPECT_TRUE(GenerationPopupShowing()); @@ -179,8 +164,9 @@ EXPECT_FALSE(GenerationPopupShowing()); } +// Disabled due to flakiness due to resizes, see http://crbug.com/407998. IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest, - MAYBE_PopupShownAndDismissedByScrolling) { + DISABLED_PopupShownAndDismissedByScrolling) { FocusPasswordField(); EXPECT_TRUE(GenerationPopupShowing()); @@ -189,3 +175,19 @@ EXPECT_FALSE(GenerationPopupShowing()); } + +// Disabled due to flakiness due to resizes, see http://crbug.com/407998. +IN_PROC_BROWSER_TEST_F(PasswordGenerationInteractiveTest, + DISABLED_GenerationTriggeredInIFrame) { + GURL url = embedded_test_server()->GetURL( + "/password/framed_signup_form.html"); + ui_test_utils::NavigateToURL(browser(), url); + + std::string focus_script = + "var frame = document.getElementById('signup_iframe');" + "var frame_doc = frame.contentDocument;" + "frame_doc.getElementById('password_field').focus();"; + + ASSERT_TRUE(content::ExecuteScript(GetRenderViewHost(), focus_script)); + EXPECT_TRUE(GenerationPopupShowing()); +}
diff --git a/chrome/browser/password_manager/password_manager_internals_service_unittest.cc b/chrome/browser/password_manager/password_manager_internals_service_unittest.cc index 82b7ffe9..07baddeb9 100644 --- a/chrome/browser/password_manager/password_manager_internals_service_unittest.cc +++ b/chrome/browser/password_manager/password_manager_internals_service_unittest.cc
@@ -8,6 +8,7 @@ #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/password_manager/content/browser/password_manager_internals_service_factory.h" #include "components/password_manager/core/browser/log_receiver.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -46,9 +47,13 @@ } // namespace +class PasswordManagerInternalsServiceTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; + // When the profile is not incognito, it should be possible to activate the // service. -TEST(PasswordManagerInternalsServiceTest, ServiceActiveNonIncognito) { +TEST_F(PasswordManagerInternalsServiceTest, ServiceActiveNonIncognito) { scoped_ptr<TestingProfile> profile(CreateProfile(NORMAL_PROFILE)); PasswordManagerInternalsService* service = PasswordManagerInternalsServiceFactory::GetForBrowserContext( @@ -68,7 +73,7 @@ // When the browser profile is incognito, it should not be possible to activate // the service. -TEST(PasswordManagerInternalsServiceTest, ServiceNotActiveIncognito) { +TEST_F(PasswordManagerInternalsServiceTest, ServiceNotActiveIncognito) { scoped_ptr<TestingProfile> profile(CreateProfile(INCOGNITO_PROFILE)); ASSERT_TRUE(profile);
diff --git a/chrome/browser/password_manager/password_manager_metrics_util_unittest.cc b/chrome/browser/password_manager/password_manager_metrics_util_unittest.cc index b662dc2..bae03d36 100644 --- a/chrome/browser/password_manager/password_manager_metrics_util_unittest.cc +++ b/chrome/browser/password_manager/password_manager_metrics_util_unittest.cc
@@ -12,6 +12,7 @@ #include "base/values.h" #include "chrome/test/base/testing_profile.h" #include "components/password_manager/core/common/password_manager_pref_names.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" class PasswordManagerMetricsUtilTest : public testing::Test { @@ -25,6 +26,7 @@ return group_id > 0; } + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; };
diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc index 7acd80d..7d4e64e 100644 --- a/chrome/browser/password_manager/password_store_factory.cc +++ b/chrome/browser/password_manager/password_store_factory.cc
@@ -356,10 +356,8 @@ #if !defined(OS_CHROMEOS) && defined(USE_X11) // Notice that the preprocessor conditions above are exactly those that will // result in using PasswordStoreX in BuildServiceInstanceFor(). - registry->RegisterIntegerPref( - password_manager::prefs::kLocalProfileId, - kInvalidLocalProfileId, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(password_manager::prefs::kLocalProfileId, + kInvalidLocalProfileId); #endif }
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc index f4690b09..fb9ef84d 100644 --- a/chrome/browser/password_manager/password_store_mac.cc +++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -1154,6 +1154,27 @@ return login_metadata_db_ && login_metadata_db_->GetBlacklistLogins(forms); } +void PasswordStoreMac::AddSiteStatsImpl( + const password_manager::InteractionsStats& stats) { + DCHECK(thread_->message_loop() == base::MessageLoop::current()); + if (login_metadata_db_) + login_metadata_db_->stats_table().AddRow(stats); +} + +void PasswordStoreMac::RemoveSiteStatsImpl(const GURL& origin_domain) { + DCHECK(thread_->message_loop() == base::MessageLoop::current()); + if (login_metadata_db_) + login_metadata_db_->stats_table().RemoveRow(origin_domain); +} + +scoped_ptr<password_manager::InteractionsStats> +PasswordStoreMac::GetSiteStatsImpl(const GURL& origin_domain) { + DCHECK(thread_->message_loop() == base::MessageLoop::current()); + return login_metadata_db_ + ? login_metadata_db_->stats_table().GetRow(origin_domain) + : scoped_ptr<password_manager::InteractionsStats>(); +} + bool PasswordStoreMac::AddToKeychainIfNecessary(const PasswordForm& form) { if (form.blacklisted_by_user) { return true;
diff --git a/chrome/browser/password_manager/password_store_mac.h b/chrome/browser/password_manager/password_store_mac.h index 60a7a6c4..172cda1 100644 --- a/chrome/browser/password_manager/password_store_mac.h +++ b/chrome/browser/password_manager/password_store_mac.h
@@ -86,6 +86,11 @@ ScopedVector<autofill::PasswordForm>* forms) override; bool FillBlacklistLogins( ScopedVector<autofill::PasswordForm>* forms) override; + void AddSiteStatsImpl( + const password_manager::InteractionsStats& stats) override; + void RemoveSiteStatsImpl(const GURL& origin_domain) override; + scoped_ptr<password_manager::InteractionsStats> GetSiteStatsImpl( + const GURL& origin_domain) override; // Adds the given form to the Keychain if it's something we want to store // there (i.e., not a blacklist entry). Returns true if the operation
diff --git a/chrome/browser/password_manager/password_store_win.cc b/chrome/browser/password_manager/password_store_win.cc index 08d6876..368bec7 100644 --- a/chrome/browser/password_manager/password_store_win.cc +++ b/chrome/browser/password_manager/password_store_win.cc
@@ -30,7 +30,7 @@ PasswordStoreWin* password_store) : web_data_service_(web_data_service), password_store_(password_store) {} - ~DBHandler(); + ~DBHandler() override; // Requests the IE7 login for |form|. This is async. |result_callback| will be // run when complete. @@ -60,7 +60,7 @@ const PasswordForm& form); // WebDataServiceConsumer implementation. - virtual void OnWebDataServiceRequestDone( + void OnWebDataServiceRequestDone( PasswordWebDataService::Handle handle, const WDTypedResult* result) override;
diff --git a/chrome/browser/password_manager/password_store_win.h b/chrome/browser/password_manager/password_store_win.h index 8bf0cb7..bfa8c83 100644 --- a/chrome/browser/password_manager/password_store_win.h +++ b/chrome/browser/password_manager/password_store_win.h
@@ -33,7 +33,7 @@ const scoped_refptr<PasswordWebDataService>& web_data_service); // PasswordStore: - virtual void Shutdown() override; + void Shutdown() override; private: class DBHandler;
diff --git a/chrome/browser/password_manager/password_store_x_unittest.cc b/chrome/browser/password_manager/password_store_x_unittest.cc index d74a8e0..7923b0e 100644 --- a/chrome/browser/password_manager/password_store_x_unittest.cc +++ b/chrome/browser/password_manager/password_store_x_unittest.cc
@@ -256,7 +256,7 @@ autofillable, false, static_cast<double>(i + 1)}; - forms->push_back(CreatePasswordFormFromDataForTesting(data).release()); + forms->push_back(CreatePasswordFormFromDataForTesting(data).Pass()); } }
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 792ecfbf..002363e 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -22,20 +22,19 @@ class PDFExtensionTest : public ExtensionApiTest { public: - virtual ~PDFExtensionTest() {} + ~PDFExtensionTest() override {} - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitch(switches::kEnableOutOfProcessPdf); } - virtual void SetUpOnMainThread() override { + void SetUpOnMainThread() override { ExtensionApiTest::SetUpOnMainThread(); ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); } - - virtual void TearDownOnMainThread() override { + void TearDownOnMainThread() override { ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete()); ExtensionApiTest::TearDownOnMainThread(); }
diff --git a/chrome/browser/pepper_flash_settings_manager.cc b/chrome/browser/pepper_flash_settings_manager.cc index 7dad619..eb64b49f 100644 --- a/chrome/browser/pepper_flash_settings_manager.cc +++ b/chrome/browser/pepper_flash_settings_manager.cc
@@ -970,15 +970,9 @@ // static void PepperFlashSettingsManager::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kDeauthorizeContentLicenses, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kDeauthorizeContentLicenses, false); - registry->RegisterBooleanPref( - prefs::kPepperFlashSettingsEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kPepperFlashSettingsEnabled, true); } uint32 PepperFlashSettingsManager::DeauthorizeContentLicenses(
diff --git a/chrome/browser/plugins/plugin_finder.cc b/chrome/browser/plugins/plugin_finder.cc index 626b0a3..6e8b5b3 100644 --- a/chrome/browser/plugins/plugin_finder.cc +++ b/chrome/browser/plugins/plugin_finder.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/json/json_reader.h" #include "base/message_loop/message_loop.h" +#include "base/metrics/histogram_macros.h" #include "base/prefs/pref_registry_simple.h" #include "base/prefs/pref_service.h" #include "base/stl_util.h" @@ -33,6 +34,22 @@ typedef std::map<std::string, PluginMetadata*> PluginMap; +// Do not change these values, as they are used in UMA. +enum class PluginListError { + // NO_ERROR is defined by Windows headers. + PLUGIN_LIST_NO_ERROR = 0, + JSON_INVALID_ESCAPE = 1, + JSON_SYNTAX_ERROR = 2, + JSON_UNEXPECTED_TOKEN = 3, + JSON_TRAILING_COMMA = 4, + JSON_TOO_MUCH_NESTING = 5, + JSON_UNEXPECTED_DATA_AFTER_ROOT = 5, + JSON_UNSUPPORTED_ENCODING = 6, + JSON_UNQUOTED_DICTIONARY_KEY = 7, + SCHEMA_ERROR = 8, + NUM_VALUES +}; + // Gets the full path of the plugin file as the identifier. std::string GetLongIdentifier(const content::WebPluginInfo& plugin) { return plugin.path.AsUTF8Unsafe(); @@ -128,6 +145,12 @@ return plugin; } +void RecordBuiltInPluginListError(PluginListError error_code) { + UMA_HISTOGRAM_ENUMERATION("PluginFinder.BuiltInPluginList.ErrorCode", + static_cast<int>(error_code), + static_cast<int>(PluginListError::NUM_VALUES)); +} + } // namespace // static @@ -151,7 +174,13 @@ // Load the built-in plugin list first. If we have a newer version stored // locally or download one, we will replace this one with it. scoped_ptr<base::DictionaryValue> plugin_list(LoadBuiltInPluginList()); - DCHECK(plugin_list); + + // Gracefully handle the case where we couldn't parse the built-in plugin list + // for some reason (https://crbug.com/388560). TODO(bauerb): Change back to a + // DCHECK once we have gathered more data about the underlying problem. + if (!plugin_list) + return; + ReinitializePlugins(plugin_list.get()); } @@ -161,17 +190,56 @@ ResourceBundle::GetSharedInstance().GetRawDataResource( IDR_PLUGIN_DB_JSON)); std::string error_str; + int error_code = base::JSONReader::JSON_NO_ERROR; scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError( - json_resource, - base::JSON_PARSE_RFC, - NULL, - &error_str)); - if (!value.get()) { + json_resource, base::JSON_PARSE_RFC, &error_code, &error_str)); + if (!value) { DLOG(ERROR) << error_str; - return NULL; + switch (error_code) { + case base::JSONReader::JSON_INVALID_ESCAPE: + RecordBuiltInPluginListError(PluginListError::JSON_INVALID_ESCAPE); + break; + case base::JSONReader::JSON_SYNTAX_ERROR: + RecordBuiltInPluginListError(PluginListError::JSON_SYNTAX_ERROR); + break; + case base::JSONReader::JSON_UNEXPECTED_TOKEN: + RecordBuiltInPluginListError(PluginListError::JSON_UNEXPECTED_TOKEN); + break; + case base::JSONReader::JSON_TRAILING_COMMA: + RecordBuiltInPluginListError(PluginListError::JSON_TRAILING_COMMA); + break; + case base::JSONReader::JSON_TOO_MUCH_NESTING: + RecordBuiltInPluginListError(PluginListError::JSON_TOO_MUCH_NESTING); + break; + case base::JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT: + RecordBuiltInPluginListError( + PluginListError::JSON_UNEXPECTED_DATA_AFTER_ROOT); + break; + case base::JSONReader::JSON_UNSUPPORTED_ENCODING: + RecordBuiltInPluginListError( + PluginListError::JSON_UNSUPPORTED_ENCODING); + break; + case base::JSONReader::JSON_UNQUOTED_DICTIONARY_KEY: + RecordBuiltInPluginListError( + PluginListError::JSON_UNQUOTED_DICTIONARY_KEY); + break; + case base::JSONReader::JSON_NO_ERROR: + case base::JSONReader::JSON_PARSE_ERROR_COUNT: + NOTREACHED(); + break; + } + return nullptr; } - if (value->GetType() != base::Value::TYPE_DICTIONARY) - return NULL; + + if (value->GetType() != base::Value::TYPE_DICTIONARY) { + // JSONReader::JSON_PARSE_ERROR_COUNT is used for the case where the JSON + // value has the wrong type. + RecordBuiltInPluginListError(PluginListError::SCHEMA_ERROR); + return nullptr; + } + + DCHECK_EQ(base::JSONReader::JSON_NO_ERROR, error_code); + RecordBuiltInPluginListError(PluginListError::PLUGIN_LIST_NO_ERROR); return static_cast<base::DictionaryValue*>(value.release()); }
diff --git a/chrome/browser/plugins/plugin_infobar_delegates.h b/chrome/browser/plugins/plugin_infobar_delegates.h index 09bf110..d103462 100644 --- a/chrome/browser/plugins/plugin_infobar_delegates.h +++ b/chrome/browser/plugins/plugin_infobar_delegates.h
@@ -117,16 +117,16 @@ private: PluginMetroModeInfoBarDelegate(Mode mode, const base::string16& name); - virtual ~PluginMetroModeInfoBarDelegate(); + ~PluginMetroModeInfoBarDelegate() override; // ConfirmInfoBarDelegate: - virtual int GetIconID() const override; - virtual base::string16 GetMessageText() const override; - virtual int GetButtons() const override; - virtual base::string16 GetButtonLabel(InfoBarButton button) const override; - virtual bool Accept() override; - virtual base::string16 GetLinkText() const override; - virtual bool LinkClicked(WindowOpenDisposition disposition) override; + int GetIconID() const override; + base::string16 GetMessageText() const override; + int GetButtons() const override; + base::string16 GetButtonLabel(InfoBarButton button) const override; + bool Accept() override; + base::string16 GetLinkText() const override; + bool LinkClicked(WindowOpenDisposition disposition) override; const Mode mode_; const base::string16 name_;
diff --git a/chrome/browser/plugins/plugin_power_saver_browsertest.cc b/chrome/browser/plugins/plugin_power_saver_browsertest.cc new file mode 100644 index 0000000..23709a37 --- /dev/null +++ b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
@@ -0,0 +1,183 @@ +// 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/command_line.h" +#include "base/strings/stringprintf.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/ppapi_test_utils.h" +#include "ppapi/shared_impl/ppapi_switches.h" +#include "third_party/WebKit/public/web/WebInputEvent.h" +#include "ui/gfx/geometry/point.h" + +class PluginPowerSaverBrowserTest : virtual public InProcessBrowserTest { + public: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kEnablePluginPowerSaver); + command_line->AppendSwitch(switches::kEnablePepperTesting); + + ASSERT_TRUE(ppapi::RegisterPowerSaverTestPlugin(command_line)); + } + + protected: + void LoadHTML(const char* html) { + std::string url_str = "data:text/html;charset=utf-8,"; + url_str.append(html); + ui_test_utils::NavigateToURL(browser(), GURL(url_str)); + EXPECT_TRUE(content::WaitForRenderFrameReady( + GetActiveWebContents()->GetMainFrame())); + } + + content::WebContents* GetActiveWebContents() { + return browser()->tab_strip_model()->GetActiveWebContents(); + } + + bool IsPluginPeripheral(const char* element_id) { + std::string script = base::StringPrintf( + "var plugin = window.document.getElementById('%s');" + "function handleEvent() {" + " if (event.data.isPeripheral != undefined &&" + " event.data.source == 'getPeripheralStatusResponse') {" + " window.domAutomationController.send(" + " event.data.isPeripheral ? 'peripheral' : 'essential');" + " plugin.removeEventListener('message', handleEvent);" + " }" + "}" + "if (plugin == undefined ||" + " (plugin.nodeName != 'OBJECT' && plugin.nodeName != 'EMBED')) {" + " window.domAutomationController.send('error');" + "} else if (plugin.postMessage == undefined) {" + " window.domAutomationController.send('peripheral');" + "} else {" + " plugin.addEventListener('message', handleEvent);" + " plugin.postMessage('getPeripheralStatus');" + "}", + element_id); + + std::string result; + EXPECT_TRUE(content::ExecuteScriptAndExtractString(GetActiveWebContents(), + script, &result)); + EXPECT_NE("error", result); + return result == "peripheral"; + } + + // This sends a simulated click at |point| and waits for test plugin to send + // a status message indicating that it is essential. The test plugin sends a + // status message during: + // - Plugin creation, to handle a plugin freshly created from a poster. + // - Peripheral status change. + // - In response to the explicit 'getPeripheralStatus' request, in case the + // test has missed the above two events. + void SimulateClickAndAwaitMarkedEssential(const char* element_id, + const gfx::Point& point) { + content::SimulateMouseClickAt(GetActiveWebContents(), 0 /* modifiers */, + blink::WebMouseEvent::ButtonLeft, point); + + std::string script = base::StringPrintf( + "var plugin = window.document.getElementById('%s');" + "function handleEvent() {" + " if (event.data.isPeripheral == false) {" + " window.domAutomationController.send('essential');" + " plugin.removeEventListener('message', handleEvent);" + " }" + "}" + "if (plugin == undefined ||" + " (plugin.nodeName != 'OBJECT' && plugin.nodeName != 'EMBED')) {" + " window.domAutomationController.send('error');" + "} else {" + " plugin.addEventListener('message', handleEvent);" + " if (plugin.postMessage != undefined) {" + " plugin.postMessage('getPeripheralStatus');" + " }" + "}", + element_id); + + std::string result; + EXPECT_TRUE(content::ExecuteScriptAndExtractString(GetActiveWebContents(), + script, &result)); + EXPECT_EQ("essential", result); + } +}; + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, SmallSameOrigin) { + LoadHTML( + "<object id='plugin' data='fake.swf' " + "type='application/x-ppapi-tests' width='400' height='100'></object>"); + EXPECT_FALSE(IsPluginPeripheral("plugin")); +} + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, SmallCrossOrigin) { + LoadHTML( + "<object id='plugin' data='http://otherorigin.com/fake.swf' " + "type='application/x-ppapi-tests' width='400' height='100'></object>"); + EXPECT_TRUE(IsPluginPeripheral("plugin")); + + SimulateClickAndAwaitMarkedEssential("plugin", gfx::Point(50, 50)); +} + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, LargeCrossOrigin) { + LoadHTML( + "<object id='plugin' data='http://otherorigin.com/fake.swf' " + "type='application/x-ppapi-tests' width='400' height='500'></object>"); + EXPECT_FALSE(IsPluginPeripheral("plugin")); +} + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, + LargePluginsPeripheralWhenPosterSpecified) { + LoadHTML( + "<object id='plugin_src' type='application/x-ppapi-tests' " + " width='400' height='500'" + " poster='snapshot1x.png' />" + "<object id='plugin_srcset' type='application/x-ppapi-tests' " + " width='400' height='500'" + " poster='snapshot1x.png 1x, snapshot2x.png 2x' />" + "<object id='plugin_legacy_syntax' type='application/x-ppapi-tests' " + " width='400' height='500'>" + " <param name='poster' value='snapshot1x.png 1x, snapshot2x.png 2x' />" + "</object>" + "<embed id='plugin_embed_src' type='application/x-ppapi-tests' " + " width='400' height='500' poster='snapshot1x.png' />" + "<embed id='plugin_embed_srcset' type='application/x-ppapi-tests' " + " width='400' height='500'" + " poster='snapshot1x.png 1x, snapshot2x.png 2x' />"); + + EXPECT_TRUE(IsPluginPeripheral("plugin_src")); + EXPECT_TRUE(IsPluginPeripheral("plugin_srcset")); + EXPECT_TRUE(IsPluginPeripheral("plugin_legacy_syntax")); + EXPECT_TRUE(IsPluginPeripheral("plugin_embed_src")); + EXPECT_TRUE(IsPluginPeripheral("plugin_embed_srcset")); +} + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, + PluginMarkedEssentialAfterPosterClicked) { + LoadHTML( + "<object id='plugin' type='application/x-ppapi-tests' " + " width='400' height='100' poster='snapshot1x.png' />"); + EXPECT_TRUE(IsPluginPeripheral("plugin")); + + SimulateClickAndAwaitMarkedEssential("plugin", gfx::Point(50, 50)); +} + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, OriginWhitelisting) { + LoadHTML( + "<object id='plugin1' data='http://otherorigin.com/fake1.swf' " + "type='application/x-ppapi-tests' width='400' height='100'></object>" + "<object id='plugin2' data='http://otherorigin.com/fake2.swf' " + "type='application/x-ppapi-tests' width='400' height='500'></object>"); + EXPECT_FALSE(IsPluginPeripheral("plugin1")); + EXPECT_FALSE(IsPluginPeripheral("plugin2")); +} + +IN_PROC_BROWSER_TEST_F(PluginPowerSaverBrowserTest, LargeCrossOriginObscured) { + LoadHTML( + "<div style='width: 100px; height: 100px; overflow: hidden;'>" + " <object id='plugin' data='http://otherorigin.com/fake.swf' " + " type='application/x-ppapi-tests' width='400' height='500'></object>" + "</div>"); + EXPECT_TRUE(IsPluginPeripheral("plugin")); +}
diff --git a/chrome/browser/plugins/plugin_prefs_factory.cc b/chrome/browser/plugins/plugin_prefs_factory.cc index 862fa91..6e176b5d 100644 --- a/chrome/browser/plugins/plugin_prefs_factory.cc +++ b/chrome/browser/plugins/plugin_prefs_factory.cc
@@ -55,30 +55,16 @@ user_prefs::PrefRegistrySyncable* registry) { base::FilePath internal_dir; PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &internal_dir); - registry->RegisterFilePathPref( - prefs::kPluginsLastInternalDirectory, - internal_dir, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterFilePathPref(prefs::kPluginsLastInternalDirectory, + internal_dir); + registry->RegisterBooleanPref(prefs::kPluginsMigratedToPepperFlash, false); registry->RegisterBooleanPref( - prefs::kPluginsMigratedToPepperFlash, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kPluginsRemovedOldComponentPepperFlashSettings, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kPluginsPluginsList, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kPluginsDisabledPlugins, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kPluginsDisabledPluginsExceptions, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kPluginsEnabledPlugins, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kEnableNpapi, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kPluginsRemovedOldComponentPepperFlashSettings, false); + registry->RegisterListPref(prefs::kPluginsPluginsList); + registry->RegisterListPref(prefs::kPluginsDisabledPlugins); + registry->RegisterListPref(prefs::kPluginsDisabledPluginsExceptions); + registry->RegisterListPref(prefs::kPluginsEnabledPlugins); + registry->RegisterBooleanPref(prefs::kEnableNpapi, false); } content::BrowserContext* PluginPrefsFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/policy/cloud/device_management_service_browsertest.cc b/chrome/browser/policy/cloud/device_management_service_browsertest.cc index 034aacb4..d8ab7a9 100644 --- a/chrome/browser/policy/cloud/device_management_service_browsertest.cc +++ b/chrome/browser/policy/cloud/device_management_service_browsertest.cc
@@ -142,7 +142,7 @@ base::MessageLoop::current()->Run(); } - virtual void SetUpOnMainThread() override { + void SetUpOnMainThread() override { std::string service_url((this->*(GetParam()))()); service_.reset(new DeviceManagementService( scoped_ptr<DeviceManagementService::Configuration>( @@ -150,7 +150,7 @@ service_->ScheduleInitialization(0); } - virtual void TearDownOnMainThread() override { + void TearDownOnMainThread() override { service_.reset(); test_server_.reset(); interceptor_.reset();
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc b/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc index dd9ea86..60c2b5c 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service_factory.cc
@@ -98,10 +98,7 @@ void UserPolicySigninServiceFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* user_prefs) { #if defined(OS_ANDROID) || defined(OS_IOS) - user_prefs->RegisterInt64Pref( - prefs::kLastPolicyCheckTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + user_prefs->RegisterInt64Pref(prefs::kLastPolicyCheckTime, 0); #endif }
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc index 4cc4e8ec..0cd839f 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -151,7 +151,7 @@ ASSERT_TRUE(IsRequestActive()); } - virtual void SetUp() override { + void SetUp() override { UserPolicySigninServiceFactory::SetDeviceManagementServiceForTesting( &device_management_service_); @@ -208,7 +208,7 @@ Mock::VerifyAndClearExpectations(mock_store_); } - virtual void TearDown() override { + void TearDown() override { UserPolicySigninServiceFactory::SetDeviceManagementServiceForTesting(NULL); UserCloudPolicyManagerFactory::GetInstance()->ClearTestingFactory(); // Free the profile before we clear out the browser prefs.
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 0991c67a..da1fba23 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -325,6 +325,9 @@ { key::kSafeBrowsingExtendedReportingOptInAllowed, prefs::kSafeBrowsingExtendedReportingOptInAllowed, base::Value::TYPE_BOOLEAN }, + { key::kSSLErrorOverrideAllowed, + prefs::kSSLErrorOverrideAllowed, + base::Value::TYPE_BOOLEAN }, #if defined(ENABLE_SPELLCHECK) { key::kSpellCheckServiceEnabled,
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index ceb95e01..629b966 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -45,6 +45,7 @@ #include "chrome/browser/extensions/updater/extension_updater.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/interstitials/security_interstitial_page.h" +#include "chrome/browser/interstitials/security_interstitial_page_test_utils.h" #include "chrome/browser/media/media_capture_devices_dispatcher.h" #include "chrome/browser/media/media_stream_devices_controller.h" #include "chrome/browser/metrics/variations/variations_service.h" @@ -849,9 +850,9 @@ class LocalePolicyTest : public PolicyTest { public: LocalePolicyTest() {} - virtual ~LocalePolicyTest() {} + ~LocalePolicyTest() override {} - virtual void SetUpInProcessBrowserTestFixture() override { + void SetUpInProcessBrowserTestFixture() override { PolicyTest::SetUpInProcessBrowserTestFixture(); PolicyMap policies; policies.Set(key::kApplicationLocaleValue, @@ -3620,6 +3621,72 @@ EXPECT_EQ(SecurityInterstitialPage::CMD_TEXT_NOT_FOUND, result); } +// Test that when SSL error overriding is allowed by policy (default), the +// proceed link appears on SSL blocking pages. +IN_PROC_BROWSER_TEST_F(PolicyTest, SSLErrorOverridingAllowed) { + net::SpawnedTestServer https_server_expired( + net::SpawnedTestServer::TYPE_HTTPS, + net::SpawnedTestServer::SSLOptions( + net::SpawnedTestServer::SSLOptions::CERT_EXPIRED), + base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); + ASSERT_TRUE(https_server_expired.Start()); + + const PrefService* const prefs = browser()->profile()->GetPrefs(); + + // Policy should allow overriding by default. + EXPECT_TRUE(prefs->GetBoolean(prefs::kSSLErrorOverrideAllowed)); + + // Policy allows overriding - navigate to an SSL error page and expect the + // proceed link. + ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/")); + + const content::InterstitialPage* const interstitial = + content::InterstitialPage::GetInterstitialPage( + browser()->tab_strip_model()->GetActiveWebContents()); + ASSERT_TRUE(interstitial); + EXPECT_TRUE(content::WaitForRenderFrameReady(interstitial->GetMainFrame())); + + // The interstitial should display the proceed link. + EXPECT_TRUE(chrome_browser_interstitials::IsInterstitialDisplayingText( + interstitial, "proceed-link")); +} + +// Test that when SSL error overriding is disallowed by policy, the +// proceed link does not appear on SSL blocking pages. +IN_PROC_BROWSER_TEST_F(PolicyTest, SSLErrorOverridingDisallowed) { + net::SpawnedTestServer https_server_expired( + net::SpawnedTestServer::TYPE_HTTPS, + net::SpawnedTestServer::SSLOptions( + net::SpawnedTestServer::SSLOptions::CERT_EXPIRED), + base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); + ASSERT_TRUE(https_server_expired.Start()); + + const PrefService* const prefs = browser()->profile()->GetPrefs(); + EXPECT_TRUE(prefs->GetBoolean(prefs::kSSLErrorOverrideAllowed)); + + // Disallowing the proceed link by setting the policy to |false|. + PolicyMap policies; + policies.Set(key::kSSLErrorOverrideAllowed, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, new base::FundamentalValue(false), NULL); + UpdateProviderPolicy(policies); + + // Policy should not allow overriding anymore. + EXPECT_FALSE(prefs->GetBoolean(prefs::kSSLErrorOverrideAllowed)); + + // Policy disallows overriding - navigate to an SSL error page and expect no + // proceed link. + ui_test_utils::NavigateToURL(browser(), https_server_expired.GetURL("/")); + const content::InterstitialPage* const interstitial = + content::InterstitialPage::GetInterstitialPage( + browser()->tab_strip_model()->GetActiveWebContents()); + ASSERT_TRUE(interstitial); + EXPECT_TRUE(content::WaitForRenderFrameReady(interstitial->GetMainFrame())); + + // The interstitial should not display the proceed link. + EXPECT_FALSE(chrome_browser_interstitials::IsInterstitialDisplayingText( + interstitial, "proceed-link")); +} + #if !defined(OS_CHROMEOS) // Similar to PolicyTest but sets the proper policy before the browser is // started.
diff --git a/chrome/browser/predictors/autocomplete_action_predictor_table_unittest.cc b/chrome/browser/predictors/autocomplete_action_predictor_table_unittest.cc index 938d10a7..717b749 100644 --- a/chrome/browser/predictors/autocomplete_action_predictor_table_unittest.cc +++ b/chrome/browser/predictors/autocomplete_action_predictor_table_unittest.cc
@@ -52,9 +52,9 @@ AutocompleteActionPredictorTable::Rows test_db_; private: + base::MessageLoop loop_; TestingProfile profile_; scoped_ptr<PredictorDatabase> db_; - base::MessageLoop loop_; content::TestBrowserThread db_thread_; };
diff --git a/chrome/browser/predictors/resource_prefetcher_unittest.cc b/chrome/browser/predictors/resource_prefetcher_unittest.cc index 4e68bdc..efcd18d8 100644 --- a/chrome/browser/predictors/resource_prefetcher_unittest.cc +++ b/chrome/browser/predictors/resource_prefetcher_unittest.cc
@@ -33,7 +33,7 @@ : ResourcePrefetcher(delegate, config, navigation_id, key_type, requests.Pass()) { } - virtual ~TestResourcePrefetcher() { } + ~TestResourcePrefetcher() override {} MOCK_METHOD1(StartURLRequest, void(net::URLRequest* request)); @@ -55,7 +55,7 @@ loop->message_loop_proxy())) { } ~TestResourcePrefetcherDelegate() { } - virtual net::URLRequestContext* GetURLRequestContext() override { + net::URLRequestContext* GetURLRequestContext() override { return request_context_getter_->GetURLRequestContext(); }
diff --git a/chrome/browser/prefetch/prefetch_browsertest.cc b/chrome/browser/prefetch/prefetch_browsertest.cc index 9ff446f..1e8c419 100644 --- a/chrome/browser/prefetch/prefetch_browsertest.cc +++ b/chrome/browser/prefetch/prefetch_browsertest.cc
@@ -4,7 +4,6 @@ #include "base/command_line.h" #include "base/prefs/pref_service.h" -#include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/net/prediction_options.h" #include "chrome/browser/profiles/profile.h" @@ -12,18 +11,14 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" -#include "chrome/common/prefetch_messages.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "net/base/network_change_notifier.h" -#include "net/url_request/url_request_filter.h" -#include "net/url_request/url_request_job.h" using chrome_browser_net::NetworkPredictionOptions; -using content::BrowserThread; using net::NetworkChangeNotifier; namespace { @@ -87,50 +82,6 @@ PrefetchBrowserTestPredictionDisabled() : PrefetchBrowserTestBase(true) {} }; -// URLRequestJob (and associated handler) which hangs. -class HangingURLRequestJob : public net::URLRequestJob { - public: - HangingURLRequestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate) - : net::URLRequestJob(request, network_delegate) {} - - // net::URLRequestJob implementation - void Start() override {} - - private: - ~HangingURLRequestJob() override {} - - DISALLOW_COPY_AND_ASSIGN(HangingURLRequestJob); -}; - -class HangingRequestInterceptor : public net::URLRequestInterceptor { - public: - explicit HangingRequestInterceptor(const base::Closure& callback) - : callback_(callback) {} - - ~HangingRequestInterceptor() override {} - - net::URLRequestJob* MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { - if (!callback_.is_null()) - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback_); - return new HangingURLRequestJob(request, network_delegate); - } - - private: - base::Closure callback_; -}; - -void CreateHangingRequestInterceptorOnIO(const GURL& url, - base::Closure callback) { - CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); - scoped_ptr<net::URLRequestInterceptor> never_respond_handler( - new HangingRequestInterceptor(callback)); - net::URLRequestFilter::GetInstance()->AddUrlInterceptor( - url, never_respond_handler.Pass()); -} - // Prefetch is disabled via field experiment. Prefetch should be dropped. IN_PROC_BROWSER_TEST_F(PrefetchBrowserTestPredictionDisabled, ExperimentDisabled) { @@ -196,24 +147,4 @@ EXPECT_TRUE(RunPrefetchExperiment(true, incognito_browser)); } -// This test will verify the following: -// - that prefetches from the browser are actually launched -// - if a prefetch is in progress, but the originating renderer is destroyed, -// that the pending prefetch request is cleaned up cleanly and does not -// result in a crash. -IN_PROC_BROWSER_TEST_F(PrefetchBrowserTestPrediction, PrefetchFromBrowser) { - const GURL kHangingUrl("http://hanging-url.com"); - base::RunLoop loop_; - BrowserThread::PostTask(BrowserThread::IO, - FROM_HERE, - base::Bind(&CreateHangingRequestInterceptorOnIO, - kHangingUrl, - loop_.QuitClosure())); - ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); - content::RenderFrameHost* rfh = - browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(); - rfh->Send(new PrefetchMsg_Prefetch(rfh->GetRoutingID(), kHangingUrl)); - loop_.Run(); -} - } // namespace
diff --git a/chrome/browser/prefs/incognito_mode_prefs.cc b/chrome/browser/prefs/incognito_mode_prefs.cc index 06bb0e0..0584bfc 100644 --- a/chrome/browser/prefs/incognito_mode_prefs.cc +++ b/chrome/browser/prefs/incognito_mode_prefs.cc
@@ -98,10 +98,8 @@ // static void IncognitoModePrefs::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kIncognitoModeAvailability, - IncognitoModePrefs::ENABLED, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kIncognitoModeAvailability, + IncognitoModePrefs::ENABLED); } // static
diff --git a/chrome/browser/prefs/leveldb_pref_store.cc b/chrome/browser/prefs/leveldb_pref_store.cc index c0af1038..2effc51 100644 --- a/chrome/browser/prefs/leveldb_pref_store.cc +++ b/chrome/browser/prefs/leveldb_pref_store.cc
@@ -62,19 +62,15 @@ public: explicit FileThreadSerializer(scoped_ptr<leveldb::DB> db) : db_(db.Pass()) {} void WriteToDatabase( - std::map<std::string, std::string>* keys_to_set, - std::set<std::string>* keys_to_delete) { + base::hash_map<std::string, std::string>* keys_to_set, + base::hash_set<std::string>* keys_to_delete) { DCHECK(keys_to_set->size() > 0 || keys_to_delete->size() > 0); leveldb::WriteBatch batch; - for (std::map<std::string, std::string>::iterator iter = - keys_to_set->begin(); - iter != keys_to_set->end(); - iter++) { + for (auto iter = keys_to_set->begin(); iter != keys_to_set->end(); iter++) { batch.Put(iter->first, iter->second); } - for (std::set<std::string>::iterator iter = keys_to_delete->begin(); - iter != keys_to_delete->end(); + for (auto iter = keys_to_delete->begin(); iter != keys_to_delete->end(); iter++) { batch.Delete(*iter); } @@ -244,11 +240,12 @@ return; DCHECK(serializer_); - scoped_ptr<std::set<std::string> > keys_to_delete(new std::set<std::string>); + scoped_ptr<base::hash_set<std::string>> keys_to_delete( + new base::hash_set<std::string>); keys_to_delete->swap(keys_to_delete_); - scoped_ptr<std::map<std::string, std::string> > keys_to_set( - new std::map<std::string, std::string>); + scoped_ptr<base::hash_map<std::string, std::string>> keys_to_set( + new base::hash_map<std::string, std::string>); keys_to_set->swap(keys_to_set_); sequenced_task_runner_->PostTask(
diff --git a/chrome/browser/prefs/leveldb_pref_store.h b/chrome/browser/prefs/leveldb_pref_store.h index 0b6b052..9d7d8f8 100644 --- a/chrome/browser/prefs/leveldb_pref_store.h +++ b/chrome/browser/prefs/leveldb_pref_store.h
@@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/containers/hash_tables.h" #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop_proxy.h" @@ -102,8 +103,8 @@ // Changes are accumulated in |keys_to_delete_| and |keys_to_set_| and are // stored in the database according to |timer_|. - std::set<std::string> keys_to_delete_; - std::map<std::string, std::string> keys_to_set_; + base::hash_set<std::string> keys_to_delete_; + base::hash_map<std::string, std::string> keys_to_set_; base::OneShotTimer<LevelDBPrefStore> timer_; base::WeakPtrFactory<LevelDBPrefStore> weak_ptr_factory_;
diff --git a/chrome/browser/prefs/pref_model_associator_unittest.cc b/chrome/browser/prefs/pref_model_associator_unittest.cc index 44e55774..3bdf8dc 100644 --- a/chrome/browser/prefs/pref_model_associator_unittest.cc +++ b/chrome/browser/prefs/pref_model_associator_unittest.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/prefs/pref_model_associator.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" class AbstractPreferenceMergeTest : public testing::Test { @@ -45,6 +46,7 @@ pref_service_->Set(pref_name.c_str(), *empty_value); } + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; PrefService* pref_service_; };
diff --git a/chrome/browser/prefs/pref_service_syncable.cc b/chrome/browser/prefs/pref_service_syncable.cc index 0a8613c..32d4d3e2 100644 --- a/chrome/browser/prefs/pref_service_syncable.cc +++ b/chrome/browser/prefs/pref_service_syncable.cc
@@ -55,13 +55,11 @@ base::Unretained(this))); // Add already-registered syncable preferences to PrefModelAssociator. - const user_prefs::PrefRegistrySyncable::PrefToStatus& syncable_preferences = - pref_registry->syncable_preferences(); - for (user_prefs::PrefRegistrySyncable::PrefToStatus::const_iterator it = - syncable_preferences.begin(); - it != syncable_preferences.end(); - ++it) { - AddRegisteredSyncablePreference(it->first.c_str(), it->second); + for (PrefRegistry::const_iterator it = pref_registry->begin(); + it != pref_registry->end(); ++it) { + const std::string& path = it->first; + AddRegisteredSyncablePreference(path, + pref_registry_->GetRegistrationFlags(path)); } // Watch for syncable preferences registered after this point. @@ -163,16 +161,14 @@ } void PrefServiceSyncable::AddRegisteredSyncablePreference( - const char* path, - const user_prefs::PrefRegistrySyncable::PrefSyncStatus sync_status) { + const std::string& path, + uint32 flags) { DCHECK(FindPreference(path)); - if (sync_status == user_prefs::PrefRegistrySyncable::SYNCABLE_PREF) { - pref_sync_associator_.RegisterPref(path); - } else if (sync_status == + if (flags & user_prefs::PrefRegistrySyncable::SYNCABLE_PREF) { + pref_sync_associator_.RegisterPref(path.c_str()); + } else if (flags & user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF) { - priority_pref_sync_associator_.RegisterPref(path); - } else { - NOTREACHED() << "invalid sync_status: " << sync_status; + priority_pref_sync_associator_.RegisterPref(path.c_str()); } }
diff --git a/chrome/browser/prefs/pref_service_syncable.h b/chrome/browser/prefs/pref_service_syncable.h index c1b4960..4b35cfc 100644 --- a/chrome/browser/prefs/pref_service_syncable.h +++ b/chrome/browser/prefs/pref_service_syncable.h
@@ -89,9 +89,7 @@ private: friend class PrefModelAssociator; - void AddRegisteredSyncablePreference( - const char* path, - const user_prefs::PrefRegistrySyncable::PrefSyncStatus sync_status); + void AddRegisteredSyncablePreference(const std::string& path, uint32 flags); // Invoked internally when the IsSyncing() state changes. void OnIsSyncingChanged();
diff --git a/chrome/browser/prefs/prefs_syncable_service_unittest.cc b/chrome/browser/prefs/prefs_syncable_service_unittest.cc index e5e84279..a55a3d1 100644 --- a/chrome/browser/prefs/prefs_syncable_service_unittest.cc +++ b/chrome/browser/prefs/prefs_syncable_service_unittest.cc
@@ -75,10 +75,8 @@ next_pref_remote_sync_node_id_(0) {} void SetUp() override { - prefs_.registry()->RegisterStringPref( - kUnsyncedPreferenceName, - kUnsyncedPreferenceDefaultValue, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs_.registry()->RegisterStringPref(kUnsyncedPreferenceName, + kUnsyncedPreferenceDefaultValue); prefs_.registry()->RegisterStringPref( prefs::kHomePage, std::string(), @@ -86,9 +84,7 @@ prefs_.registry()->RegisterListPref( prefs::kURLsToRestoreOnStartup, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - prefs_.registry()->RegisterListPref( - prefs::kURLsToRestoreOnStartupOld, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs_.registry()->RegisterListPref(prefs::kURLsToRestoreOnStartupOld); prefs_.registry()->RegisterStringPref( prefs::kDefaultCharset, l10n_util::GetStringUTF8(IDS_DEFAULT_ENCODING),
diff --git a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc index 03f47ae..f8831e0 100644 --- a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc +++ b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
@@ -102,19 +102,12 @@ it != kConfiguration + arraysize(kConfiguration); ++it) { if (it->strategy == PrefHashFilter::TRACKING_STRATEGY_ATOMIC) { - profile_pref_registry_->RegisterStringPref( - it->name, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + profile_pref_registry_->RegisterStringPref(it->name, std::string()); } else { - profile_pref_registry_->RegisterDictionaryPref( - it->name, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + profile_pref_registry_->RegisterDictionaryPref(it->name); } } - profile_pref_registry_->RegisterStringPref( - kUnprotectedPref, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + profile_pref_registry_->RegisterStringPref(kUnprotectedPref, std::string()); // As in chrome_pref_service_factory.cc, kPreferencesResetTime needs to be // declared as protected in order to be read from the proper store by the
diff --git a/chrome/browser/prefs/proxy_policy_unittest.cc b/chrome/browser/prefs/proxy_policy_unittest.cc index b7a5213f..80a0874 100644 --- a/chrome/browser/prefs/proxy_policy_unittest.cc +++ b/chrome/browser/prefs/proxy_policy_unittest.cc
@@ -19,6 +19,7 @@ #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_service_impl.h" #include "components/pref_registry/pref_registry_syncable.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "policy/policy_constants.h" #include "testing/gtest/include/gtest/gtest.h" @@ -108,7 +109,7 @@ return prefs.Pass(); } - base::MessageLoop loop_; + content::TestBrowserThreadBundle thread_bundle_; base::CommandLine command_line_; MockConfigurationPolicyProvider provider_; scoped_ptr<PolicyServiceImpl> policy_service_;
diff --git a/chrome/browser/prefs/session_startup_pref.cc b/chrome/browser/prefs/session_startup_pref.cc index 9bc0c55a..996adc84 100644 --- a/chrome/browser/prefs/session_startup_pref.cc +++ b/chrome/browser/prefs/session_startup_pref.cc
@@ -71,16 +71,9 @@ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterListPref(prefs::kURLsToRestoreOnStartup, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterListPref(prefs::kURLsToRestoreOnStartupOld, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kRestoreOnStartupMigrated, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kRestoreStartupURLsMigrationTime, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kURLsToRestoreOnStartupOld); + registry->RegisterBooleanPref(prefs::kRestoreOnStartupMigrated, false); + registry->RegisterInt64Pref(prefs::kRestoreStartupURLsMigrationTime, false); } // static
diff --git a/chrome/browser/prefs/session_startup_pref_unittest.cc b/chrome/browser/prefs/session_startup_pref_unittest.cc index 8712435..ed08296 100644 --- a/chrome/browser/prefs/session_startup_pref_unittest.cc +++ b/chrome/browser/prefs/session_startup_pref_unittest.cc
@@ -19,16 +19,10 @@ void SetUp() override { pref_service_.reset(new TestingPrefServiceSyncable); SessionStartupPref::RegisterProfilePrefs(registry()); - registry()->RegisterBooleanPref( - prefs::kHomePageIsNewTabPage, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry()->RegisterBooleanPref(prefs::kHomePageIsNewTabPage, true); // Make the tests independent of the Mac startup pref migration (see // SessionStartupPref::MigrateMacDefaultPrefIfNecessary). - registry()->RegisterStringPref( - prefs::kProfileCreatedByVersion, - "22.0.0.0", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry()->RegisterStringPref(prefs::kProfileCreatedByVersion, "22.0.0.0"); } bool IsUseLastOpenDefault() { @@ -89,10 +83,7 @@ // (so that, in effect, the default value "Open the homepage" was selected), // their preferences are migrated on upgrade to m19. TEST_F(SessionStartupPrefTest, DefaultMigration) { - registry()->RegisterStringPref( - prefs::kHomePage, - "http://google.com/", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry()->RegisterStringPref(prefs::kHomePage, "http://google.com/"); pref_service_->SetString(prefs::kHomePage, "http://chromium.org/"); pref_service_->SetBoolean(prefs::kHomePageIsNewTabPage, false); @@ -116,10 +107,7 @@ // and the NTP is being used for the homepage, their preferences are migrated // to "Open the New Tab Page" on upgrade to M19. TEST_F(SessionStartupPrefTest, DefaultMigrationHomepageIsNTP) { - registry()->RegisterStringPref( - prefs::kHomePage, - "http://google.com/", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry()->RegisterStringPref(prefs::kHomePage, "http://google.com/"); pref_service_->SetString(prefs::kHomePage, "http://chromium.org/"); pref_service_->SetBoolean(prefs::kHomePageIsNewTabPage, true); @@ -140,10 +128,7 @@ // Checks to make sure that if the user had previously selected "Open the // "homepage", their preferences are migrated on upgrade to M19. TEST_F(SessionStartupPrefTest, HomePageMigration) { - registry()->RegisterStringPref( - prefs::kHomePage, - "http://google.com/", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry()->RegisterStringPref(prefs::kHomePage, "http://google.com/"); // By design, it's impossible to set the 'restore on startup' pref to 0 // ("open the homepage") using SessionStartupPref::SetStartupPref(), so set it @@ -164,10 +149,7 @@ // "homepage", and the NTP is being used for the homepage, their preferences // are migrated on upgrade to M19. TEST_F(SessionStartupPrefTest, HomePageMigrationHomepageIsNTP) { - registry()->RegisterStringPref( - prefs::kHomePage, - "http://google.com/", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry()->RegisterStringPref(prefs::kHomePage, "http://google.com/"); // By design, it's impossible to set the 'restore on startup' pref to 0 // ("open the homepage") using SessionStartupPref::SetStartupPref(), so set it
diff --git a/chrome/browser/prefs/tracked/dictionary_hash_store_contents.cc b/chrome/browser/prefs/tracked/dictionary_hash_store_contents.cc index 7b6f542..567b9c8 100644 --- a/chrome/browser/prefs/tracked/dictionary_hash_store_contents.cc +++ b/chrome/browser/prefs/tracked/dictionary_hash_store_contents.cc
@@ -55,13 +55,8 @@ // static void DictionaryHashStoreContents::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - kPreferenceMACs, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - kSuperMACPref, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kPreferenceMACs); + registry->RegisterStringPref(kSuperMACPref, std::string()); } std::string DictionaryHashStoreContents::hash_store_id() const {
diff --git a/chrome/browser/prefs/tracked/pref_hash_filter.cc b/chrome/browser/prefs/tracked/pref_hash_filter.cc index c833f99..b6844ff 100644 --- a/chrome/browser/prefs/tracked/pref_hash_filter.cc +++ b/chrome/browser/prefs/tracked/pref_hash_filter.cc
@@ -99,8 +99,7 @@ // See GetResetTime for why this is a StringPref and not Int64Pref. registry->RegisterStringPref( prefs::kPreferenceResetTime, - base::Int64ToString(base::Time().ToInternalValue()), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + base::Int64ToString(base::Time().ToInternalValue())); } // static
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index db6e9f6..9d7ad23 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -3347,43 +3347,6 @@ "Prerender.websame_PerceivedPLTMatchedComplete", 1); } -class PrerenderBrowserTestWithNaCl : public PrerenderBrowserTest { - public: - PrerenderBrowserTestWithNaCl() {} - ~PrerenderBrowserTestWithNaCl() override {} - - void SetUpCommandLine(base::CommandLine* command_line) override { - PrerenderBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitch(switches::kEnableNaCl); - } -}; - -// Check that NaCl plugins work when enabled, with prerendering. -IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithNaCl, - PrerenderNaClPluginEnabled) { -#if defined(OS_WIN) && defined(USE_ASH) - // Disable this test in Metro+Ash for now (http://crbug.com/262796). - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kAshBrowserTests)) - return; -#endif - - PrerenderTestURL("files/prerender/prerender_plugin_nacl_enabled.html", - FINAL_STATUS_USED, - 1); - NavigateToDestURL(); - - // To avoid any chance of a race, we have to let the script send its response - // asynchronously. - WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - bool display_test_result = false; - ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, - "DidDisplayReallyPass()", - &display_test_result)); - ASSERT_TRUE(display_test_result); -} - // Checks that the referrer policy is used when prerendering. IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReferrerPolicy) { set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html"); @@ -4056,4 +4019,44 @@ GetAutocompleteActionPredictor()->IsPrerenderAbandonedForTesting()); } +// Can't run tests with NaCl plugins if built with DISABLE_NACL. +#if !defined(DISABLE_NACL) +class PrerenderBrowserTestWithNaCl : public PrerenderBrowserTest { + public: + PrerenderBrowserTestWithNaCl() {} + ~PrerenderBrowserTestWithNaCl() override {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + PrerenderBrowserTest::SetUpCommandLine(command_line); + command_line->AppendSwitch(switches::kEnableNaCl); + } +}; + +// Check that NaCl plugins work when enabled, with prerendering. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithNaCl, + PrerenderNaClPluginEnabled) { +#if defined(OS_WIN) && defined(USE_ASH) + // Disable this test in Metro+Ash for now (http://crbug.com/262796). + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAshBrowserTests)) + return; +#endif + + PrerenderTestURL("files/prerender/prerender_plugin_nacl_enabled.html", + FINAL_STATUS_USED, + 1); + NavigateToDestURL(); + + // To avoid any chance of a race, we have to let the script send its response + // asynchronously. + WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + bool display_test_result = false; + ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, + "DidDisplayReallyPass()", + &display_test_result)); + ASSERT_TRUE(display_test_result); +} +#endif // !defined(DISABLE_NACL) + } // namespace prerender
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc index b0e37e1..1a54e4b 100644 --- a/chrome/browser/prerender/prerender_unittest.cc +++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -377,8 +377,8 @@ private: // Needed to pass PrerenderManager's DCHECKs. - TestingProfile profile_; base::MessageLoop message_loop_; + TestingProfile profile_; content::TestBrowserThread ui_thread_; scoped_ptr<UnitTestPrerenderManager> prerender_manager_; scoped_ptr<PrerenderLinkManager> prerender_link_manager_;
diff --git a/chrome/browser/printing/print_dialog_cloud.cc b/chrome/browser/printing/print_dialog_cloud.cc index 5dfc021..bf4d4ff 100644 --- a/chrome/browser/printing/print_dialog_cloud.cc +++ b/chrome/browser/printing/print_dialog_cloud.cc
@@ -681,14 +681,8 @@ namespace print_dialog_cloud { void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kCloudPrintDialogWidth, - kDefaultWidth, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kCloudPrintDialogHeight, - kDefaultHeight, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kCloudPrintDialogWidth, kDefaultWidth); + registry->RegisterIntegerPref(prefs::kCloudPrintDialogHeight, kDefaultHeight); } // Called on the FILE or UI thread. This is the main entry point into creating
diff --git a/chrome/browser/printing/print_view_manager_common.cc b/chrome/browser/printing/print_view_manager_common.cc index 37f8d098..7f8ad12 100644 --- a/chrome/browser/printing/print_view_manager_common.cc +++ b/chrome/browser/printing/print_view_manager_common.cc
@@ -37,7 +37,7 @@ content::WebContents* GetWebContentsToUse(content::WebContents* contents) { #if defined(ENABLE_EXTENSIONS) extensions::GuestViewManager* guest_view_manager = - extensions::GuestViewManager::FromBrowserContextIfAvailable( + extensions::GuestViewManager::FromBrowserContext( contents->GetBrowserContext()); if (guest_view_manager) { guest_view_manager->ForEachGuest(
diff --git a/chrome/browser/printing/printing_layout_browsertest.cc b/chrome/browser/printing/printing_layout_browsertest.cc index c38d6b1..4e1d2b73 100644 --- a/chrome/browser/printing/printing_layout_browsertest.cc +++ b/chrome/browser/printing/printing_layout_browsertest.cc
@@ -45,18 +45,18 @@ emf_path_ = browser_directory.AppendASCII("metafile_dumps"); } - virtual void SetUp() override { + void SetUp() override { // Make sure there is no left overs. CleanupDumpDirectory(); InProcessBrowserTest::SetUp(); } - virtual void TearDown() override { + void TearDown() override { InProcessBrowserTest::TearDown(); base::DeleteFile(emf_path_, true); } - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitchPath(switches::kDebugPrint, emf_path_); }
diff --git a/chrome/browser/process_singleton_posix_unittest.cc b/chrome/browser/process_singleton_posix_unittest.cc index f50e760c..b62e861 100644 --- a/chrome/browser/process_singleton_posix_unittest.cc +++ b/chrome/browser/process_singleton_posix_unittest.cc
@@ -252,6 +252,7 @@ kill_callbacks_++; } + base::MessageLoop message_loop_; content::TestBrowserThread io_thread_; base::ScopedTempDir temp_dir_; base::WaitableEvent wait_event_;
diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter.cc b/chrome/browser/profile_resetter/automatic_profile_resetter.cc index 51ea44a..9dead81c 100644 --- a/chrome/browser/profile_resetter/automatic_profile_resetter.cc +++ b/chrome/browser/profile_resetter/automatic_profile_resetter.cc
@@ -218,7 +218,7 @@ // Called back by |memento_in_file_| once the |memento_value| has been read. void IncludeFileBasedMementoCallback(const std::string& memento_value) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); data_->SetString(kMementoValueInFileKey, memento_value); // As an asynchronous task, we need to take care of posting the next task. PostNextTask(); @@ -382,7 +382,7 @@ AutomaticProfileResetter::~AutomaticProfileResetter() {} void AutomaticProfileResetter::Initialize() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_UNINITIALIZED); if (!ShouldPerformDryRun() && !ShouldPerformLiveRun()) { @@ -415,7 +415,7 @@ } void AutomaticProfileResetter::Activate() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(state_ == STATE_INITIALIZED || state_ == STATE_DISABLED); if (state_ == STATE_INITIALIZED) { @@ -435,7 +435,7 @@ } void AutomaticProfileResetter::TriggerProfileReset(bool send_feedback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_HAS_SHOWN_BUBBLE); state_ = STATE_PERFORMING_RESET; @@ -449,7 +449,7 @@ } void AutomaticProfileResetter::SkipProfileReset() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_HAS_SHOWN_BUBBLE); should_show_reset_banner_ = false; @@ -465,12 +465,12 @@ } bool AutomaticProfileResetter::ShouldShowResetBanner() const { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return should_show_reset_banner_ && ShouldPerformLiveRun(); } void AutomaticProfileResetter::NotifyDidShowResetBubble() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_HAS_TRIGGERED_PROMPT); state_ = STATE_HAS_SHOWN_BUBBLE; @@ -480,7 +480,7 @@ } void AutomaticProfileResetter::NotifyDidOpenWebUIResetDialog() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // This notification is invoked unconditionally by the WebUI, only care about // it when the prompt flow is currently active (and not yet resetting). @@ -493,7 +493,7 @@ void AutomaticProfileResetter::NotifyDidCloseWebUIResetDialog( bool performed_reset) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // This notification is invoked unconditionally by the WebUI, only care about // it when the prompt flow is currently active (and not yet resetting). @@ -516,7 +516,7 @@ } void AutomaticProfileResetter::NotifyDidCloseWebUIResetBanner() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); should_show_reset_banner_ = false; } @@ -541,7 +541,7 @@ } void AutomaticProfileResetter::Shutdown() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // We better not do anything substantial at this point. The metrics service // has already been shut down; and local state has already been commited to @@ -554,7 +554,7 @@ } void AutomaticProfileResetter::PrepareEvaluationFlow() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_INITIALIZED); state_ = STATE_WAITING_ON_DEPENDENCIES; @@ -580,7 +580,7 @@ } void AutomaticProfileResetter::OnDependencyIsReady() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_WAITING_ON_DEPENDENCIES); if (template_url_service_ready_ && enumeration_of_loaded_modules_ready_) { @@ -594,7 +594,7 @@ } void AutomaticProfileResetter::BeginEvaluationFlow() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_READY); DCHECK(!program_.empty()); DCHECK(!input_builder_); @@ -609,7 +609,7 @@ void AutomaticProfileResetter::ContinueWithEvaluationFlow( scoped_ptr<base::DictionaryValue> program_input) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); input_builder_.reset(); @@ -686,7 +686,7 @@ void AutomaticProfileResetter::FinishEvaluationFlow( scoped_ptr<EvaluationResults> results) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); ReportStatistics(results->satisfied_criteria_mask, @@ -704,7 +704,7 @@ } void AutomaticProfileResetter::BeginResetPromptFlow() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_EVALUATING_CONDITIONS); state_ = STATE_HAS_TRIGGERED_PROMPT; @@ -722,7 +722,7 @@ } void AutomaticProfileResetter::OnProfileSettingsResetCompleted() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(state_, STATE_PERFORMING_RESET); delegate_->DismissPrompt(); @@ -735,7 +735,7 @@ } void AutomaticProfileResetter::PersistMementos() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(state_ == STATE_HAS_TRIGGERED_PROMPT || state_ == STATE_HAS_SHOWN_BUBBLE); DCHECK(evaluation_results_); @@ -753,7 +753,7 @@ } void AutomaticProfileResetter::FinishResetPromptFlow() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(state_ == STATE_HAS_TRIGGERED_PROMPT || state_ == STATE_HAS_SHOWN_BUBBLE || state_ == STATE_PERFORMING_RESET);
diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.cc index 02948a3..b120f7c 100644 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.cc +++ b/chrome/browser/profile_resetter/automatic_profile_resetter_delegate.cc
@@ -305,7 +305,7 @@ } void AutomaticProfileResetterDelegateImpl::OnTemplateURLServiceChanged() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(template_url_service_); if (template_url_service_->loaded() && !template_url_service_ready_event_.is_signaled()) @@ -328,7 +328,7 @@ int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (type == chrome::NOTIFICATION_MODULE_LIST_ENUMERATED && !modules_have_been_enumerated_event_.is_signaled()) { #if defined(OS_WIN) @@ -364,7 +364,7 @@ void AutomaticProfileResetterDelegateImpl:: OnBrandcodedDefaultsFetched() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(brandcoded_config_fetcher_); DCHECK(!brandcoded_config_fetcher_->IsActive()); brandcoded_defaults_ = brandcoded_config_fetcher_->GetSettings(); @@ -376,7 +376,7 @@ void AutomaticProfileResetterDelegateImpl::OnProfileSettingsResetCompleted( const base::Closure& user_callback, scoped_ptr<ResettableSettingsSnapshot> old_settings_snapshot) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (old_settings_snapshot) { ResettableSettingsSnapshot new_settings_snapshot(profile_); int difference =
diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate_unittest.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_delegate_unittest.cc index db4ec93..303f030 100644 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_delegate_unittest.cc +++ b/chrome/browser/profile_resetter/automatic_profile_resetter_delegate_unittest.cc
@@ -165,9 +165,9 @@ : public extensions::ExtensionServiceTestBase { protected: AutomaticProfileResetterDelegateTest() {} - virtual ~AutomaticProfileResetterDelegateTest() {} + ~AutomaticProfileResetterDelegateTest() override {} - virtual void SetUp() override { + void SetUp() override { extensions::ExtensionServiceTestBase::SetUp(); ExtensionServiceInitParams params = CreateDefaultInitParams(); params.pref_file.clear(); // Prescribes a TestingPrefService to be created. @@ -178,7 +178,7 @@ new AutomaticProfileResetterDelegateUnderTest(profile())); } - virtual void TearDown() override { + void TearDown() override { resetter_delegate_.reset(); template_url_service_test_util_.reset(); extensions::ExtensionServiceTestBase::TearDown();
diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_factory.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_factory.cc index 7acdff7..9c53bd2 100644 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_factory.cc +++ b/chrome/browser/profile_resetter/automatic_profile_resetter_factory.cc
@@ -56,10 +56,8 @@ void AutomaticProfileResetterFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kProfileResetPromptMementoInProfilePrefs, - "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kProfileResetPromptMementoInProfilePrefs, + ""); } bool AutomaticProfileResetterFactory::
diff --git a/chrome/browser/profile_resetter/automatic_profile_resetter_unittest.cc b/chrome/browser/profile_resetter/automatic_profile_resetter_unittest.cc index 135094f..a818494 100644 --- a/chrome/browser/profile_resetter/automatic_profile_resetter_unittest.cc +++ b/chrome/browser/profile_resetter/automatic_profile_resetter_unittest.cc
@@ -62,7 +62,7 @@ public: explicit AutomaticProfileResetterUnderTest(Profile* profile) : AutomaticProfileResetter(profile) {} - virtual ~AutomaticProfileResetterUnderTest() {} + ~AutomaticProfileResetterUnderTest() override {} MOCK_METHOD2(ReportStatistics, void(uint32, uint32)); MOCK_METHOD1(ReportPromptResult, @@ -76,7 +76,7 @@ public: MockProfileResetterDelegate() : emulated_is_default_search_provider_managed_(false) {} - virtual ~MockProfileResetterDelegate() {} + ~MockProfileResetterDelegate() override {} MOCK_METHOD0(EnumerateLoadedModulesIfNeeded, void()); MOCK_CONST_METHOD1(RequestCallbackWhenLoadedModulesAreEnumerated, @@ -99,26 +99,25 @@ MOCK_METHOD2(TriggerProfileSettingsReset, void(bool, const base::Closure&)); MOCK_METHOD0(DismissPrompt, void()); - virtual scoped_ptr<base::ListValue> - GetLoadedModuleNameDigests() const override { + scoped_ptr<base::ListValue> GetLoadedModuleNameDigests() const override { OnGetLoadedModuleNameDigestsCalled(); return scoped_ptr<base::ListValue>( emulated_loaded_module_digests_.DeepCopy()); } - virtual scoped_ptr<base::DictionaryValue> + scoped_ptr<base::DictionaryValue> GetDefaultSearchProviderDetails() const override { OnGetDefaultSearchProviderDetailsCalled(); return scoped_ptr<base::DictionaryValue>( emulated_default_search_provider_details_.DeepCopy()); } - virtual bool IsDefaultSearchProviderManaged() const override { + bool IsDefaultSearchProviderManaged() const override { OnIsDefaultSearchProviderManagedCalled(); return emulated_is_default_search_provider_managed_; } - virtual scoped_ptr<base::ListValue> + scoped_ptr<base::ListValue> GetPrepopulatedSearchProvidersDetails() const override { OnGetPrepopulatedSearchProvidersDetailsCalled(); return scoped_ptr<base::ListValue>( @@ -510,12 +509,10 @@ user_prefs::PrefRegistrySyncable* user_prefs_registry = profile_->GetTestingPrefService()->registry(); DCHECK(user_prefs_registry); - user_prefs_registry->RegisterStringPref( - kTestPreferencePath, std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + user_prefs_registry->RegisterStringPref(kTestPreferencePath, std::string()); } - virtual void SetUp() override { + void SetUp() override { variations::testing::ClearAllVariationParams(); base::FieldTrialList::CreateFieldTrial(kAutomaticProfileResetStudyName, experiment_group_name_);
diff --git a/chrome/browser/profile_resetter/jtl_interpreter.cc b/chrome/browser/profile_resetter/jtl_interpreter.cc index c9189540..be0b368c 100644 --- a/chrome/browser/profile_resetter/jtl_interpreter.cc +++ b/chrome/browser/profile_resetter/jtl_interpreter.cc
@@ -246,8 +246,8 @@ : hashed_name_(hashed_name) { DCHECK(base::IsStringUTF8(hashed_name)); } - virtual ~StoreNodeValue() {} - virtual bool Execute(ExecutionContext* context) override { + ~StoreNodeValue() override {} + bool Execute(ExecutionContext* context) override { scoped_ptr<base::Value> value; if (ExpectedTypeIsBooleanNotHashable) { if (!context->current_node()->IsType(base::Value::TYPE_BOOLEAN)) @@ -382,8 +382,8 @@ public: explicit CompareNodeToStored(const std::string& hashed_name) : hashed_name_(hashed_name) {} - virtual ~CompareNodeToStored() {} - virtual bool Execute(ExecutionContext* context) override { + ~CompareNodeToStored() override {} + bool Execute(ExecutionContext* context) override { const base::Value* stored_value = NULL; if (!context->working_memory()->Get(hashed_name_, &stored_value)) return true;
diff --git a/chrome/browser/profile_resetter/profile_resetter.cc b/chrome/browser/profile_resetter/profile_resetter.cc index 9a5ba3f..ab2a026 100644 --- a/chrome/browser/profile_resetter/profile_resetter.cc +++ b/chrome/browser/profile_resetter/profile_resetter.cc
@@ -37,7 +37,7 @@ namespace { void ResetShortcutsOnFileThread() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); // Get full path of chrome. base::FilePath chrome_exe; if (!PathService::Get(base::FILE_EXE, &chrome_exe)) @@ -127,7 +127,7 @@ } bool ProfileResetter::IsActive() const { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return pending_reset_flags_ != 0; } @@ -326,7 +326,7 @@ std::vector<ShortcutCommand> GetChromeLaunchShortcuts( const scoped_refptr<SharedCancellationFlag>& cancel) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(content::BrowserThread::FILE); #if defined(OS_WIN) // Get full path of chrome. base::FilePath chrome_exe;
diff --git a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc index 8c1b321..8b0581b 100644 --- a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc +++ b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
@@ -90,7 +90,7 @@ void RemoveCookieTester::GetCookieOnIOThread( net::URLRequestContextGetter* context_getter, const std::string& host) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); net::CookieStore* cookie_store = context_getter-> GetURLRequestContext()->cookie_store(); cookie_store->GetCookiesWithOptionsAsync( @@ -103,7 +103,7 @@ net::URLRequestContextGetter* context_getter, const std::string& host, const std::string& definition) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); net::CookieStore* cookie_store = context_getter-> GetURLRequestContext()->cookie_store(); cookie_store->SetCookieWithOptionsAsync(
diff --git a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc index 34e72e1..d7d00017 100644 --- a/chrome/browser/profile_resetter/resettable_settings_snapshot.cc +++ b/chrome/browser/profile_resetter/resettable_settings_snapshot.cc
@@ -60,7 +60,7 @@ : startup_(SessionStartupPref::GetStartupPref(profile)), shortcuts_determined_(false), weak_ptr_factory_(this) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // URLs are always stored sorted. std::sort(startup_.urls.begin(), startup_.urls.end()); @@ -90,14 +90,14 @@ } ResettableSettingsSnapshot::~ResettableSettingsSnapshot() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (cancellation_flag_.get()) cancellation_flag_->data.Set(); } void ResettableSettingsSnapshot::Subtract( const ResettableSettingsSnapshot& snapshot) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ExtensionList extensions = base::STLSetDifference<ExtensionList>( enabled_extensions_, snapshot.enabled_extensions_); enabled_extensions_.swap(extensions); @@ -105,7 +105,7 @@ int ResettableSettingsSnapshot::FindDifferentFields( const ResettableSettingsSnapshot& snapshot) const { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); int bit_mask = 0; if (startup_.type != snapshot.startup_.type || @@ -134,7 +134,7 @@ void ResettableSettingsSnapshot::RequestShortcuts( const base::Closure& callback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!cancellation_flag_.get() && !shortcuts_determined()); cancellation_flag_ = new SharedCancellationFlag; @@ -150,7 +150,7 @@ void ResettableSettingsSnapshot::SetShortcutsAndReport( const base::Closure& callback, const std::vector<ShortcutCommand>& shortcuts) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); shortcuts_ = shortcuts; shortcuts_determined_ = true; cancellation_flag_ = NULL; @@ -161,7 +161,7 @@ std::string SerializeSettingsReport(const ResettableSettingsSnapshot& snapshot, int field_mask) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); base::DictionaryValue dict; if (field_mask & ResettableSettingsSnapshot::STARTUP_MODE) { @@ -248,7 +248,7 @@ Profile* profile, const ResettableSettingsSnapshot& snapshot) { DCHECK(profile); - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); scoped_ptr<base::ListValue> list(new base::ListValue); AddPair(list.get(), l10n_util::GetStringUTF16(IDS_RESET_PROFILE_SETTINGS_LOCALE),
diff --git a/chrome/browser/profiles/chrome_version_service.cc b/chrome/browser/profiles/chrome_version_service.cc index b81b417..b5315b9c 100644 --- a/chrome/browser/profiles/chrome_version_service.cc +++ b/chrome/browser/profiles/chrome_version_service.cc
@@ -13,10 +13,7 @@ // static void ChromeVersionService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kProfileCreatedByVersion, - "1.0.0.0", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kProfileCreatedByVersion, "1.0.0.0"); } // static
diff --git a/chrome/browser/profiles/gaia_info_update_service_factory.cc b/chrome/browser/profiles/gaia_info_update_service_factory.cc index a173d68c..8c8978cf 100644 --- a/chrome/browser/profiles/gaia_info_update_service_factory.cc +++ b/chrome/browser/profiles/gaia_info_update_service_factory.cc
@@ -42,12 +42,8 @@ void GAIAInfoUpdateServiceFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* prefs) { - prefs->RegisterInt64Pref(prefs::kProfileGAIAInfoUpdateTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->RegisterStringPref(prefs::kProfileGAIAInfoPictureURL, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs->RegisterInt64Pref(prefs::kProfileGAIAInfoUpdateTime, 0); + prefs->RegisterStringPref(prefs::kProfileGAIAInfoPictureURL, std::string()); } bool GAIAInfoUpdateServiceFactory::ServiceIsNULLWhileTesting() const {
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc index 1c79bf9..a363530f 100644 --- a/chrome/browser/profiles/off_the_record_profile_impl.cc +++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -415,7 +415,7 @@ content::BrowserPluginGuestManager* OffTheRecordProfileImpl::GetGuestManager() { #if defined(ENABLE_EXTENSIONS) - return extensions::GuestViewManager::FromBrowserContextIfAvailable(this); + return extensions::GuestViewManager::FromBrowserContext(this); #else return NULL; #endif
diff --git a/chrome/browser/profiles/off_the_record_profile_io_data.cc b/chrome/browser/profiles/off_the_record_profile_io_data.cc index 9cf6632..d5c48335 100644 --- a/chrome/browser/profiles/off_the_record_profile_io_data.cc +++ b/chrome/browser/profiles/off_the_record_profile_io_data.cc
@@ -48,25 +48,25 @@ : io_data_(new OffTheRecordProfileIOData(profile->GetProfileType())), profile_(profile), initialized_(false) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(profile); } OffTheRecordProfileIOData::Handle::~Handle() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); io_data_->ShutdownOnUIThread(GetAllContextGetters().Pass()); } content::ResourceContext* OffTheRecordProfileIOData::Handle::GetResourceContext() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); LazyInitialize(); return GetResourceContextNoInit(); } content::ResourceContext* OffTheRecordProfileIOData::Handle::GetResourceContextNoInit() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Don't call LazyInitialize here, since the resource context is created at // the beginning of initalization and is used by some members while they're // being initialized (i.e. AppCacheService). @@ -80,7 +80,7 @@ // TODO(oshima): Re-enable when ChromeOS only accesses the profile on the UI // thread. #if !defined(OS_CHROMEOS) - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #endif // defined(OS_CHROMEOS) LazyInitialize(); DCHECK(!main_request_context_getter_.get()); @@ -91,7 +91,7 @@ scoped_refptr<ChromeURLRequestContextGetter> OffTheRecordProfileIOData::Handle::GetExtensionsRequestContextGetter() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); LazyInitialize(); if (!extensions_request_context_getter_.get()) { extensions_request_context_getter_ = @@ -104,7 +104,7 @@ OffTheRecordProfileIOData::Handle::GetIsolatedAppRequestContextGetter( const base::FilePath& partition_path, bool in_memory) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!partition_path.empty()); LazyInitialize(); @@ -122,7 +122,7 @@ bool in_memory, content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!partition_path.empty()); LazyInitialize(); @@ -149,7 +149,7 @@ DevToolsNetworkController* OffTheRecordProfileIOData::Handle::GetDevToolsNetworkController() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return io_data_->network_controller(); }
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index 4f65b32..13d0381 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc
@@ -84,87 +84,44 @@ std::string(), user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); #endif - registry->RegisterBooleanPref( - prefs::kSessionExitedCleanly, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kSessionExitType, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kSessionExitedCleanly, true); + registry->RegisterStringPref(prefs::kSessionExitType, std::string()); registry->RegisterBooleanPref( prefs::kSafeBrowsingEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kSafeBrowsingExtendedReportingEnabled, + false); + registry->RegisterBooleanPref(prefs::kSafeBrowsingProceedAnywayDisabled, + false); + registry->RegisterBooleanPref(prefs::kSSLErrorOverrideAllowed, true); + registry->RegisterDictionaryPref(prefs::kSafeBrowsingIncidentsSent); registry->RegisterBooleanPref( - prefs::kSafeBrowsingExtendedReportingEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kSafeBrowsingProceedAnywayDisabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kSafeBrowsingIncidentsSent, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kSafeBrowsingExtendedReportingOptInAllowed, true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kSafeBrowsingExtendedReportingOptInAllowed, true); #if defined(ENABLE_GOOGLE_NOW) - registry->RegisterBooleanPref( - prefs::kGoogleGeolocationAccessEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kGoogleGeolocationAccessEnabled, false); #endif // This pref is intentionally outside the above #if. That flag corresponds // to the Notifier extension and does not gate the launcher page. // TODO(skare): Remove or rename ENABLE_GOOGLE_NOW: http://crbug.com/459827. - registry->RegisterBooleanPref( - prefs::kGoogleNowLauncherEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDisableExtensions, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kGoogleNowLauncherEnabled, true); + registry->RegisterBooleanPref(prefs::kDisableExtensions, false); #if defined(ENABLE_EXTENSIONS) - registry->RegisterBooleanPref( - extensions::pref_names::kAlertsInitialized, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(extensions::pref_names::kAlertsInitialized, + false); #endif - registry->RegisterStringPref( - prefs::kSelectFileLastDirectory, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kSelectFileLastDirectory, std::string()); // TODO(wjmaclean): remove the following two prefs once migration to per- // partition zoom is complete. - registry->RegisterDoublePref( - prefs::kDefaultZoomLevelDeprecated, - 0.0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kPerHostZoomLevelsDeprecated, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDoublePref(prefs::kDefaultZoomLevelDeprecated, 0.0); + registry->RegisterDictionaryPref(prefs::kPerHostZoomLevelsDeprecated); - registry->RegisterDictionaryPref( - prefs::kPartitionDefaultZoomLevel, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kPartitionPerHostZoomLevels, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultApps, - "install", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kSpeechRecognitionFilterProfanities, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kProfileIconVersion, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kPartitionDefaultZoomLevel); + registry->RegisterDictionaryPref(prefs::kPartitionPerHostZoomLevels); + registry->RegisterStringPref(prefs::kDefaultApps, "install"); + registry->RegisterBooleanPref(prefs::kSpeechRecognitionFilterProfanities, + true); + registry->RegisterIntegerPref(prefs::kProfileIconVersion, 0); #if defined(OS_CHROMEOS) // TODO(dilmah): For OS_CHROMEOS we maintain kApplicationLocale in both // local state and user's profile. For other platforms we maintain @@ -175,35 +132,21 @@ prefs::kApplicationLocale, std::string(), user_prefs::PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF); - registry->RegisterStringPref( - prefs::kApplicationLocaleBackup, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kApplicationLocaleAccepted, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kCurrentWallpaperAppName, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kApplicationLocaleBackup, std::string()); + registry->RegisterStringPref(prefs::kApplicationLocaleAccepted, + std::string()); + registry->RegisterStringPref(prefs::kCurrentWallpaperAppName, std::string()); #endif #if defined(OS_ANDROID) - registry->RegisterBooleanPref( - prefs::kDevToolsRemoteEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kDevToolsRemoteEnabled, false); #endif data_reduction_proxy::RegisterSyncableProfilePrefs(registry); #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && !defined(OS_IOS) // Preferences related to the avatar bubble and user manager tutorials. - registry->RegisterIntegerPref( - prefs::kProfileAvatarTutorialShown, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kProfileAvatarTutorialShown, 0); #endif }
diff --git a/chrome/browser/profiles/profile_destroyer_unittest.cc b/chrome/browser/profiles/profile_destroyer_unittest.cc index d401041..8ffcab22 100644 --- a/chrome/browser/profiles/profile_destroyer_unittest.cc +++ b/chrome/browser/profiles/profile_destroyer_unittest.cc
@@ -21,7 +21,7 @@ destroyed_otr_profile_(false) { set_incognito(true); } - virtual void DestroyOffTheRecordProfile() override { + void DestroyOffTheRecordProfile() override { destroyed_otr_profile_ = true; } bool destroyed_otr_profile_; @@ -35,11 +35,11 @@ DCHECK_EQ(kNull, living_instance_); living_instance_ = this; } - virtual ~TestingOriginalDestructionProfile() { + ~TestingOriginalDestructionProfile() override { DCHECK_EQ(this, living_instance_); living_instance_ = NULL; } - virtual void DestroyOffTheRecordProfile() override { + void DestroyOffTheRecordProfile() override { SetOffTheRecordProfile(NULL); destroyed_otr_profile_ = true; } @@ -62,7 +62,7 @@ ProfileDestroyerTest() : off_the_record_profile_(NULL) {} protected: - virtual TestingProfile* CreateProfile() override { + TestingProfile* CreateProfile() override { if (off_the_record_profile_ == NULL) off_the_record_profile_ = new TestingOffTheRecordDestructionProfile(); return off_the_record_profile_;
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc index ab7237b..1b98bcd4 100644 --- a/chrome/browser/profiles/profile_downloader.cc +++ b/chrome/browser/profiles/profile_downloader.cc
@@ -205,7 +205,7 @@ void ProfileDownloader::StartForAccount(const std::string& account_id) { VLOG(1) << "Starting profile downloader..."; - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); ProfileOAuth2TokenService* service = ProfileOAuth2TokenServiceFactory::GetForProfile( @@ -349,7 +349,7 @@ } void ProfileDownloader::OnURLFetchComplete(const net::URLFetcher* source) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); std::string data; source->GetResponseAsString(&data); bool network_error = @@ -371,7 +371,7 @@ } void ProfileDownloader::OnImageDecoded(const SkBitmap& decoded_image) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); int image_size = delegate_->GetDesiredImageSideLength(); profile_picture_ = skia::ImageOperations::Resize( decoded_image, @@ -383,7 +383,7 @@ } void ProfileDownloader::OnDecodeImageFailed() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); delegate_->OnProfileDownloadFailure( this, ProfileDownloaderDelegate::IMAGE_DECODE_FAILED); }
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 106a677..a491300 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -309,30 +309,12 @@ // static void ProfileImpl::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kSavingBrowserHistoryDisabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kAllowDeletingBrowserHistory, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kSigninAllowed, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kForceGoogleSafeSearch, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kForceYouTubeSafetyMode, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kRecordHistory, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled, false); + registry->RegisterBooleanPref(prefs::kAllowDeletingBrowserHistory, true); + registry->RegisterBooleanPref(prefs::kSigninAllowed, true); + registry->RegisterBooleanPref(prefs::kForceGoogleSafeSearch, false); + registry->RegisterBooleanPref(prefs::kForceYouTubeSafetyMode, false); + registry->RegisterBooleanPref(prefs::kRecordHistory, false); registry->RegisterIntegerPref( prefs::kProfileAvatarIndex, -1, @@ -352,10 +334,7 @@ prefs::kProfileUsingDefaultName, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kSupervisedUserId, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kSupervisedUserId, std::string()); registry->RegisterStringPref(prefs::kProfileName, std::string(), user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); @@ -363,33 +342,15 @@ std::string(), user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); #if defined(ENABLE_PRINTING) - registry->RegisterBooleanPref( - prefs::kPrintingEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kPrintingEnabled, true); #endif - registry->RegisterBooleanPref( - prefs::kPrintPreviewDisabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kForceEphemeralProfiles, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kPrintPreviewDisabled, false); + registry->RegisterBooleanPref(prefs::kForceEphemeralProfiles, false); // Initialize the cache prefs. - registry->RegisterFilePathPref( - prefs::kDiskCacheDir, - base::FilePath(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kDiskCacheSize, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kMediaCacheSize, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterFilePathPref(prefs::kDiskCacheDir, base::FilePath()); + registry->RegisterIntegerPref(prefs::kDiskCacheSize, 0); + registry->RegisterIntegerPref(prefs::kMediaCacheSize, 0); // Deprecated. Kept around for migration. registry->RegisterBooleanPref( @@ -1053,7 +1014,7 @@ content::BrowserPluginGuestManager* ProfileImpl::GetGuestManager() { #if defined(ENABLE_EXTENSIONS) - return extensions::GuestViewManager::FromBrowserContextIfAvailable(this); + return extensions::GuestViewManager::FromBrowserContext(this); #else return NULL; #endif
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc index e82ef90f..827c441e 100644 --- a/chrome/browser/profiles/profile_impl_io_data.cc +++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -111,12 +111,12 @@ : io_data_(new ProfileImplIOData), profile_(profile), initialized_(false) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(profile); } ProfileImplIOData::Handle::~Handle() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (io_data_->predictor_ != NULL) { // io_data_->predictor_ might be NULL if Init() was never called // (i.e. we shut down before ProfileImpl::DoFinalInit() got called). @@ -154,7 +154,7 @@ storage::SpecialStoragePolicy* special_storage_policy, scoped_ptr<domain_reliability::DomainReliabilityMonitor> domain_reliability_monitor) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!io_data_->lazy_params_); DCHECK(predictor); @@ -207,14 +207,14 @@ content::ResourceContext* ProfileImplIOData::Handle::GetResourceContext() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); LazyInitialize(); return GetResourceContextNoInit(); } content::ResourceContext* ProfileImplIOData::Handle::GetResourceContextNoInit() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Don't call LazyInitialize here, since the resource context is created at // the beginning of initalization and is used by some members while they're // being initialized (i.e. AppCacheService). @@ -227,7 +227,7 @@ content::URLRequestInterceptorScopedVector request_interceptors, PrefService* local_state, IOThread* io_thread) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); LazyInitialize(); DCHECK(!main_request_context_getter_.get()); main_request_context_getter_ = ChromeURLRequestContextGetter::Create( @@ -249,7 +249,7 @@ scoped_refptr<ChromeURLRequestContextGetter> ProfileImplIOData::Handle::GetMediaRequestContextGetter() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); LazyInitialize(); if (!media_request_context_getter_.get()) { media_request_context_getter_ = @@ -260,7 +260,7 @@ scoped_refptr<ChromeURLRequestContextGetter> ProfileImplIOData::Handle::GetExtensionsRequestContextGetter() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); LazyInitialize(); if (!extensions_request_context_getter_.get()) { extensions_request_context_getter_ = @@ -275,7 +275,7 @@ bool in_memory, content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Check that the partition_path is not the same as the base profile path. We // expect isolated partition, which will never go to the default profile path. CHECK(partition_path != profile_->GetPath()); @@ -309,7 +309,7 @@ ProfileImplIOData::Handle::GetIsolatedMediaRequestContextGetter( const base::FilePath& partition_path, bool in_memory) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // We must have a non-default path, or this will act like the default media // context. CHECK(partition_path != profile_->GetPath()); @@ -338,14 +338,14 @@ DevToolsNetworkController* ProfileImplIOData::Handle::GetDevToolsNetworkController() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return io_data_->network_controller(); } void ProfileImplIOData::Handle::ClearNetworkingHistorySince( base::Time time, const base::Closure& completion) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); LazyInitialize(); BrowserThread::PostTask( @@ -358,7 +358,7 @@ } void ProfileImplIOData::Handle::LazyInitialize() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (initialized_) return; @@ -807,7 +807,7 @@ void ProfileImplIOData::ClearNetworkingHistorySinceOnIOThread( base::Time time, const base::Closure& completion) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(initialized()); DCHECK(transport_security_state());
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc index 583441d..3c7ba993 100644 --- a/chrome/browser/profiles/profile_info_cache.cc +++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -89,7 +89,7 @@ void SaveBitmap(scoped_ptr<ImageData> data, const base::FilePath& image_path, const base::Closure& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); // Make sure the destination directory exists. base::FilePath dir = image_path.DirName(); @@ -112,7 +112,7 @@ // will be NULL. void ReadBitmap(const base::FilePath& image_path, gfx::Image** out_image) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); *out_image = NULL; // If the path doesn't exist, don't even try reading it. @@ -137,13 +137,13 @@ void RunCallbackIfFileMissing(const base::FilePath& file_path, const base::Closure& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); if (!base::PathExists(file_path)) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); } void DeleteBitmap(const base::FilePath& image_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); base::DeleteFile(image_path, false); } @@ -1093,7 +1093,7 @@ void ProfileInfoCache::OnAvatarPictureLoaded(const base::FilePath& profile_path, const std::string& key, gfx::Image** image) const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/461175 // is fixed. tracked_objects::ScopedTracker tracking_profile1( @@ -1134,7 +1134,7 @@ void ProfileInfoCache::OnAvatarPictureSaved( const std::string& file_name, const base::FilePath& profile_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); FOR_EACH_OBSERVER(ProfileInfoCacheObserver, observer_list_,
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index fc63611..4f70cc0b 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -263,7 +263,7 @@ scoped_ptr<chromeos::TPMTokenInfoGetter> getter, const std::string& username_hash, const chromeos::TPMTokenInfo& info) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (info.tpm_is_enabled && info.token_slot_id != -1) { DVLOG(1) << "Got TPM slot for " << username_hash << ": " << info.token_slot_id; @@ -279,7 +279,7 @@ void GetTPMInfoForUserOnUIThread(const std::string& username, const std::string& username_hash) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(1) << "Getting TPM info from cryptohome for " << " " << username << " " << username_hash; scoped_ptr<chromeos::TPMTokenInfoGetter> scoped_token_info_getter = @@ -302,7 +302,7 @@ void StartTPMSlotInitializationOnIOThread(const std::string& username, const std::string& username_hash) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::UI, @@ -313,7 +313,7 @@ void StartNSSInitOnIOThread(const std::string& username, const std::string& username_hash, const base::FilePath& path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DVLOG(1) << "Starting NSS init for " << username << " hash:" << username_hash; @@ -354,7 +354,7 @@ void InvalidateContextGettersOnIO( scoped_ptr<ProfileIOData::ChromeURLRequestContextGetterVector> getters) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); ProfileIOData::ChromeURLRequestContextGetterVector::iterator iter; for (iter = getters->begin(); iter != getters->end(); ++iter) (*iter)->Invalidate(); @@ -363,7 +363,7 @@ } // namespace void ProfileIOData::InitializeOnUIThread(Profile* profile) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); PrefService* pref_service = profile->GetPrefs(); PrefService* local_state_pref_service = g_browser_process->local_state(); @@ -595,12 +595,12 @@ resource_context_(new ResourceContext(this)), initialized_on_UI_thread_(false), profile_type_(profile_type) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); } ProfileIOData::~ProfileIOData() { if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // Pull the contents of the request context maps onto the stack for sanity // checking of values in a minidump. http://crbug.com/260425 @@ -832,7 +832,7 @@ } void ProfileIOData::InitializeMetricsEnabledStateOnUIThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(OS_CHROMEOS) // Just fetch the value from ChromeOS' settings while we're on the UI thread. // TODO(stevet): For now, this value is only set on profile initialization. @@ -859,7 +859,7 @@ } bool ProfileIOData::GetMetricsEnabledStateOnIOThread() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); #if defined(OS_CHROMEOS) return enable_metrics_; #else @@ -897,13 +897,13 @@ ProfileIOData::ResourceContext::~ResourceContext() {} net::HostResolver* ProfileIOData::ResourceContext::GetHostResolver() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(io_data_->initialized_); return host_resolver_; } net::URLRequestContext* ProfileIOData::ResourceContext::GetRequestContext() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(io_data_->initialized_); return request_context_; } @@ -969,7 +969,7 @@ // static std::string ProfileIOData::GetSSLSessionCacheShard() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // The SSL session cache is partitioned by setting a string. This returns a // unique string to partition the SSL session cache. Each time we create a // new profile, we'll get a fresh SSL session cache which is separate from @@ -984,7 +984,7 @@ // The basic logic is implemented here. The specific initialization // is done in InitializeInternal(), implemented by subtypes. Static helper // functions have been provided to assist in common operations. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!initialized_); startup_metric_utils::ScopedSlowStartupUMA @@ -1200,7 +1200,7 @@ void ProfileIOData::ShutdownOnUIThread( scoped_ptr<ChromeURLRequestContextGetterVector> context_getters) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (signin_names_) signin_names_->ReleaseResourcesOnUIThread();
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 2e98ee41..19b6317 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -15,6 +15,7 @@ #include "base/metrics/histogram_macros.h" #include "base/prefs/pref_service.h" #include "base/prefs/scoped_user_pref_update.h" +#include "base/profiler/scoped_profile.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -38,6 +39,7 @@ #include "chrome/browser/profiles/startup_task_runner_service_factory.h" #include "chrome/browser/signin/account_reconcilor_factory.h" #include "chrome/browser/signin/account_tracker_service_factory.h" +#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/profile_sync_service_factory.h" @@ -55,6 +57,7 @@ #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/password_manager/core/browser/password_store.h" #include "components/signin/core/browser/account_tracker_service.h" +#include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/common/profile_management_switches.h" #include "content/public/browser/browser_thread.h" @@ -124,7 +127,7 @@ // Simple task to log the size of the current profile. void ProfileSizeTask(const base::FilePath& path, int enabled_app_count) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); const int64 kBytesInOneMB = 1024 * 1024; int64 size = ComputeFilesSize(path, FILE_PATH_LITERAL("*")); @@ -394,7 +397,7 @@ const base::string16& name, const base::string16& icon_url, const std::string& supervised_user_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); TRACE_EVENT1("browser,startup", "ProfileManager::CreateProfileAsync", "profile_path", @@ -573,7 +576,7 @@ const base::string16& icon_url, const CreateCallback& callback, const std::string& supervised_user_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); ProfileManager* profile_manager = g_browser_process->profile_manager(); @@ -589,7 +592,7 @@ // static base::FilePath ProfileManager::GetGuestProfilePath() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); ProfileManager* profile_manager = g_browser_process->profile_manager(); @@ -599,7 +602,7 @@ // static base::FilePath ProfileManager::GetSystemProfilePath() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); ProfileManager* profile_manager = g_browser_process->profile_manager(); @@ -713,7 +716,7 @@ base::Unretained(this), profile_dir, last_non_supervised_profile_path, - CreateCallback()), + callback), base::string16(), base::string16(), std::string()); @@ -727,7 +730,7 @@ // static void ProfileManager::CleanUpStaleProfiles( const std::vector<base::FilePath>& profile_paths) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); for (std::vector<base::FilePath>::const_iterator it = profile_paths.begin(); it != profile_paths.end(); ++it) { @@ -944,7 +947,7 @@ void ProfileManager::OnProfileCreated(Profile* profile, bool success, bool is_new_profile) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); ProfilesInfoMap::iterator iter = profiles_info_.find(profile->GetPath()); DCHECK(iter != profiles_info_.end()); @@ -990,6 +993,8 @@ void ProfileManager::DoFinalInit(Profile* profile, bool go_off_the_record) { TRACE_EVENT0("browser", "ProfileManager::DoFinalInit"); + TRACK_SCOPED_REGION("Startup", "ProfileManager::DoFinalInit"); + DoFinalInitForServices(profile, go_off_the_record); AddProfileToCache(profile); DoFinalInitLogging(profile); @@ -1004,6 +1009,8 @@ void ProfileManager::DoFinalInitForServices(Profile* profile, bool go_off_the_record) { TRACE_EVENT0("browser", "ProfileManager::DoFinalInitForServices"); + TRACK_SCOPED_REGION("Startup", "ProfileManager::DoFinalInitForServices"); + #if defined(ENABLE_EXTENSIONS) ProfileInfoCache& cache = GetProfileInfoCache(); extensions::ExtensionSystem::Get(profile)->InitForRegularProfile( @@ -1048,6 +1055,7 @@ DataReductionProxyChromeSettingsFactory::GetForBrowserContext(profile)-> MaybeActivateDataReductionProxy(true); + GaiaCookieManagerServiceFactory::GetForProfile(profile)->Init(); AccountTrackerServiceFactory::GetForProfile(profile)->EnableNetworkFetches(); AccountReconcilorFactory::GetForProfile(profile); } @@ -1070,6 +1078,7 @@ Profile* ProfileManager::CreateProfileHelper(const base::FilePath& path) { TRACE_EVENT0("browser", "ProfileManager::CreateProfileHelper"); SCOPED_UMA_HISTOGRAM_TIMER("Profile.CreateProfileHelperTime"); + TRACK_SCOPED_REGION("Startup", "ProfileManager::CreateProfileHelper"); return Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS); } @@ -1120,6 +1129,8 @@ bool ProfileManager::AddProfile(Profile* profile) { TRACE_EVENT0("browser", "ProfileManager::AddProfile"); + TRACK_SCOPED_REGION("Startup", "ProfileManager::AddProfile"); + DCHECK(profile); // Make sure that we're not loading a profile with the same ID as a profile @@ -1140,6 +1151,8 @@ Profile* ProfileManager::CreateAndInitializeProfile( const base::FilePath& profile_dir) { TRACE_EVENT0("browser", "ProfileManager::CreateAndInitializeProfile"); + TRACK_SCOPED_REGION( + "Startup", "ProfileManager::CreateAndInitializeProfile"); SCOPED_UMA_HISTOGRAM_LONG_TIMER("Profile.CreateAndInitializeProfile"); // CHECK that we are not trying to load the same profile twice, to prevent @@ -1202,8 +1215,14 @@ password_store->RemoveLoginsCreatedBetween(base::Time(), base::Time::Max()); } + } else { + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&NukeProfileFromDisk, profile_dir)); } + // Queue even a profile that was Nuked so it will be MarkedForDeletion and so + // CreateProfileAsync can't create it. QueueProfileDirectoryForDeletion(profile_dir); cache.DeleteProfileFromCache(profile_dir); ProfileMetrics::UpdateReportedProfilesStatistics(this);
diff --git a/chrome/browser/profiles/profile_metrics.cc b/chrome/browser/profiles/profile_metrics.cc index 0e42555..19e0af7 100644 --- a/chrome/browser/profiles/profile_metrics.cc +++ b/chrome/browser/profiles/profile_metrics.cc
@@ -56,7 +56,7 @@ ProfileMetrics::ProfileType GetProfileType( const base::FilePath& profile_path) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ProfileMetrics::ProfileType metric = ProfileMetrics::SECONDARY; ProfileManager* manager = g_browser_process->profile_manager(); base::FilePath user_data_dir;
diff --git a/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc b/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc index 3d847eb2..71052b5 100644 --- a/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc +++ b/chrome/browser/profiles/profile_shortcut_manager_unittest_win.cc
@@ -41,7 +41,7 @@ fake_system_desktop_(base::DIR_COMMON_DESKTOP) { } - virtual void SetUp() override { + void SetUp() override { CoInitialize(NULL); TestingBrowserProcess* browser_process = @@ -59,7 +59,7 @@ profile_3_path_ = CreateProfileDirectory(profile_3_name_); } - virtual void TearDown() override { + void TearDown() override { message_loop_.RunUntilIdle(); // Delete all profiles and ensure their shortcuts got removed.
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc index 7327fab3..fb995c1 100644 --- a/chrome/browser/profiles/profile_shortcut_manager_win.cc +++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc
@@ -139,7 +139,7 @@ // Updates the preferences with the current icon version on icon creation // success. void OnProfileIconCreateSuccess(base::FilePath profile_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!g_browser_process->profile_manager()) return; Profile* profile = @@ -163,7 +163,7 @@ const base::FilePath& profile_path, const SkBitmap& avatar_bitmap_1x, const SkBitmap& avatar_bitmap_2x) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); if (!base::PathExists(profile_path)) { LOG(ERROR) << "Profile directory " << profile_path.value() @@ -264,7 +264,7 @@ bool IsChromeShortcut(const base::FilePath& path, const base::FilePath& chrome_exe, base::string16* command_line) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); if (path.Extension() != installer::kLnkExt) return false; @@ -326,7 +326,7 @@ void RenameChromeDesktopShortcutForProfile( const base::string16& old_shortcut_filename, const base::string16& new_shortcut_filename) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); base::FilePath user_shortcuts_directory; base::FilePath system_shortcuts_directory; @@ -393,7 +393,7 @@ // thread. void CreateOrUpdateDesktopShortcutsAndIconForProfile( const CreateOrUpdateShortcutsParams& params) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); const base::FilePath shortcut_icon = CreateOrUpdateShortcutIconForProfile(params.profile_path, @@ -499,7 +499,7 @@ // shortcut(s). Must be called on the FILE thread. void DeleteDesktopShortcuts(const base::FilePath& profile_path, bool ensure_shortcuts_remain) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); base::FilePath chrome_exe; if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { @@ -550,7 +550,7 @@ // Returns true if profile at |profile_path| has any shortcuts. Does not // consider non-profile shortcuts. Must be called on the FILE thread. bool HasAnyProfileShortcuts(const base::FilePath& profile_path) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + DCHECK_CURRENTLY_ON(BrowserThread::FILE); base::FilePath chrome_exe; if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.h b/chrome/browser/profiles/profile_shortcut_manager_win.h index 30e53494..7645b8d 100644 --- a/chrome/browser/profiles/profile_shortcut_manager_win.h +++ b/chrome/browser/profiles/profile_shortcut_manager_win.h
@@ -50,38 +50,31 @@ }; explicit ProfileShortcutManagerWin(ProfileManager* manager); - virtual ~ProfileShortcutManagerWin(); + ~ProfileShortcutManagerWin() override; // ProfileShortcutManager implementation: - virtual void CreateOrUpdateProfileIcon( - const base::FilePath& profile_path) override; - virtual void CreateProfileShortcut( - const base::FilePath& profile_path) override; - virtual void RemoveProfileShortcuts( - const base::FilePath& profile_path) override; - virtual void HasProfileShortcuts( - const base::FilePath& profile_path, - const base::Callback<void(bool)>& callback) override; - virtual void GetShortcutProperties(const base::FilePath& profile_path, - base::CommandLine* command_line, - base::string16* name, - base::FilePath* icon_path) override; + void CreateOrUpdateProfileIcon(const base::FilePath& profile_path) override; + void CreateProfileShortcut(const base::FilePath& profile_path) override; + void RemoveProfileShortcuts(const base::FilePath& profile_path) override; + void HasProfileShortcuts(const base::FilePath& profile_path, + const base::Callback<void(bool)>& callback) override; + void GetShortcutProperties(const base::FilePath& profile_path, + base::CommandLine* command_line, + base::string16* name, + base::FilePath* icon_path) override; // ProfileInfoCacheObserver implementation: - virtual void OnProfileAdded(const base::FilePath& profile_path) override; - virtual void OnProfileWasRemoved( - const base::FilePath& profile_path, - const base::string16& profile_name) override; - virtual void OnProfileNameChanged( - const base::FilePath& profile_path, - const base::string16& old_profile_name) override; - virtual void OnProfileAvatarChanged( - const base::FilePath& profile_path) override; + void OnProfileAdded(const base::FilePath& profile_path) override; + void OnProfileWasRemoved(const base::FilePath& profile_path, + const base::string16& profile_name) override; + void OnProfileNameChanged(const base::FilePath& profile_path, + const base::string16& old_profile_name) override; + void OnProfileAvatarChanged(const base::FilePath& profile_path) override; // content::NotificationObserver implementation: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; private: // Gives the profile path of an alternate profile than |profile_path|.
diff --git a/chrome/browser/profiles/profile_window.cc b/chrome/browser/profiles/profile_window.cc index 0080945c..1da2c98 100644 --- a/chrome/browser/profiles/profile_window.cc +++ b/chrome/browser/profiles/profile_window.cc
@@ -109,7 +109,7 @@ chrome::HostDesktopType desktop_type, Profile* profile, Profile::CreateStatus status) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (status != Profile::CREATE_STATUS_INITIALIZED) return;
diff --git a/chrome/browser/profiles/profile_window_browsertest.cc b/chrome/browser/profiles/profile_window_browsertest.cc index b14296c..eb83cf1 100644 --- a/chrome/browser/profiles/profile_window_browsertest.cc +++ b/chrome/browser/profiles/profile_window_browsertest.cc
@@ -113,6 +113,9 @@ ProfileManager::CreateCallback()); browser_creation_observer.Wait(); + DCHECK_NE(static_cast<Profile*>(nullptr), + g_browser_process->profile_manager()->GetProfileByPath( + ProfileManager::GetGuestProfilePath())); EXPECT_EQ(num_browsers + 1, BrowserList::GetInstance(chrome::GetActiveDesktop())->size());
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc index 8963c36b..d8f5506 100644 --- a/chrome/browser/profiles/profiles_state.cc +++ b/chrome/browser/profiles/profiles_state.cc
@@ -9,6 +9,8 @@ #include "base/prefs/pref_service.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/browsing_data/browsing_data_helper.h" +#include "chrome/browser/browsing_data/browsing_data_remover.h" #include "chrome/browser/profiles/gaia_info_update_service.h" #include "chrome/browser/profiles/gaia_info_update_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -214,4 +216,19 @@ return true; } +void RemoveBrowsingDataForProfile(const base::FilePath& profile_path) { + Profile* profile = g_browser_process->profile_manager()->GetProfileByPath( + profile_path); + if (!profile) + return; + + // For guest the browsing data is in the OTR profile. + if (profile->IsGuestSession()) + profile = profile->GetOffTheRecordProfile(); + + BrowsingDataRemover::CreateForUnboundedRange(profile)->Remove( + BrowsingDataRemover::REMOVE_ALL, BrowsingDataHelper::ALL); + // BrowsingDataRemover deletes itself. +} + } // namespace profiles
diff --git a/chrome/browser/profiles/profiles_state.h b/chrome/browser/profiles/profiles_state.h index 3259040..322a29a0 100644 --- a/chrome/browser/profiles/profiles_state.h +++ b/chrome/browser/profiles/profiles_state.h
@@ -88,6 +88,10 @@ // method. bool SetActiveProfileToGuestIfLocked(); +// If the profile given by |profile_path| is loaded in the ProfileManager, use +// a BrowsingDataRemover to delete all the Profile's data. +void RemoveBrowsingDataForProfile(const base::FilePath& profile_path); + } // namespace profiles #endif // CHROME_BROWSER_PROFILES_PROFILES_STATE_H_
diff --git a/chrome/browser/push_messaging/push_messaging_application_id.cc b/chrome/browser/push_messaging/push_messaging_application_id.cc index c6b30e7..3fc92db 100644 --- a/chrome/browser/push_messaging/push_messaging_application_id.cc +++ b/chrome/browser/push_messaging/push_messaging_application_id.cc
@@ -25,9 +25,7 @@ // static void PushMessagingApplicationId::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kPushMessagingApplicationIdMap, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kPushMessagingApplicationIdMap); } // static
diff --git a/chrome/browser/push_messaging/push_messaging_browsertest.cc b/chrome/browser/push_messaging/push_messaging_browsertest.cc index 024749f..5aafa7d 100644 --- a/chrome/browser/push_messaging/push_messaging_browsertest.cc +++ b/chrome/browser/push_messaging/push_messaging_browsertest.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/browsing_data/browsing_data_helper.h" #include "chrome/browser/browsing_data/browsing_data_remover.h" #include "chrome/browser/browsing_data/browsing_data_remover_test_util.h" +#include "chrome/browser/infobars/infobar_responder.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/notifications/notification_test_util.h" #include "chrome/browser/notifications/platform_notification_service_impl.h" @@ -32,9 +33,6 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/gcm_driver/gcm_client.h" -#include "components/infobars/core/confirm_infobar_delegate.h" -#include "components/infobars/core/infobar.h" -#include "components/infobars/core/infobar_manager.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test_utils.h" @@ -46,50 +44,6 @@ #endif namespace { -// Responds to a confirm infobar by accepting or cancelling it. Responds to at -// most one infobar. -class InfoBarResponder : public infobars::InfoBarManager::Observer { - public: - InfoBarResponder(Browser* browser, bool accept) - : infobar_service_(InfoBarService::FromWebContents( - browser->tab_strip_model()->GetActiveWebContents())), - accept_(accept), - has_observed_(false) { - infobar_service_->AddObserver(this); - } - - ~InfoBarResponder() override { infobar_service_->RemoveObserver(this); } - - // infobars::InfoBarManager::Observer - void OnInfoBarAdded(infobars::InfoBar* infobar) override { - if (has_observed_) - return; - has_observed_ = true; - ConfirmInfoBarDelegate* delegate = - infobar->delegate()->AsConfirmInfoBarDelegate(); - DCHECK(delegate); - - // Respond to the infobar asynchronously, like a person. - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind( - &InfoBarResponder::Respond, base::Unretained(this), delegate)); - } - - private: - void Respond(ConfirmInfoBarDelegate* delegate) { - if (accept_) { - delegate->Accept(); - } else { - delegate->Cancel(); - } - } - - InfoBarService* infobar_service_; - bool accept_; - bool has_observed_; -}; - // Class to instantiate on the stack that is meant to be used with // FakeGCMProfileService. The ::Run() method follows the signature of // FakeGCMProfileService::UnregisterCallback. @@ -199,6 +153,10 @@ PushMessagingApplicationId GetServiceWorkerAppId( int64 service_worker_registration_id); + void SendMessageAndWaitUntilHandled( + const PushMessagingApplicationId& app_id, + const gcm::GCMClient::IncomingMessage& message); + net::SpawnedTestServer* https_server() const { return https_server_.get(); } gcm::FakeGCMProfileService* gcm_service() const { return gcm_service_; } @@ -222,6 +180,11 @@ virtual Browser* GetBrowser() const { return browser(); } + InfoBarService* GetInfoBarService() { + return InfoBarService::FromWebContents( + GetBrowser()->tab_strip_model()->GetActiveWebContents()); + } + private: scoped_ptr<net::SpawnedTestServer> https_server_; gcm::FakeGCMProfileService* gcm_service_; @@ -255,7 +218,7 @@ EXPECT_TRUE(RunScript("registerServiceWorker()", &script_result)); EXPECT_EQ("ok - service worker registered", script_result); - InfoBarResponder accepting_responder(GetBrowser(), true); + InfoBarResponder accepting_responder(GetInfoBarService(), true); EXPECT_TRUE(RunScript("requestNotificationPermission()", &script_result)); EXPECT_EQ("permission status - granted", script_result); @@ -273,6 +236,15 @@ return application_id; } +void PushMessagingBrowserTest::SendMessageAndWaitUntilHandled( + const PushMessagingApplicationId& app_id, + const gcm::GCMClient::IncomingMessage& message) { + base::RunLoop run_loop; + push_service()->SetMessageCallbackForTesting(run_loop.QuitClosure()); + push_service()->OnMessage(app_id.app_id_guid(), message); + run_loop.Run(); +} + IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, SubscribeSuccessNotificationsGranted) { TryToSubscribeSuccessfully("1-0" /* expected_push_subscription_id */); @@ -289,7 +261,7 @@ ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); ASSERT_EQ("ok - service worker registered", script_result); - InfoBarResponder accepting_responder(GetBrowser(), true); + InfoBarResponder accepting_responder(GetInfoBarService(), true); ASSERT_TRUE(RunScript("subscribePush()", &script_result)); EXPECT_EQ(std::string(kPushMessagingEndpoint) + " - 1-0", script_result); @@ -305,7 +277,7 @@ ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); ASSERT_EQ("ok - service worker registered", script_result); - InfoBarResponder cancelling_responder(GetBrowser(), false); + InfoBarResponder cancelling_responder(GetInfoBarService(), false); ASSERT_TRUE(RunScript("requestNotificationPermission();", &script_result)); ASSERT_EQ("permission status - denied", script_result); @@ -320,7 +292,7 @@ ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); ASSERT_EQ("ok - service worker registered", script_result); - InfoBarResponder accepting_responder(GetBrowser(), true); + InfoBarResponder accepting_responder(GetInfoBarService(), true); ASSERT_TRUE(RunScript("requestNotificationPermission();", &script_result)); ASSERT_EQ("permission status - granted", script_result); @@ -486,7 +458,7 @@ message.sender_id = "1234567890"; for (int n = 0; n < 2; n++) { message.data["data"] = "testdata"; - push_service()->OnMessage(app_id.app_id_guid(), message); + SendMessageAndWaitUntilHandled(app_id, message); ASSERT_TRUE(RunScript("resultQueue.pop()", &script_result)); EXPECT_EQ("testdata", script_result); EXPECT_EQ(0u, notification_manager()->GetNotificationCount()); @@ -501,12 +473,12 @@ // should show a forced one, but only on the 2nd occurrence since we allow one // mistake per 10 push events. message.data["data"] = "testdata"; - push_service()->OnMessage(app_id.app_id_guid(), message); + SendMessageAndWaitUntilHandled(app_id, message); ASSERT_TRUE(RunScript("resultQueue.pop()", &script_result, web_contents)); EXPECT_EQ("testdata", script_result); EXPECT_EQ(0u, notification_manager()->GetNotificationCount()); message.data["data"] = "testdata"; - push_service()->OnMessage(app_id.app_id_guid(), message); + SendMessageAndWaitUntilHandled(app_id, message); ASSERT_TRUE(RunScript("resultQueue.pop()", &script_result, web_contents)); EXPECT_EQ("testdata", script_result); @@ -520,7 +492,7 @@ // Currently, this notification will stick around until the user or webapp // explicitly dismisses it (though we may change this later). message.data["data"] = "shownotification"; - push_service()->OnMessage(app_id.app_id_guid(), message); + SendMessageAndWaitUntilHandled(app_id, message); ASSERT_TRUE(RunScript("resultQueue.pop()", &script_result, web_contents)); EXPECT_EQ("shownotification", script_result); EXPECT_EQ(2u, notification_manager()->GetNotificationCount()); @@ -532,7 +504,7 @@ // should not show a forced one. message.data["data"] = "shownotification"; for (int n = 0; n < 9; n++) { - push_service()->OnMessage(app_id.app_id_guid(), message); + SendMessageAndWaitUntilHandled(app_id, message); ASSERT_TRUE(RunScript("resultQueue.pop()", &script_result, web_contents)); EXPECT_EQ("shownotification", script_result); EXPECT_EQ(1u, notification_manager()->GetNotificationCount()); @@ -544,7 +516,7 @@ // Now that 10 push messages in a row have shown notifications, we should // allow the next one to mistakenly not show a notification. message.data["data"] = "testdata"; - push_service()->OnMessage(app_id.app_id_guid(), message); + SendMessageAndWaitUntilHandled(app_id, message); ASSERT_TRUE(RunScript("resultQueue.pop()", &script_result, web_contents)); EXPECT_EQ("testdata", script_result); EXPECT_EQ(0u, notification_manager()->GetNotificationCount()); @@ -589,45 +561,45 @@ notification_manager()->GetNotificationAt(0).tag()); // Verify that the renderer process hasn't crashed. - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); } #endif -IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, HasPermissionSaysDefault) { +IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PermissionStateSaysDefault) { std::string script_result; ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); ASSERT_EQ("ok - service worker registered", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); ASSERT_EQ("permission status - default", script_result); } -IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, HasPermissionSaysGranted) { +IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PermissionStateSaysGranted) { std::string script_result; ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); ASSERT_EQ("ok - service worker registered", script_result); - InfoBarResponder accepting_responder(GetBrowser(), true); + InfoBarResponder accepting_responder(GetInfoBarService(), true); ASSERT_TRUE(RunScript("requestNotificationPermission();", &script_result)); EXPECT_EQ("permission status - granted", script_result); ASSERT_TRUE(RunScript("subscribePush()", &script_result)); EXPECT_EQ(std::string(kPushMessagingEndpoint) + " - 1-0", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); } -IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, HasPermissionSaysDenied) { +IN_PROC_BROWSER_TEST_F(PushMessagingBrowserTest, PermissionStateSaysDenied) { std::string script_result; ASSERT_TRUE(RunScript("registerServiceWorker()", &script_result)); ASSERT_EQ("ok - service worker registered", script_result); - InfoBarResponder cancelling_responder(GetBrowser(), false); + InfoBarResponder cancelling_responder(GetInfoBarService(), false); ASSERT_TRUE(RunScript("requestNotificationPermission();", &script_result)); EXPECT_EQ("permission status - denied", script_result); @@ -635,7 +607,7 @@ EXPECT_EQ("AbortError - Registration failed - permission denied", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - denied", script_result); } @@ -690,7 +662,7 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); EXPECT_EQ("true - subscribed", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); scoped_refptr<content::MessageLoopRunner> message_loop_runner = @@ -703,7 +675,7 @@ message_loop_runner->Run(); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - default", script_result); ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); @@ -719,7 +691,7 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); EXPECT_EQ("true - subscribed", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); scoped_refptr<content::MessageLoopRunner> message_loop_runner = @@ -737,7 +709,7 @@ message_loop_runner->Run(); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - default", script_result); ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); @@ -753,7 +725,7 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); EXPECT_EQ("true - subscribed", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); scoped_refptr<content::MessageLoopRunner> message_loop_runner = @@ -771,7 +743,7 @@ message_loop_runner->Run(); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - denied", script_result); ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); @@ -787,7 +759,7 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); EXPECT_EQ("true - subscribed", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); scoped_refptr<content::MessageLoopRunner> message_loop_runner = @@ -800,7 +772,7 @@ message_loop_runner->Run(); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - default", script_result); ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); @@ -816,7 +788,7 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); EXPECT_EQ("true - subscribed", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); scoped_refptr<content::MessageLoopRunner> message_loop_runner = @@ -834,7 +806,7 @@ message_loop_runner->Run(); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - default", script_result); ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); @@ -850,7 +822,7 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); EXPECT_EQ("true - subscribed", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); scoped_refptr<content::MessageLoopRunner> message_loop_runner = @@ -868,7 +840,7 @@ message_loop_runner->Run(); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - denied", script_result); ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); @@ -884,7 +856,7 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); EXPECT_EQ("true - subscribed", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); scoped_refptr<content::MessageLoopRunner> message_loop_runner = @@ -908,7 +880,7 @@ message_loop_runner->Run(); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); @@ -928,7 +900,7 @@ ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); EXPECT_EQ("true - subscribed", script_result); - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); scoped_refptr<content::MessageLoopRunner> message_loop_runner = @@ -969,7 +941,7 @@ // The Push service should not unsubcribe |origin| because at no point it was // left without permission to use Push. - ASSERT_TRUE(RunScript("hasPermission()", &script_result)); + ASSERT_TRUE(RunScript("permissionState()", &script_result)); EXPECT_EQ("permission status - granted", script_result); ASSERT_TRUE(RunScript("hasSubscription()", &script_result)); @@ -1005,7 +977,7 @@ // This shouldn't (asynchronously) cause a DCHECK. // TODO(johnme): Get this test running on Android, which has a different - // codepath due to sender_id being required for unsubscribeing there. + // codepath due to sender_id being required for unsubscribing there. GetBrowser()->profile()->GetHostContentSettingsMap()-> ClearSettingsForOneType(CONTENT_SETTINGS_TYPE_PUSH_MESSAGING);
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.cc b/chrome/browser/push_messaging/push_messaging_service_impl.cc index 215b479..ea47be01 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.cc +++ b/chrome/browser/push_messaging/push_messaging_service_impl.cc
@@ -96,10 +96,7 @@ // static void PushMessagingServiceImpl::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kPushMessagingRegistrationCount, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kPushMessagingRegistrationCount, 0); PushMessagingApplicationId::RegisterProfilePrefs(registry); } @@ -184,11 +181,15 @@ void PushMessagingServiceImpl::OnMessage( const std::string& app_id, const gcm::GCMClient::IncomingMessage& message) { + base::Closure message_handled_closure = + message_callback_for_testing_.is_null() ? base::Bind(&base::DoNothing) + : message_callback_for_testing_; PushMessagingApplicationId application_id = PushMessagingApplicationId::Get(profile_, app_id); // Drop message and unregister if app id was unknown (maybe recently deleted). if (!application_id.IsValid()) { DeliverMessageCallback(app_id, GURL::EmptyGURL(), -1, message, + message_handled_closure, content::PUSH_DELIVERY_STATUS_UNKNOWN_APP_ID); return; } @@ -196,7 +197,7 @@ if (!HasPermission(application_id.origin())) { DeliverMessageCallback(app_id, application_id.origin(), application_id.service_worker_registration_id(), - message, + message, message_handled_closure, content::PUSH_DELIVERY_STATUS_PERMISSION_DENIED); return; } @@ -238,7 +239,8 @@ base::Bind(&PushMessagingServiceImpl::DeliverMessageCallback, weak_factory_.GetWeakPtr(), application_id.app_id_guid(), application_id.origin(), - application_id.service_worker_registration_id(), message)); + application_id.service_worker_registration_id(), message, + message_handled_closure)); } void PushMessagingServiceImpl::DeliverMessageCallback( @@ -246,6 +248,7 @@ const GURL& requesting_origin, int64 service_worker_registration_id, const gcm::GCMClient::IncomingMessage& message, + const base::Closure& message_handled_closure, content::PushDeliveryStatus status) { // TODO(mvanouwerkerk): Show a warning in the developer console of the // Service Worker corresponding to app_id (and/or on an internals page). @@ -256,22 +259,27 @@ // deliberately failing in order to avoid having to show notifications). case content::PUSH_DELIVERY_STATUS_SUCCESS: case content::PUSH_DELIVERY_STATUS_EVENT_WAITUNTIL_REJECTED: - RequireUserVisibleUX(requesting_origin, service_worker_registration_id); + RequireUserVisibleUX(requesting_origin, service_worker_registration_id, + message_handled_closure); break; case content::PUSH_DELIVERY_STATUS_INVALID_MESSAGE: case content::PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR: + message_handled_closure.Run(); break; case content::PUSH_DELIVERY_STATUS_UNKNOWN_APP_ID: case content::PUSH_DELIVERY_STATUS_PERMISSION_DENIED: case content::PUSH_DELIVERY_STATUS_NO_SERVICE_WORKER: - Unregister(app_id_guid, message.sender_id, UnregisterCallback()); + Unregister(app_id_guid, message.sender_id, + base::Bind(&UnregisterCallbackToClosure, + message_handled_closure)); break; } RecordDeliveryStatus(status); } void PushMessagingServiceImpl::RequireUserVisibleUX( - const GURL& requesting_origin, int64 service_worker_registration_id) { + const GURL& requesting_origin, int64 service_worker_registration_id, + const base::Closure& message_handled_closure) { #if defined(ENABLE_NOTIFICATIONS) // TODO(johnme): Relax this heuristic slightly. PlatformNotificationServiceImpl* notification_service = @@ -342,11 +350,15 @@ base::Bind(&PushMessagingServiceImpl::DidGetNotificationsShown, weak_factory_.GetWeakPtr(), requesting_origin, service_worker_registration_id, - notification_shown, notification_needed)); + notification_shown, notification_needed, + message_handled_closure)); } else { RecordUserVisibleStatus( content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_AND_NOT_SHOWN); + message_handled_closure.Run(); } +#else + message_handled_closure.Run(); #endif // defined(ENABLE_NOTIFICATIONS) } @@ -356,6 +368,7 @@ void PushMessagingServiceImpl::DidGetNotificationsShown( const GURL& requesting_origin, int64 service_worker_registration_id, bool notification_shown, bool notification_needed, + const base::Closure& message_handled_closure, const std::string& data, bool success, bool not_found) { content::ServiceWorkerContext* service_worker_context = content::BrowserContext::GetStoragePartitionForSite( @@ -367,6 +380,7 @@ // needed but not shown. We manipulate it in bitset form. std::bitset<MISSED_NOTIFICATIONS_LENGTH> missed_notifications(data); + DCHECK(notification_shown || notification_needed); // Caller must ensure this bool needed_but_not_shown = notification_needed && !notification_shown; // New entries go at the end, and old ones are shifted off the beginning once @@ -385,45 +399,52 @@ notification_needed ? content::PUSH_USER_VISIBLE_STATUS_REQUIRED_AND_SHOWN : content::PUSH_USER_VISIBLE_STATUS_NOT_REQUIRED_BUT_SHOWN); + message_handled_closure.Run(); return; } - if (needed_but_not_shown) { - if (missed_notifications.count() <= 1) { // apply grace - RecordUserVisibleStatus( - content::PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_USED_GRACE); - return; - } + DCHECK(needed_but_not_shown); + if (missed_notifications.count() <= 1) { // Apply grace. RecordUserVisibleStatus( - content:: - PUSH_USER_VISIBLE_STATUS_REQUIRED_BUT_NOT_SHOWN_GRACE_EXCEEDED); - rappor::SampleDomainAndRegistryFromGURL( - g_browser_process->rappor_service(), - "PushMessaging.GenericNotificationShown.Origin", - requesting_origin); - // 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. - // TODO(johnme): The generic notification should probably automatically - // close itself when the next push message arrives? - content::PlatformNotificationData notification_data; - // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698 - notification_data.title = base::UTF8ToUTF16(requesting_origin.host()); - notification_data.direction = - content::PlatformNotificationData::NotificationDirectionLeftToRight; - notification_data.body = - l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY); - notification_data.tag = kPushMessagingForcedNotificationTag; - notification_data.icon = GURL(); // TODO(johnme): Better icon? - notification_data.silent = true; - PlatformNotificationServiceImpl* notification_service = - PlatformNotificationServiceImpl::GetInstance(); - notification_service->DisplayPersistentNotification( - profile_, - service_worker_registration_id, - requesting_origin, - SkBitmap() /* icon */, - notification_data); + 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); + rappor::SampleDomainAndRegistryFromGURL( + g_browser_process->rappor_service(), + "PushMessaging.GenericNotificationShown.Origin", + requesting_origin); + // 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. + // TODO(johnme): The generic notification should probably automatically + // close itself when the next push message arrives? + content::PlatformNotificationData notification_data; + // TODO(johnme): Switch to FormatOriginForDisplay from crbug.com/402698 + notification_data.title = base::UTF8ToUTF16(requesting_origin.host()); + notification_data.direction = + content::PlatformNotificationData::NotificationDirectionLeftToRight; + notification_data.body = + l10n_util::GetStringUTF16(IDS_PUSH_MESSAGING_GENERIC_NOTIFICATION_BODY); + notification_data.tag = kPushMessagingForcedNotificationTag; + notification_data.icon = GURL(); // TODO(johnme): Better icon? + notification_data.silent = true; + PlatformNotificationServiceImpl* notification_service = + PlatformNotificationServiceImpl::GetInstance(); + notification_service->DisplayPersistentNotification( + profile_, + service_worker_registration_id, + requesting_origin, + SkBitmap() /* icon */, + notification_data); + message_handled_closure.Run(); +} + +void PushMessagingServiceImpl::SetMessageCallbackForTesting( + const base::Closure& callback) { + message_callback_for_testing_ = callback; } // Other gcm::GCMAppHandler methods -------------------------------------------
diff --git a/chrome/browser/push_messaging/push_messaging_service_impl.h b/chrome/browser/push_messaging/push_messaging_service_impl.h index 01de398..2a4ed65 100644 --- a/chrome/browser/push_messaging/push_messaging_service_impl.h +++ b/chrome/browser/push_messaging/push_messaging_service_impl.h
@@ -90,6 +90,7 @@ // KeyedService implementation. void Shutdown() override; + void SetMessageCallbackForTesting(const base::Closure& callback); void SetContentSettingChangedCallbackForTesting( const base::Closure& callback); @@ -104,6 +105,7 @@ const GURL& requesting_origin, int64 service_worker_registration_id, const gcm::GCMClient::IncomingMessage& message, + const base::Closure& message_handled_closure, content::PushDeliveryStatus status); // Developers are required to display a Web Notification in response to an @@ -111,12 +113,14 @@ // happened in the background. When they forget to do so, display a default // notification on their behalf. void RequireUserVisibleUX(const GURL& requesting_origin, - int64 service_worker_registration_id); + int64 service_worker_registration_id, + const base::Closure& message_handled_closure); void DidGetNotificationsShown( const GURL& requesting_origin, int64 service_worker_registration_id, bool notification_shown, bool notification_needed, + const base::Closure& message_handled_closure, const std::string& data, bool success, bool not_found); @@ -169,6 +173,7 @@ int push_registration_count_; int pending_push_registration_count_; + base::Closure message_callback_for_testing_; base::Closure content_setting_changed_callback_for_testing_; base::WeakPtrFactory<PushMessagingServiceImpl> weak_factory_;
diff --git a/chrome/browser/renderer_context_menu/spellchecker_submenu_observer_hunspell.cc b/chrome/browser/renderer_context_menu/spellchecker_submenu_observer_hunspell.cc index dafc01e..ca943f5a 100644 --- a/chrome/browser/renderer_context_menu/spellchecker_submenu_observer_hunspell.cc +++ b/chrome/browser/renderer_context_menu/spellchecker_submenu_observer_hunspell.cc
@@ -40,7 +40,7 @@ void SpellCheckerSubMenuObserver::InitMenu( const content::ContextMenuParams& params) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Add available spell-checker languages to the sub menu. content::BrowserContext* browser_context = proxy_->GetBrowserContext();
diff --git a/chrome/browser/renderer_context_menu/spellchecker_submenu_observer_mac.cc b/chrome/browser/renderer_context_menu/spellchecker_submenu_observer_mac.cc index f8ac7ef..a90bc44d 100644 --- a/chrome/browser/renderer_context_menu/spellchecker_submenu_observer_mac.cc +++ b/chrome/browser/renderer_context_menu/spellchecker_submenu_observer_mac.cc
@@ -44,7 +44,7 @@ void SpellCheckerSubMenuObserver::InitMenu( const content::ContextMenuParams& params) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Add an item that toggles the spelling panel. submenu_model_.AddCheckItem(
diff --git a/chrome/browser/renderer_context_menu/spelling_menu_observer.cc b/chrome/browser/renderer_context_menu/spelling_menu_observer.cc index 7c37a83..35979d9a 100644 --- a/chrome/browser/renderer_context_menu/spelling_menu_observer.cc +++ b/chrome/browser/renderer_context_menu/spelling_menu_observer.cc
@@ -52,7 +52,7 @@ } void SpellingMenuObserver::InitMenu(const content::ContextMenuParams& params) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!params.misspelled_word.empty() || params.dictionary_suggestions.empty());
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc index 3244504..8643a36 100644 --- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -56,7 +56,7 @@ #include "net/url_request/url_request.h" #if !defined(DISABLE_NACL) -#include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h" +#include "chrome/browser/component_updater/pnacl_component_installer.h" #endif #if defined(ENABLE_CONFIGURATION_POLICY)
diff --git a/chrome/browser/renderer_host/pepper/device_id_fetcher.cc b/chrome/browser/renderer_host/pepper/device_id_fetcher.cc index bddfbc0..3582bdc5 100644 --- a/chrome/browser/renderer_host/pepper/device_id_fetcher.cc +++ b/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
@@ -80,11 +80,8 @@ // static void DeviceIDFetcher::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* prefs) { - prefs->RegisterBooleanPref(prefs::kEnableDRM, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->RegisterStringPref( - prefs::kDRMSalt, "", user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs->RegisterBooleanPref(prefs::kEnableDRM, true); + prefs->RegisterStringPref(prefs::kDRMSalt, ""); } // static
diff --git a/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc b/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc index 9af20a8c..b6d5b6a 100644 --- a/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc +++ b/chrome/browser/renderer_host/pepper/pepper_output_protection_message_filter.cc
@@ -170,11 +170,13 @@ window_ = rfh->GetNativeView(); if (!window_) return ui::DisplayConfigurator::kInvalidClientId; - window_->AddObserver(this); ui::DisplayConfigurator* configurator = ash::Shell::GetInstance()->display_configurator(); client_id_ = configurator->RegisterContentProtectionClient(); + + if (client_id_ != ui::DisplayConfigurator::kInvalidClientId) + window_->AddObserver(this); } return client_id_; }
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/tabs_api_handler.js b/chrome/browser/resources/chromeos/chromevox/chromevox/background/tabs_api_handler.js index cc03d57..baa004d 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/tabs_api_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/tabs_api_handler.js
@@ -32,7 +32,7 @@ this.braille_ = braille; /** @type {cvox.AbstractEarcons} @private */ this.earcons_ = earcons; - /** @type {function(string)} @private */ + /** @type {function(string, Array<string>=)} @private */ this.msg_ = cvox.ChromeVox.msgs.getMsg.bind(cvox.ChromeVox.msgs); /** * Tracks whether the active tab has finished loading.
diff --git a/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js b/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js index abee04a..96c78ca 100644 --- a/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js +++ b/chrome/browser/resources/chromeos/chromevox/common/chromevox_json.js
@@ -15,9 +15,7 @@ */ if (!cvox.ChromeVoxJSON) { - /** - * @type {Object} - */ + /** Placeholder object. */ cvox.ChromeVoxJSON = {}; }
diff --git a/chrome/browser/resources/chromeos/chromevox/common/externs.js b/chrome/browser/resources/chromeos/chromevox/common/externs.js index 7d34b6d..2e2886d4 100644 --- a/chrome/browser/resources/chromeos/chromevox/common/externs.js +++ b/chrome/browser/resources/chromeos/chromevox/common/externs.js
@@ -5,18 +5,3 @@ Range.prototype.getBoundingClientRect; Document.prototype.documentElement.innerWidth; Document.prototype.documentElement.head; - -/** @constructor */ -function WeakMap() {} - -/** - * @param {Object} key - * @return {*} - */ -WeakMap.prototype.get = function(key) {}; - -/** - * @param {Object} key - * @param {*} value - */ -WeakMap.prototype.set = function(key, value) {};
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js index 5b4e23d..22eb0ca2 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js
@@ -57,6 +57,7 @@ AutomationPredicate.leaf = function(node) { return !node.firstChild || node.role == chrome.automation.RoleType.button || + node.role == chrome.automation.RoleType.slider || node.children.every(function(n) { return n.state.invisible; });
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js index ca1563f..01eab7fe 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background.js
@@ -62,13 +62,13 @@ alert: this.onEventDefault, focus: this.onEventDefault, hover: this.onEventDefault, + loadComplete: this.onLoadComplete, menuStart: this.onEventDefault, menuEnd: this.onEventDefault, menuListValueChanged: this.onEventDefault, - loadComplete: this.onLoadComplete, textChanged: this.onTextOrTextSelectionChanged, textSelectionChanged: this.onTextOrTextSelectionChanged, - valueChanged: this.onEventDefault + valueChanged: this.onValueChanged }; // Register listeners for ... @@ -182,7 +182,7 @@ case 'continuousRead': global.isReadingContinuously = true; var continueReading = function(prevRange) { - if (!global.isReadingContinuously) + if (!global.isReadingContinuously || !this.currentRange_) return; new Output().withSpeechAndBraille( @@ -193,7 +193,7 @@ this.currentRange_ = this.currentRange_.move(cursors.Unit.NODE, Dir.FORWARD); - if (this.currentRange_.equals(prevRange)) + if (!this.currentRange_ || this.currentRange_.equals(prevRange)) global.isReadingContinuously = false; }.bind(this); @@ -320,6 +320,28 @@ }, /** + * Provides all feedback once a value changed event fires. + * @param {Object} evt + */ + onValueChanged: function(evt) { + // Don't process nodes inside of web content if ChromeVox Next is inactive. + if (evt.target.root.role != chrome.automation.RoleType.desktop && + !this.active_) + return; + + if (!evt.target.state.focused) + return; + + // Value change events fire on web text fields and text areas when pressing + // enter; suppress them. + if (!this.currentRange_ || + evt.target.role != chrome.automation.RoleType.textField) { + this.onEventDefault(evt); + this.currentRange_ = cursors.Range.fromNode(evt.target); + } + }, + + /** * Called when the automation tree is changed. * @param {chrome.automation.TreeChange} treeChange */
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js index f19913f..2fc65b4 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output.js
@@ -93,6 +93,9 @@ checkBox: { msgId: 'input_type_checkbox' }, + date: { + msgId: 'input_type_date' + }, dialog: { msgId: 'dialog' }, @@ -116,6 +119,10 @@ radioButton: { msgId: 'input_type_radio' }, + spinButton: { + msgId: 'aria_role_combobox', + earcon: 'LISTBOX' + }, textBox: { msgId: 'input_type_text', earcon: 'EDITABLE_TEXT' @@ -124,6 +131,9 @@ msgId: 'input_type_text', earcon: 'EDITABLE_TEXT' }, + time: { + msgId: 'tag_time' + }, toolbar: { msgId: 'aria_role_toolbar' } @@ -156,7 +166,7 @@ Output.RULES = { navigate: { 'default': { - speak: '$name $value $role', + speak: '$name $value $description $help $role', braille: '' }, alert: { @@ -165,6 +175,10 @@ checkBox: { speak: '$name $role $checked' }, + date: { + enter: '$name $role', + leave: '@exited_container($role)' + }, dialog: { enter: '$name $role' }, @@ -207,7 +221,7 @@ '@describe_radio_unselected($name))' }, slider: { - speak: '@describe_slider($value, $name)' + speak: '@describe_slider($value, $name) $help' }, staticText: { speak: '$value $name' @@ -215,6 +229,16 @@ tab: { speak: '@describe_tab($name)' }, + textField: { + speak: '$name $value $if(' + + '$textInputType, @input_type_+$textInputType, @input_type_text) ' + + '$earcon(EDITABLE_TEXT)', + braille: '' + }, + time: { + enter: '$name $role', + leave: '@exited_container($role)' + }, toolbar: { enter: '$name $role' }, @@ -303,13 +327,26 @@ Output.prototype = { /** * Gets the output buffer for speech. + * @param {string=} opt_separator Used to join components of the output. * @return {!cvox.Spannable} */ - toSpannable: function() { + toSpannable: function(opt_separator) { + opt_separator = opt_separator || ''; return this.buffer_.reduce(function(prev, cur) { + if (prev === null) + return cur; + prev.append(opt_separator); prev.append(cur); return prev; - }, new cvox.Spannable()); + }, null); + }, + + /** + * Gets the output buffer for speech with separator '|'. + * @return {!cvox.Spannable} + */ + toSpannableForTest: function() { + return this.toSpannable('|'); }, /** @@ -536,11 +573,11 @@ this.append_(buff, text, options); } else if (token == 'indexInParent') { options.annotation.push(token); - this.append_(buff, node.indexInParent + 1); + this.append_(buff, String(node.indexInParent + 1)); } else if (token == 'parentChildCount') { options.annotation.push(token); if (node.parent) - this.append_(buff, node.parent.children.length); + this.append_(buff, String(node.parent.children.length)); } else if (token == 'state') { options.annotation.push(token); Object.getOwnPropertyNames(node.state).forEach(function(s) {
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs index be99afdb..b392f31 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/output_test.extjs
@@ -137,3 +137,91 @@ ]}, o.toSpannable()); }); }); + +TEST_F('OutputE2ETest', 'Audio', function() { + this.runWithLoadedTree('<audio src="foo.mp3" controls></audio>', + function(root) { + var el = root.firstChild.firstChild.firstChild.firstChild; + var range = cursors.Range.fromNode(el); + var o = new Output().withSpeechAndBraille(range, null, 'navigate'); + assertEqualsJSON( + {string_: 'media control|Tool bar|||play|begin playback|Button', + spans_: + // Entered container toolbar. + + // Button. + [{value: 'name', start: 23, end: 23}, + {value: 'value', start: 24, end: 24}, + {value: 'description', start: 25, end: 29}, + {value: 'help', start: 30, end: 44}, + {value: 'role', start: 45, end: 51}, + + // Button earcon. + {value: {}, start: 45, end: 51}] + }, o.toSpannableForTest()); + + el = el.nextSibling; + var prevRange = range; + range = cursors.Range.fromNode(el); + var o = new Output().withSpeechAndBraille(range, prevRange, 'navigate'); + assertEqualsJSON({string_: '0, , slider|audio time scrubber', + spans_: + [{value: 'help', start: 12, end: 31}] + }, o.toSpannableForTest()); + }); +}); + +TEST_F('OutputE2ETest', 'Input', function() { + this.runWithLoadedTree( + '<input type="text"></input>' + + '<input type="email"></input>' + + '<input type="password"></input>' + + '<input type="tel"></input>' + + '<input type="number"></input>' + + '<input type="time"></input>' + + '<input type="date"></input>', + function(root) { + var expected = {string_: '', 'spans_': [ + {value: 'name', start: 0, end: 0}, + + // Selection span. + {value: {startIndex: 0, endIndex: 0}, start: 1, end: 1}, + + {value: 'value', start: 1, end: 1}, + + // Earcon + {value: {}, start: 2, end: 2} + ]}; + + var expectedValues = [ + '||Edit text', + '||Edit text, email entry', + '||Password edit text', + '||Edit text, number entry', + {string_: '||Combo box', spans_: [{value: 'name', start: 0, end: 0}, + {value: {startIndex: 0, endIndex: 0}, start: 1, end: 1}, + {value: 'value', start: 1, end: 1}, + {value: 'role', start: 2, end: 11}, + {value: {}, start: 2, end: 11}]}, + {string_: '||Time', spans_: [{value: 'name', start: 0, end: 0}, + {value: 'value', start: 1, end: 1}, + {value: 'role', start: 2, end: 6}]}, + {string_: '||Date control', spans_: [{value: 'name', start: 0, end: 0}, + {value: 'value', start: 1, end: 1}, + {value: 'role', start: 2, end: 14}]} + ]; + + var el = root.firstChild.firstChild; + expectedValues.forEach(function(expectedValue) { + var range = cursors.Range.fromNode(el); + var o = new Output().withSpeechAndBraille(range, null, 'navigate'); + if (typeof expectedValue == 'object') { + assertEqualsJSON(expectedValue, o.toSpannableForTest()); + } else { + expected.string_ = expectedValue; + assertEqualsJSON(expected, o.toSpannableForTest()); + } + el = el.nextSibling; + }); + }); +});
diff --git a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js index 67d027b..9eabcf4 100644 --- a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js +++ b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
@@ -414,7 +414,10 @@ case 'interrupted': this.cancelUtterance_(utterance); this.currentUtterance_ = null; - this.startSpeakingNextItemInQueue_(); + for (var i = 0; i < this.utteranceQueue_.length; i++) { + this.cancelUtterance_(this.utteranceQueue_[i]); + } + this.utteranceQueue_.length = 0; break; case 'error': this.onError_(event['errorMessage']);
diff --git a/chrome/browser/resources/chromeos/chromevox/walkers/table_walker.js b/chrome/browser/resources/chromeos/chromevox/walkers/table_walker.js index 881902e..cd6f3c8 100644 --- a/chrome/browser/resources/chromeos/chromevox/walkers/table_walker.js +++ b/chrome/browser/resources/chromeos/chromevox/walkers/table_walker.js
@@ -102,7 +102,7 @@ * Returns the first cell of the table that this selection is inside. * @param {!cvox.CursorSelection} sel The selection. * @return {cvox.CursorSelection} The selection for first cell of the table. - * @expose + * @export */ cvox.TableWalker.prototype.goToFirstCell = function(sel) { return this.goTo_(sel, goog.bind(function(position) { @@ -114,7 +114,7 @@ * Returns the last cell of the table that this selection is inside. * @param {!cvox.CursorSelection} sel The selection. * @return {cvox.CursorSelection} The selection for the last cell of the table. - * @expose + * @export */ cvox.TableWalker.prototype.goToLastCell = function(sel) { return this.goTo_(sel, goog.bind(function(position) { @@ -126,7 +126,7 @@ * Returns the first cell of the row that the selection is in. * @param {!cvox.CursorSelection} sel The selection. * @return {cvox.CursorSelection} The selection for the first cell in the row. - * @expose + * @export */ cvox.TableWalker.prototype.goToRowFirstCell = function(sel) { return this.goTo_(sel, goog.bind(function(position) { @@ -138,7 +138,7 @@ * Returns the last cell of the row that the selection is in. * @param {!cvox.CursorSelection} sel The selection. * @return {cvox.CursorSelection} The selection for the last cell in the row. - * @expose + * @export */ cvox.TableWalker.prototype.goToRowLastCell = function(sel) { return this.goTo_(sel, goog.bind(function(position) { @@ -150,7 +150,7 @@ * Returns the first cell of the column that the selection is in. * @param {!cvox.CursorSelection} sel The selection. * @return {cvox.CursorSelection} The selection for the first cell in the col. - * @expose + * @export */ cvox.TableWalker.prototype.goToColFirstCell = function(sel) { return this.goTo_(sel, goog.bind(function(position) { @@ -162,7 +162,7 @@ * Returns the last cell of the column that the selection is in. * @param {!cvox.CursorSelection} sel The selection. * @return {cvox.CursorSelection} The selection for the last cell in the col. - * @expose + * @export */ cvox.TableWalker.prototype.goToColLastCell = function(sel) { return this.goTo_(sel, goog.bind(function(position) { @@ -175,7 +175,7 @@ * @param {!cvox.CursorSelection} sel The selection. * @return {cvox.CursorSelection} The selection for the first cell in the next * row. - * @expose + * @export */ cvox.TableWalker.prototype.nextRow = function(sel) { return this.goTo_(sel, goog.bind(function(position) { @@ -189,7 +189,7 @@ * @param {!cvox.CursorSelection} sel The selection. * @return {cvox.CursorSelection} The selection for the first cell in the * next col. - * @expose + * @export */ cvox.TableWalker.prototype.nextCol = function(sel) { return this.goTo_(sel, goog.bind(function(position) { @@ -201,7 +201,7 @@ /** * @param {!cvox.CursorSelection} sel The current selection. * @return {cvox.CursorSelection} The resulting selection. - * @expose + * @export */ cvox.TableWalker.prototype.announceHeaders = function(sel) { cvox.ChromeVox.tts.speak(this.getHeaderText_(sel), @@ -213,7 +213,7 @@ /** * @param {!cvox.CursorSelection} sel The current selection. * @return {cvox.CursorSelection} The resulting selection. - * @expose + * @export */ cvox.TableWalker.prototype.speakTableLocation = function(sel) { cvox.ChromeVox.navigationManager.speakDescriptionArray( @@ -227,7 +227,7 @@ /** * @param {!cvox.CursorSelection} sel The current selection. * @return {cvox.CursorSelection} The resulting selection. - * @expose + * @export */ cvox.TableWalker.prototype.exitShifterContent = function(sel) { var tableNode = this.getTableNode_(sel);
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_login.html b/chrome/browser/resources/chromeos/login/custom_elements_login.html index 2aff672..0985cbd9 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_login.html +++ b/chrome/browser/resources/chromeos/login/custom_elements_login.html
@@ -3,5 +3,6 @@ <include src="gaia_input_form.html"> <include src="gaia_header.html"> <include src="offline_gaia.html"> +<include src="gaia_password_changed.html"> <script src="chrome://oobe/custom_elements.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_login.js b/chrome/browser/resources/chromeos/login/custom_elements_login.js index b1a7b6a..829d71a9 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_login.js +++ b/chrome/browser/resources/chromeos/login/custom_elements_login.js
@@ -5,3 +5,4 @@ <include src="gaia_buttons.js"> <include src="gaia_input_form.js"> <include src="offline_gaia.js"> +<include src="gaia_password_changed.js">
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html index e3787dd..f1e82f7f 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.html +++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.html
@@ -9,6 +9,7 @@ <include src="gaia_input_form.html"> <include src="gaia_header.html"> <include src="offline_gaia.html"> +<include src="gaia_password_changed.html"> <include src="notification_card.html"> <script src="chrome://oobe/custom_elements.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js index 0516d1a..1c3cb21 100644 --- a/chrome/browser/resources/chromeos/login/custom_elements_oobe.js +++ b/chrome/browser/resources/chromeos/login/custom_elements_oobe.js
@@ -10,4 +10,5 @@ <include src="gaia_buttons.js"> <include src="gaia_input_form.js"> <include src="offline_gaia.js"> +<include src="gaia_password_changed.js"> <include src="notification_card.js">
diff --git a/chrome/browser/resources/chromeos/login/gaia_buttons.html b/chrome/browser/resources/chromeos/login/gaia_buttons.html index 003ff375..33a1cc82 100644 --- a/chrome/browser/resources/chromeos/login/gaia_buttons.html +++ b/chrome/browser/resources/chromeos/login/gaia_buttons.html
@@ -7,16 +7,27 @@ 'Enter' and 'Space'. --> <polymer-element name="gaia-paper-button" extends="paper-button" - on-keydown="onKeyDown"> + on-keydown="onKeyDown" tabindex="0"> <template> <shadow></shadow> </template> </polymer-element> <polymer-element name="gaia-core-icon-button" extends="core-icon-button" - on-keydown="onKeyDown"> + on-keydown="onKeyDown" tabindex="0"> <template> + <link rel="stylesheet" href="gaia_core_icon_button.css"> <shadow></shadow> </template> </polymer-element> +<!-- + Paper-button which is raised when it's focused. + It also triggers 'tap' event on keys 'Enter' and 'Space'. +--> +<polymer-element name="gaia-raised-on-focus-button" extends="gaia-paper-button" + on-focus="{{onButtonFocus}}" on-blur="{{onButtonBlur}}"> + <template> + <shadow></shadow> + </template> +</polymer-element>
diff --git a/chrome/browser/resources/chromeos/login/gaia_buttons.js b/chrome/browser/resources/chromeos/login/gaia_buttons.js index 4d4f0d0..974b09e 100644 --- a/chrome/browser/resources/chromeos/login/gaia_buttons.js +++ b/chrome/browser/resources/chromeos/login/gaia_buttons.js
@@ -16,3 +16,13 @@ this.fire('tap'); } }); + +Polymer('gaia-raised-on-focus-button', { + onButtonFocus: function() { + this.raised = true; + }, + + onButtonBlur: function() { + this.raised = false; + }, +});
diff --git a/chrome/browser/resources/chromeos/login/gaia_card.css b/chrome/browser/resources/chromeos/login/gaia_card.css index beabb71..8931014d 100644 --- a/chrome/browser/resources/chromeos/login/gaia_card.css +++ b/chrome/browser/resources/chromeos/login/gaia_card.css
@@ -12,28 +12,89 @@ background-color: rgb(66, 133, 244); color: rgb(255, 255, 255); height: 164px; - padding-top: 34px; } -.gaia-footer { +.gaia-footer, +#progress-bar::shadow #progressContainer { background-color: rgb(238, 238, 238); - padding-bottom: 34px; } -.gaia-header, .gaia-footer { - padding-left: 40px; - padding-right: 40px; + position: relative; } -::content /deep/ a.newgaia-link { - color: rgb(66, 133, 244); - font-size: 14px; - text-decoration: none; +.header-container { + padding: 34px 40px 16px; } -::content /deep/ gaia-paper-button.blue-button { +.footer-container { + padding: 24px 40px 34px; +} + +::content /deep/ .blue-button { background-color: rgb(66, 133, 244); color: rgb(255, 255, 255); - min-width: 88px + min-width: 90px; +} + +::content /deep/ .link-button { + color: rgb(66, 133, 244); + font-size: 14px; + margin: 0; + text-align: left; + text-transform: none; +} + +::content /deep/ .link-button:focus { + background: rgb(217, 221, 234); +} + +::content /deep/ .link-button::shadow .button-content { + padding: 0; +} + +::content /deep/ p.gaia-body-text { + color: rgba(0, 0, 0, 0.87); + font-size: 14px; + line-height: 20px; + margin: 0; +} + +::content /deep/ p.email, +::content /deep/ p.enterprise-info { + color: rgb(255, 255, 255); + font-size: 15px; + margin: 8px 0 0 0; +} + +::content /deep/ h1.welcome-message { + color: rgb(255, 255, 255); + font-size: 20px; + font-weight: normal; + margin-bottom: 0; +} + +#bottom-overlay { + background-color: rgba(0, 0, 0, 0.5); + display: none; + height: 100%; + position: absolute; + right: 0; + top: 0; + width: 100%; + z-index: 11; +} + +#progress-bar { + display: none; + width: 100%; +} + +#progress-bar::shadow #activeProgress { + background-color: rgb(255, 184, 9); +} + +:host(.disabled) #bottom-overlay, +:host(.disabled) #progress-bar { + display: block; }
diff --git a/chrome/browser/resources/chromeos/login/gaia_card.html b/chrome/browser/resources/chromeos/login/gaia_card.html index 577b1b7..72c63744 100644 --- a/chrome/browser/resources/chromeos/login/gaia_card.html +++ b/chrome/browser/resources/chromeos/login/gaia_card.html
@@ -1,5 +1,6 @@ <link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> <link rel="import" href="chrome://resources/polymer/polymer/layout.html"> +<link rel="import" href="chrome://resources/polymer/paper-progress/paper-progress.html"> <!-- Simple Gaia card which should be used for local UI elements that look like @@ -21,10 +22,17 @@ <template> <link rel="stylesheet" href="gaia_card.css"> <div class="gaia-header" vertical layout> - <content select=".header"></content> + <div class="header-container" flex vertical layout> + <content select=".header"></content> + </div> </div> + <paper-progress id="progress-bar" indeterminate></paper-progress> <div class="gaia-footer" flex vertical layout> - <content select=".footer"></content> + <div class="footer-container" flex vertical layout> + <content select=".footer"></content> + </div> + <div id="bottom-overlay"> + </div> </div> </template> </polymer-element>
diff --git a/chrome/browser/resources/chromeos/login/gaia_core_icon_button.css b/chrome/browser/resources/chromeos/login/gaia_core_icon_button.css new file mode 100644 index 0000000..4910fae --- /dev/null +++ b/chrome/browser/resources/chromeos/login/gaia_core_icon_button.css
@@ -0,0 +1,8 @@ +/* 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. + */ + +:host(:hover:not([disabled])) { + box-shadow: none; +}
diff --git a/chrome/browser/resources/chromeos/login/gaia_header.html b/chrome/browser/resources/chromeos/login/gaia_header.html index f59bc0ea..c59a1de8 100644 --- a/chrome/browser/resources/chromeos/login/gaia_header.html +++ b/chrome/browser/resources/chromeos/login/gaia_header.html
@@ -17,7 +17,7 @@ <div flex vertical justified layout start> <img self-start src="chrome://theme/IDR_LOGO_AVATAR_CIRCLE_BLUE_COLOR" alt> - <p id="email">{{email}}</p> + <p class="email">{{email}}</p> </div> </template> </polymer-element>
diff --git a/chrome/browser/resources/chromeos/login/gaia_input_form.css b/chrome/browser/resources/chromeos/login/gaia_input_form.css index 8b6a3ba8..ca7209120 100644 --- a/chrome/browser/resources/chromeos/login/gaia_input_form.css +++ b/chrome/browser/resources/chromeos/login/gaia_input_form.css
@@ -7,11 +7,35 @@ font-size: 16px; } -paper-input-decorator { - margin-bottom: 50px; +#paperInputDecorator /deep/ .unfocused-underline { + background-color: rgb(212, 212, 212); } -paper-input-decorator /deep/ .unfocused-underline { - /* line color when the input is unfocused */ - background-color: rgb(224, 224, 224); +#paperInputDecorator /deep/ .focused-underline { + background-color: rgb(66, 133, 244); +} + +#paperInputDecorator /deep/ ::-webkit-input-placeholder, +#paperInputDecorator /deep/ .label-text { + color: rgba(0, 0, 0, 0.54); +} + +#paperInputDecorator { + font-size: 15px; + margin-bottom: 28px; + padding: 0; +} + +#paperInputDecorator /deep/ #inputForm { + color: rgba(0, 0, 0, 0.87); +} + +:host-context(html[dir=rtl]) #paperInputDecorator /deep/ #inputContainer { + flex-direction: row-reverse; +} + +#paperInputDecorator /deep/ #emailDomain { + color: rgba(0, 0, 0, 0.54); + direction: ltr; + width: auto; }
diff --git a/chrome/browser/resources/chromeos/login/gaia_input_form.html b/chrome/browser/resources/chromeos/login/gaia_input_form.html index 3f2fb49..27a137d 100644 --- a/chrome/browser/resources/chromeos/login/gaia_input_form.html +++ b/chrome/browser/resources/chromeos/login/gaia_input_form.html
@@ -15,6 +15,7 @@ 'errorMsg' - error message which should be displayed when input is incorrect. 'buttonText' - text on the button. + 'emailDomain' - autocomplete domain for the inputType="email". Events: 'buttonclick' - fired on button click. @@ -27,20 +28,23 @@ setValid at the end. --> <polymer-element name="gaia-input-form" vertical start-justified layout - attributes="inputType errorMsg inputLabel buttonText"> + attributes="inputType errorMsg inputLabel buttonText emailDomain"> <template> <link rel="stylesheet" href="gaia_input_form.css"> <paper-input-decorator id="paperInputDecorator" error="{{errorMsg}}" label="{{inputLabel}}" on-tap="{{onTap}}" floatingLabel autoValidate> - <input id="inputForm" is="core-input" on-keydown="{{onKeyDown}}" - value="{{inputValue}}" required type="{{inputType}}"> + <div id="inputContainer" horizontal layout> + <input id="inputForm" is="core-input" on-keydown="{{onKeyDown}}" + value="{{inputValue}}" required type="{{inputType}}" flex> + <span id="emailDomain" hidden?="{{!emailDomain}}">{{emailDomain}}</span> + </div> </paper-input-decorator> <div horizontal justified layout center reverse> - <gaia-paper-button raised class="blue-button" - on-tap="{{onButtonClicked}}" self-end tabindex="0"> + <gaia-raised-on-focus-button id="button" class="blue-button" + on-tap="{{onButtonClicked}}" self-end> {{buttonText}} - </gaia-paper-button> + </gaia-raised-on-focus-button> <content> </content> </div> </template>
diff --git a/chrome/browser/resources/chromeos/login/gaia_input_form.js b/chrome/browser/resources/chromeos/login/gaia_input_form.js index 085a472d..7306ba7 100644 --- a/chrome/browser/resources/chromeos/login/gaia_input_form.js +++ b/chrome/browser/resources/chromeos/login/gaia_input_form.js
@@ -3,35 +3,59 @@ * found in the LICENSE file. */ -Polymer('gaia-input-form', { - inputValue: '', +Polymer('gaia-input-form', (function() { + var INPUT_EMAIL_PATTERN = "^[a-zA-Z0-9.!#$%&'*+=?^_`{|}~-]+(@[^\\s@]+)?$"; - onButtonClicked: function() { - this.fire('buttonClick'); - }, + return { - onKeyDown: function(e) { - this.setValid(true); - if (e.keyCode == 13) - return this.onButtonClicked(); - }, + inputValue: '', - onTap: function() { - this.setValid(true); - }, + onButtonClicked: function() { + this.fire('buttonClick'); + }, - focus: function() { - this.$.inputForm.focus(); - }, + onKeyDown: function(e) { + this.setValid(true); + this.setDomainVisibility(); + if (e.keyCode == 13 && !this.$.button.disabled) + this.$.button.fire('tap'); + }, - checkValidity: function() { - var input = this.$.inputForm; - var isValid = input.validity.valid; - this.setValid(isValid); - return isValid; - }, + onKeyUp: function(e) { + this.setDomainVisibility(); + }, - setValid: function(isValid) { - this.$.paperInputDecorator.isInvalid = !isValid; - } -}); + setDomainVisibility: function() { + this.$.emailDomain.hidden = !(this.inputValue.indexOf('@') === -1); + }, + + ready: function() { + if (this.inputType == 'email') { + this.$.inputForm.type = 'text'; + this.$.inputForm.pattern = INPUT_EMAIL_PATTERN; + this.$.inputForm.addEventListener('keyup', this.onKeyUp.bind(this)); + } else { + this.$.inputForm.type = this.inputType; + } + }, + + onTap: function() { + this.setValid(true); + }, + + focus: function() { + this.$.inputForm.focus(); + }, + + checkValidity: function() { + var input = this.$.inputForm; + var isValid = input.validity.valid; + this.setValid(isValid); + return isValid; + }, + + setValid: function(isValid) { + this.$.paperInputDecorator.isInvalid = !isValid; + } + }; +})());
diff --git a/chrome/browser/resources/chromeos/login/gaia_password_changed.css b/chrome/browser/resources/chromeos/login/gaia_password_changed.css new file mode 100644 index 0000000..8a64d3ca --- /dev/null +++ b/chrome/browser/resources/chromeos/login/gaia_password_changed.css
@@ -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. + */ + +:host { + height: 100%; + width: 100%; +} + +core-icon[icon='warning'] { + color: rgb(255, 193, 7); + margin: 0 15px 0 0; +} + +:host-context(html[dir=rtl]) core-icon[icon='warning'] { + margin: 0 0 0 15px; +} + +#closeButton { + color: rgb(255, 255, 255); + position: absolute; + right: 0; + top: 0; + z-index: 1; +} + +:host-context(html[dir=rtl]) #closeButton { + left: 0; + right: auto; +} + +div.margined { + margin-bottom: 24px; +}
diff --git a/chrome/browser/resources/chromeos/login/gaia_password_changed.html b/chrome/browser/resources/chromeos/login/gaia_password_changed.html new file mode 100644 index 0000000..6b5ddf87 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/gaia_password_changed.html
@@ -0,0 +1,93 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/polymer/layout.html"> +<link rel="import" href="chrome://resources/polymer/core-animated-pages/core-animated-pages.html"> +<link rel="import" href="chrome://resources/polymer/core-animated-pages/transitions/cross-fade.html"> + +<!-- + Password changed UI for the New Gaia flow. + Contains two cards with a fade transition between them: + 1. Old password input form. + 2. Warning about data loss + 3. Spinner with notice "Please wait"; + + Example: + <gaia-password-changed id="gaia-password-changed" hidden> + </gaia-password-changed> + + Attributes: + 'email' - displayed email in header. + + Events: + 'passwordEnter' - fired when user enters password. Fires with an argument + |password|. + 'proceedAnyway' - fired when user decides to skip old password and + lose all the data in cryptohome. + 'cancel' - fired when user press X-button. + + Methods: + 'invalidate' - mark password input as invalid. + 'reset' - reset element, sets in on the first screen and enables + buttons. + 'focus' - if current card is the first one it focuses password input. + +--> +<polymer-element name="gaia-password-changed" vertical layout + attributes="email"> + <template> + <link rel="stylesheet" href="gaia_password_changed.css"> + <gaia-core-icon-button id="closeButton" icon="close" on-tap="{{onClose}}"> + </gaia-core-icon-button> + <core-animated-pages id="animatedPages" transitions="cross-fade-all" flex + on-core-animated-pages-transition-end="{{onTransitionEnd}}"> + <section flex> + <gaia-card id="oldPasswordCard"> + <gaia-header class="header" email="{{email}}"> + </gaia-header> + <div horizontal layout center class="footer margined"> + <p class="gaia-body-text" + i18n-content="passwordChangedTitle"> + </p> + </div> + <gaia-input-form class="footer" id="oldPasswordInput" + inputtype="password" + i18n-values="errorMsg:oldPasswordIncorrect; + inputLabel:oldPasswordHint; + buttonText:nextButtonText"> + <gaia-paper-button noink i18n-content="forgotOldPasswordButtonText" + class="link-button" + on-tap="{{onForgotPasswordClicked}}"> + </gaia-paper-button> + </gaia-input-form> + </gaia-card> + </section> + <section flex> + <gaia-card> + <gaia-header class="header" email="{{email}}"> + </gaia-header> + <div class="footer"> + <div horizontal layout center class="margined"> + <core-icon icon="warning"></core-icon> + <p flex class="gaia-body-text" + i18n-content="passwordChangedProceedAnywayTitle"> + </p> + </div> + <div horizontal layout justified center> + <gaia-paper-button noink i18n-content="passwordChangedTryAgain" + class="link-button" + on-tap="{{onTryAgainClicked}}"> + </gaia-paper-button> + <gaia-raised-on-focus-button id="proceedAnywayBtn" + class="blue-button" on-tap="{{onProceedClicked}}" + i18n-content="proceedAnywayButton"> + </gaia-raised-on-focus-button> + </div> + </div> + </gaia-card> + </section> + <section flex vertical layout center-justified> + <throbber-notice i18n-values="text:gaiaLoadingNewGaia" self-center> + </throbber-notice> + </section> + </core-animated-pages> + </template> +</polymer-element>
diff --git a/chrome/browser/resources/chromeos/login/gaia_password_changed.js b/chrome/browser/resources/chromeos/login/gaia_password_changed.js new file mode 100644 index 0000000..f6433e9 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/gaia_password_changed.js
@@ -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. + */ + +Polymer('gaia-password-changed', { + invalidate: function() { + this.$.oldPasswordInput.setValid(false); + }, + + reset: function() { + this.$.animatedPages.selected = 0; + this.clearPassword(); + this.$.oldPasswordInput.setValid(true); + this.disabled = false; + this.$.closeButton.hidden = false; + this.$.oldPasswordCard.classList.remove('disabled'); + }, + + ready: function() { + this.$.oldPasswordInput.addEventListener('buttonClick', function() { + var inputPassword = this.$.oldPasswordInput.inputValue; + if (!inputPassword) + this.invalidate(); + else { + this.$.oldPasswordCard.classList.add('disabled'); + this.disabled = true; + this.fire('passwordEnter', {password: inputPassword}); + } + }.bind(this)); + }, + + focus: function() { + if (this.$.animatedPages.selected == 0) + this.$.oldPasswordInput.focus(); + }, + + set disabled(value) { + var controls = this.$.animatedPages.querySelectorAll( + ':host /deep/ .footer /deep/ [role="button"]'); + for (var i = 0, control; control = controls[i]; ++i) { + control.disabled = value; + } + }, + + onForgotPasswordClicked: function() { + this.clearPassword(); + this.$.animatedPages.selected += 1; + }, + + onTryAgainClicked: function() { + this.$.oldPasswordInput.setValid(true); + this.$.animatedPages.selected -= 1; + }, + + onTransitionEnd: function() { + this.focus(); + }, + + clearPassword: function() { + this.$.oldPasswordInput.inputValue = ''; + }, + + onProceedClicked: function() { + this.disabled = true; + this.$.closeButton.hidden = true; + this.$.animatedPages.selected = 2; + this.fire('proceedAnyway'); + }, + + onClose: function() { + this.disabled = true; + this.fire('cancel'); + }, +});
diff --git a/chrome/browser/resources/chromeos/login/header_bar.js b/chrome/browser/resources/chromeos/login/header_bar.js index 6a07090..9cf78ad 100644 --- a/chrome/browser/resources/chromeos/login/header_bar.js +++ b/chrome/browser/resources/chromeos/login/header_bar.js
@@ -323,6 +323,8 @@ (this.signinUIState_ == SIGNIN_UI_STATE.SAML_PASSWORD_CONFIRM); var isEnrollingConsumerManagement = (this.signinUIState_ == SIGNIN_UI_STATE.CONSUMER_MANAGEMENT_ENROLLMENT); + var isPasswordChangedUI = + (this.signinUIState_ == SIGNIN_UI_STATE.PASSWORD_CHANGED); var isMultiProfilesUI = (Oobe.getInstance().displayType == DISPLAY_TYPE.USER_ADDING); var isLockScreen = @@ -346,7 +348,7 @@ isNewGaiaScreenWithBackButton || supervisedUserCreationDialogIsActive; $('cancel-add-user-button').hidden = - (gaiaIsActive && this.isNewGaiaFlow_) || + ((gaiaIsActive || isPasswordChangedUI) && this.isNewGaiaFlow_) || accountPickerIsActive || !this.allowCancel_ || wrongHWIDWarningIsActive ||
diff --git a/chrome/browser/resources/chromeos/login/login_common.js b/chrome/browser/resources/chromeos/login/login_common.js index 0379e2f..d3d731f 100644 --- a/chrome/browser/resources/chromeos/login/login_common.js +++ b/chrome/browser/resources/chromeos/login/login_common.js
@@ -169,8 +169,8 @@ * Shows password changed screen that offers migration. * @param {boolean} showError Whether to show the incorrect password error. */ - Oobe.showPasswordChangedScreen = function(showError) { - DisplayManager.showPasswordChangedScreen(showError); + Oobe.showPasswordChangedScreen = function(showError, email) { + DisplayManager.showPasswordChangedScreen(showError, email); }; /**
diff --git a/chrome/browser/resources/chromeos/login/offline_gaia.css b/chrome/browser/resources/chromeos/login/offline_gaia.css index 58e1da0..5cc541da 100644 --- a/chrome/browser/resources/chromeos/login/offline_gaia.css +++ b/chrome/browser/resources/chromeos/login/offline_gaia.css
@@ -10,16 +10,6 @@ width: 100%; } -p { - font-size: 14px; - margin-top: 0; -} - -h1 { - font-size: 20px; - font-weight: normal; -} - #backButton { color: rgb(255, 255, 255); left: 0;
diff --git a/chrome/browser/resources/chromeos/login/offline_gaia.html b/chrome/browser/resources/chromeos/login/offline_gaia.html index 11c7c933..ea17f24 100644 --- a/chrome/browser/resources/chromeos/login/offline_gaia.html +++ b/chrome/browser/resources/chromeos/login/offline_gaia.html
@@ -16,13 +16,16 @@ Attributes: 'enterpriseInfo' - Information about device management. + 'emailDomain' - autocomplete domain for the email input. Events: - 'flowfinished' - fired when user enters login and password. Fires with an - argument |credentials| which contains. - |credentials| = { 'useOffline': true, - 'email': <typed email>, - 'password': <typed password> } + 'authCompleted' - fired when user enters login and password. Fires with an + argument |credentials| which contains. + |credentials| = { 'useOffline': true, + 'email': <email>, + 'password': <typed password> } + If user did not type domain |email| will be added by + "@gmail.com" or by 'emailDomain' if it is set. Methods: 'focus' - focuses current screen (email input or password input); 'setEmail' - accepts an argument |email|. If |email| is empty it sets @@ -30,24 +33,26 @@ screen to password input and shows error that previously entered password is incorrect. --> -<polymer-element name="offline-gaia" vertical layout attributes="enterpriseInfo"> +<polymer-element name="offline-gaia" vertical layout + attributes="enterpriseInfo emailDomain"> <template> <link rel="stylesheet" href="offline_gaia.css"> - <gaia-core-icon-button id="backButton" icon="arrow-back" on-tap="{{onBack}}" - tabindex="0"> + <gaia-core-icon-button id="backButton" icon="arrow-back" + on-tap="{{onBack}}"> </gaia-core-icon-button> <core-animated-pages id="animatedPages" transitions="slide-from-right" on-core-animated-pages-transition-end="{{onTransitionEnd}}" flex> <section flex> <gaia-card> <div class="header" flex vertical layout end-justified start> - <h1 i18n-content="offlineLoginWelcome"></h1> - <p hidden?="{{!enterpriseInfo}}"> + <h1 class="welcome-message" i18n-content="offlineLoginWelcome"></h1> + <p class="enterprise-info" hidden?="{{!enterpriseInfo}}"> {{enterpriseInfo}} </p> </div> <div class="footer" flex vertical layout justified> <gaia-input-form id="emailInput" inputType="email" + emailDomain="{{emailDomain}}" i18n-values="errorMsg:offlineLoginInvalidEmail; inputLabel:offlineLoginEmail; buttonText:offlineLoginNextBtn"> @@ -66,17 +71,14 @@ i18n-values="errorMsg:offlineLoginInvalidPassword; inputLabel:offlineLoginPassword; buttonText:offlineLoginNextBtn"> - <a href="#" class="newgaia-link" - on-tap="{{onForgotPasswordClicked}}" - on-keydown="{{onForgotPasswordKeyDown}}" - tabindex="0" - i18n-content="offlineLoginForgotPasswordBtn"> - </a> + <gaia-paper-button noink class="link-button" + i18n-content="offlineLoginForgotPasswordBtn" + on-tap="{{onForgotPasswordClicked}}"> + </gaia-paper-button> <paper-action-dialog id="forgotPasswordDlg" autoCloseDisabled backdrop on-keydown="{{onKeyDownOnDialog}}"> <p i18n-content="offlineLoginForgotPasswordDlg"></p> <gaia-paper-button id="dialogCloseBtn" affirmative autofocus - tabindex="0" i18n-content="offlineLoginCloseBtn"> </gaia-paper-button> </paper-action-dialog>
diff --git a/chrome/browser/resources/chromeos/login/offline_gaia.js b/chrome/browser/resources/chromeos/login/offline_gaia.js index 00636ee..d072dfe 100644 --- a/chrome/browser/resources/chromeos/login/offline_gaia.js +++ b/chrome/browser/resources/chromeos/login/offline_gaia.js
@@ -4,6 +4,8 @@ */ Polymer('offline-gaia', (function() { + var DEFAULT_EMAIL_DOMAIN = '@gmail.com'; + return { onTransitionEnd: function() { this.focus(); @@ -48,7 +50,7 @@ if (this.$.passwordInput.checkValidity()) { var msg = { 'useOffline': true, - 'email': this.$.emailInput.inputValue, + 'email': this.$.passwordHeader.email, 'password': this.$.passwordInput.inputValue }; this.$.passwordInput.inputValue = ''; @@ -60,6 +62,8 @@ setEmail: function(email) { if (email) { + if (this.emailDomain) + email = email.replace(this.emailDomain, ''); this.switchToPasswordCard(email); this.$.passwordInput.setValid(false); } else { @@ -75,12 +79,19 @@ switchToEmailCard() { this.$.passwordInput.inputValue = ''; this.$.passwordInput.setValid(true); + this.$.emailInput.setValid(true); this.$.backButton.hidden = true; this.$.animatedPages.selected = 0; }, switchToPasswordCard(email) { this.$.emailInput.inputValue = email; + if (email.indexOf('@') === -1) { + if (this.emailDomain) + email = email + this.emailDomain; + else + email = email + DEFAULT_EMAIL_DOMAIN; + } this.$.passwordHeader.email = email; this.$.backButton.hidden = false; this.$.animatedPages.selected = 1;
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.css b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.css index 18b1235..53d4a44 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.css +++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.css
@@ -4,9 +4,9 @@ */ #oauth-enrollment { - height: 609px; + height: 528px; padding: 0; - width: 522px; + width: 448px; } #oauth-enrollment.saml { @@ -137,20 +137,12 @@ } #oauth-enroll-cancel-button { - background: transparent none; background-image: url(chrome://theme/IDR_LOGIN_CLOSE_BUTTTON); - background-position: center; - background-repeat: no-repeat; - height: 14px; - position: absolute; - right: 15px; - top: 15px; - width: 14px; - z-index: 1; + right: 0; } html[dir=rtl] #oauth-enroll-cancel-button { - left: 15px; + left: 0; right: auto; } @@ -158,29 +150,29 @@ background-image: url(chrome://theme/IDR_LOGIN_CLOSE_BUTTTON_ON_WHITE); } +#oauth-enroll-cancel-button:hover { + cursor: pointer; +} + #oauth-enroll-back-button { - background: transparent none; background-image: url(chrome://theme/IDR_LOGIN_BACK_BUTTTON); - background-position: center; - background-repeat: no-repeat; - height: 18px; - left: 14px; - position: absolute; - top: 14px; - width: 18px; - z-index: 1; + left: 0; } html[dir=rtl] #oauth-enroll-back-button { -webkit-transform: scaleX(-1); left: auto; - right: 14px; + right: 0; } #oauth-enrollment.saml #oauth-enroll-back-button { display: none; } +#oauth-enroll-back-button:hover { + cursor: pointer; +} + .oauth-enroll-textbox { display: inline-block; position: relative;
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.html b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.html index 42462cc..98f3dba6 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.html +++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.html
@@ -3,8 +3,8 @@ found in the LICENSE file. --> <div id="oauth-enrollment" class="step no-logo hidden" hidden> - <div id="oauth-enroll-cancel-button" class="oauth-enroll-button"></div> - <div id="oauth-enroll-back-button" class="oauth-enroll-button" hidden></div> + <div id="oauth-enroll-cancel-button" class="custom-gaia-button"></div> + <div id="oauth-enroll-back-button" class="custom-gaia-button" hidden></div> <div id="oauth-enroll-step-contents"> <div id="oauth-enroll-step-signin"> <div id="oauth-enroll-auth-view-container"></div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.js b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.js index 9b55fd1..159aaf7 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment_webview.js
@@ -106,9 +106,19 @@ $('oauth-enroll-error-retry').addEventListener('click', this.doRetry_.bind(this)); + + $('oauth-enroll-cancel-button').addEventListener('mousedown', + function(e) { + e.preventDefault(); + }); + $('oauth-enroll-cancel-button').addEventListener('click', this.cancel.bind(this)); + $('oauth-enroll-back-button').addEventListener('mousedown', function(e) { + e.preventDefault(); + }); + $('oauth-enroll-back-button').addEventListener('click', (function(e) { $('oauth-enroll-back-button').hidden = true;
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css index c6f585c..9af0271 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.css +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.css
@@ -69,21 +69,24 @@ display: none; } -#close-button-item { +.custom-gaia-button { background: transparent none; - background-image: url(chrome://theme/IDR_LOGIN_CLOSE_BUTTTON); background-position: center; background-repeat: no-repeat; - height: 14px; + height: 34px; position: absolute; - right: 15px; - top: 15px; - width: 14px; + top: 0; + width: 34px; z-index: 1; } +#close-button-item { + background-image: url(chrome://theme/IDR_LOGIN_CLOSE_BUTTTON); + right: 0; +} + html[dir=rtl] #close-button-item { - left: 15px; + left: 0; right: auto; } @@ -100,23 +103,19 @@ background-image: url(chrome://theme/IDR_LOGIN_CLOSE_BUTTTON_MASKED); } +#close-button-item:hover { + cursor: pointer; +} + #back-button-item { - background: transparent none; background-image: url(chrome://theme/IDR_LOGIN_BACK_BUTTTON); - background-position: center; - background-repeat: no-repeat; - height: 18px; - left: 14px; - position: absolute; - top: 14px; - width: 18px; - z-index: 1; + left: 0; } html[dir=rtl] #back-button-item { -webkit-transform: scaleX(-1); left: auto; - right: 14px; + right: 0; } .new-gaia-flow .full-width #back-button-item { @@ -127,6 +126,10 @@ background-image: url(chrome://theme/IDR_LOGIN_BACK_BUTTTON_MASKED); } +#back-button-item:hover { + cursor: pointer; +} + .signin-text { color: #666; margin-top: 20px;
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html index f257818..a2f5856d 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html
@@ -11,7 +11,7 @@ marginheight="0" frameborder="0" scrolling="no"></iframe> - <offline-gaia id="newgaia-offline-login" hidden></offline-gaia> + <offline-gaia id="offline-gaia" hidden></offline-gaia> </div> <div id="gaia-signin-divider" class="signin-divider" hidden></div> <div id="signin-right" hidden> @@ -44,8 +44,8 @@ <div id="saml-notice-container" hidden> <span id="saml-notice-message"></span> </div> - <button id="back-button-item" class="custom-appearance" hidden - i18n-values="aria-label:backButton" tabindex="0"></button> - <button id="close-button-item" class="custom-appearance" hidden - i18n-values="aria-label:closeButton" tabindex="0"></button> + <button id="back-button-item" class="custom-appearance custom-gaia-button" + hidden i18n-values="aria-label:backButton" tabindex="0"></button> + <button id="close-button-item" class="custom-appearance custom-gaia-button" + hidden i18n-values="aria-label:closeButton" tabindex="0"></button> </div>
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js index 2da77e3..a99819ca 100644 --- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js +++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -32,7 +32,8 @@ 'onWebviewError', 'onFrameError', 'updateCancelButtonState', - 'showWhitelistCheckFailedError' + 'showWhitelistCheckFailedError', + 'updateDeviceId', ], /** @@ -137,7 +138,7 @@ $('signin-frame').parentNode.replaceChild(webview, $('signin-frame')); this.gaiaAuthHost_ = new cr.login.GaiaAuthHost(webview); - $('newgaia-offline-login').addEventListener('authCompleted', + $('offline-gaia').addEventListener('authCompleted', this.onAuthCompletedMessage_.bind(this)); } else { this.gaiaAuthHost_ = new cr.login.GaiaAuthHost($('signin-frame')); @@ -152,6 +153,8 @@ 'backButton', this.onBackButton_.bind(this)); this.gaiaAuthHost_.addEventListener( 'showView', this.onShowView_.bind(this)); + this.gaiaAuthHost_.addEventListener('attemptLogin', + this.onAttemptLogin_.bind(this)); this.gaiaAuthHost_.confirmPasswordCallback = this.onAuthConfirmPassword_.bind(this); this.gaiaAuthHost_.noPasswordCallback = @@ -162,6 +165,8 @@ this.missingGaiaInfo_.bind(this); this.gaiaAuthHost_.samlApiUsedCallback = this.samlApiUsed_.bind(this); + this.gaiaAuthHost_.addEventListener('authDomainChange', + this.onAuthDomainChange_.bind(this)); this.gaiaAuthHost_.addEventListener('authFlowChange', this.onAuthFlowChange_.bind(this)); this.gaiaAuthHost_.addEventListener('authCompleted', @@ -174,12 +179,20 @@ e.preventDefault(); }); + $('back-button-item').addEventListener('mousedown', function(e) { + e.preventDefault(); + }); + $('back-button-item').addEventListener('click', function(e) { $('back-button-item').hidden = true; $('signin-frame').back(); e.preventDefault(); }); + $('close-button-item').addEventListener('mousedown', function(e) { + e.preventDefault(); + }); + $('close-button-item').addEventListener('click', function(e) { this.cancel(); e.preventDefault(); @@ -220,7 +233,7 @@ this.isLocal_ = value; if (this.isNewGaiaFlow) { $('signin-frame').hidden = this.isLocal_; - $('newgaia-offline-login').hidden = !this.isLocal_; + $('offline-gaia').hidden = !this.isLocal_; } chrome.send('updateOfflineLogin', [value]); }, @@ -233,7 +246,7 @@ showLoadingUI_: function(show) { $('gaia-loading').hidden = !show; if (this.isNewGaiaFlow && this.isLocal) { - $('newgaia-offline-login').hidden = show; + $('offline-gaia').hidden = show; } else { $('signin-frame').hidden = show; } @@ -365,7 +378,7 @@ onAfterShow: function(data) { if (!this.loading && this.isWebviewSignin) { if (this.isLocal) - $('newgaia-offline-login').focus(); + $('offline-gaia').focus(); else $('signin-frame').focus(); } @@ -415,7 +428,7 @@ params.chromeType = data.chromeType; params.isNewGaiaFlowChromeOS = true; $('login-header-bar').showGuestButton = true; - this.gaiaAuthHost_.setDeviceId(data.deviceId); + params.deviceId = data.deviceId; } if (data.gaiaEndpoint) @@ -521,16 +534,20 @@ }, /** - * Invoked when the authFlow property is changed no the gaia host. + * Invoked when the authDomain property is changed on the GAIA host. */ - onAuthFlowChange_: function() { - var isSAML = this.isSAML(); + onAuthDomainChange_: function() { + $('saml-notice-message').textContent = loadTimeData.getStringF( + 'samlNotice', + this.gaiaAuthHost_.authDomain); + }, - if (isSAML) { - $('saml-notice-message').textContent = loadTimeData.getStringF( - 'samlNotice', - this.gaiaAuthHost_.authDomain); - } + /** + * Invoked when the authFlow property is changed on the GAIA host. + * @param {Event} e Property change event. + */ + onAuthFlowChange_: function(e) { + var isSAML = this.isSAML(); this.classList.toggle('no-right-panel', isSAML); this.classList.toggle('full-width', isSAML); @@ -621,6 +638,16 @@ }, /** + * Invoked when the auth host emits 'attemptLogin' event. + * @param {Object} Message object with |detail| field keeping email: + * like {detail: 'user@gmail.com'} . + * @private + */ + onAttemptLogin_: function(e) { + chrome.send('attemptLogin', [e.detail]); + }, + + /** * Invoked when the user has successfully authenticated via SAML, the * principals API was not used and the auth host needs the user to confirm * the scraped password. @@ -904,9 +931,12 @@ * should switch to the password screen with error. */ loadOffline: function(params) { - var offlineLogin = $('newgaia-offline-login'); + var offlineLogin = $('offline-gaia'); var strings = params.localizedStrings; - offlineLogin.enterpriseInfo = strings['stringEnterpriseInfo']; + if ('stringEnterpriseInfo' in strings) + offlineLogin.enterpriseInfo = strings['stringEnterpriseInfo']; + if ('emailDomain' in params) + offlineLogin.emailDomain = '@' + params['emailDomain']; offlineLogin.setEmail(params.email); }, @@ -930,5 +960,17 @@ if (!show) Oobe.showSigninUI(); }, + + /** + * Inform Gaia of new deviceId. + * @param {data} Object like {'deviceId': 'test-device-id'} + */ + updateDeviceId: function(data) { + if (!this.isNewGaiaFlow) + return; + + if (data && data.deviceId) + this.gaiaAuthHost_.updateDeviceId(data.deviceId); + }, }; });
diff --git a/chrome/browser/resources/chromeos/login/screen_password_changed.css b/chrome/browser/resources/chromeos/login/screen_password_changed.css index 4bddd31fb..ca979220 100644 --- a/chrome/browser/resources/chromeos/login/screen_password_changed.css +++ b/chrome/browser/resources/chromeos/login/screen_password_changed.css
@@ -88,3 +88,14 @@ #password-changed.migrate.password-error #old-password-error { display: block; } + +.password-changed .new-gaia-flow #step-logo { + display: none; +} + +.new-gaia-flow #gaia-password-changed, +.new-gaia-flow #password-changed { + height: 528px; + padding: 0; + width: 448px; +}
diff --git a/chrome/browser/resources/chromeos/login/screen_password_changed.html b/chrome/browser/resources/chromeos/login/screen_password_changed.html index 1d80eed7..9f72357 100644 --- a/chrome/browser/resources/chromeos/login/screen_password_changed.html +++ b/chrome/browser/resources/chromeos/login/screen_password_changed.html
@@ -1,3 +1,4 @@ +<link rel="import" href="chrome://oobe/custom_elements.html"> <div id="password-changed" class="step faded hidden migrate" hidden> <div id="password-changed-contents" class="step-contents"> <div id="password-changed-title" i18n-content="passwordChangedTitle"> @@ -14,9 +15,11 @@ <div id="password-changed-link-block"> <a id="password-changed-cant-remember-link" href="#" i18n-content="passwordChangedCantRemember"></a> - </div> + </div> <div id="password-changed-proceed-anyway-warning" i18n-content="passwordChangedProceedAnyway"></div> </div> <div id="password-changed-controls" class="step-controls"></div> + <gaia-password-changed id="gaia-password-changed" hidden> + </gaia-password-changed> </div>
diff --git a/chrome/browser/resources/chromeos/login/screen_password_changed.js b/chrome/browser/resources/chromeos/login/screen_password_changed.js index aadc459..4f22fb8 100644 --- a/chrome/browser/resources/chromeos/login/screen_password_changed.js +++ b/chrome/browser/resources/chromeos/login/screen_password_changed.js
@@ -42,6 +42,20 @@ $('password-changed-ok-button').disabled = true; } }); + + var gaiaPasswordChanged = $('gaia-password-changed'); + gaiaPasswordChanged.addEventListener('cancel', function(e) { + chrome.send('cancelPasswordChangedFlow'); + gaiaPasswordChanged.reset(); + }); + + gaiaPasswordChanged.addEventListener('passwordEnter', function(e) { + chrome.send('migrateUserData', [e.detail.password]); + }); + + gaiaPasswordChanged.addEventListener('proceedAnyway', function() { + chrome.send('resyncUserData'); + }); }, /** @@ -119,6 +133,10 @@ value ? 'add' : 'remove']('disabled'); }, + get isNewGaiaFlow() { + return document.querySelector('.new-gaia-flow') != undefined; + }, + /** * Cancels password migration and drops the user back to the login screen. */ @@ -139,6 +157,11 @@ chrome.send('migrateUserData', [$('old-password').value]); }, + onAfterShow: function(data) { + if (this.isNewGaiaFlow) + $('gaia-password-changed').focus(); + }, + /** * Event handler that is invoked just before the screen is hidden. */ @@ -158,19 +181,32 @@ * Show password changed screen. * @param {boolean} showError Whether to show the incorrect password error. */ - show: function(showError) { + show: function(showError, email) { + if (this.isNewGaiaFlow) { + $('password-changed-contents').hidden = true; + $('password-changed-controls').hidden = true; + var gaiaPasswordChanged = $('gaia-password-changed'); + gaiaPasswordChanged.reset(); + gaiaPasswordChanged.hidden = false; + if (showError) + gaiaPasswordChanged.invalidate(); + if (email) + gaiaPasswordChanged.email = email; + } else { + var screen = $('password-changed'); + screen.classList.toggle('password-error', showError); + screen.classList.add('migrate'); + screen.classList.remove('resync'); + $('old-password').value = ''; + $('password-changed').disabled = false; + } // We'll get here after the successful online authentication. // It assumes session is about to start so hides login screen controls. Oobe.getInstance().headerHidden = false; - var screen = $('password-changed'); - screen.classList.toggle('password-error', showError); - screen.classList.add('migrate'); - screen.classList.remove('resync'); - $('old-password').value = ''; - $('password-changed').disabled = false; - Oobe.showScreen({id: SCREEN_PASSWORD_CHANGED}); - $('password-changed-ok-button').disabled = true; + $('login-header-bar').signinUIState = SIGNIN_UI_STATE.PASSWORD_CHANGED; + if (!this.isNewGaiaFlow) + $('password-changed-ok-button').disabled = true; } }; });
diff --git a/chrome/browser/resources/downloads/item_view.js b/chrome/browser/resources/downloads/item_view.js index 4611ca8..bf2a09a 100644 --- a/chrome/browser/resources/downloads/item_view.js +++ b/chrome/browser/resources/downloads/item_view.js
@@ -346,13 +346,15 @@ switch (data.state) { case Item.States.IN_PROGRESS: case Item.States.PAUSED: // Fallthrough. - return assert(data.progress_status_text); + assert(typeof data.progress_status_text == 'string'); + return data.progress_status_text; case Item.States.CANCELLED: return loadTimeData.getString('status_cancelled'); case Item.States.DANGEROUS: break; // Intentionally hit assertNotReached(); at bottom. case Item.States.INTERRUPTED: - return assert(data.last_reason_text); + assert(typeof data.last_reason_text == 'string'); + return data.last_reason_text; case Item.States.COMPLETE: return data.file_externally_removed ? loadTimeData.getString('status_removed') : '';
diff --git a/chrome/browser/resources/extensions/extension_list.js b/chrome/browser/resources/extensions/extension_list.js index fe1cec3..731002a 100644 --- a/chrome/browser/resources/extensions/extension_list.js +++ b/chrome/browser/resources/extensions/extension_list.js
@@ -162,15 +162,26 @@ compare(a.id, b.id); } + /** @interface */ + function ExtensionListDelegate() {} + + ExtensionListDelegate.prototype = { + /** + * Called when the number of extensions in the list has changed. + */ + onExtensionCountChanged: assertNotReached, + }; + /** * Creates a new list of extensions. + * @param {extensions.ExtensionListDelegate} delegate * @constructor * @extends {HTMLDivElement} */ - function ExtensionList() { + function ExtensionList(delegate) { var div = document.createElement('div'); div.__proto__ = ExtensionList.prototype; - div.initialize(); + div.initialize(delegate); return div; } @@ -230,11 +241,25 @@ /** * Initializes the list. + * @param {!extensions.ExtensionListDelegate} delegate */ - initialize: function() { + initialize: function(delegate) { /** @private {!Array<ExtensionInfo>} */ this.extensions_ = []; + /** @private {!extensions.ExtensionListDelegate} */ + this.delegate_ = delegate; + + /** + * |loadFinished| should be used for testing purposes and will be + * fulfilled when this list has finished loading the first time. + * @type {Promise} + * */ + this.loadFinished = new Promise(function(resolve, reject) { + /** @private {function(?)} */ + this.resolveLoadFinished_ = resolve; + }.bind(this)); + chrome.developerPrivate.onItemStateChanged.addListener( function(eventData) { var EventType = chrome.developerPrivate.EventType; @@ -250,12 +275,19 @@ this.updateExtension_(eventData.extensionInfo); break; case EventType.UNINSTALLED: + var index = this.getIndexOfExtension_(eventData.item_id); + this.extensions_.splice(index, 1); var childNode = $(eventData.item_id); childNode.parentNode.removeChild(childNode); break; default: assertNotReached(); } + + if (eventData.event_type == EventType.INSTALLED || + eventData.event_type == EventType.UNINSTALLED) { + this.delegate_.onExtensionCountChanged(); + } }.bind(this)); }, @@ -283,16 +315,60 @@ this.extensions_ = extensions; this.showExtensionNodes_(); resolve(); + + // |resolve| is async so it's necessary to use |then| here in order to + // do work after other |then|s have finished. This is important so + // elements are visible when these updates happen. + this.extensionsUpdated_.then(function() { + this.onUpdateFinished_(); + this.resolveLoadFinished_(); + }.bind(this)); }.bind(this)); }.bind(this)); return this.extensionsUpdated_; }, + /** + * Updates elements that need to be visible in order to update properly. + * @private + */ + onUpdateFinished_: function() { + // Cannot focus or highlight a extension if there are none. + if (this.extensions_.length == 0) + return; + + assert(!this.hidden); + assert(!this.parentElement.hidden); + + this.updateFocusableElements(); + + var idToHighlight = this.getIdQueryParam_(); + if (idToHighlight && $(idToHighlight)) + this.scrollToNode_(idToHighlight); + + var idToOpenOptions = this.getOptionsQueryParam_(); + if (idToOpenOptions && $(idToOpenOptions)) + this.showEmbeddedExtensionOptions_(idToOpenOptions, true); + }, + /** @return {number} The number of extensions being displayed. */ getNumExtensions: function() { return this.extensions_.length; }, + /** + * @param {string} id The id of the extension. + * @return {number} The index of the extension with the given id. + * @private + */ + getIndexOfExtension_: function(id) { + for (var i = 0; i < this.extensions_.length; ++i) { + if (this.extensions_[i].id == id) + return i; + } + return -1; + }, + getIdQueryParam_: function() { return parseQueryParams(document.location)['id']; }, @@ -337,14 +413,6 @@ assertInstanceof(node, ExtensionFocusRow).destroy(); } } - - var idToHighlight = this.getIdQueryParam_(); - if (idToHighlight && $(idToHighlight)) - this.scrollToNode_(idToHighlight); - - var idToOpenOptions = this.getOptionsQueryParam_(); - if (idToOpenOptions && $(idToOpenOptions)) - this.showEmbeddedExtensionOptions_(idToOpenOptions, true); }, /** Updates each row's focusable elements without rebuilding the grid. */ @@ -1030,13 +1098,7 @@ * @private */ updateExtension_: function(extension) { - var currIndex = -1; - for (var i = 0; i < this.extensions_.length; ++i) { - if (this.extensions_[i].id == extension.id) { - currIndex = i; - break; - } - } + var currIndex = this.getIndexOfExtension_(extension.id); if (currIndex != -1) { // If there is a current version of the extension, update it with the // new version. @@ -1060,6 +1122,7 @@ }; return { - ExtensionList: ExtensionList + ExtensionList: ExtensionList, + ExtensionListDelegate: ExtensionListDelegate }; });
diff --git a/chrome/browser/resources/extensions/extensions.css b/chrome/browser/resources/extensions/extensions.css index 13f1dfda..19ab82c3 100644 --- a/chrome/browser/resources/extensions/extensions.css +++ b/chrome/browser/resources/extensions/extensions.css
@@ -159,6 +159,7 @@ .extension-list-item { background-repeat: no-repeat; + background-size: 48px 48px; display: -webkit-box; min-height: 48px; }
diff --git a/chrome/browser/resources/extensions/extensions.js b/chrome/browser/resources/extensions/extensions.js index 06b62379..48dfa5d 100644 --- a/chrome/browser/resources/extensions/extensions.js +++ b/chrome/browser/resources/extensions/extensions.js
@@ -98,6 +98,8 @@ /** * ExtensionSettings class * @class + * @constructor + * @implements {extensions.ExtensionListDelegate} */ function ExtensionSettings() {} @@ -133,7 +135,7 @@ // Set the title. uber.setTitle(loadTimeData.getString('extensionSettings')); - var extensionList = new ExtensionList(); + var extensionList = new ExtensionList(this); extensionList.id = 'extension-settings-list'; var wrapper = $('extension-list-wrapper'); wrapper.insertBefore(extensionList, wrapper.firstChild); @@ -274,11 +276,7 @@ document.documentElement.classList.remove('loading'); }, 0); - /** @const */ - var hasExtensions = extensionList.getNumExtensions() != 0; - $('no-extensions').hidden = hasExtensions; - $('extension-list-wrapper').hidden = !hasExtensions; - $('extension-settings-list').updateFocusableElements(); + this.onExtensionCountChanged(); }.bind(this)); }, @@ -294,10 +292,9 @@ /** * Shows the Extension Commands configuration UI. - * @param {Event} e Change event. * @private */ - showExtensionCommandsConfigUi_: function(e) { + showExtensionCommandsConfigUi_: function() { ExtensionSettings.showOverlay($('extension-commands-overlay')); chrome.send('metricsHandler:recordAction', ['Options_ExtensionCommands']); @@ -348,8 +345,20 @@ buttons.offsetHeight + 'px'; }.bind(this)); }, + + /** @override */ + onExtensionCountChanged: function() { + /** @const */ + var hasExtensions = $('extension-settings-list').getNumExtensions() != 0; + $('no-extensions').hidden = hasExtensions; + $('extension-list-wrapper').hidden = !hasExtensions; + }, }; + /** + * Called by the WebUI when something has changed and the extensions UI needs + * to be updated. + */ ExtensionSettings.onExtensionsChanged = function() { ExtensionSettings.getInstance().update_(); };
diff --git a/chrome/browser/resources/feedback/js/event_handler.js b/chrome/browser/resources/feedback/js/event_handler.js index 02436db..d212c49d 100644 --- a/chrome/browser/resources/feedback/js/event_handler.js +++ b/chrome/browser/resources/feedback/js/event_handler.js
@@ -63,6 +63,8 @@ 'E216473E4D15C5FB14522D32C5F8DEAAB2CECDC6', // http://crbug.com/470411 '676A08383D875E51CE4C2308D875AE77199F1413', // http://crbug.com/473845 '869A23E11B308AF45A68CC386C36AADA4BE44A01', // http://crbug.com/473845 + 'A4577D8C2AF4CF26F40CBCA83FFA4251D6F6C8F8', // http://crbug.com/478929 + 'A8208CCC87F8261AFAEB6B85D5E8D47372DDEA6B', // http://crbug.com/478929 ];
diff --git a/chrome/browser/resources/gaia_auth_host/authenticator.js b/chrome/browser/resources/gaia_auth_host/authenticator.js index 0fc093e2..80aa4b8 100644 --- a/chrome/browser/resources/gaia_auth_host/authenticator.js +++ b/chrome/browser/resources/gaia_auth_host/authenticator.js
@@ -76,6 +76,7 @@ 'constrained', // Whether the extension is loaded in a constrained // window. 'clientId', // Chrome client id. + 'useEafe', // Whether to use EAFE. 'needPassword', // Whether the host is interested in getting a password. // If this set to |false|, |confirmPasswordCallback| is // not called before dispatching |authCopleted|. @@ -105,6 +106,7 @@ this.chooseWhatToSync_ = false; this.skipForNow_ = false; this.authFlow = AuthFlow.DEFAULT; + this.authDomain = ''; this.loaded_ = false; this.idpOrigin_ = null; this.continueUrl_ = null; @@ -117,6 +119,9 @@ this.sessionIsEphemeral_ = null; this.onBeforeSetHeadersSet_ = false; + this.useEafe_ = false; + this.clientId_ = null; + this.samlHandler_ = new cr.login.SamlHandler(this.webview_); this.confirmPasswordCallback = null; this.noPasswordCallback = null; @@ -130,12 +135,6 @@ this.samlHandler_.addEventListener( 'authPageLoaded', this.onAuthPageLoaded_.bind(this)); - Object.defineProperty(this, 'authDomain', { - get: (function() { - return this.samlHandler_.authDomain; - }).bind(this), - enumerable: true - }); this.webview_.addEventListener('droplink', this.onDropLink_.bind(this)); this.webview_.addEventListener( @@ -198,6 +197,8 @@ this.continueUrl_; this.isConstrainedWindow_ = data.constrained == '1'; this.isNewGaiaFlowChromeOS = data.isNewGaiaFlowChromeOS; + this.useEafe_ = data.useEafe || false; + this.clientId_ = data.clientId; this.initialFrameUrl_ = this.constructInitialFrameUrl_(data); this.reloadUrl_ = data.frameUrl || this.initialFrameUrl_; @@ -247,7 +248,7 @@ url = appendParam(url, 'client_id', data.clientId); if (data.enterpriseDomain) url = appendParam(url, 'manageddomain', data.enterpriseDomain); - this.setDeviceId(data.deviceId); + this.deviceId_ = data.deviceId; this.sessionIsEphemeral_ = data.sessionIsEphemeral; } else { url = appendParam(url, 'continue', this.continueUrl_); @@ -269,13 +270,6 @@ }; /** - * Invoked when deviceId is set or updated. - */ - Authenticator.prototype.setDeviceId = function(deviceId) { - this.deviceId_ = deviceId; - }; - - /** * Invoked when a main frame request in the webview has completed. * @private */ @@ -400,11 +394,7 @@ if (this.isNewGaiaFlowChromeOS && this.deviceId_) { var headers = details.requestHeaders; var found = false; - var deviceId; - if (this.sessionIsEphemeral_) - deviceId = EPHEMERAL_DEVICE_ID_PREFIX + this.deviceId_; - else - deviceId = this.deviceId_; + var deviceId = this.getGAIADeviceId_(); for (var i = 0, l = headers.length; i < l; ++i) { if (headers[i].name == X_DEVICE_ID_HEADER) { @@ -424,29 +414,61 @@ }; /** - * Invoked when an HTML5 message is received from the webview element. + * Returns true if given HTML5 message is received from the webview element. * @param {object} e Payload of the received HTML5 message. - * @private */ - Authenticator.prototype.onMessageFromWebview_ = function(e) { + Authenticator.prototype.isGaiaMessage = function(e) { if (!this.isWebviewEvent_(e)) - return; + return false; // The event origin does not have a trailing slash. if (e.origin != this.idpOrigin_.substring(0, this.idpOrigin_.length - 1)) { + return false; + } + + // EAFE passes back auth code via message. + if (this.useEafe_ && + typeof e.data == 'object' && + e.data.hasOwnProperty('authorizationCode')) { + assert(!this.oauth_code_); + this.oauth_code_ = e.data.authorizationCode; + this.dispatchEvent( + new CustomEvent('authCompleted', + { + detail: { + authCodeOnly: true, + authCode: this.oauth_code_ + } + })); return; } // Gaia messages must be an object with 'method' property. if (typeof e.data != 'object' || !e.data.hasOwnProperty('method')) { - return; + return false; } + return true; + }; + + /** + * Invoked when an HTML5 message is received from the webview element. + * @param {object} e Payload of the received HTML5 message. + * @private + */ + Authenticator.prototype.onMessageFromWebview_ = function(e) { + if (!this.isGaiaMessage(e)) + return; var msg = e.data; if (msg.method == 'attemptLogin') { this.email_ = msg.email; this.password_ = msg.password; this.chooseWhatToSync_ = msg.chooseWhatToSync; + // We need to dispatch only first event, before user enters password. + if (!msg.password) { + this.dispatchEvent( + new CustomEvent('attemptLogin', {detail: msg.email})); + } } else if (msg.method == 'dialogShown') { this.dispatchEvent(new Event('dialogShown')); } else if (msg.method == 'dialogHidden') { @@ -549,6 +571,7 @@ deviceId: this.deviceId_ || '' } })); + this.clearCredentials_(); }; /** @@ -571,12 +594,8 @@ if (!e.detail.isSAMLPage) return; - if (this.authFlow != AuthFlow.SAML) { - this.authFlow = AuthFlow.SAML; - } else { - // Force an authFlowChanged event to update UI with updated auth doamin. - cr.dispatchPropertyChange(this, 'authFlow'); - } + this.authDomain = this.samlHandler_.authDomain; + this.authFlow = AuthFlow.SAML; }; /** @@ -612,8 +631,10 @@ var currentUrl = this.webview_.src; if (currentUrl.lastIndexOf(this.idpOrigin_) == 0) { var msg = { - 'method': 'handshake' + 'method': 'handshake', + 'deviceId': this.getGAIADeviceId_(), }; + this.webview_.contentWindow.postMessage(msg, currentUrl); } }; @@ -639,6 +660,21 @@ // Focus webview after dispatching event when webview is already visible. this.webview_.focus(); } + + // Sends client id to EAFE on every loadstop after a small timeout. This is + // needed because EAFE sits behind SSO and initialize asynchrounouly + // and we don't know for sure when it is loaded and ready to listen + // for message. The postMessage is guarded by EAFE's origin. + if (this.useEafe_) { + // An arbitrary small timeout for delivering the initial message. + var EAFE_INITIAL_MESSAGE_DELAY_IN_MS = 500; + window.setTimeout((function() { + var msg = { + 'clientId': this.clientId_ + }; + this.webview_.contentWindow.postMessage(msg, this.idpOrigin_); + }).bind(this), EAFE_INITIAL_MESSAGE_DELAY_IN_MS); + } }; /** @@ -665,11 +701,48 @@ }; /** + * Format deviceId for GAIA . + * @return {string} deviceId. + * @private + */ + Authenticator.prototype.getGAIADeviceId_ = function() { + // deviceId_ is empty when we do not need to send it. For example, + // in case of device enrollment. + if (!(this.isNewGaiaFlowChromeOS && this.deviceId_)) + return; + + if (this.sessionIsEphemeral_) + return EPHEMERAL_DEVICE_ID_PREFIX + this.deviceId_; + else + return this.deviceId_; + }; + + /** + * Informs Gaia of new deviceId to be used. + */ + Authenticator.prototype.updateDeviceId = function(deviceId) { + this.deviceId_ = deviceId; + var msg = { + 'method': 'updateDeviceId', + 'deviceId': this.getGAIADeviceId_(), + }; + + var currentUrl = this.webview_.src; + this.webview_.contentWindow.postMessage(msg, currentUrl); + }; + + /** * The current auth flow of the hosted auth page. * @type {AuthFlow} */ cr.defineProperty(Authenticator, 'authFlow'); + /** + * The domain name of the current auth page. + * @type {string} + */ + cr.defineProperty(Authenticator, 'authDomain'); + Authenticator.AuthFlow = AuthFlow; Authenticator.AuthMode = AuthMode; Authenticator.SUPPORTED_PARAMS = SUPPORTED_PARAMS;
diff --git a/chrome/browser/resources/gaia_auth_host/gaia_auth_host.js b/chrome/browser/resources/gaia_auth_host/gaia_auth_host.js index 44dcc80..5970e1eb3 100644 --- a/chrome/browser/resources/gaia_auth_host/gaia_auth_host.js +++ b/chrome/browser/resources/gaia_auth_host/gaia_auth_host.js
@@ -125,12 +125,6 @@ reloadUrl_: null, /** - * The domain name of the current auth page. - * @type {string} - */ - authDomain: '', - - /** * Invoked when authentication is completed successfully with credential * data. A credential data object looks like this: * <pre> @@ -440,6 +434,12 @@ }; /** + * The domain name of the current auth page. + * @type {string} + */ + cr.defineProperty(GaiaAuthHost, 'authDomain'); + + /** * The current auth flow of the hosted gaia_auth extension. * @type {AuthFlow} */
diff --git a/chrome/browser/resources/gaia_auth_host/saml_handler.js b/chrome/browser/resources/gaia_auth_host/saml_handler.js index b41fad8..bf6db2dfc 100644 --- a/chrome/browser/resources/gaia_auth_host/saml_handler.js +++ b/chrome/browser/resources/gaia_auth_host/saml_handler.js
@@ -157,6 +157,14 @@ {urls: ['<all_urls>'], types: ['main_frame', 'xmlhttprequest']}, ['blocking', 'responseHeaders']); + this.webview_.addContentScripts([{ + 'name': 'samlInjected', + 'matches': ['http://*/*', 'https://*/*'], + 'code': injectedJs, + 'all_frames': true, + 'run_at': 'document_start' + }]); + PostMessageChannel.runAsDaemon(this.onConnected_.bind(this)); } @@ -223,22 +231,6 @@ }, /** - * Injects JS code to all frames. - * @private - */ - injectJs_: function() { - if (!injectedJs) - return; - - // TODO(xiyuan): Replace this with webview.addContentScript. - this.webview_.executeScript({ - code: injectedJs, - allFrames: true, - runAt: 'document_start' - }); - }, - - /** * Invoked on the webview's contentload event. * @private */ @@ -273,7 +265,6 @@ } this.isSamlPage_ = this.pendingIsSamlPage_; - this.injectJs_(); }, /** @@ -454,14 +445,6 @@ }, }; - /** - * Sets the saml injected JS code. - * @param {string} samlInjectedJs JS code to inejct for Saml. - */ - SamlHandler.setSamlInjectedJs = function(samlInjectedJs) { - injectedJs = samlInjectedJs; - }; - return { SamlHandler: SamlHandler };
diff --git a/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js b/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js index 012c17f..84dcb2a 100644 --- a/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js +++ b/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js
@@ -2,21 +2,5 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -'use strict'; - -/** - * Global injection guard that starts as undefined and sets to true after the - * first run. This is for webview.executeScript injection where the execution - * environment remains the same for multiple injections. - * @type {boolean} - */ -var samlInjectedInitialized; - -(function() { - if (samlInjectedInitialized) - return; - samlInjectedInitialized = true; - - <include src="post_message_channel.js"> - <include src="../gaia_auth/saml_injected.js"> -})(); +<include src="post_message_channel.js"> +<include src="../gaia_auth/saml_injected.js">
diff --git a/chrome/browser/resources/google_now/background.js b/chrome/browser/resources/google_now/background.js index e24f70b..2db2d1e 100644 --- a/chrome/browser/resources/google_now/background.js +++ b/chrome/browser/resources/google_now/background.js
@@ -202,6 +202,7 @@ // Add error processing to API calls. wrapper.instrumentChromeApiFunction('gcm.onMessage.addListener', 0); wrapper.instrumentChromeApiFunction('gcm.register', 1); +wrapper.instrumentChromeApiFunction('gcm.unregister', 0); wrapper.instrumentChromeApiFunction('metricsPrivate.getVariationParams', 1); wrapper.instrumentChromeApiFunction('notifications.clear', 1); wrapper.instrumentChromeApiFunction('notifications.create', 2); @@ -1027,7 +1028,8 @@ */ function initialize() { recordEvent(GoogleNowEvent.EXTENSION_START); - registerForGcm(); + // TODO(skare): Reenable, after signin. + unregisterFromGcm(); onStateChange(); } @@ -1311,6 +1313,24 @@ } /** + * Unregisters from GCM if previously registered. + */ +function unregisterFromGcm() { + fillFromChromeLocalStorage({gcmRegistrationId: undefined}) + .then(function(items) { + if (items.gcmRegistrationId) { + console.log('Unregistering from gcm.'); + instrumented.gcm.unregister(function() { + if (!chrome.runtime.lastError) { + chrome.storage.local.remove( + ['gcmNotificationKey', 'gcmRegistrationId']); + } + }); + } + }); +} + +/** * Polls the optin state. * Sometimes we get the response to the opted in result too soon during * push messaging. We'll recheck the optin state a few times before giving up.
diff --git a/chrome/browser/resources/hangout_services/manifest.json b/chrome/browser/resources/hangout_services/manifest.json index e9ef7aa..95d5464 100644 --- a/chrome/browser/resources/hangout_services/manifest.json +++ b/chrome/browser/resources/hangout_services/manifest.json
@@ -7,7 +7,10 @@ "manifest_version": 2, "externally_connectable": { "matches": [ - "https://*.google.com/hangouts*", + "https://hangouts.google.com/*", + "https://talkgadget.google.com/*", + "https://*.talkgadget.google.com/*", + "https://plus.google.com/hangouts*", // For tests. "*://localhost/*" ]
diff --git a/chrome/browser/resources/inspect/inspect.css b/chrome/browser/resources/inspect/inspect.css index c940215..1d07473 100644 --- a/chrome/browser/resources/inspect/inspect.css +++ b/chrome/browser/resources/inspect/inspect.css
@@ -138,11 +138,6 @@ background-color: rgb(224, 32, 32); } -.port-icon.connected { - -webkit-transform: scale(1.2); - background-color: rgb(0, 255, 0); -} - .port-icon.transient { -webkit-transform: scale(1.2); background-color: orange;
diff --git a/chrome/browser/resources/inspect/inspect.js b/chrome/browser/resources/inspect/inspect.js index 78f117d..1ff6dc5 100644 --- a/chrome/browser/resources/inspect/inspect.js +++ b/chrome/browser/resources/inspect/inspect.js
@@ -917,11 +917,7 @@ var portIcon = document.createElement('div'); portIcon.className = 'port-icon'; // status === 0 is the default (connected) state. - // Positive values correspond to the tunnelling connection count - // (in DEBUG_DEVTOOLS mode). - if (status > 0) - portIcon.classList.add('connected'); - else if (status === -1 || status === -2) + if (status === -1 || status === -2) portIcon.classList.add('transient'); else if (status < 0) portIcon.classList.add('error'); @@ -930,8 +926,6 @@ var portNumber = document.createElement('div'); portNumber.className = 'port-number'; portNumber.textContent = ':' + port; - if (status > 0) - portNumber.textContent += '(' + status + ')'; devicePorts.appendChild(portNumber); }
diff --git a/chrome/browser/resources/local_ntp/local_ntp_fast.css b/chrome/browser/resources/local_ntp/local_ntp_fast.css index 61434a1f..5026e21 100644 --- a/chrome/browser/resources/local_ntp/local_ntp_fast.css +++ b/chrome/browser/resources/local_ntp/local_ntp_fast.css
@@ -190,7 +190,7 @@ .icon-ntp #mv-tiles { background: rgba(255,255,255,0.2); border-radius: 4px; - height: calc(2 * 120px); + height: calc(2 * 112px); padding: calc(36px - 18px) calc(36px - 18px - 12px); }
diff --git a/chrome/browser/resources/media_router/elements/media_router_sink_picker/media_router_sink_picker.html b/chrome/browser/resources/media_router/elements/media_router_sink_picker/media_router_sink_picker.html new file mode 100644 index 0000000..46ca70e --- /dev/null +++ b/chrome/browser/resources/media_router/elements/media_router_sink_picker/media_router_sink_picker.html
@@ -0,0 +1,14 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="../media_router_sink/media_router_sink.html"> +<polymer-element name="media-router-sink-picker"> +<template> + <div> + <template repeat="{{sink in sinkList}}"> + <media-router-sink on-click="{{onClickSink}}" sink="{{sink}}" + route="{{routeMap[sinkToRouteMap[sink.id]]}}"> + </media-router-sink> + </template> + </div> +</template> +<script src="media_router_sink_picker.js"></script> +</polymer-element>
diff --git a/chrome/browser/resources/media_router/elements/media_router_sink_picker/media_router_sink_picker.js b/chrome/browser/resources/media_router/elements/media_router_sink_picker/media_router_sink_picker.js new file mode 100644 index 0000000..85f0fcbf --- /dev/null +++ b/chrome/browser/resources/media_router/elements/media_router_sink_picker/media_router_sink_picker.js
@@ -0,0 +1,123 @@ +// 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. + +// Shows a list of discovered sinks and their routes, if they exist. +Polymer('media-router-sink-picker', { + publish: { + /** + * List of current routes. + * + * @attribute routeList + * @type {!Array<!media_router.Route>} + * @default [] + */ + routeList: [], + + /** + * List of discovered sinks. + * + * @attribute sinkList + * @type {!Array<!media_router.Sink>} + * @default [] + */ + sinkList: [], + }, + + observe: { + routeList: 'rebuildRouteMaps', + sinkList: 'rebuildSinkMap', + }, + + created: function() { + /** + * Maps media_router.Sink.id to corresponding media_router.Sink. + * @type {!Object<string, !media_router.Sink>} + */ + this.sinkMap = {}; + + /** + * Maps media_router.Route.id to corresponding media_router.Route. + * @type {!Object<string, !media_router.Route>} + */ + this.routeMap = {}; + + /** + * Maps media_router.Sink.id to corresponding media_router.Route.id. + * @type {!Object<string, string>} + */ + this.sinkToRouteMap = {}; + }, + + /** + * Called when routeList is updated. Rebuilds routeMap and sinkToRouteMap. + */ + rebuildRouteMaps: function() { + // Reset routeMap and sinkToRouteMap. + this.routeMap = {}; + this.sinkToRouteMap = {}; + + // Rebuild routeMap and sinkToRouteMap. + this.routeList.forEach(function(route) { + this.routeMap[route.id] = route; + this.sinkToRouteMap[route.sinkId] = route.id; + }, this); + }, + + /** + * Called when sinkList is updated. Rebuilds sinkMap. + */ + rebuildSinkMap: function() { + // Reset sinkMap. + this.sinkMap = {}; + + // Rebuild sinkMap. + this.sinkList.forEach(function(sink) { + this.sinkMap[sink.id] = sink; + }, this); + }, + + /** + * Adds route to routeList. + * + * @param {!media_router.Route} route The route to add. + */ + addRoute: function(route) { + // Check if the route already exists or if its associated sink + // does not exist. + if (this.routeMap[route.id] || !this.sinkMap[route.sinkId]) + return; + + // If there is an existing route associated with the same sink, its + // sinkToRouteMap entry will be overwritten with that of the new route, + // which results in the correct sink to route mapping. + this.routeList.push(route); + }, + + /** + * Returns the sink corresponding to sinkId. + * + * @param {string} sinkId The id of the media_router.Sink. + * @return {!media_router.Sink} + */ + getSink: function(sinkId) { + return this.sinkMap[sinkId]; + }, + + /** + * Fires a sink-click event. This is called when a media-router-sink + * is clicked. + * + * @param {!Event} event The event object. + * @param {Object} detail The details of the event. + * @param {!Element} sender Reference to clicked node. + */ + onClickSink: function(event, detail, sender) { + // TODO(imcheng): Indicate route request is in progress. + // TODO(imcheng): Only allow one request route at a time. + this.fire('sink-click', { + sink: sender.sink, + route: sender.route + }); + }, +});
diff --git a/chrome/browser/resources/media_router/media_router.html b/chrome/browser/resources/media_router/media_router.html new file mode 100644 index 0000000..883ac58 --- /dev/null +++ b/chrome/browser/resources/media_router/media_router.html
@@ -0,0 +1,17 @@ +<!DOCTYPE HTML> +<html i18n-values="dir:textdirection;lang:language"> +<head> + <meta charset="utf-8"> + <title i18n-content="mediaRouterTitle"></title> + <!-- + TODO(apacible): Add media router resources when available. + --> + <script src="chrome://resources/js/load_time_data.js"></script> +</head> +<body> + <!-- + TODO(apacible): Add media router resources when available. + --> + <script src="chrome://resources/js/i18n_template_polymer.js"></script> +</body> +</html>
diff --git a/chrome/browser/resources/net_internals/quic_view.html b/chrome/browser/resources/net_internals/quic_view.html index f4d5d4f..d90ebee 100644 --- a/chrome/browser/resources/net_internals/quic_view.html +++ b/chrome/browser/resources/net_internals/quic_view.html
@@ -1,7 +1,12 @@ <div id=quic-view-tab-content class=content-box> <ul style='margin-top:0'> <li>QUIC Enabled: <span jscontent="!!quic_enabled"></span></li> - <li>Alternate Protocol Probability Threshold: <span jscontent="alternate_protocol_probability_threshold"></span></li> + <!-- "alternative_service_probability_threshold" is used since release 44, + see https://crrev.com/1091283007. + "alternate_protocol_probability_threshold" is here to support importing + netlog json files from earlier browsers. + TODO(bnc): Deprecate around 2016 January. --!> + <li>Alternative Service Probability Threshold: <span jscontent="$this.alternative_service_probability_threshold || $this.alternate_protocol_probability_threshold"></span></li> <li>Origin To Force QUIC On: <span jscontent="origin_to_force_quic_on"></span></li> <li>QUIC connection options: <span jscontent="connection_options"></span></li> <li>Consistent Port Selection Enabled: <span jscontent="!!enable_quic_port_selection"></span></li>
diff --git a/chrome/browser/resources/net_internals/spdy_view.html b/chrome/browser/resources/net_internals/spdy_view.html index fbb047c..4168785 100644 --- a/chrome/browser/resources/net_internals/spdy_view.html +++ b/chrome/browser/resources/net_internals/spdy_view.html
@@ -2,8 +2,6 @@ <ul id=spdy-view-status style='margin-top:0'> <li>HTTP/2 Enabled: <span jscontent="spdy_enabled"></span></li> <li>Use Alternative Service: <span jscontent="use_alternate_protocols"></span></li> - <li>Force HTTP/2 Always: <span jscontent="force_spdy_always"></span></li> - <li>Force HTTP/2 Over SSL: <span jscontent="force_spdy_over_ssl"></span></li> <li>Next Protocols: <span jscontent="next_protos"></span></li> </ul>
diff --git a/chrome/browser/resources/options/pref_ui.js b/chrome/browser/resources/options/pref_ui.js index a4a1127..c0776fee 100644 --- a/chrome/browser/resources/options/pref_ui.js +++ b/chrome/browser/resources/options/pref_ui.js
@@ -390,7 +390,13 @@ PrefSelect.prototype = { // Set up the prototype chain - __proto__: PrefInputElement.prototype, + __proto__: HTMLSelectElement.prototype, + + /** @override */ + decorate: PrefInputElement.prototype.decorate, + + /** @override */ + handleChange: PrefInputElement.prototype.handleChange, /** * Update the associated pref when when the user selects an item. @@ -449,8 +455,47 @@ if (this.onchange) this.onchange(event); }, + + /** @override */ + setDisabled: PrefInputElement.prototype.setDisabled, + + /** @override */ + customChangeHandler: PrefInputElement.prototype.customChangeHandler, + + /** @override */ + customPrefChangeHandler: PrefInputElement.prototype.customPrefChangeHandler, }; + /** + * The name of the associated preference. + */ + cr.defineProperty(PrefSelect, 'pref', cr.PropertyKind.ATTR); + + /** + * The data type of the associated preference, only relevant for derived + * classes that support different data types. + */ + cr.defineProperty(PrefSelect, 'dataType', cr.PropertyKind.ATTR); + + /** + * Whether this input element is part of a dialog. If so, changes take effect + * in the settings UI immediately but are only actually committed when the + * user confirms the dialog. If the user cancels the dialog instead, the + * changes are rolled back in the settings UI and never committed. + */ + cr.defineProperty(PrefSelect, 'dialogPref', cr.PropertyKind.BOOL_ATTR); + + /** + * Whether the associated preference is controlled by a source other than the + * user's setting (can be 'policy', 'extension', 'recommended' or unset). + */ + cr.defineProperty(PrefSelect, 'controlledBy', cr.PropertyKind.ATTR); + + /** + * The user metric string. + */ + cr.defineProperty(PrefSelect, 'metric', cr.PropertyKind.ATTR); + ///////////////////////////////////////////////////////////////////////////// // PrefTextField class:
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css index 0aafc9d7..ff10263 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.css
@@ -14,6 +14,24 @@ width: 100%; } +#title { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#pageselector-container { + text-align: center; + /* The container resizes according to the width of the toolbar. On small + * screens with large numbers of pages, overflow page numbers without + * wrapping. */ + white-space: nowrap; +} + +#buttons { + text-align: right; +} + paper-progress { height: 56px; position: absolute;
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html index a6b9ddc..8e1e4712 100644 --- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html +++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar/viewer-pdf-toolbar.html
@@ -14,14 +14,18 @@ <paper-shadow fit></paper-shadow> <paper-progress value="{{loadProgress}}"></paper-progress> <core-toolbar class="core-narrow"> - <div id="aligner" horizontal justified layout center> - <span id="title" class="invisible ">{{docTitle}}</span> + <div id="aligner" horizontal layout center> + <span id="title" class="invisible" title="{{docTitle}}" flex five> + {{docTitle}} + </span> - <viewer-page-selector id="pageselector" class="invisible" - index="{{pageIndex}}" docLength="{{docLength}}"> - </viewer-page-selector> + <div flex one id="pageselector-container"> + <viewer-page-selector id="pageselector" class="invisible" + index="{{pageIndex}}" docLength="{{docLength}}"> + </viewer-page-selector> + </div> - <div id="buttons" class="invisible"> + <div id="buttons" class="invisible" flex five> <paper-icon-button icon="image:rotate-right" on-click="{{rotateRight}}"></paper-icon-button> <template if="{{hasBookmarks}}">
diff --git a/chrome/browser/resources/pdf/pdf.js b/chrome/browser/resources/pdf/pdf.js index 6e94d56..70cc238 100644 --- a/chrome/browser/resources/pdf/pdf.js +++ b/chrome/browser/resources/pdf/pdf.js
@@ -113,8 +113,8 @@ window.addEventListener('message', this.handleScriptingMessage.bind(this), false); - document.title = - getFilenameFromURL(this.browserApi_.getStreamInfo().originalUrl); + document.title = decodeURIComponent( + getFilenameFromURL(this.browserApi_.getStreamInfo().originalUrl)); this.plugin_.setAttribute('src', this.browserApi_.getStreamInfo().originalUrl); this.plugin_.setAttribute('stream-url',
diff --git a/chrome/browser/resources/settings/internet_page/internet_page.js b/chrome/browser/resources/settings/internet_page/internet_page.js index a0494ceb..6c3c872 100644 --- a/chrome/browser/resources/settings/internet_page/internet_page.js +++ b/chrome/browser/resources/settings/internet_page/internet_page.js
@@ -24,7 +24,7 @@ * ID of the page. * * @attribute PAGE_ID - * @const string + * @const {string} */ PAGE_ID: 'internet', @@ -32,7 +32,7 @@ * Route for the page. * * @attribute route - * @type string + * @type {string} * @default '' */ route: '', @@ -41,7 +41,7 @@ * Whether the page is a subpage. * * @attribute subpage - * @type boolean + * @type {boolean} * @default false */ subpage: false, @@ -50,7 +50,7 @@ * Title for the page header and navigation menu. * * @attribute pageTitle - * @type string + * @type {string} */ pageTitle: loadTimeData.getString('internetPageTitle'), @@ -59,7 +59,7 @@ * icon for the active internet connection. * * @attribute icon - * @type string + * @type {string} * @default 'settings-ethernet' */ icon: 'settings-ethernet',
diff --git a/chrome/browser/resources/settings/internet_page/network_summary.html b/chrome/browser/resources/settings/internet_page/network_summary.html index f612de5..85783b48 100644 --- a/chrome/browser/resources/settings/internet_page/network_summary.html +++ b/chrome/browser/resources/settings/internet_page/network_summary.html
@@ -1,27 +1,47 @@ <link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_network_list_item/cr_network_list_item.html"> +<link rel="import" href="chrome://resources/polymer/core-style/core-style.html"> <link rel="import" href="chrome://resources/cr_elements/cr_onc/cr_onc_data.html"> +<link rel="import" href="network_summary_item.html"> <link rel="import" href="network_summary_style.html"> <polymer-element name="cr-network-summary"> <template> <core-style ref="networkSummaryStyle"></core-style> <div id="summary" vertical layout> - <cr-network-list-item networkState="{{networkStates.Ethernet}}" - hidden?="{{!networkStates.Ethernet}}"> - </cr-network-list-item> - <cr-network-list-item networkState="{{networkStates.WiFi}}" - hidden?="{{!networkStates.WiFi}}"> - </cr-network-list-item> - <cr-network-list-item networkState="{{networkStates.Cellular}}" - hidden?="{{!networkStates.Cellular}}"> - </cr-network-list-item> - <cr-network-list-item networkState="{{networkStates.WiMAX}}" - hidden?="{{!networkStates.WiMAX}}"> - </cr-network-list-item> - <cr-network-list-item networkState="{{networkStates.VPN}}" - hidden?="{{!networkStates.VPN}}"> - </cr-network-list-item> + <cr-network-summary-item + deviceState="{{deviceStates.Ethernet}}" + networkState="{{networkStates.Ethernet}}" + networkStateList="{{networkStateLists.Ethernet}}" + on-selected="{{onSelected_}}"> + </cr-network-summary-item> + <cr-network-summary-item + deviceState="{{deviceStates.WiFi}}" + networkState="{{networkStates.WiFi}}" + networkStateList="{{networkStateLists.WiFi}}" + on-expanded="{{onWiFiExpanded_}}" + on-selected="{{onSelected_}}" + on-device-enabled-toggled="{{onDeviceEnabledToggled_}}"> + </cr-network-summary-item> + <cr-network-summary-item + deviceState="{{deviceStates.Cellular}}" + networkState="{{networkStates.Cellular}}" + networkStateList="{{networkStateLists.Cellular}}" + on-selected="{{onSelected_}}" + on-device-enabled-toggled="{{onDeviceEnabledToggled_}}"> + </cr-network-summary-item> + <cr-network-summary-item + deviceState="{{deviceStates.WiMAX}}" + networkState="{{networkStates.WiMAX}}" + networkStateList="{{networkStateLists.WiMAX}}" + on-selected="{{onSelected_}}" + on-device-enabled-toggled="{{onDeviceEnabledToggled_}}"> + </cr-network-summary-item> + <cr-network-summary-item + deviceState="{{deviceStates.VPN}}" + networkState="{{networkStates.VPN}}" + networkStateList="{{networkStateLists.VPN}}" + on-selected="{{onSelected_}}"> + </cr-network-summary-item> </div> </template> <script src="network_summary.js"></script>
diff --git a/chrome/browser/resources/settings/internet_page/network_summary.js b/chrome/browser/resources/settings/internet_page/network_summary.js index 34a4b9a..c4adfbf 100644 --- a/chrome/browser/resources/settings/internet_page/network_summary.js +++ b/chrome/browser/resources/settings/internet_page/network_summary.js
@@ -6,57 +6,130 @@ * @fileoverview Polymer element for displaying a summary of network states * by type: Ethernet, WiFi, Cellular, WiMAX, and VPN. */ +(function() { + +/** @typedef {chrome.networkingPrivate.DeviceStateProperties} */ +var DeviceStateProperties; + +/** @typedef {chrome.networkingPrivate.NetworkStateProperties} */ +var NetworkStateProperties; + +/** + * @typedef {{ + * Ethernet: (DeviceStateProperties|undefined), + * WiFi: (DeviceStateProperties|undefined), + * Cellular: (DeviceStateProperties|undefined), + * WiMAX: (DeviceStateProperties|undefined), + * VPN: (DeviceStateProperties|undefined) + * }} + */ +var DeviceStateObject; + +/** + * @typedef {{ + * Ethernet: (CrOncDataElement|undefined), + * WiFi: (CrOncDataElement|undefined), + * Cellular: (CrOncDataElement|undefined), + * WiMAX: (CrOncDataElement|undefined), + * VPN: (CrOncDataElement|undefined) + * }} + */ +var NetworkStateObject; + +/** + * @typedef {{ + * Ethernet: (Array<CrOncDataElement>|undefined), + * WiFi: (Array<CrOncDataElement>|undefined), + * Cellular: (Array<CrOncDataElement>|undefined), + * WiMAX: (Array<CrOncDataElement>|undefined), + * VPN: (Array<CrOncDataElement>|undefined) + * }} + */ +var NetworkStateListObject; + +/** @const {!Array<string>} */ +var NETWORK_TYPES = ['Ethernet', 'WiFi', 'Cellular', 'WiMAX', 'VPN']; + Polymer('cr-network-summary', { publish: { /** + * The device state for each network device type. + * + * @attribute deviceStates + * @type {?DeviceStateObject} + * @default null + */ + deviceStates: null, + + /** * Network state data for each network type. * * @attribute networkStates - * @type {{ - * Ethernet: (CrOncDataElement|undefined), - * WiFi: (CrOncDataElement|undefined), - * Cellular: (CrOncDataElement|undefined), - * WiMAX: (CrOncDataElement|undefined), - * VPN: (CrOncDataElement|undefined) - * }} - * @default {} + * @type {?NetworkStateObject} + * @default null */ networkStates: null, + + /** + * List of network state data for each network type. + * + * @attribute networkStateLists + * @type {?NetworkStateListObject} + * @default null + */ + networkStateLists: null, }, /** * Listener function for chrome.networkingPrivate.onNetworkListChanged event. - * @type {function(!Array<string>)} + * @type {?function(!Array<string>)} * @private */ - listChangedListener_: null, + networkListChangedListener_: null, + + /** + * Listener function for chrome.networkingPrivate.onDeviceStateListChanged + * event. + * @type {?function(!Array<string>)} + * @private + */ + deviceStateListChangedListener_: null, /** * Listener function for chrome.networkingPrivate.onNetworksChanged event. - * @type {function(!Array<string>)} + * @type {?function(!Array<string>)} * @private */ networksChangedListener_: null, /** * Dictionary of GUIDs identifying primary (active) networks for each type. - * @type {Object} + * @type {?Object} * @private */ - networkIds_: {}, + networkIds_: null, /** @override */ created: function() { + this.deviceStates = {}; this.networkStates = {}; + this.networkStateLists = {}; + this.networkIds_ = {}; }, /** @override */ attached: function() { - this.getNetworks_(); + this.getNetworkLists_(); - this.listChangedListener_ = this.onNetworkListChangedEvent_.bind(this); + this.networkListChangedListener_ = + this.onNetworkListChangedEvent_.bind(this); chrome.networkingPrivate.onNetworkListChanged.addListener( - this.listChangedListener_); + this.networkListChangedListener_); + + this.deviceStateListChangedListener_ = + this.onDeviceStateListChangedEvent_.bind(this); + chrome.networkingPrivate.onDeviceStateListChanged.addListener( + this.deviceStateListChangedListener_); this.networksChangedListener_ = this.onNetworksChangedEvent_.bind(this); chrome.networkingPrivate.onNetworksChanged.addListener( @@ -66,20 +139,66 @@ /** @override */ detached: function() { chrome.networkingPrivate.onNetworkListChanged.removeListener( - this.listChangedListener_); + this.networkListChangedListener_); + + chrome.networkingPrivate.onDeviceStateListChanged.removeListener( + this.deviceStateListChangedListener_); chrome.networkingPrivate.onNetworksChanged.removeListener( this.networksChangedListener_); }, /** + * Event triggered when the WiFi cr-network-summary-item is expanded. + * @param {!{detail: {expanded: boolean, type: string}}} event * @private */ - onNetworkListChangedEvent_: function() { - this.getNetworks_(); + onWiFiExpanded_: function(event) { + this.getNetworkStates_(); // Get the latest network states (only). + chrome.networkingPrivate.requestNetworkScan(); }, /** + * Event triggered when a cr-network-summary-item is selected. + * @param {!{detail: !CrOncDataElement}} event + * @private + */ + onSelected_: function(event) { + var onc = event.detail; + if (onc.disconnected()) { + this.connectToNetwork_(onc); + return; + } + // TODO(stevenjb): Show details for connected or unconfigured networks. + }, + + /** + * Event triggered when the enabled state of a cr-network-summary-item is + * toggled. + * @param {!{detail: {enabled: boolean, type: string}}} event + * @private + */ + onDeviceEnabledToggled_: function(event) { + if (event.detail.enabled) + chrome.networkingPrivate.enableNetworkType(event.detail.type); + else + chrome.networkingPrivate.disableNetworkType(event.detail.type); + }, + + /** + * networkingPrivate.onNetworkListChanged event callback. + * @private + */ + onNetworkListChangedEvent_: function() { this.getNetworkLists_(); }, + + /** + * networkingPrivate.onDeviceStateListChanged event callback. + * @private + */ + onDeviceStateListChangedEvent_: function() { this.getNetworkLists_(); }, + + /** + * networkingPrivate.onNetworksChanged event callback. * @param {!Array<string>} networkIds The list of changed network GUIDs. * @private */ @@ -92,48 +211,110 @@ }, this); }, - /** @private */ - getNetworks_: function() { + /** + * Handles UI requests to connect to a network. + * TODO(stevenjb): Handle Cellular activation, etc. + * @param {!CrOncDataElement} state The network state. + * @private + */ + connectToNetwork_: function(state) { + chrome.networkingPrivate.startConnect(state.data.GUID); + }, + + /** + * Requests the list of device states and network states from Chrome. + * Updates deviceStates, networkStates, and networkStateLists once the + * results are returned from Chrome. + * @private + */ + getNetworkLists_: function() { + // First get the device states. + chrome.networkingPrivate.getDeviceStates( + function(states) { + this.getDeviceStatesCallback_(states); + // Second get the network states. + this.getNetworkStates_(); + }.bind(this)); + }, + + /** + * Requests the list of network states from Chrome. Updates networkStates and + * networkStateLists once the results are returned from Chrome. + * @private + */ + getNetworkStates_: function() { var filter = { networkType: 'All', visible: true, configured: false }; - chrome.networkingPrivate.getNetworks(filter, - this.getNetworksCallback_.bind(this)); + chrome.networkingPrivate.getNetworks( + filter, this.getNetworksCallback_.bind(this)); }, /** - * @param {!Array<!chrome.networkingPrivate.NetworkStateProperties>} states - * The state properties for all networks. + * networkingPrivate.getDeviceStates callback. + * @param {!Array<!DeviceStateProperties>} states The state properties for all + * available devices. + * @private + */ + getDeviceStatesCallback_: function(states) { + /** @type {!DeviceStateObject} */ var newStates = {}; + states.forEach(function(state) { newStates[state.Type] = state; }); + this.deviceStates = newStates; + }, + + /** + * networkingPrivate.getNetworksState callback. + * @param {!Array<!NetworkStateProperties>} states The state properties for + * all visible networks. * @private */ getNetworksCallback_: function(states) { - // Clear all active networks. + // Clear any current networks. this.networkIds_ = {}; // Get the first (active) state for each type. var foundTypes = {}; + /** @type {!NetworkStateListObject} */ var oncNetworks = { + Ethernet: [], + WiFi: [], + Cellular: [], + WiMAX: [], + VPN: [] + }; states.forEach(function(state) { var type = state.Type; if (!foundTypes[type]) { foundTypes[type] = true; this.updateNetworkState_(type, state); } + oncNetworks[type].push(CrOncDataElement.create(state)); }, this); - // Set any types not found to null. TODO(stevenjb): Support types that are - // disabled but available with no active network. - var types = ['Ethernet', 'WiFi', 'Cellular', 'WiMAX', 'VPN']; - types.forEach(function(type) { - if (!foundTypes[type]) - this.updateNetworkState_(type, null); + // Set any types not found to a default value or null. + NETWORK_TYPES.forEach(function(type) { + if (!foundTypes[type]) { + /** @type {NetworkStateProperties} */ var defaultState = null; + if (this.deviceStates[type]) + defaultState = { GUID: '', Type: 'WiFi' }; + this.updateNetworkState_(type, defaultState); + } }, this); + + // Set the network list for each type. + NETWORK_TYPES.forEach(function(type) { + this.networkStateLists[type] = oncNetworks[type]; + }, this); + + // Create a VPN entry in deviceStates if there are any VPN networks. + if (this.networkStateLists.VPN && this.networkStateLists.VPN.length > 0) + this.deviceStates.VPN = { Type: 'VPN', State: 'Enabled' }; }, /** - * @param {!chrome.networkingPrivate.NetworkStateProperties} state The state - * properties for the network. + * networkingPrivate.getState callback. + * @param {!NetworkStateProperties} state The network state properties. * @private */ getStateCallback_: function(state) { @@ -148,9 +329,9 @@ * Sets 'networkStates[type]' which will update the cr-network-list-item * associated with 'type'. * @param {string} type The network type. - * @param {chrome.networkingPrivate.NetworkStateProperties} state The state - * properties for the network to associate with |type|. May be null if - * there are no networks matching |type|. + * @param {?NetworkStateProperties} state The state properties for the network + * to associate with |type|. May be null if there are no networks matching + * |type|. * @private */ updateNetworkState_: function(type, state) { @@ -159,3 +340,4 @@ this.networkIds_[state.GUID] = true; }, }); +})();
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.html b/chrome/browser/resources/settings/internet_page/network_summary_item.html new file mode 100644 index 0000000..ea2dffd --- /dev/null +++ b/chrome/browser/resources/settings/internet_page/network_summary_item.html
@@ -0,0 +1,38 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_network_list/cr_network_list.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_network_list_item/cr_network_list_item.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_onc/cr_onc_data.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_toggle_button/cr_toggle_button.html"> +<link rel="import" href="network_summary_item_style.html"> + +<polymer-element name="cr-network-summary-item"> + <template> + <core-style ref="networkSummaryStyle"></core-style> + <div vertical layout hidden?="{{!deviceState}}"> + <div id="details" horizontal layout on-click="{{onDetailsClicked_}}"> + <cr-network-list-item id="detailsItem" flex + networkState="{{networkState}}"> + </cr-network-list-item> + <div id="buttons" horizontal layout> + <cr-expand-button id="expandListButton" + class="{{ {invisible: !expandIsVisible_(deviceState, networkStateList)} | tokenList }}" + expanded="{{expanded}}"> + </cr-expand-button> + <cr-toggle-button id="deviceEnabledButton" + checked="{{deviceIsEnabled_(deviceState)}}" + class="{{ {invisible: !deviceEnabledIsVisible_(deviceState)} | tokenList }}" + on-click="{{onDeviceEnabledToggled_}}"> + </cr-toggle-button> + </div> + </div> + <cr-network-list id="networkList" vertical layout + maxHeight="{{maxHeight}}" + networks="{{networkStateList}}" + on-selected="{{onListItemSelected_}}" + opened="{{expanded}}"> + </cr-network-list> + </div> + </template> + <script src="network_summary_item.js"></script> +</polymer-element>
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item.js b/chrome/browser/resources/settings/internet_page/network_summary_item.js new file mode 100644 index 0000000..44628df --- /dev/null +++ b/chrome/browser/resources/settings/internet_page/network_summary_item.js
@@ -0,0 +1,173 @@ +// 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 Polymer element for displaying the network state for a specific + * type and a list of networks for that type. + */ +(function() { + +/** @typedef {chrome.networkingPrivate.DeviceStateProperties} */ +var DeviceStateProperties; + +Polymer('cr-network-summary-item', { + publish: { + /** + * True if the list is expanded. + * + * @attribute expanded + * @type {boolean} + * @default false + */ + expanded: false, + + /** + * The maximum height in pixels for the list of networks. + * + * @attribute maxHeight + * @type {number} + * @default 200 + */ + maxHeight: 200, + + /** + * Device state for the network type. + * + * @attribute deviceState + * @type {?DeviceStateProperties} + * @default null + */ + deviceState: null, + + /** + * Network state for the active network. + * + * @attribute networkState + * @type {?CrOncDataElement} + * @default null + */ + networkState: null, + + /** + * List of all network state data for the network type. + * + * @attribute networkStateList + * @type {?Array<!CrOncDataElement>} + * @default null + */ + networkStateList: null, + }, + + /** + * Polymer expanded changed method. + */ + expandedChanged: function() { + var type = this.deviceState ? this.deviceState.Type : ''; + this.fire('expanded', {expanded: this.expanded, type: type}); + }, + + /** + * Polymer deviceState changed method. + */ + deviceStateChanged: function() { + this.updateSelectable_(); + if (!this.deviceIsEnabled_(this.deviceState)) + this.expanded = false; + }, + + /** + * Polymer networkStateList changed method. + */ + networkStateListChanged: function() { + this.updateSelectable_(); + }, + + /** + * @param {?DeviceStateProperties} deviceState The state of a device. + * @return {boolean} Whether or not the device state is enabled. + * @private + */ + deviceIsEnabled_: function(deviceState) { + return deviceState && deviceState.State == 'Enabled'; + }, + + /** + * @param {?DeviceStateProperties} deviceState The device state. + * @return {boolean} Whether or not to show the UI to enable the network. + * @private + */ + deviceEnabledIsVisible_: function(deviceState) { + return deviceState && + deviceState.Type != 'Ethernet' && deviceState.Type != 'VPN'; + }, + + /** + * @param {?DeviceStateProperties} deviceState The device state. + * @param {?Array<!CrOncDataElement>} networkList A list of networks. + * @return {boolean} Whether or not to show the UI to expand the list. + * @private + */ + expandIsVisible_: function(deviceState, networkList) { + if (!this.deviceIsEnabled_(deviceState) || !networkList) + return false; + var minLength = (this.type == 'WiFi') ? 1 : 2; + return networkList.length >= minLength; + }, + + /** + * Event triggered when the details div is clicked on. + * @param {!Object} event The enable button event. + * @private + */ + onDetailsClicked_: function(event) { + if ((event.target.id == 'expandListButton') || + (this.deviceState && !this.deviceIsEnabled_(this.deviceState))) { + // Already handled or disabled, do nothing. + return; + } + if (this.expandIsVisible_(this.deviceState, this.networkStateList)) { + // Expandable, toggle expand. + this.expanded = !this.expanded; + return; + } + // Not expandable, fire 'selected' with |networkState|. + this.fire('selected', this.networkState); + }, + + /** + * Event triggered when a cr-network-item is the network list is selected. + * @param {!{detail: CrNetworkListItem}} event + * @private + */ + onListItemSelected_: function(event) { + var onc = event.detail; + this.fire('selected', onc); + }, + + /** + * Event triggered when the enable button is toggled. + * @param {!Object} event The enable button event. + * @private + */ + onDeviceEnabledToggled_: function(event) { + var deviceIsEnabled = this.deviceIsEnabled_(this.deviceState); + var type = this.deviceState ? this.deviceState.Type : ''; + this.fire('device-enabled-toggled', + {enabled: !deviceIsEnabled, type: type}); + // Make sure this does not propagate to onDetailsClicked_. + event.stopPropagation(); + }, + + /** + * Called whenever the 'selectable' state might change. + * @private + */ + updateSelectable_: function() { + // TODO(stevenjb): Make any actionable item selectable. + var selectable = + this.expandIsVisible_(this.deviceState, this.networkStateList); + this.$.details.classList.toggle('selectable', selectable); + }, +}); +})();
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_item_style.html b/chrome/browser/resources/settings/internet_page/network_summary_item_style.html new file mode 100644 index 0000000..8792048a --- /dev/null +++ b/chrome/browser/resources/settings/internet_page/network_summary_item_style.html
@@ -0,0 +1,31 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/core-style/core-style.html"> + +<core-style id="networkSummaryStyle"> + +#details.selectable:hover { + background-color: lightgrey; +} + +#detailsItem { + margin-bottom: 10px; +} + +#buttons { + align-items: center; +} + +.invisible { + visibility: hidden; +} + +#deviceEnabledButton { + margin: 0px 10px; +} + +#networkList { + max-height: 400px; + margin: 0px 70px 10px 40px; +} + +</core-style>
diff --git a/chrome/browser/resources/settings/internet_page/network_summary_style.html b/chrome/browser/resources/settings/internet_page/network_summary_style.html index c465b36..5621996 100644 --- a/chrome/browser/resources/settings/internet_page/network_summary_style.html +++ b/chrome/browser/resources/settings/internet_page/network_summary_style.html
@@ -2,7 +2,9 @@ <link rel="import" href="chrome://resources/polymer/core-style/core-style.html"> <core-style id="networkSummaryStyle"> -cr-network-list-item { - margin-bottom: 10px; + +#summary { + padding-right: 40px; } + </core-style>
diff --git a/chrome/browser/resources/settings/routes.html b/chrome/browser/resources/settings/routes.html index 95ea4e6..56f65e9 100644 --- a/chrome/browser/resources/settings/routes.html +++ b/chrome/browser/resources/settings/routes.html
@@ -10,3 +10,4 @@ <more-route name="dateTime" path="/dateTime"></more-route> <more-route name="downloads" path="/downloads"></more-route> <more-route name="internet" path="/internet"></more-route> +<more-route name="search" path="/search"></more-route>
diff --git a/chrome/browser/resources/settings/search_page/search_page.html b/chrome/browser/resources/settings/search_page/search_page.html new file mode 100644 index 0000000..f14ff367 --- /dev/null +++ b/chrome/browser/resources/settings/search_page/search_page.html
@@ -0,0 +1,33 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/core-menu/core-menu.html"> +<link rel="import" href="chrome://resources/polymer/paper-item/paper-item.html"> +<link rel="import" href="chrome://resources/polymer/paper-shadow/paper-shadow.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.html"> +<link rel="import" href="chrome://md-settings/checkbox/checkbox.html"> +<link rel="import" href="search_page_style.html"> + +<polymer-element name="cr-settings-search-page"> + <template> + <link rel="stylesheet" href="chrome://md-settings/settings_page/settings_page.css"> + <core-style ref="searchPageStyle"></core-style> + <paper-shadow layout vertical cross-fade> + <p i18n-content="searchExplanation"></p> + + <div class="search-engines" layout horizontal center> + <cr-dropdown-menu class="search-engines-dropdown"> + <core-menu id="searchEnginesMenu" class="menu" valueAttr="guid" + selected="{{defaultEngineGuid}}"> + <template repeat="{{engine in searchEngines}}"> + <paper-item guid="{{engine.guid}}">{{engine.name}}</paper-item> + </template> + </core-menu> + </cr-dropdown-menu> + + <cr-button class="manage-search-engines" + i18n-content="searchManageButtonLabel" raised> + </cr-button> + </div> + </paper-shadow> + </template> + <script src="search_page.js"></script> +</polymer-element>
diff --git a/chrome/browser/resources/settings/search_page/search_page.js b/chrome/browser/resources/settings/search_page/search_page.js new file mode 100644 index 0000000..22deceb --- /dev/null +++ b/chrome/browser/resources/settings/search_page/search_page.js
@@ -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. + +/** + * @fileoverview + * 'cr-settings-search-page' is the settings page containing search settings. + * + * Example: + * + * <core-animated-pages> + * <cr-settings-search-page prefs="{{prefs}}"></cr-settings-search-page> + * ... other pages ... + * </core-animated-pages> + * + * @group Chrome Settings Elements + * @element cr-settings-search-page + */ +Polymer('cr-settings-search-page', { + publish: { + /** + * Preferences state. + * + * @attribute prefs + * @type {CrSettingsPrefsElement} + * @default null + */ + prefs: null, + + /** + * Whether the page is a subpage. + * + * @attribute subpage + * @type {boolean} + * @default false + */ + subpage: false, + + /** + * ID of the page. + * + * @attribute PAGE_ID + * @const {string} + * @default 'search' + */ + PAGE_ID: 'search', + + /** + * Title for the page header and navigation menu. + * + * @attribute pageTitle + * @type {string} + */ + pageTitle: loadTimeData.getString('searchPageTitle'), + + /** + * Name of the 'core-icon' to be shown in the settings-page-header. + * + * @attribute icon + * @type {string} + * @default 'search' + */ + icon: 'search', + + /** + * List of default search engines available. + * + * @attribute searchEngines + * @type {Array<!SearchEngine} + * @default null + */ + searchEngines: null, + + /** + * GUID of the currently selected default search engine. + * + * @attribute defaultEngineGuid + * @type {string} + * @default '' + */ + defaultEngineGuid: '', + }, + + /** @override */ + created: function() { + this.searchEngines = []; + }, + + /** @override */ + domReady: function() { + chrome.searchEnginesPrivate.onDefaultSearchEnginesChanged.addListener( + this.updateSearchEngines_.bind(this)); + chrome.searchEnginesPrivate.getDefaultSearchEngines( + this.updateSearchEngines_.bind(this)); + }, + + /** + * Persists the new default search engine back to Chrome. Called when the + * user selects a new default in the search engines dropdown. + */ + defaultEngineGuidChanged: function() { + chrome.searchEnginesPrivate.setSelectedSearchEngine(this.defaultEngineGuid); + }, + + + /** + * Updates the list of search engines with the given |engines|. + * @param {!Array<!SearchEngine>} engines + * @private + */ + updateSearchEngines_: function(engines) { + this.searchEngines = engines; + for (var i = 0; i < engines.length; i++) { + if (engines[i].isSelected) { + this.defaultEngineGuid = engines[i].guid; + } + } + } +});
diff --git a/chrome/browser/resources/settings/search_page/search_page_style.html b/chrome/browser/resources/settings/search_page/search_page_style.html new file mode 100644 index 0000000..b30a0a7 --- /dev/null +++ b/chrome/browser/resources/settings/search_page/search_page_style.html
@@ -0,0 +1,16 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/core-style/core-style.html"> + +<core-style id="searchPageStyle"> +.manage-search-engines { + -webkit-margin-start: 10px; +} + +.search-engines { + margin-top: 20px; +} + +.search-engines-dropdown { + min-width: 150px; +} +</core-style>
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.html b/chrome/browser/resources/settings/settings_main/settings_main.html index 15290f9..17bbe19 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.html +++ b/chrome/browser/resources/settings/settings_main/settings_main.html
@@ -6,6 +6,7 @@ <link rel="import" href="chrome://md-settings/date_time_page/date_time_page.html"> <link rel="import" href="chrome://md-settings/downloads_page/downloads_page.html"> <link rel="import" href="chrome://md-settings/internet_page/internet_page.html"> +<link rel="import" href="chrome://md-settings/search_page/search_page.html"> <link rel="import" href="chrome://md-settings/routes.html"> <link rel="import" href="settings_main_style.html"> @@ -30,6 +31,8 @@ </if> <cr-settings-downloads-page prefs="{{prefs}}" route="downloads"> </cr-settings-downloads-page> + <cr-settings-search-page prefs="{{prefs}}" route="search"> + </cr-settings-search-page> </core-animated-pages> </more-route-selector> </div>
diff --git a/chrome/browser/resources/settings/settings_resources.grd b/chrome/browser/resources/settings/settings_resources.grd index 815ea9d3..daaca072 100644 --- a/chrome/browser/resources/settings/settings_resources.grd +++ b/chrome/browser/resources/settings/settings_resources.grd
@@ -205,6 +205,17 @@ <structure name="IDR_SETTINGS_ROUTING_MORE_ROUTING_ROUTING_EXTRACTED_JS" file="routing/more_routing/routing_extracted.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_SEARCH_PAGE_JS" + file="search_page/search_page.js" + type="chrome_html" /> + <structure name="IDR_SETTINGS_SEARCH_PAGE_HTML" + file="search_page/search_page.html" + type="chrome_html" + flattenhtml="true" + allowexternalscript="true" /> + <structure name="IDR_SETTINGS_SEARCH_PAGE_STYLE_HTML" + file="search_page/search_page_style.html" + type="chrome_html" /> <structure name="IDR_SETTINGS_SETTINGS_HTML" file="settings.html" type="chrome_html" /> @@ -227,6 +238,15 @@ <structure name="IDR_SETTINGS_NETWORK_SUMMARY_JS" file="internet_page/network_summary.js" type="chrome_html" /> + <structure name="IDR_SETTINGS_NETWORK_SUMMARY_ITEM_STYLE_HTML" + file="internet_page/network_summary_item_style.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_NETWORK_SUMMARY_ITEM_HTML" + file="internet_page/network_summary_item.html" + type="chrome_html" /> + <structure name="IDR_SETTINGS_NETWORK_SUMMARY_ITEM_JS" + file="internet_page/network_summary_item.js" + type="chrome_html" /> </if> </structures> </release>
diff --git a/chrome/browser/rlz/rlz_unittest.cc b/chrome/browser/rlz/rlz_unittest.cc index 0a0f7a2..5539649d 100644 --- a/chrome/browser/rlz/rlz_unittest.cc +++ b/chrome/browser/rlz/rlz_unittest.cc
@@ -270,9 +270,11 @@ content::RenderFrameHostTester::For(main_rfh()); // Simulate a navigation to homepage first. - rfht->SendNavigateWithTransition(0, home_url, ui::PAGE_TRANSITION_HOME_PAGE); + rfht->SendNavigateWithTransition( + 0, 0, true, home_url, ui::PAGE_TRANSITION_HOME_PAGE); // Then simulate a search from homepage. - rfht->SendNavigateWithTransition(1, search_url, ui::PAGE_TRANSITION_LINK); + rfht->SendNavigateWithTransition( + 1, 0, true, search_url, ui::PAGE_TRANSITION_LINK); } void RlzLibTest::SimulateAppListUsage() {
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor.cc b/chrome/browser/safe_browsing/browser_feature_extractor.cc index b63d8ba..bcec8a7b 100644 --- a/chrome/browser/safe_browsing/browser_feature_extractor.cc +++ b/chrome/browser/safe_browsing/browser_feature_extractor.cc
@@ -43,7 +43,7 @@ void FilterBenignIpsOnIOThread( scoped_refptr<SafeBrowsingDatabaseManager> database_manager, IPUrlMap* ips) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); for (IPUrlMap::iterator it = ips->begin(); it != ips->end();) { if (!database_manager.get() || !database_manager->MatchMalwareIP(it->first)) { @@ -108,7 +108,7 @@ const std::vector<GURL>& redirect_chain, ClientPhishingRequest* request) { NavigationEntry* entry = controller.GetEntryAtIndex(index); - bool is_secure_referrer = entry->GetReferrer().url.SchemeIsSecure(); + bool is_secure_referrer = entry->GetReferrer().url.SchemeIsCryptographic(); if (!is_secure_referrer) { AddFeature(base::StringPrintf("%s%s=%s", feature_prefix.c_str(), @@ -150,7 +150,7 @@ // We skip the last element since it should just be the current url. for (size_t i = 0; i < redirect_chain.size() - 1; i++) { std::string printable_redirect = redirect_chain[i].spec(); - if (redirect_chain[i].SchemeIsSecure()) { + if (redirect_chain[i].SchemeIsCryptographic()) { printable_redirect = features::kSecureRedirectValue; } AddFeature(base::StringPrintf("%s%s[%" PRIuS "]=%s", @@ -179,7 +179,7 @@ void BrowserFeatureExtractor::ExtractFeatures(const BrowseInfo* info, ClientPhishingRequest* request, const DoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(request); DCHECK(info); DCHECK_EQ(0U, request->url().find("http:")); @@ -248,7 +248,7 @@ BrowseInfo* info, ClientMalwareRequest* request, const MalwareDoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!callback.is_null()); // Grab the IPs because they might go away before we're done @@ -302,7 +302,7 @@ void BrowserFeatureExtractor::StartExtractFeatures( scoped_ptr<ClientPhishingRequest> request, const DoneCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); history::HistoryService* history; if (!request || !request->IsInitialized() || !GetHistoryService(&history)) { callback.Run(false, request.Pass()); @@ -324,7 +324,7 @@ bool success, const history::URLRow& row, const history::VisitVector& visits) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(request); DCHECK(!callback.is_null()); if (!success) { @@ -391,7 +391,7 @@ bool success, int num_visits, base::Time first_visit) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(request); DCHECK(!callback.is_null()); if (!success) { @@ -422,7 +422,7 @@ bool success, int num_visits, base::Time first_visit) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(request); DCHECK(!callback.is_null()); if (!success) { @@ -473,7 +473,7 @@ scoped_ptr<IPUrlMap> bad_ips, MalwareDoneCallback callback, scoped_ptr<ClientMalwareRequest> request) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); int matched_bad_ips = 0; for (IPUrlMap::const_iterator it = bad_ips->begin(); it != bad_ips->end(); ++it) {
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc index 9e92f207..0cd880c 100644 --- a/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc +++ b/chrome/browser/safe_browsing/browser_feature_extractor_unittest.cc
@@ -25,6 +25,7 @@ #include "components/history/core/browser/history_backend.h" #include "components/history/core/browser/history_service.h" #include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" #include "content/public/common/referrer.h" #include "content/public/test/test_browser_thread.h" @@ -132,6 +133,8 @@ web_contents()->GetController().LoadURL( url, content::Referrer(referrer, blink::WebReferrerPolicyDefault), type, std::string()); + int pending_id = + web_contents()->GetController().GetPendingEntry()->GetUniqueID(); static int page_id = 0; content::RenderFrameHost* rfh = @@ -141,7 +144,7 @@ } WebContentsTester::For(web_contents())->ProceedWithCrossSiteNavigation(); WebContentsTester::For(web_contents())->TestDidNavigateWithReferrer( - rfh, ++page_id, url, + rfh, ++page_id, pending_id, true, url, content::Referrer(referrer, blink::WebReferrerPolicyDefault), type); }
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc index 3e49730..6291766d 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host.cc +++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -77,7 +77,7 @@ host_(host), start_phishing_classification_cb_(start_phishing_classification), start_malware_classification_cb_(start_malware_classification) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(web_contents_); DCHECK(csd_service_); DCHECK(database_manager_.get()); @@ -85,7 +85,7 @@ } void Start() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // We start by doing some simple checks that can run on the UI thread. UMA_HISTOGRAM_BOOLEAN("SBClientPhishing.ClassificationStart", 1); @@ -174,17 +174,17 @@ virtual ~ShouldClassifyUrlRequest() { } bool ShouldClassifyForPhishing() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return !start_phishing_classification_cb_.is_null(); } bool ShouldClassifyForMalware() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return !start_malware_classification_cb_.is_null(); } void DontClassifyForPhishing(PreClassificationCheckFailures reason) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (ShouldClassifyForPhishing()) { // Track the first reason why we stopped classifying for phishing. UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail", @@ -197,7 +197,7 @@ } void DontClassifyForMalware(PreClassificationCheckFailures reason) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (ShouldClassifyForMalware()) { // Track the first reason why we stopped classifying for malware. UMA_HISTOGRAM_ENUMERATION("SBClientMalware.PreClassificationCheckFail", @@ -210,7 +210,7 @@ } void CheckSafeBrowsingDatabase(const GURL& url) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // We don't want to call the classification callbacks from the IO // thread so we simply pass the results of this method to CheckCache() // which is called on the UI thread; @@ -241,7 +241,7 @@ void CheckCache(PreClassificationCheckFailures phishing_reason, PreClassificationCheckFailures malware_reason) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (phishing_reason != NO_CLASSIFY_MAX) DontClassifyForPhishing(phishing_reason); if (malware_reason != NO_CLASSIFY_MAX) @@ -489,7 +489,7 @@ void ClientSideDetectionHost::OnPhishingPreClassificationDone( bool should_classify) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (browse_info_.get() && should_classify) { DVLOG(1) << "Instruct renderer to start phishing detection for URL: " << browse_info_->url; @@ -501,7 +501,7 @@ void ClientSideDetectionHost::OnMalwarePreClassificationDone( bool should_classify) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // If classification checks failed we should stop extracting malware features. DVLOG(2) << "Malware pre-classification checks done. Should classify: " << should_classify; @@ -511,7 +511,7 @@ } void ClientSideDetectionHost::DidStopLoading() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!csd_service_ || !browse_info_.get()) return; DVLOG(2) << "Page finished loading."; @@ -520,7 +520,7 @@ } void ClientSideDetectionHost::MaybeStartMalwareFeatureExtraction() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (csd_service_ && browse_info_.get() && should_classify_for_malware_ && pageload_complete_) { @@ -546,7 +546,7 @@ void ClientSideDetectionHost::OnPhishingDetectionDone( const std::string& verdict_str) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // There is something seriously wrong if there is no service class but // this method is called. The renderer should not start phishing detection // if there isn't any service class in the browser. @@ -581,7 +581,7 @@ void ClientSideDetectionHost::MaybeShowPhishingWarning(GURL phishing_url, bool is_phishing) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(2) << "Received server phishing verdict for URL:" << phishing_url << " is_phishing:" << is_phishing; if (is_phishing) { @@ -612,7 +612,7 @@ void ClientSideDetectionHost::MaybeShowMalwareWarning(GURL original_url, GURL malware_url, bool is_malware) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DVLOG(2) << "Received server malawre IP verdict for URL:" << malware_url << " is_malware:" << is_malware; if (is_malware && malware_url.is_valid() && original_url.is_valid()) { @@ -700,7 +700,7 @@ int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED); const ResourceRequestDetails* req = content::Details<ResourceRequestDetails>( details).ptr();
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc index d6f20d68..382460e 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc +++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -138,7 +138,7 @@ // Helper function which calls OnBlockingPageComplete for this client // object. void InvokeOnBlockingPageComplete(const UrlCheckCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // Note: this will delete the client object in the case of the CsdClient // implementation. if (!callback.is_null())
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc index 09f44b9..5dd332a3 100644 --- a/chrome/browser/safe_browsing/client_side_detection_service.cc +++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -119,12 +119,12 @@ // static ClientSideDetectionService* ClientSideDetectionService::Create( net::URLRequestContextGetter* request_context_getter) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return new ClientSideDetectionService(request_context_getter); } void ClientSideDetectionService::SetEnabledAndRefreshState(bool enabled) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); SendModelToRenderers(); // always refresh the renderer state if (enabled == enabled_) return; @@ -167,7 +167,7 @@ void ClientSideDetectionService::SendClientReportPhishingRequest( ClientPhishingRequest* verdict, const ClientReportPhishingRequestCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&ClientSideDetectionService::StartClientReportPhishingRequest, @@ -177,7 +177,7 @@ void ClientSideDetectionService::SendClientReportMalwareRequest( ClientMalwareRequest* verdict, const ClientReportMalwareRequestCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&ClientSideDetectionService::StartClientReportMalwareRequest, @@ -223,7 +223,7 @@ int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_CREATED); if (!model_.get()) { // Model might not be ready or maybe there was an error. @@ -308,7 +308,7 @@ void ClientSideDetectionService::StartClientReportPhishingRequest( ClientPhishingRequest* verdict, const ClientReportPhishingRequestCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); scoped_ptr<ClientPhishingRequest> request(verdict); if (!enabled_) { @@ -349,7 +349,7 @@ void ClientSideDetectionService::StartClientReportMalwareRequest( ClientMalwareRequest* verdict, const ClientReportMalwareRequestCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); scoped_ptr<ClientMalwareRequest> request(verdict); if (!enabled_) {
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc index 1460b2f..dd4083f9 100644 --- a/chrome/browser/safe_browsing/download_protection_service.cc +++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -255,7 +255,7 @@ database_manager_(database_manager) { } void StartCheck() override { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!database_manager_.get() || database_manager_->CheckDownloadUrl(url_chain_, this)) { CheckDone(SB_THREAT_TYPE_SAFE); @@ -313,14 +313,14 @@ type_(ClientDownloadRequest::WIN_EXECUTABLE), start_time_(base::TimeTicks::Now()), weakptr_factory_(this) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); item_->AddObserver(this); } void Start() { DVLOG(2) << "Starting SafeBrowsing download check for: " << item_->DebugString(true); - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // TODO(noelutz): implement some cache to make sure we don't issue the same // request over and over again if a user downloads the same binary multiple // times. @@ -362,7 +362,7 @@ // Start a timeout to cancel the request if it takes too long. // This should only be called after we have finished accessing the file. void StartTimeout() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!service_) { // Request has already been cancelled. return; @@ -380,7 +380,7 @@ // Canceling a request will cause us to always report the result as UNKNOWN // unless a pending request is about to call FinishRequest. void Cancel() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (fetcher_.get()) { // The DownloadProtectionService is going to release its reference, so we // might be destroyed before the URLFetcher completes. Cancel the @@ -404,7 +404,7 @@ // From the net::URLFetcherDelegate interface. void OnURLFetchComplete(const net::URLFetcher* source) override { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(source, fetcher_.get()); DVLOG(2) << "Received a response for URL: " << item_->GetUrlChain().back() << ": success=" @@ -504,7 +504,7 @@ friend class base::DeleteHelper<CheckClientDownloadRequest>; ~CheckClientDownloadRequest() override { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(item_ == NULL); } @@ -529,7 +529,7 @@ } void StartExtractFileFeatures() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(item_); // Called directly from Start(), item should still exist. // Since we do blocking I/O, offload this to a worker thread. // The task does not need to block shutdown. @@ -570,7 +570,7 @@ } void StartExtractZipFeatures() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(item_); // Called directly from Start(), item should still exist. zip_analysis_start_time_ = base::TimeTicks::Now(); // We give the zip analyzer a weak pointer to this object. Since the @@ -583,7 +583,7 @@ } void OnZipAnalysisFinished(const zip_analyzer::Results& results) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!service_) return; if (results.success) { @@ -614,7 +614,7 @@ } void CheckWhitelists() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!database_manager_.get()) { PostFinishTask(UNKNOWN, REASON_SB_DISABLED); @@ -675,7 +675,7 @@ } void GetTabRedirects() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!service_) return; @@ -702,7 +702,7 @@ void OnGotTabRedirects(const GURL& url, const history::RedirectList* redirect_list) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(url, tab_url_); if (!service_) return; @@ -716,7 +716,7 @@ } void SendRequest() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // This is our last chance to check whether the request has been canceled // before sending it. @@ -807,7 +807,7 @@ void FinishRequest(DownloadCheckResult result, DownloadCheckResultReason reason) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (finished_) { return; } @@ -867,7 +867,7 @@ bool CertificateChainIsWhitelisted( const ClientDownloadRequest_CertificateChain& chain) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (chain.element_size() < 2) { // We need to have both a signing certificate and its issuer certificate // present to construct a whitelist entry. @@ -961,12 +961,12 @@ } DownloadProtectionService::~DownloadProtectionService() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); CancelPendingRequests(); } void DownloadProtectionService::SetEnabled(bool enabled) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (enabled == enabled_) { return; } @@ -1022,12 +1022,12 @@ DownloadProtectionService::ClientDownloadRequestSubscription DownloadProtectionService::RegisterClientDownloadRequestCallback( const ClientDownloadRequestCallback& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return client_download_request_callbacks_.Add(callback); } void DownloadProtectionService::CancelPendingRequests() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); for (std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = download_requests_.begin(); it != download_requests_.end();) { @@ -1041,7 +1041,7 @@ void DownloadProtectionService::RequestFinished( CheckClientDownloadRequest* request) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); std::set<scoped_refptr<CheckClientDownloadRequest> >::iterator it = download_requests_.find(request); DCHECK(it != download_requests_.end());
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 9a6f476..6a394e35 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
@@ -216,8 +216,11 @@ EXPECT_EQ(ClientIncidentReport_EnvironmentData_Process_ModuleState:: MODULE_STATE_MODIFIED, process_report.module_state(0).modified_state()); + // See comment above about AddressSantizier. +#if !defined(ADDRESS_SANITIZER) EXPECT_EQ(std::string(kTestExportName), process_report.module_state(0).modified_export(0)); +#endif } #endif // _WIN64
diff --git a/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win_unittest.cc index 5d3d84a..33ccce19 100644 --- a/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/module_integrity_verifier_win_unittest.cc
@@ -364,9 +364,11 @@ ASSERT_EQ(1U, modification_map[kTestExportName].size()); uint32_t export_offset = modification_map[kTestExportName][0]->file_offset(); - // Edit another exported function. VerifyModule should now report both. + // Edit another exported function. VerifyModule should now report both. Add + // one to the address so that this modification and the previous are not + // coalesced in the event that the first export is only one byte (e.g., ret). + ScopedModuleModifier<1> mod2(GetAddressOfExport(kTestDllMainExportName) + 1); state.Clear(); - ScopedModuleModifier<1> mod2(GetAddressOfExport(kTestDllMainExportName)); result = NewVerifyModule(kTestDllNames[0], &state); EXPECT_EQ(MODULE_STATE_MODIFIED, result.state); ASSERT_EQ(2, state.modification_size());
diff --git a/chrome/browser/safe_browsing/malware_details_cache.cc b/chrome/browser/safe_browsing/malware_details_cache.cc index d97d991..dc5fbc5 100644 --- a/chrome/browser/safe_browsing/malware_details_cache.cc +++ b/chrome/browser/safe_browsing/malware_details_cache.cc
@@ -56,7 +56,7 @@ } bool MalwareDetailsCacheCollector::HasStarted() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); return has_started_; } @@ -64,7 +64,7 @@ // Fetch a URL and advance to the next one when done. void MalwareDetailsCacheCollector::OpenEntry() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DVLOG(1) << "OpenEntry"; if (resources_it_ == resources_->end()) { @@ -100,7 +100,7 @@ void MalwareDetailsCacheCollector::OnURLFetchComplete( const net::URLFetcher* source) { DVLOG(1) << "OnUrlFetchComplete"; - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(current_fetch_.get()); if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS && source->GetStatus().error() == net::ERR_CACHE_MISS) { @@ -139,7 +139,7 @@ ClientMalwareReportRequest::Resource* pb_resource, const net::URLFetcher* source) { DVLOG(1) << "ReadResponse"; - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); net::HttpResponseHeaders* headers = source->GetResponseHeaders(); if (!headers) { DVLOG(1) << "Missing response headers."; @@ -172,7 +172,7 @@ ClientMalwareReportRequest::Resource* pb_resource, const std::string& data) { DVLOG(1) << "ReadData"; - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); ClientMalwareReportRequest::HTTPResponse* pb_response = pb_resource->mutable_response(); if (data.size() <= kMaxBodySizeBytes) { // Only send small bodies for now. @@ -184,7 +184,7 @@ void MalwareDetailsCacheCollector::AdvanceEntry() { DVLOG(1) << "AdvanceEntry"; - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // Advance to the next resource. ++resources_it_; current_fetch_.reset(NULL); @@ -197,7 +197,7 @@ void MalwareDetailsCacheCollector::AllDone(bool success) { DVLOG(1) << "AllDone"; - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); *result_ = success; BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback_); callback_.Reset();
diff --git a/chrome/browser/safe_browsing/malware_details_history.cc b/chrome/browser/safe_browsing/malware_details_history.cc index a9038c1..5005138 100644 --- a/chrome/browser/safe_browsing/malware_details_history.cc +++ b/chrome/browser/safe_browsing/malware_details_history.cc
@@ -24,7 +24,7 @@ Profile* profile) : profile_(profile), has_started_(false) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (profile) { registrar_.Add(this, chrome::NOTIFICATION_PROFILE_DESTROYED, content::Source<Profile>(profile)); @@ -62,7 +62,7 @@ int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(type, chrome::NOTIFICATION_PROFILE_DESTROYED); DVLOG(1) << "Profile gone."; profile_ = NULL; @@ -73,7 +73,7 @@ void MalwareDetailsRedirectsCollector::StartGetRedirects( const std::vector<GURL>& urls) { // History access from profile needs to happen in UI thread - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); for (size_t i = 0; i < urls.size(); ++i) { urls_.push_back(urls[i]); } @@ -82,7 +82,7 @@ } void MalwareDetailsRedirectsCollector::GetRedirects(const GURL& url) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!profile_) { AllDone(); return;
diff --git a/chrome/browser/safe_browsing/ping_manager.cc b/chrome/browser/safe_browsing/ping_manager.cc index f8335d7..86b29d3 100644 --- a/chrome/browser/safe_browsing/ping_manager.cc +++ b/chrome/browser/safe_browsing/ping_manager.cc
@@ -24,8 +24,12 @@ using content::BrowserThread; namespace { -// URL to upload invalid certificate chain reports -const char kExtendedReportingUploadUrl[] = +// URLs to upload invalid certificate chain reports. The HTTP URL is +// preferred since a client seeing an invalid cert might not be able to +// make an HTTPS connection to report it. +// TODO(estark): insert the production HTTP URL when it's ready +const char kExtendedReportingUploadUrlInsecure[] = ""; +const char kExtendedReportingUploadUrlSecure[] = "https://sb-ssl.google.com/safebrowsing/clientreport/chrome-certs"; } // namespace @@ -35,7 +39,7 @@ SafeBrowsingPingManager* SafeBrowsingPingManager::Create( net::URLRequestContextGetter* request_context_getter, const SafeBrowsingProtocolConfig& config) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); return new SafeBrowsingPingManager(request_context_getter, config); } @@ -44,16 +48,22 @@ const SafeBrowsingProtocolConfig& config) : client_name_(config.client_name), request_context_getter_(request_context_getter), - url_prefix_(config.url_prefix), - certificate_error_reporter_( - request_context_getter - ? new CertificateErrorReporter( - request_context_getter->GetURLRequestContext(), - GURL(kExtendedReportingUploadUrl), - CertificateErrorReporter::SEND_COOKIES) - : nullptr) { + url_prefix_(config.url_prefix) { DCHECK(!url_prefix_.empty()); + if (request_context_getter) { + bool use_insecure_certificate_upload_url = + CertificateErrorReporter::IsHttpUploadUrlSupported() && + strlen(kExtendedReportingUploadUrlInsecure) > 0; + GURL certificate_upload_url(use_insecure_certificate_upload_url + ? kExtendedReportingUploadUrlInsecure + : kExtendedReportingUploadUrlSecure); + + certificate_error_reporter_.reset(new CertificateErrorReporter( + request_context_getter->GetURLRequestContext(), certificate_upload_url, + CertificateErrorReporter::SEND_COOKIES)); + } + version_ = SafeBrowsingProtocolManagerHelper::Version(); }
diff --git a/chrome/browser/safe_browsing/protocol_manager_unittest.cc b/chrome/browser/safe_browsing/protocol_manager_unittest.cc index 2bf6b3d..852a20d4 100644 --- a/chrome/browser/safe_browsing/protocol_manager_unittest.cc +++ b/chrome/browser/safe_browsing/protocol_manager_unittest.cc
@@ -315,7 +315,7 @@ class MockProtocolDelegate : public SafeBrowsingProtocolManagerDelegate { public: MockProtocolDelegate() {} - virtual ~MockProtocolDelegate() {} + ~MockProtocolDelegate() override {} MOCK_METHOD0(UpdateStarted, void()); MOCK_METHOD1(UpdateFinished, void(bool)); @@ -328,17 +328,17 @@ MOCK_METHOD3(AddChunksRaw, void(const std::string& lists, const ScopedVector<SBChunkData>& chunks, AddChunksCallback)); - virtual void AddChunks(const std::string& list, - scoped_ptr<ScopedVector<SBChunkData> > chunks, - AddChunksCallback callback) override { + void AddChunks(const std::string& list, + scoped_ptr<ScopedVector<SBChunkData>> chunks, + AddChunksCallback callback) override { AddChunksRaw(list, *chunks, callback); } // TODO(shess): Actually test this case somewhere. MOCK_METHOD1(DeleteChunksRaw, void(const std::vector<SBChunkDelete>& chunk_deletes)); - virtual void DeleteChunks( - scoped_ptr<std::vector<SBChunkDelete> > chunk_deletes) override{ + void DeleteChunks( + scoped_ptr<std::vector<SBChunkDelete>> chunk_deletes) override { DeleteChunksRaw(*chunk_deletes); } };
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc index 536953a5..cdc185a 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_unittest.cc
@@ -120,10 +120,36 @@ user_response_ = CANCEL; } - void Navigate(const char* url, int page_id) { - WebContentsTester::For(web_contents())->TestDidNavigate( - web_contents()->GetMainFrame(), page_id, GURL(url), - ui::PAGE_TRANSITION_TYPED); + void Navigate(const char* url, + int page_id, + int nav_entry_id, + bool did_create_new_entry) { + NavigateInternal(url, page_id, nav_entry_id, did_create_new_entry, false); + } + + void NavigateCrossSite(const char* url, + int page_id, + int nav_entry_id, + bool did_create_new_entry) { + NavigateInternal(url, page_id, nav_entry_id, did_create_new_entry, true); + } + + void NavigateInternal(const char* url, + int page_id, + int nav_entry_id, + bool did_create_new_entry, + bool is_cross_site) { + // The pending RVH should commit for cross-site navigations. + content::RenderFrameHost* render_frame_host = + is_cross_site + ? content::WebContentsTester::For(web_contents()) + ->GetPendingMainFrame() + : web_contents()->GetMainFrame(); + + content::WebContentsTester::For(web_contents()) + ->TestDidNavigate(render_frame_host, page_id, nav_entry_id, + did_create_new_entry, GURL(url), + ui::PAGE_TRANSITION_TYPED); } void GoBack(bool is_cross_site) { @@ -139,7 +165,9 @@ WebContentsTester::For(web_contents())->TestDidNavigate( rfh, entry->GetPageID(), - GURL(entry->GetURL()), + entry->GetUniqueID(), + false, + entry->GetURL(), ui::PAGE_TRANSITION_TYPED); } @@ -224,8 +252,7 @@ // Simulate the load causing a safe browsing interstitial to be shown. ShowInterstitial(false, kBadURL); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); base::RunLoop().RunUntilIdle(); @@ -256,11 +283,11 @@ // Start a load. controller().LoadURL(GURL(kBadURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int pending_id = controller().GetPendingEntry()->GetUniqueID(); // Simulate the load causing a safe browsing interstitial to be shown. ShowInterstitial(false, kBadURL); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); // Simulate the user clicking "proceed". @@ -269,7 +296,7 @@ // The interstitial is shown until the navigation commits. ASSERT_TRUE(InterstitialPage::GetInterstitialPage(web_contents())); // Commit the navigation. - Navigate(kBadURL, 1); + Navigate(kBadURL, 1, pending_id, true); // The interstitial should be gone now. ASSERT_FALSE(InterstitialPage::GetInterstitialPage(web_contents())); @@ -288,16 +315,15 @@ prefs::kSafeBrowsingExtendedReportingEnabled, true); // Navigate somewhere. - Navigate(kGoogleURL, 1); + Navigate(kGoogleURL, 1, 0, true); // Navigate somewhere else. - Navigate(kGoodURL, 2); + Navigate(kGoodURL, 2, 0, true); // Simulate that page loading a bad-resource triggering an interstitial. ShowInterstitial(true, kBadURL); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); // Simulate the user clicking "don't proceed". @@ -325,13 +351,12 @@ prefs::kSafeBrowsingExtendedReportingEnabled, true); // Navigate somewhere. - Navigate(kGoodURL, 1); + Navigate(kGoodURL, 1, 0, true); // Simulate that page loading a bad-resource triggering an interstitial. ShowInterstitial(true, kBadURL); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); // Simulate the user clicking "proceed". @@ -360,10 +385,10 @@ prefs::kSafeBrowsingExtendedReportingEnabled, true); // Navigate somewhere. - Navigate(kGoogleURL, 1); + Navigate(kGoogleURL, 1, 0, true); // Navigate somewhere else. - Navigate(kGoodURL, 2); + Navigate(kGoodURL, 2, 0, true); // Simulate that page loading a bad-resource triggering an interstitial. ShowInterstitial(true, kBadURL); @@ -373,8 +398,7 @@ ShowInterstitial(true, kBadURL2); ShowInterstitial(true, kBadURL3); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); // Simulate the user clicking "don't proceed". @@ -403,10 +427,10 @@ prefs::kSafeBrowsingExtendedReportingEnabled, true); // Navigate somewhere. - Navigate(kGoogleURL, 1); + Navigate(kGoogleURL, 1, 0, true); // Navigate somewhere else. - Navigate(kGoodURL, 2); + Navigate(kGoodURL, 2, 0, true); // Simulate that page loading a bad-resource triggering an interstitial. ShowInterstitial(true, kBadURL); @@ -416,8 +440,7 @@ ShowInterstitial(true, kBadURL2); ShowInterstitial(true, kBadURL3); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); // Proceed through the 1st interstitial. @@ -453,8 +476,7 @@ // Tests showing a blocking page for a page that contains multiple malware // subresources and proceeding through the multiple interstitials. -TEST_F(SafeBrowsingBlockingPageTest, - PageWithMultipleMalwareResourceProceed) { +TEST_F(SafeBrowsingBlockingPageTest, PageWithMultipleMalwareResourceProceed) { // Enable malware reports. Profile* profile = Profile::FromBrowserContext( web_contents()->GetBrowserContext()); @@ -462,7 +484,7 @@ prefs::kSafeBrowsingExtendedReportingEnabled, true); // Navigate somewhere else. - Navigate(kGoodURL, 1); + Navigate(kGoodURL, 1, 0, true); // Simulate that page loading a bad-resource triggering an interstitial. ShowInterstitial(true, kBadURL); @@ -472,8 +494,7 @@ ShowInterstitial(true, kBadURL2); ShowInterstitial(true, kBadURL3); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); // Proceed through the 1st interstitial. @@ -515,19 +536,19 @@ prefs::kSafeBrowsingExtendedReportingEnabled, true); // Navigate somewhere. - Navigate(kGoodURL, 1); + Navigate(kGoodURL, 1, 0, true); // Now navigate to a bad page triggerring an interstitial. controller().LoadURL(GURL(kBadURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int pending_id = controller().GetPendingEntry()->GetUniqueID(); ShowInterstitial(false, kBadURL); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); // Proceed, then navigate back. ProceedThroughInterstitial(sb_interstitial); - Navigate(kBadURL, 2); // Commit the navigation. + Navigate(kBadURL, 2, pending_id, true); // Commit the navigation. GoBack(true); // We are back on the good page. @@ -538,13 +559,15 @@ // Navigate forward to the malware URL. web_contents()->GetController().GoForward(); + pending_id = controller().GetPendingEntry()->GetUniqueID(); ShowInterstitial(false, kBadURL); sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); // Let's proceed and make sure everything is OK (bug 17627). ProceedThroughInterstitial(sb_interstitial); - Navigate(kBadURL, 2); // Commit the navigation. + // Commit the navigation. + NavigateCrossSite(kBadURL, 2, pending_id, false); sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_FALSE(sb_interstitial); ASSERT_EQ(2, controller().GetEntryCount()); @@ -570,8 +593,7 @@ // Simulate the load causing a safe browsing interstitial to be shown. ShowInterstitial(false, kBadURL); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); base::RunLoop().RunUntilIdle(); @@ -607,8 +629,7 @@ // Simulate the load causing a safe browsing interstitial to be shown. ShowInterstitial(false, kBadURL); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); base::RunLoop().RunUntilIdle(); @@ -642,8 +663,7 @@ // Simulate the load causing a safe browsing interstitial to be shown. ShowInterstitial(false, kBadURL); - SafeBrowsingBlockingPage* sb_interstitial = - GetSafeBrowsingBlockingPage(); + SafeBrowsingBlockingPage* sb_interstitial = GetSafeBrowsingBlockingPage(); ASSERT_TRUE(sb_interstitial); base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index eda8a58..ede1c52 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -135,7 +135,7 @@ net::URLRequestContext* SafeBrowsingURLRequestContextGetter::GetURLRequestContext() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(sb_service_->url_request_context_.get()); return sb_service_->url_request_context_.get(); @@ -302,7 +302,7 @@ // Binhash verification is only enabled for UMA users for now. bool SafeBrowsingService::DownloadBinHashNeeded() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); #if defined(FULL_SAFE_BROWSING) return (database_manager_->download_protection_enabled() && @@ -315,7 +315,7 @@ } net::URLRequestContextGetter* SafeBrowsingService::url_request_context() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); return url_request_context_getter_.get(); } @@ -330,12 +330,12 @@ } SafeBrowsingProtocolManager* SafeBrowsingService::protocol_manager() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); return protocol_manager_; } SafeBrowsingPingManager* SafeBrowsingService::ping_manager() const { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); return ping_manager_; } @@ -402,7 +402,7 @@ tracked_objects::ScopedTracker tracking_profile1( FROM_HERE_WITH_EXPLICIT_FUNCTION( "455469 SafeBrowsingService::InitURLRequestContextOnIOThread 1")); - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(!url_request_context_.get()); scoped_refptr<net::CookieStore> cookie_store( @@ -427,7 +427,7 @@ } void SafeBrowsingService::DestroyURLRequestContextOnIOThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); url_request_context_->AssertNoURLRequests(); @@ -481,7 +481,7 @@ tracked_objects::ScopedTracker tracking_profile1( FROM_HERE_WITH_EXPLICIT_FUNCTION( "455469 SafeBrowsingService::StartOnIOThread 1")); - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (enabled_) return; enabled_ = true; @@ -517,7 +517,7 @@ } void SafeBrowsingService::StopOnIOThread(bool shutdown) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); #if defined(SAFE_BROWSING_DB_LOCAL) database_manager_->StopOnIOThread(shutdown); @@ -540,7 +540,7 @@ } void SafeBrowsingService::Start() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, @@ -559,14 +559,14 @@ const content::NotificationDetails& details) { switch (type) { case chrome::NOTIFICATION_PROFILE_CREATED: { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); Profile* profile = content::Source<Profile>(source).ptr(); if (!profile->IsOffTheRecord()) AddPrefService(profile->GetPrefs()); break; } case chrome::NOTIFICATION_PROFILE_DESTROYED: { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); Profile* profile = content::Source<Profile>(source).ptr(); if (!profile->IsOffTheRecord()) RemovePrefService(profile->GetPrefs());
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.h b/chrome/browser/safe_browsing/safe_browsing_service.h index 5720e00..487be29 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.h +++ b/chrome/browser/safe_browsing/safe_browsing_service.h
@@ -104,7 +104,7 @@ safe_browsing::ClientSideDetectionService* safe_browsing_detection_service() const { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return csd_service_.get(); } @@ -112,7 +112,7 @@ // is destroyed. safe_browsing::DownloadProtectionService* download_protection_service() const { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return download_service_.get(); }
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc index f38a8f5..884b45b 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -399,7 +399,7 @@ full_hash->list_id = list_id; } - virtual void SetUp() { + void SetUp() override { // InProcessBrowserTest::SetUp() instantiates SafebrowsingService and // RegisterFactory has to be called before SafeBrowsingService is created. sb_factory_.reset(new TestSafeBrowsingServiceFactory( @@ -410,7 +410,7 @@ InProcessBrowserTest::SetUp(); } - virtual void TearDown() { + void TearDown() override { InProcessBrowserTest::TearDown(); // Unregister test factories after InProcessBrowserTest::TearDown @@ -420,7 +420,7 @@ SafeBrowsingService::RegisterFactory(NULL); } - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { // Makes sure the auto update is not triggered during the test. // This test will fill up the database using testing prefixes // and urls. @@ -443,7 +443,7 @@ InProcessBrowserTest::TearDownOnMainThread(); } - virtual void SetUpInProcessBrowserTestFixture() { + void SetUpInProcessBrowserTestFixture() override { ASSERT_TRUE(test_server()->Start()); }
diff --git a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc index f23a724..417f4cd 100644 --- a/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc +++ b/chrome/browser/safe_browsing/sandboxed_zip_analyzer.cc
@@ -34,7 +34,7 @@ } void SandboxedZipAnalyzer::Start() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Starting the analyzer will block on opening the zip file, so run this // on a worker thread. The task does not need to block shutdown. if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( @@ -112,7 +112,7 @@ } void SandboxedZipAnalyzer::StartProcessOnIOThread() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); utility_process_host_ = content::UtilityProcessHost::Create( this, BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()) @@ -125,7 +125,7 @@ } void SandboxedZipAnalyzer::OnUtilityProcessStarted() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); base::ProcessHandle utility_process = content::RenderProcessHost::run_renderer_in_process() ? base::GetCurrentProcessHandle() : @@ -144,7 +144,7 @@ void SandboxedZipAnalyzer::OnAnalyzeZipFileFinished( const zip_analyzer::Results& results) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (callback_called_) return; BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
diff --git a/chrome/browser/safe_browsing/ui_manager.cc b/chrome/browser/safe_browsing/ui_manager.cc index 382d103..b50e3e3c 100644 --- a/chrome/browser/safe_browsing/ui_manager.cc +++ b/chrome/browser/safe_browsing/ui_manager.cc
@@ -58,7 +58,7 @@ SafeBrowsingUIManager::~SafeBrowsingUIManager() { } void SafeBrowsingUIManager::StopOnIOThread(bool shutdown) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); if (shutdown) sb_service_ = NULL; @@ -78,7 +78,7 @@ void SafeBrowsingUIManager::OnBlockingPageDone( const std::vector<UnsafeResource>& resources, bool proceed) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); for (std::vector<UnsafeResource>::const_iterator iter = resources.begin(); iter != resources.end(); ++iter) { const UnsafeResource& resource = *iter; @@ -96,7 +96,7 @@ void SafeBrowsingUIManager::DisplayBlockingPage( const UnsafeResource& resource) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (resource.is_subresource && !resource.is_subframe) { // Sites tagged as serving Unwanted Software should only show a warning for // main-frame or sub-frame resource. Similar warning restrictions should be @@ -203,7 +203,7 @@ bool is_subresource, SBThreatType threat_type, const std::string& post_data) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!CanReportStats()) return; @@ -218,7 +218,7 @@ const std::string& hostname, const net::SSLInfo& ssl_info, const base::Closure& callback) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); BrowserThread::PostTaskAndReply( BrowserThread::IO, FROM_HERE, base::Bind( @@ -228,12 +228,12 @@ } void SafeBrowsingUIManager::AddObserver(Observer* observer) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); observer_list_.AddObserver(observer); } void SafeBrowsingUIManager::RemoveObserver(Observer* observer) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); observer_list_.RemoveObserver(observer); } @@ -244,7 +244,7 @@ bool is_subresource, SBThreatType threat_type, const std::string& post_data) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // The service may delete the ping manager (i.e. when user disabling service, // etc). This happens on the IO thread. @@ -263,7 +263,7 @@ void SafeBrowsingUIManager::ReportInvalidCertificateChainOnIOThread( const std::string& hostname, const net::SSLInfo& ssl_info) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // The service may delete the ping manager (i.e. when user disabling service, // etc). This happens on the IO thread. @@ -278,7 +278,7 @@ // when the report is ready. void SafeBrowsingUIManager::SendSerializedMalwareDetails( const std::string& serialized) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + DCHECK_CURRENTLY_ON(BrowserThread::IO); // The service may delete the ping manager (i.e. when user disabling service, // etc). This happens on the IO thread. @@ -292,7 +292,7 @@ } void SafeBrowsingUIManager::UpdateWhitelist(const UnsafeResource& resource) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Whitelist this domain and warning type for the given tab. WhiteListedEntry entry; entry.render_process_host_id = resource.render_process_host_id; @@ -305,7 +305,7 @@ } bool SafeBrowsingUIManager::IsWhitelisted(const UnsafeResource& resource) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); // Check if the user has already ignored our warning for this render_view // and domain. for (size_t i = 0; i < white_listed_entries_.size(); ++i) {
diff --git a/chrome/browser/search/hotword_service_factory.cc b/chrome/browser/search/hotword_service_factory.cc index 1aa72ac2..7324dcc1 100644 --- a/chrome/browser/search/hotword_service_factory.cc +++ b/chrome/browser/search/hotword_service_factory.cc
@@ -84,15 +84,9 @@ std::string(), user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); // Per-device settings (do not sync). - prefs->RegisterBooleanPref(prefs::kHotwordSearchEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->RegisterBooleanPref(prefs::kHotwordAlwaysOnSearchEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - prefs->RegisterBooleanPref(prefs::kHotwordAlwaysOnNotificationSeen, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs->RegisterBooleanPref(prefs::kHotwordSearchEnabled, false); + prefs->RegisterBooleanPref(prefs::kHotwordAlwaysOnSearchEnabled, false); + prefs->RegisterBooleanPref(prefs::kHotwordAlwaysOnNotificationSeen, false); } KeyedService* HotwordServiceFactory::BuildServiceInstanceFor(
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index f190840..feaf308 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -122,7 +122,7 @@ // Adds a localized string for the Google searchbox placeholder text. void AddGoogleSearchboxPlaceholderString(base::DictionaryValue* dictionary) { base::string16 placeholder = l10n_util::GetStringFUTF16( - IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER, + IDS_SEARCH_BOX_EMPTY_HINT, base::ASCIIToUTF16("Google")); dictionary->SetString("searchboxPlaceholder", placeholder); }
diff --git a/chrome/browser/search_engines/default_search_pref_migration_unittest.cc b/chrome/browser/search_engines/default_search_pref_migration_unittest.cc index 5508736..c4f026162 100644 --- a/chrome/browser/search_engines/default_search_pref_migration_unittest.cc +++ b/chrome/browser/search_engines/default_search_pref_migration_unittest.cc
@@ -21,6 +21,7 @@ #include "components/search_engines/search_engines_pref_names.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_service.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -44,6 +45,7 @@ } private: + content::TestBrowserThreadBundle thread_bundle_; base::ScopedTempDir temp_dir_; scoped_ptr<TestingProfile> profile_; scoped_ptr<DefaultSearchManager> default_search_manager_;
diff --git a/chrome/browser/search_engines/template_url_service_factory.cc b/chrome/browser/search_engines/template_url_service_factory.cc index ffab5b46..c4229d3 100644 --- a/chrome/browser/search_engines/template_url_service_factory.cc +++ b/chrome/browser/search_engines/template_url_service_factory.cc
@@ -81,76 +81,39 @@ registry->RegisterStringPref(prefs::kSyncedDefaultSearchProviderGUID, std::string(), user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDefaultSearchProviderEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, true); + registry->RegisterStringPref(prefs::kDefaultSearchProviderName, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderID, std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderPrepopulateID, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderSuggestURL, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderSearchURL, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderInstantURL, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderImageURL, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderNewTabURL, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderSearchURLPostParams, + std::string()); registry->RegisterStringPref( - prefs::kDefaultSearchProviderName, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDefaultSearchProviderSuggestURLPostParams, std::string()); registry->RegisterStringPref( - prefs::kDefaultSearchProviderID, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDefaultSearchProviderInstantURLPostParams, std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderImageURLPostParams, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderKeyword, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderIconURL, + std::string()); + registry->RegisterStringPref(prefs::kDefaultSearchProviderEncodings, + std::string()); + registry->RegisterListPref(prefs::kDefaultSearchProviderAlternateURLs); registry->RegisterStringPref( - prefs::kDefaultSearchProviderPrepopulateID, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderSuggestURL, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderSearchURL, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderInstantURL, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderImageURL, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderNewTabURL, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderSearchURLPostParams, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderSuggestURLPostParams, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderInstantURLPostParams, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderImageURLPostParams, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderKeyword, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderIconURL, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderEncodings, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kDefaultSearchProviderAlternateURLs, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kDefaultSearchProviderSearchTermsReplacementKey, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDefaultSearchProviderSearchTermsReplacementKey, std::string()); } content::BrowserContext* TemplateURLServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/service_process/service_process_control_browsertest.cc b/chrome/browser/service_process/service_process_control_browsertest.cc index 98f02901..5c931fa2 100644 --- a/chrome/browser/service_process/service_process_control_browsertest.cc +++ b/chrome/browser/service_process/service_process_control_browsertest.cc
@@ -65,14 +65,14 @@ ServiceProcessControl::GetInstance()->Disconnect(); } - virtual void SetUp() override { + void SetUp() override { // This should not be needed because TearDown() ends with a closed // service_process_, but HistogramsTimeout and Histograms fail without this // on Mac. service_process_.Close(); } - virtual void TearDown() override { + void TearDown() override { if (ServiceProcessControl::GetInstance()->IsConnected()) EXPECT_TRUE(ServiceProcessControl::GetInstance()->Shutdown()); #if defined(OS_MACOSX)
diff --git a/chrome/browser/shell_integration_win_unittest.cc b/chrome/browser/shell_integration_win_unittest.cc index 284eb33..74b5a8b 100644 --- a/chrome/browser/shell_integration_win_unittest.cc +++ b/chrome/browser/shell_integration_win_unittest.cc
@@ -32,7 +32,7 @@ class ShellIntegrationWinMigrateShortcutTest : public testing::Test { protected: - virtual void SetUp() override { + void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); // A path to a random target.
diff --git a/chrome/browser/signin/about_signin_internals_factory.cc b/chrome/browser/signin/about_signin_internals_factory.cc index 1236d9e..5d77ec8 100644 --- a/chrome/browser/signin/about_signin_internals_factory.cc +++ b/chrome/browser/signin/about_signin_internals_factory.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_error_controller_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" @@ -27,6 +28,7 @@ BrowserContextDependencyManager::GetInstance()) { DependsOn(AccountTrackerServiceFactory::GetInstance()); DependsOn(ChromeSigninClientFactory::GetInstance()); + DependsOn(GaiaCookieManagerServiceFactory::GetInstance()); DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance()); DependsOn(SigninErrorControllerFactory::GetInstance()); DependsOn(SigninManagerFactory::GetInstance()); @@ -56,10 +58,7 @@ for (int i = UNTIMED_FIELDS_BEGIN; i < UNTIMED_FIELDS_END; ++i) { const std::string pref_path = SigninStatusFieldToString( static_cast<UntimedSigninStatusField>(i)); - user_prefs->RegisterStringPref( - pref_path.c_str(), - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + user_prefs->RegisterStringPref(pref_path.c_str(), std::string()); } for (int i = TIMED_FIELDS_BEGIN; i < TIMED_FIELDS_END; ++i) { @@ -67,14 +66,8 @@ static_cast<TimedSigninStatusField>(i)) + ".value"; const std::string time = SigninStatusFieldToString( static_cast<TimedSigninStatusField>(i)) + ".time"; - user_prefs->RegisterStringPref( - value.c_str(), - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - user_prefs->RegisterStringPref( - time.c_str(), - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + user_prefs->RegisterStringPref(value.c_str(), std::string()); + user_prefs->RegisterStringPref(time.c_str(), std::string()); } } @@ -85,7 +78,8 @@ ProfileOAuth2TokenServiceFactory::GetForProfile(profile), AccountTrackerServiceFactory::GetForProfile(profile), SigninManagerFactory::GetForProfile(profile), - SigninErrorControllerFactory::GetForProfile(profile)); + SigninErrorControllerFactory::GetForProfile(profile), + GaiaCookieManagerServiceFactory::GetForProfile(profile)); service->Initialize(ChromeSigninClientFactory::GetForProfile(profile)); return service; }
diff --git a/chrome/browser/signin/account_reconcilor_unittest.cc b/chrome/browser/signin/account_reconcilor_unittest.cc index 7d6e9c5a..73d79c1de 100644 --- a/chrome/browser/signin/account_reconcilor_unittest.cc +++ b/chrome/browser/signin/account_reconcilor_unittest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/signin/account_reconcilor_factory.h" #include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/signin/fake_gaia_cookie_manager_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service.h" #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" #include "chrome/browser/signin/fake_signin_manager.h" @@ -88,6 +89,9 @@ FakeProfileOAuth2TokenService* token_service() { return token_service_; } TestSigninClient* test_signin_client() { return test_signin_client_; } AccountTrackerService* account_tracker() { return account_tracker_; } + FakeGaiaCookieManagerService* cookie_manager_service() { + return cookie_manager_service_; + } base::HistogramTester* histogram_tester() { return &histogram_tester_; } void SetFakeResponse(const std::string& url, @@ -114,7 +118,6 @@ content_settings::Observer* observer, const ContentSettingsPattern& primary_pattern); - GURL list_accounts_url() { return list_accounts_url_; } GURL get_check_connection_info_url() { return get_check_connection_info_url_; } @@ -126,11 +129,11 @@ FakeProfileOAuth2TokenService* token_service_; TestSigninClient* test_signin_client_; AccountTrackerService* account_tracker_; + FakeGaiaCookieManagerService* cookie_manager_service_; MockAccountReconcilor* mock_reconcilor_; net::FakeURLFetcherFactory url_fetcher_factory_; scoped_ptr<TestingProfileManager> testing_profile_manager_; base::HistogramTester histogram_tester_; - GURL list_accounts_url_; GURL get_check_connection_info_url_; DISALLOW_COPY_AND_ASSIGN(AccountReconcilorTest); @@ -140,6 +143,7 @@ : signin_manager_(NULL), token_service_(NULL), test_signin_client_(NULL), + cookie_manager_service_(NULL), mock_reconcilor_(NULL), url_fetcher_factory_(NULL) {} @@ -151,16 +155,10 @@ switches::kEnableNewProfileManagement); } - list_accounts_url_ = GaiaUrls::GetInstance()->ListAccountsURLWithSource( - GaiaConstants::kReconcilorSource); get_check_connection_info_url_ = GaiaUrls::GetInstance()->GetCheckConnectionInfoURLWithSource( GaiaConstants::kChromeSource); - // Specific tests may set a response that includes specific accounts. - SetFakeResponse(list_accounts_url().spec(), "", - net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS); - testing_profile_manager_.reset( new TestingProfileManager(TestingBrowserProcess::GetGlobal())); ASSERT_TRUE(testing_profile_manager_.get()->SetUp()); @@ -171,6 +169,9 @@ factories.push_back(std::make_pair( ProfileOAuth2TokenServiceFactory::GetInstance(), BuildFakeProfileOAuth2TokenService)); + factories.push_back(std::make_pair( + GaiaCookieManagerServiceFactory::GetInstance(), + FakeGaiaCookieManagerService::Build)); factories.push_back(std::make_pair(SigninManagerFactory::GetInstance(), FakeSigninManagerBase::Build)); factories.push_back(std::make_pair(AccountReconcilorFactory::GetInstance(), @@ -195,6 +196,17 @@ signin_manager_ = static_cast<FakeSigninManagerForTesting*>( SigninManagerFactory::GetForProfile(profile())); + + test_signin_client_ = + static_cast<TestSigninClient*>( + ChromeSigninClientFactory::GetForProfile(profile())); + + cookie_manager_service_ = + static_cast<FakeGaiaCookieManagerService*>( + GaiaCookieManagerServiceFactory::GetForProfile(profile())); + cookie_manager_service_->Init(&url_fetcher_factory_); + + cookie_manager_service_->SetListAccountsResponseHttpNotFound(); } MockAccountReconcilor* AccountReconcilorTest::GetMockReconcilor() { @@ -303,41 +315,37 @@ TEST_F(AccountReconcilorTest, GetAccountsFromCookieSuccess) { const std::string account_id = ConnectProfileToAccount("12345", "user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccountWithExpiry( + "user@gmail.com", true); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); AccountReconcilor* reconcilor = AccountReconcilorFactory::GetForProfile(profile()); ASSERT_TRUE(reconcilor); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - reconcilor->StartReconcile(); - ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); - base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(reconcilor->AreGaiaAccountsSet()); - const std::vector<std::pair<std::string, bool> >& accounts = - reconcilor->GetGaiaAccountsForTesting(); + + std::vector<std::pair<std::string, bool> > accounts; + ASSERT_TRUE(cookie_manager_service()->ListAccounts(&accounts)); ASSERT_EQ(1u, accounts.size()); ASSERT_EQ(account_id, accounts[0].first); } TEST_F(AccountReconcilorTest, GetAccountsFromCookieFailure) { ConnectProfileToAccount("12345", "user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseHttpNotFound(); + AccountReconcilor* reconcilor = AccountReconcilorFactory::GetForProfile(profile()); ASSERT_TRUE(reconcilor); - SetFakeResponse(list_accounts_url().spec(), "", - net::HTTP_NOT_FOUND, net::URLRequestStatus::SUCCESS); - reconcilor->StartReconcile(); - ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); - base::RunLoop().RunUntilIdle(); - ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); + + std::vector<std::pair<std::string, bool> > accounts; + ASSERT_FALSE(cookie_manager_service()->ListAccounts(&accounts)); + ASSERT_EQ(0u, accounts.size()); } TEST_P(AccountReconcilorTest, StartReconcileNoop) { @@ -348,13 +356,10 @@ AccountReconcilorFactory::GetForProfile(profile()); ASSERT_TRUE(reconcilor); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); + cookie_manager_service()->SetListAccountsResponseOneAccount("user@gmail.com"); reconcilor->StartReconcile(); ASSERT_TRUE(reconcilor->is_reconcile_started_); - ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); base::RunLoop().RunUntilIdle(); ASSERT_FALSE(reconcilor->is_reconcile_started_); @@ -379,9 +384,11 @@ reconcilor->StartReconcile(); ASSERT_FALSE(reconcilor->is_reconcile_started_); - ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); base::RunLoop().RunUntilIdle(); + std::vector<std::pair<std::string, bool> > accounts; + // This will be the first call to ListAccounts. + ASSERT_FALSE(cookie_manager_service()->ListAccounts(&accounts)); ASSERT_FALSE(reconcilor->is_reconcile_started_); } @@ -468,17 +475,13 @@ const std::string account_id = ConnectProfileToAccount("12345", "Dot.S@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + "dot.s@gmail.com"); AccountReconcilor* reconcilor = AccountReconcilorFactory::GetForProfile(profile()); ASSERT_TRUE(reconcilor); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"dot.s@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - reconcilor->StartReconcile(); - ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); - base::RunLoop().RunUntilIdle(); ASSERT_FALSE(reconcilor->is_reconcile_started_); @@ -493,19 +496,15 @@ ConnectProfileToAccount("12345", "user@gmail.com"); const std::string account_id2 = PickAccountIdForAccount("67890", "other@gmail.com"); + cookie_manager_service()->SetListAccountsResponseTwoAccounts( + "user@gmail.com", "other@gmail.com"); token_service()->UpdateCredentials(account_id2, "refresh_token"); AccountReconcilor* reconcilor = AccountReconcilorFactory::GetForProfile(profile()); ASSERT_TRUE(reconcilor); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], " - "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - reconcilor->StartReconcile(); - ASSERT_FALSE(reconcilor->AreGaiaAccountsSet()); base::RunLoop().RunUntilIdle(); ASSERT_FALSE(reconcilor->is_reconcile_started_); @@ -521,6 +520,8 @@ const std::string account_id = ConnectProfileToAccount("12345", "user@gmail.com"); token_service()->UpdateCredentials(account_id, "refresh_token"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + "user@gmail.com"); const std::string account_id2 = PickAccountIdForAccount("67890", "other@gmail.com"); @@ -528,10 +529,6 @@ EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2)); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - AccountReconcilor* reconcilor = GetMockReconcilor(); reconcilor->StartReconcile(); @@ -555,15 +552,12 @@ const std::string account_id = ConnectProfileToAccount("12345", "user@gmail.com"); token_service()->UpdateCredentials(account_id, "refresh_token"); + cookie_manager_service()->SetListAccountsResponseTwoAccounts( + "user@gmail.com", "other@gmail.com"); EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], " - "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - AccountReconcilor* reconcilor = GetMockReconcilor(); reconcilor->StartReconcile(); ASSERT_TRUE(reconcilor->is_reconcile_started_); @@ -591,17 +585,13 @@ const std::string account_id3 = PickAccountIdForAccount("34567", "third@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + "user@gmail.com"); token_service()->UpdateCredentials(account_id2, "refresh_token"); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2)); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id3)); - SetFakeResponse( - list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, - net::URLRequestStatus::SUCCESS); - AccountReconcilor* reconcilor = GetMockReconcilor(); reconcilor->StartReconcile(); @@ -621,13 +611,10 @@ "Signin.Reconciler.RemovedFromCookieJar.FirstRun", 0, 1); // Do another pass after I've added a third account to the token service + cookie_manager_service()->SetListAccountsResponseTwoAccounts( + "user@gmail.com", "other@gmail.com"); + cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false); - SetFakeResponse( - list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1], " - "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, - net::URLRequestStatus::SUCCESS); // This will cause the reconcilor to fire. token_service()->UpdateCredentials(account_id3, "refresh_token"); base::RunLoop().RunUntilIdle(); @@ -662,16 +649,13 @@ PickAccountIdForAccount("67890", "other@gmail.com"); token_service()->UpdateCredentials(account_id2, "refresh_token"); + cookie_manager_service()->SetListAccountsResponseTwoAccounts( + "other@gmail.com", "user@gmail.com"); EXPECT_CALL(*GetMockReconcilor(), PerformLogoutAllAccountsAction()); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id2)); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1], " - "[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - AccountReconcilor* reconcilor = GetMockReconcilor(); reconcilor->StartReconcile(); @@ -697,15 +681,13 @@ TEST_P(AccountReconcilorTest, StartReconcileOnlyOnce) { const std::string account_id = ConnectProfileToAccount("12345", "user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccount( + "user@gmail.com"); AccountReconcilor* reconcilor = AccountReconcilorFactory::GetForProfile(profile()); ASSERT_TRUE(reconcilor); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - ASSERT_FALSE(reconcilor->is_reconcile_started_); reconcilor->StartReconcile(); ASSERT_TRUE(reconcilor->is_reconcile_started_); @@ -720,14 +702,11 @@ const std::string account_id2 = PickAccountIdForAccount("67890", "other@gmail.com"); token_service()->UpdateCredentials(account_id2, "refresh_token"); + cookie_manager_service()->SetListAccountsResponseTwoAccountsWithExpiry( + "user@gmail.com", true, "other@gmail.com", false); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]," - "[\"b\", 0, \"n\", \"other@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - AccountReconcilor* reconcilor = AccountReconcilorFactory::GetForProfile(profile()); ASSERT_TRUE(reconcilor); @@ -745,13 +724,11 @@ TEST_F(AccountReconcilorTest, AddAccountToCookieCompletedWithBogusAccount) { const std::string account_id = ConnectProfileToAccount("12345", "user@gmail.com"); + cookie_manager_service()->SetListAccountsResponseOneAccountWithExpiry( + "user@gmail.com", true); EXPECT_CALL(*GetMockReconcilor(), PerformMergeAction(account_id)); - SetFakeResponse(list_accounts_url().spec(), - "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 0]]]", - net::HTTP_OK, net::URLRequestStatus::SUCCESS); - AccountReconcilor* reconcilor = AccountReconcilorFactory::GetForProfile(profile()); ASSERT_TRUE(reconcilor);
diff --git a/chrome/browser/signin/account_tracker_service_factory.cc b/chrome/browser/signin/account_tracker_service_factory.cc index 60ddfff4..0b99976 100644 --- a/chrome/browser/signin/account_tracker_service_factory.cc +++ b/chrome/browser/signin/account_tracker_service_factory.cc
@@ -39,13 +39,9 @@ void AccountTrackerServiceFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref( - AccountTrackerService::kAccountInfoPref, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kAccountIdMigrationState, - AccountTrackerService::MIGRATION_NOT_STARTED, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(AccountTrackerService::kAccountInfoPref); + registry->RegisterIntegerPref(prefs::kAccountIdMigrationState, + AccountTrackerService::MIGRATION_NOT_STARTED); } KeyedService* AccountTrackerServiceFactory::BuildServiceInstanceFor(
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc index debf8eca4..90ddd804 100644 --- a/chrome/browser/signin/chrome_signin_client.cc +++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -61,8 +61,10 @@ bool ChromeSigninClient::SettingsAllowSigninCookies( CookieSettings* cookie_settings) { GURL gaia_url = GaiaUrls::GetInstance()->gaia_url(); + GURL google_url = GaiaUrls::GetInstance()->google_url(); return cookie_settings && - cookie_settings->IsSettingCookieAllowed(gaia_url, gaia_url); + cookie_settings->IsSettingCookieAllowed(gaia_url, gaia_url) && + cookie_settings->IsSettingCookieAllowed(google_url, google_url); } PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
diff --git a/chrome/browser/signin/easy_unlock_auth_attempt.cc b/chrome/browser/signin/easy_unlock_auth_attempt.cc index 44ca2d94..5560754a 100644 --- a/chrome/browser/signin/easy_unlock_auth_attempt.cc +++ b/chrome/browser/signin/easy_unlock_auth_attempt.cc
@@ -7,7 +7,8 @@ #include "base/bind.h" #include "base/logging.h" #include "chrome/browser/signin/easy_unlock_app_manager.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "chrome/browser/signin/proximity_auth_facade.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "crypto/encryptor.h" #include "crypto/symmetric_key.h" @@ -50,25 +51,25 @@ const std::string& user_id, const std::string& key_secret, const std::string& key_label) { - if (!ScreenlockBridge::Get()->IsLocked()) + if (!GetScreenlockBridgeInstance()->IsLocked()) return; switch (auth_attempt_type) { case EasyUnlockAuthAttempt::TYPE_UNLOCK: if (success) { - ScreenlockBridge::Get()->lock_handler()->Unlock(user_id); + GetScreenlockBridgeInstance()->lock_handler()->Unlock(user_id); } else { - ScreenlockBridge::Get()->lock_handler()->EnableInput(); + GetScreenlockBridgeInstance()->lock_handler()->EnableInput(); } return; case EasyUnlockAuthAttempt::TYPE_SIGNIN: if (success) { - ScreenlockBridge::Get()->lock_handler()->AttemptEasySignin( + GetScreenlockBridgeInstance()->lock_handler()->AttemptEasySignin( user_id, key_secret, key_label); } else { // Attempting signin with an empty secret is equivalent to canceling the // attempt. - ScreenlockBridge::Get()->lock_handler()->AttemptEasySignin( + GetScreenlockBridgeInstance()->lock_handler()->AttemptEasySignin( user_id, std::string(), std::string()); } return; @@ -99,13 +100,13 @@ bool EasyUnlockAuthAttempt::Start() { DCHECK_EQ(STATE_IDLE, state_); - if (!ScreenlockBridge::Get()->IsLocked()) + if (!GetScreenlockBridgeInstance()->IsLocked()) return false; - ScreenlockBridge::LockHandler::AuthType auth_type = - ScreenlockBridge::Get()->lock_handler()->GetAuthType(user_id_); + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type = + GetScreenlockBridgeInstance()->lock_handler()->GetAuthType(user_id_); - if (auth_type != ScreenlockBridge::LockHandler::USER_CLICK) { + if (auth_type != proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK) { Cancel(user_id_); return false; } @@ -125,7 +126,7 @@ if (state_ != STATE_RUNNING || user_id != user_id_) return; - if (!ScreenlockBridge::Get()->IsLocked()) + if (!GetScreenlockBridgeInstance()->IsLocked()) return; if (type_ != TYPE_UNLOCK) { @@ -144,7 +145,7 @@ if (state_ != STATE_RUNNING || user_id != user_id_) return; - if (!ScreenlockBridge::Get()->IsLocked()) + if (!GetScreenlockBridgeInstance()->IsLocked()) return; if (type_ != TYPE_SIGNIN) {
diff --git a/chrome/browser/signin/easy_unlock_auth_attempt_unittest.cc b/chrome/browser/signin/easy_unlock_auth_attempt_unittest.cc index 0cf2f87..3b183cf 100644 --- a/chrome/browser/signin/easy_unlock_auth_attempt_unittest.cc +++ b/chrome/browser/signin/easy_unlock_auth_attempt_unittest.cc
@@ -6,7 +6,8 @@ #include "base/macros.h" #include "chrome/browser/signin/easy_unlock_app_manager.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "chrome/browser/signin/proximity_auth_facade.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_CHROMEOS) @@ -100,7 +101,7 @@ }; // Fake lock handler to be used in these tests. -class TestLockHandler : public ScreenlockBridge::LockHandler { +class TestLockHandler : public proximity_auth::ScreenlockBridge::LockHandler { public: // The state of unlock/signin procedure. enum AuthState { @@ -133,14 +134,15 @@ // Not using |SetAuthType| to make sure it's not called during tests. void set_auth_type(AuthType value) { auth_type_ = value; } - // ScreenlockBridge::LockHandler implementation: + // proximity_auth::ScreenlockBridge::LockHandler implementation: void ShowBannerMessage(const base::string16& message) override { ADD_FAILURE() << "Should not be reached."; } void ShowUserPodCustomIcon( const std::string& user_email, - const ScreenlockBridge::UserPodCustomIconOptions& icon) override { + const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions& icon) + override { ADD_FAILURE() << "Should not be reached."; } @@ -215,7 +217,7 @@ } void TearDown() override { - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); auth_attempt_.reset(); } @@ -223,7 +225,7 @@ void InitScreenLock() { lock_handler_.reset(new TestLockHandler(kTestUser1)); lock_handler_->set_state(TestLockHandler::STATE_ATTEMPTING_UNLOCK); - ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); + GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_.get()); } scoped_ptr<EasyUnlockAuthAttempt> auth_attempt_; @@ -235,7 +237,7 @@ }; TEST_F(EasyUnlockAuthAttemptUnlockTest, StartWhenNotLocked) { - ASSERT_FALSE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_FALSE(GetScreenlockBridgeInstance()->IsLocked()); EXPECT_FALSE(auth_attempt_->Start()); EXPECT_EQ(0u, app_manager_->auth_attempt_count()); @@ -243,10 +245,11 @@ TEST_F(EasyUnlockAuthAttemptUnlockTest, StartWhenAuthTypeIsPassword) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK, lock_handler_->state()); - lock_handler_->set_auth_type(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD); + lock_handler_->set_auth_type( + proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD); EXPECT_FALSE(auth_attempt_->Start()); @@ -257,7 +260,7 @@ TEST_F(EasyUnlockAuthAttemptUnlockTest, StartWhenDispatchingAuthAttemptEventFails) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK, lock_handler_->state()); app_manager_->set_auth_attempt_should_fail(true); @@ -270,7 +273,7 @@ TEST_F(EasyUnlockAuthAttemptUnlockTest, ResetBeforeFinalizeUnlock) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -285,7 +288,7 @@ TEST_F(EasyUnlockAuthAttemptUnlockTest, FinalizeUnlockFailure) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -300,7 +303,7 @@ TEST_F(EasyUnlockAuthAttemptUnlockTest, FinalizeSigninCalled) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -317,7 +320,7 @@ TEST_F(EasyUnlockAuthAttemptUnlockTest, UnlockSucceeds) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -332,7 +335,7 @@ TEST_F(EasyUnlockAuthAttemptUnlockTest, FinalizeUnlockCalledForWrongUser) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_UNLOCK, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -367,7 +370,7 @@ } void TearDown() override { - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); auth_attempt_.reset(); } @@ -375,7 +378,7 @@ void InitScreenLock() { lock_handler_.reset(new TestLockHandler(kTestUser1)); lock_handler_->set_state(TestLockHandler::STATE_ATTEMPTING_SIGNIN); - ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); + GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_.get()); } scoped_ptr<EasyUnlockAuthAttempt> auth_attempt_; @@ -387,7 +390,7 @@ }; TEST_F(EasyUnlockAuthAttemptSigninTest, StartWhenNotLocked) { - ASSERT_FALSE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_FALSE(GetScreenlockBridgeInstance()->IsLocked()); EXPECT_FALSE(auth_attempt_->Start()); EXPECT_EQ(0u, app_manager_->auth_attempt_count()); @@ -395,10 +398,11 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, StartWhenAuthTypeIsPassword) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); - lock_handler_->set_auth_type(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD); + lock_handler_->set_auth_type( + proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD); EXPECT_FALSE(auth_attempt_->Start()); @@ -409,7 +413,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, StartWhenDispatchingAuthAttemptEventFails) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); app_manager_->set_auth_attempt_should_fail(true); @@ -422,7 +426,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, ResetBeforeFinalizeSignin) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -437,7 +441,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, FinalizeSigninWithEmtpySecret) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -452,7 +456,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, FinalizeSigninWithEmtpyKey) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -467,7 +471,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, SigninSuccess) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -484,7 +488,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, WrongWrappedSecret) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -499,7 +503,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, InvalidSessionKey) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -514,7 +518,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, FinalizeUnlockCalled) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start()); @@ -529,7 +533,7 @@ TEST_F(EasyUnlockAuthAttemptSigninTest, FinalizeSigninCalledForWrongUser) { InitScreenLock(); - ASSERT_TRUE(ScreenlockBridge::Get()->IsLocked()); + ASSERT_TRUE(GetScreenlockBridgeInstance()->IsLocked()); ASSERT_EQ(TestLockHandler::STATE_ATTEMPTING_SIGNIN, lock_handler_->state()); ASSERT_TRUE(auth_attempt_->Start());
diff --git a/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc b/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc index 3a4ee63..4b7171a 100644 --- a/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc +++ b/chrome/browser/signin/easy_unlock_screenlock_state_handler.cc
@@ -14,7 +14,7 @@ namespace { -ScreenlockBridge::UserPodCustomIcon GetIconForState( +proximity_auth::ScreenlockBridge::UserPodCustomIcon GetIconForState( EasyUnlockScreenlockStateHandler::State state) { switch (state) { case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH: @@ -24,20 +24,21 @@ case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE: case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED: case EasyUnlockScreenlockStateHandler::STATE_RSSI_TOO_LOW: - return ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED; + return proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED; case EasyUnlockScreenlockStateHandler::STATE_TX_POWER_TOO_HIGH: case EasyUnlockScreenlockStateHandler:: STATE_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH: // TODO(isherman): This icon is currently identical to the regular locked // icon. Once the reduced proximity range flag is removed, consider // deleting the redundant icon. - return ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED_WITH_PROXIMITY_HINT; + return proximity_auth::ScreenlockBridge:: + USER_POD_CUSTOM_ICON_LOCKED_WITH_PROXIMITY_HINT; case EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING: - return ScreenlockBridge::USER_POD_CUSTOM_ICON_SPINNER; + return proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_SPINNER; case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED: - return ScreenlockBridge::USER_POD_CUSTOM_ICON_UNLOCKED; + return proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_UNLOCKED; default: - return ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE; + return proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE; } } @@ -93,11 +94,10 @@ } // namespace - EasyUnlockScreenlockStateHandler::EasyUnlockScreenlockStateHandler( const std::string& user_email, HardlockState initial_hardlock_state, - ScreenlockBridge* screenlock_bridge) + proximity_auth::ScreenlockBridge* screenlock_bridge) : state_(STATE_INACTIVE), user_email_(user_email), screenlock_bridge_(screenlock_bridge), @@ -140,7 +140,7 @@ // Do nothing when auth type is online. if (screenlock_bridge_->lock_handler()->GetAuthType(user_email_) == - ScreenlockBridge::LockHandler::ONLINE_SIGN_IN) { + proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN) { return; } @@ -155,14 +155,15 @@ UpdateScreenlockAuthType(); - ScreenlockBridge::UserPodCustomIcon icon = GetIconForState(state_); + proximity_auth::ScreenlockBridge::UserPodCustomIcon icon = + GetIconForState(state_); - if (icon == ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE) { + if (icon == proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE) { screenlock_bridge_->lock_handler()->HideUserPodCustomIcon(user_email_); return; } - ScreenlockBridge::UserPodCustomIconOptions icon_options; + proximity_auth::ScreenlockBridge::UserPodCustomIconOptions icon_options; icon_options.SetIcon(icon); // Don't hardlock on trial run. @@ -222,13 +223,13 @@ } void EasyUnlockScreenlockStateHandler::OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { did_see_locked_phone_ = IsLockedState(state_); RefreshScreenlockState(); } void EasyUnlockScreenlockStateHandler::OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { if (hardlock_state_ == LOGIN_FAILED) hardlock_state_ = NO_HARDLOCK; hardlock_ui_shown_ = false; @@ -259,15 +260,18 @@ return; // Do not override online signin. - const ScreenlockBridge::LockHandler::AuthType existing_auth_type = - screenlock_bridge_->lock_handler()->GetAuthType(user_email_); - if (existing_auth_type == ScreenlockBridge::LockHandler::ONLINE_SIGN_IN) + const proximity_auth::ScreenlockBridge::LockHandler::AuthType + existing_auth_type = + screenlock_bridge_->lock_handler()->GetAuthType(user_email_); + if (existing_auth_type == + proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN) return; - if (existing_auth_type != ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) { + if (existing_auth_type != + proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) { screenlock_bridge_->lock_handler()->SetAuthType( user_email_, - ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, base::string16()); } @@ -280,15 +284,17 @@ if (hardlock_ui_shown_) return; - ScreenlockBridge::UserPodCustomIconOptions icon_options; + proximity_auth::ScreenlockBridge::UserPodCustomIconOptions icon_options; if (hardlock_state_ == LOGIN_FAILED) { - icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED); + icon_options.SetIcon( + proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED); } else if (hardlock_state_ == PAIRING_CHANGED || hardlock_state_ == PAIRING_ADDED) { - icon_options.SetIcon( - ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED); + icon_options.SetIcon(proximity_auth::ScreenlockBridge:: + USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED); } else { - icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_HARDLOCKED); + icon_options.SetIcon( + proximity_auth::ScreenlockBridge::USER_POD_CUSTOM_ICON_HARDLOCKED); } base::string16 device_name = GetDeviceName(); @@ -317,7 +323,7 @@ } void EasyUnlockScreenlockStateHandler::UpdateTooltipOptions( - ScreenlockBridge::UserPodCustomIconOptions* icon_options) { + proximity_auth::ScreenlockBridge::UserPodCustomIconOptions* icon_options) { size_t resource_id = 0; base::string16 device_name; if (is_trial_run_ && state_ == STATE_AUTHENTICATED) { @@ -360,23 +366,26 @@ return; // Do not override online signin. - const ScreenlockBridge::LockHandler::AuthType existing_auth_type = - screenlock_bridge_->lock_handler()->GetAuthType(user_email_); - DCHECK_NE(ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, existing_auth_type); + const proximity_auth::ScreenlockBridge::LockHandler::AuthType + existing_auth_type = + screenlock_bridge_->lock_handler()->GetAuthType(user_email_); + DCHECK_NE(proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, + existing_auth_type); if (state_ == STATE_AUTHENTICATED) { - if (existing_auth_type != ScreenlockBridge::LockHandler::USER_CLICK) { + if (existing_auth_type != + proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK) { screenlock_bridge_->lock_handler()->SetAuthType( user_email_, - ScreenlockBridge::LockHandler::USER_CLICK, + proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, l10n_util::GetStringUTF16( IDS_EASY_UNLOCK_SCREENLOCK_USER_POD_AUTH_VALUE)); } } else if (existing_auth_type != - ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) { + proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD) { screenlock_bridge_->lock_handler()->SetAuthType( user_email_, - ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, base::string16()); } }
diff --git a/chrome/browser/signin/easy_unlock_screenlock_state_handler.h b/chrome/browser/signin/easy_unlock_screenlock_state_handler.h index d6f722b..096839a9 100644 --- a/chrome/browser/signin/easy_unlock_screenlock_state_handler.h +++ b/chrome/browser/signin/easy_unlock_screenlock_state_handler.h
@@ -8,13 +8,14 @@ #include <string> #include "base/strings/string16.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "components/proximity_auth/screenlock_bridge.h" class PrefService; // Profile specific class responsible for updating screenlock UI for the user // associated with the profile when their Easy Unlock state changes. -class EasyUnlockScreenlockStateHandler : public ScreenlockBridge::Observer { +class EasyUnlockScreenlockStateHandler + : public proximity_auth::ScreenlockBridge::Observer { public: // Available Easy Unlock states. enum State { @@ -71,9 +72,10 @@ // |initial_hardlock_state|: The initial hardlock state. // |screenlock_bridge|: The screenlock bridge used to update the screen lock // state. - EasyUnlockScreenlockStateHandler(const std::string& user_email, - HardlockState initial_hardlock_state, - ScreenlockBridge* screenlock_bridge); + EasyUnlockScreenlockStateHandler( + const std::string& user_email, + HardlockState initial_hardlock_state, + proximity_auth::ScreenlockBridge* screenlock_bridge); ~EasyUnlockScreenlockStateHandler() override; // Returns true if handler is not in INACTIVE state. @@ -104,11 +106,12 @@ State state() const { return state_; } private: - // ScreenlockBridge::Observer: - void OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; + // proximity_auth::ScreenlockBridge::Observer: + void OnScreenDidLock(proximity_auth::ScreenlockBridge::LockHandler::ScreenType + screen_type) override; void OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) + override; void OnFocusedUserChanged(const std::string& user_id) override; // Forces refresh of the Easy Unlock screenlock UI. @@ -118,7 +121,7 @@ // Updates icon's tooltip options. void UpdateTooltipOptions( - ScreenlockBridge::UserPodCustomIconOptions* icon_options); + proximity_auth::ScreenlockBridge::UserPodCustomIconOptions* icon_options); // Gets the name to be used for the device. The name depends on the device // type (example values: Chromebook and Chromebox). @@ -129,7 +132,7 @@ State state_; std::string user_email_; - ScreenlockBridge* screenlock_bridge_; + proximity_auth::ScreenlockBridge* screenlock_bridge_; // State of hardlock. HardlockState hardlock_state_;
diff --git a/chrome/browser/signin/easy_unlock_screenlock_state_handler_unittest.cc b/chrome/browser/signin/easy_unlock_screenlock_state_handler_unittest.cc index 75aa1b29..84b3901 100644 --- a/chrome/browser/signin/easy_unlock_screenlock_state_handler_unittest.cc +++ b/chrome/browser/signin/easy_unlock_screenlock_state_handler_unittest.cc
@@ -13,15 +13,16 @@ #include "base/test/histogram_tester.h" #include "chrome/browser/signin/easy_unlock_metrics.h" #include "chrome/browser/signin/easy_unlock_service.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/grit/generated_resources.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" namespace { // Icons used by EasyUnlockScreenlockStateHandler. The icon id values are the -// same as the ones set by ScreenlockBridge. +// same as the ones set by proximity_auth::ScreenlockBridge. const char kLockedIconId[] = "locked"; const char kLockedToBeActivatedIconId[] = "locked-to-be-activated"; const char kUnlockedIconId[] = "unlocked"; @@ -39,7 +40,7 @@ } // Fake lock handler to be used in these tests. -class TestLockHandler : public ScreenlockBridge::LockHandler { +class TestLockHandler : public proximity_auth::ScreenlockBridge::LockHandler { public: explicit TestLockHandler(const std::string& user_email) : user_email_(user_email), @@ -48,14 +49,15 @@ } ~TestLockHandler() override {} - // ScreenlockBridge::LockHandler implementation: + // proximity_auth::ScreenlockBridge::LockHandler implementation: void ShowBannerMessage(const base::string16& message) override { ASSERT_FALSE(true) << "Should not be reached."; } void ShowUserPodCustomIcon( const std::string& user_email, - const ScreenlockBridge::UserPodCustomIconOptions& icon) override { + const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions& icon) + override { ASSERT_EQ(user_email_, user_email); ++show_icon_count_; last_custom_icon_ = icon.ToDictionaryValue().Pass(); @@ -207,7 +209,8 @@ void SetUp() override { // Create and inject fake lock handler to the screenlock bridge. lock_handler_.reset(new TestLockHandler(user_email_)); - ScreenlockBridge* screenlock_bridge = ScreenlockBridge::Get(); + proximity_auth::ScreenlockBridge* screenlock_bridge = + GetScreenlockBridgeInstance(); screenlock_bridge->SetLockHandler(lock_handler_.get()); // Create the screenlock state handler object that will be tested. @@ -218,7 +221,7 @@ } void TearDown() override { - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); lock_handler_.reset(); state_handler_.reset(); } @@ -230,8 +233,8 @@ // The user associated with |state_handler_|. const std::string user_email_; - // Faked lock handler given to ScreenlockBridge during the test. Abstracts - // the screen lock UI. + // Faked lock handler given to proximity_auth::ScreenlockBridge during the + // test. Abstracts the screen lock UI. scoped_ptr<TestLockHandler> lock_handler_; }; @@ -241,7 +244,7 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); @@ -261,7 +264,7 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); @@ -287,7 +290,7 @@ EXPECT_TRUE(state_handler_->IsActive()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); @@ -306,14 +309,14 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::USER_HARDLOCK); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); @@ -334,14 +337,14 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::NO_PAIRING); EXPECT_FALSE(lock_handler_->HasCustomIcon()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); } @@ -361,7 +364,7 @@ EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()) << "State: " << states[i]; - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)) << "State: " << states[i]; @@ -387,7 +390,7 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); @@ -396,7 +399,7 @@ state_handler_->SetTrialRun(); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); @@ -409,7 +412,7 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); @@ -417,7 +420,7 @@ state_handler_.reset(); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); ASSERT_FALSE(lock_handler_->HasCustomIcon()); @@ -428,17 +431,17 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(user_email_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); - ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); + GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_.get()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); } @@ -448,21 +451,21 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(user_email_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); state_handler_->ChangeState( EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING); - ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); + GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_.get()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kSpinnerIconId, lock_handler_->GetCustomIconId()); @@ -492,9 +495,9 @@ << "State: " << states[i]; } - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(user_email_)); - ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); + GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_.get()); for (size_t i = 0; i < states.size(); ++i) { state_handler_->ChangeState(states[i]); @@ -618,14 +621,14 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::USER_HARDLOCK); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kHardlockedIconId, lock_handler_->GetCustomIconId()); @@ -639,7 +642,7 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); } @@ -655,10 +658,10 @@ state_handler_->SetHardlockState( EasyUnlockScreenlockStateHandler::NO_HARDLOCK); - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(user_email_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); - ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); + GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_.get()); state_handler_->ChangeState( EasyUnlockScreenlockStateHandler::STATE_NO_PHONE); @@ -666,14 +669,14 @@ EXPECT_EQ(2u, lock_handler_->GetAndResetShowIconCount()); EXPECT_TRUE(lock_handler_->HasCustomIcon()); - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(user_email_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); - ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); + GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_.get()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_TRUE(lock_handler_->HasCustomIcon()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); EXPECT_EQ(kLockedIconId, lock_handler_->GetCustomIconId()); @@ -681,7 +684,7 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); EXPECT_TRUE(lock_handler_->HasCustomIcon()); - EXPECT_EQ(ScreenlockBridge::LockHandler::USER_CLICK, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::USER_CLICK, lock_handler_->GetAuthType(user_email_)); EXPECT_TRUE(lock_handler_->CustomIconHardlocksOnClick()); } @@ -693,13 +696,13 @@ EasyUnlockScreenlockStateHandler::USER_HARDLOCK); EXPECT_EQ(2u, lock_handler_->GetAndResetShowIconCount()); - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); lock_handler_.reset(new TestLockHandler(user_email_)); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); - ScreenlockBridge::Get()->SetLockHandler(lock_handler_.get()); + GetScreenlockBridgeInstance()->SetLockHandler(lock_handler_.get()); EXPECT_EQ(1u, lock_handler_->GetAndResetShowIconCount()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); ASSERT_TRUE(lock_handler_->HasCustomIcon()); EXPECT_EQ(kHardlockedIconId, lock_handler_->GetCustomIconId()); @@ -708,14 +711,15 @@ EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED); EXPECT_EQ(0u, lock_handler_->GetAndResetShowIconCount()); EXPECT_TRUE(lock_handler_->HasCustomIcon()); - EXPECT_EQ(ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, lock_handler_->GetAuthType(user_email_)); } TEST_F(EasyUnlockScreenlockStateHandlerTest, NoOverrideOnlineSignin) { - lock_handler_->SetAuthType(user_email_, - ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, - base::string16()); + lock_handler_->SetAuthType( + user_email_, + proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, + base::string16()); std::vector<EasyUnlockScreenlockStateHandler::State> states; states.push_back(EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH); @@ -733,7 +737,7 @@ for (size_t i = 0; i < states.size(); ++i) { state_handler_->ChangeState(states[i]); - EXPECT_EQ(ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, lock_handler_->GetAuthType(user_email_)); EXPECT_FALSE(lock_handler_->HasCustomIcon()); } @@ -748,7 +752,7 @@ for (size_t i = 0; i < hardlock_states.size(); ++i) { state_handler_->SetHardlockState(hardlock_states[i]); - EXPECT_EQ(ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, + EXPECT_EQ(proximity_auth::ScreenlockBridge::LockHandler::ONLINE_SIGN_IN, lock_handler_->GetAuthType(user_email_)); EXPECT_FALSE(lock_handler_->HasCustomIcon()); }
diff --git a/chrome/browser/signin/easy_unlock_service.cc b/chrome/browser/signin/easy_unlock_service.cc index 9af5d0c..391c8a8 100644 --- a/chrome/browser/signin/easy_unlock_service.cc +++ b/chrome/browser/signin/easy_unlock_service.cc
@@ -22,12 +22,13 @@ #include "chrome/browser/signin/easy_unlock_app_manager.h" #include "chrome/browser/signin/easy_unlock_service_factory.h" #include "chrome/browser/signin/easy_unlock_service_observer.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/proximity_auth/ble/proximity_auth_ble_system.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/proximity_auth/switches.h" #include "components/user_manager/user.h" #include "device/bluetooth/bluetooth_adapter.h" @@ -261,18 +262,10 @@ // static void EasyUnlockService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kEasyUnlockAllowed, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kEasyUnlockEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kEasyUnlockPairing, - new base::DictionaryValue(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kEasyUnlockAllowed, true); + registry->RegisterBooleanPref(prefs::kEasyUnlockEnabled, false); + registry->RegisterDictionaryPref(prefs::kEasyUnlockPairing, + new base::DictionaryValue()); registry->RegisterBooleanPref( prefs::kEasyUnlockProximityRequired, false, @@ -454,9 +447,7 @@ return NULL; if (!screenlock_state_handler_) { screenlock_state_handler_.reset(new EasyUnlockScreenlockStateHandler( - GetUserEmail(), - GetHardlockState(), - ScreenlockBridge::Get())); + GetUserEmail(), GetHardlockState(), GetScreenlockBridgeInstance())); } return screenlock_state_handler_.get(); }
diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc index a7f8ea9..38cb6096 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.cc +++ b/chrome/browser/signin/easy_unlock_service_regular.cc
@@ -14,7 +14,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/common/chrome_version_info.h" #include "chrome/common/extensions/api/easy_unlock_private.h" @@ -24,6 +24,7 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/proximity_auth/cryptauth/cryptauth_access_token_fetcher.h" #include "components/proximity_auth/cryptauth/cryptauth_client_impl.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/proximity_auth/switches.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_manager.h" @@ -92,7 +93,12 @@ } std::string EasyUnlockServiceRegular::GetUserEmail() const { - return ScreenlockBridge::GetAuthenticatedUserEmail(profile()); + const SigninManagerBase* signin_manager = + SigninManagerFactory::GetForProfileIfExists(profile()); + // |profile| has to be a signed-in profile with SigninManager already + // created. Otherwise, just crash to collect stack. + DCHECK(signin_manager); + return signin_manager->GetAuthenticatedUsername(); } void EasyUnlockServiceRegular::LaunchSetup() { @@ -298,7 +304,7 @@ } void EasyUnlockServiceRegular::InitializeInternal() { - ScreenlockBridge::Get()->AddObserver(this); + GetScreenlockBridgeInstance()->AddObserver(this); registrar_.Init(profile()->GetPrefs()); registrar_.Add( prefs::kEasyUnlockAllowed, @@ -317,7 +323,7 @@ turn_off_flow_status_ = EasyUnlockService::IDLE; registrar_.RemoveAll(); - ScreenlockBridge::Get()->RemoveObserver(this); + GetScreenlockBridgeInstance()->RemoveObserver(this); } bool EasyUnlockServiceRegular::IsAllowedInternal() const { @@ -354,16 +360,16 @@ } void EasyUnlockServiceRegular::OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { will_unlock_using_easy_unlock_ = false; lock_screen_last_shown_timestamp_ = base::TimeTicks::Now(); } void EasyUnlockServiceRegular::OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { // Notifications of signin screen unlock events can also reach this code path; // disregard them. - if (screen_type != ScreenlockBridge::LockHandler::LOCK_SCREEN) + if (screen_type != proximity_auth::ScreenlockBridge::LockHandler::LOCK_SCREEN) return; // Only record metrics for users who have enabled the feature.
diff --git a/chrome/browser/signin/easy_unlock_service_regular.h b/chrome/browser/signin/easy_unlock_service_regular.h index 324d234..1f4ff9d 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.h +++ b/chrome/browser/signin/easy_unlock_service_regular.h
@@ -13,7 +13,7 @@ #include "base/prefs/pref_change_registrar.h" #include "base/time/time.h" #include "chrome/browser/signin/easy_unlock_service.h" -#include "chrome/browser/signin/screenlock_bridge.h" +#include "components/proximity_auth/screenlock_bridge.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/easy_unlock/short_lived_user_context.h" @@ -38,8 +38,9 @@ // EasyUnlockService instance that should be used for regular, non-signin // profiles. -class EasyUnlockServiceRegular : public EasyUnlockService, - public ScreenlockBridge::Observer { +class EasyUnlockServiceRegular + : public EasyUnlockService, + public proximity_auth::ScreenlockBridge::Observer { public: explicit EasyUnlockServiceRegular(Profile* profile); ~EasyUnlockServiceRegular() override; @@ -70,11 +71,12 @@ void OnWillFinalizeUnlock(bool success) override; void OnSuspendDone() override; - // ScreenlockBridge::Observer implementation: - void OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; + // proximity_auth::ScreenlockBridge::Observer implementation: + void OnScreenDidLock(proximity_auth::ScreenlockBridge::LockHandler::ScreenType + screen_type) override; void OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) + override; void OnFocusedUserChanged(const std::string& user_id) override;
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc index 5c068cd3..ad3536f 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/login/session/user_session_manager.h" #include "chrome/browser/signin/easy_unlock_app_manager.h" #include "chrome/browser/signin/easy_unlock_metrics.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chromeos/login/auth/user_context.h" #include "chromeos/tpm/tpm_token_loader.h" @@ -222,7 +223,8 @@ service_active_ = true; chromeos::LoginState::Get()->AddObserver(this); - ScreenlockBridge* screenlock_bridge = ScreenlockBridge::Get(); + proximity_auth::ScreenlockBridge* screenlock_bridge = + GetScreenlockBridgeInstance(); screenlock_bridge->AddObserver(this); if (!screenlock_bridge->focused_user_id().empty()) OnFocusedUserChanged(screenlock_bridge->focused_user_id()); @@ -234,7 +236,7 @@ service_active_ = false; weak_ptr_factory_.InvalidateWeakPtrs(); - ScreenlockBridge::Get()->RemoveObserver(this); + GetScreenlockBridgeInstance()->RemoveObserver(this); chromeos::LoginState::Get()->RemoveObserver(this); STLDeleteContainerPairSecondPointers(user_data_.begin(), user_data_.end()); user_data_.clear(); @@ -257,10 +259,11 @@ } void EasyUnlockServiceSignin::OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { // In production code, the screen type should always be the signin screen; but // in tests, the screen type might be different. - if (screen_type != ScreenlockBridge::LockHandler::SIGNIN_SCREEN) + if (screen_type != + proximity_auth::ScreenlockBridge::LockHandler::SIGNIN_SCREEN) return; // Update initial UI is when the account picker on login screen is ready. @@ -269,10 +272,11 @@ } void EasyUnlockServiceSignin::OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) { + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { // In production code, the screen type should always be the signin screen; but // in tests, the screen type might be different. - if (screen_type != ScreenlockBridge::LockHandler::SIGNIN_SCREEN) + if (screen_type != + proximity_auth::ScreenlockBridge::LockHandler::SIGNIN_SCREEN) return; DisableAppWithoutResettingScreenlockState();
diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h index 94b3cef9..634de98d5 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h
@@ -15,13 +15,14 @@ #include "base/values.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h" #include "chrome/browser/signin/easy_unlock_service.h" -#include "chrome/browser/signin/screenlock_bridge.h" #include "chromeos/login/login_state.h" +#include "components/proximity_auth/screenlock_bridge.h" // EasyUnlockService instance that should be used for signin profile. -class EasyUnlockServiceSignin : public EasyUnlockService, - public ScreenlockBridge::Observer, - public chromeos::LoginState::Observer { +class EasyUnlockServiceSignin + : public EasyUnlockService, + public proximity_auth::ScreenlockBridge::Observer, + public chromeos::LoginState::Observer { public: explicit EasyUnlockServiceSignin(Profile* profile); ~EasyUnlockServiceSignin() override; @@ -85,11 +86,12 @@ void OnWillFinalizeUnlock(bool success) override; void OnSuspendDone() override; - // ScreenlockBridge::Observer implementation: - void OnScreenDidLock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; + // proximity_auth::ScreenlockBridge::Observer implementation: + void OnScreenDidLock(proximity_auth::ScreenlockBridge::LockHandler::ScreenType + screen_type) override; void OnScreenDidUnlock( - ScreenlockBridge::LockHandler::ScreenType screen_type) override; + proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) + override; void OnFocusedUserChanged(const std::string& user_id) override; // chromeos::LoginState::Observer implementation:
diff --git a/chrome/browser/signin/fake_account_reconcilor.cc b/chrome/browser/signin/fake_account_reconcilor.cc deleted file mode 100644 index ea1573ef..0000000 --- a/chrome/browser/signin/fake_account_reconcilor.cc +++ /dev/null
@@ -1,38 +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 "chrome/browser/signin/fake_account_reconcilor.h" - -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/chrome_signin_client_factory.h" -#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" -#include "chrome/browser/signin/signin_manager_factory.h" - -FakeAccountReconcilor::FakeAccountReconcilor( - ProfileOAuth2TokenService* token_service, - SigninManagerBase* signin_manager, - SigninClient* client, - GaiaCookieManagerService* cookie_manager_service) : - AccountReconcilor( - token_service, signin_manager, client, cookie_manager_service) {} - - -// static -KeyedService* FakeAccountReconcilor::Build(content::BrowserContext* context) { - Profile* profile = Profile::FromBrowserContext(context); - AccountReconcilor* reconcilor = new FakeAccountReconcilor( - ProfileOAuth2TokenServiceFactory::GetForProfile(profile), - SigninManagerFactory::GetForProfile(profile), - ChromeSigninClientFactory::GetForProfile(profile), - GaiaCookieManagerServiceFactory::GetForProfile(profile)); - reconcilor->Initialize(true /* start_reconcile_if_tokens_available */); - return reconcilor; -} - -void FakeAccountReconcilor::GetAccountsFromCookie( - GetAccountsFromCookieCallback callback) { - std::vector<std::pair<std::string, bool> > gaia_accounts; - callback.Run(GoogleServiceAuthError::AuthErrorNone(), gaia_accounts); -}
diff --git a/chrome/browser/signin/fake_account_reconcilor.h b/chrome/browser/signin/fake_account_reconcilor.h deleted file mode 100644 index 405fda2..0000000 --- a/chrome/browser/signin/fake_account_reconcilor.h +++ /dev/null
@@ -1,31 +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 CHROME_BROWSER_SIGNIN_FAKE_ACCOUNT_RECONCILOR_H_ -#define CHROME_BROWSER_SIGNIN_FAKE_ACCOUNT_RECONCILOR_H_ - -#include "components/signin/core/browser/account_reconcilor.h" - -namespace content { -class BrowserContext; -} - -class FakeAccountReconcilor : public AccountReconcilor { - public: - FakeAccountReconcilor(ProfileOAuth2TokenService* token_service, - SigninManagerBase* signin_manager, - SigninClient* client, - GaiaCookieManagerService* cookie_manager_service); - - // Helper function to be used with KeyedService::SetTestingFactory(). - static KeyedService* Build(content::BrowserContext* context); - - protected: - // Override this method to perform no network call, instead the callback - // is called immediately - void GetAccountsFromCookie(GetAccountsFromCookieCallback callback) override; - - DISALLOW_COPY_AND_ASSIGN(FakeAccountReconcilor); -}; - -#endif // CHROME_BROWSER_SIGNIN_FAKE_ACCOUNT_RECONCILOR_H_
diff --git a/chrome/browser/signin/fake_gaia_cookie_manager_service.cc b/chrome/browser/signin/fake_gaia_cookie_manager_service.cc new file mode 100644 index 0000000..430f8abb --- /dev/null +++ b/chrome/browser/signin/fake_gaia_cookie_manager_service.cc
@@ -0,0 +1,112 @@ +// 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/signin/fake_gaia_cookie_manager_service.h" + +#include "base/strings/stringprintf.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/chrome_signin_client_factory.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "components/signin/core/browser/profile_oauth2_token_service.h" +#include "google_apis/gaia/gaia_constants.h" +#include "google_apis/gaia/gaia_urls.h" + +FakeGaiaCookieManagerService::FakeGaiaCookieManagerService( + OAuth2TokenService* token_service, + const std::string& source, + SigninClient* client) : + GaiaCookieManagerService(token_service, source, client), + url_fetcher_factory_(NULL) {} + +void FakeGaiaCookieManagerService::Init( + net::FakeURLFetcherFactory* url_fetcher_factory) { + url_fetcher_factory_ = url_fetcher_factory; +} + +void FakeGaiaCookieManagerService::SetListAccountsResponseHttpNotFound() { + DCHECK(url_fetcher_factory_); + url_fetcher_factory_->SetFakeResponse( + GaiaUrls::GetInstance()->ListAccountsURLWithSource( + GaiaConstants::kChromeSource), + "", + net::HTTP_NOT_FOUND, + net::URLRequestStatus::SUCCESS); +} + +void FakeGaiaCookieManagerService::SetListAccountsResponseNoAccounts() { + DCHECK(url_fetcher_factory_); + url_fetcher_factory_->SetFakeResponse( + GaiaUrls::GetInstance()->ListAccountsURLWithSource( + GaiaConstants::kChromeSource), + "[\"f\", []]", + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); +} + +void FakeGaiaCookieManagerService::SetListAccountsResponseOneAccount( + const char* account) { + DCHECK(url_fetcher_factory_); + url_fetcher_factory_->SetFakeResponse( + GaiaUrls::GetInstance()->ListAccountsURLWithSource( + GaiaConstants::kChromeSource), + base::StringPrintf( + "[\"f\", [[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, 1]]]", + account), + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); +} + +void FakeGaiaCookieManagerService::SetListAccountsResponseOneAccountWithExpiry( + const char* account, bool expired) { + DCHECK(url_fetcher_factory_); + url_fetcher_factory_->SetFakeResponse( + GaiaUrls::GetInstance()->ListAccountsURLWithSource( + GaiaConstants::kChromeSource), + base::StringPrintf( + "[\"f\", [[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, %d]]]", + account, expired ? 0 : 1), + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); +} + +void FakeGaiaCookieManagerService::SetListAccountsResponseTwoAccounts( + const char* account1, const char* account2) { + DCHECK(url_fetcher_factory_); + url_fetcher_factory_->SetFakeResponse( + GaiaUrls::GetInstance()->ListAccountsURLWithSource( + GaiaConstants::kChromeSource), + base::StringPrintf( + "[\"f\", [[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, 1], " + "[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, 1]]]", + account1, account2), + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); +} + +void FakeGaiaCookieManagerService::SetListAccountsResponseTwoAccountsWithExpiry( + const char* account1, bool account1_expired, + const char* account2, bool account2_expired) { + DCHECK(url_fetcher_factory_); + url_fetcher_factory_->SetFakeResponse( + GaiaUrls::GetInstance()->ListAccountsURLWithSource( + GaiaConstants::kChromeSource), + base::StringPrintf( + "[\"f\", [[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, %d], " + "[\"b\", 0, \"n\", \"%s\", \"p\", 0, 0, 0, 0, %d]]]", + account1, account1_expired ? 0 : 1, + account2, account2_expired ? 0 : 1), + net::HTTP_OK, + net::URLRequestStatus::SUCCESS); +} + +// static +KeyedService* FakeGaiaCookieManagerService::Build( + content::BrowserContext* context) { + Profile* profile = Profile::FromBrowserContext(context); + FakeGaiaCookieManagerService* service = new FakeGaiaCookieManagerService( + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + GaiaConstants::kChromeSource, + ChromeSigninClientFactory::GetForProfile(profile)); + return service; +}
diff --git a/chrome/browser/signin/fake_gaia_cookie_manager_service.h b/chrome/browser/signin/fake_gaia_cookie_manager_service.h new file mode 100644 index 0000000..b03750c9 --- /dev/null +++ b/chrome/browser/signin/fake_gaia_cookie_manager_service.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 CHROME_BROWSER_SIGNIN_FAKE_GAIA_COOKIE_MANAGER_SERVICE_H_ +#define CHROME_BROWSER_SIGNIN_FAKE_GAIA_COOKIE_MANAGER_SERVICE_H_ + +#include "components/signin/core/browser/gaia_cookie_manager_service.h" + +#include "net/url_request/test_url_fetcher_factory.h" + +namespace content { +class BrowserContext; +} + +class FakeGaiaCookieManagerService : public GaiaCookieManagerService { + public: + FakeGaiaCookieManagerService(OAuth2TokenService* token_service, + const std::string& source, + SigninClient* client); + + void Init(net::FakeURLFetcherFactory* url_fetcher_factory); + + void SetListAccountsResponseHttpNotFound(); + void SetListAccountsResponseNoAccounts(); + void SetListAccountsResponseOneAccount(const char* account); + void SetListAccountsResponseOneAccountWithExpiry( + const char* account, bool expired); + void SetListAccountsResponseTwoAccounts(const char* account1, + const char* account2); + void SetListAccountsResponseTwoAccountsWithExpiry( + const char* account1, bool account1_expired, + const char* account2, bool account2_expired); + + // Helper function to be used with KeyedService::SetTestingFactory(). + static KeyedService* Build(content::BrowserContext* context); + + private: + // Provide a fake response for calls to /ListAccounts. + net::FakeURLFetcherFactory* url_fetcher_factory_; + + DISALLOW_COPY_AND_ASSIGN(FakeGaiaCookieManagerService); +}; + +#endif // CHROME_BROWSER_SIGNIN_FAKE_GAIA_COOKIE_MANAGER_SERVICE_H_
diff --git a/chrome/browser/signin/local_auth.cc b/chrome/browser/signin/local_auth.cc index 9b20c322..5c6ea03 100644 --- a/chrome/browser/signin/local_auth.cc +++ b/chrome/browser/signin/local_auth.cc
@@ -175,10 +175,8 @@ void LocalAuth::RegisterLocalAuthPrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kGoogleServicesPasswordHash, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kGoogleServicesPasswordHash, + std::string()); } void LocalAuth::SetLocalAuthCredentialsWithEncoding(size_t info_index,
diff --git a/chrome/browser/signin/local_auth_unittest.cc b/chrome/browser/signin/local_auth_unittest.cc index 14aea881..a675290 100644 --- a/chrome/browser/signin/local_auth_unittest.cc +++ b/chrome/browser/signin/local_auth_unittest.cc
@@ -12,10 +12,15 @@ #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/os_crypt/os_crypt.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" -TEST(LocalAuthTest, SetAndCheckCredentials) { +class LocalAuthTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(LocalAuthTest, SetAndCheckCredentials) { TestingProfileManager testing_profile_manager( TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(testing_profile_manager.SetUp()); @@ -55,8 +60,7 @@ EXPECT_NE(passhash, cache.GetLocalAuthCredentialsOfProfileAtIndex(0)); } - -TEST(LocalAuthTest, SetUpgradeAndCheckCredentials) { +TEST_F(LocalAuthTest, SetUpgradeAndCheckCredentials) { TestingProfileManager testing_profile_manager( TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(testing_profile_manager.SetUp()); @@ -92,7 +96,7 @@ } // Test truncation where each byte is left whole. -TEST(LocalAuthTest, TruncateStringEvenly) { +TEST_F(LocalAuthTest, TruncateStringEvenly) { std::string two_chars = "A6"; std::string three_chars = "A6C"; EXPECT_EQ(two_chars, LocalAuth::TruncateStringByBits(two_chars, 16)); @@ -103,7 +107,7 @@ } // Test truncation that affects the results within a byte. -TEST(LocalAuthTest, TruncateStringUnevenly) { +TEST_F(LocalAuthTest, TruncateStringUnevenly) { std::string two_chars = "Az"; std::string three_chars = "AzC"; // 'z' = 0x7A, ':' = 0x3A.
diff --git a/chrome/browser/signin/proximity_auth_facade.cc b/chrome/browser/signin/proximity_auth_facade.cc new file mode 100644 index 0000000..bef1143 --- /dev/null +++ b/chrome/browser/signin/proximity_auth_facade.cc
@@ -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. + +#include "chrome/browser/signin/proximity_auth_facade.h" + +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_window.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "components/proximity_auth/proximity_auth_client.h" +#include "components/proximity_auth/screenlock_bridge.h" +#include "components/signin/core/browser/signin_manager_base.h" + +namespace { + +// A Chrome-specific implementation of the ProximityAuthClient. +class ChromeProximityAuthClient : public proximity_auth::ProximityAuthClient { + public: + ChromeProximityAuthClient() {} + ~ChromeProximityAuthClient() override {} + + // proximity_auth::ProximityAuthClient implementation: + std::string GetAuthenticatedUsername( + content::BrowserContext* browser_context) const override; + void Lock(content::BrowserContext* browser_context) override; + + private: + DISALLOW_COPY_AND_ASSIGN(ChromeProximityAuthClient); +}; + +std::string ChromeProximityAuthClient::GetAuthenticatedUsername( + content::BrowserContext* browser_context) const { + Profile* profile = Profile::FromBrowserContext(browser_context); + const SigninManagerBase* signin_manager = + SigninManagerFactory::GetForProfileIfExists(profile); + // |profile| has to be a signed-in profile with SigninManager already + // created. Otherwise, just crash to collect stack. + DCHECK(signin_manager); + return signin_manager->GetAuthenticatedUsername(); +} + +void ChromeProximityAuthClient::Lock(content::BrowserContext* browser_context) { + profiles::LockProfile(Profile::FromBrowserContext(browser_context)); +} + +// A facade class that is the glue required to initialize and manage the +// lifecycle of various objects of the Proximity Auth component. +class ProximityAuthFacade { + public: + proximity_auth::ScreenlockBridge* GetScreenlockBridge() { + return &screenlock_bridge_; + } + + private: + friend struct base::DefaultLazyInstanceTraits<ProximityAuthFacade>; + friend struct base::DefaultDeleter<ProximityAuthFacade>; + + ProximityAuthFacade() : screenlock_bridge_(&proximity_auth_client_) {} + ~ProximityAuthFacade() {} + + ChromeProximityAuthClient proximity_auth_client_; + proximity_auth::ScreenlockBridge screenlock_bridge_; + + DISALLOW_COPY_AND_ASSIGN(ProximityAuthFacade); +}; + +base::LazyInstance<ProximityAuthFacade> g_proximity_auth_facade_instance = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +proximity_auth::ScreenlockBridge* GetScreenlockBridgeInstance() { + return g_proximity_auth_facade_instance.Pointer()->GetScreenlockBridge(); +}
diff --git a/chrome/browser/signin/proximity_auth_facade.h b/chrome/browser/signin/proximity_auth_facade.h new file mode 100644 index 0000000..9a99ed1 --- /dev/null +++ b/chrome/browser/signin/proximity_auth_facade.h
@@ -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. + +#ifndef CHROME_BROWSER_SIGNIN_PROXIMITY_AUTH_FACADE_H_ +#define CHROME_BROWSER_SIGNIN_PROXIMITY_AUTH_FACADE_H_ + +namespace proximity_auth { +class ScreenlockBridge; +} + +// Returns the global proximity_auth::ScreenlockBridge instance. +proximity_auth::ScreenlockBridge* GetScreenlockBridgeInstance(); + +#endif // CHROME_BROWSER_SIGNIN_PROXIMITY_AUTH_FACADE_H_
diff --git a/chrome/browser/signin/screenlock_bridge.cc b/chrome/browser/signin/screenlock_bridge.cc deleted file mode 100644 index c8db7a3..0000000 --- a/chrome/browser/signin/screenlock_bridge.cc +++ /dev/null
@@ -1,190 +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 "chrome/browser/signin/screenlock_bridge.h" - -#include "base/logging.h" -#include "base/strings/string16.h" -#include "chrome/browser/profiles/profile_window.h" -#include "chrome/browser/signin/signin_manager_factory.h" -#include "components/signin/core/browser/signin_manager.h" - -#if defined(OS_CHROMEOS) -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/session_manager_client.h" -#endif - -namespace { - -base::LazyInstance<ScreenlockBridge> g_screenlock_bridge_bridge_instance = - LAZY_INSTANCE_INITIALIZER; - -// Ids for the icons that are supported by lock screen and signin screen -// account picker as user pod custom icons. -// The id's should be kept in sync with values used by user_pod_row.js. -const char kLockedUserPodCustomIconId[] = "locked"; -const char kLockedToBeActivatedUserPodCustomIconId[] = "locked-to-be-activated"; -const char kLockedWithProximityHintUserPodCustomIconId[] = - "locked-with-proximity-hint"; -const char kUnlockedUserPodCustomIconId[] = "unlocked"; -const char kHardlockedUserPodCustomIconId[] = "hardlocked"; -const char kSpinnerUserPodCustomIconId[] = "spinner"; - -// Given the user pod icon, returns its id as used by the user pod UI code. -std::string GetIdForIcon(ScreenlockBridge::UserPodCustomIcon icon) { - switch (icon) { - case ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED: - return kLockedUserPodCustomIconId; - case ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED: - return kLockedToBeActivatedUserPodCustomIconId; - case ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED_WITH_PROXIMITY_HINT: - return kLockedWithProximityHintUserPodCustomIconId; - case ScreenlockBridge::USER_POD_CUSTOM_ICON_UNLOCKED: - return kUnlockedUserPodCustomIconId; - case ScreenlockBridge::USER_POD_CUSTOM_ICON_HARDLOCKED: - return kHardlockedUserPodCustomIconId; - case ScreenlockBridge::USER_POD_CUSTOM_ICON_SPINNER: - return kSpinnerUserPodCustomIconId; - default: - return ""; - } -} - -} // namespace - -// static -ScreenlockBridge* ScreenlockBridge::Get() { - return g_screenlock_bridge_bridge_instance.Pointer(); -} - -ScreenlockBridge::UserPodCustomIconOptions::UserPodCustomIconOptions() - : autoshow_tooltip_(false), - hardlock_on_click_(false), - is_trial_run_(false) { -} - -ScreenlockBridge::UserPodCustomIconOptions::~UserPodCustomIconOptions() {} - -scoped_ptr<base::DictionaryValue> -ScreenlockBridge::UserPodCustomIconOptions::ToDictionaryValue() const { - scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); - std::string icon_id = GetIdForIcon(icon_); - result->SetString("id", icon_id); - - if (!tooltip_.empty()) { - base::DictionaryValue* tooltip_options = new base::DictionaryValue(); - tooltip_options->SetString("text", tooltip_); - tooltip_options->SetBoolean("autoshow", autoshow_tooltip_); - result->Set("tooltip", tooltip_options); - } - - if (!aria_label_.empty()) - result->SetString("ariaLabel", aria_label_); - - if (hardlock_on_click_) - result->SetBoolean("hardlockOnClick", true); - - if (is_trial_run_) - result->SetBoolean("isTrialRun", true); - - return result.Pass(); -} - -void ScreenlockBridge::UserPodCustomIconOptions::SetIcon( - ScreenlockBridge::UserPodCustomIcon icon) { - icon_ = icon; -} - -void ScreenlockBridge::UserPodCustomIconOptions::SetTooltip( - const base::string16& tooltip, - bool autoshow) { - tooltip_ = tooltip; - autoshow_tooltip_ = autoshow; -} - -void ScreenlockBridge::UserPodCustomIconOptions::SetAriaLabel( - const base::string16& aria_label) { - aria_label_ = aria_label; -} - -void ScreenlockBridge::UserPodCustomIconOptions::SetHardlockOnClick() { - hardlock_on_click_ = true; -} - -void ScreenlockBridge::UserPodCustomIconOptions::SetTrialRun() { - is_trial_run_ = true; -} - -// static -std::string ScreenlockBridge::GetAuthenticatedUserEmail( - const Profile* profile) { - // |profile| has to be a signed-in profile with SigninManager already - // created. Otherwise, just crash to collect stack. - const SigninManagerBase* signin_manager = - SigninManagerFactory::GetForProfileIfExists(profile); - return signin_manager->GetAuthenticatedUsername(); -} - -ScreenlockBridge::ScreenlockBridge() : lock_handler_(NULL) { -} - -ScreenlockBridge::~ScreenlockBridge() { -} - -void ScreenlockBridge::SetLockHandler(LockHandler* lock_handler) { - DCHECK(lock_handler_ == NULL || lock_handler == NULL); - - // Don't notify observers if there is no change -- i.e. if the screen was - // already unlocked, and is remaining unlocked. - if (lock_handler == lock_handler_) - return; - - // TODO(isherman): If |lock_handler| is null, then |lock_handler_| might have - // been freed. Cache the screen type rather than querying it below. - LockHandler::ScreenType screen_type; - if (lock_handler_) - screen_type = lock_handler_->GetScreenType(); - else - screen_type = lock_handler->GetScreenType(); - - lock_handler_ = lock_handler; - if (lock_handler_) - FOR_EACH_OBSERVER(Observer, observers_, OnScreenDidLock(screen_type)); - else - FOR_EACH_OBSERVER(Observer, observers_, OnScreenDidUnlock(screen_type)); -} - -void ScreenlockBridge::SetFocusedUser(const std::string& user_id) { - if (user_id == focused_user_id_) - return; - focused_user_id_ = user_id; - FOR_EACH_OBSERVER(Observer, observers_, OnFocusedUserChanged(user_id)); -} - -bool ScreenlockBridge::IsLocked() const { - return lock_handler_ != NULL; -} - -void ScreenlockBridge::Lock(Profile* profile) { -#if defined(OS_CHROMEOS) - chromeos::SessionManagerClient* session_manager = - chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); - session_manager->RequestLockScreen(); -#else - profiles::LockProfile(profile); -#endif -} - -void ScreenlockBridge::Unlock(Profile* profile) { - if (lock_handler_) - lock_handler_->Unlock(GetAuthenticatedUserEmail(profile)); -} - -void ScreenlockBridge::AddObserver(Observer* observer) { - observers_.AddObserver(observer); -} - -void ScreenlockBridge::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -}
diff --git a/chrome/browser/signin/screenlock_bridge.h b/chrome/browser/signin/screenlock_bridge.h deleted file mode 100644 index d376f68..0000000 --- a/chrome/browser/signin/screenlock_bridge.h +++ /dev/null
@@ -1,192 +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 CHROME_BROWSER_SIGNIN_SCREENLOCK_BRIDGE_H_ -#define CHROME_BROWSER_SIGNIN_SCREENLOCK_BRIDGE_H_ - -#include <string> - -#include "base/basictypes.h" -#include "base/lazy_instance.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/strings/string16.h" -#include "base/values.h" - - -class Profile; - -// ScreenlockBridge brings together the screenLockPrivate API and underlying -// support. On ChromeOS, it delegates calls to the ScreenLocker. On other -// platforms, it delegates calls to UserManagerUI (and friends). -// TODO(tbarzic): Rename ScreenlockBridge to SignInScreenBridge, as this is not -// used solely for the lock screen anymore. -class ScreenlockBridge { - public: - // User pod icons supported by lock screen / signin screen UI. - enum UserPodCustomIcon { - USER_POD_CUSTOM_ICON_NONE, - USER_POD_CUSTOM_ICON_HARDLOCKED, - USER_POD_CUSTOM_ICON_LOCKED, - USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED, - // TODO(isherman): The "locked with proximity hint" icon is currently the - // same as the "locked" icon. It's treated as a separate case to allow an - // easy asset swap without changing the code, in case we decide to use a - // different icon for this case. If we definitely decide against that, then - // this enum entry should be removed. - USER_POD_CUSTOM_ICON_LOCKED_WITH_PROXIMITY_HINT, - USER_POD_CUSTOM_ICON_UNLOCKED, - USER_POD_CUSTOM_ICON_SPINNER - }; - - // Class containing parameters describing the custom icon that should be - // shown on a user's screen lock pod next to the input field. - class UserPodCustomIconOptions { - public: - UserPodCustomIconOptions(); - ~UserPodCustomIconOptions(); - - // Converts parameters to a dictionary values that can be sent to the - // screenlock web UI. - scoped_ptr<base::DictionaryValue> ToDictionaryValue() const; - - // Sets the icon that should be shown in the UI. - void SetIcon(UserPodCustomIcon icon); - - // Sets the icon tooltip. If |autoshow| is set the tooltip is automatically - // shown with the icon. - void SetTooltip(const base::string16& tooltip, bool autoshow); - - // Sets the accessibility label of the icon. If this attribute is not - // provided, then the tooltip will be used. - void SetAriaLabel(const base::string16& aria_label); - - // If hardlock on click is set, clicking the icon in the screenlock will - // go to state where password is required for unlock. - void SetHardlockOnClick(); - - // If the current lock screen is a trial run to introduce users to Easy - // Unlock, the icon will record metrics upon click. - void SetTrialRun(); - - private: - UserPodCustomIcon icon_; - - base::string16 tooltip_; - bool autoshow_tooltip_; - - base::string16 aria_label_; - - bool hardlock_on_click_; - - bool is_trial_run_; - - DISALLOW_COPY_AND_ASSIGN(UserPodCustomIconOptions); - }; - - class LockHandler { - public: - // Supported authentication types. Keep in sync with the enum in - // user_pod_row.js. - enum AuthType { - OFFLINE_PASSWORD = 0, - ONLINE_SIGN_IN = 1, - NUMERIC_PIN = 2, - USER_CLICK = 3, - EXPAND_THEN_USER_CLICK = 4, - FORCE_OFFLINE_PASSWORD = 5 - }; - - enum ScreenType { - SIGNIN_SCREEN = 0, - LOCK_SCREEN = 1, - OTHER_SCREEN = 2 - }; - - // Displays |message| in a banner on the lock screen. - virtual void ShowBannerMessage(const base::string16& message) = 0; - - // Shows a custom icon in the user pod on the lock screen. - virtual void ShowUserPodCustomIcon( - const std::string& user_email, - const UserPodCustomIconOptions& icon) = 0; - - // Hides the custom icon in user pod for a user. - virtual void HideUserPodCustomIcon(const std::string& user_email) = 0; - - // (Re)enable lock screen UI. - virtual void EnableInput() = 0; - - // Set the authentication type to be used on the lock screen. - virtual void SetAuthType(const std::string& user_email, - AuthType auth_type, - const base::string16& auth_value) = 0; - - // Returns the authentication type used for a user. - virtual AuthType GetAuthType(const std::string& user_email) const = 0; - - // Returns the type of the screen -- a signin or a lock screen. - virtual ScreenType GetScreenType() const = 0; - - // Unlock from easy unlock app for a user. - virtual void Unlock(const std::string& user_email) = 0; - - // Attempts to login the user using an easy unlock key. - virtual void AttemptEasySignin(const std::string& user_email, - const std::string& secret, - const std::string& key_label) = 0; - - protected: - virtual ~LockHandler() {} - }; - - class Observer { - public: - // Invoked after the screen is locked. - virtual void OnScreenDidLock(LockHandler::ScreenType screen_type) = 0; - - // Invoked after the screen lock is dismissed. - virtual void OnScreenDidUnlock(LockHandler::ScreenType screen_type) = 0; - - // Invoked when the user focused on the lock screen changes. - virtual void OnFocusedUserChanged(const std::string& user_id) = 0; - - protected: - virtual ~Observer() {} - }; - - static ScreenlockBridge* Get(); - static std::string GetAuthenticatedUserEmail(const Profile* profile); - - void SetLockHandler(LockHandler* lock_handler); - void SetFocusedUser(const std::string& user_id); - - bool IsLocked() const; - void Lock(Profile* profile); - void Unlock(Profile* profile); - - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - - LockHandler* lock_handler() { return lock_handler_; } - - std::string focused_user_id() const { return focused_user_id_; } - - private: - friend struct base::DefaultLazyInstanceTraits<ScreenlockBridge>; - friend struct base::DefaultDeleter<ScreenlockBridge>; - - ScreenlockBridge(); - ~ScreenlockBridge(); - - LockHandler* lock_handler_; // Not owned - // The last focused user's id. - std::string focused_user_id_; - ObserverList<Observer, true> observers_; - - DISALLOW_COPY_AND_ASSIGN(ScreenlockBridge); -}; - -#endif // CHROME_BROWSER_SIGNIN_SCREENLOCK_BRIDGE_H_
diff --git a/chrome/browser/signin/signin_error_notifier_ash_unittest.cc b/chrome/browser/signin/signin_error_notifier_ash_unittest.cc index 3cb2e57..8cd42ef 100644 --- a/chrome/browser/signin/signin_error_notifier_ash_unittest.cc +++ b/chrome/browser/signin/signin_error_notifier_ash_unittest.cc
@@ -48,8 +48,7 @@ class ScreenTypeDelegateDesktop : public gfx::ScreenTypeDelegate { public: ScreenTypeDelegateDesktop() {} - virtual gfx::ScreenType GetScreenTypeForNativeView( - gfx::NativeView view) override { + gfx::ScreenType GetScreenTypeForNativeView(gfx::NativeView view) override { return chrome::IsNativeViewInAsh(view) ? gfx::SCREEN_TYPE_ALTERNATE : gfx::SCREEN_TYPE_NATIVE;
diff --git a/chrome/browser/signin/signin_header_helper.cc b/chrome/browser/signin/signin_header_helper.cc index 0387202..83e502b8 100644 --- a/chrome/browser/signin/signin_header_helper.cc +++ b/chrome/browser/signin/signin_header_helper.cc
@@ -250,7 +250,7 @@ // embedded in a webui page, otherwise user may end up with a blank page as // gaia uses the header to decide whether it returns 204 for certain end // points. - if (is_guest && webview_info.owner_extension_id.empty()) + if (is_guest && webview_info.owner_host.empty()) return false; #endif // !OS_ANDROID && !OS_IOS
diff --git a/chrome/browser/signin/signin_manager_factory.cc b/chrome/browser/signin/signin_manager_factory.cc index 9222645..9b5406fe 100644 --- a/chrome/browser/signin/signin_manager_factory.cc +++ b/chrome/browser/signin/signin_manager_factory.cc
@@ -81,53 +81,29 @@ void SigninManagerFactory::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kGoogleServicesHostedDomain, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kGoogleServicesLastUsername, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kGoogleServicesHostedDomain, + std::string()); + registry->RegisterStringPref(prefs::kGoogleServicesLastUsername, + std::string()); registry->RegisterInt64Pref( prefs::kGoogleServicesRefreshTokenAnnotateScheduledTime, - base::Time().ToInternalValue(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kGoogleServicesSigninScopedDeviceId, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kGoogleServicesAccountId, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kGoogleServicesUserAccountId, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kAutologinEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kReverseAutologinEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + base::Time().ToInternalValue()); + registry->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId, + std::string()); + registry->RegisterStringPref(prefs::kGoogleServicesAccountId, std::string()); + registry->RegisterStringPref(prefs::kGoogleServicesUserAccountId, + std::string()); + registry->RegisterBooleanPref(prefs::kAutologinEnabled, true); + registry->RegisterBooleanPref(prefs::kReverseAutologinEnabled, true); registry->RegisterListPref(prefs::kReverseAutologinRejectedEmailList, - new base::ListValue, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kSignedInTime, - base::Time().ToInternalValue(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + new base::ListValue); + registry->RegisterInt64Pref(prefs::kSignedInTime, + base::Time().ToInternalValue()); LocalAuth::RegisterLocalAuthPrefs(registry); // Deprecated prefs: will be removed in a future release. - registry->RegisterStringPref( - prefs::kGoogleServicesUsername, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kGoogleServicesUsername, std::string()); } // static
diff --git a/chrome/browser/signin/signin_promo.cc b/chrome/browser/signin/signin_promo.cc index a3404a91..22663ca 100644 --- a/chrome/browser/signin/signin_promo.cc +++ b/chrome/browser/signin/signin_promo.cc
@@ -252,22 +252,10 @@ void RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kSignInPromoStartupCount, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kSignInPromoUserSkipped, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kSignInPromoShowOnFirstRunAllowed, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kSignInPromoShowNTPBubble, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kSignInPromoStartupCount, 0); + registry->RegisterBooleanPref(prefs::kSignInPromoUserSkipped, false); + registry->RegisterBooleanPref(prefs::kSignInPromoShowOnFirstRunAllowed, true); + registry->RegisterBooleanPref(prefs::kSignInPromoShowNTPBubble, false); } } // namespace signin
diff --git a/chrome/browser/signin/signin_tracker_factory.cc b/chrome/browser/signin/signin_tracker_factory.cc index 0c9f3da..0e1a5372 100644 --- a/chrome/browser/signin/signin_tracker_factory.cc +++ b/chrome/browser/signin/signin_tracker_factory.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/signin/signin_tracker_factory.h" -#include "chrome/browser/signin/account_reconcilor_factory.h" #include "chrome/browser/signin/chrome_signin_client_factory.h" #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" @@ -18,15 +17,9 @@ scoped_ptr<SigninTracker> SigninTrackerFactory::CreateForProfile( Profile* profile, SigninTracker::Observer* observer) { - // Determine whether to use the AccountReconcilor. - AccountReconcilor* account_reconcilor = NULL; - if (switches::IsEnableAccountConsistency()) - account_reconcilor = AccountReconcilorFactory::GetForProfile(profile); - return scoped_ptr<SigninTracker>(new SigninTracker( ProfileOAuth2TokenServiceFactory::GetForProfile(profile), SigninManagerFactory::GetForProfile(profile), - account_reconcilor, GaiaCookieManagerServiceFactory::GetForProfile(profile), ChromeSigninClientFactory::GetForProfile(profile), observer));
diff --git a/chrome/browser/speech/tts_controller_impl.cc b/chrome/browser/speech/tts_controller_impl.cc index 88195924..cad1bb3 100644 --- a/chrome/browser/speech/tts_controller_impl.cc +++ b/chrome/browser/speech/tts_controller_impl.cc
@@ -7,7 +7,6 @@ #include <string> #include <vector> -#include "base/float_util.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/speech/tts_platform.h"
diff --git a/chrome/browser/speech/tts_linux.cc b/chrome/browser/speech/tts_linux.cc index 2f29236a..1ede2b3 100644 --- a/chrome/browser/speech/tts_linux.cc +++ b/chrome/browser/speech/tts_linux.cc
@@ -192,6 +192,10 @@ libspeechd_loader_.spd_set_voice_rate(conn_, 100 * log10(rate) / log10(3)); libspeechd_loader_.spd_set_voice_pitch(conn_, 100 * log10(pitch) / log10(3)); + // Support languages other than the default + if (!lang.empty()) + libspeechd_loader_.spd_set_language(conn_, lang.c_str()); + utterance_ = utterance; utterance_id_ = utterance_id;
diff --git a/chrome/browser/speech/tts_win.cc b/chrome/browser/speech/tts_win.cc index 2422bed..c711f9e 100644 --- a/chrome/browser/speech/tts_win.cc +++ b/chrome/browser/speech/tts_win.cc
@@ -15,26 +15,26 @@ class TtsPlatformImplWin : public TtsPlatformImpl { public: - virtual bool PlatformImplAvailable() { + bool PlatformImplAvailable() override { return true; } - virtual bool Speak( + bool Speak( int utterance_id, const std::string& utterance, const std::string& lang, const VoiceData& voice, - const UtteranceContinuousParameters& params); + const UtteranceContinuousParameters& params) override; - virtual bool StopSpeaking(); + bool StopSpeaking() override; - virtual void Pause(); + void Pause() override; - virtual void Resume(); + void Resume() override; - virtual bool IsSpeaking(); + bool IsSpeaking() override; - virtual void GetVoices(std::vector<VoiceData>* out_voices) override; + void GetVoices(std::vector<VoiceData>* out_voices) override; // Get the single instance of this class. static TtsPlatformImplWin* GetInstance(); @@ -43,7 +43,7 @@ private: TtsPlatformImplWin(); - virtual ~TtsPlatformImplWin() {} + ~TtsPlatformImplWin() override {} void OnSpeechEvent();
diff --git a/chrome/browser/spellchecker/feedback_sender_unittest.cc b/chrome/browser/spellchecker/feedback_sender_unittest.cc index 5f6963d6..93949fb 100644 --- a/chrome/browser/spellchecker/feedback_sender_unittest.cc +++ b/chrome/browser/spellchecker/feedback_sender_unittest.cc
@@ -141,8 +141,8 @@ scoped_ptr<spellcheck::FeedbackSender> feedback_; private: - TestingProfile profile_; base::MessageLoop loop_; + TestingProfile profile_; content::TestBrowserThread ui_thread_; scoped_ptr<base::FieldTrialList> field_trial_list_; scoped_refptr<base::FieldTrial> field_trial_;
diff --git a/chrome/browser/spellchecker/spellcheck_factory.cc b/chrome/browser/spellchecker/spellcheck_factory.cc index bd4ac1fd5..edbed40 100644 --- a/chrome/browser/spellchecker/spellcheck_factory.cc +++ b/chrome/browser/spellchecker/spellcheck_factory.cc
@@ -71,12 +71,8 @@ // TODO(estade): IDS_SPELLCHECK_DICTIONARY should be an ASCII string. user_prefs->RegisterStringPref( prefs::kSpellCheckDictionary, - l10n_util::GetStringUTF8(IDS_SPELLCHECK_DICTIONARY), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - user_prefs->RegisterBooleanPref( - prefs::kSpellCheckUseSpellingService, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + l10n_util::GetStringUTF8(IDS_SPELLCHECK_DICTIONARY)); + user_prefs->RegisterBooleanPref(prefs::kSpellCheckUseSpellingService, false); user_prefs->RegisterBooleanPref( prefs::kEnableContinuousSpellcheck, true,
diff --git a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc index 479a8f0..ad9fa56 100644 --- a/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc +++ b/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
@@ -214,7 +214,7 @@ GURL SpellcheckHunspellDictionary::GetDictionaryURL() { static const char kDownloadServerUrl[] = - "http://cache.pack.google.com/edgedl/chrome/dict/"; + "https://redirector.gvt1.com/edgedl/chrome/dict/"; std::string bdict_file = dictionary_file_.path.BaseName().MaybeAsASCII(); DCHECK(!bdict_file.empty());
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc index 717d1384..529cbca 100644 --- a/chrome/browser/ssl/ssl_blocking_page.cc +++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -248,7 +248,9 @@ callback_(callback), cert_error_(cert_error), ssl_info_(ssl_info), - overridable_(IsOptionsOverridable(options_mask)), + overridable_(IsOverridable( + options_mask, + Profile::FromBrowserContext(web_contents->GetBrowserContext()))), danger_overridable_(true), strict_enforcement_((options_mask & STRICT_ENFORCEMENT) != 0), expired_but_previously_allowed_( @@ -697,7 +699,11 @@ } // static -bool SSLBlockingPage::IsOptionsOverridable(int options_mask) { - return (options_mask & SSLBlockingPage::OVERRIDABLE) && - !(options_mask & SSLBlockingPage::STRICT_ENFORCEMENT); +bool SSLBlockingPage::IsOverridable(int options_mask, + const Profile* const profile) { + const bool is_overridable = + (options_mask & SSLBlockingPage::OVERRIDABLE) && + !(options_mask & SSLBlockingPage::STRICT_ENFORCEMENT) && + profile->GetPrefs()->GetBoolean(prefs::kSSLErrorOverrideAllowed); + return is_overridable; }
diff --git a/chrome/browser/ssl/ssl_blocking_page.h b/chrome/browser/ssl/ssl_blocking_page.h index ce694f80..36026b50 100644 --- a/chrome/browser/ssl/ssl_blocking_page.h +++ b/chrome/browser/ssl/ssl_blocking_page.h
@@ -13,6 +13,7 @@ #include "base/task/cancelable_task_tracker.h" #include "base/time/time.h" #include "chrome/browser/interstitials/security_interstitial_page.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ssl/ssl_cert_reporter.h" #include "net/ssl/ssl_info.h" #include "url/gurl.h" @@ -71,8 +72,9 @@ // InterstitialPageDelegate method: InterstitialPageDelegate::TypeID GetTypeForTesting() const override; - // Returns true if |options_mask| refers to an overridable SSL error. - static bool IsOptionsOverridable(int options_mask); + // Returns true if |options_mask| refers to an overridable SSL error and + // if SSL error overriding is allowed by policy. + static bool IsOverridable(int options_mask, const Profile* const profile); void SetSSLCertReporterForTesting( scoped_ptr<SSLCertReporter> ssl_cert_reporter);
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc index 59da844..d536049 100644 --- a/chrome/browser/ssl/ssl_browser_tests.cc +++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -42,7 +42,6 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_frame_host.h" -#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" @@ -56,15 +55,10 @@ #include "net/base/net_errors.h" #include "net/base/test_data_directory.h" #include "net/cert/cert_status_flags.h" -#include "net/cert/test_root_certs.h" #include "net/cert/x509_certificate.h" -#include "net/dns/host_resolver.h" -#include "net/dns/mock_host_resolver.h" -#include "net/http/http_transaction_factory.h" #include "net/ssl/ssl_info.h" #include "net/test/spawned_test_server/spawned_test_server.h" #include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" #if defined(USE_NSS_CERTS) #include "chrome/browser/net/nss_context.h" @@ -273,33 +267,6 @@ } // namespace CertificateReporting -void RootCertsChangedOnIOThread( - const scoped_refptr<net::URLRequestContextGetter> context_getter) { - net::CertDatabase::GetInstance()->NotifyObserversOfCACertChanged(NULL); - context_getter->GetURLRequestContext() - ->http_transaction_factory() - ->GetSession() - ->CloseAllConnections(); -} - -// Alerts the URLRequestContext for the given WebContents that a root -// certificate has changed state or been removed. This, in turn, clears any -// cached certificate validation in the cert verifier. This will also close all -// connections in the socket pool of |contents|, so calls to this should be made -// with care. -void RootCertsChanged(WebContents* contents) { - scoped_refptr<net::URLRequestContextGetter> url_request_context = - contents->GetBrowserContext()->GetRequestContextForRenderProcess( - contents->GetRenderProcessHost()->GetID()); - base::RunLoop run_loop; - content::BrowserThread::PostTaskAndReply( - content::BrowserThread::IO, FROM_HERE, - base::Bind(&RootCertsChangedOnIOThread, url_request_context), - run_loop.QuitClosure()); - run_loop.Run(); - base::RunLoop().RunUntilIdle(); -} - } // namespace class SSLUITest : public InProcessBrowserTest { @@ -2349,29 +2316,31 @@ // However, if this is followed by another visit, and a good certificate // is seen for the same host, the original exception is forgotten. IN_PROC_BROWSER_TEST_F(SSLUITest, BadCertFollowedByGoodCert) { + // It is necessary to use |https_server_expired_| rather than + // |https_server_mismatched| because the former shares a host with + // |https_server_| and cert exceptions are per host. + ASSERT_TRUE(https_server_expired_.Start()); ASSERT_TRUE(https_server_.Start()); + + std::string https_server_expired_host = + https_server_.GetURL("files/ssl/google.html").host(); std::string https_server_host = https_server_.GetURL("files/ssl/google.html").host(); + ASSERT_EQ(https_server_expired_host, https_server_host); WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); - net::TestRootCerts* root_certs = net::TestRootCerts::GetInstance(); - - ASSERT_TRUE(root_certs); - root_certs->Clear(); Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext()); ChromeSSLHostStateDelegate* state = reinterpret_cast<ChromeSSLHostStateDelegate*>( profile->GetSSLHostStateDelegate()); - ui_test_utils::NavigateToURL(browser(), - https_server_.GetURL("files/ssl/google.html")); + ui_test_utils::NavigateToURL( + browser(), https_server_expired_.GetURL("files/ssl/google.html")); ProceedThroughInterstitial(tab); EXPECT_TRUE(state->HasAllowException(https_server_host)); - ASSERT_TRUE(https_server_.LoadTestRootCert()); - RootCertsChanged(tab); ui_test_utils::NavigateToURL(browser(), https_server_.GetURL("files/ssl/google.html")); ASSERT_FALSE(tab->GetInterstitialPage());
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc index 25e4b6a..72da17f 100644 --- a/chrome/browser/ssl/ssl_error_handler.cc +++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -187,9 +187,11 @@ void SSLErrorHandler::ShowCaptivePortalInterstitial(const GURL& landing_url) { #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) // Show captive portal blocking page. The interstitial owns the blocking page. - RecordUMA(SSLBlockingPage::IsOptionsOverridable(options_mask_) ? - SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE : - SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE); + const Profile* const profile = + Profile::FromBrowserContext(web_contents_->GetBrowserContext()); + RecordUMA(SSLBlockingPage::IsOverridable(options_mask_, profile) + ? SHOW_CAPTIVE_PORTAL_INTERSTITIAL_OVERRIDABLE + : SHOW_CAPTIVE_PORTAL_INTERSTITIAL_NONOVERRIDABLE); (new CaptivePortalBlockingPage(web_contents_, request_url_, landing_url, callback_))->Show(); // Once an interstitial is displayed, no need to keep the handler around. @@ -202,9 +204,11 @@ void SSLErrorHandler::ShowSSLInterstitial() { // Show SSL blocking page. The interstitial owns the blocking page. - RecordUMA(SSLBlockingPage::IsOptionsOverridable(options_mask_) ? - SHOW_SSL_INTERSTITIAL_OVERRIDABLE : - SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE); + const Profile* const profile = + Profile::FromBrowserContext(web_contents_->GetBrowserContext()); + RecordUMA(SSLBlockingPage::IsOverridable(options_mask_, profile) + ? SHOW_SSL_INTERSTITIAL_OVERRIDABLE + : SHOW_SSL_INTERSTITIAL_NONOVERRIDABLE); (new SSLBlockingPage(web_contents_, cert_error_, ssl_info_, request_url_, options_mask_, base::Time::NowFromSystemTime(), ssl_cert_reporter_.Pass(), callback_))->Show();
diff --git a/chrome/browser/ssl/ssl_error_info.cc b/chrome/browser/ssl/ssl_error_info.cc index d4ad26d..00916e8c 100644 --- a/chrome/browser/ssl/ssl_error_info.cc +++ b/chrome/browser/ssl/ssl_error_info.cc
@@ -59,10 +59,13 @@ } case CERT_DATE_INVALID: if (cert->HasExpired()) { + // Make sure to round up to the smallest integer value not less than + // the expiration value (https://crbug.com/476758). + int expiration_value = + (base::Time::Now() - cert->valid_expiry()).InDays() + 1; details = l10n_util::GetStringFUTF16( IDS_CERT_ERROR_EXPIRED_DETAILS, UTF8ToUTF16(request_url.host()), - base::IntToString16( - (base::Time::Now() - cert->valid_expiry()).InDays()), + base::IntToString16(expiration_value), base::TimeFormatFriendlyDate(base::Time::Now())); short_description = l10n_util::GetStringUTF16(IDS_CERT_ERROR_EXPIRED_DESCRIPTION);
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service.cc b/chrome/browser/supervised_user/child_accounts/child_account_service.cc index ab5868f..673849d 100644 --- a/chrome/browser/supervised_user/child_accounts/child_account_service.cc +++ b/chrome/browser/supervised_user/child_accounts/child_account_service.cc
@@ -95,10 +95,7 @@ void ChildAccountService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kChildAccountStatusKnown, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kChildAccountStatusKnown, false); } void ChildAccountService::SetIsChildAccount(bool is_child_account) {
diff --git a/chrome/browser/supervised_user/experimental/supervised_user_blacklist.cc b/chrome/browser/supervised_user/experimental/supervised_user_blacklist.cc index 14843ff6..a69f57e 100644 --- a/chrome/browser/supervised_user/experimental/supervised_user_blacklist.cc +++ b/chrome/browser/supervised_user/experimental/supervised_user_blacklist.cc
@@ -75,7 +75,8 @@ void SupervisedUserBlacklist::ReadFromFile(const base::FilePath& path, const base::Closure& done_callback) { base::PostTaskAndReplyWithResult( - BrowserThread::GetBlockingPool(), + BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(), FROM_HERE, base::Bind(&ReadFromBinaryFileOnFileThread, path), base::Bind(&SupervisedUserBlacklist::OnReadFromFileCompleted,
diff --git a/chrome/browser/supervised_user/experimental/supervised_user_blacklist_downloader.cc b/chrome/browser/supervised_user/experimental/supervised_user_blacklist_downloader.cc index 6b602e1..946b5fc 100644 --- a/chrome/browser/supervised_user/experimental/supervised_user_blacklist_downloader.cc +++ b/chrome/browser/supervised_user/experimental/supervised_user_blacklist_downloader.cc
@@ -35,7 +35,8 @@ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); base::PostTaskAndReplyWithResult( - BrowserThread::GetBlockingPool(), + BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(), FROM_HERE, base::Bind(&base::PathExists, path), base::Bind(&SupervisedUserBlacklistDownloader::OnFileExistsCheckDone,
diff --git a/chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service_unittest.cc b/chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service_unittest.cc index 4d1859008..67224b5 100644 --- a/chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service_unittest.cc +++ b/chrome/browser/supervised_user/legacy/supervised_user_pref_mapping_service_unittest.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" const char kFakeSupervisedUserId[] = "fakeID"; @@ -38,6 +39,7 @@ shared_settings_service_->Shutdown(); } + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; SupervisedUserSharedSettingsService* shared_settings_service_; SupervisedUserPrefMappingService* mapping_service_;
diff --git a/chrome/browser/supervised_user/legacy/supervised_user_registration_utility.cc b/chrome/browser/supervised_user/legacy/supervised_user_registration_utility.cc index b8563d2..5242fd6 100644 --- a/chrome/browser/supervised_user/legacy/supervised_user_registration_utility.cc +++ b/chrome/browser/supervised_user/legacy/supervised_user_registration_utility.cc
@@ -306,7 +306,9 @@ } syncer::GetSessionName( - content::BrowserThread::GetBlockingPool(), + content::BrowserThread::GetBlockingPool() + ->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(), base::Bind(&SupervisedUserRegistrationUtilityImpl::FetchToken, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.cc b/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.cc index ddd6f29..94480d8 100644 --- a/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.cc +++ b/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.cc
@@ -164,9 +164,7 @@ // static void SupervisedUserSharedSettingsService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kSupervisedUserSharedSettings, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kSupervisedUserSharedSettings); } // static
diff --git a/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_unittest.cc b/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_unittest.cc index 522fe7ce..eed022a 100644 --- a/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_unittest.cc +++ b/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "sync/api/fake_sync_change_processor.h" #include "sync/api/sync_change.h" #include "sync/api/sync_change_processor_wrapper_for_test.h" @@ -130,6 +131,7 @@ su_id, key, *value, true)); } + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; SupervisedUserSharedSettingsService settings_service_; SyncDataList changed_settings_;
diff --git a/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_update_unittest.cc b/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_update_unittest.cc index 17f9f14..59329ac 100644 --- a/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_update_unittest.cc +++ b/chrome/browser/supervised_user/legacy/supervised_user_shared_settings_update_unittest.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.h" #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_update.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "sync/api/sync_change.h" #include "testing/gtest/include/gtest/gtest.h" @@ -20,6 +21,7 @@ } protected: + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; SupervisedUserSharedSettingsService service_; scoped_ptr<bool> result_;
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc index b8807313..f5f54579 100644 --- a/chrome/browser/supervised_user/supervised_user_service.cc +++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -289,21 +289,13 @@ // static void SupervisedUserService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kSupervisedUserManualHosts, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kSupervisedUserManualURLs, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kDefaultSupervisedUserFilteringBehavior, - SupervisedUserURLFilter::ALLOW, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref(prefs::kSupervisedUserCreationAllowed, true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kSupervisedUserManualHosts); + registry->RegisterDictionaryPref(prefs::kSupervisedUserManualURLs); + registry->RegisterIntegerPref(prefs::kDefaultSupervisedUserFilteringBehavior, + SupervisedUserURLFilter::ALLOW); + registry->RegisterBooleanPref(prefs::kSupervisedUserCreationAllowed, true); for (const char* pref : kCustodianInfoPrefs) { - registry->RegisterStringPref(pref, std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(pref, std::string()); } } @@ -623,7 +615,8 @@ void SupervisedUserService::LoadBlacklist(const base::FilePath& path, const GURL& url) { base::PostTaskAndReplyWithResult( - BrowserThread::GetBlockingPool(), + BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(), FROM_HERE, base::Bind(&base::PathExists, path), base::Bind(&SupervisedUserService::OnBlacklistFileChecked,
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc b/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc index 60e37a8..40a738a 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc +++ b/chrome/browser/supervised_user/supervised_user_settings_service_unittest.cc
@@ -8,6 +8,7 @@ #include "base/prefs/testing_pref_store.h" #include "base/strings/string_util.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "sync/api/fake_sync_change_processor.h" #include "sync/api/sync_change.h" #include "sync/api/sync_change_processor_wrapper_for_test.h" @@ -133,6 +134,7 @@ void TearDown() override { settings_service_.Shutdown(); } + content::TestBrowserThreadBundle thread_bundle_; base::DictionaryValue split_items_; scoped_ptr<base::Value> atomic_setting_value_; SupervisedUserSettingsService settings_service_;
diff --git a/chrome/browser/supervised_user/supervised_user_site_list.cc b/chrome/browser/supervised_user/supervised_user_site_list.cc index 90c31e18..2c1b89a 100644 --- a/chrome/browser/supervised_user/supervised_user_site_list.cc +++ b/chrome/browser/supervised_user/supervised_user_site_list.cc
@@ -43,9 +43,8 @@ // struct. void AddWhitelistEntries(const base::DictionaryValue* site_dict, SupervisedUserSiteList::Site* site) { - std::vector<std::string>* patterns = &site->patterns; - bool found = false; + const base::ListValue* whitelist = nullptr; if (site_dict->GetList(kWhitelistKey, &whitelist)) { found = true; @@ -56,22 +55,24 @@ continue; } - patterns->push_back(pattern); + site->patterns.push_back(pattern); } } - std::vector<std::string>* hashes = &site->hostname_hashes; const base::ListValue* hash_list = nullptr; if (site_dict->GetList(kHostnameHashesKey, &hash_list)) { found = true; for (const base::Value* entry : *hash_list) { std::string hash; if (!entry->GetAsString(&hash)) { - LOG(ERROR) << "Invalid whitelist entry"; + LOG(ERROR) << "Invalid hostname_hashes entry"; continue; } + // TODO(treib): Check that |hash| has exactly 40 (2*base::kSHA1Length) + // characters from [0-9a-fA-F]. Or just store the raw bytes (from + // base::HexStringToBytes). - hashes->push_back(hash); + site->hostname_hashes.push_back(hash); } } @@ -91,7 +92,7 @@ return; } - patterns->push_back(url.host()); + site->patterns.push_back(url.host()); } } // namespace @@ -105,7 +106,9 @@ void SupervisedUserSiteList::Load(const base::FilePath& path, const LoadedCallback& callback) { base::PostTaskAndReplyWithResult( - content::BrowserThread::GetBlockingPool(), + content::BrowserThread::GetBlockingPool() + ->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(), FROM_HERE, base::Bind(&ReadFileOnBlockingThread, path), base::Bind(&SupervisedUserSiteList::ParseJson, path, callback)); @@ -191,8 +194,7 @@ base::ListValue* sites = nullptr; if (!dict->GetList(kSitesKey, &sites)) { - LOG(ERROR) << "Site list " << path.value() - << " does not contain any sites"; + LOG(ERROR) << "Site list " << path.value() << " does not contain any sites"; return; }
diff --git a/chrome/browser/supervised_user/supervised_user_site_list.h b/chrome/browser/supervised_user/supervised_user_site_list.h index d98dda6..61625e76 100644 --- a/chrome/browser/supervised_user/supervised_user_site_list.h +++ b/chrome/browser/supervised_user/supervised_user_site_list.h
@@ -49,7 +49,7 @@ // A list of URL patterns that should be whitelisted for the site. std::vector<std::string> patterns; - // A list of SHA1 hashes of hostnames that should be whitelisted + // A list of hex-encoded SHA1 hashes of hostnames that should be whitelisted // for the site. std::vector<std::string> hostname_hashes;
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.cc b/chrome/browser/supervised_user/supervised_user_url_filter.cc index c75039b8..d9b641c2 100644 --- a/chrome/browser/supervised_user/supervised_user_url_filter.cc +++ b/chrome/browser/supervised_user/supervised_user_url_filter.cc
@@ -165,7 +165,10 @@ : default_behavior_(ALLOW), contents_(new Contents()), blacklist_(nullptr), - blocking_task_runner_(BrowserThread::GetBlockingPool()) { + blocking_task_runner_( + BrowserThread::GetBlockingPool() + ->GetTaskRunnerWithShutdownBehavior( + base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get()) { // Detach from the current thread so we can be constructed on a different // thread than the one where we're used. DetachFromThread();
diff --git a/chrome/browser/supervised_user/supervised_user_whitelist_service.cc b/chrome/browser/supervised_user/supervised_user_whitelist_service.cc index 73840c7..c8fd104 100644 --- a/chrome/browser/supervised_user/supervised_user_whitelist_service.cc +++ b/chrome/browser/supervised_user/supervised_user_whitelist_service.cc
@@ -43,9 +43,7 @@ // static void SupervisedUserWhitelistService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kSupervisedUserWhitelists, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kSupervisedUserWhitelists); } void SupervisedUserWhitelistService::Init() {
diff --git a/chrome/browser/supervised_user/supervised_user_whitelist_service_unittest.cc b/chrome/browser/supervised_user/supervised_user_whitelist_service_unittest.cc index 2ea29670..a269d8d 100644 --- a/chrome/browser/supervised_user/supervised_user_whitelist_service_unittest.cc +++ b/chrome/browser/supervised_user/supervised_user_whitelist_service_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "sync/api/sync_change.h" #include "sync/api/sync_error_factory.h" #include "sync/protocol/sync.pb.h" @@ -152,7 +153,7 @@ site_lists_changed_callback_.Run(); } - base::MessageLoop message_loop_; + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; scoped_ptr<MockSupervisedUserWhitelistInstaller> installer_;
diff --git a/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc b/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc index bbc5a4dc..7301b1d 100644 --- a/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc +++ b/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc
@@ -151,9 +151,9 @@ profile_manager_(TestingBrowserProcess::GetGlobal()), fake_manager_(NULL) {} - virtual ~SyncBackendHostTest() {} + ~SyncBackendHostTest() override {} - virtual void SetUp() override { + void SetUp() override { ASSERT_TRUE(profile_manager_.SetUp()); profile_ = profile_manager_.CreateTestingProfile(kTestProfileName); sync_prefs_.reset(new sync_driver::SyncPrefs(profile_->GetPrefs())); @@ -184,7 +184,7 @@ network_resources_.reset(new syncer::HttpBridgeNetworkResources()); } - virtual void TearDown() override { + void TearDown() override { if (backend_) { backend_->StopSyncingForShutdown(); backend_->Shutdown(syncer::STOP_SYNC);
diff --git a/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc b/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc index 1129bbf..3db65e9 100644 --- a/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc +++ b/chrome/browser/sync/glue/sync_backend_registrar_unittest.cc
@@ -60,10 +60,10 @@ protected: SyncBackendRegistrarTest() - : sync_thread_(NULL), - thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD | + : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD | content::TestBrowserThreadBundle::REAL_FILE_THREAD | - content::TestBrowserThreadBundle::REAL_IO_THREAD) {} + content::TestBrowserThreadBundle::REAL_IO_THREAD), + sync_thread_(NULL) {} ~SyncBackendRegistrarTest() override {} @@ -101,12 +101,12 @@ } } + content::TestBrowserThreadBundle thread_bundle_; syncer::TestUserShare test_user_share_; TestingProfile profile_; scoped_ptr<SyncBackendRegistrar> registrar_; base::Thread* sync_thread_; - content::TestBrowserThreadBundle thread_bundle_; }; TEST_F(SyncBackendRegistrarTest, ConstructorEmpty) {
diff --git a/chrome/browser/sync/profile_sync_components_factory_mock.h b/chrome/browser/sync/profile_sync_components_factory_mock.h index 3e106962..c6594b7 100644 --- a/chrome/browser/sync/profile_sync_components_factory_mock.h +++ b/chrome/browser/sync/profile_sync_components_factory_mock.h
@@ -26,7 +26,7 @@ ProfileSyncComponentsFactoryMock( sync_driver::AssociatorInterface* model_associator, sync_driver::ChangeProcessor* change_processor); - virtual ~ProfileSyncComponentsFactoryMock(); + ~ProfileSyncComponentsFactoryMock() override; MOCK_METHOD1(RegisterDataTypes, void(ProfileSyncService*)); MOCK_METHOD5(CreateDataTypeManager, @@ -44,14 +44,14 @@ const base::WeakPtr<sync_driver::SyncPrefs>& sync_prefs, const base::FilePath& sync_folder)); - virtual scoped_ptr<sync_driver::LocalDeviceInfoProvider> + scoped_ptr<sync_driver::LocalDeviceInfoProvider> CreateLocalDeviceInfoProvider() override; void SetLocalDeviceInfoProvider( scoped_ptr<sync_driver::LocalDeviceInfoProvider> local_device); MOCK_METHOD1(GetSyncableServiceForType, base::WeakPtr<syncer::SyncableService>(syncer::ModelType)); - virtual scoped_ptr<syncer::AttachmentService> CreateAttachmentService( + scoped_ptr<syncer::AttachmentService> CreateAttachmentService( scoped_ptr<syncer::AttachmentStoreForSync> attachment_store, const syncer::UserShare& user_share, const std::string& store_birthday,
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index 9b09cd1..70f1d06 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc
@@ -293,8 +293,8 @@ if (IsManaged() || sync_prefs_.IsStartSuppressed()) return false; - // Sync is logged in if there is a non-empty effective username. - return !signin_->GetEffectiveUsername().empty(); + // Sync is logged in if there is a non-empty effective account id. + return !signin_->GetAccountIdToUse().empty(); } bool ProfileSyncService::IsOAuthRefreshTokenAvailable() { @@ -321,7 +321,7 @@ RegisterAuthNotifications(); - if (!HasSyncSetupCompleted() || signin_->GetEffectiveUsername().empty()) { + if (!HasSyncSetupCompleted() || signin_->GetAccountIdToUse().empty()) { // Clean up in case of previous crash / setup abort / signout. DisableForUser(); } @@ -347,7 +347,7 @@ if (browser_sync::BackupRollbackController::IsBackupEnabled()) { // Backup is needed if user's not signed in or signed in but previous // backup didn't finish, i.e. backend didn't switch from backup to sync. - need_backup_ = signin_->GetEffectiveUsername().empty() || + need_backup_ = signin_->GetAccountIdToUse().empty() || sync_prefs_.GetFirstSyncTime().is_null(); // Try to resume rollback if it didn't finish in last session. @@ -357,7 +357,7 @@ } #if defined(ENABLE_PRE_SYNC_BACKUP) - if (!running_rollback && signin_->GetEffectiveUsername().empty()) { + if (!running_rollback && signin_->GetAccountIdToUse().empty()) { CleanUpBackup(); } #else @@ -2554,7 +2554,7 @@ } void ProfileSyncService::UpdateFirstSyncTimePref() { - if (signin_->GetEffectiveUsername().empty()) { + if (signin_->GetAccountIdToUse().empty()) { // Clear if user's not signed in and rollback is done. if (backend_mode_ != ROLLBACK) sync_prefs_.ClearFirstSyncTime();
diff --git a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc index 17ed42e..5974e36b 100644 --- a/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_bookmark_unittest.cc
@@ -328,7 +328,6 @@ ProfileSyncServiceBookmarkTest() : model_(NULL), - thread_bundle_(content::TestBrowserThreadBundle::DEFAULT), local_merge_result_(syncer::BOOKMARKS), syncer_merge_result_(syncer::BOOKMARKS) {} @@ -753,6 +752,9 @@ model_->bookmark_bar_node()->id()); } + private: + content::TestBrowserThreadBundle thread_bundle_; + protected: TestingProfile profile_; BookmarkModel* model_; @@ -762,7 +764,6 @@ scoped_ptr<BookmarkModelAssociator> model_associator_; private: - content::TestBrowserThreadBundle thread_bundle_; syncer::SyncMergeResult local_merge_result_; syncer::SyncMergeResult syncer_merge_result_; };
diff --git a/chrome/browser/sync/profile_sync_service_factory_unittest.cc b/chrome/browser/sync/profile_sync_service_factory_unittest.cc index e3c2da1a..c1fb61b 100644 --- a/chrome/browser/sync/profile_sync_service_factory_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_factory_unittest.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" class ProfileSyncServiceFactoryTest : public testing::Test { @@ -17,6 +18,7 @@ profile_.reset(new TestingProfile()); } + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<Profile> profile_; };
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc index 2a7bc23..3542aa5 100644 --- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -90,7 +90,7 @@ class HistoryBackendMock : public HistoryBackend { public: HistoryBackendMock() : HistoryBackend(nullptr, nullptr) {} - virtual bool IsExpiredVisitTime(const base::Time& time) override { + bool IsExpiredVisitTime(const base::Time& time) override { return time.ToInternalValue() == EXPIRED_VISIT; } MOCK_METHOD1(GetAllTypedURLs, bool(history::URLRows* entries));
diff --git a/chrome/browser/sync/startup_controller_unittest.cc b/chrome/browser/sync/startup_controller_unittest.cc index 186a759..9c1d537 100644 --- a/chrome/browser/sync/startup_controller_unittest.cc +++ b/chrome/browser/sync/startup_controller_unittest.cc
@@ -16,6 +16,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_profile.h" #include "components/sync_driver/sync_prefs.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace browser_sync { @@ -94,7 +95,7 @@ private: bool started_; - base::MessageLoop message_loop_; + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<StartupController> controller_; scoped_ptr<FakeSupervisedUserSigninManagerWrapper> signin_; scoped_ptr<FakeProfileOAuth2TokenService> token_service_;
diff --git a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc index 8de7117..6f213a5 100644 --- a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc +++ b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
@@ -48,9 +48,8 @@ class ScreenTypeDelegateDesktop : public gfx::ScreenTypeDelegate { public: ScreenTypeDelegateDesktop() {} - virtual ~ScreenTypeDelegateDesktop() {} - virtual gfx::ScreenType GetScreenTypeForNativeView( - gfx::NativeView view) override { + ~ScreenTypeDelegateDesktop() override {} + gfx::ScreenType GetScreenTypeForNativeView(gfx::NativeView view) override { return chrome::IsNativeViewInAsh(view) ? gfx::SCREEN_TYPE_ALTERNATE : gfx::SCREEN_TYPE_NATIVE;
diff --git a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc index 14d9d2a9..154d4b3 100644 --- a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
@@ -4,13 +4,23 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/strings/string_number_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/time/time.h" #include "chrome/browser/sync/profile_sync_service.h" +#include "chrome/browser/sync/test/integration/bookmarks_helper.h" +#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" +#include "chrome/browser/sync/test/integration/sync_integration_test_util.h" #include "chrome/browser/sync/test/integration/sync_test.h" #include "content/public/browser/browser_thread.h" +#include "sync/syncable/directory.h" +#include "sync/test/directory_backing_store_corruption_testing.h" +#include "url/gurl.h" using content::BrowserThread; +using sync_integration_test_util::AwaitCommitActivityCompletion; +using syncer::syncable::corruption_testing::kNumEntriesRequiredForCorruption; +using syncer::syncable::corruption_testing::CorruptDatabase; class SingleClientDirectorySyncTest : public SyncTest { public: @@ -32,6 +42,21 @@ return e.TimedWait(base::TimeDelta::FromSeconds(45)); } +// A status change checker that waits for an unrecoverable sync error to occur. +class SyncUnrecoverableErrorChecker : public SingleClientStatusChangeChecker { + public: + explicit SyncUnrecoverableErrorChecker(ProfileSyncService* service) + : SingleClientStatusChangeChecker(service) {} + + bool IsExitConditionSatisfied() override { + return service()->HasUnrecoverableError(); + } + + std::string GetDebugMessage() const override { + return "Sync Unrecoverable Error"; + } +}; + IN_PROC_BROWSER_TEST_F(SingleClientDirectorySyncTest, StopThenDisableDeletesDirectory) { ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; @@ -51,3 +76,60 @@ ASSERT_FALSE(base::DirectoryExists(directory_path)); } + +// Verify that when the sync directory's backing store becomes corrupted, we +// trigger an unrecoverable error and delete the database. +// +// If this test fails, see the definition of kNumEntriesRequiredForCorruption +// for one possible cause. +IN_PROC_BROWSER_TEST_F(SingleClientDirectorySyncTest, + DeleteDirectoryWhenCorrupted) { + ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + + // Create some bookmarks. + const GURL url("https://www.google.com"); + const bookmarks::BookmarkNode* top = bookmarks_helper::AddFolder( + 0, bookmarks_helper::GetOtherNode(0), 0, "top"); + for (int i = 0; i < kNumEntriesRequiredForCorruption; ++i) { + ASSERT_TRUE( + bookmarks_helper::AddURL(0, top, 0, base::Int64ToString(i), url)); + } + + // Sync and wait for syncing to complete. + ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + ASSERT_TRUE(AwaitCommitActivityCompletion(GetSyncService((0)))); + ASSERT_TRUE(bookmarks_helper::ModelMatchesVerifier(0)); + + // Flush the directory to the backing store and wait until the flush + // completes. + ProfileSyncService* sync_service = GetSyncService(0); + sync_service->FlushDirectory(); + base::MessageLoop* sync_loop = sync_service->GetSyncLoopForTest(); + ASSERT_TRUE(WaitForExistingTasksOnLoop(sync_loop)); + + // Now corrupt the database. + const base::FilePath directory_path(sync_service->GetDirectoryPathForTest()); + const base::FilePath sync_db(directory_path.Append( + syncer::syncable::Directory::kSyncDatabaseFilename)); + ASSERT_TRUE(CorruptDatabase(sync_db)); + + // Write a bunch more bookmarks and flush the directory to ensure sync notices + // the corruption. The key here is to force sync to actually write a lot of + // data to its DB so it will see the corruption we introduced above. + for (int i = 0; i < kNumEntriesRequiredForCorruption; ++i) { + ASSERT_TRUE( + bookmarks_helper::AddURL(0, top, 0, base::Int64ToString(i), url)); + } + sync_service->FlushDirectory(); + + // Wait for an unrecoverable error to occur. + SyncUnrecoverableErrorChecker checker(sync_service); + checker.Wait(); + ASSERT_TRUE(!checker.TimedOut()); + ASSERT_TRUE(sync_service->HasUnrecoverableError()); + + // Wait until the sync loop has processed any existing tasks and see that the + // directory no longer exists. + ASSERT_TRUE(WaitForExistingTasksOnLoop(sync_loop)); + ASSERT_FALSE(base::DirectoryExists(directory_path)); +}
diff --git a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc index 9f794cd..ddf32d0 100644 --- a/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc +++ b/chrome/browser/sync_file_system/sync_file_system_service_unittest.cc
@@ -131,7 +131,7 @@ : thread_bundle_(content::TestBrowserThreadBundle::REAL_FILE_THREAD | content::TestBrowserThreadBundle::REAL_IO_THREAD) {} - virtual void SetUp() override { + void SetUp() override { in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); file_system_.reset(new CannedSyncableFileSystem( GURL(kOrigin), @@ -165,7 +165,7 @@ file_system_->SetUp(CannedSyncableFileSystem::QUOTA_ENABLED); } - virtual void TearDown() override { + void TearDown() override { sync_service_->Shutdown(); file_system_->TearDown(); RevokeSyncableFileSystem();
diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc index b08fba6..1858854 100644 --- a/chrome/browser/themes/theme_service_factory.cc +++ b/chrome/browser/themes/theme_service_factory.cc
@@ -75,31 +75,17 @@ default_uses_system_theme = linux_ui->GetDefaultUsesSystemTheme(); #endif - registry->RegisterBooleanPref( - prefs::kUsesSystemTheme, - default_uses_system_theme, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kUsesSystemTheme, + default_uses_system_theme); #endif - registry->RegisterFilePathPref( - prefs::kCurrentThemePackFilename, - base::FilePath(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kCurrentThemeID, - ThemeService::kDefaultThemeID, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kCurrentThemeImages, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kCurrentThemeColors, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kCurrentThemeTints, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kCurrentThemeDisplayProperties, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterFilePathPref(prefs::kCurrentThemePackFilename, + base::FilePath()); + registry->RegisterStringPref(prefs::kCurrentThemeID, + ThemeService::kDefaultThemeID); + registry->RegisterDictionaryPref(prefs::kCurrentThemeImages); + registry->RegisterDictionaryPref(prefs::kCurrentThemeColors); + registry->RegisterDictionaryPref(prefs::kCurrentThemeTints); + registry->RegisterDictionaryPref(prefs::kCurrentThemeDisplayProperties); } content::BrowserContext* ThemeServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/thumbnails/thumbnail_service_unittest.cc b/chrome/browser/thumbnails/thumbnail_service_unittest.cc index e900d44b..075983a 100644 --- a/chrome/browser/thumbnails/thumbnail_service_unittest.cc +++ b/chrome/browser/thumbnails/thumbnail_service_unittest.cc
@@ -4,13 +4,19 @@ #include "chrome/browser/thumbnails/thumbnail_service_impl.h" +#include "base/bind.h" #include "base/memory/ref_counted.h" +#include "chrome/browser/history/history_utils.h" #include "chrome/browser/history/top_sites_factory.h" -#include "chrome/browser/history/top_sites_impl.h" +#include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" +#include "components/history/core/browser/top_sites_impl.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" -typedef testing::Test ThumbnailServiceTest; +class ThumbnailServiceTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; namespace { @@ -19,7 +25,11 @@ class MockTopSites : public history::TopSitesImpl { public: explicit MockTopSites(Profile* profile) - : history::TopSitesImpl(profile, history::PrepopulatedPageList()), + : history::TopSitesImpl(profile->GetPrefs(), + nullptr, + prefs::kNtpMostVisitedURLsBlacklist, + history::PrepopulatedPageList(), + base::Bind(CanAddURLToHistory)), capacity_(1) {} // history::TopSitesImpl overrides.
diff --git a/chrome/browser/translate/cld_data_harness.h b/chrome/browser/translate/cld_data_harness.h index 1ca3cb5e..6a78d78d 100644 --- a/chrome/browser/translate/cld_data_harness.h +++ b/chrome/browser/translate/cld_data_harness.h
@@ -46,7 +46,7 @@ // test::CldDataHarnessFactory::Get->CreateCldDataHarness()) { // // (your additional setup code here) // } -// virtual void SetUpOnMainThread() override { +// void SetUpOnMainThread() override { // cld_data_scope->Init(); // InProcessBrowserTest::SetUpOnMainThread(); // }
diff --git a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc index 7772956b..4eb0792 100644 --- a/chrome/browser/translate/translate_manager_render_view_host_unittest.cc +++ b/chrome/browser/translate/translate_manager_render_view_host_unittest.cc
@@ -840,8 +840,11 @@ NavEntryCommittedObserver nav_observer(web_contents()); web_contents()->GetController().LoadURL( url, content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int pending_id = + web_contents()->GetController().GetPendingEntry()->GetUniqueID(); content::RenderFrameHostTester::For(web_contents()->GetMainFrame()) - ->SendNavigateWithTransition(0, url, ui::PAGE_TRANSITION_TYPED); + ->SendNavigateWithTransition(0, pending_id, false, url, + ui::PAGE_TRANSITION_TYPED); // Test that we are really getting a same page navigation, the test would be // useless if it was not the case. @@ -894,12 +897,12 @@ // Simulate a sub-frame auto-navigating. subframe_tester->SendNavigateWithTransition( - 0, GURL("http://pub.com"), ui::PAGE_TRANSITION_AUTO_SUBFRAME); + 0, 0, false, GURL("http://pub.com"), ui::PAGE_TRANSITION_AUTO_SUBFRAME); EXPECT_TRUE(GetTranslateInfoBar() == NULL); // Simulate the user navigating in a sub-frame. subframe_tester->SendNavigateWithTransition( - 1, GURL("http://pub.com"), ui::PAGE_TRANSITION_MANUAL_SUBFRAME); + 1, 0, true, GURL("http://pub.com"), ui::PAGE_TRANSITION_MANUAL_SUBFRAME); EXPECT_TRUE(GetTranslateInfoBar() == NULL); // Navigate out of page, a new infobar should show.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 04872b7..3151b879 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -128,6 +128,7 @@ deps += [ "//components/copresence", "//components/feedback/proto", + "//components/proximity_auth/webui", "//device/bluetooth", "//third_party/libusb", ] @@ -210,6 +211,16 @@ ".", "//chrome") deps += [ "//extensions/components/native_app_window" ] + if (is_chromeos) { + # TODO(GYP): crbug.com/481629. These files should probably not be + # a part of ui_views_non_mac_sources at all. + sources -= [ + "views/frame/opaque_browser_frame_view.cc", + "views/frame/opaque_browser_frame_view.h", + "views/frame/opaque_browser_frame_view_linux.cc", + "views/frame/opaque_browser_frame_view_linux.h", + ] + } } if (use_ash) { sources += rebase_path(gypi_values.chrome_browser_ui_ash_views_sources, @@ -416,6 +427,7 @@ sources += rebase_path(gypi_values.chrome_browser_ui_media_router_sources, ".", "//chrome") + deps += [ "//chrome/browser/media/router:router_core" ] } if (enable_webrtc) { sources += rebase_path(gypi_values.chrome_browser_ui_webrtc_sources,
diff --git a/chrome/browser/ui/android/infobars/infobar_container_android.cc b/chrome/browser/ui/android/infobars/infobar_container_android.cc index 08c844bf..7e17d63e 100644 --- a/chrome/browser/ui/android/infobars/infobar_container_android.cc +++ b/chrome/browser/ui/android/infobars/infobar_container_android.cc
@@ -26,6 +26,14 @@ RemoveAllInfoBarsForDestruction(); } +void InfoBarContainerAndroid::SetWebContents(JNIEnv* env, + jobject obj, + jobject web_contents) { + InfoBarService* infobar_service = InfoBarService::FromWebContents( + content::WebContents::FromJavaWebContents(web_contents)); + ChangeInfoBarManager(infobar_service); +} + void InfoBarContainerAndroid::Destroy(JNIEnv* env, jobject obj) { delete this; } @@ -74,14 +82,9 @@ // Native JNI methods --------------------------------------------------------- -static jlong Init(JNIEnv* env, - jobject obj, - jobject web_contents) { +static jlong Init(JNIEnv* env, jobject obj) { InfoBarContainerAndroid* infobar_container = new InfoBarContainerAndroid(env, obj); - InfoBarService* infobar_service = InfoBarService::FromWebContents( - content::WebContents::FromJavaWebContents(web_contents)); - infobar_container->ChangeInfoBarManager(infobar_service); return reinterpret_cast<intptr_t>(infobar_container); }
diff --git a/chrome/browser/ui/android/infobars/infobar_container_android.h b/chrome/browser/ui/android/infobars/infobar_container_android.h index f29942e..2e22da9 100644 --- a/chrome/browser/ui/android/infobars/infobar_container_android.h +++ b/chrome/browser/ui/android/infobars/infobar_container_android.h
@@ -24,6 +24,7 @@ public: InfoBarContainerAndroid(JNIEnv* env, jobject infobar_container); + void SetWebContents(JNIEnv* env, jobject obj, jobject web_contents); void Destroy(JNIEnv* env, jobject obj); JavaObjectWeakGlobalRef java_container() const {
diff --git a/chrome/browser/ui/android/tab_model/tab_model_unittest.cc b/chrome/browser/ui/android/tab_model/tab_model_unittest.cc index 8f099e0a..103c08c 100644 --- a/chrome/browser/ui/android/tab_model/tab_model_unittest.cc +++ b/chrome/browser/ui/android/tab_model/tab_model_unittest.cc
@@ -8,10 +8,13 @@ #include "chrome/test/base/testing_profile.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -typedef testing::Test TabModelTest; +class TabModelTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; namespace { class TabModelAndroidProfileMock : public TestingProfile {
diff --git a/chrome/browser/ui/android/toolbar/toolbar_model_android.cc b/chrome/browser/ui/android/toolbar/toolbar_model_android.cc index 3990d36e..2884faf 100644 --- a/chrome/browser/ui/android/toolbar/toolbar_model_android.cc +++ b/chrome/browser/ui/android/toolbar/toolbar_model_android.cc
@@ -117,11 +117,7 @@ static const int64_t kJanuary2016 = INT64_C(13096080000000000); if (content::CertStore::GetInstance()->RetrieveCert(ssl.cert_id, &cert) && (ssl.cert_status & net::CERT_STATUS_SHA1_SIGNATURE_PRESENT) && - cert->valid_expiry() > base::Time::FromInternalValue(kJanuary2016) && - // NOTE: This use of SHA1IdentityUIWarning needs to be kept in sync - // with WebsiteSettings::Init(). - base::FieldTrialList::FindFullName("SHA1IdentityUIWarning") == - "Enabled") { + cert->valid_expiry() > base::Time::FromInternalValue(kJanuary2016)) { return true; } }
diff --git a/chrome/browser/ui/app_list/app_list_prefs.cc b/chrome/browser/ui/app_list/app_list_prefs.cc index 47f62a9..e4c37dea 100644 --- a/chrome/browser/ui/app_list/app_list_prefs.cc +++ b/chrome/browser/ui/app_list/app_list_prefs.cc
@@ -73,8 +73,7 @@ // static void AppListPrefs::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - kPrefModel, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kPrefModel); } // static
diff --git a/chrome/browser/ui/ash/chrome_launcher_prefs.cc b/chrome/browser/ui/ash/chrome_launcher_prefs.cc index 3d60817..ed925e73 100644 --- a/chrome/browser/ui/ash/chrome_launcher_prefs.cc +++ b/chrome/browser/ui/ash/chrome_launcher_prefs.cc
@@ -57,28 +57,15 @@ registry->RegisterStringPref(prefs::kShelfAutoHideBehavior, kShelfAutoHideBehaviorNever, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kShelfAutoHideBehaviorLocal, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kShelfAutoHideBehaviorLocal, + std::string()); registry->RegisterStringPref(prefs::kShelfAlignment, kShelfAlignmentBottom, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kShelfAlignmentLocal, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kShelfPreferences, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kLogoutDialogDurationMs, - 20000, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kShowLogoutButtonInTray, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kShelfAlignmentLocal, std::string()); + registry->RegisterDictionaryPref(prefs::kShelfPreferences); + registry->RegisterIntegerPref(prefs::kLogoutDialogDurationMs, 20000); + registry->RegisterBooleanPref(prefs::kShowLogoutButtonInTray, false); } base::DictionaryValue* CreateAppDict(const std::string& app_id) {
diff --git a/chrome/browser/ui/autofill/account_chooser_model_unittest.cc b/chrome/browser/ui/autofill/account_chooser_model_unittest.cc index 39fe699..e2f9b5c7 100644 --- a/chrome/browser/ui/autofill/account_chooser_model_unittest.cc +++ b/chrome/browser/ui/autofill/account_chooser_model_unittest.cc
@@ -8,6 +8,7 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/autofill/core/browser/autofill_metrics.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -53,6 +54,7 @@ TestAccountChooserModel* model() { return &model_; } private: + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; testing::NiceMock<MockAccountChooserModelDelegate> delegate_; TestAccountChooserModel model_;
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc index e1e566e..da2d94c 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc +++ b/chrome/browser/ui/autofill/autofill_dialog_controller_browsertest.cc
@@ -115,22 +115,22 @@ false); } - virtual ~TestAutofillDialogController() {} + ~TestAutofillDialogController() override {} GURL FakeSignInUrl() const { return GURL(chrome::kChromeUIVersionURL); } - virtual void ShowSignIn(const GURL& url) override { + void ShowSignIn(const GURL& url) override { AutofillDialogControllerImpl::ShowSignIn(FakeSignInUrl()); } - virtual void ViewClosed() override { + void ViewClosed() override { message_loop_runner_->Quit(); AutofillDialogControllerImpl::ViewClosed(); } - virtual base::string16 InputValidityMessage( + base::string16 InputValidityMessage( DialogSection section, ServerFieldType type, const base::string16& value) override { @@ -140,7 +140,7 @@ section, type, value); } - virtual ValidityMessages InputsAreValid( + ValidityMessages InputsAreValid( DialogSection section, const FieldValueMap& inputs) override { if (!use_validation_) @@ -150,7 +150,7 @@ // Saving to Chrome is tested in AutofillDialogControllerImpl unit tests. // TODO(estade): test that the view defaults to saving to Chrome. - virtual bool ShouldOfferToSaveInChrome() const override { + bool ShouldOfferToSaveInChrome() const override { return true; } @@ -164,7 +164,7 @@ MOCK_METHOD0(LoadRiskFingerprintData, void()); - virtual std::vector<DialogNotification> CurrentNotifications() override { + std::vector<DialogNotification> CurrentNotifications() override { return notifications_; } @@ -206,20 +206,19 @@ } protected: - virtual PersonalDataManager* GetManager() const override { + PersonalDataManager* GetManager() const override { return &const_cast<TestAutofillDialogController*>(this)->test_manager_; } - virtual AddressValidator* GetValidator() override { + AddressValidator* GetValidator() override { return &mock_validator_; } - virtual wallet::WalletClient* GetWalletClient() override { + wallet::WalletClient* GetWalletClient() override { return &mock_wallet_client_; } - virtual bool IsSignInContinueUrl(const GURL& url, size_t* user_index) const - override { + bool IsSignInContinueUrl(const GURL& url, size_t* user_index) const override { *user_index = sign_in_user_index_; return url == wallet::GetSignInContinueUrl(); }
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc index 4b7e267..3932837 100644 --- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -146,73 +146,69 @@ public: TestAutofillDialogView() : updates_started_(0), save_details_locally_checked_(true) {} - virtual ~TestAutofillDialogView() {} + ~TestAutofillDialogView() override {} - virtual void Show() override {} - virtual void Hide() override {} + void Show() override {} + void Hide() override {} - virtual void UpdatesStarted() override { + void UpdatesStarted() override { updates_started_++; } - virtual void UpdatesFinished() override { + void UpdatesFinished() override { updates_started_--; EXPECT_GE(updates_started_, 0); } - virtual void UpdateNotificationArea() override { + void UpdateNotificationArea() override { EXPECT_GE(updates_started_, 1); } - virtual void UpdateAccountChooser() override { + void UpdateAccountChooser() override { EXPECT_GE(updates_started_, 1); } - virtual void UpdateButtonStrip() override { + void UpdateButtonStrip() override { EXPECT_GE(updates_started_, 1); } - virtual void UpdateOverlay() override { + void UpdateOverlay() override { EXPECT_GE(updates_started_, 1); } - virtual void UpdateDetailArea() override { + void UpdateDetailArea() override { EXPECT_GE(updates_started_, 1); } - virtual void UpdateSection(DialogSection section) override { + void UpdateSection(DialogSection section) override { section_updates_[section]++; EXPECT_GE(updates_started_, 1); } - virtual void UpdateErrorBubble() override { + void UpdateErrorBubble() override { EXPECT_GE(updates_started_, 1); } - virtual void FillSection(DialogSection section, - ServerFieldType originating_type) override {} - virtual void GetUserInput(DialogSection section, FieldValueMap* output) - override { + void FillSection(DialogSection section, + ServerFieldType originating_type) override {} + void GetUserInput(DialogSection section, FieldValueMap* output) override { *output = outputs_[section]; } - virtual base::string16 GetCvc() override { return base::string16(); } + base::string16 GetCvc() override { return base::string16(); } - virtual bool SaveDetailsLocally() override { - return save_details_locally_checked_; - } + bool SaveDetailsLocally() override { return save_details_locally_checked_; } - virtual const content::NavigationController* ShowSignIn(const GURL& url) - override { + const content::NavigationController* ShowSignIn(const GURL& url) override { return NULL; } - virtual void HideSignIn() override {} + void HideSignIn() override {} MOCK_METHOD0(ModelChanged, void()); MOCK_METHOD0(UpdateForErrors, void()); - virtual void OnSignInResize(const gfx::Size& pref_size) override {} - virtual void ValidateSection(DialogSection) override {} + void OnSignInResize(const gfx::Size& pref_size) override {} + void ValidateSection(DialogSection) override {} void SetUserInput(DialogSection section, const FieldValueMap& map) { outputs_[section] = map; @@ -262,9 +258,9 @@ mock_new_card_bubble_controller_(mock_new_card_bubble_controller), submit_button_delay_count_(0) {} - virtual ~TestAutofillDialogController() {} + ~TestAutofillDialogController() override {} - virtual AutofillDialogView* CreateView() override { + AutofillDialogView* CreateView() override { return new testing::NiceMock<TestAutofillDialogView>(); } @@ -333,24 +329,24 @@ using AutofillDialogControllerImpl::SignedInState; protected: - virtual PersonalDataManager* GetManager() const override { + PersonalDataManager* GetManager() const override { return const_cast<TestAutofillDialogController*>(this)-> GetTestingManager(); } - virtual AddressValidator* GetValidator() override { + AddressValidator* GetValidator() override { return &mock_validator_; } - virtual wallet::WalletClient* GetWalletClient() override { + wallet::WalletClient* GetWalletClient() override { return &mock_wallet_client_; } - virtual void OpenTabWithUrl(const GURL& url) override { + void OpenTabWithUrl(const GURL& url) override { open_tab_url_ = url; } - virtual void ShowNewCreditCardBubble( + void ShowNewCreditCardBubble( scoped_ptr<CreditCard> new_card, scoped_ptr<AutofillProfile> billing_profile) override { mock_new_card_bubble_controller_->Show(new_card.Pass(), @@ -359,7 +355,7 @@ // AutofillDialogControllerImpl calls this method before showing the dialog // window. - virtual void SubmitButtonDelayBegin() override { + void SubmitButtonDelayBegin() override { // Do not delay enabling the submit button in testing. submit_button_delay_count_++; }
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc index 122bcd90..88dd2d00 100644 --- a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc +++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -80,7 +80,7 @@ test_controller_common_(new TestPopupControllerCommon(element_bounds)) { controller_common_.reset(test_controller_common_); } - virtual ~TestAutofillPopupController() {} + ~TestAutofillPopupController() override {} void set_display(const gfx::Display& display) { test_controller_common_->set_display(display); @@ -117,7 +117,7 @@ } private: - virtual void ShowView() override {} + void ShowView() override {} TestPopupControllerCommon* test_controller_common_; };
diff --git a/chrome/browser/ui/autofill/country_combobox_model_unittest.cc b/chrome/browser/ui/autofill/country_combobox_model_unittest.cc index 1952c14..8c0d88e5 100644 --- a/chrome/browser/ui/autofill/country_combobox_model_unittest.cc +++ b/chrome/browser/ui/autofill/country_combobox_model_unittest.cc
@@ -11,6 +11,7 @@ #include "components/autofill/core/browser/autofill_country.h" #include "components/autofill/core/browser/test_personal_data_manager.h" #include "components/signin/core/browser/account_tracker_service.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h" #include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui_component.h" @@ -34,6 +35,7 @@ private: // NB: order is important here - |profile_| must go down after |manager_|. + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; TestPersonalDataManager manager_; scoped_ptr<CountryComboboxModel> model_;
diff --git a/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc index 7454e2a..41f39509 100644 --- a/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc +++ b/chrome/browser/ui/autofill/generated_credit_card_bubble_controller_unittest.cc
@@ -15,6 +15,8 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/web_contents_tester.h" @@ -76,9 +78,19 @@ BackingCard()); } - void NavigateWithTransition(ui::PageTransition trans) { - content::WebContentsTester::For(test_web_contents_.get())->TestDidNavigate( - test_web_contents_->GetMainFrame(), 1, GURL("about:blank"), trans); + void NavigateWithTransition(ui::PageTransition transition) { + content::LoadCommittedDetails details; + content::FrameNavigateParams params; + + // The transition is in two places; fill in both. + scoped_ptr<content::NavigationEntry> navigation_entry( + content::NavigationEntry::Create()); + navigation_entry->SetTransitionType(transition); + params.transition = transition; + details.entry = navigation_entry.get(); + + ASSERT_NE(nullptr, controller()); + controller()->DidNavigateMainFrame(details, params); } private:
diff --git a/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc b/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc index 770be539..c252dbe 100644 --- a/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc +++ b/chrome/browser/ui/bookmarks/bookmark_ui_utils_unittest.cc
@@ -8,6 +8,7 @@ #include "chrome/test/base/testing_profile.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/test/test_bookmark_client.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #if !defined(OS_ANDROID) && !defined(OS_IOS) @@ -18,7 +19,11 @@ namespace { -TEST(BookmarkUIUtilsTest, HasBookmarkURLs) { +class BookmarkUIUtilsTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(BookmarkUIUtilsTest, HasBookmarkURLs) { bookmarks::TestBookmarkClient client; scoped_ptr<BookmarkModel> model(client.CreateModel()); @@ -60,7 +65,7 @@ EXPECT_FALSE(chrome::HasBookmarkURLs(nodes)); } -TEST(BookmarkUIUtilsTest, HasBookmarkURLsAllowedInIncognitoMode) { +TEST_F(BookmarkUIUtilsTest, HasBookmarkURLsAllowedInIncognitoMode) { bookmarks::TestBookmarkClient client; scoped_ptr<BookmarkModel> model(client.CreateModel()); TestingProfile profile;
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 8ba7764..7bd8596 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -35,8 +35,6 @@ #include "chrome/browser/background/background_contents_service_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_shutdown.h" -#include "chrome/browser/browsing_data/browsing_data_helper.h" -#include "chrome/browser/browsing_data/browsing_data_remover.h" #include "chrome/browser/character_encoding.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/tab_specific_content_settings.h" @@ -69,6 +67,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_destroyer.h" #include "chrome/browser/profiles/profile_metrics.h" +#include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/repost_form_warning_controller.h" #include "chrome/browser/search/search.h" #include "chrome/browser/sessions/session_service.h" @@ -524,11 +523,7 @@ // profile has BrowserContextKeyedServices that the Incognito profile // doesn't, so the ProfileDestroyer can't delete it properly. // TODO(mlerman): Delete the guest using an improved ProfileDestroyer. - BrowsingDataRemover* data_remover = - BrowsingDataRemover::CreateForUnboundedRange(profile_); - data_remover->Remove(BrowsingDataRemover::REMOVE_ALL, - BrowsingDataHelper::ALL); - // BrowsingDataRemover deletes itself. + profiles::RemoveBrowsingDataForProfile(profile_->GetPath()); #endif } else { // An incognito profile is no longer needed, this indirectly frees
diff --git a/chrome/browser/ui/browser_browsertest.cc b/chrome/browser/ui/browser_browsertest.cc index ac03700f..8f4764e 100644 --- a/chrome/browser/ui/browser_browsertest.cc +++ b/chrome/browser/ui/browser_browsertest.cc
@@ -2157,7 +2157,7 @@ public: LaunchBrowserWithNonAsciiUserDatadir() {} - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); base::FilePath tmp_profile = temp_dir_.path().AppendASCII("tmp_profile"); tmp_profile = tmp_profile.Append(L"Test Chrome G\u00E9raldine"); @@ -2187,7 +2187,7 @@ public: LaunchBrowserWithTrailingSlashDatadir() {} - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); base::FilePath tmp_profile = temp_dir_.path().AppendASCII("tmp_profile"); tmp_profile = tmp_profile.Append(L"Test Chrome\\");
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index ac87bb1..570de3e 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -130,12 +130,12 @@ default_browser_worker_->StartCheckIsDefault(); } - virtual ~SwitchToMetroUIHandler() { + ~SwitchToMetroUIHandler() override { default_browser_worker_->ObserverDestroyed(); } private: - virtual void SetDefaultWebClientUIState( + void SetDefaultWebClientUIState( ShellIntegration::DefaultWebClientUIState state) override { switch (state) { case ShellIntegration::STATE_PROCESSING: @@ -157,7 +157,7 @@ delete this; } - virtual void OnSetAsDefaultConcluded(bool success) override { + void OnSetAsDefaultConcluded(bool success) override { if (!success) { delete this; return; @@ -166,7 +166,7 @@ default_browser_worker_->StartCheckIsDefault(); } - virtual bool IsInteractiveSetDefaultPermitted() override { + bool IsInteractiveSetDefaultPermitted() override { return true; }
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc index 9edc021b..13bef78 100644 --- a/chrome/browser/ui/browser_ui_prefs.cc +++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -40,10 +40,7 @@ // late: we need the pref to be already initialized. Doing it here also saves // us from having to hard-code pref registration in the several unit tests // that use this preference. - registry->RegisterBooleanPref( - prefs::kShowUpdatePromotionInfoBar, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kShowUpdatePromotionInfoBar, true); #endif registry->RegisterBooleanPref( prefs::kDeleteBrowsingHistory, @@ -77,91 +74,35 @@ prefs::kDeleteTimePeriod, 0, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kLastClearBrowsingDataTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref(prefs::kModuleConflictBubbleShown, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kCheckDefaultBrowser, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebAppCreateOnDesktop, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebAppCreateInAppsMenu, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebAppCreateInQuickLaunchBar, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterInt64Pref(prefs::kLastClearBrowsingDataTime, 0); + registry->RegisterIntegerPref(prefs::kModuleConflictBubbleShown, 0); + registry->RegisterBooleanPref(prefs::kCheckDefaultBrowser, true); + registry->RegisterBooleanPref(prefs::kWebAppCreateOnDesktop, true); + registry->RegisterBooleanPref(prefs::kWebAppCreateInAppsMenu, true); + registry->RegisterBooleanPref(prefs::kWebAppCreateInQuickLaunchBar, true); registry->RegisterBooleanPref( prefs::kEnableTranslate, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kCloudPrintEmail, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kCloudPrintProxyEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kCloudPrintSubmitEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDevToolsDisabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kBrowserWindowPlacement, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kBrowserWindowPlacementPopup, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - prefs::kAppWindowPlacement, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kImportAutofillFormData, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kImportBookmarks, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kImportHistory, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kImportHomepage, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kImportSavedPasswords, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kImportSearchEngine, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kCloudPrintEmail, std::string()); + registry->RegisterBooleanPref(prefs::kCloudPrintProxyEnabled, true); + registry->RegisterBooleanPref(prefs::kCloudPrintSubmitEnabled, true); + registry->RegisterBooleanPref(prefs::kDevToolsDisabled, false); + registry->RegisterDictionaryPref(prefs::kBrowserWindowPlacement); + registry->RegisterDictionaryPref(prefs::kBrowserWindowPlacementPopup); + registry->RegisterDictionaryPref(prefs::kAppWindowPlacement); + registry->RegisterBooleanPref(prefs::kImportAutofillFormData, true); + registry->RegisterBooleanPref(prefs::kImportBookmarks, true); + registry->RegisterBooleanPref(prefs::kImportHistory, true); + registry->RegisterBooleanPref(prefs::kImportHomepage, true); + registry->RegisterBooleanPref(prefs::kImportSavedPasswords, true); + registry->RegisterBooleanPref(prefs::kImportSearchEngine, true); registry->RegisterBooleanPref( prefs::kEnableDoNotTrack, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); #if defined(ENABLE_WEBRTC) - registry->RegisterBooleanPref( - prefs::kWebRTCMultipleRoutesEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kWebRTCMultipleRoutesEnabled, true); #endif // Dictionaries to keep track of default tasks in the file browser. @@ -174,27 +115,12 @@ // We need to register the type of these preferences in order to query // them even though they're only typically controlled via policy. - registry->RegisterBooleanPref( - prefs::kPluginsAllowOutdated, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kPluginsAlwaysAuthorize, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kClearPluginLSODataEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kHideWebStoreIcon, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kPluginsAllowOutdated, false); + registry->RegisterBooleanPref(prefs::kPluginsAlwaysAuthorize, false); + registry->RegisterBooleanPref(prefs::kClearPluginLSODataEnabled, true); + registry->RegisterBooleanPref(prefs::kHideWebStoreIcon, false); #if !defined(OS_MACOSX) - registry->RegisterBooleanPref( - prefs::kFullscreenAllowed, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kFullscreenAllowed, true); #endif }
diff --git a/chrome/browser/ui/browser_view_prefs.cc b/chrome/browser/ui/browser_view_prefs.cc index 175b0c7..636cde5 100644 --- a/chrome/browser/ui/browser_view_prefs.cc +++ b/chrome/browser/ui/browser_view_prefs.cc
@@ -46,10 +46,8 @@ custom_frame_default = ui::GetCustomFramePrefDefault(); #endif - registry->RegisterBooleanPref( - prefs::kUseCustomChromeFrame, - custom_frame_default, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kUseCustomChromeFrame, + custom_frame_default); } void MigrateBrowserTabStripPrefs(PrefService* prefs) {
diff --git a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm index 37fa729..2c5212c 100644 --- a/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm +++ b/chrome/browser/ui/cocoa/autofill/password_generation_popup_view_cocoa_unittest.mm
@@ -28,31 +28,31 @@ MOCK_METHOD0(PasswordAccepted, void()); - virtual void OnSavedPasswordsLinkClicked() override {} + void OnSavedPasswordsLinkClicked() override {} - virtual int GetMinimumWidth() override { return 200; } + int GetMinimumWidth() override { return 200; } - virtual bool display_password() const override { return true; } + bool display_password() const override { return true; } - virtual bool password_selected() const override { return false; } + bool password_selected() const override { return false; } MOCK_CONST_METHOD0(password, base::string16()); - virtual base::string16 SuggestedText() override { + base::string16 SuggestedText() override { return base::ASCIIToUTF16("Suggested by Chrome"); } - virtual const base::string16& HelpText() override { return help_text_; } + const base::string16& HelpText() override { return help_text_; } - virtual const gfx::Range& HelpTextLinkRange() override { return link_range_; } + const gfx::Range& HelpTextLinkRange() override { return link_range_; } // AutofillPopupViewDelegate implementation. - virtual void Hide() override {} + void Hide() override {} MOCK_METHOD0(ViewDestroyed, void()); - virtual void SetSelectionAtPoint(const gfx::Point&) override {} - virtual bool AcceptSelectedLine() override { return true; } - virtual void SelectionCleared() override {} - virtual const gfx::Rect& popup_bounds() const override { + void SetSelectionAtPoint(const gfx::Point&) override {} + bool AcceptSelectedLine() override { return true; } + void SelectionCleared() override {} + const gfx::Rect& popup_bounds() const override { return popup_bounds_; } MOCK_METHOD0(container_view, gfx::NativeView());
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm index 8ac4371..727df0bf 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller_unittest.mm
@@ -94,7 +94,12 @@ @private NSSize cellSize_; } +#if !defined(MAC_OS_X_VERSION_10_10) || \ + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10 +// In the OSX 10.10 SDK, cellSize became an atomic property, so there is no +// need to redeclare it. @property (nonatomic, readonly) NSSize cellSize; +#endif // MAC_OS_X_VERSION_10_10 @end @implementation CellWithDesiredSize
diff --git a/chrome/browser/ui/cocoa/custom_frame_view.mm b/chrome/browser/ui/cocoa/custom_frame_view.mm index acfff1f..08ae9d42 100644 --- a/chrome/browser/ui/cocoa/custom_frame_view.mm +++ b/chrome/browser/ui/cocoa/custom_frame_view.mm
@@ -77,6 +77,12 @@ } } +// TODO(erikchen): Clang throws a warning if a designated initializer doesn't +// call the super initializer, even if the method raises an exception. These +// pragmas shouldn't be necessary. +// http://www.crbug.com/479019. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wobjc-designated-initializers" - (id)initWithFrame:(NSRect)frame { // This class is not for instantiating. [self doesNotRecognizeSelector:_cmd]; @@ -88,6 +94,7 @@ [self doesNotRecognizeSelector:_cmd]; return nil; } +#pragma clang diagnostic pop // Override to move the fullscreen button to the left of the profile avatar. - (NSPoint)_fullScreenButtonOrigin {
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm index 50cbba93..6b161ae3 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
@@ -59,7 +59,6 @@ private: // ToolbarActionViewDelegate: - ToolbarActionViewController* GetPreferredPopupViewController() override; content::WebContents* GetCurrentWebContents() const override; void UpdateState() override; void OnPopupShown(bool by_user) override; @@ -123,12 +122,6 @@ } } -ToolbarActionViewController* -ToolbarActionViewDelegateBridge::GetPreferredPopupViewController() { - return [[controller_ mainButtonForId:viewController_->GetId()] - viewController]; -} - content::WebContents* ToolbarActionViewDelegateBridge::GetCurrentWebContents() const { return [controller_ currentWebContents];
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_test_util_mac.mm b/chrome/browser/ui/cocoa/extensions/browser_action_test_util_mac.mm index da052fa..51e9f0f 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_action_test_util_mac.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_action_test_util_mac.mm
@@ -4,11 +4,14 @@ #include "chrome/browser/extensions/browser_action_test_util.h" +#include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" +#include "base/path_service.h" #include "base/strings/sys_string_conversions.h" #include "chrome/browser/ui/browser.h" #import "chrome/browser/ui/cocoa/browser_window_cocoa.h" #import "chrome/browser/ui/cocoa/browser_window_controller.h" +#import "chrome/browser/ui/cocoa/cocoa_test_helper.h" #import "chrome/browser/ui/cocoa/extensions/browser_action_button.h" #import "chrome/browser/ui/cocoa/extensions/browser_actions_container_view.h" #import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h" @@ -19,6 +22,8 @@ #import "chrome/browser/ui/cocoa/themed_window.h" #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" +#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" +#include "chrome/common/chrome_constants.h" #include "grit/theme_resources.h" #include "ui/base/theme_provider.h" #include "ui/gfx/geometry/rect.h" @@ -26,11 +31,54 @@ namespace { -BrowserActionsController* GetController( +// The Cocoa implementation of the TestToolbarActionsBarHelper, which creates +// (and owns) a BrowserActionsController and BrowserActionsContainerView for +// testing purposes. +class TestToolbarActionsBarHelperCocoa : public TestToolbarActionsBarHelper { + public: + TestToolbarActionsBarHelperCocoa(Browser* browser, + BrowserActionsController* mainController); + ~TestToolbarActionsBarHelperCocoa() override; + + BrowserActionsController* controller() { return controller_.get(); } + + private: + // The owned BrowserActionsContainerView and BrowserActionsController; the + // mac implementation of the ToolbarActionsBar delegate and view. + base::scoped_nsobject<BrowserActionsContainerView> containerView_; + base::scoped_nsobject<BrowserActionsController> controller_; + + DISALLOW_COPY_AND_ASSIGN(TestToolbarActionsBarHelperCocoa); +}; + +TestToolbarActionsBarHelperCocoa::TestToolbarActionsBarHelperCocoa( Browser* browser, - ToolbarActionsBarDelegate* barDelegate) { - if (barDelegate) - return [BrowserActionsController fromToolbarActionsBarDelegate:barDelegate]; + BrowserActionsController* mainController) { + // Make sure that Cocoa has been bootstrapped. + if (!base::mac::FrameworkBundle()) { + // Look in the framework bundle for resources. + base::FilePath path; + PathService::Get(base::DIR_EXE, &path); + path = path.Append(chrome::kFrameworkName); + base::mac::SetOverrideFrameworkBundlePath(path); + } + + containerView_.reset([[BrowserActionsContainerView alloc] + initWithFrame:NSMakeRect(0, 0, 0, 15)]); + controller_.reset( + [[BrowserActionsController alloc] initWithBrowser:browser + containerView:containerView_.get() + mainController:mainController]); +} + +TestToolbarActionsBarHelperCocoa::~TestToolbarActionsBarHelperCocoa() { +} + +BrowserActionsController* GetController(Browser* browser, + TestToolbarActionsBarHelper* helper) { + if (helper) { + return static_cast<TestToolbarActionsBarHelperCocoa*>(helper)->controller(); + } BrowserWindowCocoa* window = static_cast<BrowserWindowCocoa*>(browser->window()); @@ -40,23 +88,37 @@ BrowserActionButton* GetButton( Browser* browser, - ToolbarActionsBarDelegate* barDelegate, + TestToolbarActionsBarHelper* helper, int index) { - return [GetController(browser, barDelegate) buttonWithIndex:index]; + return [GetController(browser, helper) buttonWithIndex:index]; } } // namespace +BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser) + : BrowserActionTestUtil(browser, true) { +} + +BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser, + bool is_real_window) + : browser_(browser) { + if (!is_real_window) + test_helper_.reset(new TestToolbarActionsBarHelperCocoa(browser, nullptr)); +} + +BrowserActionTestUtil::~BrowserActionTestUtil() {} + int BrowserActionTestUtil::NumberOfBrowserActions() { - return [GetController(browser_, bar_delegate_) buttonCount]; + return [GetController(browser_, test_helper_.get()) buttonCount]; } int BrowserActionTestUtil::VisibleBrowserActions() { - return [GetController(browser_, bar_delegate_) visibleButtonCount]; + return [GetController(browser_, test_helper_.get()) visibleButtonCount]; } bool BrowserActionTestUtil::IsChevronShowing() { - BrowserActionsController* controller = GetController(browser_, bar_delegate_); + BrowserActionsController* controller = + GetController(browser_, test_helper_.get()); // The magic "18" comes from kChevronWidth in browser_actions_controller.mm. return ![controller chevronIsHidden] && NSWidth([[controller containerView] animationEndFrame]) >= 18; @@ -67,11 +129,11 @@ } bool BrowserActionTestUtil::HasIcon(int index) { - return [GetButton(browser_, bar_delegate_, index) image] != nil; + return [GetButton(browser_, test_helper_.get(), index) image] != nil; } gfx::Image BrowserActionTestUtil::GetIcon(int index) { - NSImage* ns_image = [GetButton(browser_, bar_delegate_, index) image]; + NSImage* ns_image = [GetButton(browser_, test_helper_.get(), index) image]; // gfx::Image takes ownership of the |ns_image| reference. We have to increase // the ref count so |ns_image| stays around when the image object is // destroyed. @@ -80,16 +142,17 @@ } void BrowserActionTestUtil::Press(int index) { - NSButton* button = GetButton(browser_, bar_delegate_, index); + NSButton* button = GetButton(browser_, test_helper_.get(), index); [button performClick:nil]; } std::string BrowserActionTestUtil::GetExtensionId(int index) { - return [GetButton(browser_, bar_delegate_, index) viewController]->GetId(); + return + [GetButton(browser_, test_helper_.get(), index) viewController]->GetId(); } std::string BrowserActionTestUtil::GetTooltip(int index) { - NSString* tooltip = [GetButton(browser_, bar_delegate_, index) toolTip]; + NSString* tooltip = [GetButton(browser_, test_helper_.get(), index) toolTip]; return base::SysNSStringToUTF8(tooltip); } @@ -116,7 +179,8 @@ } bool BrowserActionTestUtil::ActionButtonWantsToRun(size_t index) { - BrowserActionsController* controller = GetController(browser_, bar_delegate_); + BrowserActionsController* controller = + GetController(browser_, test_helper_.get()); ui::ThemeProvider* themeProvider = [[[controller containerView] window] themeProvider]; DCHECK(themeProvider); @@ -141,7 +205,13 @@ } ToolbarActionsBar* BrowserActionTestUtil::GetToolbarActionsBar() { - return [GetController(browser_, bar_delegate_) toolbarActionsBar]; + return [GetController(browser_, test_helper_.get()) toolbarActionsBar]; +} + +scoped_ptr<BrowserActionTestUtil> BrowserActionTestUtil::CreateOverflowBar() { + CHECK(!GetToolbarActionsBar()->in_overflow_mode()) + << "Only a main bar can create an overflow bar!"; + return make_scoped_ptr(new BrowserActionTestUtil(browser_, this)); } // static @@ -153,3 +223,10 @@ gfx::Size BrowserActionTestUtil::GetMaxPopupSize() { return gfx::Size(NSSizeToCGSize([ExtensionPopupController maxPopupSize])); } + +BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser, + BrowserActionTestUtil* main_bar) + : browser_(browser), + test_helper_(new TestToolbarActionsBarHelperCocoa( + browser_, GetController(browser_, main_bar->test_helper_.get()))) { +}
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h index 073e7dd..28b46b8 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h +++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h
@@ -115,8 +115,6 @@ @interface BrowserActionsController(TestingAPI) - (BrowserActionButton*)buttonWithIndex:(NSUInteger)index; - (ToolbarActionsBar*)toolbarActionsBar; -+ (BrowserActionsController*)fromToolbarActionsBarDelegate: - (ToolbarActionsBarDelegate*)delegate; @end #endif // CHROME_BROWSER_UI_COCOA_EXTENSIONS_BROWSER_ACTIONS_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm index 10ae632..4b5e33d 100644 --- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
@@ -184,7 +184,6 @@ bool IsAnimating() const override; void StopAnimating() override; int GetChevronWidth() const override; - bool IsPopupRunning() const override; void OnOverflowedActionWantsToRunChanged(bool overflowed_action_wants_to_run) override; void ShowExtensionMessageBubble( @@ -257,10 +256,6 @@ return kChevronWidth; } -bool ToolbarActionsBarBridge::IsPopupRunning() const { - return [ExtensionPopupController popup] != nil; -} - void ToolbarActionsBarBridge::OnOverflowedActionWantsToRunChanged( bool overflowed_action_wants_to_run) { [[controller_ toolbarController] @@ -950,9 +945,4 @@ return toolbarActionsBar_.get(); } -+ (BrowserActionsController*)fromToolbarActionsBarDelegate: - (ToolbarActionsBarDelegate*)delegate { - return static_cast<ToolbarActionsBarBridge*>(delegate)->controller_for_test(); -} - @end
diff --git a/chrome/browser/ui/cocoa/extensions/bundle_util.h b/chrome/browser/ui/cocoa/extensions/bundle_util.h new file mode 100644 index 0000000..f099f362 --- /dev/null +++ b/chrome/browser/ui/cocoa/extensions/bundle_util.h
@@ -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. + +#ifndef CHROME_BROWSER_UI_COCOA_EXTENSIONS_BUNDLE_UTIL_H_ +#define CHROME_BROWSER_UI_COCOA_EXTENSIONS_BUNDLE_UTIL_H_ + +#import <Cocoa/Cocoa.h> + +#include "chrome/browser/extensions/bundle_installer.h" + +// For each item in |items|, adds a line containing the item's icon and title +// to |items_field|. Returns the required height for |items_field| in pixels. +CGFloat PopulateBundleItemsList( + const extensions::BundleInstaller::ItemList& items, + NSView* items_field); + +#endif // CHROME_BROWSER_UI_COCOA_EXTENSIONS_BUNDLE_UTIL_H_
diff --git a/chrome/browser/ui/cocoa/extensions/bundle_util.mm b/chrome/browser/ui/cocoa/extensions/bundle_util.mm new file mode 100644 index 0000000..6207e90 --- /dev/null +++ b/chrome/browser/ui/cocoa/extensions/bundle_util.mm
@@ -0,0 +1,64 @@ +// 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/cocoa/extensions/bundle_util.h" + +#include "base/mac/mac_util.h" +#include "base/mac/scoped_nsobject.h" +#include "base/strings/sys_string_conversions.h" +#include "ui/gfx/image/image_skia.h" +#include "ui/gfx/image/image_skia_util_mac.h" +#import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" + +namespace { + +const CGFloat kExtensionIconSize = 32; + +} // namespace + +CGFloat PopulateBundleItemsList( + const extensions::BundleInstaller::ItemList& items, + NSView* items_field) { + const CGFloat title_width = + [items_field frame].size.width - kExtensionIconSize; + CGFloat offset = 0; + // Go over the items backwards, since Cocoa coords go from the bottom up. + for (size_t i = items.size(); i > 0; --i) { + const extensions::BundleInstaller::Item& item = items[i - 1]; + + NSString* title = base::SysUTF16ToNSString(item.GetNameForDisplay()); + base::scoped_nsobject<NSTextField> title_view([[NSTextField alloc] + initWithFrame:NSMakeRect(kExtensionIconSize, offset, title_width, 0)]); + [title_view setBordered:NO]; + [title_view setEditable:NO]; + [title_view setStringValue:title]; + [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:title_view]; + + NSRect title_frame = [title_view frame]; + NSRect icon_frame = + NSMakeRect(0, offset, kExtensionIconSize, kExtensionIconSize); + + // Vertically center-align icon and title. + CGFloat align = (icon_frame.size.height - title_frame.size.height) / 2; + if (align > 0) { + title_frame.origin.y += align; + [title_view setFrame:title_frame]; + } else { + icon_frame.origin.y -= align; + } + + gfx::ImageSkia skia_image = gfx::ImageSkia::CreateFrom1xBitmap(item.icon); + NSImage* image = gfx::NSImageFromImageSkiaWithColorSpace( + skia_image, base::mac::GetSystemColorSpace()); + base::scoped_nsobject<NSImageView> icon_view( + [[NSImageView alloc] initWithFrame:icon_frame]); + [icon_view setImage:image]; + + [items_field addSubview:icon_view]; + [items_field addSubview:title_view]; + + offset = NSMaxY(NSUnionRect(title_frame, icon_frame)); + } + return offset; +}
diff --git a/chrome/browser/ui/cocoa/extensions/device_permissions_view_controller.mm b/chrome/browser/ui/cocoa/extensions/device_permissions_view_controller.mm index 21207b7..e48e6e0c9 100644 --- a/chrome/browser/ui/cocoa/extensions/device_permissions_view_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/device_permissions_view_controller.mm
@@ -29,7 +29,6 @@ } - (IBAction)ok:(id)sender { - __block std::vector<scoped_refptr<device::UsbDevice>> devices; [[tableView_ selectedRowIndexes] enumerateIndexesUsingBlock:^(NSUInteger index, BOOL* stop) { prompt_->GrantDevicePermission(index);
diff --git a/chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.h b/chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.h index f4e915f..dfe55aa 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.h +++ b/chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.h
@@ -26,7 +26,6 @@ bool IsMenuRunning() const override; void RegisterCommand() override; void OnDelegateSet() override; - void CloseActivePopup() override; extensions::ExtensionViewHost* ShowPopupWithUrl( ExtensionActionViewController::PopupShowAction show_action, const GURL& popup_url,
diff --git a/chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.mm b/chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.mm index 716e262..cf76fda 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_action_platform_delegate_cocoa.mm
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "chrome/browser/extensions/extension_action.h" +#include "chrome/browser/extensions/extension_view_host.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #import "chrome/browser/ui/cocoa/browser_window_controller.h" @@ -74,12 +75,6 @@ content::Source<Profile>(controller_->browser()->profile())); } -void ExtensionActionPlatformDelegateCocoa::CloseActivePopup() { - ExtensionPopupController* popup = [ExtensionPopupController popup]; - if (popup && ![popup isClosing]) - [popup close]; -} - extensions::ExtensionViewHost* ExtensionActionPlatformDelegateCocoa::ShowPopupWithUrl( ExtensionActionViewController::PopupShowAction show_action, @@ -130,9 +125,16 @@ const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { - case extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: - CloseActivePopup(); + case extensions::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE: { + extensions::ExtensionHost* host = + content::Details<extensions::ExtensionHost>(details).ptr(); + if (host->extension_id() == controller_->GetId()) { + ExtensionPopupController* popup = [ExtensionPopupController popup]; + if (popup && ![popup isClosing] && [popup extensionViewHost] == host) + [popup close]; + } break; + } case extensions::NOTIFICATION_EXTENSION_COMMAND_BROWSER_ACTION_MAC: case extensions::NOTIFICATION_EXTENSION_COMMAND_PAGE_ACTION_MAC: { DCHECK_EQ(type,
diff --git a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm index 835ba3c..75c72aef 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_install_view_controller.mm
@@ -15,6 +15,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #import "chrome/browser/ui/chrome_style.h" +#include "chrome/browser/ui/cocoa/extensions/bundle_util.h" #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/grit/generated_resources.h" @@ -102,59 +103,90 @@ NSString* const kPermissionsDetailIndex = @"permissionsDetailIndex"; NSString* const kPermissionsDetailType = @"permissionsDetailType"; +// Computes the |control|'s desired height to fit its contents, constrained to +// be kMaxControlHeight at most. +CGFloat ComputeDesiredControlHeight(NSControl* control) { + NSRect rect = [control frame]; + rect.size.height = kMaxControlHeight; + return [[control cell] cellSizeForBounds:rect].height; +} + // Adjust the |control|'s height so that its content is not clipped. -// This also adds the change in height to the |totalOffset| and shifts the +// This also adds the change in height to the |total_offset| and shifts the // control down by that amount. void OffsetControlVerticallyToFitContent(NSControl* control, - CGFloat* totalOffset) { + CGFloat* total_offset) { // Adjust the control's height so that its content is not clipped. - NSRect currentRect = [control frame]; - NSRect fitRect = currentRect; - fitRect.size.height = kMaxControlHeight; - CGFloat desiredHeight = [[control cell] cellSizeForBounds:fitRect].height; - CGFloat offset = desiredHeight - NSHeight(currentRect); + NSRect current_rect = [control frame]; + CGFloat desired_height = ComputeDesiredControlHeight(control); + CGFloat offset = desired_height - NSHeight(current_rect); - [control setFrameSize:NSMakeSize(NSWidth(currentRect), - NSHeight(currentRect) + offset)]; + [control setFrameSize:NSMakeSize(NSWidth(current_rect), + NSHeight(current_rect) + offset)]; - *totalOffset += offset; + *total_offset += offset; // Move the control vertically by the new total offset. NSPoint origin = [control frame].origin; - origin.y -= *totalOffset; + origin.y -= *total_offset; [control setFrameOrigin:origin]; } -// Gets the desired height of |outlineView|. Simply using the view's frame +// Adjust the |view|'s height so that its subviews are not clipped. +// This also adds the change in height to the |total_offset| and shifts the +// control down by that amount. +void OffsetViewVerticallyToFitContent(NSView* view, CGFloat* total_offset) { + // Adjust the view's height so that its subviews are not clipped. + CGFloat desired_height = 0; + for (NSView* subview in [view subviews]) { + int required_height = NSMaxY([subview frame]); + if (required_height > desired_height) + desired_height = required_height; + } + NSRect current_rect = [view frame]; + CGFloat offset = desired_height - NSHeight(current_rect); + + [view setFrameSize:NSMakeSize(NSWidth(current_rect), + NSHeight(current_rect) + offset)]; + + *total_offset += offset; + + // Move the view vertically by the new total offset. + NSPoint origin = [view frame].origin; + origin.y -= *total_offset; + [view setFrameOrigin:origin]; +} + +// Gets the desired height of |outline_view|. Simply using the view's frame // doesn't work if an animation is pending. -CGFloat GetDesiredOutlineViewHeight(NSOutlineView* outlineView) { +CGFloat GetDesiredOutlineViewHeight(NSOutlineView* outline_view) { CGFloat height = 0; - for (NSInteger i = 0; i < [outlineView numberOfRows]; ++i) - height += NSHeight([outlineView rectOfRow:i]); + for (NSInteger i = 0; i < [outline_view numberOfRows]; ++i) + height += NSHeight([outline_view rectOfRow:i]); return height; } -void OffsetOutlineViewVerticallyToFitContent(NSOutlineView* outlineView, - CGFloat* totalOffset) { - NSScrollView* scrollView = [outlineView enclosingScrollView]; - NSRect frame = [scrollView frame]; - CGFloat desiredHeight = GetDesiredOutlineViewHeight(outlineView); - if (desiredHeight > kMaxControlHeight) - desiredHeight = kMaxControlHeight; - CGFloat offset = desiredHeight - NSHeight(frame); +void OffsetOutlineViewVerticallyToFitContent(NSOutlineView* outline_view, + CGFloat* total_offset) { + NSScrollView* scroll_view = [outline_view enclosingScrollView]; + NSRect frame = [scroll_view frame]; + CGFloat desired_height = GetDesiredOutlineViewHeight(outline_view); + if (desired_height > kMaxControlHeight) + desired_height = kMaxControlHeight; + CGFloat offset = desired_height - NSHeight(frame); frame.size.height += offset; - *totalOffset += offset; + *total_offset += offset; // Move the control vertically by the new total offset. - frame.origin.y -= *totalOffset; - [scrollView setFrame:frame]; + frame.origin.y -= *total_offset; + [scroll_view setFrame:frame]; } -void AppendRatingStarsShim(const gfx::ImageSkia* skiaImage, void* data) { +void AppendRatingStarsShim(const gfx::ImageSkia* skia_image, void* data) { ExtensionInstallViewController* controller = static_cast<ExtensionInstallViewController*>(data); - [controller appendRatingStar:skiaImage]; + [controller appendRatingStar:skia_image]; } void DrawBulletInFrame(NSRect frame) { @@ -270,9 +302,7 @@ gfx::SkColorToCalibratedNSColor(chrome_style::GetLinkColor())]; } - // The bundle install dialog has no icon. - if (![self isBundleInstall]) - [iconView_ setImage:prompt_->icon().ToNSImage()]; + [iconView_ setImage:prompt_->icon().ToNSImage()]; // The dialog is laid out in the NIB exactly how we want it assuming that // each label fits on one line. However, for each label, we want to allow @@ -309,22 +339,12 @@ } if ([self isBundleInstall]) { - // We display the list of extension names as a simple text string, seperated - // by newlines. BundleInstaller::ItemList items = prompt_->bundle()->GetItemsWithState( BundleInstaller::Item::STATE_PENDING); + PopulateBundleItemsList(items, itemsField_); - NSMutableString* joinedItems = [NSMutableString string]; - for (size_t i = 0; i < items.size(); ++i) { - if (i > 0) - [joinedItems appendString:@"\n"]; - [joinedItems appendString:base::SysUTF16ToNSString( - items[i].GetNameForDisplay())]; - } - [itemsField_ setStringValue:joinedItems]; - - // Adjust the controls to fit the list of extensions. - OffsetControlVerticallyToFitContent(itemsField_, &totalOffset); + // Adjust the view to fit the list of extensions. + OffsetViewVerticallyToFitContent(itemsField_, &totalOffset); } // If there are any warnings, retained devices or retained files, then we
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h index 4840414..2d3f2a19 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h +++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h
@@ -95,9 +95,9 @@ base::scoped_nsobject<HyperlinkTextView> promo_; // Only shown for bundle installs. IBOutlet NSTextField* installedHeadingMsg_; - IBOutlet NSTextField* installedItemsMsg_; + IBOutlet NSView* installedItemsView_; IBOutlet NSTextField* failedHeadingMsg_; - IBOutlet NSTextField* failedItemsMsg_; + IBOutlet NSView* failedItemsView_; } @property(nonatomic, readonly) const extensions::BundleInstaller* bundle;
diff --git a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm index d42ba95..1d56a8cf 100644 --- a/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.mm
@@ -19,6 +19,7 @@ #include "chrome/browser/ui/cocoa/browser_window_cocoa.h" #include "chrome/browser/ui/cocoa/browser_window_controller.h" #include "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h" +#include "chrome/browser/ui/cocoa/extensions/bundle_util.h" #include "chrome/browser/ui/cocoa/hover_close_button.h" #include "chrome/browser/ui/cocoa/info_bubble_view.h" #include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" @@ -337,12 +338,12 @@ if (type_ == extension_installed_bubble::kBundle) { NSInteger installedListHeight = [self addExtensionList:installedHeadingMsg_ - itemsMsg:installedItemsMsg_ + itemsView:installedItemsView_ state:BundleInstaller::Item::STATE_INSTALLED]; NSInteger failedListHeight = [self addExtensionList:failedHeadingMsg_ - itemsMsg:failedItemsMsg_ + itemsView:failedItemsView_ state:BundleInstaller::Item::STATE_FAILED]; newWindowHeight += installedListHeight + failedListHeight; @@ -462,41 +463,36 @@ } - (NSInteger)addExtensionList:(NSTextField*)headingMsg - itemsMsg:(NSTextField*)itemsMsg + itemsView:(NSView*)itemsView state:(BundleInstaller::Item::State)state { base::string16 heading = bundle_->GetHeadingTextFor(state); bool hidden = heading.empty(); [headingMsg setHidden:hidden]; - [itemsMsg setHidden:hidden]; + [itemsView setHidden:hidden]; if (hidden) return 0; [headingMsg setStringValue:base::SysUTF16ToNSString(heading)]; [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:headingMsg]; - NSMutableString* joinedItems = [NSMutableString string]; - BundleInstaller::ItemList items = bundle_->GetItemsWithState(state); - for (size_t i = 0; i < items.size(); ++i) { - if (i > 0) - [joinedItems appendString:@"\n"]; - [joinedItems appendString:base::SysUTF16ToNSString( - items[i].GetNameForDisplay())]; - } + CGFloat height = + PopulateBundleItemsList(bundle_->GetItemsWithState(state), itemsView); - [itemsMsg setStringValue:joinedItems]; - [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:itemsMsg]; + NSRect frame = [itemsView frame]; + frame.size.height = height; + [itemsView setFrame:frame]; return NSHeight([headingMsg frame]) + extension_installed_bubble::kInnerVerticalMargin + - NSHeight([itemsMsg frame]); + NSHeight([itemsView frame]); } // Adjust y-position of messages to sit properly in new window height. - (void)setMessageFrames:(int)newWindowHeight { if (type_ == extension_installed_bubble::kBundle) { // Layout the messages from the bottom up. - NSTextField* msgs[] = { failedItemsMsg_, failedHeadingMsg_, - installedItemsMsg_, installedHeadingMsg_ }; + NSView* msgs[] = { failedItemsView_, failedHeadingMsg_, + installedItemsView_, installedHeadingMsg_ }; NSInteger offsetFromBottom = 0; BOOL isFirstVisible = YES; for (size_t i = 0; i < arraysize(msgs); ++i) {
diff --git a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_unittest.mm b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_unittest.mm index 396eba4..0621695 100644 --- a/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_unittest.mm +++ b/chrome/browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_unittest.mm
@@ -50,9 +50,9 @@ class MediaGalleriesDialogTest : public testing::Test { public: MediaGalleriesDialogTest() {} - virtual ~MediaGalleriesDialogTest() {} + ~MediaGalleriesDialogTest() override {} - virtual void SetUp() override { + void SetUp() override { std::vector<base::string16> headers; headers.push_back(base::string16()); headers.push_back(base::ASCIIToUTF16("header2")); @@ -62,7 +62,7 @@ Times(AnyNumber()); } - virtual void TearDown() override { + void TearDown() override { Mock::VerifyAndClearExpectations(&controller_); dialog_.reset(); }
diff --git a/chrome/browser/ui/cocoa/extensions/test_toolbar_actions_bar_helper_cocoa.mm b/chrome/browser/ui/cocoa/extensions/test_toolbar_actions_bar_helper_cocoa.mm deleted file mode 100644 index aa3b39c7..0000000 --- a/chrome/browser/ui/cocoa/extensions/test_toolbar_actions_bar_helper_cocoa.mm +++ /dev/null
@@ -1,65 +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 "chrome/browser/ui/toolbar/test_toolbar_actions_bar_helper.h" - -#import "base/mac/scoped_nsobject.h" -#import "chrome/browser/ui/cocoa/extensions/browser_actions_container_view.h" -#import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h" -#import "chrome/browser/ui/cocoa/cocoa_test_helper.h" - -namespace { - -// The Cocoa implementation of the TestToolbarActionsBarHelper, which creates -// (and owns) a BrowserActionsController and BrowserActionsContainerView for -// testing purposes. -class TestToolbarActionsBarHelperCocoa : public TestToolbarActionsBarHelper { - public: - TestToolbarActionsBarHelperCocoa(Browser* browser, - TestToolbarActionsBarHelperCocoa* mainBar); - ~TestToolbarActionsBarHelperCocoa() override; - - private: - // TestToolbarActionsBarHelper: - ToolbarActionsBar* GetToolbarActionsBar() override; - - // The owned BrowserActionsContainerView and BrowserActionsController; the - // mac implementation of the ToolbarActionsBar delegate and view. - base::scoped_nsobject<BrowserActionsContainerView> containerView_; - base::scoped_nsobject<BrowserActionsController> controller_; - - DISALLOW_COPY_AND_ASSIGN(TestToolbarActionsBarHelperCocoa); -}; - -TestToolbarActionsBarHelperCocoa::TestToolbarActionsBarHelperCocoa( - Browser* browser, - TestToolbarActionsBarHelperCocoa* mainBar) { - // Make sure that Cocoa has been bootstrapped. - CocoaTest::BootstrapCocoa(); - - containerView_.reset([[BrowserActionsContainerView alloc] - initWithFrame:NSMakeRect(0, 0, 0, 15)]); - BrowserActionsController* mainController = - mainBar ? mainBar->controller_.get() : nil; - controller_.reset([[BrowserActionsController alloc] - initWithBrowser:browser - containerView:containerView_.get() - mainController:mainController]); -} - -TestToolbarActionsBarHelperCocoa::~TestToolbarActionsBarHelperCocoa() {} - -ToolbarActionsBar* TestToolbarActionsBarHelperCocoa::GetToolbarActionsBar() { - return [controller_ toolbarActionsBar]; -} - -} // namespace - -scoped_ptr<TestToolbarActionsBarHelper> TestToolbarActionsBarHelper::Create( - Browser* browser, - TestToolbarActionsBarHelper* main_bar) { - return make_scoped_ptr(new TestToolbarActionsBarHelperCocoa( - browser, - static_cast<TestToolbarActionsBarHelperCocoa*>(main_bar))); -}
diff --git a/chrome/browser/ui/cocoa/infobars/translate_infobar_unittest.mm b/chrome/browser/ui/cocoa/infobars/translate_infobar_unittest.mm index 04f4fe8..d16e8067 100644 --- a/chrome/browser/ui/cocoa/infobars/translate_infobar_unittest.mm +++ b/chrome/browser/ui/cocoa/infobars/translate_infobar_unittest.mm
@@ -57,11 +57,11 @@ MOCK_METHOD0(TranslationDeclined, void()); - virtual bool IsTranslatableLanguageByPrefs() override { return true; } + bool IsTranslatableLanguageByPrefs() override { return true; } MOCK_METHOD0(ToggleTranslatableLanguageByPrefs, void()); - virtual bool IsSiteBlacklisted() override { return false; } + bool IsSiteBlacklisted() override { return false; } MOCK_METHOD0(ToggleSiteBlacklist, void()); - virtual bool ShouldAlwaysTranslate() override { return false; } + bool ShouldAlwaysTranslate() override { return false; } MOCK_METHOD0(ToggleAlwaysTranslate, void()); };
diff --git a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h index 9880790..a9defee 100644 --- a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h +++ b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h
@@ -67,7 +67,6 @@ void SetToolTip(const base::string16& tooltip); // Overridden from ToolbarActionViewDelegate: - ToolbarActionViewController* GetPreferredPopupViewController() override; content::WebContents* GetCurrentWebContents() const override; void UpdateState() override;
diff --git a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm index ff473dd9..cd042ef6 100644 --- a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm +++ b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.mm
@@ -39,8 +39,8 @@ page_action->extension_id()); DCHECK(extension); - viewController_.reset( - new ExtensionActionViewController(extension, browser, page_action)); + viewController_.reset(new ExtensionActionViewController( + extension, browser, page_action, nullptr)); viewController_->SetDelegate(this); // We set the owner last of all so that we can determine whether we are in @@ -144,11 +144,6 @@ tooltip_.reset([nsTooltip retain]); } -ToolbarActionViewController* -PageActionDecoration::GetPreferredPopupViewController() { - return viewController_.get(); -} - content::WebContents* PageActionDecoration::GetCurrentWebContents() const { return owner_ ? owner_->GetWebContents() : nullptr; }
diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm index c6a2a6e..e3aaaa3c 100644 --- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm +++ b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm
@@ -5,9 +5,11 @@ #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h" #include "base/bind.h" +#include "base/command_line.h" #import "base/mac/bundle_locations.h" #include "base/strings/sys_string_conversions.h" #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h" +#include "chrome/common/chrome_switches.h" #include "chrome/grit/generated_resources.h" #include "content/public/browser/browser_thread.h" #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h" @@ -283,6 +285,15 @@ imageTitle:imageTitle]); [items_ insertObject:item atIndex:index]; [sourceBrowser_ reloadData]; + + NSString* autoselectSource = base::SysUTF8ToNSString( + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kAutoSelectDesktopCaptureSource)); + + if ([autoselectSource isEqualToString:imageTitle]) { + [self reportResult:[item sourceID]]; + [self close]; + } } - (void)sourceRemovedAtIndex:(int)index {
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h index 174fee1..ec0d2c13 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h
@@ -33,7 +33,6 @@ void OnTabChanged(const content::WebContents* web_contents) override; void ResetTabState(content::WebContents* web_contents) override; void Update() override; - void UpdatePlaceholderText() override; void OpenMatch(const AutocompleteMatch& match, WindowOpenDisposition disposition, const GURL& alternate_nav_url,
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm index 66a1bc2..d4aebcc0 100644 --- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm +++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.mm
@@ -214,8 +214,6 @@ } void OmniboxViewMac::Update() { - UpdatePlaceholderText(); - if (model()->UpdatePermanentText()) { // Something visibly changed. Re-enable URL replacement. controller()->GetToolbarModel()->set_url_replacement_enabled(true); @@ -237,20 +235,6 @@ } } -void OmniboxViewMac::UpdatePlaceholderText() { - if (OmniboxFieldTrial::DisplayHintTextWhenPossible()) { - NSDictionary* placeholder_attributes = @{ - NSForegroundColorAttributeName : [NSColor disabledControlTextColor] - }; - base::scoped_nsobject<NSMutableAttributedString> placeholder_text( - [[NSMutableAttributedString alloc] - initWithString:base::SysUTF16ToNSString(GetHintText()) - attributes:placeholder_attributes]); - ApplyTextStyle(placeholder_text); - [[field_ cell] setPlaceholderAttributedString:placeholder_text]; - } -} - void OmniboxViewMac::OpenMatch(const AutocompleteMatch& match, WindowOpenDisposition disposition, const GURL& alternate_nav_url,
diff --git a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm index dd1b20e..5c2936f 100644 --- a/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/one_click_signin_bubble_controller_unittest.mm
@@ -31,7 +31,7 @@ weak_ptr_factory_.GetWeakPtr()); } - virtual void SetUp() override { + void SetUp() override { CocoaProfileTest::SetUp(); BrowserWindowCocoa* browser_window = static_cast<BrowserWindowCocoa*>(browser()->window()); @@ -45,7 +45,7 @@ [[controller_ viewController] nibName]); } - virtual void TearDown() override { + void TearDown() override { controller_.reset(); CocoaProfileTest::TearDown(); }
diff --git a/chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller_unittest.mm index d357b89..475e5e82 100644 --- a/chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller_unittest.mm
@@ -17,6 +17,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/signin/core/common/profile_management_switches.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest_mac.h" #import "ui/base/cocoa/controls/hyperlink_button_cell.h" #include "ui/events/test/cocoa_test_event_utils.h" @@ -67,6 +68,7 @@ } private: + content::TestBrowserThreadBundle thread_bundle_; TestingProfileManager manager_; // Weak; releases self.
diff --git a/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm b/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm index 437bed15..5ee576fe 100644 --- a/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm +++ b/chrome/browser/ui/cocoa/profiles/profile_menu_controller.mm
@@ -5,6 +5,7 @@ #import "chrome/browser/ui/cocoa/profiles/profile_menu_controller.h" #include "base/mac/scoped_nsobject.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/sys_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/avatar_menu.h" @@ -25,6 +26,20 @@ #include "ui/base/l10n/l10n_util_mac.h" #include "ui/gfx/image/image.h" +namespace { + +// Used in UMA histogram macros, shouldn't be reordered or renumbered +enum ValidateMenuItemSelector { + UNKNOWN_SELECTOR = 0, + NEW_PROFILE, + EDIT_PROFILE, + SWITCH_PROFILE_MENU, + SWITCH_PROFILE_DOCK, + MAX_VALIDATE_MENU_SELECTOR, +}; + +} // namespace + @interface ProfileMenuController (Private) - (void)initializeMenu; @end @@ -169,8 +184,31 @@ [menuItem action] != @selector(editProfile:); } - const AvatarMenu::Item& itemData = avatarMenu_->GetItemAt( - avatarMenu_->GetActiveProfileIndex()); + size_t index = avatarMenu_->GetActiveProfileIndex(); + if (avatarMenu_->GetNumberOfItems() <= index) { + ValidateMenuItemSelector currentSelector = UNKNOWN_SELECTOR; + if ([menuItem action] == @selector(newProfile:)) + currentSelector = NEW_PROFILE; + else if ([menuItem action] == @selector(editProfile:)) + currentSelector = EDIT_PROFILE; + else if ([menuItem action] == @selector(switchToProfileFromMenu:)) + currentSelector = SWITCH_PROFILE_MENU; + else if ([menuItem action] == @selector(switchToProfileFromDock:)) + currentSelector = SWITCH_PROFILE_DOCK; + UMA_HISTOGRAM_BOOLEAN("Profile.ValidateMenuItemInvalidIndex.IsGuest", + activeProfile->IsGuestSession()); + UMA_HISTOGRAM_CUSTOM_COUNTS( + "Profile.ValidateMenuItemInvalidIndex.ProfileCount", + avatarMenu_->GetNumberOfItems(), + 1, 20, 20); + UMA_HISTOGRAM_ENUMERATION("Profile.ValidateMenuItemInvalidIndex.Selector", + currentSelector, + MAX_VALIDATE_MENU_SELECTOR); + + return NO; + } + + const AvatarMenu::Item& itemData = avatarMenu_->GetItemAt(index); if ([menuItem action] == @selector(switchToProfileFromDock:) || [menuItem action] == @selector(switchToProfileFromMenu:)) { if (!itemData.legacy_supervised)
diff --git a/chrome/browser/ui/cocoa/status_bubble_mac.mm b/chrome/browser/ui/cocoa/status_bubble_mac.mm index 667d952..7380c06 100644 --- a/chrome/browser/ui/cocoa/status_bubble_mac.mm +++ b/chrome/browser/ui/cocoa/status_bubble_mac.mm
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/compiler_specific.h" +#include "base/debug/stack_trace.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_block.h" #include "base/mac/sdk_forward_declarations.h" @@ -142,6 +143,32 @@ @end +// Mac implementation of the status bubble. +// +// Child windows interact with Spaces in interesting ways, so this code has to +// follow these rules: +// +// 1) NSWindows cannot have zero size. At times when the status bubble window +// has no specific size (for example, when hidden), its size is set to +// ui::kWindowSizeDeterminedLater. +// +// 2) Child window frames are in the coordinate space of the screen, not of the +// parent window. If a child window has its origin at (0, 0), Spaces will +// position it in the corner of the screen but group it with the parent +// window in Spaces. This causes Chrome windows to have a large (mostly +// blank) area in Spaces. To avoid this, child windows always have their +// origin set to the lower-left corner of the window. +// +// 3) Detached child windows may show up as top-level windows in Spaces. To +// avoid this, once the status bubble is Attach()ed to the parent, it is +// never detached (except in rare cases when reparenting to a fullscreen +// window). +// +// 4) To avoid unnecessary redraws, if a bubble is in the kBubbleHidden state, +// its size is always set to ui::kWindowSizeDeterminedLater. The proper +// width for the current URL or status text is not calculated until the +// bubble leaves the kBubbleHidden state. + StatusBubbleMac::StatusBubbleMac(NSWindow* parent, id delegate) : parent_(parent), delegate_(delegate), @@ -177,16 +204,25 @@ url_ = url; languages_ = languages; - NSRect frame = [window_ frame]; - - // Reset frame size when bubble is hidden. + CGFloat bubble_width = NSWidth([window_ frame]); if (state_ == kBubbleHidden) { - is_expanded_ = false; - frame.size.width = NSWidth(CalculateWindowFrame(/*expand=*/false)); - [window_ setFrame:frame display:NO]; + // TODO(rohitrao): The window size is expected to be (1,1) whenever the + // window is hidden, but the GPU bots are hitting cases where this is not + // true. Instead of enforcing this invariant with a DCHECK, add temporary + // logging to try and debug it and fix up the window size if needed. + // This logging is temporary and should be removed: crbug.com/467998 + NSRect frame = [window_ frame]; + if (!CGSizeEqualToSize(frame.size, ui::kWindowSizeDeterminedLater.size)) { + LOG(ERROR) << "Window size should be (1,1), but is instead (" + << frame.size.width << "," << frame.size.height << ")"; + LOG(ERROR) << base::debug::StackTrace().ToString(); + frame.size = ui::kWindowSizeDeterminedLater.size; + [window_ setFrame:frame display:NO]; + } + bubble_width = NSWidth(CalculateWindowFrame(/*expand=*/false)); } - int text_width = static_cast<int>(NSWidth(frame) - + int text_width = static_cast<int>(bubble_width - kBubbleViewTextPositionX - kTextPadding); @@ -260,8 +296,10 @@ show = false; if (show) { - UpdateSizeAndPosition(); + // Call StartShowing() first to update the current bubble state before + // calculating a new size. StartShowing(); + UpdateSizeAndPosition(); } else { StartHiding(); } @@ -284,21 +322,22 @@ } } + NSRect frame = CalculateWindowFrame(/*expand=*/false); if (!fade_out) { // No animation is in progress, so the opacity can be set directly. [window_ setAlphaValue:0.0]; SetState(kBubbleHidden); + frame.size = ui::kWindowSizeDeterminedLater.size; } // Stop any width animation and reset the bubble size. if (!immediate_) { [NSAnimationContext beginGrouping]; [[NSAnimationContext currentContext] setDuration:kMinimumTimeInterval]; - [[window_ animator] setFrame:CalculateWindowFrame(/*expand=*/false) - display:NO]; + [[window_ animator] setFrame:frame display:NO]; [NSAnimationContext endGrouping]; } else { - [window_ setFrame:CalculateWindowFrame(/*expand=*/false) display:NO]; + [window_ setFrame:frame display:NO]; } [status_text_ release]; @@ -446,7 +485,14 @@ DCHECK(is_attached()); // Magic setFrame: See http://crbug.com/58506 and http://crrev.com/3564021 . - [window_ setFrame:CalculateWindowFrame(/*expand=*/false) display:NO]; + // TODO(rohitrao): Does the frame size actually matter here? Can we always + // set it to kWindowSizeDeterminedLater? + NSRect frame = [window_ frame]; + frame.size = ui::kWindowSizeDeterminedLater.size; + if (state_ != kBubbleHidden) { + frame = CalculateWindowFrame(/*expand=*/false); + } + [window_ setFrame:frame display:NO]; [parent_ removeChildWindow:window_]; // See crbug.com/28107 ... [window_ orderOut:nil]; // ... and crbug.com/29054. @@ -472,6 +518,8 @@ return; if (state == kBubbleHidden) { + is_expanded_ = false; + // When hidden (with alpha of 0), make the window have the minimum size, // while still keeping the same origin. It's important to not set the // origin to 0,0 as that will cause the window to use more space in @@ -717,6 +765,31 @@ if (!window_) return; + // There is no need to update the size if the bubble is hidden. + if (state_ == kBubbleHidden) { + // Verify that hidden bubbles always have size equal to + // ui::kWindowSizeDeterminedLater. + + // TODO(rohitrao): The GPU bots are hitting cases where this is not true. + // Instead of enforcing this invariant with a DCHECK, add temporary logging + // to try and debug it and fix up the window size if needed. + // This logging is temporary and should be removed: crbug.com/467998 + NSRect frame = [window_ frame]; + if (!CGSizeEqualToSize(frame.size, ui::kWindowSizeDeterminedLater.size)) { + LOG(ERROR) << "Window size should be (1,1), but is instead (" + << frame.size.width << "," << frame.size.height << ")"; + LOG(ERROR) << base::debug::StackTrace().ToString(); + frame.size = ui::kWindowSizeDeterminedLater.size; + } + + // During the fullscreen animation, the parent window's origin may change + // without updating the status bubble. To avoid animation glitches, always + // update the bubble's origin to match the parent's, even when hidden. + frame.origin = [parent_ frame].origin; + [window_ setFrame:frame display:NO]; + return; + } + SetFrameAvoidingMouse(CalculateWindowFrame(/*expand=*/false), GetMouseLocation()); }
diff --git a/chrome/browser/ui/cocoa/status_bubble_mac_unittest.mm b/chrome/browser/ui/cocoa/status_bubble_mac_unittest.mm index a828a43..0ffc1133 100644 --- a/chrome/browser/ui/cocoa/status_bubble_mac_unittest.mm +++ b/chrome/browser/ui/cocoa/status_bubble_mac_unittest.mm
@@ -667,3 +667,19 @@ ASSERT_TRUE(CheckAvoidsMouse(x, smallValue)); } } + +TEST_F(StatusBubbleMacTest, ReparentBubble) { + // The second window is borderless, like the window used in fullscreen mode. + base::scoped_nsobject<NSWindow> fullscreenParent( + [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 800, 600) + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:NO]); + + // Switch parents with the bubble hidden. + bubble_->SwitchParentWindow(fullscreenParent); + + // Switch back to the original parent with the bubble showing. + bubble_->SetStatus(UTF8ToUTF16("Showing")); + bubble_->SwitchParentWindow(test_window()); +}
diff --git a/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h b/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h index 6d5b2236..e7cbc171 100644 --- a/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h +++ b/chrome/browser/ui/cocoa/tab_contents/instant_overlay_controller_mac.h
@@ -16,11 +16,11 @@ public: InstantOverlayControllerMac(Browser* browser, OverlayableContentsController* overlay); - virtual ~InstantOverlayControllerMac(); + ~InstantOverlayControllerMac() override; private: // Overridden from InstantOverlayController: - virtual void OverlayStateChanged(const InstantOverlayModel& model) override; + void OverlayStateChanged(const InstantOverlayModel& model) override; OverlayableContentsController* const overlay_;
diff --git a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller_unittest.mm b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller_unittest.mm index 1699a49..ee0a496 100644 --- a/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/website_settings/permission_bubble_controller_unittest.mm
@@ -52,7 +52,7 @@ MOCK_METHOD0(Closing, void()); MOCK_METHOD1(SetView, void(PermissionBubbleView*)); - virtual void SetUp() override { + void SetUp() override { CocoaTest::SetUp(); bridge_.reset(new PermissionBubbleCocoa(nil)); AddRequest(kPermissionA); @@ -61,7 +61,7 @@ bridge:bridge_.get()]; } - virtual void TearDown() override { + void TearDown() override { [controller_ close]; chrome::testing::NSRunLoopRunAllPending(); STLDeleteElements(&requests_);
diff --git a/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm b/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm index c67b35a..38d94ad 100644 --- a/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm +++ b/chrome/browser/ui/cocoa/window_size_autosaver_unittest.mm
@@ -29,10 +29,8 @@ defer:NO]; // TODO(joi): Do all registration up front. static_cast<user_prefs::PrefRegistrySyncable*>( - profile()->GetPrefs()->DeprecatedGetPrefRegistry())-> - RegisterDictionaryPref( - path_, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + profile()->GetPrefs()->DeprecatedGetPrefRegistry()) + ->RegisterDictionaryPref(path_); } void TearDown() override {
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc index 28e7c27..5fd817a 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
@@ -51,8 +51,8 @@ void UpdateFullscreenWithToolbar(bool with_toolbar) override; bool IsFullscreenWithToolbar() const override; #if defined(OS_WIN) - virtual void SetMetroSnapMode(bool enable) override; - virtual bool IsInMetroSnapMode() const override; + void SetMetroSnapMode(bool enable) override; + bool IsInMetroSnapMode() const override; #endif static const char* GetWindowStateString(WindowState state); WindowState state() const { return state_; }
diff --git a/chrome/browser/ui/extensions/extension_action_platform_delegate.h b/chrome/browser/ui/extensions/extension_action_platform_delegate.h index 89be6c2..d4d3dc7 100644 --- a/chrome/browser/ui/extensions/extension_action_platform_delegate.h +++ b/chrome/browser/ui/extensions/extension_action_platform_delegate.h
@@ -30,9 +30,6 @@ // Called once the delegate is set, in order to do any extra initialization. virtual void OnDelegateSet() = 0; - // Closes the active popup (whether it was this action's popup or not). - virtual void CloseActivePopup() = 0; - // Shows the popup for the extension action, given the associated |popup_url|. // |grant_tab_permissions| is true if active tab permissions should be given // to the extension; this is only true if the popup is opened through a user
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.cc b/chrome/browser/ui/extensions/extension_action_view_controller.cc index 1b759012..76ab240 100644 --- a/chrome/browser/ui/extensions/extension_action_view_controller.cc +++ b/chrome/browser/ui/extensions/extension_action_view_controller.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/extensions/accelerator_priority.h" #include "chrome/browser/ui/extensions/extension_action_platform_delegate.h" #include "chrome/browser/ui/toolbar/toolbar_action_view_delegate.h" +#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" #include "chrome/common/extensions/api/extension_action/action_info.h" #include "extensions/browser/extension_host.h" #include "extensions/browser/extension_registry.h" @@ -31,10 +32,12 @@ ExtensionActionViewController::ExtensionActionViewController( const extensions::Extension* extension, Browser* browser, - ExtensionAction* extension_action) + ExtensionAction* extension_action, + ToolbarActionsBar* toolbar_actions_bar) : extension_(extension), browser_(browser), extension_action_(extension_action), + toolbar_actions_bar_(toolbar_actions_bar), popup_host_(nullptr), view_delegate_(nullptr), platform_delegate_(ExtensionActionPlatformDelegate::Create(this)), @@ -195,8 +198,7 @@ ExtensionAction::ACTION_SHOW_POPUP) { GURL popup_url = extension_action_->GetPopupUrl( SessionTabHelper::IdForTab(view_delegate_->GetCurrentWebContents())); - return static_cast<ExtensionActionViewController*>( - view_delegate_->GetPreferredPopupViewController()) + return GetPreferredPopupViewController() ->ShowPopupWithUrl(show_action, popup_url, grant_tab_permissions); } return false; @@ -241,6 +243,17 @@ return extension_registry_->enabled_extensions().Contains(extension_->id()); } +void ExtensionActionViewController::HideActivePopup() { + if (toolbar_actions_bar_) { + toolbar_actions_bar_->HideActivePopup(); + } else { + DCHECK_EQ(ActionInfo::TYPE_PAGE, extension_action_->action_type()); + // In the traditional toolbar, page actions only know how to close their own + // popups. + HidePopup(); + } +} + bool ExtensionActionViewController::GetExtensionCommand( extensions::Command* command) { DCHECK(command); @@ -256,6 +269,16 @@ extension_->id(), CommandService::ACTIVE, command, NULL); } +ExtensionActionViewController* +ExtensionActionViewController::GetPreferredPopupViewController() { + if (toolbar_actions_bar_ && toolbar_actions_bar_->in_overflow_mode()) { + return static_cast<ExtensionActionViewController*>( + toolbar_actions_bar_->GetMainControllerForAction(this)); + } + + return this; +} + bool ExtensionActionViewController::ShowPopupWithUrl( PopupShowAction show_action, const GURL& popup_url, @@ -267,7 +290,7 @@ // Always hide the current popup, even if it's not owned by this extension. // Only one popup should be visible at a time. - platform_delegate_->CloseActivePopup(); + HideActivePopup(); // If we were showing a popup already, then we treat the action to open the // same one as a desire to close it (like clicking a menu button that was @@ -279,6 +302,8 @@ show_action, popup_url, grant_tab_permissions); if (popup_host_) { popup_host_observer_.Add(popup_host_); + if (toolbar_actions_bar_) + toolbar_actions_bar_->SetPopupOwner(this); view_delegate_->OnPopupShown(grant_tab_permissions); } return is_showing_popup(); @@ -287,5 +312,7 @@ void ExtensionActionViewController::OnPopupClosed() { popup_host_observer_.Remove(popup_host_); popup_host_ = nullptr; + if (toolbar_actions_bar_) + toolbar_actions_bar_->SetPopupOwner(nullptr); view_delegate_->OnPopupClosed(); }
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.h b/chrome/browser/ui/extensions/extension_action_view_controller.h index 3bbdb08a..fbc67bc6 100644 --- a/chrome/browser/ui/extensions/extension_action_view_controller.h +++ b/chrome/browser/ui/extensions/extension_action_view_controller.h
@@ -16,6 +16,7 @@ class ExtensionAction; class ExtensionActionPlatformDelegate; class GURL; +class ToolbarActionsBar; namespace extensions { class Command; @@ -40,7 +41,8 @@ ExtensionActionViewController(const extensions::Extension* extension, Browser* browser, - ExtensionAction* extension_action); + ExtensionAction* extension_action, + ToolbarActionsBar* toolbar_actions_bar); ~ExtensionActionViewController() override; // ToolbarActionViewController: @@ -70,6 +72,9 @@ // ExtensionContextMenuModel::PopupDelegate: void InspectPopup() override; + // Closes the active popup (whether it was this action's popup or not). + void HideActivePopup(); + // Populates |command| with the command associated with |extension|, if one // exists. Returns true if |command| was populated. bool GetExtensionCommand(extensions::Command* command); @@ -98,6 +103,11 @@ // itself before we're notified to remove it. bool ExtensionIsValid() const; + // In some cases (such as when an action is shown in a menu), a substitute + // ToolbarActionViewController should be used for showing popups. This + // returns the preferred controller. + ExtensionActionViewController* GetPreferredPopupViewController(); + // Executes the extension action with |show_action|. If // |grant_tab_permissions| is true, this will grant the extension active tab // permissions. Only do this if this was done through a user action (and not @@ -126,6 +136,13 @@ // by this class. ExtensionAction* extension_action_; + // The owning ToolbarActionsBar, if any. This will be null if this is a + // page action without the toolbar redesign turned on. + // TODO(devlin): Would this be better behind a delegate interface? On the one + // hand, it's odd for this class to know about ToolbarActionsBar, but on the + // other, yet-another-delegate-class might just confuse things. + ToolbarActionsBar* toolbar_actions_bar_; + // The extension popup's host if the popup is visible; null otherwise. extensions::ExtensionViewHost* popup_host_;
diff --git a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc index 810cfa1..3f9927b 100644 --- a/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc +++ b/chrome/browser/ui/gesture_prefs_observer_factory_aura.cc
@@ -205,8 +205,7 @@ for (size_t i = 0; i < overscroll_prefs.size(); ++i) { registry->RegisterDoublePref( overscroll_prefs[i].pref_name, - content::GetOverscrollConfig(overscroll_prefs[i].config), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + content::GetOverscrollConfig(overscroll_prefs[i].config)); } } @@ -215,24 +214,17 @@ GestureConfiguration* gesture_config = GestureConfiguration::GetInstance(); registry->RegisterIntegerPref( prefs::kFlingMaxCancelToDownTimeInMs, - gesture_config->fling_max_cancel_to_down_time_in_ms(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kFlingMaxTapGapTimeInMs, - gesture_config->fling_max_tap_gap_time_in_ms(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + gesture_config->fling_max_cancel_to_down_time_in_ms()); + registry->RegisterIntegerPref(prefs::kFlingMaxTapGapTimeInMs, + gesture_config->fling_max_tap_gap_time_in_ms()); registry->RegisterIntegerPref( prefs::kTabScrubActivationDelayInMs, - gesture_config->tab_scrub_activation_delay_in_ms(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kSemiLongPressTimeInMs, - gesture_config->semi_long_press_time_in_ms(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + gesture_config->tab_scrub_activation_delay_in_ms()); + registry->RegisterIntegerPref(prefs::kSemiLongPressTimeInMs, + gesture_config->semi_long_press_time_in_ms()); registry->RegisterDoublePref( prefs::kMaxSeparationForGestureTouchesInPixels, - gesture_config->max_separation_for_gesture_touches_in_pixels(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + gesture_config->max_separation_for_gesture_touches_in_pixels()); RegisterOverscrollPrefs(registry); }
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc index 652e04e7..73458c6 100644 --- a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc +++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/libgtk2ui/gtk2_ui.h" +#include <math.h> #include <set> #include <pango/pango.h> @@ -1427,8 +1428,9 @@ float Gtk2UI::GetDeviceScaleFactor() const { const int kCSSDefaultDPI = 96; - const float scale = GetDPI() / kCSSDefaultDPI; - return ui::GetScaleForScaleFactor(ui::GetSupportedScaleFactor(scale)); + float scale = GetDPI() / kCSSDefaultDPI; + // Round to 2 decimals, e.g. to 1.33. + return roundf(scale * 100) / 100; } } // namespace libgtk2ui
diff --git a/chrome/browser/ui/login/login_prompt.cc b/chrome/browser/ui/login/login_prompt.cc index 3fce558..cc9f890 100644 --- a/chrome/browser/ui/login/login_prompt.cc +++ b/chrome/browser/ui/login/login_prompt.cc
@@ -36,6 +36,10 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/text_elider.h" +#if defined(ENABLE_EXTENSIONS) +#include "extensions/browser/guest_view/guest_view_base.h" +#endif + using autofill::PasswordForm; using content::BrowserThread; using content::NavigationController; @@ -472,8 +476,29 @@ password_manager::ContentPasswordManagerDriver* driver = handler->GetPasswordManagerDriverForLogin(); + // The realm is controlled by the remote server, so there is no reason + // to believe it is of a reasonable length. + base::string16 elided_realm; + gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm); + + base::string16 host_and_port = base::ASCIIToUTF16( + request_url.scheme() + "://" + auth_info->challenger.ToString()); + base::string16 explanation = elided_realm.empty() ? + l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM, + host_and_port) : + l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, + host_and_port, + elided_realm); + if (!driver) { - // Same logic as above. +#if defined(ENABLE_EXTENSIONS) + // A WebContents in a <webview> (a GuestView type) does not have a password + // manager, but still needs to be able to show login prompts. + if (extensions::GuestViewBase::FromWebContents(parent_contents)) { + handler->BuildViewForPasswordManager(nullptr, explanation); + return; + } +#endif handler->CancelAuth(); return; } @@ -493,19 +518,6 @@ driver->OnPasswordFormsParsed(v); handler->SetPasswordManager(driver->GetPasswordManager()); - // The realm is controlled by the remote server, so there is no reason - // to believe it is of a reasonable length. - base::string16 elided_realm; - gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm); - - base::string16 host_and_port = base::ASCIIToUTF16( - request_url.scheme() + "://" + auth_info->challenger.ToString()); - base::string16 explanation = elided_realm.empty() ? - l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM, - host_and_port) : - l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, - host_and_port, - elided_realm); handler->BuildViewForPasswordManager(driver->GetPasswordManager(), explanation); }
diff --git a/chrome/browser/ui/metro_pin_tab_helper_win.h b/chrome/browser/ui/metro_pin_tab_helper_win.h index 98ec19b..2233f46 100644 --- a/chrome/browser/ui/metro_pin_tab_helper_win.h +++ b/chrome/browser/ui/metro_pin_tab_helper_win.h
@@ -22,17 +22,17 @@ : public content::WebContentsObserver, public content::WebContentsUserData<MetroPinTabHelper> { public: - virtual ~MetroPinTabHelper(); + ~MetroPinTabHelper() override; bool IsPinned() const; void TogglePinnedToStartScreen(); // content::WebContentsObserver overrides: - virtual void DidNavigateMainFrame( + void DidNavigateMainFrame( const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) override; - virtual void DidUpdateFaviconURL( + void DidUpdateFaviconURL( const std::vector<content::FaviconURL>& candidates) override; private:
diff --git a/chrome/browser/ui/network_profile_bubble.cc b/chrome/browser/ui/network_profile_bubble.cc index 4b5d23ce..29aaa76 100644 --- a/chrome/browser/ui/network_profile_bubble.cc +++ b/chrome/browser/ui/network_profile_bubble.cc
@@ -41,12 +41,12 @@ // window. class BrowserListObserver : public chrome::BrowserListObserver { private: - virtual ~BrowserListObserver(); + ~BrowserListObserver() override; // Overridden from chrome::BrowserListObserver: - virtual void OnBrowserAdded(Browser* browser) override; - virtual void OnBrowserRemoved(Browser* browser) override; - virtual void OnBrowserSetLastActive(Browser* browser) override; + void OnBrowserAdded(Browser* browser) override; + void OnBrowserRemoved(Browser* browser) override; + void OnBrowserSetLastActive(Browser* browser) override; }; BrowserListObserver::~BrowserListObserver() { @@ -159,14 +159,9 @@ // static void NetworkProfileBubble::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kNetworkProfileWarningsLeft, - kMaxWarnings, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kNetworkProfileLastWarningTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kNetworkProfileWarningsLeft, + kMaxWarnings); + registry->RegisterInt64Pref(prefs::kNetworkProfileLastWarningTime, 0); } // static
diff --git a/chrome/browser/ui/omnibox/omnibox_controller_unittest.cc b/chrome/browser/ui/omnibox/omnibox_controller_unittest.cc index 423bc87..b6075b94 100644 --- a/chrome/browser/ui/omnibox/omnibox_controller_unittest.cc +++ b/chrome/browser/ui/omnibox/omnibox_controller_unittest.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/ui/omnibox/omnibox_controller.h" #include "chrome/test/base/testing_profile.h" #include "components/omnibox/autocomplete_provider.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" class OmniboxControllerTest : public testing::Test { @@ -23,6 +24,7 @@ } private: + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; scoped_ptr<OmniboxController> omnibox_controller_;
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc index 6bc5f55..b770759f 100644 --- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc +++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
@@ -935,8 +935,6 @@ false, true); } - view_->UpdatePlaceholderText(); - content::RecordAction(base::UserMetricsAction("AcceptedKeywordHint")); UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, entered_method, ENTERED_KEYWORD_MODE_NUM_ITEMS); @@ -988,8 +986,6 @@ is_keyword_hint_ = false; view_->OnAfterPossibleChange(); } - - view_->UpdatePlaceholderText(); } void OmniboxEditModel::OnSetFocus(bool control_down) { @@ -1299,7 +1295,6 @@ selection_start); view_->UpdatePopup(); if (allow_exact_keyword_match_) { - view_->UpdatePlaceholderText(); UMA_HISTOGRAM_ENUMERATION(kEnteredKeywordModeHistogram, ENTERED_KEYWORD_MODE_VIA_SPACE_IN_MIDDLE, ENTERED_KEYWORD_MODE_NUM_ITEMS);
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc b/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc index e025070..87c9738a 100644 --- a/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc +++ b/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ui/omnibox/omnibox_view.h" #include "chrome/browser/ui/toolbar/test_toolbar_model.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" using base::ASCIIToUTF16; @@ -28,7 +29,6 @@ void OnTabChanged(const WebContents* web_contents) override {} void ResetTabState(WebContents* web_contents) override {} void Update() override {} - void UpdatePlaceholderText() override {} void OpenMatch(const AutocompleteMatch& match, WindowOpenDisposition disposition, const GURL& alternate_nav_url, @@ -129,6 +129,7 @@ TestToolbarModel* toolbar_model() { return &toolbar_model_; } private: + content::TestBrowserThreadBundle thread_bundle_; TestToolbarModel toolbar_model_; };
diff --git a/chrome/browser/ui/omnibox/omnibox_popup_model.cc b/chrome/browser/ui/omnibox/omnibox_popup_model.cc index d20ee265..2284acc 100644 --- a/chrome/browser/ui/omnibox/omnibox_popup_model.cc +++ b/chrome/browser/ui/omnibox/omnibox_popup_model.cc
@@ -51,13 +51,8 @@ bool allow_shrinking_contents, int* contents_max_width, int* description_max_width) { - if (available_width <= 0) { - *contents_max_width = 0; - *description_max_width = 0; - return; - } - - *contents_max_width = contents_width; + available_width = std::max(available_width, 0); + *contents_max_width = std::min(contents_width, available_width); *description_max_width = description_width; // If the description is empty, the contents can get the full width. @@ -67,6 +62,10 @@ // If we want to display the description, we need to reserve enough space for // the separator. available_width -= separator_width; + if (available_width < 0) { + *description_max_width = 0; + return; + } if (contents_width + description_width > available_width) { if (allow_shrinking_contents) { @@ -79,19 +78,24 @@ (available_width + 1) / 2, available_width - description_width); const int kMinimumContentsWidth = 300; - *contents_max_width = std::min( - std::max(*contents_max_width, kMinimumContentsWidth), contents_width); + *contents_max_width = std::min(std::min( + std::max(*contents_max_width, kMinimumContentsWidth), contents_width), + available_width); } // Give the description the remaining space, unless this makes it too small // to display anything meaningful, in which case just hide the description // and let the contents take up the whole width. - *description_max_width = available_width - *contents_max_width; + *description_max_width = + std::min(description_width, available_width - *contents_max_width); const int kMinimumDescriptionWidth = 75; if (*description_max_width < std::min(description_width, kMinimumDescriptionWidth)) { *description_max_width = 0; - *contents_max_width = contents_width; + // Since we're not going to display the description, the contents can have + // the space we reserved for the separator. + available_width += separator_width; + *contents_max_width = std::min(contents_width, available_width); } } }
diff --git a/chrome/browser/ui/omnibox/omnibox_popup_model_unittest.cc b/chrome/browser/ui/omnibox/omnibox_popup_model_unittest.cc index f7c3b4b..85787b3 100644 --- a/chrome/browser/ui/omnibox/omnibox_popup_model_unittest.cc +++ b/chrome/browser/ui/omnibox/omnibox_popup_model_unittest.cc
@@ -63,7 +63,7 @@ OmniboxPopupModel::ComputeMatchMaxWidths( contents_width, separator_width, description_width, available_width, true, &contents_max_width, &description_max_width); - EXPECT_EQ(contents_width, contents_max_width); + EXPECT_EQ(available_width, contents_max_width); EXPECT_EQ(0, description_max_width); // Half and half.
diff --git a/chrome/browser/ui/omnibox/omnibox_view.cc b/chrome/browser/ui/omnibox/omnibox_view.cc index f66cff6..833cdfa 100644 --- a/chrome/browser/ui/omnibox/omnibox_view.cc +++ b/chrome/browser/ui/omnibox/omnibox_view.cc
@@ -115,31 +115,6 @@ return (id == IDR_OMNIBOX_HTTP) ? IDR_LOCATION_BAR_HTTP : id; } -base::string16 OmniboxView::GetHintText() const { - // If the user is in keyword mode (the "Search <some site>:" chip is showing) - // then it doesn't make sense to show the "Search <default search engine>" - // hint text. - if (model_->is_keyword_selected()) - return base::string16(); - - // Attempt to determine the default search provider and use that in the hint - // text. - TemplateURLService* template_url_service = - TemplateURLServiceFactory::GetForProfile(model_->profile()); - if (template_url_service) { - TemplateURL* template_url = - template_url_service->GetDefaultSearchProvider(); - if (template_url) - return l10n_util::GetStringFUTF16( - IDS_OMNIBOX_EMPTY_HINT_WITH_DEFAULT_SEARCH_PROVIDER, - template_url->AdjustedShortNameForLocaleDirection()); - } - - // Otherwise return a hint based on there being no default search provider. - return l10n_util::GetStringUTF16( - IDS_OMNIBOX_EMPTY_HINT_NO_DEFAULT_SEARCH_PROVIDER); -} - void OmniboxView::SetUserText(const base::string16& text) { SetUserText(text, text, true); }
diff --git a/chrome/browser/ui/omnibox/omnibox_view.h b/chrome/browser/ui/omnibox/omnibox_view.h index f60b155..9c55c3d 100644 --- a/chrome/browser/ui/omnibox/omnibox_view.h +++ b/chrome/browser/ui/omnibox/omnibox_view.h
@@ -60,10 +60,6 @@ // Called when any relevant state changes other than changing tabs. virtual void Update() = 0; - // Updates the placeholder text with the value of GetHintText() if hint texts - // are enabled. - virtual void UpdatePlaceholderText() = 0; - // Asks the browser to load the specified match, using the supplied // disposition. |alternate_nav_url|, if non-empty, contains the // alternate navigation URL for for this match. See comments on @@ -93,11 +89,6 @@ // Returns the resource ID of the icon to show for the current text. int GetIcon() const; - // Returns the hint text that should be displayed when there is no text in the - // omnibox. In keyword mode, this is an empty string. Otherwise, it's - // instructions to search the user's default search engine or type a URL. - base::string16 GetHintText() const; - // The user text is the text the user has manually keyed in. When present, // this is shown in preference to the permanent text; hitting escape will // revert to the permanent text.
diff --git a/chrome/browser/ui/passwords/password_bubble_experiment.cc b/chrome/browser/ui/passwords/password_bubble_experiment.cc index 8afabfca..1ccd086a 100644 --- a/chrome/browser/ui/passwords/password_bubble_experiment.cc +++ b/chrome/browser/ui/passwords/password_bubble_experiment.cc
@@ -26,10 +26,7 @@ const char kParamNopeThreshold[] = "consecutive_nope_threshold"; void RegisterPrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kPasswordBubbleNopesCount, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kPasswordBubbleNopesCount, 0); } bool ShouldShowNeverForThisSiteDefault(PrefService* prefs) {
diff --git a/chrome/browser/ui/passwords/password_bubble_experiment_unittest.cc b/chrome/browser/ui/passwords/password_bubble_experiment_unittest.cc index e6084b950..6533742 100644 --- a/chrome/browser/ui/passwords/password_bubble_experiment_unittest.cc +++ b/chrome/browser/ui/passwords/password_bubble_experiment_unittest.cc
@@ -12,6 +12,7 @@ #include "chrome/test/base/testing_profile.h" #include "components/variations/entropy_provider.h" #include "components/variations/variations_associated_data.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -51,6 +52,7 @@ PrefService* prefs() { return profile_->GetPrefs(); } private: + content::TestBrowserThreadBundle thread_bundle_; base::ScopedTempDir temp_dir_; scoped_ptr<TestingProfile> profile_; scoped_ptr<base::FieldTrialList> field_trial_list_;
diff --git a/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc b/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc index 3386881..9669bb0 100644 --- a/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc +++ b/chrome/browser/ui/passwords/password_manager_presenter_unittest.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/ui/passwords/password_ui_view.h" #include "chrome/test/base/testing_profile.h" #include "components/password_manager/core/browser/mock_password_store.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -22,10 +23,10 @@ : profile_(profile), password_manager_presenter_(this) { password_manager_presenter_.Initialize(); } - virtual ~MockPasswordUIView() {} - virtual Profile* GetProfile() override; + ~MockPasswordUIView() override {} + Profile* GetProfile() override; #if !defined(OS_ANDROID) - virtual gfx::NativeWindow GetNativeWindow() const override; + gfx::NativeWindow GetNativeWindow() const override; #endif MOCK_METHOD2(ShowPassword, void(size_t, const base::string16&)); MOCK_METHOD2(SetPasswordList, @@ -66,6 +67,7 @@ MockPasswordUIView* GetUIController() { return mock_controller_.get(); } private: + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; scoped_ptr<MockPasswordUIView> mock_controller_;
diff --git a/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h b/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h index 686174c..a95a46d 100644 --- a/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h +++ b/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h
@@ -12,21 +12,20 @@ : public pdf::PDFWebContentsHelperClient { public: ChromePDFWebContentsHelperClient(); - virtual ~ChromePDFWebContentsHelperClient(); + ~ChromePDFWebContentsHelperClient() override; private: // pdf::PDFWebContentsHelperClient: - virtual void UpdateLocationBar(content::WebContents* contents) override; + void UpdateLocationBar(content::WebContents* contents) override; - virtual void UpdateContentRestrictions(content::WebContents* contents, - int content_restrictions) override; + void UpdateContentRestrictions(content::WebContents* contents, + int content_restrictions) override; - virtual void OnPDFHasUnsupportedFeature( - content::WebContents* contents) override; + void OnPDFHasUnsupportedFeature(content::WebContents* contents) override; - virtual void OnSaveURL(content::WebContents* contents) override; + void OnSaveURL(content::WebContents* contents) override; - virtual void OnShowPDFPasswordDialog( + void OnShowPDFPasswordDialog( content::WebContents* contents, const base::string16& prompt, const pdf::PasswordDialogClosedCallback& callback) override;
diff --git a/chrome/browser/ui/pdf/pdf_browsertest_base.h b/chrome/browser/ui/pdf/pdf_browsertest_base.h index 4beecd4..ee144679 100644 --- a/chrome/browser/ui/pdf/pdf_browsertest_base.h +++ b/chrome/browser/ui/pdf/pdf_browsertest_base.h
@@ -26,7 +26,7 @@ public content::NotificationObserver { public: PDFBrowserTest(); - virtual ~PDFBrowserTest(); + ~PDFBrowserTest() override; protected: // Use our own TestServer so that we can serve files from the pdf directory. @@ -47,12 +47,12 @@ content::ReadbackResponse response); // content::NotificationObserver - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; // InProcessBrowserTest - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; // True if the snapshot differed from the expected value. bool snapshot_different_;
diff --git a/chrome/browser/ui/pdf/pdf_unsupported_feature.cc b/chrome/browser/ui/pdf/pdf_unsupported_feature.cc index dc40e45..dbdd9d3 100644 --- a/chrome/browser/ui/pdf/pdf_unsupported_feature.cc +++ b/chrome/browser/ui/pdf/pdf_unsupported_feature.cc
@@ -57,16 +57,16 @@ : public pdf::OpenPDFInReaderPromptClient { public: explicit PDFEnableAdobeReaderPromptClient(Profile* profile); - virtual ~PDFEnableAdobeReaderPromptClient(); + ~PDFEnableAdobeReaderPromptClient() override; // pdf::OpenPDFInReaderPromptClient - virtual base::string16 GetMessageText() const override; - virtual base::string16 GetAcceptButtonText() const override; - virtual base::string16 GetCancelButtonText() const override; - virtual bool ShouldExpire( + base::string16 GetMessageText() const override; + base::string16 GetAcceptButtonText() const override; + base::string16 GetCancelButtonText() const override; + bool ShouldExpire( const content::LoadCommittedDetails& details) const override; - virtual void Accept() override; - virtual void Cancel() override; + void Accept() override; + void Cancel() override; private: void OnYes(); @@ -163,7 +163,7 @@ protected: // InterstitialPageDelegate implementation. - virtual std::string GetHTMLContents() override { + std::string GetHTMLContents() override { base::DictionaryValue strings; strings.SetString( "title", @@ -191,7 +191,7 @@ return webui::GetI18nTemplateHtml(html, &strings); } - virtual void CommandReceived(const std::string& command) override { + void CommandReceived(const std::string& command) override { if (command == "0") { content::RecordAction( UserMetricsAction("PDF_ReaderInterstitialCancel")); @@ -215,8 +215,7 @@ interstitial_page_->Proceed(); } - virtual void OverrideRendererPrefs( - content::RendererPreferences* prefs) override { + void OverrideRendererPrefs(content::RendererPreferences* prefs) override { Profile* profile = Profile::FromBrowserContext(web_contents_->GetBrowserContext()); renderer_preferences_util::UpdateFromSystemSettings( @@ -238,16 +237,16 @@ public: PDFUnsupportedFeaturePromptClient(WebContents* web_contents, const AdobeReaderPluginInfo& reader_info); - virtual ~PDFUnsupportedFeaturePromptClient(); + ~PDFUnsupportedFeaturePromptClient() override; // pdf::OpenPDFInReaderPromptClient: - virtual base::string16 GetMessageText() const override; - virtual base::string16 GetAcceptButtonText() const override; - virtual base::string16 GetCancelButtonText() const override; - virtual bool ShouldExpire( + base::string16 GetMessageText() const override; + base::string16 GetAcceptButtonText() const override; + base::string16 GetCancelButtonText() const override; + bool ShouldExpire( const content::LoadCommittedDetails& details) const override; - virtual void Accept() override; - virtual void Cancel() override; + void Accept() override; + void Cancel() override; private: WebContents* web_contents_;
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc index 68dc7618..a614dd93 100644 --- a/chrome/browser/ui/prefs/prefs_tab_helper.cc +++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -124,10 +124,7 @@ if (fonts_with_defaults.find(pref_name) == fonts_with_defaults.end()) { // We haven't already set a default value for this font preference, so set // an empty string as the default. - registry->RegisterStringPref( - pref_name, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(pref_name, std::string()); } } } @@ -325,16 +322,14 @@ (*map)[script] = base::UTF8ToUTF16(pref_value); } -void RegisterLocalizedFontPref( - user_prefs::PrefRegistrySyncable* registry, - const char* path, - int default_message_id, - user_prefs::PrefRegistrySyncable::PrefSyncStatus status) { +void RegisterLocalizedFontPref(user_prefs::PrefRegistrySyncable* registry, + const char* path, + int default_message_id) { int val = 0; bool success = base::StringToInt(l10n_util::GetStringUTF8( default_message_id), &val); DCHECK(success); - registry->RegisterIntegerPref(path, val, status); + registry->RegisterIntegerPref(path, val); } } // namespace @@ -524,71 +519,37 @@ void PrefsTabHelper::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { WebPreferences pref_defaults; + registry->RegisterBooleanPref(prefs::kWebKitJavascriptEnabled, + pref_defaults.javascript_enabled); + registry->RegisterBooleanPref(prefs::kWebKitWebSecurityEnabled, + pref_defaults.web_security_enabled); registry->RegisterBooleanPref( - prefs::kWebKitJavascriptEnabled, - pref_defaults.javascript_enabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitWebSecurityEnabled, - pref_defaults.web_security_enabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitJavascriptCanOpenWindowsAutomatically, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitLoadsImagesAutomatically, - pref_defaults.loads_images_automatically, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitPluginsEnabled, - pref_defaults.plugins_enabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitDomPasteEnabled, - pref_defaults.dom_paste_enabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitShrinksStandaloneImagesToFit, - pref_defaults.shrinks_standalone_images_to_fit, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitTextAreasAreResizable, - pref_defaults.text_areas_are_resizable, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitJavaEnabled, - pref_defaults.java_enabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebkitTabsToLinks, - pref_defaults.tabs_to_links, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitAllowRunningInsecureContent, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitAllowDisplayingInsecureContent, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kEnableReferrers, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kWebKitJavascriptCanOpenWindowsAutomatically, true); + registry->RegisterBooleanPref(prefs::kWebKitLoadsImagesAutomatically, + pref_defaults.loads_images_automatically); + registry->RegisterBooleanPref(prefs::kWebKitPluginsEnabled, + pref_defaults.plugins_enabled); + registry->RegisterBooleanPref(prefs::kWebKitDomPasteEnabled, + pref_defaults.dom_paste_enabled); + registry->RegisterBooleanPref(prefs::kWebKitShrinksStandaloneImagesToFit, + pref_defaults.shrinks_standalone_images_to_fit); + registry->RegisterBooleanPref(prefs::kWebKitTextAreasAreResizable, + pref_defaults.text_areas_are_resizable); + registry->RegisterBooleanPref(prefs::kWebKitJavaEnabled, + pref_defaults.java_enabled); + registry->RegisterBooleanPref(prefs::kWebkitTabsToLinks, + pref_defaults.tabs_to_links); + registry->RegisterBooleanPref(prefs::kWebKitAllowRunningInsecureContent, + false); + registry->RegisterBooleanPref(prefs::kWebKitAllowDisplayingInsecureContent, + true); + registry->RegisterBooleanPref(prefs::kEnableReferrers, true); #if defined(OS_ANDROID) - registry->RegisterDoublePref( - prefs::kWebKitFontScaleFactor, - 1.0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitForceEnableZoom, - pref_defaults.force_enable_zoom, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kWebKitPasswordEchoEnabled, - pref_defaults.password_echo_enabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDoublePref(prefs::kWebKitFontScaleFactor, 1.0); + registry->RegisterBooleanPref(prefs::kWebKitForceEnableZoom, + pref_defaults.force_enable_zoom); + registry->RegisterBooleanPref(prefs::kWebKitPasswordEchoEnabled, + pref_defaults.password_echo_enabled); #endif registry->RegisterStringPref( prefs::kAcceptLanguages, @@ -628,10 +589,8 @@ // prefs (e.g., via the extensions workflow), or the problem turns out to // not be really critical after all. if (browser_script != pref_script) { - registry->RegisterStringPref( - pref.pref_name, - l10n_util::GetStringUTF8(pref.resource_id), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(pref.pref_name, + l10n_util::GetStringUTF8(pref.resource_id)); fonts_with_defaults.insert(pref.pref_name); } } @@ -641,38 +600,22 @@ RegisterFontFamilyPrefs(registry, fonts_with_defaults); #endif - RegisterLocalizedFontPref( - registry, - prefs::kWebKitDefaultFontSize, - IDS_DEFAULT_FONT_SIZE, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - RegisterLocalizedFontPref( - registry, - prefs::kWebKitDefaultFixedFontSize, - IDS_DEFAULT_FIXED_FONT_SIZE, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - RegisterLocalizedFontPref( - registry, - prefs::kWebKitMinimumFontSize, - IDS_MINIMUM_FONT_SIZE, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - RegisterLocalizedFontPref( - registry, - prefs::kWebKitMinimumLogicalFontSize, - IDS_MINIMUM_LOGICAL_FONT_SIZE, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + RegisterLocalizedFontPref(registry, prefs::kWebKitDefaultFontSize, + IDS_DEFAULT_FONT_SIZE); + RegisterLocalizedFontPref(registry, prefs::kWebKitDefaultFixedFontSize, + IDS_DEFAULT_FIXED_FONT_SIZE); + RegisterLocalizedFontPref(registry, prefs::kWebKitMinimumFontSize, + IDS_MINIMUM_FONT_SIZE); + RegisterLocalizedFontPref(registry, prefs::kWebKitMinimumLogicalFontSize, + IDS_MINIMUM_LOGICAL_FONT_SIZE); registry->RegisterBooleanPref( prefs::kWebKitUsesUniversalDetector, l10n_util::GetStringUTF8(IDS_USES_UNIVERSAL_DETECTOR) == "true", user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterStringPref( prefs::kStaticEncodings, - l10n_util::GetStringUTF8(IDS_STATIC_ENCODING_LIST), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kRecentlySelectedEncoding, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + l10n_util::GetStringUTF8(IDS_STATIC_ENCODING_LIST)); + registry->RegisterStringPref(prefs::kRecentlySelectedEncoding, std::string()); } // static
diff --git a/chrome/browser/ui/startup/autolaunch_prompt_win.cc b/chrome/browser/ui/startup/autolaunch_prompt_win.cc index d3e4f60..7f3559a 100644 --- a/chrome/browser/ui/startup/autolaunch_prompt_win.cc +++ b/chrome/browser/ui/startup/autolaunch_prompt_win.cc
@@ -42,18 +42,17 @@ private: explicit AutolaunchInfoBarDelegate(Profile* profile); - virtual ~AutolaunchInfoBarDelegate(); + ~AutolaunchInfoBarDelegate() override; void set_should_expire() { should_expire_ = true; } // ConfirmInfoBarDelegate: - virtual int GetIconID() const override; - virtual bool ShouldExpireInternal( - const NavigationDetails& details) const override; - virtual base::string16 GetMessageText() const override; - virtual base::string16 GetButtonLabel(InfoBarButton button) const override; - virtual bool Accept() override; - virtual bool Cancel() override; + int GetIconID() const override; + bool ShouldExpireInternal(const NavigationDetails& details) const override; + base::string16 GetMessageText() const override; + base::string16 GetButtonLabel(InfoBarButton button) const override; + bool Accept() override; + bool Cancel() override; // Weak pointer to the profile, not owned by us. Profile* profile_; @@ -168,9 +167,7 @@ } void RegisterAutolaunchUserPrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kShownAutoLaunchInfobar, 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kShownAutoLaunchInfobar, 0); } } // namespace chrome
diff --git a/chrome/browser/ui/startup/default_browser_prompt_win.cc b/chrome/browser/ui/startup/default_browser_prompt_win.cc index ec438e6..4b19c16 100644 --- a/chrome/browser/ui/startup/default_browser_prompt_win.cc +++ b/chrome/browser/ui/startup/default_browser_prompt_win.cc
@@ -38,9 +38,9 @@ } // content::NotificationObserver override: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; content::NotificationRegistrar registrar_; Profile* profile_;
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index 29a57c0..82f182b 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -22,6 +22,7 @@ #include "base/metrics/histogram_macros.h" #include "base/metrics/statistics_recorder.h" #include "base/prefs/pref_service.h" +#include "base/profiler/scoped_profile.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" @@ -273,6 +274,7 @@ Profile* last_used_profile, const Profiles& last_opened_profiles) { TRACE_EVENT0("startup", "StartupBrowserCreator::Start"); + TRACK_SCOPED_REGION("Startup", "StartupBrowserCreator::Start"); SCOPED_UMA_HISTOGRAM_TIMER("Startup.StartupBrowserCreator_Start"); return ProcessCmdLineImpl(cmd_line, cur_dir, true, last_used_profile, last_opened_profiles, this);
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc index 1277b64..8df2618 100644 --- a/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc +++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper.cc
@@ -113,7 +113,7 @@ } ProfileSigninConfirmationHelper::~ProfileSigninConfirmationHelper() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } void ProfileSigninConfirmationHelper::OnHistoryQueryResults( @@ -164,7 +164,7 @@ } void ProfileSigninConfirmationHelper::ReturnResult(bool result) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Pass |true| into the callback as soon as one of the tasks passes a // result of |true|, otherwise pass the last returned result. if (--pending_requests_ == 0 || result) { @@ -229,7 +229,7 @@ void CheckShouldPromptForNewProfile( Profile* profile, const base::Callback<void(bool)>& return_result) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (HasBeenShutdown(profile) || HasBookmarks(profile) ||
diff --git a/chrome/browser/ui/sync/sync_promo_ui_unittest.cc b/chrome/browser/ui/sync/sync_promo_ui_unittest.cc index e19b22c..a44dffc 100644 --- a/chrome/browser/ui/sync/sync_promo_ui_unittest.cc +++ b/chrome/browser/ui/sync/sync_promo_ui_unittest.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" class SyncPromoUITest : public testing::Test { @@ -33,6 +34,7 @@ switches::kDisableSync); } + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<TestingProfile> profile_; private:
diff --git a/chrome/browser/ui/tab_contents/core_tab_helper.cc b/chrome/browser/ui/tab_contents/core_tab_helper.cc index 26fdafa..b2ef8e0 100644 --- a/chrome/browser/ui/tab_contents/core_tab_helper.cc +++ b/chrome/browser/ui/tab_contents/core_tab_helper.cc
@@ -92,9 +92,8 @@ tracked_objects::ScopedTracker tracking_profile1( FROM_HERE_WITH_EXPLICIT_FUNCTION( "467185 CoreTabHelper::GetStatusTextForWebContents1")); - auto guest_manager = - extensions::GuestViewManager::FromBrowserContextIfAvailable( - source->GetBrowserContext()); + auto guest_manager = extensions::GuestViewManager::FromBrowserContext( + source->GetBrowserContext()); if (!source->IsLoading() || source->GetLoadState().state == net::LOAD_STATE_IDLE) { // TODO(robliao): Remove ScopedTracker below once https://crbug.com/467185
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc index fb3a6ce..9214292 100644 --- a/chrome/browser/ui/tab_helpers.cc +++ b/chrome/browser/ui/tab_helpers.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/favicon/favicon_helper.h" #include "chrome/browser/history/history_tab_helper.h" +#include "chrome/browser/history/top_sites_factory.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/net/net_error_tab_helper.h" #include "chrome/browser/net/predictor_tab_helper.h" @@ -19,6 +20,7 @@ #include "chrome/browser/predictors/resource_prefetch_predictor_factory.h" #include "chrome/browser/predictors/resource_prefetch_predictor_tab_helper.h" #include "chrome/browser/prerender/prerender_tab_helper.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/tab_contents/navigation_metrics_recorder.h" #include "chrome/browser/translate/chrome_translate_client.h" @@ -37,6 +39,8 @@ #include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/core/browser/autofill_manager.h" #include "components/dom_distiller/content/web_contents_main_frame_observer.h" +#include "components/history/content/browser/web_contents_top_sites_observer.h" +#include "components/history/core/browser/top_sites.h" #include "components/password_manager/core/browser/password_manager.h" #include "content/public/browser/web_contents.h" @@ -145,6 +149,10 @@ CoreTabHelper::CreateForWebContents(web_contents); favicon::CreateContentFaviconDriverForWebContents(web_contents); FindTabHelper::CreateForWebContents(web_contents); + history::WebContentsTopSitesObserver::CreateForWebContents( + web_contents, TopSitesFactory::GetForProfile( + Profile::FromBrowserContext( + web_contents->GetBrowserContext())).get()); HistoryTabHelper::CreateForWebContents(web_contents); InfoBarService::CreateForWebContents(web_contents); ManagePasswordsUIController::CreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/tabs/pinned_tab_codec.cc b/chrome/browser/ui/tabs/pinned_tab_codec.cc index 922d86a4..af46b1d 100644 --- a/chrome/browser/ui/tabs/pinned_tab_codec.cc +++ b/chrome/browser/ui/tabs/pinned_tab_codec.cc
@@ -103,8 +103,7 @@ // static void PinnedTabCodec::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(prefs::kPinnedTabs, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kPinnedTabs); } // static
diff --git a/chrome/browser/ui/toolbar/test_toolbar_actions_bar_helper.h b/chrome/browser/ui/toolbar/test_toolbar_actions_bar_helper.h deleted file mode 100644 index 7c9ce5d..0000000 --- a/chrome/browser/ui/toolbar/test_toolbar_actions_bar_helper.h +++ /dev/null
@@ -1,33 +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 CHROME_BROWSER_UI_TOOLBAR_TEST_TOOLBAR_ACTIONS_BAR_HELPER_H_ -#define CHROME_BROWSER_UI_TOOLBAR_TEST_TOOLBAR_ACTIONS_BAR_HELPER_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" - -class Browser; -class ToolbarActionsBar; - -// A cross-platform container that creates and owns a ToolbarActionsBar and the -// corresponding view. -class TestToolbarActionsBarHelper { - public: - TestToolbarActionsBarHelper() {} - virtual ~TestToolbarActionsBarHelper() {} - - // Creates and returns a TestToolbarActionsBarHelper. If |main_bar| is - // non-null, the created actions bar will be in overflow mode. - static scoped_ptr<TestToolbarActionsBarHelper> Create( - Browser* browser, - TestToolbarActionsBarHelper* main_bar); - - virtual ToolbarActionsBar* GetToolbarActionsBar() = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(TestToolbarActionsBarHelper); -}; - -#endif // CHROME_BROWSER_UI_TOOLBAR_TEST_TOOLBAR_ACTIONS_BAR_HELPER_H_
diff --git a/chrome/browser/ui/toolbar/toolbar_action_view_delegate.h b/chrome/browser/ui/toolbar/toolbar_action_view_delegate.h index 7c7c4d19..bc7413c 100644 --- a/chrome/browser/ui/toolbar/toolbar_action_view_delegate.h +++ b/chrome/browser/ui/toolbar/toolbar_action_view_delegate.h
@@ -15,11 +15,6 @@ // ToolbarActionViewController. class ToolbarActionViewDelegate { public: - // In some cases (such as when an action is shown in a menu), a substitute - // ToolbarActionViewController should be used for showing popups. This - // returns the preferred controller. - virtual ToolbarActionViewController* GetPreferredPopupViewController() = 0; - // Returns the current web contents. virtual content::WebContents* GetCurrentWebContents() const = 0;
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc index a8cf716..619d07d 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc
@@ -119,6 +119,7 @@ model_(extensions::ExtensionToolbarModel::Get(browser_->profile())), main_bar_(main_bar), platform_settings_(main_bar != nullptr), + popup_owner_(nullptr), model_observer_(this), suppress_layout_(false), suppress_animation_(true), @@ -153,10 +154,8 @@ prefs::kToolbarIconSurfacingBubbleAcknowledged, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kToolbarIconSurfacingBubbleLastShowTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterInt64Pref(prefs::kToolbarIconSurfacingBubbleLastShowTime, + 0); } gfx::Size ToolbarActionsBar::GetPreferredSize() const { @@ -284,7 +283,8 @@ toolbar_actions_.push_back(new ExtensionActionViewController( extension.get(), browser_, - action_manager->GetExtensionAction(*extension))); + action_manager->GetExtensionAction(*extension), + this)); } // Component actions come second, and are suppressed if the extension @@ -340,6 +340,7 @@ } void ToolbarActionsBar::DeleteActions() { + HideActivePopup(); delegate_->RemoveAllViews(); toolbar_actions_.clear(); } @@ -393,6 +394,27 @@ model_->SetVisibleIconCount(model_->visible_icon_count() + delta); } +void ToolbarActionsBar::SetPopupOwner( + ToolbarActionViewController* popup_owner) { + // We should never be setting a popup owner when one already exists, and + // never unsetting one when one wasn't set. + DCHECK((!popup_owner_ && popup_owner) || + (popup_owner_ && !popup_owner)); + popup_owner_ = popup_owner; +} + +void ToolbarActionsBar::HideActivePopup() { + if (popup_owner_) + popup_owner_->HidePopup(); + DCHECK(!popup_owner_); +} + +ToolbarActionViewController* ToolbarActionsBar::GetMainControllerForAction( + ToolbarActionViewController* action) { + return in_overflow_mode() ? + main_bar_->GetActionForId(action->GetId()) : action; +} + void ToolbarActionsBar::MaybeShowExtensionBubble() { scoped_ptr<extensions::ExtensionMessageBubbleController> controller = ExtensionMessageBubbleFactory(browser_->profile()).GetController(); @@ -414,7 +436,8 @@ extension, browser_, extensions::ExtensionActionManager::Get(browser_->profile())-> - GetExtensionAction(*extension))); + GetExtensionAction(*extension), + this)); delegate_->AddViewForAction(toolbar_actions_[index], index); @@ -499,7 +522,7 @@ const extensions::Extension* extension, bool grant_active_tab) { // Don't override another popup, and only show in the active window. - if (delegate_->IsPopupRunning() || !browser_->window()->IsActive()) + if (popup_owner() || !browser_->window()->IsActive()) return false; ToolbarActionViewController* action = GetActionForId(extension->id());
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.h b/chrome/browser/ui/toolbar/toolbar_actions_bar.h index 6cdba0d..838699e 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar.h +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.h
@@ -122,6 +122,16 @@ int dropped_index, DragType drag_type); + // Sets the active popup owner to be |popup_owner|. + void SetPopupOwner(ToolbarActionViewController* popup_owner); + + // Hides the actively showing popup, if any. + void HideActivePopup(); + + // Returns the main (i.e., not overflow) controller for the given action. + ToolbarActionViewController* GetMainControllerForAction( + ToolbarActionViewController* action); + const std::vector<ToolbarActionViewController*>& toolbar_actions() const { return toolbar_actions_.get(); } @@ -134,6 +144,8 @@ const PlatformSettings& platform_settings() const { return platform_settings_; } + ToolbarActionViewController* popup_owner() { return popup_owner_; } + bool in_overflow_mode() const { return main_bar_ != nullptr; } ToolbarActionsBarDelegate* delegate_for_test() { return delegate_; } @@ -187,8 +199,6 @@ // Shows an extension message bubble, if any should be shown. void MaybeShowExtensionBubble(); - bool in_overflow_mode() const { return main_bar_ != nullptr; } - // The delegate for this object (in a real build, this is the view). ToolbarActionsBarDelegate* delegate_; @@ -208,6 +218,10 @@ // The toolbar actions. ToolbarActions toolbar_actions_; + // The action that triggered the current popup (just a reference to an action + // from toolbar_actions_). + ToolbarActionViewController* popup_owner_; + ScopedObserver<extensions::ExtensionToolbarModel, extensions::ExtensionToolbarModel::Observer> model_observer_;
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h b/chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h index af71316..33967e58 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h
@@ -57,9 +57,6 @@ // Returns the width (including padding) for the overflow chevron. virtual int GetChevronWidth() const = 0; - // Returns true if there is currently a popup running. - virtual bool IsPopupRunning() const = 0; - // Notifies the delegate that the value of whether or not any overflowed // action wants to run has changed. virtual void OnOverflowedActionWantsToRunChanged(
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc index e583536..01b5872 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/ui/extensions/extension_toolbar_icon_surfacing_bubble_delegate.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/toolbar/test_toolbar_actions_bar_helper.h" #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" #include "chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h" #include "chrome/common/pref_names.h" @@ -138,10 +137,10 @@ size_t visible_count) WARN_UNUSED_RESULT; ToolbarActionsBar* toolbar_actions_bar() { - return main_bar_helper_->GetToolbarActionsBar(); + return browser_action_test_util_->GetToolbarActionsBar(); } ToolbarActionsBar* overflow_bar() { - return overflow_bar_helper_->GetToolbarActionsBar(); + return overflow_browser_action_test_util_->GetToolbarActionsBar(); } extensions::ExtensionToolbarModel* toolbar_model() { return toolbar_model_; @@ -154,14 +153,6 @@ } private: - // The test helper that owns the ToolbarActionsBar and the platform-specific - // view for it. - scoped_ptr<TestToolbarActionsBarHelper> main_bar_helper_; - - // The test helper for the overflow bar; only non-null if |use_redesign| is - // true. - scoped_ptr<TestToolbarActionsBarHelper> overflow_bar_helper_; - // The associated ExtensionToolbarModel (owned by the keyed service setup). extensions::ExtensionToolbarModel* toolbar_model_; @@ -201,28 +192,21 @@ extensions::extension_action_test_util::CreateToolbarModelForProfile( profile()); - main_bar_helper_ = TestToolbarActionsBarHelper::Create(browser(), nullptr); - ToolbarActionsBar::disable_animations_for_testing_ = true; ToolbarActionsBar::set_send_overflowed_action_changes_for_testing(false); - browser_action_test_util_.reset( - new BrowserActionTestUtil(browser(), - toolbar_actions_bar()->delegate_for_test())); + browser_action_test_util_.reset(new BrowserActionTestUtil(browser(), false)); if (use_redesign_) { - overflow_bar_helper_ = - TestToolbarActionsBarHelper::Create(browser(), main_bar_helper_.get()); - overflow_browser_action_test_util_.reset( - new BrowserActionTestUtil(browser(), - overflow_bar()->delegate_for_test())); + overflow_browser_action_test_util_ = + browser_action_test_util_->CreateOverflowBar(); } } void ToolbarActionsBarUnitTest::TearDown() { // Since the profile gets destroyed in BrowserWithTestWindowTest::TearDown(), // we need to delete this now. - overflow_bar_helper_.reset(); - main_bar_helper_.reset(); + browser_action_test_util_.reset(); + overflow_browser_action_test_util_.reset(); ToolbarActionsBar::disable_animations_for_testing_ = false; redesign_switch_.reset(); BrowserWithTestWindowTest::TearDown();
diff --git a/chrome/browser/ui/toolbar/toolbar_model_impl.cc b/chrome/browser/ui/toolbar/toolbar_model_impl.cc index 25f63ae..2bf97bf6 100644 --- a/chrome/browser/ui/toolbar/toolbar_model_impl.cc +++ b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
@@ -51,20 +51,6 @@ namespace { -// Converts a SHA-1 field trial group into the appropriate SecurityLevel. -bool GetSecurityLevelForFieldTrialGroup(const std::string& group, - ToolbarModel::SecurityLevel* level) { - if (group == "Error") - *level = ToolbarModel::SECURITY_ERROR; - else if (group == "Warning") - *level = ToolbarModel::SECURITY_WARNING; - else if (group == "HTTP") - *level = ToolbarModel::NONE; - else - return false; - return true; -} - ToolbarModel::SecurityLevel GetSecurityLevelForNonSecureFieldTrial() { std::string choice = base::CommandLine::ForCurrentProcess()-> GetSwitchValueASCII(switches::kMarkNonSecureAs); @@ -136,37 +122,16 @@ // The internal representation of the dates for UI treatment of SHA-1. // See http://crbug.com/401365 for details static const int64_t kJanuary2017 = INT64_C(13127702400000000); - static const int64_t kJune2016 = INT64_C(13109213000000000); // kJanuary2016 needs to be kept in sync with // ToolbarModelAndroid::IsDeprecatedSHA1Present(). static const int64_t kJanuary2016 = INT64_C(13096080000000000); - - ToolbarModel::SecurityLevel security_level = NONE; - // Gated behind a field trial, so that it is possible to adjust the - // UI treatment (to be more or less severe, as necessary) over the - // course of multiple releases. - // See http://crbug.com/401365 for the timeline, with the end state - // being that > kJanuary2017 = Error, and > kJanuary2016 = - // Warning, and kJune2016 disappearing entirely. if (cert->valid_expiry() >= - base::Time::FromInternalValue(kJanuary2017) && - GetSecurityLevelForFieldTrialGroup( - base::FieldTrialList::FindFullName("SHA1ToolbarUIJanuary2017"), - &security_level)) { - return security_level; - } - if (cert->valid_expiry() >= base::Time::FromInternalValue(kJune2016) && - GetSecurityLevelForFieldTrialGroup( - base::FieldTrialList::FindFullName("SHA1ToolbarUIJune2016"), - &security_level)) { - return security_level; + base::Time::FromInternalValue(kJanuary2017)) { + return SECURITY_ERROR; } if (cert->valid_expiry() >= - base::Time::FromInternalValue(kJanuary2016) && - GetSecurityLevelForFieldTrialGroup( - base::FieldTrialList::FindFullName("SHA1ToolbarUIJanuary2016"), - &security_level)) { - return security_level; + base::Time::FromInternalValue(kJanuary2016)) { + return SECURITY_WARNING; } } if (net::IsCertStatusError(ssl.cert_status)) {
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc index 9f27c2e4..ab6e717a 100644 --- a/chrome/browser/ui/toolbar/wrench_menu_model.cc +++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -794,7 +794,8 @@ return false; #endif case IDC_UPGRADE_DIALOG: - return UpgradeDetector::GetInstance()->notify_upgrade(); + return browser_defaults::kShowUpgradeMenuItem && + UpgradeDetector::GetInstance()->notify_upgrade(); #if !defined(OS_LINUX) || defined(USE_AURA) case IDC_BOOKMARK_PAGE: return !chrome::ShouldRemoveBookmarkThisPageUI(browser_->profile()); @@ -877,7 +878,7 @@ ui::ResourceBundle::GetSharedInstance(). GetNativeImageNamed(IDR_INPUT_ALERT_MENU)); - if (IsCommandIdVisible(browser_defaults::kShowUpgradeMenuItem)) + if (IsCommandIdVisible(IDC_UPGRADE_DIALOG)) AddItem(IDC_UPGRADE_DIALOG, GetUpgradeDialogMenuItemName()); if (AddGlobalErrorMenuItems() ||
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc b/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc index 8801cc6..ad58edd 100644 --- a/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc +++ b/chrome/browser/ui/toolbar/wrench_menu_model_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/toolbar/wrench_menu_model.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/defaults.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/ui/browser.h" @@ -12,6 +13,7 @@ #include "chrome/browser/ui/global_error/global_error_service.h" #include "chrome/browser/ui/global_error/global_error_service_factory.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/upgrade_detector.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/menu_model_test.h" #include "chrome/test/base/testing_browser_process.h" @@ -125,6 +127,12 @@ // the exact number. EXPECT_GT(itemCount, 10); + UpgradeDetector* detector = UpgradeDetector::GetInstance(); + detector->NotifyUpgradeRecommended(); + EXPECT_TRUE(detector->notify_upgrade()); + EXPECT_EQ(browser_defaults::kShowUpgradeMenuItem, + model.IsCommandIdVisible(IDC_UPGRADE_DIALOG)); + // Execute a couple of the items and make sure it gets back to our delegate. // We can't use CountEnabledExecutable() here because the encoding menu's // delegate is internal, it doesn't use the one we pass in.
diff --git a/chrome/browser/ui/views/app_list/win/activation_tracker_win.h b/chrome/browser/ui/views/app_list/win/activation_tracker_win.h index 9daeacf8..6c619b4 100644 --- a/chrome/browser/ui/views/app_list/win/activation_tracker_win.h +++ b/chrome/browser/ui/views/app_list/win/activation_tracker_win.h
@@ -15,10 +15,10 @@ class ActivationTrackerWin : public app_list::AppListViewObserver { public: explicit ActivationTrackerWin(AppListServiceWin* service); - ~ActivationTrackerWin(); + ~ActivationTrackerWin() override; // app_list::AppListViewObserver: - virtual void OnActivationChanged(views::Widget* widget, bool active) override; + void OnActivationChanged(views::Widget* widget, bool active) override; void OnViewHidden();
diff --git a/chrome/browser/ui/views/app_list/win/app_list_controller_delegate_win.h b/chrome/browser/ui/views/app_list/win/app_list_controller_delegate_win.h index 7bc7834..6a21f8a 100644 --- a/chrome/browser/ui/views/app_list/win/app_list_controller_delegate_win.h +++ b/chrome/browser/ui/views/app_list/win/app_list_controller_delegate_win.h
@@ -11,15 +11,15 @@ class AppListControllerDelegateWin : public AppListControllerDelegateViews { public: explicit AppListControllerDelegateWin(AppListServiceViews* service); - virtual ~AppListControllerDelegateWin(); + ~AppListControllerDelegateWin() override; // AppListControllerDelegate overrides: - virtual bool ForceNativeDesktop() const override; - virtual gfx::ImageSkia GetWindowIcon() override; + bool ForceNativeDesktop() const override; + gfx::ImageSkia GetWindowIcon() override; private: // AppListcontrollerDelegateImpl: - virtual void FillLaunchParams(AppLaunchParams* params) override; + void FillLaunchParams(AppLaunchParams* params) override; DISALLOW_COPY_AND_ASSIGN(AppListControllerDelegateWin); };
diff --git a/chrome/browser/ui/views/app_list/win/app_list_service_win.h b/chrome/browser/ui/views/app_list/win/app_list_service_win.h index 6168b31..16648f91 100644 --- a/chrome/browser/ui/views/app_list/win/app_list_service_win.h +++ b/chrome/browser/ui/views/app_list/win/app_list_service_win.h
@@ -15,26 +15,26 @@ class AppListServiceWin : public AppListServiceViews { public: - virtual ~AppListServiceWin(); + ~AppListServiceWin() override; static AppListServiceWin* GetInstance(); // AppListService overrides: - virtual void SetAppListNextPaintCallback(void (*callback)()) override; - virtual void Init(Profile* initial_profile) override; - virtual void ShowForProfile(Profile* requested_profile) override; - virtual void CreateShortcut() override; + void SetAppListNextPaintCallback(void (*callback)()) override; + void Init(Profile* initial_profile) override; + void ShowForProfile(Profile* requested_profile) override; + void CreateShortcut() override; private: friend struct DefaultSingletonTraits<AppListServiceWin>; // AppListServiceViews overrides: - virtual void OnViewBeingDestroyed(); + void OnViewBeingDestroyed() override; // AppListShowerDelegate overrides: - virtual void OnViewCreated() override; - virtual void OnViewDismissed() override; - virtual void MoveNearCursor(app_list::AppListView* view) override; + void OnViewCreated() override; + void OnViewDismissed() override; + void MoveNearCursor(app_list::AppListView* view) override; AppListServiceWin();
diff --git a/chrome/browser/ui/views/app_list/win/app_list_win_unittest.cc b/chrome/browser/ui/views/app_list/win/app_list_win_unittest.cc index 09cc27f..00b18b7 100644 --- a/chrome/browser/ui/views/app_list/win/app_list_win_unittest.cc +++ b/chrome/browser/ui/views/app_list/win/app_list_win_unittest.cc
@@ -49,7 +49,7 @@ class AppListWinUnitTest : public testing::Test { public: - virtual void SetUp() override { + void SetUp() override { display_.set_bounds(gfx::Rect(0, 0, kScreenWidth, kScreenHeight)); display_.set_work_area(gfx::Rect(0, 0, kScreenWidth, kScreenHeight)); cursor_ = gfx::Point();
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc index f182d57..4c89f6e 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_footer_panel.cc
@@ -148,8 +148,9 @@ } bool AppInfoFooterPanel::CanCreateShortcuts() const { - // Ash platforms can't create shortcuts, and extensions can't have shortcuts. - return !app_->is_extension() && + // Ash platforms can't create shortcuts. Extensions and the Chrome + // component app can't have shortcuts. + return app_->id() != extension_misc::kChromeAppId && !app_->is_extension() && (chrome::GetHostDesktopTypeForNativeWindow(parent_window_) != chrome::HOST_DESKTOP_TYPE_ASH); }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel_unittest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel_unittest.cc index b256553b..cbf5b820 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel_unittest.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_panel_unittest.cc
@@ -51,10 +51,9 @@ .Build(); } - TestingProfile profile_; - // We need the UI thread in order to construct UI elements in the view. content::TestBrowserThreadBundle thread_bundle_; + TestingProfile profile_; }; // Tests that an app with no permissions is treated correctly.
diff --git a/chrome/browser/ui/views/apps/app_window_desktop_native_widget_aura_win.h b/chrome/browser/ui/views/apps/app_window_desktop_native_widget_aura_win.h index 75f3464..2bb5ce2 100644 --- a/chrome/browser/ui/views/apps/app_window_desktop_native_widget_aura_win.h +++ b/chrome/browser/ui/views/apps/app_window_desktop_native_widget_aura_win.h
@@ -29,11 +29,10 @@ ChromeNativeAppWindowViewsWin* app_window); protected: - virtual ~AppWindowDesktopNativeWidgetAuraWin(); + ~AppWindowDesktopNativeWidgetAuraWin() override; // Overridden from views::DesktopNativeWidgetAura: - virtual void InitNativeWidget( - const views::Widget::InitParams& params) override; + void InitNativeWidget(const views::Widget::InitParams& params) override; void Maximize() override; void Minimize() override;
diff --git a/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.h b/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.h index 2ef2063..fb3cb19 100644 --- a/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.h +++ b/chrome/browser/ui/views/apps/app_window_desktop_window_tree_host_win.h
@@ -22,15 +22,13 @@ AppWindowDesktopWindowTreeHostWin( ChromeNativeAppWindowViewsWin* app_window, views::DesktopNativeWidgetAura* desktop_native_widget_aura); - virtual ~AppWindowDesktopWindowTreeHostWin(); + ~AppWindowDesktopWindowTreeHostWin() override; private: // Overridden from DesktopWindowTreeHostWin: - virtual bool GetClientAreaInsets(gfx::Insets* insets) const override; - virtual void HandleFrameChanged() override; - virtual void PostHandleMSG(UINT message, - WPARAM w_param, - LPARAM l_param) override; + bool GetClientAreaInsets(gfx::Insets* insets) const override; + void HandleFrameChanged() override; + void PostHandleMSG(UINT message, WPARAM w_param, LPARAM l_param) override; // Updates the glass frame area by calling the DwmExtendFrameIntoClientArea // Windows function.
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.h index ceec2b9..d4e2d54 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.h +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.h
@@ -24,6 +24,7 @@ // ui::BaseWindow implementation. void Show() override; void ShowInactive() override; + void FlashFrame(bool flash) override; // NativeAppWindow implementation. // These are used to simulate Mac-style hide/show. Since windows can be hidden
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.mm b/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.mm index 3356dcb..1d2f0fd 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.mm +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.mm
@@ -50,6 +50,12 @@ ChromeNativeAppWindowViews::ShowInactive(); } +void ChromeNativeAppWindowViewsMac::FlashFrame(bool flash) { + apps::ExtensionAppShimHandler::RequestUserAttentionForWindow( + app_window(), flash ? apps::APP_SHIM_ATTENTION_CRITICAL + : apps::APP_SHIM_ATTENTION_CANCEL); +} + void ChromeNativeAppWindowViewsMac::ShowWithApp() { is_hidden_with_app_ = false; if (!app_window()->is_hidden())
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h index e43ce51..c4d5ed3 100644 --- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h +++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h
@@ -34,23 +34,23 @@ void EnsureCaptionStyleSet(); // Overridden from ChromeNativeAppWindowViews: - virtual void OnBeforeWidgetInit( + void OnBeforeWidgetInit( const extensions::AppWindow::CreateParams& create_params, views::Widget::InitParams* init_params, views::Widget* widget) override; - virtual void InitializeDefaultWindow( + void InitializeDefaultWindow( const extensions::AppWindow::CreateParams& create_params) override; - virtual views::NonClientFrameView* CreateStandardDesktopAppFrame() override; + views::NonClientFrameView* CreateStandardDesktopAppFrame() override; // Overridden from ui::BaseWindow: - virtual void Show() override; - virtual void Activate() override; + void Show() override; + void Activate() override; // Overridden from views::WidgetDelegate: bool CanMinimize() const override; // Overridden from extensions::NativeAppWindow: - virtual void UpdateShelfMenu() override; + void UpdateShelfMenu() override; // Populated if there is a glass frame, which provides special information // to the native widget implementation. This will be NULL if there is no
diff --git a/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.h b/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.h index 7de1d1a..cccd40b6 100644 --- a/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.h +++ b/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.h
@@ -19,28 +19,27 @@ explicit GlassAppWindowFrameViewWin(extensions::NativeAppWindow* window, views::Widget* widget); - virtual ~GlassAppWindowFrameViewWin(); + ~GlassAppWindowFrameViewWin() override; gfx::Insets GetGlassInsets() const; private: // views::NonClientFrameView implementation. - virtual gfx::Rect GetBoundsForClientView() const override; - virtual gfx::Rect GetWindowBoundsForClientBounds( + gfx::Rect GetBoundsForClientView() const override; + gfx::Rect GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const override; - virtual int NonClientHitTest(const gfx::Point& point) override; - virtual void GetWindowMask(const gfx::Size& size, - gfx::Path* window_mask) override; - virtual void ResetWindowControls() override {} - virtual void UpdateWindowIcon() override {} - virtual void UpdateWindowTitle() override {} - virtual void SizeConstraintsChanged() override {} + int NonClientHitTest(const gfx::Point& point) override; + void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) override; + void ResetWindowControls() override {} + void UpdateWindowIcon() override {} + void UpdateWindowTitle() override {} + void SizeConstraintsChanged() override {} // views::View implementation. - virtual gfx::Size GetPreferredSize() const override; - virtual const char* GetClassName() const override; - virtual gfx::Size GetMinimumSize() const override; - virtual gfx::Size GetMaximumSize() const override; + gfx::Size GetPreferredSize() const override; + const char* GetClassName() const override; + gfx::Size GetMinimumSize() const override; + gfx::Size GetMaximumSize() const override; extensions::NativeAppWindow* window_; views::Widget* widget_;
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views_unittest.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views_unittest.cc index de06d74..ea4513aca 100644 --- a/chrome/browser/ui/views/autofill/autofill_dialog_views_unittest.cc +++ b/chrome/browser/ui/views/autofill/autofill_dialog_views_unittest.cc
@@ -50,10 +50,10 @@ class AutofillDialogViewsTest : public TestWithBrowserView { public: AutofillDialogViewsTest() {} - virtual ~AutofillDialogViewsTest() {} + ~AutofillDialogViewsTest() override {} // TestWithBrowserView: - virtual void SetUp() override { + void SetUp() override { TestWithBrowserView::SetUp(); view_delegate_.SetProfile(profile()); @@ -79,7 +79,7 @@ dialog_->Show(); } - virtual void TearDown() override { + void TearDown() override { dialog_->GetWidget()->CloseNow(); dialog_.reset();
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc index 01931d3..edaf860 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc
@@ -41,9 +41,9 @@ class AutofillPopupBaseViewTest : public InProcessBrowserTest { public: AutofillPopupBaseViewTest() {} - virtual ~AutofillPopupBaseViewTest() {} + ~AutofillPopupBaseViewTest() override {} - virtual void SetUpOnMainThread() override { + void SetUpOnMainThread() override { gfx::NativeView native_view = browser()->tab_strip_model()->GetActiveWebContents()->GetNativeView(); EXPECT_CALL(mock_delegate_, container_view())
diff --git a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc index 984aee66..20425fb 100644 --- a/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc +++ b/chrome/browser/ui/views/autofill/card_unmask_prompt_views.cc
@@ -109,7 +109,8 @@ // TODO(estade): it's somewhat jarring when the error comes back too // quickly. overlay_animation_.Reset(); - storage_row_->SetAlpha(255); + if (storage_row_) + storage_row_->SetAlpha(255); progress_overlay_->SetVisible(false); if (allow_retry) {
diff --git a/chrome/browser/ui/views/chrome_views_delegate.cc b/chrome/browser/ui/views/chrome_views_delegate.cc index 01a0585..4e935736 100644 --- a/chrome/browser/ui/views/chrome_views_delegate.cc +++ b/chrome/browser/ui/views/chrome_views_delegate.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser_window_state.h" #include "chrome/common/chrome_version_info.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/context_factory.h" #include "grit/chrome_unscaled_resources.h" #include "ui/base/resource/resource_bundle.h" @@ -388,6 +389,16 @@ return chrome::VersionInfo().Name(); } +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +scoped_refptr<base::TaskRunner> + ChromeViewsDelegate::GetTaskRunnerForAuraLinuxAccessibilityInit() { + // This should be on the FILE thread so that we can open libatk-bridge.so + // without blocking. + return content::BrowserThread::GetMessageLoopProxyForThread( + content::BrowserThread::FILE); +} +#endif + #if defined(OS_WIN) int ChromeViewsDelegate::GetAppbarAutohideEdges(HMONITOR monitor, const base::Closure& callback) {
diff --git a/chrome/browser/ui/views/chrome_views_delegate.h b/chrome/browser/ui/views/chrome_views_delegate.h index d4d197f..18ba035 100644 --- a/chrome/browser/ui/views/chrome_views_delegate.h +++ b/chrome/browser/ui/views/chrome_views_delegate.h
@@ -28,9 +28,9 @@ void NotifyAccessibilityEvent(views::View* view, ui::AXEvent event_type) override; #if defined(OS_WIN) - virtual HICON GetDefaultWindowIcon() const override; - virtual HICON GetSmallWindowIcon() const override; - virtual bool IsWindowInMetro(gfx::NativeWindow window) const override; + HICON GetDefaultWindowIcon() const override; + HICON GetSmallWindowIcon() const override; + bool IsWindowInMetro(gfx::NativeWindow window) const override; #elif defined(OS_LINUX) && !defined(OS_CHROMEOS) gfx::ImageSkia* GetDefaultWindowIcon() const override; #endif @@ -49,9 +49,13 @@ #endif ui::ContextFactory* GetContextFactory() override; std::string GetApplicationName() override; +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + scoped_refptr<base::TaskRunner> + GetTaskRunnerForAuraLinuxAccessibilityInit() override; +#endif #if defined(OS_WIN) - virtual int GetAppbarAutohideEdges(HMONITOR monitor, - const base::Closure& callback) override; + int GetAppbarAutohideEdges(HMONITOR monitor, + const base::Closure& callback) override; #endif private:
diff --git a/chrome/browser/ui/views/color_chooser_dialog.h b/chrome/browser/ui/views/color_chooser_dialog.h index b23061a3..0afc50f9 100644 --- a/chrome/browser/ui/views/color_chooser_dialog.h +++ b/chrome/browser/ui/views/color_chooser_dialog.h
@@ -23,11 +23,11 @@ ColorChooserDialog(views::ColorChooserListener* listener, SkColor initial_color, gfx::NativeWindow owning_window); - virtual ~ColorChooserDialog(); + ~ColorChooserDialog() override; // BaseShellDialog: - virtual bool IsRunning(gfx::NativeWindow owning_window) const override; - virtual void ListenerDestroyed() override; + bool IsRunning(gfx::NativeWindow owning_window) const override; + void ListenerDestroyed() override; private: struct ExecuteOpenParams {
diff --git a/chrome/browser/ui/views/color_chooser_win.cc b/chrome/browser/ui/views/color_chooser_win.cc index ce4ee36..8d44da4c 100644 --- a/chrome/browser/ui/views/color_chooser_win.cc +++ b/chrome/browser/ui/views/color_chooser_win.cc
@@ -23,15 +23,15 @@ ColorChooserWin(content::WebContents* web_contents, SkColor initial_color); - ~ColorChooserWin(); + ~ColorChooserWin() override; // content::ColorChooser overrides: - virtual void End() override; - virtual void SetSelectedColor(SkColor color) override {} + void End() override; + void SetSelectedColor(SkColor color) override {} // views::ColorChooserListener overrides: - virtual void OnColorChosen(SkColor color); - virtual void OnColorChooserDialogClosed(); + void OnColorChosen(SkColor color) override; + void OnColorChooserDialogClosed() override; private: static ColorChooserWin* current_color_chooser_;
diff --git a/chrome/browser/ui/views/conflicting_module_view_win.h b/chrome/browser/ui/views/conflicting_module_view_win.h index 3775092c..fa4e496 100644 --- a/chrome/browser/ui/views/conflicting_module_view_win.h +++ b/chrome/browser/ui/views/conflicting_module_view_win.h
@@ -32,7 +32,7 @@ static void MaybeShow(Browser* browser, views::View* anchor_view); private: - virtual ~ConflictingModuleView(); + ~ConflictingModuleView() override; // Shows the bubble and updates the counter for how often it has been shown. void ShowBubble(); @@ -42,22 +42,21 @@ void DismissBubble(); // views::BubbleDelegateView implementation: - virtual void Init() override; + void Init() override; // views::ButtonListener implementation. - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) override; + void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::View implementation. - virtual void GetAccessibleState(ui::AXViewState* state) override; - virtual void ViewHierarchyChanged( + void GetAccessibleState(ui::AXViewState* state) override; + void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) override; // content::NotificationObserver implementation. - virtual void Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + void Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; Browser* browser_;
diff --git a/chrome/browser/ui/views/desktop_media_picker_views_unittest.cc b/chrome/browser/ui/views/desktop_media_picker_views_unittest.cc index 0e2e3f1..50c594c 100644 --- a/chrome/browser/ui/views/desktop_media_picker_views_unittest.cc +++ b/chrome/browser/ui/views/desktop_media_picker_views_unittest.cc
@@ -23,9 +23,9 @@ class DesktopMediaPickerViewsTest : public testing::Test { public: DesktopMediaPickerViewsTest() {} - virtual ~DesktopMediaPickerViewsTest() {} + ~DesktopMediaPickerViewsTest() override {} - virtual void SetUp() override { + void SetUp() override { bool enable_pixel_output = false; ui::ContextFactory* context_factory = ui::InitializeContextFactoryForTests(enable_pixel_output); @@ -56,7 +56,7 @@ base::Unretained(this))); } - virtual void TearDown() override { + void TearDown() override { test_helper_->TearDown(); ui::TerminateContextFactoryForTests(); }
diff --git a/chrome/browser/ui/views/extensions/bundle_installed_bubble.cc b/chrome/browser/ui/views/extensions/bundle_installed_bubble.cc index 01b8b2a..5ef269b 100644 --- a/chrome/browser/ui/views/extensions/bundle_installed_bubble.cc +++ b/chrome/browser/ui/views/extensions/bundle_installed_bubble.cc
@@ -2,20 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/i18n/rtl.h" -#include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/bundle_installer.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/browser/ui/views/toolbar/wrench_toolbar_button.h" -#include "chrome/grit/generated_resources.h" -#include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/resources/grit/ui_resources.h" #include "ui/views/bubble/bubble_delegate.h" #include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/grid_layout.h" #include "ui/views/layout/layout_constants.h" @@ -25,11 +20,17 @@ namespace { -// The ID of the column set for the bubble. -const int kColumnSetId = 0; +// The ID of the column set that holds the headings and the close button. +const int kHeadingColumnSetId = 0; -// The width of the left column. -const int kLeftColumnWidth = 325; +// The width of the columns that hold the heading texts and extension names. +const int kTextColumnWidth = 325; + +// The ID of the column set that holds extension icons and names. +const int kItemsColumnSetId = 1; + +// The size of extension icons, and width of the corresponding column. +const int kIconSize = 32; class BundleInstalledBubble : public views::BubbleDelegateView, public views::ButtonListener { @@ -40,23 +41,38 @@ : views::BubbleDelegateView(anchor_view, arrow) { GridLayout* layout = GridLayout::CreatePanel(this); SetLayoutManager(layout); - views::ColumnSet* column_set = layout->AddColumnSet(kColumnSetId); - column_set->AddColumn(GridLayout::LEADING, - GridLayout::FILL, - 0, // no resizing - GridLayout::USE_PREF, - 0, // no fixed with - kLeftColumnWidth); - column_set->AddPaddingColumn(0, views::kPanelHorizMargin); - column_set->AddColumn(GridLayout::LEADING, - GridLayout::LEADING, - 0, // no resizing - GridLayout::USE_PREF, - 0, // no fixed width - 0); // no min width (only holds close button) + views::ColumnSet* heading_column_set = + layout->AddColumnSet(kHeadingColumnSetId); + heading_column_set->AddColumn(GridLayout::LEADING, + GridLayout::FILL, + 100.0f, // take all available space + GridLayout::USE_PREF, + 0, // no fixed width + kTextColumnWidth); + heading_column_set->AddPaddingColumn(0, views::kPanelHorizMargin); + heading_column_set->AddColumn(GridLayout::TRAILING, + GridLayout::LEADING, + 0, // no resizing + GridLayout::USE_PREF, + 0, // no fixed width + 0); // no min width (only holds close button) - layout->StartRow(0, kColumnSetId); + views::ColumnSet* items_column_set = + layout->AddColumnSet(kItemsColumnSetId); + items_column_set->AddColumn(GridLayout::CENTER, + GridLayout::CENTER, + 0, // no resizing + GridLayout::FIXED, + kIconSize, + kIconSize); + items_column_set->AddPaddingColumn(0, views::kPanelHorizMargin); + items_column_set->AddColumn(GridLayout::LEADING, + GridLayout::CENTER, + 100.0f, // take all available space + GridLayout::USE_PREF, + 0, // no fixed width + kTextColumnWidth); AddContent(layout, bundle); } @@ -65,32 +81,34 @@ private: void AddContent(GridLayout* layout, const BundleInstaller* bundle) { - base::string16 installed_heading = bundle->GetHeadingTextFor( + bool has_installed_items = bundle->HasItemWithState( BundleInstaller::Item::STATE_INSTALLED); - base::string16 failed_heading = bundle->GetHeadingTextFor( + bool has_failed_items = bundle->HasItemWithState( BundleInstaller::Item::STATE_FAILED); // Insert the list of installed items. - if (!installed_heading.empty()) { - layout->StartRow(0, kColumnSetId); - AddHeading(layout, installed_heading); + if (has_installed_items) { + layout->StartRow(0, kHeadingColumnSetId); + AddHeading(layout, bundle->GetHeadingTextFor( + BundleInstaller::Item::STATE_INSTALLED)); AddCloseButton(layout, this); AddItemList(layout, bundle->GetItemsWithState( BundleInstaller::Item::STATE_INSTALLED)); // Insert a line of padding if we're showing both sections. - if (!failed_heading.empty()) + if (has_failed_items) layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); } // Insert the list of failed items. - if (!failed_heading.empty()) { - layout->StartRow(0, kColumnSetId); - AddHeading(layout, failed_heading); + if (has_failed_items) { + layout->StartRow(0, kHeadingColumnSetId); + AddHeading(layout, bundle->GetHeadingTextFor( + BundleInstaller::Item::STATE_FAILED)); // The close button should be in the second column of the first row, so // we add it here if there was no installed items section. - if (installed_heading.empty()) + if (!has_installed_items) AddCloseButton(layout, this); AddItemList(layout, bundle->GetItemsWithState( @@ -101,18 +119,23 @@ } void AddItemList(GridLayout* layout, const BundleInstaller::ItemList& items) { - for (size_t i = 0; i < items.size(); ++i) { - base::string16 extension_name = - base::UTF8ToUTF16(items[i].localized_name); - base::i18n::AdjustStringForLocaleDirection(&extension_name); + for (const BundleInstaller::Item& item : items) { layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); - layout->StartRow(0, kColumnSetId); - views::Label* extension_label = new views::Label( - l10n_util::GetStringFUTF16( - IDS_EXTENSION_PERMISSION_LINE, extension_name)); + layout->StartRow(0, kItemsColumnSetId); + gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(item.icon); + gfx::Size size(image.width(), image.height()); + if (size.width() > kIconSize || size.height() > kIconSize) + size = gfx::Size(kIconSize, kIconSize); + views::ImageView* image_view = new views::ImageView; + image_view->SetImage(image); + image_view->SetImageSize(size); + layout->AddView(image_view); + + views::Label* extension_label = + new views::Label(item.GetNameForDisplay()); extension_label->SetMultiLine(true); extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - extension_label->SizeToFit(kLeftColumnWidth); + extension_label->SizeToFit(kTextColumnWidth); layout->AddView(extension_label); } } @@ -136,7 +159,7 @@ heading, rb.GetFontList(ui::ResourceBundle::MediumFont)); heading_label->SetMultiLine(true); heading_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - heading_label->SizeToFit(kLeftColumnWidth); + heading_label->SizeToFit(kTextColumnWidth); layout->AddView(heading_label); }
diff --git a/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc b/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc index be61117..503a7f10 100644 --- a/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc +++ b/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc
@@ -91,19 +91,6 @@ GetDelegateViews()->GetAsView()->set_context_menu_controller(this); } -void ExtensionActionPlatformDelegateViews::CloseActivePopup() { - if (controller_->extension_action()->action_type() == - ActionInfo::TYPE_BROWSER) { - BrowserView::GetBrowserViewForBrowser(controller_->browser())->toolbar()-> - browser_actions()->HideActivePopup(); - } else { - DCHECK_EQ(ActionInfo::TYPE_PAGE, - controller_->extension_action()->action_type()); - // Page actions only know how to close their own popups. - controller_->HidePopup(); - } -} - extensions::ExtensionViewHost* ExtensionActionPlatformDelegateViews::ShowPopupWithUrl( ExtensionActionViewController::PopupShowAction show_action, @@ -211,7 +198,7 @@ context_menu_owner = this; // We shouldn't have both a popup and a context menu showing. - CloseActivePopup(); + controller_->HideActivePopup(); gfx::Point screen_loc; views::View::ConvertPointToScreen(GetDelegateViews()->GetAsView(),
diff --git a/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.h b/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.h index 83b31fbf..f10da0f7 100644 --- a/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.h +++ b/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.h
@@ -42,7 +42,6 @@ bool IsMenuRunning() const override; void RegisterCommand() override; void OnDelegateSet() override; - void CloseActivePopup() override; extensions::ExtensionViewHost* ShowPopupWithUrl( ExtensionActionViewController::PopupShowAction show_action, const GURL& popup_url,
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc index 325fbdd..555c290 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -66,6 +66,12 @@ // align with the button below it. const int kIconOffset = 16; +// Size of the icons of individual extensions for bundle installs. +const int kSmallIconSize = 32; + +// Padding between extension icon and title for bundle installs. +const int kSmallIconPadding = 6; + // The dialog will resize based on its content, but this sets a maximum height // before overflowing a scrollbar. const int kDialogMaxHeight = 300; @@ -78,10 +84,6 @@ // permissions. const int kNoPermissionsLeftColumnWidth = 200; -// Width of the left column for bundle install prompts. There's only one column -// in this case, so make it wider than normal. -const int kBundleLeftColumnWidth = 300; - // Width of the left column for external install prompts. The text is long in // this case, so make it wider than normal. const int kExternalInstallLeftColumnWidth = 350; @@ -125,6 +127,36 @@ layout->AddView(view); } +IconedView::IconedView(views::View* view, const gfx::ImageSkia& image) { + views::GridLayout* layout = new views::GridLayout(this); + SetLayoutManager(layout); + views::ColumnSet* column_set = layout->AddColumnSet(0); + column_set->AddColumn(views::GridLayout::CENTER, + views::GridLayout::LEADING, + 0, + views::GridLayout::FIXED, + kSmallIconSize, + 0); + column_set->AddPaddingColumn(0, kSmallIconPadding); + column_set->AddColumn(views::GridLayout::LEADING, + views::GridLayout::CENTER, + 0, + views::GridLayout::USE_PREF, + 0, // No fixed width. + 0); + layout->StartRow(0, 0); + + gfx::Size size(image.width(), image.height()); + if (size.width() > kSmallIconSize || size.height() > kSmallIconSize) + size = gfx::Size(kSmallIconSize, kSmallIconSize); + views::ImageView* image_view = new views::ImageView; + image_view->SetImage(image); + image_view->SetImageSize(size); + + layout->AddView(image_view); + layout->AddView(view); +} + void ShowExtensionInstallDialogImpl( ExtensionInstallPromptShowParams* show_params, ExtensionInstallPrompt::Delegate* delegate, @@ -204,8 +236,6 @@ (prompt_->ShouldShowPermissions() + prompt_->GetRetainedFileCount()) > 0 ? kPermissionsLeftColumnWidth : kNoPermissionsLeftColumnWidth; - if (is_bundle_install()) - left_column_width = kBundleLeftColumnWidth; if (is_external_install()) left_column_width = kExternalInstallLeftColumnWidth; @@ -224,8 +254,7 @@ scroll_view_->SetContents(scrollable_); int dialog_width = left_column_width + 2 * views::kPanelHorizMargin; - if (!is_bundle_install()) - dialog_width += views::kPanelHorizMargin + kIconSize + kIconOffset; + dialog_width += views::kPanelHorizMargin + kIconSize + kIconOffset; if (prompt_->has_webstore_data()) { layout->StartRow(0, column_set_id); @@ -261,19 +290,19 @@ if (is_bundle_install()) { BundleInstaller::ItemList items = prompt_->bundle()->GetItemsWithState( BundleInstaller::Item::STATE_PENDING); - for (size_t i = 0; i < items.size(); ++i) { - base::string16 extension_name = - base::UTF8ToUTF16(items[i].localized_name); - base::i18n::AdjustStringForLocaleDirection(&extension_name); - layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + layout->AddPaddingRow(0, views::kRelatedControlSmallVerticalSpacing); + for (const BundleInstaller::Item& item : items) { layout->StartRow(0, column_set_id); - views::Label* extension_label = new views::Label( - PrepareForDisplay(extension_name, true)); + views::Label* extension_label = + new views::Label(item.GetNameForDisplay()); extension_label->SetMultiLine(true); extension_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - extension_label->SizeToFit(left_column_width); - layout->AddView(extension_label); + extension_label->SizeToFit( + left_column_width - kSmallIconSize - kSmallIconPadding); + gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(item.icon); + layout->AddView(new IconedView(extension_label, image)); } + layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); } bool has_permissions = @@ -472,15 +501,13 @@ views::GridLayout::USE_PREF, 0, // no fixed width left_column_width); - if (!is_bundle_install()) { - column_set->AddPaddingColumn(0, views::kPanelHorizMargin); - column_set->AddColumn(views::GridLayout::TRAILING, - views::GridLayout::LEADING, - 0, // no resizing - views::GridLayout::USE_PREF, - 0, // no fixed width - kIconSize); - } + column_set->AddPaddingColumn(0, views::kPanelHorizMargin); + column_set->AddColumn(views::GridLayout::TRAILING, + views::GridLayout::LEADING, + 0, // no resizing + views::GridLayout::USE_PREF, + 0, // no fixed width + kIconSize); layout->StartRow(0, column_set_id); @@ -493,38 +520,37 @@ heading->SizeToFit(left_column_width); layout->AddView(heading); - if (!is_bundle_install()) { - // Scale down to icon size, but allow smaller icons (don't scale up). - const gfx::ImageSkia* image = prompt_->icon().ToImageSkia(); - gfx::Size size(image->width(), image->height()); - if (size.width() > kIconSize || size.height() > kIconSize) - size = gfx::Size(kIconSize, kIconSize); - views::ImageView* icon = new views::ImageView(); - icon->SetImageSize(size); - icon->SetImage(*image); - icon->SetHorizontalAlignment(views::ImageView::CENTER); - icon->SetVerticalAlignment(views::ImageView::CENTER); - if (single_detail_row) { - layout->AddView(icon); - } else { - int icon_row_span = 1; - if (is_inline_install()) { - // Also span the rating, user_count and store_link rows. - icon_row_span = 4; - } else if (prompt_->ShouldShowPermissions()) { - size_t permission_count = prompt_->GetPermissionCount( - ExtensionInstallPrompt::PermissionsType::ALL_PERMISSIONS); - // Also span the permission header and each of the permission rows (all - // have a padding row above it). This also works for the 'no special - // permissions' case. - icon_row_span = 3 + permission_count * 2; - } else if (prompt_->GetRetainedFileCount()) { - // Also span the permission header and the retained files container. - icon_row_span = 4; - } - layout->AddView(icon, 1, icon_row_span); + // Scale down to icon size, but allow smaller icons (don't scale up). + const gfx::ImageSkia* image = prompt_->icon().ToImageSkia(); + gfx::Size size(image->width(), image->height()); + if (size.width() > kIconSize || size.height() > kIconSize) + size = gfx::Size(kIconSize, kIconSize); + views::ImageView* icon = new views::ImageView(); + icon->SetImageSize(size); + icon->SetImage(*image); + icon->SetHorizontalAlignment(views::ImageView::CENTER); + icon->SetVerticalAlignment(views::ImageView::CENTER); + if (single_detail_row) { + layout->AddView(icon); + } else { + int icon_row_span = 1; + if (is_inline_install()) { + // Also span the rating, user_count and store_link rows. + icon_row_span = 4; + } else if (prompt_->ShouldShowPermissions()) { + size_t permission_count = prompt_->GetPermissionCount( + ExtensionInstallPrompt::PermissionsType::ALL_PERMISSIONS); + // Also span the permission header and each of the permission rows (all + // have a padding row above it). This also works for the 'no special + // permissions' case. + icon_row_span = 3 + permission_count * 2; + } else if (prompt_->GetRetainedFileCount()) { + // Also span the permission header and the retained files container. + icon_row_span = 4; } + layout->AddView(icon, 1, icon_row_span); } + return layout; }
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h index c904edd..4d97b50 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
@@ -147,6 +147,15 @@ DISALLOW_COPY_AND_ASSIGN(BulletedView); }; +// A simple view that prepends a view with an icon with the help of a grid +// layout. +class IconedView : public views::View { + public: + IconedView(views::View* view, const gfx::ImageSkia& image); + private: + DISALLOW_COPY_AND_ASSIGN(IconedView); +}; + // A view to display text with an expandable details section. class ExpandableContainerView : public views::View, public views::ButtonListener,
diff --git a/chrome/browser/ui/views/extensions/media_galleries_dialog_views_unittest.cc b/chrome/browser/ui/views/extensions/media_galleries_dialog_views_unittest.cc index 266904a7..b865b09 100644 --- a/chrome/browser/ui/views/extensions/media_galleries_dialog_views_unittest.cc +++ b/chrome/browser/ui/views/extensions/media_galleries_dialog_views_unittest.cc
@@ -35,8 +35,8 @@ class MediaGalleriesDialogTest : public testing::Test { public: MediaGalleriesDialogTest() {} - virtual ~MediaGalleriesDialogTest() {} - virtual void SetUp() override { + ~MediaGalleriesDialogTest() override {} + void SetUp() override { std::vector<base::string16> headers; headers.push_back(base::string16()); headers.push_back(base::ASCIIToUTF16("header2")); @@ -46,7 +46,7 @@ Times(AnyNumber()); } - virtual void TearDown() override { + void TearDown() override { Mock::VerifyAndClearExpectations(&controller_); }
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc index a280299..ea2d19d 100644 --- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc +++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
@@ -41,27 +41,27 @@ : delegate_(delegate) { } - virtual bool UsingSystemTheme() const override { + bool UsingSystemTheme() const override { return delegate_->UsingSystemTheme(); } - virtual gfx::ImageSkia* GetImageSkiaNamed(int id) const override { + gfx::ImageSkia* GetImageSkiaNamed(int id) const override { return delegate_->GetImageSkiaNamed( chrome::MapThemeImage(chrome::HOST_DESKTOP_TYPE_NATIVE, id)); } - virtual SkColor GetColor(int id) const override { + SkColor GetColor(int id) const override { return delegate_->GetColor(id); } - virtual int GetDisplayProperty(int id) const override { + int GetDisplayProperty(int id) const override { return delegate_->GetDisplayProperty(id); } - virtual bool ShouldUseNativeFrame() const override { + bool ShouldUseNativeFrame() const override { return delegate_->ShouldUseNativeFrame(); } - virtual bool HasCustomImage(int id) const override { + bool HasCustomImage(int id) const override { return delegate_->HasCustomImage( chrome::MapThemeImage(chrome::HOST_DESKTOP_TYPE_NATIVE, id)); } - virtual base::RefCountedMemory* GetRawData( + base::RefCountedMemory* GetRawData( int id, ui::ScaleFactor scale_factor) const override { return delegate_->GetRawData(id, scale_factor);
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.h b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.h index bfb355b..26f20c22 100644 --- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.h +++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.h
@@ -29,31 +29,29 @@ views::DesktopNativeWidgetAura* desktop_native_widget_aura, BrowserView* browser_view, BrowserFrame* browser_frame); - virtual ~BrowserDesktopWindowTreeHostWin(); + ~BrowserDesktopWindowTreeHostWin() override; private: views::NativeMenuWin* GetSystemMenu(); // Overridden from BrowserDesktopWindowTreeHost: - virtual DesktopWindowTreeHost* AsDesktopWindowTreeHost() override; - virtual int GetMinimizeButtonOffset() const override; - virtual bool UsesNativeSystemMenu() const override; + DesktopWindowTreeHost* AsDesktopWindowTreeHost() override; + int GetMinimizeButtonOffset() const override; + bool UsesNativeSystemMenu() const override; // Overridden from DesktopWindowTreeHostWin: - virtual int GetInitialShowState() const override; - virtual bool GetClientAreaInsets(gfx::Insets* insets) const override; - virtual void HandleCreate() override; - virtual void HandleFrameChanged() override; - virtual bool PreHandleMSG(UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* result) override; - virtual void PostHandleMSG(UINT message, - WPARAM w_param, - LPARAM l_param) override; - virtual bool IsUsingCustomFrame() const override; - virtual bool ShouldUseNativeFrame() const override; - virtual void FrameTypeChanged() override; + int GetInitialShowState() const override; + bool GetClientAreaInsets(gfx::Insets* insets) const override; + void HandleCreate() override; + void HandleFrameChanged() override; + bool PreHandleMSG(UINT message, + WPARAM w_param, + LPARAM l_param, + LRESULT* result) override; + void PostHandleMSG(UINT message, WPARAM w_param, LPARAM l_param) override; + bool IsUsingCustomFrame() const override; + bool ShouldUseNativeFrame() const override; + void FrameTypeChanged() override; void UpdateDWMFrame();
diff --git a/chrome/browser/ui/views/frame/browser_frame_ashwin.h b/chrome/browser/ui/views/frame/browser_frame_ashwin.h index 8bad8ee..2352689 100644 --- a/chrome/browser/ui/views/frame/browser_frame_ashwin.h +++ b/chrome/browser/ui/views/frame/browser_frame_ashwin.h
@@ -14,11 +14,12 @@ BrowserFrameAshWin(BrowserFrame* browser_frame, BrowserView* browser_view); protected: - virtual ~BrowserFrameAshWin(); + ~BrowserFrameAshWin() override; // Overridden from aura::client::ActivationChangeObserver: - virtual void OnWindowFocused(aura::Window* gained_focus, - aura::Window* lost_focus) override; + void OnWindowFocused(aura::Window* gained_focus, + aura::Window* lost_focus) override; + private: DISALLOW_COPY_AND_ASSIGN(BrowserFrameAshWin); };
diff --git a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc index ae7560a..ef19840 100644 --- a/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc +++ b/chrome/browser/ui/views/frame/browser_window_property_manager_browsertest_win.cc
@@ -169,7 +169,7 @@ public: BrowserTestWithProfileShortcutManager() {} - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitch(switches::kEnableProfileShortcutManager); }
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h index 7d29eb9..292d56e1 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -17,43 +17,41 @@ public: // Constructs a non-client view for an BrowserFrame. GlassBrowserFrameView(BrowserFrame* frame, BrowserView* browser_view); - virtual ~GlassBrowserFrameView(); + ~GlassBrowserFrameView() override; // BrowserNonClientFrameView: - virtual gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const override; - virtual int GetTopInset() const override; - virtual int GetThemeBackgroundXInset() const override; - virtual void UpdateThrobber(bool running) override; - virtual gfx::Size GetMinimumSize() const override; + gfx::Rect GetBoundsForTabStrip(views::View* tabstrip) const override; + int GetTopInset() const override; + int GetThemeBackgroundXInset() const override; + void UpdateThrobber(bool running) override; + gfx::Size GetMinimumSize() const override; // views::NonClientFrameView: - virtual gfx::Rect GetBoundsForClientView() const override; - virtual gfx::Rect GetWindowBoundsForClientBounds( + gfx::Rect GetBoundsForClientView() const override; + gfx::Rect GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const override; - virtual int NonClientHitTest(const gfx::Point& point) override; - virtual void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) - override {} - virtual void ResetWindowControls() override {} - virtual void UpdateWindowIcon() override {} - virtual void UpdateWindowTitle() override {} - virtual void SizeConstraintsChanged() override {} + int NonClientHitTest(const gfx::Point& point) override; + void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) override {} + void ResetWindowControls() override {} + void UpdateWindowIcon() override {} + void UpdateWindowTitle() override {} + void SizeConstraintsChanged() override {} protected: // views::View: - virtual void OnPaint(gfx::Canvas* canvas) override; - virtual void Layout() override; + void OnPaint(gfx::Canvas* canvas) override; + void Layout() override; // views::ButtonListener: - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) override; + void ButtonPressed(views::Button* sender, const ui::Event& event) override; // BrowserNonClientFrameView: void UpdateNewAvatarButtonImpl() override; private: // views::NonClientFrameView: - virtual bool DoesIntersectRect(const views::View* target, - const gfx::Rect& rect) const override; + bool DoesIntersectRect(const views::View* target, + const gfx::Rect& rect) const override; // Returns the thickness of the border that makes up the window frame edges. // This does not include any client edge.
diff --git a/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h b/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h index 86f03a21..b1bc124 100644 --- a/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h +++ b/chrome/browser/ui/views/frame/system_menu_insertion_delegate_win.h
@@ -15,10 +15,10 @@ class SystemMenuInsertionDelegateWin : public views::MenuInsertionDelegateWin { public: SystemMenuInsertionDelegateWin() {} - virtual ~SystemMenuInsertionDelegateWin() {} + ~SystemMenuInsertionDelegateWin() override {} // Overridden from views::MenuInsertionDelegateWin: - virtual int GetInsertionIndex(HMENU native_menu) override; + int GetInsertionIndex(HMENU native_menu) override; private: DISALLOW_COPY_AND_ASSIGN(SystemMenuInsertionDelegateWin);
diff --git a/chrome/browser/ui/views/location_bar/page_action_image_view.cc b/chrome/browser/ui/views/location_bar/page_action_image_view.cc index c0403057..10cd7d6 100644 --- a/chrome/browser/ui/views/location_bar/page_action_image_view.cc +++ b/chrome/browser/ui/views/location_bar/page_action_image_view.cc
@@ -28,7 +28,8 @@ extensions::ExtensionRegistry::Get(browser->profile())-> enabled_extensions().GetByID(page_action->extension_id()), browser, - page_action)), + page_action, + nullptr)), owner_(owner), preview_enabled_(false) { // There should be an associated focus manager so that we can safely register @@ -138,11 +139,6 @@ return GetWidget(); } -ToolbarActionViewController* -PageActionImageView::GetPreferredPopupViewController() { - return view_controller_.get(); -} - views::View* PageActionImageView::GetReferenceViewForPopup() { return this; }
diff --git a/chrome/browser/ui/views/location_bar/page_action_image_view.h b/chrome/browser/ui/views/location_bar/page_action_image_view.h index b158edb..f2ea484 100644 --- a/chrome/browser/ui/views/location_bar/page_action_image_view.h +++ b/chrome/browser/ui/views/location_bar/page_action_image_view.h
@@ -65,7 +65,6 @@ bool IsShownInMenu() override; views::FocusManager* GetFocusManagerForAccelerator() override; views::Widget* GetParentForContextMenu() override; - ToolbarActionViewController* GetPreferredPopupViewController() override; views::View* GetReferenceViewForPopup() override; views::MenuButton* GetContextMenuButton() override; content::WebContents* GetCurrentWebContents() const override;
diff --git a/chrome/browser/ui/views/location_bar/star_view_browsertest.cc b/chrome/browser/ui/views/location_bar/star_view_browsertest.cc index f5c620df..c0b7b21 100644 --- a/chrome/browser/ui/views/location_bar/star_view_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/star_view_browsertest.cc
@@ -73,7 +73,7 @@ public: StarViewTestNoDWM() {} - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { command_line->AppendSwitch(switches::kDisableDwmComposition); } };
diff --git a/chrome/browser/ui/views/menu_controller_interactive_uitest.cc b/chrome/browser/ui/views/menu_controller_interactive_uitest.cc index a49aaa80e..05c4c23 100644 --- a/chrome/browser/ui/views/menu_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/menu_controller_interactive_uitest.cc
@@ -13,11 +13,11 @@ MenuControllerMnemonicTest() { } - virtual ~MenuControllerMnemonicTest() { + ~MenuControllerMnemonicTest() override { } // MenuTestBase overrides: - virtual void BuildMenu(views::MenuItemView* menu) override { + void BuildMenu(views::MenuItemView* menu) override { ASSERT_NE(ui::VKEY_DIVIDE, '/'); menu->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One&/")); menu->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two"));
diff --git a/chrome/browser/ui/views/menu_controller_test.cc b/chrome/browser/ui/views/menu_controller_test.cc index 496ea057..64b245f 100644 --- a/chrome/browser/ui/views/menu_controller_test.cc +++ b/chrome/browser/ui/views/menu_controller_test.cc
@@ -13,17 +13,16 @@ MenuControllerMnemonicTest() { } - virtual ~MenuControllerMnemonicTest() { - } + ~MenuControllerMnemonicTest() override {} // MenuTestBase overrides: - virtual void BuildMenu(views::MenuItemView* menu) override { + void BuildMenu(views::MenuItemView* menu) override { ASSERT_NE(ui::VKEY_DIVIDE, '/'); menu->AppendMenuItemWithLabel(1, base::ASCIIToUTF16("One&/")); menu->AppendMenuItemWithLabel(2, base::ASCIIToUTF16("Two")); } - virtual void DoTestWithMenuOpen() { + void DoTestWithMenuOpen() override { ASSERT_TRUE(menu()->GetSubmenu()->IsShowing()); KeyPress(KEYCODE, CreateEventTask(this, &MenuControllerMnemonicTest::Step2));
diff --git a/chrome/browser/ui/views/menu_item_view_interactive_uitest.cc b/chrome/browser/ui/views/menu_item_view_interactive_uitest.cc index 00160be5..c28a9a0d 100644 --- a/chrome/browser/ui/views/menu_item_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/menu_item_view_interactive_uitest.cc
@@ -18,11 +18,11 @@ MenuItemViewTestBasic() { } - virtual ~MenuItemViewTestBasic() { + ~MenuItemViewTestBasic() override { } // MenuTestBase implementation - virtual void BuildMenu(views::MenuItemView* menu) override { + void BuildMenu(views::MenuItemView* menu) override { menu->AppendMenuItemWithLabel(1, ASCIIToUTF16("item 1")); menu->AppendMenuItemWithLabel(2, ASCIIToUTF16("item 2")); menu->AppendSeparator(); @@ -30,7 +30,7 @@ } // Click on item INDEX. - virtual void DoTestWithMenuOpen() override { + void DoTestWithMenuOpen() override { views::SubmenuView* submenu = menu()->GetSubmenu(); ASSERT_TRUE(submenu); ASSERT_TRUE(submenu->IsShowing()); @@ -68,17 +68,17 @@ MenuItemViewTestInsert() : inserted_item_(NULL) { } - virtual ~MenuItemViewTestInsert() { + ~MenuItemViewTestInsert() override { } // MenuTestBase implementation - virtual void BuildMenu(views::MenuItemView* menu) override { + void BuildMenu(views::MenuItemView* menu) override { menu->AppendMenuItemWithLabel(1, ASCIIToUTF16("item 1")); menu->AppendMenuItemWithLabel(2, ASCIIToUTF16("item 2")); } // Insert item at INSERT_INDEX and click item at SELECT_INDEX. - virtual void DoTestWithMenuOpen() override { + void DoTestWithMenuOpen() override { views::SubmenuView* submenu = menu()->GetSubmenu(); ASSERT_TRUE(submenu); ASSERT_TRUE(submenu->IsShowing()); @@ -150,11 +150,11 @@ inserted_item_(NULL) { } - virtual ~MenuItemViewTestInsertWithSubmenu() { + ~MenuItemViewTestInsertWithSubmenu() override { } // MenuTestBase implementation - virtual void BuildMenu(views::MenuItemView* menu) override { + void BuildMenu(views::MenuItemView* menu) override { submenu_ = menu->AppendSubMenu(1, ASCIIToUTF16("My Submenu")); submenu_->AppendMenuItemWithLabel(101, ASCIIToUTF16("submenu item 1")); submenu_->AppendMenuItemWithLabel(101, ASCIIToUTF16("submenu item 2")); @@ -162,7 +162,7 @@ } // Post submenu. - virtual void DoTestWithMenuOpen() override { + void DoTestWithMenuOpen() override { Click(submenu_, CreateEventTask(this, &MenuItemViewTestInsertWithSubmenu::Step2)); } @@ -209,18 +209,18 @@ MenuItemViewTestRemove() { } - virtual ~MenuItemViewTestRemove() { + ~MenuItemViewTestRemove() override { } // MenuTestBase implementation - virtual void BuildMenu(views::MenuItemView* menu) override { + void BuildMenu(views::MenuItemView* menu) override { menu->AppendMenuItemWithLabel(1, ASCIIToUTF16("item 1")); menu->AppendMenuItemWithLabel(2, ASCIIToUTF16("item 2")); menu->AppendMenuItemWithLabel(3, ASCIIToUTF16("item 3")); } // Remove item at REMOVE_INDEX and click item at SELECT_INDEX. - virtual void DoTestWithMenuOpen() override { + void DoTestWithMenuOpen() override { views::SubmenuView* submenu = menu()->GetSubmenu(); ASSERT_TRUE(submenu); ASSERT_TRUE(submenu->IsShowing()); @@ -275,11 +275,11 @@ MenuItemViewTestRemoveWithSubmenu() : submenu_(NULL) { } - virtual ~MenuItemViewTestRemoveWithSubmenu() { + ~MenuItemViewTestRemoveWithSubmenu() override { } // MenuTestBase implementation - virtual void BuildMenu(views::MenuItemView* menu) override { + void BuildMenu(views::MenuItemView* menu) override { menu->AppendMenuItemWithLabel(1, ASCIIToUTF16("item 1")); submenu_ = menu->AppendSubMenu(2, ASCIIToUTF16("My Submenu")); submenu_->AppendMenuItemWithLabel(101, ASCIIToUTF16("submenu item 1")); @@ -287,7 +287,7 @@ } // Post submenu. - virtual void DoTestWithMenuOpen() override { + void DoTestWithMenuOpen() override { views::SubmenuView* submenu = menu()->GetSubmenu(); ASSERT_TRUE(submenu); ASSERT_TRUE(submenu->IsShowing());
diff --git a/chrome/browser/ui/views/message_center/web_notification_tray.h b/chrome/browser/ui/views/message_center/web_notification_tray.h index c6ddd0a..e08984c 100644 --- a/chrome/browser/ui/views/message_center/web_notification_tray.h +++ b/chrome/browser/ui/views/message_center/web_notification_tray.h
@@ -67,7 +67,7 @@ // StatusIconObserver implementation. void OnStatusIconClicked() override; #if defined(OS_WIN) - virtual void OnBalloonClicked() override; + void OnBalloonClicked() override; // This shows a platform-specific balloon informing the user of the existence // of the message center in the status tray area.
diff --git a/chrome/browser/ui/views/network_profile_bubble_view.h b/chrome/browser/ui/views/network_profile_bubble_view.h index f24c517..97720f6 100644 --- a/chrome/browser/ui/views/network_profile_bubble_view.h +++ b/chrome/browser/ui/views/network_profile_bubble_view.h
@@ -25,17 +25,16 @@ content::PageNavigator* navigator, Profile* profile); private: - virtual ~NetworkProfileBubbleView(); + ~NetworkProfileBubbleView() override; // views::BubbleDelegateView: - virtual void Init() override; + void Init() override; // views::ButtonListener: - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) override; + void ButtonPressed(views::Button* sender, const ui::Event& event) override; // views::LinkListener: - virtual void LinkClicked(views::Link* source, int event_flags) override; + void LinkClicked(views::Link* source, int event_flags) override; // Used for loading pages. content::PageNavigator* navigator_;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc index b50d8e6..b5a23479 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -223,8 +223,6 @@ } void OmniboxViewViews::Update() { - UpdatePlaceholderText(); - const ToolbarModel::SecurityLevel old_security_level = security_level_; security_level_ = controller()->GetToolbarModel()->GetSecurityLevel(false); if (model()->UpdatePermanentText()) { @@ -258,11 +256,6 @@ } } -void OmniboxViewViews::UpdatePlaceholderText() { - if (OmniboxFieldTrial::DisplayHintTextWhenPossible()) - set_placeholder_text(GetHintText()); -} - base::string16 OmniboxViewViews::GetText() const { // TODO(oshima): IME support return text();
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h index fb4c8751..a469a3f 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -70,7 +70,6 @@ void OnTabChanged(const content::WebContents* web_contents) override; void ResetTabState(content::WebContents* web_contents) override; void Update() override; - void UpdatePlaceholderText() override; base::string16 GetText() const override; void SetUserText(const base::string16& text, const base::string16& display_text,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc index a748590..c12e047 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/command_updater.h" #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_CHROMEOS) @@ -106,6 +107,7 @@ #endif } + content::TestBrowserThreadBundle thread_bundle_; TestingProfile profile_; CommandUpdater command_updater_; TestingOmniboxEditController omnibox_edit_controller_;
diff --git a/chrome/browser/ui/views/panels/panel_stack_view.h b/chrome/browser/ui/views/panels/panel_stack_view.h index 5abe1e72..56f8ce8 100644 --- a/chrome/browser/ui/views/panels/panel_stack_view.h +++ b/chrome/browser/ui/views/panels/panel_stack_view.h
@@ -94,14 +94,14 @@ #if defined(OS_WIN) // Overridden from ui::HWNDMessageFilter: - virtual bool FilterMessage(HWND hwnd, - UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* l_result) override; + bool FilterMessage(HWND hwnd, + UINT message, + WPARAM w_param, + LPARAM l_param, + LRESULT* l_result) override; // Overridden from TaskbarWindowThumbnailerDelegateWin: - virtual std::vector<HWND> GetSnapshotWindowHandles() const override; + std::vector<HWND> GetSnapshotWindowHandles() const override; // Updates the live preview snapshot when something changes, like // adding/removing/moving/resizing a stacked panel.
diff --git a/chrome/browser/ui/views/panels/panel_view.h b/chrome/browser/ui/views/panels/panel_view.h index 3d4a0a8..b68e76a 100644 --- a/chrome/browser/ui/views/panels/panel_view.h +++ b/chrome/browser/ui/views/panels/panel_view.h
@@ -143,11 +143,11 @@ // Overridden from ui::HWNDMessageFilter: #if defined(OS_WIN) - virtual bool FilterMessage(HWND hwnd, - UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* l_result) override; + bool FilterMessage(HWND hwnd, + UINT message, + WPARAM w_param, + LPARAM l_param, + LRESULT* l_result) override; #endif // Overridden from AnimationDelegate:
diff --git a/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h b/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h index 66e4fa36..3040039 100644 --- a/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h +++ b/chrome/browser/ui/views/panels/taskbar_window_thumbnailer_win.h
@@ -25,7 +25,7 @@ public: TaskbarWindowThumbnailerWin(HWND hwnd, TaskbarWindowThumbnailerDelegateWin* delegate); - virtual ~TaskbarWindowThumbnailerWin(); + ~TaskbarWindowThumbnailerWin() override; // Starts using the custom snapshot for live preview. The snapshot is only // captured once when the system requests it, so the updates of the panels' @@ -48,11 +48,11 @@ private: // Overridden from ui::HWNDMessageFilter: - virtual bool FilterMessage(HWND hwnd, - UINT message, - WPARAM w_param, - LPARAM l_param, - LRESULT* l_result) override; + bool FilterMessage(HWND hwnd, + UINT message, + WPARAM w_param, + LPARAM l_param, + LRESULT* l_result) override; // Message handlers. bool OnDwmSendIconicThumbnail(int width, int height, LRESULT* l_result);
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 0daf101f..1134383b 100644 --- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc +++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -89,7 +89,6 @@ full_width, 0); break; - case DOUBLE_BUTTON_COLUMN_SET: column_set->AddColumn(views::GridLayout::TRAILING, views::GridLayout::CENTER, @@ -127,6 +126,7 @@ views::GridLayout::USE_PREF, 0, 0); + break; case TRIPLE_BUTTON_COLUMN_SET: column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::CENTER,
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc index 51fd37a..1d548a9 100644 --- a/chrome/browser/ui/views/session_crashed_bubble_view.cc +++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -134,7 +134,7 @@ if (!IsBubbleUIEnabled()) return false; - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (browser->profile()->IsOffTheRecord()) return true;
diff --git a/chrome/browser/ui/views/status_icons/status_icon_win.h b/chrome/browser/ui/views/status_icons/status_icon_win.h index 300bf0c..c2f4ac7 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_win.h +++ b/chrome/browser/ui/views/status_icons/status_icon_win.h
@@ -28,7 +28,7 @@ public: // Constructor which provides this icon's unique ID and messaging window. StatusIconWin(StatusTrayWin* tray, UINT id, HWND window, UINT message); - virtual ~StatusIconWin(); + ~StatusIconWin() override; // Handles a click event from the user - if |left_button_click| is true and // there is a registered observer, passes the click event to the observer, @@ -46,16 +46,16 @@ UINT message_id() const { return message_id_; } // Overridden from StatusIcon: - virtual void SetImage(const gfx::ImageSkia& image) override; - virtual void SetToolTip(const base::string16& tool_tip) override; - virtual void DisplayBalloon(const gfx::ImageSkia& icon, - const base::string16& title, - const base::string16& contents) override; - virtual void ForceVisible() override; + void SetImage(const gfx::ImageSkia& image) override; + void SetToolTip(const base::string16& tool_tip) override; + void DisplayBalloon(const gfx::ImageSkia& icon, + const base::string16& title, + const base::string16& contents) override; + void ForceVisible() override; protected: // Overridden from StatusIcon: - virtual void UpdatePlatformContextMenu(StatusIconMenuModel* menu) override; + void UpdatePlatformContextMenu(StatusIconMenuModel* menu) override; private: void InitIconData(NOTIFYICONDATA* icon_data);
diff --git a/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.h b/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.h index 44676dd..42ec2c0e 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.h +++ b/chrome/browser/ui/views/status_icons/status_tray_state_changer_win.h
@@ -63,9 +63,9 @@ void EnsureTrayIconVisible(); // IUnknown. - virtual ULONG STDMETHODCALLTYPE AddRef() override; - virtual ULONG STDMETHODCALLTYPE Release() override; - virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, PVOID*) override; + ULONG STDMETHODCALLTYPE AddRef() override; + ULONG STDMETHODCALLTYPE Release() override; + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, PVOID*) override; // INotificationCB. // Notify is called in response to RegisterCallback for each current
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.cc b/chrome/browser/ui/views/status_icons/status_tray_win.cc index 471a00a4..2a9c2f29 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_win.cc +++ b/chrome/browser/ui/views/status_icons/status_tray_win.cc
@@ -70,7 +70,7 @@ worker_thread_.init_com_with_mta(false); } - virtual void EnqueueChange(UINT icon_id, HWND window) override { + void EnqueueChange(UINT icon_id, HWND window) override { DCHECK(CalledOnValidThread()); if (pending_requests_ == 0) worker_thread_.Start();
diff --git a/chrome/browser/ui/views/status_icons/status_tray_win.h b/chrome/browser/ui/views/status_icons/status_tray_win.h index e4271d6..260a366 100644 --- a/chrome/browser/ui/views/status_icons/status_tray_win.h +++ b/chrome/browser/ui/views/status_icons/status_tray_win.h
@@ -28,7 +28,7 @@ class StatusTrayWin : public StatusTray { public: StatusTrayWin(); - ~StatusTrayWin(); + ~StatusTrayWin() override; void UpdateIconVisibilityInBackground(StatusIconWin* status_icon); @@ -38,10 +38,9 @@ protected: // Overriden from StatusTray: - virtual StatusIcon* CreatePlatformStatusIcon(StatusIconType type, - const gfx::ImageSkia& image, - const base::string16& tool_tip) - override; + StatusIcon* CreatePlatformStatusIcon(StatusIconType type, + const gfx::ImageSkia& image, + const base::string16& tool_tip) override; private: FRIEND_TEST_ALL_PREFIXES(StatusTrayWinTest, EnsureVisibleTest);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index b01e196..3581de7 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -256,7 +256,7 @@ protected: // views::View: #if defined(OS_WIN) - virtual void OnMouseReleased(const ui::MouseEvent& event) override; + void OnMouseReleased(const ui::MouseEvent& event) override; #endif void OnPaint(gfx::Canvas* canvas) override;
diff --git a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc index 28339f43..48edbf0 100644 --- a/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc +++ b/chrome/browser/ui/views/toolbar/browser_action_test_util_views.cc
@@ -22,26 +22,80 @@ namespace { +// The views-specific implementation of the TestToolbarActionsBarHelper, which +// creates and owns a BrowserActionsContainer. +class TestToolbarActionsBarHelperViews : public TestToolbarActionsBarHelper { + public: + TestToolbarActionsBarHelperViews(Browser* browser, + BrowserActionsContainer* main_bar); + ~TestToolbarActionsBarHelperViews() override; + + BrowserActionsContainer* browser_actions_container() { + return browser_actions_container_; + } + + private: + // The parent of the BrowserActionsContainer, which directly owns the + // container as part of the views hierarchy. + views::View container_parent_; + + // The created BrowserActionsContainer. Owned by |container_parent_|. + BrowserActionsContainer* browser_actions_container_; + + DISALLOW_COPY_AND_ASSIGN(TestToolbarActionsBarHelperViews); +}; + +TestToolbarActionsBarHelperViews::TestToolbarActionsBarHelperViews( + Browser* browser, + BrowserActionsContainer* main_bar) + : browser_actions_container_( + new BrowserActionsContainer(browser, main_bar)) { + // The BrowserActionsContainer expects to have a parent (and be added to the + // view hierarchy), so wrap it in a shell view. + container_parent_.set_owned_by_client(); + container_parent_.AddChildView(browser_actions_container_); +} + +TestToolbarActionsBarHelperViews::~TestToolbarActionsBarHelperViews() { +} + BrowserActionsContainer* GetContainer(Browser* browser, - ToolbarActionsBarDelegate* bar_delegate) { - if (bar_delegate) - return static_cast<BrowserActionsContainer*>(bar_delegate); + TestToolbarActionsBarHelper* helper) { + if (helper) { + return static_cast<TestToolbarActionsBarHelperViews*>(helper) + ->browser_actions_container(); + } return BrowserView::GetBrowserViewForBrowser(browser)->toolbar()-> browser_actions(); } } // namespace +BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser) + : BrowserActionTestUtil(browser, true) { +} + +BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser, + bool is_real_window) + : browser_(browser) { + if (!is_real_window) + test_helper_.reset(new TestToolbarActionsBarHelperViews(browser, nullptr)); +} + +BrowserActionTestUtil::~BrowserActionTestUtil() { +} + int BrowserActionTestUtil::NumberOfBrowserActions() { - return GetContainer(browser_, bar_delegate_)->num_toolbar_actions(); + return GetContainer(browser_, test_helper_.get())->num_toolbar_actions(); } int BrowserActionTestUtil::VisibleBrowserActions() { - return GetContainer(browser_, bar_delegate_)->VisibleBrowserActions(); + return GetContainer(browser_, test_helper_.get())->VisibleBrowserActions(); } bool BrowserActionTestUtil::IsChevronShowing() { - BrowserActionsContainer* container = GetContainer(browser_, bar_delegate_); + BrowserActionsContainer* container = + GetContainer(browser_, test_helper_.get()); gfx::Size visible_size = container->GetVisibleBounds().size(); return container->chevron() && container->chevron()->visible() && @@ -52,62 +106,72 @@ void BrowserActionTestUtil::InspectPopup(int index) { ToolbarActionView* view = - GetContainer(browser_, bar_delegate_)->GetToolbarActionViewAt(index); + GetContainer(browser_, test_helper_.get())->GetToolbarActionViewAt(index); static_cast<ExtensionActionViewController*>(view->view_controller())-> InspectPopup(); } bool BrowserActionTestUtil::HasIcon(int index) { - return !GetContainer(browser_, bar_delegate_)->GetToolbarActionViewAt(index)-> - GetImage(views::Button::STATE_NORMAL).isNull(); + return !GetContainer(browser_, test_helper_.get()) + ->GetToolbarActionViewAt(index) + ->GetImage(views::Button::STATE_NORMAL) + .isNull(); } gfx::Image BrowserActionTestUtil::GetIcon(int index) { - gfx::ImageSkia icon = - GetContainer(browser_, bar_delegate_)->GetToolbarActionViewAt(index)-> - GetIconForTest(); + gfx::ImageSkia icon = GetContainer(browser_, test_helper_.get()) + ->GetToolbarActionViewAt(index) + ->GetIconForTest(); return gfx::Image(icon); } void BrowserActionTestUtil::Press(int index) { - GetContainer(browser_, bar_delegate_)->GetToolbarActionViewAt(index)-> - view_controller()->ExecuteAction(true); + GetContainer(browser_, test_helper_.get()) + ->GetToolbarActionViewAt(index) + ->view_controller() + ->ExecuteAction(true); } std::string BrowserActionTestUtil::GetExtensionId(int index) { - return GetContainer(browser_, bar_delegate_)->GetToolbarActionViewAt(index)-> - view_controller()->GetId(); + return GetContainer(browser_, test_helper_.get()) + ->GetToolbarActionViewAt(index) + ->view_controller() + ->GetId(); } std::string BrowserActionTestUtil::GetTooltip(int index) { base::string16 text; - GetContainer(browser_, bar_delegate_)->GetToolbarActionViewAt(index)-> - GetTooltipText(gfx::Point(), &text); + GetContainer(browser_, test_helper_.get()) + ->GetToolbarActionViewAt(index) + ->GetTooltipText(gfx::Point(), &text); return base::UTF16ToUTF8(text); } gfx::NativeView BrowserActionTestUtil::GetPopupNativeView() { - return GetContainer(browser_, bar_delegate_)->TestGetPopup(); + ToolbarActionViewController* popup_owner = + GetToolbarActionsBar()->popup_owner(); + return popup_owner ? popup_owner->GetPopupNativeView() : nullptr; } bool BrowserActionTestUtil::HasPopup() { - return GetContainer(browser_, bar_delegate_)->TestGetPopup() != NULL; + return GetPopupNativeView() != nullptr; } gfx::Size BrowserActionTestUtil::GetPopupSize() { - gfx::NativeView popup = GetContainer(browser_, bar_delegate_)->TestGetPopup(); + gfx::NativeView popup = GetPopupNativeView(); views::Widget* widget = views::Widget::GetWidgetForNativeView(popup); return widget->GetWindowBoundsInScreen().size(); } bool BrowserActionTestUtil::HidePopup() { - GetContainer(browser_, bar_delegate_)->HideActivePopup(); + GetToolbarActionsBar()->HideActivePopup(); return !HasPopup(); } bool BrowserActionTestUtil::ActionButtonWantsToRun(size_t index) { - return GetContainer(browser_, bar_delegate_)->GetToolbarActionViewAt(index)-> - wants_to_run_for_testing(); + return GetContainer(browser_, test_helper_.get()) + ->GetToolbarActionViewAt(index) + ->wants_to_run_for_testing(); } bool BrowserActionTestUtil::OverflowedActionButtonWantsToRun() { @@ -116,7 +180,13 @@ } ToolbarActionsBar* BrowserActionTestUtil::GetToolbarActionsBar() { - return GetContainer(browser_, bar_delegate_)->toolbar_actions_bar(); + return GetContainer(browser_, test_helper_.get())->toolbar_actions_bar(); +} + +scoped_ptr<BrowserActionTestUtil> BrowserActionTestUtil::CreateOverflowBar() { + CHECK(!GetToolbarActionsBar()->in_overflow_mode()) + << "Only a main bar can create an overflow bar!"; + return make_scoped_ptr(new BrowserActionTestUtil(browser_, this)); } // static @@ -128,3 +198,11 @@ gfx::Size BrowserActionTestUtil::GetMaxPopupSize() { return gfx::Size(ExtensionPopup::kMaxWidth, ExtensionPopup::kMaxHeight); } + +BrowserActionTestUtil::BrowserActionTestUtil(Browser* browser, + BrowserActionTestUtil* main_bar) + : browser_(browser), + test_helper_(new TestToolbarActionsBarHelperViews( + browser_, + GetContainer(browser_, main_bar->test_helper_.get()))) { +}
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.cc b/chrome/browser/ui/views/toolbar/browser_actions_container.cc index 02f9e0c2..8e7977c9 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container.cc +++ b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
@@ -79,7 +79,6 @@ main_container->toolbar_actions_bar_.get() : nullptr)), browser_(browser), main_container_(main_container), - popup_owner_(NULL), container_width_(0), resize_area_(NULL), chevron_(NULL), @@ -202,36 +201,6 @@ browser_)->toolbar()->app_menu()); } -void BrowserActionsContainer::SetPopupOwner(ToolbarActionView* popup_owner) { - // We should never be setting a popup owner when one already exists, and - // never unsetting one when one wasn't set. - DCHECK((!popup_owner_ && popup_owner) || - (popup_owner_ && !popup_owner)); - popup_owner_ = popup_owner; -} - -void BrowserActionsContainer::HideActivePopup() { - if (popup_owner_) - popup_owner_->view_controller()->HidePopup(); -} - -ToolbarActionView* BrowserActionsContainer::GetMainViewForAction( - ToolbarActionView* view) { - if (!in_overflow_mode()) - return view; // This is the main view. - - // The overflow container and main container each have the same views and - // view indices, so we can return the view of the index that |view| has in - // this container. - ToolbarActionViews::const_iterator iter = - std::find(toolbar_action_views_.begin(), - toolbar_action_views_.end(), - view); - DCHECK(iter != toolbar_action_views_.end()); - size_t index = iter - toolbar_action_views_.begin(); - return main_container_->toolbar_action_views_[index]; -} - void BrowserActionsContainer::AddViewForAction( ToolbarActionViewController* view_controller, size_t index) { @@ -261,7 +230,6 @@ } void BrowserActionsContainer::RemoveAllViews() { - HideActivePopup(); STLDeleteElements(&toolbar_action_views_); } @@ -338,10 +306,6 @@ return chevron_ ? chevron_->GetPreferredSize().width() + kChevronSpacing : 0; } -bool BrowserActionsContainer::IsPopupRunning() const { - return popup_owner_ != nullptr; -} - void BrowserActionsContainer::OnOverflowedActionWantsToRunChanged( bool overflowed_action_wants_to_run) { DCHECK(!in_overflow_mode()); @@ -734,12 +698,6 @@ active_tab_permission_granter(); } -gfx::NativeView BrowserActionsContainer::TestGetPopup() { - return popup_owner_ ? - popup_owner_->view_controller()->GetPopupNativeView() : - NULL; -} - void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) { // If the views haven't been initialized yet, wait for the next call to // paint (one will be triggered by entering highlight mode).
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.h b/chrome/browser/ui/views/toolbar/browser_actions_container.h index 94ebf43..e87e309d 100644 --- a/chrome/browser/ui/views/toolbar/browser_actions_container.h +++ b/chrome/browser/ui/views/toolbar/browser_actions_container.h
@@ -190,9 +190,6 @@ void ExecuteExtensionCommand(const extensions::Extension* extension, const extensions::Command& command); - // Hides the currently-active popup, if there is one. - void HideActivePopup(); - // Add or remove an observer. void AddObserver(BrowserActionsContainerObserver* observer); void RemoveObserver(BrowserActionsContainerObserver* observer); @@ -235,8 +232,6 @@ bool ShownInsideMenu() const override; void OnToolbarActionViewDragDone() override; views::MenuButton* GetOverflowReferenceView() override; - void SetPopupOwner(ToolbarActionView* popup_owner) override; - ToolbarActionView* GetMainViewForAction(ToolbarActionView* view) override; // ToolbarActionsBarDelegate: void AddViewForAction(ToolbarActionViewController* action, @@ -252,7 +247,6 @@ bool IsAnimating() const override; void StopAnimating() override; int GetChevronWidth() const override; - bool IsPopupRunning() const override; void OnOverflowedActionWantsToRunChanged( bool overflowed_action_wants_to_run) override; void ShowExtensionMessageBubble( @@ -267,9 +261,6 @@ extensions::ActiveTabPermissionGranter* GetActiveTabPermissionGranter() override; - // Retrieve the current popup. This should only be used by unit tests. - gfx::NativeView TestGetPopup(); - views::BubbleDelegateView* active_bubble() { return active_bubble_; } protected: @@ -312,10 +303,6 @@ // the difference between main and overflow. BrowserActionsContainer* main_container_; - // The view that triggered the current popup (just a reference to a view - // from toolbar_action_views_). - ToolbarActionView* popup_owner_; - // The current width of the container. int container_width_;
diff --git a/chrome/browser/ui/views/toolbar/test_toolbar_actions_bar_helper_views.cc b/chrome/browser/ui/views/toolbar/test_toolbar_actions_bar_helper_views.cc deleted file mode 100644 index 0e8b71b4..0000000 --- a/chrome/browser/ui/views/toolbar/test_toolbar_actions_bar_helper_views.cc +++ /dev/null
@@ -1,62 +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 "chrome/browser/ui/toolbar/test_toolbar_actions_bar_helper.h" - -#include "chrome/browser/ui/views/toolbar/browser_actions_container.h" -#include "ui/views/view.h" - -namespace { - -// The views-specific implementation of the TestToolbarActionsBarHelper, which -// creates and owns a BrowserActionsContainer. -class TestToolbarActionsBarHelperViews : public TestToolbarActionsBarHelper { - public: - TestToolbarActionsBarHelperViews(Browser* browser, - TestToolbarActionsBarHelperViews* main_bar); - ~TestToolbarActionsBarHelperViews() override; - - private: - // TestToolbarActionsBarHelper: - ToolbarActionsBar* GetToolbarActionsBar() override; - - // The parent of the BrowserActionsContainer, which directly owns the - // container as part of the views hierarchy. - views::View container_parent_; - - // The created BrowserActionsContainer. Owned by |container_parent_|. - BrowserActionsContainer* browser_actions_container_; - - DISALLOW_COPY_AND_ASSIGN(TestToolbarActionsBarHelperViews); -}; - -TestToolbarActionsBarHelperViews::TestToolbarActionsBarHelperViews( - Browser* browser, - TestToolbarActionsBarHelperViews* main_bar) - : browser_actions_container_( - new BrowserActionsContainer( - browser, - main_bar ? main_bar->browser_actions_container_ : nullptr)) { - // The BrowserActionsContainer expects to have a parent (and be added to the - // view hierarchy), so wrap it in a shell view. - container_parent_.set_owned_by_client(); - container_parent_.AddChildView(browser_actions_container_); -} - -TestToolbarActionsBarHelperViews::~TestToolbarActionsBarHelperViews() {} - -ToolbarActionsBar* TestToolbarActionsBarHelperViews::GetToolbarActionsBar() { - return browser_actions_container_->toolbar_actions_bar(); -} - -} // namespace - -// static -scoped_ptr<TestToolbarActionsBarHelper> -TestToolbarActionsBarHelper::Create(Browser* browser, - TestToolbarActionsBarHelper* main_bar) { - return make_scoped_ptr(new TestToolbarActionsBarHelperViews( - browser, - static_cast<TestToolbarActionsBarHelperViews*>(main_bar))); -}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc index b4cca4f..b125066d 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -260,13 +260,6 @@ GetWidget(); } -ToolbarActionViewController* -ToolbarActionView::GetPreferredPopupViewController() { - return delegate_->ShownInsideMenu() ? - delegate_->GetMainViewForAction(this)->view_controller() : - view_controller(); -} - views::View* ToolbarActionView::GetReferenceViewForPopup() { // Browser actions in the overflow menu can still show popups, so we may need // a reference view other than this button's parent. If so, use the overflow @@ -284,7 +277,6 @@ } void ToolbarActionView::OnPopupShown(bool by_user) { - delegate_->SetPopupOwner(this); // If this was through direct user action, we press the menu button. if (by_user) { // We set the state of the menu button we're using as a reference view, @@ -298,6 +290,5 @@ } void ToolbarActionView::OnPopupClosed() { - delegate_->SetPopupOwner(nullptr); pressed_lock_.reset(); // Unpress the menu button if it was pressed. }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h index 229a259..97b1453 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -50,14 +50,6 @@ // reference point for a popup when this view isn't visible. virtual views::MenuButton* GetOverflowReferenceView() = 0; - // Sets the delegate's active popup owner to be |popup_owner|. - virtual void SetPopupOwner(ToolbarActionView* popup_owner) = 0; - - // Returns the primary ToolbarActionView associated with the given - // |extension|. - virtual ToolbarActionView* GetMainViewForAction( - ToolbarActionView* view) = 0; - protected: ~Delegate() override {} }; @@ -128,7 +120,6 @@ bool IsShownInMenu() override; views::FocusManager* GetFocusManagerForAccelerator() override; views::Widget* GetParentForContextMenu() override; - ToolbarActionViewController* GetPreferredPopupViewController() override; views::View* GetReferenceViewForPopup() override; views::MenuButton* GetContextMenuButton() override; void OnPopupShown(bool by_user) override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc index 6bbacf87..d724a4f 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_unittest.cc
@@ -35,10 +35,6 @@ views::MenuButton* GetOverflowReferenceView() override { return overflow_reference_view_; } - void SetPopupOwner(ToolbarActionView* popup_owner) override {} - ToolbarActionView* GetMainViewForAction(ToolbarActionView* view) override { - return nullptr; - } void WriteDragDataForView(views::View* sender, const gfx::Point& press_pt, ui::OSExchangeData* data) override {}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button_test.cc b/chrome/browser/ui/views/toolbar/toolbar_button_test.cc index 24c34edf..c22775a7 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_button_test.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_button_test.cc
@@ -20,56 +20,56 @@ menu_closed_(false) { } - virtual ~ToolbarButtonDragTest() { + ~ToolbarButtonDragTest() override { } // ViewEventTestBase implementation. - virtual void SetUp() override { + void SetUp() override { button_ = new ToolbarButton(NULL, new ui::SimpleMenuModel(this)); ViewEventTestBase::SetUp(); } - virtual void TearDown() override { + void TearDown() override { ViewEventTestBase::TearDown(); } - virtual views::View* CreateContentsView() override { + views::View* CreateContentsView() override { return button_; } - virtual gfx::Size GetPreferredSize() const override { + gfx::Size GetPreferredSize() const override { return button_->GetPreferredSize(); } // ui::SimpleMenuModel::Delegate implementation. - virtual bool IsCommandIdChecked(int id) const override { + bool IsCommandIdChecked(int id) const override { return false; } - virtual bool IsCommandIdEnabled(int id) const override { + bool IsCommandIdEnabled(int id) const override { return true; } - virtual bool GetAcceleratorForCommandId( + bool GetAcceleratorForCommandId( int id, ui::Accelerator* accelerator) override { return false; } - virtual void ExecuteCommand(int id, int event_flags) override { + void ExecuteCommand(int id, int event_flags) override { } - virtual void MenuWillShow(ui::SimpleMenuModel* /*source*/) override { + void MenuWillShow(ui::SimpleMenuModel* /*source*/) override { menu_shown_ = true; } - virtual void MenuClosed(ui::SimpleMenuModel* /*source*/) override { + void MenuClosed(ui::SimpleMenuModel* /*source*/) override { menu_closed_ = true; } // ViewEventTestBase implementation. - virtual void DoTestOnMessageLoop() override { + void DoTestOnMessageLoop() override { // Click on the ToolbarButton. ui_test_utils::MoveMouseToCenterAndPress( button_,
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index d86cd49..c7666c4c 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -762,4 +762,7 @@ else label = l10n_util::GetStringUTF16(IDS_TRANSLATE_BUBBLE_ACCEPT); advanced_done_button_->SetText(label); + advanced_done_button_->SizeToPreferredSize(); + if (advanced_view_) + advanced_view_->Layout(); }
diff --git a/chrome/browser/ui/views/uninstall_view.h b/chrome/browser/ui/views/uninstall_view.h index aca00e0..da2bf7454 100644 --- a/chrome/browser/ui/views/uninstall_view.h +++ b/chrome/browser/ui/views/uninstall_view.h
@@ -30,24 +30,22 @@ public: explicit UninstallView(int* user_selection, const base::Closure& quit_closure); - virtual ~UninstallView(); + ~UninstallView() override; // Overridden form views::ButtonListener. - virtual void ButtonPressed(views::Button* sender, - const ui::Event& event) override; + void ButtonPressed(views::Button* sender, const ui::Event& event) override; // Overridden from views::DialogDelegateView: - virtual bool Accept() override; - virtual bool Cancel() override; - virtual base::string16 GetDialogButtonLabel( - ui::DialogButton button) const override; + bool Accept() override; + bool Cancel() override; + base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; // Overridden from views::WidgetDelegate: - virtual base::string16 GetWindowTitle() const override; + base::string16 GetWindowTitle() const override; // Overridden from ui::ComboboxModel: - virtual int GetItemCount() const override; - virtual base::string16 GetItemAt(int index) override; + int GetItemCount() const override; + base::string16 GetItemAt(int index) override; private: typedef std::map<base::string16, base::string16> BrowsersMap;
diff --git a/chrome/browser/ui/website_settings/website_settings.cc b/chrome/browser/ui/website_settings/website_settings.cc index 297b4be..ea26719 100644 --- a/chrome/browser/ui/website_settings/website_settings.cc +++ b/chrome/browser/ui/website_settings/website_settings.cc
@@ -512,11 +512,7 @@ static const int64_t kSHA1LastIssuanceDate = INT64_C(13096080000000000); if ((ssl.cert_status & net::CERT_STATUS_SHA1_SIGNATURE_PRESENT) && cert->valid_expiry() > - base::Time::FromInternalValue(kSHA1LastIssuanceDate) && - // NOTE: This use of SHA1IdentityUIWarning needs to be kept in sync - // with ToolbarModelImpl::IsDeprecatedSHA1Present(). - base::FieldTrialList::FindFullName("SHA1IdentityUIWarning") == - "Enabled") { + base::Time::FromInternalValue(kSHA1LastIssuanceDate)) { site_identity_status_ = SITE_IDENTITY_STATUS_DEPRECATED_SIGNATURE_ALGORITHM; site_identity_details_ +=
diff --git a/chrome/browser/ui/webui/DEPS b/chrome/browser/ui/webui/DEPS index acfa06d..1c3fbd8 100644 --- a/chrome/browser/ui/webui/DEPS +++ b/chrome/browser/ui/webui/DEPS
@@ -20,4 +20,5 @@ "+components/dom_distiller/webui", "+components/invalidation", + "+components/proximity_auth", ]
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 78dc56cf..aa7dd6f4f 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -21,7 +21,6 @@ #include "chrome/browser/ui/webui/bookmarks_ui.h" #include "chrome/browser/ui/webui/components_ui.h" #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" -#include "chrome/browser/ui/webui/copresence_ui.h" #include "chrome/browser/ui/webui/crashes_ui.h" #include "chrome/browser/ui/webui/device_log_ui.h" #include "chrome/browser/ui/webui/domain_reliability_internals_ui.h" @@ -104,8 +103,11 @@ #include "chrome/browser/ui/webui/net_export_ui.h" #else #include "chrome/browser/devtools/device/webrtc/webrtc_device_provider.h" +#include "chrome/browser/ui/webui/copresence_ui.h" #include "chrome/browser/ui/webui/devtools_ui.h" #include "chrome/browser/ui/webui/inspect_ui.h" +#include "components/proximity_auth/webui/proximity_auth_ui.h" +#include "components/proximity_auth/webui/url_constants.h" #endif #if defined(OS_CHROMEOS) @@ -432,12 +434,16 @@ return &NewWebUI<KeyboardOverlayUI>; if (url.host() == chrome::kChromeUIMobileSetupHost) return &NewWebUI<MobileSetupUI>; + if (url.host() == chrome::kChromeUINetworkHost) + return &NewWebUI<chromeos::NetworkUI>; if (url.host() == chrome::kChromeUINfcDebugHost) return &NewWebUI<chromeos::NfcDebugUI>; if (url.host() == chrome::kChromeUIOobeHost) return &NewWebUI<chromeos::OobeUI>; if (url.host() == chrome::kChromeUIOobeMdHost) return &NewWebUI<OobeMdUI>; + if (url.host() == chrome::kChromeUIPowerHost) + return &NewWebUI<chromeos::PowerUI>; if (url.host() == chrome::kChromeUIProvidedFileSystemsHost) return &NewWebUI<chromeos::ProvidedFileSystemsUI>; if (url.host() == chrome::kChromeUIProxySettingsHost) @@ -452,10 +458,6 @@ return &NewWebUI<chromeos::SlowUI>; if (url.host() == chrome::kChromeUISlowTraceHost) return &NewWebUI<chromeos::SlowTraceController>; - if (url.host() == chrome::kChromeUINetworkHost) - return &NewWebUI<chromeos::NetworkUI>; - if (url.host() == chrome::kChromeUIPowerHost) - return &NewWebUI<chromeos::PowerUI>; #endif // defined(OS_CHROMEOS) #if defined(OS_ANDROID) || defined(OS_IOS) if (url.host() == chrome::kChromeUINetExportHost) @@ -467,6 +469,8 @@ return &NewWebUI<InlineLoginUI>; if (url.SchemeIs(content::kChromeDevToolsScheme)) return &NewWebUI<DevToolsUI>; + if (url.host() == proximity_auth::kChromeUIProximityAuthHost) + return &NewWebUI<proximity_auth::ProximityAuthUI>; if (url.host() == chrome::kChromeUIWebRTCDeviceProviderHost) return &NewWebUI<WebRTCDeviceProvider::WebUI>;
diff --git a/chrome/browser/ui/webui/chromeos/image_source.cc b/chrome/browser/ui/webui/chromeos/image_source.cc index 84ddaeb..698e697 100644 --- a/chrome/browser/ui/webui/chromeos/image_source.cc +++ b/chrome/browser/ui/webui/chromeos/image_source.cc
@@ -28,7 +28,7 @@ void ImageLoaded( const content::URLDataSource::GotDataCallback& got_data_callback, const user_manager::UserImage& user_image) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK_CURRENTLY_ON(BrowserThread::UI); if (user_image.has_raw_image()) got_data_callback.Run(new base::RefCountedBytes(user_image.raw_image()));
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc index 16b2205..381e40b3 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -207,8 +207,9 @@ CallJS("refocusCurrentPod"); } -void CoreOobeHandler::ShowPasswordChangedScreen(bool show_password_error) { - CallJS("showPasswordChangedScreen", show_password_error); +void CoreOobeHandler::ShowPasswordChangedScreen(bool show_password_error, + const std::string& email) { + CallJS("showPasswordChangedScreen", show_password_error, email); } void CoreOobeHandler::SetUsageStats(bool checked) {
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h index a8572abe..c0b1073 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -79,7 +79,8 @@ void ResetSignInUI(bool force_online) override; void ClearUserPodPassword() override; void RefocusCurrentPod() override; - void ShowPasswordChangedScreen(bool show_password_error) override; + void ShowPasswordChangedScreen(bool show_password_error, + const std::string& email) override; void SetUsageStats(bool checked) override; void SetOemEulaUrl(const std::string& oem_eula_url) override; void SetTpmPassword(const std::string& tmp_password) override;
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc index 510bb42da..53643e7 100644 --- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -318,6 +318,9 @@ case policy::EnterpriseInstallAttributes::LOCK_WRONG_DOMAIN: ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_USER, true); return; + case policy::EnterpriseInstallAttributes::LOCK_WRONG_MODE: + ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_LOCK_WRONG_MODE, true); + return; } NOTREACHED(); return;
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index bffd9ef..84153c9 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -416,6 +416,7 @@ &GaiaScreenHandler::HandleToggleWebviewSignin); AddCallback("toggleEasyBootstrap", &GaiaScreenHandler::HandleToggleEasyBootstrap); + AddCallback("attemptLogin", &GaiaScreenHandler::HandleAttemptLogin); } void GaiaScreenHandler::HandleFrameLoadingCompleted(int status) { @@ -578,6 +579,21 @@ LoadAuthExtension(kForceReload, kSilentLoad, kNoOfflineUI); } +void GaiaScreenHandler::HandleAttemptLogin(const std::string& email) { + std::string device_id = + user_manager::UserManager::Get()->GetKnownUserDeviceId( + gaia::CanonicalizeEmail(email)); + + if (!device_id.empty() && StartupUtils::IsWebviewSigninEnabled()) { + base::DictionaryValue params; + params.SetString("deviceId", device_id); + CallJS("updateDeviceId", params); + } else { + // Mark current temporary device Id as used. + temporary_device_id_ = std::string(); + } +} + void GaiaScreenHandler::HandleGaiaUIReady() { if (focus_stolen_) { // Set focus to the Gaia page. @@ -920,10 +936,14 @@ context.has_users = !Delegate()->GetUsers().empty(); } - if (context.device_id.empty()) { - context.device_id = base::GenerateGUID(); - DCHECK(!context.device_id.empty()); + if (!context.email.empty()) { + context.device_id = user_manager::UserManager::Get()->GetKnownUserDeviceId( + gaia::CanonicalizeEmail(context.email)); } + + if (context.device_id.empty()) + context.device_id = GetTemporaryDeviceId(); + context.session_is_ephemeral = ChromeUserManager::Get()->AreEphemeralUsersEnabled(); @@ -946,4 +966,12 @@ signin_screen_handler_ = handler; } +std::string GaiaScreenHandler::GetTemporaryDeviceId() { + if (temporary_device_id_.empty()) + temporary_device_id_ = base::GenerateGUID(); + + DCHECK(!temporary_device_id_.empty()); + return temporary_device_id_; +} + } // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h index 463442826..8d1d639 100644 --- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -133,6 +133,8 @@ void HandleToggleEasyBootstrap(); + void HandleAttemptLogin(const std::string& email); + void HandleToggleWebviewSignin(); // This is called when ConsumerManagementService::SetOwner() returns. @@ -202,6 +204,9 @@ SigninScreenHandlerDelegate* Delegate(); + // Returns temporary unused device Id. + std::string GetTemporaryDeviceId(); + // Current state of Gaia frame. FrameState frame_state_; @@ -268,6 +273,10 @@ // GAIA extension loader. scoped_ptr<ScopedGaiaAuthExtension> auth_extension_; + // Temporary DeviceId to be used for new users. + // If it's empty, new deviceId should be generated. + std::string temporary_device_id_; + base::WeakPtrFactory<GaiaScreenHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(GaiaScreenHandler);
diff --git a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc index 06c2423..d49c85c 100644 --- a/chrome/browser/ui/webui/chromeos/login/l10n_util.cc +++ b/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
@@ -422,7 +422,7 @@ scoped_ptr<chromeos::locale_util::LanguageSwitchResult> language_switch_result, UILanguageListResolvedCallback callback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); scoped_ptr<scoped_ptr<base::ListValue>> new_language_list( new scoped_ptr<base::ListValue>());
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index 5fd7b4f..c631d08 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" +#include "chrome/browser/chromeos/chromeos_utils.h" #include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/login/error_screens_histogram_helper.h" #include "chrome/browser/chromeos/login/hwid_checker.h" @@ -50,6 +51,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_metrics.h" #include "chrome/browser/signin/easy_unlock_service.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h" @@ -293,8 +295,8 @@ max_mode_delegate_->RemoveObserver(this); max_mode_delegate_.reset(NULL); } - ScreenlockBridge::Get()->SetLockHandler(NULL); - ScreenlockBridge::Get()->SetFocusedUser(""); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetFocusedUser(""); } // static @@ -413,6 +415,16 @@ IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY); builder->Add("proceedAnywayButton", IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON); + builder->Add("nextButtonText", IDS_NEWGAIA_OFFLINE_NEXT_BUTTON_TEXT); + builder->Add("forgotOldPasswordButtonText", + IDS_LOGIN_NEWGAIA_PASSWORD_CHANGED_FORGOT_PASSWORD); + builder->AddF("passwordChangedTitle", + IDS_LOGIN_NEWGAIA_PASSWORD_CHANGED_TITLE, + GetChromeDeviceType()); + builder->Add("passwordChangedProceedAnywayTitle", + IDS_LOGIN_NEWGAIA_PASSWORD_CHANGED_PROCEED_ANYWAY); + builder->Add("passwordChangedTryAgain", + IDS_LOGIN_NEWGAIA_PASSWORD_CHANGED_TRY_AGAIN); builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT); builder->Add("publicAccountReminder", IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER); @@ -921,8 +933,9 @@ base::StringValue("")); } -void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error) { - core_oobe_actor_->ShowPasswordChangedScreen(show_password_error); +void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error, + const std::string& email) { + core_oobe_actor_->ShowPasswordChangedScreen(show_password_error, email); } void SigninScreenHandler::ShowSigninScreenForCreds( @@ -997,7 +1010,7 @@ const std::string& password) { if (!delegate_) return; - UserContext user_context(username); + UserContext user_context(gaia::SanitizeEmail(username)); user_context.SetKey(Key(password)); delegate_->Login(user_context, SigninSpecifics()); } @@ -1244,7 +1257,7 @@ void SigninScreenHandler::HandleFocusPod(const std::string& user_id) { SetUserInputMethod(user_id, ime_state_.get()); WallpaperManager::Get()->SetUserWallpaperDelayed(user_id); - ScreenlockBridge::Get()->SetFocusedUser(user_id); + GetScreenlockBridgeInstance()->SetFocusedUser(user_id); if (delegate_) delegate_->CheckUserStatus(user_id); if (!test_focus_pod_callback_.is_null())
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index 695345745..951600b 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -20,12 +20,12 @@ #include "chrome/browser/chromeos/login/signin_specifics.h" #include "chrome/browser/chromeos/login/ui/login_display.h" #include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/signin/screenlock_bridge.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h" #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h" #include "chrome/browser/ui/webui/chromeos/touch_view_controller_delegate.h" #include "chromeos/network/portal_detector/network_portal_detector.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -88,7 +88,8 @@ virtual void ShowErrorScreen(LoginDisplay::SigninError error_id) = 0; virtual void ShowGaiaPasswordChanged(const std::string& username) = 0; virtual void ShowSigninUI(const std::string& email) = 0; - virtual void ShowPasswordChangedDialog(bool show_password_error) = 0; + virtual void ShowPasswordChangedDialog(bool show_password_error, + const std::string& email) = 0; // Show sign-in screen for the given credentials. virtual void ShowSigninScreenForCreds(const std::string& username, const std::string& password) = 0; @@ -297,7 +298,8 @@ HelpAppLauncher::HelpTopic help_topic_id) override; void ShowGaiaPasswordChanged(const std::string& username) override; void ShowSigninUI(const std::string& email) override; - void ShowPasswordChangedDialog(bool show_password_error) override; + void ShowPasswordChangedDialog(bool show_password_error, + const std::string& email) override; void ShowErrorScreen(LoginDisplay::SigninError error_id) override; void ShowSigninScreenForCreds(const std::string& username, const std::string& password) override;
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc b/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc index 2846abdb..ed1d6f3 100644 --- a/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc +++ b/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc
@@ -8,9 +8,9 @@ #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" #include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h" #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" -#include "chrome/browser/signin/screenlock_bridge.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "components/user_manager/user.h" #include "testing/gtest/include/gtest/gtest.h" @@ -68,8 +68,8 @@ FakeChromeUserManager* fake_user_manager_; ScopedUserManagerEnabler user_manager_enabler_; scoped_ptr<TestingProfileManager> profile_manager_; - std::map<std::string, - ScreenlockBridge::LockHandler::AuthType> user_auth_type_map; + std::map<std::string, proximity_auth::ScreenlockBridge::LockHandler::AuthType> + user_auth_type_map; scoped_ptr<MultiProfileUserController> controller_; DISALLOW_COPY_AND_ASSIGN(SigninPrepareUserListTest);
diff --git a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc index 4a015d78..d533099 100644 --- a/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/supervised_user_creation_screen_handler.cc
@@ -225,10 +225,8 @@ bool is_owner = ((*it)->email() == owner); base::DictionaryValue* user_dict = new base::DictionaryValue(); UserSelectionScreen::FillUserDictionary( - *it, - is_owner, - false, /* is_signin_to_add */ - ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, + *it, is_owner, false, /* is_signin_to_add */ + proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD, NULL, /* public_session_recommended_locales */ user_dict); users_list->Append(user_dict);
diff --git a/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.cc index 80f8bb7..18c0ac30 100644 --- a/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.cc
@@ -87,7 +87,7 @@ void UserBoardScreenHandler::SetAuthType( const std::string& user_id, - ScreenlockBridge::LockHandler::AuthType auth_type, + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type, const base::string16& initial_value) { CallJS("login.AccountPickerScreen.setAuthType", user_id, static_cast<int>(auth_type), base::StringValue(initial_value));
diff --git a/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h index 36b1118..1c854370 100644 --- a/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h
@@ -47,9 +47,10 @@ void ShowUserPodCustomIcon(const std::string& user_id, const base::DictionaryValue& icon) override; void HideUserPodCustomIcon(const std::string& user_id) override; - void SetAuthType(const std::string& user_id, - ScreenlockBridge::LockHandler::AuthType auth_type, - const base::string16& initial_value) override; + void SetAuthType( + const std::string& user_id, + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type, + const base::string16& initial_value) override; void Bind(UserBoardModel& model) override; void Unbind() override;
diff --git a/chrome/browser/ui/webui/downloads_ui_browsertest.js b/chrome/browser/ui/webui/downloads_ui_browsertest.js index 0eb73ac..96ffd19 100644 --- a/chrome/browser/ui/webui/downloads_ui_browsertest.js +++ b/chrome/browser/ui/webui/downloads_ui_browsertest.js
@@ -96,6 +96,18 @@ expectGT(firstContainer.querySelector('.date').textContent.trim().length, 0); }); +TEST_F('BaseDownloadsWebUITest', 'EmptyProgressStatusText', function() { + this.createdDownloads[0].state = downloads.Item.States.PAUSED; + this.createdDownloads[0].progress_status_text = ''; + downloads.Manager.updateItem(this.createdDownloads[0]); // Might assert(). +}); + +TEST_F('BaseDownloadsWebUITest', 'EmptyLastStatusText', function() { + this.createdDownloads[0].state = downloads.Item.States.INTERRUPTED; + this.createdDownloads[0].last_reason_text = ''; + downloads.Manager.updateItem(this.createdDownloads[0]); // Might assert(). +}); + /** * @constructor * @extends {BaseDownloadsWebUITest}
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js index f96ed80..3fdd656 100644 --- a/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js +++ b/chrome/browser/ui/webui/extensions/extension_settings_browsertest.js
@@ -29,6 +29,9 @@ __proto__: testing.Test.prototype, /** @override */ + isAsync: true, + + /** @override */ runAccessibilityChecks: true, /** @override */ @@ -43,28 +46,162 @@ /** @override */ typedefCppFixture: 'ExtensionSettingsUIBrowserTest', + + /** @override */ + setUp: function() { + // Make all transitions take 0ms for testing purposes. + var noTransitionStyle = document.createElement('style'); + noTransitionStyle.textContent = + '* {' + + ' -webkit-transition-duration: 0ms !important;' + + ' -webkit-transition-delay: 0ms !important;' + + '}'; + document.querySelector('head').appendChild(noTransitionStyle); + }, + + /** + * Holds an array of steps that should happen in order during a test. + * The last step should be |testDone|. + * @protected {Array<!Function>} + * */ + steps: [], + + /** + * Advances to the next step in the test. Every step should call this. + * @protected + * */ + nextStep: function() { + assertTrue(this.steps.length > 0); + this.steps.shift().call(this); + }, + + /** + * Will wait for the page to load before calling the next step. This should be + * the first step in every test. + * @protected + * */ + waitForPageLoad: function() { + assertEquals(this.browsePreload, document.location.href); + var extensionList = getRequiredElement('extension-settings-list'); + extensionList.loadFinished.then(this.nextStep.bind(this)); + }, + + /** @protected */ + verifyDeveloperModeWorks: function() { + this.ignoreDevModeA11yFailures(); + var extensionSettings = getRequiredElement('extension-settings'); + assertFalse(extensionSettings.classList.contains('dev-mode')); + $('toggle-dev-on').click(); + assertTrue(extensionSettings.classList.contains('dev-mode')); + chrome.developerPrivate.getProfileConfiguration(function(profileInfo) { + assertTrue(profileInfo.inDeveloperMode); + + // A 0ms timeout is necessary so that all the transitions can finish. + window.setTimeout(this.nextStep.bind(this), 0); + }.bind(this)); + }, + + /** @protected */ + testDeveloperMode: function() { + var next = this.nextStep.bind(this); + var checkDevModeIsOff = function() { + chrome.developerPrivate.getProfileConfiguration(function(profileInfo) { + assertFalse(profileInfo.inDeveloperMode); + next(); + }); + }; + this.steps = [this.waitForPageLoad, + checkDevModeIsOff, + this.verifyDeveloperModeWorks, + testDone]; + this.nextStep(); + }, + + /** + * TODO(hcarmona): Remove this as part of fixing crbug.com/463245. + * Will ignore accessibility failures caused by the transition when developer + * mode is enabled. + * @protected + */ + ignoreDevModeA11yFailures: function() { + this.accessibilityAuditConfig.ignoreSelectors( + 'focusableElementNotVisibleAndNotAriaHidden', + '#load-unpacked'); + this.accessibilityAuditConfig.ignoreSelectors( + 'focusableElementNotVisibleAndNotAriaHidden', + '#pack-extension'); + this.accessibilityAuditConfig.ignoreSelectors( + 'focusableElementNotVisibleAndNotAriaHidden', + '#update-extensions-now'); + }, }; -TEST_F('ExtensionSettingsWebUITest', 'testChromeSendHandled', function() { - assertEquals(this.browsePreload, document.location.href); - - // This dialog should be hidden at first. - assertFalse($('pack-extension-overlay').classList.contains('showing')); - - // Show the dialog, which triggers a chrome.send() for metrics purposes. - cr.dispatchSimpleEvent($('pack-extension'), 'click'); - assertTrue($('pack-extension-overlay').classList.contains('showing')); +// Verify that developer mode doesn't change behavior when the number of +// extensions changes. +TEST_F('ExtensionSettingsWebUITest', 'testDeveloperModeNoExtensions', + function() { + this.testDeveloperMode(); }); +TEST_F('ExtensionSettingsWebUITest', 'testEmptyExtensionList', function() { + var verifyListIsHiddenAndEmpty = function() { + assertTrue($('extension-list-wrapper').hidden); + assertFalse($('no-extensions').hidden); + assertEquals(0, $('extension-settings-list').childNodes.length); + this.nextStep(); + }; + + this.steps = [this.waitForPageLoad, verifyListIsHiddenAndEmpty, testDone]; + this.nextStep(); +}); + +TEST_F('ExtensionSettingsWebUITest', 'testChromeSendHandled', function() { + var testPackExtenion = function() { + // This dialog should be hidden at first. + assertFalse($('pack-extension-overlay').classList.contains('showing')); + + // Show the dialog, which triggers a chrome.send() for metrics purposes. + cr.dispatchSimpleEvent($('pack-extension'), 'click'); + assertTrue($('pack-extension-overlay').classList.contains('showing')); + this.nextStep(); + }; + + this.steps = [this.waitForPageLoad, testPackExtenion, testDone]; + this.nextStep(); +}); + +/** + * @param {chrome.developerPrivate.EventType} eventType + * @param {function():void} callback + * @constructor + */ +function UpdateListener(eventType, callback) { + this.callback_ = callback; + this.eventType_ = eventType; + this.onItemStateChangedListener_ = this.onItemStateChanged_.bind(this); + chrome.developerPrivate.onItemStateChanged.addListener( + this.onItemStateChangedListener_); +} + +UpdateListener.prototype = { + /** @private */ + onItemStateChanged_: function(data) { + if (this.eventType_ == data.event_type) { + window.setTimeout(function() { + chrome.developerPrivate.onItemStateChanged.removeListener( + this.onItemStateChangedListener_); + this.callback_(); + }.bind(this), 0); + } + } +}; + function BasicExtensionSettingsWebUITest() {} BasicExtensionSettingsWebUITest.prototype = { __proto__: ExtensionSettingsWebUITest.prototype, /** @override */ - isAsync: true, - - /** @override */ testGenPreamble: function() { // Install multiple types of extensions to ensure we handle each type. // TODO(devlin): There are more types to add here. @@ -76,67 +213,54 @@ GEN(' SetAutoConfirmUninstall();'); }, - /** @protected {Array<!Function>} */ - steps: [], - - /** @protected */ - nextStep: function() { - assertTrue(this.steps.length > 0); - this.steps.shift().call(this); - }, - - /** @protected */ - waitForPageLoad: function() { - var extensionList = getRequiredElement('extension-settings-list'); - extensionList.extensionsUpdated_.then(this.nextStep.bind(this)); - }, - /** @protected */ verifyDisabledWorks: function() { - chrome.management.setEnabled(GOOD_CRX_ID, false, function() { + var listener = new UpdateListener( + chrome.developerPrivate.EventType.UNLOADED, + function() { var node = getRequiredElement(GOOD_CRX_ID); assertTrue(node.classList.contains('inactive-extension')); this.nextStep(); }.bind(this)); + chrome.management.setEnabled(GOOD_CRX_ID, false); }, /** @protected */ verifyEnabledWorks: function() { - chrome.management.setEnabled(GOOD_CRX_ID, true, function() { + var listener = new UpdateListener( + chrome.developerPrivate.EventType.LOADED, + function() { var node = getRequiredElement(GOOD_CRX_ID); assertFalse(node.classList.contains('inactive-extension')); this.nextStep(); }.bind(this)); + chrome.management.setEnabled(GOOD_CRX_ID, true); }, /** @protected */ verifyUninstallWorks: function() { - var next = this.nextStep.bind(this); - chrome.test.runWithUserGesture(function() { - chrome.management.uninstall(GOOD_CRX_ID, function() { - assertEquals(null, $(GOOD_CRX_ID)); - next(); - }); - }); - }, - - /** @protected */ - verifyDeveloperModeWorks: function() { - var extensionSettings = getRequiredElement('extension-settings'); - assertFalse(extensionSettings.classList.contains('dev-mode')); - $('toggle-dev-on').click(); - assertTrue(extensionSettings.classList.contains('dev-mode')); - chrome.developerPrivate.getProfileConfiguration(function(profileInfo) { - assertTrue(profileInfo.inDeveloperMode); + var listener = new UpdateListener( + chrome.developerPrivate.EventType.UNINSTALLED, + function() { + assertEquals(null, $(GOOD_CRX_ID)); this.nextStep(); }.bind(this)); + chrome.test.runWithUserGesture(function() { + chrome.management.uninstall(GOOD_CRX_ID); + }); }, }; +// Verify that developer mode doesn't change behavior when the number of +// extensions changes. +TEST_F('BasicExtensionSettingsWebUITest', 'testDeveloperModeManyExtensions', + function() { + this.testDeveloperMode(); +}); + + TEST_F('BasicExtensionSettingsWebUITest', 'testDisable', function() { - this.steps = [this.waitForPageLoad, - this.verifyDisabledWorks, - testDone]; + this.steps = [this.waitForPageLoad, this.verifyDisabledWorks, testDone]; this.nextStep(); }); @@ -149,24 +273,21 @@ }); TEST_F('BasicExtensionSettingsWebUITest', 'testUninstall', function() { - this.steps = [this.waitForPageLoad, - this.verifyUninstallWorks, - testDone]; + this.steps = [this.waitForPageLoad, this.verifyUninstallWorks, testDone]; this.nextStep(); }); -TEST_F('BasicExtensionSettingsWebUITest', 'testDeveloperMode', function() { - var next = this.nextStep.bind(this); - var checkDevModeIsOff = function() { - chrome.developerPrivate.getProfileConfiguration(function(profileInfo) { - assertFalse(profileInfo.inDeveloperMode); - next(); - }); +TEST_F('BasicExtensionSettingsWebUITest', 'testNonEmptyExtensionList', + function() { + var verifyListIsNotHiddenAndEmpty = function() { + assertFalse($('extension-list-wrapper').hidden); + assertTrue($('no-extensions').hidden); + assertGT($('extension-settings-list').childNodes.length, 0); + + this.nextStep(); }; - this.steps = [checkDevModeIsOff, - this.waitForPageLoad, - this.verifyDeveloperModeWorks, - testDone]; + + this.steps = [this.waitForPageLoad, verifyListIsNotHiddenAndEmpty, testDone]; this.nextStep(); }); @@ -176,44 +297,17 @@ __proto__: ExtensionSettingsWebUITest.prototype, /** @override */ - isAsync: true, - - /** @override */ testGenPreamble: function() { GEN(' InstallGoodExtension();'); GEN(' InstallErrorsExtension();'); }, - - enableDeveloperMode: function(callback) { - var devControls = $('dev-controls'); - - // Make sure developer controls are hidden before checkbox is clicked. - assertEquals(0, devControls.offsetHeight); - $('toggle-dev-on').click(); - - document.addEventListener('webkitTransitionEnd', function f(e) { - if (e.target == devControls) { - // Make sure developer controls are not hidden after checkbox is - // clicked. - assertGT(devControls.offsetHeight, 0); - - document.removeEventListener(f, 'webkitTransitionEnd'); - callback(); - } - }); - ensureTransitionEndEvent(devControls, 4000); - }, }; -TEST_F('AsyncExtensionSettingsWebUITest', 'testDeveloperModeA11y', function() { - this.enableDeveloperMode(testDone); -}); - // Often times out on all platforms: http://crbug.com/467528 TEST_F('AsyncExtensionSettingsWebUITest', 'DISABLED_testErrorListButtonVisibility', function() { - this.enableDeveloperMode(function() { + var testButtonVisibility = function() { // 2 extensions are loaded: // The 'good' extension will have 0 errors wich means no error list // buttons. @@ -231,8 +325,14 @@ // Hidden buttons must NOT be part of the focusRow. assertFalse(hiddenButtons[0].hasAttribute('column-type')); - testDone(); - }); + this.nextStep(); + }; + + this.steps = [this.waitForPageLoad, + this.verifyDeveloperModeWorks, + testButtonVisibility, + testDone]; + this.nextStep(); }); /** @@ -240,16 +340,10 @@ * @extends {testing.Test} * @constructor */ -function ExtensionSettingsCommandsConfigWebUITest() {} +function SettingsCommandsExtensionSettingsWebUITest() {} -ExtensionSettingsCommandsConfigWebUITest.prototype = { - __proto__: testing.Test.prototype, - - /** @override */ - runAccessibilityChecks: true, - - /** @override */ - accessibilityIssuesAreErrors: true, +SettingsCommandsExtensionSettingsWebUITest.prototype = { + __proto__: ExtensionSettingsWebUITest.prototype, /** * A URL to load before starting each test. @@ -259,91 +353,93 @@ browsePreload: 'chrome://extensions-frame/configureCommands', }; -TEST_F('ExtensionSettingsCommandsConfigWebUITest', 'testChromeSendHandler', +TEST_F('SettingsCommandsExtensionSettingsWebUITest', 'testChromeSendHandler', function() { // Just navigating to the page should trigger the chrome.send(). - assertEquals(this.browsePreload, document.location.href); - assertTrue($('extension-commands-overlay').classList.contains('showing')); + var assertOverlayVisible = function() { + assertTrue($('extension-commands-overlay').classList.contains('showing')); + this.nextStep(); + }; + + this.steps = [this.waitForPageLoad, assertOverlayVisible, testDone]; + this.nextStep(); }); /** * @constructor * @extends {ExtensionSettingsWebUITest} */ -function InstalledExtensionSettingsWebUITest() {} +function InstallGoodExtensionSettingsWebUITest() {} -InstalledExtensionSettingsWebUITest.prototype = { +InstallGoodExtensionSettingsWebUITest.prototype = { __proto__: ExtensionSettingsWebUITest.prototype, /** @override */ - typedefCppFixture: 'ExtensionSettingsUIBrowserTest', - - /** @override */ testGenPreamble: function() { GEN(' InstallGoodExtension();'); }, + + emptyTestForAccessibility() { + this.steps = [this.waitForPageLoad, testDone]; + this.nextStep(); + }, }; -/** @this {InstalledExtensionSettingsWebUITest} */ -function runAudit() { - assertEquals(this.browsePreload, document.location.href); - this.runAccessibilityAudit(); -} +TEST_F('InstallGoodExtensionSettingsWebUITest', 'testAccessibility', + function() { + this.emptyTestForAccessibility(); +}); -TEST_F('InstalledExtensionSettingsWebUITest', 'baseAccessibilityOk', runAudit); +TEST_F('InstallGoodExtensionSettingsWebUITest', 'showOptions', function() { + var showExtensionOptions = function() { + var optionsOverlay = extensions.ExtensionOptionsOverlay.getInstance(); + optionsOverlay.setExtensionAndShowOverlay(GOOD_CRX_ID, 'GOOD!', '', + this.nextStep.bind(this)); -/** - * @constructor - * @extends {InstalledExtensionSettingsWebUITest} - */ -function AsyncInstalledExtensionSettingsWebUITest() {} + // Preferred size changes don't happen in browser tests. Just fake it. + document.querySelector('extensionoptions').onpreferredsizechanged( + {width: 500, height: 500}); + }; -AsyncInstalledExtensionSettingsWebUITest.prototype = { - __proto__: InstalledExtensionSettingsWebUITest.prototype, - - /** @override */ - isAsync: true, -}; - -TEST_F('AsyncInstalledExtensionSettingsWebUITest', 'showOptions', function() { - var optionsOverlay = extensions.ExtensionOptionsOverlay.getInstance(); - optionsOverlay.setExtensionAndShowOverlay(GOOD_CRX_ID, 'GOOD!', '', testDone); - - // Preferred size changes don't happen in browser tests. Just fake it. - var size = {width: 500, height: 500}; - document.querySelector('extensionoptions').onpreferredsizechanged(size); + this.steps = [this.waitForPageLoad, showExtensionOptions, testDone]; + this.nextStep(); }); /** * @constructor - * @extends {InstalledExtensionSettingsWebUITest} + * @extends {InstallGoodExtensionSettingsWebUITest} */ function ManagedExtensionSettingsWebUITest() {} ManagedExtensionSettingsWebUITest.prototype = { - __proto__: InstalledExtensionSettingsWebUITest.prototype, + __proto__: InstallGoodExtensionSettingsWebUITest.prototype, /** @override */ testGenPreamble: function() { GEN(' AddManagedPolicyProvider();'); - InstalledExtensionSettingsWebUITest.prototype.testGenPreamble.call(this); + InstallGoodExtensionSettingsWebUITest.prototype.testGenPreamble.call(this); }, }; -TEST_F('ManagedExtensionSettingsWebUITest', 'testAccessibility', runAudit); +TEST_F('ManagedExtensionSettingsWebUITest', 'testAccessibility', function() { + this.emptyTestForAccessibility(); +}); /** * @constructor - * @extends {InstalledExtensionSettingsWebUITest} + * @extends {InstallGoodExtensionSettingsWebUITest} */ -function ExtensionOptionsDialogWebUITest() {} +function OptionsDialogExtensionSettingsWebUITest() {} -ExtensionOptionsDialogWebUITest.prototype = { - __proto__: InstalledExtensionSettingsWebUITest.prototype, +OptionsDialogExtensionSettingsWebUITest.prototype = { + __proto__: InstallGoodExtensionSettingsWebUITest.prototype, /** @override */ browsePreload: ExtensionSettingsWebUITest.prototype.browsePreload + '?options=' + GOOD_CRX_ID, }; -TEST_F('ExtensionOptionsDialogWebUITest', 'testAccessibility', runAudit); +TEST_F('OptionsDialogExtensionSettingsWebUITest', 'testAccessibility', + function() { + this.emptyTestForAccessibility(); +});
diff --git a/chrome/browser/ui/webui/flags_ui.cc b/chrome/browser/ui/webui/flags_ui.cc index 4d503ddc..0918de1 100644 --- a/chrome/browser/ui/webui/flags_ui.cc +++ b/chrome/browser/ui/webui/flags_ui.cc
@@ -333,8 +333,7 @@ #if defined(OS_CHROMEOS) // static void FlagsUI::RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(prefs::kEnabledLabsExperiments, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kEnabledLabsExperiments); } #endif
diff --git a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc index f3994911f..70a00e4c 100644 --- a/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc +++ b/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc
@@ -8,7 +8,6 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" #include "chrome/browser/chromeos/login/users/mock_user_manager.h" #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" #include "chrome/browser/chromeos/settings/cros_settings.h" @@ -17,6 +16,7 @@ #include "chromeos/dbus/fake_update_engine_client.h" #include "chromeos/dbus/shill_service_client.h" #include "chromeos/network/network_handler.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -67,7 +67,7 @@ "eth", shill::kTypeEthernet, shill::kStateOnline, true /* visible */); - loop_.RunUntilIdle(); + base::MessageLoop::current()->RunUntilIdle(); } void TearDown() override { @@ -77,14 +77,13 @@ DeviceSettingsService::Shutdown(); } + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<VersionUpdater> version_updater_; FakeUpdateEngineClient* fake_update_engine_client_; // Not owned. MockUserManager* mock_user_manager_; // Not owned. ScopedUserManagerEnabler user_manager_enabler_; - base::MessageLoop loop_; - DISALLOW_COPY_AND_ASSIGN(VersionUpdaterCrosTest); };
diff --git a/chrome/browser/ui/webui/help/version_updater_win.cc b/chrome/browser/ui/webui/help/version_updater_win.cc index 9825fe02..4311801 100644 --- a/chrome/browser/ui/webui/help/version_updater_win.cc +++ b/chrome/browser/ui/webui/help/version_updater_win.cc
@@ -36,11 +36,11 @@ // Clients must use VersionUpdater::Create(). VersionUpdaterWin(); - virtual ~VersionUpdaterWin(); + ~VersionUpdaterWin() override; // VersionUpdater implementation. - virtual void CheckForUpdate(const StatusCallback& callback) override; - virtual void RelaunchBrowser() const override; + void CheckForUpdate(const StatusCallback& callback) override; + void RelaunchBrowser() const override; // chrome::UpdateCheckCallback. void OnUpdateCheckResults(GoogleUpdateUpgradeResult result, @@ -62,12 +62,12 @@ void BeginUpdateCheckOnFileThread(bool install_if_newer); - // Used for callbacks. - base::WeakPtrFactory<VersionUpdaterWin> weak_factory_; - // Callback used to communicate update status to the client. StatusCallback callback_; + // Used for callbacks. + base::WeakPtrFactory<VersionUpdaterWin> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(VersionUpdaterWin); };
diff --git a/chrome/browser/ui/webui/instant_ui.cc b/chrome/browser/ui/webui/instant_ui.cc index ef8e551..162ac8c 100644 --- a/chrome/browser/ui/webui/instant_ui.cc +++ b/chrome/browser/ui/webui/instant_ui.cc
@@ -172,8 +172,6 @@ // static void InstantUI::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kInstantUIZeroSuggestUrlPrefix, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kInstantUIZeroSuggestUrlPrefix, + std::string()); }
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc index 859b831..049c95a 100644 --- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc +++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
@@ -345,10 +345,10 @@ &fetcher_impl_factory_, fake_url_fetcher_creator_.callback()) { } - virtual ~LocalDiscoveryUITest() { + ~LocalDiscoveryUITest() override { } - virtual void SetUpOnMainThread() override { + void SetUpOnMainThread() override { WebUIBrowserTest::SetUpOnMainThread(); test_service_discovery_client_ = new TestServiceDiscoveryClient(); @@ -425,7 +425,7 @@ AddLibrary(base::FilePath(FILE_PATH_LITERAL("local_discovery_ui_test.js"))); } - virtual void SetUpCommandLine(base::CommandLine* command_line) override { + void SetUpCommandLine(base::CommandLine* command_line) override { #if defined(OS_CHROMEOS) // On chromeos, don't sign in with the stub-user automatically. Use the // kLoginUser instead.
diff --git a/chrome/browser/ui/webui/media_router/media_cast_mode.cc b/chrome/browser/ui/webui/media_router/media_cast_mode.cc new file mode 100644 index 0000000..dd9a430 --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_cast_mode.cc
@@ -0,0 +1,68 @@ +// 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/webui/media_router/media_cast_mode.h" + +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace media_router { + +std::string MediaCastModeToTitle(MediaCastMode mode, const std::string& host) { + switch (mode) { + case MediaCastMode::DEFAULT: + return l10n_util::GetStringFUTF8( + IDS_MEDIA_ROUTER_DEFAULT_CAST_MODE_TITLE, base::UTF8ToUTF16(host)); + case MediaCastMode::TAB_MIRROR: + return l10n_util::GetStringUTF8( + IDS_MEDIA_ROUTER_TAB_MIRROR_CAST_MODE_TITLE); + case MediaCastMode::DESKTOP_OR_WINDOW_MIRROR: + return l10n_util::GetStringUTF8( + IDS_MEDIA_ROUTER_DESKTOP_OR_WINDOW_MIRROR_CAST_MODE_TITLE); + case MediaCastMode::SOUND_OPTIMIZED_TAB_MIRROR: + return l10n_util::GetStringUTF8( + IDS_MEDIA_ROUTER_SOUND_OPTIMIZED_TAB_MIRROR_CAST_MODE_TITLE); + default: + NOTREACHED(); + return ""; + } +} + +std::string MediaCastModeToDescription( + MediaCastMode mode, const std::string& host) { + switch (mode) { + case MediaCastMode::DEFAULT: + return l10n_util::GetStringFUTF8( + IDS_MEDIA_ROUTER_DEFAULT_CAST_MODE, base::UTF8ToUTF16(host)); + case MediaCastMode::TAB_MIRROR: + return l10n_util::GetStringUTF8( + IDS_MEDIA_ROUTER_TAB_MIRROR_CAST_MODE); + case MediaCastMode::DESKTOP_OR_WINDOW_MIRROR: + return l10n_util::GetStringUTF8( + IDS_MEDIA_ROUTER_DESKTOP_OR_WINDOW_MIRROR_CAST_MODE); + case MediaCastMode::SOUND_OPTIMIZED_TAB_MIRROR: + return l10n_util::GetStringUTF8( + IDS_MEDIA_ROUTER_SOUND_OPTIMIZED_TAB_MIRROR_CAST_MODE); + default: + NOTREACHED(); + return ""; + } +} + +bool IsValidCastModeNum(int cast_mode_num) { + return cast_mode_num >= MediaCastMode::DEFAULT && + cast_mode_num < MediaCastMode::NUM_CAST_MODES; +} + +MediaCastMode GetPreferredCastMode(const CastModeSet& cast_modes) { + if (cast_modes.empty()) { + LOG(ERROR) << "Called with empty cast_modes!"; + return MediaCastMode::DEFAULT; + } + return *cast_modes.begin(); +} + +} // namespace media_router
diff --git a/chrome/browser/ui/webui/media_router/media_cast_mode.h b/chrome/browser/ui/webui/media_router/media_cast_mode.h new file mode 100644 index 0000000..7c9e069 --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_cast_mode.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 CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_CAST_MODE_H_ +#define CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_CAST_MODE_H_ + +#include <set> +#include <string> + +namespace media_router { + +// A cast mode represents one way that the current WebContents (i.e., tab) may +// be presented to a media sink. These must be declared in the priority order +// returned by GetPreferredCastMode. +enum MediaCastMode { + // The default presentation for the WebContents. Only available when the + // document has provided a default presentation URL. + DEFAULT, + // Capture the rendered WebContents and stream it to a media sink. Always + // available. + TAB_MIRROR, + // Capture the entire desktop or a native application window and stream it to + // a media sink. Always available. + DESKTOP_OR_WINDOW_MIRROR, + // Same as TAB_MIRROR, but capture at a reduced frame rate; suitable for + // static or audio-only content. Always available. + SOUND_OPTIMIZED_TAB_MIRROR, + // The number of cast modes; not a valid cast mode. Add new cast modes above. + NUM_CAST_MODES, +}; + +using CastModeSet = std::set<MediaCastMode>; + +// Returns a localized title string for |mode| and |host| (e.g. google.com). +std::string MediaCastModeToTitle(MediaCastMode mode, const std::string& host); + +// Returns a localized description string for |mode| and |host|. +std::string MediaCastModeToDescription(MediaCastMode mode, + const std::string& host); + +// Returns true if |cast_mode_num| is a valid MediaCastMode, false otherwise. +bool IsValidCastModeNum(int cast_mode_num); + +// Returns the preferred cast mode from the current set of cast modes. +// There must be at least one cast mode in |cast_modes|. +MediaCastMode GetPreferredCastMode(const CastModeSet& cast_modes); + +} // namespace media_router + +#endif // CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_CAST_MODE_H_
diff --git a/chrome/browser/ui/webui/media_router/media_cast_mode_unittest.cc b/chrome/browser/ui/webui/media_router/media_cast_mode_unittest.cc new file mode 100644 index 0000000..a495010 --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_cast_mode_unittest.cc
@@ -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. + +#include "chrome/browser/ui/webui/media_router/media_cast_mode.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media_router { + +TEST(MediaCastModeTest, PreferredCastMode) { + CastModeSet cast_modes; + + EXPECT_EQ(MediaCastMode::DEFAULT, GetPreferredCastMode(cast_modes)); + + cast_modes.insert(MediaCastMode::SOUND_OPTIMIZED_TAB_MIRROR); + EXPECT_EQ(MediaCastMode::SOUND_OPTIMIZED_TAB_MIRROR, + GetPreferredCastMode(cast_modes)); + + cast_modes.insert(MediaCastMode::DESKTOP_OR_WINDOW_MIRROR); + EXPECT_EQ(MediaCastMode::DESKTOP_OR_WINDOW_MIRROR, + GetPreferredCastMode(cast_modes)); + + cast_modes.insert(MediaCastMode::TAB_MIRROR); + EXPECT_EQ(MediaCastMode::TAB_MIRROR, + GetPreferredCastMode(cast_modes)); + + cast_modes.insert(MediaCastMode::DEFAULT); + EXPECT_EQ(MediaCastMode::DEFAULT, + GetPreferredCastMode(cast_modes)); + + cast_modes.erase(MediaCastMode::TAB_MIRROR); + EXPECT_EQ(MediaCastMode::DEFAULT, + GetPreferredCastMode(cast_modes)); + + cast_modes.erase(MediaCastMode::DESKTOP_OR_WINDOW_MIRROR); + EXPECT_EQ(MediaCastMode::DEFAULT, + GetPreferredCastMode(cast_modes)); + + cast_modes.erase(MediaCastMode::SOUND_OPTIMIZED_TAB_MIRROR); + EXPECT_EQ(MediaCastMode::DEFAULT, + GetPreferredCastMode(cast_modes)); +} + +TEST(MediaCastModeTest, MediaCastModeToTitleAndDescription) { + for (int cast_mode = MediaCastMode::DEFAULT; + cast_mode < MediaCastMode::NUM_CAST_MODES; cast_mode++) { + EXPECT_TRUE(!MediaCastModeToTitle( + static_cast<MediaCastMode>(cast_mode), "youtube.com").empty()); + EXPECT_TRUE(!MediaCastModeToDescription( + static_cast<MediaCastMode>(cast_mode), "youtube.com").empty()); + } +} + +TEST(MediaCastModeTest, IsValidCastModeNum) { + for (int cast_mode = MediaCastMode::DEFAULT; + cast_mode < MediaCastMode::NUM_CAST_MODES; cast_mode++) { + EXPECT_TRUE(IsValidCastModeNum(cast_mode)); + } + EXPECT_FALSE(IsValidCastModeNum(MediaCastMode::NUM_CAST_MODES)); + EXPECT_FALSE(IsValidCastModeNum(-1)); +} + +} // namespace media_router
diff --git a/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc new file mode 100644 index 0000000..9681e33 --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.cc
@@ -0,0 +1,39 @@ +// 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/webui/media_router/media_router_localized_strings_provider.h" + +#include "chrome/grit/generated_resources.h" +#include "content/public/browser/web_ui_data_source.h" + +namespace { + +// Note that media_router.html contains a <script> tag which imports a script +// of the following name. These names must be kept in sync. +const char kLocalizedStringsFile[] = "strings.js"; + +void AddMediaRouterStrings(content::WebUIDataSource* html_source) { + html_source->AddLocalizedString("mediaRouterTitle", IDS_MEDIA_ROUTER_TITLE); +} + +void AddRouteDetailsStrings(content::WebUIDataSource* html_source) { + html_source->AddLocalizedString("castingActivityStatus", + IDS_MEDIA_ROUTER_CASTING_ACTIVITY_STATUS); + html_source->AddLocalizedString("backToSinkPicker", + IDS_MEDIA_ROUTER_BACK_TO_SINK_PICKER); + html_source->AddLocalizedString("stopCastingButton", + IDS_MEDIA_ROUTER_STOP_CASTING_BUTTON); +} + +} // namespace + +namespace media_router { + +void AddLocalizedStrings(content::WebUIDataSource* html_source) { + AddMediaRouterStrings(html_source); + AddRouteDetailsStrings(html_source); + html_source->SetJsonPath(kLocalizedStringsFile); +} + +} // namespace media_router
diff --git a/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.h b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.h new file mode 100644 index 0000000..e700a0e --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_router_localized_strings_provider.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 CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_ROUTER_LOCALIZED_STRINGS_PROVIDER_H_ +#define CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_ROUTER_LOCALIZED_STRINGS_PROVIDER_H_ + +namespace content { +class WebUIDataSource; +} + +namespace media_router { + +// Adds the strings needed by Media Router to |html_source|. This function +// causes |html_source| to expose a strings.js file from its source which +// contains a mapping from string's name to its translated value. +void AddLocalizedStrings(content::WebUIDataSource* html_source); + +} // namespace media_router + +#endif // CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_ROUTER_LOCALIZED_STRINGS_PROVIDER_H_
diff --git a/chrome/browser/ui/webui/media_router/media_router_resources_provider.cc b/chrome/browser/ui/webui/media_router/media_router_resources_provider.cc new file mode 100644 index 0000000..7d1e89ec --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_router_resources_provider.cc
@@ -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. + +#include "chrome/browser/ui/webui/media_router/media_router_resources_provider.h" + +#include "content/public/browser/web_ui_data_source.h" +#include "grit/browser_resources.h" + +namespace { + +void AddIcons(content::WebUIDataSource* html_source) { + html_source->AddResourcePath("elements/icon/chromecast-icon.png", + IDR_MEDIA_ROUTER_CHROMECAST_ICON); + html_source->AddResourcePath("elements/icon/chromecast-icon2x.png", + IDR_MEDIA_ROUTER_CHROMECAST_2X_ICON); + html_source->AddResourcePath("elements/icon/close-gray.png", + IDR_CLOSE_GRAY_ICON); + html_source->AddResourcePath("elements/icon/close-gray2x.png", + IDR_CLOSE_GRAY_2X_ICON); + html_source->AddResourcePath("elements/icon/drop-down-arrow.png", + IDR_DROP_DOWN_ARROW_ICON); + html_source->AddResourcePath("elements/icon/drop-down-arrow2x.png", + IDR_DROP_DOWN_ARROW_2X_ICON); + html_source->AddResourcePath("elements/icon/drop-down-arrow-hover.png", + IDR_DROP_DOWN_ARROW_HOVER_ICON); + html_source->AddResourcePath("elements/icon/drop-down-arrow-hover2x.png", + IDR_DROP_DOWN_ARROW_HOVER_2X_ICON); + html_source->AddResourcePath("elements/icon/drop-down-arrow-showing.png", + IDR_DROP_DOWN_ARROW_SHOWING_ICON); + html_source->AddResourcePath("elements/icon/drop-down-arrow-showing2x.png", + IDR_DROP_DOWN_ARROW_SHOWING_2X_ICON); + html_source->AddResourcePath("elements/icon/generic-device.png", + IDR_MEDIA_ROUTER_GENERIC_DEVICE_2X_ICON); + html_source->AddResourcePath("elements/icon/generic-device2x.png", + IDR_MEDIA_ROUTER_GENERIC_DEVICE_2X_ICON); + html_source->AddResourcePath("elements/icon/hangouts-icon.png", + IDR_MEDIA_ROUTER_HANGOUTS_2X_ICON); + html_source->AddResourcePath("elements/icon/hangouts-icon2x.png", + IDR_MEDIA_ROUTER_HANGOUTS_2X_ICON); + html_source->AddResourcePath("elements/icon/sad-face.png", + IDR_SAD_FACE_ICON); + html_source->AddResourcePath("elements/icon/sad-face2x.png", + IDR_SAD_FACE_2X_ICON); +} + +void AddMainWebResources(content::WebUIDataSource* html_source) { + // TODO(apacible): Add resources when they are available. + html_source->AddResourcePath("media_router_data.js", + IDR_MEDIA_ROUTER_DATA_JS); +} + +void AddPolymerElements(content::WebUIDataSource* html_source) { + // TODO(apacible): Add resources when they are available. + html_source->AddResourcePath( + "elements/cast_mode_picker/cast_mode_picker.css", + IDR_CAST_MODE_PICKER_CSS); + html_source->AddResourcePath( + "elements/cast_mode_picker/cast_mode_picker.html", + IDR_CAST_MODE_PICKER_HTML); + html_source->AddResourcePath( + "elements/cast_mode_picker/cast_mode_picker.js", + IDR_CAST_MODE_PICKER_JS); + html_source->AddResourcePath( + "elements/drop_down_button/drop_down_button.css", + IDR_DROP_DOWN_BUTTON_CSS); + html_source->AddResourcePath( + "elements/drop_down_button/drop_down_button.html", + IDR_DROP_DOWN_BUTTON_HTML); + html_source->AddResourcePath( + "elements/drop_down_button/drop_down_button.js", + IDR_DROP_DOWN_BUTTON_JS); + html_source->AddResourcePath( + "elements/issue_banner/issue_banner.css", + IDR_ISSUE_BANNER_CSS); + html_source->AddResourcePath( + "elements/issue_banner/issue_banner.html", + IDR_ISSUE_BANNER_HTML); + html_source->AddResourcePath( + "elements/issue_banner/issue_banner.js", + IDR_ISSUE_BANNER_JS); +} + +} // namespace + +namespace media_router { + +void AddMediaRouterUIResources(content::WebUIDataSource* html_source) { + AddIcons(html_source); + AddMainWebResources(html_source); + AddPolymerElements(html_source); + html_source->SetDefaultResource(IDR_MEDIA_ROUTER_HTML); +} + +} // namespace media_router
diff --git a/chrome/browser/ui/webui/media_router/media_router_resources_provider.h b/chrome/browser/ui/webui/media_router/media_router_resources_provider.h new file mode 100644 index 0000000..1c62084 --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_router_resources_provider.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 CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_ROUTER_RESOURCES_PROVIDER_H_ +#define CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_ROUTER_RESOURCES_PROVIDER_H_ + +namespace content { +class WebUIDataSource; +} + +namespace media_router { + +// Adds the resources needed by Media Router to |html_source|. +void AddMediaRouterUIResources(content::WebUIDataSource* html_source); + +} // namespace media_router + +#endif // CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_ROUTER_RESOURCES_PROVIDER_H_
diff --git a/chrome/browser/ui/webui/media_router/media_sink_with_cast_modes.cc b/chrome/browser/ui/webui/media_router/media_sink_with_cast_modes.cc new file mode 100644 index 0000000..d24e207f0 --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_sink_with_cast_modes.cc
@@ -0,0 +1,20 @@ +// 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/webui/media_router/media_sink_with_cast_modes.h" + +namespace media_router { + +MediaSinkWithCastModes::MediaSinkWithCastModes(const MediaSink& sink) + : sink(sink) { +} + +MediaSinkWithCastModes::~MediaSinkWithCastModes() { +} + +bool MediaSinkWithCastModes::Equals(const MediaSinkWithCastModes& other) const { + return sink.Equals(other.sink) && cast_modes == other.cast_modes; +} + +} // namespace media_router
diff --git a/chrome/browser/ui/webui/media_router/media_sink_with_cast_modes.h b/chrome/browser/ui/webui/media_router/media_sink_with_cast_modes.h new file mode 100644 index 0000000..48c651d --- /dev/null +++ b/chrome/browser/ui/webui/media_router/media_sink_with_cast_modes.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 CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_SINK_WITH_CAST_MODES_H_ +#define CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_SINK_WITH_CAST_MODES_H_ + +#include <set> + +#include "chrome/browser/media/router/media_sink.h" +#include "chrome/browser/ui/webui/media_router/media_cast_mode.h" + +namespace media_router { + +// Contains information on a MediaSink and the set of cast modes it is +// compatible with. This should be interpreted under the context of a +// QueryResultManager which contains a mapping from MediaCastMode to +// MediaSource. +struct MediaSinkWithCastModes { + explicit MediaSinkWithCastModes(const MediaSink& sink); + ~MediaSinkWithCastModes(); + + MediaSink sink; + CastModeSet cast_modes; + + bool Equals(const MediaSinkWithCastModes& other) const; +}; + +} // namespace media_router + +#endif // CHROME_BROWSER_UI_WEBUI_MEDIA_ROUTER_MEDIA_SINK_WITH_CAST_MODES_H_
diff --git a/chrome/browser/ui/webui/mojo_web_ui_controller.h b/chrome/browser/ui/webui/mojo_web_ui_controller.h index bb934df..e2025259 100644 --- a/chrome/browser/ui/webui/mojo_web_ui_controller.h +++ b/chrome/browser/ui/webui/mojo_web_ui_controller.h
@@ -54,9 +54,8 @@ public: explicit MojoWebUIController(content::WebUI* contents) : MojoWebUIControllerBase(contents), weak_factory_(this) {} - virtual ~MojoWebUIController() {} - virtual void RenderViewCreated( - content::RenderViewHost* render_view_host) override { + ~MojoWebUIController() override {} + void RenderViewCreated(content::RenderViewHost* render_view_host) override { MojoWebUIControllerBase::RenderViewCreated(render_view_host); render_view_host->GetMainFrame()->GetServiceRegistry()-> AddService<Interface>(
diff --git a/chrome/browser/ui/webui/ntp/foreign_session_handler.cc b/chrome/browser/ui/webui/ntp/foreign_session_handler.cc index a11ad9e..d0adc4ad 100644 --- a/chrome/browser/ui/webui/ntp/foreign_session_handler.cc +++ b/chrome/browser/ui/webui/ntp/foreign_session_handler.cc
@@ -58,9 +58,7 @@ // static void ForeignSessionHandler::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kNtpCollapsedForeignSessions, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kNtpCollapsedForeignSessions); } // static
diff --git a/chrome/browser/ui/webui/ntp/most_visited_handler.cc b/chrome/browser/ui/webui/ntp/most_visited_handler.cc index e8e8a3f..9deda8c 100644 --- a/chrome/browser/ui/webui/ntp/most_visited_handler.cc +++ b/chrome/browser/ui/webui/ntp/most_visited_handler.cc
@@ -290,7 +290,5 @@ // static void MostVisitedHandler::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kNtpMostVisitedURLsBlacklist, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kNtpMostVisitedURLsBlacklist); }
diff --git a/chrome/browser/ui/webui/ntp/new_tab_page_handler.cc b/chrome/browser/ui/webui/ntp/new_tab_page_handler.cc index 4d16b74..aef4044 100644 --- a/chrome/browser/ui/webui/ntp/new_tab_page_handler.cc +++ b/chrome/browser/ui/webui/ntp/new_tab_page_handler.cc
@@ -172,10 +172,7 @@ void NewTabPageHandler::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { // TODO(estade): should be syncable. - registry->RegisterIntegerPref( - prefs::kNtpShownPage, - APPS_PAGE_ID, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kNtpShownPage, APPS_PAGE_ID); } // static
diff --git a/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc b/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc index 59632f0..e6493f1 100644 --- a/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc +++ b/chrome/browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc
@@ -9,6 +9,7 @@ #include "base/metrics/statistics_recorder.h" #include "base/strings/utf_string_conversions.h" #include "chrome/common/ntp_logging_events.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -36,7 +37,11 @@ } // namespace -TEST(NTPUserDataLoggerTest, TestLogging) { +class NTPUserDataLoggerTest : public testing::Test { + content::TestBrowserThreadBundle thread_bundle_; +}; + +TEST_F(NTPUserDataLoggerTest, TestLogging) { base::StatisticsRecorder::Initialize(); // Ensure empty statistics. @@ -101,7 +106,7 @@ EXPECT_EQ(1, GetTotalCount("NewTabPage.SuggestionsType")); } -TEST(NTPUserDataLoggerTest, TestLogMostVisitedImpression) { +TEST_F(NTPUserDataLoggerTest, TestLogMostVisitedImpression) { base::StatisticsRecorder::Initialize(); EXPECT_EQ(0, GetBinCount("NewTabPage.SuggestionsImpression.foobar", 1)); @@ -127,7 +132,7 @@ EXPECT_EQ(1, GetBinCount("NewTabPage.SuggestionsImpression.foobar", 5)); } -TEST(NTPUserDataLoggerTest, TestLogMostVisitedNavigation) { +TEST_F(NTPUserDataLoggerTest, TestLogMostVisitedNavigation) { base::StatisticsRecorder::Initialize(); EXPECT_EQ(0, GetTotalCount("NewTabPage.MostVisited"));
diff --git a/chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc b/chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc index 6e5daad..d6bc880 100644 --- a/chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc +++ b/chrome/browser/ui/webui/ntp/suggestions_combiner_unittest.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/ui/webui/ntp/suggestions_page_handler.h" #include "chrome/browser/ui/webui/ntp/suggestions_source.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -204,6 +205,7 @@ } protected: + content::TestBrowserThreadBundle thread_bundle_; Profile* profile_; SuggestionsHandler* suggestions_handler_; SuggestionsCombiner* combiner_;
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc index d1f6f6f0..a5ab5b7 100644 --- a/chrome/browser/ui/webui/options/browser_options_handler.cc +++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -1385,12 +1385,22 @@ void BrowserOptionsHandler::DeleteProfile(const base::ListValue* args) { DCHECK(args); const base::Value* file_path_value; - if (!args->Get(0, &file_path_value)) + if (!args->Get(0, &file_path_value)) { + NOTREACHED(); return; + } base::FilePath file_path; - if (!base::GetValueAsFilePath(*file_path_value, &file_path)) + if (!base::GetValueAsFilePath(*file_path_value, &file_path)) { + NOTREACHED(); return; + } + + // The Profile Data doesn't get wiped until Chrome closes. Since we promised + // that the user's data would be removed, do so immediately. The helper is + // invoked from other calls but we only promised we'd do the removal here. + profiles::RemoveBrowsingDataForProfile(file_path); + helper::DeleteProfileAtPath(file_path, web_ui()); }
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc index ca4cc50..c451e04b 100644 --- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc +++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -279,7 +279,7 @@ js_display->SetBoolean("isPrimary", display.id() == primary_id); js_display->SetBoolean("isInternal", display.IsInternal()); js_display->SetInteger("orientation", - static_cast<int>(display_info.rotation())); + static_cast<int>(display_info.GetActiveRotation())); base::ListValue* js_resolutions = new base::ListValue(); for (const ash::DisplayMode& display_mode : display_info.display_modes()) { @@ -438,7 +438,8 @@ content::RecordAction( base::UserMetricsAction("Options_DisplaySetOrientation")); - ash::ScreenRotationAnimator(display_id).Rotate(new_rotation); + ash::ScreenRotationAnimator(display_id) + .Rotate(new_rotation, gfx::Display::ROTATION_SOURCE_USER); } void DisplayOptionsHandler::HandleSetColorProfile(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/options/preferences_browsertest.h b/chrome/browser/ui/webui/options/preferences_browsertest.h index 86ae2c4..eeb13b58a 100644 --- a/chrome/browser/ui/webui/options/preferences_browsertest.h +++ b/chrome/browser/ui/webui/options/preferences_browsertest.h
@@ -36,10 +36,10 @@ class PreferencesBrowserTest : public InProcessBrowserTest { public: PreferencesBrowserTest(); - ~PreferencesBrowserTest(); + ~PreferencesBrowserTest() override; // InProcessBrowserTest implementation: - virtual void SetUpOnMainThread() override; + void SetUpOnMainThread() override; void OnPreferenceChanged(const std::string& pref_name); @@ -49,7 +49,7 @@ void SetUpPrefs(); // InProcessBrowserTest implementation: - virtual void SetUpInProcessBrowserTestFixture() override; + void SetUpInProcessBrowserTestFixture() override; // Sets user policies through the mock policy provider. void SetUserPolicies(const std::vector<std::string>& names,
diff --git a/chrome/browser/ui/webui/options/sync_setup_handler.cc b/chrome/browser/ui/webui/options/sync_setup_handler.cc index bc9e41f..ea7bd989 100644 --- a/chrome/browser/ui/webui/options/sync_setup_handler.cc +++ b/chrome/browser/ui/webui/options/sync_setup_handler.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_info_cache.h" #include "chrome/browser/profiles/profile_metrics.h" +#include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/signin/signin_error_controller_factory.h" #include "chrome/browser/signin/signin_header_helper.h" #include "chrome/browser/signin/signin_manager_factory.h" @@ -656,6 +657,7 @@ bool delete_profile = false; if (args->GetBoolean(0, &delete_profile) && delete_profile) { + profiles::RemoveBrowsingDataForProfile(GetProfile()->GetPath()); // Do as BrowserOptionsHandler::DeleteProfile(). options::helper::DeleteProfileAtPath(GetProfile()->GetPath(), web_ui()); }
diff --git a/chrome/browser/ui/webui/plugins_ui.cc b/chrome/browser/ui/webui/plugins_ui.cc index b4f084ef1..9d5d8241 100644 --- a/chrome/browser/ui/webui/plugins_ui.cc +++ b/chrome/browser/ui/webui/plugins_ui.cc
@@ -521,10 +521,7 @@ // static void PluginsUI::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kPluginsShowDetails, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kPluginsShowDetails, false); registry->RegisterDictionaryPref( prefs::kContentSettingsPluginWhitelist, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc index 35517fa1..1f701a6 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/local_discovery/pwg_raster_converter.h" #include "chrome/browser/ui/webui/print_preview/extension_printer_handler.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/api/printer_provider/printer_provider_api.h" #include "extensions/browser/api/printer_provider/printer_provider_api_factory.h" #include "extensions/browser/api/printer_provider/printer_provider_print_job.h" @@ -370,7 +371,7 @@ profile_ = profile_builder.Build(); extension_printer_handler_.reset(new ExtensionPrinterHandler( - profile_.get(), message_loop_.task_runner())); + profile_.get(), base::MessageLoop::current()->task_runner())); pwg_raster_converter_ = new FakePWGRasterConverter(); extension_printer_handler_->SetPwgRasterConverterForTesting( @@ -389,7 +390,7 @@ FakePWGRasterConverter* pwg_raster_converter_; private: - base::MessageLoop message_loop_; + content::TestBrowserThreadBundle thread_bundle_; scoped_ptr<TestingProfile> profile_;
diff --git a/chrome/browser/ui/webui/print_preview/sticky_settings.cc b/chrome/browser/ui/webui/print_preview/sticky_settings.cc index 073f78b..e9077b1d 100644 --- a/chrome/browser/ui/webui/print_preview/sticky_settings.cc +++ b/chrome/browser/ui/webui/print_preview/sticky_settings.cc
@@ -61,9 +61,7 @@ void StickySettings::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kPrintPreviewStickySettings, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kPrintPreviewStickySettings); } std::string* StickySettings::printer_app_state() {
diff --git a/chrome/browser/ui/webui/profiler_ui.cc b/chrome/browser/ui/webui/profiler_ui.cc index a16c05f1..ae30b225 100644 --- a/chrome/browser/ui/webui/profiler_ui.cc +++ b/chrome/browser/ui/webui/profiler_ui.cc
@@ -53,17 +53,17 @@ protected: // content::URLDataSource implementation. - virtual std::string GetSource() override { + std::string GetSource() override { return chrome::kChromeUIProfilerHost; } - virtual std::string GetMimeType(const std::string& path) const override { + std::string GetMimeType(const std::string& path) const override { if (EndsWith(path, ".js", false)) return "application/javascript"; return "text/html"; } - virtual void StartDataRequest( + void StartDataRequest( const std::string& path, bool is_incognito, const content::URLDataSource::GotDataCallback& callback) override { @@ -163,17 +163,14 @@ } void ProfilerUI::ReceivedProfilerData( + const metrics::ProfilerDataAttributes& attributes, const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, - base::ProcessId process_id, - content::ProcessType process_type, - int profiling_phase, - base::TimeDelta phase_start, - base::TimeDelta phase_finish, const metrics::ProfilerEvents& past_events) { // Serialize the data to JSON. base::DictionaryValue json_data; task_profiler::TaskProfilerDataSerializer::ToValue( - process_data_phase, process_id, process_type, &json_data); + process_data_phase, attributes.process_id, attributes.process_type, + &json_data); // Send the data to the renderer. web_ui()->CallJavascriptFunction("g_browserBridge.receivedData", json_data);
diff --git a/chrome/browser/ui/webui/profiler_ui.h b/chrome/browser/ui/webui/profiler_ui.h index 8835d49..4a490c83 100644 --- a/chrome/browser/ui/webui/profiler_ui.h +++ b/chrome/browser/ui/webui/profiler_ui.h
@@ -22,12 +22,8 @@ private: // TrackingSynchronizerObserver: void ReceivedProfilerData( + const metrics::ProfilerDataAttributes& attributes, const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, - base::ProcessId process_id, - content::ProcessType process_type, - int profiling_phase, - base::TimeDelta phase_start, - base::TimeDelta phase_finish, const metrics::ProfilerEvents& past_events) override; // Used to get |weak_ptr_| to self on the UI thread.
diff --git a/chrome/browser/ui/webui/set_as_default_browser_ui.cc b/chrome/browser/ui/webui/set_as_default_browser_ui.cc index 9645460..5674678 100644 --- a/chrome/browser/ui/webui/set_as_default_browser_ui.cc +++ b/chrome/browser/ui/webui/set_as_default_browser_ui.cc
@@ -98,16 +98,16 @@ public: explicit SetAsDefaultBrowserHandler( const base::WeakPtr<ResponseDelegate>& response_delegate); - virtual ~SetAsDefaultBrowserHandler(); + ~SetAsDefaultBrowserHandler() override; // WebUIMessageHandler implementation. - virtual void RegisterMessages() override; + void RegisterMessages() override; // ShellIntegration::DefaultWebClientObserver implementation. - virtual void SetDefaultWebClientUIState( + void SetDefaultWebClientUIState( ShellIntegration::DefaultWebClientUIState state) override; - virtual void OnSetAsDefaultConcluded(bool close_chrome) override; - virtual bool IsInteractiveSetDefaultPermitted() override; + void OnSetAsDefaultConcluded(bool close_chrome) override; + bool IsInteractiveSetDefaultPermitted() override; private: // Handler for the 'Next' (or 'make Chrome the Metro browser') button. @@ -201,31 +201,29 @@ public chrome::BrowserListObserver { public: SetAsDefaultBrowserDialogImpl(Profile* profile, Browser* browser); - virtual ~SetAsDefaultBrowserDialogImpl(); + ~SetAsDefaultBrowserDialogImpl() override; // Show a modal web dialog with kChromeUIMetroFlowURL page. void ShowDialog(); protected: // Overridden from WebDialogDelegate: - virtual ui::ModalType GetDialogModalType() const override; - virtual base::string16 GetDialogTitle() const override; - virtual GURL GetDialogContentURL() const override; - virtual void GetWebUIMessageHandlers( + ui::ModalType GetDialogModalType() const override; + base::string16 GetDialogTitle() const override; + GURL GetDialogContentURL() const override; + void GetWebUIMessageHandlers( std::vector<WebUIMessageHandler*>* handlers) const override; - virtual void GetDialogSize(gfx::Size* size) const override; - virtual std::string GetDialogArgs() const override; - virtual void OnDialogClosed(const std::string& json_retval) override; - virtual void OnCloseContents(WebContents* source, - bool* out_close_dialog) override; - virtual bool ShouldShowDialogTitle() const override; - virtual bool HandleContextMenu( - const content::ContextMenuParams& params) override; + void GetDialogSize(gfx::Size* size) const override; + std::string GetDialogArgs() const override; + void OnDialogClosed(const std::string& json_retval) override; + void OnCloseContents(WebContents* source, bool* out_close_dialog) override; + bool ShouldShowDialogTitle() const override; + bool HandleContextMenu(const content::ContextMenuParams& params) override; // Overridden from ResponseDelegate: - virtual void SetDialogInteractionResult(MakeChromeDefaultResult result); + void SetDialogInteractionResult(MakeChromeDefaultResult result) override; // Overridden from BrowserListObserver: - virtual void OnBrowserRemoved(Browser* browser) override; + void OnBrowserRemoved(Browser* browser) override; private: Profile* profile_;
diff --git a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index b1d7dc8..77fbb47 100644 --- a/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc
@@ -104,6 +104,23 @@ } #endif +void AddSearchStrings(content::WebUIDataSource* html_source) { + html_source->AddLocalizedString("searchPageTitle", + IDS_SETTINGS_SEARCH_PAGE_TITLE); + html_source->AddLocalizedString("searchExplanation", + IDS_SETTINGS_SEARCH_EXPLANATION); + html_source->AddLocalizedString("searchManageButtonLabel", + IDS_SETTINGS_SEARCH_MANAGE_BUTTON_LABEL); + html_source->AddLocalizedString("searchOkGoogleLabel", + IDS_SETTINGS_SEARCH_OK_GOOGLE_LABEL); + html_source->AddLocalizedString( + "searchOkGoogleLearnMoreLink", + IDS_SETTINGS_SEARCH_OK_GOOGLE_LEARN_MORE_LINK); + html_source->AddLocalizedString( + "searchOkGoogleDescriptionLabel", + IDS_SETTINGS_SEARCH_OK_GOOGLE_DESCRIPTION_LABEL); +} + } // namespace namespace settings { @@ -115,6 +132,7 @@ #if defined(OS_CHROMEOS) AddInternetStrings(html_source); #endif + AddSearchStrings(html_source); html_source->SetJsonPath(kLocalizedStringsFile); }
diff --git a/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chrome/browser/ui/webui/signin/inline_login_ui.cc index e807990b..e38d985 100644 --- a/chrome/browser/ui/webui/signin/inline_login_ui.cc +++ b/chrome/browser/ui/webui/signin/inline_login_ui.cc
@@ -138,7 +138,7 @@ #endif if (is_webview) { extensions::GuestViewManager* manager = - extensions::GuestViewManager::FromBrowserContextIfAvailable( + extensions::GuestViewManager::FromBrowserContext( web_contents->GetBrowserContext()); if (manager) { manager->ForEachGuest(web_contents,
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc index 7f5e2bfd..7da4dc0 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -84,30 +84,87 @@ namespace login_ui_test_utils { void WaitUntilUIReady(Browser* browser) { - content::DOMMessageQueue message_queue; - ASSERT_TRUE(content::ExecuteScript( + std::string message; + ASSERT_TRUE(content::ExecuteScriptAndExtractString( browser->tab_strip_model()->GetActiveWebContents(), "if (!inline.login.getAuthExtHost())" " inline.login.initialize();" "var handler = function() {" - " window.domAutomationController.setAutomationId(0);" " window.domAutomationController.send('ready');" "};" "if (inline.login.isAuthReady())" " handler();" "else" - " inline.login.getAuthExtHost().addEventListener('ready', handler);")); - - std::string message; - do { - ASSERT_TRUE(message_queue.WaitForMessage(&message)); - } while (message != "\"ready\""); + " inline.login.getAuthExtHost().addEventListener('ready', handler);", + &message)); + ASSERT_EQ("ready", message); } -void ExecuteJsToSigninInSigninFrame(Browser* browser, - const std::string& email, - const std::string& password) { - std::string js = +void WaitUntilElementExistsInSigninFrame(Browser* browser, + const std::string& element_id) { + std::string message; + std::string js = + "function WaitForElementById(elementId) {" + " var retries = 10; /* 10 seconds. */" + " function CheckelementExists() {" + " if (document.getElementById(elementId) != null) {" + " window.domAutomationController.send('found');" + " } else if (retries > 0) { " + " retries--;" + " window.setTimeout(CheckelementExists, 1000);" + " } else {" + " window.domAutomationController.send('failed');" + " }" + " }" + " CheckelementExists();" + "}" + "WaitForElementById('" + element_id + "');"; + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(content::ExecuteScriptAndExtractString( + InlineLoginUI::GetAuthFrame(web_contents, GURL(), "signin-frame"), + js, &message)); + + ASSERT_EQ("found", message) << + "Failed to find element with id " << element_id; +} + +bool ElementExistsInSigninFrame(Browser* browser, + const std::string& element_id) { + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + bool result = false; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + InlineLoginUI::GetAuthFrame(web_contents, GURL(), "signin-frame"), + "window.domAutomationController.send(" + " document.getElementById('" + element_id + "') != null);", + &result)); + return result; +} + +void SigninInNewGaiaFlow(Browser* browser, + const std::string& email, + const std::string& password) { + std::string js = "document.getElementById('Email').value = '" + email + "';" + "document.getElementById('next').click();"; + + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(content::ExecuteScript(InlineLoginUI::GetAuthFrame( + web_contents, GURL(), "signin-frame"), js)); + + WaitUntilElementExistsInSigninFrame(browser, "Passwd"); + js = "document.getElementById('Passwd').value = '" + password + "';" + "document.getElementById('signIn').click();"; + + ASSERT_TRUE(content::ExecuteScript(InlineLoginUI::GetAuthFrame( + web_contents, GURL(), "signin-frame"), js)); +} + +void SigninInOldGaiaFlow(Browser* browser, + const std::string& email, + const std::string& password) { + std::string js = "document.getElementById('Email').value = '" + email + "';" "document.getElementById('Passwd').value = '" + password + "';" "document.getElementById('signIn').click();"; @@ -118,6 +175,16 @@ web_contents, GURL(), "signin-frame"), js)); } +void ExecuteJsToSigninInSigninFrame(Browser* browser, + const std::string& email, + const std::string& password) { + WaitUntilElementExistsInSigninFrame(browser, "Email"); + if (ElementExistsInSigninFrame(browser, "next")) + SigninInNewGaiaFlow(browser, email, password); + else + SigninInOldGaiaFlow(browser, email, password); +} + bool SignInWithUI(Browser* browser, const std::string& username, const std::string& password) {
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.h b/chrome/browser/ui/webui/signin/login_ui_test_utils.h index 3f17f46c..bf9a11051 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.h +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.h
@@ -14,12 +14,31 @@ // Blocks until the login UI is available and ready for authorization. void WaitUntilUIReady(Browser* browser); +// Blocks until an element with id |element_id| exists in the signin page. +void WaitUntilElementExistsInSigninFrame(Browser* browser, + const std::string& element_id); + +// Returns whether an element with id |element_id| exists in the signin page. +bool ElementExistsInSigninFrame(Browser* browser, + const std::string& element_id); + // Executes JavaScript code to sign in a user with email and password to the -// auth iframe hosted by gaia_auth extension. +// auth iframe hosted by gaia_auth extension. This function automatically +// detects the version of GAIA sign in page to use. void ExecuteJsToSigninInSigninFrame(Browser* browser, const std::string& email, const std::string& password); +// Executes JS to sign in the user in the new GAIA sign in flow. +void SigninInNewGaiaFlow(Browser* browser, + const std::string& email, + const std::string& password); + +// Executes JS to sign in the user in the old GAIA sign in flow. +void SigninInOldGaiaFlow(Browser* browser, + const std::string& email, + const std::string& password); + // A function to sign in a user using Chrome sign-in UI interface. // This will block until a signin succeeded or failed notification is observed. bool SignInWithUI(Browser* browser,
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc index feddfc81..a8f83a5 100644 --- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc +++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/profiles/profile_window.h" #include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/signin/local_auth.h" +#include "chrome/browser/signin/proximity_auth_facade.h" #include "chrome/browser/ui/app_list/app_list_service.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_dialogs.h" @@ -297,7 +298,7 @@ } UserManagerScreenHandler::~UserManagerScreenHandler() { - ScreenlockBridge::Get()->SetLockHandler(NULL); + GetScreenlockBridgeInstance()->SetLockHandler(NULL); } void UserManagerScreenHandler::ShowBannerMessage( @@ -309,7 +310,8 @@ void UserManagerScreenHandler::ShowUserPodCustomIcon( const std::string& user_email, - const ScreenlockBridge::UserPodCustomIconOptions& icon_options) { + const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions& + icon_options) { scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue(); if (!icon || icon->empty()) return; @@ -332,10 +334,10 @@ void UserManagerScreenHandler::SetAuthType( const std::string& user_email, - ScreenlockBridge::LockHandler::AuthType auth_type, + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type, const base::string16& auth_value) { if (GetAuthType(user_email) == - ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD) + proximity_auth::ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD) return; user_auth_type_map_[user_email] = auth_type; @@ -346,17 +348,17 @@ base::StringValue(auth_value)); } -ScreenlockBridge::LockHandler::AuthType UserManagerScreenHandler::GetAuthType( - const std::string& user_email) const { +proximity_auth::ScreenlockBridge::LockHandler::AuthType +UserManagerScreenHandler::GetAuthType(const std::string& user_email) const { UserAuthTypeMap::const_iterator it = user_auth_type_map_.find(user_email); if (it == user_auth_type_map_.end()) - return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; + return proximity_auth::ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; return it->second; } -ScreenlockBridge::LockHandler::ScreenType +proximity_auth::ScreenlockBridge::LockHandler::ScreenType UserManagerScreenHandler::GetScreenType() const { - return ScreenlockBridge::LockHandler::LOCK_SCREEN; + return proximity_auth::ScreenlockBridge::LockHandler::LOCK_SCREEN; } void UserManagerScreenHandler::Unlock(const std::string& user_email) { @@ -388,7 +390,7 @@ desktop_type_ = chrome::GetHostDesktopTypeForNativeView( web_ui()->GetWebContents()->GetNativeView()); - ScreenlockBridge::Get()->SetLockHandler(this); + GetScreenlockBridgeInstance()->SetLockHandler(this); } void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) { @@ -458,15 +460,26 @@ void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) { DCHECK(args); const base::Value* profile_path_value; - if (!args->Get(0, &profile_path_value)) + if (!args->Get(0, &profile_path_value)) { + NOTREACHED(); return; + } base::FilePath profile_path; - if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) + if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) { + NOTREACHED(); return; + } - if (!profiles::IsMultipleProfilesEnabled()) + if (!profiles::IsMultipleProfilesEnabled()) { + NOTREACHED(); return; + } + + // The Profile Data doesn't get wiped until Chrome closes. Since we promised + // that the user's data would be removed, do so immediately. If the profile + // hasn't been loaded then the ProfileManager will delete it right away. + profiles::RemoveBrowsingDataForProfile(profile_path); g_browser_process->profile_manager()->ScheduleProfileForDeletion( profile_path, @@ -535,9 +548,10 @@ const base::ListValue* args) { std::string email; CHECK(args->GetString(0, &email)); - SetAuthType(email, - ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD, - base::string16()); + SetAuthType( + email, + proximity_auth::ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD, + base::string16()); HideUserPodCustomIcon(email); }
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.h b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h index 2a68f7e8..98bf442 100644 --- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.h +++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.h
@@ -14,8 +14,8 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_metrics.h" -#include "chrome/browser/signin/screenlock_bridge.h" #include "chrome/browser/ui/host_desktop.h" +#include "components/proximity_auth/screenlock_bridge.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/web_ui_message_handler.h" @@ -29,10 +29,11 @@ class ListValue; } -class UserManagerScreenHandler : public content::WebUIMessageHandler, - public ScreenlockBridge::LockHandler, - public GaiaAuthConsumer, - public content::NotificationObserver { +class UserManagerScreenHandler + : public content::WebUIMessageHandler, + public proximity_auth::ScreenlockBridge::LockHandler, + public GaiaAuthConsumer, + public content::NotificationObserver { public: UserManagerScreenHandler(); ~UserManagerScreenHandler() override; @@ -47,16 +48,18 @@ const content::NotificationSource& source, const content::NotificationDetails& details) override; - // ScreenlockBridge::LockHandler implementation. + // proximity_auth::ScreenlockBridge::LockHandler implementation. void ShowBannerMessage(const base::string16& message) override; void ShowUserPodCustomIcon( const std::string& user_email, - const ScreenlockBridge::UserPodCustomIconOptions& icon_options) override; + const proximity_auth::ScreenlockBridge::UserPodCustomIconOptions& + icon_options) override; void HideUserPodCustomIcon(const std::string& user_email) override; void EnableInput() override; - void SetAuthType(const std::string& user_email, - ScreenlockBridge::LockHandler::AuthType auth_type, - const base::string16& auth_value) override; + void SetAuthType( + const std::string& user_email, + proximity_auth::ScreenlockBridge::LockHandler::AuthType auth_type, + const base::string16& auth_value) override; AuthType GetAuthType(const std::string& user_email) const override; ScreenType GetScreenType() const override; void Unlock(const std::string& user_email) override; @@ -115,7 +118,8 @@ // URL hash, used to key post-profile actions if present. std::string url_hash_; - typedef std::map<std::string, ScreenlockBridge::LockHandler::AuthType> + typedef std::map<std::string, + proximity_auth::ScreenlockBridge::LockHandler::AuthType> UserAuthTypeMap; UserAuthTypeMap user_auth_type_map_;
diff --git a/chrome/browser/ui/webui/signin_internals_ui.cc b/chrome/browser/ui/webui/signin_internals_ui.cc index f01cac7..a709e406 100644 --- a/chrome/browser/ui/webui/signin_internals_ui.cc +++ b/chrome/browser/ui/webui/signin_internals_ui.cc
@@ -8,8 +8,10 @@ #include "base/profiler/scoped_tracker.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/about_signin_internals_factory.h" +#include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" #include "chrome/common/url_constants.h" #include "components/signin/core/browser/about_signin_internals.h" +#include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "grit/signin_internals_resources.h" @@ -70,7 +72,15 @@ web_ui()->CallJavascriptFunction( "chrome.signin.getSigninInfo.handleReply", *about_signin_internals->GetSigninStatus()); - about_signin_internals->GetCookieAccountsAsync(); + + std::vector<std::pair<std::string, bool>> cookie_accounts; + GaiaCookieManagerService* cookie_manager_service = + GaiaCookieManagerServiceFactory::GetForProfile(profile); + if (cookie_manager_service->ListAccounts(&cookie_accounts)) { + about_signin_internals->OnGaiaAccountsInCookieUpdated( + cookie_accounts, + GoogleServiceAuthError(GoogleServiceAuthError::NONE)); + } return true; }
diff --git a/chrome/browser/ui/webui/webui_webview_browsertest.cc b/chrome/browser/ui/webui/webui_webview_browsertest.cc index ae9eb9f..a8fcadc 100644 --- a/chrome/browser/ui/webui/webui_webview_browsertest.cc +++ b/chrome/browser/ui/webui/webui_webview_browsertest.cc
@@ -4,6 +4,8 @@ #include "base/macros.h" #include "base/path_service.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/ui_test_utils.h" @@ -17,7 +19,7 @@ void SetUpOnMainThread() override { WebUIBrowserTest::SetUpOnMainThread(); AddLibrary( - base::FilePath(FILE_PATH_LITERAL("webview_execute_script_test.js"))); + base::FilePath(FILE_PATH_LITERAL("webview_content_script_test.js"))); base::FilePath test_data_dir; PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); @@ -52,3 +54,98 @@ "testExecuteScriptCodeFromFile", new base::StringValue(GetTestUrl("empty.html").spec()))); } + +IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddContentScript) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testAddContentScript", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} + +IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddMultiContentScripts) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testAddMultiContentScripts", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} + +IN_PROC_BROWSER_TEST_F( + WebUIWebViewBrowserTest, + AddContentScriptWithSameNameShouldOverwriteTheExistingOne) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testAddContentScriptWithSameNameShouldOverwriteTheExistingOne", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} + +IN_PROC_BROWSER_TEST_F( + WebUIWebViewBrowserTest, + AddContentScriptToOneWebViewShouldNotInjectToTheOtherWebView) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testAddContentScriptToOneWebViewShouldNotInjectToTheOtherWebView", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} + +IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddAndRemoveContentScripts) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testAddAndRemoveContentScripts", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} + +IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, + AddContentScriptsWithNewWindowAPI) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testAddContentScriptsWithNewWindowAPI", + new base::StringValue(GetTestUrl("guest_from_opener.html").spec()))); +} + +IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, + ContentScriptIsInjectedAfterTerminateAndReloadWebView) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testContentScriptIsInjectedAfterTerminateAndReloadWebView", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} + +IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, + ContentScriptExistsAsLongAsWebViewTagExists) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testContentScriptExistsAsLongAsWebViewTagExists", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} + +IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddContentScriptWithCode) { + ui_test_utils::NavigateToURL(browser(), GetWebViewEnabledWebUIURL()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testAddContentScriptWithCode", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} + +#if defined(OS_CHROMEOS) +// Right now we only have incognito WebUI on CrOS, but this should +// theoretically work for all platforms. +IN_PROC_BROWSER_TEST_F(WebUIWebViewBrowserTest, AddContentScriptIncognito) { + Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord( + browser()->profile(), GetWebViewEnabledWebUIURL()); + + SetWebUIInstance( + incognito_browser->tab_strip_model()->GetActiveWebContents()->GetWebUI()); + + ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest( + "testAddContentScript", + new base::StringValue(GetTestUrl("empty.html").spec()))); +} +#endif
diff --git a/chrome/browser/upgrade_detector.h b/chrome/browser/upgrade_detector.h index 53e8ee31..e117a67c 100644 --- a/chrome/browser/upgrade_detector.h +++ b/chrome/browser/upgrade_detector.h
@@ -132,6 +132,8 @@ } private: + FRIEND_TEST_ALL_PREFIXES(WrenchMenuModelTest, Basics); + // Initiates an Idle check. See IdleCallback below. void CheckIdle();
diff --git a/chrome/browser/web_applications/web_app_mac_unittest.mm b/chrome/browser/web_applications/web_app_mac_unittest.mm index 499ac56..fd29851 100644 --- a/chrome/browser/web_applications/web_app_mac_unittest.mm +++ b/chrome/browser/web_applications/web_app_mac_unittest.mm
@@ -223,7 +223,7 @@ NSString* plist_path = base::mac::FilePathToNSString( shim_path_.Append("Contents").Append("Info.plist")); NSMutableDictionary* plist = - [NSDictionary dictionaryWithContentsOfFile:plist_path]; + [NSMutableDictionary dictionaryWithContentsOfFile:plist_path]; [plist setObject:@"fake_user_data_dir" forKey:app_mode::kCrAppModeUserDataDirKey]; [plist writeToFile:plist_path
diff --git a/chrome/browser/web_resource/notification_promo.cc b/chrome/browser/web_resource/notification_promo.cc index a71c0e7..cdae454 100644 --- a/chrome/browser/web_resource/notification_promo.cc +++ b/chrome/browser/web_resource/notification_promo.cc
@@ -326,8 +326,7 @@ // TODO(dbeam): Registered only for migration. Remove in M28 when // we're reasonably sure all prefs are gone. // http://crbug.com/168887 - registry->RegisterDictionaryPref( - kPrefPromoObject, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kPrefPromoObject); } // static
diff --git a/chrome/browser/web_resource/promo_resource_service.cc b/chrome/browser/web_resource/promo_resource_service.cc index 140dff0..3fdeda2b 100644 --- a/chrome/browser/web_resource/promo_resource_service.cc +++ b/chrome/browser/web_resource/promo_resource_service.cc
@@ -71,10 +71,7 @@ user_prefs::PrefRegistrySyncable* registry) { // TODO(dbeam): This is registered only for migration; remove in M28 // when all prefs have been cleared. http://crbug.com/168887 - registry->RegisterStringPref( - prefs::kNtpPromoResourceCacheUpdate, - "0", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate, "0"); NotificationPromo::RegisterProfilePrefs(registry); }
diff --git a/chrome/browser_tests.isolate b/chrome/browser_tests.isolate index 89f84393..194b887 100644 --- a/chrome/browser_tests.isolate +++ b/chrome/browser_tests.isolate
@@ -37,6 +37,7 @@ 'files': [ '<(PRODUCT_DIR)/libclearkeycdm.so', '<(PRODUCT_DIR)/libclearkeycdmadapter.so', + '<(PRODUCT_DIR)/libpower_saver_test_plugin.so', '<(PRODUCT_DIR)/libppapi_tests.so', ], }, @@ -186,6 +187,7 @@ '<(PRODUCT_DIR)/osmesa.so', '<(PRODUCT_DIR)/plugins/npapi_test_plugin.plugin/', '<(PRODUCT_DIR)/plugins/test_netscape_plugin.plugin/', + '<(PRODUCT_DIR)/power_saver_test_plugin.plugin/Contents/MacOS/power_saver_test_plugin', '<(PRODUCT_DIR)/ppapi_tests.plugin/Contents/MacOS/ppapi_tests', ], }, @@ -206,6 +208,7 @@ '<(PRODUCT_DIR)/clearkeycdm.dll', '<(PRODUCT_DIR)/clearkeycdmadapter.dll', '<(PRODUCT_DIR)/plugins/', + '<(PRODUCT_DIR)/power_saver_test_plugin.dll', '<(PRODUCT_DIR)/ppapi_tests.dll', 'tools/build/repack_locales.py', ],
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 55d9dce..46108eed 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp
@@ -411,20 +411,10 @@ { 'target_name': 'chrome_version_resources', 'type': 'none', - 'conditions': [ - ['branding == "Chrome"', { - 'variables': { - 'branding_path': 'app/theme/google_chrome/BRANDING', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_path': 'app/theme/chromium/BRANDING', - }, - }], - ], 'variables': { 'output_dir': 'chrome_version', 'template_input_path': 'app/chrome_version.rc.version', + 'branding_path': 'app/theme/<(branding_path_component)/BRANDING', }, 'direct_dependent_settings': { 'include_dirs': [ @@ -452,18 +442,8 @@ 'variables': { 'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE', + 'branding_path': 'app/theme/<(branding_path_component)/BRANDING', }, - 'conditions': [ - ['branding == "Chrome"', { - 'variables': { - 'branding_path': 'app/theme/google_chrome/BRANDING', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_path': 'app/theme/chromium/BRANDING', - }, - }], - ], 'inputs': [ '<(version_path)', '<(branding_path)',
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 0ba338a3..4a4355cb 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi
@@ -82,8 +82,6 @@ 'browser/android/dev_tools_server.h', 'browser/android/dom_distiller/external_feedback_reporter_android.cc', 'browser/android/dom_distiller/external_feedback_reporter_android.h', - 'browser/android/dom_distiller/feedback_reporter_android.cc', - 'browser/android/dom_distiller/feedback_reporter_android.h', 'browser/android/download/android_download_manager_overwrite_infobar_delegate.cc', 'browser/android/download/android_download_manager_overwrite_infobar_delegate.h', 'browser/android/download/chrome_download_delegate.cc', @@ -298,6 +296,8 @@ 'browser/component_updater/component_updater_resource_throttle.h', 'browser/component_updater/ev_whitelist_component_installer.cc', 'browser/component_updater/ev_whitelist_component_installer.h', + 'browser/component_updater/pnacl_component_installer.cc', + 'browser/component_updater/pnacl_component_installer.h', 'browser/component_updater/recovery_component_installer.cc', 'browser/component_updater/recovery_component_installer.h', 'browser/component_updater/supervised_user_whitelist_installer.cc', @@ -435,6 +435,8 @@ 'browser/image_decoder.h', 'browser/image_holder.cc', 'browser/image_holder.h', + 'browser/infobars/infobar_responder.cc', + 'browser/infobars/infobar_responder.h', 'browser/infobars/infobar_service.cc', 'browser/infobars/infobar_service.h', 'browser/infobars/insecure_content_infobar_delegate.cc', @@ -1420,6 +1422,8 @@ 'browser/signin/easy_unlock_service_regular.h', 'browser/signin/easy_unlock_service_signin_chromeos.cc', 'browser/signin/easy_unlock_service_signin_chromeos.h', + 'browser/signin/proximity_auth_facade.cc', + 'browser/signin/proximity_auth_facade.h', 'browser/speech/extension_api/tts_engine_extension_api.cc', 'browser/speech/extension_api/tts_engine_extension_api.h', 'browser/speech/extension_api/tts_engine_extension_observer.cc', @@ -1609,8 +1613,6 @@ 'browser/history/history_utils.h', 'browser/history/top_sites_factory.cc', 'browser/history/top_sites_factory.h', - 'browser/history/top_sites_impl.cc', - 'browser/history/top_sites_impl.h', 'browser/history/web_history_service_factory.cc', 'browser/history/web_history_service_factory.h', ], @@ -1790,8 +1792,6 @@ 'browser/metrics/variations/variations_service.h', ], 'chrome_browser_nacl_sources': [ - 'browser/component_updater/pnacl/pnacl_component_installer.cc', - 'browser/component_updater/pnacl/pnacl_component_installer.h', 'browser/nacl_host/nacl_browser_delegate_impl.cc', 'browser/nacl_host/nacl_browser_delegate_impl.h', 'browser/nacl_host/nacl_infobar_delegate.cc', @@ -2598,8 +2598,6 @@ 'browser/signin/profile_identity_provider.h', 'browser/signin/profile_oauth2_token_service_factory.cc', 'browser/signin/profile_oauth2_token_service_factory.h', - 'browser/signin/screenlock_bridge.cc', - 'browser/signin/screenlock_bridge.h', 'browser/signin/signin_cookie_changed_subscription.cc', 'browser/signin/signin_cookie_changed_subscription.h', 'browser/signin/signin_error_controller_factory.cc',
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi index 1f3b14c..04c8043 100644 --- a/chrome/chrome_browser_chromeos.gypi +++ b/chrome/chrome_browser_chromeos.gypi
@@ -609,6 +609,8 @@ 'browser/chromeos/login/signin/oauth2_login_verifier.h', 'browser/chromeos/login/signin/oauth2_token_fetcher.cc', 'browser/chromeos/login/signin/oauth2_token_fetcher.h', + 'browser/chromeos/login/signin/oauth2_token_initializer.cc', + 'browser/chromeos/login/signin/oauth2_token_initializer.h', 'browser/chromeos/login/signin/token_handle_util.cc', 'browser/chromeos/login/signin/token_handle_util.h', 'browser/chromeos/login/signin_screen_controller.cc',
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index 040f4354..65d53ef 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi
@@ -120,6 +120,8 @@ 'browser/extensions/api/activity_log_private/activity_log_private_api.h', 'browser/extensions/api/audio_modem/audio_modem_api.cc', 'browser/extensions/api/audio_modem/audio_modem_api.h', + 'browser/extensions/api/autofill_private/autofill_private_api.cc', + 'browser/extensions/api/autofill_private/autofill_private_api.h', 'browser/extensions/api/automation_internal/automation_action_adapter.h', 'browser/extensions/api/automation_internal/automation_internal_api.cc', 'browser/extensions/api/automation_internal/automation_internal_api.h', @@ -303,6 +305,8 @@ 'browser/extensions/api/image_writer_private/write_from_url_operation.h', 'browser/extensions/api/inline_install_private/inline_install_private_api.cc', 'browser/extensions/api/inline_install_private/inline_install_private_api.h', + 'browser/extensions/api/instance_id/instance_id_api.cc', + 'browser/extensions/api/instance_id/instance_id_api.h', 'browser/extensions/api/launcher_page/launcher_page_api.cc', 'browser/extensions/api/launcher_page/launcher_page_api.h', 'browser/extensions/api/location/location_api.cc', @@ -392,6 +396,12 @@ 'browser/extensions/api/runtime/chrome_runtime_api_delegate.h', 'browser/extensions/api/screenlock_private/screenlock_private_api.cc', 'browser/extensions/api/screenlock_private/screenlock_private_api.h', + 'browser/extensions/api/search_engines_private/search_engines_private_api.cc', + 'browser/extensions/api/search_engines_private/search_engines_private_api.h', + 'browser/extensions/api/search_engines_private/search_engines_private_event_router.cc', + 'browser/extensions/api/search_engines_private/search_engines_private_event_router.h', + 'browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.cc', + 'browser/extensions/api/search_engines_private/search_engines_private_event_router_factory.h', 'browser/extensions/api/sessions/session_id.cc', 'browser/extensions/api/sessions/session_id.h', 'browser/extensions/api/sessions/sessions_api.cc',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 3331795..c366e153c 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi
@@ -967,6 +967,8 @@ 'browser/ui/cocoa/extensions/browser_actions_container_view.mm', 'browser/ui/cocoa/extensions/browser_actions_controller.h', 'browser/ui/cocoa/extensions/browser_actions_controller.mm', + 'browser/ui/cocoa/extensions/bundle_util.h', + 'browser/ui/cocoa/extensions/bundle_util.mm', 'browser/ui/cocoa/extensions/device_permissions_dialog_controller.h', 'browser/ui/cocoa/extensions/device_permissions_dialog_controller.mm', 'browser/ui/cocoa/extensions/device_permissions_view_controller.h', @@ -1445,6 +1447,14 @@ 'chrome_browser_ui_media_router_sources': [ 'browser/ui/toolbar/media_router_action.h', 'browser/ui/toolbar/media_router_action.cc', + 'browser/ui/webui/media_router/media_cast_mode.cc', + 'browser/ui/webui/media_router/media_cast_mode.h', + 'browser/ui/webui/media_router/media_sink_with_cast_modes.cc', + 'browser/ui/webui/media_router/media_sink_with_cast_modes.h', + 'browser/ui/webui/media_router/media_router_localized_strings_provider.cc', + 'browser/ui/webui/media_router/media_router_localized_strings_provider.h', + 'browser/ui/webui/media_router/media_router_resources_provider.cc', + 'browser/ui/webui/media_router/media_router_resources_provider.h', ], 'chrome_browser_ui_non_mac_sources': [ 'browser/ui/web_contents_sizer.cc', @@ -3129,6 +3139,9 @@ 'sources': [ '<@(chrome_browser_ui_google_now_non_android_sources)' ], }], ['enable_media_router==1', { + 'dependencies': [ + 'browser/media/router/media_router.gyp:media_router', + ], 'sources': [ '<@(chrome_browser_ui_media_router_sources)' ], }], ['enable_supervised_users==0', { @@ -3165,6 +3178,7 @@ ['OS!="android" and OS!="ios"', { 'dependencies': [ '../components/components.gyp:feedback_proto', + '../components/components.gyp:proximity_auth_webui', '../device/bluetooth/bluetooth.gyp:device_bluetooth', '../third_party/libusb/libusb.gyp:libusb', ],
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi index 7faa5e6..73e94be 100644 --- a/chrome/chrome_common.gypi +++ b/chrome/chrome_common.gypi
@@ -85,8 +85,6 @@ 'common/multi_process_lock_linux.cc', 'common/multi_process_lock_mac.cc', 'common/multi_process_lock_win.cc', - 'common/origin_util.cc', - 'common/origin_util.h', 'common/omnibox_focus_state.h', 'common/partial_circular_buffer.cc', 'common/partial_circular_buffer.h', @@ -147,8 +145,6 @@ 'common/extensions/api/spellcheck/spellcheck_handler.h', 'common/extensions/api/storage/storage_schema_manifest_handler.cc', 'common/extensions/api/storage/storage_schema_manifest_handler.h', - 'common/extensions/api/supervised_user_private/supervised_user_handler.cc', - 'common/extensions/api/supervised_user_private/supervised_user_handler.h', 'common/extensions/api/system_indicator/system_indicator_handler.cc', 'common/extensions/api/system_indicator/system_indicator_handler.h', 'common/extensions/api/url_handlers/url_handlers_parser.cc',
diff --git a/chrome/chrome_exe.gypi b/chrome/chrome_exe.gypi index 6c3c0ba1..11a42f3 100644 --- a/chrome/chrome_exe.gypi +++ b/chrome/chrome_exe.gypi
@@ -316,18 +316,8 @@ # Unique dir to write to so the [lang].lproj/InfoPlist.strings # for the main app and the helper app don't name collide. 'output_path': '<(INTERMEDIATE_DIR)/app_infoplist_strings', + 'branding_name': '<(branding_path_component)_strings', }, - 'conditions': [ - [ 'branding == "Chrome"', { - 'variables': { - 'branding_name': 'google_chrome_strings', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_name': 'chromium_strings', - }, - }], - ], 'inputs': [ '<(tool_path)', '<(version_path)',
diff --git a/chrome/chrome_installer.gypi b/chrome/chrome_installer.gypi index b3e1a17..dc976c5 100644 --- a/chrome/chrome_installer.gypi +++ b/chrome/chrome_installer.gypi
@@ -6,7 +6,8 @@ 'variables': { 'lastchange_path': '../build/util/LASTCHANGE', 'libpeer_target_type%': 'static_library', - # 'branding_dir' is set in the 'conditions' section at the bottom. + 'branding_dir': 'app/theme/<(branding_path_component)', + 'branding_dir_100': 'app/theme/default_100_percent/<(branding_path_component)', }, 'conditions': [ ['OS=="win"', { @@ -158,18 +159,9 @@ 'action_name': 'installer_util_strings', 'variables': { 'create_string_rc_py': 'installer/util/prebuild/create_string_rc.py', + 'brand_strings': '<(branding_path_component)_strings', }, - 'conditions': [ - ['branding=="Chrome"', { - 'variables': { - 'brand_strings': 'google_chrome_strings', - }, - }, { - 'variables': { - 'brand_strings': 'chromium_strings', - }, - }], - ], + 'inputs': [ '<(create_string_rc_py)', 'app/<(brand_strings).grd', @@ -193,6 +185,7 @@ }, }, { + # GN version: //chrome/installer/launcher_support 'target_name': 'launcher_support', 'type': 'static_library', 'include_dirs': [ @@ -300,24 +293,6 @@ }, ], 'conditions': [ - # TODO(mark): <(branding_dir) should be defined by the - # global condition block at the bottom of the file, but - # this doesn't work due to the following issue: - # - # http://code.google.com/p/gyp/issues/detail?id=22 - # - # Remove this block once the above issue is fixed. - [ 'branding == "Chrome"', { - 'variables': { - 'branding_dir': 'app/theme/google_chrome', - 'branding_dir_100': 'app/theme/default_100_percent/google_chrome', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_dir': 'app/theme/chromium', - 'branding_dir_100': 'app/theme/default_100_percent/chromium', - }, - }], ['target_arch=="ia32"', { 'msvs_settings': { 'VCCLCompilerTool': { @@ -1091,16 +1066,5 @@ }, ], # targets }], # OS=="mac" - [ 'branding == "Chrome"', { - 'variables': { - 'branding_dir': 'app/theme/google_chrome', - 'branding_dir_100': 'app/theme/default_100_percent/google_chrome', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_dir': 'app/theme/chromium', - 'branding_dir_100': 'app/theme/default_100_percent/chromium', - }, - }], ], }
diff --git a/chrome/chrome_installer_util.gypi b/chrome/chrome_installer_util.gypi index 8c9d875..ba1698b 100644 --- a/chrome/chrome_installer_util.gypi +++ b/chrome/chrome_installer_util.gypi
@@ -107,6 +107,7 @@ ['OS=="win"', { 'targets': [ { + # GN version: //chrome/installer/util 'target_name': 'installer_util', 'type': 'static_library', 'variables': {
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index 74ed87a..56bb402 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi
@@ -40,8 +40,6 @@ 'renderer/plugins/plugin_uma.h', 'renderer/plugins/shadow_dom_plugin_placeholder.cc', 'renderer/plugins/shadow_dom_plugin_placeholder.h', - 'renderer/prefetch_helper.cc', - 'renderer/prefetch_helper.h', 'renderer/prerender/prerender_dispatcher.cc', 'renderer/prerender/prerender_dispatcher.h', 'renderer/prerender/prerender_extra_data.cc',
diff --git a/chrome/chrome_shell.gypi b/chrome/chrome_shell.gypi index b614ff3..6ff6f3d7 100644 --- a/chrome/chrome_shell.gypi +++ b/chrome/chrome_shell.gypi
@@ -55,11 +55,6 @@ 'dependencies': [ 'libchromeshell_base', ], - 'includes': [ - # File 'protection' is based on non-trivial linker magic. TODO(pasko): - # remove it when crbug.com/424562 is fixed. - '../base/files/protect_file_posix.gypi', - ], }, { # GN: //chrome/android:chrome_sync_shell
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 190001f..8c21609e 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi
@@ -188,6 +188,7 @@ 'browser/extensions/api/proxy/proxy_apitest.cc', 'browser/extensions/api/reading_list_private/reading_list_private_apitest.cc', 'browser/extensions/api/screenlock_private/screenlock_private_apitest.cc', + 'browser/extensions/api/search_engines_private/search_engines_private_apitest.cc', 'browser/extensions/api/sessions/sessions_apitest.cc', 'browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc', 'browser/extensions/api/settings_private/settings_private_apitest.cc', @@ -349,6 +350,7 @@ 'browser/net/websocket_browsertest.cc', 'browser/password_manager/password_manager_browsertest.cc', 'browser/pdf/pdf_extension_test.cc', + 'browser/plugins/plugin_power_saver_browsertest.cc', 'browser/prefetch/prefetch_browsertest.cc', 'browser/prefs/pref_functional_browsertest.cc', 'browser/prefs/pref_service_browsertest.cc', @@ -758,6 +760,7 @@ 'browser/chromeos/shutdown_policy_browsertest.cc', 'browser/chromeos/system/device_disabling_browsertest.cc', 'browser/chromeos/system/tray_accessibility_browsertest.cc', + 'browser/download/notification/download_notification_browsertest.cc', 'browser/extensions/api/vpn_provider/vpn_provider_apitest.cc', 'browser/ui/webui/options/chromeos/accounts_options_browsertest.cc', 'browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc', @@ -2002,6 +2005,7 @@ '../ui/web_dialogs/web_dialogs.gyp:web_dialogs_test_support', '../v8/tools/gyp/v8.gyp:v8', # Runtime dependencies + '../ppapi/ppapi_internal.gyp:power_saver_test_plugin', '../ppapi/ppapi_internal.gyp:ppapi_tests', '../remoting/remoting.gyp:remoting_browser_test_resources', '../remoting/remoting.gyp:remoting_webapp_unittests', @@ -2106,7 +2110,6 @@ '../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_media_galleries', '../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_packaged_app', '../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_socket_permissions', - '../ppapi/ppapi_tests_mojo.gyp:ppapi_tests_mojo', ], 'conditions': [ ['chromeos==1', { @@ -2935,6 +2938,8 @@ '../components/components.gyp:precache_javatests', '../content/content_shell_and_tests.gyp:content_java_test_support', '../sync/sync.gyp:sync_javatests', + '../testing/android/on_device_instrumentation.gyp:broker_java', + '../testing/android/on_device_instrumentation.gyp:require_driver_apk', '../ui/android/ui_android.gyp:ui_javatests', ], 'variables': {
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index a5ac421..5e6b6fd5 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi
@@ -60,10 +60,10 @@ 'browser/chrome_elf_init_unittest_win.cc', 'browser/chrome_process_singleton_win_unittest.cc', 'browser/command_updater_unittest.cc', - 'browser/component_updater/test/chrome_component_updater_configurator_unittest.cc', - 'browser/component_updater/test/cld_component_installer_unittest.cc', - 'browser/component_updater/test/component_updater_service_unittest.cc', - 'browser/component_updater/test/supervised_user_whitelist_installer_unittest.cc', + 'browser/component_updater/chrome_component_updater_configurator_unittest.cc', + 'browser/component_updater/cld_component_installer_unittest.cc', + 'browser/component_updater/component_updater_service_unittest.cc', + 'browser/component_updater/supervised_user_whitelist_installer_unittest.cc', 'browser/content_settings/content_settings_default_provider_unittest.cc', 'browser/content_settings/content_settings_mock_observer.cc', 'browser/content_settings/content_settings_mock_observer.h', @@ -416,7 +416,6 @@ 'browser/ui/cocoa/extensions/extension_install_view_controller_unittest.mm', 'browser/ui/cocoa/extensions/extension_installed_bubble_controller_unittest.mm', 'browser/ui/cocoa/extensions/media_galleries_dialog_cocoa_unittest.mm', - 'browser/ui/cocoa/extensions/test_toolbar_actions_bar_helper_cocoa.mm', 'browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac_unittest.mm', 'browser/ui/cocoa/find_bar/find_bar_bridge_unittest.mm', 'browser/ui/cocoa/find_bar/find_bar_cocoa_controller_unittest.mm', @@ -559,7 +558,6 @@ 'common/mac/mock_launchd.cc', 'common/mac/mock_launchd.h', 'common/mac/objc_zombie_unittest.mm', - 'common/origin_util_unittest.cc', 'common/partial_circular_buffer_unittest.cc', 'common/pref_names_util_unittest.cc', 'common/search_urls_unittest.cc', @@ -1072,7 +1070,7 @@ 'browser/ui/autofill/mock_autofill_dialog_view_delegate.h', ], 'chrome_unit_tests_plugins_sources': [ - 'browser/component_updater/test/component_installers_unittest.cc', + 'browser/component_updater/component_installers_unittest.cc', 'browser/metrics/plugin_metrics_provider_unittest.cc', 'browser/plugins/plugin_finder_unittest.cc', 'browser/plugins/plugin_info_message_filter_unittest.cc', @@ -1372,7 +1370,6 @@ 'browser/ui/views/tabs/tab_strip_unittest.cc', 'browser/ui/views/tabs/tab_unittest.cc', 'browser/ui/views/toolbar/reload_button_unittest.cc', - 'browser/ui/views/toolbar/test_toolbar_actions_bar_helper_views.cc', 'browser/ui/views/toolbar/toolbar_action_view_unittest.cc', 'browser/ui/views/translate/translate_bubble_view_unittest.cc', 'browser/ui/views/validation_message_bubble_delegate_unittest.cc', @@ -1514,7 +1511,6 @@ 'browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc', 'browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.cc', 'browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.h', - 'browser/ui/toolbar/test_toolbar_actions_bar_helper.h', 'browser/ui/toolbar/test_toolbar_model.cc', 'browser/ui/toolbar/test_toolbar_model.h', 'browser/ui/toolbar/toolbar_actions_bar_unittest.cc', @@ -1523,6 +1519,7 @@ 'browser/ui/toolbar/wrench_menu_model_unittest.cc', 'browser/ui/website_settings/permission_menu_model_unittest.cc', 'browser/ui/webui/help/version_updater_chromeos_unittest.cc', + 'browser/ui/webui/media_router/media_cast_mode_unittest.cc', 'browser/ui/webui/ntp/ntp_user_data_logger_unittest.cc', 'browser/ui/webui/ntp/suggestions_combiner_unittest.cc', 'browser/ui/webui/options/autofill_options_handler_unittest.cc', @@ -1687,10 +1684,10 @@ 'browser/sessions/session_restore_test_helper.h', 'browser/sessions/session_service_test_helper.cc', 'browser/sessions/session_service_test_helper.h', - 'browser/signin/fake_account_reconcilor.cc', - 'browser/signin/fake_account_reconcilor.h', 'browser/signin/fake_account_tracker_service.cc', 'browser/signin/fake_account_tracker_service.h', + 'browser/signin/fake_gaia_cookie_manager_service.cc', + 'browser/signin/fake_gaia_cookie_manager_service.h', 'browser/signin/fake_profile_oauth2_token_service.cc', 'browser/signin/fake_profile_oauth2_token_service.h', 'browser/signin/fake_profile_oauth2_token_service_builder.cc',
diff --git a/chrome/chrome_watcher/BUILD.gn b/chrome/chrome_watcher/BUILD.gn index db5f5e8..1a67b22 100644 --- a/chrome/chrome_watcher/BUILD.gn +++ b/chrome/chrome_watcher/BUILD.gn
@@ -32,6 +32,7 @@ deps = [ ":chrome_watcher_resources", ":client", + "//chrome/installer/util", "//base", "//components/browser_watcher", ]
diff --git a/chrome/chrome_watcher/DEPS b/chrome/chrome_watcher/DEPS index 9b1e8bd..d7f54021 100644 --- a/chrome/chrome_watcher/DEPS +++ b/chrome/chrome_watcher/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+base", + "+chrome/installer/util", "+components/browser_watcher", "+syzygy/kasko/api", ]
diff --git a/chrome/chrome_watcher/chrome_watcher.gypi b/chrome/chrome_watcher/chrome_watcher.gypi index 8a4eaf3..9836501 100644 --- a/chrome/chrome_watcher/chrome_watcher.gypi +++ b/chrome/chrome_watcher/chrome_watcher.gypi
@@ -61,6 +61,7 @@ 'dependencies': [ 'chrome_watcher_client', 'chrome_watcher_resources', + 'installer_util', '../base/base.gyp:base', '../components/components.gyp:browser_watcher', ],
diff --git a/chrome/chrome_watcher/chrome_watcher_main.cc b/chrome/chrome_watcher/chrome_watcher_main.cc index 54da49cb..c6db791 100644 --- a/chrome/chrome_watcher/chrome_watcher_main.cc +++ b/chrome/chrome_watcher/chrome_watcher_main.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" +#include "base/file_version_info.h" #include "base/files/file_path.h" #include "base/logging_win.h" #include "base/macros.h" @@ -17,12 +18,17 @@ #include "base/process/process.h" #include "base/run_loop.h" #include "base/sequenced_task_runner.h" +#include "base/strings/string16.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" +#include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/template_util.h" #include "base/threading/thread.h" #include "base/time/time.h" #include "base/win/scoped_handle.h" #include "chrome/chrome_watcher/chrome_watcher_main_api.h" +#include "chrome/installer/util/util_constants.h" #include "components/browser_watcher/endsession_watcher_window_win.h" #include "components/browser_watcher/exit_code_watcher_win.h" #include "components/browser_watcher/exit_funnel_win.h" @@ -201,6 +207,7 @@ void OnWindowEvent( const base::string16& registry_path, base::Process process, + const base::Callback<void(const base::Process&)>& on_hung_callback, browser_watcher::WindowHangMonitor::WindowEvent window_event) { browser_watcher::ExitFunnel exit_funnel; if (exit_funnel.Init(registry_path.c_str(), process.Handle())) { @@ -210,6 +217,8 @@ break; case browser_watcher::WindowHangMonitor::WINDOW_HUNG: exit_funnel.RecordEvent(L"MessageWindowHung"); + if (!on_hung_callback.is_null()) + on_hung_callback.Run(process); break; case browser_watcher::WindowHangMonitor::WINDOW_VANISHED: exit_funnel.RecordEvent(L"MessageWindowVanished"); @@ -221,6 +230,53 @@ } } +#ifdef KASKO +void DumpHungBrowserProcess(const base::string16& channel, + const base::Process& process) { + // TODO(erikwright): Rather than recreating these crash keys here, it would be + // ideal to read them directly from the browser process. + + // This is looking up the version of chrome_watcher.dll, which is equivalent + // for our purposes to chrome.dll. + scoped_ptr<FileVersionInfo> version_info( + FileVersionInfo::CreateFileVersionInfoForModule( + reinterpret_cast<HMODULE>(&__ImageBase))); + using CrashKeyStrings = std::pair<base::string16, base::string16>; + std::vector<CrashKeyStrings> crash_key_strings; + if (version_info.get()) { + crash_key_strings.push_back( + CrashKeyStrings(L"prod", version_info->product_short_name())); + base::string16 version = version_info->product_version(); + if (!version_info->is_official_build()) + version.append(base::ASCIIToUTF16("-devel")); + crash_key_strings.push_back(CrashKeyStrings(L"ver", version)); + } else { + // No version info found. Make up the values. + crash_key_strings.push_back(CrashKeyStrings(L"prod", L"Chrome")); + crash_key_strings.push_back(CrashKeyStrings(L"ver", L"0.0.0.0-devel")); + } + crash_key_strings.push_back(CrashKeyStrings(L"channel", channel)); + crash_key_strings.push_back(CrashKeyStrings(L"plat", L"Win32")); + crash_key_strings.push_back(CrashKeyStrings(L"ptype", L"browser")); + crash_key_strings.push_back( + CrashKeyStrings(L"pid", base::IntToString16(process.Pid()))); + crash_key_strings.push_back(CrashKeyStrings(L"hung-process", L"1")); + + std::vector<const base::char16*> key_buffers; + std::vector<const base::char16*> value_buffers; + for (auto& strings : crash_key_strings) { + key_buffers.push_back(strings.first.c_str()); + value_buffers.push_back(strings.second.c_str()); + } + key_buffers.push_back(nullptr); + value_buffers.push_back(nullptr); + // TODO(erikwright): Make the dump-type channel-dependent. + kasko::api::SendReportForProcess(process.Handle(), + kasko::api::LARGER_DUMP_TYPE, + key_buffers.data(), value_buffers.data()); +} +#endif // KASKO + } // namespace // The main entry point to the watcher, declared as extern "C" to avoid name @@ -229,7 +285,8 @@ HANDLE process_handle, HANDLE on_initialized_event_handle, const base::char16* browser_data_directory, - const base::char16* message_window_name) { + const base::char16* message_window_name, + const base::char16* channel_name) { base::Process process(process_handle); base::win::ScopedHandle on_initialized_event(on_initialized_event_handle); @@ -244,6 +301,8 @@ // chrome.exe in order to report its exit status. ::SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY); + base::Callback<void(const base::Process&)> on_hung_callback; + #ifdef KASKO bool launched_kasko = kasko::api::InitializeReporter( GetKaskoEndpoint(process.Pid()).c_str(), @@ -256,6 +315,10 @@ .Append(kPermanentlyFailedReportsSubdir) .value() .c_str()); + if (launched_kasko && + base::StringPiece16(channel_name) == installer::kChromeChannelCanary) { + on_hung_callback = base::Bind(&DumpHungBrowserProcess, channel_name); + } #endif // KASKO // Run a UI message loop on the main thread. @@ -269,13 +332,16 @@ return 1; } - browser_watcher::WindowHangMonitor hang_monitor( - base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(20), - base::Bind(&OnWindowEvent, registry_path, - base::Passed(process.Duplicate()))); - hang_monitor.Initialize(process.Duplicate(), message_window_name); + { + // Scoped to force |hang_monitor| destruction before Kasko is shut down. + browser_watcher::WindowHangMonitor hang_monitor( + base::TimeDelta::FromSeconds(60), base::TimeDelta::FromSeconds(20), + base::Bind(&OnWindowEvent, registry_path, + base::Passed(process.Duplicate()), on_hung_callback)); + hang_monitor.Initialize(process.Duplicate(), message_window_name); - run_loop.Run(); + run_loop.Run(); + } #ifdef KASKO if (launched_kasko)
diff --git a/chrome/chrome_watcher/chrome_watcher_main_api.h b/chrome/chrome_watcher/chrome_watcher_main_api.h index 82cebdb6..d070a57 100644 --- a/chrome/chrome_watcher/chrome_watcher_main_api.h +++ b/chrome/chrome_watcher/chrome_watcher_main_api.h
@@ -26,12 +26,15 @@ // reports. |on_initialized_event| will be signaled once the watcher process is // fully initialized. Takes ownership of |parent_process| and // |on_initialized_event|. +// |channel_name| is the current Chrome distribution channel (one of +// installer::kChromeChannelXXX). typedef int (*ChromeWatcherMainFunction)( const base::char16* registry_path, HANDLE parent_process, HANDLE on_initialized_event, const base::char16* browser_data_directory, - const base::char16* message_window_name); + const base::char16* message_window_name, + const base::char16* channel_name); // Returns an RPC endpoint name for the identified client process. This method // may be invoked in both the client and the watcher process with the PID of the
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc index b705da1..854f7e5a 100644 --- a/chrome/common/chrome_content_client.cc +++ b/chrome/common/chrome_content_client.cc
@@ -551,3 +551,14 @@ return false; } #endif + +void ChromeContentClient::AddSecureSchemesAndOrigins( + std::set<std::string>* schemes, + std::set<GURL>* origins) { + schemes->insert(content::kChromeUIScheme); + schemes->insert(extensions::kExtensionScheme); + schemes->insert(extensions::kExtensionResourceScheme); + + // TODO(kinuko): Handle command-line options for whitelisting + // insecure origins. crbug.com/441605 +}
diff --git a/chrome/common/chrome_content_client.h b/chrome/common/chrome_content_client.h index 9e76754e..67507d9 100644 --- a/chrome/common/chrome_content_client.h +++ b/chrome/common/chrome_content_client.h
@@ -72,6 +72,9 @@ int sandbox_type, int* sandbox_profile_resource_id) const override; #endif + + void AddSecureSchemesAndOrigins(std::set<std::string>* schemes, + std::set<GURL>* origins) override; }; #endif // CHROME_COMMON_CHROME_CONTENT_CLIENT_H_
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index fe6b9416..d0209ee4 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -64,11 +64,11 @@ // URLs. This provides an override to get the old insecure behavior. const char kAllowRunningInsecureContent[] = "allow-running-insecure-content"; -// Specifies the threshold to be used when determining of an Alternate-Protocol -// advertisement will be honored. If the advertised probability is larger -// than the threshold, then it will be honored. -const char kAlternateProtocolProbabilityThreshold[] = - "alternate-protocol-probability-threshold"; +// Specifies the probability threshold for alternative services: an advertised +// alternative service will only be honored if the advertised probability is +// greater than or equal to this threshold. +const char kAlternativeServiceProbabilityThreshold[] = + "alternative-service-probability-threshold"; // Prevents Chrome from requiring authorization to run certain widely installed // but less commonly used plugins.
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index e12d932..a4547fc1 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -33,7 +33,7 @@ extern const char kAllowInsecureLocalhost[]; extern const char kAllowOutdatedPlugins[]; extern const char kAllowRunningInsecureContent[]; -extern const char kAlternateProtocolProbabilityThreshold[]; +extern const char kAlternativeServiceProbabilityThreshold[]; extern const char kAlwaysAuthorizePlugins[]; extern const char kAppId[]; extern const char kApp[]; @@ -321,6 +321,7 @@ extern const char kTryChromeAgain[]; extern const char kUninstall[]; extern const char kUnlimitedStorage[]; +extern const char kUnsafetyTreatInsecureOriginAsSecure[]; extern const char kUseSimpleCacheBackend[]; extern const char kUseSpdy[]; extern const char kUserAgent[];
diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h index 970cbbd..7289083 100644 --- a/chrome/common/common_message_generator.h +++ b/chrome/common/common_message_generator.h
@@ -7,7 +7,6 @@ #include "chrome/common/benchmarking_messages.h" #include "chrome/common/chrome_utility_messages.h" #include "chrome/common/mac/app_shim_messages.h" -#include "chrome/common/prefetch_messages.h" #include "chrome/common/prerender_messages.h" #include "chrome/common/render_messages.h" #include "chrome/common/tts_messages.h"
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json index c8b4fc6..43759a6f 100644 --- a/chrome/common/extensions/api/_api_features.json +++ b/chrome/common/extensions/api/_api_features.json
@@ -84,6 +84,18 @@ "dependencies": ["permission:audioModem"], "contexts": ["blessed_extension"] }, + "autofillPrivate": [{ + "dependencies": ["permission:autofillPrivate"], + "contexts": ["blessed_extension"] + }, { + "channel": "trunk", + "contexts": ["webui"], + "matches": [ + "chrome://md-settings/*", + "chrome://settings/*", + "chrome://settings-frame/*" + ] + }], "automationInternal": { "internal": true, "dependencies": ["manifest:automation"], @@ -495,6 +507,10 @@ "dependencies": ["permission:inputMethodPrivate"], "contexts": ["blessed_extension"] }, + "instanceID": { + "dependencies": ["permission:gcm"], + "contexts": ["blessed_extension"] + }, "launcherPage": { "dependencies": ["manifest:launcher_page"], "contexts": ["blessed_extension"] @@ -619,6 +635,18 @@ "dependencies": ["permission:rtcPrivate"], "contexts": ["blessed_extension"] }, + "searchEnginesPrivate": [{ + "dependencies": ["permission:searchEnginesPrivate"], + "contexts": ["blessed_extension"] + }, { + "channel": "trunk", + "contexts": ["webui"], + "matches": [ + "chrome://md-settings/*", + "chrome://settings/*", + "chrome://settings-frame/*" + ] + }], "sessions": { "dependencies": ["permission:sessions"], "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json index de15be2..d6eb23f 100644 --- a/chrome/common/extensions/api/_permission_features.json +++ b/chrome/common/extensions/api/_permission_features.json
@@ -66,6 +66,11 @@ ] } ], + "autofillPrivate": { + "channel": "trunk", + "extension_types": ["extension", "platform_app"], + "location": "component" + }, "autotestPrivate": { "channel": "stable", "extension_types": ["extension", "legacy_packaged_app"], @@ -869,6 +874,11 @@ "extension_types": ["platform_app"], "location": "component" }, + "searchEnginesPrivate": { + "channel": "trunk", + "extension_types": ["extension", "platform_app"], + "location": "component" + }, "screensaver": { "channel": "stable", "extension_types": ["legacy_packaged_app", "hosted_app", "platform_app"]
diff --git a/chrome/common/extensions/api/autofill_private.idl b/chrome/common/extensions/api/autofill_private.idl new file mode 100644 index 0000000..51124d99 --- /dev/null +++ b/chrome/common/extensions/api/autofill_private.idl
@@ -0,0 +1,214 @@ +// 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. + +// Use the <code>chrome.autofillPrivate</code> API to add, remove, or update +// autofill data from the settings UI. +namespace autofillPrivate { + // Fields used as part of an address. + enum AddressField { + FULL_NAME, + COMPANY_NAME, + ADDRESS_LINES, + ADDRESS_LEVEL_1, + ADDRESS_LEVEL_2, + ADDRESS_LEVEL_3, + POSTAL_CODE, + SORTING_CODE, + COUNTRY_CODE + }; + + // Metadata about an autofill entry (address or credit card) which is used to + // render a summary list of all entries. + dictionary AutofillMetadata { + // Short summary of the address which is displayed in the UI; an + // undefined value means that this entry has just been created on the client + // and has not yet been given a summary. + DOMString summaryLabel; + + // Short, secondary summary of the address which is displalyed in the UI; an + // undefined value means that this entry has just been created on the client + // and has not yet been given a summary. + DOMString? summarySublabel; + + // Whether the entry is locally owned by Chrome (as opposed to being a + // profile synced down from the server). Non-local entries may not be + // editable. + boolean? isLocal; + + // For credit cards, whether this is a full copy of the card + boolean? isCached; + }; + + // An address entry which can be saved in the autofill section of the + // settings UI. + dictionary AddressEntry { + // Globally unique identifier for this entry. + DOMString? guid; + + DOMString[]? fullNames; + + DOMString? companyName; + + // Street address (multiple lines, newlines preserved). + DOMString? addressLines; + + // The broadest administrative level in the address, i.e. the province + // within which the locality is found; for example, in the US, this would be + // the state; in Switzerland it would be the canton; in the UK, the post + // town. + DOMString? addressLevel1; + + // The second administrative level, in addresses with two or more + // administrative levels; in the countries with two administrative levels, + // this would typically be the city, town, village, or other locality within + // which the relevant street address is found. + DOMString? addressLevel2; + + // The third administrative level, in addresses with three or more + // administrative levels. + DOMString? addressLevel3; + + // Postal code, post code, ZIP code, CEDEX code (if CEDEX, append "CEDEX", + // and the arrondissement, if relevant, to the address-level2 field). + DOMString? postalCode; + + // A sorting code is similar to a postal code. However, whereas a postal + // code normally refers to a single geographical location, a sorting code + // often does not. Instead, a sorting code is assigned to an organization, + // which might be geographically distributed. The most prominent example of + // a sorting code system is CEDEX in France. + DOMString? sortingCode; + + DOMString? country; + + DOMString[]? phoneNumbers; + + DOMString[]? emailAddresses; + + DOMString? languageCode; + + AutofillMetadata? metadata; + }; + + // A component to be shown in an address editor. Different countries have + // different components to their addresses. + dictionary AddressComponent { + // The type of field that this is. + AddressField field; + + // The name of the field. + DOMString fieldName; + + // A hint for the UI regarding whether the input is likely to be long. + boolean isLongField; + }; + + // The address components for a given country code. Each entry in |components| + // constitutes a row in the UI, while each inner array contains the list of + // components to use in that row. For example, city, state, and zip code are + // all included on the same line for US addresses. This dictionary also + // includes the associated language code. + dictionary AddressComponents { + // The components. + AddressComponent[][] components; + + // The language code. + DOMString languageCode; + }; + + // A credit card entry which can be saved in the autofill section of the + // settings UI. + dictionary CreditCardEntry { + // Globally unique identifier for this entry. + DOMString? guid; + + // Name of the person who owns the credit card. + DOMString? name; + + // Credit card number. + DOMString? cardNumber; + + // Month as 2-character string ("01" = January, "12" = December). + DOMString? expirationMonth; + + // Year as a 4-character string (as in "2015"). + DOMString? expirationYear; + + AutofillMetadata? metadata; + }; + + // Parameters to be passed to validatePhoneNumbers(). + dictionary ValidatePhoneParams { + // The phone numbers to validate. + DOMString[] phoneNumbers; + + // The index into |phoneNumbers| at which the newly-added/edited phone + // number resides. + long indexOfNewNumber; + + // The country code for the numbers. + DOMString countryCode; + }; + + callback GetAddressComponentsCallback = + void(AddressComponents components); + callback ValidatePhoneNumbersCallback = + void(DOMString[] validatedPhoneNumbers); + + interface Functions { + // Saves the given address. If |address| has an empty string as its ID, it + // will be assigned a new one and added as a new entry. + // + // |address|: The address entry to save. + static void saveAddress(AddressEntry address); + + // Gets the address components for a given country code. + // + // |countryCode|: The country code for which to fetch the components. + // |callback|: Callback which will be called with components. + static void getAddressComponents(DOMString countryCode, + GetAddressComponentsCallback callback); + + // Saves the given credit card. If |card| has an empty string as its + // ID, it will be assigned a new one and added as a new entry. + // + // |card|: The card entry to save. + static void saveCreditCard(CreditCardEntry card); + + // Removes the entry (address or credit card) with the given ID. + // + // |guid|: ID of the entry to remove. + static void removeEntry(DOMString guid); + + // Validates a newly-added phone number and invokes the callback with a list + // of validated numbers. Note that if the newly-added number was invalid, it + // will not be returned in the list of valid numbers. + // + // |params|: The parameters to this function. + // |callback|: Callback which will be called with validated phone numbers. + static DOMString[] validatePhoneNumbers(ValidatePhoneParams params, + ValidatePhoneNumbersCallback callback); + + // Clears the data associated with a wallet card which was saved + // locally so that the saved copy is masked (e.g., "Card ending + // in 1234"). + // + // |guid|: GUID of the credit card to mask. + static void maskCreditCard(DOMString guid); + }; + + interface Events { + // Fired when the address list has changed, meaning that an entry has been + // added, removed, or changed. + // + // |entries| The updated list of entries. + static void onAddressListChanged(AddressEntry[] entries); + + // Fired when the credit card list has changed, meaning that an entry has + // been added, removed, or changed. + // + // |entries| The updated list of entries. + static void onCreditCardListChanged(CreditCardEntry[] entries); + }; +};
diff --git a/chrome/common/extensions/api/gcd_private.idl b/chrome/common/extensions/api/gcd_private.idl index 36e8a9af..9f275f3 100644 --- a/chrome/common/extensions/api/gcd_private.idl +++ b/chrome/common/extensions/api/gcd_private.idl
@@ -91,9 +91,9 @@ // |sessionId| : The session ID (identifies the session for future calls). // |status| : The status of operation (success or type of error). // |pairingTypes| is the list of supported pairing types. - callback EstablishSessionCallback = void(long sessionId, - Status status, - PairingType[] pairingTypes); + callback CreateSessionCallback = void(long sessionId, + Status status, + PairingType[] pairingTypes); // Called when the response to the message sent is available or on error. // |status| : The status of operation (success or type of error). @@ -129,19 +129,10 @@ // Get the list of SSIDs with prefetched callbacks. static void getPrefetchedWifiNameList(SSIDListCallback callback); - // Deprecated. Establish the session. - // TODO(vitalybuka): Remove after uptate of apps using this. - // http://crbug.com/461504 - // |ipAddress| : The IPv4 or IPv6 address of the device. - // |port| : The port with Privet HTTP server. - static void establishSession(DOMString ipAddress, - long port, - EstablishSessionCallback callback); - // Create new pairing. // |serviceName| : The mDns service name of the device. static void createSession(DOMString serviceName, - EstablishSessionCallback callback); + CreateSessionCallback callback); // Start pairing with selected method. Should be called after // |establishSession|.
diff --git a/chrome/common/extensions/api/instance_id.idl b/chrome/common/extensions/api/instance_id.idl new file mode 100644 index 0000000..8ed0e7a9 --- /dev/null +++ b/chrome/common/extensions/api/instance_id.idl
@@ -0,0 +1,89 @@ +// 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. + +// Use the <code>chrome.instanceID</code> API to access the InstanceID service. +namespace instanceID { + // Parameters for getToken. + dictionary GetTokenParams { + // Identifies the entity that is authorized to access resources associated + // with this Instance ID. It can be another Instance ID or a project ID. + DOMString audience; + + // Identifies authorized actions that the authorized entity can take. + // E.g. for sending GCM messages, <code>GCM</code> scope should be used. + DOMString scope; + + // Allows including a small number of string key/value pairs that will be + // associated with the token and may be used in processing the request. + object? options; + }; + + // Parameters for deleteToken. + dictionary DeleteTokenParams { + // The audience that is passed for obtaining a token. + DOMString audience; + + // The scope that is passed for obtaining a token. + DOMString scope; + }; + + // |instanceID| : The Instance ID assigned to the app. + callback GetIDCallback = void(DOMString instanceID); + + // |creationTime| : The time when the Instance ID has been generated, + // represented in milliseconds since the epoch. + callback GetCreationTimeCallback = void(long creationTime); + + // |token| : The token assigned by the requested service. + callback GetTokenCallback = void(DOMString token); + + callback DeleteIDCallback = void(); + + callback DeleteTokenCallback = void(); + + interface Functions { + // Retrieves an identifier for the app instance. The instance ID will be + // returned by the <code>callback</code>. + // The same ID will be returned as long as the application identity has not + // been revoked or expired. + // |callback| : Function called when the retrieval completes. It should + // check $(ref:runtime.lastError) for error when instanceID is empty. + static void getID(GetIDCallback callback); + + // Retrieves the time when the InstanceID has been generated. The creation + // time will be returned by the <code>callback</code>. + // |callback| : Function called when the retrieval completes. It should + // check $(ref:runtime.lastError) for error when creationTime is zero. + static void getCreationTime(GetCreationTimeCallback callback); + + // Return a token that allows the identified audience to access the service + // defined as scope. + // |getTokenParams| : getToken parameters. + // |callback| : Function called when the retrieval completes. It should + // check $(ref:runtime.lastError) for error when token is empty. + static void getToken(GetTokenParams getTokenParams, + GetTokenCallback callback); + + // Revokes a granted token. + // |deleteTokenParams| : deleteToken parameters. + // |callback| : Function called when the deletion completes. The token + // was revoked successfully if $(ref:runtime.lastError) is not set. + static void deleteToken(DeleteTokenParams deleteTokenParams, + DeleteTokenCallback callback); + + // Resets the app instance identifier and revokes all tokens associated with + // it. + // |callback| : Function called when the deletion completes. The instance + // identifier was revoked successfully if $(ref:runtime.lastError) is + // not set. + static void deleteID(DeleteIDCallback callback); + }; + + interface Events { + // Fired when all the granted tokens need to be refreshed. The Instance ID + // also needs to be refreshed when updateID is set to true. + // |updateID| : Instance ID also needs to be refreshed. + static void onTokenRefresh(boolean updateID); + }; +};
diff --git a/chrome/common/extensions/api/schemas.gypi b/chrome/common/extensions/api/schemas.gypi index 97d39314..e36f2d2 100644 --- a/chrome/common/extensions/api/schemas.gypi +++ b/chrome/common/extensions/api/schemas.gypi
@@ -12,6 +12,7 @@ 'accessibility_private.json', 'activity_log_private.json', 'audio_modem.idl', + 'autofill_private.idl', 'automation.idl', 'automation_internal.idl', 'autotest_private.idl', @@ -39,8 +40,6 @@ 'easy_unlock_private.idl', 'experience_sampling_private.json', 'feedback_private.idl', - 'file_manager_private.idl', - 'file_manager_private_internal.idl', 'file_system.idl', 'font_settings.json', 'gcd_private.idl', @@ -53,6 +52,7 @@ 'identity_private.idl', 'image_writer_private.idl', 'inline_install_private.idl', + 'instance_id.idl', 'launcher_page.idl', 'location.idl', 'manifest_types.json', @@ -67,6 +67,7 @@ 'preferences_private.json', 'reading_list_private.json', 'screenlock_private.idl', + 'search_engines_private.idl', 'sessions.json', 'settings_private.idl', 'signed_in_devices.idl', @@ -105,6 +106,8 @@ 'enterprise_platform_keys_internal.idl', 'enterprise_platform_keys_private.json', 'file_browser_handler_internal.json', + 'file_manager_private.idl', + 'file_manager_private_internal.idl', 'file_system_provider.idl', 'file_system_provider_internal.idl', 'first_run_private.json',
diff --git a/chrome/common/extensions/api/search_engines_private.idl b/chrome/common/extensions/api/search_engines_private.idl new file mode 100644 index 0000000..b24d6e8 --- /dev/null +++ b/chrome/common/extensions/api/search_engines_private.idl
@@ -0,0 +1,36 @@ +// 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. + +// Use the <code>chrome.searchEnginesPrivate</code> API to get or set +// preferences from the settings UI. +namespace searchEnginesPrivate { + + dictionary SearchEngine { + // The unique ID of the engine in the list. + DOMString guid; + + // The name of the engine. + DOMString name; + + // Whether the engine is the selected a.k.a. "default" search engine. + boolean? isSelected; + }; + + callback SearchEnginesCallback = void (SearchEngine[] engines); + + interface Functions { + // Gets a list of the "default” search engines. + // Exactly one of the values should have default == true. + static void getDefaultSearchEngines(SearchEnginesCallback callback); + + // Sets the search engine with the given GUID as the selected default. + static void setSelectedSearchEngine(DOMString guid); + }; + + interface Events { + // Fires when the list of default search engines changes or + // when the user selects a preferred default search engine. + static void onDefaultSearchEnginesChanged(SearchEngine[] engines); + }; +};
diff --git a/chrome/common/extensions/api/supervised_user_private/supervised_user_handler.cc b/chrome/common/extensions/api/supervised_user_private/supervised_user_handler.cc deleted file mode 100644 index 486ed72..0000000 --- a/chrome/common/extensions/api/supervised_user_private/supervised_user_handler.cc +++ /dev/null
@@ -1,99 +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 "chrome/common/extensions/api/supervised_user_private/supervised_user_handler.h" - -#include "base/lazy_instance.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "extensions/common/error_utils.h" -#include "extensions/common/manifest_constants.h" - -namespace extensions { - -namespace keys = manifest_keys; - -SupervisedUserInfo::SupervisedUserInfo() { -} - -SupervisedUserInfo::~SupervisedUserInfo() { -} - -// static -bool SupervisedUserInfo::IsContentPack(const Extension* extension) { - SupervisedUserInfo* info = static_cast<SupervisedUserInfo*>( - extension->GetManifestData(keys::kContentPack)); - return info ? !info->site_list.empty() : false; -} - -// static -ExtensionResource SupervisedUserInfo::GetContentPackSiteList( - const Extension* extension) { - SupervisedUserInfo* info = static_cast<SupervisedUserInfo*>( - extension->GetManifestData(keys::kContentPack)); - return info && !info->site_list.empty() - ? extension->GetResource(info->site_list) - : ExtensionResource(); -} - -SupervisedUserHandler::SupervisedUserHandler() { -} - -SupervisedUserHandler::~SupervisedUserHandler() { -} - -bool SupervisedUserHandler::Parse(Extension* extension, base::string16* error) { - if (!extension->manifest()->HasKey(keys::kContentPack)) - return true; - - scoped_ptr<SupervisedUserInfo> info(new SupervisedUserInfo); - const base::DictionaryValue* content_pack_value = NULL; - if (!extension->manifest()->GetDictionary(keys::kContentPack, - &content_pack_value)) { - *error = base::ASCIIToUTF16(manifest_errors::kInvalidContentPack); - return false; - } - - if (!LoadSites(info.get(), content_pack_value, error) || - !LoadConfigurations(info.get(), content_pack_value, error)) { - return false; - } - - extension->SetManifestData(keys::kContentPack, info.release()); - return true; -} - -const std::vector<std::string> SupervisedUserHandler::Keys() const { - return SingleKey(keys::kContentPack); -} - -bool SupervisedUserHandler::LoadSites( - SupervisedUserInfo* info, - const base::DictionaryValue* content_pack_value, - base::string16* error) { - if (!content_pack_value->HasKey(keys::kContentPackSites)) - return true; - - base::FilePath::StringType site_list_string; - if (!content_pack_value->GetString(keys::kContentPackSites, - &site_list_string)) { - *error = base::ASCIIToUTF16(manifest_errors::kInvalidContentPackSites); - return false; - } - - info->site_list = base::FilePath(site_list_string); - - return true; -} - -bool SupervisedUserHandler::LoadConfigurations( - SupervisedUserInfo* info, - const base::DictionaryValue* content_pack_value, - base::string16* error) { - NOTIMPLEMENTED(); - return true; -} - -} // namespace extensions
diff --git a/chrome/common/extensions/api/supervised_user_private/supervised_user_handler.h b/chrome/common/extensions/api/supervised_user_private/supervised_user_handler.h deleted file mode 100644 index 6383523..0000000 --- a/chrome/common/extensions/api/supervised_user_private/supervised_user_handler.h +++ /dev/null
@@ -1,53 +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 CHROME_COMMON_EXTENSIONS_API_SUPERVISED_USER_PRIVATE_SUPERVISED_USER_HANDLER_H_ -#define CHROME_COMMON_EXTENSIONS_API_SUPERVISED_USER_PRIVATE_SUPERVISED_USER_HANDLER_H_ - -#include <string> - -#include "base/files/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "extensions/common/extension.h" -#include "extensions/common/extension_resource.h" -#include "extensions/common/manifest.h" -#include "extensions/common/manifest_handler.h" - -namespace extensions { - -struct SupervisedUserInfo : public Extension::ManifestData { - SupervisedUserInfo(); - ~SupervisedUserInfo() override; - - static bool IsContentPack(const Extension* extension); - static ExtensionResource GetContentPackSiteList(const Extension* extension); - - // A file containing a list of sites for a supervised user. - base::FilePath site_list; -}; - -// Parses the "content_pack" manifest key for a supervised user. -class SupervisedUserHandler : public ManifestHandler { - public: - SupervisedUserHandler(); - ~SupervisedUserHandler() override; - - bool Parse(Extension* extension, base::string16* error) override; - - private: - const std::vector<std::string> Keys() const override; - - bool LoadSites(SupervisedUserInfo* info, - const base::DictionaryValue* content_pack_value, - base::string16* error); - bool LoadConfigurations(SupervisedUserInfo* info, - const base::DictionaryValue* content_pack_value, - base::string16* error); - - DISALLOW_COPY_AND_ASSIGN(SupervisedUserHandler); -}; - -} // namespace extensions - -#endif // CHROME_COMMON_EXTENSIONS_API_SUPERVISED_USER_PRIVATE_SUPERVISED_USER_HANDLER_H_
diff --git a/chrome/common/extensions/api/tabs.json b/chrome/common/extensions/api/tabs.json index 2d7999e..1b64d4a 100644 --- a/chrome/common/extensions/api/tabs.json +++ b/chrome/common/extensions/api/tabs.json
@@ -487,6 +487,7 @@ { "type": "function", "name": "callback", + "optional": true, "parameters": [ { "name": "window", @@ -815,6 +816,7 @@ { "type": "function", "name": "callback", + "optional": true, "description": "Called after the zoom settings have been changed.", "parameters": [] }
diff --git a/chrome/common/extensions/api/webview_tag.json b/chrome/common/extensions/api/webview_tag.json index 30603b0..e73b170 100644 --- a/chrome/common/extensions/api/webview_tag.json +++ b/chrome/common/extensions/api/webview_tag.json
@@ -338,7 +338,22 @@ { "name": "back", "type": "function", - "description": "Navigates backward one history entry if possible. Equivalent to <code>go(-1)</code>." + "description": "Navigates backward one history entry if possible. Equivalent to <code>go(-1)</code>.", + "parameters": [ + { + "type": "function", + "name": "callback", + "description": "Called after the navigation has either failed or completed successfully.", + "optional": true, + "parameters": [ + { + "name": "success", + "type": "boolean", + "description": "Indicates whether the navigation was successful." + } + ] + } + ] }, { "name": "canGoBack", @@ -439,7 +454,21 @@ "name": "forward", "type": "function", "description": "Navigates forward one history entry if possible. Equivalent to <code>go(1)</code>.", - "parameters": [] + "parameters": [ + { + "type": "function", + "name": "callback", + "description": "Called after the navigation has either failed or completed successfully.", + "optional": true, + "parameters": [ + { + "name": "success", + "type": "boolean", + "description": "Indicates whether the navigation was successful." + } + ] + } + ] }, { "name": "getProcessId", @@ -506,6 +535,7 @@ { "type": "function", "name": "callback", + "description": "Called after the navigation has either failed or completed successfully.", "optional": true, "parameters": [ {
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc index bb2f0da9..d81d313 100644 --- a/chrome/common/extensions/chrome_extensions_client.cc +++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -103,12 +103,6 @@ // TODO(dmazzoni): remove this once we have an extension API that // allows any extension to request read-only access to webui pages. scripting_whitelist_.push_back(extension_misc::kChromeVoxExtensionId); - - // Whitelist "Discover DevTools Companion" extension from Google that - // needs the ability to script DevTools pages. Companion will assist - // online courses and will be needed while the online educational programs - // are in place. - scripting_whitelist_.push_back("angkfkebojeancgemegoedelbnjgcgme"); } const PermissionMessageProvider&
diff --git a/chrome/common/extensions/chrome_manifest_handlers.cc b/chrome/common/extensions/chrome_manifest_handlers.cc index 59eebc71..cd09981 100644 --- a/chrome/common/extensions/chrome_manifest_handlers.cc +++ b/chrome/common/extensions/chrome_manifest_handlers.cc
@@ -14,7 +14,6 @@ #include "chrome/common/extensions/api/plugins/plugins_handler.h" #include "chrome/common/extensions/api/speech/tts_engine_manifest_handler.h" #include "chrome/common/extensions/api/spellcheck/spellcheck_handler.h" -#include "chrome/common/extensions/api/supervised_user_private/supervised_user_handler.h" #include "chrome/common/extensions/api/system_indicator/system_indicator_handler.h" #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" #include "chrome/common/extensions/chrome_manifest_url_handlers.h" @@ -60,7 +59,6 @@ (new SettingsOverridesHandler)->Register(); (new SpellcheckHandler)->Register(); (new StorageSchemaManifestHandler)->Register(); - (new SupervisedUserHandler)->Register(); (new SystemIndicatorHandler)->Register(); (new ThemeHandler)->Register(); (new TtsEngineManifestHandler)->Register();
diff --git a/chrome/common/extensions/docs/templates/public/apps/instanceID.html b/chrome/common/extensions/docs/templates/public/apps/instanceID.html new file mode 100644 index 0000000..8bc884cb --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/instanceID.html
@@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.apps.instanceID/}}
diff --git a/chrome/common/extensions/docs/templates/public/extensions/instanceID.html b/chrome/common/extensions/docs/templates/public/extensions/instanceID.html new file mode 100644 index 0000000..ed90fc4e --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/instanceID.html
@@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.extensions.instanceID/}}
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc index 92bb884..4eb4d675 100644 --- a/chrome/common/extensions/permissions/chrome_api_permissions.cc +++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -341,6 +341,16 @@ APIPermissionInfo::kFlagCannotBeOptional, IDS_EXTENSION_PROMPT_WARNING_SETTINGS_PRIVATE, PermissionMessage::kSettingsPrivate}, + {APIPermission::kSearchEnginesPrivate, + "searchEnginesPrivate", + APIPermissionInfo::kFlagCannotBeOptional, + IDS_EXTENSION_PROMPT_WARNING_SEARCH_ENGINES_PRIVATE, + PermissionMessage::kSearchEnginesPrivate}, + {APIPermission::kAutofillPrivate, + "autofillPrivate", + APIPermissionInfo::kFlagCannotBeOptional, + IDS_EXTENSION_PROMPT_WARNING_AUTOFILL_PRIVATE, + PermissionMessage::kAutofillPrivate}, // Full url access permissions. {APIPermission::kDebugger,
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_rules.cc b/chrome/common/extensions/permissions/chrome_permission_message_rules.cc index 397ddd9..1f2ffae0 100644 --- a/chrome/common/extensions/permissions/chrome_permission_message_rules.cc +++ b/chrome/common/extensions/permissions/chrome_permission_message_rules.cc
@@ -320,10 +320,6 @@ APIPermission::kAccessibilityFeaturesRead}, {}}, - {IDS_EXTENSION_PROMPT_WARNING_AUDIO_AND_VIDEO_CAPTURE, - {APIPermission::kAudioCapture, APIPermission::kVideoCapture}, - {}}, - // TODO(sashab): Add the missing combinations of media galleries // permissions so a valid permission is generated for all combinations. {IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ_WRITE_DELETE, @@ -499,9 +495,15 @@ {IDS_EXTENSION_PROMPT_WARNING_MUSIC_MANAGER_PRIVATE, {APIPermission::kMusicManagerPrivate}, {}}, + {IDS_EXTENSION_PROMPT_WARNING_SEARCH_ENGINES_PRIVATE, + {APIPermission::kSearchEnginesPrivate}, + {}}, {IDS_EXTENSION_PROMPT_WARNING_SETTINGS_PRIVATE, {APIPermission::kSettingsPrivate}, {}}, + {IDS_EXTENSION_PROMPT_WARNING_AUTOFILL_PRIVATE, + {APIPermission::kAutofillPrivate}, + {}}, // Platform-app permission messages. @@ -538,6 +540,10 @@ {APIPermission::kStartupPages}, {}}, + {IDS_EXTENSION_PROMPT_WARNING_AUDIO_AND_VIDEO_CAPTURE, + {APIPermission::kAudioCapture, APIPermission::kVideoCapture}, + {}}, + // Individual message rules taken from // ExtensionsAPIPermissions::GetAllPermissions(): {IDS_EXTENSION_PROMPT_WARNING_AUDIO_CAPTURE,
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc index f212652a..7d8d7484 100644 --- a/chrome/common/extensions/permissions/permission_set_unittest.cc +++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -1139,46 +1139,42 @@ } TEST(PermissionsTest, GetWarningMessages_AudioVideo) { + const std::string kAudio("Use your microphone"); + const std::string kVideo("Use your camera"); + const std::string kBoth("Use your microphone and camera"); + // Both audio and video present. scoped_refptr<Extension> extension = LoadManifest("permissions", "audio-video.json"); const PermissionMessageProvider* provider = PermissionMessageProvider::Get(); PermissionSet* set = const_cast<PermissionSet*>( extension->permissions_data()->active_permissions().get()); - EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), - "Use your microphone")); - EXPECT_FALSE( - VerifyHasPermissionMessage(set, extension->GetType(), "Use your camera")); - EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(), - "Use your microphone and camera")); + EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kAudio)); + EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kVideo)); + EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(), kBoth)); PermissionMessageStrings warnings = provider->GetPermissionMessageStrings(set, extension->GetType()); - size_t combined_index = IndexOf(warnings, "Use your microphone and camera"); + size_t combined_index = IndexOf(warnings, kBoth); size_t combined_size = warnings.size(); // Just audio present. set->apis_.erase(APIPermission::kVideoCapture); - EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(), - "Use your microphone")); - EXPECT_FALSE( - VerifyHasPermissionMessage(set, extension->GetType(), "Use your camera")); - EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), - "Use your microphone and camera")); + EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(), kAudio)); + EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kVideo)); + EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kBoth)); warnings = provider->GetPermissionMessageStrings(set, extension->GetType()); EXPECT_EQ(combined_size, warnings.size()); - EXPECT_EQ(combined_index, IndexOf(warnings, "Use your microphone")); + EXPECT_EQ(combined_index, IndexOf(warnings, kAudio)); // Just video present. set->apis_.erase(APIPermission::kAudioCapture); set->apis_.insert(APIPermission::kVideoCapture); - EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), - "Use your microphone")); - EXPECT_TRUE( - VerifyHasPermissionMessage(set, extension->GetType(), "Use your camera")); - EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), - "Use your microphone and camera")); + EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kAudio)); + EXPECT_TRUE(VerifyHasPermissionMessage(set, extension->GetType(), kVideo)); + EXPECT_FALSE(VerifyHasPermissionMessage(set, extension->GetType(), kBoth)); warnings = provider->GetPermissionMessageStrings(set, extension->GetType()); EXPECT_EQ(combined_size, warnings.size()); + EXPECT_EQ(combined_index, IndexOf(warnings, kVideo)); } TEST(PermissionsTest, GetWarningMessages_CombinedSessions) {
diff --git a/chrome/common/instant_types.h b/chrome/common/instant_types.h index bc33f89..f30cde36 100644 --- a/chrome/common/instant_types.h +++ b/chrome/common/instant_types.h
@@ -38,6 +38,8 @@ THEME_BKGRND_IMAGE_ALIGN_TOP, THEME_BKGRND_IMAGE_ALIGN_RIGHT, THEME_BKGRND_IMAGE_ALIGN_BOTTOM, + + THEME_BKGRND_IMAGE_ALIGN_LAST = THEME_BKGRND_IMAGE_ALIGN_BOTTOM, }; // The tiling of the theme background image. @@ -46,6 +48,8 @@ THEME_BKGRND_IMAGE_REPEAT_X, THEME_BKGRND_IMAGE_REPEAT_Y, THEME_BKGRND_IMAGE_REPEAT, + + THEME_BKGRND_IMAGE_LAST = THEME_BKGRND_IMAGE_REPEAT, }; // The RGBA color components for the text and links of the theme.
diff --git a/chrome/common/local_discovery/local_domain_resolver_unittest.cc b/chrome/common/local_discovery/local_domain_resolver_unittest.cc index 146cca2e..2a612833 100644 --- a/chrome/common/local_discovery/local_domain_resolver_unittest.cc +++ b/chrome/common/local_discovery/local_domain_resolver_unittest.cc
@@ -60,7 +60,7 @@ class LocalDomainResolverTest : public testing::Test { public: - virtual void SetUp() override { + void SetUp() override { mdns_client_.StartListening(&socket_factory_); }
diff --git a/chrome/common/origin_util.cc b/chrome/common/origin_util.cc deleted file mode 100644 index b2f7d63..0000000 --- a/chrome/common/origin_util.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright (c) 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/common/origin_util.h" - -#include "content/public/common/url_constants.h" -#include "extensions/common/constants.h" -#include "net/base/net_util.h" -#include "url/gurl.h" - -bool IsOriginSecure(const GURL& url) { - if (url.SchemeIsCryptographic() || url.SchemeIsFile()) - return true; - - if (url.SchemeIsFileSystem() && url.inner_url() && - IsOriginSecure(*url.inner_url())) { - return true; - } - - std::string hostname = url.HostNoBrackets(); - if (net::IsLocalhost(hostname)) - return true; - - std::string scheme = url.scheme(); - if (scheme == content::kChromeUIScheme || - scheme == extensions::kExtensionScheme || - scheme == extensions::kExtensionResourceScheme) { - return true; - } - - return false; -}
diff --git a/chrome/common/origin_util.h b/chrome/common/origin_util.h deleted file mode 100644 index 2b8cd5e..0000000 --- a/chrome/common/origin_util.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright (c) 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 CHROME_COMMON_ORIGIN_UTIL_H_ -#define CHROME_COMMON_ORIGIN_UTIL_H_ - -class GURL; - -// Returns true if the origin is trustworthy: that is, if its contents can be -// said to have been transferred to the browser in a way that a network attacker -// cannot tamper with or observe. -// -// See https://www.w3.org/TR/powerful-features/#is-origin-trustworthy. -bool IsOriginSecure(const GURL& url); - -#endif // CHROME_COMMON_ORIGIN_UTIL_H_
diff --git a/chrome/common/origin_util_unittest.cc b/chrome/common/origin_util_unittest.cc deleted file mode 100644 index 63eff639..0000000 --- a/chrome/common/origin_util_unittest.cc +++ /dev/null
@@ -1,45 +0,0 @@ -// Copyright (c) 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/common/origin_util.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -TEST(URLSchemesTest, IsOriginSecure) { - EXPECT_TRUE(IsOriginSecure(GURL("file:///test/fun.html"))); - EXPECT_TRUE(IsOriginSecure(GURL("file:///test/"))); - - EXPECT_TRUE(IsOriginSecure(GURL("https://example.com/fun.html"))); - EXPECT_FALSE(IsOriginSecure(GURL("http://example.com/fun.html"))); - - EXPECT_TRUE(IsOriginSecure(GURL("wss://example.com/fun.html"))); - EXPECT_FALSE(IsOriginSecure(GURL("ws://example.com/fun.html"))); - - EXPECT_TRUE(IsOriginSecure(GURL("http://localhost/fun.html"))); - EXPECT_FALSE(IsOriginSecure(GURL("http://localhost.com/fun.html"))); - EXPECT_TRUE(IsOriginSecure(GURL("https://localhost.com/fun.html"))); - - EXPECT_TRUE(IsOriginSecure(GURL("http://127.0.0.1/fun.html"))); - EXPECT_TRUE(IsOriginSecure(GURL("ftp://127.0.0.1/fun.html"))); - EXPECT_TRUE(IsOriginSecure(GURL("http://127.3.0.1/fun.html"))); - EXPECT_FALSE( - IsOriginSecure(GURL("http://127.example.com/fun.html"))); - EXPECT_TRUE( - IsOriginSecure(GURL("https://127.example.com/fun.html"))); - - EXPECT_TRUE(IsOriginSecure(GURL("http://[::1]/fun.html"))); - EXPECT_FALSE(IsOriginSecure(GURL("http://[::2]/fun.html"))); - EXPECT_FALSE( - IsOriginSecure(GURL("http://[::1].example.com/fun.html"))); - - EXPECT_FALSE(IsOriginSecure( - GURL("filesystem:http://www.example.com/temporary/"))); - EXPECT_FALSE(IsOriginSecure( - GURL("filesystem:ftp://www.example.com/temporary/"))); - EXPECT_TRUE(IsOriginSecure( - GURL("filesystem:ftp://127.0.0.1/temporary/"))); - EXPECT_TRUE(IsOriginSecure( - GURL("filesystem:https://www.example.com/temporary/"))); -}
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index eca2d70..0e93b1f44 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -350,6 +350,10 @@ const char kSafeBrowsingExtendedReportingOptInAllowed[] = "safebrowsing.extended_reporting_opt_in_allowed"; +// Boolean that is true when the SSL interstitial should allow users to +// proceed anyway. Otherwise, proceeding is not possible. +const char kSSLErrorOverrideAllowed[] = "ssl.error_override_allowed"; + // Enum that specifies whether Incognito mode is: // 0 - Enabled. Default behaviour. Default mode is available on demand. // 1 - Disabled. Used cannot browse pages in Incognito mode.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 6344211..a6e36ba 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -145,6 +145,7 @@ extern const char kSafeBrowsingProceedAnywayDisabled[]; extern const char kSafeBrowsingIncidentsSent[]; extern const char kSafeBrowsingExtendedReportingOptInAllowed[]; +extern const char kSSLErrorOverrideAllowed[]; extern const char kIncognitoModeAvailability[]; extern const char kSearchSuggestEnabled[]; #if defined(OS_ANDROID)
diff --git a/chrome/common/prefetch_messages.h b/chrome/common/prefetch_messages.h deleted file mode 100644 index e4f691a..0000000 --- a/chrome/common/prefetch_messages.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 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. - -// Multiply-included message file, no traditional include guard. -#include "ipc/ipc_message.h" -#include "ipc/ipc_message_macros.h" -#include "ipc/ipc_param_traits.h" -#include "url/gurl.h" - -#define IPC_MESSAGE_START PrefetchMsgStart - -// Prefetch Messages -// These are messages sent from the browser to the renderer related to -// prefetching. - -// Instructs the renderer to launch a prefetch within its context. -IPC_MESSAGE_ROUTED1(PrefetchMsg_Prefetch, - GURL /* url */)
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index e3f38656..c9218057 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h
@@ -80,11 +80,15 @@ IPC_ENUM_TRAITS_MAX_VALUE(OmniboxFocusState, OMNIBOX_FOCUS_STATE_LAST) IPC_ENUM_TRAITS_MAX_VALUE(search_provider::OSDDType, search_provider::OSDD_TYPE_LAST) -IPC_ENUM_TRAITS(search_provider::InstallState) -IPC_ENUM_TRAITS(ThemeBackgroundImageAlignment) -IPC_ENUM_TRAITS(ThemeBackgroundImageTiling) -IPC_ENUM_TRAITS(blink::WebConsoleMessage::Level) -IPC_ENUM_TRAITS(content::TopControlsState) +IPC_ENUM_TRAITS_MAX_VALUE(search_provider::InstallState, + search_provider::INSTALLED_STATE_LAST) +IPC_ENUM_TRAITS_MAX_VALUE(ThemeBackgroundImageAlignment, + THEME_BKGRND_IMAGE_ALIGN_LAST) +IPC_ENUM_TRAITS_MAX_VALUE(ThemeBackgroundImageTiling, THEME_BKGRND_IMAGE_LAST) +IPC_ENUM_TRAITS_MAX_VALUE(blink::WebConsoleMessage::Level, + blink::WebConsoleMessage::LevelLast) +IPC_ENUM_TRAITS_MAX_VALUE(content::TopControlsState, + content::TOP_CONTROLS_STATE_LAST) // Output parameters for ChromeViewHostMsg_GetPluginInfo message. IPC_STRUCT_BEGIN(ChromeViewHostMsg_GetPluginInfo_Output)
diff --git a/chrome/common/safe_browsing/binary_feature_extractor_win_unittest.cc b/chrome/common/safe_browsing/binary_feature_extractor_win_unittest.cc index 980ce857..f050c0d 100644 --- a/chrome/common/safe_browsing/binary_feature_extractor_win_unittest.cc +++ b/chrome/common/safe_browsing/binary_feature_extractor_win_unittest.cc
@@ -21,7 +21,7 @@ class BinaryFeatureExtractorWinTest : public testing::Test { protected: - virtual void SetUp() override { + void SetUp() override { base::FilePath source_path; ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_path)); testdata_path_ = source_path
diff --git a/chrome/common/safe_browsing/pe_image_reader_win.cc b/chrome/common/safe_browsing/pe_image_reader_win.cc index 16185ba..74d1d9e 100644 --- a/chrome/common/safe_browsing/pe_image_reader_win.cc +++ b/chrome/common/safe_browsing/pe_image_reader_win.cc
@@ -37,19 +37,19 @@ : optional_header_(reinterpret_cast<const OPTIONAL_HEADER_TYPE*>( optional_header_start)) {} - virtual WordSize GetWordSize() override { + WordSize GetWordSize() override { return TraitsType::word_size; } - virtual size_t GetDataDirectoryOffset() override { + size_t GetDataDirectoryOffset() override { return offsetof(OPTIONAL_HEADER_TYPE, DataDirectory); } - virtual DWORD GetDataDirectorySize() override { + DWORD GetDataDirectorySize() override { return optional_header_->NumberOfRvaAndSizes; } - virtual const IMAGE_DATA_DIRECTORY* GetDataDirectoryEntries() override { + const IMAGE_DATA_DIRECTORY* GetDataDirectoryEntries() override { return &optional_header_->DataDirectory[0]; }
diff --git a/chrome/common/safe_browsing/pe_image_reader_win_unittest.cc b/chrome/common/safe_browsing/pe_image_reader_win_unittest.cc index d0a208b..939e7a6 100644 --- a/chrome/common/safe_browsing/pe_image_reader_win_unittest.cc +++ b/chrome/common/safe_browsing/pe_image_reader_win_unittest.cc
@@ -35,7 +35,7 @@ protected: PeImageReaderTest() : expected_data_(GetParam()) {} - virtual void SetUp() override { + void SetUp() override { ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_file_path_)); data_file_path_ = data_file_path_.AppendASCII("safe_browsing"); data_file_path_ = data_file_path_.AppendASCII(expected_data_->filename);
diff --git a/chrome/common/search_provider.h b/chrome/common/search_provider.h index d55416c..9b51df93 100644 --- a/chrome/common/search_provider.h +++ b/chrome/common/search_provider.h
@@ -33,7 +33,9 @@ INSTALLED_BUT_NOT_DEFAULT = 1, // The search provider is set as the user's default. - INSTALLED_AS_DEFAULT = 2 + INSTALLED_AS_DEFAULT = 2, + + INSTALLED_STATE_LAST = INSTALLED_AS_DEFAULT }; } // namespace search_provider
diff --git a/chrome/installer/installer_tools.gyp b/chrome/installer/installer_tools.gyp index fea3d488..3033e218 100644 --- a/chrome/installer/installer_tools.gyp +++ b/chrome/installer/installer_tools.gyp
@@ -7,7 +7,7 @@ 'version_py': '<(DEPTH)/build/util/version.py', 'version_path': '<(DEPTH)/chrome/VERSION', 'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE', - # 'branding_dir' is set in the 'conditions' section at the bottom. + 'branding_dir': '<(DEPTH)/chrome/app/theme/<(branding_path_component)', 'msvs_use_common_release': 0, 'msvs_use_common_linker_extras': 0, }, @@ -34,14 +34,5 @@ }, ], }], - [ 'branding == "Chrome"', { - 'variables': { - 'branding_dir': '<(DEPTH)/chrome/app/theme/google_chrome', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_dir': '<(DEPTH)/chrome/app/theme/chromium', - }, - }], ], }
diff --git a/chrome/installer/launcher_support/BUILD.gn b/chrome/installer/launcher_support/BUILD.gn new file mode 100644 index 0000000..9abab50d --- /dev/null +++ b/chrome/installer/launcher_support/BUILD.gn
@@ -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. + +source_set("launcher_support") { + sources = [ + "chrome_launcher_support.cc", + "chrome_launcher_support.h", + ] + + deps = [ + "//base", + ] +}
diff --git a/chrome/installer/mini_installer.gyp b/chrome/installer/mini_installer.gyp index fdbd85d0..76e72ee 100644 --- a/chrome/installer/mini_installer.gyp +++ b/chrome/installer/mini_installer.gyp
@@ -3,7 +3,7 @@ 'version_py': '<(DEPTH)/build/util/version.py', 'version_path': '../../chrome/VERSION', 'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE', - # 'branding_dir' is set in the 'conditions' section at the bottom. + 'branding_dir': '../app/theme/<(branding_path_component)', 'msvs_use_common_release': 0, 'msvs_use_common_linker_extras': 0, 'mini_installer_internal_deps%': 0, @@ -298,24 +298,6 @@ 'message': 'Create installer archive', }, ], - # TODO(mark): <(branding_dir) should be defined by the - # global condition block at the bottom of the file, but - # this doesn't work due to the following issue: - # - # http://code.google.com/p/gyp/issues/detail?id=22 - # - # Remove this block once the above issue is fixed. - 'conditions': [ - [ 'branding == "Chrome"', { - 'variables': { - 'branding_dir': '../app/theme/google_chrome', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_dir': '../app/theme/chromium', - }, - }], - ], }, ], 'conditions': [ @@ -338,14 +320,5 @@ }], ], }], - [ 'branding == "Chrome"', { - 'variables': { - 'branding_dir': '../app/theme/google_chrome', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_dir': '../app/theme/chromium', - }, - }], ], }
diff --git a/chrome/installer/mini_installer_syzygy.gyp b/chrome/installer/mini_installer_syzygy.gyp index 4d19617b2..db7f5c8 100644 --- a/chrome/installer/mini_installer_syzygy.gyp +++ b/chrome/installer/mini_installer_syzygy.gyp
@@ -6,7 +6,7 @@ 'version_py': '<(DEPTH)/build/util/version.py', 'version_path': '<(DEPTH)/chrome/VERSION', 'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE', - # 'branding_dir' is set in the 'conditions' section at the bottom. + 'branding_dir': '../app/theme/<(branding_path_component)', 'msvs_use_common_release': 0, 'msvs_use_common_linker_extras': 0, }, @@ -64,14 +64,5 @@ },{ 'targets': [], }], - [ 'branding == "Chrome"', { - 'variables': { - 'branding_dir': '../app/theme/google_chrome', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_dir': '../app/theme/chromium', - }, - }], ], }
diff --git a/chrome/installer/setup/archive_patch_helper_unittest.cc b/chrome/installer/setup/archive_patch_helper_unittest.cc index 099dd17..f42ed5b 100644 --- a/chrome/installer/setup/archive_patch_helper_unittest.cc +++ b/chrome/installer/setup/archive_patch_helper_unittest.cc
@@ -24,12 +24,12 @@ data_dir_.clear(); } - virtual void SetUp() override { + void SetUp() override { // Create a temp directory for testing. ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); } - virtual void TearDown() override { + void TearDown() override { // Clean up test directory manually so we can fail if it leaks. ASSERT_TRUE(test_dir_.Delete()); }
diff --git a/chrome/installer/setup/install_unittest.cc b/chrome/installer/setup/install_unittest.cc index 5c3f32c..d011f7e 100644 --- a/chrome/installer/setup/install_unittest.cc +++ b/chrome/installer/setup/install_unittest.cc
@@ -33,7 +33,7 @@ class CreateVisualElementsManifestTest : public testing::Test { protected: - virtual void SetUp() override { + void SetUp() override { // Create a temp directory for testing. ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); @@ -46,7 +46,7 @@ test_dir_.path().Append(installer::kVisualElementsManifest); } - virtual void TearDown() override { + void TearDown() override { // Clean up test directory manually so we can fail if it leaks. ASSERT_TRUE(test_dir_.Delete()); } @@ -66,7 +66,7 @@ class InstallShortcutTest : public testing::Test { protected: - virtual void SetUp() override { + void SetUp() override { EXPECT_EQ(S_OK, CoInitialize(NULL)); dist_ = BrowserDistribution::GetDistribution(); @@ -139,7 +139,7 @@ fake_user_desktop_.path().Append(alternate_shortcut_name); } - virtual void TearDown() override { + void TearDown() override { // Try to unpin potentially pinned shortcuts (although pinning isn't tested, // the call itself might still have pinned the Start Menu shortcuts). base::win::TaskbarUnpinShortcutLink(
diff --git a/chrome/installer/setup/install_worker_unittest.cc b/chrome/installer/setup/install_worker_unittest.cc index c288549..d47f042 100644 --- a/chrome/installer/setup/install_worker_unittest.cc +++ b/chrome/installer/setup/install_worker_unittest.cc
@@ -491,7 +491,7 @@ class OldIELowRightsTests : public InstallWorkerTest, public ::testing::WithParamInterface<std::tr1::tuple<bool, bool> > { protected: - virtual void SetUp() override { + void SetUp() override { InstallWorkerTest::SetUp(); const ParamType& param = GetParam();
diff --git a/chrome/installer/setup/run_all_unittests.cc b/chrome/installer/setup/run_all_unittests.cc index fa354085..df5a3973 100644 --- a/chrome/installer/setup/run_all_unittests.cc +++ b/chrome/installer/setup/run_all_unittests.cc
@@ -8,7 +8,7 @@ #include "chrome/installer/setup/setup_util_unittest.h" int main(int argc, char** argv) { - TestSuite test_suite(argc, argv); + base::TestSuite test_suite(argc, argv); // Handle the --adjust-process-priority switch, which is used to test the // installer::AdjustProcessPriority() function in a subprocess.
diff --git a/chrome/installer/setup/setup_util_unittest.cc b/chrome/installer/setup/setup_util_unittest.cc index c07ec98..dd92f56 100644 --- a/chrome/installer/setup/setup_util_unittest.cc +++ b/chrome/installer/setup/setup_util_unittest.cc
@@ -35,12 +35,12 @@ class SetupUtilTestWithDir : public testing::Test { protected: - virtual void SetUp() override { + void SetUp() override { // Create a temp directory for testing. ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); } - virtual void TearDown() override { + void TearDown() override { // Clean up test directory manually so we can fail if it leaks. ASSERT_TRUE(test_dir_.Delete()); } @@ -290,7 +290,7 @@ } }; - virtual void SetUp() override { + void SetUp() override { SetupUtilTestWithDir::SetUp(); product_version_ = Version("30.0.1559.0"); max_version_ = Version("47.0.1559.0"); @@ -316,7 +316,7 @@ ASSERT_EQ(1, base::WriteFile(GetMaxVersionArchivePath(), "b", 1)); } - virtual void TearDown() override { + void TearDown() override { original_state_.reset(); SetupUtilTestWithDir::TearDown(); } @@ -411,7 +411,7 @@ class MigrateMultiToSingleTest : public testing::Test { protected: - virtual void SetUp() override { + void SetUp() override { registry_override_manager_.OverrideRegistry(kRootKey); }
diff --git a/chrome/installer/upgrade_test.gyp b/chrome/installer/upgrade_test.gyp index 061604e..bccc94db 100644 --- a/chrome/installer/upgrade_test.gyp +++ b/chrome/installer/upgrade_test.gyp
@@ -4,6 +4,7 @@ { 'variables': { + 'branding_dir': '../app/theme/<(branding_path_component)', 'version_py': '<(DEPTH)/build/util/version.py', 'version_path': '../../chrome/VERSION', 'lastchange_path': '<(DEPTH)/build/util/LASTCHANGE', @@ -87,14 +88,5 @@ }, ], }], - [ 'branding == "Chrome"', { - 'variables': { - 'branding_dir': '../app/theme/google_chrome', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_dir': '../app/theme/chromium', - }, - }], ], }
diff --git a/chrome/installer/util/advanced_firewall_manager_win_unittest.cc b/chrome/installer/util/advanced_firewall_manager_win_unittest.cc index 5920ea2d..08037f7af 100644 --- a/chrome/installer/util/advanced_firewall_manager_win_unittest.cc +++ b/chrome/installer/util/advanced_firewall_manager_win_unittest.cc
@@ -17,11 +17,11 @@ protected: // Sets up the test fixture. - virtual void SetUp() override { + void SetUp() override { if (base::GetCurrentProcessIntegrityLevel() != base::HIGH_INTEGRITY) { LOG(WARNING) << "XP or not elevated. Skipping the test."; return; - }; + } skip_test_ = false; base::FilePath exe_path; PathService::Get(base::FILE_EXE, &exe_path); @@ -30,7 +30,7 @@ } // Tears down the test fixture. - virtual void TearDown() override { + void TearDown() override { if (!skip_test_) manager_.DeleteAllRules(); }
diff --git a/chrome/installer/util/callback_work_item.h b/chrome/installer/util/callback_work_item.h index c81d02a..3cc22f6 100644 --- a/chrome/installer/util/callback_work_item.h +++ b/chrome/installer/util/callback_work_item.h
@@ -33,10 +33,10 @@ // } class CallbackWorkItem : public WorkItem { public: - virtual ~CallbackWorkItem(); + ~CallbackWorkItem() override; - virtual bool Do() override; - virtual void Rollback() override; + bool Do() override; + void Rollback() override; bool IsRollback() const;
diff --git a/chrome/installer/util/chrome_binaries_operations.h b/chrome/installer/util/chrome_binaries_operations.h index f0929f7..88b8199 100644 --- a/chrome/installer/util/chrome_binaries_operations.h +++ b/chrome/installer/util/chrome_binaries_operations.h
@@ -17,42 +17,40 @@ public: ChromeBinariesOperations() {} - virtual void ReadOptions(const MasterPreferences& prefs, - std::set<base::string16>* options) const override; + void ReadOptions(const MasterPreferences& prefs, + std::set<base::string16>* options) const override; - virtual void ReadOptions(const base::CommandLine& uninstall_command, - std::set<base::string16>* options) const override; + void ReadOptions(const base::CommandLine& uninstall_command, + std::set<base::string16>* options) const override; - virtual void AddKeyFiles( - const std::set<base::string16>& options, - std::vector<base::FilePath>* key_files) const override; + void AddKeyFiles(const std::set<base::string16>& options, + std::vector<base::FilePath>* key_files) const override; - virtual void AddComDllList( - const std::set<base::string16>& options, - std::vector<base::FilePath>* com_dll_list) const override; + void AddComDllList(const std::set<base::string16>& options, + std::vector<base::FilePath>* com_dll_list) const override; - virtual void AppendProductFlags(const std::set<base::string16>& options, - base::CommandLine* cmd_line) const override; + void AppendProductFlags(const std::set<base::string16>& options, + base::CommandLine* cmd_line) const override; - virtual void AppendRenameFlags(const std::set<base::string16>& options, - base::CommandLine* cmd_line) const override; + void AppendRenameFlags(const std::set<base::string16>& options, + base::CommandLine* cmd_line) const override; - virtual bool SetChannelFlags(const std::set<base::string16>& options, - bool set, - ChannelInfo* channel_info) const override; + bool SetChannelFlags(const std::set<base::string16>& options, + bool set, + ChannelInfo* channel_info) const override; - virtual bool ShouldCreateUninstallEntry( + bool ShouldCreateUninstallEntry( const std::set<base::string16>& options) const override; - virtual void AddDefaultShortcutProperties( + void AddDefaultShortcutProperties( BrowserDistribution* dist, const base::FilePath& target_exe, ShellUtil::ShortcutProperties* properties) const override; - virtual void LaunchUserExperiment(const base::FilePath& setup_path, - const std::set<base::string16>& options, - InstallStatus status, - bool system_level) const override; + void LaunchUserExperiment(const base::FilePath& setup_path, + const std::set<base::string16>& options, + InstallStatus status, + bool system_level) const override; private: DISALLOW_COPY_AND_ASSIGN(ChromeBinariesOperations);
diff --git a/chrome/installer/util/chrome_browser_operations.h b/chrome/installer/util/chrome_browser_operations.h index eb695c7..fe17c91 100644 --- a/chrome/installer/util/chrome_browser_operations.h +++ b/chrome/installer/util/chrome_browser_operations.h
@@ -16,42 +16,40 @@ public: ChromeBrowserOperations() {} - virtual void ReadOptions(const MasterPreferences& prefs, - std::set<base::string16>* options) const override; + void ReadOptions(const MasterPreferences& prefs, + std::set<base::string16>* options) const override; - virtual void ReadOptions(const base::CommandLine& uninstall_command, - std::set<base::string16>* options) const override; + void ReadOptions(const base::CommandLine& uninstall_command, + std::set<base::string16>* options) const override; - virtual void AddKeyFiles( - const std::set<base::string16>& options, - std::vector<base::FilePath>* key_files) const override; + void AddKeyFiles(const std::set<base::string16>& options, + std::vector<base::FilePath>* key_files) const override; - virtual void AddComDllList( - const std::set<base::string16>& options, - std::vector<base::FilePath>* com_dll_list) const override; + void AddComDllList(const std::set<base::string16>& options, + std::vector<base::FilePath>* com_dll_list) const override; - virtual void AppendProductFlags(const std::set<base::string16>& options, - base::CommandLine* cmd_line) const override; + void AppendProductFlags(const std::set<base::string16>& options, + base::CommandLine* cmd_line) const override; - virtual void AppendRenameFlags(const std::set<base::string16>& options, - base::CommandLine* cmd_line) const override; + void AppendRenameFlags(const std::set<base::string16>& options, + base::CommandLine* cmd_line) const override; - virtual bool SetChannelFlags(const std::set<base::string16>& options, - bool set, - ChannelInfo* channel_info) const override; + bool SetChannelFlags(const std::set<base::string16>& options, + bool set, + ChannelInfo* channel_info) const override; - virtual bool ShouldCreateUninstallEntry( + bool ShouldCreateUninstallEntry( const std::set<base::string16>& options) const override; - virtual void AddDefaultShortcutProperties( + void AddDefaultShortcutProperties( BrowserDistribution* dist, const base::FilePath& target_exe, ShellUtil::ShortcutProperties* properties) const override; - virtual void LaunchUserExperiment(const base::FilePath& setup_path, - const std::set<base::string16>& options, - InstallStatus status, - bool system_level) const override; + void LaunchUserExperiment(const base::FilePath& setup_path, + const std::set<base::string16>& options, + InstallStatus status, + bool system_level) const override; private: DISALLOW_COPY_AND_ASSIGN(ChromeBrowserOperations);
diff --git a/chrome/installer/util/chrome_browser_sxs_operations.h b/chrome/installer/util/chrome_browser_sxs_operations.h index f60a485..06893f10 100644 --- a/chrome/installer/util/chrome_browser_sxs_operations.h +++ b/chrome/installer/util/chrome_browser_sxs_operations.h
@@ -16,11 +16,11 @@ public: ChromeBrowserSxSOperations() {} - virtual void AppendProductFlags(const std::set<base::string16>& options, - base::CommandLine* cmd_line) const override; + void AppendProductFlags(const std::set<base::string16>& options, + base::CommandLine* cmd_line) const override; - virtual void AppendRenameFlags(const std::set<base::string16>& options, - base::CommandLine* cmd_line) const override; + void AppendRenameFlags(const std::set<base::string16>& options, + base::CommandLine* cmd_line) const override; private: DISALLOW_COPY_AND_ASSIGN(ChromeBrowserSxSOperations);
diff --git a/chrome/installer/util/chrome_frame_distribution.h b/chrome/installer/util/chrome_frame_distribution.h index 9088fe2..ac3b879b 100644 --- a/chrome/installer/util/chrome_frame_distribution.h +++ b/chrome/installer/util/chrome_frame_distribution.h
@@ -13,46 +13,45 @@ class ChromeFrameDistribution : public BrowserDistribution { public: - virtual base::string16 GetBrowserProgIdPrefix() override; + base::string16 GetBrowserProgIdPrefix() override; - virtual base::string16 GetBrowserProgIdDesc() override; + base::string16 GetBrowserProgIdDesc() override; - virtual base::string16 GetDisplayName() override; + base::string16 GetDisplayName() override; - virtual base::string16 GetShortcutName(ShortcutType shortcut_type) override; + base::string16 GetShortcutName(ShortcutType shortcut_type) override; - virtual int GetIconIndex(ShortcutType shortcut_type) override; + int GetIconIndex(ShortcutType shortcut_type) override; - virtual base::string16 GetBaseAppName() override; + base::string16 GetBaseAppName() override; - virtual base::string16 GetInstallSubDir() override; + base::string16 GetInstallSubDir() override; - virtual base::string16 GetPublisherName() override; + base::string16 GetPublisherName() override; - virtual base::string16 GetAppDescription() override; + base::string16 GetAppDescription() override; - virtual base::string16 GetLongAppDescription() override; + base::string16 GetLongAppDescription() override; - virtual std::string GetSafeBrowsingName() override; + std::string GetSafeBrowsingName() override; - virtual std::string GetNetworkStatsServer() const override; + std::string GetNetworkStatsServer() const override; - virtual base::string16 GetUninstallLinkName() override; + base::string16 GetUninstallLinkName() override; - virtual base::string16 GetUninstallRegPath() override; + base::string16 GetUninstallRegPath() override; - virtual base::string16 GetIconFilename() override; + base::string16 GetIconFilename() override; - virtual DefaultBrowserControlPolicy GetDefaultBrowserControlPolicy() override; + DefaultBrowserControlPolicy GetDefaultBrowserControlPolicy() override; - virtual bool CanCreateDesktopShortcuts() override; + bool CanCreateDesktopShortcuts() override; - virtual bool GetCommandExecuteImplClsid( - base::string16* handler_class_uuid) override; + bool GetCommandExecuteImplClsid(base::string16* handler_class_uuid) override; - virtual void UpdateInstallStatus(bool system_install, - installer::ArchiveType archive_type, - installer::InstallStatus install_status) override; + void UpdateInstallStatus(bool system_install, + installer::ArchiveType archive_type, + installer::InstallStatus install_status) override; protected: friend class BrowserDistribution;
diff --git a/chrome/installer/util/chrome_frame_operations.h b/chrome/installer/util/chrome_frame_operations.h index 60d0dec..407890b 100644 --- a/chrome/installer/util/chrome_frame_operations.h +++ b/chrome/installer/util/chrome_frame_operations.h
@@ -16,42 +16,40 @@ public: ChromeFrameOperations() {} - virtual void ReadOptions(const MasterPreferences& prefs, - std::set<base::string16>* options) const override; + void ReadOptions(const MasterPreferences& prefs, + std::set<base::string16>* options) const override; - virtual void ReadOptions(const base::CommandLine& uninstall_command, - std::set<base::string16>* options) const override; + void ReadOptions(const base::CommandLine& uninstall_command, + std::set<base::string16>* options) const override; - virtual void AddKeyFiles( - const std::set<base::string16>& options, - std::vector<base::FilePath>* key_files) const override; + void AddKeyFiles(const std::set<base::string16>& options, + std::vector<base::FilePath>* key_files) const override; - virtual void AddComDllList( - const std::set<base::string16>& options, - std::vector<base::FilePath>* com_dll_list) const override; + void AddComDllList(const std::set<base::string16>& options, + std::vector<base::FilePath>* com_dll_list) const override; - virtual void AppendProductFlags(const std::set<base::string16>& options, - base::CommandLine* cmd_line) const override; + void AppendProductFlags(const std::set<base::string16>& options, + base::CommandLine* cmd_line) const override; - virtual void AppendRenameFlags(const std::set<base::string16>& options, - base::CommandLine* cmd_line) const override; + void AppendRenameFlags(const std::set<base::string16>& options, + base::CommandLine* cmd_line) const override; - virtual bool SetChannelFlags(const std::set<base::string16>& options, - bool set, - ChannelInfo* channel_info) const override; + bool SetChannelFlags(const std::set<base::string16>& options, + bool set, + ChannelInfo* channel_info) const override; - virtual bool ShouldCreateUninstallEntry( + bool ShouldCreateUninstallEntry( const std::set<base::string16>& options) const override; - virtual void AddDefaultShortcutProperties( + void AddDefaultShortcutProperties( BrowserDistribution* dist, const base::FilePath& target_exe, ShellUtil::ShortcutProperties* properties) const override; - virtual void LaunchUserExperiment(const base::FilePath& setup_path, - const std::set<base::string16>& options, - InstallStatus status, - bool system_level) const override; + void LaunchUserExperiment(const base::FilePath& setup_path, + const std::set<base::string16>& options, + InstallStatus status, + bool system_level) const override; private: DISALLOW_COPY_AND_ASSIGN(ChromeFrameOperations);
diff --git a/chrome/installer/util/chromium_binaries_distribution.h b/chrome/installer/util/chromium_binaries_distribution.h index 2d440be..986b8f3 100644 --- a/chrome/installer/util/chromium_binaries_distribution.h +++ b/chrome/installer/util/chromium_binaries_distribution.h
@@ -14,40 +14,39 @@ class ChromiumBinariesDistribution : public BrowserDistribution { public: - virtual base::string16 GetBrowserProgIdPrefix() override; + base::string16 GetBrowserProgIdPrefix() override; - virtual base::string16 GetBrowserProgIdDesc() override; + base::string16 GetBrowserProgIdDesc() override; - virtual base::string16 GetDisplayName() override; + base::string16 GetDisplayName() override; - virtual base::string16 GetShortcutName(ShortcutType shortcut_type) override; + base::string16 GetShortcutName(ShortcutType shortcut_type) override; - virtual int GetIconIndex(ShortcutType shortcut_type) override; + int GetIconIndex(ShortcutType shortcut_type) override; - virtual base::string16 GetBaseAppName() override; + base::string16 GetBaseAppName() override; - virtual base::string16 GetBaseAppId() override; + base::string16 GetBaseAppId() override; - virtual base::string16 GetInstallSubDir() override; + base::string16 GetInstallSubDir() override; - virtual base::string16 GetPublisherName() override; + base::string16 GetPublisherName() override; - virtual base::string16 GetAppDescription() override; + base::string16 GetAppDescription() override; - virtual base::string16 GetLongAppDescription() override; + base::string16 GetLongAppDescription() override; - virtual std::string GetSafeBrowsingName() override; + std::string GetSafeBrowsingName() override; - virtual base::string16 GetUninstallLinkName() override; + base::string16 GetUninstallLinkName() override; - virtual base::string16 GetUninstallRegPath() override; + base::string16 GetUninstallRegPath() override; - virtual DefaultBrowserControlPolicy GetDefaultBrowserControlPolicy() override; + DefaultBrowserControlPolicy GetDefaultBrowserControlPolicy() override; - virtual bool GetChromeChannel(base::string16* channel) override; + bool GetChromeChannel(base::string16* channel) override; - virtual bool GetCommandExecuteImplClsid( - base::string16* handler_class_uuid) override; + bool GetCommandExecuteImplClsid(base::string16* handler_class_uuid) override; protected: friend class BrowserDistribution;
diff --git a/chrome/installer/util/conditional_work_item_list.cc b/chrome/installer/util/conditional_work_item_list.cc index ad66944..fcf1955 100644 --- a/chrome/installer/util/conditional_work_item_list.cc +++ b/chrome/installer/util/conditional_work_item_list.cc
@@ -35,7 +35,13 @@ return base::PathExists(key_path_); } +Not::Not(WorkItem::Condition* original_condition) + : original_condition_(original_condition) { +} + +Not::~Not() { +} + bool Not::ShouldRun() const { return !original_condition_->ShouldRun(); } -
diff --git a/chrome/installer/util/conditional_work_item_list.h b/chrome/installer/util/conditional_work_item_list.h index 1e90a78e..97cdd7a 100644 --- a/chrome/installer/util/conditional_work_item_list.h +++ b/chrome/installer/util/conditional_work_item_list.h
@@ -48,13 +48,13 @@ // This class assumes ownership of original_condition. class Not : public WorkItem::Condition { public: - explicit Not(WorkItem::Condition* original_condition) - : original_condition_(original_condition) {} + explicit Not(WorkItem::Condition* original_condition); + ~Not(); + bool ShouldRun() const; private: scoped_ptr<WorkItem::Condition> original_condition_; }; - #endif // CHROME_INSTALLER_UTIL_CONDITIONAL_WORK_ITEM_LIST_H_
diff --git a/chrome/installer/util/delete_reg_key_work_item.h b/chrome/installer/util/delete_reg_key_work_item.h index 0fc11f6..54cddba 100644 --- a/chrome/installer/util/delete_reg_key_work_item.h +++ b/chrome/installer/util/delete_reg_key_work_item.h
@@ -21,11 +21,11 @@ // the key and its subkeys take on their default security descriptors. class DeleteRegKeyWorkItem : public WorkItem { public: - virtual ~DeleteRegKeyWorkItem(); + ~DeleteRegKeyWorkItem() override; - virtual bool Do() override; + bool Do() override; - virtual void Rollback() override; + void Rollback() override; private: friend class WorkItem;
diff --git a/chrome/installer/util/firewall_manager_win.cc b/chrome/installer/util/firewall_manager_win.cc index 0171a6f..202d062 100644 --- a/chrome/installer/util/firewall_manager_win.cc +++ b/chrome/installer/util/firewall_manager_win.cc
@@ -23,23 +23,23 @@ class FirewallManagerAdvancedImpl : public FirewallManager { public: FirewallManagerAdvancedImpl() {} - virtual ~FirewallManagerAdvancedImpl() {} + ~FirewallManagerAdvancedImpl() override {} bool Init(const base::string16& app_name, const base::FilePath& app_path) { return manager_.Init(app_name, app_path); } // FirewallManager methods. - virtual bool CanUseLocalPorts() override { + bool CanUseLocalPorts() override { return !manager_.IsFirewallEnabled() || manager_.HasAnyRule(); }; - virtual bool AddFirewallRules() override { + bool AddFirewallRules() override { return manager_.AddUDPRule(GetMdnsRuleName(), GetMdnsRuleDescription(), kDefaultMdnsPort); } - virtual void RemoveFirewallRules() override { + void RemoveFirewallRules() override { manager_.DeleteAllRules(); } @@ -67,25 +67,25 @@ class FirewallManagerLegacyImpl : public FirewallManager { public: FirewallManagerLegacyImpl() {} - virtual ~FirewallManagerLegacyImpl() {} + ~FirewallManagerLegacyImpl() override {} bool Init(const base::string16& app_name, const base::FilePath& app_path) { return manager_.Init(app_name, app_path); } // FirewallManager methods. - virtual bool CanUseLocalPorts() override { + bool CanUseLocalPorts() override { return !manager_.IsFirewallEnabled() || manager_.GetAllowIncomingConnection(NULL); }; - virtual bool AddFirewallRules() override { + bool AddFirewallRules() override { // Change nothing if rule is set. return manager_.GetAllowIncomingConnection(NULL) || manager_.SetAllowIncomingConnection(true); } - virtual void RemoveFirewallRules() override { + void RemoveFirewallRules() override { manager_.DeleteRule(); }
diff --git a/chrome/installer/util/google_chrome_distribution.h b/chrome/installer/util/google_chrome_distribution.h index d6611ba4..18076da 100644 --- a/chrome/installer/util/google_chrome_distribution.h +++ b/chrome/installer/util/google_chrome_distribution.h
@@ -29,57 +29,56 @@ // distribution_data contains Google Update related data that will be // concatenated to the survey url if the file in local_data_path indicates // the user has opted in to providing anonymous usage data. - virtual void DoPostUninstallOperations( + void DoPostUninstallOperations( const Version& version, const base::FilePath& local_data_path, const base::string16& distribution_data) override; - virtual base::string16 GetActiveSetupGuid() override; + base::string16 GetActiveSetupGuid() override; - virtual base::string16 GetShortcutName(ShortcutType shortcut_type) override; + base::string16 GetShortcutName(ShortcutType shortcut_type) override; - virtual base::string16 GetIconFilename() override; + base::string16 GetIconFilename() override; - virtual int GetIconIndex(ShortcutType shortcut_type) override; + int GetIconIndex(ShortcutType shortcut_type) override; - virtual base::string16 GetBaseAppName() override; + base::string16 GetBaseAppName() override; - virtual base::string16 GetBaseAppId() override; + base::string16 GetBaseAppId() override; - virtual base::string16 GetBrowserProgIdPrefix() override; + base::string16 GetBrowserProgIdPrefix() override; - virtual base::string16 GetBrowserProgIdDesc() override; + base::string16 GetBrowserProgIdDesc() override; - virtual base::string16 GetInstallSubDir() override; + base::string16 GetInstallSubDir() override; - virtual base::string16 GetPublisherName() override; + base::string16 GetPublisherName() override; - virtual base::string16 GetAppDescription() override; + base::string16 GetAppDescription() override; - virtual std::string GetSafeBrowsingName() override; + std::string GetSafeBrowsingName() override; - virtual std::string GetNetworkStatsServer() const override; + std::string GetNetworkStatsServer() const override; // This method reads data from the Google Update ClientState key for // potential use in the uninstall survey. It must be called before the // key returned by GetVersionKey() is deleted. - virtual base::string16 GetDistributionData(HKEY root_key) override; + base::string16 GetDistributionData(HKEY root_key) override; - virtual base::string16 GetUninstallLinkName() override; + base::string16 GetUninstallLinkName() override; - virtual base::string16 GetUninstallRegPath() override; + base::string16 GetUninstallRegPath() override; - virtual bool GetCommandExecuteImplClsid( - base::string16* handler_class_uuid) override; + bool GetCommandExecuteImplClsid(base::string16* handler_class_uuid) override; - virtual void UpdateInstallStatus( + void UpdateInstallStatus( bool system_install, installer::ArchiveType archive_type, installer::InstallStatus install_status) override; - virtual bool ShouldSetExperimentLabels() override; + bool ShouldSetExperimentLabels() override; - virtual bool HasUserExperiments() override; + bool HasUserExperiments() override; protected: // Disallow construction from others.
diff --git a/chrome/installer/util/google_chrome_sxs_distribution.h b/chrome/installer/util/google_chrome_sxs_distribution.h index c1be524f..9ae8c3a 100644 --- a/chrome/installer/util/google_chrome_sxs_distribution.h +++ b/chrome/installer/util/google_chrome_sxs_distribution.h
@@ -19,22 +19,21 @@ // system level install and setting as default browser. class GoogleChromeSxSDistribution : public GoogleChromeDistribution { public: - virtual base::string16 GetBaseAppName() override; - virtual base::string16 GetShortcutName(ShortcutType shortcut_type) override; - virtual int GetIconIndex(ShortcutType shortcut_type) override; - virtual base::string16 GetStartMenuShortcutSubfolder( + base::string16 GetBaseAppName() override; + base::string16 GetShortcutName(ShortcutType shortcut_type) override; + int GetIconIndex(ShortcutType shortcut_type) override; + base::string16 GetStartMenuShortcutSubfolder( Subfolder subfolder_type) override; - virtual base::string16 GetBaseAppId() override; - virtual base::string16 GetBrowserProgIdPrefix() override; - virtual base::string16 GetBrowserProgIdDesc() override; - virtual base::string16 GetInstallSubDir() override; - virtual base::string16 GetUninstallRegPath() override; - virtual DefaultBrowserControlPolicy GetDefaultBrowserControlPolicy() override; - virtual bool GetChromeChannel(base::string16* channel) override; - virtual bool GetCommandExecuteImplClsid( - base::string16* handler_class_uuid) override; - virtual bool ShouldSetExperimentLabels() override; - virtual bool HasUserExperiments() override; + base::string16 GetBaseAppId() override; + base::string16 GetBrowserProgIdPrefix() override; + base::string16 GetBrowserProgIdDesc() override; + base::string16 GetInstallSubDir() override; + base::string16 GetUninstallRegPath() override; + DefaultBrowserControlPolicy GetDefaultBrowserControlPolicy() override; + bool GetChromeChannel(base::string16* channel) override; + bool GetCommandExecuteImplClsid(base::string16* handler_class_uuid) override; + bool ShouldSetExperimentLabels() override; + bool HasUserExperiments() override; // returns the channel name for GoogleChromeSxSDistribution static base::string16 ChannelName(); private:
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc index 024cf5b..46b933b 100644 --- a/chrome/installer/util/google_update_settings_unittest.cc +++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -988,7 +988,7 @@ protected: static const wchar_t kDummyCommand[]; - virtual void SetUp() override { + void SetUp() override { GoogleUpdateSettingsTest::SetUp(); system_install_ = GetParam(); root_key_ = system_install_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; @@ -1047,7 +1047,7 @@ protected: static const wchar_t kDummyVersion[]; - virtual void SetUp() override { + void SetUp() override { GoogleUpdateSettingsTest::SetUp(); system_install_ = GetParam(); root_key_ = system_install_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; @@ -1165,7 +1165,7 @@ static void SetUpTestCase(); static void TearDownTestCase(); protected: - virtual void SetUp() override; + void SetUp() override; static void MakeChromeMultiInstall(HKEY root_key); static void ApplySetting(StatsState::StateSetting setting, HKEY root_key,
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h index edc6e36..5a269674 100644 --- a/chrome/installer/util/install_util.h +++ b/chrome/installer/util/install_util.h
@@ -165,7 +165,7 @@ public: explicit ValueEquals(const base::string16& value_to_match) : value_to_match_(value_to_match) { } - virtual bool Evaluate(const base::string16& value) const override; + bool Evaluate(const base::string16& value) const override; protected: base::string16 value_to_match_; private: @@ -190,8 +190,8 @@ class ProgramCompare : public RegistryValuePredicate { public: explicit ProgramCompare(const base::FilePath& path_to_match); - virtual ~ProgramCompare(); - virtual bool Evaluate(const base::string16& value) const override; + ~ProgramCompare() override; + bool Evaluate(const base::string16& value) const override; bool EvaluatePath(const base::FilePath& path) const; protected:
diff --git a/chrome/installer/util/installation_validator.h b/chrome/installer/util/installation_validator.h index 28e7a83e..b66a2535 100644 --- a/chrome/installer/util/installation_validator.h +++ b/chrome/installer/util/installation_validator.h
@@ -99,40 +99,40 @@ // Validation rules for the Chrome browser. class ChromeRules : public ProductRules { public: - virtual BrowserDistribution::Type distribution_type() const override; - virtual void AddUninstallSwitchExpectations( + BrowserDistribution::Type distribution_type() const override; + void AddUninstallSwitchExpectations( const ProductContext& ctx, SwitchExpectations* expectations) const override; - virtual void AddRenameSwitchExpectations( + void AddRenameSwitchExpectations( const ProductContext& ctx, SwitchExpectations* expectations) const override; - virtual bool UsageStatsAllowed(const ProductContext& ctx) const override; + bool UsageStatsAllowed(const ProductContext& ctx) const override; }; // Validation rules for Chrome Frame. class ChromeFrameRules : public ProductRules { public: - virtual BrowserDistribution::Type distribution_type() const override; - virtual void AddUninstallSwitchExpectations( + BrowserDistribution::Type distribution_type() const override; + void AddUninstallSwitchExpectations( const ProductContext& ctx, SwitchExpectations* expectations) const override; - virtual void AddRenameSwitchExpectations( + void AddRenameSwitchExpectations( const ProductContext& ctx, SwitchExpectations* expectations) const override; - virtual bool UsageStatsAllowed(const ProductContext& ctx) const override; + bool UsageStatsAllowed(const ProductContext& ctx) const override; }; // Validation rules for the multi-install Chrome binaries. class ChromeBinariesRules : public ProductRules { public: - virtual BrowserDistribution::Type distribution_type() const override; - virtual void AddUninstallSwitchExpectations( + BrowserDistribution::Type distribution_type() const override; + void AddUninstallSwitchExpectations( const ProductContext& ctx, SwitchExpectations* expectations) const override; - virtual void AddRenameSwitchExpectations( + void AddRenameSwitchExpectations( const ProductContext& ctx, SwitchExpectations* expectations) const override; - virtual bool UsageStatsAllowed(const ProductContext& ctx) const override; + bool UsageStatsAllowed(const ProductContext& ctx) const override; }; struct ProductContext {
diff --git a/chrome/installer/util/legacy_firewall_manager_win_unittest.cc b/chrome/installer/util/legacy_firewall_manager_win_unittest.cc index 5fd4638..61e5c24 100644 --- a/chrome/installer/util/legacy_firewall_manager_win_unittest.cc +++ b/chrome/installer/util/legacy_firewall_manager_win_unittest.cc
@@ -16,7 +16,7 @@ protected: // Sets up the test fixture. - virtual void SetUp() override { + void SetUp() override { if (base::GetCurrentProcessIntegrityLevel() != base::HIGH_INTEGRITY) { LOG(WARNING) << "Not elevated. Skipping the test."; return; @@ -29,7 +29,7 @@ } // Tears down the test fixture. - virtual void TearDown() override { + void TearDown() override { if (!skip_test_) manager_.DeleteRule(); }
diff --git a/chrome/installer/util/non_updating_app_registration_data.h b/chrome/installer/util/non_updating_app_registration_data.h index f5d7558..a25f97a0 100644 --- a/chrome/installer/util/non_updating_app_registration_data.h +++ b/chrome/installer/util/non_updating_app_registration_data.h
@@ -14,11 +14,11 @@ class NonUpdatingAppRegistrationData : public AppRegistrationData { public: explicit NonUpdatingAppRegistrationData(const base::string16& key_path); - virtual ~NonUpdatingAppRegistrationData(); - virtual base::string16 GetAppGuid() const override; - virtual base::string16 GetStateKey() const override; - virtual base::string16 GetStateMediumKey() const override; - virtual base::string16 GetVersionKey() const override; + ~NonUpdatingAppRegistrationData() override; + base::string16 GetAppGuid() const override; + base::string16 GetStateKey() const override; + base::string16 GetStateMediumKey() const override; + base::string16 GetVersionKey() const override; private: const base::string16 key_path_;
diff --git a/chrome/installer/util/run_all_unittests.cc b/chrome/installer/util/run_all_unittests.cc index 3e1f5e4..fb1b1d7 100644 --- a/chrome/installer/util/run_all_unittests.cc +++ b/chrome/installer/util/run_all_unittests.cc
@@ -9,7 +9,7 @@ #include "chrome/common/chrome_paths.h" int main(int argc, char** argv) { - TestSuite test_suite(argc, argv); + base::TestSuite test_suite(argc, argv); // Register Chrome Path provider so that we can get test data dir. chrome::RegisterPathProvider();
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc index 469d10d5..548fbb8 100644 --- a/chrome/installer/util/shell_util.cc +++ b/chrome/installer/util/shell_util.cc
@@ -1568,6 +1568,17 @@ const wchar_t* ShellUtil::kRegDelegateExecute = L"DelegateExecute"; const wchar_t* ShellUtil::kRegOpenWithProgids = L"OpenWithProgids"; +ShellUtil::ShortcutProperties::ShortcutProperties(ShellChange level_in) + : level(level_in), + icon_index(0), + dual_mode(false), + pin_to_taskbar(false), + options(0U) { +} + +ShellUtil::ShortcutProperties::~ShortcutProperties() { +} + bool ShellUtil::QuickIsChromeRegisteredInHKLM(BrowserDistribution* dist, const base::FilePath& chrome_exe, const base::string16& suffix) {
diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h index 27e51e4..787e6053 100644 --- a/chrome/installer/util/shell_util.h +++ b/chrome/installer/util/shell_util.h
@@ -92,9 +92,8 @@ PROPERTIES_DUAL_MODE = 1 << 6, }; - explicit ShortcutProperties(ShellChange level_in) - : level(level_in), icon_index(0), dual_mode(false), - pin_to_taskbar(false), options(0U) {} + explicit ShortcutProperties(ShellChange level_in); + ~ShortcutProperties(); // Sets the target executable to launch from this shortcut. // This is mandatory when creating a shortcut.
diff --git a/chrome/installer/util/shell_util_unittest.cc b/chrome/installer/util/shell_util_unittest.cc index 1897e8b3..0294c43 100644 --- a/chrome/installer/util/shell_util_unittest.cc +++ b/chrome/installer/util/shell_util_unittest.cc
@@ -52,7 +52,7 @@ protected: ShellUtilShortcutTest() : test_properties_(ShellUtil::CURRENT_USER) {} - virtual void SetUp() override { + void SetUp() override { dist_ = BrowserDistribution::GetDistribution(); ASSERT_TRUE(dist_ != NULL); product_.reset(new installer::Product(dist_)); @@ -811,7 +811,7 @@ ShellUtilRegistryTest() {} protected: - virtual void SetUp() override { + void SetUp() override { registry_overrides_.OverrideRegistry(HKEY_CURRENT_USER); // .test2 files already have a default application.
diff --git a/chrome/installer/util/updating_app_registration_data.h b/chrome/installer/util/updating_app_registration_data.h index e8afdd3..d9114b9 100644 --- a/chrome/installer/util/updating_app_registration_data.h +++ b/chrome/installer/util/updating_app_registration_data.h
@@ -14,11 +14,11 @@ class UpdatingAppRegistrationData : public AppRegistrationData { public: explicit UpdatingAppRegistrationData(const base::string16& app_guid); - virtual ~UpdatingAppRegistrationData(); - virtual base::string16 GetAppGuid() const override; - virtual base::string16 GetStateKey() const override; - virtual base::string16 GetStateMediumKey() const override; - virtual base::string16 GetVersionKey() const override; + ~UpdatingAppRegistrationData() override; + base::string16 GetAppGuid() const override; + base::string16 GetStateKey() const override; + base::string16 GetStateMediumKey() const override; + base::string16 GetVersionKey() const override; private: const base::string16 app_guid_;
diff --git a/chrome/renderer/autofill/autofill_renderer_browsertest.cc b/chrome/renderer/autofill/autofill_renderer_browsertest.cc index 0ff5d27..e6f4ec1 100644 --- a/chrome/renderer/autofill/autofill_renderer_browsertest.cc +++ b/chrome/renderer/autofill/autofill_renderer_browsertest.cc
@@ -22,6 +22,7 @@ #include "third_party/WebKit/public/web/WebFormElement.h" #include "third_party/WebKit/public/web/WebInputElement.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" +#include "third_party/WebKit/public/web/WebView.h" using base::ASCIIToUTF16; using blink::WebDocument; @@ -245,6 +246,31 @@ EXPECT_FORM_FIELD_DATA_EQUALS(expected, forms[0].fields[8]); } +TEST_F(AutofillRendererTest, IgnoreNonUserGestureTextFieldChanges) { + LoadHTML("<form method='post'>" + " <input type='text' id='full_name'/>" + "</form>"); + + blink::WebInputElement full_name = + GetMainFrame()->document().getElementById("full_name") + .to<blink::WebInputElement>(); + while (!full_name.focused()) + GetMainFrame()->view()->advanceFocus(false); + + // Not a user gesture, so no IPC message to browser. + full_name.setValue("Alice", true); + GetMainFrame()->toWebLocalFrame()->autofillClient()->textFieldDidChange( + full_name); + base::MessageLoop::current()->RunUntilIdle(); + ASSERT_EQ(nullptr, render_thread_->sink().GetFirstMessageMatching( + AutofillHostMsg_TextFieldDidChange::ID)); + + // A user gesture will send a message to the browser. + SimulateUserInputChangeForElement(&full_name, "Alice"); + ASSERT_NE(nullptr, render_thread_->sink().GetFirstMessageMatching( + AutofillHostMsg_TextFieldDidChange::ID)); +} + class RequestAutocompleteRendererTest : public AutofillRendererTest { public: RequestAutocompleteRendererTest()
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc index 394aef8..88d8994a 100644 --- a/chrome/renderer/autofill/form_autofill_browsertest.cc +++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -90,6 +90,7 @@ "</FORM>"; const char kUnownedFormHtml[] = + "<HEAD><TITLE>enter shipping info</TITLE></HEAD>" "<INPUT type='text' id='firstname'/>" "<INPUT type='text' id='lastname'/>" "<INPUT type='hidden' id='imhidden'/>" @@ -1037,6 +1038,7 @@ EXPECT_TRUE( FindFormAndFieldForFormControlElement(firstname, &form, &field)); EXPECT_EQ(GURL(web_frame->document().url()), form.origin); + EXPECT_FALSE(form.origin.is_empty()); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://buh.com"), form.action); @@ -1131,6 +1133,7 @@ EXPECT_TRUE( FindFormAndFieldForFormControlElement(firstname, &form, &field)); EXPECT_EQ(GURL(web_frame->document().url()), form.origin); + EXPECT_FALSE(form.origin.is_empty()); if (!unowned) { EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL("http://buh.com"), form.action); @@ -1918,6 +1921,7 @@ &field)); EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL(frame->document().url()), form.origin); + EXPECT_FALSE(form.origin.is_empty()); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector<FormFieldData>& fields = form.fields; @@ -2030,6 +2034,7 @@ const FormData& form = forms[0]; EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL(web_frame->document().url()), form.origin); + EXPECT_FALSE(form.origin.is_empty()); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector<FormFieldData>& fields = form.fields; @@ -2055,6 +2060,7 @@ const FormData& form2 = forms[1]; EXPECT_EQ(ASCIIToUTF16("TestForm2"), form2.name); EXPECT_EQ(GURL(web_frame->document().url()), form2.origin); + EXPECT_FALSE(form.origin.is_empty()); EXPECT_EQ(GURL("http://zoo.com"), form2.action); const std::vector<FormFieldData>& fields2 = form2.fields; @@ -2277,6 +2283,7 @@ TEST_F(FormAutofillTest, FindFormForInputElementForUnownedForm) { TestFindFormForInputElement( + "<HEAD><TITLE>delivery recipient</TITLE></HEAD>" "<INPUT type='text' id='firstname' value='John'/>" "<INPUT type='text' id='lastname' value='Smith'/>" "<INPUT type='text' id='email' value='john@example.com'" @@ -2304,6 +2311,7 @@ TEST_F(FormAutofillTest, FindFormForTextAreaElementForUnownedForm) { TestFindFormForTextAreaElement( + "<HEAD><TITLE>delivery address</TITLE></HEAD>" "<INPUT type='text' id='firstname' value='John'/>" "<INPUT type='text' id='lastname' value='Smith'/>" "<INPUT type='text' id='email' value='john@example.com'" @@ -3371,6 +3379,7 @@ TEST_F(FormAutofillTest, FillFormMaxLengthForUnownedForm) { TestFillFormMaxLength( + "<HEAD><TITLE>delivery recipient info</TITLE></HEAD>" "<INPUT type='text' id='firstname' maxlength='5'/>" "<INPUT type='text' id='lastname' maxlength='7'/>" "<INPUT type='text' id='email' maxlength='9'/>" @@ -3383,6 +3392,7 @@ // maxlength (defined in WebKit.) TEST_F(FormAutofillTest, FillFormNegativeMaxLength) { TestFillFormNegativeMaxLength( + "<HEAD><TITLE>delivery recipient info</TITLE></HEAD>" "<FORM name='TestForm' action='http://buh.com' method='post'>" " <INPUT type='text' id='firstname' maxlength='-1'/>" " <INPUT type='text' id='lastname' maxlength='-10'/>" @@ -3394,6 +3404,7 @@ TEST_F(FormAutofillTest, FillFormNegativeMaxLengthForUnownedForm) { TestFillFormNegativeMaxLength( + "<HEAD><TITLE>delivery recipient info</TITLE></HEAD>" "<INPUT type='text' id='firstname' maxlength='-1'/>" "<INPUT type='text' id='lastname' maxlength='-10'/>" "<INPUT type='text' id='email' maxlength='-13'/>" @@ -3414,6 +3425,7 @@ TEST_F(FormAutofillTest, FillFormEmptyNameForUnownedForm) { TestFillFormEmptyName( + "<HEAD><TITLE>delivery recipient info</TITLE></HEAD>" "<INPUT type='text' id='firstname'/>" "<INPUT type='text' id='lastname'/>" "<INPUT type='text' id='email'/>" @@ -3440,6 +3452,7 @@ TEST_F(FormAutofillTest, FillFormEmptyFormNamesForUnownedForm) { TestFillFormEmptyFormNames( + "<HEAD><TITLE>enter delivery preferences</TITLE></HEAD>" "<INPUT type='text' id='firstname'/>" "<INPUT type='text' id='middlename'/>" "<INPUT type='text' id='lastname'/>" @@ -3463,7 +3476,6 @@ " <input type='submit' name='reply-send' value='Send'>" "</FORM>"); - WebFrame* frame = GetMainFrame(); ASSERT_NE(nullptr, frame); @@ -3479,6 +3491,7 @@ nullptr)); EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name); EXPECT_EQ(GURL(frame->document().url()), form.origin); + EXPECT_FALSE(form.origin.is_empty()); EXPECT_EQ(GURL("http://cnn.com"), form.action); const std::vector<FormFieldData>& fields = form.fields; @@ -3593,11 +3606,13 @@ } TEST_F(FormAutofillTest, FillFormNonEmptyFieldForUnownedForm) { - TestFillFormNonEmptyField("<INPUT type='text' id='firstname'/>" - "<INPUT type='text' id='lastname'/>" - "<INPUT type='text' id='email'/>" - "<INPUT type='submit' value='Send'/>", - true); + TestFillFormNonEmptyField( + "<HEAD><TITLE>delivery recipient info</TITLE></HEAD>" + "<INPUT type='text' id='firstname'/>" + "<INPUT type='text' id='lastname'/>" + "<INPUT type='text' id='email'/>" + "<INPUT type='submit' value='Send'/>", + true); } TEST_F(FormAutofillTest, ClearFormWithNode) { @@ -3622,6 +3637,7 @@ TEST_F(FormAutofillTest, ClearFormWithNodeForUnownedForm) { TestClearFormWithNode( + "<HEAD><TITLE>store checkout</TITLE></HEAD>" " <!-- Indented on purpose //-->" " <INPUT type='text' id='firstname' value='Wyatt'/>" " <INPUT type='text' id='lastname' value='Earp'/>" @@ -3657,6 +3673,7 @@ TEST_F(FormAutofillTest, ClearFormWithNodeContainingSelectOneForUnownedForm) { TestClearFormWithNodeContainingSelectOne( + "<HEAD><TITLE>store checkout</TITLE></HEAD>" "<INPUT type='text' id='firstname' value='Wyatt'/>" "<INPUT type='text' id='lastname' value='Earp'/>" "<SELECT id='state' name='state'>" @@ -3683,6 +3700,7 @@ TEST_F(FormAutofillTest, ClearPreviewedFormWithElementForUnownedForm) { TestClearPreviewedFormWithElement( + "<HEAD><TITLE>store checkout</TITLE></HEAD>" "<INPUT type='text' id='firstname' value='Wyatt'/>" "<INPUT type='text' id='lastname'/>" "<INPUT type='text' id='email'/>" @@ -3706,6 +3724,7 @@ TEST_F(FormAutofillTest, ClearPreviewedFormWithNonEmptyInitiatingNodeForUnownedForm) { TestClearPreviewedFormWithNonEmptyInitiatingNode( + "<HEAD><TITLE>shipping details</TITLE></HEAD>" "<INPUT type='text' id='firstname' value='W'/>" "<INPUT type='text' id='lastname'/>" "<INPUT type='text' id='email'/>" @@ -3729,6 +3748,7 @@ TEST_F(FormAutofillTest, ClearPreviewedFormWithAutofilledInitiatingNodeForUnownedForm) { TestClearPreviewedFormWithAutofilledInitiatingNode( + "<HEAD><TITLE>shipping details</TITLE></HEAD>" "<INPUT type='text' id='firstname' value='W'/>" "<INPUT type='text' id='lastname'/>" "<INPUT type='text' id='email'/>" @@ -3751,6 +3771,7 @@ TEST_F(FormAutofillTest, ClearOnlyAutofilledFieldsForUnownedForm) { TestClearOnlyAutofilledFields( + "<HEAD><TITLE>shipping details</TITLE></HEAD>" "<INPUT type='text' id='firstname' value='Wyatt'/>" "<INPUT type='text' id='lastname' value='Earp'/>" "<INPUT type='email' id='email' value='wyatt@earp.com'/>" @@ -3913,9 +3934,9 @@ const ExtractMask extract_mask = static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS); - const GURL dummy_origin("http://www.example.com"); - LoadHTML("<DIV>" + LoadHTML("<HEAD><TITLE>delivery info</TITLE></HEAD>" + "<DIV>" " <FIELDSET>" " <LABEL for='firstname'>First name:</LABEL>" " <LABEL for='lastname'>Last name:</LABEL>" @@ -3938,11 +3959,11 @@ FormData form; EXPECT_TRUE(UnownedFormElementsAndFieldSetsToFormData( - fieldsets, control_elements, nullptr, dummy_origin, extract_mask, &form, - nullptr)); + fieldsets, control_elements, nullptr, frame->document(), extract_mask, + &form, nullptr)); EXPECT_TRUE(form.name.empty()); - EXPECT_EQ(dummy_origin, form.origin); + EXPECT_EQ(frame->document().url(), form.origin); EXPECT_FALSE(form.action.is_valid()); const std::vector<FormFieldData>& fields = form.fields; @@ -3975,9 +3996,9 @@ const ExtractMask extract_mask = static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS); - const GURL dummy_origin("http://www.example.com"); - LoadHTML("<DIV>" + LoadHTML("<HEAD><TITLE>shipping details</TITLE></HEAD>" + "<DIV>" " <FIELDSET>" " <LABEL for='firstname'>First name:</LABEL>" " <LABEL for='lastname'>Last name:</LABEL>" @@ -3998,11 +4019,11 @@ FormData form; EXPECT_TRUE(UnownedFormElementsAndFieldSetsToFormData( - fieldsets, control_elements, nullptr, dummy_origin, extract_mask, &form, - nullptr)); + fieldsets, control_elements, nullptr, frame->document(), extract_mask, + &form, nullptr)); EXPECT_TRUE(form.name.empty()); - EXPECT_EQ(dummy_origin, form.origin); + EXPECT_EQ(frame->document().url(), form.origin); EXPECT_FALSE(form.action.is_valid()); const std::vector<FormFieldData>& fields = form.fields; @@ -4034,7 +4055,6 @@ const ExtractMask extract_mask = static_cast<ExtractMask>(EXTRACT_VALUE | EXTRACT_OPTIONS); - const GURL dummy_origin("http://www.example.com"); LoadHTML(kFormHtml); @@ -4048,8 +4068,8 @@ FormData form; EXPECT_FALSE(UnownedFormElementsAndFieldSetsToFormData( - fieldsets, control_elements, nullptr, dummy_origin, extract_mask, &form, - nullptr)); + fieldsets, control_elements, nullptr, frame->document(), extract_mask, + &form, nullptr)); } } // namespace autofill
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index 0b57f44..7ff1938 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -297,40 +297,6 @@ ->textFieldDidEndEditing(input); } - void SimulateInputChangeForElement(const std::string& new_value, - bool move_caret_to_end, - WebFrame* input_frame, - WebInputElement& input, - bool is_user_input) { - input.setValue(WebString::fromUTF8(new_value), is_user_input); - // The field must have focus or AutofillAgent will think the - // change should be ignored. - while (!input.focused()) - input_frame->document().frame()->view()->advanceFocus(false); - if (move_caret_to_end) - input.setSelectionRange(new_value.length(), new_value.length()); - if (is_user_input) { - AutofillMsg_FirstUserGestureObservedInTab msg(0); - content::RenderFrame::FromWebFrame(input_frame)->OnMessageReceived(msg); - - // Also pass the message to the testing object. - if (input_frame == GetMainFrame()) - password_autofill_agent_->FirstUserGestureObserved(); - } - input_frame->toWebLocalFrame()->autofillClient()->textFieldDidChange(input); - // Processing is delayed because of a Blink bug: - // https://bugs.webkit.org/show_bug.cgi?id=16976 - // See PasswordAutofillAgent::TextDidChangeInTextField() for details. - - // Autocomplete will trigger a style recalculation when we put up the next - // frame, but we don't want to wait that long. Instead, trigger a style - // recalcuation manually after TextFieldDidChangeImpl runs. - base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind( - &PasswordAutofillAgentTest::LayoutMainFrame, base::Unretained(this))); - - base::MessageLoop::current()->RunUntilIdle(); - } - void SimulateSuggestionChoice(WebInputElement& username_input) { base::string16 username(base::ASCIIToUTF16(kAliceUsername)); base::string16 password(base::ASCIIToUTF16(kAlicePassword)); @@ -353,26 +319,12 @@ ->OnMessageReceived(msg); } - void LayoutMainFrame() { - GetMainFrame()->view()->layout(); + void SimulateUsernameChange(const std::string& username) { + SimulateUserInputChangeForElement(&username_element_, username); } - void SimulateUsernameChange(const std::string& username, - bool move_caret_to_end, - bool is_user_input = false) { - SimulateInputChangeForElement(username, - move_caret_to_end, - GetMainFrame(), - username_element_, - is_user_input); - } - - void SimulateKeyDownEvent(const WebInputElement& element, - ui::KeyboardCode key_code) { - blink::WebKeyboardEvent key_event; - key_event.windowsKeyCode = key_code; - static_cast<blink::WebAutofillClient*>(autofill_agent_) - ->textFieldDidReceiveKeyDown(element, key_event); + void SimulatePasswordChange(const std::string& password) { + SimulateUserInputChangeForElement(&password_element_, password); } void CheckTextFieldsStateForElements(const WebInputElement& username_element, @@ -688,7 +640,7 @@ SimulateOnFillPasswordForm(fill_data_); // Simulate the user changing the username to some unknown username. - SimulateUsernameChange("alicia", true); + SimulateUsernameChange("alicia"); // The password should have been cleared. CheckTextFieldsState("alicia", false, std::string(), false); @@ -705,31 +657,31 @@ CheckTextFieldsState(std::string(), false, std::string(), false); // No autocomplete should happen when text is entered in the username. - SimulateUsernameChange("a", true); + SimulateUsernameChange("a"); CheckTextFieldsState("a", false, std::string(), false); - SimulateUsernameChange("al", true); + SimulateUsernameChange("al"); CheckTextFieldsState("al", false, std::string(), false); - SimulateUsernameChange(kAliceUsername, true); + SimulateUsernameChange(kAliceUsername); CheckTextFieldsState(kAliceUsername, false, std::string(), false); // Autocomplete should happen only when the username textfield is blurred with // a full match. - username_element_.setValue("a"); + SimulateUsernameChange("a"); static_cast<blink::WebAutofillClient*>(autofill_agent_) ->textFieldDidEndEditing(username_element_); CheckTextFieldsState("a", false, std::string(), false); - username_element_.setValue("al"); + SimulateUsernameChange("al"); static_cast<blink::WebAutofillClient*>(autofill_agent_) ->textFieldDidEndEditing(username_element_); CheckTextFieldsState("al", false, std::string(), false); - username_element_.setValue("alices"); + SimulateUsernameChange("alices"); static_cast<blink::WebAutofillClient*>(autofill_agent_) ->textFieldDidEndEditing(username_element_); CheckTextFieldsState("alices", false, std::string(), false); - username_element_.setValue(ASCIIToUTF16(kAliceUsername)); + SimulateUsernameChange(kAliceUsername); static_cast<blink::WebAutofillClient*>(autofill_agent_) ->textFieldDidEndEditing(username_element_); - CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); + CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); } // Tests that inline autocompletion works properly. @@ -741,57 +693,55 @@ // Simulate the user typing in the first letter of 'alice', a stored // username. - SimulateUsernameChange("a", true); + SimulateUsernameChange("a"); // Both the username and password text fields should reflect selection of the // stored login. - CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); + CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); // And the selection should have been set to 'lice', the last 4 letters. CheckUsernameSelection(1, 5); // Now the user types the next letter of the same username, 'l'. - SimulateUsernameChange("al", true); + SimulateUserTypingASCIICharacter('l', true); // Now the fields should have the same value, but the selection should have a // different start value. - CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); + CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); CheckUsernameSelection(2, 5); - // Test that deleting does not trigger autocomplete. - SimulateKeyDownEvent(username_element_, ui::VKEY_BACK); - SimulateUsernameChange("alic", true); - CheckTextFieldsState("alic", false, std::string(), false); - CheckUsernameSelection(4, 4); // No selection. - // Reset the last pressed key to something other than backspace. - SimulateKeyDownEvent(username_element_, ui::VKEY_A); + // Test that backspace will erase the selection and will stop autocompletion. + SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true); + CheckTextFieldsState("al", false, std::string(), false); + CheckUsernameSelection(2, 2); // No selection. // Now lets say the user goes astray from the stored username and types the // letter 'f', spelling 'alf'. We don't know alf (that's just sad), so in // practice the username should no longer be 'alice' and the selected range // should be empty. - SimulateUsernameChange("alf", true); + SimulateUserTypingASCIICharacter('f', true); CheckTextFieldsState("alf", false, std::string(), false); CheckUsernameSelection(3, 3); // No selection. // Ok, so now the user removes all the text and enters the letter 'b'. - SimulateUsernameChange("b", true); + SimulateUsernameChange("b"); // The username and password fields should match the 'bob' entry. - CheckTextFieldsState(kBobUsername, true, kBobPassword, true); + CheckTextFieldsDOMState(kBobUsername, true, kBobPassword, true); CheckUsernameSelection(1, 3); // Then, the user again removes all the text and types an uppercase 'C'. - SimulateUsernameChange("C", true); + SimulateUsernameChange("C"); // The username and password fields should match the 'Carol' entry. - CheckTextFieldsState(kCarolUsername, true, kCarolPassword, true); + CheckTextFieldsDOMState(kCarolUsername, true, kCarolPassword, true); CheckUsernameSelection(1, 5); + // The user removes all the text and types a lowercase 'c'. We only // want case-sensitive autocompletion, so the username and the selected range // should be empty. - SimulateUsernameChange("c", true); + SimulateUsernameChange("c"); CheckTextFieldsState("c", false, std::string(), false); CheckUsernameSelection(1, 1); // Check that we complete other_possible_usernames as well. - SimulateUsernameChange("R", true); - CheckTextFieldsState(kCarolAlternateUsername, true, kCarolPassword, true); + SimulateUsernameChange("R"); + CheckTextFieldsDOMState(kCarolAlternateUsername, true, kCarolPassword, true); CheckUsernameSelection(1, 17); } @@ -920,8 +870,9 @@ // Simulate the user typing in the username in the iframe which should cause // an autofill. - SimulateInputChangeForElement( - kAliceUsername, true, iframe, username_input, true); + content::RenderFrame::FromWebFrame(iframe) + ->OnMessageReceived(AutofillMsg_FirstUserGestureObservedInTab(0)); + SimulateUserInputChangeForElement(&username_input, kAliceUsername); CheckTextFieldsStateForElements(username_input, kAliceUsername, @@ -1029,9 +980,9 @@ // set directly. SimulateElementClick(kUsernameName); - // Simulate the user entering her username and selecting the matching autofill - // from the dropdown. - SimulateUsernameChange(kAliceUsername, true, true); + // Simulate the user entering the first letter of her username and selecting + // the matching autofill from the dropdown. + SimulateUsernameChange("a"); SimulateSuggestionChoice(username_element_); // The username and password should now have been autocompleted. @@ -1289,10 +1240,10 @@ ClearUsernameAndPasswordFields(); // Simulate the user typing in the first letter of 'alice', a stored username. - SimulateUsernameChange("a", true); + SimulateUsernameChange("a"); // Both the username and password text fields should reflect selection of the // stored login. - CheckTextFieldsState(kAliceUsername, true, kAlicePassword, true); + CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); // The selection should have been set to 'lice', the last 4 letters. CheckUsernameSelection(1, 5); @@ -1314,7 +1265,7 @@ EXPECT_EQ(kAliceUsername, username_element_.value().utf8()); EXPECT_TRUE(username_element_.suggestedValue().isEmpty()); EXPECT_TRUE(username_element_.isAutofilled()); - EXPECT_TRUE(password_element_.value().isEmpty()); + EXPECT_EQ(kAlicePassword, password_element_.value().utf8()); EXPECT_TRUE(password_element_.suggestedValue().isEmpty()); EXPECT_TRUE(password_element_.isAutofilled()); CheckUsernameSelection(1, 5); @@ -1414,17 +1365,18 @@ // Now simulate a user typing in an unrecognized username and then // clicking on the username element. This should also produce a message with // all the usernames. - SimulateUsernameChange("baz", true); + SimulateUsernameChange("baz"); render_thread_->sink().ClearMessages(); static_cast<PageClickListener*>(autofill_agent_) ->FormControlElementClicked(username_element_, true); CheckSuggestions("baz", true); + ClearUsernameAndPasswordFields(); // Now simulate a user typing in the first letter of the username and then // clicking on the username element. While the typing of the first letter will // inline autocomplete, clicking on the element should still produce a full // suggestion list. - SimulateUsernameChange("a", true); + SimulateUsernameChange("a"); render_thread_->sink().ClearMessages(); static_cast<PageClickListener*>(autofill_agent_) ->FormControlElementClicked(username_element_, true); @@ -1520,10 +1472,8 @@ // typed by the user. TEST_F(PasswordAutofillAgentTest, RememberLastNonEmptyUsernameAndPasswordOnSubmit_ScriptCleared) { - SimulateInputChangeForElement( - "temp", true, GetMainFrame(), username_element_, true); - SimulateInputChangeForElement( - "random", true, GetMainFrame(), password_element_, true); + SimulateUsernameChange("temp"); + SimulatePasswordChange("random"); // Simulate that the username and the password value was cleared by the // site's JavaScript before submit. @@ -1543,16 +1493,12 @@ // remembered. TEST_F(PasswordAutofillAgentTest, RememberLastNonEmptyUsernameAndPasswordOnSubmit_UserCleared) { - SimulateInputChangeForElement( - "temp", true, GetMainFrame(), username_element_, true); - SimulateInputChangeForElement( - "random", true, GetMainFrame(), password_element_, true); + SimulateUsernameChange("temp"); + SimulatePasswordChange("random"); // Simulate that the user actually cleared the username and password again. - SimulateInputChangeForElement("", true, GetMainFrame(), username_element_, - true); - SimulateInputChangeForElement( - "", true, GetMainFrame(), password_element_, true); + SimulateUsernameChange(""); + SimulatePasswordChange(""); static_cast<content::RenderFrameObserver*>(password_autofill_agent_) ->WillSubmitForm(username_element_.form()); @@ -1574,10 +1520,8 @@ LoadHTML(kNewPasswordFormHTML); UpdateUsernameAndPasswordElements(); - SimulateInputChangeForElement( - "temp", true, GetMainFrame(), username_element_, true); - SimulateInputChangeForElement( - "random", true, GetMainFrame(), password_element_, true); + SimulateUsernameChange("temp"); + SimulatePasswordChange("random"); // Simulate that the username and the password value was cleared by // the site's JavaScript before submit. @@ -1602,22 +1546,14 @@ fill_data_.wait_for_username = true; SimulateOnFillPasswordForm(fill_data_); // Simulate that the user typed her name to make the autofill work. - SimulateInputChangeForElement(kAliceUsername, - /*move_caret_to_end=*/true, - GetMainFrame(), - username_element_, - /*is_user_input=*/true); + SimulateUsernameChange(kAliceUsername); SimulateDidEndEditing(GetMainFrame(), username_element_); const std::string old_username(username_element_.value().utf8()); const std::string old_password(password_element_.value().utf8()); const std::string new_password(old_password + "modify"); // The user changes the password. - SimulateInputChangeForElement(new_password, - /*move_caret_to_end=*/true, - GetMainFrame(), - password_element_, - /*is_user_input=*/true); + SimulatePasswordChange(new_password); // The user switches back into the username field, but leaves that without // changes. @@ -1637,14 +1573,10 @@ ClearUsernameAndPasswordFields(); // The user enters a password - SimulateInputChangeForElement("someOtherPassword", - /*move_caret_to_end=*/true, - GetMainFrame(), - password_element_, - /*is_user_input=*/true); + SimulatePasswordChange("someOtherPassword"); // Simulate the user typing a stored username. - SimulateUsernameChange(kAliceUsername, true); + SimulateUsernameChange(kAliceUsername); // The autofileld password should replace the typed one. CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); } @@ -1655,10 +1587,8 @@ // typed by the user. TEST_F(PasswordAutofillAgentTest, RememberLastTypedUsernameAndPasswordOnSubmit_ScriptChanged) { - SimulateInputChangeForElement("temp", true, GetMainFrame(), username_element_, - true); - SimulateInputChangeForElement("random", true, GetMainFrame(), - password_element_, true); + SimulateUsernameChange("temp"); + SimulatePasswordChange("random"); // Simulate that the username and the password value was changed by the // site's JavaScript before submit. @@ -1705,10 +1635,8 @@ RememberLastTypedAfterAutofilledUsernameAndPasswordOnSubmit_ScriptChanged) { SimulateOnFillPasswordForm(fill_data_); - SimulateInputChangeForElement("temp", true, GetMainFrame(), username_element_, - true); - SimulateInputChangeForElement("random", true, GetMainFrame(), - password_element_, true); + SimulateUsernameChange("temp"); + SimulatePasswordChange("random"); // Simulate that the username and the password value was changed by the // site's JavaScript before submit. @@ -1728,12 +1656,10 @@ // PasswordAutofillAgent should remember the username that was autofilled, // not last typed. TEST_F(PasswordAutofillAgentTest, RememberAutofilledUsername) { - SimulateInputChangeForElement("Te", true, GetMainFrame(), username_element_, - true); + SimulateUsernameChange("Te"); // Simulate that the username was changed by autofilling. username_element_.setValue(WebString("temp")); - SimulateInputChangeForElement("random", true, GetMainFrame(), - password_element_, true); + SimulatePasswordChange("random"); static_cast<content::RenderFrameObserver*>(password_autofill_agent_) ->WillSendSubmitEvent(username_element_.form()); @@ -1878,12 +1804,9 @@ LoadHTML(kFormHTMLWithTwoTextFields); UpdateUsernameAndPasswordElements(); blink::WebInputElement email_element = GetInputElementByID(kEmailName); - SimulateInputChangeForElement("temp", true, GetMainFrame(), username_element_, - true); - SimulateInputChangeForElement("temp@google.com", true, GetMainFrame(), - email_element, true); - SimulateInputChangeForElement("random", true, GetMainFrame(), - password_element_, true); + SimulateUsernameChange("temp"); + SimulateUserInputChangeForElement(&email_element, "temp@google.com"); + SimulatePasswordChange("random"); static_cast<content::RenderFrameObserver*>(password_autofill_agent_) ->WillSendSubmitEvent(username_element_.form()); static_cast<content::RenderFrameObserver*>(password_autofill_agent_) @@ -1900,13 +1823,9 @@ LoadHTML(kFormHTMLWithTwoTextFields); UpdateUsernameAndPasswordElements(); blink::WebInputElement email_element = GetInputElementByID(kEmailName); - SimulateInputChangeForElement("temp", true, GetMainFrame(), username_element_, - true); - SimulateInputChangeForElement("temp@google.com", true, GetMainFrame(), - email_element, true); - SimulateInputChangeForElement("random", true, GetMainFrame(), - password_element_, true); - + SimulateUsernameChange("temp"); + SimulateUserInputChangeForElement(&email_element, "temp@google.com"); + SimulatePasswordChange("random"); // Find FormData for visible password form. blink::WebFormElement form_element = username_element_.form(); FormData form_data;
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc index 3d0a401..801f0d2d 100644 --- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -19,6 +19,7 @@ #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebWidget.h" +#include "ui/events/keycodes/keyboard_codes.h" using blink::WebDocument; using blink::WebElement; @@ -309,29 +310,18 @@ EXPECT_EQ(password, second_password_element.value()); // After editing the first field they are still the same. - base::string16 edited_password = base::ASCIIToUTF16("edited_password"); - first_password_element.setValue(edited_password); - // Cast to WebAutofillClient where textFieldDidChange() is public. - static_cast<blink::WebAutofillClient*>(autofill_agent_)->textFieldDidChange( - first_password_element); - // textFieldDidChange posts a task, so we need to wait until it's been - // processed. - base::MessageLoop::current()->RunUntilIdle(); + std::string edited_password_ascii = "edited_password"; + SimulateUserInputChangeForElement(&first_password_element, + edited_password_ascii); + base::string16 edited_password = base::ASCIIToUTF16(edited_password_ascii); EXPECT_EQ(edited_password, first_password_element.value()); EXPECT_EQ(edited_password, second_password_element.value()); // Verify that password mirroring works correctly even when the password // is deleted. - base::string16 empty_password; - first_password_element.setValue(empty_password); - // Cast to WebAutofillClient where textFieldDidChange() is public. - static_cast<blink::WebAutofillClient*>(autofill_agent_)->textFieldDidChange( - first_password_element); - // textFieldDidChange posts a task, so we need to wait until it's been - // processed. - base::MessageLoop::current()->RunUntilIdle(); - EXPECT_EQ(empty_password, first_password_element.value()); - EXPECT_EQ(empty_password, second_password_element.value()); + SimulateUserInputChangeForElement(&first_password_element, std::string()); + EXPECT_EQ(base::string16(), first_password_element.value()); + EXPECT_EQ(base::string16(), second_password_element.value()); } TEST_F(PasswordGenerationAgentTest, BlacklistedTest) { @@ -394,15 +384,9 @@ WebInputElement first_password_element = element.to<WebInputElement>(); // Make a password just under maximum offer size. - first_password_element.setValue( - base::ASCIIToUTF16( - std::string(password_generation_->kMaximumOfferSize - 1, 'a'))); - // Cast to WebAutofillClient where textFieldDidChange() is public. - static_cast<blink::WebAutofillClient*>(autofill_agent_)->textFieldDidChange( - first_password_element); - // textFieldDidChange posts a task, so we need to wait until it's been - // processed. - base::MessageLoop::current()->RunUntilIdle(); + SimulateUserInputChangeForElement( + &first_password_element, + std::string(password_generation_->kMaximumOfferSize - 1, 'a')); // There should now be a message to show the UI. ASSERT_EQ(1u, password_generation_->messages().size()); EXPECT_EQ(AutofillHostMsg_ShowPasswordGenerationPopup::ID, @@ -410,15 +394,8 @@ password_generation_->clear_messages(); // Simulate a user typing a password just over maximum offer size. - first_password_element.setValue( - base::ASCIIToUTF16( - std::string(password_generation_->kMaximumOfferSize + 1, 'a'))); - // Cast to WebAutofillClient where textFieldDidChange() is public. - static_cast<blink::WebAutofillClient*>(autofill_agent_)->textFieldDidChange( - first_password_element); - // textFieldDidChange posts a task, so we need to wait until it's been - // processed. - base::MessageLoop::current()->RunUntilIdle(); + SimulateUserTypingASCIICharacter('a', false); + SimulateUserTypingASCIICharacter('a', true); // There should now be a message to hide the UI. ASSERT_EQ(1u, password_generation_->messages().size()); EXPECT_EQ(AutofillHostMsg_HidePasswordGenerationPopup::ID, @@ -427,15 +404,7 @@ // Simulate the user deleting characters. The generation popup should be shown // again. - first_password_element.setValue( - base::ASCIIToUTF16( - std::string(password_generation_->kMaximumOfferSize, 'a'))); - // Cast to WebAutofillClient where textFieldDidChange() is public. - static_cast<blink::WebAutofillClient*>(autofill_agent_)->textFieldDidChange( - first_password_element); - // textFieldDidChange posts a task, so we need to wait until it's been - // processed. - base::MessageLoop::current()->RunUntilIdle(); + SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true); // There should now be a message to show the UI. ASSERT_EQ(1u, password_generation_->messages().size()); EXPECT_EQ(AutofillHostMsg_ShowPasswordGenerationPopup::ID,
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 0c254e7..ad8fee1 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -42,7 +42,6 @@ #include "chrome/renderer/plugins/plugin_preroller.h" #include "chrome/renderer/plugins/plugin_uma.h" #include "chrome/renderer/plugins/shadow_dom_plugin_placeholder.h" -#include "chrome/renderer/prefetch_helper.h" #include "chrome/renderer/prerender/prerender_dispatcher.h" #include "chrome/renderer/prerender/prerender_helper.h" #include "chrome/renderer/prerender/prerender_media_load_deferrer.h" @@ -556,9 +555,7 @@ if (render_frame->GetRenderView()->GetMainRenderFrame() == render_frame) { // Only attach NetErrorHelper to the main frame, since only the main frame // should get error pages. - // PrefetchHelper is also needed only for main frames. new NetErrorHelper(render_frame); - new prefetch::PrefetchHelper(render_frame); } PasswordGenerationAgent* password_generation_agent =
diff --git a/chrome/renderer/prefetch_helper.cc b/chrome/renderer/prefetch_helper.cc deleted file mode 100644 index b64eb19..0000000 --- a/chrome/renderer/prefetch_helper.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright (c) 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/renderer/prefetch_helper.h" - -#include "chrome/common/prefetch_messages.h" -#include "content/public/renderer/render_frame.h" -#include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebURLLoaderOptions.h" - -namespace prefetch { - -PrefetchHelper::PrefetchHelper(content::RenderFrame* render_frame) - : content::RenderFrameObserver(render_frame) { -} - -PrefetchHelper::~PrefetchHelper() { - STLDeleteElements(&loader_set_); -} - -bool PrefetchHelper::OnMessageReceived( - const IPC::Message& message) { - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(PrefetchHelper, message) - IPC_MESSAGE_HANDLER(PrefetchMsg_Prefetch, OnPrefetch) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - - return handled; -} - -void PrefetchHelper::OnPrefetch(const GURL& url) { - blink::WebFrame* frame = render_frame()->GetWebFrame(); - blink::WebURLRequest request(url); - request.setRequestContext(blink::WebURLRequest::RequestContextPrefetch); - request.setPriority(blink::WebURLRequest::PriorityVeryLow); - blink::WebURLLoaderOptions options; - options.allowCredentials = true; - options.crossOriginRequestPolicy = - blink::WebURLLoaderOptions::CrossOriginRequestPolicyAllow; - blink::WebURLLoader* loader = frame->createAssociatedURLLoader(options); - loader->loadAsynchronously(request, this); - loader_set_.insert(loader); -} - -void PrefetchHelper::didFinishLoading(blink::WebURLLoader* loader, - double finishTime, - int64_t totalEncodedDataLength) { - loader_set_.erase(loader); -} - -void PrefetchHelper::didFail(blink::WebURLLoader* loader, - const blink::WebURLError& error) { - loader_set_.erase(loader); -} - -} // namespace prefetch
diff --git a/chrome/renderer/prefetch_helper.h b/chrome/renderer/prefetch_helper.h deleted file mode 100644 index ec44b7a..0000000 --- a/chrome/renderer/prefetch_helper.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright (c) 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 CHROME_RENDERER_PREFETCH_HELPER_H_ -#define CHROME_RENDERER_PREFETCH_HELPER_H_ - -#include <set> - -#include "content/public/renderer/render_frame_observer.h" -#include "third_party/WebKit/public/platform/WebURLLoader.h" -#include "third_party/WebKit/public/platform/WebURLLoaderClient.h" -#include "url/gurl.h" - -namespace prefetch { - -// Helper class initiating prefetches on behalf of a RenderFrame. -class PrefetchHelper : public content::RenderFrameObserver, - public blink::WebURLLoaderClient { - public: - explicit PrefetchHelper(content::RenderFrame* render_frame); - virtual ~PrefetchHelper(); - - // blink::WebURLLoaderClient implementation - virtual void didFinishLoading(blink::WebURLLoader* loader, - double finishTime, - int64_t totalEncodedDataLength) override; - virtual void didFail(blink::WebURLLoader* loader, - const blink::WebURLError& error) override; - - private: - // RenderViewObserver implementation - bool OnMessageReceived(const IPC::Message& message) override; - - void OnPrefetch(const GURL& url); - - std::set<blink::WebURLLoader*> loader_set_; - - DISALLOW_COPY_AND_ASSIGN(PrefetchHelper); -}; - -} // namespace prefetch - -#endif // CHROME_RENDERER_PREFETCH_HELPER_H_
diff --git a/chrome/renderer/prerender/prerender_dispatcher.h b/chrome/renderer/prerender/prerender_dispatcher.h index aa4b7cf4..52038f10 100644 --- a/chrome/renderer/prerender/prerender_dispatcher.h +++ b/chrome/renderer/prerender/prerender_dispatcher.h
@@ -27,7 +27,7 @@ public blink::WebPrerenderingSupport { public: PrerenderDispatcher(); - virtual ~PrerenderDispatcher(); + ~PrerenderDispatcher() override; bool IsPrerenderURL(const GURL& url) const; @@ -46,9 +46,9 @@ bool OnControlMessageReceived(const IPC::Message& message) override; // From WebPrerenderingSupport: - virtual void add(const blink::WebPrerender& prerender) override; - virtual void cancel(const blink::WebPrerender& prerender) override; - virtual void abandon(const blink::WebPrerender& prerender) override; + void add(const blink::WebPrerender& prerender) override; + void cancel(const blink::WebPrerender& prerender) override; + void abandon(const blink::WebPrerender& prerender) override; // From WebKit, prerender elements launched by renderers in our process. std::map<int, blink::WebPrerender> prerenders_;
diff --git a/chrome/renderer/prerender/prerenderer_client.h b/chrome/renderer/prerender/prerenderer_client.h index 92f24d6..134f236 100644 --- a/chrome/renderer/prerender/prerenderer_client.h +++ b/chrome/renderer/prerender/prerenderer_client.h
@@ -20,7 +20,7 @@ ~PrerendererClient() override; // Implements blink::WebPrerendererClient - virtual void willAddPrerender(blink::WebPrerender* prerender) override; + void willAddPrerender(blink::WebPrerender* prerender) override; }; } // namespace prerender
diff --git a/chrome/renderer/resources/extensions/file_system_provider_custom_bindings.js b/chrome/renderer/resources/extensions/file_system_provider_custom_bindings.js index c9b7212..4bf4a82a 100644 --- a/chrome/renderer/resources/extensions/file_system_provider_custom_bindings.js +++ b/chrome/renderer/resources/extensions/file_system_provider_custom_bindings.js
@@ -263,8 +263,6 @@ eventBindings.registerArgumentMassager( 'fileSystemProvider.onMountRequested', function(args, dispatch) { - var executionStart = Date.now(); - var options = args[0]; var onSuccessCallback = function() { // TODO(mtomasz): To be implemented. };
diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js index a158ac4..f6e5b3e 100644 --- a/chrome/renderer/resources/extensions/searchbox_api.js +++ b/chrome/renderer/resources/extensions/searchbox_api.js
@@ -48,7 +48,21 @@ // This method is restricted to chrome-search://most-visited pages by // checking the invoking context's origin in searchbox_extension.cc. this.getMostVisitedItemData = function(restrictedId) { - return GetMostVisitedItemData(restrictedId); + var item = GetMostVisitedItemData(restrictedId); + if (item) { + var sizeInPx = Math.floor(48 * window.devicePixelRatio + 0.5); + // Populate large icon and fallback icon data, if they exist. We'll + // render everything here, once these become available by default. + if (item.largeIconUrl) { + item.largeIconUrl += + sizeInPx + "/" + item.renderViewId + "/" + item.rid; + } + if (item.fallbackIconUrl) { + item.fallbackIconUrl += + sizeInPx + ",,,,/" + item.renderViewId + "/" + item.rid; + } + } + return item; }; this.paste = function(value) { @@ -102,13 +116,16 @@ var mostVisitedItems = GetMostVisitedItems(); for (var i = 0, item; item = mostVisitedItems[i]; ++i) { item.faviconUrl = GenerateFaviconURL(item.renderViewId, item.rid); + // These properties are private data and should not be returned to // the page. They are only accessible via getMostVisitedItemData(). - item.url = null; - item.title = null; - item.domain = null; - item.direction = null; - item.renderViewId = null; + delete item.url; + delete item.title; + delete item.domain; + delete item.direction; + delete item.renderViewId; + delete item.largeIconUrl; + delete item.fallbackIconUrl; } return mostVisitedItems; }
diff --git a/chrome/renderer/resources/plugin_placeholders.css b/chrome/renderer/resources/plugin_placeholders.css index 4bd5fd9ec..cae0362 100644 --- a/chrome/renderer/resources/plugin_placeholders.css +++ b/chrome/renderer/resources/plugin_placeholders.css
@@ -2,12 +2,14 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -body { +html, body { + -webkit-user-select: none; font-family: sans-serif; + height: 100%; margin: 0; overflow: hidden; text-align: center; - -webkit-user-select: none; + width: 100%; } h1 { @@ -37,33 +39,33 @@ } #inner { - position: relative; height: 100%; - width: 100%; - top: 50%; <if expr="not is_android"> margin-top: -70px; </if> <if expr="is_android"> margin-top: -14px; </if> + position: relative; + top: 50%; + width: 100%; } #close { -<if expr="not is_android"> - visibility: hidden; -</if> - cursor: pointer; - position: absolute; - right: 3px; - top: 3px; - height: 14px; - width: 14px; background-image: -webkit-image-set( url(../../../ui/resources/default_100_percent/close_2.png) 1x, url(../../../ui/resources/default_200_percent/close_2.png) 2x); background-position: right top; background-repeat: no-repeat; + cursor: pointer; + height: 14px; + position: absolute; + right: 3px; + top: 3px; +<if expr="not is_android"> + visibility: hidden; +</if> + width: 14px; } #close:hover {
diff --git a/chrome/renderer/resources/plugin_poster.html b/chrome/renderer/resources/plugin_poster.html index 0a3742a6..08eba009 100644 --- a/chrome/renderer/resources/plugin_poster.html +++ b/chrome/renderer/resources/plugin_poster.html
@@ -4,32 +4,32 @@ <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no"> <script> -function notifyDidFinishLoading() { - if (plugin.didFinishLoading) - plugin.didFinishLoading(); -} + window.onload = function() { + if (plugin.didFinishLoading) + plugin.didFinishLoading(); + }; -document.onkeydown = function(e) { - if (e.keyIdentifier == 'Enter' || e.keyIdentifier == 'U+0020') { - plugin.load(); - e.preventDefault(); - } -}; + window.onkeydown = function(e) { + if (e.keyIdentifier == 'Enter' || e.keyIdentifier == 'U+0020') { + plugin.load(); + e.preventDefault(); + } + }; </script> <link rel="stylesheet" href="plugin_placeholders.css"></link> <style> #outer { - position: relative; border: none; cursor: pointer; + position: relative; } #shielding { background-color: rgba(0, 0, 0, 0.5); + height: 100%; + left: 0px; position: absolute; top: 0px; - left: 0px; - height: 100%; width: 100%; z-index: 2; } @@ -44,14 +44,15 @@ #poster { height: 100%; + object-fit: contain; width: 100%; z-index: 1; } #inner_container { height: 100%; - width: 100%; position: relative; + width: 100%; } #inner { @@ -61,8 +62,8 @@ <base i18n-values="href:baseurl"> </head> -<body onload="notifyDidFinishLoading();"> - <div i18n-values="title:name" id="outer" onclick="plugin.load()"> +<body> + <div i18n-values="title:name" id="outer"> <img id="poster" i18n-values="srcset:poster"> <div id="shielding"> <div id="inner_container" @@ -73,5 +74,14 @@ </div> </div> </div> + <script> + document.getElementById('poster').onerror = function() { + this.hidden = true; + }; + + document.getElementById('outer').onclick = function() { + plugin.load(); + }; + </script> </body> </html>
diff --git a/chrome/renderer/searchbox/searchbox_extension.cc b/chrome/renderer/searchbox/searchbox_extension.cc index c9e69b3..727ed9c 100644 --- a/chrome/renderer/searchbox/searchbox_extension.cc +++ b/chrome/renderer/searchbox/searchbox_extension.cc
@@ -117,27 +117,6 @@ "chrome-search://thumb/%d/%d", render_view_id, most_visited_item_id)); } -v8::Handle<v8::String> GenerateLargeIconURL( - v8::Isolate* isolate, - int render_view_id, - InstantRestrictedID most_visited_item_id) { - const int kIconSize = 96; // To support high DPI; on screen it's 48 dp. - return UTF8ToV8String( - isolate, - base::StringPrintf("chrome-search://large-icon/%d/%d/%d", - kIconSize, render_view_id, most_visited_item_id)); -} - -v8::Handle<v8::String> GenerateFallbackIconURL( - v8::Isolate* isolate, - int render_view_id, - InstantRestrictedID most_visited_item_id) { - return UTF8ToV8String( - isolate, - base::StringPrintf("chrome-search://fallback-icon/,,,,1/%d/%d", - render_view_id, most_visited_item_id)); -} - // Populates a Javascript MostVisitedItem object from |mv_item|. // NOTE: Includes "url", "title" and "domain" which are private data, so should // not be returned to the Instant page. These should be erased before returning @@ -178,10 +157,13 @@ if (IsIconNTPEnabled()) { // Update website http://www.chromium.org/embeddedsearch when we make this // permanent. + // Large icon size is 48px * window.devicePixelRatio. This is easier to set + // from JS, where IsIconNTPEnabled() is not available. So we add stubs + // here, and let JS fill in details. obj->Set(v8::String::NewFromUtf8(isolate, "largeIconUrl"), - GenerateLargeIconURL(isolate, render_view_id, restricted_id)); + v8::String::NewFromUtf8(isolate, "chrome-search://large-icon/")); obj->Set(v8::String::NewFromUtf8(isolate, "fallbackIconUrl"), - GenerateFallbackIconURL(isolate, render_view_id, restricted_id)); + v8::String::NewFromUtf8(isolate, "chrome-search://fallback-icon/")); } obj->Set(v8::String::NewFromUtf8(isolate, "title"), UTF16ToV8String(isolate, title));
diff --git a/chrome/renderer/spellchecker/spellcheck_provider.h b/chrome/renderer/spellchecker/spellcheck_provider.h index 4efe504..793b3918 100644 --- a/chrome/renderer/spellchecker/spellcheck_provider.h +++ b/chrome/renderer/spellchecker/spellcheck_provider.h
@@ -68,27 +68,27 @@ blink::WebTextCheckingCompletion* completion); // blink::WebSpellCheckClient implementation. - virtual void spellCheck( + void spellCheck( const blink::WebString& text, int& offset, int& length, blink::WebVector<blink::WebString>* optional_suggestions) override; - virtual void checkTextOfParagraph( + void checkTextOfParagraph( const blink::WebString& text, blink::WebTextCheckingTypeMask mask, blink::WebVector<blink::WebTextCheckingResult>* results) override; - virtual void requestCheckingOfText( + void requestCheckingOfText( const blink::WebString& text, const blink::WebVector<uint32>& markers, const blink::WebVector<unsigned>& marker_offsets, blink::WebTextCheckingCompletion* completion) override; - virtual blink::WebString autoCorrectWord( + blink::WebString autoCorrectWord( const blink::WebString& misspelled_word) override; - virtual void showSpellingUI(bool show) override; - virtual bool isShowingSpellingUI() override; - virtual void updateSpellingUIWithMisspelledWord( + void showSpellingUI(bool show) override; + bool isShowingSpellingUI() override; + void updateSpellingUIWithMisspelledWord( const blink::WebString& word) override; #if !defined(OS_MACOSX)
diff --git a/chrome/renderer/spellchecker/spellcheck_provider_test.h b/chrome/renderer/spellchecker/spellcheck_provider_test.h index 5c1c559..56ab49d 100644 --- a/chrome/renderer/spellchecker/spellcheck_provider_test.h +++ b/chrome/renderer/spellchecker/spellcheck_provider_test.h
@@ -25,10 +25,9 @@ FakeTextCheckingCompletion(); ~FakeTextCheckingCompletion(); - virtual void didFinishCheckingText( + void didFinishCheckingText( const blink::WebVector<blink::WebTextCheckingResult>& results) override; - virtual void didCancelCheckingText() override; - + void didCancelCheckingText() override; size_t completion_count_; size_t cancellation_count_;
diff --git a/chrome/renderer/spellchecker/spellcheck_unittest.cc b/chrome/renderer/spellchecker/spellcheck_unittest.cc index f82ac80..79f150e3 100644 --- a/chrome/renderer/spellchecker/spellcheck_unittest.cc +++ b/chrome/renderer/spellchecker/spellcheck_unittest.cc
@@ -110,14 +110,13 @@ : completion_count_(0) { } - virtual void didFinishCheckingText( - const blink::WebVector<blink::WebTextCheckingResult>& results) - override { + void didFinishCheckingText( + const blink::WebVector<blink::WebTextCheckingResult>& results) override { completion_count_++; last_results_ = results; } - virtual void didCancelCheckingText() override { + void didCancelCheckingText() override { completion_count_++; }
diff --git a/chrome/renderer/translate/translate_helper_browsertest.cc b/chrome/renderer/translate/translate_helper_browsertest.cc index 3c0db27..4c22f80 100644 --- a/chrome/renderer/translate/translate_helper_browsertest.cc +++ b/chrome/renderer/translate/translate_helper_browsertest.cc
@@ -28,7 +28,7 @@ extensions::EXTENSION_GROUP_INTERNAL_TRANSLATE_SCRIPTS, extensions::kExtensionScheme) {} - virtual base::TimeDelta AdjustDelay(int delayInMs) override { + base::TimeDelta AdjustDelay(int delayInMs) override { // Just returns base::TimeDelta() which has initial value 0. // Tasks doesn't need to be delayed in tests. return base::TimeDelta();
diff --git a/chrome/renderer/tts_dispatcher.h b/chrome/renderer/tts_dispatcher.h index cc40403..8dea4c06 100644 --- a/chrome/renderer/tts_dispatcher.h +++ b/chrome/renderer/tts_dispatcher.h
@@ -34,18 +34,17 @@ explicit TtsDispatcher(blink::WebSpeechSynthesizerClient* client); private: - virtual ~TtsDispatcher(); + ~TtsDispatcher() override; // RenderProcessObserver override. bool OnControlMessageReceived(const IPC::Message& message) override; // blink::WebSpeechSynthesizer implementation. - virtual void updateVoiceList() override; - virtual void speak(const blink::WebSpeechSynthesisUtterance& utterance) - override; - virtual void pause() override; - virtual void resume() override; - virtual void cancel() override; + void updateVoiceList() override; + void speak(const blink::WebSpeechSynthesisUtterance& utterance) override; + void pause() override; + void resume() override; + void cancel() override; blink::WebSpeechSynthesisUtterance FindUtterance(int utterance_id);
diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc index 30fb0b4..6aed0ba57 100644 --- a/chrome/service/cloud_print/print_system_win.cc +++ b/chrome/service/cloud_print/print_system_win.cc
@@ -133,28 +133,28 @@ PrintServerWatcherWin() : delegate_(NULL) {} // PrintSystem::PrintServerWatcher implementation. - virtual bool StartWatching( - PrintSystem::PrintServerWatcher::Delegate* delegate) override{ + bool StartWatching( + PrintSystem::PrintServerWatcher::Delegate* delegate) override { delegate_ = delegate; return watcher_.Start(std::string(), this); } - virtual bool StopWatching() override{ + bool StopWatching() override { bool ret = watcher_.Stop(); delegate_ = NULL; return ret; } // PrintSystemWatcherWin::Delegate implementation. - virtual void OnPrinterAdded() override { + void OnPrinterAdded() override { delegate_->OnPrinterAdded(); } - virtual void OnPrinterDeleted() override {} - virtual void OnPrinterChanged() override {} - virtual void OnJobChanged() override {} + void OnPrinterDeleted() override {} + void OnPrinterChanged() override {} + void OnJobChanged() override {} protected: - virtual ~PrintServerWatcherWin() {} + ~PrintServerWatcherWin() override {} private: PrintSystem::PrintServerWatcher::Delegate* delegate_; @@ -173,39 +173,38 @@ } // PrintSystem::PrinterWatcher implementation. - virtual bool StartWatching( - PrintSystem::PrinterWatcher::Delegate* delegate) override { + bool StartWatching(PrintSystem::PrinterWatcher::Delegate* delegate) override { delegate_ = delegate; return watcher_.Start(printer_name_, this); } - virtual bool StopWatching() override { + bool StopWatching() override { bool ret = watcher_.Stop(); delegate_ = NULL; return ret; } - virtual bool GetCurrentPrinterInfo( + bool GetCurrentPrinterInfo( printing::PrinterBasicInfo* printer_info) override { return watcher_.GetCurrentPrinterInfo(printer_info); } // PrintSystemWatcherWin::Delegate implementation. - virtual void OnPrinterAdded() override { + void OnPrinterAdded() override { NOTREACHED(); } - virtual void OnPrinterDeleted() override { + void OnPrinterDeleted() override { delegate_->OnPrinterDeleted(); } - virtual void OnPrinterChanged() override { + void OnPrinterChanged() override { delegate_->OnPrinterChanged(); } - virtual void OnJobChanged() override { + void OnJobChanged() override { delegate_->OnJobChanged(); } protected: - virtual ~PrinterWatcherWin() {} + ~PrinterWatcherWin() override {} private: std::string printer_name_; @@ -220,14 +219,14 @@ JobSpoolerWin() : core_(new Core) {} // PrintSystem::JobSpooler implementation. - virtual bool Spool(const std::string& print_ticket, - const std::string& print_ticket_mime_type, - const base::FilePath& print_data_file_path, - const std::string& print_data_mime_type, - const std::string& printer_name, - const std::string& job_title, - const std::vector<std::string>& tags, - JobSpooler::Delegate* delegate) override { + bool Spool(const std::string& print_ticket, + const std::string& print_ticket_mime_type, + const base::FilePath& print_data_file_path, + const std::string& print_data_mime_type, + const std::string& printer_name, + const std::string& job_title, + const std::vector<std::string>& tags, + JobSpooler::Delegate* delegate) override { // TODO(gene): add tags handling. scoped_refptr<printing::PrintBackend> print_backend( printing::PrintBackend::CreateInstance(NULL)); @@ -239,7 +238,7 @@ } protected: - virtual ~JobSpoolerWin() {} + ~JobSpoolerWin() override {} private: // We use a Core class because we want a separate RefCountedThreadSafe @@ -249,7 +248,7 @@ public: Core() : job_id_(-1), delegate_(NULL), saved_dc_(0) {} - ~Core() {} + ~Core() override {} bool Spool(const std::string& print_ticket, const std::string& print_ticket_mime_type, @@ -331,7 +330,7 @@ } // ServiceUtilityProcessHost::Client implementation. - virtual void OnRenderPDFPagesToMetafilePageDone( + void OnRenderPDFPagesToMetafilePageDone( float scale_factor, const printing::MetafilePlayer& emf) override { PreparePageDCForPrinting(printer_dc_.Get(), scale_factor); @@ -341,14 +340,14 @@ } // ServiceUtilityProcessHost::Client implementation. - virtual void OnRenderPDFPagesToMetafileDone(bool success) override { + void OnRenderPDFPagesToMetafileDone(bool success) override { PrintJobDone(success); } - virtual void OnChildDied() override { PrintJobDone(false); } + void OnChildDied() override { PrintJobDone(false); } // base::win::ObjectWatcher::Delegate implementation. - virtual void OnObjectSignaled(HANDLE object) override { + void OnObjectSignaled(HANDLE object) override { DCHECK(xps_print_job_.get()); DCHECK(object == job_progress_event_.Get()); ResetEvent(job_progress_event_.Get()); @@ -523,12 +522,12 @@ } // ServiceUtilityProcessHost::Client implementation. - virtual void OnChildDied() override { + void OnChildDied() override { OnGetPrinterCapsAndDefaults(false, printer_name_, printing::PrinterCapsAndDefaults()); } - virtual void OnGetPrinterCapsAndDefaults( + void OnGetPrinterCapsAndDefaults( bool succeeded, const std::string& printer_name, const printing::PrinterCapsAndDefaults& caps_and_defaults) override { @@ -537,7 +536,7 @@ Release(); } - virtual void OnGetPrinterSemanticCapsAndDefaults( + void OnGetPrinterSemanticCapsAndDefaults( bool succeeded, const std::string& printer_name, const printing::PrinterSemanticCapsAndDefaults& semantic_info) override { @@ -615,26 +614,26 @@ PrintSystemWin(); // PrintSystem implementation. - virtual PrintSystemResult Init() override; - virtual PrintSystem::PrintSystemResult EnumeratePrinters( + PrintSystemResult Init() override; + PrintSystem::PrintSystemResult EnumeratePrinters( printing::PrinterList* printer_list) override; - virtual void GetPrinterCapsAndDefaults( + void GetPrinterCapsAndDefaults( const std::string& printer_name, const PrinterCapsAndDefaultsCallback& callback) override; - virtual bool IsValidPrinter(const std::string& printer_name) override; - virtual bool ValidatePrintTicket( + bool IsValidPrinter(const std::string& printer_name) override; + bool ValidatePrintTicket( const std::string& printer_name, const std::string& print_ticket_data, const std::string& print_ticket_data_mime_type) override; - virtual bool GetJobDetails(const std::string& printer_name, - PlatformJobId job_id, - PrintJobDetails *job_details) override; - virtual PrintSystem::PrintServerWatcher* CreatePrintServerWatcher() override; - virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher( + bool GetJobDetails(const std::string& printer_name, + PlatformJobId job_id, + PrintJobDetails* job_details) override; + PrintSystem::PrintServerWatcher* CreatePrintServerWatcher() override; + PrintSystem::PrinterWatcher* CreatePrinterWatcher( const std::string& printer_name) override; - virtual PrintSystem::JobSpooler* CreateJobSpooler() override; - virtual bool UseCddAndCjt() override; - virtual std::string GetSupportedMimeTypes() override; + PrintSystem::JobSpooler* CreateJobSpooler() override; + bool UseCddAndCjt() override; + std::string GetSupportedMimeTypes() override; private: std::string PrintSystemWin::GetPrinterDriverInfo(
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc index 50da0b73..765a4308 100644 --- a/chrome/service/service_utility_process_host.cc +++ b/chrome/service/service_utility_process_host.cc
@@ -60,8 +60,7 @@ public: ServiceSandboxedProcessLauncherDelegate() {} - virtual void PreSpawnTarget(sandbox::TargetPolicy* policy, - bool* success) override { + void PreSpawnTarget(sandbox::TargetPolicy* policy, bool* success) override { // Service process may run as windows service and it fails to create a // window station. policy->SetAlternateDesktop(false);
diff --git a/chrome/service/service_utility_process_host.h b/chrome/service/service_utility_process_host.h index db9d884..a69c7ac 100644 --- a/chrome/service/service_utility_process_host.h +++ b/chrome/service/service_utility_process_host.h
@@ -85,7 +85,7 @@ ServiceUtilityProcessHost(Client* client, base::MessageLoopProxy* client_message_loop_proxy); - virtual ~ServiceUtilityProcessHost(); + ~ServiceUtilityProcessHost() override; // Starts a process to render the specified pages in the given PDF file into // a metafile. Currently only implemented for Windows. If the PDF has fewer @@ -113,9 +113,9 @@ virtual base::FilePath GetUtilityProcessCmd(); // ChildProcessHostDelegate implementation: - virtual void OnChildDisconnected() override; - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual const base::Process& GetProcess() const override; + void OnChildDisconnected() override; + bool OnMessageReceived(const IPC::Message& message) override; + const base::Process& GetProcess() const override; private: // Starts a process. Returns true iff it succeeded.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 6a9af83..8268f25 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -720,7 +720,6 @@ # "../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_background_keepalive", # TODO(GYP) # "../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_media_galleries", # TODO(GYP) # "../ppapi/tests/extensions/extensions.gyp:ppapi_tests_extensions_packaged_app", # TODO(GYP) - # "../ppapi/ppapi_tests_mojo.gyp:ppapi_tests_mojo", # TODO(GYP) ] if (is_chromeos) { sources += [ "//third_party/liblouis/nacl_wrapper/liblouis_wrapper_browsertest.cc" ]
diff --git a/chrome/test/base/browser_with_test_window_test.cc b/chrome/test/base/browser_with_test_window_test.cc index 09f57d5..245c9b9b 100644 --- a/chrome/test/base/browser_with_test_window_test.cc +++ b/chrome/test/base/browser_with_test_window_test.cc
@@ -165,12 +165,16 @@ if (controller->GetPendingEntryIndex() >= 0) { test_rfh_tester->SendNavigateWithTransition( controller->GetPendingEntry()->GetPageID(), + controller->GetPendingEntry()->GetUniqueID(), + false, controller->GetPendingEntry()->GetURL(), controller->GetPendingEntry()->GetTransitionType()); } else { test_rfh_tester->SendNavigateWithTransition( controller->GetWebContents()->GetMaxPageIDForSiteInstance( test_rfh->GetSiteInstance()) + 1, + controller->GetPendingEntry()->GetUniqueID(), + true, controller->GetPendingEntry()->GetURL(), controller->GetPendingEntry()->GetTransitionType()); }
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h index dce95477..e3411675 100644 --- a/chrome/test/base/test_browser_window.h +++ b/chrome/test/base/test_browser_window.h
@@ -76,8 +76,8 @@ void UpdateFullscreenWithToolbar(bool with_toolbar) override; bool IsFullscreenWithToolbar() const override; #if defined(OS_WIN) - virtual void SetMetroSnapMode(bool enable) override {} - virtual bool IsInMetroSnapMode() const override; + void SetMetroSnapMode(bool enable) override {} + bool IsInMetroSnapMode() const override; #endif LocationBar* GetLocationBar() const override; void SetFocusToLocationBar(bool select_all) override {}
diff --git a/chrome/test/base/test_chrome_web_ui_controller_factory_browsertest.cc b/chrome/test/base/test_chrome_web_ui_controller_factory_browsertest.cc index 15ef7f9..28ea7a5c 100644 --- a/chrome/test/base/test_chrome_web_ui_controller_factory_browsertest.cc +++ b/chrome/test/base/test_chrome_web_ui_controller_factory_browsertest.cc
@@ -43,7 +43,7 @@ // going to this handler. class TestChromeWebUIControllerFactoryTest : public InProcessBrowserTest { public: - virtual void SetUpOnMainThread() override { + void SetUpOnMainThread() override { content::WebUIControllerFactory::UnregisterFactoryForTesting( ChromeWebUIControllerFactory::GetInstance()); test_factory_.reset(new TestChromeWebUIControllerFactory); @@ -52,7 +52,7 @@ GURL(kChromeTestChromeWebUIControllerFactory).host(), &mock_provider_); } - virtual void TearDownOnMainThread() override { + void TearDownOnMainThread() override { test_factory_->RemoveFactoryOverride( GURL(kChromeTestChromeWebUIControllerFactory).host()); content::WebUIControllerFactory::UnregisterFactoryForTesting(
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc index 1dfbfa20..6f3eba8 100644 --- a/chrome/test/base/testing_profile.cc +++ b/chrome/test/base/testing_profile.cc
@@ -28,7 +28,6 @@ #include "chrome/browser/history/chrome_history_client_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/history/top_sites_factory.h" -#include "chrome/browser/history/top_sites_impl.h" #include "chrome/browser/history/web_history_service_factory.h" #include "chrome/browser/net/pref_proxy_config_tracker.h" #include "chrome/browser/net/proxy_service_factory.h" @@ -66,6 +65,7 @@ #include "components/history/core/browser/history_db_task.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/top_sites.h" +#include "components/history/core/browser/top_sites_impl.h" #include "components/history/core/browser/top_sites_observer.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/core/refcounted_keyed_service.h" @@ -287,13 +287,9 @@ } scoped_refptr<RefcountedKeyedService> BuildTopSites( - content::BrowserContext* profile) { - history::TopSitesImpl* top_sites = new history::TopSitesImpl( - static_cast<Profile*>(profile), history::PrepopulatedPageList()); - top_sites->Init( - profile->GetPath().Append(chrome::kTopSitesFilename), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB)); - return make_scoped_refptr(top_sites); + content::BrowserContext* context) { + return TopSitesFactory::BuildTopSites(context, + history::PrepopulatedPageList()); } } // namespace @@ -959,7 +955,7 @@ content::BrowserPluginGuestManager* TestingProfile::GetGuestManager() { #if defined(ENABLE_EXTENSIONS) - return extensions::GuestViewManager::FromBrowserContextIfAvailable(this); + return extensions::GuestViewManager::FromBrowserContext(this); #else return NULL; #endif
diff --git a/chrome/test/base/ui_test_utils.h b/chrome/test/base/ui_test_utils.h index db5c0e0f..632b861 100644 --- a/chrome/test/base/ui_test_utils.h +++ b/chrome/test/base/ui_test_utils.h
@@ -219,9 +219,9 @@ return true; } - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override { const U* details_ptr = content::Details<U>(details).ptr(); if (details_ptr) details_[source.map_key()] = *details_ptr;
diff --git a/chrome/test/base/web_ui_browser_test_browsertest.cc b/chrome/test/base/web_ui_browser_test_browsertest.cc index fd66ebd8..8ddf2e9 100644 --- a/chrome/test/base/web_ui_browser_test_browsertest.cc +++ b/chrome/test/base/web_ui_browser_test_browsertest.cc
@@ -108,7 +108,7 @@ MOCK_METHOD1(HandleTestPasses, void(const base::ListValue*)); private: - virtual void RegisterMessages() override { + void RegisterMessages() override { web_ui()->RegisterMessageCallback("startAsyncTest", base::Bind(&AsyncWebUIMessageHandler::HandleStartAsyncTest, base::Unretained(this))); @@ -138,12 +138,12 @@ private: // Provide this object's handler. - virtual WebUIMessageHandler* GetMockMessageHandler() override { + WebUIMessageHandler* GetMockMessageHandler() override { return &message_handler_; } // Set up and browse to kDummyURL for all tests. - virtual void SetUpOnMainThread() override { + void SetUpOnMainThread() override { WebUIBrowserTest::SetUpOnMainThread(); AddLibrary(base::FilePath(FILE_PATH_LITERAL("async.js"))); ui_test_utils::NavigateToURL(browser(), GURL(kDummyURL));
diff --git a/chrome/test/data/android/banners/native_app_manifest.json b/chrome/test/data/android/banners/native_app_manifest.json deleted file mode 100644 index f17b499e..0000000 --- a/chrome/test/data/android/banners/native_app_manifest.json +++ /dev/null
@@ -1,7 +0,0 @@ -{ - "prefer_related_applications": true, - "related_applications": [{ - "platform": "play", - "id": "test.package" - }] -}
diff --git a/chrome/test/data/android/banners/native_app_test.html b/chrome/test/data/android/banners/native_app_test.html deleted file mode 100644 index 28f4f6c..0000000 --- a/chrome/test/data/android/banners/native_app_test.html +++ /dev/null
@@ -1,9 +0,0 @@ -<html> - <head> - <title>AppBannerManager test page</title> - <link rel="manifest" href="native_app_manifest.json" /> - </head> - <body> - Promoting the "test.package" package. - </body> -</html>
diff --git a/chrome/test/data/android/banners/native_app_test.png b/chrome/test/data/android/banners/native_app_test.png deleted file mode 100644 index 579808ee..0000000 --- a/chrome/test/data/android/banners/native_app_test.png +++ /dev/null Binary files differ
diff --git a/chrome/test/data/autofill/autofill_noform_dynamic.html b/chrome/test/data/autofill/autofill_noform_dynamic.html index 65ded26..bd3e6eb 100644 --- a/chrome/test/data/autofill/autofill_noform_dynamic.html +++ b/chrome/test/data/autofill/autofill_noform_dynamic.html
@@ -2,7 +2,7 @@ <!-- Autofill test with dynamically created fields, and without a form tag. --> <html> <head> - <title>Dynamic Autofill Test - No Form</title> + <title>Dynamic Autofill Test - No Form - Collects address information</title> <script> function AddFields() { var fields = document.getElementById("fields");
diff --git a/chrome/test/data/autofill/heuristics/input/25_checkout_m_llbean.com.html b/chrome/test/data/autofill/heuristics/input/25_checkout_m_llbean.com.html index 7df7e9f5..830b474 100644 --- a/chrome/test/data/autofill/heuristics/input/25_checkout_m_llbean.com.html +++ b/chrome/test/data/autofill/heuristics/input/25_checkout_m_llbean.com.html
@@ -1,3 +1,5 @@ +<head><title>L.L.Bean Secure Checkout:</title></head> +<form id="stepShippingForm" name="stepShippingForm" class="formElements container_12" autocomplete="off"> <div> <div><select id="shipPersonTitle" name="_1_personTitle" selectedtitle=""> <option value="" selected="selected">Title (optional)</option> <option value="Mr."> Mr.</option> <option value="Mrs."> Mrs.</option> <option value="Ms."> Ms.</option> <option value="Dr."> Dr.</option> <option value="Sir"> Sir</option> </select> </div> <div><label for="shipFirstName">First Name </label><input value="" id="shipFirstName" maxlength="20" name="_1_firstName" type="text" autocomplete="off" autocapitalize="on" autocorrect="off"> <span></span><div></div></div> @@ -30,3 +32,4 @@ <div id="shipLocaleMessage"></div><br> <div> <span> <div><input name="un_jtt_cktbtn_0" type="submit" value="Continue to Billing Address" myclass=""></div> </span> <div><a data-address="" data-step="payment">Return to Previous Recipient</a></div> <div><a data-address="" data-step="payment" href="/shoppingbag.html">Return to Shopping Bag</a></div> <div><a data-address="" data-step="payment" href="/checkout.html#payment">Cancel</a></div> </div> </div> +</form>
diff --git a/chrome/test/data/autofill/heuristics/input/b465571.html b/chrome/test/data/autofill/heuristics/input/b465571.html index 132e736f..ae1162d8 100644 --- a/chrome/test/data/autofill/heuristics/input/b465571.html +++ b/chrome/test/data/autofill/heuristics/input/b465571.html
@@ -1,3 +1,5 @@ + +<form id="checkoutCommand" class="stdForm" action="/checkout" method="post"> <fieldset id="shipAdr"> <ol> <li> <label for="address.name">* Name <span class="fText">(first and last)</span>: </label> @@ -93,3 +95,4 @@ </span> </li> </ol> +</form>
diff --git a/chrome/test/data/autofill/heuristics/input/bug_454366.html b/chrome/test/data/autofill/heuristics/input/bug_454366.html index 6ebcd47..641ca987 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_454366.html +++ b/chrome/test/data/autofill/heuristics/input/bug_454366.html
@@ -1,5 +1,5 @@ <html> -<head></head> +<head><title>Google+ - terms to make this test non-trivial: payment checkout address</title></head> <body> <input type="text name="hist_state" id="hist_state" style="display: none;"> <div class="g-h-f-ci g-h-f-Au">
diff --git a/chrome/test/data/autofill/heuristics/input/bug_454366b.html b/chrome/test/data/autofill/heuristics/input/bug_454366b.html index 32133d4..e87252b 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_454366b.html +++ b/chrome/test/data/autofill/heuristics/input/bug_454366b.html
@@ -1,5 +1,5 @@ <html> -<head></head> +<head><title>Google+ - terms to make this test non-trivial: payment checkout address</title></head> <body> <input type="text name="hist_state" id="hist_state" style="display: none;"> <div class="g-h-f-ci g-h-f-Au">
diff --git a/chrome/test/data/autofill/heuristics/input/bug_459132.html b/chrome/test/data/autofill/heuristics/input/bug_459132.html index 9df9803..d23dbbb 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_459132.html +++ b/chrome/test/data/autofill/heuristics/input/bug_459132.html
@@ -1,6 +1,14 @@ -<div id="fb_mod_personal" class="lh_fbMargin clearfix"> +<form data-dojo-attach-point="containerNode" data-dojo-attach-event="onreset:_onReset,onsubmit:_onSubmit" name="FeedbackForm" lang="en" action="https://www.lufthansa.com/online/portal/lh/de/help_contact/feedback/!ut/p/c5/04_SB8K8xLLM9MSSzPy8xBz9CP0os3hHg2B_U3d350DfMA9jA0czF5OgUFNLC9MAU6B8JE75gAADYnQb4ACOhHR76Uel5-QnAV0ZDnI3bne4mOKXB7kTJI_HJX4e-bmp-gW5oRGVwZ66AI5DSgQ!/dl3/d3/L0lJSklna2tra2tra25wQSEvb013d0FBQVlnQUNFSVFRaUtVUXhnb1lCem5KUUZnQSEvNEJuNHNvMFZnTGE5Mmd6a0xLQnl3ZyEhLzZfQTBTTzVHR0NRTVZIMzBBNkQ0UlU1OTg1UDUvN19BMFNPNUdHQ1FNVkgzMEE2RDRSVTU5MEkwMS9zYS5GZWVkYmFja0lucHV0QWN0aW9uL25vcm1hbC9EZWZhdWx0/?l=en&cid=18002&action=FeedbackInputAction&command=sumbitForm&p=LH&s=DE&l=en&cid=18002&action=FeedbackInputAction&command=sumbitForm&p=LH&s=DE" id="fb_form" method="post" widgetid="fb_form"> + + <!-- Hidden input to disable content header portlet--> + <input type="hidden" name="formSubmitted" value="true"> + <input type="hidden" value="" name="formtype" id="formTypeInput"> + <input type="hidden" name="isFlynet" value="false"> + <input type="hidden" name="categoryId" id="categoryId" value=""> + + <div id="fb_mod_personal" class="lh_fbMargin clearfix"> <div class="fieldwrapper wide"> - <h1>Your personal data</h1> + <h1>Your personal data</h1> </div> <span class="overwriteMessage">Please note that any changes will not be saved to your profile.</span> @@ -15,13 +23,14 @@ <div class="cl"> <div class="fieldwrapper"> <label for="firstname" class="firstname">First name</label> - <div id="firstname"><div class="dijit dijitReset dijitInline dijitLeft fb_protect firstname dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete" id="widget_firstname" role="presentation" widgetid="firstname"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="FirstName_1" type="text" tabindex="0" id="firstname" aria-required="true" maxlength="50" value="" aria-invalid="true"></div></div></div> + <div id="firstname"><div class="dijit dijitReset dijitInline dijitLeft fb_protect firstname dijitTextBox dijitValidationTextBox dijitTextBoxError dijitValidationTextBoxError dijitError" id="widget_firstname" role="presentation" widgetid="firstname"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="FirstName_1" type="text" tabindex="0" id="firstname" aria-required="true" maxlength="50" value="" aria-invalid="true"></div></div></div> </div> </div> + <div class="cl"> <div class="fieldwrapper"> <label for="lastname" class="lastname">Last name</label> - <div id="lastname"><div class="dijit dijitReset dijitInline dijitLeft fb_protect lastname dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete" id="widget_lastname" role="presentation" widgetid="lastname"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="LastName_1" type="text" tabindex="0" id="lastname" aria-required="true" maxlength="50" value="" aria-invalid="true"></div></div></div> + <div id="lastname"><div class="dijit dijitReset dijitInline dijitLeft fb_protect lastname dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete" id="widget_lastname" role="presentation" widgetid="lastname"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="LastName_1" type="text" tabindex="0" id="lastname" aria-required="true" maxlength="50" value="" aria-invalid="false"></div></div></div> </div> </div> </div> @@ -30,16 +39,19 @@ <div class="cl"> <div class="fieldwrapper"> <label for="email" class="email">Email</label> - <div id="email"><div class="dijit dijitReset dijitInline dijitLeft fb_protect email dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete" id="widget_email" role="presentation" widgetid="email"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="Email_1" type="text" tabindex="0" id="email" aria-required="true" value="" aria-invalid="true"></div></div></div> + <div id="email"><div class="dijit dijitReset dijitInline dijitLeft fb_protect email dijitTextBox dijitValidationTextBox dijitTextBoxIncomplete dijitValidationTextBoxIncomplete dijitIncomplete dijitTextBoxFocused dijitValidationTextBoxFocused dijitTextBoxIncompleteFocused dijitValidationTextBoxIncompleteFocused dijitIncompleteFocused dijitFocused" id="widget_email" role="presentation" widgetid="email"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="Email_1" type="text" tabindex="0" id="email" aria-required="true" value="" aria-invalid="false"></div></div></div> </div> </div> + <div class="cl"> <div class="fieldwrapper"> <label for="r_email" class="email">Re-enter email</label> <div id="r_email"><div class="dijit dijitReset dijitInline dijitLeft dijitTextBox dijitValidationTextBox fb_protect email" id="widget_r_email" role="presentation" widgetid="r_email"><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><div class="dijitReset dijitInputField dijitInputContainer"><input class="dijitReset dijitInputInner" data-dojo-attach-point="textbox,focusNode" autocomplete="off" name="rEmail_1" type="text" tabindex="0" id="r_email" aria-required="true" value="" aria-invalid="false"></div></div></div> </div> </div> + </div> + <div class="subtpl clear"> <div class="cl"> <div class="fieldwrapper"> @@ -48,4 +60,742 @@ </div> </div> </div> -/div> +</div> + <div id="fb_mod_catSelector" class="lh_fbMargin clearfix"> + <div class="subtpl"> + <div class="cl w50 firstColumn"> + <h1>What can we do for you?</h1> + <table class="dijit dijitReset dijitInline dijitLeft dijitDownArrowButton fb_protect cat_select1 dijitSelectFixedWidth dijitValidationTextBoxFixedWidth dijitSelect dijitValidationTextBox dijitSelectIncomplete dijitValidationTextBoxIncomplete dijitIncomplete" data-dojo-attach-point="_buttonNode,tableNode,focusNode,_popupStateNode" cellspacing="0" cellpadding="0" role="listbox" aria-haspopup="true" tabindex="0" id="CAT_SELECT_1" aria-required="true" widgetid="CAT_SELECT_1" aria-expanded="false" aria-invalid="true" style="-webkit-user-select: none; display: block; width: auto; font-size: 14px; padding: 1px 0px 1px 10px; margin: 10px 0px 0px;"><tbody role="presentation"><tr role="presentation"><td class="dijitReset dijitStretch dijitButtonContents" role="presentation"><div class="dijitReset dijitInputField dijitButtonText" data-dojo-attach-point="containerNode,textDirNode" role="presentation"><span role="option" class="dijitReset dijitInline dijitSelectLabel dijitValidationTextBoxLabel ">Please select a category</span></div><div class="dijitReset dijitValidationContainer"><input class="dijitReset dijitInputField dijitValidationIcon dijitValidationInner" value="Χ " type="text" tabindex="-1" readonly="readonly" role="presentation"></div><input type="hidden" name="Category_1" data-dojo-attach-point="valueNode" value=" " aria-hidden="true"></td><td class="dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer" data-dojo-attach-point="titleNode" role="presentation"><input class="dijitReset dijitInputField dijitArrowButtonInner" value="â–¼ " type="text" tabindex="-1" readonly="readonly" role="presentation"></td></tr></tbody></table></div> + + <div class="cr w50 secondColumn"> + <p class="x-hidden"> + <iframe src="" id="iInterceptor"></iframe> + </p> + </div> + </div> + <div class="selectorQuestion fb_borderSeperator x-hidden clear"></div> +</div> + + <div id="fb_mod_dynamicWrapper" class="lh_fbMargin x-hidden"> + <h1>Please fill in more detailed information</h1> + + + <div id="fb_mod_cstm_wrp" class="fb_borderSeperator x-hidden"> + <div id="fb_mod_address" class="x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Your address</h3> + </div> + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="street_name" class="street_name">Street name</label> + <div id="street_name"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper"> + <label for="street_no" class="street_no">Number</label> + <div id="street_no"></div> + </div> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="zip" class="zip">ZIP</label> + <div id="zip"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper"> + <label for="city" class="city">City</label> + <div id="city"></div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="fieldwrapper"> + <label for="address_details" class="addressDetails">Additional address line <span class="optional"><span> </span>optional</span></label> + <div id="address_details"></div> + </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="country" class="country">Country</label> + <div id="country"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper x-hidden"> + <label for="regions" class="regions">State / Region</label> + <div id="regions"> </div> + </div> + </div> + </div> +</div> + <div id="fb_mod_phone" class="x-hidden"> + <div class="subtpl clear"> + <label for="phone" class="phone">Telephone</label> + <div class="cl"> + <div class="fieldwrapper wide"> + <div id="phone_country"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper wide"> + <div id="phone_area"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper wide"> + <div id="phone_number"></div> + </div> + </div> + </div> +</div> + +<div id="fb_mod_customer2" class="x-hidden fb_borderSeperator"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Personal data of customer <a href="#" id="passenger2" class="fb_removePassenger"><span>Remove</span></a></h3> + </div> + + <div class="subtpl"> + <div class="fieldwrapper"> + <div id="adressChkBox2"> + <label for="adressCheckbox2" class="customerChk">Copy address above</label> + </div> + </div> + </div> + + <div class="subtpl clear"> + <div class="fieldwrapper"> + <label for="title2" class="title">Title</label> + <div id="title2"></div> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="firstname2" class="firstname">First name</label> + <div id="firstname2"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper"> + <label for="lastname2" class="lastname">Last name</label> + <div id="lastname2"></div> + </div> + </div> + </div> + + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="email2" class="email">Email</label> + <div id="email2"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <label for="r_email2" class="email">Re-enter email</label> + <div id="r_email2"></div> + </div> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="mam_number2" class="mam_number">Miles & More number</label> + <div id="mam_number2"></div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="street_name2" class="street_name">Street name</label> + <div id="street_name2"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper"> + <label for="street_no2" class="street_no">Number</label> + <div id="street_no2"></div> + </div> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="zip2" class="zip">ZIP</label> + <div id="zip2"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <label for="city2" class="city">City</label> + <div id="city2"></div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="fieldwrapper"> + <label for="address_details2" class="addressDetails">Additional address line</label> + <div id="address_details2"></div> + </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="country2" class="country">Country</label> + <div id="country2"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper x-hidden"> + <label for="regions2">State / Region</label> + <div id="regions2"> </div> + </div> + </div> + </div> + + <div class="subtpl clear"> + <label for="phone2" class="phone">Telephone</label> + <div class="cl"> + <div class="fieldwrapper"> + <div id="phone_country2" class="cl"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <div id="phone_area2"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <div id="phone_number2" class="cl"></div> + </div> + </div> + </div> +</div> + +<div id="fb_mod_customer3" class="x-hidden fb_borderSeperator"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Personal data of customer <a href="#" id="passenger3" class="fb_removePassenger"><span>Remove</span></a></h3> + </div> + + <div class="subtpl"> + <div class="fieldwrapper"> + <div id="adressChkBox3"> + <label for="adressCheckbox3" class="customerChk">Copy address above</label> + </div> + </div> + </div> + + <div class="subtpl clear"> + <div class="fieldwrapper"> + <label for="title3" class="title">Title</label> + <div id="title3"></div> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="firstname3" class="firstname">First name</label> + <div id="firstname3"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper"> + <label for="lastname3" class="lastname">Last name</label> + <div id="lastname3"></div> + </div> + </div> + </div> + + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="email3" class="email">Email</label> + <div id="email3"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <label for="r_email3" class="email">Re-enter email</label> + <div id="r_email3"></div> + </div> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="mam_number3" class="mam_number">Miles & More number</label> + <div id="mam_number3"></div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="street_name3" class="street_name">Street name</label> + <div id="street_name3"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper"> + <label for="street_no3" class="street_no">Number</label> + <div id="street_no3"></div> + </div> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="zip3" class="zip">ZIP</label> + <div id="zip3"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <label for="city3" class="city">City</label> + <div id="city3"></div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="fieldwrapper"> + <label for="address_details3" class="addressDetails">Additional address line</label> + <div id="address_details3"></div> + </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="country3" class="country">Country</label> + <div id="country3"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper x-hidden"> + <label for="regions3">State / Region</label> + <div id="regions3"> </div> + </div> + </div> + </div> + + <div class="subtpl clear"> + <label for="phone3" class="phone">Telephone</label> + <div class="cl"> + <div class="fieldwrapper"> + <div id="phone_country3" class="cl"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <div id="phone_area3"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <div id="phone_number3" class="cl"></div> + </div> + </div> + </div> +</div> + + <div id="addCustomer"></div> + </div> + + + <div id="fb_mod_prm"> + <div id="fb_mod_flightDetails" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Flight information</h3> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="fd_file_key">File key</label> + <div id="fd_FileKey"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper"> + <label for="fd_flight_number" class="flight_number">Flight number</label> <span class="flight_number_prefix">LH</span> + <div id="fd_FlightNumber"></div> + </div> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="fd_flight_date">Flight date</label> + <div id="fd_flight_date"> + <input type="text" id="FlightDate2" name="FlightDate2" class="fb_protect datepicker" widgetid="FlightDate2" readonly=""> + <input type="hidden" id="FlightDateHidden2" name="FlightDateHidden2" disabled=""> + </div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="fd_flight_time">Flight time</label> + <div id="fd_FlightTime"></div> + </div> + </div> + </div> +</div> + <div id="fb_mod_assistanceType" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Please choose the appropriate option</h3> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <div id="at_LongDistances"></div> + <label for="at_long_distances_radio" class="fb_radio">I cannot walk long distances, however, short distances and stairs are no problem</label> + </div> + </div> + </div> + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <div id="at_Staircases"></div> + <label for="at_staircases_radio" class="fb_radio">I can walk short and long distances, but I have difficulties with stairs</label> + </div> + </div> + </div> + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper wide"> + <div id="at_Walking"></div> + <label for="at_walking_radio" class="fb_radio">I cannot walk at all</label> + </div> + </div> + </div> +</div> + <div id="fb_mod_disabilityType" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <div id="dt_Blind"></div> + <label for="dt_blind_chkbox" class="fb_radio">I am blind or have a severe visual impairment.</label> + </div> + </div> + </div> + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <div id="dt_Deaf"></div> + <label for="dt_deaf_chkbox" class="fb_radio">I am deaf or have a severe hearing impairment</label> + </div> + </div> + </div> + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper wide"> + <div id="dt_Dpna"></div> + <label for="dt_dpna_chkbox" class="fb_radio">I need help finding my way around</label> + </div> + </div> + </div> +</div> + <div id="fb_mod_companionReasons" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <div id="cr_Hc"></div> + <label for="cr_hc_radio" class="fb_radio">I have to travel with an especially trained dog due to my handicap</label> + </div> + </div> + </div> + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper wide"> + <div id="cr_Pr"></div> + <label for="cr_pr_radio" class="fb_radio">I need to travel in companionship of a dog due to psychological reasons</label> + </div> + </div> + </div> +</div> + <div class="subtpl"> + <div class="cr"> + <div id="fd_reset" class="x-hidden"></div> + </div> + </div> + +</div> + <div id="fb_mod_pir" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Property Irregularity Report Number (PIR)</h3> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="pir">PIR number / File Reference (e.g. FRALH12345)</label> + <div id="pir"></div> + </div> + </div> + </div> +</div> + <div id="fb_mod_flight" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Flight information<span class="optional"><span> </span>optional</span></h3> + </div> + <div class="subtpl"> + <div class="fieldwrapper"> + <label for="FlightDate" class="flightDate">Flight date</label> + <input type="text" id="FlightDate" name="FlightDate" class="fb_protect datepicker" widgetid="FlightDate" readonly=""> + <input type="hidden" id="FlightDateHidden" name="FlightDateHidden" disabled=""> + </div> + </div> + + <div class="subtpl clear"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="airline" class="airline">Airline</label> + <div id="airline"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper"> + <label for="flight_number" class="flight_number">Flight number</label> <span class="flight_number_prefix"></span> + <div id="flight_number"></div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="fieldwrapper"> + <label for="seat_number" class="seat_number">Seat number</label> + <div id="seat_number"></div> + </div> + </div> + + <div class="subtpl clear"> + <div class="fieldwrapper wide aa-link"> + <label for="f-originName0" class="origin">Origin</label> + <input type="text" autocomplete="off" id="f-originName0" name="originName"> + <input type="hidden" id="f-originCode0" name="originCode"> + <a href="#" id="lnk-origin" data-dojo-type="lh.widget.AirportAtlas" data-dojo-props="fieldId:'f-originName0',hiddenFieldId:'f-originCode0',url:'/dlvutils/AirportAtlasApplication?app=FB&selected=DE&lang=en',serviceUrl:'/dlvutils/AirportAtlasApplication', app:'FB', language:'en'"> + <span class="airport-dir"> </span> + </a> + <div id="lh-typeahead-append-node-f-origin0" class="dijitMenu" tabindex="-1" style="display:none;"> + <div id="lh-typeahead-close-f-origin0" class="dijitMenuCloseButton">close</div></div> + <div id="lh-airport-f-origin0" style="display:none;"></div> + </div> + </div> + + <div class="subtpl clear"> + <div class="fieldwrapper wide aa-link"> + <label for="f-destinationName0">Destination</label> + <input type="text" autocomplete="off" id="f-destinationName0" name="destinationName"> + <input type="hidden" id="f-destinationCode0" name="destinationCode"> + <a href="#" id="lnk-destination" data-dojo-type="lh.widget.AirportAtlas" data-dojo-props="fieldId:'f-destinationName0',hiddenFieldId:'f-destinationCode0',url:'/dlvutils/AirportAtlasApplication?app=FB&lang=en',serviceUrl:'/dlvutils/AirportAtlasApplication', app:'FB', language:'en'"> + <span class="airport-dir"> </span> + </a> + <div id="lh-typeahead-append-node-f-destination0" class="dijitMenu" tabindex="-1" style="display:none;"> + <div id="lh-typeahead-close-f-destination0" class="dijitMenuCloseButton">close</div></div> + <div id="lh-airport-f-destination" style="display:none;"></div> + </div> + </div> +</div> + <div id="fb_mod_ticket" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Ticket / booking information<a class="infoMessage" title="Information" id="ticket_toolTip1" href="javascript:void(0);"> </a></h3> + </div> + <div connectid="ticket_toolTip1" dojotype="dijit.Tooltip" showdelay="250" label="Please enter your ticketnumber (s. ticket) or the booking code / filekey from your booking confirmation" class="dijitTooltipData" id="dijit_Tooltip_3" lang="en" widgetid="dijit_Tooltip_3"> </div> + + <div class="fbRadioWrapper"> + <div class="fieldwrapper wide"> + <label for="ticket_no" class="marginLeft">Ticket number</label> + <div id="ticket_no"></div> + </div> + </div> + + <div class="fbRadioWrapper"> + <div class="fieldwrapper wide"> + <label for="file_key" class="marginLeft">File key</label> + <div id="file_key"></div> + </div> + </div> +</div> + <div id="fb_mod_refund" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Refund <a class="infoMessage" title="Information" id="ticket_toolTip1" href="javascript:void(0);"> </a></h3> + <div connectid="ticket_toolTip1" dojotype="dijit.Tooltip" showdelay="250" label="Please enter your details" class="dijitTooltipData" id="dijit_Tooltip_4" lang="en" widgetid="dijit_Tooltip_4"> </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <div id="refundTicketChkbox"> + <label for="refundTicketCheckbox" class="customerChk">Refund entire ticket</label> + </div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="refund_reason">Refund reason</label> + <div id="refund_reason"></div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="refund_filey_key" class="refund_file_key">File key <span class="optional"><span> </span>optional</span></label> + <div id="refund_file_key"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="ticket_no_lh" class="ticket_no_lh">Ticket number</label> + <span class="ticket_number_prefix">220</span><div id="ticket_no_lh"></div> + </div> + </div> + </div> + + <div class="subtpl x-hidden"> + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="refund_segment">Travel segments to be refunded</label> + <div id="refund_segment"></div> + </div> + </div> + </div> +</div> + <div id="fb_mod_bank" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Bank account information<a class="infoMessage" id="bank_toolTip1" href="javascript:void(0);"> </a></h3> + <div connectid="bank_toolTip1" dojotype="dijit.Tooltip" showdelay="250" label="Please enter your bank account information" class="dijitTooltipData" id="dijit_Tooltip_5" lang="en" widgetid="dijit_Tooltip_5"> </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper"> + <label for="card_holder">Account holder</label> + <div id="card_holder"></div> + </div> + </div> + <div class="cl"> + <div class="fieldwrapper"> + <label for="bank_name">Bank name</label> + <div id="bank_name"></div> + </div> + </div> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="iban">IBAN Number</label> + <div id="iban"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="bic">SWIFT/BIC code</label> + <div id="bic"></div> + </div> + </div> + </div> +</div> + <div id="fb_mod_technial" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Technical information</h3> + </div> + + <div class="subtpl"> + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="browser">Browser name</label> + <div id="browser"></div> + </div> + </div> + + <div class="cl"> + <div class="fieldwrapper wide"> + <label for="os">Operating system</label> + <div id="os"></div> + </div> + </div> + </div> +</div> + <div id="fb_mod_feedbackID" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Feedback ID</h3> + </div> + + <div class="subtpl"> + <div class="fieldwrapper wide"> + <label for="feedbackId">Please enter your feedback ID</label> + <div id="feedbackId"></div> + </div> + </div> +</div> + <div id="fb_mod_comment" class="lh_fbMargin fb_borderSeperator x-hidden"> + <div class="fieldwrapper wide"> + <h3 class="pi_containerSubline">Your feedback or question</h3> + </div> + <div class="fieldwrapper wide"> + <div id="comment"></div> + </div> +</div> + + + </div> + + + <input type="hidden" class="x-fup-hd-filename" name="FileName_1" id="attach_filename_1" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_2" id="attach_filename_2" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_3" id="attach_filename_3" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_4" id="attach_filename_4" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_5" id="attach_filename_5" value=""> + <input type="hidden" class="x-fup-hd-filename" name="FileName_6" id="attach_filename_6" value=""> <br> + + <input type="hidden" class="x-fup-hd-fileid" name="FileId_1" id="attach_fileid_1" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_2" id="attach_fileid_2" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_3" id="attach_fileid_3" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_4" id="attach_fileid_4" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_5" id="attach_fileid_5" value=""> + <input type="hidden" class="x-fup-hd-fileid" name="FileId_6" id="attach_fileid_6" value=""> + + + </form>
diff --git a/chrome/test/data/autofill/heuristics/input/bug_460832.html b/chrome/test/data/autofill/heuristics/input/bug_460832.html index 0c98cfa02..734d9daf 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_460832.html +++ b/chrome/test/data/autofill/heuristics/input/bug_460832.html
@@ -1,3 +1,6 @@ +<head> + <title>Google.com - Calendar - terms to make this test non-trivial: payments checkout address</title> +</head> <div class="ep" data-eid="foo"> <div class="ep-ea noprint"> <div id=":27.print-btn" class="ep-ea-btn-wrapper ep-ea-print-btn">
diff --git a/chrome/test/data/autofill/heuristics/input/bug_462080.html b/chrome/test/data/autofill/heuristics/input/bug_462080.html index 1b66d24..382f65e 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_462080.html +++ b/chrome/test/data/autofill/heuristics/input/bug_462080.html
@@ -1,3 +1,6 @@ +<head> +<title><title>payment instructions - Google Slides</title></title> +</head> <div class="modal-dialog-content"> <div class="simple-sharing-contents"> <div class="simple-sharing-link-area">
diff --git a/chrome/test/data/autofill/heuristics/input/bug_463856.html b/chrome/test/data/autofill/heuristics/input/bug_463856.html index fe112c8..482a117 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_463856.html +++ b/chrome/test/data/autofill/heuristics/input/bug_463856.html
@@ -1,3 +1,6 @@ +<head> + <title>Google+ - terms to make this test non-trivial: payment checkout address</title> +</head> <input name="hist_state" type="text"></input> <input placeholder="Location (optional)" type="text"></input> <input name="sbdp" placeholder="+ Invite names, circles, or email addresses" type="text"></input>
diff --git a/chrome/test/data/autofill/heuristics/input/bug_465053.html b/chrome/test/data/autofill/heuristics/input/bug_465053.html index 511aae1..1e06b98 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_465053.html +++ b/chrome/test/data/autofill/heuristics/input/bug_465053.html
@@ -1,3 +1,7 @@ +<head> + <title>Google Developers Console</title> +</head> +<form class="p6n-billing-freetrial-signup-form p6n-align-left p6n-form ng-pristine ng-scope ng-invalid ng-invalid-required" name="controller.signupForm"> <div class="creation-form-content" data-value="creditCard"> <div id="creditCardForm" class="instrument-form payments-instruments-creditcard" data-component-name="CREDIT_CARD"> <div class="b3-credit-card-field b3-card-number-input-container"><img class="b3id-detected-card-icon card-icon-images-row" style="display: none;"> @@ -180,3 +184,4 @@ <input type="hidden" id="creditCardForm.supportedCountries" name="supportedCountries" value="["AD","AE","AF","AG","AI","AL","AM","AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB","BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO","BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD","CF","CG","CH","CI","CK","CL","CM","CN","CO","CR","CV","CX","CY","CZ","DE","DJ","DK","DM","DO","DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ","FK","FM","FO","FR","GA","GB","GD","GE","GF","GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT","GU","GW","GY","HK","HM","HN","HR","HT","HU","ID","IE","IL","IN","IO","IQ","IS","IT","JM","JO","JP","KE","KG","KH","KI","KM","KN","KR","KW","KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT","LU","LV","LY","MA","MC","MD","ME","MG","MH","MK","ML","MN","MO","MP","MQ","MR","MS","MT","MU","MV","MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF","PG","PH","PK","PL","PM","PN","PR","PS","PT","PW","PY","QA","RE","RO","RS","RU","RW","SA","SB","SC","SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO","SR","ST","SV","SZ","TC","TD","TF","TG","TH","TJ","TK","TL","TM","TN","TO","TR","TT","TV","TW","TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE","VG","VI","VN","VU","WF","WS","YE","YT","ZA","ZM","ZW"]"> </div> </div> +</form>
diff --git a/chrome/test/data/autofill/heuristics/input/bug_465576.html b/chrome/test/data/autofill/heuristics/input/bug_465576.html index d44c735..809a019 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_465576.html +++ b/chrome/test/data/autofill/heuristics/input/bug_465576.html
@@ -1,3 +1,7 @@ +<head> + <title>NikeStore</title> +</head> +<form id="creditCardForm" method="post" action="/payment/checkout/addNewCard.htm?country=US&view=html&billingCountry=US&langLocale=en_US" novalidate=""> <div id="creditCardFormContainer"> <div class="cardNotification hidden"> <div class="nsg-form--global-message--alert"> @@ -110,3 +114,4 @@ </div> </div> </div> +</form>
diff --git a/chrome/test/data/autofill/heuristics/input/bug_471748.html b/chrome/test/data/autofill/heuristics/input/bug_471748.html index 27b9ac3f..0ef0e3b 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_471748.html +++ b/chrome/test/data/autofill/heuristics/input/bug_471748.html
@@ -1,41 +1,46 @@ -<div class="pay_method"> - <h3 class="h_check">Pay with Credit Card:</h3> +<head> + <title>Payment Information</title> +</head> +<form name="info" method="post" action="https://www.runningwarehouse.com/finalcheckout.html" id="creditcard"> + <div class="pay_method"> + <h3 class="h_check">Pay with Credit Card:</h3> - <div class="saved_wrap clearfix"> + <div class="saved_wrap clearfix"> - </div> + </div> - <div id="fade_card"> - <div class="cc_row card_type cf"> - <label for="cctype">Card Type:</label> - <div class="cc_selwrap"> - <div class="dropdownbox"><div class="current_selection"><span class="selection_text" title="Visa">Visa</span><span class="drop_arrow"><span></span></span></div><ul class="optionslist"><li class="option selected">Visa</li><li class="option">MasterCard</li><li class="option">American Express</li><li class="option">Discover</li></ul></div><select name="ccType" id="cctype" class="fancy_select" style="display: none;"> - <option value="VISA" selected="">Visa</option> - <option value="MASTERCARD">MasterCard</option> - <option value="AMEX">American Express</option> - <option value="DISCOVER">Discover</option> - </select> + <div id="fade_card"> + <div class="cc_row card_type cf"> + <label for="cctype">Card Type:</label> + <div class="cc_selwrap"> + <div class="dropdownbox"><div class="current_selection"><span class="selection_text" title="Visa">Visa</span><span class="drop_arrow"><span></span></span></div><ul class="optionslist"><li class="option selected">Visa</li><li class="option">MasterCard</li><li class="option">American Express</li><li class="option">Discover</li></ul></div><select name="ccType" id="cctype" class="fancy_select" style="display: none;"> + <option value="VISA" selected="">Visa</option> + <option value="MASTERCARD">MasterCard</option> + <option value="AMEX">American Express</option> + <option value="DISCOVER">Discover</option> + </select> + </div> + <div class="cc_iconwrap"> + <span class="cc_icon ic_visa selected">Visa</span> + <span class="cc_icon ic_mc">MasterCard</span> + <span class="cc_icon ic_ae">American Express</span> + <span class="cc_icon ic_disc">Discover</span> + </div> </div> - <div class="cc_iconwrap"> - <span class="cc_icon ic_visa selected">Visa</span> - <span class="cc_icon ic_mc">MasterCard</span> - <span class="cc_icon ic_ae">American Express</span> - <span class="cc_icon ic_disc">Discover</span> + <div class="cc_row cc_num"> + <label for="cardnum">Card #:</label> + <input type="text" name="cardnum" id="cardnum" maxlength="19" class="check_text"> + </div> + <div class="cc_row"> + <label for="expdate">Expire Date:</label> + <input type="text" name="expdate" id="expdate" maxlength="5" class="check_text"> + <span>MM/YY</span> + </div> + <div class="cc_row"> + <label for="cvv2">CCV2:</label> + <input type="text" name="cvv2" id="cvv2" maxlength="4" class="check_text"> + <a href="https://www.runningwarehouse.com/cvv2.html#cvv2_info" class="lightboxpop" data-boxheight="375" data-boxwidth="500">what's this?</a> </div> </div> - <div class="cc_row cc_num"> - <label for="cardnum">Card #:</label> - <input type="text" name="cardnum" id="cardnum" maxlength="19" class="check_text"> - </div> - <div class="cc_row"> - <label for="expdate">Expire Date:</label> - <input type="text" name="expdate" id="expdate" maxlength="5" class="check_text"> - <span>MM/YY</span> - </div> - <div class="cc_row"> - <label for="cvv2">CCV2:</label> - <input type="text" name="cvv2" id="cvv2" maxlength="4" class="check_text"> - <a href="https://www.runningwarehouse.com/cvv2.html#cvv2_info" class="lightboxpop" data-boxheight="375" data-boxwidth="500">what's this?</a> - </div> </div> -</div> +</form>
diff --git a/chrome/test/data/autofill/heuristics/input/bug_471831.html b/chrome/test/data/autofill/heuristics/input/bug_471831.html index e9298e1..e976141 100644 --- a/chrome/test/data/autofill/heuristics/input/bug_471831.html +++ b/chrome/test/data/autofill/heuristics/input/bug_471831.html
@@ -1,3 +1,7 @@ +<head> + <title>Stripe: Checkout</title> +</head> +<form class="checkoutView" method="POST" novalidate="true"> <div class="layoutView paymentView" style="opacity: 1; height: 291px; transition: none; -webkit-transition: none; transform: translateX(0px); overflow: inherit;"> <div class="layoutSubview" style="height: 55px; transform: translateY(0px); opacity: 1; transition: none; -webkit-transition: none;"> <div class="emailInput input"> @@ -93,3 +97,4 @@ </div> </div> </div> +</form>
diff --git a/chrome/test/data/autofill/heuristics/output/b465571.out b/chrome/test/data/autofill/heuristics/output/b465571.out index 51b6bcc..74f090d 100644 --- a/chrome/test/data/autofill/heuristics/output/b465571.out +++ b/chrome/test/data/autofill/heuristics/output/b465571.out
@@ -5,5 +5,5 @@ ADDRESS_HOME_STATE | address.state | * State: | | address.name_1-default ADDRESS_HOME_ZIP | address.postalCode | * Zip: | | address.name_1-default PHONE_HOME_WHOLE_NUMBER | address.phoneNumber | * Phone Number: | | address.name_1-default -UNKNOWN_TYPE | address.rememberedAsBoolean | | true | address.name_1-default -UNKNOWN_TYPE | address.primary | | true | address.name_1-default +UNKNOWN_TYPE | address.rememberedAsBoolean | Save this shipping address for future orders. | true | address.name_1-default +UNKNOWN_TYPE | address.primary | Make this my primary shipping address. | true | address.name_1-default
diff --git a/chrome/test/data/autofill/heuristics/output/bug_459132.out b/chrome/test/data/autofill/heuristics/output/bug_459132.out index 86bf84a7..60f7d22 100644 --- a/chrome/test/data/autofill/heuristics/output/bug_459132.out +++ b/chrome/test/data/autofill/heuristics/output/bug_459132.out
@@ -10,3 +10,9 @@ EMAIL_ADDRESS | rEmail_1 | Re-enter email | | _1-default UNKNOWN_TYPE | | Miles & More number optional | Χ | _1-default UNKNOWN_TYPE | MamNumber_1 | Miles & More number optional | | _1-default +UNKNOWN_TYPE | | Please select a category | Χ | _1-default +UNKNOWN_TYPE | | Please select a category | â–¼ | _1-default +UNKNOWN_TYPE | FlightDate2 | Flight date | | _1-default +UNKNOWN_TYPE | FlightDate | Flight date | | _1-default +UNKNOWN_TYPE | originName | Origin | | _1-default +UNKNOWN_TYPE | destinationName | Destination | | _1-default
diff --git a/chrome/test/data/autofill/heuristics/output/bug_465576.out b/chrome/test/data/autofill/heuristics/output/bug_465576.out index 5ace284..0577aad 100644 --- a/chrome/test/data/autofill/heuristics/output/bug_465576.out +++ b/chrome/test/data/autofill/heuristics/output/bug_465576.out
@@ -2,5 +2,5 @@ CREDIT_CARD_NUMBER | creditCardNumber | Card Number * | | cardTypeSelect_1-cc CREDIT_CARD_EXP_MONTH | expirationMonth | Expiry Date * | | cardTypeSelect_1-cc CREDIT_CARD_EXP_4_DIGIT_YEAR | expirationYear | Expiry Date * | | cardTypeSelect_1-cc -CREDIT_CARD_VERIFICATION_CODE | cvNumber | Where do I find this? | | cardTypeSelect_1-cc +CREDIT_CARD_VERIFICATION_CODE | cvNumber | security code * | | cardTypeSelect_1-cc PHONE_HOME_WHOLE_NUMBER | phoneNumber | Billing Phone Your registered number with your payment issuer is required to process your order. * | | cardTypeSelect_1-default
diff --git a/chrome/test/data/autofill/heuristics/output/bug_471748.out b/chrome/test/data/autofill/heuristics/output/bug_471748.out index 6aa4821..6f4d1d3 100644 --- a/chrome/test/data/autofill/heuristics/output/bug_471748.out +++ b/chrome/test/data/autofill/heuristics/output/bug_471748.out
@@ -1,4 +1,4 @@ -CREDIT_CARD_TYPE | ccType | VisaVisaMasterCardAmerican ExpressDiscover | VISA | ccType_1-cc +CREDIT_CARD_TYPE | ccType | Card Type: | VISA | ccType_1-cc CREDIT_CARD_NUMBER | cardnum | Card #: | | ccType_1-cc CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR | expdate | Expire Date: | | ccType_1-cc CREDIT_CARD_VERIFICATION_CODE | cvv2 | CCV2: | | ccType_1-cc
diff --git a/chrome/test/data/extensions/api_test/activity_log_private/test/test.js b/chrome/test/data/extensions/api_test/activity_log_private/test/test.js index 35a00cb4..15667c16 100644 --- a/chrome/test/data/extensions/api_test/activity_log_private/test/test.js +++ b/chrome/test/data/extensions/api_test/activity_log_private/test/test.js
@@ -526,4 +526,17 @@ }); } -setupTestCasesAndRun(); +// Temporarily disable this unittest in order to rename +// blink::EventTargetNames::LocalDOMWindow to +// blink::EventTargetNames::DOMWindow. +// see http://crrev.com/1086663003 and http://crrev.com/1088943008 +// +// The plan is +// 1) Disable the test temporarily. +// 2) Rename LocalDOMWindow to DOMWindow in blink. +// 3) Rename LocalDOMWindow to DOMWindow in this test and enable the test. +// +// TODO(yukishiino): Enable this test. +// +// setupTestCasesAndRun(); +chrome.test.runTests([]);
diff --git a/chrome/test/data/extensions/api_test/bookmarks/manifest.json b/chrome/test/data/extensions/api_test/bookmarks/manifest.json index 3ba97066..cc9c3b04 100644 --- a/chrome/test/data/extensions/api_test/bookmarks/manifest.json +++ b/chrome/test/data/extensions/api_test/bookmarks/manifest.json
@@ -4,6 +4,7 @@ "manifest_version": 2, "description": "end-to-end browser test for chrome.bookmarks API", "background": { + "persistent": false, "scripts": ["test.js"] }, "permissions": ["bookmarks"]
diff --git a/chrome/test/data/extensions/api_test/developer/generated_output/behllobkkfkfnphdnhnkndlbkcpglgmj.json b/chrome/test/data/extensions/api_test/developer/generated_output/behllobkkfkfnphdnhnkndlbkcpglgmj.json index df1a9be..bf12798 100644 --- a/chrome/test/data/extensions/api_test/developer/generated_output/behllobkkfkfnphdnhnkndlbkcpglgmj.json +++ b/chrome/test/data/extensions/api_test/developer/generated_output/behllobkkfkfnphdnhnkndlbkcpglgmj.json
@@ -19,7 +19,6 @@ "specified": false, "url": "" }, - "iconUrl": "chrome://extension-icon/behllobkkfkfnphdnhnkndlbkcpglgmj/48/1", "id": "behllobkkfkfnphdnhnkndlbkcpglgmj", "incognitoAccess": { "isActive": false,
diff --git a/chrome/test/data/extensions/api_test/developer/generated_output/bjafgdebaacbbbecmhlhpofkepfkgcpa.json b/chrome/test/data/extensions/api_test/developer/generated_output/bjafgdebaacbbbecmhlhpofkepfkgcpa.json index 1ca9149f6..c91b13a 100644 --- a/chrome/test/data/extensions/api_test/developer/generated_output/bjafgdebaacbbbecmhlhpofkepfkgcpa.json +++ b/chrome/test/data/extensions/api_test/developer/generated_output/bjafgdebaacbbbecmhlhpofkepfkgcpa.json
@@ -19,7 +19,6 @@ "specified": false, "url": "" }, - "iconUrl": "chrome://extension-icon/bjafgdebaacbbbecmhlhpofkepfkgcpa/48/1", "id": "bjafgdebaacbbbecmhlhpofkepfkgcpa", "incognitoAccess": { "isActive": false,
diff --git a/chrome/test/data/extensions/api_test/developer/generated_output/hpiknbiabeeppbpihjehijgoemciehgk.json b/chrome/test/data/extensions/api_test/developer/generated_output/hpiknbiabeeppbpihjehijgoemciehgk.json index 3c5f298..cc40a40 100644 --- a/chrome/test/data/extensions/api_test/developer/generated_output/hpiknbiabeeppbpihjehijgoemciehgk.json +++ b/chrome/test/data/extensions/api_test/developer/generated_output/hpiknbiabeeppbpihjehijgoemciehgk.json
@@ -19,7 +19,6 @@ "specified": false, "url": "" }, - "iconUrl": "chrome://extension-icon/hpiknbiabeeppbpihjehijgoemciehgk/48/1", "id": "hpiknbiabeeppbpihjehijgoemciehgk", "incognitoAccess": { "isActive": false,
diff --git a/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/background.js b/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/background.js new file mode 100644 index 0000000..633ebde --- /dev/null +++ b/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/background.js
@@ -0,0 +1,7 @@ +// Copyright (c) 2013 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. + +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('window.html'); +});
diff --git a/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/manifest.json b/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/manifest.json new file mode 100644 index 0000000..753b1b0 --- /dev/null +++ b/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/manifest.json
@@ -0,0 +1,12 @@ +{ + "name": "App window, 'display-mode' media feature test", + "description": "tests the 'display mode' media feature for the fullscreened app window", + "version": "1", + "manifest_version": 2, + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "permissions": [ ] +}
diff --git a/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/window.html b/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/window.html new file mode 100644 index 0000000..ff97be2 --- /dev/null +++ b/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/window.html
@@ -0,0 +1,10 @@ +<!-- + * Copyright (c) 2012 The Chromium Authors. All rights reserved. Use of this + * source code is governed by a BSD-style license that can be found in the + * LICENSE file. +--> +<html> +<body> +<script src="window.js"></script> +</body> +</html>
diff --git a/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/window.js b/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/window.js new file mode 100644 index 0000000..99e5bb54 --- /dev/null +++ b/chrome/test/data/extensions/api_test/fullscreen/mq_display_mode/window.js
@@ -0,0 +1,30 @@ +// Copyright (c) 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. +function checkWindowRestored() { + var standalone = matchMedia( '(display-mode: standalone)' ); + chrome.test.assertTrue(standalone.matches, + "Display mode of the restored window is 'standalone'"); + + chrome.test.succeed(); +} + +function checkWindowFullscreened() { + var fullscreen = matchMedia( '(display-mode: fullscreen)' ); + chrome.test.assertTrue(fullscreen.matches, + "Display mode of the fullscreened window is 'fullscreen'"); + + window.onresize = checkWindowRestored; + chrome.app.window.current().restore(); +} + +window.onload = function() { + function checkDisplayModeMediaFeature() { + var standalone = matchMedia( '(display-mode: standalone)' ); + chrome.test.assertTrue(standalone.matches, + "Initially display mode is 'standalone'"); + window.onresize = checkWindowFullscreened; + chrome.app.window.current().fullscreen(); + }; + chrome.test.runTests([checkDisplayModeMediaFeature]); +}
diff --git a/chrome/test/data/extensions/api_test/gcd_private/api/session.js b/chrome/test/data/extensions/api_test/gcd_private/api/session.js index 0139e0d4..dcbe90c 100644 --- a/chrome/test/data/extensions/api_test/gcd_private/api/session.js +++ b/chrome/test/data/extensions/api_test/gcd_private/api/session.js
@@ -29,7 +29,8 @@ chrome.test.notifyPass(); } - chrome.gcdPrivate.establishSession("1.2.3.4", 9090, onSessionEstablished); + chrome.gcdPrivate.createSession("myService._privet._tcp.local", + onSessionEstablished); } ]); };
diff --git a/chrome/test/data/extensions/api_test/search_engines_private/main.html b/chrome/test/data/extensions/api_test/search_engines_private/main.html new file mode 100644 index 0000000..c401f14 --- /dev/null +++ b/chrome/test/data/extensions/api_test/search_engines_private/main.html
@@ -0,0 +1,11 @@ +<!-- + * 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. +--> +<script src="test.js"></script> + +<html> +<head><title>searchEnginesPrivate component API interface test</title></head> +<body><h2>chrome.searchEnginesPrivate.* tests</h2></body> +</html>
diff --git a/chrome/test/data/extensions/api_test/search_engines_private/manifest.json b/chrome/test/data/extensions/api_test/search_engines_private/manifest.json new file mode 100644 index 0000000..2d18ce0 --- /dev/null +++ b/chrome/test/data/extensions/api_test/search_engines_private/manifest.json
@@ -0,0 +1,10 @@ +{ + "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC74Vbx3EbhPc/FOvn6+HxCjMSml0HdPMiuRjj5a3b+MnRML1iJ9OAgbKUYJ/u3s25/cGq8pNB0NbyupHGEqvqAE7TcNr1mdgs0PWxh2IOI1GKrxlzxpqzQuFmxq5WHKr5RrwZ4/Xq0t/+e8JkvhZdW0jarz/28Jom0gkM5lorsewIDAQAB", + "name": "searchEnginesPrivate API interface test", + "version": "0.1", + "manifest_version": 2, + "description": "Test of chrome.searchEnginesPrivate interface", + "permissions": [ + "searchEnginesPrivate" + ] +}
diff --git a/chrome/test/data/extensions/api_test/search_engines_private/test.js b/chrome/test/data/extensions/api_test/search_engines_private/test.js new file mode 100644 index 0000000..4e52b7e --- /dev/null +++ b/chrome/test/data/extensions/api_test/search_engines_private/test.js
@@ -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. + +// This just tests the interface. It does not test for specific results, only +// that callbacks are correctly invoked, expected parameters are correct, +// and failures are detected. + +function callbackResult(result) { + if (chrome.runtime.lastError) + chrome.test.fail(chrome.runtime.lastError.message); + else if (result == false) + chrome.test.fail('Failed: ' + result); +} + +var availableTests = [ + function setSelectedSearchEngine() { + chrome.searchEnginesPrivate.getDefaultSearchEngines(function(engines) { + chrome.searchEnginesPrivate.setSelectedSearchEngine( + engines[engines.length - 1].guid); + chrome.searchEnginesPrivate.getDefaultSearchEngines(function(newEngines) { + chrome.test.assertTrue(newEngines[newEngines.length - 1].isSelected); + chrome.test.succeed(); + }); + }); + }, + + function onDefaultSearchEnginesChanged() { + chrome.searchEnginesPrivate.onDefaultSearchEnginesChanged.addListener( + function(engines) { + chrome.test.assertTrue(engines[1].isSelected, + 'Engine 1 should be selected'); + chrome.test.succeed(); + }); + chrome.searchEnginesPrivate.getDefaultSearchEngines(function(engines) { + chrome.searchEnginesPrivate.setSelectedSearchEngine(engines[1].guid); + }); + } +]; + +var testToRun = window.location.search.substring(1); +chrome.test.runTests(availableTests.filter(function(op) { + return op.name == testToRun; +})); +
diff --git a/chrome/test/data/extensions/api_test/window_open/panel/test.js b/chrome/test/data/extensions/api_test/window_open/panel/test.js index f55054db..780e3111 100644 --- a/chrome/test/data/extensions/api_test/window_open/panel/test.js +++ b/chrome/test/data/extensions/api_test/window_open/panel/test.js
@@ -3,9 +3,19 @@ // found in the LICENSE file. var panelWindowId = 0; +var panelLoaded = false; // This function is called by the panel during the test run. function panelCallback() { + panelLoaded = true; + maybeReadyForTest(); +} + +function maybeReadyForTest() { + // The order of the two callbacks is not guaranteed. + if( panelWindowId === 0 || !panelLoaded) + return; + // We have now added a panel so the total counts is 2 (browser + panel). chrome.test.assertEq(2, chrome.extension.getViews().length); // Verify that we're able to get the view of the panel by its window id. @@ -29,6 +39,7 @@ chrome.test.assertEq(true, win.alwaysOnTop); panelWindowId = win.id; // The panel will call back to us through panelCallback (above). + maybeReadyForTest(); }); } ]);
diff --git a/chrome/test/data/extensions/fullscreen_app/blank.html b/chrome/test/data/extensions/fullscreen_app/blank.html index 17071824..1641069 100644 --- a/chrome/test/data/extensions/fullscreen_app/blank.html +++ b/chrome/test/data/extensions/fullscreen_app/blank.html
@@ -1 +1,5 @@ -<html><head></head><body></body></html> \ No newline at end of file +<html> +<head></head> +<body></body> +<script src="check_media_feature.js" type="text/javascript"></script> +</html>
diff --git a/chrome/test/data/extensions/fullscreen_app/check_media_feature.js b/chrome/test/data/extensions/fullscreen_app/check_media_feature.js new file mode 100644 index 0000000..7f37900f --- /dev/null +++ b/chrome/test/data/extensions/fullscreen_app/check_media_feature.js
@@ -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. +var fullscreen = matchMedia( '(display-mode: fullscreen)' ); +var p = document.createElement("p"); +document.body.appendChild(p); +if (fullscreen.matches) { + p.innerHTML = "(display-mode: fullscreen) matches."; + p.style.color = "green"; +} else { + p.innerHTML = "(display-mode: fullscreen) does not match."; + p.style.color = "red"; +}
diff --git a/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/embedder.js b/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/embedder.js index 435c5cb..5d41fa5 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/embedder.js +++ b/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/embedder.js
@@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var LOG = function(msg) { window.console.log(msg); }; +var LOG = function(var_args) { + window.console.log(Array.prototype.slice.call(arguments)); +}; function ClearDataTester() { this.webview_ = null; @@ -19,62 +21,123 @@ ClearDataTester.prototype.setWebview = function(webview) { this.webview_ = webview; + this.webview_.onconsolemessage = this.onGuestConsoleMessage_.bind(this); }; +ClearDataTester.prototype.onGuestConsoleMessage_ = function(e) { + LOG('G:', e.message); + if (e.message == 'ERROR') { + this.fail(); + } +}; + +ClearDataTester.prototype.requestXhrFromWebView_ = function() { + var msg = ['sendXhr']; + this.webview_.contentWindow.postMessage(JSON.stringify(msg), '*'); +}; + +ClearDataTester.prototype.fail = function() { + chrome.test.sendMessage('TEST_FAILED'); +}; + +ClearDataTester.prototype.pass = function() { + chrome.test.sendMessage('TEST_PASSED'); +}; + +// This test instructs a <webview> to load same resource request via xhr +// multiple times. That makes some of those requests to be served from +// http cache. +// Calling clearData{cache: true} resets the cache and next request +// from the same resource should not be served from cache. ClearDataTester.prototype.testClearDataCache = function() { - this.webview_.clearData( - {since: 10}, {"cache": true}, function doneCallback() { - LOG('clearData done'); - chrome.test.sendMessage('WebViewTest.CLEAR_DATA_DONE'); - }); + // Request same resource multiple times from <webview>, latter + // ones would be served from cache. + var responseCount = 0; + var servedFromCacheCount = 0; + + var responseStartedHandler = function(details) { + LOG('onResponseStarted, url:', details.url, + 'fromCache:', details.fromCache); + if (details.url.indexOf('/cache-control-response') == -1) { + return; + } + + ++responseCount; + if (details.fromCache) { + ++servedFromCacheCount; + } + + if (responseCount == 5) { + // We should see some request getting served from cache. + if (servedFromCacheCount <= 0) { + this.fail(); + return; + } + + // Clear cache from <webview>. + this.webview_.clearData( + {since: 10}, {'cache': true}, function doneCallback() { + LOG('clearData done'); + this.requestXhrFromWebView_(); + // Now request the same resource again, this time it should + // not be served from cache. + this.requestXhrFromWebView_(); + }.bind(this)); + } else if (responseCount == 6) { + if (details.fromCache) { + // Response received after clearData should not be served from cache. + this.fail(); + } else { + this.pass(); + } + } + }.bind(this); + + this.webview_.request.onResponseStarted.addListener( + responseStartedHandler, {urls: ['<all_urls>']}); + + for (var i = 0; i < 5; ++i) { + this.requestXhrFromWebView_(); + } }; var tester = new ClearDataTester(); // window.* exported functions begin. -window.testClearDataCache = function() { - LOG('window.testClearDataCache'); - tester.testClearDataCache(); +window.runTest = function(testName) { + switch (testName) { + case 'testClearCache': + tester.testClearDataCache(); + break; + default: + LOG('curious test to run:', testName); + tester.fail(); + break; + } }; // window.* exported functions end. -function setUpTest(messageCallback) { - var guestUrl = 'data:text/html,<html><body>guest</body></html>'; +function setUpTest(guestURL, doneCallback) { var webview = document.createElement('webview'); webview.onloadstop = function(e) { LOG('webview has loaded.'); - webview.executeScript( - {file: 'guest.js'}, - function(results) { - if (!results || !results.length) { - chrome.test.sendMessage('WebViewTest.FAILURE'); - return; - } - LOG('Script has been injected into webview.'); - // Establish a communication channel with the guest. - var msg = ['connect']; - webview.contentWindow.postMessage(JSON.stringify(msg), '*'); - }); + doneCallback(webview); }; - window.addEventListener('message', function(e) { - var data = JSON.parse(e.data); - if (data[0] == 'connected') { - console.log('A communication channel has been established with webview.'); - } - messageCallback(webview); - }); - - webview.setAttribute('src', guestUrl); + webview.setAttribute('src', guestURL); document.body.appendChild(webview); } onload = function() { chrome.test.getConfig(function(config) { - setUpTest(function(webview) { + LOG('config: ' + config.testServer.port); + var guestURL = 'http://localhost:' + config.testServer.port + + '/extensions/platform_apps/web_view/clear_data_cache/guest.html'; + setUpTest(guestURL, function(webview) { LOG('Guest load completed.'); - chrome.test.sendMessage('WebViewTest.LAUNCHED'); + //chrome.test.sendMessage('WebViewTest.LAUNCHED'); + chrome.test.sendMessage('Launched'); tester.setWebview(webview); }); });
diff --git a/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/guest.html b/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/guest.html new file mode 100644 index 0000000..74e3cff --- /dev/null +++ b/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/guest.html
@@ -0,0 +1,10 @@ +<!-- + * 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. +--> +<html> +<body> + <script src="guest.js"></script> +</body> +</html>
diff --git a/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/guest.js b/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/guest.js index 6b90df3..72b5aea 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/guest.js +++ b/chrome/test/data/extensions/platform_apps/web_view/clear_data_cache/guest.js
@@ -5,24 +5,33 @@ var LOG = function(msg) { window.console.log(msg); }; LOG('Guest script loading.'); -// The window reference of the embedder to send post message reply. -var embedderWindowChannel = null; +var fail = function() { + // Embedder catches this message and fails the test. + LOG('ERROR'); +}; -// A value that uniquely identifies the guest sending the messages to the -// embedder. -var channelId = 0; -var notifyEmbedder = function(msg_array) { - var msg = msg_array.concat([channelId]); - embedderWindowChannel.postMessage(JSON.stringify(msg), '*'); +var sendXhr = function() { + var xhr = new XMLHttpRequest(); + xhr.onload = function() { + LOG('xhr.onload'); + if (xhr.responseText != 'dummy text') { + fail(); + } + }; + xhr.onerror = function() { + fail(); + }; + xhr.open('GET', '/cache-control-response', true); + xhr.send(); }; var onPostMessageReceived = function(e) { - embedderWindowChannel = e.source; var data = JSON.parse(e.data); - if (data[0] == 'connect') { - channelId = data[1]; - notifyEmbedder(['connected']); + if (data[0] != 'sendXhr') { + fail(); return; } + + sendXhr(); }; window.addEventListener('message', onPostMessageReceived, false);
diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js index e423621..7a4887ee 100644 --- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js +++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
@@ -764,12 +764,12 @@ function testAddContentScript() { var webview = document.createElement('webview'); - console.log("Step 1: call <webview>.addContentScripts."); + console.log('Step 1: call <webview>.addContentScripts.'); webview.addContentScripts( [{"name": 'myrule', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel.js"], - "run_at": "document_start"}]); + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel.js'], + "run_at": 'document_start'}]); webview.addEventListener('loadstop', function() { var msg = [request_to_comm_channel_1]; @@ -798,16 +798,16 @@ function testAddMultipleContentScripts() { var webview = document.createElement('webview'); - console.log("Step 1: call <webview>.addContentScripts(myrule1 & myrule2)"); + console.log('Step 1: call <webview>.addContentScripts(myrule1 & myrule2)'); webview.addContentScripts( [{"name": 'myrule1', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel.js"], - "run_at": "document_start"}, + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel.js'], + "run_at": 'document_start'}, {"name": 'myrule2', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel_2.js"], - "run_at": "document_start"}]); + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel_2.js'], + "run_at": 'document_start'}]); webview.addEventListener('loadstop', function() { var msg1 = [request_to_comm_channel_1]; @@ -851,12 +851,12 @@ function testAddContentScriptWithSameNameShouldOverwriteTheExistingOne() { var webview = document.createElement('webview'); - console.log("Step 1: call <webview>.addContentScripts(myrule1)"); + console.log('Step 1: call <webview>.addContentScripts(myrule1)'); webview.addContentScripts( [{"name": 'myrule1', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel.js"], - "run_at": "document_start"}]); + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel.js'], + "run_at": 'document_start'}]); var connect_script_1 = true; var connect_script_2 = false; @@ -883,9 +883,9 @@ ); webview.addContentScripts( [{"name": 'myrule1', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel_2.js"], - "run_at": "document_start"}]); + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel_2.js'], + "run_at": 'document_start'}]); connect_script_2 = true; should_get_response_from_script_1 = false; webview.src = embedder.emptyGuestURL; @@ -917,15 +917,15 @@ var webview1 = document.createElement('webview'); var webview2 = document.createElement('webview'); - console.log("Step 1: call <webview1>.addContentScripts."); + console.log('Step 1: call <webview1>.addContentScripts.'); webview1.addContentScripts( [{"name": 'myrule', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel.js"], - "run_at": "document_start"}]); + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel.js'], + "run_at": 'document_start'}]); webview2.addEventListener('loadstop', function() { - console.log("Step 2: webview2 requests to build communication channel."); + console.log('Step 2: webview2 requests to build communication channel.'); var msg = [request_to_comm_channel_1]; webview2.contentWindow.postMessage(JSON.stringify(msg), '*'); setTimeout(function() { @@ -958,12 +958,12 @@ function testAddAndRemoveContentScripts() { var webview = document.createElement('webview'); - console.log("Step 1: call <webview>.addContentScripts."); + console.log('Step 1: call <webview>.addContentScripts.'); webview.addContentScripts( [{"name": 'myrule', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel.js"], - "run_at": "document_start"}]); + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel.js'], + "run_at": 'document_start'}]); var count = 0; webview.addEventListener('loadstop', function() { @@ -1024,9 +1024,9 @@ console.log('Step 2: call newwebview.addContentScripts.'); newwebview.addContentScripts( [{"name": 'myrule', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel.js"], - "run_at": "document_start"}]); + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel.js'], + "run_at": 'document_start'}]); newwebview.addEventListener('loadstop', function(evt) { var msg = [request_to_comm_channel_1]; @@ -1037,7 +1037,7 @@ document.body.appendChild(newwebview); // attach the new window to the new <webview>. - console.log("Step 3: attaches the new webview."); + console.log('Step 3: attaches the new webview.'); e.window.attach(newwebview); }); @@ -1070,9 +1070,9 @@ console.log('Step 1: call <webview>.addContentScripts.'); webview.addContentScripts( [{"name": 'myrule', - "matches": ["http://*/extensions/*"], - "js": ["inject_comm_channel.js"], - "run_at": "document_start"}]); + "matches": ['http://*/extensions/*'], + "js": ['inject_comm_channel.js'], + "run_at": 'document_start'}]); var count = 0; webview.addEventListener('loadstop', function() { @@ -1118,9 +1118,9 @@ console.log('Step 1: call <webview>.addContentScripts.'); webview.addContentScripts( [{"name": 'myrule', - "matches": ["http://*/extensions/*"], - "js": ["simple_script.js"], - "run_at": "document_end"}]); + "matches": ['http://*/extensions/*'], + "js": ['simple_script.js'], + "run_at": 'document_end'}]); var count = 0; webview.addEventListener('loadstop', function() { @@ -1156,6 +1156,31 @@ document.body.appendChild(webview); } +function testAddContentScriptWithCode() { + var webview = document.createElement('webview'); + + console.log('Step 1: call <webview>.addContentScripts.'); + webview.addContentScripts( + [{"name": 'myrule', + "matches": ['http://*/extensions/*'], + "code": 'document.body.style.backgroundColor = \'red\';', + "run_at": 'document_end'}]); + + webview.addEventListener('loadstop', function() { + console.log('Step 2: call webview.executeScript() to check result.') + webview.executeScript({ + code: 'document.body.style.backgroundColor;'}, + function(results) { + embedder.test.assertEq(1, results.length); + embedder.test.assertEq('red', results[0]); + embedder.test.succeed(); + }); + }); + + webview.src = embedder.emptyGuestURL; + document.body.appendChild(webview); +} + function testExecuteScriptFail() { var webview = document.createElement('webview'); document.body.appendChild(webview); @@ -2659,6 +2684,7 @@ testContentScriptIsInjectedAfterTerminateAndReloadWebView, 'testContentScriptExistsAsLongAsWebViewTagExists': testContentScriptExistsAsLongAsWebViewTagExists, + 'testAddContentScriptWithCode': testAddContentScriptWithCode, 'testExecuteScriptFail': testExecuteScriptFail, 'testExecuteScript': testExecuteScript, 'testExecuteScriptIsAbortedWhenWebViewSourceIsChanged':
diff --git a/chrome/test/data/guest_from_opener.html b/chrome/test/data/guest_from_opener.html new file mode 100644 index 0000000..d4ce302a --- /dev/null +++ b/chrome/test/data/guest_from_opener.html
@@ -0,0 +1,18 @@ +<!doctype html> +<!-- + * Copyright (c) 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. +--> +<html> +<head> + <title>A guest that opens a new window.</title> + <script type="text/javascript"> + window.onload = function() { + window.open(document.documentURI); + }; + </script> +</head> +<body style="padding: 0; margin: 0;"> +</body> +</html>
diff --git a/chrome/test/data/password/framed_signup_form.html b/chrome/test/data/password/framed_signup_form.html new file mode 100644 index 0000000..a8dd6b5 --- /dev/null +++ b/chrome/test/data/password/framed_signup_form.html
@@ -0,0 +1,8 @@ +<html> +<body> + +<iframe src="signup_form.html" id="signup_iframe" name="signup_iframe"> +</iframe> + +</body> +</html>
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index cb38eb4..f9344ce 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -2221,7 +2221,7 @@ "os": ["chromeos"], "can_be_recommended": true }, - + "ForceMaximizeOnFirstRun": { "os": ["chromeos"], "test_policy": { "ForceMaximizeOnFirstRun": true }, @@ -2230,6 +2230,14 @@ ] }, + "SSLErrorOverrideAllowed": { + "os": ["win", "linux", "mac", "chromeos"], + "test_policy": { "SSLErrorOverrideAllowed": true }, + "pref_mappings": [ + { "pref": "ssl.error_override_allowed" } + ] + }, + "----- Chrome OS device policies ---------------------------------------": {}, "DevicePolicyRefreshRate": {
diff --git a/chrome/test/data/push_messaging/push_test.js b/chrome/test/data/push_messaging/push_test.js index 19118ad..b58c002 100644 --- a/chrome/test/data/push_messaging/push_test.js +++ b/chrome/test/data/push_messaging/push_test.js
@@ -103,9 +103,9 @@ }).catch(sendErrorToTest); } -function hasPermission() { +function permissionState() { navigator.serviceWorker.ready.then(function(swRegistration) { - return swRegistration.pushManager.hasPermission() + return swRegistration.pushManager.permissionState() .then(function(permission) { sendResultToTest('permission status - ' + permission); });
diff --git a/chrome/test/data/webrtc/getusermedia.js b/chrome/test/data/webrtc/getusermedia.js index 4307e60..b1af494 100644 --- a/chrome/test/data/webrtc/getusermedia.js +++ b/chrome/test/data/webrtc/getusermedia.js
@@ -54,7 +54,8 @@ returnToTest('Browser does not support WebRTC.'); return; } - debug('Requesting doGetUserMedia: constraints: ' + constraints); + debug('Requesting doGetUserMedia: constraints: ' + + JSON.stringify(constraints, null, 0).replace(/[\r\n]/g, '')); getUserMedia(constraints, function(stream) { ensureGotAllExpectedStreams_(stream, constraints); @@ -73,7 +74,10 @@ */ function obtainGetUserMediaResult() { returnToTest(gRequestWebcamAndMicrophoneResult); - return gRequestWebcamAndMicrophoneResult; + var ret = gRequestWebcamAndMicrophoneResult; + // Reset for the next call. + gRequestWebcamAndMicrophoneResult = 'not-called-yet'; + return ret; } /**
diff --git a/chrome/test/data/webrtc/resources/speech_44kHz_16bit_stereo.wav.sha1 b/chrome/test/data/webrtc/resources/speech_44kHz_16bit_stereo.wav.sha1 index c8ec280..f2661b5 100644 --- a/chrome/test/data/webrtc/resources/speech_44kHz_16bit_stereo.wav.sha1 +++ b/chrome/test/data/webrtc/resources/speech_44kHz_16bit_stereo.wav.sha1
@@ -1 +1 @@ -5639bef92b4a2cff0e09003773efb7b3b34252d4 \ No newline at end of file +98ee0246a46e1b8025353db62e73dbbc81423ef5 \ No newline at end of file
diff --git a/chrome/test/data/webui/async_gen.h b/chrome/test/data/webui/async_gen.h index e8af827..f2b05de1 100644 --- a/chrome/test/data/webui/async_gen.h +++ b/chrome/test/data/webui/async_gen.h
@@ -16,7 +16,7 @@ class WebUIBrowserAsyncGenTest : public WebUIBrowserTest { public: WebUIBrowserAsyncGenTest(); - virtual ~WebUIBrowserAsyncGenTest(); + ~WebUIBrowserAsyncGenTest() override; protected: class AsyncWebUIMessageHandler : public content::WebUIMessageHandler { @@ -30,7 +30,7 @@ void HandleCallJS(const base::ListValue* list_value); // WebUIMessageHandler implementation. - virtual void RegisterMessages() override; + void RegisterMessages() override; }; // Handler for this test fixture. @@ -38,11 +38,11 @@ private: // Provide this object's handler. - virtual content::WebUIMessageHandler* GetMockMessageHandler() override { + content::WebUIMessageHandler* GetMockMessageHandler() override { return &message_handler_; } - virtual void SetUpOnMainThread() override { + void SetUpOnMainThread() override { WebUIBrowserTest::SetUpOnMainThread(); EXPECT_CALL(message_handler_, HandleTearDown(::testing::_)); }
diff --git a/chrome/test/data/webui/chrome_send_browsertest.h b/chrome/test/data/webui/chrome_send_browsertest.h index 465ec09a..44eef8c9 100644 --- a/chrome/test/data/webui/chrome_send_browsertest.h +++ b/chrome/test/data/webui/chrome_send_browsertest.h
@@ -14,7 +14,7 @@ class ChromeSendWebUITest : public WebUIBrowserTest { public: ChromeSendWebUITest(); - virtual ~ChromeSendWebUITest(); + ~ChromeSendWebUITest() override; // Mocked message handler class to register expects using gmock framework. class ChromeSendWebUIMessageHandler : public content::WebUIMessageHandler { @@ -25,7 +25,7 @@ MOCK_METHOD1(HandleCheckSend, void(const base::ListValue*)); private: - virtual void RegisterMessages() override; + void RegisterMessages() override; }; @@ -34,7 +34,7 @@ ::testing::StrictMock<ChromeSendWebUIMessageHandler> message_handler_; private: - virtual content::WebUIMessageHandler* GetMockMessageHandler() override; + content::WebUIMessageHandler* GetMockMessageHandler() override; DISALLOW_COPY_AND_ASSIGN(ChromeSendWebUITest); };
diff --git a/chrome/test/data/webui/context_menu_handler_test.html b/chrome/test/data/webui/context_menu_handler_test.html new file mode 100644 index 0000000..366ed0e --- /dev/null +++ b/chrome/test/data/webui/context_menu_handler_test.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<html> +<body> +<script> + +function testShowAndHideEvents() { + // Keep original Date.now not to affect other code. + var originalDateNow = Date.now; + + // Initial value is 1 since 0 becomes false. + var currentTime = 1; + + // Overrides Date.now to simulate time. + Date.now = function() { return currentTime; }; + + var cmh = cr.ui.contextMenuHandler; + + // Create context menu. + var menu = document.createElement('div'); + cr.ui.decorate(menu, cr.ui.Menu); + document.body.appendChild(menu); + + var menuItem = document.createElement('div'); + menu.addMenuItem(menuItem); + + // Create target elements. + var elem1 = document.createElement('div'); + var elem2 = document.createElement('div'); + + cmh.setContextMenu(elem1, menu); + cmh.setContextMenu(elem2, menu); + + var events = []; + cmh.addEventListener('show', function(e) { events.push(e); }); + cmh.addEventListener('hide', function(e) { events.push(e); }); + + // Show context menu of elem1. + elem1.dispatchEvent(new MouseEvent('contextmenu')); + assertEquals(1, events.length); + assertEquals('show', events[0].type); + assertEquals(elem1, events[0].element); + assertEquals(menu, events[0].menu); + + // Show context menu of elem2. + document.dispatchEvent(new MouseEvent('mousedown')); + + // On Windows to prevent context menu show again by mouse right button up, + // we need to wait at least 50ms from the last hide of context menu. + currentTime += 51; // ms + + elem2.dispatchEvent(new MouseEvent('contextmenu')); + assertEquals(3, events.length); + assertEquals('hide', events[1].type); + assertEquals(elem1, events[1].element); + assertEquals(menu, events[1].menu); + assertEquals('show', events[2].type); + assertEquals(elem2, events[2].element); + assertEquals(menu, events[2].menu); + + Date.now = originalDateNow; +} + +</script> +</body> +</html>
diff --git a/chrome/test/data/webui/inject_comm_channel.js b/chrome/test/data/webui/inject_comm_channel.js new file mode 100644 index 0000000..224ab26b --- /dev/null +++ b/chrome/test/data/webui/inject_comm_channel.js
@@ -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. + +var embedder = null; + +function reportConnected() { + var msg = ['connected']; + embedder.postMessage(JSON.stringify(msg), '*'); +} + +window.addEventListener('message', function(e) { + embedder = e.source; + var data = JSON.parse(e.data); + switch (data[0]) { + case 'connect': { + reportConnected(); + break; + } + } +});
diff --git a/chrome/test/data/webui/inject_comm_channel_2.js b/chrome/test/data/webui/inject_comm_channel_2.js new file mode 100644 index 0000000..b90cd94 --- /dev/null +++ b/chrome/test/data/webui/inject_comm_channel_2.js
@@ -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. + +var embedder = null; + +function reportConnected_request() { + var msg = ['connected_response']; + embedder.postMessage(JSON.stringify(msg), '*'); +} + +window.addEventListener('message', function(e) { + embedder = e.source; + var data = JSON.parse(e.data); + switch (data[0]) { + case 'connect_request': { + reportConnected_request(); + break; + } + } +});
diff --git a/chrome/test/data/webui/webui_resource_browsertest.cc b/chrome/test/data/webui/webui_resource_browsertest.cc index c447683..6fe54c5 100644 --- a/chrome/test/data/webui/webui_resource_browsertest.cc +++ b/chrome/test/data/webui/webui_resource_browsertest.cc
@@ -173,3 +173,17 @@ AddLibrary(IDR_WEBUI_JS_CR_UI_COMMAND); RunTest(base::FilePath(FILE_PATH_LITERAL("command_test.html"))); } + +IN_PROC_BROWSER_TEST_F(WebUIResourceBrowserTest, ContextMenuHandlerTest) { + AddLibrary(IDR_WEBUI_JS_ASSERT); + AddLibrary(IDR_WEBUI_JS_EVENT_TRACKER); + AddLibrary(IDR_WEBUI_JS_CR); + AddLibrary(IDR_WEBUI_JS_CR_EVENT_TARGET); + AddLibrary(IDR_WEBUI_JS_CR_UI); + AddLibrary(IDR_WEBUI_JS_CR_UI_POSITION_UTIL); + AddLibrary(IDR_WEBUI_JS_CR_UI_MENU_ITEM); + AddLibrary(IDR_WEBUI_JS_CR_UI_MENU_BUTTON); + AddLibrary(IDR_WEBUI_JS_CR_UI_MENU); + AddLibrary(IDR_WEBUI_JS_CR_UI_CONTEXT_MENU_HANDLER); + RunTest(base::FilePath(FILE_PATH_LITERAL("context_menu_handler_test.html"))); +}
diff --git a/chrome/test/data/webui/webview_content_script_test.js b/chrome/test/data/webui/webview_content_script_test.js new file mode 100644 index 0000000..2a666090 --- /dev/null +++ b/chrome/test/data/webui/webview_content_script_test.js
@@ -0,0 +1,467 @@ +// 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. + +var REQUEST_TO_COMM_CHANNEL_1 = 'connect'; +var REQUEST_TO_COMM_CHANNEL_2 = 'connect_request'; +var RESPONSE_FROM_COMM_CHANNEL_1 = 'connected'; +var RESPONSE_FROM_COMM_CHANNEL_2 = 'connected_response'; + +function createWebview() { + var webview = document.createElement('webview'); + document.body.appendChild(webview); + return webview; +} + +function onGetBackgroundExecuted(results) { + chrome.send('testResult', [results.length == 1 && results[0] == 'red']); +}; + +function testExecuteScriptCode(url) { + var webview = createWebview(); + + var onSetBackgroundExecuted = function() { + webview.executeScript({ + code: 'document.body.style.backgroundColor;' + }, onGetBackgroundExecuted); + }; + + var onLoadStop = function() { + webview.executeScript({ + code: 'document.body.style.backgroundColor = \'red\';' + }, onSetBackgroundExecuted); + }; + + webview.addEventListener('loadstop', onLoadStop); + webview.src = url; +} + +function testExecuteScriptCodeFromFile(url) { + var webview = createWebview(); + + var onSetBackgroundExecuted = function() { + webview.executeScript({ + code: 'document.body.style.backgroundColor;' + }, onGetBackgroundExecuted); + }; + + var onLoadStop = function() { + webview.executeScript({ + file: 'test/webview_execute_script.js' + }, onSetBackgroundExecuted); + }; + + webview.addEventListener('loadstop', onLoadStop); + webview.src = url; +} + +// This test verifies that a content script will be injected to the webview when +// the webview is navigated to a page that matches the URL pattern defined in +// the content sript. +function testAddContentScript(url) { + var webview = document.createElement('webview'); + + console.log('Step 1: call <webview>.addContentScripts.'); + webview.addContentScripts( + [{'name': 'myrule', + 'matches': ['http://*/empty*'], + 'js': ['test/inject_comm_channel.js', 'test/inject_comm_channel_2.js'], + 'run_at': 'document_start'}]); + + webview.addEventListener('loadstop', function() { + console.log('Step 2: postMessage to build connection.'); + var msg = [REQUEST_TO_COMM_CHANNEL_1]; + webview.contentWindow.postMessage(JSON.stringify(msg), '*'); + }); + + window.addEventListener('message', function(e) { + if (e.source != webview.contentWindow) + return; + var data = JSON.parse(e.data); + if (data == RESPONSE_FROM_COMM_CHANNEL_1) { + console.log( + 'Step 3: A communication channel has been established with webview.'); + chrome.send('testResult', [true]); + return; + } + console.log('Unexpected message: \'' + data[0] + '\''); + chrome.send('testResult', [false]); + }); + + webview.src = url; + document.body.appendChild(webview); +} + +// Adds two content scripts with the same URL pattern to <webview> at the same +// time. This test verifies that both scripts are injected when the <webview> +// navigates to a URL that matches the URL pattern. +function testAddMultiContentScripts(url) { + var webview = document.createElement('webview'); + + console.log('Step 1: call <webview>.addContentScripts(myrule1 & myrule2)'); + webview.addContentScripts( + [{'name': 'myrule1', + 'matches': ['http://*/empty*'], + 'js': ['test/inject_comm_channel.js'], + 'run_at': 'document_start'}, + {'name': 'myrule2', + 'matches': ['http://*/empty*'], + 'js': ['test/inject_comm_channel_2.js'], + 'run_at': 'document_start'}]); + + webview.addEventListener('loadstop', function() { + console.log('Step 2: postMessage to build connection.'); + var msg1 = [REQUEST_TO_COMM_CHANNEL_1]; + webview.contentWindow.postMessage(JSON.stringify(msg1), '*'); + console.log('Step 3: postMessage to build connection to the other script.'); + var msg2 = [REQUEST_TO_COMM_CHANNEL_2]; + webview.contentWindow.postMessage(JSON.stringify(msg2), '*'); + }); + + var response_1 = false; + var response_2 = false; + window.addEventListener('message', function(e) { + if (e.source != webview.contentWindow) + return; + var data = JSON.parse(e.data); + if (data == RESPONSE_FROM_COMM_CHANNEL_1) { + console.log( + 'Step 4: A communication channel has been established with webview.'); + response_1 = true; + if (response_1 && response_2) + chrome.send('testResult', [true]); + return; + } else if (data == RESPONSE_FROM_COMM_CHANNEL_2) { + console.log( + 'Step 5: A communication channel has been established with webview.'); + response_2 = true; + if (response_1 && response_2) + chrome.send('testResult', [true]); + return; + } + console.log('Unexpected message: \'' + data[0] + '\''); + chrome.send('testResult', [false]); + }); + + webview.src = url; + document.body.appendChild(webview); +} + +// Adds a content script to <webview> and navigates. After seeing the script is +// injected, we add another content script with the same name to the <webview>. +// This test verifies that the second script will replace the first one and be +// injected after navigating the <webview>. Meanwhile, the <webview> shouldn't +// get any message from the first script anymore. +function testAddContentScriptWithSameNameShouldOverwriteTheExistingOne(url) { + var webview = document.createElement('webview'); + + console.log('Step 1: call <webview>.addContentScripts(myrule1)'); + webview.addContentScripts( + [{'name': 'myrule1', + 'matches': ['http://*/empty*'], + 'js': ['test/inject_comm_channel.js'], + 'run_at': 'document_start'}]); + var connect_script_1 = true; + var connect_script_2 = false; + + webview.addEventListener('loadstop', function() { + if (connect_script_1) { + var msg1 = [REQUEST_TO_COMM_CHANNEL_1]; + webview.contentWindow.postMessage(JSON.stringify(msg1), '*'); + connect_script_1 = false; + } + if (connect_script_2) { + var msg2 = [REQUEST_TO_COMM_CHANNEL_2]; + webview.contentWindow.postMessage(JSON.stringify(msg2), '*'); + connect_script_2 = false; + } + }); + + var should_get_response_from_script_1 = true; + window.addEventListener('message', function(e) { + if (e.source != webview.contentWindow) + return; + var data = JSON.parse(e.data); + if (data == RESPONSE_FROM_COMM_CHANNEL_1) { + if (should_get_response_from_script_1) { + console.log( + 'Step 2: A communication channel has been established with webview.' + ); + console.log('Step 3: <webview>.addContentScripts() with a updated' + + ' \'myrule1\''); + webview.addContentScripts( + [{'name': 'myrule1', + 'matches': ['http://*/empty*'], + 'js': ['test/inject_comm_channel_2.js'], + 'run_at': 'document_start'}]); + connect_script_2 = true; + should_get_response_from_script_1 = false; + webview.src = url; + } else { + chrome.send('testResult', [false]); + } + return; + } else if (data == RESPONSE_FROM_COMM_CHANNEL_2) { + console.log( + 'Step 4: Another communication channel has been established ' + + 'with webview.'); + setTimeout(function() { + chrome.send('testResult', [true]); + }, 0); + return; + } + console.log('Unexpected message: \'' + data[0] + '\''); + chrome.send('testResult', [false]); + }); + + webview.src = url; + document.body.appendChild(webview); +} + +// There are two <webview>s are added to the DOM, and we add a content script +// to one of them. This test verifies that the script won't be injected in +// the other <webview>. +function testAddContentScriptToOneWebViewShouldNotInjectToTheOtherWebView(url) { + var webview1 = document.createElement('webview'); + var webview2 = document.createElement('webview'); + + console.log('Step 1: call <webview1>.addContentScripts.'); + webview1.addContentScripts( + [{'name': 'myrule', + 'matches': ['http://*/empty*'], + 'js': ['test/inject_comm_channel.js'], + 'run_at': 'document_start'}]); + + webview2.addEventListener('loadstop', function() { + console.log('Step 2: webview2 requests to build communication channel.'); + var msg = [REQUEST_TO_COMM_CHANNEL_1]; + webview2.contentWindow.postMessage(JSON.stringify(msg), '*'); + setTimeout(function() { + chrome.send('testResult', [true]); + }, 0); + }); + + window.addEventListener('message', function(e) { + if (e.source != webview2.contentWindow) + return; + var data = JSON.parse(e.data); + if (data == RESPONSE_FROM_COMM_CHANNEL_1) { + chrome.send('testResult', [false]); + return; + } + console.log('Unexpected message: \'' + data[0] + '\''); + chrome.send('testResult', [false]); + }); + + webview1.src = url; + webview2.src = url; + document.body.appendChild(webview1); + document.body.appendChild(webview2); +} + +// Adds a content script to <webview> and navigates to a URL that matches the +// URL pattern defined in the script. After the first navigation, we remove this +// script from the <webview> and navigates to the same URL. This test verifies +// taht the script is injected during the first navigation, but isn't injected +// after removing it. +function testAddAndRemoveContentScripts(url) { + var webview = document.createElement('webview'); + + console.log('Step 1: call <webview>.addContentScripts.'); + webview.addContentScripts( + [{'name': 'myrule', + 'matches': ['http://*/empty*'], + 'js': ['test/inject_comm_channel.js'], + 'run_at': 'document_start'}]); + + var should_get_response_from_script_1 = true; + + var count = 0; + webview.addEventListener('loadstop', function() { + if (count == 0) { + console.log('Step 2: post message to build connect.'); + var msg = [REQUEST_TO_COMM_CHANNEL_1]; + webview.contentWindow.postMessage(JSON.stringify(msg), '*'); + ++count; + } else if (count == 1) { + console.log('Step 5: post message to build connect again.'); + var msg = [REQUEST_TO_COMM_CHANNEL_1]; + webview.contentWindow.postMessage(JSON.stringify(msg), '*'); + setTimeout(function() { + chrome.send('testResult', [true]); + }, 0); + } + }); + + window.addEventListener('message', function(e) { + if (e.source != webview.contentWindow) + return; + var data = JSON.parse(e.data); + if (data[0] == RESPONSE_FROM_COMM_CHANNEL_1 && + should_get_response_from_script_1) { + console.log('Step 3: A communication channel has been established ' + + 'with webview.'); + should_get_response_from_script_1 = false; + console.log( + 'Step 4: call <webview>.removeContentScripts and navigate.'); + webview.removeContentScripts(); + webview.src = url; + return; + } + console.log('Unexpected message: \'' + data[0] + '\''); + chrome.send('testResult', [false]); + }); + + webview.src = url; + document.body.appendChild(webview); +} + +// This test verifies that the addContentScripts API works with the new window +// API. +function testAddContentScriptsWithNewWindowAPI(url) { + var webview = document.createElement('webview'); + + var newwebview; + webview.addEventListener('newwindow', function(e) { + e.preventDefault(); + newwebview = document.createElement('webview'); + + console.log('Step 2: call newwebview.addContentScripts.'); + newwebview.addContentScripts( + [{'name': 'myrule', + 'matches': ['http://*/guest_from_opener*'], + 'js': ['test/inject_comm_channel.js'], + 'run_at': 'document_start'}]); + + newwebview.addEventListener('loadstop', function(evt) { + var msg = [REQUEST_TO_COMM_CHANNEL_1]; + console.log('Step 4: new webview postmessage to build communication ' + + 'channel.'); + newwebview.contentWindow.postMessage(JSON.stringify(msg), '*'); + }); + + document.body.appendChild(newwebview); + // attach the new window to the new <webview>. + console.log('Step 3: attaches the new webview.'); + e.window.attach(newwebview); + }); + + window.addEventListener('message', function(e) { + if (!newwebview || e.source != newwebview.contentWindow) + return; + var data = JSON.parse(e.data); + if (data == RESPONSE_FROM_COMM_CHANNEL_1 && + e.source == newwebview.contentWindow) { + console.log('Step 5: a communication channel has been established ' + + 'with the new webview.'); + chrome.send('testResult', [true]); + return; + } else { + chrome.send('testResult', [false]); + return; + } + console.log('Unexpected message: \'' + data[0] + '\''); + chrome.send('testResult', [false]); + }); + + console.log('Step 1: navigates the webview to window open guest URL.'); + webview.setAttribute('src', url); + document.body.appendChild(webview); +} + +// Adds a content script to <webview>. This test verifies that the script is +// injected after terminate and reload <webview>. +function testContentScriptIsInjectedAfterTerminateAndReloadWebView(url) { + var webview = document.createElement('webview'); + + console.log('Step 1: call <webview>.addContentScripts.'); + webview.addContentScripts( + [{'name': 'myrule', + 'matches': ['http://*/empty*'], + 'js': ['test/webview_execute_script.js'], + 'run_at': 'document_end'}]); + + var count = 0; + webview.addEventListener('loadstop', function() { + if (count == 0) { + console.log('Step 2: call webview.terminate().'); + webview.terminate(); + ++count; + return; + } else if (count == 1) { + console.log('Step 4: call <webview>.executeScript to check result.'); + webview.executeScript({ + code: 'document.body.style.backgroundColor;' + }, onGetBackgroundExecuted); + } + }); + + webview.addEventListener('exit', function() { + console.log('Step 3: call webview.reload().'); + webview.reload(); + }); + + webview.src = url; + document.body.appendChild(webview); +} + +// This test verifies the content script won't be removed when the guest is +// destroyed, i.e., removed <webview> from the DOM. +function testContentScriptExistsAsLongAsWebViewTagExists(url) { + var webview = document.createElement('webview'); + + console.log('Step 1: call <webview>.addContentScripts.'); + webview.addContentScripts( + [{'name': 'myrule', + 'matches': ['http://*/empty*'], + 'js': ['test/webview_execute_script.js'], + 'run_at': 'document_end'}]); + + var count = 0; + webview.addEventListener('loadstop', function() { + if (count == 0) { + console.log('Step 2: check the result of content script injected.'); + webview.executeScript({ + code: 'document.body.style.backgroundColor;' + }, function(results) { + assertEquals(1, results.length); + assertEquals('red', results[0]); + + console.log('Step 3: remove webview from the DOM.'); + document.body.removeChild(webview); + console.log('Step 4: add webview back to the DOM.'); + document.body.appendChild(webview); + ++count; + }); + } else if (count == 1) { + console.log('Step 5: check the result of content script injected again.'); + webview.executeScript({ + code: 'document.body.style.backgroundColor;' + }, onGetBackgroundExecuted); + } + }); + + webview.src = url; + document.body.appendChild(webview); +} + +function testAddContentScriptWithCode(url) { + var webview = document.createElement('webview'); + + console.log('Step 1: call <webview>.addContentScripts.'); + webview.addContentScripts( + [{'name': 'myrule', + 'matches': ['http://*/empty*'], + 'code': 'document.body.style.backgroundColor = \'red\';', + 'run_at': 'document_end'}]); + + webview.addEventListener('loadstop', function() { + console.log('Step 2: call webview.executeScript() to check result.') + webview.executeScript({ + code: 'document.body.style.backgroundColor;' + }, onGetBackgroundExecuted); + }); + + webview.src = url; + document.body.appendChild(webview); +}
diff --git a/chrome/test/data/webui/webview_execute_script_test.js b/chrome/test/data/webui/webview_execute_script_test.js deleted file mode 100644 index 5485904d..0000000 --- a/chrome/test/data/webui/webview_execute_script_test.js +++ /dev/null
@@ -1,51 +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. - -function createWebview() { - var webview = document.createElement('webview'); - document.body.appendChild(webview); - return webview; -} - -function onGetBackgroundExecuted(results) { - chrome.send('testResult', [results.length == 1 && results[0] == 'red']); -}; - -function testExecuteScriptCode(url) { - var webview = createWebview(); - - var onSetBackgroundExecuted = function() { - webview.executeScript({ - code: 'document.body.style.backgroundColor;' - }, onGetBackgroundExecuted); - }; - - var onLoadStop = function() { - webview.executeScript({ - code: 'document.body.style.backgroundColor = \'red\';' - }, onSetBackgroundExecuted); - }; - - webview.addEventListener('loadstop', onLoadStop); - webview.src = url; -} - -function testExecuteScriptCodeFromFile(url) { - var webview = createWebview(); - - var onSetBackgroundExecuted = function() { - webview.executeScript({ - code: 'document.body.style.backgroundColor;' - }, onGetBackgroundExecuted); - }; - - var onLoadStop = function() { - webview.executeScript({ - file: 'test/webview_execute_script.js' - }, onSetBackgroundExecuted); - }; - - webview.addEventListener('loadstop', onLoadStop); - webview.src = url; -}
diff --git a/chrome/test/logging/win/log_file_printer.cc b/chrome/test/logging/win/log_file_printer.cc index fc2fb48f..943712ae 100644 --- a/chrome/test/logging/win/log_file_printer.cc +++ b/chrome/test/logging/win/log_file_printer.cc
@@ -87,34 +87,34 @@ class EventPrinter : public logging_win::LogFileDelegate { public: explicit EventPrinter(std::ostream* out); - virtual ~EventPrinter(); + ~EventPrinter() override; - virtual void OnUnknownEvent(const EVENT_TRACE* event) override; + void OnUnknownEvent(const EVENT_TRACE* event) override; - virtual void OnUnparsableEvent(const EVENT_TRACE* event) override; + void OnUnparsableEvent(const EVENT_TRACE* event) override; - virtual void OnFileHeader(const EVENT_TRACE* event, - const TRACE_LOGFILE_HEADER* header) override; + void OnFileHeader(const EVENT_TRACE* event, + const TRACE_LOGFILE_HEADER* header) override; - virtual void OnLogMessage(const EVENT_TRACE* event, - logging::LogSeverity severity, - const base::StringPiece& message) override; + void OnLogMessage(const EVENT_TRACE* event, + logging::LogSeverity severity, + const base::StringPiece& message) override; - virtual void OnLogMessageFull(const EVENT_TRACE* event, - logging::LogSeverity severity, - DWORD stack_depth, - const intptr_t* backtrace, - int line, - const base::StringPiece& file, - const base::StringPiece& message) override; + void OnLogMessageFull(const EVENT_TRACE* event, + logging::LogSeverity severity, + DWORD stack_depth, + const intptr_t* backtrace, + int line, + const base::StringPiece& file, + const base::StringPiece& message) override; - virtual void OnTraceEvent(const EVENT_TRACE* event, - const base::StringPiece& name, - char type, - intptr_t id, - const base::StringPiece& extra, - DWORD stack_depth, - const intptr_t* backtrace) override; + void OnTraceEvent(const EVENT_TRACE* event, + const base::StringPiece& name, + char type, + intptr_t id, + const base::StringPiece& extra, + DWORD stack_depth, + const intptr_t* backtrace) override; private: void PrintTimeStamp(LARGE_INTEGER time_stamp);
diff --git a/chrome/test/logging/win/test_log_collector.cc b/chrome/test/logging/win/test_log_collector.cc index ec582a5..a218d60 100644 --- a/chrome/test/logging/win/test_log_collector.cc +++ b/chrome/test/logging/win/test_log_collector.cc
@@ -50,43 +50,40 @@ // Ownership of |default_result_printer| is taken by the new instance. EventListener(TestLogCollector* test_log_collector, testing::TestEventListener* default_result_printer); - virtual ~EventListener(); + ~EventListener() override; // Sets up the log collector. - virtual void OnTestProgramStart( - const testing::UnitTest& unit_test) override { + void OnTestProgramStart(const testing::UnitTest& unit_test) override { test_log_collector_->SetUp(); default_result_printer_->OnTestProgramStart(unit_test); } - virtual void OnTestIterationStart(const testing::UnitTest& unit_test, - int iteration) override { + void OnTestIterationStart(const testing::UnitTest& unit_test, + int iteration) override { default_result_printer_->OnTestIterationStart(unit_test, iteration); } - virtual void OnEnvironmentsSetUpStart( - const testing::UnitTest& unit_test) override { + void OnEnvironmentsSetUpStart(const testing::UnitTest& unit_test) override { default_result_printer_->OnEnvironmentsSetUpStart(unit_test); } - virtual void OnEnvironmentsSetUpEnd( - const testing::UnitTest& unit_test) override { + void OnEnvironmentsSetUpEnd(const testing::UnitTest& unit_test) override { default_result_printer_->OnEnvironmentsSetUpEnd(unit_test); } - virtual void OnTestCaseStart(const testing::TestCase& test_case) override { + void OnTestCaseStart(const testing::TestCase& test_case) override { default_result_printer_->OnTestCaseStart(test_case); } // Calls back to the collector to start collecting logs for this test. - virtual void OnTestStart(const testing::TestInfo& test_info) override { + void OnTestStart(const testing::TestInfo& test_info) override { default_result_printer_->OnTestStart(test_info); test_log_collector_->StartSessionForTest(test_info); } // Calls back to the collector with the partial result. If the collector // does not handle it, it is given to the default result printer. - virtual void OnTestPartResult( + void OnTestPartResult( const testing::TestPartResult& test_part_result) override { if (!test_log_collector_->LogTestPartResult(test_part_result)) default_result_printer_->OnTestPartResult(test_part_result); @@ -94,32 +91,32 @@ // Calls back to the collector to handle the collected log for the test that // has just ended. - virtual void OnTestEnd(const testing::TestInfo& test_info) override { + void OnTestEnd(const testing::TestInfo& test_info) override { test_log_collector_->ProcessSessionForTest(test_info); default_result_printer_->OnTestEnd(test_info); } - virtual void OnTestCaseEnd(const testing::TestCase& test_case) override { + void OnTestCaseEnd(const testing::TestCase& test_case) override { default_result_printer_->OnTestCaseEnd(test_case); } - virtual void OnEnvironmentsTearDownStart( + void OnEnvironmentsTearDownStart( const testing::UnitTest& unit_test) override { default_result_printer_->OnEnvironmentsTearDownStart(unit_test); } - virtual void OnEnvironmentsTearDownEnd( + void OnEnvironmentsTearDownEnd( const testing::UnitTest& unit_test) override { default_result_printer_->OnEnvironmentsTearDownEnd(unit_test); } - virtual void OnTestIterationEnd(const testing::UnitTest& unit_test, - int iteration) override { + void OnTestIterationEnd(const testing::UnitTest& unit_test, + int iteration) override { default_result_printer_->OnTestIterationEnd(unit_test, iteration); } // Tears down the log collector. - virtual void OnTestProgramEnd(const testing::UnitTest& unit_test) override { + void OnTestProgramEnd(const testing::UnitTest& unit_test) override { default_result_printer_->OnTestProgramEnd(unit_test); test_log_collector_->TearDown(); }
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc index fcd1f16f..8e0ed84 100644 --- a/chrome/test/ppapi/ppapi_browsertest.cc +++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -1407,57 +1407,4 @@ RunTests("socket_permissions"); } -class MojoPPAPITest : public InProcessBrowserTest { - public: - MojoPPAPITest() : InProcessBrowserTest() { } - virtual ~MojoPPAPITest() { } - - void RunTestInternal() { - base::FilePath document_root; - ASSERT_TRUE(ui_test_utils::GetRelativeBuildDirectory(&document_root)); - net::SpawnedTestServer http_server(net::SpawnedTestServer::TYPE_HTTP, - net::SpawnedTestServer::kLocalhost, - document_root); - ASSERT_TRUE(http_server.Start()); - - std::string query = "files/test_case.html?testcase=Mojo&mode=mojo"; - GURL test_url = http_server.GetURL(query); - - PPAPITestMessageHandler handler; - content::JavascriptTestObserver observer( - browser()->tab_strip_model()->GetActiveWebContents(), - &handler); - ui_test_utils::NavigateToURL(browser(), test_url); - - ASSERT_TRUE(observer.Run()) << handler.error_message(); - result_ = handler.message(); - } - - void RunTest() { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kEnableNaClMojo); - RunTestInternal(); - EXPECT_STREQ("PASS", result_.c_str()); - } - void RunTestWithoutFlag() { - RunTestInternal(); - EXPECT_STREQ("Plugin crashed. 'NaCl module crashed'", result_.c_str()); - } - private: - std::string result_; -}; - -IN_PROC_BROWSER_TEST_F(MojoPPAPITest, Mojo) { - RunTest(); -} - -#if defined(OS_WIN) -#define MAYBE_MojoFailsWithoutFlag DISABLED_MojoFailsWithoutFlag -#else -#define MAYBE_MojoFailsWithoutFlag MojoFailsWithoutFlag -#endif - -IN_PROC_BROWSER_TEST_F(MojoPPAPITest, MAYBE_MojoFailsWithoutFlag) { - RunTestWithoutFlag(); -} #endif
diff --git a/chrome/test/ppapi/ppapi_test.h b/chrome/test/ppapi/ppapi_test.h index c2a2c62..0110ca5 100644 --- a/chrome/test/ppapi/ppapi_test.h +++ b/chrome/test/ppapi/ppapi_test.h
@@ -21,8 +21,8 @@ public: PPAPITestMessageHandler(); - virtual MessageResponse HandleMessage(const std::string& json) override; - virtual void Reset() override; + MessageResponse HandleMessage(const std::string& json) override; + void Reset() override; const std::string& message() const { return message_; @@ -39,9 +39,9 @@ PPAPITestBase(); // InProcessBrowserTest: - virtual void SetUp() override; - virtual void SetUpCommandLine(base::CommandLine* command_line) override; - virtual void SetUpOnMainThread() override; + void SetUp() override; + void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpOnMainThread() override; virtual std::string BuildQuery(const std::string& base, const std::string& test_case) = 0; @@ -66,9 +66,9 @@ private: // content::NotificationObserver: - virtual void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; void VerifyInfoBarState(); @@ -94,17 +94,18 @@ public: PPAPITest(); - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; - virtual std::string BuildQuery(const std::string& base, - const std::string& test_case) override; + std::string BuildQuery(const std::string& base, + const std::string& test_case) override; + protected: bool in_process_; // Controls the --ppapi-in-process switch. }; class PPAPIPrivateTest : public PPAPITest { protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; // Variant of PPAPITest that runs plugins out-of-process to test proxy @@ -113,74 +114,72 @@ public: OutOfProcessPPAPITest(); - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; class OutOfProcessPPAPIPrivateTest : public OutOfProcessPPAPITest { protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; // NaCl plugin test runner for Newlib runtime. class PPAPINaClTest : public PPAPITestBase { public: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; - virtual void SetUpOnMainThread() override; + void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpOnMainThread() override; // PPAPITestBase overrides. - virtual void RunTest(const std::string& test_case) override; - virtual void RunTestViaHTTP(const std::string& test_case) override; - virtual void RunTestWithSSLServer(const std::string& test_case) override; - virtual void RunTestWithWebSocketServer( - const std::string& test_case) override; - virtual void RunTestIfAudioOutputAvailable( - const std::string& test_case) override; - virtual void RunTestViaHTTPIfAudioOutputAvailable( + void RunTest(const std::string& test_case) override; + void RunTestViaHTTP(const std::string& test_case) override; + void RunTestWithSSLServer(const std::string& test_case) override; + void RunTestWithWebSocketServer(const std::string& test_case) override; + void RunTestIfAudioOutputAvailable(const std::string& test_case) override; + void RunTestViaHTTPIfAudioOutputAvailable( const std::string& test_case) override; }; // NaCl plugin test runner for Newlib runtime. class PPAPINaClNewlibTest : public PPAPINaClTest { public: - virtual std::string BuildQuery(const std::string& base, - const std::string& test_case) override; + std::string BuildQuery(const std::string& base, + const std::string& test_case) override; }; class PPAPIPrivateNaClNewlibTest : public PPAPINaClNewlibTest { protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; // NaCl plugin test runner for GNU-libc runtime. class PPAPINaClGLibcTest : public PPAPINaClTest { public: - virtual std::string BuildQuery(const std::string& base, - const std::string& test_case) override; + std::string BuildQuery(const std::string& base, + const std::string& test_case) override; }; class PPAPIPrivateNaClGLibcTest : public PPAPINaClGLibcTest { protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; // NaCl plugin test runner for the PNaCl + Newlib runtime. class PPAPINaClPNaClTest : public PPAPINaClTest { public: - virtual std::string BuildQuery(const std::string& base, - const std::string& test_case) override; + std::string BuildQuery(const std::string& base, + const std::string& test_case) override; }; class PPAPIPrivateNaClPNaClTest : public PPAPINaClPNaClTest { protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; // Test Non-SFI Mode, using PNaCl toolchain to produce nexes. class PPAPINaClPNaClNonSfiTest : public PPAPINaClTest { public: - virtual void SetUpCommandLine(base::CommandLine* command_line); + void SetUpCommandLine(base::CommandLine* command_line) override; - virtual std::string BuildQuery(const std::string& base, - const std::string& test_case) override; + std::string BuildQuery(const std::string& base, + const std::string& test_case) override; }; // TODO(hidehiko): Switch NonSfi tests to use nacl_helper_nonsfi, when @@ -188,12 +187,12 @@ // for more details. class PPAPINaClPNaClTransitionalNonSfiTest : public PPAPINaClPNaClNonSfiTest { public: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; class PPAPIPrivateNaClPNaClNonSfiTest : public PPAPINaClPNaClNonSfiTest { protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; // TODO(hidehiko): Switch NonSfi tests to use nacl_helper_nonsfi, when @@ -202,22 +201,22 @@ class PPAPIPrivateNaClPNaClTransitionalNonSfiTest : public PPAPIPrivateNaClPNaClNonSfiTest { protected: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; }; class PPAPINaClTestDisallowedSockets : public PPAPITestBase { public: - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; - virtual std::string BuildQuery(const std::string& base, - const std::string& test_case) override; + std::string BuildQuery(const std::string& base, + const std::string& test_case) override; }; class PPAPIBrokerInfoBarTest : public OutOfProcessPPAPITest { public: // PPAPITestBase override: - virtual void SetUpOnMainThread() override; + void SetUpOnMainThread() override; }; #endif // CHROME_TEST_PPAPI_PPAPI_TEST_H_
diff --git a/chrome/test/remoting/remote_desktop_browsertest.cc b/chrome/test/remoting/remote_desktop_browsertest.cc index 15dc575..9b58af1 100644 --- a/chrome/test/remoting/remote_desktop_browsertest.cc +++ b/chrome/test/remoting/remote_desktop_browsertest.cc
@@ -487,6 +487,7 @@ LoadScript(content, FILE_PATH_LITERAL("mock_session_connector.js")); LoadScript(content, FILE_PATH_LITERAL("mock_signal_strategy.js")); LoadScript(content, FILE_PATH_LITERAL("timeout_waiter.js")); + LoadScript(content, FILE_PATH_LITERAL("sinon.js")); } void RemoteDesktopBrowserTest::Cleanup() {
diff --git a/chrome/utility/font_cache_handler_win.h b/chrome/utility/font_cache_handler_win.h index e92ef4a..2e2fb40 100644 --- a/chrome/utility/font_cache_handler_win.h +++ b/chrome/utility/font_cache_handler_win.h
@@ -24,10 +24,10 @@ class FontCacheHandler : public UtilityMessageHandler { public: FontCacheHandler() {} - virtual ~FontCacheHandler() {} + ~FontCacheHandler() override {} // IPC::Listener implementation - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; private: void OnBuildFontCache(const base::FilePath& full_path);
diff --git a/chrome/utility/importer/external_process_importer_bridge.h b/chrome/utility/importer/external_process_importer_bridge.h index 35566a3..4611859e 100644 --- a/chrome/utility/importer/external_process_importer_bridge.h +++ b/chrome/utility/importer/external_process_importer_bridge.h
@@ -54,7 +54,7 @@ void AddHomePage(const GURL& home_page) override; #if defined(OS_WIN) - virtual void AddIE7PasswordInfo( + void AddIE7PasswordInfo( const importer::ImporterIE7PasswordInfo& password_info) override; #endif
diff --git a/chrome/utility/importer/ie_importer_win.h b/chrome/utility/importer/ie_importer_win.h index dd33c9a..08f6995 100644 --- a/chrome/utility/importer/ie_importer_win.h +++ b/chrome/utility/importer/ie_importer_win.h
@@ -22,9 +22,9 @@ IEImporter(); // Importer: - virtual void StartImport(const importer::SourceProfile& source_profile, - uint16 items, - ImporterBridge* bridge) override; + void StartImport(const importer::SourceProfile& source_profile, + uint16 items, + ImporterBridge* bridge) override; private: typedef std::vector<ImportedBookmarkEntry> BookmarkVector;
diff --git a/chrome/utility/shell_handler_win.h b/chrome/utility/shell_handler_win.h index 729f111..6c993f74 100644 --- a/chrome/utility/shell_handler_win.h +++ b/chrome/utility/shell_handler_win.h
@@ -30,10 +30,10 @@ class ShellHandler : public UtilityMessageHandler { public: ShellHandler(); - virtual ~ShellHandler(); + ~ShellHandler() override; // IPC::Listener implementation - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; private: void OnOpenFileViaShell(const base::FilePath& full_path);
diff --git a/chrome_elf/blacklist/blacklist.cc b/chrome_elf/blacklist/blacklist.cc index 6aef1cc..8cb2bb1d 100644 --- a/chrome_elf/blacklist/blacklist.cc +++ b/chrome_elf/blacklist/blacklist.cc
@@ -51,6 +51,7 @@ L"libwinhook.dll", // V-Bates. L"lmrn.dll", // Unknown. L"minisp.dll", // Unknown (suspected malware). + L"minisp32.dll", // Unknown (suspected malware). L"safetynut.dll", // Unknown (suspected adware). L"smdmf.dll", // Unknown (suspected adware). L"systemk.dll", // Unknown (suspected adware).
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java index e9bbcc03..937018d8 100644 --- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java +++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastBrowserHelper.java
@@ -20,6 +20,7 @@ import org.chromium.content.browser.DeviceUtils; import org.chromium.content.common.ContentSwitches; import org.chromium.media.MediaDrmBridge; +import org.chromium.net.NetworkChangeNotifier; import java.util.UUID; @@ -75,6 +76,9 @@ Log.d(TAG, "Loading BrowserStartupController..."); BrowserStartupController.get(context, LibraryProcessType.PROCESS_BROWSER) .startBrowserProcessesSync(false); + NetworkChangeNotifier.init(context); + // Cast shell always expects to receive notifications to track network state. + NetworkChangeNotifier.registerToReceiveNotificationsAlways(); sIsBrowserInitialized = true; MediaDrmBridge.addKeySystemUuidMapping(PLAYREADY_KEY_SYSTEM_NAME, PLAYREADY_UUID); return true;
diff --git a/chromecast/browser/service/cast_service.cc b/chromecast/browser/service/cast_service.cc index 91fd2e4..d725abe 100644 --- a/chromecast/browser/service/cast_service.cc +++ b/chromecast/browser/service/cast_service.cc
@@ -34,8 +34,6 @@ void CastService::Finalize() { DCHECK(thread_checker_->CalledOnValidThread()); FinalizeInternal(); - // Consume any pending tasks which may access components being destroyed soon. - base::RunLoop().RunUntilIdle(); } void CastService::Start() {
diff --git a/chromecast/media/base/media_codec_support_simple.cc b/chromecast/media/base/media_codec_support_simple.cc index efdda17a..24e83be 100644 --- a/chromecast/media/base/media_codec_support_simple.cc +++ b/chromecast/media/base/media_codec_support_simple.cc
@@ -4,6 +4,8 @@ #include "chromecast/media/base/media_codec_support.h" +#include "base/bind.h" + namespace chromecast { namespace media {
diff --git a/chromecast/media/cdm/browser_cdm_cast.cc b/chromecast/media/cdm/browser_cdm_cast.cc index 33c10c5..07c3c3e 100644 --- a/chromecast/media/cdm/browser_cdm_cast.cc +++ b/chromecast/media/cdm/browser_cdm_cast.cc
@@ -68,7 +68,7 @@ } void BrowserCdmCast::OnSessionMessage(const std::string& session_id, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& destination_url) { // Note: Message type is not supported in Chromecast. Do our best guess here. ::media::MediaKeys::MessageType message_type = @@ -99,31 +99,6 @@ player_tracker_impl_->NotifyNewKey(); } -void BrowserCdmCast::SetServerCertificateHelper( - const std::vector<uint8>& certificate_data, - scoped_ptr<::media::SimpleCdmPromise> promise) { - SetServerCertificate(certificate_data.data(), - certificate_data.size(), - promise.Pass()); -} - -void BrowserCdmCast::CreateSessionAndGenerateRequestHelper( - ::media::MediaKeys::SessionType session_type, - ::media::EmeInitDataType init_data_type, - const std::vector<uint8>& init_data, - scoped_ptr<::media::NewSessionCdmPromise> promise) { - CreateSessionAndGenerateRequest( - session_type, init_data_type, init_data.data(), init_data.size(), - promise.Pass()); -} - -void BrowserCdmCast::UpdateSessionHelper( - const std::string& session_id, - const std::vector<uint8>& response, - scoped_ptr<::media::SimpleCdmPromise> promise) { - UpdateSession(session_id, response.data(), response.size(), promise.Pass()); -} - // A macro runs current member function on |cdm_loop_| thread. #define FORWARD_ON_CDM_THREAD(param_fn, ...) \ cdm_loop_->PostTask( \ @@ -160,29 +135,26 @@ } void BrowserCdmCastUi::SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<::media::SimpleCdmPromise> promise) { DCHECK(thread_checker_.CalledOnValidThread()); FORWARD_ON_CDM_THREAD( - SetServerCertificateHelper, - std::vector<uint8>(certificate_data, - certificate_data + certificate_data_length), + SetServerCertificate, + certificate, base::Passed(&promise)); } void BrowserCdmCastUi::CreateSessionAndGenerateRequest( ::media::MediaKeys::SessionType session_type, ::media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<::media::NewSessionCdmPromise> promise) { DCHECK(thread_checker_.CalledOnValidThread()); FORWARD_ON_CDM_THREAD( - CreateSessionAndGenerateRequestHelper, + CreateSessionAndGenerateRequest, session_type, init_data_type, - std::vector<uint8>(init_data, init_data + init_data_length), + init_data, base::Passed(&promise)); } @@ -197,14 +169,13 @@ void BrowserCdmCastUi::UpdateSession( const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<::media::SimpleCdmPromise> promise) { DCHECK(thread_checker_.CalledOnValidThread()); FORWARD_ON_CDM_THREAD( - UpdateSessionHelper, + UpdateSession, session_id, - std::vector<uint8>(response, response + response_length), + response, base::Passed(&promise)); }
diff --git a/chromecast/media/cdm/browser_cdm_cast.h b/chromecast/media/cdm/browser_cdm_cast.h index 28fb9848..1f2d8e7 100644 --- a/chromecast/media/cdm/browser_cdm_cast.h +++ b/chromecast/media/cdm/browser_cdm_cast.h
@@ -9,6 +9,7 @@ #include <map> #include <string> +#include <vector> #include "base/callback.h" #include "base/macros.h" @@ -67,7 +68,7 @@ protected: void OnSessionMessage(const std::string& session_id, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& destination_url); void OnSessionClosed(const std::string& session_id); void OnSessionKeysChange(const std::string& session_id, @@ -76,19 +77,6 @@ private: friend class BrowserCdmCastUi; - // Helper methods for forwarding calls to methods that take raw pointers. - void SetServerCertificateHelper( - const std::vector<uint8>& certificate_data, - scoped_ptr<::media::SimpleCdmPromise> promise); - void CreateSessionAndGenerateRequestHelper( - ::media::MediaKeys::SessionType session_type, - ::media::EmeInitDataType init_data_type, - const std::vector<uint8>& init_data, - scoped_ptr<::media::NewSessionCdmPromise> promise); - void UpdateSessionHelper(const std::string& session_id, - const std::vector<uint8>& response, - scoped_ptr<::media::SimpleCdmPromise> promise); - ::media::SessionMessageCB session_message_cb_; ::media::SessionClosedCB session_closed_cb_; ::media::LegacySessionErrorCB legacy_session_error_cb_; @@ -122,21 +110,18 @@ private: // ::media::MediaKeys implementation: void SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<::media::SimpleCdmPromise> promise) override; void CreateSessionAndGenerateRequest( ::media::MediaKeys::SessionType session_type, ::media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<::media::NewSessionCdmPromise> promise) override; void LoadSession(::media::MediaKeys::SessionType session_type, const std::string& session_id, scoped_ptr<::media::NewSessionCdmPromise> promise) override; void UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<::media::SimpleCdmPromise> promise) override; void CloseSession(const std::string& session_id, scoped_ptr<::media::SimpleCdmPromise> promise) override;
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc index 371cf315..cfce893 100644 --- a/chromecast/renderer/cast_content_renderer_client.cc +++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -147,6 +147,13 @@ webview->settings()->setShrinksViewportContentToFit(false); webview->settings()->setMediaControlsOverlayPlayButtonEnabled(false); + // Scale 1 ensures window.innerHeight/Width match application resolution. + // PageScaleOverride is the 'user agent' value which overrides page + // settings (from meta viewport tag) - thus preventing inconsistency + // between Android and non-Android cast_shell. + webview->setDefaultPageScaleLimits(1.f, 1.f); + webview->setInitialPageScaleOverride(1.f); + // Disable application cache as Chromecast doesn't support off-line // application running. webview->settings()->setOfflineWebApplicationCacheEnabled(false);
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index afa1728..ff31dbc 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -140,6 +140,7 @@ "//net:test_support", "//testing/gmock", "//testing/gtest", + "//third_party/icu", "//url", ":cryptohome_proto", ":power_manager_proto",
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index de5659fe..2c7d2b0 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -6996.0.0 \ No newline at end of file +7005.0.0 \ No newline at end of file
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index a5df534..b98e2605 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp
@@ -441,6 +441,8 @@ 'settings/cros_settings_provider.h', 'settings/timezone_settings.cc', 'settings/timezone_settings.h', + 'settings/timezone_settings_helper.cc', + 'settings/timezone_settings_helper.h', 'system/name_value_pairs_parser.cc', 'system/name_value_pairs_parser.h', 'system/statistics_provider.cc', @@ -519,6 +521,7 @@ 'network/shill_property_handler_unittest.cc', 'process_proxy/process_output_watcher_unittest.cc', 'process_proxy/process_proxy_unittest.cc', + 'settings/timezone_settings_unittest.cc', 'system/name_value_pairs_parser_unittest.cc', 'system/version_loader_unittest.cc', 'timezone/timezone_unittest.cc', @@ -672,6 +675,8 @@ '../net/net.gyp:net_test_support', '../testing/gmock.gyp:gmock', '../testing/gtest.gyp:gtest', + '../third_party/icu/icu.gyp:icuuc', + '../third_party/icu/icu.gyp:icui18n', '../url/url.gyp:url_lib', 'chromeos_test_support', 'cryptohome_proto',
diff --git a/chromeos/dbus/fake_shill_manager_client.cc b/chromeos/dbus/fake_shill_manager_client.cc index e6f97cb5..4dc7671 100644 --- a/chromeos/dbus/fake_shill_manager_client.cc +++ b/chromeos/dbus/fake_shill_manager_client.cc
@@ -10,6 +10,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/values.h" #include "chromeos/chromeos_switches.h" #include "chromeos/dbus/dbus_thread_manager.h" @@ -30,6 +31,7 @@ // Allow parsed command line option 'tdls_busy' to set the fake busy count. int s_tdls_busy_count = 0; +int s_extra_wifi_networks = 0; // Used to compare values for finding entries to erase in a ListValue. // (ListValue only implements a const_iterator version of Find). @@ -735,6 +737,15 @@ base::FundamentalValue(true)); profiles->AddService(shared_profile, kPortaledWifiPath); } + + for (int i = 0; i < s_extra_wifi_networks; ++i) { + int id = 4 + i; + std::string path = base::StringPrintf("/service/wifi%d", id); + std::string guid = base::StringPrintf("wifi%d_guid", id); + std::string name = base::StringPrintf("wifi%d", id); + services->AddService(path, guid, name, shill::kTypeWifi, + shill::kStateIdle, add_to_visible); + } } // Wimax @@ -1078,6 +1089,9 @@ bool FakeShillManagerClient::SetInitialNetworkState(std::string type_arg, std::string state_arg) { + int state_arg_as_int = -1; + base::StringToInt(state_arg, &state_arg_as_int); + std::string state; if (state_arg.empty() || state_arg == "1" || state_arg == "on" || state_arg == "enabled" || state_arg == "connected" || @@ -1088,6 +1102,10 @@ state_arg == "inactive" || state_arg == shill::kStateIdle) { // Technology enabled, services are created but are not connected. state = shill::kStateIdle; + } else if (type_arg == shill::kTypeWifi && state_arg_as_int > 1) { + // Enabled and connected, add extra wifi networks. + state = shill::kStateOnline; + s_extra_wifi_networks = state_arg_as_int - 1; } else if (state_arg == "disabled" || state_arg == "disconnect") { // Technology disabled but available, services created but not connected. state = kNetworkDisabled;
diff --git a/chromeos/dbus/services/service_provider_test_helper.cc b/chromeos/dbus/services/service_provider_test_helper.cc index c4c5c654..9b70172 100644 --- a/chromeos/dbus/services/service_provider_test_helper.cc +++ b/chromeos/dbus/services/service_provider_test_helper.cc
@@ -20,6 +20,8 @@ ServiceProviderTestHelper::ServiceProviderTestHelper() : response_received_(false) { + if (!base::MessageLoop::current()) + message_loop_.reset(new base::MessageLoop()); } ServiceProviderTestHelper::~ServiceProviderTestHelper() { @@ -129,7 +131,7 @@ base::Unretained(this))); // Check for a response. if (!response_received_) - message_loop_.Run(); + base::MessageLoop::current()->Run(); // Return response. return response_.release(); } @@ -155,8 +157,8 @@ scoped_ptr<dbus::Response> response) { response_ = response.Pass(); response_received_ = true; - if (message_loop_.is_running()) - message_loop_.Quit(); + if (base::MessageLoop::current()->is_running()) + base::MessageLoop::current()->Quit(); } } // namespace chromeos
diff --git a/chromeos/dbus/services/service_provider_test_helper.h b/chromeos/dbus/services/service_provider_test_helper.h index 196f6a6..c5091b1 100644 --- a/chromeos/dbus/services/service_provider_test_helper.h +++ b/chromeos/dbus/services/service_provider_test_helper.h
@@ -88,7 +88,7 @@ scoped_refptr<dbus::MockObjectProxy> mock_object_proxy_; dbus::ExportedObject::MethodCallCallback method_callback_; dbus::ObjectProxy::SignalCallback on_signal_callback_; - base::MessageLoop message_loop_; + scoped_ptr<base::MessageLoop> message_loop_; bool response_received_; scoped_ptr<dbus::Response> response_; };
diff --git a/chromeos/login/auth/user_context.cc b/chromeos/login/auth/user_context.cc index d82ae5a..4f51b34 100644 --- a/chromeos/login/auth/user_context.cc +++ b/chromeos/login/auth/user_context.cc
@@ -19,6 +19,7 @@ key_(other.key_), auth_code_(other.auth_code_), refresh_token_(other.refresh_token_), + access_token_(other.access_token_), user_id_hash_(other.user_id_hash_), is_using_oauth_(other.is_using_oauth_), auth_flow_(other.auth_flow_), @@ -49,14 +50,13 @@ } bool UserContext::operator==(const UserContext& context) const { - return context.user_id_ == user_id_ && - context.gaia_id_ == gaia_id_ && - context.key_ == key_ && - context.auth_code_ == auth_code_ && + return context.user_id_ == user_id_ && context.gaia_id_ == gaia_id_ && + context.key_ == key_ && context.auth_code_ == auth_code_ && + context.refresh_token_ == refresh_token_ && + context.access_token_ == access_token_ && context.user_id_hash_ == user_id_hash_ && context.is_using_oauth_ == is_using_oauth_ && - context.auth_flow_ == auth_flow_ && - context.user_type_ == user_type_ && + context.auth_flow_ == auth_flow_ && context.user_type_ == user_type_ && context.public_session_locale_ == public_session_locale_ && context.public_session_input_method_ == public_session_input_method_; } @@ -89,6 +89,10 @@ return refresh_token_; } +const std::string& UserContext::GetAccessToken() const { + return access_token_; +} + const std::string& UserContext::GetUserIDHash() const { return user_id_hash_; } @@ -142,6 +146,10 @@ refresh_token_ = refresh_token; } +void UserContext::SetAccessToken(const std::string& access_token) { + access_token_ = access_token; +} + void UserContext::SetUserIDHash(const std::string& user_id_hash) { user_id_hash_ = user_id_hash; }
diff --git a/chromeos/login/auth/user_context.h b/chromeos/login/auth/user_context.h index bac7f4f..727df7f 100644 --- a/chromeos/login/auth/user_context.h +++ b/chromeos/login/auth/user_context.h
@@ -48,6 +48,7 @@ Key* GetKey(); const std::string& GetAuthCode() const; const std::string& GetRefreshToken() const; + const std::string& GetAccessToken() const; const std::string& GetUserIDHash() const; bool IsUsingOAuth() const; AuthFlow GetAuthFlow() const; @@ -63,6 +64,7 @@ void SetKey(const Key& key); void SetAuthCode(const std::string& auth_code); void SetRefreshToken(const std::string& refresh_token); + void SetAccessToken(const std::string& access_token); void SetUserIDHash(const std::string& user_id_hash); void SetIsUsingOAuth(bool is_using_oauth); void SetAuthFlow(AuthFlow auth_flow); @@ -79,6 +81,7 @@ Key key_; std::string auth_code_; std::string refresh_token_; + std::string access_token_; // OAuthLogin scoped access token. std::string user_id_hash_; bool is_using_oauth_; AuthFlow auth_flow_;
diff --git a/chromeos/network/firewall_hole.cc b/chromeos/network/firewall_hole.cc index 425e423..3ad3463 100644 --- a/chromeos/network/firewall_hole.cc +++ b/chromeos/network/firewall_hole.cc
@@ -50,7 +50,7 @@ void PortReleased(FirewallHole::PortType type, uint16_t port, const std::string& interface, - FirewallHole::ScopedFileDescriptor lifeline_fd, + dbus::ScopedFileDescriptor lifeline_fd, bool success) { if (!success) { LOG(WARNING) << "Failed to release firewall hole for " @@ -61,20 +61,13 @@ } // namespace -void CHROMEOS_EXPORT FirewallHole::FileDescriptorDeleter::operator()( - dbus::FileDescriptor* fd) { - base::WorkerPool::PostTask( - FROM_HERE, base::Bind(&base::DeletePointer<dbus::FileDescriptor>, fd), - false); -} - // static void FirewallHole::Open(PortType type, uint16_t port, const std::string& interface, const OpenCallback& callback) { - ScopedFileDescriptor lifeline_local(new dbus::FileDescriptor()); - ScopedFileDescriptor lifeline_remote(new dbus::FileDescriptor()); + dbus::ScopedFileDescriptor lifeline_local(new dbus::FileDescriptor()); + dbus::ScopedFileDescriptor lifeline_remote(new dbus::FileDescriptor()); // This closure shares pointers with the one below. PostTaskAndReply // guarantees that it will always be deleted first. @@ -109,8 +102,8 @@ void FirewallHole::RequestPortAccess(PortType type, uint16_t port, const std::string& interface, - ScopedFileDescriptor lifeline_local, - ScopedFileDescriptor lifeline_remote, + dbus::ScopedFileDescriptor lifeline_local, + dbus::ScopedFileDescriptor lifeline_remote, const OpenCallback& callback) { if (!lifeline_local->is_valid() || !lifeline_remote->is_valid()) { callback.Run(nullptr); @@ -140,7 +133,7 @@ void FirewallHole::PortAccessGranted(PortType type, uint16_t port, const std::string& interface, - ScopedFileDescriptor lifeline_fd, + dbus::ScopedFileDescriptor lifeline_fd, const FirewallHole::OpenCallback& callback, bool success) { if (success) { @@ -154,7 +147,7 @@ FirewallHole::FirewallHole(PortType type, uint16_t port, const std::string& interface, - ScopedFileDescriptor lifeline_fd) + dbus::ScopedFileDescriptor lifeline_fd) : type_(type), port_(port), interface_(interface),
diff --git a/chromeos/network/firewall_hole.h b/chromeos/network/firewall_hole.h index 2bd6788..e6d119d 100644 --- a/chromeos/network/firewall_hole.h +++ b/chromeos/network/firewall_hole.h
@@ -11,10 +11,7 @@ #include "base/callback_forward.h" #include "base/memory/scoped_ptr.h" #include "chromeos/chromeos_export.h" - -namespace dbus { -class FileDescriptor; -} +#include "dbus/file_descriptor.h" namespace chromeos { @@ -29,14 +26,6 @@ typedef base::Callback<void(scoped_ptr<FirewallHole>)> OpenCallback; - // This provides a simple way to pass around file descriptors since they must - // be closed on a thread that is allowed to perform I/O. - struct FileDescriptorDeleter { - void CHROMEOS_EXPORT operator()(dbus::FileDescriptor* fd); - }; - typedef scoped_ptr<dbus::FileDescriptor, FileDescriptorDeleter> - ScopedFileDescriptor; - // Opens a port on the system firewall for the given network interface (or all // interfaces if |interface| is ""). The hole will be closed when the object // provided to the callback is destroyed. @@ -51,28 +40,28 @@ static void RequestPortAccess(PortType type, uint16_t port, const std::string& interface, - ScopedFileDescriptor lifeline_local, - ScopedFileDescriptor lifeline_remote, + dbus::ScopedFileDescriptor lifeline_local, + dbus::ScopedFileDescriptor lifeline_remote, const OpenCallback& callback); static void PortAccessGranted(PortType type, uint16_t port, const std::string& interface, - ScopedFileDescriptor lifeline_fd, + dbus::ScopedFileDescriptor lifeline_fd, const FirewallHole::OpenCallback& callback, bool success); FirewallHole(PortType type, uint16_t port, const std::string& interface, - ScopedFileDescriptor lifeline_fd); + dbus::ScopedFileDescriptor lifeline_fd); const PortType type_; const uint16_t port_; const std::string interface_; // A file descriptor used by firewalld to track the lifetime of this process. - ScopedFileDescriptor lifeline_fd_; + dbus::ScopedFileDescriptor lifeline_fd_; }; } // namespace chromeos
diff --git a/chromeos/network/onc/onc_signature.cc b/chromeos/network/onc/onc_signature.cc index b84421d..e939c17d 100644 --- a/chromeos/network/onc/onc_signature.cc +++ b/chromeos/network/onc/onc_signature.cc
@@ -67,6 +67,7 @@ {::onc::eap::kServerCARef, &kStringSignature}, {::onc::eap::kServerCARefs, &kStringListSignature}, {::onc::eap::kUseSystemCAs, &kBoolSignature}, + {::onc::eap::kUseProactiveKeyCaching, &kBoolSignature}, {NULL}}; const OncFieldSignature ipsec_fields[] = {
diff --git a/chromeos/network/onc/onc_translation_tables.cc b/chromeos/network/onc/onc_translation_tables.cc index 575fdef..d3d00a0 100644 --- a/chromeos/network/onc/onc_translation_tables.cc +++ b/chromeos/network/onc/onc_translation_tables.cc
@@ -33,6 +33,8 @@ {::onc::eap::kSaveCredentials, shill::kSaveCredentialsProperty}, {::onc::eap::kServerCAPEMs, shill::kEapCaCertPemProperty}, {::onc::eap::kUseSystemCAs, shill::kEapUseSystemCasProperty}, + {::onc::eap::kUseProactiveKeyCaching, + shill::kEapUseProactiveKeyCachingProperty}, {NULL}}; const FieldTranslationEntry ipsec_fields[] = {
diff --git a/chromeos/settings/timezone_settings.cc b/chromeos/settings/timezone_settings.cc index 99539ae0..4d0b0b4 100644 --- a/chromeos/settings/timezone_settings.cc +++ b/chromeos/settings/timezone_settings.cc
@@ -20,6 +20,7 @@ #include "base/sys_info.h" #include "base/task_runner.h" #include "base/threading/worker_pool.h" +#include "chromeos/settings/timezone_settings_helper.h" namespace { @@ -166,6 +167,7 @@ "Asia/Singapore", "Asia/Manila", "Asia/Taipei", + "Asia/Ulaanbaatar", "Asia/Makassar", "Asia/Irkutsk", "Asia/Yakutsk", @@ -275,7 +277,7 @@ // Otherwise, returns a timezone from |timezones_|, if such exists, that has // the same rule as the given |timezone|. // Otherwise, returns NULL. - // Note multiple timezones with the same time zone offset may exist + // Note multiple timezones with the same time zone rules may exist // e.g. // US/Pacific == America/Los_Angeles const icu::TimeZone* GetKnownTimezoneOrNull( @@ -362,18 +364,7 @@ const icu::TimeZone* TimezoneSettingsBaseImpl::GetKnownTimezoneOrNull( const icu::TimeZone& timezone) const { - const icu::TimeZone* known_timezone = NULL; - for (std::vector<icu::TimeZone*>::const_iterator iter = timezones_.begin(); - iter != timezones_.end(); ++iter) { - const icu::TimeZone* entry = *iter; - if (*entry == timezone) - return entry; - if (entry->hasSameRules(timezone)) - known_timezone = entry; - } - - // May return NULL if we did not find a matching timezone in our list. - return known_timezone; + return chromeos::system::GetKnownTimezoneOrNull(timezone, timezones_); } void TimezoneSettingsImpl::SetTimezone(const icu::TimeZone& timezone) { @@ -419,6 +410,11 @@ icu::TimeZone::setDefault(*timezone_); VLOG(1) << "Timezone initially set to " << id; + icu::UnicodeString resolvedId; + std::string resolvedIdStr; + timezone_->getID(resolvedId); + VLOG(1) << "Timezone initially resolved to " + << resolvedId.toUTF8String(resolvedIdStr); } void TimezoneSettingsStubImpl::SetTimezone(const icu::TimeZone& timezone) { @@ -428,6 +424,8 @@ if (!known_timezone) known_timezone = &timezone; + std::string id = base::UTF16ToUTF8(GetTimezoneID(*known_timezone)); + VLOG(1) << "Setting timezone to " << id; timezone_.reset(known_timezone->clone()); icu::TimeZone::setDefault(*known_timezone); FOR_EACH_OBSERVER(Observer, observers_, TimezoneChanged(*known_timezone));
diff --git a/chromeos/settings/timezone_settings_helper.cc b/chromeos/settings/timezone_settings_helper.cc new file mode 100644 index 0000000..781f774 --- /dev/null +++ b/chromeos/settings/timezone_settings_helper.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 "chromeos/settings/timezone_settings_helper.h" + +#include "base/logging.h" +#include "chromeos/chromeos_export.h" + +namespace chromeos { +namespace system { + +CHROMEOS_EXPORT const icu::TimeZone* GetKnownTimezoneOrNull( + const icu::TimeZone& timezone, + const std::vector<icu::TimeZone*>& timezone_list) { + const icu::TimeZone* known_timezone = NULL; + icu::UnicodeString id, canonical_id; + timezone.getID(id); + UErrorCode status = U_ZERO_ERROR; + icu::TimeZone::getCanonicalID(id, canonical_id, status); + DCHECK(U_SUCCESS(status)); + for (const auto* entry : timezone_list) { + if (*entry == timezone) + return entry; + // Compare the canonical IDs as well. + // For instance, Asia/Ulan_Bator -> Asia/Ulaanbaatar or + // Canada/Pacific -> America/Vancouver + icu::UnicodeString entry_id, entry_canonical_id; + entry->getID(entry_id); + icu::TimeZone::getCanonicalID(entry_id, entry_canonical_id, status); + DCHECK(U_SUCCESS(status)); + if (entry_canonical_id == canonical_id) + return entry; + // Last resort: If no match is found, the last timezone in the list + // with matching rules will be returned. + if (entry->hasSameRules(timezone)) + known_timezone = entry; + } + + // May return NULL if we did not find a matching timezone in our list. + return known_timezone; +} + +} // namespace system +} // namespace chromeos
diff --git a/chromeos/settings/timezone_settings_helper.h b/chromeos/settings/timezone_settings_helper.h new file mode 100644 index 0000000..c8ed8ee --- /dev/null +++ b/chromeos/settings/timezone_settings_helper.h
@@ -0,0 +1,25 @@ +// 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 CHROMEOS_SETTINGS_TIMEZONE_SETTINGS_HELPER_H_ +#define CHROMEOS_SETTINGS_TIMEZONE_SETTINGS_HELPER_H_ + +#include <vector> + +#include "third_party/icu/source/i18n/unicode/timezone.h" + +namespace chromeos { +namespace system { + +// Return a timezone in the list matching |timezone| in terms of +// id and canonical id. If both fail, return a timezone with +// the same rules. Otherwise, return null. +const icu::TimeZone* GetKnownTimezoneOrNull( + const icu::TimeZone& timezone, + const std::vector<icu::TimeZone*>& timezone_list); + +} // namespace system +} // namespace chromeos + +#endif // CHROMEOS_SETTINGS_TIMEZONE_SETTINGS_HELPER_H_
diff --git a/chromeos/settings/timezone_settings_unittest.cc b/chromeos/settings/timezone_settings_unittest.cc new file mode 100644 index 0000000..d8b5b5f --- /dev/null +++ b/chromeos/settings/timezone_settings_unittest.cc
@@ -0,0 +1,104 @@ +// 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/scoped_ptr.h" +#include "base/stl_util.h" +#include "chromeos/settings/timezone_settings_helper.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/icu/source/common/unicode/unistr.h" +#include "third_party/icu/source/i18n/unicode/timezone.h" + +namespace chromeos { +namespace system { + +using icu::TimeZone; +using icu::UnicodeString; + +const char* kTimeZones[] = { + "America/Los_Angeles", + "America/Vancouver", + "America/Chicago", + "America/Winnipeg", + "America/Mexico_City", + "America/Buenos_Aires", + "Asia/Ho_Chi_Minh", + "Asia/Seoul", + "Europe/Athens", + "Asia/Ulaanbaatar", +}; + +class KnownTimeZoneTest : public testing::Test { + public: + KnownTimeZoneTest() {} + ~KnownTimeZoneTest() override {} + + void SetUp() override { + for (const char* id : kTimeZones) { + timezones_.push_back(TimeZone::createTimeZone(UnicodeString(id))); + } + } + + void TearDown() override { STLDeleteElements(&timezones_); } + + protected: + std::vector<TimeZone*> timezones_; +}; + +TEST_F(KnownTimeZoneTest, IdMatch) { + static struct { + const char* id; + const char* matched; + } timezone_match_list[] = { + // Self matches + {"America/Los_Angeles", "America/Los_Angeles"}, + {"America/Vancouver", "America/Vancouver"}, // Should not be Los_Angeles + {"America/Winnipeg", "America/Winnipeg"}, + {"Asia/Seoul", "Asia/Seoul"}, + // Canonical ID matches + {"Canada/Pacific", "America/Vancouver"}, + {"US/Pacific", "America/Los_Angeles"}, + {"US/Central", "America/Chicago"}, + {"Mexico/General", "America/Mexico_City"}, + {"Asia/Ulan_Bator", "Asia/Ulaanbaatar"}, + // Asia/Saigon is canonical, but the list has Asia/Ho_Chi_Minh + {"Asia/Saigon", "Asia/Ho_Chi_Minh"}, + }; + + for (const auto& pair : timezone_match_list) { + scoped_ptr<TimeZone> input( + TimeZone::createTimeZone(UnicodeString(pair.id))); + scoped_ptr<TimeZone> expected( + TimeZone::createTimeZone(UnicodeString(pair.matched))); + const TimeZone* actual = GetKnownTimezoneOrNull(*input, timezones_); + EXPECT_NE(nullptr, actual) << "input=" << pair.id; + if (actual == nullptr) + continue; + UnicodeString actual_id; + actual->getID(actual_id); + std::string actual_id_str; + actual_id.toUTF8String(actual_id_str); + EXPECT_EQ(*expected, *actual) << "input=" << pair.id << ", " + << "expected=" << pair.matched << ", " + << "actual=" << actual_id_str; + } +} + +TEST_F(KnownTimeZoneTest, NoMatch) { + static const char* no_match_list[] = { + "Africa/Juba", // Not in the list + "Africa/Tripoli", // UTC+2 with no DST != Europe/Athens + "America/Tijuana", // Historically != America/Los_Angeles + "Europe/Sofia", // Historically != Europe/Athens + "America/Argentina/Cordoba", // Historically != America/Buenos_Aires + "Asia/Tokyo", // Historically != Asia/Seoul + }; + for (const char* id : no_match_list) { + scoped_ptr<TimeZone> input(TimeZone::createTimeZone(UnicodeString(id))); + EXPECT_EQ(NULL, GetKnownTimezoneOrNull(*input, timezones_)) + << "input=" << id; + } +} + +} // namespace system +} // namespace chromeos
diff --git a/chromeos/test/data/network/shill_wifi_clientcert.json b/chromeos/test/data/network/shill_wifi_clientcert.json index 2b90e7f..b3ff20f 100644 --- a/chromeos/test/data/network/shill_wifi_clientcert.json +++ b/chromeos/test/data/network/shill_wifi_clientcert.json
@@ -1,6 +1,7 @@ { "EAP.EAP": "TLS", "EAP.Identity": "abc ${LOGIN_ID}@my.domain.com", + "EAP.UseProactiveKeyCaching": true, "EAP.UseSystemCAs": true, "GUID": "{77db0089-0bc8-4358-929c-123xcv}", "Mode": "managed",
diff --git a/chromeos/test/data/network/translation_of_shill_wifi_clientcert.onc b/chromeos/test/data/network/translation_of_shill_wifi_clientcert.onc index 7a32530..52dd992 100644 --- a/chromeos/test/data/network/translation_of_shill_wifi_clientcert.onc +++ b/chromeos/test/data/network/translation_of_shill_wifi_clientcert.onc
@@ -6,6 +6,7 @@ "EAP": { "Identity": "abc ${LOGIN_ID}@my.domain.com", "SaveCredentials": true, + "UseProactiveKeyCaching": true, "UseSystemCAs": true }, "HexSSID":"4F70656E577274", // "OpenWrt"
diff --git a/chromeos/test/data/network/wifi_clientcert_with_cert_pems.onc b/chromeos/test/data/network/wifi_clientcert_with_cert_pems.onc index 7e31b61..6e2f47b 100644 --- a/chromeos/test/data/network/wifi_clientcert_with_cert_pems.onc +++ b/chromeos/test/data/network/wifi_clientcert_with_cert_pems.onc
@@ -9,6 +9,7 @@ "EAP": { "Outer": "EAP-TLS", "Identity": "abc ${LOGIN_ID}@my.domain.com", + "UseProactiveKeyCaching": true, "UseSystemCAs": true, "ClientCertType": "Pattern", "ClientCertPattern": {
diff --git a/cloud_print/gcp20/prototype/cloud_print_request.h b/cloud_print/gcp20/prototype/cloud_print_request.h index 681299f..5cd8357 100644 --- a/cloud_print/gcp20/prototype/cloud_print_request.h +++ b/cloud_print/gcp20/prototype/cloud_print_request.h
@@ -38,7 +38,7 @@ virtual void OnFetchTimeoutReached() = 0; }; - virtual ~CloudPrintRequest(); + ~CloudPrintRequest() override; // Creates GET request. static scoped_ptr<CloudPrintRequest> CreateGet(const GURL& url, @@ -63,7 +63,7 @@ Delegate* delegate); // net::URLFetcherDelegate methods: - virtual void OnURLFetchComplete(const net::URLFetcher* source) override; + void OnURLFetchComplete(const net::URLFetcher* source) override; // Method for handling timeout. void OnRequestTimeout();
diff --git a/cloud_print/gcp20/prototype/cloud_print_requester.h b/cloud_print/gcp20/prototype/cloud_print_requester.h index 91c24a0..d916a4f 100644 --- a/cloud_print/gcp20/prototype/cloud_print_requester.h +++ b/cloud_print/gcp20/prototype/cloud_print_requester.h
@@ -134,20 +134,20 @@ typedef base::Callback<void(const std::string&)> ParserCallback; // CloudPrintRequester::Delegate methods: - virtual void OnFetchComplete(const std::string& response) override; - virtual void OnFetchError(const std::string& server_api, - int server_code, - int server_http_code) override; - virtual void OnFetchTimeoutReached() override; + void OnFetchComplete(const std::string& response) override; + void OnFetchError(const std::string& server_api, + int server_code, + int server_http_code) override; + void OnFetchTimeoutReached() override; // gaia::GaiaOAuthClient::Delegate methods: - virtual void OnGetTokensResponse(const std::string& refresh_token, - const std::string& access_token, - int expires_in_seconds) override; - virtual void OnRefreshTokenResponse(const std::string& access_token, - int expires_in_seconds) override; - virtual void OnOAuthError() override; - virtual void OnNetworkError(int response_code) override; + void OnGetTokensResponse(const std::string& refresh_token, + const std::string& access_token, + int expires_in_seconds) override; + void OnRefreshTokenResponse(const std::string& access_token, + int expires_in_seconds) override; + void OnOAuthError() override; + void OnNetworkError(int response_code) override; // Creates GET request. scoped_ptr<CloudPrintRequest> CreateGet(const GURL& url,
diff --git a/cloud_print/gcp20/prototype/cloud_print_url_request_context_getter.h b/cloud_print/gcp20/prototype/cloud_print_url_request_context_getter.h index 1fb52a6..3be24996 100644 --- a/cloud_print/gcp20/prototype/cloud_print_url_request_context_getter.h +++ b/cloud_print/gcp20/prototype/cloud_print_url_request_context_getter.h
@@ -18,13 +18,13 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner); // URLRequestContextGetter implementation. - virtual net::URLRequestContext* GetURLRequestContext() override; + net::URLRequestContext* GetURLRequestContext() override; - virtual scoped_refptr<base::SingleThreadTaskRunner> + scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; private: - virtual ~CloudPrintURLRequestContextGetter(); + ~CloudPrintURLRequestContextGetter() override; scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; scoped_ptr<net::URLRequestContext> context_;
diff --git a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h index 32dde8c..8c8ed9d0 100644 --- a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h +++ b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h
@@ -65,7 +65,7 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner, Delegate* delegate); - virtual ~CloudPrintXmppListener(); + ~CloudPrintXmppListener() override; // Connects to the server. void Connect(const std::string& access_token); @@ -75,12 +75,12 @@ private: // notifier::PushClientObserver methods: - virtual void OnNotificationsEnabled() override; - virtual void OnNotificationsDisabled( + void OnNotificationsEnabled() override; + void OnNotificationsDisabled( notifier::NotificationsDisabledReason reason) override; - virtual void OnIncomingNotification( + void OnIncomingNotification( const notifier::Notification& notification) override; - virtual void OnPingResponse() override; + void OnPingResponse() override; // Stops listening and sending pings. void Disconnect();
diff --git a/cloud_print/gcp20/prototype/printer.h b/cloud_print/gcp20/prototype/printer.h index 1c83939..fde8b8f7 100644 --- a/cloud_print/gcp20/prototype/printer.h +++ b/cloud_print/gcp20/prototype/printer.h
@@ -30,7 +30,7 @@ Printer(); // Destroys the object. - virtual ~Printer(); + ~Printer() override; // Starts all servers. bool Start(); @@ -54,78 +54,77 @@ std::string GetRawCdd(); // PrivetHttpServer::Delegate methods: - virtual PrivetHttpServer::RegistrationErrorStatus RegistrationStart( + PrivetHttpServer::RegistrationErrorStatus RegistrationStart( const std::string& user) override; - virtual PrivetHttpServer::RegistrationErrorStatus RegistrationGetClaimToken( + PrivetHttpServer::RegistrationErrorStatus RegistrationGetClaimToken( const std::string& user, std::string* token, std::string* claim_url) override; - virtual PrivetHttpServer::RegistrationErrorStatus RegistrationComplete( + PrivetHttpServer::RegistrationErrorStatus RegistrationComplete( const std::string& user, std::string* device_id) override; - virtual PrivetHttpServer::RegistrationErrorStatus RegistrationCancel( + PrivetHttpServer::RegistrationErrorStatus RegistrationCancel( const std::string& user) override; - virtual void GetRegistrationServerError(std::string* description) override; - virtual void CreateInfo(PrivetHttpServer::DeviceInfo* info) override; - virtual bool IsRegistered() const override; - virtual bool IsLocalPrintingAllowed() const override; - virtual bool CheckXPrivetTokenHeader(const std::string& token) const override; - virtual const base::DictionaryValue& GetCapabilities() override; - virtual LocalPrintJob::CreateResult CreateJob( + void GetRegistrationServerError(std::string* description) override; + void CreateInfo(PrivetHttpServer::DeviceInfo* info) override; + bool IsRegistered() const override; + bool IsLocalPrintingAllowed() const override; + bool CheckXPrivetTokenHeader(const std::string& token) const override; + const base::DictionaryValue& GetCapabilities() override; + LocalPrintJob::CreateResult CreateJob( const std::string& ticket, std::string* job_id, int* expires_in, int* error_timeout, std::string* error_description) override; - virtual LocalPrintJob::SaveResult SubmitDoc( + LocalPrintJob::SaveResult SubmitDoc( const LocalPrintJob& job, std::string* job_id, int* expires_in, std::string* error_description, int* timeout) override; - virtual LocalPrintJob::SaveResult SubmitDocWithId( + LocalPrintJob::SaveResult SubmitDocWithId( const LocalPrintJob& job, const std::string& job_id, int* expires_in, std::string* error_description, int* timeout) override; - virtual bool GetJobState(const std::string& id, - LocalPrintJob::Info* info) override; + bool GetJobState(const std::string& id, LocalPrintJob::Info* info) override; // CloudRequester::Delegate methods: - virtual void OnRegistrationStartResponseParsed( + void OnRegistrationStartResponseParsed( const std::string& registration_token, const std::string& complete_invite_url, const std::string& device_id) override; - virtual void OnRegistrationFinished( + void OnRegistrationFinished( const std::string& refresh_token, const std::string& access_token, int access_token_expires_in_seconds) override; - virtual void OnXmppJidReceived(const std::string& xmpp_jid) override; - virtual void OnAccesstokenReceviced(const std::string& access_token, - int expires_in_seconds) override; - virtual void OnRegistrationError(const std::string& description) override; - virtual void OnNetworkError() override; - virtual void OnServerError(const std::string& description) override; - virtual void OnAuthError() override; - virtual std::string GetAccessToken() override; - virtual void OnPrintJobsAvailable( + void OnXmppJidReceived(const std::string& xmpp_jid) override; + void OnAccesstokenReceviced(const std::string& access_token, + int expires_in_seconds) override; + void OnRegistrationError(const std::string& description) override; + void OnNetworkError() override; + void OnServerError(const std::string& description) override; + void OnAuthError() override; + std::string GetAccessToken() override; + void OnPrintJobsAvailable( const std::vector<cloud_print_response_parser::Job>& jobs) override; - virtual void OnPrintJobDownloaded( + void OnPrintJobDownloaded( const cloud_print_response_parser::Job& job) override; - virtual void OnPrintJobDone() override; - virtual void OnLocalSettingsReceived( + void OnPrintJobDone() override; + void OnLocalSettingsReceived( LocalSettings::State state, const LocalSettings& settings) override; - virtual void OnLocalSettingsUpdated() override; + void OnLocalSettingsUpdated() override; // CloudPrintXmppListener::Delegate methods: - virtual void OnXmppConnected() override; - virtual void OnXmppAuthError() override; - virtual void OnXmppNetworkError() override; - virtual void OnXmppNewPrintJob(const std::string& device_id) override; - virtual void OnXmppNewLocalSettings(const std::string& device_id) override; - virtual void OnXmppDeleteNotification(const std::string& device_id) override; + void OnXmppConnected() override; + void OnXmppAuthError() override; + void OnXmppNetworkError() override; + void OnXmppNewPrintJob(const std::string& device_id) override; + void OnXmppNewLocalSettings(const std::string& device_id) override; + void OnXmppDeleteNotification(const std::string& device_id) override; // Method for trying to reconnecting to server on start or after network fail. void TryConnect();
diff --git a/cloud_print/gcp20/prototype/privet_http_server.h b/cloud_print/gcp20/prototype/privet_http_server.h index 26fcdfb6..5f92d68 100644 --- a/cloud_print/gcp20/prototype/privet_http_server.h +++ b/cloud_print/gcp20/prototype/privet_http_server.h
@@ -141,16 +141,15 @@ private: // net::HttpServer::Delegate methods: - virtual void OnConnect(int connection_id) override {} - virtual void OnHttpRequest( + void OnConnect(int connection_id) override {} + void OnHttpRequest( int connection_id, const net::HttpServerRequestInfo& info) override; - virtual void OnWebSocketRequest( + void OnWebSocketRequest( int connection_id, const net::HttpServerRequestInfo& info) override; - virtual void OnWebSocketMessage(int connection_id, - const std::string& data) override; - virtual void OnClose(int connection_id) override; + void OnWebSocketMessage(int connection_id, const std::string& data) override; + void OnClose(int connection_id) override; // Sends error as response. Invoked when request method is invalid. void ReportInvalidMethod(int connection_id);
diff --git a/cloud_print/service/win/chrome_launcher.h b/cloud_print/service/win/chrome_launcher.h index 073add7..189bbc7 100644 --- a/cloud_print/service/win/chrome_launcher.h +++ b/cloud_print/service/win/chrome_launcher.h
@@ -17,12 +17,13 @@ public: explicit ChromeLauncher(const base::FilePath& user_data); - virtual ~ChromeLauncher(); + ~ChromeLauncher() override; bool Start(); void Stop(); - virtual void Run() override; + // base::DelegateSimpleThread::Delegate: + void Run() override; static std::string CreateServiceStateFile( const std::string& proxy_id,
diff --git a/cloud_print/service/win/cloud_print_service_config.cc b/cloud_print/service/win/cloud_print_service_config.cc index 9eeeee3..a0f5044d 100644 --- a/cloud_print/service/win/cloud_print_service_config.cc +++ b/cloud_print/service/win/cloud_print_service_config.cc
@@ -34,10 +34,10 @@ class Dispatcher : public base::MessagePumpDispatcher { public: explicit Dispatcher(SetupDialog* dialog) : dialog_(dialog) {} - virtual ~Dispatcher() {}; + ~Dispatcher() override {} // MessagePumpDispatcher: - virtual uint32_t Dispatch(const MSG& msg) override { + uint32_t Dispatch(const MSG& msg) override { MSG msg2 = msg; uint32_t action = POST_DISPATCH_NONE; if (!dialog_->IsDialogMessage(&msg2))
diff --git a/cloud_print/service/win/service_listener.h b/cloud_print/service/win/service_listener.h index c1001673..7344edd7 100644 --- a/cloud_print/service/win/service_listener.h +++ b/cloud_print/service/win/service_listener.h
@@ -23,10 +23,10 @@ class ServiceListener : public IPC::Listener { public: explicit ServiceListener(const base::FilePath& user_data_dir); - virtual ~ServiceListener(); + ~ServiceListener() override; - virtual bool OnMessageReceived(const IPC::Message& msg) override; - virtual void OnChannelConnected(int32 peer_pid) override; + bool OnMessageReceived(const IPC::Message& msg) override; + void OnChannelConnected(int32 peer_pid) override; private: void Disconnect();
diff --git a/cloud_print/service/win/setup_listener.h b/cloud_print/service/win/setup_listener.h index a43aea1f..b0c2c67 100644 --- a/cloud_print/service/win/setup_listener.h +++ b/cloud_print/service/win/setup_listener.h
@@ -36,10 +36,10 @@ static const wchar_t kSetupPipeName[]; explicit SetupListener(const base::string16& user); - virtual ~SetupListener(); + ~SetupListener() override; - virtual bool OnMessageReceived(const IPC::Message& msg) override; - virtual void OnChannelError() override; + bool OnMessageReceived(const IPC::Message& msg) override; + void OnChannelError() override; bool WaitResponce(const base::TimeDelta& delta);
diff --git a/codereview.settings b/codereview.settings index 9789920c..31af4b3 100644 --- a/codereview.settings +++ b/codereview.settings
@@ -10,3 +10,4 @@ LINT_IGNORE_REGEX: webkit/api/.* PROJECT: chromium PENDING_REF_PREFIX: refs/pending/ +RUN_POST_UPLOAD_HOOK: True
diff --git a/components/autofill.gypi b/components/autofill.gypi index 25f6909a..283881c 100644 --- a/components/autofill.gypi +++ b/components/autofill.gypi
@@ -27,6 +27,8 @@ 'autofill/core/common/autofill_l10n_util.h', 'autofill/core/common/autofill_pref_names.cc', 'autofill/core/common/autofill_pref_names.h', + 'autofill/core/common/autofill_regexes.cc', + 'autofill/core/common/autofill_regexes.h', 'autofill/core/common/autofill_switches.cc', 'autofill/core/common/autofill_switches.h', 'autofill/core/common/form_data.cc', @@ -48,6 +50,9 @@ 'autofill/core/common/web_element_descriptor.cc', 'autofill/core/common/web_element_descriptor.h', ], + + # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. + 'msvs_disabled_warnings': [4267, ], }, { @@ -126,8 +131,6 @@ 'autofill/core/browser/autofill_profile.h', 'autofill/core/browser/autofill_regex_constants.cc', 'autofill/core/browser/autofill_regex_constants.h', - 'autofill/core/browser/autofill_regexes.cc', - 'autofill/core/browser/autofill_regexes.h', 'autofill/core/browser/autofill_scanner.cc', 'autofill/core/browser/autofill_scanner.h', 'autofill/core/browser/autofill_server_field_info.h',
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 31068330..16099c0c 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -4,6 +4,7 @@ #include "components/autofill/content/renderer/autofill_agent.h" +#include "base/auto_reset.h" #include "base/bind.h" #include "base/command_line.h" #include "base/message_loop/message_loop.h" @@ -43,6 +44,7 @@ #include "third_party/WebKit/public/web/WebNode.h" #include "third_party/WebKit/public/web/WebOptionElement.h" #include "third_party/WebKit/public/web/WebTextAreaElement.h" +#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" #include "third_party/WebKit/public/web/WebView.h" #include "ui/base/l10n/l10n_util.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -62,6 +64,7 @@ using blink::WebOptionElement; using blink::WebString; using blink::WebTextAreaElement; +using blink::WebUserGestureIndicator; using blink::WebVector; namespace autofill { @@ -149,7 +152,6 @@ autofill_query_id_(0), was_query_node_autofilled_(false), has_shown_autofill_popup_for_current_edit_(false), - did_set_node_text_(false), ignore_text_changes_(false), is_popup_possibly_visible_(false), weak_ptr_factory_(this) { @@ -378,15 +380,12 @@ } void AutofillAgent::textFieldDidChange(const WebFormControlElement& element) { + DCHECK(toWebInputElement(&element) || IsTextAreaElement(element)); if (ignore_text_changes_) return; - DCHECK(toWebInputElement(&element) || IsTextAreaElement(element)); - - if (did_set_node_text_) { - did_set_node_text_ = false; + if (!WebUserGestureIndicator::isProcessingUserGesture()) return; - } // We post a task for doing the Autofill as the caret position is not set // properly at this point (http://bugs.webkit.org/show_bug.cgi?id=16976) and @@ -714,7 +713,7 @@ void AutofillAgent::FillFieldWithValue(const base::string16& value, WebInputElement* node) { - did_set_node_text_ = true; + base::AutoReset<bool> auto_reset(&ignore_text_changes_, true); node->setEditingValue(value.substr(0, node->maxLength())); }
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h index 4ec475c..39d6573 100644 --- a/components/autofill/content/renderer/autofill_agent.h +++ b/components/autofill/content/renderer/autofill_agent.h
@@ -252,9 +252,6 @@ // currently editing? Used to keep track of state for metrics logging. bool has_shown_autofill_popup_for_current_edit_; - // If true we just set the node text so we shouldn't show the popup. - bool did_set_node_text_; - // Whether or not to ignore text changes. Useful for when we're committing // a composition when we are defocusing the WebView and we don't want to // trigger an autofill popup to show.
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc index b1f3056e..ab28cde 100644 --- a/components/autofill/content/renderer/form_autofill_util.cc +++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -14,6 +14,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/common/autofill_data_validation.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/autofill_switches.h" #include "components/autofill/core/common/form_data.h" #include "components/autofill/core/common/form_field_data.h" @@ -1161,9 +1162,8 @@ // labels for all form control elements are scraped from the DOM and set in // WebFormElementToFormData. field->name = element.nameForAutofill(); - field->form_control_type = base::UTF16ToUTF8(element.formControlType()); - field->autocomplete_attribute = - base::UTF16ToUTF8(element.getAttribute(kAutocomplete)); + field->form_control_type = element.formControlType().utf8(); + field->autocomplete_attribute = element.getAttribute(kAutocomplete).utf8(); if (field->autocomplete_attribute.size() > kMaxDataLength) { // Discard overly long attribute values to avoid DOS-ing the browser // process. However, send over a default string to indicate that the @@ -1286,11 +1286,28 @@ const std::vector<blink::WebElement>& fieldsets, const std::vector<blink::WebFormControlElement>& control_elements, const blink::WebFormControlElement* element, - const GURL& origin, + const blink::WebDocument& document, ExtractMask extract_mask, FormData* form, FormFieldData* field) { - form->origin = origin; + // Only attempt formless Autofill on checkout flows. This avoids the many + // false positives found on the non-checkout web. See http://crbug.com/462375 + // For now this early abort only applies to English-language pages, because + // the regex is not translated. Note that an empty "lang" attribute counts as + // English. A potential problem is that this only checks document.title(), but + // should actually check the main frame's title. Thus it may make bad + // decisions for iframes. + WebElement html_element = document.documentElement(); + std::string lang; + if (!html_element.isNull()) + lang = html_element.getAttribute("lang").utf8(); + if ((lang.empty() || StartsWithASCII(lang, "en", false)) && + !MatchesPattern(document.title(), + base::UTF8ToUTF16("payment|checkout|address|delivery|shipping"))) { + return false; + } + + form->origin = document.url(); form->user_submitted = false; form->is_form_tag = false; @@ -1314,7 +1331,7 @@ std::vector<WebFormControlElement> control_elements = GetUnownedAutofillableFormFieldElements(document.all(), &fieldsets); return UnownedFormElementsAndFieldSetsToFormData( - fieldsets, control_elements, &element, document.url(), extract_mask, + fieldsets, control_elements, &element, document, extract_mask, form, field); }
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h index 0faf82c..1be05cd 100644 --- a/components/autofill/content/renderer/form_autofill_util.h +++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -122,7 +122,7 @@ const std::vector<blink::WebElement>& fieldsets, const std::vector<blink::WebFormControlElement>& control_elements, const blink::WebFormControlElement* element, - const GURL& origin, + const blink::WebDocument& document, ExtractMask extract_mask, FormData* form, FormFieldData* field);
diff --git a/components/autofill/content/renderer/form_cache.cc b/components/autofill/content/renderer/form_cache.cc index 029c5fa0..c1a41a8 100644 --- a/components/autofill/content/renderer/form_cache.cc +++ b/components/autofill/content/renderer/form_cache.cc
@@ -133,7 +133,7 @@ FormData synthetic_form; if (!UnownedFormElementsAndFieldSetsToFormData( - fieldsets, control_elements, nullptr, document.url(), extract_mask, + fieldsets, control_elements, nullptr, document, extract_mask, &synthetic_form, nullptr)) { return forms; }
diff --git a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc index 6971997..d733c53 100644 --- a/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc +++ b/components/autofill/content/renderer/password_form_conversion_utils_browsertest.cc
@@ -105,7 +105,7 @@ DISALLOW_COPY_AND_ASSIGN(PasswordFormBuilder); }; -// RenderVIewTest-based tests crash on Android +// RenderViewTest-based tests crash on Android // http://crbug.com/187500 #if defined(OS_ANDROID) #define MAYBE_PasswordFormConversionUtilsTest \
diff --git a/components/autofill/content/renderer/password_generation_agent.cc b/components/autofill/content/renderer/password_generation_agent.cc index d77d1b26..e780bb4 100644 --- a/components/autofill/content/renderer/password_generation_agent.cc +++ b/components/autofill/content/renderer/password_generation_agent.cc
@@ -118,49 +118,50 @@ PasswordGenerationAgent::~PasswordGenerationAgent() {} void PasswordGenerationAgent::DidFinishDocumentLoad() { - if (render_frame()->GetWebFrame()->parent()) - return; + // Update stats for main frame navigation. + if (!render_frame()->GetWebFrame()->parent()) { + // In every navigation, the IPC message sent by the password autofill + // manager to query whether the current form is blacklisted or not happens + // when the document load finishes, so we need to clear previous states + // here before we hear back from the browser. We only clear this state on + // main frame load as we don't want subframe loads to clear state that we + // have received from the main frame. Note that we assume there is only one + // account creation form, but there could be multiple password forms in + // each frame. + not_blacklisted_password_form_origins_.clear(); + generation_enabled_forms_.clear(); + generation_element_.reset(); + possible_account_creation_forms_.clear(); - // In every navigation, the IPC message sent by the password autofill manager - // to query whether the current form is blacklisted or not happens when the - // document load finishes, so we need to clear previous states here before we - // hear back from the browser. We only clear this state on main frame load - // as we don't want subframe loads to clear state that we have received from - // the main frame. Note that we assume there is only one account creation - // form, but there could be multiple password forms in each frame. - not_blacklisted_password_form_origins_.clear(); - generation_enabled_forms_.clear(); - generation_element_.reset(); - possible_account_creation_forms_.clear(); + // Log statistics after navigation so that we only log once per page. + if (generation_form_data_ && + generation_form_data_->password_elements.empty()) { + password_generation::LogPasswordGenerationEvent( + password_generation::NO_SIGN_UP_DETECTED); + } else { + password_generation::LogPasswordGenerationEvent( + password_generation::SIGN_UP_DETECTED); + } + generation_form_data_.reset(); + password_is_generated_ = false; + if (password_edited_) { + password_generation::LogPasswordGenerationEvent( + password_generation::PASSWORD_EDITED); + } + password_edited_ = false; - // Log statistics after navigation so that we only log once per page. - if (generation_form_data_ && - generation_form_data_->password_elements.empty()) { - password_generation::LogPasswordGenerationEvent( - password_generation::NO_SIGN_UP_DETECTED); - } else { - password_generation::LogPasswordGenerationEvent( - password_generation::SIGN_UP_DETECTED); - } - generation_form_data_.reset(); - password_is_generated_ = false; - if (password_edited_) { - password_generation::LogPasswordGenerationEvent( - password_generation::PASSWORD_EDITED); - } - password_edited_ = false; + if (generation_popup_shown_) { + password_generation::LogPasswordGenerationEvent( + password_generation::GENERATION_POPUP_SHOWN); + } + generation_popup_shown_ = false; - if (generation_popup_shown_) { - password_generation::LogPasswordGenerationEvent( - password_generation::GENERATION_POPUP_SHOWN); + if (editing_popup_shown_) { + password_generation::LogPasswordGenerationEvent( + password_generation::EDITING_POPUP_SHOWN); + } + editing_popup_shown_ = false; } - generation_popup_shown_ = false; - - if (editing_popup_shown_) { - password_generation::LogPasswordGenerationEvent( - password_generation::EDITING_POPUP_SHOWN); - } - editing_popup_shown_ = false; FindPossibleGenerationForm(); } @@ -213,7 +214,7 @@ if (!possible_account_creation_forms_.empty()) { VLOG(2) << possible_account_creation_forms_.size() - << " possible account creation forms deteceted"; + << " possible account creation forms deteceted"; DetermineGenerationElement(); } }
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index 6c2d3d1..a689000 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -42,8 +42,6 @@ "autofill_profile.h", "autofill_regex_constants.cc", "autofill_regex_constants.h", - "autofill_regexes.cc", - "autofill_regexes.h", "autofill_scanner.cc", "autofill_scanner.h", "autofill_server_field_info.h", @@ -207,7 +205,6 @@ "autofill_merge_unittest.cc", "autofill_metrics_unittest.cc", "autofill_profile_unittest.cc", - "autofill_regexes_unittest.cc", "autofill_type_unittest.cc", "autofill_xml_parser_unittest.cc", "contact_info_unittest.cc",
diff --git a/components/autofill/core/browser/autocomplete_history_manager.cc b/components/autofill/core/browser/autocomplete_history_manager.cc index 79d75b8c1..acfb47d 100644 --- a/components/autofill/core/browser/autocomplete_history_manager.cc +++ b/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -124,17 +124,15 @@ // - autocomplete is not disabled // - value is not a credit card number // - value is not a SSN + // - field was not identified as a CVC field (this is handled in + // AutofillManager) std::vector<FormFieldData> values; - for (std::vector<FormFieldData>::const_iterator iter = - form.fields.begin(); - iter != form.fields.end(); ++iter) { - if (!iter->value.empty() && - !iter->name.empty() && - IsTextField(*iter) && - iter->should_autocomplete && - !autofill::IsValidCreditCardNumber(iter->value) && - !autofill::IsSSN(iter->value)) { - values.push_back(*iter); + for (const FormFieldData& field : form.fields) { + if (!field.value.empty() && !field.name.empty() && IsTextField(field) && + field.should_autocomplete && + !autofill::IsValidCreditCardNumber(field.value) && + !autofill::IsSSN(field.value)) { + values.push_back(field); } }
diff --git a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc index d3733b51..1bedd27 100644 --- a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc +++ b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -166,7 +166,9 @@ } // Tests that text entered into fields specifying autocomplete="off" is not sent -// to the WebDatabase to be saved. +// to the WebDatabase to be saved. Note this is also important as the mechanism +// for preventing CVCs from being saved. +// See AutofillManagerTest.DontSaveCvcInAutocompleteHistory TEST_F(AutocompleteHistoryManagerTest, FieldWithAutocompleteOff) { FormData form; form.name = ASCIIToUTF16("MyForm");
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index beb4281..c0a5bff 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -166,10 +166,8 @@ prefs::kAutofillEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kAutofillWalletSyncExperimentEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kAutofillWalletSyncExperimentEnabled, + false); // TODO(estade): Should this be syncable? registry->RegisterBooleanPref( prefs::kAutofillWalletImportEnabled, @@ -177,44 +175,27 @@ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); // This choice is made on a per-device basis, so it's not syncable. registry->RegisterBooleanPref( - prefs::kAutofillWalletImportStorageCheckboxState, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kAutofillWalletImportStorageCheckboxState, true); #if defined(OS_MACOSX) registry->RegisterBooleanPref( prefs::kAutofillAuxiliaryProfilesEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); #else // defined(OS_MACOSX) - registry->RegisterBooleanPref( - prefs::kAutofillAuxiliaryProfilesEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kAutofillAuxiliaryProfilesEnabled, + false); #endif // defined(OS_MACOSX) #if defined(OS_MACOSX) - registry->RegisterBooleanPref( - prefs::kAutofillMacAddressBookQueried, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kAutofillMacAddressBookQueried, false); #endif // defined(OS_MACOSX) - registry->RegisterDoublePref( - prefs::kAutofillPositiveUploadRate, - kAutofillPositiveUploadRateDefaultValue, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDoublePref( - prefs::kAutofillNegativeUploadRate, - kAutofillNegativeUploadRateDefaultValue, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDoublePref(prefs::kAutofillPositiveUploadRate, + kAutofillPositiveUploadRateDefaultValue); + registry->RegisterDoublePref(prefs::kAutofillNegativeUploadRate, + kAutofillNegativeUploadRateDefaultValue); #if defined(OS_MACOSX) && !defined(OS_IOS) - registry->RegisterBooleanPref( - prefs::kAutofillUseMacAddressBook, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kAutofillMacAddressBookShowedCount, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kAutofillUseMacAddressBook, false); + registry->RegisterIntegerPref(prefs::kAutofillMacAddressBookShowedCount, 0); #endif // defined(OS_MACOSX) && !defined(OS_IOS) } @@ -383,12 +364,24 @@ if (!IsValidFormData(form)) return false; - // Let Autocomplete know as well. - autocomplete_history_manager_->OnFormSubmitted(form); - + // We will always give Autocomplete a chance to save the data. scoped_ptr<FormStructure> submitted_form = ValidateSubmittedForm(form); - if (!submitted_form) + if (!submitted_form) { + autocomplete_history_manager_->OnFormSubmitted(form); return false; + } + + // However, if Autofill has recognized a field as CVC, that shouldn't be + // saved. + FormData form_for_autocomplete = submitted_form->ToFormData(); + form_for_autocomplete.user_submitted = form.user_submitted; + for (size_t i = 0; i < submitted_form->field_count(); ++i) { + if (submitted_form->field(i)->Type().GetStorableType() == + CREDIT_CARD_VERIFICATION_CODE) { + form_for_autocomplete.fields[i].should_autocomplete = false; + } + } + autocomplete_history_manager_->OnFormSubmitted(form_for_autocomplete); address_form_event_logger_->OnFormSubmitted(); credit_card_form_event_logger_->OnFormSubmitted();
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index f69634a..c0696cf 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -474,6 +474,8 @@ FormSubmittedAutocompleteEnabled); FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, AutocompleteOffRespectedForAutocomplete); + FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, + DontSaveCvcInAutocompleteHistory); FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, DontOfferToSaveWalletCard); DISALLOW_COPY_AND_ASSIGN(AutofillManager); };
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index d2255cb5..cc04eb0 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -45,6 +45,7 @@ using base::ASCIIToUTF16; using base::UTF8ToUTF16; using testing::_; +using testing::SaveArg; namespace autofill { @@ -2417,11 +2418,8 @@ autofill_manager_.reset( new TestAutofillManager(autofill_driver_.get(), &client, NULL)); autofill_manager_->set_autofill_enabled(false); - scoped_ptr<MockAutocompleteHistoryManager> autocomplete_history_manager; - autocomplete_history_manager.reset( + autofill_manager_->autocomplete_history_manager_.reset( new MockAutocompleteHistoryManager(autofill_driver_.get(), &client)); - autofill_manager_->autocomplete_history_manager_ = - autocomplete_history_manager.Pass(); // Set up our form data. FormData form; @@ -2471,11 +2469,8 @@ autofill_manager_->set_autofill_enabled(false); autofill_manager_->SetExternalDelegate(external_delegate_.get()); - scoped_ptr<MockAutocompleteHistoryManager> autocomplete_history_manager; - autocomplete_history_manager.reset( + autofill_manager_->autocomplete_history_manager_.reset( new MockAutocompleteHistoryManager(autofill_driver_.get(), &client)); - autofill_manager_->autocomplete_history_manager_ = - autocomplete_history_manager.Pass(); MockAutocompleteHistoryManager* m = static_cast< MockAutocompleteHistoryManager*>( autofill_manager_->autocomplete_history_manager_.get()); @@ -3130,6 +3125,55 @@ "04/12", kVisaCard, autofill_manager_->GetPackedCreditCardID(4))); } +// Test that inputs detected to be CVC inputs are forced to +// !should_autocomplete for AutocompleteHistoryManager::OnFormSubmitted. +TEST_F(AutofillManagerTest, DontSaveCvcInAutocompleteHistory) { + autofill_manager_->autocomplete_history_manager_.reset( + new MockAutocompleteHistoryManager(autofill_driver_.get(), + &autofill_client_)); + FormData form_seen_by_ahm; + MockAutocompleteHistoryManager* mock_ahm = + static_cast<MockAutocompleteHistoryManager*>( + autofill_manager_->autocomplete_history_manager_.get()); + EXPECT_CALL(*mock_ahm, OnFormSubmitted(_)) + .WillOnce(SaveArg<0>(&form_seen_by_ahm)); + + FormData form; + form.name = ASCIIToUTF16("MyForm"); + form.origin = GURL("http://myform.com/form.html"); + form.action = GURL("http://myform.com/submit.html"); + form.user_submitted = true; + + struct { + const char* label; + const char* name; + const char* value; + ServerFieldType expected_field_type; + } fields[] = { + {"Card number", "1", "4234-5678-9012-3456", CREDIT_CARD_NUMBER}, + {"Card verification code", "2", "123", CREDIT_CARD_VERIFICATION_CODE}, + {"expiration date", "3", "04/2020", CREDIT_CARD_EXP_4_DIGIT_YEAR}, + }; + + for (size_t i = 0; i < arraysize(fields); ++i) { + FormFieldData field; + test::CreateTestFormField(fields[i].label, fields[i].name, fields[i].value, + "text", &field); + form.fields.push_back(field); + } + + std::vector<FormData> forms(1, form); + FormsSeen(forms); + FormSubmitted(form); + + EXPECT_EQ(form.fields.size(), form_seen_by_ahm.fields.size()); + ASSERT_EQ(arraysize(fields), form_seen_by_ahm.fields.size()); + for (size_t i = 0; i < arraysize(fields); ++i) { + EXPECT_EQ(form_seen_by_ahm.fields[i].should_autocomplete, + fields[i].expected_field_type != CREDIT_CARD_VERIFICATION_CODE); + } +} + TEST_F(AutofillManagerTest, DontOfferToSaveWalletCard) { // This line silences the warning from RealPanWalletClient about matching // sync and wallet server types.
diff --git a/components/autofill/core/browser/autofill_regexes.cc b/components/autofill/core/browser/autofill_regexes.cc deleted file mode 100644 index bd5c0e9..0000000 --- a/components/autofill/core/browser/autofill_regexes.cc +++ /dev/null
@@ -1,80 +0,0 @@ -// Copyright 2013 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/autofill/core/browser/autofill_regexes.h" - -#include "base/containers/scoped_ptr_hash_map.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/singleton.h" -#include "base/strings/string16.h" -#include "third_party/icu/source/i18n/unicode/regex.h" - -namespace { - -// A singleton class that serves as a cache of compiled regex patterns. -class AutofillRegexes { - public: - static AutofillRegexes* GetInstance(); - - // Returns the compiled regex matcher corresponding to |pattern|. - icu::RegexMatcher* GetMatcher(const base::string16& pattern); - - private: - AutofillRegexes(); - ~AutofillRegexes(); - friend struct DefaultSingletonTraits<AutofillRegexes>; - - // Maps patterns to their corresponding regex matchers. - base::ScopedPtrHashMap<base::string16, icu::RegexMatcher> matchers_; - - DISALLOW_COPY_AND_ASSIGN(AutofillRegexes); -}; - -// static -AutofillRegexes* AutofillRegexes::GetInstance() { - return Singleton<AutofillRegexes>::get(); -} - -AutofillRegexes::AutofillRegexes() { -} - -AutofillRegexes::~AutofillRegexes() { -} - -icu::RegexMatcher* AutofillRegexes::GetMatcher(const base::string16& pattern) { - auto it = matchers_.find(pattern); - if (it == matchers_.end()) { - const icu::UnicodeString icu_pattern(pattern.data(), pattern.length()); - - UErrorCode status = U_ZERO_ERROR; - scoped_ptr<icu::RegexMatcher> matcher( - new icu::RegexMatcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status)); - DCHECK(U_SUCCESS(status)); - - auto result = matchers_.add(pattern, matcher.Pass()); - DCHECK(result.second); - it = result.first; - } - return it->second; -} - -} // namespace - -namespace autofill { - -bool MatchesPattern(const base::string16& input, - const base::string16& pattern) { - icu::RegexMatcher* matcher = - AutofillRegexes::GetInstance()->GetMatcher(pattern); - icu::UnicodeString icu_input(input.data(), input.length()); - matcher->reset(icu_input); - - UErrorCode status = U_ZERO_ERROR; - UBool match = matcher->find(0, status); - DCHECK(U_SUCCESS(status)); - return match == TRUE; -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_regexes.h b/components/autofill/core/browser/autofill_regexes.h deleted file mode 100644 index f4b5775..0000000 --- a/components/autofill/core/browser/autofill_regexes.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2013 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_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEXES_H_ -#define COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEXES_H_ - -#include "base/strings/string16.h" - -// Parsing utilities. -namespace autofill { - -// Case-insensitive regular expression matching. -// Returns true if |pattern| is found in |input|. -bool MatchesPattern(const base::string16& input, - const base::string16& pattern); - -} // namespace autofill - -#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_AUTOFILL_REGEXES_H_
diff --git a/components/autofill/core/browser/autofill_regexes_unittest.cc b/components/autofill/core/browser/autofill_regexes_unittest.cc deleted file mode 100644 index d77afa7..0000000 --- a/components/autofill/core/browser/autofill_regexes_unittest.cc +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright 2013 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/autofill/core/browser/autofill_regexes.h" - -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "components/autofill/core/browser/autofill_regex_constants.h" -#include "testing/gtest/include/gtest/gtest.h" - -using base::ASCIIToUTF16; - -namespace autofill { - -TEST(AutofillRegexesTest, AutofillRegexes) { - struct TestCase { - const char* const input; - const char* const pattern; - }; - - const TestCase kPositiveCases[] = { - // Empty pattern - {"", ""}, - {"Look, ma' -- a non-empty string!", ""}, - // Substring - {"string", "tri"}, - // Substring at beginning - {"string", "str"}, - {"string", "^str"}, - // Substring at end - {"string", "ring"}, - {"string", "ring$"}, - // Case-insensitive - {"StRiNg", "string"}, - }; - for (size_t i = 0; i < arraysize(kPositiveCases); ++i) { - const TestCase& test_case = kPositiveCases[i]; - SCOPED_TRACE(test_case.input); - SCOPED_TRACE(test_case.pattern); - EXPECT_TRUE(autofill::MatchesPattern(ASCIIToUTF16(test_case.input), - ASCIIToUTF16(test_case.pattern))); - } - - const TestCase kNegativeCases[] = { - // Empty string - {"", "Look, ma' -- a non-empty pattern!"}, - // Substring - {"string", "trn"}, - // Substring at beginning - {"string", " str"}, - {"string", "^tri"}, - // Substring at end - {"string", "ring "}, - {"string", "rin$"}, - }; - for (size_t i = 0; i < arraysize(kNegativeCases); ++i) { - const TestCase& test_case = kNegativeCases[i]; - SCOPED_TRACE(test_case.input); - SCOPED_TRACE(test_case.pattern); - EXPECT_FALSE(autofill::MatchesPattern(ASCIIToUTF16(test_case.input), - ASCIIToUTF16(test_case.pattern))); - } -} - -} // namespace autofill
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index c69611a..a8be18b 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -40,19 +40,14 @@ // PDM depends on this pref, which is normally registered in // SigninManagerFactory. - registry->RegisterStringPref( - ::prefs::kGoogleServicesAccountId, std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(::prefs::kGoogleServicesAccountId, + std::string()); // PDM depends on these prefs, which are normally registered in // AccountTrackerServiceFactory. - registry->RegisterListPref( - AccountTrackerService::kAccountInfoPref, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - ::prefs::kAccountIdMigrationState, - AccountTrackerService::MIGRATION_NOT_STARTED, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(AccountTrackerService::kAccountInfoPref); + registry->RegisterIntegerPref(::prefs::kAccountIdMigrationState, + AccountTrackerService::MIGRATION_NOT_STARTED); base::PrefServiceFactory factory; factory.set_user_prefs(make_scoped_refptr(new TestingPrefStore()));
diff --git a/components/autofill/core/browser/credit_card.cc b/components/autofill/core/browser/credit_card.cc index 38b4294..b4c1c9e 100644 --- a/components/autofill/core/browser/credit_card.cc +++ b/components/autofill/core/browser/credit_card.cc
@@ -20,10 +20,10 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/validation.h" #include "components/autofill/core/common/autofill_l10n_util.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "components/autofill/core/common/form_field_data.h" #include "grit/components_scaled_resources.h" #include "grit/components_strings.h" @@ -408,7 +408,6 @@ if (!card_number.empty() && StripSeparators(text) == card_number) matching_types->insert(CREDIT_CARD_NUMBER); -NOTIMPLEMENTED() << " GETMATCINGTYPES " << text; int month; if (ConvertMonth(text, app_locale, &month) && month == expiration_month_) {
diff --git a/components/autofill/core/browser/credit_card_field.cc b/components/autofill/core/browser/credit_card_field.cc index 7d48bd5..d6b67dc 100644 --- a/components/autofill/core/browser/credit_card_field.cc +++ b/components/autofill/core/browser/credit_card_field.cc
@@ -15,9 +15,9 @@ #include "base/time/time.h" #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/autofill_regex_constants.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_scanner.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/common/autofill_regexes.h" #include "grit/components_strings.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/components/autofill/core/browser/form_field.cc b/components/autofill/core/browser/form_field.cc index 7ea3ce4..50d7e8a3 100644 --- a/components/autofill/core/browser/form_field.cc +++ b/components/autofill/core/browser/form_field.cc
@@ -15,13 +15,13 @@ #include "base/strings/utf_string_conversions.h" #include "components/autofill/core/browser/address_field.h" #include "components/autofill/core/browser/autofill_field.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/autofill_scanner.h" #include "components/autofill/core/browser/credit_card_field.h" #include "components/autofill/core/browser/email_field.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/name_field.h" #include "components/autofill/core/browser/phone_field.h" +#include "components/autofill/core/common/autofill_regexes.h" namespace autofill { namespace {
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 5c76c62..5387952 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -363,31 +363,26 @@ is_form_tag_(form.is_form_tag) { // Copy the form fields. std::map<base::string16, size_t> unique_names; - for (std::vector<FormFieldData>::const_iterator field = - form.fields.begin(); - field != form.fields.end(); ++field) { - if (!ShouldSkipField(*field)) { + for (const FormFieldData& field : form.fields) { + if (!ShouldSkipField(field)) { // Add all supported form fields (including with empty names) to the // signature. This is a requirement for Autofill servers. form_signature_field_names_.append("&"); - form_signature_field_names_.append(StripDigitsIfRequired(field->name)); + form_signature_field_names_.append(StripDigitsIfRequired(field.name)); ++active_field_count_; } - if (field->form_control_type == "password") + if (field.form_control_type == "password") has_password_field_ = true; // Generate a unique name for this field by appending a counter to the name. // Make sure to prepend the counter with a non-numeric digit so that we are // guaranteed to avoid collisions. - if (!unique_names.count(field->name)) - unique_names[field->name] = 1; - else - ++unique_names[field->name]; - base::string16 unique_name = field->name + base::ASCIIToUTF16("_") + - base::IntToString16(unique_names[field->name]); - fields_.push_back(new AutofillField(*field, unique_name)); + base::string16 unique_name = + field.name + base::ASCIIToUTF16("_") + + base::IntToString16(++unique_names[field.name]); + fields_.push_back(new AutofillField(field, unique_name)); } }
diff --git a/components/autofill/core/browser/validation.cc b/components/autofill/core/browser/validation.cc index 0688c298..ef7c330 100644 --- a/components/autofill/core/browser/validation.cc +++ b/components/autofill/core/browser/validation.cc
@@ -9,10 +9,9 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" -#include "components/autofill/core/browser/autofill_regexes.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/state_names.h" - +#include "components/autofill/core/common/autofill_regexes.h" namespace autofill {
diff --git a/components/autofill/core/common/BUILD.gn b/components/autofill/core/common/BUILD.gn index 9ba33f3..aef3013 100644 --- a/components/autofill/core/common/BUILD.gn +++ b/components/autofill/core/common/BUILD.gn
@@ -12,6 +12,8 @@ "autofill_l10n_util.h", "autofill_pref_names.cc", "autofill_pref_names.h", + "autofill_regexes.cc", + "autofill_regexes.h", "autofill_switches.cc", "autofill_switches.h", "form_data.cc", @@ -45,11 +47,14 @@ if (is_android) { # deps += [ 'autofill_jni_headers' ] TODO(GYP) } + + configs += [ "//build/config/compiler:no_size_t_to_int_warning" ] } source_set("unit_tests") { testonly = true sources = [ + "autofill_regexes_unittest.cc", "form_data_unittest.cc", "form_field_data_unittest.cc", "password_form_fill_data_unittest.cc",
diff --git a/components/autofill/core/common/autofill_regexes.cc b/components/autofill/core/common/autofill_regexes.cc new file mode 100644 index 0000000..64a60f6c --- /dev/null +++ b/components/autofill/core/common/autofill_regexes.cc
@@ -0,0 +1,80 @@ +// Copyright 2013 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/autofill/core/common/autofill_regexes.h" + +#include "base/containers/scoped_ptr_hash_map.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/singleton.h" +#include "base/strings/string16.h" +#include "third_party/icu/source/i18n/unicode/regex.h" + +namespace { + +// A singleton class that serves as a cache of compiled regex patterns. +class AutofillRegexes { + public: + static AutofillRegexes* GetInstance(); + + // Returns the compiled regex matcher corresponding to |pattern|. + icu::RegexMatcher* GetMatcher(const base::string16& pattern); + + private: + AutofillRegexes(); + ~AutofillRegexes(); + friend struct DefaultSingletonTraits<AutofillRegexes>; + + // Maps patterns to their corresponding regex matchers. + base::ScopedPtrHashMap<base::string16, icu::RegexMatcher> matchers_; + + DISALLOW_COPY_AND_ASSIGN(AutofillRegexes); +}; + +// static +AutofillRegexes* AutofillRegexes::GetInstance() { + return Singleton<AutofillRegexes>::get(); +} + +AutofillRegexes::AutofillRegexes() { +} + +AutofillRegexes::~AutofillRegexes() { +} + +icu::RegexMatcher* AutofillRegexes::GetMatcher(const base::string16& pattern) { + auto it = matchers_.find(pattern); + if (it == matchers_.end()) { + const icu::UnicodeString icu_pattern(pattern.data(), pattern.length()); + + UErrorCode status = U_ZERO_ERROR; + scoped_ptr<icu::RegexMatcher> matcher( + new icu::RegexMatcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status)); + DCHECK(U_SUCCESS(status)); + + auto result = matchers_.add(pattern, matcher.Pass()); + DCHECK(result.second); + it = result.first; + } + return it->second; +} + +} // namespace + +namespace autofill { + +bool MatchesPattern(const base::string16& input, + const base::string16& pattern) { + icu::RegexMatcher* matcher = + AutofillRegexes::GetInstance()->GetMatcher(pattern); + icu::UnicodeString icu_input(input.data(), input.length()); + matcher->reset(icu_input); + + UErrorCode status = U_ZERO_ERROR; + UBool match = matcher->find(0, status); + DCHECK(U_SUCCESS(status)); + return match == TRUE; +} + +} // namespace autofill
diff --git a/components/autofill/core/common/autofill_regexes.h b/components/autofill/core/common/autofill_regexes.h new file mode 100644 index 0000000..1bf1aa7 --- /dev/null +++ b/components/autofill/core/common/autofill_regexes.h
@@ -0,0 +1,20 @@ +// Copyright 2013 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_AUTOFILL_CORE_COMMON_AUTOFILL_REGEXES_H_ +#define COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEXES_H_ + +#include "base/strings/string16.h" + +// Parsing utilities. +namespace autofill { + +// Case-insensitive regular expression matching. +// Returns true if |pattern| is found in |input|. +bool MatchesPattern(const base::string16& input, + const base::string16& pattern); + +} // namespace autofill + +#endif // COMPONENTS_AUTOFILL_CORE_COMMON_AUTOFILL_REGEXES_H_
diff --git a/components/autofill/core/common/autofill_regexes_unittest.cc b/components/autofill/core/common/autofill_regexes_unittest.cc new file mode 100644 index 0000000..954a7e8 --- /dev/null +++ b/components/autofill/core/common/autofill_regexes_unittest.cc
@@ -0,0 +1,66 @@ +// Copyright 2013 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/autofill/core/common/autofill_regexes.h" + +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_regex_constants.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::ASCIIToUTF16; + +namespace autofill { + +TEST(AutofillRegexesTest, AutofillRegexes) { + struct TestCase { + const char* const input; + const char* const pattern; + }; + + const TestCase kPositiveCases[] = { + // Empty pattern + {"", ""}, + {"Look, ma' -- a non-empty string!", ""}, + // Substring + {"string", "tri"}, + // Substring at beginning + {"string", "str"}, + {"string", "^str"}, + // Substring at end + {"string", "ring"}, + {"string", "ring$"}, + // Case-insensitive + {"StRiNg", "string"}, + }; + for (size_t i = 0; i < arraysize(kPositiveCases); ++i) { + const TestCase& test_case = kPositiveCases[i]; + SCOPED_TRACE(test_case.input); + SCOPED_TRACE(test_case.pattern); + EXPECT_TRUE(autofill::MatchesPattern(ASCIIToUTF16(test_case.input), + ASCIIToUTF16(test_case.pattern))); + } + + const TestCase kNegativeCases[] = { + // Empty string + {"", "Look, ma' -- a non-empty pattern!"}, + // Substring + {"string", "trn"}, + // Substring at beginning + {"string", " str"}, + {"string", "^tri"}, + // Substring at end + {"string", "ring "}, + {"string", "rin$"}, + }; + for (size_t i = 0; i < arraysize(kNegativeCases); ++i) { + const TestCase& test_case = kNegativeCases[i]; + SCOPED_TRACE(test_case.input); + SCOPED_TRACE(test_case.pattern); + EXPECT_FALSE(autofill::MatchesPattern(ASCIIToUTF16(test_case.input), + ASCIIToUTF16(test_case.pattern))); + } +} + +} // namespace autofill
diff --git a/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc b/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc index 28bc794..379e4ec 100644 --- a/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc +++ b/components/bookmarks/browser/bookmark_expanded_state_tracker_unittest.cc
@@ -24,10 +24,8 @@ scoped_refptr<user_prefs::PrefRegistrySyncable> registry( new user_prefs::PrefRegistrySyncable()); registry->RegisterListPref(prefs::kBookmarkEditorExpandedNodes, - new base::ListValue, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedBookmarks, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + new base::ListValue); + registry->RegisterListPref(prefs::kManagedBookmarks); base::PrefServiceFactory factory; factory.set_user_prefs(make_scoped_refptr(new TestingPrefStore())); return factory.Create(registry.get());
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc index 80808ca6..10d5b2f 100644 --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc
@@ -886,7 +886,7 @@ // This method does not explicitly acquires a lock. url_lock_.AssertAcquired(); DCHECK(removed_urls); - BookmarkNode* parent = AsMutable(node->parent()); + BookmarkNode* parent = node->parent(); DCHECK(parent); parent->Remove(node); RemoveNode(node, removed_urls);
diff --git a/components/bookmarks/browser/bookmark_storage.cc b/components/bookmarks/browser/bookmark_storage.cc index daafdbe..2612f9c3 100644 --- a/components/bookmarks/browser/bookmark_storage.cc +++ b/components/bookmarks/browser/bookmark_storage.cc
@@ -205,10 +205,10 @@ return false; } - std::string data; - if (!SerializeData(&data)) + scoped_ptr<std::string> data(new std::string); + if (!SerializeData(data.get())) return false; - writer_.WriteNow(data); + writer_.WriteNow(data.Pass()); return true; }
diff --git a/components/bookmarks/browser/bookmark_utils.cc b/components/bookmarks/browser/bookmark_utils.cc index 758f19f..ccd5ebb5 100644 --- a/components/bookmarks/browser/bookmark_utils.cc +++ b/components/bookmarks/browser/bookmark_utils.cc
@@ -393,10 +393,7 @@ prefs::kShowBookmarkBar, false, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kEditBookmarksEnabled, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kEditBookmarksEnabled, true); registry->RegisterBooleanPref( prefs::kShowAppsShortcutInBookmarkBar, true,
diff --git a/components/clipboard/BUILD.gn b/components/clipboard/BUILD.gn index cfdcb25..c7caccf 100644 --- a/components/clipboard/BUILD.gn +++ b/components/clipboard/BUILD.gn
@@ -4,21 +4,30 @@ import("//third_party/mojo/src/mojo/public/mojo_application.gni") -mojo_native_application("clipboard") { +source_set("lib") { sources = [ "clipboard_standalone_impl.cc", "clipboard_standalone_impl.h", + ] + + deps = [ + "//components/clipboard/public/interfaces", + ] +} + +mojo_native_application("clipboard") { + sources = [ "main.cc", ] deps = [ + ":lib", "//base", "//mojo/application", "//mojo/common", "//mojo/environment:chromium", "//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/public/cpp/bindings:callback", - "//third_party/mojo_services/src/clipboard/public/interfaces", ] } @@ -33,11 +42,11 @@ deps = [ "//base", + "//components/clipboard/public/interfaces", "//mojo/application", "//mojo/application:test_support", "//mojo/common", "//third_party/mojo/src/mojo/public/cpp/bindings", - "//third_party/mojo_services/src/clipboard/public/interfaces", ] data_deps = [ ":clipboard($default_toolchain)" ]
diff --git a/components/clipboard/OWNERS b/components/clipboard/OWNERS new file mode 100644 index 0000000..4733a4f --- /dev/null +++ b/components/clipboard/OWNERS
@@ -0,0 +1 @@ +erg@chromium.org
diff --git a/components/clipboard/clipboard_apptest.cc b/components/clipboard/clipboard_apptest.cc index bda9469..da45d2e 100644 --- a/components/clipboard/clipboard_apptest.cc +++ b/components/clipboard/clipboard_apptest.cc
@@ -4,10 +4,10 @@ #include "base/bind.h" #include "base/run_loop.h" +#include "components/clipboard/public/interfaces/clipboard.mojom.h" #include "mojo/application/application_test_base_chromium.h" #include "mojo/common/common_type_converters.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" -#include "third_party/mojo_services/src/clipboard/public/interfaces/clipboard.mojom.h" using mojo::Array; using mojo::Clipboard;
diff --git a/components/clipboard/clipboard_standalone_impl.h b/components/clipboard/clipboard_standalone_impl.h index eecae95..218c96c 100644 --- a/components/clipboard/clipboard_standalone_impl.h +++ b/components/clipboard/clipboard_standalone_impl.h
@@ -8,8 +8,8 @@ #include <base/memory/scoped_ptr.h> #include <string> +#include "components/clipboard/public/interfaces/clipboard.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/mojo_services/src/clipboard/public/interfaces/clipboard.mojom.h" namespace clipboard {
diff --git a/components/clipboard/public/interfaces/BUILD.gn b/components/clipboard/public/interfaces/BUILD.gn new file mode 100644 index 0000000..6ee9bb7 --- /dev/null +++ b/components/clipboard/public/interfaces/BUILD.gn
@@ -0,0 +1,12 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "clipboard.mojom", + ] +}
diff --git a/components/clipboard/public/interfaces/clipboard.mojom b/components/clipboard/public/interfaces/clipboard.mojom new file mode 100644 index 0000000..ca4d6b1 --- /dev/null +++ b/components/clipboard/public/interfaces/clipboard.mojom
@@ -0,0 +1,43 @@ +// 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 mojo; + +interface Clipboard { + enum Type { + COPY_PASTE = 0, + SELECTION = 1, + DRAG = 2 + }; + + // Mime type constants + const string MIME_TYPE_TEXT = "text/plain"; + const string MIME_TYPE_HTML = "text/html"; + const string MIME_TYPE_URL = "text/url"; + + // Returns a sequence number which uniquely identifies clipboard state. + // Clients are able to assume that the clipboard contents are unchanged as + // long as this number has not changed. This number is monotonically + // increasing, is increased when the clipboard state changes, and is + // provided by Windows, Linux, and Mac. + GetSequenceNumber(Type clipboard_type) => (uint64 sequence); + + // Returns the available mime types. (Note: the chrome interface has a + // |contains_filenames| parameter here, but it appears to always be set + // to false.) + GetAvailableMimeTypes(Type clipboard_types) => (array<string> types); + + // Returns the data associated with a Mime type, returning NULL if that data + // doesn't exist. Note: because of the inherit raciness of clipboard access, + // this may return NULL even if you just verified that it exists with + // GetAvailableFormatMimeTypes(). We don't want to provide one API to return + // the entire clipboard state because the combined size of the clipboard can + // be megabytes, especially when image data is involved. + ReadMimeType(Type clipboard_type, string mime_type) => (array<uint8>? data); + + // Writes a set of mime types to the clipboard. This will increment the + // sequence number. In the case of an empty or null map, this will just + // clear the clipboard. + WriteClipboardData(Type clipboard_type, map<string, array<uint8>>? data); +};
diff --git a/components/components_browsertests.isolate b/components/components_browsertests.isolate index e60cea1..0419dcd7 100644 --- a/components/components_browsertests.isolate +++ b/components/components_browsertests.isolate
@@ -56,6 +56,7 @@ 'variables': { 'files': [ 'test/data/', + 'dom_distiller/core/javascript/', '../third_party/dom_distiller_js/dist/test/data/', ], },
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index f48690f..2e0483d 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp
@@ -41,7 +41,6 @@ 'autofill/core/browser/autofill_merge_unittest.cc', 'autofill/core/browser/autofill_metrics_unittest.cc', 'autofill/core/browser/autofill_profile_unittest.cc', - 'autofill/core/browser/autofill_regexes_unittest.cc', 'autofill/core/browser/autofill_type_unittest.cc', 'autofill/core/browser/autofill_xml_parser_unittest.cc', 'autofill/core/browser/contact_info_unittest.cc', @@ -59,6 +58,7 @@ 'autofill/core/browser/webdata/autofill_profile_syncable_service_unittest.cc', 'autofill/core/browser/webdata/autofill_table_unittest.cc', 'autofill/core/browser/webdata/web_data_service_unittest.cc', + 'autofill/core/common/autofill_regexes_unittest.cc', 'autofill/core/common/form_data_unittest.cc', 'autofill/core/common/form_field_data_unittest.cc', 'autofill/core/common/password_form_fill_data_unittest.cc', @@ -346,6 +346,7 @@ 'password_manager/core/browser/password_store_unittest.cc', 'password_manager/core/browser/password_syncable_service_unittest.cc', 'password_manager/core/browser/psl_matching_helper_unittest.cc', + 'password_manager/core/browser/statistics_table_unittest.cc', 'password_manager/core/common/credential_manager_types_unittest.cc', ], 'policy_unittest_sources': [ @@ -405,6 +406,7 @@ 'proximity_auth_unittest_sources': [ 'proximity_auth/bluetooth_connection_finder_unittest.cc', 'proximity_auth/bluetooth_connection_unittest.cc', + 'proximity_auth/bluetooth_throttler_impl_unittest.cc', 'proximity_auth/client_unittest.cc', 'proximity_auth/connection_unittest.cc', 'proximity_auth/cryptauth/base64url_unittest.cc', @@ -415,6 +417,7 @@ 'proximity_auth/cryptauth/fake_secure_message_delegate_unittest.cc', 'proximity_auth/proximity_auth_system_unittest.cc', 'proximity_auth/remote_status_update_unittest.cc', + 'proximity_auth/throttled_bluetooth_connection_finder_unittest.cc', 'proximity_auth/wire_message_unittest.cc', ], 'query_parser_unittest_sources': [ @@ -429,6 +432,7 @@ 'rappor/rappor_prefs_unittest.cc', 'rappor/rappor_service_unittest.cc', 'rappor/rappor_utils_unittest.cc', + 'rappor/sampler_unittest.cc', ], 'scheduler_unittest_sources': [ 'scheduler/child/nestable_task_runner_for_test.cc', @@ -521,14 +525,14 @@ 'ui/zoom/page_zoom_unittests.cc', ], 'update_client_unittest_sources': [ - 'update_client/test/component_patcher_unittest.cc', - 'update_client/test/crx_downloader_unittest.cc', - 'update_client/test/ping_manager_unittest.cc', - 'update_client/test/request_sender_unittest.cc', - 'update_client/test/update_checker_unittest.cc', - 'update_client/test/update_client_unittest.cc', - 'update_client/test/update_response_unittest.cc', + 'update_client/component_patcher_unittest.cc', + 'update_client/crx_downloader_unittest.cc', + 'update_client/ping_manager_unittest.cc', + 'update_client/request_sender_unittest.cc', + 'update_client/update_checker_unittest.cc', + 'update_client/update_client_unittest.cc', 'update_client/update_query_params_unittest.cc', + 'update_client/update_response_unittest.cc', ], 'url_fixer_unittest_sources': [ 'url_fixer/url_fixer_unittest.cc',
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc index d6246c72..39c5a2e2 100644 --- a/components/content_settings/core/browser/content_settings_default_provider.cc +++ b/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -139,10 +139,8 @@ // Whether the deprecated mediastream default setting has already been // migrated into microphone and camera default settings. - registry->RegisterBooleanPref( - prefs::kMigratedDefaultMediaStreamSetting, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kMigratedDefaultMediaStreamSetting, + false); } DefaultProvider::DefaultProvider(PrefService* prefs, bool incognito)
diff --git a/components/content_settings/core/browser/content_settings_policy_provider.cc b/components/content_settings/core/browser/content_settings_policy_provider.cc index 8c65dbd..a398a6c 100644 --- a/components/content_settings/core/browser/content_settings_policy_provider.cc +++ b/components/content_settings/core/browser/content_settings_policy_provider.cc
@@ -122,68 +122,38 @@ // static void PolicyProvider::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(prefs::kManagedAutoSelectCertificateForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedCookiesAllowedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedCookiesBlockedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedImagesAllowedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedImagesBlockedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedPluginsAllowedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedPluginsBlockedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedPopupsAllowedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedPopupsBlockedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedNotificationsAllowedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kManagedNotificationsBlockedForUrls, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kManagedAutoSelectCertificateForUrls); + registry->RegisterListPref(prefs::kManagedCookiesAllowedForUrls); + registry->RegisterListPref(prefs::kManagedCookiesBlockedForUrls); + registry->RegisterListPref(prefs::kManagedCookiesSessionOnlyForUrls); + registry->RegisterListPref(prefs::kManagedImagesAllowedForUrls); + registry->RegisterListPref(prefs::kManagedImagesBlockedForUrls); + registry->RegisterListPref(prefs::kManagedJavaScriptAllowedForUrls); + registry->RegisterListPref(prefs::kManagedJavaScriptBlockedForUrls); + registry->RegisterListPref(prefs::kManagedPluginsAllowedForUrls); + registry->RegisterListPref(prefs::kManagedPluginsBlockedForUrls); + registry->RegisterListPref(prefs::kManagedPopupsAllowedForUrls); + registry->RegisterListPref(prefs::kManagedPopupsBlockedForUrls); + registry->RegisterListPref(prefs::kManagedNotificationsAllowedForUrls); + registry->RegisterListPref(prefs::kManagedNotificationsBlockedForUrls); // Preferences for default content setting policies. If a policy is not set of // the corresponding preferences below is set to CONTENT_SETTING_DEFAULT. - registry->RegisterIntegerPref( - prefs::kManagedDefaultCookiesSetting, - CONTENT_SETTING_DEFAULT, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kManagedDefaultImagesSetting, - CONTENT_SETTING_DEFAULT, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kManagedDefaultJavaScriptSetting, - CONTENT_SETTING_DEFAULT, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kManagedDefaultPluginsSetting, - CONTENT_SETTING_DEFAULT, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kManagedDefaultPopupsSetting, - CONTENT_SETTING_DEFAULT, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kManagedDefaultGeolocationSetting, - CONTENT_SETTING_DEFAULT, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kManagedDefaultNotificationsSetting, - CONTENT_SETTING_DEFAULT, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kManagedDefaultMediaStreamSetting, - CONTENT_SETTING_DEFAULT, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kManagedDefaultCookiesSetting, + CONTENT_SETTING_DEFAULT); + registry->RegisterIntegerPref(prefs::kManagedDefaultImagesSetting, + CONTENT_SETTING_DEFAULT); + registry->RegisterIntegerPref(prefs::kManagedDefaultJavaScriptSetting, + CONTENT_SETTING_DEFAULT); + registry->RegisterIntegerPref(prefs::kManagedDefaultPluginsSetting, + CONTENT_SETTING_DEFAULT); + registry->RegisterIntegerPref(prefs::kManagedDefaultPopupsSetting, + CONTENT_SETTING_DEFAULT); + registry->RegisterIntegerPref(prefs::kManagedDefaultGeolocationSetting, + CONTENT_SETTING_DEFAULT); + registry->RegisterIntegerPref(prefs::kManagedDefaultNotificationsSetting, + CONTENT_SETTING_DEFAULT); + registry->RegisterIntegerPref(prefs::kManagedDefaultMediaStreamSetting, + CONTENT_SETTING_DEFAULT); } PolicyProvider::PolicyProvider(PrefService* prefs) : prefs_(prefs) {
diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc index 6f7c006..0b56355 100644 --- a/components/content_settings/core/browser/content_settings_pref_provider.cc +++ b/components/content_settings/core/browser/content_settings_pref_provider.cc
@@ -112,15 +112,12 @@ user_prefs::PrefRegistrySyncable* registry) { registry->RegisterIntegerPref( prefs::kContentSettingsVersion, - ContentSettingsPattern::kContentSettingsPatternVersion, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + ContentSettingsPattern::kContentSettingsPatternVersion); registry->RegisterDictionaryPref( prefs::kContentSettingsPatternPairs, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kMigratedContentSettingsPatternPairs, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kMigratedContentSettingsPatternPairs, + false); for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) { registry->RegisterDictionaryPref(
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc index 39f70ee..73dd809 100644 --- a/components/content_settings/core/browser/host_content_settings_map.cc +++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -106,10 +106,7 @@ // static void HostContentSettingsMap::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kContentSettingsWindowLastTabIndex, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 0); // Register the prefs for the content settings providers. content_settings::DefaultProvider::RegisterProfilePrefs(registry);
diff --git a/components/core_services/BUILD.gn b/components/core_services/BUILD.gn new file mode 100644 index 0000000..b82d36e --- /dev/null +++ b/components/core_services/BUILD.gn
@@ -0,0 +1,26 @@ +# 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("//build/config/ui.gni") +import("//third_party/mojo/src/mojo/public/mojo_application.gni") +import("//testing/test.gni") + +# core_services should be thought of as a bundle of many of the services which +# we ship with. +mojo_native_application("core_services") { + sources = [ + "core_services_application_delegate.cc", + "main.cc", + ] + + deps = [ + "//base", + "//components/clipboard:lib", + "//mojo/application", + "//mojo/common", + "//mojo/environment:chromium", + "//third_party/mojo/src/mojo/public/interfaces/application", + "//third_party/mojo/src/mojo/public/cpp/bindings:bindings", + ] +}
diff --git a/components/core_services/DEPS b/components/core_services/DEPS new file mode 100644 index 0000000..213f11f --- /dev/null +++ b/components/core_services/DEPS
@@ -0,0 +1,7 @@ +include_rules = [ + "+components/clipboard", + "+mojo/application", + "+mojo/common", + "+third_party/mojo_services/src/clipboard", + "+third_party/mojo/src/mojo/public", +]
diff --git a/components/core_services/OWNERS b/components/core_services/OWNERS new file mode 100644 index 0000000..a4e2d8ff --- /dev/null +++ b/components/core_services/OWNERS
@@ -0,0 +1,2 @@ +erg@chromium.org +sky@chromium.org
diff --git a/components/core_services/core_services_application_delegate.cc b/components/core_services/core_services_application_delegate.cc new file mode 100644 index 0000000..29669503 --- /dev/null +++ b/components/core_services/core_services_application_delegate.cc
@@ -0,0 +1,57 @@ +// 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/core_services/core_services_application_delegate.h" + +#include "components/clipboard/clipboard_standalone_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" + +namespace core_services { + +CoreServicesApplicationDelegate::CoreServicesApplicationDelegate() {} + +CoreServicesApplicationDelegate::~CoreServicesApplicationDelegate() {} + +bool CoreServicesApplicationDelegate::ConfigureIncomingConnection( + mojo::ApplicationConnection* connection) { + // TODO(erg): For version one, we'll just say that all incoming connections + // get access to the same objects, which imply that there will be one + // instance of the service in its own process. However, in the long run, + // we'll want this to be more configurable. Some services are singletons, + // while we'll want to spawn a new process with multiple instances for other + // services. + connection->AddService<mojo::ServiceProvider>(this); + return true; +} + +void CoreServicesApplicationDelegate::Create( + mojo::ApplicationConnection* connection, + mojo::InterfaceRequest<ServiceProvider> request) { + provider_bindings_.AddBinding(this, request.Pass()); +} + +void CoreServicesApplicationDelegate::ConnectToService( + const mojo::String& service_name, + mojo::ScopedMessagePipeHandle client_handle) { + if (service_name == mojo::Clipboard::Name_) { + // TODO(erg): So what we do here probably doesn't look like the + // InProcessNativeRunner / NativeApplicationSupport. + // native_application_support.cc does the whole SetThunks() stuff. This has + // already happened since Core Services is a mojo application. So we want + // some sort of lightweight runner here. + // + // But...the actual child process stuff is its own mojom! (Also, it's + // entangled with mojo::Shell::ChildProcessMain().) All concept of app + // paths are the things which are used to execute the application in + // child_process.cc. + + // TODO(erg): The lifetime of ClipboardStandaloneImpl is wrong. Right now, + // a new object is made for each request, but we obviously want there to be + // one clipboard across all callers. + new clipboard::ClipboardStandaloneImpl( + mojo::MakeRequest<mojo::Clipboard>(client_handle.Pass())); + } +} + +} // namespace core_services
diff --git a/components/core_services/core_services_application_delegate.h b/components/core_services/core_services_application_delegate.h new file mode 100644 index 0000000..2662e41 --- /dev/null +++ b/components/core_services/core_services_application_delegate.h
@@ -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. + +#ifndef COMPONENTS_CORE_SERVICES_APPLICATION_DELEGATE_H_ +#define COMPONENTS_CORE_SERVICES_APPLICATION_DELEGATE_H_ + +#include "base/macros.h" +#include "mojo/common/weak_binding_set.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" +#include "third_party/mojo/src/mojo/public/cpp/application/interface_factory_impl.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" + +namespace core_services { + +// The CoreServices application is a singleton ServiceProvider. There is one +// instance of the CoreServices ServiceProvider. +class CoreServicesApplicationDelegate + : public mojo::ApplicationDelegate, + public mojo::InterfaceFactory<mojo::ServiceProvider>, + public mojo::ServiceProvider { + public: + CoreServicesApplicationDelegate(); + ~CoreServicesApplicationDelegate() override; + + private: + // Overridden from mojo::ApplicationDelegate: + bool ConfigureIncomingConnection( + mojo::ApplicationConnection* connection) override; + + // Overridden from mojo::InterfaceFactory<ServiceProvider>: + void Create(mojo::ApplicationConnection* connection, + mojo::InterfaceRequest<ServiceProvider> request) override; + + // Overridden from ServiceProvider: + void ConnectToService(const mojo::String& service_name, + mojo::ScopedMessagePipeHandle client_handle) override; + + // Bindings for all of our connections. + mojo::WeakBindingSet<ServiceProvider> provider_bindings_; + + DISALLOW_COPY_AND_ASSIGN(CoreServicesApplicationDelegate); +}; + +} // namespace core_services + +#endif // COMPONENTS_CORE_SERVICES_APPLICATION_DELEGATE_H_
diff --git a/components/core_services/main.cc b/components/core_services/main.cc new file mode 100644 index 0000000..1f664c8 --- /dev/null +++ b/components/core_services/main.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 "components/core_services/core_services_application_delegate.h" +#include "mojo/application/application_runner_chromium.h" +#include "third_party/mojo/src/mojo/public/c/system/main.h" + +MojoResult MojoMain(MojoHandle shell_handle) { + mojo::ApplicationRunnerChromium runner( + new core_services::CoreServicesApplicationDelegate); + return runner.Run(shell_handle); +}
diff --git a/components/cronet/android/cronet_url_request_context_adapter.cc b/components/cronet/android/cronet_url_request_context_adapter.cc index 5a1f569..6553f1e 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.cc +++ b/components/cronet/android/cronet_url_request_context_adapter.cc
@@ -164,7 +164,7 @@ // Currently (circa M39) enabling QUIC requires setting probability threshold. if (config->enable_quic) { context_->http_server_properties() - ->SetAlternateProtocolProbabilityThreshold(0.0f); + ->SetAlternativeServiceProbabilityThreshold(0.0f); for (auto hint = config->quic_hints.begin(); hint != config->quic_hints.end(); ++hint) { const URLRequestContextConfig::QuicHint& quic_hint = **hint; @@ -286,23 +286,23 @@ DCHECK(is_context_initialized_); DCHECK(context_); // Do nothing if already logging to a file. - if (net_log_logger_) + if (write_to_file_observer_) return; base::FilePath file_path(file_name); base::ScopedFILE file(base::OpenFile(file_path, "w")); if (!file) return; - net_log_logger_.reset(new net::WriteToFileNetLogObserver()); - net_log_logger_->StartObserving(context_->net_log(), file.Pass(), nullptr, - context_.get()); + write_to_file_observer_.reset(new net::WriteToFileNetLogObserver()); + write_to_file_observer_->StartObserving(context_->net_log(), file.Pass(), + nullptr, context_.get()); } void CronetURLRequestContextAdapter::StopNetLogOnNetworkThread() { DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); - if (net_log_logger_) { - net_log_logger_->StopObserving(context_.get()); - net_log_logger_.reset(); + if (write_to_file_observer_) { + write_to_file_observer_->StopObserving(context_.get()); + write_to_file_observer_.reset(); } }
diff --git a/components/cronet/android/cronet_url_request_context_adapter.h b/components/cronet/android/cronet_url_request_context_adapter.h index d20c02fc..fea2454d 100644 --- a/components/cronet/android/cronet_url_request_context_adapter.h +++ b/components/cronet/android/cronet_url_request_context_adapter.h
@@ -86,8 +86,9 @@ // Network thread is owned by |this|, but is destroyed from java thread. base::Thread* network_thread_; - // |net_log_logger_| and |context_| should only be accessed on network thread. - scoped_ptr<net::WriteToFileNetLogObserver> net_log_logger_; + // |write_to_file_observer_| and |context_| should only be accessed on + // network thread. + scoped_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_; scoped_ptr<net::URLRequestContext> context_; scoped_ptr<net::ProxyConfigService> proxy_config_service_;
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUploadTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUploadTest.java index 218cbf6b..074eaad 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/CronetUploadTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/CronetUploadTest.java
@@ -22,8 +22,6 @@ private TestDrivenDataProvider mDataProvider; private CronetUploadDataStream mUploadDataStream; private TestUploadDataStreamHandler mHandler; - // Address of native CronetUploadDataStreamAdapter object. - private long mAdapter = 0; @Override protected void setUp() throws Exception { @@ -33,8 +31,8 @@ List<byte[]> reads = Arrays.asList("hello".getBytes()); mDataProvider = new TestDrivenDataProvider(executor, reads); mUploadDataStream = new CronetUploadDataStream(mDataProvider, executor); - mAdapter = mUploadDataStream.createAdapterForTesting(); - mHandler = new TestUploadDataStreamHandler(mAdapter); + mHandler = new TestUploadDataStreamHandler( + mUploadDataStream.createAdapterForTesting()); } @Override @@ -241,9 +239,13 @@ mDataProvider.waitForReadRequest(); mHandler.checkReadCallbackNotInvoked(); - // Destroy the C++ object, which should trigger the Java - // onAdapterDestroyed() which should block until the read completes. - mAdapter = 0; + // Destroy the C++ TestUploadDataStreamHandler. The handler owns the + // CronetUploadDataStreamAdapter, which this will cause it to destroy on + // the network thread. Destroying the adapter will result in calling + // the CronetUploadDataSteam's onAdapterDestroyed() method on its + // executor thread, which will then destroy the + // CronetUploadDataStreamDelegate. + mHandler.destroyNativeObjects(); // Make the read complete should not encounter a crash. mDataProvider.onReadSucceeded(mUploadDataStream); @@ -282,15 +284,16 @@ mDataProvider.waitForRewindRequest(); mHandler.checkInitCallbackNotInvoked(); - // Destroy the C++ object, which should trigger the Java - // onAdapterDestroyed(). - mAdapter = 0; + // Destroy the C++ TestUploadDataStreamHandler. The handler owns the + // CronetUploadDataStreamAdapter, which this will cause it to destroy on + // the network thread. Destroying the adapter will result in calling + // the CronetUploadDataSteam's onAdapterDestroyed() method on its + // executor thread, which will then destroy the + // CronetUploadDataStreamDelegate. + mHandler.destroyNativeObjects(); // Signal rewind completes, and wait for init to complete. - mHandler.checkInitCallbackNotInvoked(); mDataProvider.onRewindSucceeded(mUploadDataStream); - mHandler.waitForInitComplete(); - mDataProvider.assertRewindNotPending(); assertEquals(1, mDataProvider.getNumRewindCalls()); assertEquals(1, mDataProvider.getNumReadCalls());
diff --git a/components/cronet/android/test/src/org/chromium/net/TestUploadDataStreamHandler.java b/components/cronet/android/test/src/org/chromium/net/TestUploadDataStreamHandler.java index 9b7bb21..2179515 100644 --- a/components/cronet/android/test/src/org/chromium/net/TestUploadDataStreamHandler.java +++ b/components/cronet/android/test/src/org/chromium/net/TestUploadDataStreamHandler.java
@@ -37,8 +37,10 @@ } public void destroyNativeObjects() { - nativeDestroy(mTestUploadDataStreamHandler); - mTestUploadDataStreamHandler = 0; + if (mTestUploadDataStreamHandler != 0) { + nativeDestroy(mTestUploadDataStreamHandler); + mTestUploadDataStreamHandler = 0; + } } /**
diff --git a/components/cronet/android/url_request_context_adapter.cc b/components/cronet/android/url_request_context_adapter.cc index 8fc3e02..d2adeb4 100644 --- a/components/cronet/android/url_request_context_adapter.cc +++ b/components/cronet/android/url_request_context_adapter.cc
@@ -154,7 +154,7 @@ // Currently (circa M39) enabling QUIC requires setting probability threshold. if (config_->enable_quic) { context_->http_server_properties() - ->SetAlternateProtocolProbabilityThreshold(0.0f); + ->SetAlternativeServiceProbabilityThreshold(0.0f); for (size_t hint = 0; hint < config_->quic_hints.size(); ++hint) { const URLRequestContextConfig::QuicHint& quic_hint = *config_->quic_hints[hint]; @@ -278,7 +278,7 @@ const std::string& file_name) { DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); // Do nothing if already logging to a file. - if (net_log_logger_) + if (write_to_file_observer_) return; base::FilePath file_path(file_name); @@ -286,16 +286,16 @@ if (!file) return; - net_log_logger_.reset(new net::WriteToFileNetLogObserver()); - net_log_logger_->StartObserving(context_->net_log(), file.Pass(), nullptr, - context_.get()); + write_to_file_observer_.reset(new net::WriteToFileNetLogObserver()); + write_to_file_observer_->StartObserving(context_->net_log(), file.Pass(), + nullptr, context_.get()); } void URLRequestContextAdapter::StopNetLogHelper() { DCHECK(GetNetworkTaskRunner()->BelongsToCurrentThread()); - if (net_log_logger_) { - net_log_logger_->StopObserving(context_.get()); - net_log_logger_.reset(); + if (write_to_file_observer_) { + write_to_file_observer_->StopObserving(context_.get()); + write_to_file_observer_.reset(); } }
diff --git a/components/cronet/android/url_request_context_adapter.h b/components/cronet/android/url_request_context_adapter.h index 932ad92..cdcc79fb 100644 --- a/components/cronet/android/url_request_context_adapter.h +++ b/components/cronet/android/url_request_context_adapter.h
@@ -107,7 +107,7 @@ bool load_disable_cache_; base::Thread* network_thread_; scoped_ptr<NetLogObserver> net_log_observer_; - scoped_ptr<net::WriteToFileNetLogObserver> net_log_logger_; + scoped_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_; scoped_ptr<net::ProxyConfigService> proxy_config_service_; scoped_ptr<URLRequestContextConfig> config_;
diff --git a/components/data_reduction_proxy/OWNERS b/components/data_reduction_proxy/OWNERS index 78f98aaa..54d32cf 100644 --- a/components/data_reduction_proxy/OWNERS +++ b/components/data_reduction_proxy/OWNERS
@@ -1,6 +1,5 @@ bengr@chromium.org bolian@chromium.org -marq@chromium.org sclittle@chromium.org jeremyim@chromium.org
diff --git a/components/data_reduction_proxy/content/browser/data_reduction_proxy_debug_blocking_page_unittest.cc b/components/data_reduction_proxy/content/browser/data_reduction_proxy_debug_blocking_page_unittest.cc index 0effde6..64d5076 100644 --- a/components/data_reduction_proxy/content/browser/data_reduction_proxy_debug_blocking_page_unittest.cc +++ b/components/data_reduction_proxy/content/browser/data_reduction_proxy_debug_blocking_page_unittest.cc
@@ -104,29 +104,56 @@ user_response_ = CANCEL; } - void Navigate(const char* url, int page_id) { - content::WebContentsTester::For(web_contents())->TestDidNavigate( - web_contents()->GetMainFrame(), page_id, GURL(url), - ui::PAGE_TRANSITION_TYPED); + void Navigate(const char* url, + int page_id, + int nav_entry_id, + bool did_create_new_entry) { + NavigateInternal(url, page_id, nav_entry_id, did_create_new_entry, false); + } + + void NavigateCrossSite(const char* url, + int page_id, + int nav_entry_id, + bool did_create_new_entry) { + NavigateInternal(url, page_id, nav_entry_id, did_create_new_entry, true); + } + + void NavigateInternal(const char* url, + int page_id, + int nav_entry_id, + bool did_create_new_entry, + bool is_cross_site) { + // The pending RVH should commit for cross-site navigations. + content::RenderFrameHost* render_frame_host = + is_cross_site + ? content::WebContentsTester::For(web_contents()) + ->GetPendingMainFrame() + : web_contents()->GetMainFrame(); + + content::WebContentsTester::For(web_contents()) + ->TestDidNavigate(render_frame_host, page_id, nav_entry_id, + did_create_new_entry, GURL(url), + ui::PAGE_TRANSITION_TYPED); } void GoBack(bool is_cross_site) { - content::NavigationEntry* entry = - web_contents()->GetController().GetEntryAtOffset(-1); - ASSERT_TRUE(entry); - web_contents()->GetController().GoBack(); + content::NavigationEntry* entry = + web_contents()->GetController().GetEntryAtOffset(-1); + ASSERT_TRUE(entry); + web_contents()->GetController().GoBack(); - // The pending RVH should commit for cross-site navigations. - content::RenderFrameHost* render_frame_host = is_cross_site ? - content::WebContentsTester::For( - web_contents())->GetPendingMainFrame() : - web_contents()->GetMainFrame(); - content::WebContentsTester::For(web_contents())->TestDidNavigate( - render_frame_host, - entry->GetPageID(), - GURL(entry->GetURL()), - ui::PAGE_TRANSITION_TYPED); - } + // The pending RVH should commit for cross-site navigations. + content::RenderFrameHost* render_frame_host = + is_cross_site + ? content::WebContentsTester::For(web_contents()) + ->GetPendingMainFrame() + : web_contents()->GetMainFrame(); + + content::WebContentsTester::For(web_contents()) + ->TestDidNavigate(render_frame_host, entry->GetPageID(), + entry->GetUniqueID(), false, GURL(entry->GetURL()), + ui::PAGE_TRANSITION_TYPED); + } void ShowInterstitial(bool is_subresource, const char* url) { DataReductionProxyDebugUIManager::BypassResource resource; @@ -229,6 +256,7 @@ // Start a load. controller().LoadURL(GURL(kBypassURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int pending_id = controller().GetPendingEntry()->GetUniqueID(); // Simulate the load causing an interstitial to be shown. ShowInterstitial(false, kBypassURL); @@ -244,7 +272,7 @@ // The interstitial is shown until the navigation commits. ASSERT_TRUE(GetDataReductionProxyDebugBlockingPage()); // Commit the navigation. - Navigate(kBypassURL, 1); + Navigate(kBypassURL, 1, pending_id, true); // The interstitial should be gone now. EXPECT_EQ(OK, user_response()); ASSERT_FALSE(GetDataReductionProxyDebugBlockingPage()); @@ -254,10 +282,10 @@ // and not proceeding. TEST_F(DataReductionProxyDebugBlockingPageTest, BypassSubresourceDontProceed) { // Navigate somewhere. - Navigate(kGoogleURL, 1); + Navigate(kGoogleURL, 1, 0, true); // Navigate somewhere else. - Navigate(kOtherURL, 2); + Navigate(kOtherURL, 2, 0, true); // Simulate that page loading a bypass-resource triggering an interstitial. ShowInterstitial(true, kBypassURL); @@ -283,7 +311,7 @@ // and proceeding. TEST_F(DataReductionProxyDebugBlockingPageTest, BypassSubresourceProceed) { // Navigate somewhere. - Navigate(kGoogleURL, 1); + Navigate(kGoogleURL, 1, 0, true); // Simulate that page loading a bypass-resource triggering an interstitial. ShowInterstitial(true, kBypassURL); @@ -310,15 +338,15 @@ TEST_F(DataReductionProxyDebugBlockingPageTest, BypassMultipleSubresourcesDontProceed) { // Navigate somewhere. - Navigate(kGoogleURL, 1); + Navigate(kGoogleURL, 1, 0, true); // Navigate somewhere else. - Navigate(kOtherURL, 2); + Navigate(kOtherURL, 2, 0, true); // Simulate that page loading a bypass-resource triggering an interstitial. ShowInterstitial(true, kBypassURL); - // More bypassedd resources loading causing more interstitials. The new + // More bypassed resources loading causing more interstitials. The new // interstitials should be queued. ShowInterstitial(true, kBypassURL2); ShowInterstitial(true, kBypassURL3); @@ -332,7 +360,7 @@ EXPECT_EQ(CANCEL, user_response()); EXPECT_FALSE(GetDataReductionProxyDebugBlockingPage()); - // The user did not proceed, the controler should be back to the first page, + // The user did not proceed, the controller should be back to the first page, // the 2nd one should have been removed from the navigation controller. ASSERT_EQ(1, controller().GetEntryCount()); EXPECT_EQ(kGoogleURL, controller().GetActiveEntry()->GetURL().spec()); @@ -344,7 +372,7 @@ TEST_F(DataReductionProxyDebugBlockingPageTest, BypassMultipleSubresourcesProceed) { // Navigate somewhere. - Navigate(kGoogleURL, 1); + Navigate(kGoogleURL, 1, 0, true); // Simulate that page loading a bypass-resource triggering an interstitial. ShowInterstitial(true, kBypassURL); @@ -371,11 +399,12 @@ // controller entries are OK. TEST_F(DataReductionProxyDebugBlockingPageTest, NavigatingBackAndForth) { // Navigate somewhere. - Navigate(kGoogleURL, 1); + Navigate(kGoogleURL, 1, 0, true); // Now navigate to a bypassed page triggerring an interstitial. controller().LoadURL(GURL(kBypassURL), content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int pending_id = controller().GetPendingEntry()->GetUniqueID(); ShowInterstitial(false, kBypassURL); DataReductionProxyDebugBlockingPage* interstitial = GetDataReductionProxyDebugBlockingPage(); @@ -383,7 +412,7 @@ // Proceed through the 1st interstitial. ProceedThroughInterstitial(interstitial); - Navigate(kBypassURL, 2); // Commit the navigation. + Navigate(kBypassURL, 2, pending_id, true); // Commit navigation. GoBack(true); // We are back on the first page. @@ -394,13 +423,15 @@ // Navigate forward to the bypassed URL. web_contents()->GetController().GoForward(); + pending_id = controller().GetPendingEntry()->GetUniqueID(); ShowInterstitial(false, kBypassURL); interstitial = GetDataReductionProxyDebugBlockingPage(); ASSERT_TRUE(interstitial); // Let's proceed and make sure everything is OK. ProceedThroughInterstitial(interstitial); - Navigate(kBypassURL, 2); // Commit the navigation. + // Commit the navigation. + NavigateCrossSite(kBypassURL, 2, pending_id, false); interstitial = GetDataReductionProxyDebugBlockingPage(); ASSERT_FALSE(interstitial); ASSERT_EQ(2, controller().GetEntryCount());
diff --git a/components/data_reduction_proxy/content/browser/data_reduction_proxy_debug_resource_throttle_unittest.cc b/components/data_reduction_proxy/content/browser/data_reduction_proxy_debug_resource_throttle_unittest.cc index e7e37892..7845c058 100644 --- a/components/data_reduction_proxy/content/browser/data_reduction_proxy_debug_resource_throttle_unittest.cc +++ b/components/data_reduction_proxy/content/browser/data_reduction_proxy_debug_resource_throttle_unittest.cc
@@ -105,6 +105,7 @@ } private: + base::MessageLoop message_loop_; net::TestURLRequestContext context_; net::TestDelegate delegate_; // |test_job_interceptor_| is owned by |test_job_factory_|.
diff --git a/components/data_reduction_proxy/content/browser/data_reduction_proxy_message_filter_unittest.cc b/components/data_reduction_proxy/content/browser/data_reduction_proxy_message_filter_unittest.cc index ab2252b..eef60db 100644 --- a/components/data_reduction_proxy/content/browser/data_reduction_proxy_message_filter_unittest.cc +++ b/components/data_reduction_proxy/content/browser/data_reduction_proxy_message_filter_unittest.cc
@@ -38,6 +38,7 @@ } private: + base::MessageLoopForIO message_loop_; scoped_ptr<DataReductionProxyTestContext> test_context_; scoped_refptr<DataReductionProxyMessageFilter> message_filter_; };
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc index 0934c3e6..d6f2da6 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -311,6 +311,7 @@ } protected: + base::MessageLoopForIO message_loop_; scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; scoped_ptr<net::URLRequestInterceptor> simple_interceptor_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc index 87e94d2..d1796571 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
@@ -7,7 +7,6 @@ #include "base/callback.h" #include "base/metrics/histogram.h" #include "base/metrics/sparse_histogram.h" -#include "base/prefs/pref_member.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_tamper_detection.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" @@ -170,7 +169,7 @@ void DataReductionProxyBypassStats::RecordBytesHistograms( const net::URLRequest& request, - const BooleanPrefMember& data_reduction_proxy_enabled, + bool data_reduction_proxy_enabled, const net::ProxyConfig& data_reduction_proxy_config) { RecordBypassedBytesHistograms(request, data_reduction_proxy_enabled, data_reduction_proxy_config); @@ -226,12 +225,12 @@ void DataReductionProxyBypassStats::RecordBypassedBytesHistograms( const net::URLRequest& request, - const BooleanPrefMember& data_reduction_proxy_enabled, + bool data_reduction_proxy_enabled, const net::ProxyConfig& data_reduction_proxy_config) { int64 content_length = request.received_response_content_length(); // Only record histograms when the data reduction proxy is enabled. - if (!data_reduction_proxy_enabled.GetValue()) + if (!data_reduction_proxy_enabled) return; // TODO(bengr): Add histogram(s) for byte counts of unsupported schemes, e.g.,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h index efff8d11..dcec95e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h
@@ -6,7 +6,6 @@ #define COMPONENTS_DATA_REDUCTION_PROXY_CORE_BROWSER_DATA_REDUCTION_PROXY_BYPASS_STATS_H_ #include "base/callback.h" -#include "base/prefs/pref_member.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "net/base/host_port_pair.h" #include "net/base/network_change_notifier.h" @@ -68,7 +67,7 @@ // completed URLRequest |request|. void RecordBytesHistograms( const net::URLRequest& request, - const BooleanPrefMember& data_reduction_proxy_enabled, + bool data_reduction_proxy_enabled, const net::ProxyConfig& data_reduction_proxy_config); // Called by |ChromeNetworkDelegate| when a proxy is put into the bad proxy @@ -104,7 +103,7 @@ // tells us the state of the kDataReductionProxyEnabled preference. void RecordBypassedBytesHistograms( const net::URLRequest& request, - const BooleanPrefMember& data_reduction_proxy_enabled, + bool data_reduction_proxy_enabled, const net::ProxyConfig& data_reduction_proxy_config); // Records UMA of the number of response bytes of responses that are expected
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc index cc1930e..bf1345e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
@@ -130,6 +130,7 @@ } private: + base::MessageLoopForIO message_loop_; net::TestURLRequestContext context_; net::TestDelegate delegate_; scoped_ptr<net::URLRequest> mock_url_request_; @@ -704,6 +705,7 @@ } private: + base::MessageLoopForIO message_loop_; net::TestDelegate delegate_; net::MockClientSocketFactory mock_socket_factory_; net::TestURLRequestContext context_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc index 19ec5f4..ca35828 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -146,6 +146,7 @@ } private: + base::MessageLoopForIO message_loop_; net::TestURLRequestContext context_; net::MockClientSocketFactory mock_socket_factory_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc index 6dfb7b8..504d9561 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -179,6 +179,7 @@ } private: + base::MessageLoopForIO message_loop_; scoped_ptr<DataReductionProxyTestContext> test_context_; scoped_ptr<TestDataReductionProxyParams> expected_params_; };
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc index d669dcd..9d9972b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_configurator_unittest.cc
@@ -50,6 +50,7 @@ } } + base::MessageLoop message_loop_; scoped_ptr<DataReductionProxyTestContext> test_context_; scoped_ptr<DataReductionProxyConfigurator> config_; };
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc index b4189e23..a7e2965 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
@@ -131,6 +131,7 @@ default_context_->Init(); } + base::MessageLoopForIO message_loop_; scoped_ptr<DataReductionProxyTestContext> test_context_; net::TestNetworkDelegate default_network_delegate_; scoped_ptr<net::URLRequestJobFactory> job_factory_; @@ -235,6 +236,7 @@ } private: + base::MessageLoopForIO message_loop_; net::TestNetLog net_log_; net::TestNetworkDelegate network_delegate_; net::TestURLRequestContext context_; @@ -329,6 +331,7 @@ } private: + base::MessageLoopForIO message_loop_; net::TestDelegate delegate_; net::MockClientSocketFactory mock_socket_factory_; net::TestURLRequestContext context_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc index 5a4c5d8..37ecf967 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -5,11 +5,8 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "base/bind.h" -#include "base/command_line.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/prefs/pref_member.h" -#include "base/single_thread_task_runner.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" @@ -93,13 +90,14 @@ net::NetLog* net_log, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, + bool enabled, bool enable_quic, const std::string& user_agent) : client_(client), net_log_(net_log), io_task_runner_(io_task_runner), ui_task_runner_(ui_task_runner), - shutdown_on_ui_(false), + enabled_(enabled), url_request_context_getter_(nullptr), basic_url_request_context_getter_( new BasicHTTPURLRequestContextGetter(user_agent, io_task_runner)), @@ -148,26 +146,14 @@ } DataReductionProxyIOData::DataReductionProxyIOData() - : shutdown_on_ui_(false), - url_request_context_getter_(nullptr), - weak_factory_(this) { + : url_request_context_getter_(nullptr), weak_factory_(this) { } DataReductionProxyIOData::~DataReductionProxyIOData() { - DCHECK(shutdown_on_ui_); -} - -void DataReductionProxyIOData::InitOnUIThread(PrefService* pref_service) { - DCHECK(ui_task_runner_->BelongsToCurrentThread()); - enabled_.Init(prefs::kDataReductionProxyEnabled, pref_service); - enabled_.MoveToThread(io_task_runner_); } void DataReductionProxyIOData::ShutdownOnUIThread() { - DCHECK(!shutdown_on_ui_); DCHECK(ui_task_runner_->BelongsToCurrentThread()); - enabled_.Destroy(); - shutdown_on_ui_ = true; } void DataReductionProxyIOData::SetDataReductionProxyService( @@ -197,9 +183,7 @@ bool DataReductionProxyIOData::IsEnabled() const { DCHECK(io_task_runner_->BelongsToCurrentThread()); - return enabled_.GetValue() || - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableDataReductionProxy); + return enabled_; } void DataReductionProxyIOData::RetrieveConfig() { @@ -225,7 +209,7 @@ wrapped_network_delegate.Pass(), config_.get(), request_options_.get(), configurator_.get())); if (track_proxy_bypass_statistics) - network_delegate->InitIODataAndUMA(this, &enabled_, bypass_stats_.get()); + network_delegate->InitIODataAndUMA(this, bypass_stats_.get()); return network_delegate.Pass(); } @@ -233,6 +217,7 @@ bool alternative_enabled, bool at_startup) { DCHECK(io_task_runner_->BelongsToCurrentThread()); + enabled_ = enabled; config_->SetProxyConfig(enabled, alternative_enabled, at_startup); }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h index 9a6f3b8..4acbc48 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
@@ -9,7 +9,7 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" -#include "base/prefs/pref_member.h" +#include "base/single_thread_task_runner.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_debug_ui_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics.h" @@ -42,23 +42,21 @@ public: // Constructs a DataReductionProxyIOData object. |param_flags| is used to // set information about the DNS names used by the proxy, and allowable - // configurations. + // configurations. |enabled| sets the initial state of the Data Reduction + // Proxy. DataReductionProxyIOData( const Client& client, int param_flags, net::NetLog* net_log, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, + bool enabled, bool enable_quic, const std::string& user_agent); virtual ~DataReductionProxyIOData(); - // Initializes preferences, including a preference to track whether the - // Data Reduction Proxy is enabled. - void InitOnUIThread(PrefService* pref_service); - - // Destroys the statistics preferences. + // Performs UI thread specific shutdown logic. void ShutdownOnUIThread(); // Sets the Data Reduction Proxy service after it has been created. @@ -205,12 +203,9 @@ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; - // Used - bool shutdown_on_ui_; - - // Preference that determines if the Data Reduction Proxy has been enabled - // by the user. In practice, this can be overridden by the command line. - BooleanPrefMember enabled_; + // Whether the Data Reduction Proxy has been enabled or not by the user. In + // practice, this can be overridden by the command line. + bool enabled_; // The net::URLRequestContextGetter used for making URL requests. net::URLRequestContextGetter* url_request_context_getter_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc index 4caf215..24fc634a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -94,8 +94,8 @@ TEST_F(DataReductionProxyIODataTest, TestConstruction) { scoped_ptr<DataReductionProxyIOData> io_data(new DataReductionProxyIOData( Client::UNKNOWN, DataReductionProxyParams::kAllowed, net_log(), - message_loop_proxy(), message_loop_proxy(), false /* enable_quic */, - std::string() /* user_agent */)); + message_loop_proxy(), message_loop_proxy(), false /* enabled */, + false /* enable_quic */, std::string() /* user_agent */)); // Check that the SimpleURLRequestContextGetter uses vanilla HTTP. net::URLRequestContext* request_context = @@ -141,9 +141,6 @@ true); EXPECT_NE(nullptr, io_data->bypass_stats()); - // The Data Reduction Proxy isn't actually enabled here. - io_data->InitOnUIThread(prefs()); - EXPECT_FALSE(io_data->IsEnabled()); io_data->ShutdownOnUIThread(); }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc index be48a2a..5c44a5f7 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_metrics_unittest.cc
@@ -26,6 +26,7 @@ TEST(ChromeNetworkDailyDataSavingMetricsTest, GetDataReductionProxyRequestType) { + base::MessageLoopForIO message_loop; scoped_ptr<DataReductionProxyTestContext> test_context = DataReductionProxyTestContext::Builder() .WithParamsFlags(DataReductionProxyParams::kAllowed)
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc index 6ef70dc..9a66acdf 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.cc
@@ -7,7 +7,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/metrics/histogram.h" -#include "base/prefs/pref_service.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h" @@ -81,7 +80,6 @@ : LayeredNetworkDelegate(network_delegate.Pass()), received_content_length_(0), original_content_length_(0), - data_reduction_proxy_enabled_(nullptr), data_reduction_proxy_config_(config), data_reduction_proxy_bypass_stats_(nullptr), data_reduction_proxy_request_options_(request_options), @@ -96,12 +94,9 @@ void DataReductionProxyNetworkDelegate::InitIODataAndUMA( DataReductionProxyIOData* io_data, - BooleanPrefMember* data_reduction_proxy_enabled, DataReductionProxyBypassStats* bypass_stats) { - DCHECK(data_reduction_proxy_enabled); DCHECK(bypass_stats); data_reduction_proxy_io_data_ = io_data; - data_reduction_proxy_enabled_ = data_reduction_proxy_enabled; data_reduction_proxy_bypass_stats_ = bypass_stats; } @@ -191,10 +186,9 @@ original_content_length, freshness_lifetime); - if (data_reduction_proxy_enabled_ && - data_reduction_proxy_bypass_stats_) { + if (data_reduction_proxy_io_data_ && data_reduction_proxy_bypass_stats_) { data_reduction_proxy_bypass_stats_->RecordBytesHistograms( - *request, *data_reduction_proxy_enabled_, + *request, data_reduction_proxy_io_data_->IsEnabled(), configurator_->GetProxyConfig()); } DVLOG(2) << __FUNCTION__ @@ -210,10 +204,10 @@ DataReductionProxyRequestType request_type) { DCHECK_GE(received_content_length, 0); DCHECK_GE(original_content_length, 0); - if (data_reduction_proxy_enabled_) { + if (data_reduction_proxy_io_data_) { data_reduction_proxy_io_data_->UpdateContentLengths( received_content_length, original_content_length, - data_reduction_proxy_enabled_->GetValue(), request_type); + data_reduction_proxy_io_data_->IsEnabled(), request_type); } received_content_length_ += received_content_length; original_content_length_ += original_content_length;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h index 8cb016eb..0290d6e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate.h
@@ -13,12 +13,7 @@ #include "net/base/layered_network_delegate.h" #include "net/proxy/proxy_retry_info.h" -template<class T> class PrefMember; - -typedef PrefMember<bool> BooleanPrefMember; - class GURL; -class PrefService; namespace net { class HttpResponseHeaders; @@ -64,7 +59,6 @@ // report UMA. void InitIODataAndUMA( DataReductionProxyIOData* io_data, - BooleanPrefMember* data_reduction_proxy_enabled, DataReductionProxyBypassStats* bypass_stats); // Creates a |Value| summary of the state of the network session. The caller @@ -117,9 +111,6 @@ // Total original size of all content before it was transferred. int64 original_content_length_; - // Weak, owned by our owner. - BooleanPrefMember* data_reduction_proxy_enabled_; - // All raw Data Reduction Proxy pointers must outlive |this|. DataReductionProxyConfig* data_reduction_proxy_config_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc index c96c862..b35c4011 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_network_delegate_unittest.cc
@@ -147,6 +147,7 @@ data_reduction_proxy_network_delegate_; private: + base::MessageLoopForIO message_loop_; net::TestURLRequestContext context_; net::TestDelegate delegate_; // |test_job_interceptor_| is owned by |test_job_factory_|.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc index 00acd883..2b59e3a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.cc
@@ -30,69 +30,35 @@ // Make sure any changes here that have the potential to impact android_webview // are reflected in RegisterSimpleProfilePrefs. void RegisterSyncableProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kDataReductionProxyEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDataReductionProxyAltEnabled, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kDataReductionProxyWasEnabledBefore, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kDataReductionProxyEnabled, false); + registry->RegisterBooleanPref(prefs::kDataReductionProxyAltEnabled, false); + registry->RegisterBooleanPref(prefs::kDataReductionProxyWasEnabledBefore, + false); - registry->RegisterInt64Pref( - prefs::kHttpReceivedContentLength, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kHttpOriginalContentLength, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterInt64Pref(prefs::kHttpReceivedContentLength, 0); + registry->RegisterInt64Pref(prefs::kHttpOriginalContentLength, 0); - registry->RegisterBooleanPref( - prefs::kStatisticsPrefsMigrated, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kStatisticsPrefsMigrated, false); registry->RegisterBooleanPref(prefs::kUpdateDailyReceivedContentLengths, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + false); + registry->RegisterListPref(prefs::kDailyHttpOriginalContentLength); + registry->RegisterListPref(prefs::kDailyHttpReceivedContentLength); registry->RegisterListPref( - prefs::kDailyHttpOriginalContentLength, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled); registry->RegisterListPref( - prefs::kDailyHttpReceivedContentLength, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDailyContentLengthWithDataReductionProxyEnabled); registry->RegisterListPref( - prefs::kDailyOriginalContentLengthWithDataReductionProxyEnabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled); registry->RegisterListPref( - prefs::kDailyContentLengthWithDataReductionProxyEnabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDailyContentLengthShortBypassWithDataReductionProxyEnabled); registry->RegisterListPref( - prefs::kDailyContentLengthHttpsWithDataReductionProxyEnabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDailyContentLengthLongBypassWithDataReductionProxyEnabled); registry->RegisterListPref( - prefs::kDailyContentLengthShortBypassWithDataReductionProxyEnabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDailyContentLengthUnknownWithDataReductionProxyEnabled); registry->RegisterListPref( - prefs::kDailyContentLengthLongBypassWithDataReductionProxyEnabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref( - prefs::kDailyContentLengthUnknownWithDataReductionProxyEnabled, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref( - prefs::kDailyOriginalContentLengthViaDataReductionProxy, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref( - prefs::kDailyContentLengthViaDataReductionProxy, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kDailyHttpContentLengthLastUpdateDate, - 0L, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + prefs::kDailyOriginalContentLengthViaDataReductionProxy); + registry->RegisterListPref(prefs::kDailyContentLengthViaDataReductionProxy); + registry->RegisterInt64Pref(prefs::kDailyHttpContentLengthLastUpdateDate, 0L); } void RegisterSimpleProfilePrefs(PrefRegistrySimple* registry) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc index 4ea8a9a..eb7f5b5 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options_unittest.cc
@@ -174,6 +174,7 @@ EXPECT_EQ(expected_header, header_value); } + base::MessageLoopForIO message_loop_; scoped_ptr<TestDataReductionProxyRequestOptions> request_options_; scoped_ptr<DataReductionProxyTestContext> test_context_; };
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc index 57f18bb6..0c5b802b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.cc
@@ -13,6 +13,7 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" @@ -21,13 +22,6 @@ const char kUMAProxyStartupStateHistogram[] = "DataReductionProxy.StartupState"; -bool IsEnabledOnCommandLine() { - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - return command_line.HasSwitch( - data_reduction_proxy::switches::kEnableDataReductionProxy); -} - bool IsLoFiEnabledOnCommandLine() { const base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); @@ -116,7 +110,8 @@ } bool DataReductionProxySettings::IsDataReductionProxyEnabled() const { - return spdy_proxy_auth_enabled_.GetValue() || IsEnabledOnCommandLine(); + return spdy_proxy_auth_enabled_.GetValue() || + DataReductionProxyParams::ShouldForceEnableDataReductionProxy(); } bool DataReductionProxySettings::CanUseDataReductionProxy(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h index 3df3671c..dc5ec7f 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_test_utils.h
@@ -83,6 +83,7 @@ return true; } + base::MessageLoopForIO message_loop_; scoped_ptr<DataReductionProxyTestContext> test_context_; scoped_ptr<DataReductionProxySettings> settings_; base::Time last_update_time_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc index dce4f0a..0bcc780 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings_unittest.cc
@@ -143,6 +143,7 @@ } TEST(DataReductionProxySettingsStandaloneTest, TestEndToEndSecureProxyCheck) { + base::MessageLoopForIO message_loop; struct TestCase { const char* response_headers; const char* response_body; @@ -215,6 +216,7 @@ } TEST(DataReductionProxySettingsStandaloneTest, TestOnProxyEnabledPrefChange) { + base::MessageLoopForIO message_loop; scoped_ptr<DataReductionProxyTestContext> drp_test_context = DataReductionProxyTestContext::Builder() .WithParamsFlags(DataReductionProxyParams::kAllowed |
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc index f070f13..f71ce8d 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
@@ -4,7 +4,6 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h" -#include "base/message_loop/message_loop.h" #include "base/prefs/testing_pref_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_compression_stats.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h" @@ -178,7 +177,8 @@ scoped_ptr<DataReductionProxyEventCreator> event_creator, scoped_ptr<DataReductionProxyRequestOptions> request_options, scoped_ptr<DataReductionProxyConfigurator> configurator, - scoped_ptr<DataReductionProxyConfigServiceClient> config_client) + scoped_ptr<DataReductionProxyConfigServiceClient> config_client, + bool enabled) : DataReductionProxyIOData() { io_task_runner_ = task_runner; ui_task_runner_ = task_runner; @@ -192,10 +192,10 @@ base::Unretained(this)))); io_task_runner_ = task_runner; ui_task_runner_ = task_runner; + enabled_ = enabled; } TestDataReductionProxyIOData::~TestDataReductionProxyIOData() { - shutdown_on_ui_ = true; } DataReductionProxyTestContext::Builder::Builder() @@ -293,7 +293,6 @@ DataReductionProxyTestContext::Builder::Build() { // Check for invalid builder combinations. DCHECK(!(use_mock_config_ && use_config_client_)); - scoped_ptr<base::MessageLoopForIO> loop(new base::MessageLoopForIO()); unsigned int test_context_flags = 0; scoped_refptr<base::SingleThreadTaskRunner> task_runner = @@ -388,13 +387,13 @@ scoped_ptr<TestDataReductionProxyIOData> io_data( new TestDataReductionProxyIOData( task_runner, config.Pass(), event_creator.Pass(), - request_options.Pass(), configurator.Pass(), config_client.Pass())); - io_data->InitOnUIThread(pref_service.get()); + request_options.Pass(), configurator.Pass(), config_client.Pass(), + true /* enabled */)); io_data->SetSimpleURLRequestContextGetter(request_context_getter); scoped_ptr<DataReductionProxyTestContext> test_context( new DataReductionProxyTestContext( - loop.Pass(), task_runner, pref_service.Pass(), net_log.Pass(), + task_runner, pref_service.Pass(), net_log.Pass(), request_context_getter, mock_socket_factory_, io_data.Pass(), settings.Pass(), storage_delegate.Pass(), raw_params, test_context_flags)); @@ -406,7 +405,6 @@ } DataReductionProxyTestContext::DataReductionProxyTestContext( - scoped_ptr<base::MessageLoop> loop, scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_ptr<TestingPrefServiceSimple> simple_pref_service, scoped_ptr<net::TestNetLog> net_log, @@ -418,7 +416,6 @@ TestDataReductionProxyParams* params, unsigned int test_context_flags) : test_context_flags_(test_context_flags), - loop_(loop.Pass()), task_runner_(task_runner), simple_pref_service_(simple_pref_service.Pass()), net_log_(net_log.Pass()),
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h index e5c4ca0..81a8984 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
@@ -167,7 +167,8 @@ scoped_ptr<DataReductionProxyEventCreator> event_creator, scoped_ptr<DataReductionProxyRequestOptions> request_options, scoped_ptr<DataReductionProxyConfigurator> configurator, - scoped_ptr<DataReductionProxyConfigServiceClient> config_client); + scoped_ptr<DataReductionProxyConfigServiceClient> config_client, + bool enabled); ~TestDataReductionProxyIOData() override; DataReductionProxyConfigurator* configurator() const { @@ -386,7 +387,6 @@ }; DataReductionProxyTestContext( - scoped_ptr<base::MessageLoop> loop, scoped_refptr<base::SingleThreadTaskRunner> task_runner, scoped_ptr<TestingPrefServiceSimple> simple_pref_service, scoped_ptr<net::TestNetLog> net_log, @@ -405,8 +405,6 @@ unsigned int test_context_flags_; - scoped_ptr<base::MessageLoop> loop_; - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; scoped_ptr<TestingPrefServiceSimple> simple_pref_service_; scoped_ptr<net::TestNetLog> net_log_;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc index 05c996bb..9f512d42 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_event_store_unittest.cc
@@ -11,6 +11,7 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_event_creator.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" #include "net/http/http_status_code.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/test_net_log.h" #include "testing/gtest/include/gtest/gtest.h" @@ -30,8 +31,8 @@ new DataReductionProxyEventCreator(event_store_.get())); } - net::TestNetLog::CapturedEntry GetSingleEntry() const { - net::TestNetLog::CapturedEntryList entries; + net::CapturedNetLogEntry GetSingleEntry() const { + net::CapturedNetLogEntry::List entries; net_log_->GetEntries(&entries); EXPECT_EQ(1u, entries.size()); return entries[0]; @@ -63,7 +64,7 @@ TestDataReductionProxyParams::DefaultFallbackOrigin(), TestDataReductionProxyParams::DefaultSSLOrigin()); EXPECT_EQ(1u, event_store()->stored_events_.size()); - net::TestNetLog::CapturedEntry entry = GetSingleEntry(); + net::CapturedNetLogEntry entry = GetSingleEntry(); EXPECT_EQ(net::NetLog::TYPE_DATA_REDUCTION_PROXY_ENABLED, entry.type); } @@ -72,7 +73,7 @@ EXPECT_EQ(0u, event_store()->stored_events_.size()); event_creator()->AddProxyDisabledEvent(net_log()); EXPECT_EQ(1u, event_store()->stored_events_.size()); - net::TestNetLog::CapturedEntry entry = GetSingleEntry(); + net::CapturedNetLogEntry entry = GetSingleEntry(); EXPECT_EQ(net::NetLog::TYPE_DATA_REDUCTION_PROXY_ENABLED, entry.type); } @@ -83,7 +84,7 @@ event_creator()->AddBypassActionEvent(bound_net_log(), "bypass", GURL(), base::TimeDelta::FromMinutes(1)); EXPECT_EQ(1u, event_store()->stored_events_.size()); - net::TestNetLog::CapturedEntry entry = GetSingleEntry(); + net::CapturedNetLogEntry entry = GetSingleEntry(); EXPECT_EQ(net::NetLog::TYPE_DATA_REDUCTION_PROXY_BYPASS_REQUESTED, entry.type); EXPECT_NE(nullptr, event_store()->last_bypass_event_.get()); @@ -96,7 +97,7 @@ GURL(), base::TimeDelta::FromMinutes(1)); EXPECT_EQ(1u, event_store()->stored_events_.size()); EXPECT_EQ(1u, net_log()->GetSize()); - net::TestNetLog::CapturedEntry entry = GetSingleEntry(); + net::CapturedNetLogEntry entry = GetSingleEntry(); EXPECT_EQ(net::NetLog::TYPE_DATA_REDUCTION_PROXY_BYPASS_REQUESTED, entry.type); EXPECT_NE(nullptr, event_store()->last_bypass_event_.get()); @@ -109,7 +110,7 @@ event_creator()->BeginSecureProxyCheck(bound_net_log(), GURL()); EXPECT_EQ(1u, event_store()->stored_events_.size()); EXPECT_EQ(1u, net_log()->GetSize()); - net::TestNetLog::CapturedEntry entry = GetSingleEntry(); + net::CapturedNetLogEntry entry = GetSingleEntry(); EXPECT_EQ(net::NetLog::TYPE_DATA_REDUCTION_PROXY_CANARY_REQUEST, entry.type); EXPECT_EQ(DataReductionProxyEventStorageDelegate::CHECK_PENDING, @@ -123,7 +124,7 @@ event_creator()->EndSecureProxyCheck(bound_net_log(), 0, net::HTTP_OK, true); EXPECT_EQ(1u, event_store()->stored_events_.size()); EXPECT_EQ(1u, net_log()->GetSize()); - net::TestNetLog::CapturedEntry entry = GetSingleEntry(); + net::CapturedNetLogEntry entry = GetSingleEntry(); EXPECT_EQ(net::NetLog::TYPE_DATA_REDUCTION_PROXY_CANARY_REQUEST, entry.type); EXPECT_EQ(DataReductionProxyEventStorageDelegate::CHECK_SUCCESS,
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc index 79205a2..d62b73b 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.cc
@@ -102,7 +102,6 @@ bool DataReductionProxyParams::IsLoFiEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( data_reduction_proxy::switches::kEnableDataReductionProxyLoFi); - } //static @@ -136,6 +135,12 @@ data_reduction_proxy::switches::kEnableDataReductionProxyConfigClient); } +// static +bool DataReductionProxyParams::ShouldForceEnableDataReductionProxy() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + data_reduction_proxy::switches::kEnableDataReductionProxy); +} + void DataReductionProxyParams::EnableQuic(bool enable) { quic_enabled_ = enable; DCHECK(!quic_enabled_ || IsIncludedInQuicFieldTrial());
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h index 0f6aea8..fe345ec 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_params.h
@@ -116,6 +116,10 @@ // Returns true if the Data Reduction Proxy config client should be used. static bool IsConfigClientEnabled(); + // Returns true if the Data Reduction Proxy is forced to be enabled from the + // command line. + static bool ShouldForceEnableDataReductionProxy(); + // Constructs configuration parameters. If |kAllowed|, then the standard // data reduction proxy configuration is allowed to be used. If // |kfallbackAllowed| a fallback proxy can be used if the primary proxy is
diff --git a/components/dom_distiller.gypi b/components/dom_distiller.gypi index fa2f4ee..c2bb83d 100644 --- a/components/dom_distiller.gypi +++ b/components/dom_distiller.gypi
@@ -82,6 +82,8 @@ 'dom_distiller/core/dom_distiller_model.cc', 'dom_distiller/core/dom_distiller_model.h', 'dom_distiller/core/dom_distiller_observer.h', + 'dom_distiller/core/dom_distiller_request_view_base.cc', + 'dom_distiller/core/dom_distiller_request_view_base.h', 'dom_distiller/core/dom_distiller_service.cc', 'dom_distiller/core/dom_distiller_service.h', 'dom_distiller/core/dom_distiller_service_android.cc',
diff --git a/components/dom_distiller/content/distiller_page_web_contents_browsertest.cc b/components/dom_distiller/content/distiller_page_web_contents_browsertest.cc index d1d2dff..0ba7c61b 100644 --- a/components/dom_distiller/content/distiller_page_web_contents_browsertest.cc +++ b/components/dom_distiller/content/distiller_page_web_contents_browsertest.cc
@@ -5,6 +5,7 @@ #include "base/memory/weak_ptr.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "components/dom_distiller/content/distiller_page_web_contents.h" #include "components/dom_distiller/content/web_contents_main_frame_observer.h" @@ -100,6 +101,11 @@ quit_closure_.Run(); } + void OnJsExecutionDone(base::Closure callback, const base::Value* value) { + js_result_.reset(value->DeepCopy()); + callback.Run(); + } + private: void AddComponentsResources() { base::FilePath pak_file; @@ -119,8 +125,10 @@ void SetUpTestServer() { base::FilePath path; PathService::Get(base::DIR_SOURCE_ROOT, &path); - path = path.AppendASCII("components/test/data/dom_distiller"); - embedded_test_server()->ServeFilesFromDirectory(path); + embedded_test_server()->ServeFilesFromDirectory( + path.AppendASCII("components/test/data/dom_distiller")); + embedded_test_server()->ServeFilesFromDirectory( + path.AppendASCII("components/dom_distiller/core/javascript")); ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); } @@ -133,6 +141,7 @@ DistillerPageWebContents* distiller_page_; base::Closure quit_closure_; scoped_ptr<proto::DomDistillerResult> distiller_result_; + scoped_ptr<base::Value> js_result_; }; // Use this class to be able to leak the WebContents, which is needed for when @@ -458,4 +467,40 @@ } } +IN_PROC_BROWSER_TEST_F(DistillerPageWebContentsTest, + TestPinch) { + // Load the test file in content shell and wait until it has fully loaded. + content::WebContents* web_contents = shell()->web_contents(); + dom_distiller::WebContentsMainFrameObserver::CreateForWebContents( + web_contents); + base::RunLoop url_loaded_runner; + WebContentsMainFrameHelper main_frame_loaded(web_contents, + url_loaded_runner.QuitClosure(), + true); + web_contents->GetController().LoadURL( + embedded_test_server()->GetURL("/pinch_tester.html"), + content::Referrer(), + ui::PAGE_TRANSITION_TYPED, + std::string()); + url_loaded_runner.Run(); + + // Execute the JS to run the tests, and wait until it has finished. + base::RunLoop run_loop; + web_contents->GetMainFrame()->ExecuteJavaScript( + base::UTF8ToUTF16("(function() {return pinchtest.run();})();"), + base::Bind(&DistillerPageWebContentsTest::OnJsExecutionDone, + base::Unretained(this), run_loop.QuitClosure())); + run_loop.Run(); + + // Convert to dictionary and parse the results. + const base::DictionaryValue* dict; + ASSERT_TRUE(js_result_); + ASSERT_TRUE(js_result_->GetAsDictionary(&dict)); + + ASSERT_TRUE(dict->HasKey("success")); + bool success; + ASSERT_TRUE(dict->GetBoolean("success", &success)); + EXPECT_TRUE(success); +} + } // namespace dom_distiller
diff --git a/components/dom_distiller/content/dom_distiller_viewer_source.cc b/components/dom_distiller/content/dom_distiller_viewer_source.cc index 5015464..f1ed1a8 100644 --- a/components/dom_distiller/content/dom_distiller_viewer_source.cc +++ b/components/dom_distiller/content/dom_distiller_viewer_source.cc
@@ -14,6 +14,7 @@ #include "base/metrics/user_metrics.h" #include "base/strings/utf_string_conversions.h" #include "components/dom_distiller/core/distilled_page_prefs.h" +#include "components/dom_distiller/core/dom_distiller_request_view_base.h" #include "components/dom_distiller/core/dom_distiller_service.h" #include "components/dom_distiller/core/external_feedback_reporter.h" #include "components/dom_distiller/core/feedback_reporter.h" @@ -32,32 +33,44 @@ namespace dom_distiller { +namespace { + +class ContentDataCallback : public DistillerDataCallback { + public: + ContentDataCallback(const content::URLDataSource::GotDataCallback& callback); + // Runs the callback. + void RunCallback(std::string& data) override; + + private: + // The callback that actually gets run. + content::URLDataSource::GotDataCallback callback_; +}; + +ContentDataCallback::ContentDataCallback( + const content::URLDataSource::GotDataCallback& callback) { + callback_ = callback; +} + +void ContentDataCallback::RunCallback(std::string& data) { + callback_.Run(base::RefCountedString::TakeString(&data)); +} + +} // namespace + // Handles receiving data asynchronously for a specific entry, and passing // it along to the data callback for the data source. Lifetime matches that of // the current main frame's page in the Viewer instance. class DomDistillerViewerSource::RequestViewerHandle - : public ViewRequestDelegate, - public content::WebContentsObserver, - public DistilledPagePrefs::Observer { + : public DomDistillerRequestViewBase, + public content::WebContentsObserver { public: - explicit RequestViewerHandle( - content::WebContents* web_contents, - const std::string& expected_scheme, - const std::string& expected_request_path, - const content::URLDataSource::GotDataCallback& callback, - DistilledPagePrefs* distilled_page_prefs); + RequestViewerHandle(content::WebContents* web_contents, + const std::string& expected_scheme, + const std::string& expected_request_path, + scoped_ptr<ContentDataCallback> callback, + DistilledPagePrefs* distilled_page_prefs); ~RequestViewerHandle() override; - // Flag this request as an error and send the error page template. - void flagAsErrorPage(); - - // ViewRequestDelegate implementation: - void OnArticleReady(const DistilledArticleProto* article_proto) override; - - void OnArticleUpdated(ArticleDistillationUpdate article_update) override; - - void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); - // content::WebContentsObserver implementation: void DidNavigateMainFrame( const content::LoadCommittedDetails& details, @@ -70,38 +83,19 @@ private: // Sends JavaScript to the attached Viewer, buffering data if the viewer isn't // ready. - void SendJavaScript(const std::string& buffer); + void SendJavaScript(const std::string& buffer) override; // Cancels the current view request. Once called, no updates will be // propagated to the view, and the request to DomDistillerService will be // cancelled. void Cancel(); - // DistilledPagePrefs::Observer implementation: - void OnChangeFontFamily( - DistilledPagePrefs::FontFamily new_font_family) override; - void OnChangeTheme(DistilledPagePrefs::Theme new_theme) override; - - // The handle to the view request towards the DomDistillerService. It - // needs to be kept around to ensure the distillation request finishes. - scoped_ptr<ViewerHandle> viewer_handle_; - // The scheme hosting the current view request; std::string expected_scheme_; // The query path for the current view request. std::string expected_request_path_; - // Holds the callback to where the data retrieved is sent back. - content::URLDataSource::GotDataCallback callback_; - - // Number of pages of the distilled article content that have been rendered by - // the viewer. - int page_count_; - - // Interface for accessing preferences for distilled pages. - DistilledPagePrefs* distilled_page_prefs_; - // Whether the page is sufficiently initialized to handle updates from the // distiller. bool waiting_for_page_ready_; @@ -109,24 +103,18 @@ // Temporary store of pending JavaScript if the page isn't ready to receive // data from distillation. std::string buffer_; - - // Flag to tell this observer that the web contents are in an error state. - bool is_error_page_; }; DomDistillerViewerSource::RequestViewerHandle::RequestViewerHandle( content::WebContents* web_contents, const std::string& expected_scheme, const std::string& expected_request_path, - const content::URLDataSource::GotDataCallback& callback, + scoped_ptr<ContentDataCallback> callback, DistilledPagePrefs* distilled_page_prefs) - : expected_scheme_(expected_scheme), + : DomDistillerRequestViewBase(callback.Pass(), distilled_page_prefs), + expected_scheme_(expected_scheme), expected_request_path_(expected_request_path), - callback_(callback), - page_count_(0), - distilled_page_prefs_(distilled_page_prefs), - waiting_for_page_ready_(true), - is_error_page_(false) { + waiting_for_page_ready_(true) { content::WebContentsObserver::Observe(web_contents); distilled_page_prefs_->AddObserver(this); } @@ -135,14 +123,6 @@ distilled_page_prefs_->RemoveObserver(this); } -void DomDistillerViewerSource::RequestViewerHandle::flagAsErrorPage() { - is_error_page_ = true; - std::string error_page_html = viewer::GetErrorPageHtml( - distilled_page_prefs_->GetTheme(), - distilled_page_prefs_->GetFontFamily()); - callback_.Run(base::RefCountedString::TakeString(&error_page_html)); -} - void DomDistillerViewerSource::RequestViewerHandle::SendJavaScript( const std::string& buffer) { if (waiting_for_page_ready_) { @@ -190,7 +170,7 @@ void DomDistillerViewerSource::RequestViewerHandle::DidFinishLoad( content::RenderFrameHost* render_frame_host, const GURL& validated_url) { - if (is_error_page_) { + if (IsErrorPage()) { waiting_for_page_ready_ = false; SendJavaScript(viewer::GetErrorPageJs()); SendJavaScript(viewer::GetShowFeedbackFormJs()); @@ -209,76 +189,6 @@ buffer_.clear(); } -void DomDistillerViewerSource::RequestViewerHandle::OnArticleReady( - const DistilledArticleProto* article_proto) { - // TODO(mdjones): Move this logic to super class so it can be used in both - // android and IOS. http://crbug.com/472797 - if (page_count_ == 0) { - std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( - &article_proto->pages(0), - distilled_page_prefs_->GetTheme(), - distilled_page_prefs_->GetFontFamily()); - callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); - // Send first page to client. - SendJavaScript(viewer::GetUnsafeArticleContentJs(article_proto)); - // If any content was loaded, show the feedback form. - SendJavaScript(viewer::GetShowFeedbackFormJs()); - } else if (page_count_ == article_proto->pages_size()) { - // We may still be showing the "Loading" indicator. - SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); - } else { - // It's possible that we didn't get some incremental updates from the - // distiller. Ensure all remaining pages are flushed to the viewer. - for (;page_count_ < article_proto->pages_size(); page_count_++) { - const DistilledPageProto& page = article_proto->pages(page_count_); - SendJavaScript( - viewer::GetUnsafeIncrementalDistilledPageJs( - &page, - page_count_ == article_proto->pages_size())); - } - } - // No need to hold on to the ViewerHandle now that distillation is complete. - viewer_handle_.reset(); -} - -void DomDistillerViewerSource::RequestViewerHandle::OnArticleUpdated( - ArticleDistillationUpdate article_update) { - for (;page_count_ < static_cast<int>(article_update.GetPagesSize()); - page_count_++) { - const DistilledPageProto& page = - article_update.GetDistilledPage(page_count_); - // Send the page content to the client. This will execute after the page is - // ready. - SendJavaScript(viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); - - if (page_count_ == 0) { - // This is the first page, so send Viewer page scaffolding too. - std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( - &page, - distilled_page_prefs_->GetTheme(), - distilled_page_prefs_->GetFontFamily()); - callback_.Run(base::RefCountedString::TakeString(&unsafe_page_html)); - // If any content was loaded, show the feedback form. - SendJavaScript(viewer::GetShowFeedbackFormJs()); - } - } -} - -void DomDistillerViewerSource::RequestViewerHandle::TakeViewerHandle( - scoped_ptr<ViewerHandle> viewer_handle) { - viewer_handle_ = viewer_handle.Pass(); -} - -void DomDistillerViewerSource::RequestViewerHandle::OnChangeTheme( - DistilledPagePrefs::Theme new_theme) { - SendJavaScript(viewer::GetDistilledPageThemeJs(new_theme)); -} - -void DomDistillerViewerSource::RequestViewerHandle::OnChangeFontFamily( - DistilledPagePrefs::FontFamily new_font) { - SendJavaScript(viewer::GetDistilledPageFontFamilyJs(new_font)); -} - DomDistillerViewerSource::DomDistillerViewerSource( DomDistillerServiceInterface* dom_distiller_service, const std::string& scheme, @@ -322,6 +232,7 @@ return; } else if (kFeedbackBad == path) { FeedbackReporter::ReportQuality(false); + callback.Run(NULL); if (!external_feedback_reporter_) return; content::WebContents* contents = @@ -331,6 +242,7 @@ return; } else if (kFeedbackGood == path) { FeedbackReporter::ReportQuality(true); + callback.Run(NULL); return; } content::WebContents* web_contents = @@ -338,10 +250,12 @@ DCHECK(web_contents); // An empty |path| is invalid, but guard against it. If not empty, assume // |path| starts with '?', which is stripped away. + scoped_ptr<ContentDataCallback> data_callback( + new ContentDataCallback(callback)); const std::string path_after_query_separator = path.size() > 0 ? path.substr(1) : ""; RequestViewerHandle* request_viewer_handle = new RequestViewerHandle( - web_contents, scheme_, path_after_query_separator, callback, + web_contents, scheme_, path_after_query_separator, data_callback.Pass(), dom_distiller_service_->GetDistilledPagePrefs()); scoped_ptr<ViewerHandle> viewer_handle = viewer::CreateViewRequest( dom_distiller_service_, path, request_viewer_handle, @@ -354,7 +268,7 @@ // after receiving the callback. request_viewer_handle->TakeViewerHandle(viewer_handle.Pass()); } else { - request_viewer_handle->flagAsErrorPage(); + request_viewer_handle->FlagAsErrorPage(); } };
diff --git a/components/dom_distiller/core/BUILD.gn b/components/dom_distiller/core/BUILD.gn index a9b1cda..565f1fe 100644 --- a/components/dom_distiller/core/BUILD.gn +++ b/components/dom_distiller/core/BUILD.gn
@@ -32,6 +32,8 @@ "dom_distiller_model.cc", "dom_distiller_model.h", "dom_distiller_observer.h", + "dom_distiller_request_view_base.cc", + "dom_distiller_request_view_base.h", "dom_distiller_service.cc", "dom_distiller_service.h", "dom_distiller_store.cc",
diff --git a/components/dom_distiller/core/css/distilledpage.css b/components/dom_distiller/core/css/distilledpage.css index adfb682..bdb60f2 100644 --- a/components/dom_distiller/core/css/distilledpage.css +++ b/components/dom_distiller/core/css/distilledpage.css
@@ -73,12 +73,17 @@ /* Base typography. */ -body, html { font-size: 14px; +} + +body { height: 100%; line-height: 1.4; text-rendering: optimizeLegibility; + transition-property: color, background-color; + transition-duration: 0.5s; + transition-timing-function: ease; overflow-x: hidden; -webkit-overflow-scrolling: touch; } @@ -93,7 +98,7 @@ } .dark { - color: #FFF; + color: #DDD; background-color: #000; } @@ -151,18 +156,18 @@ /* Margins for Show Original link. */ #showOriginal { - margin: auto 1.296rem 1.296rem 1.296rem; + margin: auto 1.296rem 1.296rem 5%; } #content { - margin: 0.2rem; + margin: 0.2rem 2.2%; } /* Main margins. */ body { max-width: 800px; - margin: 0px; + margin: 0px auto 0px auto; } #mainContent { @@ -202,29 +207,38 @@ /* Link colors for light, dark and sepia themes */ -a:link { +.light a:link, +.sepia a:link { color: #55F; } -a:visited { +.dark a:link { + color: #88F; +} + +.light a:visited, +.sepia a:visited { color: #902290; } +.dark a:visited { + color: #D872D8; +} + blockquote { border-left: 4px solid #eee; padding-left: 1em; } cite { - color: rgba(0, 0, 0, .54); + opacity: .54; font-style: italic; } hr { - background-color: #e4dfdf; - border: none; - height: 1px; - margin: inherit auto; + opacity: .5; + border-style: solid; + height: 1px 0 0 0; width: 75%; } @@ -235,9 +249,8 @@ } q { - color: #222; + opacity: .8; display:block; - font-size: 1.5rem; font-style: italic; font-weight: 600; line-height: 1.444; @@ -265,7 +278,7 @@ img+[class*='caption'], object+[class*='caption'], video+[class*='caption'] { - color: rgba(0,0,0,.54); + opacity: .54; display: table; font-style: italic; margin: 0 auto; @@ -314,6 +327,10 @@ padding-bottom: 120px; } +#feedbackContainer { + font-size: 14px; +} + .footerFeedback { background-color: #4285F4; clear: both; @@ -325,13 +342,14 @@ } .feedbackContent { + font-size: 14px; background-color: #4285F4; clear: both; padding: 14px; } #feedbackQuestion { - font-size: 20px; + font-size: 1.4em; font-weight: 700; text-align: center; width: 100%;
diff --git a/components/dom_distiller/core/dom_distiller_request_view_base.cc b/components/dom_distiller/core/dom_distiller_request_view_base.cc new file mode 100644 index 0000000..3488d6b --- /dev/null +++ b/components/dom_distiller/core/dom_distiller_request_view_base.cc
@@ -0,0 +1,115 @@ +// 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/dom_distiller/core/dom_distiller_request_view_base.h" + +#include <sstream> +#include <string> +#include <vector> + +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/utf_string_conversions.h" +#include "components/dom_distiller/core/distilled_page_prefs.h" +#include "components/dom_distiller/core/dom_distiller_service.h" +#include "components/dom_distiller/core/task_tracker.h" +#include "components/dom_distiller/core/url_constants.h" +#include "components/dom_distiller/core/viewer.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/url_data_source.h" +#include "net/base/url_util.h" +#include "net/url_request/url_request.h" + +namespace dom_distiller { + +DomDistillerRequestViewBase::DomDistillerRequestViewBase( + scoped_ptr<DistillerDataCallback> callback, + DistilledPagePrefs* distilled_page_prefs) + : callback_(callback.Pass()), + page_count_(0), + distilled_page_prefs_(distilled_page_prefs), + is_error_page_(false) { +} + +DomDistillerRequestViewBase::~DomDistillerRequestViewBase() { +} + +void DomDistillerRequestViewBase::FlagAsErrorPage() { + is_error_page_ = true; + std::string error_page_html = + viewer::GetErrorPageHtml(distilled_page_prefs_->GetTheme(), + distilled_page_prefs_->GetFontFamily()); + callback_->RunCallback(error_page_html); +} + +bool DomDistillerRequestViewBase::IsErrorPage() { + return is_error_page_; +} + +void DomDistillerRequestViewBase::OnArticleReady( + const DistilledArticleProto* article_proto) { + if (page_count_ == 0) { + std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( + &article_proto->pages(0), distilled_page_prefs_->GetTheme(), + distilled_page_prefs_->GetFontFamily()); + callback_->RunCallback(unsafe_page_html); + // Send first page to client. + SendJavaScript(viewer::GetUnsafeArticleContentJs(article_proto)); + // If any content was loaded, show the feedback form. + SendJavaScript(viewer::GetShowFeedbackFormJs()); + } else if (page_count_ == article_proto->pages_size()) { + // We may still be showing the "Loading" indicator. + SendJavaScript(viewer::GetToggleLoadingIndicatorJs(true)); + } else { + // It's possible that we didn't get some incremental updates from the + // distiller. Ensure all remaining pages are flushed to the viewer. + for (; page_count_ < article_proto->pages_size(); page_count_++) { + const DistilledPageProto& page = article_proto->pages(page_count_); + SendJavaScript(viewer::GetUnsafeIncrementalDistilledPageJs( + &page, page_count_ == article_proto->pages_size())); + } + } + // No need to hold on to the ViewerHandle now that distillation is complete. + viewer_handle_.reset(); +} + +void DomDistillerRequestViewBase::OnArticleUpdated( + ArticleDistillationUpdate article_update) { + for (; page_count_ < static_cast<int>(article_update.GetPagesSize()); + page_count_++) { + const DistilledPageProto& page = + article_update.GetDistilledPage(page_count_); + // Send the page content to the client. This will execute after the page is + // ready. + SendJavaScript(viewer::GetUnsafeIncrementalDistilledPageJs(&page, false)); + + if (page_count_ == 0) { + // This is the first page, so send Viewer page scaffolding too. + std::string unsafe_page_html = viewer::GetUnsafeArticleTemplateHtml( + &page, distilled_page_prefs_->GetTheme(), + distilled_page_prefs_->GetFontFamily()); + callback_->RunCallback(unsafe_page_html); + // If any content was loaded, show the feedback form. + SendJavaScript(viewer::GetShowFeedbackFormJs()); + } + } +} + +void DomDistillerRequestViewBase::OnChangeTheme( + DistilledPagePrefs::Theme new_theme) { + SendJavaScript(viewer::GetDistilledPageThemeJs(new_theme)); +} + +void DomDistillerRequestViewBase::OnChangeFontFamily( + DistilledPagePrefs::FontFamily new_font) { + SendJavaScript(viewer::GetDistilledPageFontFamilyJs(new_font)); +} + +void DomDistillerRequestViewBase::TakeViewerHandle( + scoped_ptr<ViewerHandle> viewer_handle) { + viewer_handle_ = viewer_handle.Pass(); +} + +} // namespace dom_distiller
diff --git a/components/dom_distiller/core/dom_distiller_request_view_base.h b/components/dom_distiller/core/dom_distiller_request_view_base.h new file mode 100644 index 0000000..16b8ca7d --- /dev/null +++ b/components/dom_distiller/core/dom_distiller_request_view_base.h
@@ -0,0 +1,87 @@ +// 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_DOM_DISTILLER_CORE_DOM_DISTILLER_REQUEST_VIEW_BASE_H_ +#define COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_REQUEST_VIEW_BASE_H_ + +#include <sstream> +#include <string> +#include <vector> + +#include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/utf_string_conversions.h" +#include "components/dom_distiller/core/distilled_page_prefs.h" +#include "components/dom_distiller/core/dom_distiller_service.h" +#include "components/dom_distiller/core/task_tracker.h" +#include "components/dom_distiller/core/viewer.h" +#include "content/public/browser/url_data_source.h" +#include "net/base/url_util.h" + +namespace dom_distiller { + +// This interface is used to abstract the data callback from the distiller. The +// callbacks for different platforms have different numbers of parameters +// (namely iOS and Android) which makes this necessary. +class DistillerDataCallback { + public: + virtual ~DistillerDataCallback(){}; + virtual void RunCallback(std::string& data) = 0; +}; + +// Handles receiving data asynchronously for a specific entry, and passing +// it along to the data callback for the data source. Lifetime matches that of +// the current main frame's page in the Viewer instance. +class DomDistillerRequestViewBase + : public ViewRequestDelegate, + public DistilledPagePrefs::Observer { + public: + explicit DomDistillerRequestViewBase( + scoped_ptr<DistillerDataCallback> callback, + DistilledPagePrefs* distilled_page_prefs); + ~DomDistillerRequestViewBase() override; + + // Flag this request as an error and send the error page template. + void FlagAsErrorPage(); + // Get if this viewer is in an error state. + bool IsErrorPage(); + + // ViewRequestDelegate implementation: + void OnArticleReady(const DistilledArticleProto* article_proto) override; + + void OnArticleUpdated(ArticleDistillationUpdate article_update) override; + + void TakeViewerHandle(scoped_ptr<ViewerHandle> viewer_handle); + + protected: + // DistilledPagePrefs::Observer implementation: + void OnChangeFontFamily( + DistilledPagePrefs::FontFamily new_font_family) override; + void OnChangeTheme(DistilledPagePrefs::Theme new_theme) override; + + // Sends JavaScript to the attached Viewer, buffering data if the viewer isn't + // ready. + virtual void SendJavaScript(const std::string& buffer) = 0; + + // The handle to the view request towards the DomDistillerService. It + // needs to be kept around to ensure the distillation request finishes. + scoped_ptr<ViewerHandle> viewer_handle_; + + // Holds the callback to where the data retrieved is sent back. + scoped_ptr<DistillerDataCallback> callback_; + + // Number of pages of the distilled article content that have been rendered by + // the viewer. + int page_count_; + + // Interface for accessing preferences for distilled pages. + DistilledPagePrefs* distilled_page_prefs_; + + // Flag to tell this observer that the web contents are in an error state. + bool is_error_page_; +}; + +} // namespace dom_distiller + +#endif // COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_REQUEST_VIEW_BASE_H_
diff --git a/components/dom_distiller/core/javascript/dom_distiller_viewer.js b/components/dom_distiller/core/javascript/dom_distiller_viewer.js index 78b67499..4122dc7c 100644 --- a/components/dom_distiller/core/javascript/dom_distiller_viewer.js +++ b/components/dom_distiller/core/javascript/dom_distiller_viewer.js
@@ -163,3 +163,209 @@ contentWrap.style.paddingBottom = '0px'; }, true); +document.getElementById('contentWrap').addEventListener('transitionend', + function(e) { + var contentWrap = document.getElementById('contentWrap'); + contentWrap.style.transition = ''; + }, true); + +var pincher = (function() { + 'use strict'; + // When users pinch in Reader Mode, the page would zoom in or out as if it + // is a normal web page allowing user-zoom. At the end of pinch gesture, the + // page would do text reflow. These pinch-to-zoom and text reflow effects + // are not native, but are emulated using CSS and JavaScript. + // + // In order to achieve near-native zooming and panning frame rate, fake 3D + // transform is used so that the layer doesn't repaint for each frame. + // + // After the text reflow, the web content shown in the viewport should + // roughly be the same paragraph before zooming. + // + // The control point of font size is the html element, so that both "em" and + // "rem" are adjusted. + // + // TODO(wychen): Improve scroll position when elementFromPoint is body. + + var pinching = false; + var fontSizeAnchor = 1.0; + + var focusElement = null; + var focusPos = 0; + var initClientMid; + + var clampedScale = 1; + + var lastSpan; + var lastClientMid; + + var scale = 1; + var shiftX; + var shiftY; + + // The zooming speed relative to pinching speed. + const FONT_SCALE_MULTIPLIER = 0.5; + const MIN_SPAN_LENGTH = 20; + + // The font size is guaranteed to be in px. + var baseSize = + parseFloat(getComputedStyle(document.documentElement).fontSize); + + var refreshTransform = function() { + var slowedScale = Math.exp(Math.log(scale) * FONT_SCALE_MULTIPLIER); + clampedScale = Math.max(0.4, Math.min(2.5, fontSizeAnchor * slowedScale)); + + // Use "fake" 3D transform so that the layer is not repainted. + // With 2D transform, the frame rate would be much lower. + document.body.style.transform = + 'translate3d(' + shiftX + 'px,' + + shiftY + 'px, 0px)' + + 'scale(' + clampedScale/fontSizeAnchor + ')'; + }; + + function endPinch() { + pinching = false; + + document.body.style.transformOrigin = ''; + document.body.style.transform = ''; + document.documentElement.style.fontSize = clampedScale * baseSize + "px"; + + var rect = focusElement.getBoundingClientRect(); + var targetTop = focusPos * (rect.bottom - rect.top) + rect.top + + document.body.scrollTop - (initClientMid.y + shiftY); + document.body.scrollTop = targetTop; + } + + function touchSpan(e) { + var count = e.touches.length; + var mid = touchClientMid(e); + var sum = 0; + for (var i = 0; i < count; i++) { + var dx = (e.touches[i].clientX - mid.x); + var dy = (e.touches[i].clientY - mid.y); + sum += Math.hypot(dx, dy); + } + // Avoid very small span. + return Math.max(MIN_SPAN_LENGTH, sum/count); + } + + function touchClientMid(e) { + var count = e.touches.length; + var sumX = 0; + var sumY = 0; + for (var i = 0; i < count; i++) { + sumX += e.touches[i].clientX; + sumY += e.touches[i].clientY; + } + return {x: sumX/count, y: sumY/count}; + } + + function touchPageMid(e) { + var clientMid = touchClientMid(e); + return {x: clientMid.x - e.touches[0].clientX + e.touches[0].pageX, + y: clientMid.y - e.touches[0].clientY + e.touches[0].pageY}; + } + + return { + handleTouchStart: function(e) { + if (e.touches.length < 2) return; + e.preventDefault(); + + var span = touchSpan(e); + var clientMid = touchClientMid(e); + + if (e.touches.length > 2) { + lastSpan = span; + lastClientMid = clientMid; + refreshTransform(); + return; + } + + scale = 1; + shiftX = 0; + shiftY = 0; + + pinching = true; + fontSizeAnchor = + parseFloat(getComputedStyle(document.documentElement).fontSize) / + baseSize; + + var pinchOrigin = touchPageMid(e); + document.body.style.transformOrigin = + pinchOrigin.x + 'px ' + pinchOrigin.y + 'px'; + + // Try to preserve the pinching center after text reflow. + // This is accurate to the HTML element level. + focusElement = document.elementFromPoint(clientMid.x, clientMid.y); + var rect = focusElement.getBoundingClientRect(); + initClientMid = clientMid; + focusPos = (initClientMid.y - rect.top) / (rect.bottom - rect.top); + + lastSpan = span; + lastClientMid = clientMid; + + refreshTransform(); + }, + + handleTouchMove: function(e) { + if (!pinching) return; + if (e.touches.length < 2) return; + e.preventDefault(); + + var span = touchSpan(e); + var clientMid = touchClientMid(e); + + scale *= touchSpan(e) / lastSpan; + shiftX += clientMid.x - lastClientMid.x; + shiftY += clientMid.y - lastClientMid.y; + + refreshTransform(); + + lastSpan = span; + lastClientMid = clientMid; + }, + + handleTouchEnd: function(e) { + if (!pinching) return; + e.preventDefault(); + + var span = touchSpan(e); + var clientMid = touchClientMid(e); + + if (e.touches.length >= 2) { + lastSpan = span; + lastClientMid = clientMid; + refreshTransform(); + return; + } + + endPinch(); + }, + + handleTouchCancel: function(e) { + endPinch(); + }, + + reset: function() { + scale = 1; + shiftX = 0; + shiftY = 0; + clampedScale = 1; + document.documentElement.style.fontSize = clampedScale * baseSize + "px"; + }, + + status: function() { + return { + scale: scale, + clampedScale: clampedScale, + shiftX: shiftX, + shiftY: shiftY + }; + } + }; +}()); + +window.addEventListener('touchstart', pincher.handleTouchStart, false); +window.addEventListener('touchmove', pincher.handleTouchMove, false); +window.addEventListener('touchend', pincher.handleTouchEnd, false); +window.addEventListener('touchcancel', pincher.handleTouchCancel, false);
diff --git a/components/domain_reliability/beacon.cc b/components/domain_reliability/beacon.cc index 0d7abf7..2a85c53 100644 --- a/components/domain_reliability/beacon.cc +++ b/components/domain_reliability/beacon.cc
@@ -33,6 +33,7 @@ beacon_value->Set("failure_data", failure_value); } beacon_value->SetString("server_ip", server_ip); + beacon_value->SetBoolean("was_proxied", was_proxied); beacon_value->SetString("protocol", protocol); if (http_response_code >= 0) beacon_value->SetInteger("http_response_code", http_response_code);
diff --git a/components/domain_reliability/beacon.h b/components/domain_reliability/beacon.h index cb5ed8c5..aba7bf95 100644 --- a/components/domain_reliability/beacon.h +++ b/components/domain_reliability/beacon.h
@@ -39,6 +39,9 @@ int chrome_error; // IP address of the server the request went to. std::string server_ip; + // Whether the request went through a proxy. If true, |server_ip| will be + // empty. + bool was_proxied; // Protocol used to make the request. std::string protocol; // HTTP response code returned by the server, or -1 if none was received.
diff --git a/components/domain_reliability/context_unittest.cc b/components/domain_reliability/context_unittest.cc index 8633c48..8025021 100644 --- a/components/domain_reliability/context_unittest.cc +++ b/components/domain_reliability/context_unittest.cc
@@ -30,6 +30,7 @@ beacon.status = "ok"; beacon.chrome_error = net::OK; beacon.server_ip = "127.0.0.1"; + beacon.was_proxied = false; beacon.protocol = "HTTP"; beacon.http_response_code = 200; beacon.elapsed = base::TimeDelta::FromMilliseconds(250); @@ -179,7 +180,8 @@ "\"http_response_code\":200,\"network_changed\":false," "\"protocol\":\"HTTP\",\"request_age_ms\":300250," "\"request_elapsed_ms\":250,\"resource\":\"always_report\"," - "\"server_ip\":\"127.0.0.1\",\"status\":\"ok\"}]," + "\"server_ip\":\"127.0.0.1\",\"status\":\"ok\"," + "\"was_proxied\":false}]," "\"reporter\":\"test-reporter\"," "\"resources\":[{\"failed_requests\":0,\"name\":\"always_report\"," "\"successful_requests\":1}]}"; @@ -216,7 +218,8 @@ "\"http_response_code\":200,\"network_changed\":true," "\"protocol\":\"HTTP\",\"request_age_ms\":300250," "\"request_elapsed_ms\":250,\"resource\":\"always_report\"," - "\"server_ip\":\"127.0.0.1\",\"status\":\"ok\"}]," + "\"server_ip\":\"127.0.0.1\",\"status\":\"ok\"," + "\"was_proxied\":false}]," "\"reporter\":\"test-reporter\"," "\"resources\":[{\"failed_requests\":0,\"name\":\"always_report\"," "\"successful_requests\":1}]}";
diff --git a/components/domain_reliability/monitor.cc b/components/domain_reliability/monitor.cc index bd86ad9..83a6af19 100644 --- a/components/domain_reliability/monitor.cc +++ b/components/domain_reliability/monitor.cc
@@ -280,6 +280,7 @@ beacon.http_response_code = response_code; beacon.start_time = request.load_timing_info.request_start; beacon.elapsed = time_->NowTicks() - beacon.start_time; + beacon.was_proxied = request.response_info.was_fetched_via_proxy; beacon.domain = request.url.host(); context_manager_.RouteBeacon(request.url, beacon); }
diff --git a/components/enhanced_bookmarks/bookmark_server_cluster_service.cc b/components/enhanced_bookmarks/bookmark_server_cluster_service.cc index e433717..b0e0dcd 100644 --- a/components/enhanced_bookmarks/bookmark_server_cluster_service.cc +++ b/components/enhanced_bookmarks/bookmark_server_cluster_service.cc
@@ -112,9 +112,7 @@ // static void BookmarkServerClusterService::RegisterPrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - prefs::kBookmarkClusters, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(prefs::kBookmarkClusters); } scoped_ptr<net::URLFetcher> BookmarkServerClusterService::CreateFetcher() {
diff --git a/components/favicon/core/large_icon_service.cc b/components/favicon/core/large_icon_service.cc index 702761c8..9aeb8e89 100644 --- a/components/favicon/core/large_icon_service.cc +++ b/components/favicon/core/large_icon_service.cc
@@ -45,9 +45,9 @@ const favicon_base::FaviconRawBitmapResult& bitmap_result) { // If there are no bitmaps, return a result with an empty |bitmap| and a // default |fallback_icon_style|. - favicon_base::LargeIconResult result; if (!bitmap_result.is_valid()) { - callback.Run(result); + callback.Run( + favicon_base::LargeIconResult(new favicon_base::FallbackIconStyle())); return; } @@ -59,7 +59,7 @@ bitmap_result.pixel_size.width() != bitmap_result.pixel_size.height()) { // TODO(beaudoin): Resize the icon if it's large enough. Alternatively, // return it and let the HTML resize it. - result.fallback_icon_style.reset(new favicon_base::FallbackIconStyle()); + favicon_base::LargeIconResult result(new favicon_base::FallbackIconStyle()); favicon_base::SetDominantColorAsBackground( bitmap_result.bitmap_data, result.fallback_icon_style.get()); callback.Run(result); @@ -70,8 +70,7 @@ // it. // TODO(beaudoin): Resize the icon if it's too large. Alternatively, return // it and let the HTML resize it. - result.bitmap = bitmap_result; - callback.Run(result); + callback.Run(favicon_base::LargeIconResult(bitmap_result)); } } // namespace favicon
diff --git a/components/favicon_base/favicon_types.cc b/components/favicon_base/favicon_types.cc index e69f1d7be..2ed5eb0 100644 --- a/components/favicon_base/favicon_types.cc +++ b/components/favicon_base/favicon_types.cc
@@ -27,7 +27,11 @@ // -------------------------------------------------------- // LargeIconResult -LargeIconResult::LargeIconResult() {} +LargeIconResult::LargeIconResult(const FaviconRawBitmapResult& bitmap_in) + : bitmap(bitmap_in) {} + +LargeIconResult::LargeIconResult(FallbackIconStyle* fallback_icon_style_in) + : fallback_icon_style(fallback_icon_style_in) {} LargeIconResult::~LargeIconResult() {}
diff --git a/components/favicon_base/favicon_types.h b/components/favicon_base/favicon_types.h index f7c812ab..469d0fa 100644 --- a/components/favicon_base/favicon_types.h +++ b/components/favicon_base/favicon_types.h
@@ -79,7 +79,11 @@ // either the bitmap data if the favicon database has a sufficiently large // favicon bitmap and the style of the fallback icon otherwise. struct LargeIconResult { - LargeIconResult(); + explicit LargeIconResult(const FaviconRawBitmapResult& bitmap_in); + + // Takes ownership of |fallback_icon_style_in|. + explicit LargeIconResult(FallbackIconStyle* fallback_icon_style_in); + ~LargeIconResult(); // The bitmap from the favicon database if the database has a sufficiently
diff --git a/components/gcm_driver/gcm_channel_status_syncer.cc b/components/gcm_driver/gcm_channel_status_syncer.cc index 852922d..4e29222 100644 --- a/components/gcm_driver/gcm_channel_status_syncer.cc +++ b/components/gcm_driver/gcm_channel_status_syncer.cc
@@ -68,18 +68,11 @@ // static void GCMChannelStatusSyncer::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kGCMChannelStatus, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kGCMChannelStatus, true); registry->RegisterIntegerPref( prefs::kGCMChannelPollIntervalSeconds, - GCMChannelStatusRequest::default_poll_interval_seconds(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kGCMChannelLastCheckTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + GCMChannelStatusRequest::default_poll_interval_seconds()); + registry->RegisterInt64Pref(prefs::kGCMChannelLastCheckTime, 0); } // static
diff --git a/components/gles2/BUILD.gn b/components/gles2/BUILD.gn index 002d3e7..3046782 100644 --- a/components/gles2/BUILD.gn +++ b/components/gles2/BUILD.gn
@@ -7,7 +7,7 @@ source_set("gles2") { visibility = [ "//components/native_viewport:*", - "//mojo/shell:lib", # For android + "//mojo/runner:lib", # For android ] sources = [ @@ -26,11 +26,11 @@ ] deps = [ "//base", + "//components/gpu/public/interfaces", "//gpu/command_buffer/service", "//mojo/converters/geometry", "//third_party/mojo/src/mojo/public/cpp/bindings", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/gpu/public/interfaces", + "//ui/mojo/geometry:interfaces", "//ui/gfx", "//ui/gfx/geometry", "//ui/gl", @@ -49,10 +49,10 @@ deps = [ "//base", + "//components/gpu/public/interfaces", "//gpu/command_buffer/common", "//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/public/cpp/system", - "//third_party/mojo_services/src/gpu/public/interfaces", ] include_dirs = [ "../.." ]
diff --git a/components/gles2/DEPS b/components/gles2/DEPS index 916b0dc3..3a90be0d 100644 --- a/components/gles2/DEPS +++ b/components/gles2/DEPS
@@ -1,8 +1,7 @@ include_rules = [ + "+components/gpu", "+gpu", "+mojo/converters", "+third_party/mojo/src/mojo/public", - "+third_party/mojo_services/src/geometry", - "+third_party/mojo_services/src/gpu", "+ui", ]
diff --git a/components/gles2/OWNERS b/components/gles2/OWNERS new file mode 100644 index 0000000..e6a7642f --- /dev/null +++ b/components/gles2/OWNERS
@@ -0,0 +1,4 @@ +ben@chromium.org +erg@chromium.org +msw@chromium.org +sky@chromium.org
diff --git a/components/gles2/command_buffer_driver.h b/components/gles2/command_buffer_driver.h index d5627f8..675fa41 100644 --- a/components/gles2/command_buffer_driver.h +++ b/components/gles2/command_buffer_driver.h
@@ -10,7 +10,7 @@ #include "base/memory/scoped_ptr.h" #include "base/single_thread_task_runner.h" #include "base/timer/timer.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom.h" +#include "components/gpu/public/interfaces/command_buffer.mojom.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h"
diff --git a/components/gles2/command_buffer_impl.h b/components/gles2/command_buffer_impl.h index 8d8c9e9..b0ec223 100644 --- a/components/gles2/command_buffer_impl.h +++ b/components/gles2/command_buffer_impl.h
@@ -8,9 +8,9 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" +#include "components/gpu/public/interfaces/command_buffer.mojom.h" +#include "components/gpu/public/interfaces/viewport_parameter_listener.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/viewport_parameter_listener.mojom.h" namespace gpu { class SyncPointManager;
diff --git a/components/gles2/command_buffer_type_conversions.cc b/components/gles2/command_buffer_type_conversions.cc index 35de081..bd52b8d0 100644 --- a/components/gles2/command_buffer_type_conversions.cc +++ b/components/gles2/command_buffer_type_conversions.cc
@@ -4,7 +4,7 @@ #include "components/gles2/command_buffer_type_conversions.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom.h" +#include "components/gpu/public/interfaces/command_buffer.mojom.h" namespace mojo {
diff --git a/components/gles2/command_buffer_type_conversions.h b/components/gles2/command_buffer_type_conversions.h index 1ac166f..e40d460342 100644 --- a/components/gles2/command_buffer_type_conversions.h +++ b/components/gles2/command_buffer_type_conversions.h
@@ -5,10 +5,10 @@ #ifndef COMPONENTS_GLES2_COMMAND_BUFFER_TYPE_CONVERSIONS_H_ #define COMPONENTS_GLES2_COMMAND_BUFFER_TYPE_CONVERSIONS_H_ +#include "components/gpu/public/interfaces/command_buffer.mojom.h" #include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/common/command_buffer.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/type_converter.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom.h" namespace mojo {
diff --git a/components/gles2/gpu_impl.h b/components/gles2/gpu_impl.h index c2700768..737d118f 100644 --- a/components/gles2/gpu_impl.h +++ b/components/gles2/gpu_impl.h
@@ -9,11 +9,11 @@ #include "base/memory/ref_counted.h" #include "base/threading/thread.h" #include "components/gles2/gpu_state.h" +#include "components/gpu/public/interfaces/command_buffer.mojom.h" +#include "components/gpu/public/interfaces/gpu.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/mojo_services/src/geometry/public/interfaces/geometry.mojom.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/gpu.mojom.h" +#include "ui/mojo/geometry/geometry.mojom.h" namespace gfx { class GLShareGroup;
diff --git a/components/gpu/OWNERS b/components/gpu/OWNERS new file mode 100644 index 0000000..e6a7642f --- /dev/null +++ b/components/gpu/OWNERS
@@ -0,0 +1,4 @@ +ben@chromium.org +erg@chromium.org +msw@chromium.org +sky@chromium.org
diff --git a/components/gpu/public/interfaces/BUILD.gn b/components/gpu/public/interfaces/BUILD.gn new file mode 100644 index 0000000..151272b --- /dev/null +++ b/components/gpu/public/interfaces/BUILD.gn
@@ -0,0 +1,20 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "command_buffer.mojom", + "context_provider.mojom", + "gpu.mojom", + "gpu_capabilities.mojom", + "viewport_parameter_listener.mojom", + ] + + deps = [ + "//ui/mojo/geometry:interfaces", + ] +}
diff --git a/components/gpu/public/interfaces/command_buffer.mojom b/components/gpu/public/interfaces/command_buffer.mojom new file mode 100644 index 0000000..d1bfe34 --- /dev/null +++ b/components/gpu/public/interfaces/command_buffer.mojom
@@ -0,0 +1,55 @@ +// 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 mojo; + +import "components/gpu/public/interfaces/gpu_capabilities.mojom"; + +struct CommandBufferState { + int32 num_entries; + int32 get_offset; + int32 put_offset; + int32 token; + int32 error; // TODO(piman): enum + int32 context_lost_reason; // TODO(piman): enum + uint32 generation; +}; + +interface CommandBufferSyncClient { + DidInitialize(bool success, GpuCapabilities capabilities); + DidMakeProgress(CommandBufferState state); +}; + +interface CommandBufferSyncPointClient { + DidInsertSyncPoint(uint32 sync_point); +}; + +interface CommandBufferLostContextObserver { + DidLoseContext(int32 context_lost_reason); +}; + +interface CommandBuffer { + // Initialize attempts to initialize the command buffer. Success or failure + // will be communicated via the CommandBufferSyncClient DidInitialize() call. + // If the context is lost after creation the LostContext method on the + // CommandBufferLostContextObserver's will be called then this pipe will be + // closed. + Initialize(CommandBufferSyncClient sync_client, + CommandBufferSyncPointClient sync_point_client, + CommandBufferLostContextObserver lost_observer, + handle<shared_buffer> shared_state); + SetGetBuffer(int32 buffer); + Flush(int32 put_offset); + MakeProgress(int32 last_get_offset); + RegisterTransferBuffer( + int32 id, handle<shared_buffer> transfer_buffer, uint32 size); + DestroyTransferBuffer(int32 id); + + // InsertSyncPoint returns the sync point returned via DidInsertSyncPoint. + // If |retire| is true, the sync point is retired on insertion. Otherwise, + // explicitly call RetireSyncPoint to retire it. + InsertSyncPoint(bool retire); + RetireSyncPoint(uint32 sync_point); + Echo() => (); +};
diff --git a/components/gpu/public/interfaces/context_provider.mojom b/components/gpu/public/interfaces/context_provider.mojom new file mode 100644 index 0000000..e51c92a --- /dev/null +++ b/components/gpu/public/interfaces/context_provider.mojom
@@ -0,0 +1,28 @@ +// 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 mojo; + +import "components/gpu/public/interfaces/command_buffer.mojom"; +import "components/gpu/public/interfaces/viewport_parameter_listener.mojom"; + +// A ContextProvider can be used to provide new command buffers related to a +// particular context, for instance configured to draw to a particular display. +interface ContextProvider { + // This initializes a new command buffer for this provider when available, + // closing connections to the previously created command buffer (if any). + // + // This call may not return for an extended period of time if a command + // buffer cannot be produced immediately, for example if it is associated + // with a view that is offscreen. + // + // If a viewport_parameter_listener is provided it will notified be when + // vsync parameters change for this context. + // + // The returned handle will be null if no command buffer can be created for + // this request, for example if another request is made on the same provider + // before a previous call returns. + Create(ViewportParameterListener? viewport_parameter_listener) + => (CommandBuffer? gles2_client); +};
diff --git a/components/gpu/public/interfaces/gpu.mojom b/components/gpu/public/interfaces/gpu.mojom new file mode 100644 index 0000000..b0f18ea --- /dev/null +++ b/components/gpu/public/interfaces/gpu.mojom
@@ -0,0 +1,12 @@ +// 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 mojo; + +import "components/gpu/public/interfaces/command_buffer.mojom"; + +interface Gpu { + // Creates a new offscreen OpenGL ES 2.0 context. + CreateOffscreenGLES2Context(CommandBuffer& gles2_client); +};
diff --git a/third_party/mojo_services/src/gpu/public/interfaces/gpu_capabilities.mojom b/components/gpu/public/interfaces/gpu_capabilities.mojom similarity index 100% rename from third_party/mojo_services/src/gpu/public/interfaces/gpu_capabilities.mojom rename to components/gpu/public/interfaces/gpu_capabilities.mojom
diff --git a/third_party/mojo_services/src/gpu/public/interfaces/viewport_parameter_listener.mojom b/components/gpu/public/interfaces/viewport_parameter_listener.mojom similarity index 100% rename from third_party/mojo_services/src/gpu/public/interfaces/viewport_parameter_listener.mojom rename to components/gpu/public/interfaces/viewport_parameter_listener.mojom
diff --git a/components/history.gypi b/components/history.gypi index 7bf0dd0..6b21304 100644 --- a/components/history.gypi +++ b/components/history.gypi
@@ -13,6 +13,8 @@ ], 'dependencies': [ '../base/base.gyp:base', + '../base/base.gyp:base_i18n', + '../base/base.gyp:base_prefs', '../google_apis/google_apis.gyp:google_apis', '../net/net.gyp:net', '../skia/skia.gyp:skia', @@ -23,6 +25,7 @@ '../ui/gfx/gfx.gyp:gfx', '../url/url.gyp:url_lib', 'favicon_base', + 'history_core_common', 'keyed_service_core', 'query_parser', 'signin_core_browser', @@ -80,6 +83,8 @@ 'history/core/browser/top_sites_cache.h', 'history/core/browser/top_sites_database.cc', 'history/core/browser/top_sites_database.h', + 'history/core/browser/top_sites_impl.cc', + 'history/core/browser/top_sites_impl.h', 'history/core/browser/top_sites_observer.h', 'history/core/browser/typed_url_syncable_service.cc', 'history/core/browser/typed_url_syncable_service.h', @@ -182,6 +187,7 @@ 'dependencies': [ '../base/base.gyp:base', '../content/content.gyp:content_browser', + '../url/url.gyp:url_lib', 'history_core_browser', 'visitedlink_browser', ], @@ -194,9 +200,34 @@ 'history/content/browser/history_context_helper.h', 'history/content/browser/history_database_helper.cc', 'history/content/browser/history_database_helper.h', + 'history/content/browser/web_contents_top_sites_observer.cc', + 'history/content/browser/web_contents_top_sites_observer.h', ], } ], }], + ['OS=="ios"', { + 'targets': [ + { + 'target_name': 'history_ios_browser', + 'type': 'static_library', + 'include_dirs': [ + '..', + ], + 'dependencies': [ + '../base/base.gyp:base', + '../ios/web/ios_web.gyp:ios_web', + '../url/url.gyp:url_lib', + 'history_core_browser', + ], + 'sources': [ + 'history/ios/browser/history_database_helper.cc', + 'history/ios/browser/history_database_helper.h', + 'history/ios/browser/web_state_top_sites_observer.cc', + 'history/ios/browser/web_state_top_sites_observer.h', + ], + }, + ], + }], ], }
diff --git a/components/history/content/browser/BUILD.gn b/components/history/content/browser/BUILD.gn index 22f91b5..ba7d7c4 100644 --- a/components/history/content/browser/BUILD.gn +++ b/components/history/content/browser/BUILD.gn
@@ -12,6 +12,8 @@ "history_context_helper.h", "history_database_helper.cc", "history_database_helper.h", + "web_contents_top_sites_observer.cc", + "web_contents_top_sites_observer.h", ] deps = [ @@ -19,5 +21,6 @@ "//components/history/core/browser", "//components/visitedlink/browser", "//content/public/browser", + "//url:url", ] }
diff --git a/components/history/content/browser/web_contents_top_sites_observer.cc b/components/history/content/browser/web_contents_top_sites_observer.cc new file mode 100644 index 0000000..83ab57e --- /dev/null +++ b/components/history/content/browser/web_contents_top_sites_observer.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/history/content/browser/web_contents_top_sites_observer.h" + +#include "base/logging.h" +#include "components/history/core/browser/top_sites.h" +#include "content/public/browser/navigation_details.h" +#include "content/public/browser/navigation_entry.h" + +DEFINE_WEB_CONTENTS_USER_DATA_KEY(history::WebContentsTopSitesObserver); + +namespace history { + +// static +void WebContentsTopSitesObserver::CreateForWebContents( + content::WebContents* web_contents, + TopSites* top_sites) { + DCHECK(web_contents); + if (!FromWebContents(web_contents)) { + web_contents->SetUserData(UserDataKey(), new WebContentsTopSitesObserver( + web_contents, top_sites)); + } +} + +WebContentsTopSitesObserver::WebContentsTopSitesObserver( + content::WebContents* web_contents, + TopSites* top_sites) + : content::WebContentsObserver(web_contents), top_sites_(top_sites) { +} + +WebContentsTopSitesObserver::~WebContentsTopSitesObserver() { +} + +void WebContentsTopSitesObserver::NavigationEntryCommitted( + const content::LoadCommittedDetails& load_details) { + DCHECK(load_details.entry); + if (top_sites_) + top_sites_->OnNavigationCommitted(load_details.entry->GetURL()); +} + +} // namespace history
diff --git a/components/history/content/browser/web_contents_top_sites_observer.h b/components/history/content/browser/web_contents_top_sites_observer.h new file mode 100644 index 0000000..da7ecc56 --- /dev/null +++ b/components/history/content/browser/web_contents_top_sites_observer.h
@@ -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. + +#ifndef COMPONENTS_HISTORY_CONTENT_BROWSER_WEB_CONTENTS_TOP_SITES_OBSERVER_H_ +#define COMPONENTS_HISTORY_CONTENT_BROWSER_WEB_CONTENTS_TOP_SITES_OBSERVER_H_ + +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents_user_data.h" + +namespace history { + +class TopSites; + +// WebContentsTopSitesObserver forwards navigation events from +// content::WebContents to TopSites. +class WebContentsTopSitesObserver + : public content::WebContentsObserver, + public content::WebContentsUserData<WebContentsTopSitesObserver> { + public: + static void CreateForWebContents(content::WebContents* web_contents, + TopSites* top_sites); + + private: + friend class content::WebContentsUserData<WebContentsTopSitesObserver>; + + WebContentsTopSitesObserver(content::WebContents* web_contents, + TopSites* top_sites); + ~WebContentsTopSitesObserver() override; + + // content::WebContentsObserver implementation. + void NavigationEntryCommitted( + const content::LoadCommittedDetails& load_details) override; + + // Underlying TopSites instance, may be null during testing. + TopSites* top_sites_; + + DISALLOW_COPY_AND_ASSIGN(WebContentsTopSitesObserver); +}; + +} // namespace history + +#endif // COMPONENTS_HISTORY_CONTENT_BROWSER_WEB_CONTENTS_TOP_SITES_OBSERVER_H_
diff --git a/components/history/core/browser/BUILD.gn b/components/history/core/browser/BUILD.gn index b2ed448b..d0f5008a 100644 --- a/components/history/core/browser/BUILD.gn +++ b/components/history/core/browser/BUILD.gn
@@ -55,6 +55,8 @@ "top_sites_cache.h", "top_sites_database.cc", "top_sites_database.h", + "top_sites_impl.cc", + "top_sites_impl.h", "top_sites_observer.h", "typed_url_syncable_service.cc", "typed_url_syncable_service.h", @@ -80,7 +82,10 @@ deps = [ "//base", + "//base:i18n", + "//base:prefs", "//components/favicon_base", + "//components/history/core/common", "//components/keyed_service/core", "//components/query_parser", "//components/signin/core/browser",
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index 5f2bd55..faf00c6 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -1607,8 +1607,12 @@ bitmap_id_sizes[i].bitmap_id, base::Time::Now()); bitmap_identical = true; } else { + // Expire the favicon bitmap because sync can provide incorrect + // |bitmap_data|. See crbug.com/474421 for more details. Expiring the + // favicon bitmap causes it to be redownloaded the next time that the + // user visits any page which uses |icon_url|. thumbnail_db_->SetFaviconBitmap(bitmap_id_sizes[i].bitmap_id, - bitmap_data, base::Time::Now()); + bitmap_data, base::Time()); replaced_bitmap = true; } break;
diff --git a/components/history/core/browser/thumbnail_database.cc b/components/history/core/browser/thumbnail_database.cc index e1579f9a..7fc68d4 100644 --- a/components/history/core/browser/thumbnail_database.cc +++ b/components/history/core/browser/thumbnail_database.cc
@@ -1143,13 +1143,19 @@ "ON (old.id = mapping.old_icon_id)"; const char kDropOldFaviconsTable[] = "DROP TABLE old_favicons"; + // Set the retained favicon bitmaps to be expired (last_updated == 0). + // The user may be deleting their favicon bitmaps because the favicon bitmaps + // are incorrect. Expiring a favicon bitmap causes it to be redownloaded when + // the user visits a page associated with the favicon bitmap. See + // crbug.com/474421 for an example of a bug which caused favicon bitmaps to + // become incorrect. const char kRenameFaviconBitmapsTable[] = "ALTER TABLE favicon_bitmaps RENAME TO old_favicon_bitmaps"; const char kCopyFaviconBitmaps[] = "INSERT INTO favicon_bitmaps " " (icon_id, last_updated, image_data, width, height, last_requested) " - "SELECT mapping.new_icon_id, old.last_updated, " - " old.image_data, old.width, old.height, old.last_requested " + "SELECT mapping.new_icon_id, 0, old.image_data, old.width, old.height," + " old.last_requested " "FROM old_favicon_bitmaps AS old " "JOIN temp.icon_id_mapping AS mapping " "ON (old.icon_id = mapping.old_icon_id)";
diff --git a/components/history/core/browser/thumbnail_database.h b/components/history/core/browser/thumbnail_database.h index e75b495..4253cb25 100644 --- a/components/history/core/browser/thumbnail_database.h +++ b/components/history/core/browser/thumbnail_database.h
@@ -232,6 +232,8 @@ private: FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, RetainDataForPageUrls); + FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, + RetainDataForPageUrlsExpiresRetainedFavicons); FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version3); FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version4); FRIEND_TEST_ALL_PREFIXES(ThumbnailDatabaseTest, Version5);
diff --git a/components/history/core/browser/top_sites.h b/components/history/core/browser/top_sites.h index 132a45c..03626f4 100644 --- a/components/history/core/browser/top_sites.h +++ b/components/history/core/browser/top_sites.h
@@ -167,6 +167,9 @@ // called from the UI thread. virtual bool AddForcedURL(const GURL& url, const base::Time& time) = 0; + // Called when user has navigated to |url|. + virtual void OnNavigationCommitted(const GURL& url) = 0; + // Add Observer to the list. void AddObserver(TopSitesObserver* observer); @@ -179,8 +182,11 @@ ~TopSites() override; private: - ObserverList<TopSitesObserver, true> observer_list_; friend class base::RefCountedThreadSafe<TopSites>; + + ObserverList<TopSitesObserver, true> observer_list_; + + DISALLOW_COPY_AND_ASSIGN(TopSites); }; } // namespace history
diff --git a/components/history/core/browser/top_sites_impl.cc b/components/history/core/browser/top_sites_impl.cc new file mode 100644 index 0000000..c5b18735 --- /dev/null +++ b/components/history/core/browser/top_sites_impl.cc
@@ -0,0 +1,914 @@ +// Copyright (c) 2013 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/history/core/browser/top_sites_impl.h" + +#include <algorithm> +#include <set> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/logging.h" +#include "base/md5.h" +#include "base/memory/ref_counted_memory.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/metrics/histogram.h" +#include "base/prefs/pref_service.h" +#include "base/prefs/scoped_user_pref_update.h" +#include "base/single_thread_task_runner.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "base/task_runner.h" +#include "base/values.h" +#include "components/history/core/browser/history_backend.h" +#include "components/history/core/browser/history_db_task.h" +#include "components/history/core/browser/page_usage_data.h" +#include "components/history/core/browser/top_sites_cache.h" +#include "components/history/core/browser/url_utils.h" +#include "components/history/core/common/thumbnail_score.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/layout.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/image/image_util.h" + +using base::DictionaryValue; + +namespace history { +namespace { + +void RunOrPostGetMostVisitedURLsCallback( + base::TaskRunner* task_runner, + bool include_forced_urls, + const TopSitesImpl::GetMostVisitedURLsCallback& callback, + const MostVisitedURLList& all_urls, + const MostVisitedURLList& nonforced_urls) { + const MostVisitedURLList* urls = + include_forced_urls ? &all_urls : &nonforced_urls; + if (task_runner->RunsTasksOnCurrentThread()) + callback.Run(*urls); + else + task_runner->PostTask(FROM_HERE, base::Bind(callback, *urls)); +} + +// Compares two MostVisitedURL having a non-null |last_forced_time|. +bool ForcedURLComparator(const MostVisitedURL& first, + const MostVisitedURL& second) { + DCHECK(!first.last_forced_time.is_null() && + !second.last_forced_time.is_null()); + return first.last_forced_time < second.last_forced_time; +} + +// How many non-forced top sites to store in the cache. +const size_t kNonForcedTopSitesNumber = 20; + +// How many forced top sites to store in the cache. +const size_t kForcedTopSitesNumber = 20; + +// Max number of temporary images we'll cache. See comment above +// temp_images_ for details. +const size_t kMaxTempTopImages = 8; + +const int kDaysOfHistory = 90; +// Time from startup to first HistoryService query. +const int64 kUpdateIntervalSecs = 15; +// Intervals between requests to HistoryService. +const int64 kMinUpdateIntervalMinutes = 1; +const int64 kMaxUpdateIntervalMinutes = 60; + +// Use 100 quality (highest quality) because we're very sensitive to +// artifacts for these small sized, highly detailed images. +const int kTopSitesImageQuality = 100; + +} // namespace + +// Initially, histogram is not recorded. +bool TopSitesImpl::histogram_recorded_ = false; + +TopSitesImpl::TopSitesImpl(PrefService* pref_service, + HistoryService* history_service, + const char* blacklist_pref_name, + const PrepopulatedPageList& prepopulated_pages, + const CanAddURLToHistoryFn& can_add_url_to_history) + : backend_(nullptr), + cache_(new TopSitesCache()), + thread_safe_cache_(new TopSitesCache()), + last_num_urls_changed_(0), + prepopulated_pages_(prepopulated_pages), + pref_service_(pref_service), + blacklist_pref_name_(blacklist_pref_name), + history_service_(history_service), + can_add_url_to_history_(can_add_url_to_history), + loaded_(false), + history_service_observer_(this) { + DCHECK(pref_service_); + DCHECK(blacklist_pref_name_); + DCHECK(!can_add_url_to_history_.is_null()); +} + +void TopSitesImpl::Init( + const base::FilePath& db_name, + const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner) { + // Create the backend here, rather than in the constructor, so that + // unit tests that do not need the backend can run without a problem. + backend_ = new TopSitesBackend(db_task_runner); + backend_->Init(db_name); + backend_->GetMostVisitedThumbnails( + base::Bind(&TopSitesImpl::OnGotMostVisitedThumbnails, + base::Unretained(this)), + &cancelable_task_tracker_); +} + +bool TopSitesImpl::SetPageThumbnail(const GURL& url, + const gfx::Image& thumbnail, + const ThumbnailScore& score) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (!loaded_) { + // TODO(sky): I need to cache these and apply them after the load + // completes. + return false; + } + + bool add_temp_thumbnail = false; + if (!IsKnownURL(url)) { + if (!IsNonForcedFull()) { + add_temp_thumbnail = true; + } else { + return false; // This URL is not known to us. + } + } + + if (!can_add_url_to_history_.Run(url)) + return false; // It's not a real webpage. + + scoped_refptr<base::RefCountedBytes> thumbnail_data; + if (!EncodeBitmap(thumbnail, &thumbnail_data)) + return false; + + if (add_temp_thumbnail) { + // Always remove the existing entry and then add it back. That way if we end + // up with too many temp thumbnails we'll prune the oldest first. + RemoveTemporaryThumbnailByURL(url); + AddTemporaryThumbnail(url, thumbnail_data.get(), score); + return true; + } + + return SetPageThumbnailEncoded(url, thumbnail_data.get(), score); +} + +bool TopSitesImpl::SetPageThumbnailToJPEGBytes( + const GURL& url, + const base::RefCountedMemory* memory, + const ThumbnailScore& score) { + DCHECK(thread_checker_.CalledOnValidThread()); + + if (!loaded_) { + // TODO(sky): I need to cache these and apply them after the load + // completes. + return false; + } + + bool add_temp_thumbnail = false; + if (!IsKnownURL(url)) { + if (!IsNonForcedFull()) { + add_temp_thumbnail = true; + } else { + return false; // This URL is not known to us. + } + } + + if (!can_add_url_to_history_.Run(url)) + return false; // It's not a real webpage. + + if (add_temp_thumbnail) { + // Always remove the existing entry and then add it back. That way if we end + // up with too many temp thumbnails we'll prune the oldest first. + RemoveTemporaryThumbnailByURL(url); + AddTemporaryThumbnail(url, memory, score); + return true; + } + + return SetPageThumbnailEncoded(url, memory, score); +} + +// WARNING: this function may be invoked on any thread. +void TopSitesImpl::GetMostVisitedURLs( + const GetMostVisitedURLsCallback& callback, + bool include_forced_urls) { + MostVisitedURLList filtered_urls; + { + base::AutoLock lock(lock_); + if (!loaded_) { + // A request came in before we finished loading. Store the callback and + // we'll run it on current thread when we finish loading. + pending_callbacks_.push_back( + base::Bind(&RunOrPostGetMostVisitedURLsCallback, + base::MessageLoopProxy::current(), + include_forced_urls, + callback)); + return; + } + if (include_forced_urls) { + filtered_urls = thread_safe_cache_->top_sites(); + } else { + filtered_urls.assign(thread_safe_cache_->top_sites().begin() + + thread_safe_cache_->GetNumForcedURLs(), + thread_safe_cache_->top_sites().end()); + } + } + callback.Run(filtered_urls); +} + +bool TopSitesImpl::GetPageThumbnail( + const GURL& url, + bool prefix_match, + scoped_refptr<base::RefCountedMemory>* bytes) { + // WARNING: this may be invoked on any thread. + // Perform exact match. + { + base::AutoLock lock(lock_); + if (thread_safe_cache_->GetPageThumbnail(url, bytes)) + return true; + } + + // Resource bundle is thread safe. + for (const auto& prepopulated_page : prepopulated_pages_) { + if (url == prepopulated_page.most_visited.url) { + *bytes = + ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( + prepopulated_page.thumbnail_id, ui::SCALE_FACTOR_100P); + return true; + } + } + + if (prefix_match) { + // If http or https, search with |url| first, then try the other one. + std::vector<GURL> url_list; + url_list.push_back(url); + if (url.SchemeIsHTTPOrHTTPS()) + url_list.push_back(ToggleHTTPAndHTTPS(url)); + + for (std::vector<GURL>::iterator it = url_list.begin(); + it != url_list.end(); ++it) { + base::AutoLock lock(lock_); + + GURL canonical_url; + // Test whether any stored URL is a prefix of |url|. + canonical_url = thread_safe_cache_->GetGeneralizedCanonicalURL(*it); + if (!canonical_url.is_empty() && + thread_safe_cache_->GetPageThumbnail(canonical_url, bytes)) { + return true; + } + } + } + + return false; +} + +bool TopSitesImpl::GetPageThumbnailScore(const GURL& url, + ThumbnailScore* score) { + // WARNING: this may be invoked on any thread. + base::AutoLock lock(lock_); + return thread_safe_cache_->GetPageThumbnailScore(url, score); +} + +bool TopSitesImpl::GetTemporaryPageThumbnailScore(const GURL& url, + ThumbnailScore* score) { + for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end(); + ++i) { + if (i->first == url) { + *score = i->second.thumbnail_score; + return true; + } + } + return false; +} + + +// Returns the index of |url| in |urls|, or -1 if not found. +static int IndexOf(const MostVisitedURLList& urls, const GURL& url) { + for (size_t i = 0; i < urls.size(); i++) { + if (urls[i].url == url) + return i; + } + return -1; +} + +void TopSitesImpl::SyncWithHistory() { + DCHECK(thread_checker_.CalledOnValidThread()); + if (loaded_ && temp_images_.size()) { + // If we have temporary thumbnails it means there isn't much data, and most + // likely the user is first running Chrome. During this time we throttle + // updating from history by 30 seconds. If the user creates a new tab page + // during this window of time we force updating from history so that the new + // tab page isn't so far out of date. + timer_.Stop(); + StartQueryForMostVisited(); + } +} + +bool TopSitesImpl::HasBlacklistedItems() const { + const base::DictionaryValue* blacklist = + pref_service_->GetDictionary(blacklist_pref_name_); + return blacklist && !blacklist->empty(); +} + +void TopSitesImpl::AddBlacklistedURL(const GURL& url) { + DCHECK(thread_checker_.CalledOnValidThread()); + + base::Value* dummy = base::Value::CreateNullValue(); + { + DictionaryPrefUpdate update(pref_service_, blacklist_pref_name_); + base::DictionaryValue* blacklist = update.Get(); + blacklist->SetWithoutPathExpansion(GetURLHash(url), dummy); + } + + ResetThreadSafeCache(); + NotifyTopSitesChanged(); +} + +void TopSitesImpl::RemoveBlacklistedURL(const GURL& url) { + DCHECK(thread_checker_.CalledOnValidThread()); + { + DictionaryPrefUpdate update(pref_service_, blacklist_pref_name_); + base::DictionaryValue* blacklist = update.Get(); + blacklist->RemoveWithoutPathExpansion(GetURLHash(url), nullptr); + } + ResetThreadSafeCache(); + NotifyTopSitesChanged(); +} + +bool TopSitesImpl::IsBlacklisted(const GURL& url) { + DCHECK(thread_checker_.CalledOnValidThread()); + const base::DictionaryValue* blacklist = + pref_service_->GetDictionary(blacklist_pref_name_); + return blacklist && blacklist->HasKey(GetURLHash(url)); +} + +void TopSitesImpl::ClearBlacklistedURLs() { + DCHECK(thread_checker_.CalledOnValidThread()); + { + DictionaryPrefUpdate update(pref_service_, blacklist_pref_name_); + base::DictionaryValue* blacklist = update.Get(); + blacklist->Clear(); + } + ResetThreadSafeCache(); + NotifyTopSitesChanged(); +} + +void TopSitesImpl::ShutdownOnUIThread() { + history_service_ = nullptr; + history_service_observer_.RemoveAll(); + // Cancel all requests so that the service doesn't callback to us after we've + // invoked Shutdown (this could happen if we have a pending request and + // Shutdown is invoked). + cancelable_task_tracker_.TryCancelAll(); + if (backend_) + backend_->Shutdown(); +} + +// static +void TopSitesImpl::DiffMostVisited(const MostVisitedURLList& old_list, + const MostVisitedURLList& new_list, + TopSitesDelta* delta) { + + // Add all the old URLs for quick lookup. This maps URLs to the corresponding + // index in the input. + std::map<GURL, size_t> all_old_urls; + size_t num_old_forced = 0; + for (size_t i = 0; i < old_list.size(); i++) { + if (!old_list[i].last_forced_time.is_null()) + num_old_forced++; + DCHECK(old_list[i].last_forced_time.is_null() || i < num_old_forced) + << "Forced URLs must all appear before non-forced URLs."; + all_old_urls[old_list[i].url] = i; + } + + // Check all the URLs in the new set to see which ones are new or just moved. + // When we find a match in the old set, we'll reset its index to our special + // marker. This allows us to quickly identify the deleted ones in a later + // pass. + const size_t kAlreadyFoundMarker = static_cast<size_t>(-1); + int rank = -1; // Forced URLs have a rank of -1. + for (size_t i = 0; i < new_list.size(); i++) { + // Increase the rank if we're going through forced URLs. This works because + // non-forced URLs all come after forced URLs. + if (new_list[i].last_forced_time.is_null()) + rank++; + DCHECK(new_list[i].last_forced_time.is_null() == (rank != -1)) + << "Forced URLs must all appear before non-forced URLs."; + std::map<GURL, size_t>::iterator found = all_old_urls.find(new_list[i].url); + if (found == all_old_urls.end()) { + MostVisitedURLWithRank added; + added.url = new_list[i]; + added.rank = rank; + delta->added.push_back(added); + } else { + DCHECK(found->second != kAlreadyFoundMarker) + << "Same URL appears twice in the new list."; + int old_rank = found->second >= num_old_forced ? + found->second - num_old_forced : -1; + if (old_rank != rank || + old_list[found->second].last_forced_time != + new_list[i].last_forced_time) { + MostVisitedURLWithRank moved; + moved.url = new_list[i]; + moved.rank = rank; + delta->moved.push_back(moved); + } + found->second = kAlreadyFoundMarker; + } + } + + // Any member without the special marker in the all_old_urls list means that + // there wasn't a "new" URL that mapped to it, so it was deleted. + for (std::map<GURL, size_t>::const_iterator i = all_old_urls.begin(); + i != all_old_urls.end(); ++i) { + if (i->second != kAlreadyFoundMarker) + delta->deleted.push_back(old_list[i->second]); + } +} + +base::CancelableTaskTracker::TaskId TopSitesImpl::StartQueryForMostVisited() { + DCHECK(loaded_); + if (!history_service_) + return base::CancelableTaskTracker::kBadTaskId; + + return history_service_->QueryMostVisitedURLs( + num_results_to_request_from_history(), kDaysOfHistory, + base::Bind(&TopSitesImpl::OnTopSitesAvailableFromHistory, + base::Unretained(this)), + &cancelable_task_tracker_); +} + +bool TopSitesImpl::IsKnownURL(const GURL& url) { + return loaded_ && cache_->IsKnownURL(url); +} + +const std::string& TopSitesImpl::GetCanonicalURLString(const GURL& url) const { + return cache_->GetCanonicalURL(url).spec(); +} + +bool TopSitesImpl::IsNonForcedFull() { + return loaded_ && cache_->GetNumNonForcedURLs() >= kNonForcedTopSitesNumber; +} + +bool TopSitesImpl::IsForcedFull() { + return loaded_ && cache_->GetNumForcedURLs() >= kForcedTopSitesNumber; +} + +TopSitesImpl::~TopSitesImpl() { +} + +bool TopSitesImpl::SetPageThumbnailNoDB( + const GURL& url, + const base::RefCountedMemory* thumbnail_data, + const ThumbnailScore& score) { + // This should only be invoked when we know about the url. + DCHECK(cache_->IsKnownURL(url)); + + const MostVisitedURL& most_visited = + cache_->top_sites()[cache_->GetURLIndex(url)]; + Images* image = cache_->GetImage(url); + + // When comparing the thumbnail scores, we need to take into account the + // redirect hops, which are not generated when the thumbnail is because the + // redirects weren't known. We fill that in here since we know the redirects. + ThumbnailScore new_score_with_redirects(score); + new_score_with_redirects.redirect_hops_from_dest = + GetRedirectDistanceForURL(most_visited, url); + + if (!ShouldReplaceThumbnailWith(image->thumbnail_score, + new_score_with_redirects) && + image->thumbnail.get()) + return false; // The one we already have is better. + + image->thumbnail = const_cast<base::RefCountedMemory*>(thumbnail_data); + image->thumbnail_score = new_score_with_redirects; + + ResetThreadSafeImageCache(); + return true; +} + +bool TopSitesImpl::SetPageThumbnailEncoded( + const GURL& url, + const base::RefCountedMemory* thumbnail, + const ThumbnailScore& score) { + if (!SetPageThumbnailNoDB(url, thumbnail, score)) + return false; + + // Update the database. + if (!cache_->IsKnownURL(url)) + return false; + + size_t index = cache_->GetURLIndex(url); + int url_rank = index - cache_->GetNumForcedURLs(); + const MostVisitedURL& most_visited = cache_->top_sites()[index]; + backend_->SetPageThumbnail(most_visited, + url_rank < 0 ? -1 : url_rank, + *(cache_->GetImage(most_visited.url))); + return true; +} + +// static +bool TopSitesImpl::EncodeBitmap(const gfx::Image& bitmap, + scoped_refptr<base::RefCountedBytes>* bytes) { + if (bitmap.IsEmpty()) + return false; + *bytes = new base::RefCountedBytes(); + std::vector<unsigned char> data; + if (!gfx::JPEG1xEncodedDataFromImage(bitmap, kTopSitesImageQuality, &data)) + return false; + + // As we're going to cache this data, make sure the vector is only as big as + // it needs to be, as JPEGCodec::Encode() over-allocates data.capacity(). + // (In a C++0x future, we can just call shrink_to_fit() in Encode()) + (*bytes)->data() = data; + return true; +} + +void TopSitesImpl::RemoveTemporaryThumbnailByURL(const GURL& url) { + for (TempImages::iterator i = temp_images_.begin(); i != temp_images_.end(); + ++i) { + if (i->first == url) { + temp_images_.erase(i); + return; + } + } +} + +void TopSitesImpl::AddTemporaryThumbnail( + const GURL& url, + const base::RefCountedMemory* thumbnail, + const ThumbnailScore& score) { + if (temp_images_.size() == kMaxTempTopImages) + temp_images_.erase(temp_images_.begin()); + + TempImage image; + image.first = url; + image.second.thumbnail = const_cast<base::RefCountedMemory*>(thumbnail); + image.second.thumbnail_score = score; + temp_images_.push_back(image); +} + +void TopSitesImpl::TimerFired() { + StartQueryForMostVisited(); +} + +// static +int TopSitesImpl::GetRedirectDistanceForURL(const MostVisitedURL& most_visited, + const GURL& url) { + for (size_t i = 0; i < most_visited.redirects.size(); i++) { + if (most_visited.redirects[i] == url) + return static_cast<int>(most_visited.redirects.size() - i - 1); + } + NOTREACHED() << "URL should always be found."; + return 0; +} + +PrepopulatedPageList TopSitesImpl::GetPrepopulatedPages() { + return prepopulated_pages_; +} + +bool TopSitesImpl::loaded() const { + return loaded_; +} + +bool TopSitesImpl::AddForcedURL(const GURL& url, const base::Time& time) { + DCHECK(thread_checker_.CalledOnValidThread()); + size_t num_forced = cache_->GetNumForcedURLs(); + MostVisitedURLList new_list(cache_->top_sites()); + MostVisitedURL new_url; + + if (cache_->IsKnownURL(url)) { + size_t index = cache_->GetURLIndex(url); + // Do nothing if we currently have that URL as non-forced. + if (new_list[index].last_forced_time.is_null()) + return false; + + // Update the |last_forced_time| of the already existing URL. Delete it and + // reinsert it at the right location. + new_url = new_list[index]; + new_list.erase(new_list.begin() + index); + num_forced--; + } else { + new_url.url = url; + new_url.redirects.push_back(url); + } + new_url.last_forced_time = time; + // Add forced URLs and sort. Added to the end of the list of forced URLs + // since this is almost always where it needs to go, unless the user's local + // clock is fiddled with. + MostVisitedURLList::iterator mid = new_list.begin() + num_forced; + new_list.insert(mid, new_url); + mid = new_list.begin() + num_forced; // Mid was invalidated. + std::inplace_merge(new_list.begin(), mid, mid + 1, ForcedURLComparator); + SetTopSites(new_list, CALL_LOCATION_FROM_OTHER_PLACES); + return true; +} + +void TopSitesImpl::OnNavigationCommitted(const GURL& url) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (!loaded_ || IsNonForcedFull()) + return; + + if (!cache_->IsKnownURL(url) && can_add_url_to_history_.Run(url)) { + // To avoid slamming history we throttle requests when the url updates. To + // do otherwise negatively impacts perf tests. + RestartQueryForTopSitesTimer(GetUpdateDelay()); + } +} + +bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls, + size_t num_forced_urls) { + bool added = false; + for (const auto& prepopulated_page : prepopulated_pages_) { + if (urls->size() - num_forced_urls < kNonForcedTopSitesNumber && + IndexOf(*urls, prepopulated_page.most_visited.url) == -1) { + urls->push_back(prepopulated_page.most_visited); + added = true; + } + } + return added; +} + +size_t TopSitesImpl::MergeCachedForcedURLs(MostVisitedURLList* new_list) { + DCHECK(thread_checker_.CalledOnValidThread()); + // Add all the new URLs for quick lookup. Take that opportunity to count the + // number of forced URLs in |new_list|. + std::set<GURL> all_new_urls; + size_t num_forced = 0; + for (size_t i = 0; i < new_list->size(); ++i) { + for (size_t j = 0; j < (*new_list)[i].redirects.size(); j++) { + all_new_urls.insert((*new_list)[i].redirects[j]); + } + if (!(*new_list)[i].last_forced_time.is_null()) + ++num_forced; + } + + // Keep the forced URLs from |cache_| that are not found in |new_list|. + MostVisitedURLList filtered_forced_urls; + for (size_t i = 0; i < cache_->GetNumForcedURLs(); ++i) { + if (all_new_urls.find(cache_->top_sites()[i].url) == all_new_urls.end()) + filtered_forced_urls.push_back(cache_->top_sites()[i]); + } + num_forced += filtered_forced_urls.size(); + + // Prepend forced URLs and sort in order of ascending |last_forced_time|. + new_list->insert(new_list->begin(), filtered_forced_urls.begin(), + filtered_forced_urls.end()); + std::inplace_merge( + new_list->begin(), new_list->begin() + filtered_forced_urls.size(), + new_list->begin() + num_forced, ForcedURLComparator); + + // Drop older forced URLs if the list overflows. Since forced URLs are always + // sort in increasing order of |last_forced_time|, drop the first ones. + if (num_forced > kForcedTopSitesNumber) { + new_list->erase(new_list->begin(), + new_list->begin() + (num_forced - kForcedTopSitesNumber)); + num_forced = kForcedTopSitesNumber; + } + + return num_forced; +} + +void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, + MostVisitedURLList* out) { + // Log the number of times ApplyBlacklist is called so we can compute the + // average number of blacklisted items per user. + const base::DictionaryValue* blacklist = + pref_service_->GetDictionary(blacklist_pref_name_); + UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); + UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", + (blacklist ? blacklist->size() : 0)); + size_t num_non_forced_urls = 0; + size_t num_forced_urls = 0; + for (size_t i = 0; i < urls.size(); ++i) { + if (!IsBlacklisted(urls[i].url)) { + if (urls[i].last_forced_time.is_null()) { + // Non-forced URL. + if (num_non_forced_urls >= kNonForcedTopSitesNumber) + continue; + num_non_forced_urls++; + } else { + // Forced URL. + if (num_forced_urls >= kForcedTopSitesNumber) + continue; + num_forced_urls++; + } + out->push_back(urls[i]); + } + } +} + +std::string TopSitesImpl::GetURLHash(const GURL& url) { + // We don't use canonical URLs here to be able to blacklist only one of + // the two 'duplicate' sites, e.g. 'gmail.com' and 'mail.google.com'. + return base::MD5String(url.spec()); +} + +base::TimeDelta TopSitesImpl::GetUpdateDelay() { + if (cache_->top_sites().size() <= prepopulated_pages_.size()) + return base::TimeDelta::FromSeconds(30); + + int64 range = kMaxUpdateIntervalMinutes - kMinUpdateIntervalMinutes; + int64 minutes = kMaxUpdateIntervalMinutes - + last_num_urls_changed_ * range / cache_->top_sites().size(); + return base::TimeDelta::FromMinutes(minutes); +} + +void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites, + const CallLocation location) { + DCHECK(thread_checker_.CalledOnValidThread()); + + MostVisitedURLList top_sites(new_top_sites); + size_t num_forced_urls = MergeCachedForcedURLs(&top_sites); + AddPrepopulatedPages(&top_sites, num_forced_urls); + + TopSitesDelta delta; + DiffMostVisited(cache_->top_sites(), top_sites, &delta); + + TopSitesBackend::RecordHistogram record_or_not = + TopSitesBackend::RECORD_HISTOGRAM_NO; + + // Record the delta size into a histogram if this function is called from + // function OnGotMostVisitedThumbnails and no histogram value has been + // recorded before. + if (location == CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_THUMBNAILS && + !histogram_recorded_) { + size_t delta_size = + delta.deleted.size() + delta.added.size() + delta.moved.size(); + UMA_HISTOGRAM_COUNTS_100("History.FirstSetTopSitesDeltaSize", delta_size); + // Will be passed to TopSitesBackend to let it record the histogram too. + record_or_not = TopSitesBackend::RECORD_HISTOGRAM_YES; + // Change it to true so that the histogram will not be recorded any more. + histogram_recorded_ = true; + } + + if (!delta.deleted.empty() || !delta.added.empty() || !delta.moved.empty()) { + backend_->UpdateTopSites(delta, record_or_not); + } + + last_num_urls_changed_ = delta.added.size() + delta.moved.size(); + + // We always do the following steps (setting top sites in cache, and resetting + // thread safe cache ...) as this method is invoked during startup at which + // point the caches haven't been updated yet. + cache_->SetTopSites(top_sites); + + // See if we have any tmp thumbnails for the new sites. + if (!temp_images_.empty()) { + for (size_t i = 0; i < top_sites.size(); ++i) { + const MostVisitedURL& mv = top_sites[i]; + GURL canonical_url = cache_->GetCanonicalURL(mv.url); + // At the time we get the thumbnail redirects aren't known, so we have to + // iterate through all the images. + for (TempImages::iterator it = temp_images_.begin(); + it != temp_images_.end(); ++it) { + if (canonical_url == cache_->GetCanonicalURL(it->first)) { + SetPageThumbnailEncoded( + mv.url, it->second.thumbnail.get(), it->second.thumbnail_score); + temp_images_.erase(it); + break; + } + } + } + } + + if (top_sites.size() - num_forced_urls >= kNonForcedTopSitesNumber) + temp_images_.clear(); + + ResetThreadSafeCache(); + ResetThreadSafeImageCache(); + NotifyTopSitesChanged(); + + // Restart the timer that queries history for top sites. This is done to + // ensure we stay in sync with history. + RestartQueryForTopSitesTimer(GetUpdateDelay()); +} + +int TopSitesImpl::num_results_to_request_from_history() const { + DCHECK(thread_checker_.CalledOnValidThread()); + + const base::DictionaryValue* blacklist = + pref_service_->GetDictionary(blacklist_pref_name_); + return kNonForcedTopSitesNumber + (blacklist ? blacklist->size() : 0); +} + +void TopSitesImpl::MoveStateToLoaded() { + DCHECK(thread_checker_.CalledOnValidThread()); + + MostVisitedURLList filtered_urls_all; + MostVisitedURLList filtered_urls_nonforced; + PendingCallbacks pending_callbacks; + { + base::AutoLock lock(lock_); + + if (loaded_) + return; // Don't do anything if we're already loaded. + loaded_ = true; + + // Now that we're loaded we can service the queued up callbacks. Copy them + // here and service them outside the lock. + if (!pending_callbacks_.empty()) { + // We always filter out forced URLs because callers of GetMostVisitedURLs + // are not interested in them. + filtered_urls_all = thread_safe_cache_->top_sites(); + filtered_urls_nonforced.assign(thread_safe_cache_->top_sites().begin() + + thread_safe_cache_->GetNumForcedURLs(), + thread_safe_cache_->top_sites().end()); + pending_callbacks.swap(pending_callbacks_); + } + } + + for (size_t i = 0; i < pending_callbacks.size(); i++) + pending_callbacks[i].Run(filtered_urls_all, filtered_urls_nonforced); + + if (history_service_) + history_service_observer_.Add(history_service_); + + NotifyTopSitesLoaded(); +} + +void TopSitesImpl::ResetThreadSafeCache() { + base::AutoLock lock(lock_); + MostVisitedURLList cached; + ApplyBlacklist(cache_->top_sites(), &cached); + thread_safe_cache_->SetTopSites(cached); +} + +void TopSitesImpl::ResetThreadSafeImageCache() { + base::AutoLock lock(lock_); + thread_safe_cache_->SetThumbnails(cache_->images()); +} + +void TopSitesImpl::RestartQueryForTopSitesTimer(base::TimeDelta delta) { + if (timer_.IsRunning() && ((timer_start_time_ + timer_.GetCurrentDelay()) < + (base::TimeTicks::Now() + delta))) { + return; + } + + timer_start_time_ = base::TimeTicks::Now(); + timer_.Stop(); + timer_.Start(FROM_HERE, delta, this, &TopSitesImpl::TimerFired); +} + +void TopSitesImpl::OnGotMostVisitedThumbnails( + const scoped_refptr<MostVisitedThumbnails>& thumbnails) { + DCHECK(thread_checker_.CalledOnValidThread()); + + // Set the top sites directly in the cache so that SetTopSites diffs + // correctly. + cache_->SetTopSites(thumbnails->most_visited); + SetTopSites(thumbnails->most_visited, + CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_THUMBNAILS); + cache_->SetThumbnails(thumbnails->url_to_images_map); + + ResetThreadSafeImageCache(); + + MoveStateToLoaded(); + + // Start a timer that refreshes top sites from history. + RestartQueryForTopSitesTimer( + base::TimeDelta::FromSeconds(kUpdateIntervalSecs)); +} + +void TopSitesImpl::OnTopSitesAvailableFromHistory( + const MostVisitedURLList* pages) { + DCHECK(pages); + SetTopSites(*pages, CALL_LOCATION_FROM_OTHER_PLACES); +} + +void TopSitesImpl::OnURLsDeleted(HistoryService* history_service, + bool all_history, + bool expired, + const URLRows& deleted_rows, + const std::set<GURL>& favicon_urls) { + if (!loaded_) + return; + + if (all_history) { + SetTopSites(MostVisitedURLList(), CALL_LOCATION_FROM_OTHER_PLACES); + backend_->ResetDatabase(); + } else { + std::set<size_t> indices_to_delete; // Indices into top_sites_. + for (const auto& row : deleted_rows) { + if (cache_->IsKnownURL(row.url())) + indices_to_delete.insert(cache_->GetURLIndex(row.url())); + } + + if (indices_to_delete.empty()) + return; + + MostVisitedURLList new_top_sites(cache_->top_sites()); + for (std::set<size_t>::reverse_iterator i = indices_to_delete.rbegin(); + i != indices_to_delete.rend(); i++) { + new_top_sites.erase(new_top_sites.begin() + *i); + } + SetTopSites(new_top_sites, CALL_LOCATION_FROM_OTHER_PLACES); + } + StartQueryForMostVisited(); +} + +} // namespace history
diff --git a/components/history/core/browser/top_sites_impl.h b/components/history/core/browser/top_sites_impl.h new file mode 100644 index 0000000..e28ceb59d --- /dev/null +++ b/components/history/core/browser/top_sites_impl.h
@@ -0,0 +1,320 @@ +// Copyright (c) 2013 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_HISTORY_CORE_BROWSER_TOP_SITES_IMPL_H_ +#define COMPONENTS_HISTORY_CORE_BROWSER_TOP_SITES_IMPL_H_ + +#include <list> +#include <set> +#include <string> +#include <utility> +#include <vector> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/gtest_prod_util.h" +#include "base/memory/ref_counted.h" +#include "base/scoped_observer.h" +#include "base/synchronization/lock.h" +#include "base/task/cancelable_task_tracker.h" +#include "base/threading/thread_checker.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "components/history/core/browser/history_service.h" +#include "components/history/core/browser/history_service_observer.h" +#include "components/history/core/browser/history_types.h" +#include "components/history/core/browser/page_usage_data.h" +#include "components/history/core/browser/top_sites.h" +#include "components/history/core/browser/top_sites_backend.h" +#include "components/history/core/common/thumbnail_score.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/image/image.h" +#include "url/gurl.h" + +class PrefService; + +namespace base { +class FilePath; +class RefCountedBytes; +class RefCountedMemory; +class SingleThreadTaskRunner; +} + +namespace history { + +class HistoryService; +class TopSitesCache; +class TopSitesImplTest; + +// This class allows requests for most visited urls and thumbnails on any +// thread. All other methods must be invoked on the UI thread. All mutations +// to internal state happen on the UI thread and are scheduled to update the +// db using TopSitesBackend. +class TopSitesImpl : public TopSites, public HistoryServiceObserver { + public: + // Called to check whether an URL can be added to the history. Must be + // callable multiple time and during the whole lifetime of TopSitesImpl. + using CanAddURLToHistoryFn = base::Callback<bool(const GURL&)>; + + TopSitesImpl(PrefService* pref_service, + HistoryService* history_service, + const char* blacklist_pref_name, + const PrepopulatedPageList& prepopulated_pages, + const CanAddURLToHistoryFn& can_add_url_to_history); + + // Initializes TopSitesImpl. + void Init(const base::FilePath& db_name, + const scoped_refptr<base::SingleThreadTaskRunner>& db_task_runner); + + // TopSites implementation. + bool SetPageThumbnail(const GURL& url, + const gfx::Image& thumbnail, + const ThumbnailScore& score) override; + bool SetPageThumbnailToJPEGBytes(const GURL& url, + const base::RefCountedMemory* memory, + const ThumbnailScore& score) override; + void GetMostVisitedURLs(const GetMostVisitedURLsCallback& callback, + bool include_forced_urls) override; + bool GetPageThumbnail(const GURL& url, + bool prefix_match, + scoped_refptr<base::RefCountedMemory>* bytes) override; + bool GetPageThumbnailScore(const GURL& url, ThumbnailScore* score) override; + bool GetTemporaryPageThumbnailScore(const GURL& url, + ThumbnailScore* score) override; + void SyncWithHistory() override; + bool HasBlacklistedItems() const override; + void AddBlacklistedURL(const GURL& url) override; + void RemoveBlacklistedURL(const GURL& url) override; + bool IsBlacklisted(const GURL& url) override; + void ClearBlacklistedURLs() override; + base::CancelableTaskTracker::TaskId StartQueryForMostVisited() override; + bool IsKnownURL(const GURL& url) override; + const std::string& GetCanonicalURLString(const GURL& url) const override; + bool IsNonForcedFull() override; + bool IsForcedFull() override; + PrepopulatedPageList GetPrepopulatedPages() override; + bool loaded() const override; + bool AddForcedURL(const GURL& url, const base::Time& time) override; + void OnNavigationCommitted(const GURL& url) override; + + // RefcountedKeyedService: + void ShutdownOnUIThread() override; + + protected: + ~TopSitesImpl() override; + + private: + // TODO(yiyaoliu): Remove the enums and related code when crbug/223430 is + // fixed. + // An enum representing different situations under which function + // SetTopSites can be initiated. + // This is needed because a histogram is used to record speed related metrics + // when SetTopSites are initiated from OnGotMostVisitedThumbnails, which + // usually happens early and might affect Chrome startup speed. + enum CallLocation { + // SetTopSites is called from function OnGotMostVisitedThumbnails. + CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_THUMBNAILS, + // All other situations. + CALL_LOCATION_FROM_OTHER_PLACES + }; + + friend class TopSitesImplTest; + FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisited); + FRIEND_TEST_ALL_PREFIXES(TopSitesImplTest, DiffMostVisitedWithForced); + + typedef base::Callback<void(const MostVisitedURLList&, + const MostVisitedURLList&)> PendingCallback; + + typedef std::pair<GURL, Images> TempImage; + typedef std::list<TempImage> TempImages; + typedef std::vector<PendingCallback> PendingCallbacks; + + // Generates the diff of things that happened between "old" and "new." + // + // This treats forced URLs separately than non-forced URLs. + // + // The URLs that are in "new" but not "old" will be have their index into + // "new" put in |added_urls|. The non-forced URLs that are in "old" but not + // "new" will have their index into "old" put into |deleted_urls|. + // + // URLs appearing in both old and new lists but having different indices will + // have their index into "new" be put into |moved_urls|. + static void DiffMostVisited(const MostVisitedURLList& old_list, + const MostVisitedURLList& new_list, + TopSitesDelta* delta); + + // Sets the thumbnail without writing to the database. Useful when + // reading last known top sites from the DB. + // Returns true if the thumbnail was set, false if the existing one is better. + bool SetPageThumbnailNoDB(const GURL& url, + const base::RefCountedMemory* thumbnail_data, + const ThumbnailScore& score); + + // A version of SetPageThumbnail that takes RefCountedBytes as + // returned by HistoryService. + bool SetPageThumbnailEncoded(const GURL& url, + const base::RefCountedMemory* thumbnail, + const ThumbnailScore& score); + + // Encodes the bitmap to bytes for storage to the db. Returns true if the + // bitmap was successfully encoded. + static bool EncodeBitmap(const gfx::Image& bitmap, + scoped_refptr<base::RefCountedBytes>* bytes); + + // Removes the cached thumbnail for url. Does nothing if |url| if not cached + // in |temp_images_|. + void RemoveTemporaryThumbnailByURL(const GURL& url); + + // Add a thumbnail for an unknown url. See temp_thumbnails_map_. + void AddTemporaryThumbnail(const GURL& url, + const base::RefCountedMemory* thumbnail, + const ThumbnailScore& score); + + // Called by our timer. Starts the query for the most visited sites. + void TimerFired(); + + // Finds the given URL in the redirect chain for the given TopSite, and + // returns the distance from the destination in hops that the given URL is. + // The URL is assumed to be in the list. The destination is 0. + static int GetRedirectDistanceForURL(const MostVisitedURL& most_visited, + const GURL& url); + + // Add prepopulated pages: 'welcome to Chrome' and themes gallery to |urls|. + // Returns true if any pages were added. + bool AddPrepopulatedPages(MostVisitedURLList* urls, + size_t num_forced_urls); + + // Add all the forced URLs from |cache_| into |new_list|, making sure not to + // add any URL that's already in |new_list|'s non-forced URLs. The forced URLs + // in |cache_| and |new_list| are assumed to appear at the front of the list + // and be sorted in increasing |last_forced_time|. This will still be true + // after the call. If the list of forced URLs overflows the older ones are + // dropped. Returns the number of forced URLs after the merge. + size_t MergeCachedForcedURLs(MostVisitedURLList* new_list); + + // Takes |urls|, produces it's copy in |out| after removing blacklisted URLs. + // Also ensures we respect the maximum number of forced URLs and non-forced + // URLs. + void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out); + + // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs. + std::string GetURLHash(const GURL& url); + + // Returns the delay until the next update of history is needed. + // Uses num_urls_changed + base::TimeDelta GetUpdateDelay(); + + // Updates URLs in |cache_| and the db (in the background). + // The non-forced URLs in |new_top_sites| replace those in |cache_|. + // The forced URLs of |new_top_sites| are merged with those in |cache_|, + // if the list of forced URLs overflows, the oldest ones are dropped. + // All mutations to cache_ *must* go through this. Should + // be called from the UI thread. + void SetTopSites(const MostVisitedURLList& new_top_sites, + const CallLocation location); + + // Returns the number of most visited results to request from history. This + // changes depending upon how many urls have been blacklisted. Should be + // called from the UI thread. + int num_results_to_request_from_history() const; + + // Invoked when transitioning to LOADED. Notifies any queued up callbacks. + // Should be called from the UI thread. + void MoveStateToLoaded(); + + void ResetThreadSafeCache(); + + void ResetThreadSafeImageCache(); + + // Stops and starts timer with a delay of |delta|. + void RestartQueryForTopSitesTimer(base::TimeDelta delta); + + // Callback from TopSites with the top sites/thumbnails. Should be called + // from the UI thread. + void OnGotMostVisitedThumbnails( + const scoped_refptr<MostVisitedThumbnails>& thumbnails); + + // Called when history service returns a list of top URLs. + void OnTopSitesAvailableFromHistory(const MostVisitedURLList* data); + + // history::HistoryServiceObserver: + void OnURLsDeleted(HistoryService* history_service, + bool all_history, + bool expired, + const URLRows& deleted_rows, + const std::set<GURL>& favicon_urls) override; + + // Ensures that non thread-safe methods are called on the correct thread. + base::ThreadChecker thread_checker_; + + scoped_refptr<TopSitesBackend> backend_; + + // The top sites data. + scoped_ptr<TopSitesCache> cache_; + + // Copy of the top sites data that may be accessed on any thread (assuming + // you hold |lock_|). The data in |thread_safe_cache_| has blacklisted and + // pinned urls applied (|cache_| does not). + scoped_ptr<TopSitesCache> thread_safe_cache_; + + // Lock used to access |thread_safe_cache_|. + mutable base::Lock lock_; + + // Task tracker for history and backend requests. + base::CancelableTaskTracker cancelable_task_tracker_; + + // Timer that asks history for the top sites. This is used to make sure our + // data stays in sync with history. + base::OneShotTimer<TopSitesImpl> timer_; + + // The time we started |timer_| at. Only valid if |timer_| is running. + base::TimeTicks timer_start_time_; + + // The number of URLs changed on the last update. + size_t last_num_urls_changed_; + + // The pending requests for the top sites list. Can only be non-empty at + // startup. After we read the top sites from the DB, we'll always have a + // cached list and be able to run callbacks immediately. + PendingCallbacks pending_callbacks_; + + // Stores thumbnails for unknown pages. When SetPageThumbnail is + // called, if we don't know about that URL yet and we don't have + // enough Top Sites (new profile), we store it until the next + // SetNonForcedTopSites call. + TempImages temp_images_; + + // URL List of prepopulated page. + PrepopulatedPageList prepopulated_pages_; + + // PrefService holding the NTP URL blacklist dictionary. Must outlive + // TopSitesImpl. + PrefService* pref_service_; + + // Key for the NTP URL blacklist dictionary in PrefService. + const char* blacklist_pref_name_; + + // HistoryService that TopSitesImpl can query. May be null, but if defined it + // must outlive TopSitesImpl. + HistoryService* history_service_; + + // Can URL be added to the history? + CanAddURLToHistoryFn can_add_url_to_history_; + + // Are we loaded? + bool loaded_; + + // Have the SetTopSites execution time related histograms been recorded? + // The histogram should only be recorded once for each Chrome execution. + static bool histogram_recorded_; + + ScopedObserver<HistoryService, HistoryServiceObserver> + history_service_observer_; + + DISALLOW_COPY_AND_ASSIGN(TopSitesImpl); +}; + +} // namespace history + +#endif // COMPONENTS_HISTORY_CORE_BROWSER_TOP_SITES_IMPL_H_
diff --git a/components/history/core/test/test_history_database.cc b/components/history/core/test/test_history_database.cc index d2c76c7a..ca5f275 100644 --- a/components/history/core/test/test_history_database.cc +++ b/components/history/core/test/test_history_database.cc
@@ -7,10 +7,8 @@ #include "components/history/core/browser/history_database_params.h" namespace history { -namespace { const DownloadInterruptReason kTestDownloadInterruptReasonNone = 0; const DownloadInterruptReason kTestDownloadInterruptReasonCrash = 1; -} // namespace TestHistoryDatabase::TestHistoryDatabase() : HistoryDatabase(kTestDownloadInterruptReasonNone,
diff --git a/components/history/core/test/test_history_database.h b/components/history/core/test/test_history_database.h index 178b8a8..52b431b 100644 --- a/components/history/core/test/test_history_database.h +++ b/components/history/core/test/test_history_database.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_HISTORY_CORE_TEST_TEST_HISTORY_DATABASE_H_ #define COMPONENTS_HISTORY_CORE_TEST_TEST_HISTORY_DATABASE_H_ +#include "components/history/core/browser/download_types.h" #include "components/history/core/browser/history_database.h" namespace base { @@ -15,6 +16,13 @@ struct HistoryDatabaseParams; +// The download successfully completed. Value for tests. +extern const DownloadInterruptReason kTestDownloadInterruptReasonNone; + +// The download was interrupted by a browser crash. Internal use only. +// Resume pending downloads if possible. Value for tests. +extern const DownloadInterruptReason kTestDownloadInterruptReasonCrash; + // TestHistoryDatabase is a simple wrapper around HistoryDatabase that provides // default values to the constructor. class TestHistoryDatabase : public HistoryDatabase {
diff --git a/components/history/ios/browser/DEPS b/components/history/ios/browser/DEPS new file mode 100644 index 0000000..0fc0ddd --- /dev/null +++ b/components/history/ios/browser/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ios/web/public", +]
diff --git a/components/history/ios/browser/history_database_helper.cc b/components/history/ios/browser/history_database_helper.cc new file mode 100644 index 0000000..6f2f22e0 --- /dev/null +++ b/components/history/ios/browser/history_database_helper.cc
@@ -0,0 +1,34 @@ +// 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/history/ios/browser/history_database_helper.h" + +#include "base/files/file_path.h" +#include "components/history/core/browser/history_database_params.h" + +namespace history { +namespace { + +// Values are copied from content/public/browser/download_interrupt_reasons.h. +// Their value is irrelevant for iOS but must be kept in sync until iOS code +// downstream stops compiling some part of content. + +// The download successfully completed. +const DownloadInterruptReason kDownloadInterruptReasonNone = 0; + +// The download was interrupted by a browser crash. +// Resume pending downloads if possible. +const DownloadInterruptReason kDownloadInterruptReasonCrash = 50; + +} // namespace + +HistoryDatabaseParams HistoryDatabaseParamsForPath( + const base::FilePath& history_dir) { + return HistoryDatabaseParams( + history_dir, + kDownloadInterruptReasonNone, + kDownloadInterruptReasonCrash); +} + +} // namespace
diff --git a/components/history/ios/browser/history_database_helper.h b/components/history/ios/browser/history_database_helper.h new file mode 100644 index 0000000..3093efe3 --- /dev/null +++ b/components/history/ios/browser/history_database_helper.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 COMPONENTS_HISTORY_IOS_BROWSER_HISTORY_DATABASE_HELPER_H_ +#define COMPONENTS_HISTORY_IOS_BROWSER_HISTORY_DATABASE_HELPER_H_ + +namespace base { +class FilePath; +} + +namespace history { + +struct HistoryDatabaseParams; + +// Returns a HistoryDatabaseParams for |history_dir|. +HistoryDatabaseParams HistoryDatabaseParamsForPath( + const base::FilePath& history_dir); + +} // namespace history + +#endif // COMPONENTS_HISTORY_IOS_BROWSER_HISTORY_DATABASE_HELPER_H_
diff --git a/components/history/ios/browser/web_state_top_sites_observer.cc b/components/history/ios/browser/web_state_top_sites_observer.cc new file mode 100644 index 0000000..ac95a55 --- /dev/null +++ b/components/history/ios/browser/web_state_top_sites_observer.cc
@@ -0,0 +1,41 @@ +// 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/history/ios/browser/web_state_top_sites_observer.h" + +#include "base/logging.h" +#include "components/history/core/browser/top_sites.h" +#include "ios/web/public/load_committed_details.h" +#include "ios/web/public/navigation_item.h" + +DEFINE_WEB_STATE_USER_DATA_KEY(history::WebStateTopSitesObserver); + +namespace history { + +// static +void WebStateTopSitesObserver::CreateForWebState(web::WebState* web_state, + TopSites* top_sites) { + DCHECK(web_state); + if (!FromWebState(web_state)) { + web_state->SetUserData(UserDataKey(), + new WebStateTopSitesObserver(web_state, top_sites)); + } +} + +WebStateTopSitesObserver::WebStateTopSitesObserver(web::WebState* web_state, + TopSites* top_sites) + : web::WebStateObserver(web_state), top_sites_(top_sites) { +} + +WebStateTopSitesObserver::~WebStateTopSitesObserver() { +} + +void WebStateTopSitesObserver::NavigationItemCommitted( + const web::LoadCommittedDetails& load_details) { + DCHECK(load_details.item); + if (top_sites_) + top_sites_->OnNavigationCommitted(load_details.item->GetURL()); +} + +} // namespace history
diff --git a/components/history/ios/browser/web_state_top_sites_observer.h b/components/history/ios/browser/web_state_top_sites_observer.h new file mode 100644 index 0000000..0d62276 --- /dev/null +++ b/components/history/ios/browser/web_state_top_sites_observer.h
@@ -0,0 +1,41 @@ +// 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_HISTORY_IOS_BROWSER_WEB_STATE_TOP_SITES_OBSERVER_H_ +#define COMPONENTS_HISTORY_IOS_BROWSER_WEB_STATE_TOP_SITES_OBSERVER_H_ + +#include "ios/web/public/web_state/web_state_observer.h" +#include "ios/web/public/web_state/web_state_user_data.h" + +namespace history { + +class TopSites; + +// WebStateTopSitesObserver forwards navigation events from web::WebState to +// TopSites. +class WebStateTopSitesObserver + : public web::WebStateObserver, + public web::WebStateUserData<WebStateTopSitesObserver> { + public: + static void CreateForWebState(web::WebState* web_state, TopSites* top_sites); + + private: + friend class web::WebStateUserData<WebStateTopSitesObserver>; + + WebStateTopSitesObserver(web::WebState* web_state, TopSites* top_sites); + ~WebStateTopSitesObserver() override; + + // web::WebStateObserver implementation. + void NavigationItemCommitted( + const web::LoadCommittedDetails& load_details) override; + + // Underlying TopSites instance, may be null during testing. + TopSites* top_sites_; + + DISALLOW_COPY_AND_ASSIGN(WebStateTopSitesObserver); +}; + +} // namespace history + +#endif // COMPONENTS_HISTORY_IOS_BROWSER_WEB_STATE_TOP_SITES_OBSERVER_H_
diff --git a/components/html_viewer/BUILD.gn b/components/html_viewer/BUILD.gn index 75856bcb..bb8e2cca 100644 --- a/components/html_viewer/BUILD.gn +++ b/components/html_viewer/BUILD.gn
@@ -103,8 +103,12 @@ "//cc", "//cc/blink", "//cc/surfaces", + "//components/clipboard/public/interfaces", + "//components/gpu/public/interfaces", + "//components/surfaces/public/interfaces", "//components/webcrypto", "//gin", + "//mandoline/services/navigation/public/interfaces", "//media", "//media/blink", "//media/mojo", @@ -120,12 +124,8 @@ "//third_party/mojo/src/mojo/public/cpp/utility", "//third_party/mojo/src/mojo/public/interfaces/application", "//third_party/mojo_services/src/accessibility/public/interfaces", - "//third_party/mojo_services/src/clipboard/public/interfaces", "//third_party/mojo_services/src/content_handler/public/interfaces", - "//third_party/mojo_services/src/gpu/public/interfaces", - "//third_party/mojo_services/src/input_events/public/interfaces", - "//third_party/mojo_services/src/navigation/public/interfaces", - "//third_party/mojo_services/src/surfaces/public/interfaces", + "//ui/mojo/events:interfaces", "//ui/events", "//ui/events:gesture_detection", "//ui/events/blink", @@ -137,9 +137,9 @@ ] public_deps = [ + "//components/view_manager/public/cpp", "//third_party/WebKit/public:blink", "//third_party/mojo/src/mojo/public/cpp/bindings", - "//third_party/mojo_services/src/view_manager/public/cpp", ":generate_blink_resource_map", ] @@ -178,7 +178,7 @@ sources = [ "android/java/org/chromium/html_viewer/Main.java", ] - jni_package = "mojo/services/html_viewer" + jni_package = "components/html_viewer" } android_library("html_viewer_java_classes") {
diff --git a/components/html_viewer/DEPS b/components/html_viewer/DEPS index c513c40c..ee48acc 100644 --- a/components/html_viewer/DEPS +++ b/components/html_viewer/DEPS
@@ -3,8 +3,13 @@ "+base/test", "+blink/public/resources", "+cc", + "+components/clipboard", + "+components/gpu", + "+components/surfaces", + "+components/view_manager", "+components/webcrypto", "+gin", + "+mandoline/services", "+media", "+mojo/application", "+mojo/cc", @@ -15,12 +20,14 @@ "+net/base", "+net/test/spawned_test_server", "+skia", + "+third_party/WebKit/public", "+third_party/mojo/src/mojo/public", "+third_party/mojo_services/src", - "+third_party/WebKit/public", "+third_party/skia/include", "+ui/base", "+ui/events", "+ui/gfx/geometry", + "+ui/mojo/events", + "+ui/mojo/geometry", "+ui/native_theme", ]
diff --git a/components/html_viewer/blink_basic_type_converters.h b/components/html_viewer/blink_basic_type_converters.h index ad2d08b..7eecace6 100644 --- a/components/html_viewer/blink_basic_type_converters.h +++ b/components/html_viewer/blink_basic_type_converters.h
@@ -9,7 +9,7 @@ #include "third_party/WebKit/public/platform/WebVector.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" -#include "third_party/mojo_services/src/geometry/public/interfaces/geometry.mojom.h" +#include "ui/mojo/geometry/geometry.mojom.h" namespace blink { struct WebRect;
diff --git a/components/html_viewer/blink_input_events_type_converters.cc b/components/html_viewer/blink_input_events_type_converters.cc index 0fd8366..0e8b1d6 100644 --- a/components/html_viewer/blink_input_events_type_converters.cc +++ b/components/html_viewer/blink_input_events_type_converters.cc
@@ -7,7 +7,7 @@ #include "base/logging.h" #include "base/time/time.h" #include "third_party/WebKit/public/web/WebInputEvent.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_event_constants.mojom.h" +#include "ui/mojo/events/input_event_constants.mojom.h" namespace mojo { namespace {
diff --git a/components/html_viewer/blink_input_events_type_converters.h b/components/html_viewer/blink_input_events_type_converters.h index 6ea239c..26247b3 100644 --- a/components/html_viewer/blink_input_events_type_converters.h +++ b/components/html_viewer/blink_input_events_type_converters.h
@@ -6,7 +6,7 @@ #define COMPONENTS_HTML_VIEWER_BLINK_INPUT_EVENTS_TYPE_CONVERTERS_H_ #include "base/memory/scoped_ptr.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" +#include "ui/mojo/events/input_events.mojom.h" namespace blink { class WebInputEvent;
diff --git a/components/html_viewer/blink_platform_impl.cc b/components/html_viewer/blink_platform_impl.cc index 4c4ff85..4f71823 100644 --- a/components/html_viewer/blink_platform_impl.cc +++ b/components/html_viewer/blink_platform_impl.cc
@@ -25,6 +25,7 @@ #include "net/base/net_util.h" #include "third_party/WebKit/public/platform/WebWaitableEvent.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/connect.h" #include "ui/events/gestures/blink/web_gesture_curve_impl.h" namespace html_viewer { @@ -72,8 +73,10 @@ network_service_->GetCookieStore(GetProxy(&cookie_store)); cookie_jar_.reset(new WebCookieJarImpl(cookie_store.Pass())); + mojo::ServiceProviderPtr service_provider; + app->ConnectToService("mojo:core_services", &service_provider); mojo::ClipboardPtr clipboard; - app->ConnectToService("mojo:clipboard", &clipboard); + mojo::ConnectToService(service_provider.get(), &clipboard); clipboard_.reset(new WebClipboardImpl(clipboard.Pass())); } }
diff --git a/components/html_viewer/html_document.cc b/components/html_viewer/html_document.cc index e1b57cf..227dae3 100644 --- a/components/html_viewer/html_document.cc +++ b/components/html_viewer/html_document.cc
@@ -18,6 +18,8 @@ #include "components/html_viewer/web_media_player_factory.h" #include "components/html_viewer/web_storage_namespace_impl.h" #include "components/html_viewer/web_url_loader_impl.h" +#include "components/surfaces/public/interfaces/surfaces.mojom.h" +#include "components/view_manager/public/cpp/view.h" #include "media/blink/webencryptedmediaclient_impl.h" #include "media/cdm/default_cdm_factory.h" #include "media/filters/default_media_permission.h" @@ -37,8 +39,6 @@ #include "third_party/mojo/src/mojo/public/cpp/application/connect.h" #include "third_party/mojo/src/mojo/public/cpp/system/data_pipe.h" #include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkDevice.h"
diff --git a/components/html_viewer/html_document.h b/components/html_viewer/html_document.h index 4068888..1eee3e0 100644 --- a/components/html_viewer/html_document.h +++ b/components/html_viewer/html_document.h
@@ -11,6 +11,10 @@ #include "base/macros.h" #include "components/html_viewer/ax_provider_impl.h" #include "components/html_viewer/touch_handler.h" +#include "components/view_manager/public/cpp/view_manager_client_factory.h" +#include "components/view_manager/public/cpp/view_manager_delegate.h" +#include "components/view_manager/public/cpp/view_observer.h" +#include "mandoline/services/navigation/public/interfaces/navigation.mojom.h" #include "mojo/services/network/public/interfaces/url_loader.mojom.h" #include "third_party/WebKit/public/web/WebFrameClient.h" #include "third_party/WebKit/public/web/WebSandboxFlags.h" @@ -21,10 +25,6 @@ #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_impl.h" #include "third_party/mojo/src/mojo/public/interfaces/application/application.mojom.h" #include "third_party/mojo_services/src/content_handler/public/interfaces/content_handler.mojom.h" -#include "third_party/mojo_services/src/navigation/public/interfaces/navigation.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_observer.h" namespace base { class MessageLoopProxy;
diff --git a/components/html_viewer/touch_handler.cc b/components/html_viewer/touch_handler.cc index e968e602..7e84a1c 100644 --- a/components/html_viewer/touch_handler.cc +++ b/components/html_viewer/touch_handler.cc
@@ -6,10 +6,10 @@ #include "third_party/WebKit/public/web/WebInputEvent.h" #include "third_party/WebKit/public/web/WebView.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" #include "ui/events/blink/blink_event_util.h" #include "ui/events/gesture_detection/gesture_provider_config_helper.h" #include "ui/events/gesture_detection/motion_event_generic.h" +#include "ui/mojo/events/input_events.mojom.h" namespace html_viewer { namespace {
diff --git a/components/html_viewer/web_clipboard_impl.h b/components/html_viewer/web_clipboard_impl.h index f671e31..407ef81 100644 --- a/components/html_viewer/web_clipboard_impl.h +++ b/components/html_viewer/web_clipboard_impl.h
@@ -5,8 +5,8 @@ #ifndef COMPONENTS_HTML_VIEWER_WEB_CLIPBOARD_IMPL_H_ #define COMPONENTS_HTML_VIEWER_WEB_CLIPBOARD_IMPL_H_ +#include "components/clipboard/public/interfaces/clipboard.mojom.h" #include "third_party/WebKit/public/platform/WebClipboard.h" -#include "third_party/mojo_services/src/clipboard/public/interfaces/clipboard.mojom.h" namespace html_viewer {
diff --git a/components/html_viewer/web_layer_tree_view_impl.cc b/components/html_viewer/web_layer_tree_view_impl.cc index 94f1485..f29252a 100644 --- a/components/html_viewer/web_layer_tree_view_impl.cc +++ b/components/html_viewer/web_layer_tree_view_impl.cc
@@ -10,11 +10,11 @@ #include "cc/output/begin_frame_args.h" #include "cc/scheduler/begin_frame_source.h" #include "cc/trees/layer_tree_host.h" +#include "components/view_manager/public/cpp/view.h" #include "mojo/cc/context_provider_mojo.h" #include "mojo/cc/output_surface_mojo.h" #include "mojo/converters/surfaces/surfaces_type_converters.h" #include "third_party/WebKit/public/web/WebWidget.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" namespace html_viewer {
diff --git a/components/html_viewer/web_layer_tree_view_impl.h b/components/html_viewer/web_layer_tree_view_impl.h index b2c352a2..212fc35 100644 --- a/components/html_viewer/web_layer_tree_view_impl.h +++ b/components/html_viewer/web_layer_tree_view_impl.h
@@ -11,10 +11,10 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "cc/trees/layer_tree_host_client.h" +#include "components/gpu/public/interfaces/gpu.mojom.h" +#include "components/surfaces/public/interfaces/surfaces.mojom.h" #include "mojo/cc/output_surface_mojo.h" #include "third_party/WebKit/public/platform/WebLayerTreeView.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/gpu.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom.h" namespace base { class MessageLoopProxy; @@ -103,8 +103,7 @@ const blink::WebLayer* innerViewportScrollLayer, const blink::WebLayer* outerViewportScrollLayer); virtual void clearViewportLayers(); - virtual void registerSelection(const blink::WebSelectionBound& start, - const blink::WebSelectionBound& end) {} + virtual void registerSelection(const blink::WebSelection& selection) {} virtual void clearSelection() {} virtual void setShowFPSCounter(bool) {} virtual void setShowPaintRects(bool) {}
diff --git a/components/html_viewer/web_url_loader_impl.cc b/components/html_viewer/web_url_loader_impl.cc index b4874b2f..f9bd9a2 100644 --- a/components/html_viewer/web_url_loader_impl.cc +++ b/components/html_viewer/web_url_loader_impl.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/logging.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" #include "base/thread_task_runner_handle.h" #include "components/html_viewer/blink_url_request_type_converters.h" @@ -250,8 +251,8 @@ // Send a receive data for each blob item. for (size_t i = 0; i < items.size(); ++i) { - client_->didReceiveData(this, items[i]->data.data(), items[i]->data.size(), - -1); + const int data_size = base::checked_cast<int>(items[i]->data.size()); + client_->didReceiveData(this, items[i]->data.data(), data_size, -1); } // Send a closing finish. @@ -270,7 +271,7 @@ if (rv == MOJO_RESULT_OK) { base::WeakPtr<WebURLLoaderImpl> self(weak_factory_.GetWeakPtr()); client_->didReceiveData(this, static_cast<const char*>(buf), buf_size, -1); - // We may have been deleted durining didReceiveData. + // We may have been deleted during didReceiveData. if (!self) return; EndReadDataRaw(response_body_stream_.get(), buf_size);
diff --git a/components/invalidation/invalidator_storage.cc b/components/invalidation/invalidator_storage.cc index 13ba4b1..cd7ae9c 100644 --- a/components/invalidation/invalidator_storage.cc +++ b/components/invalidation/invalidator_storage.cc
@@ -57,21 +57,14 @@ // static void InvalidatorStorage::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(prefs::kInvalidatorSavedInvalidations, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kInvalidatorInvalidationState, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kInvalidatorClientId, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(prefs::kInvalidatorSavedInvalidations); + registry->RegisterStringPref(prefs::kInvalidatorInvalidationState, + std::string()); + registry->RegisterStringPref(prefs::kInvalidatorClientId, std::string()); // This pref is obsolete. We register it so we can clear it. // At some point in the future, it will be safe to remove this. - registry->RegisterListPref(kInvalidatorMaxInvalidationVersions, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(kInvalidatorMaxInvalidationVersions); } // static
diff --git a/components/keyed_service.gypi b/components/keyed_service.gypi index 22ebf665..06c431c 100644 --- a/components/keyed_service.gypi +++ b/components/keyed_service.gypi
@@ -18,6 +18,8 @@ 'msvs_disabled_warnings': [ 4267, ], 'dependencies': [ '../base/base.gyp:base', + '../base/base.gyp:base_prefs', + 'user_prefs', ], 'sources': [ 'keyed_service/core/dependency_graph.cc', @@ -55,12 +57,10 @@ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations. 'msvs_disabled_warnings': [ 4267, ], 'dependencies': [ - 'keyed_service_core', '../base/base.gyp:base', - '../base/base.gyp:base_prefs', '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../content/content.gyp:content_common', - 'user_prefs', + 'keyed_service_core', ], 'include_dirs': [ '..', @@ -89,7 +89,6 @@ ], 'dependencies': [ '../base/base.gyp:base', - '../base/base.gyp:base_prefs', '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations', '../ios/web/ios_web.gyp:ios_web', 'keyed_service_core', @@ -98,10 +97,10 @@ '..', ], 'sources': [ + 'keyed_service/ios/browser_state_context_converter.cc', + 'keyed_service/ios/browser_state_context_converter.h', 'keyed_service/ios/browser_state_dependency_manager.cc', 'keyed_service/ios/browser_state_dependency_manager.h', - 'keyed_service/ios/browser_state_helper.cc', - 'keyed_service/ios/browser_state_helper.h', 'keyed_service/ios/browser_state_keyed_service_factory.cc', 'keyed_service/ios/browser_state_keyed_service_factory.h', 'keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc',
diff --git a/components/keyed_service/content/BUILD.gn b/components/keyed_service/content/BUILD.gn index 6d3d5b6..dcd0523 100644 --- a/components/keyed_service/content/BUILD.gn +++ b/components/keyed_service/content/BUILD.gn
@@ -26,10 +26,8 @@ deps = [ "//base", - "//base:prefs", "//base/third_party/dynamic_annotations", - "//content/public/common", "//components/keyed_service/core", - "//components/user_prefs", + "//content/public/common", ] }
diff --git a/components/keyed_service/content/browser_context_dependency_manager.cc b/components/keyed_service/content/browser_context_dependency_manager.cc index cc112d3..55978c4 100644 --- a/components/keyed_service/content/browser_context_dependency_manager.cc +++ b/components/keyed_service/content/browser_context_dependency_manager.cc
@@ -19,7 +19,7 @@ #endif // NDEBUG void BrowserContextDependencyManager::RegisterProfilePrefsForServices( - const content::BrowserContext* context, + content::BrowserContext* context, user_prefs::PrefRegistrySyncable* pref_registry) { TRACE_EVENT0( "browser", @@ -77,13 +77,15 @@ return Singleton<BrowserContextDependencyManager>::get(); } -BrowserContextDependencyManager::BrowserContextDependencyManager() {} +BrowserContextDependencyManager::BrowserContextDependencyManager() { +} -BrowserContextDependencyManager::~BrowserContextDependencyManager() {} +BrowserContextDependencyManager::~BrowserContextDependencyManager() { +} #ifndef NDEBUG void BrowserContextDependencyManager::DumpContextDependencies( - const base::SupportsUserData* context) const { + base::SupportsUserData* context) const { // Whenever we try to build a destruction ordering, we should also dump a // dependency graph to "/path/to/context/context-dependencies.dot". if (base::CommandLine::ForCurrentProcess()->HasSwitch(
diff --git a/components/keyed_service/content/browser_context_dependency_manager.h b/components/keyed_service/content/browser_context_dependency_manager.h index 18a273f..4a2fdbc 100644 --- a/components/keyed_service/content/browser_context_dependency_manager.h +++ b/components/keyed_service/content/browser_context_dependency_manager.h
@@ -33,7 +33,7 @@ // a key to prevent multiple registrations on the same BrowserContext in // tests. void RegisterProfilePrefsForServices( - const content::BrowserContext* context, + content::BrowserContext* context, user_prefs::PrefRegistrySyncable* registry); // Called by each BrowserContext to alert us of its creation. Several @@ -91,8 +91,7 @@ #ifndef NDEBUG // DependencyManager: - void DumpContextDependencies( - const base::SupportsUserData* context) const final; + void DumpContextDependencies(base::SupportsUserData* context) const final; #endif // NDEBUG // A list of callbacks to call just before executing
diff --git a/components/keyed_service/content/browser_context_keyed_base_factory.cc b/components/keyed_service/content/browser_context_keyed_base_factory.cc index d09ea4a..fe461ff 100644 --- a/components/keyed_service/content/browser_context_keyed_base_factory.cc +++ b/components/keyed_service/content/browser_context_keyed_base_factory.cc
@@ -4,10 +4,7 @@ #include "components/keyed_service/content/browser_context_keyed_base_factory.h" -#include "base/prefs/pref_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/user_prefs/user_prefs.h" #include "content/public/browser/browser_context.h" BrowserContextKeyedBaseFactory::BrowserContextKeyedBaseFactory( @@ -53,16 +50,6 @@ KeyedServiceBaseFactory::ContextDestroyed(context); } -user_prefs::PrefRegistrySyncable* -BrowserContextKeyedBaseFactory::GetAssociatedPrefRegistry( - base::SupportsUserData* context) const { - PrefService* prefs = user_prefs::UserPrefs::Get(context); - user_prefs::PrefRegistrySyncable* registry = - static_cast<user_prefs::PrefRegistrySyncable*>( - prefs->DeprecatedGetPrefRegistry()); - return registry; -} - base::SupportsUserData* BrowserContextKeyedBaseFactory::GetContextToUse( base::SupportsUserData* context) const { return GetBrowserContextToUse(static_cast<content::BrowserContext*>(context));
diff --git a/components/keyed_service/content/browser_context_keyed_base_factory.h b/components/keyed_service/content/browser_context_keyed_base_factory.h index f747cac..fc5a5d36 100644 --- a/components/keyed_service/content/browser_context_keyed_base_factory.h +++ b/components/keyed_service/content/browser_context_keyed_base_factory.h
@@ -90,7 +90,7 @@ private: // Registers any user preferences on this service. This is called by - // RegisterProfilePrefsIfNecessary() and should be overriden by any service + // RegisterPrefsIfNecessaryForContext() and should be overriden by any service // that wants to register profile-specific preferences. virtual void RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) {} @@ -107,8 +107,6 @@ virtual void CreateServiceNow(content::BrowserContext* context) = 0; // KeyedServiceBaseFactory: - user_prefs::PrefRegistrySyncable* GetAssociatedPrefRegistry( - base::SupportsUserData* context) const final; base::SupportsUserData* GetContextToUse( base::SupportsUserData* context) const final; bool ServiceIsCreatedWithContext() const final;
diff --git a/components/keyed_service/content/browser_context_keyed_service_factory.cc b/components/keyed_service/content/browser_context_keyed_service_factory.cc index 1c61c502c..d7edb8e 100644 --- a/components/keyed_service/content/browser_context_keyed_service_factory.cc +++ b/components/keyed_service/content/browser_context_keyed_service_factory.cc
@@ -5,7 +5,6 @@ #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "base/logging.h" -#include "base/prefs/pref_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/core/keyed_service.h" #include "components/pref_registry/pref_registry_syncable.h" @@ -97,16 +96,6 @@ return static_cast<content::BrowserContext*>(context)->IsOffTheRecord(); } -user_prefs::PrefRegistrySyncable* -BrowserContextKeyedServiceFactory::GetAssociatedPrefRegistry( - base::SupportsUserData* context) const { - PrefService* prefs = user_prefs::UserPrefs::Get(context); - user_prefs::PrefRegistrySyncable* registry = - static_cast<user_prefs::PrefRegistrySyncable*>( - prefs->DeprecatedGetPrefRegistry()); - return registry; -} - base::SupportsUserData* BrowserContextKeyedServiceFactory::GetContextToUse( base::SupportsUserData* context) const { return GetBrowserContextToUse(static_cast<content::BrowserContext*>(context));
diff --git a/components/keyed_service/content/browser_context_keyed_service_factory.h b/components/keyed_service/content/browser_context_keyed_service_factory.h index dde840d..24c3467 100644 --- a/components/keyed_service/content/browser_context_keyed_service_factory.h +++ b/components/keyed_service/content/browser_context_keyed_service_factory.h
@@ -124,7 +124,7 @@ friend class BrowserContextDependencyManagerUnittests; // Registers any user preferences on this service. This is called by - // RegisterProfilePrefsIfNecessary() and should be overriden by any service + // RegisterPrefsIfNecessaryForContext() and should be overriden by any service // that wants to register profile-specific preferences. virtual void RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) {} @@ -135,8 +135,6 @@ bool IsOffTheRecord(base::SupportsUserData* context) const final; // KeyedServiceBaseFactory: - user_prefs::PrefRegistrySyncable* GetAssociatedPrefRegistry( - base::SupportsUserData* context) const final; base::SupportsUserData* GetContextToUse( base::SupportsUserData* context) const final; bool ServiceIsCreatedWithContext() const final;
diff --git a/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.cc b/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.cc index 4d22f5671..7a7a6f07 100644 --- a/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.cc +++ b/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.cc
@@ -5,11 +5,8 @@ #include "components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h" #include "base/logging.h" -#include "base/prefs/pref_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/core/refcounted_keyed_service.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/user_prefs/user_prefs.h" #include "content/public/browser/browser_context.h" void RefcountedBrowserContextKeyedServiceFactory::SetTestingFactory( @@ -102,16 +99,6 @@ return static_cast<content::BrowserContext*>(context)->IsOffTheRecord(); } -user_prefs::PrefRegistrySyncable* -RefcountedBrowserContextKeyedServiceFactory::GetAssociatedPrefRegistry( - base::SupportsUserData* context) const { - PrefService* prefs = user_prefs::UserPrefs::Get(context); - user_prefs::PrefRegistrySyncable* registry = - static_cast<user_prefs::PrefRegistrySyncable*>( - prefs->DeprecatedGetPrefRegistry()); - return registry; -} - base::SupportsUserData* RefcountedBrowserContextKeyedServiceFactory::GetContextToUse( base::SupportsUserData* context) const {
diff --git a/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h b/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h index ca005c2..01fedff 100644 --- a/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h +++ b/components/keyed_service/content/refcounted_browser_context_keyed_service_factory.h
@@ -130,7 +130,7 @@ friend class BrowserContextDependencyManagerUnittests; // Registers any user preferences on this service. This is called by - // RegisterProfilePrefsIfNecessary() and should be overriden by any service + // RegisterPrefsIfNecessaryForContext() and should be overriden by any service // that wants to register profile-specific preferences. virtual void RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) {} @@ -141,8 +141,6 @@ bool IsOffTheRecord(base::SupportsUserData* context) const final; // KeyedServiceBaseFactory: - user_prefs::PrefRegistrySyncable* GetAssociatedPrefRegistry( - base::SupportsUserData* context) const final; base::SupportsUserData* GetContextToUse( base::SupportsUserData* context) const final; bool ServiceIsCreatedWithContext() const final;
diff --git a/components/keyed_service/core/BUILD.gn b/components/keyed_service/core/BUILD.gn index 8585cbb..4c5a6be 100644 --- a/components/keyed_service/core/BUILD.gn +++ b/components/keyed_service/core/BUILD.gn
@@ -32,5 +32,7 @@ deps = [ "//base", + "//base:prefs", + "//components/user_prefs", ] }
diff --git a/components/keyed_service/core/dependency_manager.cc b/components/keyed_service/core/dependency_manager.cc index 7eea3cdc..59cc867 100644 --- a/components/keyed_service/core/dependency_manager.cc +++ b/components/keyed_service/core/dependency_manager.cc
@@ -34,7 +34,7 @@ } void DependencyManager::RegisterPrefsForServices( - const base::SupportsUserData* context, + base::SupportsUserData* context, user_prefs::PrefRegistrySyncable* pref_registry) { std::vector<DependencyNode*> construction_order; if (!dependency_graph_.GetConstructionOrder(&construction_order)) { @@ -44,7 +44,8 @@ for (const auto& dependency_node : construction_order) { KeyedServiceBaseFactory* factory = static_cast<KeyedServiceBaseFactory*>(dependency_node); - factory->RegisterPrefsIfNecessaryForContext(context, pref_registry); + base::SupportsUserData* typed_context = factory->GetTypedContext(context); + factory->RegisterPrefsIfNecessaryForContext(typed_context, pref_registry); } } @@ -66,11 +67,12 @@ for (const auto& dependency_node : construction_order) { KeyedServiceBaseFactory* factory = static_cast<KeyedServiceBaseFactory*>(dependency_node); + base::SupportsUserData* typed_context = factory->GetTypedContext(context); if (is_testing_context && factory->ServiceIsNULLWhileTesting() && - !factory->HasTestingFactory(context)) { - factory->SetEmptyTestingFactory(context); + !factory->HasTestingFactory(typed_context)) { + factory->SetEmptyTestingFactory(typed_context); } else if (factory->ServiceIsCreatedWithContext()) { - factory->CreateServiceNow(context); + factory->CreateServiceNow(typed_context); } } } @@ -89,7 +91,8 @@ for (const auto& dependency_node : destruction_order) { KeyedServiceBaseFactory* factory = static_cast<KeyedServiceBaseFactory*>(dependency_node); - factory->ContextShutdown(context); + base::SupportsUserData* typed_context = factory->GetTypedContext(context); + factory->ContextShutdown(typed_context); } #ifndef NDEBUG @@ -100,13 +103,14 @@ for (const auto& dependency_node : destruction_order) { KeyedServiceBaseFactory* factory = static_cast<KeyedServiceBaseFactory*>(dependency_node); - factory->ContextDestroyed(context); + base::SupportsUserData* typed_context = factory->GetTypedContext(context); + factory->ContextDestroyed(typed_context); } } #ifndef NDEBUG void DependencyManager::AssertContextWasntDestroyed( - const base::SupportsUserData* context) { + base::SupportsUserData* context) { if (dead_context_pointers_.find(context) != dead_context_pointers_.end()) { NOTREACHED() << "Attempted to access a context that was ShutDown(). " << "This is most likely a heap smasher in progress. After " @@ -116,7 +120,7 @@ } void DependencyManager::MarkContextLiveForTesting( - const base::SupportsUserData* context) { + base::SupportsUserData* context) { dead_context_pointers_.erase(context); }
diff --git a/components/keyed_service/core/dependency_manager.h b/components/keyed_service/core/dependency_manager.h index 1cce3976..06e5357 100644 --- a/components/keyed_service/core/dependency_manager.h +++ b/components/keyed_service/core/dependency_manager.h
@@ -45,7 +45,7 @@ // Registers preferences for all services via |registry| associated with // |context| (the association is managed by the embedder). The |context| // is used as a key to prevent multiple registration during tests. - void RegisterPrefsForServices(const base::SupportsUserData* context, + void RegisterPrefsForServices(base::SupportsUserData* context, user_prefs::PrefRegistrySyncable* registry); // Called upon creation of |context| to create services that want to be @@ -68,14 +68,14 @@ #ifndef NDEBUG // Debugging assertion called as part of GetServiceForContext() in debug // mode. This will NOTREACHED() whenever the |context| is considered stale. - void AssertContextWasntDestroyed(const base::SupportsUserData* context); + void AssertContextWasntDestroyed(base::SupportsUserData* context); // Marks |context| as live (i.e., not stale). This method can be called as a // safeguard against |AssertContextWasntDestroyed()| checks going off due to // |context| aliasing am instance from a prior test (i.e., 0xWhatever might // be created, be destroyed, and then a new object might be created at // 0xWhatever). - void MarkContextLiveForTesting(const base::SupportsUserData* context); + void MarkContextLiveForTesting(base::SupportsUserData* context); // Dumps service dependency graph as a Graphviz dot file |dot_file| with a // title |top_level_name|. Helper for |DumpContextDependencies|. @@ -89,7 +89,7 @@ #ifndef NDEBUG // Hook for subclass to dump the dependency graph of service for |context|. virtual void DumpContextDependencies( - const base::SupportsUserData* context) const = 0; + base::SupportsUserData* context) const = 0; #endif // NDEBUG DependencyGraph dependency_graph_; @@ -99,7 +99,7 @@ // These pointers are most likely invalid, but we keep track of their // locations in memory so we can nicely assert if we're asked to do anything // with them. - std::set<const base::SupportsUserData*> dead_context_pointers_; + std::set<base::SupportsUserData*> dead_context_pointers_; #endif // NDEBUG };
diff --git a/components/keyed_service/core/keyed_service_base_factory.cc b/components/keyed_service/core/keyed_service_base_factory.cc index 7157c0e..20ef210 100644 --- a/components/keyed_service/core/keyed_service_base_factory.cc +++ b/components/keyed_service/core/keyed_service_base_factory.cc
@@ -8,6 +8,8 @@ #include "base/supports_user_data.h" #include "base/trace_event/trace_event.h" #include "components/keyed_service/core/dependency_manager.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "components/user_prefs/user_prefs.h" void KeyedServiceBaseFactory::RegisterUserPrefsOnContextForTest( base::SupportsUserData* context) { @@ -35,9 +37,8 @@ // to enforce a uniquenes check here because some tests create one context and // multiple services of the same type attached to that context (serially, not // parallel) and we don't want to register multiple times on the same context. - // This is the purpose of RegisterProfilePrefsIfNecessary() which could be - // replaced directly by RegisterProfilePrefs() if this method is ever phased - // out. + // This is the purpose of RegisterPrefsIfNecessaryForContext() which could be + // replaced directly by RegisterPrefs() if this method is ever phased out. RegisterPrefsIfNecessaryForContext(context, GetAssociatedPrefRegistry(context)); } @@ -60,7 +61,7 @@ } void KeyedServiceBaseFactory::RegisterPrefsIfNecessaryForContext( - const base::SupportsUserData* context, + base::SupportsUserData* context, user_prefs::PrefRegistrySyncable* registry) { if (!ArePreferencesSetOn(context)) { RegisterPrefs(registry); @@ -68,16 +69,29 @@ } } +user_prefs::PrefRegistrySyncable* +KeyedServiceBaseFactory::GetAssociatedPrefRegistry( + base::SupportsUserData* context) const { + PrefService* prefs = + user_prefs::UserPrefs::Get(GetContextForDependencyManager(context)); + user_prefs::PrefRegistrySyncable* registry = + static_cast<user_prefs::PrefRegistrySyncable*>( + prefs->DeprecatedGetPrefRegistry()); + return registry; +} + #ifndef NDEBUG void KeyedServiceBaseFactory::AssertContextWasntDestroyed( - const base::SupportsUserData* context) const { + base::SupportsUserData* context) const { DCHECK(CalledOnValidThread()); + context = GetContextForDependencyManager(context); dependency_manager_->AssertContextWasntDestroyed(context); } void KeyedServiceBaseFactory::MarkContextLiveForTesting( - const base::SupportsUserData* context) { + base::SupportsUserData* context) { DCHECK(CalledOnValidThread()); + context = GetContextForDependencyManager(context); dependency_manager_->MarkContextLiveForTesting(context); } #endif @@ -95,17 +109,28 @@ // While object destruction can be customized in ways where the object is // only dereferenced, this still must run on the UI thread. DCHECK(CalledOnValidThread()); - registered_preferences_.erase(context); } bool KeyedServiceBaseFactory::ArePreferencesSetOn( - const base::SupportsUserData* context) const { + base::SupportsUserData* context) const { return registered_preferences_.find(context) != registered_preferences_.end(); } void KeyedServiceBaseFactory::MarkPreferencesSetOn( - const base::SupportsUserData* context) { + base::SupportsUserData* context) { DCHECK(!ArePreferencesSetOn(context)); registered_preferences_.insert(context); } + +#if defined(OS_IOS) +base::SupportsUserData* KeyedServiceBaseFactory::GetTypedContext( + base::SupportsUserData* context) const { + return context; +} + +base::SupportsUserData* KeyedServiceBaseFactory::GetContextForDependencyManager( + base::SupportsUserData* context) const { + return context; +} +#endif // defined(OS_IOS)
diff --git a/components/keyed_service/core/keyed_service_base_factory.h b/components/keyed_service/core/keyed_service_base_factory.h index a22e940..a9ea21fe 100644 --- a/components/keyed_service/core/keyed_service_base_factory.h +++ b/components/keyed_service/core/keyed_service_base_factory.h
@@ -57,14 +57,14 @@ #ifndef NDEBUG // Debugging assertion that will NOTREACHED() is |context| is considered // stale. Should be used by subclasses when accessing |context|. - void AssertContextWasntDestroyed(const base::SupportsUserData* context) const; + void AssertContextWasntDestroyed(base::SupportsUserData* context) const; // Marks |context| as live (i.e., not stale). This method can be called as a // safeguard against |AssertContextWasntDestroyed()| checks going off due to // |context| aliasing am instance from a prior test (i.e., 0xWhatever might // be created, be destroyed, and then a new object might be created at // 0xWhatever). - void MarkContextLiveForTesting(const base::SupportsUserData* context); + void MarkContextLiveForTesting(base::SupportsUserData* context); #endif // Calls RegisterProfilePrefs() after doing house keeping required to work @@ -72,13 +72,13 @@ // TODO(gab): This method can be replaced by RegisterProfilePrefs() directly // once RegisterUserPrefsOnContextForTest() is phased out. void RegisterPrefsIfNecessaryForContext( - const base::SupportsUserData* context, + base::SupportsUserData* context, user_prefs::PrefRegistrySyncable* registry); // Returns the |user_pref::PrefRegistrySyncable| associated with |context|. // The way they are associated is controlled by the embedder. - virtual user_prefs::PrefRegistrySyncable* GetAssociatedPrefRegistry( - base::SupportsUserData* context) const = 0; + user_prefs::PrefRegistrySyncable* GetAssociatedPrefRegistry( + base::SupportsUserData* context) const; // Finds which context (if any) to use. virtual base::SupportsUserData* GetContextToUse( @@ -109,10 +109,59 @@ virtual void ContextDestroyed(base::SupportsUserData* context); // Returns whether the preferences have been registered on this context. - bool ArePreferencesSetOn(const base::SupportsUserData* context) const; + bool ArePreferencesSetOn(base::SupportsUserData* context) const; // Mark context has having preferences registered. - void MarkPreferencesSetOn(const base::SupportsUserData* context); + void MarkPreferencesSetOn(base::SupportsUserData* context); + + // The iOS code downstream used BrowserContextKeyedServiceFactories. The code + // is currently ported to use BrowserStateKeyedServiceFactories instead but + // has to support mixed dependencies to ease the migration — which can then + // be done incrementally. This means that on iOS the DependencyManager can + // reference both type of factories and the context need to be converted to + // the correct typed context. + // + // GetTypedContext()/GetContextForDependencyManager() are there to supports + // the mixed dependencies. On all platform except iOS they are pass-through + // and returns the original object. On iOS, they convert the context to resp. + // web::BrowserState/content::BrowserContext casted as base::SupportsUserData. + // + // TODO(ios): migration is tracked by http://crbug.com/478763 and those two + // methods (and their *Internal implementation) must be removed once migration + // is complete. + + // Returns the correctly typed context for the KeyedServiceFactory (either a + // content::BrowserContext for BrowserContextKeyedServiceFactory or a + // web::BrowserState for a BrowserStateKeyedServiceFactory) when using mixed + // dependency (iOS). Simple pass-through on all other platforms. + // + // TODO(ios): remove this method and its call-sites once iOS only uses + // BrowserStateKeyedServiceFactories, http://crbug.com/478763 +#if defined(OS_IOS) + virtual base::SupportsUserData* GetTypedContext( + base::SupportsUserData* context) const; +#else + base::SupportsUserData* GetTypedContext( + base::SupportsUserData* context) const { + return context; + } +#endif // defined(OS_IOS) + + // Returns the content::BrowserContext associated to |context| for interaction + // with the DependencyManager when using mixed dependency (iOS). Simple pass- + // through on all other platforms. + // + // TODO(ios): remove this method and its call-sites once iOS only uses + // BrowserStateKeyedServiceFactories, http://crbug.com/478763 +#if defined(OS_IOS) + virtual base::SupportsUserData* GetContextForDependencyManager( + base::SupportsUserData* context) const; +#else + base::SupportsUserData* GetContextForDependencyManager( + base::SupportsUserData* context) const { + return context; + } +#endif // defined(OS_IOS) private: friend class DependencyManager; @@ -135,7 +184,7 @@ virtual void CreateServiceNow(base::SupportsUserData* context) = 0; // Contexts that have this service's preferences registered on them. - std::set<const base::SupportsUserData*> registered_preferences_; + std::set<base::SupportsUserData*> registered_preferences_; #if !defined(NDEBUG) // A static string passed in to the constructor. Should be unique across all
diff --git a/components/keyed_service/ios/DEPS b/components/keyed_service/ios/DEPS index 0bb1ec2..0fc0ddd 100644 --- a/components/keyed_service/ios/DEPS +++ b/components/keyed_service/ios/DEPS
@@ -1,4 +1,3 @@ include_rules = [ - "+components/pref_registry", "+ios/web/public", ]
diff --git a/components/keyed_service/ios/browser_state_context_converter.cc b/components/keyed_service/ios/browser_state_context_converter.cc new file mode 100644 index 0000000..608bb55 --- /dev/null +++ b/components/keyed_service/ios/browser_state_context_converter.cc
@@ -0,0 +1,28 @@ +// 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/keyed_service/ios/browser_state_context_converter.h" + +namespace { + +// Global BrowserStateContextConverter* instance, may be null. +BrowserStateContextConverter* g_browser_state_context_converter = nullptr; + +} // namespace + +// static +void BrowserStateContextConverter::SetInstance( + BrowserStateContextConverter* instance) { + g_browser_state_context_converter = instance; +} + +BrowserStateContextConverter* BrowserStateContextConverter::GetInstance() { + return g_browser_state_context_converter; +} + +BrowserStateContextConverter::BrowserStateContextConverter() { +} + +BrowserStateContextConverter::~BrowserStateContextConverter() { +}
diff --git a/components/keyed_service/ios/browser_state_context_converter.h b/components/keyed_service/ios/browser_state_context_converter.h new file mode 100644 index 0000000..7af647d --- /dev/null +++ b/components/keyed_service/ios/browser_state_context_converter.h
@@ -0,0 +1,55 @@ +// 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_KEYED_SERVICE_IOS_BROWSER_STATE_CONTEXT_CONVERTER_H_ +#define COMPONENTS_KEYED_SERVICE_IOS_BROWSER_STATE_CONTEXT_CONVERTER_H_ + +#include "base/macros.h" + +namespace base { +class SupportsUserData; +} + +// BrowserStateContextConverter does safe conversion of base::SupportsUserData* +// to web::BrowserState* or content::BrowserContext*. +// +// iOS code is still using BrowserContextKeyedServiceFactory and until the +// conversion is complete — http://crbug.com/478763 — there is need to have +// mixed dependency between BCKSF and BSKSF. +// +// The implementation has BrowserStateKeyedServiceFactory supporting a +// BrowserContextDependencyManager as DependencyManager. Thus the context +// parameter passed to the BrowserStateKeyedServiceFactory can either be +// content::BrowserContext if the method is invoked by DependencyManager +// or web::BrowserState if the method is invoked via the type-safe public +// API. +// +// The public API of BrowserStateKeyedServiceFactory is type-safe (all +// public method receive web::BrowserState for context object), so only +// methods that take a base::SupportsUserData need to discriminate +// between the two objects. +class BrowserStateContextConverter { + public: + // Sets/Gets the global BrowserStateContextConverter instance. May return null + // when mixed dependencies are disabled. + static void SetInstance(BrowserStateContextConverter* instance); + static BrowserStateContextConverter* GetInstance(); + + // Converts |context| to a web::BrowserState* and returns it casted as a + // base::SupportsUserData*. + virtual base::SupportsUserData* GetBrowserStateForContext( + base::SupportsUserData* context) = 0; + // Converts |context| to a content::BrowserContext* and returns it casted as a + // base::SupportsUserData*. + virtual base::SupportsUserData* GetBrowserContextForContext( + base::SupportsUserData* context) = 0; + + protected: + BrowserStateContextConverter(); + virtual ~BrowserStateContextConverter(); + + DISALLOW_COPY_AND_ASSIGN(BrowserStateContextConverter); +}; + +#endif // COMPONENTS_KEYED_SERVICE_IOS_BROWSER_STATE_CONTEXT_CONVERTER_H_
diff --git a/components/keyed_service/ios/browser_state_dependency_manager.cc b/components/keyed_service/ios/browser_state_dependency_manager.cc index e5267e3d..d2aa17d4 100644 --- a/components/keyed_service/ios/browser_state_dependency_manager.cc +++ b/components/keyed_service/ios/browser_state_dependency_manager.cc
@@ -13,8 +13,8 @@ return Singleton<BrowserStateDependencyManager>::get(); } -void BrowserStateDependencyManager::RegisterProfilePrefsForServices( - const web::BrowserState* context, +void BrowserStateDependencyManager::RegisterBrowserStatePrefsForServices( + web::BrowserState* context, user_prefs::PrefRegistrySyncable* pref_registry) { RegisterPrefsForServices(context, pref_registry); } @@ -62,6 +62,6 @@ #ifndef NDEBUG void BrowserStateDependencyManager::DumpContextDependencies( - const base::SupportsUserData* context) const { + base::SupportsUserData* context) const { } #endif // NDEBUG
diff --git a/components/keyed_service/ios/browser_state_dependency_manager.h b/components/keyed_service/ios/browser_state_dependency_manager.h index aaca3ba3..c13f4a8 100644 --- a/components/keyed_service/ios/browser_state_dependency_manager.h +++ b/components/keyed_service/ios/browser_state_dependency_manager.h
@@ -34,8 +34,8 @@ // |context| should be the BrowserState containing |registry| and is used as // a key to prevent multiple registrations on the same BrowserState in // tests. - void RegisterProfilePrefsForServices( - const web::BrowserState* context, + void RegisterBrowserStatePrefsForServices( + web::BrowserState* context, user_prefs::PrefRegistrySyncable* registry); // Called by each BrowserState to alert us of its creation. Service that @@ -80,8 +80,7 @@ #ifndef NDEBUG // DependencyManager: - void DumpContextDependencies( - const base::SupportsUserData* context) const final; + void DumpContextDependencies(base::SupportsUserData* context) const final; #endif // NDEBUG DISALLOW_COPY_AND_ASSIGN(BrowserStateDependencyManager);
diff --git a/components/keyed_service/ios/browser_state_helper.cc b/components/keyed_service/ios/browser_state_helper.cc deleted file mode 100644 index c8e39f8e..0000000 --- a/components/keyed_service/ios/browser_state_helper.cc +++ /dev/null
@@ -1,50 +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/keyed_service/ios/browser_state_helper.h" - -#include "base/logging.h" -#include "base/supports_user_data.h" -#include "ios/web/public/browser_state.h" - -// iOS code is still using BrowserContextKeyedServiceFactory and until the -// upstreaming is complete (http://crbug.com/419366) there is need to have -// mixed dependency between BCKSF and BSKSF. -// -// The implementation has BrowserStateKeyedServiceFactory supporting a -// BrowserContextDependencyManager as DependencyManager. Thus the context -// parameter passed to the BrowserStateKeyedServiceFactory can either be -// content::BrowserContext if the method is invoked by DependencyManager -// or web::BrowserState if the method is invoked via the type-safe public -// API. -// -// The public API of BrowserStateKeyedServiceFactory is type-safe (all -// public method receive web::BrowserState for context object), so only -// methods that take a base::SupportsUserData need to discriminate -// between the two objects. -// -// If the base::SupportsUserData is a web::BrowserState then the public -// method web::BrowserState::FromSupportsUserData can do the conversion -// safely. If this method fails then context is content::BrowserContext -// and the methods defined below allow the embedder to provides helper -// to find the associated web::BrowserState (there is a 1:1 mapping). - -namespace { -BrowserStateFromContextFn g_browser_state_from_context = nullptr; -} // namespace - -void SetBrowserStateFromContextHelper(BrowserStateFromContextFn helper) { - g_browser_state_from_context = helper; -} - -web::BrowserState* BrowserStateFromContext(base::SupportsUserData* context) { - web::BrowserState* state = nullptr; - if (context) { - state = web::BrowserState::FromSupportsUserData(context); - if (!state && g_browser_state_from_context) - state = g_browser_state_from_context(context); - DCHECK(state) << "cannot convert context to web::BrowserState"; - } - return state; -}
diff --git a/components/keyed_service/ios/browser_state_helper.h b/components/keyed_service/ios/browser_state_helper.h deleted file mode 100644 index 2c4e0b5c..0000000 --- a/components/keyed_service/ios/browser_state_helper.h +++ /dev/null
@@ -1,32 +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_KEYED_SERVICE_IOS_BROWSER_STATE_HELPER_H_ -#define COMPONENTS_KEYED_SERVICE_IOS_BROWSER_STATE_HELPER_H_ - -namespace base { -class SupportsUserData; -} - -namespace web { -class BrowserState; -} - -// TODO(sdefresne): remove this file and all usage of the methods once iOS code -// only use BrowserStateKeyedServiceFactory, http://crbug.com/419366 - -// |BrowserStateFromContextFn| converts from a base::SupportsUserData as passed -// to a (Refcounted)?BrowserStateKeyedServiceFactory to a web::BrowserState. -using BrowserStateFromContextFn = - web::BrowserState* (*)(base::SupportsUserData*); - -// Registers an helper function to convert a |context| to a web::BrowserState -// to allow the embedder to overrides how the BSKSF does the conversion. -void SetBrowserStateFromContextHelper(BrowserStateFromContextFn helper); - -// Converts a |context| to a web::BrowserState using the helper registered by -// the embedder if any. Usage is restricted to //components/keyed_service/ios. -web::BrowserState* BrowserStateFromContext(base::SupportsUserData* context); - -#endif // COMPONENTS_KEYED_SERVICE_IOS_BROWSER_STATE_HELPER_H_
diff --git a/components/keyed_service/ios/browser_state_keyed_service_factory.cc b/components/keyed_service/ios/browser_state_keyed_service_factory.cc index 3d2b751..c5279912 100644 --- a/components/keyed_service/ios/browser_state_keyed_service_factory.cc +++ b/components/keyed_service/ios/browser_state_keyed_service_factory.cc
@@ -5,12 +5,9 @@ #include "components/keyed_service/ios/browser_state_keyed_service_factory.h" #include "base/logging.h" -#include "base/prefs/pref_service.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/keyed_service/ios/browser_state_context_converter.h" #include "components/keyed_service/ios/browser_state_dependency_manager.h" -#include "components/keyed_service/ios/browser_state_helper.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/user_prefs/user_prefs.h" #include "ios/web/public/browser_state.h" void BrowserStateKeyedServiceFactory::SetTestingFactory( @@ -79,30 +76,46 @@ KeyedService* BrowserStateKeyedServiceFactory::BuildServiceInstanceFor( base::SupportsUserData* context) const { - return BuildServiceInstanceFor(BrowserStateFromContext(context)); + return BuildServiceInstanceFor(static_cast<web::BrowserState*>(context)); } bool BrowserStateKeyedServiceFactory::IsOffTheRecord( base::SupportsUserData* context) const { - return BrowserStateFromContext(context)->IsOffTheRecord(); + return static_cast<web::BrowserState*>(context)->IsOffTheRecord(); } -user_prefs::PrefRegistrySyncable* -BrowserStateKeyedServiceFactory::GetAssociatedPrefRegistry( +#if defined(OS_IOS) +base::SupportsUserData* BrowserStateKeyedServiceFactory::GetTypedContext( base::SupportsUserData* context) const { - // TODO(droger): Move this code to KeyedServiceFactory and share it with the - // other platforms once iOS no longer needs BrowserStateFromContext(). - PrefService* prefs = - user_prefs::UserPrefs::Get(BrowserStateFromContext(context)); - user_prefs::PrefRegistrySyncable* registry = - static_cast<user_prefs::PrefRegistrySyncable*>( - prefs->DeprecatedGetPrefRegistry()); - return registry; + if (context) { + BrowserStateContextConverter* context_converter = + BrowserStateContextConverter::GetInstance(); + if (context_converter) { + context = context_converter->GetBrowserStateForContext(context); + DCHECK(context); + } + } + return context; } +base::SupportsUserData* +BrowserStateKeyedServiceFactory::GetContextForDependencyManager( + base::SupportsUserData* context) const { + if (context) { + BrowserStateContextConverter* context_converter = + BrowserStateContextConverter::GetInstance(); + if (context_converter) { + context = context_converter->GetBrowserContextForContext(context); + DCHECK(context); + } + } + return context; +} +#endif // defined(OS_IOS) + base::SupportsUserData* BrowserStateKeyedServiceFactory::GetContextToUse( base::SupportsUserData* context) const { - return GetBrowserStateToUse(BrowserStateFromContext(context)); + return GetBrowserStateToUse(static_cast<web::BrowserState*>(context)); } bool BrowserStateKeyedServiceFactory::ServiceIsCreatedWithContext() const { @@ -111,15 +124,15 @@ void BrowserStateKeyedServiceFactory::ContextShutdown( base::SupportsUserData* context) { - BrowserStateShutdown(BrowserStateFromContext(context)); + BrowserStateShutdown(static_cast<web::BrowserState*>(context)); } void BrowserStateKeyedServiceFactory::ContextDestroyed( base::SupportsUserData* context) { - BrowserStateDestroyed(BrowserStateFromContext(context)); + BrowserStateDestroyed(static_cast<web::BrowserState*>(context)); } void BrowserStateKeyedServiceFactory::RegisterPrefs( user_prefs::PrefRegistrySyncable* registry) { - RegisterProfilePrefs(registry); + RegisterBrowserStatePrefs(registry); }
diff --git a/components/keyed_service/ios/browser_state_keyed_service_factory.h b/components/keyed_service/ios/browser_state_keyed_service_factory.h index 9f3d366..7341aa19 100644 --- a/components/keyed_service/ios/browser_state_keyed_service_factory.h +++ b/components/keyed_service/ios/browser_state_keyed_service_factory.h
@@ -108,9 +108,9 @@ private: // Registers any user preferences on this service. This is called by - // RegisterProfilePrefsIfNecessary() and should be overriden by any service + // RegisterPrefsIfNecessaryForContext() and should be overriden by any service // that wants to register profile-specific preferences. - virtual void RegisterProfilePrefs( + virtual void RegisterBrowserStatePrefs( user_prefs::PrefRegistrySyncable* registry) {} // KeyedServiceFactory: @@ -119,8 +119,12 @@ bool IsOffTheRecord(base::SupportsUserData* context) const final; // KeyedServiceBaseFactory: - user_prefs::PrefRegistrySyncable* GetAssociatedPrefRegistry( - base::SupportsUserData* context) const final; +#if defined(OS_IOS) + base::SupportsUserData* GetTypedContext( + base::SupportsUserData* context) const override; + base::SupportsUserData* GetContextForDependencyManager( + base::SupportsUserData* context) const override; +#endif // defined(OS_IOS) base::SupportsUserData* GetContextToUse( base::SupportsUserData* context) const final; bool ServiceIsCreatedWithContext() const final;
diff --git a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc index 26828c0..3de6b2f 100644 --- a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc +++ b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.cc
@@ -6,8 +6,8 @@ #include "base/logging.h" #include "components/keyed_service/core/refcounted_keyed_service.h" +#include "components/keyed_service/ios/browser_state_context_converter.h" #include "components/keyed_service/ios/browser_state_dependency_manager.h" -#include "components/keyed_service/ios/browser_state_helper.h" #include "ios/web/public/browser_state.h" void RefcountedBrowserStateKeyedServiceFactory::SetTestingFactory( @@ -86,25 +86,48 @@ scoped_refptr<RefcountedKeyedService> RefcountedBrowserStateKeyedServiceFactory::BuildServiceInstanceFor( base::SupportsUserData* context) const { - return BuildServiceInstanceFor(BrowserStateFromContext(context)); + return BuildServiceInstanceFor(static_cast<web::BrowserState*>(context)); } bool RefcountedBrowserStateKeyedServiceFactory::IsOffTheRecord( base::SupportsUserData* context) const { - return BrowserStateFromContext(context)->IsOffTheRecord(); + return static_cast<web::BrowserState*>(context)->IsOffTheRecord(); } -user_prefs::PrefRegistrySyncable* -RefcountedBrowserStateKeyedServiceFactory::GetAssociatedPrefRegistry( +#if defined(OS_IOS) +base::SupportsUserData* +RefcountedBrowserStateKeyedServiceFactory::GetTypedContext( base::SupportsUserData* context) const { - NOTREACHED(); - return nullptr; + if (context) { + BrowserStateContextConverter* context_converter = + BrowserStateContextConverter::GetInstance(); + if (context_converter) { + context = context_converter->GetBrowserStateForContext(context); + DCHECK(context); + } + } + return context; } base::SupportsUserData* +RefcountedBrowserStateKeyedServiceFactory::GetContextForDependencyManager( + base::SupportsUserData* context) const { + if (context) { + BrowserStateContextConverter* context_converter = + BrowserStateContextConverter::GetInstance(); + if (context_converter) { + context = context_converter->GetBrowserContextForContext(context); + DCHECK(context); + } + } + return context; +} +#endif // defined(OS_IOS) + +base::SupportsUserData* RefcountedBrowserStateKeyedServiceFactory::GetContextToUse( base::SupportsUserData* context) const { - return GetBrowserStateToUse(BrowserStateFromContext(context)); + return GetBrowserStateToUse(static_cast<web::BrowserState*>(context)); } bool RefcountedBrowserStateKeyedServiceFactory::ServiceIsCreatedWithContext() @@ -114,15 +137,15 @@ void RefcountedBrowserStateKeyedServiceFactory::ContextShutdown( base::SupportsUserData* context) { - BrowserStateShutdown(BrowserStateFromContext(context)); + BrowserStateShutdown(static_cast<web::BrowserState*>(context)); } void RefcountedBrowserStateKeyedServiceFactory::ContextDestroyed( base::SupportsUserData* context) { - BrowserStateDestroyed(BrowserStateFromContext(context)); + BrowserStateDestroyed(static_cast<web::BrowserState*>(context)); } void RefcountedBrowserStateKeyedServiceFactory::RegisterPrefs( user_prefs::PrefRegistrySyncable* registry) { - RegisterProfilePrefs(registry); + RegisterBrowserStatePrefs(registry); }
diff --git a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h index fae4b53..e5fe8477 100644 --- a/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h +++ b/components/keyed_service/ios/refcounted_browser_state_keyed_service_factory.h
@@ -115,9 +115,9 @@ private: // Registers any user preferences on this service. This is called by - // RegisterProfilePrefsIfNecessary() and should be overriden by any service + // RegisterPrefsIfNecessaryForContext() and should be overriden by any service // that wants to register profile-specific preferences. - virtual void RegisterProfilePrefs( + virtual void RegisterBrowserStatePrefs( user_prefs::PrefRegistrySyncable* registry) {} // RefcountedKeyedServiceFactory: @@ -126,8 +126,12 @@ bool IsOffTheRecord(base::SupportsUserData* context) const final; // KeyedServiceBaseFactory: - user_prefs::PrefRegistrySyncable* GetAssociatedPrefRegistry( - base::SupportsUserData* context) const final; +#if defined(OS_IOS) + base::SupportsUserData* GetTypedContext( + base::SupportsUserData* context) const override; + base::SupportsUserData* GetContextForDependencyManager( + base::SupportsUserData* context) const override; +#endif // defined(OS_IOS) base::SupportsUserData* GetContextToUse( base::SupportsUserData* context) const final; bool ServiceIsCreatedWithContext() const final;
diff --git a/components/kiosk_wm/BUILD.gn b/components/kiosk_wm/BUILD.gn index 2e41546..70c1d54 100644 --- a/components/kiosk_wm/BUILD.gn +++ b/components/kiosk_wm/BUILD.gn
@@ -3,7 +3,7 @@ # found in the LICENSE file. import("//third_party/mojo/src/mojo/public/mojo_application.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") # Mojo shell in chromium is only used for Mandoline, and Mandoline only uses # kiosk_wm, so we name the target window_manager to avoid having to remap on the @@ -21,17 +21,16 @@ deps = [ "//base", + "//components/view_manager/public/cpp", "//components/window_manager:lib", + "//mandoline/services/navigation/public/interfaces", "//mojo/application", "//mojo/common:common", "//mojo/converters/geometry", - "//mojo/converters/input_events", "//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/public/cpp/utility", "//third_party/mojo/src/mojo/public/interfaces/application", - "//third_party/mojo_services/src/input_events/public/interfaces", - "//third_party/mojo_services/src/navigation/public/interfaces", - "//third_party/mojo_services/src/view_manager/public/cpp", - "//ui/base", + "//ui/gfx/geometry", + "//ui/mojo/events:interfaces", ] }
diff --git a/components/kiosk_wm/DEPS b/components/kiosk_wm/DEPS index f170cf72..86063497 100644 --- a/components/kiosk_wm/DEPS +++ b/components/kiosk_wm/DEPS
@@ -1,5 +1,7 @@ include_rules = [ + "+components/view_manager", "+components/window_manager", + "+mandoline/services", "+mojo/application", "+mojo/common", "+third_party/mojo/src/mojo/public",
diff --git a/components/kiosk_wm/OWNERS b/components/kiosk_wm/OWNERS new file mode 100644 index 0000000..e6a7642f --- /dev/null +++ b/components/kiosk_wm/OWNERS
@@ -0,0 +1,4 @@ +ben@chromium.org +erg@chromium.org +msw@chromium.org +sky@chromium.org
diff --git a/components/kiosk_wm/kiosk_wm.cc b/components/kiosk_wm/kiosk_wm.cc index 83331b7e..88fe5f55 100644 --- a/components/kiosk_wm/kiosk_wm.cc +++ b/components/kiosk_wm/kiosk_wm.cc
@@ -7,7 +7,7 @@ #include "base/command_line.h" #include "base/strings/utf_string_conversions.h" #include "components/kiosk_wm/merged_service_provider.h" -#include "components/window_manager/basic_focus_rules.h" +#include "ui/gfx/geometry/size.h" namespace kiosk_wm { @@ -77,11 +77,8 @@ root_->AddChild(content_); content_->SetVisible(true); - window_manager_app_->InitFocus( - make_scoped_ptr(new window_manager::BasicFocusRules(root_))); - window_manager_app_->accelerator_manager()->Register( - ui::Accelerator(ui::VKEY_BROWSER_BACK, 0), - ui::AcceleratorManager::kNormalPriority, this); + window_manager_app_->AddAccelerator(mojo::KEYBOARD_CODE_BROWSER_BACK, + mojo::EVENT_FLAGS_NONE); // Now that we're ready, either load a pending url or the default url. if (!pending_url_.empty()) @@ -109,6 +106,13 @@ navigator_host_.RecordNavigation(url); } +void KioskWM::OnAcceleratorPressed(mojo::View* view, + mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) { + DCHECK_EQ(mojo::KEYBOARD_CODE_BROWSER_BACK, keyboard_code); + navigator_host_.RequestNavigateHistory(-1); +} + void KioskWM::Create(mojo::ApplicationConnection* connection, mojo::InterfaceRequest<mojo::NavigatorHost> request) { navigator_host_.Bind(request.Pass()); @@ -134,15 +138,4 @@ Embed(url, nullptr, nullptr); } -bool KioskWM::AcceleratorPressed(const ui::Accelerator& accelerator) { - if (accelerator.key_code() != ui::VKEY_BROWSER_BACK) - return false; - navigator_host_.RequestNavigateHistory(-1); - return true; -} - -bool KioskWM::CanHandleAccelerators() const { - return true; -} - } // namespace kiosk_wm
diff --git a/components/kiosk_wm/kiosk_wm.h b/components/kiosk_wm/kiosk_wm.h index 2d3def0..e4be9b6 100644 --- a/components/kiosk_wm/kiosk_wm.h +++ b/components/kiosk_wm/kiosk_wm.h
@@ -7,18 +7,17 @@ #include "base/memory/weak_ptr.h" #include "components/kiosk_wm/navigator_host_impl.h" +#include "components/view_manager/public/cpp/view_manager.h" +#include "components/view_manager/public/cpp/view_manager_delegate.h" +#include "components/view_manager/public/cpp/view_observer.h" #include "components/window_manager/window_manager_app.h" #include "components/window_manager/window_manager_delegate.h" +#include "mandoline/services/navigation/public/interfaces/navigation.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" #include "third_party/mojo/src/mojo/public/cpp/application/connect.h" #include "third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" -#include "third_party/mojo_services/src/navigation/public/interfaces/navigation.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_observer.h" -#include "ui/base/accelerators/accelerator.h" +#include "ui/mojo/events/input_events.mojom.h" namespace kiosk_wm { @@ -28,8 +27,7 @@ public mojo::ViewManagerDelegate, public mojo::ViewObserver, public window_manager::WindowManagerDelegate, - public mojo::InterfaceFactory<mojo::NavigatorHost>, - public ui::AcceleratorTarget { + public mojo::InterfaceFactory<mojo::NavigatorHost> { public: KioskWM(); ~KioskWM() override; @@ -62,15 +60,14 @@ void Embed(const mojo::String& url, mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::ServiceProviderPtr exposed_services) override; + void OnAcceleratorPressed(mojo::View* view, + mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) override; // Overridden from mojo::InterfaceFactory<mojo::NavigatorHost>: void Create(mojo::ApplicationConnection* connection, mojo::InterfaceRequest<mojo::NavigatorHost> request) override; - // Overriden from ui::AcceleratorTarget: - bool AcceleratorPressed(const ui::Accelerator& accelerator) override; - bool CanHandleAccelerators() const override; - scoped_ptr<window_manager::WindowManagerApp> window_manager_app_; // Only support being embedded once, so both application-level
diff --git a/components/kiosk_wm/merged_service_provider.h b/components/kiosk_wm/merged_service_provider.h index 1606ea81..c6280787 100644 --- a/components/kiosk_wm/merged_service_provider.h +++ b/components/kiosk_wm/merged_service_provider.h
@@ -6,10 +6,10 @@ #define COMPONENTS_KIOSK_WM_MERGED_SERVICE_PROVIDER_H_ #include "base/memory/scoped_ptr.h" +#include "mandoline/services/navigation/public/interfaces/navigation.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/application/interface_factory.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" #include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" -#include "third_party/mojo_services/src/navigation/public/interfaces/navigation.mojom.h" namespace kiosk_wm {
diff --git a/components/kiosk_wm/navigator_host_impl.h b/components/kiosk_wm/navigator_host_impl.h index 283d4ab6..5762adca 100644 --- a/components/kiosk_wm/navigator_host_impl.h +++ b/components/kiosk_wm/navigator_host_impl.h
@@ -6,9 +6,9 @@ #define COMPONENTS_KIOSK_WM_NAVIGATOR_HOST_IMPL_H_ #include "base/memory/weak_ptr.h" +#include "mandoline/services/navigation/public/interfaces/navigation.mojom.h" #include "mojo/common/weak_binding_set.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" -#include "third_party/mojo_services/src/navigation/public/interfaces/navigation.mojom.h" namespace kiosk_wm { class KioskWM;
diff --git a/components/metrics.gypi b/components/metrics.gypi index ddad096..45a36d1 100644 --- a/components/metrics.gypi +++ b/components/metrics.gypi
@@ -148,6 +148,7 @@ 'metrics/profiler/profiler_metrics_provider.h', 'metrics/profiler/tracking_synchronizer.cc', 'metrics/profiler/tracking_synchronizer.h', + 'metrics/profiler/tracking_synchronizer_observer.cc', 'metrics/profiler/tracking_synchronizer_observer.h', ], },
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index 1c7301ca2..47dc5be 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -120,6 +120,7 @@ "profiler/profiler_metrics_provider.h", "profiler/tracking_synchronizer.cc", "profiler/tracking_synchronizer.h", + "profiler/tracking_synchronizer_observer.cc", "profiler/tracking_synchronizer_observer.h", ]
diff --git a/components/metrics/net/network_metrics_provider.cc b/components/metrics/net/network_metrics_provider.cc index e845cde5..954df23a 100644 --- a/components/metrics/net/network_metrics_provider.cc +++ b/components/metrics/net/network_metrics_provider.cc
@@ -49,10 +49,13 @@ wifi_phy_layer_protocol_is_ambiguous_); network->set_wifi_phy_layer_protocol(GetWifiPHYLayerProtocol()); - // Resets the "ambiguous" flags, since a new metrics log session has started. - connection_type_is_ambiguous_ = false; - // TODO(isherman): This line seems unnecessary. + // Update the connection type. Note that this is necessary to set the network + // type to "none" if there is no network connection for an entire UMA logging + // window, since OnConnectionTypeChanged() ignores transitions to the "none" + // state. connection_type_ = net::NetworkChangeNotifier::GetConnectionType(); + // Reset the "ambiguous" flags, since a new metrics log session has started. + connection_type_is_ambiguous_ = false; wifi_phy_layer_protocol_is_ambiguous_ = false; if (!wifi_access_point_info_provider_.get()) { @@ -73,8 +76,15 @@ void NetworkMetricsProvider::OnConnectionTypeChanged( net::NetworkChangeNotifier::ConnectionType type) { + // To avoid reporting an ambiguous connection type for users on flaky + // connections, ignore transitions to the "none" state. Note that the + // connection type is refreshed in ProvideSystemProfileMetrics() each time a + // new UMA logging window begins, so users who genuinely transition to offline + // mode for an extended duration will still be at least partially represented + // in the metrics logs. if (type == net::NetworkChangeNotifier::CONNECTION_NONE) return; + if (type != connection_type_ && connection_type_ != net::NetworkChangeNotifier::CONNECTION_NONE) { connection_type_is_ambiguous_ = true;
diff --git a/components/metrics/profiler/tracking_synchronizer.cc b/components/metrics/profiler/tracking_synchronizer.cc index ad36441..ac91b3d 100644 --- a/components/metrics/profiler/tracking_synchronizer.cc +++ b/components/metrics/profiler/tracking_synchronizer.cc
@@ -180,11 +180,12 @@ // TrackingSynchronizer methods and members. -TrackingSynchronizer::TrackingSynchronizer(base::TimeTicks now) - : last_used_sequence_number_(kNeverUsableSequenceNumber), start_time_(now) { +TrackingSynchronizer::TrackingSynchronizer(scoped_ptr<base::TickClock> clock) + : last_used_sequence_number_(kNeverUsableSequenceNumber), + clock_(clock.Pass()) { DCHECK(!g_tracking_synchronizer); g_tracking_synchronizer = this; - phase_start_times_.push_back(now); + phase_start_times_.push_back(clock_->NowTicks()); #if !defined(OS_IOS) // TODO: This ifdef and other ifdefs for OS_IOS in this file are only @@ -227,6 +228,20 @@ base::TimeDelta::FromMinutes(1)); } +// static +void TrackingSynchronizer::OnProfilingPhaseCompleted( + ProfilerEventProto::ProfilerEvent profiling_event) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (!g_tracking_synchronizer) { + // System teardown is happening. + return; + } + + g_tracking_synchronizer->NotifyAllProcessesOfProfilingPhaseCompletion( + profiling_event); +} + void TrackingSynchronizer::OnPendingProcesses(int sequence_number, int pending_processes, bool end) { @@ -261,24 +276,63 @@ // Increment pending process count for sending browser's profiler data. request->IncrementProcessesPending(); + const int current_profiling_phase = phase_completion_events_sequence_.size(); + #if !defined(OS_IOS) // Get profiler data from renderer and browser child processes. - content::ProfilerController::GetInstance()->GetProfilerData(sequence_number); + content::ProfilerController::GetInstance()->GetProfilerData( + sequence_number, current_profiling_phase); #endif // Send process data snapshot from browser process. tracked_objects::ProcessDataSnapshot process_data_snapshot; - tracked_objects::ThreadData::Snapshot(&process_data_snapshot); + tracked_objects::ThreadData::Snapshot(current_profiling_phase, + &process_data_snapshot); + DecrementPendingProcessesAndSendData(sequence_number, process_data_snapshot, content::PROCESS_TYPE_BROWSER); return sequence_number; } +void TrackingSynchronizer::RegisterPhaseCompletion( + ProfilerEventProto::ProfilerEvent profiling_event) { + phase_completion_events_sequence_.push_back(profiling_event); + phase_start_times_.push_back(clock_->NowTicks()); +} + +void TrackingSynchronizer::NotifyAllProcessesOfProfilingPhaseCompletion( + ProfilerEventProto::ProfilerEvent profiling_event) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (variations::GetVariationParamValue("UMALogPhasedProfiling", + "send_split_profiles") == "false") { + return; + } + + int profiling_phase = phase_completion_events_sequence_.size(); + + // If you hit this check, stop and think. You just added a new profiling + // phase. Each profiling phase takes additional memory in DeathData's list of + // snapshots. We cannot grow it indefinitely. Consider collapsing older phases + // after they were sent to UMA server, or other ways to save memory. + DCHECK_LT(profiling_phase, 1); + + RegisterPhaseCompletion(profiling_event); + +#if !defined(OS_IOS) + // Notify renderer and browser child processes. + content::ProfilerController::GetInstance()->OnProfilingPhaseCompleted( + profiling_phase); +#endif + + // Notify browser process. + tracked_objects::ThreadData::OnProfilingPhaseCompleted(profiling_phase); +} + void TrackingSynchronizer::SendData( const tracked_objects::ProcessDataSnapshot& profiler_data, content::ProcessType process_type, - base::TimeTicks now, TrackingSynchronizerObserver* observer) const { // We are going to loop though past profiling phases and notify the request // about each phase that is contained in profiler_data. past_events @@ -290,20 +344,19 @@ // comparison. for (size_t phase = 0; phase <= phase_completion_events_sequence_.size(); ++phase) { - auto it = profiler_data.phased_process_data_snapshots.find(phase); + auto it = profiler_data.phased_snapshots.find(phase); - if (it != profiler_data.phased_process_data_snapshots.end()) { + if (it != profiler_data.phased_snapshots.end()) { // If the phase is contained in the received snapshot, notify the // request. - const base::TimeDelta phase_start = - phase_start_times_[phase] - start_time_; - const base::TimeDelta phase_finish = - (phase + 1 < phase_start_times_.size() ? phase_start_times_[phase + 1] - : now) - - start_time_; - observer->ReceivedProfilerData(it->second, profiler_data.process_id, - process_type, phase, phase_start, - phase_finish, past_events); + const base::TimeTicks phase_start = phase_start_times_[phase]; + const base::TimeTicks phase_finish = phase + 1 < phase_start_times_.size() + ? phase_start_times_[phase + 1] + : clock_->NowTicks(); + observer->ReceivedProfilerData( + ProfilerDataAttributes(phase, profiler_data.process_id, process_type, + phase_start, phase_finish), + it->second, past_events); } if (phase < phase_completion_events_sequence_.size()) { @@ -324,7 +377,7 @@ TrackingSynchronizerObserver* observer = request->callback_object_.get(); if (observer) - SendData(profiler_data, process_type, base::TimeTicks::Now(), observer); + SendData(profiler_data, process_type, observer); // Delete request if we have heard back from all child processes. request->DecrementProcessesPending();
diff --git a/components/metrics/profiler/tracking_synchronizer.h b/components/metrics/profiler/tracking_synchronizer.h index 590f3c32..f7158cb 100644 --- a/components/metrics/profiler/tracking_synchronizer.h +++ b/components/metrics/profiler/tracking_synchronizer.h
@@ -13,6 +13,7 @@ #include "base/lazy_instance.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/time/tick_clock.h" #include "base/time/time.h" #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" #include "content/public/browser/profiler_subscriber.h" @@ -43,9 +44,9 @@ // Construction also sets up the global singleton instance. This instance is // used to communicate between the IO and UI thread, and is destroyed only as // the main thread (browser_main) terminates, which means the IO thread has - // already completed, and will not need this instance any further. |now| is - // the current time, but can be something else in tests. - explicit TrackingSynchronizer(base::TimeTicks now); + // already completed, and will not need this instance any further. + // |clock| is a clock used for durations of profiling phases. + explicit TrackingSynchronizer(scoped_ptr<base::TickClock> clock); // Contact all processes, and get them to upload to the browser any/all // changes to profiler data. It calls |callback_object|'s SetData method with @@ -54,6 +55,11 @@ static void FetchProfilerDataAsynchronously( const base::WeakPtr<TrackingSynchronizerObserver>& callback_object); + // Called when a profiling phase completes. |profiling_event| is the event + // that triggered the completion of the current phase, and begins a new phase. + static void OnProfilingPhaseCompleted( + ProfilerEventProto::ProfilerEvent profiling_event); + // ------------------------------------------------------ // ProfilerSubscriber methods for browser child processes // ------------------------------------------------------ @@ -64,15 +70,24 @@ int pending_processes, bool end) override; + protected: + ~TrackingSynchronizer() override; + + // Update the sequence of completed phases with a new phase completion info. + void RegisterPhaseCompletion( + ProfilerEventProto::ProfilerEvent profiling_event); + + // Notify |observer| about |profiler_data| received from process of type + // |process_type|. + void SendData(const tracked_objects::ProcessDataSnapshot& profiler_data, + content::ProcessType process_type, + TrackingSynchronizerObserver* observer) const; + private: friend class base::RefCountedThreadSafe<TrackingSynchronizer>; - // TODO(vadimt): Remove friending TrackingSynchronizerTest_ProfilerData_Test. - friend class TrackingSynchronizerTest_ProfilerData_Test; class RequestContext; - ~TrackingSynchronizer() override; - // Send profiler_data back to callback_object_ by calling // DecrementPendingProcessesAndSendData which records that we are waiting // for one less profiler data from renderer or browser child process for the @@ -89,13 +104,10 @@ int RegisterAndNotifyAllProcesses( const base::WeakPtr<TrackingSynchronizerObserver>& callback_object); - // Notify |observer| about |profiler_data| received from process of type - // |process_type|. |now| is the current time, but can be something else in - // tests. - void SendData(const tracked_objects::ProcessDataSnapshot& profiler_data, - content::ProcessType process_type, - base::TimeTicks now, - TrackingSynchronizerObserver* observer) const; + // Notifies all processes of a completion of a profiling phase. + // |profiling_event| is the event associated with the phase change. + void NotifyAllProcessesOfProfilingPhaseCompletion( + ProfilerEventProto::ProfilerEvent profiling_event); // It finds the RequestContext for the given |sequence_number| and notifies // the RequestContext's |callback_object_| about the |value|. This is called @@ -127,10 +139,8 @@ std::vector<ProfilerEventProto::ProfilerEvent> phase_completion_events_sequence_; - // TODO(vadimt): consider moving 2 fields below to metrics service. - // Time of the profiling start. Used to calculate times of phase change - // moments relative to this value. - const base::TimeTicks start_time_; + // Clock for profiling phase durations. + const scoped_ptr<base::TickClock> clock_; // Times of starts of all profiling phases, including the current phase. The // index in the vector is the phase number.
diff --git a/components/metrics/profiler/tracking_synchronizer_observer.cc b/components/metrics/profiler/tracking_synchronizer_observer.cc new file mode 100644 index 0000000..39309d3f --- /dev/null +++ b/components/metrics/profiler/tracking_synchronizer_observer.cc
@@ -0,0 +1,22 @@ +// Copyright (c) 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/profiler/tracking_synchronizer_observer.h" + +namespace metrics { + +ProfilerDataAttributes::ProfilerDataAttributes( + int profiling_phase, + base::ProcessId process_id, + content::ProcessType process_type, + base::TimeTicks phase_start, + base::TimeTicks phase_finish) + : profiling_phase(profiling_phase), + process_id(process_id), + process_type(process_type), + phase_start(phase_start), + phase_finish(phase_finish) { +} + +} // namespace metrics
diff --git a/components/metrics/profiler/tracking_synchronizer_observer.h b/components/metrics/profiler/tracking_synchronizer_observer.h index 0e94350..c9f88a73 100644 --- a/components/metrics/profiler/tracking_synchronizer_observer.h +++ b/components/metrics/profiler/tracking_synchronizer_observer.h
@@ -8,6 +8,7 @@ #include <vector> #include "base/process/process_handle.h" +#include "base/time/time.h" #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" #include "content/public/common/process_type.h" @@ -26,31 +27,46 @@ // efficient. typedef std::vector<ProfilerEventProto::ProfilerEvent> ProfilerEvents; +// Attributes of profiler data passed to +// TrackingSynchronizerObserver::ReceivedProfilerData. +struct ProfilerDataAttributes { + ProfilerDataAttributes(int profiling_phase, + base::ProcessId process_id, + content::ProcessType process_type, + base::TimeTicks phase_start, + base::TimeTicks phase_finish); + + // 0-indexed profiling phase number. + const int profiling_phase; + + // ID of the process that reported the data. + const base::ProcessId process_id; + + // Type of the process that reported the data. + const content::ProcessType process_type; + + // Time of the profiling phase start. + const base::TimeTicks phase_start; + + // Time of the profiling phase finish. + const base::TimeTicks phase_finish; +}; + // Observer for notifications from the TrackingSynchronizer class. class TrackingSynchronizerObserver { public: - // TODO(vadimt): Consider isherman@ idea: I'd change the phase_start and - // phase_finish from TimeDeltas to TimeTicks. And I'd omit the |past_events| - // list -- either in favor of a single ProfilerEvent that corresponds to the - // phase, or a method on the TrackingSynchronizer that can translate a - // profiling_phase to a ProfilerEvent. - - // Received |process_data_phase| for profiling phase |profiling_phase| from a - // single process of |process_type|. The phase start and finish times, - // relative to the start time are |phase_start| and - // |phase_finish|. All profiling phases prior to the reported one have already - // completed, and each completion was associated with an instance of - // ProfilerEventProto::ProfilerEvent. |past_events| contains events associated - // with completions of phases prior to the reported one. + // Received |process_data_phase| for profiling phase and process defined by + // |attributes|. + // Each completed phase is associated with an event that triggered the + // completion of the phase. |past_events| contains the set of events that + // completed prior to the reported phase. This data structure is useful for + // quickly computing the full set of profiled traces that occurred before or + // after a given event. // The observer should assume there might be more data coming until // FinishedReceivingData() is called. virtual void ReceivedProfilerData( + const ProfilerDataAttributes& attributes, const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, - base::ProcessId process_id, - content::ProcessType process_type, - int profiling_phase, - base::TimeDelta phase_start, - base::TimeDelta phase_finish, const ProfilerEvents& past_events) = 0; // The observer should not expect any more calls to |ReceivedProfilerData()|
diff --git a/components/metrics/profiler/tracking_synchronizer_unittest.cc b/components/metrics/profiler/tracking_synchronizer_unittest.cc index a597a47..7e02937 100644 --- a/components/metrics/profiler/tracking_synchronizer_unittest.cc +++ b/components/metrics/profiler/tracking_synchronizer_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/memory/ref_counted.h" +#include "base/test/simple_test_tick_clock.h" #include "base/tracked_objects.h" #include "components/metrics/profiler/tracking_synchronizer.h" #include "components/metrics/profiler/tracking_synchronizer_observer.h" @@ -26,24 +27,23 @@ } void ReceivedProfilerData( + const ProfilerDataAttributes& attributes, const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, - base::ProcessId process_id, - content::ProcessType process_type, - int profiling_phase, - base::TimeDelta phase_start, - base::TimeDelta phase_finish, const ProfilerEvents& past_events) override { - EXPECT_EQ(static_cast<base::ProcessId>(239), process_id); - EXPECT_EQ(content::ProcessType::PROCESS_TYPE_PLUGIN, process_type); + EXPECT_EQ(static_cast<base::ProcessId>(239), attributes.process_id); + EXPECT_EQ(content::ProcessType::PROCESS_TYPE_PLUGIN, + attributes.process_type); ASSERT_EQ(1u, process_data_phase.tasks.size()); - switch (profiling_phase) { + switch (attributes.profiling_phase) { case 0: EXPECT_FALSE(got_phase_0_); got_phase_0_ = true; - EXPECT_EQ(base::TimeDelta::FromMilliseconds(0), phase_start); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(222), phase_finish); + EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(111), + attributes.phase_start); + EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(333), + attributes.phase_finish); EXPECT_EQ("death_thread0", process_data_phase.tasks[0].death_thread_name); @@ -54,8 +54,10 @@ EXPECT_FALSE(got_phase_1_); got_phase_1_ = true; - EXPECT_EQ(base::TimeDelta::FromMilliseconds(222), phase_start); - EXPECT_EQ(base::TimeDelta::FromMilliseconds(666), phase_finish); + EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(333), + attributes.phase_start); + EXPECT_EQ(base::TimeTicks() + base::TimeDelta::FromMilliseconds(777), + attributes.phase_finish); EXPECT_EQ("death_thread1", process_data_phase.tasks[0].death_thread_name); @@ -77,9 +79,17 @@ DISALLOW_COPY_AND_ASSIGN(TestObserver); }; -base::TimeTicks TestTimeFromMs(int64 ms) { - return base::TimeTicks() + base::TimeDelta::FromMilliseconds(ms); -} +class TestTrackingSynchronizer : public TrackingSynchronizer { + public: + explicit TestTrackingSynchronizer(scoped_ptr<base::TickClock> clock) + : TrackingSynchronizer(clock.Pass()) {} + + using TrackingSynchronizer::RegisterPhaseCompletion; + using TrackingSynchronizer::SendData; + + private: + ~TestTrackingSynchronizer() override {} +}; } // namespace @@ -88,13 +98,18 @@ #if !defined(OS_IOS) content::TestBrowserThreadBundle thread_bundle; #endif - scoped_refptr<TrackingSynchronizer> tracking_synchronizer = - new TrackingSynchronizer(TestTimeFromMs(111)); - // Mimic a phase change event. - tracking_synchronizer->phase_completion_events_sequence_.push_back( + auto clock = new base::SimpleTestTickClock(); // Will be owned by + // |tracking_synchronizer|. + clock->Advance(base::TimeDelta::FromMilliseconds(111)); + + scoped_refptr<TestTrackingSynchronizer> tracking_synchronizer = + new TestTrackingSynchronizer(make_scoped_ptr(clock)); + + clock->Advance(base::TimeDelta::FromMilliseconds(222)); + + tracking_synchronizer->RegisterPhaseCompletion( ProfilerEventProto::EVENT_FIRST_NONEMPTY_PAINT); - tracking_synchronizer->phase_start_times_.push_back(TestTimeFromMs(333)); tracked_objects::ProcessDataSnapshot profiler_data; ProcessDataPhaseSnapshot snapshot0; @@ -102,17 +117,17 @@ task_snapshot0.death_thread_name = "death_thread0"; snapshot0.tasks.push_back(task_snapshot0); ProcessDataPhaseSnapshot snapshot1; - profiler_data.phased_process_data_snapshots[0] = snapshot0; + profiler_data.phased_snapshots[0] = snapshot0; tracked_objects::TaskSnapshot task_snapshot1; task_snapshot1.death_thread_name = "death_thread1"; snapshot1.tasks.push_back(task_snapshot1); - profiler_data.phased_process_data_snapshots[1] = snapshot1; + profiler_data.phased_snapshots[1] = snapshot1; profiler_data.process_id = 239; + clock->Advance(base::TimeDelta::FromMilliseconds(444)); TestObserver test_observer; - tracking_synchronizer->SendData(profiler_data, - content::ProcessType::PROCESS_TYPE_PLUGIN, - TestTimeFromMs(777), &test_observer); + tracking_synchronizer->SendData( + profiler_data, content::ProcessType::PROCESS_TYPE_PLUGIN, &test_observer); } } // namespace metrics
diff --git a/components/nacl.gyp b/components/nacl.gyp index 5888d75..9c8e2b3d 100644 --- a/components/nacl.gyp +++ b/components/nacl.gyp
@@ -73,11 +73,9 @@ '../base/base.gyp:base_static', '../crypto/crypto.gyp:crypto', '../ipc/ipc.gyp:ipc', - '../mojo/mojo_nacl.gyp:monacl_syscall', '../native_client/src/trusted/service_runtime/service_runtime.gyp:sel_main_chrome', '../ppapi/ppapi_internal.gyp:ppapi_ipc', '../ppapi/ppapi_internal.gyp:ppapi_shared', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', ], 'conditions': [ ['disable_nacl_untrusted==0', { @@ -227,7 +225,6 @@ ], 'dependencies': [ 'nacl_linux', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl', ], 'cflags': ['-fPIE'], 'ldflags!': [ @@ -335,11 +332,9 @@ }, 'dependencies': [ 'nacl_common_win64', - '../mojo/mojo_nacl.gyp:monacl_syscall_win64', '../native_client/src/trusted/service_runtime/service_runtime.gyp:sel_main_chrome64', '../ppapi/ppapi_internal.gyp:ppapi_shared_win64', '../ppapi/ppapi_internal.gyp:ppapi_ipc_win64', - '../third_party/mojo/mojo_edk.gyp:mojo_system_impl_win64', ], 'export_dependent_settings': [ '../ppapi/ppapi_internal.gyp:ppapi_ipc_win64',
diff --git a/components/nacl/BUILD.gn b/components/nacl/BUILD.gn index cb4496f2..5576df1 100644 --- a/components/nacl/BUILD.gn +++ b/components/nacl/BUILD.gn
@@ -33,7 +33,6 @@ "//content/public/common", "//crypto", "//ipc", - "//mojo/nacl:monacl_sel", "//native_client/src/trusted/service_runtime:sel_main_chrome", "//ppapi/c", "//ppapi/proxy:ipc", @@ -181,7 +180,6 @@ "//content/public/common", "//crypto", "//ipc", - "//mojo/nacl:monacl_sel", "//sandbox/linux:libc_urandom_override", ]
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc index 0335029..2abf7a1 100644 --- a/components/nacl/browser/nacl_process_host.cc +++ b/components/nacl/browser/nacl_process_host.cc
@@ -840,8 +840,6 @@ params.validation_cache_key = nacl_browser->GetValidationCacheKey(); params.version = NaClBrowser::GetDelegate()->GetVersionString(); params.enable_debug_stub = enable_nacl_debug; - params.enable_mojo = base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableNaClMojo); const ChildProcessData& data = process_->GetData(); if (!ShareHandleToSelLdr(data.handle,
diff --git a/components/nacl/common/nacl_messages.h b/components/nacl/common/nacl_messages.h index 191d5b9..46cae3f 100644 --- a/components/nacl/common/nacl_messages.h +++ b/components/nacl/common/nacl_messages.h
@@ -25,7 +25,6 @@ IPC_STRUCT_TRAITS_MEMBER(version) IPC_STRUCT_TRAITS_MEMBER(enable_debug_stub) IPC_STRUCT_TRAITS_MEMBER(enable_ipc_proxy) - IPC_STRUCT_TRAITS_MEMBER(enable_mojo) IPC_STRUCT_TRAITS_MEMBER(process_type) IPC_STRUCT_TRAITS_MEMBER(crash_info_shmem_handle) IPC_STRUCT_TRAITS_END()
diff --git a/components/nacl/common/nacl_switches.cc b/components/nacl/common/nacl_switches.cc index 4f158ad..6c5c81c 100644 --- a/components/nacl/common/nacl_switches.cc +++ b/components/nacl/common/nacl_switches.cc
@@ -12,9 +12,6 @@ // Enables debugging via RSP over a socket. const char kEnableNaClDebug[] = "enable-nacl-debug"; -// Enables Mojo support for Native Client plugins. -const char kEnableNaClMojo[] = "enable-nacl-mojo"; - // Enables Non-SFI mode, in which programs can be run without NaCl's SFI // sandbox. const char kEnableNaClNonSfiMode[] = "enable-nacl-nonsfi-mode";
diff --git a/components/nacl/common/nacl_switches.h b/components/nacl/common/nacl_switches.h index ebaaa86..f6a4b4f 100644 --- a/components/nacl/common/nacl_switches.h +++ b/components/nacl/common/nacl_switches.h
@@ -13,7 +13,6 @@ // alongside the definition of their values in the .cc file. extern const char kDisablePnaclCrashThrottling[]; extern const char kEnableNaClDebug[]; -extern const char kEnableNaClMojo[]; extern const char kEnableNaClNonSfiMode[]; extern const char kEnablePNaClSubzero[]; extern const char kNaClBrokerProcess[];
diff --git a/components/nacl/common/nacl_types.cc b/components/nacl/common/nacl_types.cc index 4abb828..f7e628b 100644 --- a/components/nacl/common/nacl_types.cc +++ b/components/nacl/common/nacl_types.cc
@@ -12,7 +12,6 @@ validation_cache_enabled(false), enable_debug_stub(false), enable_ipc_proxy(false), - enable_mojo(false), process_type(kUnknownNaClProcessType), crash_info_shmem_handle(base::SharedMemory::NULLHandle()) { }
diff --git a/components/nacl/common/nacl_types.h b/components/nacl/common/nacl_types.h index f691edf..e5b7136 100644 --- a/components/nacl/common/nacl_types.h +++ b/components/nacl/common/nacl_types.h
@@ -95,9 +95,6 @@ bool enable_debug_stub; bool enable_ipc_proxy; - // Enables plugin code to use Mojo APIs. See mojo/nacl for details. - bool enable_mojo; - NaClAppProcessType process_type; // For NaCl <-> renderer crash information reporting.
diff --git a/components/nacl/loader/DEPS b/components/nacl/loader/DEPS index 9cb889f..1b8ec2f 100644 --- a/components/nacl/loader/DEPS +++ b/components/nacl/loader/DEPS
@@ -29,7 +29,5 @@ # For sending PpapiHostMsg_ChannelCreated in nacl_ipc_adapter.cc: "+ppapi/proxy/ppapi_messages.h", - # For supporting Mojo in plugins. - "+mojo/nacl", "+third_party/mojo/src/mojo/edk", ]
diff --git a/components/nacl/loader/nacl_helper_linux.cc b/components/nacl/loader/nacl_helper_linux.cc index 6670eb2..e7e75fb 100644 --- a/components/nacl/loader/nacl_helper_linux.cc +++ b/components/nacl/loader/nacl_helper_linux.cc
@@ -43,11 +43,6 @@ #include "ipc/ipc_switches.h" #include "sandbox/linux/services/libc_urandom_override.h" -#if !defined(OS_NACL_NONSFI) -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" -#endif - #if defined(OS_NACL_NONSFI) #include "native_client/src/public/nonsfi/irt_exception_handling.h" #else @@ -464,12 +459,6 @@ CheckRDebug(argv[0]); #endif -// TODO(teravest): Enable mojo for nonsfi. http://crbug.com/473418 -#if !defined(OS_NACL_NONSFI) - mojo::embedder::Init( - make_scoped_ptr(new mojo::embedder::SimplePlatformSupport())); -#endif - scoped_ptr<nacl::NaClSandbox> nacl_sandbox(new nacl::NaClSandbox); // Make sure that the early initialization did not start any spurious // threads.
diff --git a/components/nacl/loader/nacl_helper_win_64.cc b/components/nacl/loader/nacl_helper_win_64.cc index 7dfc376f..d67b7b3 100644 --- a/components/nacl/loader/nacl_helper_win_64.cc +++ b/components/nacl/loader/nacl_helper_win_64.cc
@@ -20,8 +20,6 @@ #include "content/public/common/main_function_params.h" #include "content/public/common/sandbox_init.h" #include "sandbox/win/src/sandbox_types.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" extern int NaClMain(const content::MainFunctionParams&); @@ -64,8 +62,6 @@ // Route stdio to parent console (if any) or create one. if (command_line.HasSwitch(switches::kEnableLogging)) base::RouteStdioToConsole(); - mojo::embedder::Init( - make_scoped_ptr(new mojo::embedder::SimplePlatformSupport())); // Initialize the sandbox for this process. bool sandbox_initialized_ok = content::InitializeSandbox(&sandbox_info);
diff --git a/components/nacl/loader/nacl_listener.cc b/components/nacl/loader/nacl_listener.cc index 4cf4a3e..901c0c9 100644 --- a/components/nacl/loader/nacl_listener.cc +++ b/components/nacl/loader/nacl_listener.cc
@@ -28,13 +28,9 @@ #include "ipc/ipc_switches.h" #include "ipc/ipc_sync_channel.h" #include "ipc/ipc_sync_message_filter.h" -#include "mojo/nacl/mojo_syscall.h" #include "native_client/src/public/chrome_main.h" #include "native_client/src/public/nacl_app.h" #include "native_client/src/public/nacl_desc.h" -#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" -#include "third_party/mojo/src/mojo/edk/embedder/platform_support.h" -#include "third_party/mojo/src/mojo/edk/embedder/simple_platform_support.h" #if defined(OS_POSIX) #include "base/file_descriptor_posix.h" @@ -437,16 +433,6 @@ args->nexe_desc = NaClDescCreateWithFilePathMetadata(nexe_file, file_path_str.c_str()); - if (params.enable_mojo) { - // InjectMojo adds a file descriptor to the process that allows Mojo calls - // to use an implementation defined outside the NaCl sandbox. See - // //mojo/nacl for implementation details. - InjectMojo(nap); - } else { - // When Mojo isn't enabled, we inject a file descriptor that intentionally - // fails on any imc_sendmsg() call to make debugging easier. - InjectDisabledMojo(nap); - } // TODO(yusukes): Support pre-opening resource files. CHECK(params.prefetched_resource_files.empty());
diff --git a/components/native_viewport/BUILD.gn b/components/native_viewport/BUILD.gn index 39dee00..71ad605 100644 --- a/components/native_viewport/BUILD.gn +++ b/components/native_viewport/BUILD.gn
@@ -43,11 +43,11 @@ ":lib", "//base", "//components/gles2", + "//components/native_viewport/public/cpp:args", + "//components/native_viewport/public/interfaces", "//mojo/application", "//mojo/common:tracing_impl", "//third_party/mojo/src/mojo/public/cpp/bindings:bindings", - "//third_party/mojo_services/src/native_viewport/public/interfaces", - "//third_party/mojo_services/src/native_viewport/public/cpp:args", "//ui/events", "//ui/events/platform", "//ui/gl", @@ -78,19 +78,19 @@ deps = [ "//base", "//components/gles2", + "//components/native_viewport/public/interfaces", "//gpu/command_buffer/service", "//mojo/application", "//mojo/common", "//mojo/converters/geometry", "//mojo/converters/input_events", "//mojo/environment:chromium", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/native_viewport/public/interfaces", "//ui/events", "//ui/events/platform", "//ui/gfx", "//ui/gfx/geometry", "//ui/gl", + "//ui/mojo/geometry:interfaces", "//ui/platform_window", ]
diff --git a/components/native_viewport/DEPS b/components/native_viewport/DEPS index 391a942..bdbbeda 100644 --- a/components/native_viewport/DEPS +++ b/components/native_viewport/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+components/gles2", + "+components/gpu", "+jni", "+mojo/application", "+mojo/common",
diff --git a/components/native_viewport/OWNERS b/components/native_viewport/OWNERS new file mode 100644 index 0000000..e6a7642f --- /dev/null +++ b/components/native_viewport/OWNERS
@@ -0,0 +1,4 @@ +ben@chromium.org +erg@chromium.org +msw@chromium.org +sky@chromium.org
diff --git a/components/native_viewport/main.cc b/components/native_viewport/main.cc index ca8fa05..1ebfb27 100644 --- a/components/native_viewport/main.cc +++ b/components/native_viewport/main.cc
@@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <algorithm> - #include "base/command_line.h" #include "base/macros.h" #include "base/message_loop/message_loop.h" #include "components/gles2/gpu_impl.h" #include "components/native_viewport/native_viewport_impl.h" +#include "components/native_viewport/public/cpp/args.h" #include "mojo/application/application_runner_chromium.h" #include "mojo/common/tracing_impl.h" #include "third_party/mojo/src/mojo/public/c/system/main.h" @@ -16,7 +15,6 @@ #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" #include "third_party/mojo/src/mojo/public/cpp/application/interface_factory_impl.h" -#include "third_party/mojo_services/src/native_viewport/public/cpp/args.h" #include "ui/events/event_switches.h" #include "ui/gl/gl_surface.h" @@ -38,27 +36,14 @@ void Initialize(mojo::ApplicationImpl* application) override { tracing_.Initialize(application); -#if defined(OS_LINUX) - // Apply the switch for kTouchEvents to CommandLine (if set). This allows - // redirecting the mouse to a touch device on X for testing. base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - const std::string touch_event_string("--" + - std::string(switches::kTouchDevices)); - auto touch_iter = std::find(application->args().begin(), - application->args().end(), - touch_event_string); - if (touch_iter != application->args().end() && - ++touch_iter != application->args().end()) { - command_line->AppendSwitchASCII(touch_event_string, *touch_iter); + is_headless_ = command_line->HasSwitch(mojo::kUseHeadlessConfig); + if (!is_headless_) { + if (command_line->HasSwitch(mojo::kUseTestConfig)) + gfx::GLSurface::InitializeOneOffForTests(); + else + gfx::GLSurface::InitializeOneOff(); } -#endif - - if (application->HasArg(mojo::kUseTestConfig)) - gfx::GLSurface::InitializeOneOffForTests(); - else - gfx::GLSurface::InitializeOneOff(); - - is_headless_ = application->HasArg(mojo::kUseHeadlessConfig); } bool ConfigureIncomingConnection(ApplicationConnection* connection) override {
diff --git a/components/native_viewport/native_viewport_impl.h b/components/native_viewport/native_viewport_impl.h index 8a8f3fbf..93d729b5 100644 --- a/components/native_viewport/native_viewport_impl.h +++ b/components/native_viewport/native_viewport_impl.h
@@ -9,11 +9,11 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "components/gpu/public/interfaces/gpu.mojom.h" #include "components/native_viewport/onscreen_context_provider.h" #include "components/native_viewport/platform_viewport.h" +#include "components/native_viewport/public/interfaces/native_viewport.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/gpu.mojom.h" -#include "third_party/mojo_services/src/native_viewport/public/interfaces/native_viewport.mojom.h" #include "ui/gfx/geometry/rect.h" namespace gles2 {
diff --git a/components/native_viewport/onscreen_context_provider.h b/components/native_viewport/onscreen_context_provider.h index 3159740..c232d25 100644 --- a/components/native_viewport/onscreen_context_provider.h +++ b/components/native_viewport/onscreen_context_provider.h
@@ -6,8 +6,8 @@ #define COMPONENTS_NATIVE_VIEWPORT_ONSCREEN_CONTEXT_PROVIDER_H_ #include "base/memory/ref_counted.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/context_provider.mojom.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/viewport_parameter_listener.mojom.h" +#include "components/gpu/public/interfaces/context_provider.mojom.h" +#include "components/gpu/public/interfaces/viewport_parameter_listener.mojom.h" #include "ui/gfx/native_widget_types.h" namespace gles2 {
diff --git a/components/native_viewport/platform_viewport.h b/components/native_viewport/platform_viewport.h index 5ab6961..3e58119 100644 --- a/components/native_viewport/platform_viewport.h +++ b/components/native_viewport/platform_viewport.h
@@ -6,10 +6,10 @@ #define COMPONENTS_NATIVE_VIEWPORT_PLATFORM_VIEWPORT_H_ #include "base/memory/scoped_ptr.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" -#include "third_party/mojo_services/src/native_viewport/public/interfaces/native_viewport.mojom.h" +#include "components/native_viewport/public/interfaces/native_viewport.mojom.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" +#include "ui/mojo/events/input_events.mojom.h" namespace gfx { class Rect;
diff --git a/components/native_viewport/public/cpp/BUILD.gn b/components/native_viewport/public/cpp/BUILD.gn new file mode 100644 index 0000000..9d2fc36 --- /dev/null +++ b/components/native_viewport/public/cpp/BUILD.gn
@@ -0,0 +1,13 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojo_sdk_source_set("args") { + sources = [ + "args.h", + "lib/args.cc", + ] +}
diff --git a/components/native_viewport/public/cpp/args.h b/components/native_viewport/public/cpp/args.h new file mode 100644 index 0000000..83d7d7c --- /dev/null +++ b/components/native_viewport/public/cpp/args.h
@@ -0,0 +1,17 @@ +// 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_NATIVE_VIEWPORT_PUBLIC_CPP_ARGS_H_ +#define COMPONENTS_NATIVE_VIEWPORT_PUBLIC_CPP_ARGS_H_ + +namespace mojo { + +// All args in alphabetical order. The switches should be documented +// alongside the definition of their values in the .cc file. +extern const char kUseHeadlessConfig[]; +extern const char kUseTestConfig[]; + +} // namespace mojo + +#endif // COMPONENTS_NATIVE_VIEWPORT_PUBLIC_CPP_ARGS_H_
diff --git a/components/native_viewport/public/cpp/lib/args.cc b/components/native_viewport/public/cpp/lib/args.cc new file mode 100644 index 0000000..f7a9ce0 --- /dev/null +++ b/components/native_viewport/public/cpp/lib/args.cc
@@ -0,0 +1,14 @@ +// 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/native_viewport/public/cpp/args.h" + +namespace mojo { + +// Create native viewport in headless mode. +const char kUseHeadlessConfig[] = "use-headless-config"; +// Force gl to be initialized in test mode. +const char kUseTestConfig[] = "use-test-config"; + +} // namespace mojo
diff --git a/components/native_viewport/public/interfaces/BUILD.gn b/components/native_viewport/public/interfaces/BUILD.gn new file mode 100644 index 0000000..4bf4a46 --- /dev/null +++ b/components/native_viewport/public/interfaces/BUILD.gn
@@ -0,0 +1,19 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "native_viewport.mojom", + ] + + public_deps = [ + "//components/gpu/public/interfaces", + "//components/surfaces/public/interfaces:surface_id", + "//ui/mojo/geometry:interfaces", + "//ui/mojo/events:interfaces", + ] +}
diff --git a/components/native_viewport/public/interfaces/native_viewport.mojom b/components/native_viewport/public/interfaces/native_viewport.mojom new file mode 100644 index 0000000..49ce3778 --- /dev/null +++ b/components/native_viewport/public/interfaces/native_viewport.mojom
@@ -0,0 +1,41 @@ +// 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 mojo; + +import "components/gpu/public/interfaces/context_provider.mojom"; +import "ui/mojo/geometry/geometry.mojom"; +import "ui/mojo/events/input_events.mojom"; + +struct ViewportMetrics { + Size size; + float device_pixel_ratio = 1.0; +}; + +interface NativeViewport { + // TODO(sky): having a create function is awkward. Should there be a factory + // to create the NativeViewport that takes the size? + Create(Size size) => (ViewportMetrics metrics); + + Show(); + Hide(); + Close(); + SetSize(Size size); + SetEventDispatcher(NativeViewportEventDispatcher dispatcher); + + // Requests a ContextProvider capable of producing contexts that draw to + // this native viewport. + GetContextProvider(ContextProvider& provider); + + // The initial viewport metrics will be sent in the reply to the Create + // method. Call RequestMetrics() to receive updates when the viewport metrics + // change. The reply will be sent when the viewport metrics are different from + // the values last sent, so to receive continuous updates call this method + // again after receiving the callback. + RequestMetrics() => (ViewportMetrics metrics); +}; + +interface NativeViewportEventDispatcher { + OnEvent(Event event) => (); +};
diff --git a/components/omnibox/omnibox_field_trial.cc b/components/omnibox/omnibox_field_trial.cc index cdd0932..d152c8d 100644 --- a/components/omnibox/omnibox_field_trial.cc +++ b/components/omnibox/omnibox_field_trial.cc
@@ -313,12 +313,6 @@ kAnswersInSuggestRule) == "true"; } -bool OmniboxFieldTrial::DisplayHintTextWhenPossible() { - return variations::GetVariationParamValue( - kBundledExperimentFieldTrialName, - kDisplayHintTextWhenPossibleRule) == "true"; -} - bool OmniboxFieldTrial::DisableResultsCaching() { return variations::GetVariationParamValue( kBundledExperimentFieldTrialName, @@ -405,8 +399,6 @@ const char OmniboxFieldTrial::kZeroSuggestRule[] = "ZeroSuggest"; const char OmniboxFieldTrial::kZeroSuggestVariantRule[] = "ZeroSuggestVariant"; const char OmniboxFieldTrial::kAnswersInSuggestRule[] = "AnswersInSuggest"; -const char OmniboxFieldTrial::kDisplayHintTextWhenPossibleRule[] = - "DisplayHintTextWhenPossible"; const char OmniboxFieldTrial::kDisableResultsCachingRule[] = "DisableResultsCaching"; const char
diff --git a/components/omnibox/omnibox_field_trial.h b/components/omnibox/omnibox_field_trial.h index 5d19f03..feae507f 100644 --- a/components/omnibox/omnibox_field_trial.h +++ b/components/omnibox/omnibox_field_trial.h
@@ -250,15 +250,6 @@ static bool EnableAnswersInSuggest(); // --------------------------------------------------------- - // For the DisplayHintTextWhenPossible experiment that's part of the - // bundled omnibox field trial. - - // Returns true if the omnibox should display hint text (Search - // <search engine> or type URL) when possible (i.e., the omnibox - // is otherwise non-empty). - static bool DisplayHintTextWhenPossible(); - - // --------------------------------------------------------- // For SearchProvider related experiments. // Returns true if the search provider should not be caching results. @@ -323,7 +314,6 @@ static const char kZeroSuggestRule[]; static const char kZeroSuggestVariantRule[]; static const char kAnswersInSuggestRule[]; - static const char kDisplayHintTextWhenPossibleRule[]; static const char kDisableResultsCachingRule[]; static const char kMeasureSuggestPollingDelayFromLastKeystrokeRule[]; static const char kSuggestPollingDelayMsRule[];
diff --git a/components/onc/docs/onc_spec.html b/components/onc/docs/onc_spec.html index e791588..d3f9a92 100644 --- a/components/onc/docs/onc_spec.html +++ b/components/onc/docs/onc_spec.html
@@ -2049,6 +2049,16 @@ is <span class="value">false</span>, and no <span class="field">ServerCARef</span> is set, the certificate must be a self signed certificate, and no CA signature is required. </dd> + + <dt class="field">UseProactiveKeyCaching</dt> + <dd> + <span class="field_meta"> + (optional, defaults to <span class="value">false</span>) + <span class="type">boolean</span> + </span> + Indicates whether Proactive Key Caching (also known as Opportunistic + Key Caching) should be used on a per-service basis. + </dd> </dl> <p class="rule">
diff --git a/components/onc/onc_constants.cc b/components/onc/onc_constants.cc index 3007ac5..a1cfb24 100644 --- a/components/onc/onc_constants.cc +++ b/components/onc/onc_constants.cc
@@ -293,6 +293,7 @@ const char kServerCARef[] = "ServerCARef"; const char kServerCARefs[] = "ServerCARefs"; const char kUseSystemCAs[] = "UseSystemCAs"; +const char kUseProactiveKeyCaching[] = "UseProactiveKeyCaching"; } // namespace eap namespace vpn {
diff --git a/components/onc/onc_constants.h b/components/onc/onc_constants.h index 2ed2434..a28ec83b 100644 --- a/components/onc/onc_constants.h +++ b/components/onc/onc_constants.h
@@ -311,6 +311,7 @@ ONC_EXPORT extern const char kServerCARef[]; ONC_EXPORT extern const char kServerCARefs[]; ONC_EXPORT extern const char kUseSystemCAs[]; +ONC_EXPORT extern const char kUseProactiveKeyCaching[]; } // namespace eap namespace vpn {
diff --git a/components/password_manager.gypi b/components/password_manager.gypi index b560a66..62792ef 100644 --- a/components/password_manager.gypi +++ b/components/password_manager.gypi
@@ -90,6 +90,8 @@ 'password_manager/core/browser/password_syncable_service.h', 'password_manager/core/browser/psl_matching_helper.cc', 'password_manager/core/browser/psl_matching_helper.h', + 'password_manager/core/browser/statistics_table.cc', + 'password_manager/core/browser/statistics_table.h', 'password_manager/core/browser/test_affiliation_fetcher_factory.h', 'password_manager/core/browser/webdata/logins_table.cc', 'password_manager/core/browser/webdata/logins_table.h',
diff --git a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc index 66c42564..315387c 100644 --- a/components/password_manager/content/renderer/credential_manager_client_browsertest.cc +++ b/components/password_manager/content/renderer/credential_manager_client_browsertest.cc
@@ -16,11 +16,20 @@ namespace { -class CredentialManagerClientTest : public content::RenderViewTest { +// This test has crashed on Android since commit +// d94a4430bc4448406b7564790d06110c7c5bcaaf was merged. +// http://crbug.com/481415 +#if defined(OS_ANDROID) +#define MAYBE_CredentialManagerClientTest DISABLED_CredentialManagerClientTest +#else +#define MAYBE_CredentialManagerClientTest CredentialManagerClientTest +#endif // defined(OS_ANDROID) + +class MAYBE_CredentialManagerClientTest : public content::RenderViewTest { public: - CredentialManagerClientTest() + MAYBE_CredentialManagerClientTest() : callback_errored_(false), callback_succeeded_(false) {} - ~CredentialManagerClientTest() override {} + ~MAYBE_CredentialManagerClientTest() override {} void SetUp() override { content::RenderViewTest::SetUp(); @@ -108,7 +117,7 @@ class TestNotificationCallbacks : public blink::WebCredentialManagerClient::NotificationCallbacks { public: - explicit TestNotificationCallbacks(CredentialManagerClientTest* test) + explicit TestNotificationCallbacks(MAYBE_CredentialManagerClientTest* test) : test_(test) {} virtual ~TestNotificationCallbacks() {} @@ -120,13 +129,13 @@ } private: - CredentialManagerClientTest* test_; + MAYBE_CredentialManagerClientTest* test_; }; class TestRequestCallbacks : public blink::WebCredentialManagerClient::RequestCallbacks { public: - explicit TestRequestCallbacks(CredentialManagerClientTest* test) + explicit TestRequestCallbacks(MAYBE_CredentialManagerClientTest* test) : test_(test) {} virtual ~TestRequestCallbacks() {} @@ -140,12 +149,12 @@ } private: - CredentialManagerClientTest* test_; + MAYBE_CredentialManagerClientTest* test_; }; } // namespace -TEST_F(CredentialManagerClientTest, SendNotifyFailedSignIn) { +TEST_F(MAYBE_CredentialManagerClientTest, SendNotifyFailedSignIn) { int request_id; EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_NotifyFailedSignIn::ID, request_id)); @@ -162,7 +171,7 @@ EXPECT_FALSE(callback_errored()); } -TEST_F(CredentialManagerClientTest, SendNotifySignedIn) { +TEST_F(MAYBE_CredentialManagerClientTest, SendNotifySignedIn) { int request_id; EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_NotifySignedIn::ID, request_id)); @@ -179,7 +188,7 @@ EXPECT_FALSE(callback_errored()); } -TEST_F(CredentialManagerClientTest, SendNotifySignedOut) { +TEST_F(MAYBE_CredentialManagerClientTest, SendNotifySignedOut) { int request_id; EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_NotifySignedOut::ID, request_id)); @@ -196,7 +205,7 @@ EXPECT_FALSE(callback_errored()); } -TEST_F(CredentialManagerClientTest, SendRequestCredential) { +TEST_F(MAYBE_CredentialManagerClientTest, SendRequestCredential) { int request_id; EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_RequestCredential::ID, request_id)); @@ -215,7 +224,7 @@ EXPECT_FALSE(callback_errored()); } -TEST_F(CredentialManagerClientTest, SendRequestCredentialEmpty) { +TEST_F(MAYBE_CredentialManagerClientTest, SendRequestCredentialEmpty) { int request_id; EXPECT_FALSE(ExtractRequestId(CredentialManagerHostMsg_RequestCredential::ID, request_id));
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 9880bd3b..f46488d 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -72,6 +72,8 @@ "password_syncable_service.h", "psl_matching_helper.cc", "psl_matching_helper.h", + "statistics_table.cc", + "statistics_table.h", "test_affiliation_fetcher_factory.h", "webdata/logins_table.cc", "webdata/logins_table.h",
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index f59f8c6d..91c71d06 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -29,7 +29,7 @@ namespace password_manager { -const int kCurrentVersionNumber = 12; +const int kCurrentVersionNumber = 13; static const int kCompatibleVersionNumber = 1; Pickle SerializeVector(const std::vector<base::string16>& vec) { @@ -233,7 +233,13 @@ // Initialize the tables. if (!InitLoginsTable()) { - LOG(WARNING) << "Unable to initialize the password store database."; + LOG(WARNING) << "Unable to initialize the logins table."; + db_.Close(); + return false; + } + + if (!stats_table_.Init(&db_)) { + LOG(WARNING) << "Unable to initialize the stats table."; db_.Close(); return false; } @@ -374,6 +380,9 @@ "generation_upload_status INTEGER")) return false; meta_table_.SetVersionNumber(12); + case 12: + // The stats table was added. Nothing to do really. + meta_table_.SetVersionNumber(13); case kCurrentVersionNumber: // Already up to date return true;
diff --git a/components/password_manager/core/browser/login_database.h b/components/password_manager/core/browser/login_database.h index 008afa35..ca3db84 100644 --- a/components/password_manager/core/browser/login_database.h +++ b/components/password_manager/core/browser/login_database.h
@@ -16,6 +16,7 @@ #include "components/password_manager/core/browser/password_store.h" #include "components/password_manager/core/browser/password_store_change.h" #include "components/password_manager/core/browser/psl_matching_helper.h" +#include "components/password_manager/core/browser/statistics_table.h" #include "sql/connection.h" #include "sql/meta_table.h" @@ -108,6 +109,8 @@ // whether further use of this login database will succeed is unspecified. bool DeleteAndRecreateDatabaseFile(); + StatisticsTable& stats_table() { return stats_table_; } + private: // Result values for encryption/decryption actions. enum EncryptionResult { @@ -165,6 +168,7 @@ base::FilePath db_path_; mutable sql::Connection db_; sql::MetaTable meta_table_; + StatisticsTable stats_table_; DISALLOW_COPY_AND_ASSIGN(LoginDatabase); };
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h index 70f54e9..7b76b91 100644 --- a/components/password_manager/core/browser/mock_password_store.h +++ b/components/password_manager/core/browser/mock_password_store.h
@@ -47,6 +47,12 @@ MOCK_METHOD1(FillBlacklistLogins, bool(ScopedVector<autofill::PasswordForm>*)); MOCK_METHOD1(NotifyLoginsChanged, void(const PasswordStoreChangeList&)); + void AddSiteStatsImpl(const InteractionsStats& stats) override {} + void RemoveSiteStatsImpl(const GURL& origin_domain) override {} + scoped_ptr<InteractionsStats> GetSiteStatsImpl( + const GURL& origin_domain) override { + return scoped_ptr<InteractionsStats>(); + } PasswordStoreSync* GetSyncInterface() { return this; }
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc index 88fdc57..44f4a8d2 100644 --- a/components/password_manager/core/browser/password_form_manager.cc +++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -388,6 +388,10 @@ // the worse-scoring "protected" ones for later. ScopedVector<PasswordForm> protected_credentials; for (size_t i = 0; i < logins_result.size(); ++i) { + // Take ownership of the PasswordForm from the ScopedVector. + scoped_ptr<PasswordForm> login(logins_result[i]); + logins_result[i] = nullptr; + if (credential_scores[i] < 0) continue; if (credential_scores[i] < best_score) { @@ -399,45 +403,46 @@ // instead of explicitly handling empty path matches. bool is_credential_protected = observed_form_.scheme == PasswordForm::SCHEME_HTML && - StartsWithASCII("/", logins_result[i]->origin.path(), true) && - credential_scores[i] > 0 && !logins_result[i]->blacklisted_by_user; + StartsWithASCII("/", login->origin.path(), true) && + credential_scores[i] > 0 && !login->blacklisted_by_user; // Passwords generated on a signup form must show on a login form even if // there are better-matching saved credentials. TODO(gcasto): We don't // want to cut credentials that were saved on signup forms even if they // weren't generated, but currently it's hard to distinguish between those // forms and two different login forms on the same domain. Filed // http://crbug.com/294468 to look into this. - is_credential_protected |= - logins_result[i]->type == PasswordForm::TYPE_GENERATED; + is_credential_protected |= login->type == PasswordForm::TYPE_GENERATED; - if (is_credential_protected) { - protected_credentials.push_back(logins_result[i]); - logins_result[i] = nullptr; - } + if (is_credential_protected) + protected_credentials.push_back(login.Pass()); continue; } // If there is another best-score match for the same username, replace it. // TODO(vabr): Spare the replacing and keep the first instead of the last // candidate. - auto& best_match = best_matches_[logins_result[i]->username_value]; + PasswordForm*& best_match = best_matches_[login->username_value]; if (best_match == preferred_match_) preferred_match_ = nullptr; delete best_match; - - best_match = logins_result[i]; - logins_result[i] = nullptr; - preferred_match_ = best_match->preferred ? best_match : preferred_match_; + // Transfer ownership into the map. + best_match = login.release(); + if (best_match->preferred) + preferred_match_ = best_match; } // Add the protected results if we don't already have a result with the same // username. - for (auto& protege : protected_credentials) { - auto& corresponding_best_match = best_matches_[protege->username_value]; - if (!corresponding_best_match) { - corresponding_best_match = protege; - protege = nullptr; - } + for (ScopedVector<PasswordForm>::iterator it = protected_credentials.begin(); + it != protected_credentials.end(); ++it) { + // Take ownership of the PasswordForm from the ScopedVector. + scoped_ptr<PasswordForm> protege(*it); + *it = nullptr; + + PasswordForm*& corresponding_best_match = + best_matches_[protege->username_value]; + if (!corresponding_best_match) + corresponding_best_match = protege.release(); } client_->AutofillResultsComputed();
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h index 2da08e0e..aa0d9e2 100644 --- a/components/password_manager/core/browser/password_form_manager.h +++ b/components/password_manager/core/browser/password_form_manager.h
@@ -10,6 +10,7 @@ #include "build/build_config.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/stl_util.h" #include "components/autofill/core/browser/field_types.h"
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index 7a20908..cdad6fe 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -970,7 +970,7 @@ // Feed the incomplete credentials to the manager. ScopedVector<PasswordForm> simulated_results; - simulated_results.push_back(incomplete_form.release()); + simulated_results.push_back(incomplete_form.Pass()); form_manager.OnGetPasswordStoreResults(simulated_results.Pass()); form_manager.ProvisionallySave( @@ -1372,7 +1372,7 @@ client_with_store.KillDriver(); ScopedVector<PasswordForm> simulated_results; - simulated_results.push_back(form.release()); + simulated_results.push_back(form.Pass()); form_manager.OnGetPasswordStoreResults(simulated_results.Pass()); }
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index a42f4f2..2a0aff7 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -96,14 +96,10 @@ prefs::kPasswordManagerSavingEnabled, true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kPasswordManagerAutoSignin, true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kPasswordManagerAllowShowPasswords, true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kPasswordManagerGroupsForDomains, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kPasswordManagerAutoSignin, true); + registry->RegisterBooleanPref(prefs::kPasswordManagerAllowShowPasswords, + true); + registry->RegisterListPref(prefs::kPasswordManagerGroupsForDomains); } #if defined(OS_WIN)
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index e5746e54..749044c 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -368,7 +368,7 @@ scoped_ptr<PasswordForm> existing_different( new PasswordForm(MakeSimpleForm())); existing_different->username_value = ASCIIToUTF16("google2"); - result.push_back(existing_different.release()); + result.push_back(existing_different.Pass()); EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2); EXPECT_CALL(*store_, GetLogins(_, _, _)) .WillOnce(WithArg<2>(InvokeConsumer(&result)));
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 5b13a3c..4a357919 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -59,6 +59,13 @@ consumer_weak_, base::Passed(&results))); } +void PasswordStore::GetLoginsRequest::NotifyWithSiteStatistics( + scoped_ptr<InteractionsStats> stats) { + origin_loop_->PostTask(FROM_HERE, + base::Bind(&PasswordStoreConsumer::OnGetSiteStatistics, + consumer_weak_, base::Passed(&stats))); +} + PasswordStore::PasswordStore( scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner, scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner) @@ -163,6 +170,22 @@ } } +void PasswordStore::AddSiteStats(const InteractionsStats& stats) { + ScheduleTask(base::Bind(&PasswordStore::AddSiteStatsImpl, this, stats)); +} + +void PasswordStore::RemoveSiteStats(const GURL& origin_domain) { + ScheduleTask( + base::Bind(&PasswordStore::RemoveSiteStatsImpl, this, origin_domain)); +} + +void PasswordStore::GetSiteStats(const GURL& origin_domain, + PasswordStoreConsumer* consumer) { + scoped_ptr<GetLoginsRequest> request(new GetLoginsRequest(consumer)); + ScheduleTask(base::Bind(&PasswordStore::NotifySiteStats, this, origin_domain, + base::Passed(&request))); +} + void PasswordStore::AddObserver(Observer* observer) { observers_->AddObserver(observer); } @@ -302,6 +325,11 @@ NotifyLoginsChanged(changes); } +void PasswordStore::NotifySiteStats(const GURL& origin_domain, + scoped_ptr<GetLoginsRequest> request) { + request->NotifyWithSiteStatistics(GetSiteStatsImpl(origin_domain)); +} + void PasswordStore::GetLoginsWithAffiliationsImpl( const PasswordForm& form, AuthorizationPromptPolicy prompt_policy,
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 74ff469..c1194cfc 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -15,6 +15,7 @@ #include "base/time/time.h" #include "components/password_manager/core/browser/password_store_change.h" #include "components/password_manager/core/browser/password_store_sync.h" +#include "components/password_manager/core/browser/statistics_table.h" #include "sync/api/syncable_service.h" namespace autofill { @@ -128,6 +129,16 @@ virtual void ReportMetrics(const std::string& sync_username, bool custom_passphrase_sync_enabled); + // Adds or replaces the statistics for the domain |stats.origin_domain|. + void AddSiteStats(const InteractionsStats& stats); + + // Removes the statistics for |origin_domain|. + void RemoveSiteStats(const GURL& origin_domain); + + // Retrieves the statistics for |origin_domain| and notifies |consumer| on + // completion. The request will be cancelled if the consumer is destroyed. + void GetSiteStats(const GURL& origin_domain, PasswordStoreConsumer* consumer); + // Adds an observer to be notified when the password store data changes. void AddObserver(Observer* observer); @@ -162,6 +173,8 @@ void NotifyConsumerWithResults( ScopedVector<autofill::PasswordForm> results); + void NotifyWithSiteStatistics(scoped_ptr<InteractionsStats> stats); + void set_ignore_logins_cutoff(base::Time cutoff) { ignore_logins_cutoff_ = cutoff; } @@ -235,6 +248,13 @@ // Finds all blacklist PasswordForms, and notifies the consumer. virtual void GetBlacklistLoginsImpl(scoped_ptr<GetLoginsRequest> request) = 0; + // Synchronous implementation for manipulating with statistics. + virtual void AddSiteStatsImpl(const InteractionsStats& stats) = 0; + virtual void RemoveSiteStatsImpl(const GURL& origin_domain) = 0; + // Returns a raw pointer so that InteractionsStats can be forward declared. + virtual scoped_ptr<InteractionsStats> GetSiteStatsImpl( + const GURL& origin_domain) WARN_UNUSED_RESULT = 0; + // Log UMA stats for number of bulk deletions. void LogStatsForBulkDeletion(int num_deletions); @@ -288,6 +308,10 @@ void RemoveLoginsSyncedBetweenInternal(base::Time delete_begin, base::Time delete_end); + // Notifies |request| about the stats for |origin_domain|. + void NotifySiteStats(const GURL& origin_domain, + scoped_ptr<GetLoginsRequest> request); + // Extended version of GetLoginsImpl that also returns credentials stored for // the specified affiliated Android applications. That is, it finds all // PasswordForms with a signon_realm that is either:
diff --git a/components/password_manager/core/browser/password_store_consumer.cc b/components/password_manager/core/browser/password_store_consumer.cc index da62aed..8347f2b 100644 --- a/components/password_manager/core/browser/password_store_consumer.cc +++ b/components/password_manager/core/browser/password_store_consumer.cc
@@ -4,6 +4,8 @@ #include "components/password_manager/core/browser/password_store_consumer.h" +#include "components/password_manager/core/browser/statistics_table.h" + namespace password_manager { PasswordStoreConsumer::PasswordStoreConsumer() : weak_ptr_factory_(this) { @@ -12,4 +14,8 @@ PasswordStoreConsumer::~PasswordStoreConsumer() { } +void PasswordStoreConsumer::OnGetSiteStatistics( + scoped_ptr<InteractionsStats> stats) { +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store_consumer.h b/components/password_manager/core/browser/password_store_consumer.h index 1ffdae3..b8934995 100644 --- a/components/password_manager/core/browser/password_store_consumer.h +++ b/components/password_manager/core/browser/password_store_consumer.h
@@ -16,6 +16,8 @@ namespace password_manager { +struct InteractionsStats; + // Reads from the PasswordStore are done asynchronously on a separate // thread. PasswordStoreConsumer provides the virtual callback method, which is // guaranteed to be executed on this (the UI) thread. It also provides the @@ -25,10 +27,13 @@ public: PasswordStoreConsumer(); - // Called when the request is finished, with the associated |results|. + // Called when the GetLogins() request is finished, with the associated + // |results|. virtual void OnGetPasswordStoreResults( ScopedVector<autofill::PasswordForm> results) = 0; + virtual void OnGetSiteStatistics(scoped_ptr<InteractionsStats> stats); + // The base::CancelableTaskTracker can be used for cancelling the // tasks associated with the consumer. base::CancelableTaskTracker* cancelable_task_tracker() {
diff --git a/components/password_manager/core/browser/password_store_default.cc b/components/password_manager/core/browser/password_store_default.cc index 4e24ad1..54be8f86 100644 --- a/components/password_manager/core/browser/password_store_default.cc +++ b/components/password_manager/core/browser/password_store_default.cc
@@ -148,4 +148,23 @@ return login_db_ && login_db_->GetBlacklistLogins(forms); } +void PasswordStoreDefault::AddSiteStatsImpl(const InteractionsStats& stats) { + DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + if (login_db_) + login_db_->stats_table().AddRow(stats); +} + +void PasswordStoreDefault::RemoveSiteStatsImpl(const GURL& origin_domain) { + DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + if (login_db_) + login_db_->stats_table().RemoveRow(origin_domain); +} + +scoped_ptr<InteractionsStats> PasswordStoreDefault::GetSiteStatsImpl( + const GURL& origin_domain) { + DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread()); + return login_db_ ? login_db_->stats_table().GetRow(origin_domain) + : scoped_ptr<InteractionsStats>(); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store_default.h b/components/password_manager/core/browser/password_store_default.h index ecfd38ffa..ab02004 100644 --- a/components/password_manager/core/browser/password_store_default.h +++ b/components/password_manager/core/browser/password_store_default.h
@@ -59,8 +59,11 @@ ScopedVector<autofill::PasswordForm>* forms) override; bool FillBlacklistLogins( ScopedVector<autofill::PasswordForm>* forms) override; + void AddSiteStatsImpl(const InteractionsStats& stats) override; + void RemoveSiteStatsImpl(const GURL& origin_domain) override; + scoped_ptr<InteractionsStats> GetSiteStatsImpl( + const GURL& origin_domain) override; - protected: inline bool DeleteAndRecreateDatabaseFile() { return login_db_->DeleteAndRecreateDatabaseFile(); }
diff --git a/components/password_manager/core/browser/password_store_default_unittest.cc b/components/password_manager/core/browser/password_store_default_unittest.cc index 324b783..12ded5b 100644 --- a/components/password_manager/core/browser/password_store_default_unittest.cc +++ b/components/password_manager/core/browser/password_store_default_unittest.cc
@@ -121,7 +121,7 @@ ScopedVector<PasswordForm> expected_forms; for (unsigned int i = 0; i < arraysize(form_data); ++i) { expected_forms.push_back( - CreatePasswordFormFromDataForTesting(form_data[i]).release()); + CreatePasswordFormFromDataForTesting(form_data[i]).Pass()); store->AddLogin(*expected_forms.back()); }
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index 6d1a350..ba4140b 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -225,7 +225,7 @@ ScopedVector<PasswordForm> all_forms; for (size_t i = 0; i < arraysize(form_data); ++i) { all_forms.push_back( - CreatePasswordFormFromDataForTesting(form_data[i]).release()); + CreatePasswordFormFromDataForTesting(form_data[i]).Pass()); store->AddLogin(*all_forms.back()); } base::MessageLoop::current()->RunUntilIdle();
diff --git a/components/password_manager/core/browser/statistics_table.cc b/components/password_manager/core/browser/statistics_table.cc new file mode 100644 index 0000000..1246ee9 --- /dev/null +++ b/components/password_manager/core/browser/statistics_table.cc
@@ -0,0 +1,83 @@ +// 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/password_manager/core/browser/statistics_table.h" + +#include "sql/connection.h" +#include "sql/statement.h" + +namespace password_manager { +namespace { + +// Convenience enum for interacting with SQL queries that use all the columns. +enum LoginTableColumns { + COLUMN_ORIGIN_DOMAIN = 0, + COLUMN_NOPES, + COLUMN_DISMISSALS, + COLUMN_DATE, +}; + +} // namespace + +StatisticsTable::StatisticsTable() : db_(nullptr) { +} + +StatisticsTable::~StatisticsTable() { +} + +bool StatisticsTable::Init(sql::Connection* db) { + db_ = db; + if (!db_->DoesTableExist("stats")) { + const char query[] = + "CREATE TABLE stats (" + "origin_domain VARCHAR NOT NULL PRIMARY KEY, " + "nopes_count INTEGER, " + "dismissal_count INTEGER, " + "start_date INTEGER NOT NULL)"; + if (!db_->Execute(query)) + return false; + } + return true; +} + +bool StatisticsTable::AddRow(const InteractionsStats& stats) { + sql::Statement s(db_->GetCachedStatement( + SQL_FROM_HERE, + "INSERT OR REPLACE INTO stats " + "(origin_domain, nopes_count, dismissal_count, start_date) " + "VALUES (?, ?, ?, ?)")); + s.BindString(COLUMN_ORIGIN_DOMAIN, stats.origin_domain.spec()); + s.BindInt(COLUMN_NOPES, stats.nopes_count); + s.BindInt(COLUMN_DISMISSALS, stats.dismissal_count); + s.BindInt64(COLUMN_DATE, stats.start_date.ToInternalValue()); + return s.Run(); +} + +bool StatisticsTable::RemoveRow(const GURL& domain) { + sql::Statement s(db_->GetCachedStatement(SQL_FROM_HERE, + "DELETE FROM stats WHERE " + "origin_domain = ? ")); + s.BindString(0, domain.spec()); + return s.Run(); +} + +scoped_ptr<InteractionsStats> StatisticsTable::GetRow(const GURL& domain) { + const char query[] = + "SELECT origin_domain, nopes_count, " + "dismissal_count, start_date FROM stats WHERE origin_domain == ?"; + sql::Statement s(db_->GetCachedStatement(SQL_FROM_HERE, query)); + s.BindString(0, domain.spec()); + if (s.Step()) { + scoped_ptr<InteractionsStats> stats(new InteractionsStats); + stats->origin_domain = GURL(s.ColumnString(COLUMN_ORIGIN_DOMAIN)); + stats->nopes_count = s.ColumnInt(COLUMN_NOPES); + stats->dismissal_count = s.ColumnInt(COLUMN_DISMISSALS); + stats->start_date = + base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE)); + return stats.Pass(); + } + return scoped_ptr<InteractionsStats>(); +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/statistics_table.h b/components/password_manager/core/browser/statistics_table.h new file mode 100644 index 0000000..d135309 --- /dev/null +++ b/components/password_manager/core/browser/statistics_table.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_PASSWORD_MANAGER_CORE_BROWSER_STATISTICS_TABLE_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_STATISTICS_TABLE_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "url/gurl.h" + +namespace sql { +class Connection; +} + +namespace password_manager { + +// The statistics containing user interactions with a site. +struct InteractionsStats { + // The domain of the site. + GURL origin_domain; + + // Number of times the user clicked "Don't save the password". + int nopes_count; + + // Number of times the user dismissed the bubble. + int dismissal_count; + + // The beginning date of the measurements. + base::Time start_date; +}; + +// Represents 'stats' table in the Login Database. +class StatisticsTable { + public: + StatisticsTable(); + ~StatisticsTable(); + + // Initializes |db_| and creates the statistics table if it doesn't exist. + bool Init(sql::Connection* db); + + // Adds or replaces the statistics about |stats.origin_domain|. + bool AddRow(const InteractionsStats& stats); + + // Removes the statistics for |domain|. Returns true if the SQL completed + // successfully. + bool RemoveRow(const GURL& domain); + + // Returns the statistics for |domain| if it exists. + scoped_ptr<InteractionsStats> GetRow(const GURL& domain); + + private: + sql::Connection* db_; + + DISALLOW_COPY_AND_ASSIGN(StatisticsTable); +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_STATISTICS_TABLE_H_
diff --git a/components/password_manager/core/browser/statistics_table_unittest.cc b/components/password_manager/core/browser/statistics_table_unittest.cc new file mode 100644 index 0000000..c3d28ff --- /dev/null +++ b/components/password_manager/core/browser/statistics_table_unittest.cc
@@ -0,0 +1,91 @@ +// 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/password_manager/core/browser/statistics_table.h" + +#include "base/files/scoped_temp_dir.h" +#include "sql/connection.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace password_manager { +namespace { + +const char kTestDomain[] = "http://google.com"; + +void CheckStatsAreEqual(const InteractionsStats& left, + const InteractionsStats& right) { + EXPECT_EQ(left.origin_domain, right.origin_domain); + EXPECT_EQ(left.nopes_count, right.nopes_count); + EXPECT_EQ(left.dismissal_count, right.dismissal_count); + EXPECT_EQ(left.start_date, right.start_date); +} + +class StatisticsTableTest : public testing::Test { + protected: + void SetUp() override { + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + ReloadDatabase(); + + test_data_.origin_domain = GURL(kTestDomain); + test_data_.nopes_count = 5; + test_data_.dismissal_count = 10; + test_data_.start_date = base::Time::FromTimeT(1); + } + + void ReloadDatabase() { + base::FilePath file = temp_dir_.path().AppendASCII("TestDatabase"); + db_.reset(new StatisticsTable); + connection_.reset(new sql::Connection); + connection_->set_exclusive_locking(); + ASSERT_TRUE(connection_->Open(file)); + ASSERT_TRUE(db_->Init(connection_.get())); + } + + InteractionsStats& test_data() { return test_data_; } + StatisticsTable* db() { return db_.get(); } + + private: + base::ScopedTempDir temp_dir_; + scoped_ptr<sql::Connection> connection_; + scoped_ptr<StatisticsTable> db_; + InteractionsStats test_data_; +}; + +TEST_F(StatisticsTableTest, Sanity) { + EXPECT_TRUE(db()->AddRow(test_data())); + scoped_ptr<InteractionsStats> stats = db()->GetRow(test_data().origin_domain); + ASSERT_TRUE(stats); + CheckStatsAreEqual(test_data(), *stats); + EXPECT_TRUE(db()->RemoveRow(test_data().origin_domain)); + EXPECT_FALSE(db()->GetRow(test_data().origin_domain)); +} + +TEST_F(StatisticsTableTest, Reload) { + EXPECT_TRUE(db()->AddRow(test_data())); + EXPECT_TRUE(db()->GetRow(test_data().origin_domain)); + + ReloadDatabase(); + + scoped_ptr<InteractionsStats> stats = db()->GetRow(test_data().origin_domain); + ASSERT_TRUE(stats); + CheckStatsAreEqual(test_data(), *stats); +} + +TEST_F(StatisticsTableTest, DoubleOperation) { + EXPECT_TRUE(db()->AddRow(test_data())); + test_data().nopes_count++; + EXPECT_TRUE(db()->AddRow(test_data())); + + scoped_ptr<InteractionsStats> stats = db()->GetRow(test_data().origin_domain); + ASSERT_TRUE(stats); + CheckStatsAreEqual(test_data(), *stats); + + EXPECT_TRUE(db()->RemoveRow(test_data().origin_domain)); + EXPECT_FALSE(db()->GetRow(test_data().origin_domain)); + EXPECT_TRUE(db()->RemoveRow(test_data().origin_domain)); + EXPECT_FALSE(db()->GetRow(test_data().origin_domain)); +} + +} // namespace +} // namespace password_manager
diff --git a/components/password_manager/core/browser/test_password_store.cc b/components/password_manager/core/browser/test_password_store.cc index a420e9e..60f2536 100644 --- a/components/password_manager/core/browser/test_password_store.cc +++ b/components/password_manager/core/browser/test_password_store.cc
@@ -139,4 +139,15 @@ return true; } +void TestPasswordStore::AddSiteStatsImpl(const InteractionsStats& stats) { +} + +void TestPasswordStore::RemoveSiteStatsImpl(const GURL& origin_domain) { +} + +scoped_ptr<InteractionsStats> TestPasswordStore::GetSiteStatsImpl( + const GURL& origin_domain) { + return scoped_ptr<InteractionsStats>(); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/test_password_store.h b/components/password_manager/core/browser/test_password_store.h index 96f6104a..72addcdf 100644 --- a/components/password_manager/core/browser/test_password_store.h +++ b/components/password_manager/core/browser/test_password_store.h
@@ -66,6 +66,10 @@ ScopedVector<autofill::PasswordForm>* forms) override; bool FillBlacklistLogins( ScopedVector<autofill::PasswordForm>* forms) override; + void AddSiteStatsImpl(const InteractionsStats& stats) override; + void RemoveSiteStatsImpl(const GURL& origin_domain) override; + scoped_ptr<InteractionsStats> GetSiteStatsImpl( + const GURL& origin_domain) override; private: PasswordMap stored_passwords_;
diff --git a/components/policy.gypi b/components/policy.gypi index c2b99d8..06253e8 100644 --- a/components/policy.gypi +++ b/components/policy.gypi
@@ -103,6 +103,7 @@ { 'inputs': [ 'policy/resources/policy_templates.json', + '<(DEPTH)/chrome/VERSION', '<(generate_policy_source_script_path)', ], 'outputs': [ @@ -123,6 +124,7 @@ '--cloud-policy-protobuf=<(cloud_policy_proto_path)', '--cloud-policy-decoder=<(protobuf_decoder_path)', '--app-restrictions-definition=<(app_restrictions_path)', + '<(DEPTH)/chrome/VERSION', '<(OS)', '<(chromeos)', 'policy/resources/policy_templates.json',
diff --git a/components/policy/BUILD.gn b/components/policy/BUILD.gn index a708c2a6..27e3007 100644 --- a/components/policy/BUILD.gn +++ b/components/policy/BUILD.gn
@@ -64,6 +64,8 @@ action("cloud_policy_code_generate") { script = "tools/generate_policy_source.py" + chrome_version_abspath = "//chrome/VERSION" + chrome_version_path = rebase_path(chrome_version_abspath, root_build_dir) if (is_chromeos) { chromeos_flag = "1" @@ -72,6 +74,7 @@ } inputs = [ + chrome_version_abspath, "resources/policy_templates.json", ] outputs = [ @@ -100,6 +103,7 @@ rebase_path(protobuf_decoder_path, root_build_dir), "--app-restrictions-definition=" + rebase_path(app_restrictions_path, root_build_dir), + chrome_version_path, target_os, chromeos_flag, rebase_path("resources/policy_templates.json", root_build_dir),
diff --git a/components/policy/core/browser/url_blacklist_manager.cc b/components/policy/core/browser/url_blacklist_manager.cc index 631ac7c..4e39e4e 100644 --- a/components/policy/core/browser/url_blacklist_manager.cc +++ b/components/policy/core/browser/url_blacklist_manager.cc
@@ -510,10 +510,8 @@ // static void URLBlacklistManager::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterListPref(policy_prefs::kUrlBlacklist, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(policy_prefs::kUrlWhitelist, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(policy_prefs::kUrlBlacklist); + registry->RegisterListPref(policy_prefs::kUrlWhitelist); } } // namespace policy
diff --git a/components/policy/core/common/cloud/enterprise_metrics.h b/components/policy/core/common/cloud/enterprise_metrics.h index 9f27d445..a805b8a 100644 --- a/components/policy/core/common/cloud/enterprise_metrics.h +++ b/components/policy/core/common/cloud/enterprise_metrics.h
@@ -218,6 +218,8 @@ kMetricEnrollmentLockReadbackError = 49, // Failed to update device attributes. kMetricEnrollmentAttributeUpdateFailed = 50, + // Lockbox error at re-enrollment: mode does not match install attributes. + kMetricEnrollmentLockModeMismatch = 51, }; // Events related to policy refresh.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 82b162c..eb45ccb 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -123,7 +123,7 @@ # persistent IDs for all fields (but not for groups!) are needed. These are # specified by the 'id' keys of each policy. NEVER CHANGE EXISTING IDs, # because doing so would break the deployed wire format! -# For your editing convenience: highest ID currently used: 299 +# For your editing convenience: highest ID currently used: 300 # # Placeholders: # The following placeholder strings are automatically substituted: @@ -7335,6 +7335,21 @@ 'desc': '''If this policy is set to true, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will unconditionally maximize the the first window shown on first run. If this policy is set to false or not configured, a heuristic will decide whether to maximize the first window shown, based on the screen size.''', }, + { + 'name': 'SSLErrorOverrideAllowed', + 'type': 'main', + 'schema': { 'type': 'boolean' }, + 'supported_on': ['chrome.*:44-', 'chrome_os:44-', 'android:44-'], + 'features': { + 'dynamic_refresh': True, + 'per_profile': True, + }, + 'example_value': True, + 'id': 300, + 'caption': '''Allow proceeding from the SSL warning page''', + 'desc': '''Chrome shows a warning page when users navigate to sites that have SSL errors. By default or when this policy is set to true, users are allowed to click through these warning pages. + Setting this policy to false disallows users to click through any warning page.''', + }, ], 'messages': { # Messages that are not associated to any policies.
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py index b3a723b..2a9e645 100755 --- a/components/policy/tools/generate_policy_source.py +++ b/components/policy/tools/generate_policy_source.py
@@ -62,7 +62,7 @@ self.caption = PolicyDetails._RemovePlaceholders(item['caption']) self.value = item['value'] - def __init__(self, policy, os, is_chromium_os): + def __init__(self, policy, chrome_major_version, os, is_chromium_os): self.id = policy['id'] self.name = policy['name'] features = policy.get('features', {}) @@ -77,8 +77,18 @@ expected_platform = 'chrome_os' if is_chromium_os else os.lower() self.platforms = [] - for platform, version in [ p.split(':') for p in policy['supported_on'] ]: - if not version.endswith('-'): + for platform, version_range in [ p.split(':') + for p in policy['supported_on'] ]: + split_result = version_range.split('-') + if len(split_result) != 2: + raise RuntimeError('supported_on must have exactly one dash: "%s"' % p) + (version_min, version_max) = split_result + if version_min == '': + raise RuntimeError('supported_on must define a start version: "%s"' % p) + + # Skip if the current Chromium version does not support the policy. + if (int(version_min) > chrome_major_version or + version_max != '' and int(version_max) < chrome_major_version): continue if platform.startswith('chrome.'): @@ -127,6 +137,18 @@ return result +def ParseVersionFile(version_path): + major_version = None + for line in open(version_path, 'r').readlines(): + key, val = line.rstrip('\r\n').split('=', 1) + if key == 'MAJOR': + major_version = val + break + if major_version is None: + raise RuntimeError('VERSION file does not contain major version.') + return major_version + + def main(): parser = OptionParser(usage=__doc__) parser.add_option('--pch', '--policy-constants-header', dest='header_path', @@ -155,17 +177,20 @@ (opts, args) = parser.parse_args() - if len(args) != 3: - print 'exactly platform, chromium_os flag and input file must be specified.' + if len(args) != 4: + print('Please specify path to src/chrome/VERSION, platform, ' + 'chromium_os flag and input file as positional parameters.') parser.print_help() return 2 - os = args[0] - is_chromium_os = args[1] == '1' - template_file_name = args[2] + version_path = args[0] + os = args[1] + is_chromium_os = args[2] == '1' + template_file_name = args[3] + major_version = ParseVersionFile(version_path) template_file_contents = _LoadJSONFile(template_file_name) - policy_details = [ PolicyDetails(policy, os, is_chromium_os) + policy_details = [ PolicyDetails(policy, major_version, os, is_chromium_os) for policy in _Flatten(template_file_contents) ] sorted_policy_details = sorted(policy_details, key=lambda policy: policy.name)
diff --git a/components/precache/android/java/src/org/chromium/components/precache/NetworkInfoDelegate.java b/components/precache/android/java/src/org/chromium/components/precache/NetworkInfoDelegate.java index 17dbf82..f5abcd5 100644 --- a/components/precache/android/java/src/org/chromium/components/precache/NetworkInfoDelegate.java +++ b/components/precache/android/java/src/org/chromium/components/precache/NetworkInfoDelegate.java
@@ -7,7 +7,6 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; -import android.os.Build; import org.chromium.base.VisibleForTesting; @@ -52,10 +51,6 @@ } protected boolean isActiveNetworkMetered() { - // ConnectivityManager.isActiveNetworkMetered was added in SDK API 16. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { - return false; - } return mConnectivityManager.isActiveNetworkMetered(); } }
diff --git a/components/pref_registry/pref_registry_syncable.cc b/components/pref_registry/pref_registry_syncable.cc index 49d0020a..bb90417 100644 --- a/components/pref_registry/pref_registry_syncable.cc +++ b/components/pref_registry/pref_registry_syncable.cc
@@ -17,107 +17,23 @@ PrefRegistrySyncable::~PrefRegistrySyncable() { } -const PrefRegistrySyncable::PrefToStatus& -PrefRegistrySyncable::syncable_preferences() const { - return syncable_preferences_; -} - void PrefRegistrySyncable::SetSyncableRegistrationCallback( const SyncableRegistrationCallback& cb) { callback_ = cb; } -void PrefRegistrySyncable::RegisterBooleanPref(const char* path, - bool default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference( - path, new base::FundamentalValue(default_value), sync_status); -} +void PrefRegistrySyncable::OnPrefRegistered(const std::string& path, + base::Value* default_value, + uint32 flags) { + // Tests that |flags| does not contain both SYNCABLE_PREF and + // SYNCABLE_PRIORITY_PREF flags at the same time. + DCHECK(!(flags & PrefRegistrySyncable::SYNCABLE_PREF) || + !(flags & PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF)); -void PrefRegistrySyncable::RegisterIntegerPref(const char* path, - int default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference( - path, new base::FundamentalValue(default_value), sync_status); -} - -void PrefRegistrySyncable::RegisterDoublePref(const char* path, - double default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference( - path, new base::FundamentalValue(default_value), sync_status); -} - -void PrefRegistrySyncable::RegisterStringPref(const char* path, - const std::string& default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference( - path, new base::StringValue(default_value), sync_status); -} - -void PrefRegistrySyncable::RegisterFilePathPref( - const char* path, - const base::FilePath& default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference( - path, new base::StringValue(default_value.value()), sync_status); -} - -void PrefRegistrySyncable::RegisterListPref(const char* path, - PrefSyncStatus sync_status) { - RegisterSyncablePreference(path, new base::ListValue(), sync_status); -} - -void PrefRegistrySyncable::RegisterListPref(const char* path, - base::ListValue* default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference(path, default_value, sync_status); -} - -void PrefRegistrySyncable::RegisterDictionaryPref(const char* path, - PrefSyncStatus sync_status) { - RegisterSyncablePreference(path, new base::DictionaryValue(), sync_status); -} - -void PrefRegistrySyncable::RegisterDictionaryPref( - const char* path, - base::DictionaryValue* default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference(path, default_value, sync_status); -} - -void PrefRegistrySyncable::RegisterInt64Pref( - const char* path, - int64 default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference( - path, - new base::StringValue(base::Int64ToString(default_value)), - sync_status); -} - -void PrefRegistrySyncable::RegisterUint64Pref( - const char* path, - uint64 default_value, - PrefSyncStatus sync_status) { - RegisterSyncablePreference( - path, - new base::StringValue(base::Uint64ToString(default_value)), - sync_status); -} - -void PrefRegistrySyncable::RegisterSyncablePreference( - const char* path, - base::Value* default_value, - PrefSyncStatus sync_status) { - PrefRegistry::RegisterPreference(path, default_value); - - if (sync_status == PrefRegistrySyncable::SYNCABLE_PREF || - sync_status == PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF) { - syncable_preferences_[path] = sync_status; - + if (flags & PrefRegistrySyncable::SYNCABLE_PREF || + flags & PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF) { if (!callback_.is_null()) - callback_.Run(path, sync_status); + callback_.Run(path, flags); } }
diff --git a/components/pref_registry/pref_registry_syncable.h b/components/pref_registry/pref_registry_syncable.h index c3ca2b9..f95250d 100644 --- a/components/pref_registry/pref_registry_syncable.h +++ b/components/pref_registry/pref_registry_syncable.h
@@ -5,11 +5,10 @@ #ifndef COMPONENTS_PREF_REGISTRY_PREF_REGISTRY_SYNCABLE_H_ #define COMPONENTS_PREF_REGISTRY_PREF_REGISTRY_SYNCABLE_H_ -#include <set> #include <string> #include "base/callback.h" -#include "base/prefs/pref_registry.h" +#include "base/prefs/pref_registry_simple.h" #include "components/pref_registry/pref_registry_export.h" namespace base { @@ -32,30 +31,37 @@ // appropriate time before the PrefService for these preferences is // constructed. See e.g. chrome/browser/prefs/browser_prefs.cc which // does this for Chrome. -class PREF_REGISTRY_EXPORT PrefRegistrySyncable : public PrefRegistry { +// +// TODO(raymes): This class only exists to support SyncableRegistrationCallback +// logic which is only required to support pref registration after the +// PrefService has been created which is only used by tests. We can remove this +// entire class and those tests with some work. +class PREF_REGISTRY_EXPORT PrefRegistrySyncable : public PrefRegistrySimple { public: - // Enum used when registering preferences to determine if it should - // be synced or not. Syncable priority preferences are preferences that are - // never encrypted and are synced before other datatypes. Because they're - // never encrypted, on first sync, they can be synced down before the user - // is prompted for a passphrase. - enum PrefSyncStatus { - UNSYNCABLE_PREF, - SYNCABLE_PREF, - SYNCABLE_PRIORITY_PREF, + // Enum of flags used when registering preferences to determine if it should + // be synced or not. These flags are mutually exclusive, only one of them + // should ever be specified. + // + // Note: These must NOT overlap with PrefRegistry::PrefRegistrationFlags. + enum PrefRegistrationFlags { + // The pref will not be synced. + UNSYNCABLE_PREF = PrefRegistry::NO_REGISTRATION_FLAGS, + + // The pref will be synced. + SYNCABLE_PREF = 1 << 1, + + // The pref will be synced. The pref will never be encrypted and will be + // synced before other datatypes. Because they're never encrypted, on first + // sync, they can be synced down before the user is prompted for a + // passphrase. + SYNCABLE_PRIORITY_PREF = 1 << 2, }; - typedef - base::Callback<void(const char* path, const PrefSyncStatus sync_status)> - SyncableRegistrationCallback; + typedef base::Callback<void(const std::string& path, uint32 flags)> + SyncableRegistrationCallback; PrefRegistrySyncable(); - typedef std::map<std::string, PrefSyncStatus> PrefToStatus; - - // Retrieve the set of syncable preferences currently registered. - const PrefToStatus& syncable_preferences() const; - // Exactly one callback can be set for the event of a syncable // preference being registered. It will be fired after the // registration has occurred. @@ -65,38 +71,6 @@ // instead. void SetSyncableRegistrationCallback(const SyncableRegistrationCallback& cb); - void RegisterBooleanPref(const char* path, - bool default_value, - PrefSyncStatus sync_status); - void RegisterIntegerPref(const char* path, - int default_value, - PrefSyncStatus sync_status); - void RegisterDoublePref(const char* path, - double default_value, - PrefSyncStatus sync_status); - void RegisterStringPref(const char* path, - const std::string& default_value, - PrefSyncStatus sync_status); - void RegisterFilePathPref(const char* path, - const base::FilePath& default_value, - PrefSyncStatus sync_status); - void RegisterListPref(const char* path, - PrefSyncStatus sync_status); - void RegisterDictionaryPref(const char* path, - PrefSyncStatus sync_status); - void RegisterListPref(const char* path, - base::ListValue* default_value, - PrefSyncStatus sync_status); - void RegisterDictionaryPref(const char* path, - base::DictionaryValue* default_value, - PrefSyncStatus sync_status); - void RegisterInt64Pref(const char* path, - int64 default_value, - PrefSyncStatus sync_status); - void RegisterUint64Pref(const char* path, - uint64 default_value, - PrefSyncStatus sync_status); - // Returns a new PrefRegistrySyncable that uses the same defaults // store. scoped_refptr<PrefRegistrySyncable> ForkForIncognito(); @@ -104,15 +78,13 @@ private: ~PrefRegistrySyncable() override; - void RegisterSyncablePreference(const char* path, - base::Value* default_value, - PrefSyncStatus sync_status); + // PrefRegistrySimple overrides. + void OnPrefRegistered(const std::string& path, + base::Value* default_value, + uint32 flags) override; SyncableRegistrationCallback callback_; - // Contains the names of all registered preferences that are syncable. - PrefToStatus syncable_preferences_; - DISALLOW_COPY_AND_ASSIGN(PrefRegistrySyncable); };
diff --git a/components/printing/renderer/print_web_view_helper.h b/components/printing/renderer/print_web_view_helper.h index 562b1e0..a4eea7b 100644 --- a/components/printing/renderer/print_web_view_helper.h +++ b/components/printing/renderer/print_web_view_helper.h
@@ -26,7 +26,7 @@ struct PrintMsg_PrintPages_Params; struct PrintHostMsg_SetOptionsFromDocument_Params; -// RenderVIewTest-based tests crash on Android +// RenderViewTest-based tests crash on Android // http://crbug.com/187500 #if defined(OS_ANDROID) #define MAYBE_PrintWebViewHelperTest DISABLED_PrintWebViewHelperTest
diff --git a/components/printing/test/print_web_view_helper_browsertest.cc b/components/printing/test/print_web_view_helper_browsertest.cc index 65ecc23..864adc63 100644 --- a/components/printing/test/print_web_view_helper_browsertest.cc +++ b/components/printing/test/print_web_view_helper_browsertest.cc
@@ -248,7 +248,7 @@ DISALLOW_COPY_AND_ASSIGN(PrintWebViewHelperTestBase); }; -// RenderVIewTest-based tests crash on Android +// RenderViewTest-based tests crash on Android // http://crbug.com/187500 #if defined(OS_ANDROID) #define MAYBE_PrintWebViewHelperTest DISABLED_PrintWebViewHelperTest @@ -505,7 +505,7 @@ // These print preview tests do not work on Chrome OS yet. #if !defined(OS_CHROMEOS) -// RenderVIewTest-based tests crash on Android +// RenderViewTest-based tests crash on Android // http://crbug.com/187500 #if defined(OS_ANDROID) #define MAYBE_PrintWebViewHelperPreviewTest \
diff --git a/components/proximity_auth.gypi b/components/proximity_auth.gypi index 7da4644c..e10cc9c 100644 --- a/components/proximity_auth.gypi +++ b/components/proximity_auth.gypi
@@ -16,15 +16,20 @@ '../net/net.gyp:net', ], 'sources': [ + "proximity_auth/ble/bluetooth_low_energy_connection_finder.cc", + "proximity_auth/ble/bluetooth_low_energy_connection_finder.h", + "proximity_auth/ble/proximity_auth_ble_system.cc", + "proximity_auth/ble/proximity_auth_ble_system.h", "proximity_auth/bluetooth_connection.cc", "proximity_auth/bluetooth_connection.h", "proximity_auth/bluetooth_connection_finder.cc", "proximity_auth/bluetooth_connection_finder.h", + "proximity_auth/bluetooth_throttler.h", + "proximity_auth/bluetooth_throttler_impl.cc", + "proximity_auth/bluetooth_throttler_impl.h", "proximity_auth/bluetooth_util.cc", "proximity_auth/bluetooth_util.h", "proximity_auth/bluetooth_util_chromeos.cc", - "proximity_auth/ble/proximity_auth_ble_system.cc", - "proximity_auth/ble/proximity_auth_ble_system.h", "proximity_auth/client.cc", "proximity_auth/client.h", "proximity_auth/client_observer.h", @@ -32,14 +37,19 @@ "proximity_auth/connection.h", "proximity_auth/connection_finder.h", "proximity_auth/connection_observer.h", + "proximity_auth/proximity_auth_client.h", "proximity_auth/proximity_auth_system.cc", "proximity_auth/proximity_auth_system.h", "proximity_auth/remote_device.h", "proximity_auth/remote_status_update.cc", "proximity_auth/remote_status_update.h", + "proximity_auth/screenlock_bridge.cc", + "proximity_auth/screenlock_bridge.h", "proximity_auth/secure_context.h", "proximity_auth/switches.cc", "proximity_auth/switches.h", + "proximity_auth/throttled_bluetooth_connection_finder.cc", + "proximity_auth/throttled_bluetooth_connection_finder.h", "proximity_auth/wire_message.cc", "proximity_auth/wire_message.h", ], @@ -114,5 +124,28 @@ 'cryptauth_proto', ], }, + { + # GN version: //components/proximity_auth/webui + 'target_name': 'proximity_auth_webui', + 'type': 'static_library', + 'dependencies': [ + '../base/base.gyp:base', + '../content/content.gyp:content_browser', + 'components_resources.gyp:components_resources', + 'proximity_auth', + 'cryptauth', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + 'proximity_auth/webui/proximity_auth_ui.cc', + 'proximity_auth/webui/proximity_auth_ui.h', + 'proximity_auth/webui/proximity_auth_webui_handler.cc', + 'proximity_auth/webui/proximity_auth_webui_handler.h', + 'proximity_auth/webui/url_constants.cc', + 'proximity_auth/webui/url_constants.h', + ], + }, ], }
diff --git a/components/proximity_auth/BUILD.gn b/components/proximity_auth/BUILD.gn index 380459e6..e2faf96 100644 --- a/components/proximity_auth/BUILD.gn +++ b/components/proximity_auth/BUILD.gn
@@ -10,6 +10,9 @@ "bluetooth_connection.h", "bluetooth_connection_finder.cc", "bluetooth_connection_finder.h", + "bluetooth_throttler.h", + "bluetooth_throttler_impl.cc", + "bluetooth_throttler_impl.h", "bluetooth_util.cc", "bluetooth_util.h", "bluetooth_util_chromeos.cc", @@ -20,14 +23,19 @@ "connection.h", "connection_finder.h", "connection_observer.h", + "proximity_auth_client.h", "proximity_auth_system.cc", "proximity_auth_system.h", "remote_device.h", "remote_status_update.cc", "remote_status_update.h", + "screenlock_bridge.cc", + "screenlock_bridge.h", "secure_context.h", "switches.cc", "switches.h", + "throttled_bluetooth_connection_finder.cc", + "throttled_bluetooth_connection_finder.h", "wire_message.cc", "wire_message.h", ] @@ -44,10 +52,12 @@ sources = [ "bluetooth_connection_finder_unittest.cc", "bluetooth_connection_unittest.cc", + "bluetooth_throttler_impl_unittest.cc", "client_unittest.cc", "connection_unittest.cc", "proximity_auth_system_unittest.cc", "remote_status_update_unittest.cc", + "throttled_bluetooth_connection_finder_unittest.cc", "wire_message_unittest.cc", ]
diff --git a/components/proximity_auth/DEPS b/components/proximity_auth/DEPS index 6d746ad..161da31 100644 --- a/components/proximity_auth/DEPS +++ b/components/proximity_auth/DEPS
@@ -2,3 +2,9 @@ "+device/bluetooth", "+net", ] + +specific_include_rules = { + "screenlock_bridge\.*": [ + "+chromeos", + ], +}
diff --git a/components/proximity_auth/ble/BUILD.gn b/components/proximity_auth/ble/BUILD.gn index db2d0db..71324c5c 100644 --- a/components/proximity_auth/ble/BUILD.gn +++ b/components/proximity_auth/ble/BUILD.gn
@@ -4,6 +4,8 @@ source_set("ble") { sources = [ + "bluetooth_low_energy_connection_finder.cc", + "bluetooth_low_energy_connection_finder.h", "proximity_auth_ble_system.cc", "proximity_auth_ble_system.h", ]
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc new file mode 100644 index 0000000..0fdec85 --- /dev/null +++ b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.cc
@@ -0,0 +1,181 @@ +// 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/proximity_auth/ble/bluetooth_low_energy_connection_finder.h" + +#include <string> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/logging.h" +#include "device/bluetooth/bluetooth_adapter_factory.h" +#include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/bluetooth_discovery_session.h" +#include "device/bluetooth/bluetooth_uuid.h" + +using device::BluetoothAdapter; +using device::BluetoothDevice; +using device::BluetoothGattConnection; + +namespace proximity_auth { + +BluetoothLowEnergyConnectionFinder::BluetoothLowEnergyConnectionFinder( + const std::string& remote_service_uuid) + : remote_service_uuid_(device::BluetoothUUID(remote_service_uuid)), + connected_(false), + weak_ptr_factory_(this) { +} + +BluetoothLowEnergyConnectionFinder::~BluetoothLowEnergyConnectionFinder() { + if (discovery_session_) { + StopDiscoverySession(); + } + if (adapter_) { + adapter_->RemoveObserver(this); + adapter_ = NULL; + } +} + +void BluetoothLowEnergyConnectionFinder::Find( + const BluetoothDevice::GattConnectionCallback& connection_callback) { + if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) { + VLOG(1) << "[BCF] Bluetooth is unsupported on this platform. Aborting."; + return; + } + VLOG(1) << "Finding connection"; + + connection_callback_ = connection_callback; + + device::BluetoothAdapterFactory::GetAdapter( + base::Bind(&BluetoothLowEnergyConnectionFinder::OnAdapterInitialized, + weak_ptr_factory_.GetWeakPtr())); +} + +void BluetoothLowEnergyConnectionFinder::Find( + const ConnectionCallback& connection_callback) { + NOTREACHED(); +} + +void BluetoothLowEnergyConnectionFinder::DeviceAdded(BluetoothAdapter* adapter, + BluetoothDevice* device) { + if (device) { + VLOG(1) << "New device found: " << device->GetName(); + HandleDeviceAdded(device); + } +} + +void BluetoothLowEnergyConnectionFinder::OnAdapterInitialized( + scoped_refptr<BluetoothAdapter> adapter) { + VLOG(1) << "Adapter ready"; + + adapter_ = adapter; + adapter_->AddObserver(this); + + std::vector<BluetoothDevice*> devices = adapter_->GetDevices(); + for (auto iter = devices.begin(); iter != devices.end(); iter++) { + HandleDeviceAdded((*iter)); + } + + StartDiscoverySession(); +} + +void BluetoothLowEnergyConnectionFinder::HandleDeviceAdded( + BluetoothDevice* remote_device) { + if (!connected_ && HasService(remote_device)) { + CreateConnection(remote_device); + } +} + +void BluetoothLowEnergyConnectionFinder::OnDiscoverySessionStarted( + scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { + VLOG(1) << "Discovery session started"; + discovery_session_ = discovery_session.Pass(); +} + +void BluetoothLowEnergyConnectionFinder::OnStartDiscoverySessionError() { + VLOG(1) << "Error starting discovery session"; +} + +void BluetoothLowEnergyConnectionFinder::StartDiscoverySession() { + DCHECK(adapter_); + if (discovery_session_ && discovery_session_->IsActive()) { + VLOG(1) << "Discovery session already active"; + return; + } + adapter_->StartDiscoverySession( + base::Bind(&BluetoothLowEnergyConnectionFinder::OnDiscoverySessionStarted, + weak_ptr_factory_.GetWeakPtr()), + base::Bind( + &BluetoothLowEnergyConnectionFinder::OnStartDiscoverySessionError, + weak_ptr_factory_.GetWeakPtr())); +} + +void BluetoothLowEnergyConnectionFinder::OnDiscoverySessionStopped() { + VLOG(1) << "Discovery session stopped"; + discovery_session_.reset(); +} + +void BluetoothLowEnergyConnectionFinder::OnStopDiscoverySessionError() { + VLOG(1) << "Error stopping discovery session"; +} + +void BluetoothLowEnergyConnectionFinder::StopDiscoverySession() { + VLOG(1) << "Stopping discovery sesison"; + + if (!adapter_) { + VLOG(1) << "Adapter not initialized"; + return; + } + if (!discovery_session_ || !discovery_session_->IsActive()) { + VLOG(1) << "No Active discovery session"; + } + + discovery_session_->Stop( + base::Bind(&BluetoothLowEnergyConnectionFinder::OnDiscoverySessionStopped, + weak_ptr_factory_.GetWeakPtr()), + base::Bind( + &BluetoothLowEnergyConnectionFinder::OnStopDiscoverySessionError, + weak_ptr_factory_.GetWeakPtr())); +} + +bool BluetoothLowEnergyConnectionFinder::HasService( + BluetoothDevice* remote_device) { + if (remote_device) { + std::vector<device::BluetoothUUID> uuids = remote_device->GetUUIDs(); + for (auto iter = uuids.begin(); iter != uuids.end(); iter++) { + if (remote_service_uuid_ == *iter) { + return true; + } + } + } + return false; +} + +void BluetoothLowEnergyConnectionFinder::OnCreateConnectionError( + BluetoothDevice::ConnectErrorCode error_code) { + VLOG(1) << "Error creating connection"; +} + +void BluetoothLowEnergyConnectionFinder::OnConnectionCreated( + scoped_ptr<BluetoothGattConnection> connection) { + VLOG(1) << "Connection created"; + connected_ = true; + StopDiscoverySession(); + connection_callback_.Run(connection.Pass()); +} + +void BluetoothLowEnergyConnectionFinder::CreateConnection( + device::BluetoothDevice* remote_device) { + VLOG(1) << "SmartLock service found (" + << remote_service_uuid_.canonical_value() << ")\n" + << "device = " << remote_device->GetAddress() + << ", name = " << remote_device->GetName(); + remote_device->CreateGattConnection( + base::Bind(&BluetoothLowEnergyConnectionFinder::OnConnectionCreated, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&BluetoothLowEnergyConnectionFinder::OnCreateConnectionError, + weak_ptr_factory_.GetWeakPtr())); +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h new file mode 100644 index 0000000..618a502 --- /dev/null +++ b/components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h
@@ -0,0 +1,106 @@ +// 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_PROXIMITY_AUTH_BLE_BLUETOOTH_LOW_ENERGY_CONNECTION_FINDER_H +#define COMPONENTS_PROXIMITY_AUTH_BLE_BLUETOOTH_LOW_ENERGY_CONNECTION_FINDER_H + +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "components/proximity_auth/connection_finder.h" +#include "device/bluetooth/bluetooth_adapter.h" +#include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/bluetooth_discovery_session.h" +#include "device/bluetooth/bluetooth_gatt_connection.h" + +namespace proximity_auth { + +// This ConnectionFinder implementation is specialized in finding a Bluetooth +// Low Energy remote device. +class BluetoothLowEnergyConnectionFinder + : public ConnectionFinder, + public device::BluetoothAdapter::Observer { + public: + BluetoothLowEnergyConnectionFinder(const std::string& remote_service_uuid); + ~BluetoothLowEnergyConnectionFinder() override; + + // Finds a connection the remote device, only the first one is functional. + void Find(const device::BluetoothDevice::GattConnectionCallback& + connection_callback); + void Find(const ConnectionCallback& connection_callback) override; + + protected: + // device::BluetoothAdapter::Observer: + void DeviceAdded(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override; + + private: + // Callback to be called when the Bluetooth adapter is initialized. + void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter); + + // Checks if |remote_device| contains |remote_service_uuid| and creates a + // connection in that case. + void HandleDeviceAdded(device::BluetoothDevice* remote_device); + + // Callback called when a new discovery session is started. + void OnDiscoverySessionStarted( + scoped_ptr<device::BluetoothDiscoverySession> discovery_session); + + // Callback called when there is an error starting a new discovery session. + void OnStartDiscoverySessionError(); + + // Starts a discovery session for |adapter_|. + void StartDiscoverySession(); + + // Callback called when |discovery_session_| is stopped. + void OnDiscoverySessionStopped(); + + // Callback called when there is an error stopping |discovery_session_|. + void OnStopDiscoverySessionError(); + + // Stops the discovery session given by |discovery_session_|. + void StopDiscoverySession(); + + // Checks if a service with |service_uuid| is offered by |remote_device|. + bool HasService(device::BluetoothDevice* remote_device); + + // Callback called when there is an error creating the connection. + void OnCreateConnectionError( + device::BluetoothDevice::ConnectErrorCode error_code); + + // Callback called when the connection is created. + void OnConnectionCreated( + scoped_ptr<device::BluetoothGattConnection> connection); + + // Creates a GATT connection with |remote_device|, |connection_callback_| will + // be called once the connection is established. + void CreateConnection(device::BluetoothDevice* remote_device); + + // The uuid of the service it looks for to establish a GattConnection. + device::BluetoothUUID remote_service_uuid_; + + // The Bluetooth adapter over which the Bluetooth connection will be made. + scoped_refptr<device::BluetoothAdapter> adapter_; + + // The discovery session associated to this object. + scoped_ptr<device::BluetoothDiscoverySession> discovery_session_; + + // True if there is a connection. + bool connected_; + + // Callback called when the connection is established. + device::BluetoothDevice::GattConnectionCallback connection_callback_; + + base::WeakPtrFactory<BluetoothLowEnergyConnectionFinder> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyConnectionFinder); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_BLE_BLUETOOTH_CONNECTION_FINDER_H
diff --git a/components/proximity_auth/ble/proximity_auth_ble_system.cc b/components/proximity_auth/ble/proximity_auth_ble_system.cc index b4f20e4..ecdb90d0 100644 --- a/components/proximity_auth/ble/proximity_auth_ble_system.cc +++ b/components/proximity_auth/ble/proximity_auth_ble_system.cc
@@ -4,16 +4,33 @@ #include "components/proximity_auth/ble/proximity_auth_ble_system.h" +#include "base/bind.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "components/proximity_auth/connection.h" +#include "device/bluetooth/bluetooth_device.h" + +#include "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h" namespace proximity_auth { +const char kSmartLockServiceUUID[] = "b3b7e28e-a000-3e17-bd86-6e97b9e28c11"; + +void ConnectionCallback( + scoped_ptr<device::BluetoothGattConnection> connection) { + VLOG(1) << "Connection established"; +} + ProximityAuthBleSystem::ProximityAuthBleSystem() { VLOG(1) << "Starting Proximity Auth over Bluetooth Low Energy."; + connection_finder_ = scoped_ptr<BluetoothLowEnergyConnectionFinder>( + new BluetoothLowEnergyConnectionFinder(kSmartLockServiceUUID)); + connection_finder_->Find(base::Bind(&ConnectionCallback)); } ProximityAuthBleSystem::~ProximityAuthBleSystem() { VLOG(1) << "Stopping Proximity over Bluetooth Low Energy."; + connection_finder_.reset(); } } // namespace proximity_auth
diff --git a/components/proximity_auth/ble/proximity_auth_ble_system.h b/components/proximity_auth/ble/proximity_auth_ble_system.h index ab59bae..29ba662 100644 --- a/components/proximity_auth/ble/proximity_auth_ble_system.h +++ b/components/proximity_auth/ble/proximity_auth_ble_system.h
@@ -6,6 +6,9 @@ #define COMPONENTS_PROXIMITY_AUTH_BLE_PROXIMITY_AUTH_BLE_SYSTEM_H_ #include "base/macros.h" +#include "base/memory/scoped_ptr.h" + +#include "components/proximity_auth/ble/bluetooth_low_energy_connection_finder.h" namespace proximity_auth { @@ -19,6 +22,8 @@ ~ProximityAuthBleSystem(); private: + scoped_ptr<BluetoothLowEnergyConnectionFinder> connection_finder_; + DISALLOW_COPY_AND_ASSIGN(ProximityAuthBleSystem); };
diff --git a/components/proximity_auth/bluetooth_connection_finder.cc b/components/proximity_auth/bluetooth_connection_finder.cc index 3fe6567..1f26d2ffc 100644 --- a/components/proximity_auth/bluetooth_connection_finder.cc +++ b/components/proximity_auth/bluetooth_connection_finder.cc
@@ -119,10 +119,10 @@ } void BluetoothConnectionFinder::OnConnectionStatusChanged( - const Connection& connection, + Connection* connection, Connection::Status old_status, Connection::Status new_status) { - DCHECK_EQ(&connection, connection_.get()); + DCHECK_EQ(connection, connection_.get()); if (connection_->IsConnected()) { base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
diff --git a/components/proximity_auth/bluetooth_connection_finder.h b/components/proximity_auth/bluetooth_connection_finder.h index 40b28dd4..cca88f63 100644 --- a/components/proximity_auth/bluetooth_connection_finder.h +++ b/components/proximity_auth/bluetooth_connection_finder.h
@@ -64,7 +64,7 @@ void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter); // ConnectionObserver: - void OnConnectionStatusChanged(const Connection& connection, + void OnConnectionStatusChanged(Connection* connection, Connection::Status old_status, Connection::Status new_status) override;
diff --git a/components/proximity_auth/bluetooth_throttler.h b/components/proximity_auth/bluetooth_throttler.h new file mode 100644 index 0000000..1e428fe --- /dev/null +++ b/components/proximity_auth/bluetooth_throttler.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 COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_H +#define COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_H + +namespace base { +class TimeDelta; +} + +namespace proximity_auth { + +class Connection; + +// An interface for throttling repeated connection attempts to the same device. +// This throttling is necessary to prevent a kernel race condition when +// connecting before the previous connection fully closes, putting the +// connection in a corrupted, and unrecoverable state. http://crbug.com/345232 +class BluetoothThrottler { + public: + virtual ~BluetoothThrottler() {} + + // Returns the current delay that must be respected prior to reattempting to + // establish a connection with the remote device. The returned value is 0 if + // no delay is needed. + virtual base::TimeDelta GetDelay() const = 0; + + // Should be called when a connection to the remote device is established. + // Note that the |connection| is passed as a weak reference. The throttler + // will ensure, by registering as an observer, that it never attempts to use + // the connection after it has been destroyed. + virtual void OnConnection(Connection* connection) = 0; +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_H
diff --git a/components/proximity_auth/bluetooth_throttler_impl.cc b/components/proximity_auth/bluetooth_throttler_impl.cc new file mode 100644 index 0000000..9963fb0 --- /dev/null +++ b/components/proximity_auth/bluetooth_throttler_impl.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 "components/proximity_auth/bluetooth_throttler_impl.h" + +#include "base/stl_util.h" +#include "base/time/tick_clock.h" +#include "components/proximity_auth/connection.h" + +namespace proximity_auth { +namespace { + +// Time to wait after disconnect before reconnecting. +const int kCooldownTimeSecs = 7; + +} // namespace + +BluetoothThrottlerImpl::BluetoothThrottlerImpl( + scoped_ptr<base::TickClock> clock) + : clock_(clock.Pass()) { +} + +BluetoothThrottlerImpl::~BluetoothThrottlerImpl() { + for (Connection* connection : connections_) { + connection->RemoveObserver(this); + } +} + +base::TimeDelta BluetoothThrottlerImpl::GetDelay() const { + if (last_disconnect_time_.is_null()) + return base::TimeDelta(); + + base::TimeTicks now = clock_->NowTicks(); + base::TimeTicks throttled_start_time = + last_disconnect_time_ + GetCooldownTimeDelta(); + if (now >= throttled_start_time) + return base::TimeDelta(); + + return throttled_start_time - now; +} + +void BluetoothThrottlerImpl::OnConnection(Connection* connection) { + DCHECK(!ContainsKey(connections_, connection)); + connections_.insert(connection); + connection->AddObserver(this); +} + +base::TimeDelta BluetoothThrottlerImpl::GetCooldownTimeDelta() const { + return base::TimeDelta::FromSeconds(kCooldownTimeSecs); +} + +void BluetoothThrottlerImpl::OnConnectionStatusChanged( + Connection* connection, + Connection::Status old_status, + Connection::Status new_status) { + DCHECK(ContainsKey(connections_, connection)); + if (old_status == Connection::CONNECTED && + new_status == Connection::DISCONNECTED) { + last_disconnect_time_ = clock_->NowTicks(); + connection->RemoveObserver(this); + connections_.erase(connection); + } +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/bluetooth_throttler_impl.h b/components/proximity_auth/bluetooth_throttler_impl.h new file mode 100644 index 0000000..3ba71541 --- /dev/null +++ b/components/proximity_auth/bluetooth_throttler_impl.h
@@ -0,0 +1,69 @@ +// 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_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_IMPL_H +#define COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_IMPL_H + +#include <set> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "components/proximity_auth/bluetooth_throttler.h" +#include "components/proximity_auth/connection_observer.h" + +namespace base { +class TickClock; +} + +namespace proximity_auth { + +class Connection; + +// This class throttles repeated connection attempts to the same device. This +// throttling is necessary to prevent a kernel race condition when connecting +// before the previous connection fully closes, putting the connection in a +// corrupted, and unrecoverable state. http://crbug.com/345232 +class BluetoothThrottlerImpl : public BluetoothThrottler, + public ConnectionObserver { + public: + // Creates a throttler for connections to a remote device, using the |clock| + // as a time source. + explicit BluetoothThrottlerImpl(scoped_ptr<base::TickClock> clock); + ~BluetoothThrottlerImpl() override; + + // BluetoothThrottler: + base::TimeDelta GetDelay() const override; + void OnConnection(Connection* connection) override; + + protected: + // Returns the duration to wait, after disconnecting, before reattempting a + // connection to the remote device. Exposed for testing. + base::TimeDelta GetCooldownTimeDelta() const; + + private: + // ConnectionObserver: + void OnConnectionStatusChanged(Connection* connection, + Connection::Status old_status, + Connection::Status new_status) override; + + // Tracks the last seen disconnect time for the |remote_device_|. + base::TimeTicks last_disconnect_time_; + + // The time source. + scoped_ptr<base::TickClock> clock_; + + // The currently connected connections. + // Each connection is stored as a weak reference, which is safe because |this| + // instance is registered as an observer, and will unregister when the + // connection disconnects, which is guaranteed to occur before the connection + // is destroyed. + std::set<Connection*> connections_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothThrottlerImpl); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_THROTTLER_IMPL_H
diff --git a/components/proximity_auth/bluetooth_throttler_impl_unittest.cc b/components/proximity_auth/bluetooth_throttler_impl_unittest.cc new file mode 100644 index 0000000..1bca940f --- /dev/null +++ b/components/proximity_auth/bluetooth_throttler_impl_unittest.cc
@@ -0,0 +1,88 @@ +// 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/proximity_auth/bluetooth_throttler_impl.h" + +#include "base/test/simple_test_tick_clock.h" +#include "base/time/time.h" +#include "components/proximity_auth/wire_message.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace proximity_auth { +namespace { + +class StubConnection : public Connection { + public: + StubConnection() : Connection(RemoteDevice()) {} + ~StubConnection() override {} + + void Connect() override {} + void Disconnect() override {} + void SendMessageImpl(scoped_ptr<WireMessage> message) override {} + + private: + DISALLOW_COPY_AND_ASSIGN(StubConnection); +}; + +class TestBluetoothThrottler : public BluetoothThrottlerImpl { + public: + explicit TestBluetoothThrottler(scoped_ptr<base::TickClock> clock) + : BluetoothThrottlerImpl(clock.Pass()) {} + ~TestBluetoothThrottler() override {} + + // Increase visibility for testing. + using BluetoothThrottlerImpl::GetCooldownTimeDelta; + + private: + DISALLOW_COPY_AND_ASSIGN(TestBluetoothThrottler); +}; + +} // namespace + +class ProximityAuthBluetoothThrottlerImplTest : public testing::Test { + public: + ProximityAuthBluetoothThrottlerImplTest() + : clock_(new base::SimpleTestTickClock), + throttler_(make_scoped_ptr(clock_)) { + // The throttler treats null times as special, so start with a non-null + // time. + clock_->Advance(base::TimeDelta::FromSeconds(1)); + } + + protected: + // The clock is owned by the |throttler_|. + base::SimpleTestTickClock* clock_; + TestBluetoothThrottler throttler_; +}; + +TEST_F(ProximityAuthBluetoothThrottlerImplTest, + GetDelay_FirstConnectionIsNotThrottled) { + EXPECT_EQ(base::TimeDelta(), throttler_.GetDelay()); +} + +TEST_F(ProximityAuthBluetoothThrottlerImplTest, + GetDelay_ConnectionAfterDisconnectIsThrottled) { + // Simulate a connection followed by a disconnection. + StubConnection connection; + throttler_.OnConnection(&connection); + static_cast<ConnectionObserver*>(&throttler_) + ->OnConnectionStatusChanged(&connection, Connection::CONNECTED, + Connection::DISCONNECTED); + EXPECT_GT(throttler_.GetDelay(), base::TimeDelta()); +} + +TEST_F(ProximityAuthBluetoothThrottlerImplTest, + GetDelay_DelayedConnectionAfterDisconnectIsNotThrottled) { + // Simulate a connection followed by a disconnection, then allow the cooldown + // period to elapse. + StubConnection connection; + throttler_.OnConnection(&connection); + static_cast<ConnectionObserver*>(&throttler_) + ->OnConnectionStatusChanged(&connection, Connection::CONNECTED, + Connection::DISCONNECTED); + clock_->Advance(throttler_.GetCooldownTimeDelta()); + EXPECT_EQ(base::TimeDelta(), throttler_.GetDelay()); +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/client.cc b/components/proximity_auth/client.cc index 016c505..a0b6a06 100644 --- a/components/proximity_auth/client.cc +++ b/components/proximity_auth/client.cc
@@ -177,10 +177,10 @@ FOR_EACH_OBSERVER(ClientObserver, observers_, OnUnlockResponse(true)); } -void Client::OnConnectionStatusChanged(const Connection& connection, +void Client::OnConnectionStatusChanged(Connection* connection, Connection::Status old_status, Connection::Status new_status) { - DCHECK_EQ(&connection, connection_.get()); + DCHECK_EQ(connection, connection_.get()); if (new_status != Connection::CONNECTED) { VLOG(1) << "[Client] Secure channel disconnected..."; connection_->RemoveObserver(this);
diff --git a/components/proximity_auth/client.h b/components/proximity_auth/client.h index 5cd5107..3b66e8e 100644 --- a/components/proximity_auth/client.h +++ b/components/proximity_auth/client.h
@@ -91,7 +91,7 @@ void HandleUnlockResponseMessage(const base::DictionaryValue& message); // ConnectionObserver: - void OnConnectionStatusChanged(const Connection& connection, + void OnConnectionStatusChanged(Connection* connection, Connection::Status old_status, Connection::Status new_status) override; void OnMessageReceived(const Connection& connection,
diff --git a/components/proximity_auth/connection.cc b/components/proximity_auth/connection.cc index 65f6dd6..437be60 100644 --- a/components/proximity_auth/connection.cc +++ b/components/proximity_auth/connection.cc
@@ -54,9 +54,8 @@ Status old_status = status_; status_ = status; - FOR_EACH_OBSERVER(ConnectionObserver, - observers_, - OnConnectionStatusChanged(*this, old_status, status_)); + FOR_EACH_OBSERVER(ConnectionObserver, observers_, + OnConnectionStatusChanged(this, old_status, status_)); } void Connection::OnDidSendMessage(const WireMessage& message, bool success) {
diff --git a/components/proximity_auth/connection_finder.h b/components/proximity_auth/connection_finder.h index 51292da..246a9a0d 100644 --- a/components/proximity_auth/connection_finder.h +++ b/components/proximity_auth/connection_finder.h
@@ -16,7 +16,6 @@ // Interface for finding a connection to a remote device. class ConnectionFinder { public: - ConnectionFinder() {} virtual ~ConnectionFinder() {} // Attempts to find a connection to a remote device. The finder will try to @@ -27,9 +26,6 @@ typedef base::Callback<void(scoped_ptr<Connection> connection)> ConnectionCallback; virtual void Find(const ConnectionCallback& connection_callback) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(ConnectionFinder); }; } // namespace proximity_auth
diff --git a/components/proximity_auth/connection_observer.h b/components/proximity_auth/connection_observer.h index 89bf974..27cfb35 100644 --- a/components/proximity_auth/connection_observer.h +++ b/components/proximity_auth/connection_observer.h
@@ -15,8 +15,8 @@ class ConnectionObserver { public: // Called when the |connection|'s status changes from |old_status| to - // |new_status|. - virtual void OnConnectionStatusChanged(const Connection& connection, + // |new_status|. The |connectoin| is guaranteed to be non-null. + virtual void OnConnectionStatusChanged(Connection* connection, Connection::Status old_status, Connection::Status new_status) {}
diff --git a/components/proximity_auth/connection_unittest.cc b/components/proximity_auth/connection_unittest.cc index 8fb1593..3fb5f50 100644 --- a/components/proximity_auth/connection_unittest.cc +++ b/components/proximity_auth/connection_unittest.cc
@@ -59,7 +59,7 @@ virtual ~MockConnectionObserver() {} MOCK_METHOD3(OnConnectionStatusChanged, - void(const Connection& connection, + void(Connection* connection, Connection::Status old_status, Connection::Status new_status)); MOCK_METHOD2(OnMessageReceived, @@ -143,10 +143,9 @@ StrictMock<MockConnectionObserver> observer; connection.AddObserver(&observer); - EXPECT_CALL( - observer, - OnConnectionStatusChanged( - Ref(connection), Connection::DISCONNECTED, Connection::CONNECTED)); + EXPECT_CALL(observer, + OnConnectionStatusChanged(&connection, Connection::DISCONNECTED, + Connection::CONNECTED)); connection.SetStatus(Connection::CONNECTED); }
diff --git a/components/proximity_auth/proximity_auth_client.h b/components/proximity_auth/proximity_auth_client.h new file mode 100644 index 0000000..b9ad7521 --- /dev/null +++ b/components/proximity_auth/proximity_auth_client.h
@@ -0,0 +1,39 @@ +// 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_PROXIMITY_AUTH_CLIENT_H_ +#define COMPONENTS_PROXIMITY_AUTH_CLIENT_H_ + +#include <string> + +#include "base/macros.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace proximity_auth { + +// An interface that needs to be supplied to the Proximity Auth component by its +// embedder. +class ProximityAuthClient { + public: + // Returns the authenticated username for |browser_context|. + virtual std::string GetAuthenticatedUsername( + content::BrowserContext* browser_context) const = 0; + + // Locks the screen for |browser_context|. + virtual void Lock(content::BrowserContext* browser_context) = 0; + + protected: + ProximityAuthClient() {} + virtual ~ProximityAuthClient() {} + + private: + DISALLOW_COPY_AND_ASSIGN(ProximityAuthClient); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_CLIENT_H_
diff --git a/components/proximity_auth/screenlock_bridge.cc b/components/proximity_auth/screenlock_bridge.cc new file mode 100644 index 0000000..2af83781 --- /dev/null +++ b/components/proximity_auth/screenlock_bridge.cc
@@ -0,0 +1,176 @@ +// 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/screenlock_bridge.h" + +#include "base/logging.h" +#include "base/strings/string16.h" +#include "components/proximity_auth/proximity_auth_client.h" + +#if defined(OS_CHROMEOS) +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/session_manager_client.h" +#endif + +namespace proximity_auth { +namespace { + +// Ids for the icons that are supported by lock screen and signin screen +// account picker as user pod custom icons. +// The id's should be kept in sync with values used by user_pod_row.js. +const char kLockedUserPodCustomIconId[] = "locked"; +const char kLockedToBeActivatedUserPodCustomIconId[] = "locked-to-be-activated"; +const char kLockedWithProximityHintUserPodCustomIconId[] = + "locked-with-proximity-hint"; +const char kUnlockedUserPodCustomIconId[] = "unlocked"; +const char kHardlockedUserPodCustomIconId[] = "hardlocked"; +const char kSpinnerUserPodCustomIconId[] = "spinner"; + +// Given the user pod icon, returns its id as used by the user pod UI code. +std::string GetIdForIcon(ScreenlockBridge::UserPodCustomIcon icon) { + switch (icon) { + case ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED: + return kLockedUserPodCustomIconId; + case ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED: + return kLockedToBeActivatedUserPodCustomIconId; + case ScreenlockBridge::USER_POD_CUSTOM_ICON_LOCKED_WITH_PROXIMITY_HINT: + return kLockedWithProximityHintUserPodCustomIconId; + case ScreenlockBridge::USER_POD_CUSTOM_ICON_UNLOCKED: + return kUnlockedUserPodCustomIconId; + case ScreenlockBridge::USER_POD_CUSTOM_ICON_HARDLOCKED: + return kHardlockedUserPodCustomIconId; + case ScreenlockBridge::USER_POD_CUSTOM_ICON_SPINNER: + return kSpinnerUserPodCustomIconId; + default: + return ""; + } +} + +} // namespace + +ScreenlockBridge::ScreenlockBridge(ProximityAuthClient* client) + : client_(client), lock_handler_(nullptr) { + DCHECK(client_); +} + +ScreenlockBridge::~ScreenlockBridge() { +} + +ScreenlockBridge::UserPodCustomIconOptions::UserPodCustomIconOptions() + : autoshow_tooltip_(false), + hardlock_on_click_(false), + is_trial_run_(false) { +} + +ScreenlockBridge::UserPodCustomIconOptions::~UserPodCustomIconOptions() { +} + +scoped_ptr<base::DictionaryValue> +ScreenlockBridge::UserPodCustomIconOptions::ToDictionaryValue() const { + scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); + std::string icon_id = GetIdForIcon(icon_); + result->SetString("id", icon_id); + + if (!tooltip_.empty()) { + base::DictionaryValue* tooltip_options = new base::DictionaryValue(); + tooltip_options->SetString("text", tooltip_); + tooltip_options->SetBoolean("autoshow", autoshow_tooltip_); + result->Set("tooltip", tooltip_options); + } + + if (!aria_label_.empty()) + result->SetString("ariaLabel", aria_label_); + + if (hardlock_on_click_) + result->SetBoolean("hardlockOnClick", true); + + if (is_trial_run_) + result->SetBoolean("isTrialRun", true); + + return result.Pass(); +} + +void ScreenlockBridge::UserPodCustomIconOptions::SetIcon( + ScreenlockBridge::UserPodCustomIcon icon) { + icon_ = icon; +} + +void ScreenlockBridge::UserPodCustomIconOptions::SetTooltip( + const base::string16& tooltip, + bool autoshow) { + tooltip_ = tooltip; + autoshow_tooltip_ = autoshow; +} + +void ScreenlockBridge::UserPodCustomIconOptions::SetAriaLabel( + const base::string16& aria_label) { + aria_label_ = aria_label; +} + +void ScreenlockBridge::UserPodCustomIconOptions::SetHardlockOnClick() { + hardlock_on_click_ = true; +} + +void ScreenlockBridge::UserPodCustomIconOptions::SetTrialRun() { + is_trial_run_ = true; +} + +void ScreenlockBridge::SetLockHandler(LockHandler* lock_handler) { + DCHECK(lock_handler_ == nullptr || lock_handler == nullptr); + + // Don't notify observers if there is no change -- i.e. if the screen was + // already unlocked, and is remaining unlocked. + if (lock_handler == lock_handler_) + return; + + // TODO(isherman): If |lock_handler| is null, then |lock_handler_| might have + // been freed. Cache the screen type rather than querying it below. + LockHandler::ScreenType screen_type; + if (lock_handler_) + screen_type = lock_handler_->GetScreenType(); + else + screen_type = lock_handler->GetScreenType(); + + lock_handler_ = lock_handler; + if (lock_handler_) + FOR_EACH_OBSERVER(Observer, observers_, OnScreenDidLock(screen_type)); + else + FOR_EACH_OBSERVER(Observer, observers_, OnScreenDidUnlock(screen_type)); +} + +void ScreenlockBridge::SetFocusedUser(const std::string& user_id) { + if (user_id == focused_user_id_) + return; + focused_user_id_ = user_id; + FOR_EACH_OBSERVER(Observer, observers_, OnFocusedUserChanged(user_id)); +} + +bool ScreenlockBridge::IsLocked() const { + return lock_handler_ != nullptr; +} + +void ScreenlockBridge::Lock(content::BrowserContext* browser_context) { +#if defined(OS_CHROMEOS) + chromeos::SessionManagerClient* session_manager = + chromeos::DBusThreadManager::Get()->GetSessionManagerClient(); + session_manager->RequestLockScreen(); +#else + client_->Lock(browser_context); +#endif +} + +void ScreenlockBridge::Unlock(content::BrowserContext* browser_context) { + if (lock_handler_) + lock_handler_->Unlock(client_->GetAuthenticatedUsername(browser_context)); +} + +void ScreenlockBridge::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void ScreenlockBridge::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/screenlock_bridge.h b/components/proximity_auth/screenlock_bridge.h new file mode 100644 index 0000000..8386370 --- /dev/null +++ b/components/proximity_auth/screenlock_bridge.h
@@ -0,0 +1,190 @@ +// 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_SCREENLOCK_BRIDGE_H_ +#define COMPONENTS_PROXIMITY_AUTH_SCREENLOCK_BRIDGE_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" +#include "base/strings/string16.h" +#include "base/values.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace proximity_auth { + +class ProximityAuthClient; + +// ScreenlockBridge brings together the screenLockPrivate API and underlying +// support. On ChromeOS, it delegates calls to the ScreenLocker. On other +// platforms, it delegates calls to UserManagerUI (and friends). +// TODO(tbarzic): Rename ScreenlockBridge to SignInScreenBridge, as this is not +// used solely for the lock screen anymore. +class ScreenlockBridge { + public: + // |client| is not owned and must outlive this object. + explicit ScreenlockBridge(ProximityAuthClient* client); + ~ScreenlockBridge(); + + // User pod icons supported by lock screen / signin screen UI. + enum UserPodCustomIcon { + USER_POD_CUSTOM_ICON_NONE, + USER_POD_CUSTOM_ICON_HARDLOCKED, + USER_POD_CUSTOM_ICON_LOCKED, + USER_POD_CUSTOM_ICON_LOCKED_TO_BE_ACTIVATED, + // TODO(isherman): The "locked with proximity hint" icon is currently the + // same as the "locked" icon. It's treated as a separate case to allow an + // easy asset swap without changing the code, in case we decide to use a + // different icon for this case. If we definitely decide against that, then + // this enum entry should be removed. + USER_POD_CUSTOM_ICON_LOCKED_WITH_PROXIMITY_HINT, + USER_POD_CUSTOM_ICON_UNLOCKED, + USER_POD_CUSTOM_ICON_SPINNER + }; + + // Class containing parameters describing the custom icon that should be + // shown on a user's screen lock pod next to the input field. + class UserPodCustomIconOptions { + public: + UserPodCustomIconOptions(); + ~UserPodCustomIconOptions(); + + // Converts parameters to a dictionary values that can be sent to the + // screenlock web UI. + scoped_ptr<base::DictionaryValue> ToDictionaryValue() const; + + // Sets the icon that should be shown in the UI. + void SetIcon(UserPodCustomIcon icon); + + // Sets the icon tooltip. If |autoshow| is set the tooltip is automatically + // shown with the icon. + void SetTooltip(const base::string16& tooltip, bool autoshow); + + // Sets the accessibility label of the icon. If this attribute is not + // provided, then the tooltip will be used. + void SetAriaLabel(const base::string16& aria_label); + + // If hardlock on click is set, clicking the icon in the screenlock will + // go to state where password is required for unlock. + void SetHardlockOnClick(); + + // If the current lock screen is a trial run to introduce users to Easy + // Unlock, the icon will record metrics upon click. + void SetTrialRun(); + + private: + UserPodCustomIcon icon_; + + base::string16 tooltip_; + bool autoshow_tooltip_; + + base::string16 aria_label_; + + bool hardlock_on_click_; + + bool is_trial_run_; + + DISALLOW_COPY_AND_ASSIGN(UserPodCustomIconOptions); + }; + + class LockHandler { + public: + // Supported authentication types. Keep in sync with the enum in + // user_pod_row.js. + enum AuthType { + OFFLINE_PASSWORD = 0, + ONLINE_SIGN_IN = 1, + NUMERIC_PIN = 2, + USER_CLICK = 3, + EXPAND_THEN_USER_CLICK = 4, + FORCE_OFFLINE_PASSWORD = 5 + }; + + enum ScreenType { SIGNIN_SCREEN = 0, LOCK_SCREEN = 1, OTHER_SCREEN = 2 }; + + // Displays |message| in a banner on the lock screen. + virtual void ShowBannerMessage(const base::string16& message) = 0; + + // Shows a custom icon in the user pod on the lock screen. + virtual void ShowUserPodCustomIcon( + const std::string& user_email, + const UserPodCustomIconOptions& icon) = 0; + + // Hides the custom icon in user pod for a user. + virtual void HideUserPodCustomIcon(const std::string& user_email) = 0; + + // (Re)enable lock screen UI. + virtual void EnableInput() = 0; + + // Set the authentication type to be used on the lock screen. + virtual void SetAuthType(const std::string& user_email, + AuthType auth_type, + const base::string16& auth_value) = 0; + + // Returns the authentication type used for a user. + virtual AuthType GetAuthType(const std::string& user_email) const = 0; + + // Returns the type of the screen -- a signin or a lock screen. + virtual ScreenType GetScreenType() const = 0; + + // Unlocks from easy unlock app for a user. + virtual void Unlock(const std::string& user_email) = 0; + + // Attempts to login the user using an easy unlock key. + virtual void AttemptEasySignin(const std::string& user_email, + const std::string& secret, + const std::string& key_label) = 0; + + protected: + virtual ~LockHandler() {} + }; + + class Observer { + public: + // Invoked after the screen is locked. + virtual void OnScreenDidLock(LockHandler::ScreenType screen_type) = 0; + + // Invoked after the screen lock is dismissed. + virtual void OnScreenDidUnlock(LockHandler::ScreenType screen_type) = 0; + + // Invoked when the user focused on the lock screen changes. + virtual void OnFocusedUserChanged(const std::string& user_id) = 0; + + protected: + virtual ~Observer() {} + }; + + void SetLockHandler(LockHandler* lock_handler); + void SetFocusedUser(const std::string& user_id); + + bool IsLocked() const; + void Lock(content::BrowserContext* browser_context); + void Unlock(content::BrowserContext* browser_context); + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + LockHandler* lock_handler() { return lock_handler_; } + + std::string focused_user_id() const { return focused_user_id_; } + + private: + ProximityAuthClient* client_; // Not owned. Must outlive this object. + LockHandler* lock_handler_; // Not owned + // The last focused user's id. + std::string focused_user_id_; + ObserverList<Observer, true> observers_; + + DISALLOW_COPY_AND_ASSIGN(ScreenlockBridge); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_SCREENLOCK_BRIDGE_H_
diff --git a/components/proximity_auth/throttled_bluetooth_connection_finder.cc b/components/proximity_auth/throttled_bluetooth_connection_finder.cc new file mode 100644 index 0000000..252a47f9 --- /dev/null +++ b/components/proximity_auth/throttled_bluetooth_connection_finder.cc
@@ -0,0 +1,55 @@ +// 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/proximity_auth/throttled_bluetooth_connection_finder.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/task_runner.h" +#include "base/time/time.h" +#include "components/proximity_auth/bluetooth_connection_finder.h" +#include "components/proximity_auth/bluetooth_throttler.h" + +namespace proximity_auth { + +ThrottledBluetoothConnectionFinder::ThrottledBluetoothConnectionFinder( + scoped_ptr<BluetoothConnectionFinder> connection_finder, + scoped_refptr<base::TaskRunner> task_runner, + BluetoothThrottler* throttler) + : connection_finder_(connection_finder.Pass()), + task_runner_(task_runner), + throttler_(throttler), + weak_ptr_factory_(this) { +} + +ThrottledBluetoothConnectionFinder::~ThrottledBluetoothConnectionFinder() { +} + +void ThrottledBluetoothConnectionFinder::Find( + const ConnectionCallback& connection_callback) { + const base::TimeDelta delay = throttler_->GetDelay(); + + // Wait, if needed. + if (delay != base::TimeDelta()) { + task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&ThrottledBluetoothConnectionFinder::Find, + weak_ptr_factory_.GetWeakPtr(), connection_callback), + delay); + return; + } + + connection_finder_->Find( + base::Bind(&ThrottledBluetoothConnectionFinder::OnConnection, + weak_ptr_factory_.GetWeakPtr(), connection_callback)); +} + +void ThrottledBluetoothConnectionFinder::OnConnection( + const ConnectionCallback& connection_callback, + scoped_ptr<Connection> connection) { + throttler_->OnConnection(connection.get()); + connection_callback.Run(connection.Pass()); +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/throttled_bluetooth_connection_finder.h b/components/proximity_auth/throttled_bluetooth_connection_finder.h new file mode 100644 index 0000000..c107bb3 --- /dev/null +++ b/components/proximity_auth/throttled_bluetooth_connection_finder.h
@@ -0,0 +1,60 @@ +// 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_PROXIMITY_AUTH_THROTTLED_BLUETOOTH_CONNECTION_FINDER_H +#define COMPONENTS_PROXIMITY_AUTH_THROTTLED_BLUETOOTH_CONNECTION_FINDER_H + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "components/proximity_auth/connection_finder.h" + +namespace base { +class TaskRunner; +} + +namespace proximity_auth { + +class BluetoothConnectionFinder; +class BluetoothThrottler; +class Connection; + +// A Bluetooth connection finder that delays Find() requests according to the +// throttler's cooldown period. +class ThrottledBluetoothConnectionFinder : public ConnectionFinder { + public: + // Note: The |throttler| is not owned, and must outlive |this| instance. + ThrottledBluetoothConnectionFinder( + scoped_ptr<BluetoothConnectionFinder> connection_finder, + scoped_refptr<base::TaskRunner> task_runner, + BluetoothThrottler* throttler); + ~ThrottledBluetoothConnectionFinder() override; + + // ConnectionFinder: + void Find(const ConnectionCallback& connection_callback) override; + + private: + // Callback to be called when a connection is found. + void OnConnection(const ConnectionCallback& connection_callback, + scoped_ptr<Connection> connection); + + // The underlying connection finder. + scoped_ptr<BluetoothConnectionFinder> connection_finder_; + + // The task runner used for posting delayed messages. + scoped_refptr<base::TaskRunner> task_runner_; + + // The throttler managing this connection finder. The throttler is not owned, + // and must outlive |this| instance. + BluetoothThrottler* throttler_; + + base::WeakPtrFactory<ThrottledBluetoothConnectionFinder> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ThrottledBluetoothConnectionFinder); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_THROTTLED_BLUETOOTH_CONNECTION_FINDER_H
diff --git a/components/proximity_auth/throttled_bluetooth_connection_finder_unittest.cc b/components/proximity_auth/throttled_bluetooth_connection_finder_unittest.cc new file mode 100644 index 0000000..cf2ca7b --- /dev/null +++ b/components/proximity_auth/throttled_bluetooth_connection_finder_unittest.cc
@@ -0,0 +1,133 @@ +// 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/proximity_auth/throttled_bluetooth_connection_finder.h" + +#include "base/bind.h" +#include "base/test/test_simple_task_runner.h" +#include "base/time/time.h" +#include "components/proximity_auth/bluetooth_connection_finder.h" +#include "components/proximity_auth/bluetooth_throttler.h" +#include "components/proximity_auth/connection.h" +#include "components/proximity_auth/remote_device.h" +#include "components/proximity_auth/wire_message.h" +#include "device/bluetooth/bluetooth_uuid.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::NiceMock; +using testing::Return; +using testing::_; + +namespace proximity_auth { +namespace { + +const int kPollingIntervalSeconds = 7; +const char kUuid[] = "DEADBEEF-CAFE-FEED-FOOD-D15EA5EBEEF"; + +// A callback that stores a found |connection| into |out|. +void SaveConnection(scoped_ptr<Connection>* out, + scoped_ptr<Connection> connection) { + *out = connection.Pass(); +} + +class StubConnection : public Connection { + public: + StubConnection() : Connection(RemoteDevice()) {} + ~StubConnection() override {} + + void Connect() override {} + void Disconnect() override {} + void SendMessageImpl(scoped_ptr<WireMessage> message) override {} + + private: + DISALLOW_COPY_AND_ASSIGN(StubConnection); +}; + +class MockBluetoothThrottler : public BluetoothThrottler { + public: + MockBluetoothThrottler() {} + ~MockBluetoothThrottler() override {} + + MOCK_CONST_METHOD0(GetDelay, base::TimeDelta()); + MOCK_METHOD1(OnConnection, void(Connection* connection)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockBluetoothThrottler); +}; + +class FakeBluetoothConnectionFinder : public BluetoothConnectionFinder { + public: + FakeBluetoothConnectionFinder() + : BluetoothConnectionFinder( + RemoteDevice(), + device::BluetoothUUID(kUuid), + base::TimeDelta::FromSeconds(kPollingIntervalSeconds)) {} + ~FakeBluetoothConnectionFinder() override {} + + void Find(const ConnectionCallback& connection_callback) override { + connection_callback.Run(make_scoped_ptr(new StubConnection)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(FakeBluetoothConnectionFinder); +}; + +} // namespace + +class ProximityAuthThrottledBluetoothConnectionFinderTest + : public testing::Test { + public: + ProximityAuthThrottledBluetoothConnectionFinderTest() + : task_runner_(new base::TestSimpleTaskRunner) {} + + protected: + scoped_refptr<base::TestSimpleTaskRunner> task_runner_; + NiceMock<MockBluetoothThrottler> throttler_; +}; + +TEST_F(ProximityAuthThrottledBluetoothConnectionFinderTest, + Find_ExecutesImmediatelyWhenUnthrottled) { + ON_CALL(throttler_, GetDelay()).WillByDefault(Return(base::TimeDelta())); + + ThrottledBluetoothConnectionFinder connection_finder( + make_scoped_ptr(new FakeBluetoothConnectionFinder), task_runner_, + &throttler_); + scoped_ptr<Connection> connection; + connection_finder.Find(base::Bind(&SaveConnection, &connection)); + EXPECT_TRUE(connection); +} + +TEST_F(ProximityAuthThrottledBluetoothConnectionFinderTest, + Find_ExecutesAfterADelayWhenThrottled) { + ON_CALL(throttler_, GetDelay()) + .WillByDefault(Return(base::TimeDelta::FromSeconds(1))); + + ThrottledBluetoothConnectionFinder connection_finder( + make_scoped_ptr(new FakeBluetoothConnectionFinder), task_runner_, + &throttler_); + scoped_ptr<Connection> connection; + connection_finder.Find(base::Bind(&SaveConnection, &connection)); + EXPECT_FALSE(connection); + + // The connection should be found once the throttling period has elapsed. + ON_CALL(throttler_, GetDelay()).WillByDefault(Return(base::TimeDelta())); + task_runner_->RunUntilIdle(); + EXPECT_TRUE(connection); +} + +TEST_F(ProximityAuthThrottledBluetoothConnectionFinderTest, + OnConnection_ForwardsNotificationToThrottler) { + ON_CALL(throttler_, GetDelay()).WillByDefault(Return(base::TimeDelta())); + + ThrottledBluetoothConnectionFinder connection_finder( + make_scoped_ptr(new FakeBluetoothConnectionFinder), task_runner_, + &throttler_); + scoped_ptr<Connection> connection; + EXPECT_CALL(throttler_, OnConnection(_)); + connection_finder.Find(base::Bind(&SaveConnection, &connection)); + EXPECT_TRUE(connection); +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/webui/BUILD.gn b/components/proximity_auth/webui/BUILD.gn new file mode 100644 index 0000000..8009a43e --- /dev/null +++ b/components/proximity_auth/webui/BUILD.gn
@@ -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. + +# GYP version: components/proximity_auth.gypi:proximity_auth_webui +static_library("webui") { + sources = [ + "proximity_auth_ui.cc", + "proximity_auth_ui.h", + "proximity_auth_webui_handler.cc", + "proximity_auth_webui_handler.h", + "url_constants.cc", + "url_constants.h", + ] + + deps = [ + "//base", + "//components/resources", + "//content/public/browser", + ] +}
diff --git a/components/proximity_auth/webui/DEPS b/components/proximity_auth/webui/DEPS new file mode 100644 index 0000000..445e4883 --- /dev/null +++ b/components/proximity_auth/webui/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+content/public/browser", + "+grit/components_resources.h", +]
diff --git a/components/proximity_auth/webui/proximity_auth_ui.cc b/components/proximity_auth/webui/proximity_auth_ui.cc new file mode 100644 index 0000000..09a2686 --- /dev/null +++ b/components/proximity_auth/webui/proximity_auth_ui.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 "components/proximity_auth/webui/proximity_auth_ui.h" + +#include "components/proximity_auth/webui/proximity_auth_webui_handler.h" +#include "components/proximity_auth/webui/url_constants.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "grit/components_resources.h" + +namespace proximity_auth { + +ProximityAuthUI::ProximityAuthUI(content::WebUI* web_ui) + : content::WebUIController(web_ui) { + content::WebUIDataSource* source = + content::WebUIDataSource::Create(kChromeUIProximityAuthHost); + source->SetDefaultResource(IDR_PROXIMITY_AUTH_HTML); + source->AddResourcePath("proximity_auth.css", IDR_PROXIMITY_AUTH_CSS); + source->AddResourcePath("proximity_auth.js", IDR_PROXIMITY_AUTH_JS); + source->SetJsonPath("strings.js"); + + content::BrowserContext* browser_context = + web_ui->GetWebContents()->GetBrowserContext(); + content::WebUIDataSource::Add(browser_context, source); + web_ui->AddMessageHandler(new ProximityAuthWebUIHandler()); +} + +ProximityAuthUI::~ProximityAuthUI() { +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/webui/proximity_auth_ui.h b/components/proximity_auth/webui/proximity_auth_ui.h new file mode 100644 index 0000000..04b169b4 --- /dev/null +++ b/components/proximity_auth/webui/proximity_auth_ui.h
@@ -0,0 +1,29 @@ +// 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_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_UI_H_ +#define COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_UI_H_ + +#include <string> + +#include "content/public/browser/web_ui_controller.h" + +namespace proximity_auth { + +class ProximityAuthService; + +// The WebUI controller for chrome://proximity-auth. +class ProximityAuthUI : public content::WebUIController { + public: + // Note: |web_ui| is not owned by this instance. + explicit ProximityAuthUI(content::WebUI* web_ui); + ~ProximityAuthUI() override; + + private: + DISALLOW_COPY_AND_ASSIGN(ProximityAuthUI); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_UI_H_
diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/components/proximity_auth/webui/proximity_auth_webui_handler.cc new file mode 100644 index 0000000..3d81f66 --- /dev/null +++ b/components/proximity_auth/webui/proximity_auth_webui_handler.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 "components/proximity_auth/webui/proximity_auth_webui_handler.h" + +namespace proximity_auth { + +ProximityAuthWebUIHandler::ProximityAuthWebUIHandler() { +} + +ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() { +} + +void ProximityAuthWebUIHandler::RegisterMessages() { +} + +} // namespace proximity_auth
diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.h b/components/proximity_auth/webui/proximity_auth_webui_handler.h new file mode 100644 index 0000000..8cc0508 --- /dev/null +++ b/components/proximity_auth/webui/proximity_auth_webui_handler.h
@@ -0,0 +1,29 @@ +// 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_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_WEBUI_HANDLER_H_ +#define COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_WEBUI_HANDLER_H_ + +#include "content/public/browser/web_ui_message_handler.h" + +namespace proximity_auth { + +class ProximityAuthService; + +// Handles messages from the chrome://proximity-auth page. +class ProximityAuthWebUIHandler : public content::WebUIMessageHandler { + public: + ProximityAuthWebUIHandler(); + ~ProximityAuthWebUIHandler() override; + + // content::WebUIMessageHandler implementation. + void RegisterMessages() override; + + private: + DISALLOW_COPY_AND_ASSIGN(ProximityAuthWebUIHandler); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_WEBUI_HANDLER_H_
diff --git a/components/proximity_auth/webui/resources/proximity_auth.css b/components/proximity_auth/webui/resources/proximity_auth.css new file mode 100644 index 0000000..25ecca3 --- /dev/null +++ b/components/proximity_auth/webui/resources/proximity_auth.css
@@ -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. + */ + +html, +body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; +} + +canvas { + width: 100%; + height: 100%; + margin: 0; +}
diff --git a/components/proximity_auth/webui/resources/proximity_auth.html b/components/proximity_auth/webui/resources/proximity_auth.html new file mode 100644 index 0000000..ac4d8e2 --- /dev/null +++ b/components/proximity_auth/webui/resources/proximity_auth.html
@@ -0,0 +1,23 @@ +<!DOCTYPE HTML> +<!-- +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. +--> + +<html> +<head> + <meta charset="utf-8"> + <title></title> + <meta name="viewport" + content="width=device-width, initial-scale=1"> + <link rel="stylesheet" href="proximity_auth.css"> + + <script src="strings.js"></script> +</head> +<body> + <canvas id='canvas'> </canvas> + + <script src="proximity_auth.js"></script> +</body> +</html>
diff --git a/components/proximity_auth/webui/resources/proximity_auth.js b/components/proximity_auth/webui/resources/proximity_auth.js new file mode 100644 index 0000000..f643147 --- /dev/null +++ b/components/proximity_auth/webui/resources/proximity_auth.js
@@ -0,0 +1,90 @@ +// 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. + +// TODO(tengs): This page is just a placeholder. The real page still needs to be +// built. + +function LSystem(rules, startState, iterations) { + symbols = startState.split('').map(function(character) { + return { c: character, i: 0 }; + }); + + while (true) { + var index = -1; + for (var i = 0; i < symbols.length; ++i) { + var symbol = symbols[i]; + if (symbol.i < iterations && rules[symbol.c] != null) { + index = i; + break; + } + } + if (index == -1) + break; + + var symbol = symbols[index]; + var newSymbols = rules[symbol.c].apply(symbol).split('').map(function(c) { + return { c: c, i: symbol.i + 1 }; + }); + + Array.prototype.splice.apply(symbols, [index, 1].concat(newSymbols)); + } + + return symbols.map(function(symbol) { + return symbol.c; + }); +}; + +var rules = { + 'X': function(x) { return 'X+YF'; }, + 'Y': function(y) { return 'FX-Y'; }, +} +var startState = 'FX+FX+'; +var iterations = 10; + +function draw() { + var canvas = document.getElementById('canvas'); + canvas.width = canvas.offsetWidth; + canvas.height = canvas.offsetHeight; + + var canvasWidth = canvas.offsetWidth; + var canvasHeight = canvas.offsetHeight; + var context = canvas.getContext('2d'); + + context.lineWidth = 2; + var segmentWidth = 0.015 * canvasHeight; + var pos = { + x: 0.5 * canvasWidth, + y: 0.25 * canvasHeight, + }; + var dir = { x: 1, y: 0, }; + + var commands = LSystem(rules, startState, iterations); + var drawCommand = function() { + var command = commands.shift(); + if (command === 'F') { + context.beginPath(); + context.moveTo(pos.x, pos.y); + + pos = { + x: pos.x + dir.x * segmentWidth, + y: pos.y + dir.y * segmentWidth, + }; + + context.lineTo(pos.x, pos.y); + var r = Math.round(pos.x / canvasWidth * 256); + var b = Math.round(pos.y / canvasHeight * 256); + var g = 180; + context.strokeStyle = 'rgb(' + r + ',' + g + ',' + b + ')'; + context.stroke(); + } else if (command === '+') { + dir = { x: -dir.y, y: dir.x } + } else if (command === '-') { + dir = { x: dir.y, y: -dir.x } + } + } + + window.setInterval(drawCommand, 10); +} + +document.addEventListener("DOMContentLoaded", draw);
diff --git a/components/proximity_auth/webui/url_constants.cc b/components/proximity_auth/webui/url_constants.cc new file mode 100644 index 0000000..a8978df --- /dev/null +++ b/components/proximity_auth/webui/url_constants.cc
@@ -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. + +#include "components/proximity_auth/webui/url_constants.h" + +namespace proximity_auth { + +const char kChromeUIProximityAuthHost[] = "proximity-auth"; +const char kChromeUIProximityAuthURL[] = "chrome://proximity-auth/"; + +} // namespace proximity_auth
diff --git a/components/proximity_auth/webui/url_constants.h b/components/proximity_auth/webui/url_constants.h new file mode 100644 index 0000000..340add3 --- /dev/null +++ b/components/proximity_auth/webui/url_constants.h
@@ -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. + +#ifndef COMPONENTS_PROXIMITY_AUTH_WEBUI_URL_CONSTANTS_H_ +#define COMPONENTS_PROXIMITY_AUTH_WEBUI_URL_CONSTANTS_H_ + +namespace proximity_auth { + +extern const char kChromeUIProximityAuthHost[]; +extern const char kChromeUIProximityAuthURL[]; + +} // namespace dom_distiller + +#endif // COMPONENTS_PROXIMITY_AUTH_WEBUI_URL_CONSTANTS_H_
diff --git a/components/rappor.gypi b/components/rappor.gypi index 3fed8109..88c77f0c 100644 --- a/components/rappor.gypi +++ b/components/rappor.gypi
@@ -41,6 +41,12 @@ 'rappor/rappor_service.h', 'rappor/rappor_utils.cc', 'rappor/rappor_utils.h', + 'rappor/reports.cc', + 'rappor/reports.h', + 'rappor/sample.cc', + 'rappor/sample.h', + 'rappor/sampler.cc', + 'rappor/sampler.h', ], 'variables': { 'proto_in_dir': 'rappor/proto',
diff --git a/components/rappor/BUILD.gn b/components/rappor/BUILD.gn index 8bad347..416d69c 100644 --- a/components/rappor/BUILD.gn +++ b/components/rappor/BUILD.gn
@@ -24,6 +24,12 @@ "rappor_service.h", "rappor_utils.cc", "rappor_utils.h", + "reports.cc", + "reports.h", + "sample.cc", + "sample.h", + "sampler.cc", + "sampler.h", ] deps = [ @@ -63,6 +69,7 @@ "rappor_prefs_unittest.cc", "rappor_service_unittest.cc", "rappor_utils_unittest.cc", + "sampler_unittest.cc", ] deps = [
diff --git a/components/rappor/bloom_filter.cc b/components/rappor/bloom_filter.cc index 9ad8f3ca..6c6f654 100644 --- a/components/rappor/bloom_filter.cc +++ b/components/rappor/bloom_filter.cc
@@ -9,6 +9,16 @@ namespace rappor { +namespace { + +uint32_t ComputeHash(const std::string& str, uint32_t seed) { + // Using CityHash here because we have support for it in Dremel. Many hash + // functions, such as MD5, SHA1, or Murmur, would probably also work. + return CityHash64WithSeed(str.data(), str.size(), seed); +} + +} // namespace + BloomFilter::BloomFilter(uint32_t bytes_size, uint32_t hash_function_count, uint32_t hash_seed_offset) @@ -25,10 +35,7 @@ bytes_[i] = 0; } for (size_t i = 0; i < hash_function_count_; ++i) { - // Using CityHash here because we have support for it in Dremel. Many hash - // functions, such as MD5, SHA1, or Murmur, would probably also work. - uint32_t index = - CityHash64WithSeed(str.data(), str.size(), hash_seed_offset_ + i); + uint32_t index = ComputeHash(str, hash_seed_offset_ + i); // Note that the "bytes" are uint8_t, so they are always 8-bits. uint32_t byte_index = (index / 8) % bytes_.size(); uint32_t bit_index = index % 8; @@ -43,4 +50,23 @@ } } +namespace internal { + +uint64_t GetBloomBits(uint32_t bytes_size, + uint32_t hash_function_count, + uint32_t hash_seed_offset, + const std::string& str) { + // Make sure result fits in uint64. + DCHECK_LE(bytes_size, 8u); + uint64_t output = 0; + const uint32_t bits_size = bytes_size * 8; + for (size_t i = 0; i < hash_function_count; ++i) { + uint32_t index = ComputeHash(str, hash_seed_offset + i); + output |= 1ULL << uint64_t(index % bits_size); + } + return output; +} + +} // namespace internal + } // namespace rappor
diff --git a/components/rappor/bloom_filter.h b/components/rappor/bloom_filter.h index 482f1c3..20adfab5 100644 --- a/components/rappor/bloom_filter.h +++ b/components/rappor/bloom_filter.h
@@ -47,6 +47,17 @@ DISALLOW_COPY_AND_ASSIGN(BloomFilter); }; + +namespace internal { + +// A function for getting bloom filters less than or equal to 64 bits. +uint64_t GetBloomBits(uint32_t bytes_size, + uint32_t hash_function_count, + uint32_t hash_seed_offset, + const std::string& str); + +} // namespace internal + } // namespace rappor #endif // COMPONENTS_RAPPOR_BLOOM_FILTER_H_
diff --git a/components/rappor/bloom_filter_unittest.cc b/components/rappor/bloom_filter_unittest.cc index 25f965f8..a7ca069 100644 --- a/components/rappor/bloom_filter_unittest.cc +++ b/components/rappor/bloom_filter_unittest.cc
@@ -51,4 +51,15 @@ EXPECT_EQ(1, CountBits(filter.bytes())); } +TEST(BloomFilterTest, GetBloomBitsSmall) { + uint64_t bytes_from_get = internal::GetBloomBits(1u, 4u, 0u, "Bar"); + EXPECT_EQ(0xa8u, bytes_from_get); +} + +TEST(BloomFilterTest, GetBloomBitsLarge) { + // Make sure that a 64-bit bloom filter can set the full range of bits. + uint64_t bytes_from_get = internal::GetBloomBits(8u, 1024u, 0u, "Bar"); + EXPECT_EQ(0xffffffffffffffffu, bytes_from_get); +} + } // namespace rappor
diff --git a/components/rappor/rappor_metric.cc b/components/rappor/rappor_metric.cc index 862ead89..3c368a3 100644 --- a/components/rappor/rappor_metric.cc +++ b/components/rappor/rappor_metric.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/rand_util.h" +#include "components/rappor/reports.h" namespace rappor { @@ -38,35 +39,7 @@ } ByteVector RapporMetric::GetReport(const std::string& secret) const { - // Generate a deterministically random mask of fake data using the - // client's secret key + real data as a seed. The inclusion of the secret - // in the seed avoids correlations between real and fake data. - // The seed isn't a human-readable string. - const std::string personalization_string = metric_name_ + - std::string(bytes().begin(), bytes().end()); - HmacByteVectorGenerator hmac_generator(bytes().size(), secret, - personalization_string); - const ByteVector fake_mask = - hmac_generator.GetWeightedRandomByteVector(parameters().fake_prob); - ByteVector fake_bits = - hmac_generator.GetWeightedRandomByteVector(parameters().fake_one_prob); - - // Redact most of the real data by replacing it with the fake data, hiding - // and limiting the amount of information an individual client reports on. - const ByteVector* fake_and_redacted_bits = - ByteVectorMerge(fake_mask, bytes(), &fake_bits); - - // Generate biased coin flips for each bit. - ByteVectorGenerator coin_generator(bytes().size()); - const ByteVector zero_coins = - coin_generator.GetWeightedRandomByteVector(parameters().zero_coin_prob); - ByteVector one_coins = - coin_generator.GetWeightedRandomByteVector(parameters().one_coin_prob); - - // Create a randomized response report on the fake and redacted data, sending - // the outcome of flipping a zero coin for the zero bits in that data, and of - // flipping a one coin for the one bits in that data, as the final report. - return *ByteVectorMerge(*fake_and_redacted_bits, zero_coins, &one_coins); + return internal::GenerateReport(secret, parameters(), bytes()); } void RapporMetric::SetBytesForTesting(const ByteVector& bytes) {
diff --git a/components/rappor/rappor_service.cc b/components/rappor/rappor_service.cc index 7fc4fce..9c950b5 100644 --- a/components/rappor/rappor_service.cc +++ b/components/rappor/rappor_service.cc
@@ -184,26 +184,23 @@ } bool RapporService::ExportMetrics(RapporReports* reports) { - if (metrics_map_.empty()) { - DVLOG(2) << "metrics_map_ is empty."; - return false; - } - DCHECK_GE(cohort_, 0); reports->set_cohort(cohort_); - for (std::map<std::string, RapporMetric*>::const_iterator it = - metrics_map_.begin(); - it != metrics_map_.end(); - ++it) { - const RapporMetric* metric = it->second; + for (const auto& kv : metrics_map_) { + const RapporMetric* metric = kv.second; RapporReports::Report* report = reports->add_report(); - report->set_name_hash(metrics::HashMetricName(it->first)); + report->set_name_hash(metrics::HashMetricName(kv.first)); ByteVector bytes = metric->GetReport(secret_); report->set_bits(std::string(bytes.begin(), bytes.end())); } STLDeleteValues(&metrics_map_); - return true; + + sampler_.ExportMetrics(secret_, reports); + + DVLOG(2) << "Generated a report with " << reports->report_size() + << "metrics."; + return reports->report_size() > 0; } bool RapporService::IsInitialized() const { @@ -232,7 +229,7 @@ DVLOG(2) << "Metric not logged due to incognito mode."; return; } - // Skip this metric if it's reporting level is less than the enabled + // Skip this metric if its reporting level is less than the enabled // reporting level. if (recording_level_ < parameters.recording_level) { DVLOG(2) << "Metric not logged due to recording_level " @@ -259,4 +256,27 @@ return new_metric; } +scoped_ptr<Sample> RapporService::CreateSample(RapporType type) { + DCHECK(IsInitialized()); + return scoped_ptr<Sample>( + new Sample(cohort_, kRapporParametersForType[type])); +} + +void RapporService::RecordSampleObj(const std::string& metric_name, + scoped_ptr<Sample> sample) { + if (is_incognito_callback_.Run()) { + DVLOG(2) << "Metric not logged due to incognito mode."; + return; + } + // Skip this metric if its reporting level is less than the enabled + // reporting level. + if (recording_level_ < sample->parameters().recording_level) { + DVLOG(2) << "Metric not logged due to recording_level " + << recording_level_ << " < " + << sample->parameters().recording_level; + return; + } + sampler_.AddSample(metric_name, sample.Pass()); +} + } // namespace rappor
diff --git a/components/rappor/rappor_service.h b/components/rappor/rappor_service.h index d50b91e..564c7f5 100644 --- a/components/rappor/rappor_service.h +++ b/components/rappor/rappor_service.h
@@ -15,6 +15,8 @@ #include "base/timer/timer.h" #include "components/metrics/daily_event.h" #include "components/rappor/rappor_parameters.h" +#include "components/rappor/sample.h" +#include "components/rappor/sampler.h" class PrefRegistrySimple; class PrefService; @@ -63,6 +65,26 @@ // If |may_upload| is true, reports will be uploaded from the queue. void Update(RecordingLevel recording_level, bool may_upload); + // Constructs a Sample object for the caller to record fields in. + scoped_ptr<Sample> CreateSample(RapporType); + + // Records a Sample of rappor metric specified by |metric_name|. + // + // TODO(holte): Rename RecordSample to RecordString and then rename this + // to RecordSample. + // + // example: + // scoped_ptr<Sample> sample = rappor_service->CreateSample(MY_METRIC_TYPE); + // sample->SetStringField("Field1", "some string"); + // sample->SetFlagsValue("Field2", SOME|FLAGS); + // rappor_service->RecordSample("MyMetric", sample.Pass()); + // + // This will result in a report setting two metrics "MyMetric.Field1" and + // "MyMetric.Field2", and they will both be generated from the same sample, + // to allow for correllations to be computed. + void RecordSampleObj(const std::string& metric_name, + scoped_ptr<Sample> sample); + // Records a sample of the rappor metric specified by |metric_name|. // Creates and initializes the metric, if it doesn't yet exist. virtual void RecordSample(const std::string& metric_name, @@ -141,6 +163,8 @@ // The map owns the metrics it contains. std::map<std::string, RapporMetric*> metrics_map_; + internal::Sampler sampler_; + DISALLOW_COPY_AND_ASSIGN(RapporService); };
diff --git a/components/rappor/rappor_service_unittest.cc b/components/rappor/rappor_service_unittest.cc index eefdb52ec..de612cc 100644 --- a/components/rappor/rappor_service_unittest.cc +++ b/components/rappor/rappor_service_unittest.cc
@@ -6,6 +6,7 @@ #include "base/base64.h" #include "base/prefs/testing_pref_service.h" +#include "components/metrics/metrics_hashes.h" #include "components/rappor/byte_vector_utils.h" #include "components/rappor/proto/rappor_metric.pb.h" #include "components/rappor/rappor_parameters.h" @@ -95,4 +96,24 @@ EXPECT_EQ(0, reports.report_size()); } +// Check that Sample objects record correctly. +TEST(RapporServiceTest, RecordSample) { + TestRapporService rappor_service; + scoped_ptr<Sample> sample = rappor_service.CreateSample(COARSE_RAPPOR_TYPE); + sample->SetStringField("Url", "example.com"); + sample->SetFlagsField("Flags1", 0xbcd, 12); + rappor_service.RecordSampleObj("ObjMetric", sample.Pass()); + uint64_t url_hash = metrics::HashMetricName("ObjMetric.Url"); + uint64_t flags_hash = metrics::HashMetricName("ObjMetric.Flags1"); + RapporReports reports; + rappor_service.GetReports(&reports); + EXPECT_EQ(2, reports.report_size()); + size_t url_index = reports.report(0).name_hash() == url_hash ? 0 : 1; + size_t flags_index = url_index == 0 ? 1 : 0; + EXPECT_EQ(url_hash, reports.report(url_index).name_hash()); + EXPECT_EQ(1u, reports.report(url_index).bits().size()); + EXPECT_EQ(flags_hash, reports.report(flags_index).name_hash()); + EXPECT_EQ(2u, reports.report(flags_index).bits().size()); +} + } // namespace rappor
diff --git a/components/rappor/reports.cc b/components/rappor/reports.cc new file mode 100644 index 0000000..91f01e92 --- /dev/null +++ b/components/rappor/reports.cc
@@ -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. + +#include "components/rappor/reports.h" + +#include "base/logging.h" +#include "base/rand_util.h" +#include "components/rappor/byte_vector_utils.h" +#include "components/rappor/rappor_parameters.h" + +namespace rappor { + +namespace internal { + +ByteVector GenerateReport(const std::string& secret, + const RapporParameters& parameters, + const ByteVector& value) { + // Generate a deterministically random mask of fake data using the + // client's secret key + real data as a seed. The inclusion of the secret + // in the seed avoids correlations between real and fake data. + // The seed isn't a human-readable string. + const std::string personalization_string = + std::string(value.begin(), value.end()); + HmacByteVectorGenerator hmac_generator(value.size(), secret, + personalization_string); + const ByteVector fake_mask = + hmac_generator.GetWeightedRandomByteVector(parameters.fake_prob); + ByteVector fake_bits = + hmac_generator.GetWeightedRandomByteVector(parameters.fake_one_prob); + + // Redact most of the real data by replacing it with the fake data, hiding + // and limiting the amount of information an individual client reports on. + const ByteVector* fake_and_redacted_bits = + ByteVectorMerge(fake_mask, value, &fake_bits); + + // Generate biased coin flips for each bit. + ByteVectorGenerator coin_generator(value.size()); + const ByteVector zero_coins = + coin_generator.GetWeightedRandomByteVector(parameters.zero_coin_prob); + ByteVector one_coins = + coin_generator.GetWeightedRandomByteVector(parameters.one_coin_prob); + + // Create a randomized response report on the fake and redacted data, sending + // the outcome of flipping a zero coin for the zero bits in that data, and of + // flipping a one coin for the one bits in that data, as the final report. + return *ByteVectorMerge(*fake_and_redacted_bits, zero_coins, &one_coins); +} + +} // namespace internal + +} // namespace rappor
diff --git a/components/rappor/reports.h b/components/rappor/reports.h new file mode 100644 index 0000000..de2006b --- /dev/null +++ b/components/rappor/reports.h
@@ -0,0 +1,27 @@ +// 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_RAPPOR_REPORTS_H_ +#define COMPONENTS_RAPPOR_REPORTS_H_ + +#include "components/rappor/reports.h" + +#include "components/rappor/byte_vector_utils.h" + +namespace rappor { + +struct RapporParameters; + +namespace internal { + +// Generate a randomized report for a single metric/field. +ByteVector GenerateReport(const std::string& secret, + const RapporParameters& parameters, + const ByteVector& value); + +} // namespace internal + +} // namespace rappor + +#endif // COMPONENTS_RAPPOR_REPORTS_H_
diff --git a/components/rappor/sample.cc b/components/rappor/sample.cc new file mode 100644 index 0000000..6fbe615 --- /dev/null +++ b/components/rappor/sample.cc
@@ -0,0 +1,77 @@ +// 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/rappor/sample.h" + +#include <map> +#include <string> + +#include "base/logging.h" +#include "components/metrics/metrics_hashes.h" +#include "components/rappor/bloom_filter.h" +#include "components/rappor/byte_vector_utils.h" +#include "components/rappor/proto/rappor_metric.pb.h" +#include "components/rappor/reports.h" + +namespace rappor { + +Sample::Sample(int32_t cohort_seed, const RapporParameters& parameters) + : parameters_(parameters), + bloom_offset_((cohort_seed % parameters_.num_cohorts) * + parameters_.bloom_filter_hash_function_count) { + // Must use bloom filter size that fits in uint64. + DCHECK_LE(parameters_.bloom_filter_size_bytes, 8); +} + +Sample::~Sample() { +} + +void Sample::SetStringField(const std::string& field_name, + const std::string& value) { + DCHECK_EQ(0u, sizes_[field_name]); + fields_[field_name] = internal::GetBloomBits( + parameters_.bloom_filter_size_bytes, + parameters_.bloom_filter_hash_function_count, + bloom_offset_, + value); + sizes_[field_name] = parameters_.bloom_filter_size_bytes; +} + +void Sample::SetFlagsField(const std::string& field_name, + uint64_t flags, + size_t num_flags) { + DCHECK_EQ(0u, sizes_[field_name]); + DCHECK_GT(num_flags, 0u); + DCHECK_LE(num_flags, 64u); + DCHECK(num_flags == 64u || flags >> num_flags == 0); + fields_[field_name] = flags; + sizes_[field_name] = (num_flags + 7) / 8; +} + +void Sample::ExportMetrics(const std::string& secret, + const std::string& metric_name, + RapporReports* reports) const { + for (const auto& kv : fields_) { + uint64_t value = kv.second; + const auto it = sizes_.find(kv.first); + DCHECK(it != sizes_.end()); + uint64_t size = it->second; + ByteVector value_bytes(size); + for (size_t i = 0; i < size; i++) { + // Get the value of the i-th smallest byte and copy it to the byte vector. + uint64_t shift = i * 8; + uint64_t byte_mask = 0xff << shift; + value_bytes[i] = (value & byte_mask) >> shift; + } + ByteVector report_bytes = internal::GenerateReport( + secret, parameters_, value_bytes); + + RapporReports::Report* report = reports->add_report(); + report->set_name_hash(metrics::HashMetricName( + metric_name + "." + kv.first)); + report->set_bits(std::string(report_bytes.begin(), report_bytes.end())); + } +} + +} // namespace rappor
diff --git a/components/rappor/sample.h b/components/rappor/sample.h new file mode 100644 index 0000000..5eaf1de --- /dev/null +++ b/components/rappor/sample.h
@@ -0,0 +1,70 @@ +// 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_RAPPOR_SAMPLE_H_ +#define COMPONENTS_RAPPOR_SAMPLE_H_ + +#include <map> +#include <string> + +#include "base/basictypes.h" +#include "base/macros.h" +#include "components/rappor/rappor_parameters.h" + +namespace rappor { + +class RapporReports; +class RapporService; +class TestSamplerFactory; + +// Sample is a container for information about a single instance of some event +// we are sending Rappor data about. It may contain multiple different fields, +// which describe different details of the event, and they will be sent in the +// same Rappor report, enabling analysis of correlations between those fields. +class Sample { + public: + ~Sample(); + + // Sets a string value field in this sample. + void SetStringField(const std::string& field_name, const std::string& value); + + // Sets a group of boolean flags as a field in this sample. + // |flags| should be a set of boolean flags stored in the lowest |num_flags| + // bits of |flags|. + void SetFlagsField(const std::string& field_name, + uint64_t flags, + size_t num_flags); + + // Generate randomized reports and store them in |reports|. + void ExportMetrics(const std::string& secret, + const std::string& metric_name, + RapporReports* reports) const; + + const RapporParameters& parameters() { return parameters_; } + + private: + friend class TestSamplerFactory; + friend class RapporService; + + // Constructs a sample. Instead of calling this directly, call + // RapporService::MakeSampleObj to create a sample. + Sample(int32_t cohort_seed, const RapporParameters& parameters); + + const RapporParameters parameters_; + + // Offset used for bloom filter hash functions. + uint32_t bloom_offset_; + + // Size of each of the different fields, in bytes. + std::map<std::string, size_t> sizes_; + + // The non-randomized report values for each field. + std::map<std::string, uint64_t> fields_; + + DISALLOW_COPY_AND_ASSIGN(Sample); +}; + +} // namespace rappor + +#endif // COMPONENTS_RAPPOR_SAMPLE_H_
diff --git a/components/rappor/sampler.cc b/components/rappor/sampler.cc new file mode 100644 index 0000000..5d3e8e3 --- /dev/null +++ b/components/rappor/sampler.cc
@@ -0,0 +1,39 @@ +// 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/rappor/sampler.h" + +#include <map> +#include <string> + +#include "base/rand_util.h" + +namespace rappor { + +namespace internal { + +Sampler::Sampler() {} + +Sampler::~Sampler() {} + +void Sampler::AddSample(const std::string& metric_name, + scoped_ptr<Sample> sample) { + ++sample_counts_[metric_name]; + // Replace the previous sample with a 1 in sample_count_ chance so that each + // sample has equal probability of being reported. + if (base::RandGenerator(sample_counts_[metric_name]) == 0) + samples_.set(metric_name, sample.Pass()); +} + +void Sampler::ExportMetrics(const std::string& secret, RapporReports* reports) { + for (const auto& kv : samples_) { + kv.second->ExportMetrics(secret, kv.first, reports); + } + samples_.clear(); + sample_counts_.clear(); +} + +} // namespace internal + +} // namespace rappor
diff --git a/components/rappor/sampler.h b/components/rappor/sampler.h new file mode 100644 index 0000000..c2b13e1 --- /dev/null +++ b/components/rappor/sampler.h
@@ -0,0 +1,53 @@ +// 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_RAPPOR_SAMPLER_H_ +#define COMPONENTS_RAPPOR_SAMPLER_H_ + +#include <map> +#include <string> + +#include "base/containers/scoped_ptr_hash_map.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "components/rappor/rappor_parameters.h" +#include "components/rappor/sample.h" + +namespace rappor { + +class RapporReports; + +namespace internal { + +// Sampler manages the collection and storage of Sample objects. +// For each metric name, it will randomly select one Sample to store and +// use when generating RapporReports. +class Sampler { + public: + Sampler(); + ~Sampler(); + + // Store this sample for metric name, randomly selecting a sample if + // others have already been recorded. + void AddSample(const std::string& metric_name, scoped_ptr<Sample> sample); + + // Generate randomized reports for all stored samples and store them + // in |reports|, then discard the samples. + void ExportMetrics(const std::string& secret, RapporReports* reports); + + private: + // The number of samples recorded for each metric since the last export. + std::map<std::string, int> sample_counts_; + + // Stores a Sample for each metric, by metric name. + base::ScopedPtrHashMap<std::string, Sample> samples_; + + DISALLOW_COPY_AND_ASSIGN(Sampler); +}; + +} // namespace internal + +} // namespace rappor + +#endif // COMPONENTS_RAPPOR_SAMPLER_H_
diff --git a/components/rappor/sampler_unittest.cc b/components/rappor/sampler_unittest.cc new file mode 100644 index 0000000..2790c6f --- /dev/null +++ b/components/rappor/sampler_unittest.cc
@@ -0,0 +1,60 @@ +// 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/rappor/sampler.h" + +#include "components/rappor/byte_vector_utils.h" +#include "components/rappor/proto/rappor_metric.pb.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace rappor { + +const RapporParameters kTestRapporParameters = { + 1 /* Num cohorts */, + 1 /* Bloom filter size bytes */, + 4 /* Bloom filter hash count */, + PROBABILITY_75 /* Fake data probability */, + PROBABILITY_50 /* Fake one probability */, + PROBABILITY_75 /* One coin probability */, + PROBABILITY_50 /* Zero coin probability */, + FINE_LEVEL /* Reporting level (not used) */}; + +class TestSamplerFactory { + public: + static scoped_ptr<Sample> CreateSample() { + return scoped_ptr<Sample>(new Sample(0, kTestRapporParameters)); + } +}; + +namespace internal { + +// Test that exporting deletes samples. +TEST(RapporSamplerTest, TestExport) { + Sampler sampler; + + scoped_ptr<Sample> sample1 = TestSamplerFactory::CreateSample(); + sample1->SetStringField("Foo", "Junk"); + sampler.AddSample("Metric1", sample1.Pass()); + + scoped_ptr<Sample> sample2 = TestSamplerFactory::CreateSample(); + sample2->SetStringField("Foo", "Junk2"); + sampler.AddSample("Metric1", sample2.Pass()); + + // Since the two samples were for one metric, we should randomly get one + // of the two. + RapporReports reports; + std::string secret = HmacByteVectorGenerator::GenerateEntropyInput(); + sampler.ExportMetrics(secret, &reports); + EXPECT_EQ(1, reports.report_size()); + EXPECT_EQ(1u, reports.report(0).bits().size()); + + // First export should clear the metric. + RapporReports reports2; + sampler.ExportMetrics(secret, &reports2); + EXPECT_EQ(0, reports2.report_size()); +} + +} // namespace internal + +} // namespace rappor
diff --git a/components/resources/OWNERS b/components/resources/OWNERS index 4f523eef..6b2a180 100644 --- a/components/resources/OWNERS +++ b/components/resources/OWNERS
@@ -2,4 +2,6 @@ per-file data_reduction_proxy*=sclittle@chromium.org per-file dom_distiller*=cjhopman@chromium.org per-file dom_distiller*=nyquist@chromium.org +per-file proximity_auth*=isherman@chromium.org +per-file proximity_auth*=tengs@chromium.org per-file webui_generator_resources.grdp=dzhioev@chromium.org
diff --git a/components/resources/components_resources.grd b/components/resources/components_resources.grd index 099086b..b2ecc7b0 100644 --- a/components/resources/components_resources.grd +++ b/components/resources/components_resources.grd
@@ -11,6 +11,7 @@ <part file="data_reduction_proxy_resources.grdp" /> <part file="dom_distiller_resources.grdp" /> <part file="printing_resources.grdp" /> + <part file="proximity_auth_resources.grdp" /> <part file="translate_resources.grdp" /> <part file="webui_generator_resources.grdp" /> </includes>
diff --git a/components/resources/proximity_auth_resources.grdp b/components/resources/proximity_auth_resources.grdp new file mode 100644 index 0000000..1af2a00 --- /dev/null +++ b/components/resources/proximity_auth_resources.grdp
@@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <include name="IDR_PROXIMITY_AUTH_HTML" file="../proximity_auth/webui/resources/proximity_auth.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_PROXIMITY_AUTH_CSS" file="../proximity_auth/webui/resources/proximity_auth.css" type="BINDATA" /> + <include name="IDR_PROXIMITY_AUTH_JS" file="../proximity_auth/webui/resources/proximity_auth.js" type="BINDATA" /> +</grit-part>
diff --git a/components/scheduler/child/scheduler_helper.cc b/components/scheduler/child/scheduler_helper.cc index 19e8d2b6..cb2d191 100644 --- a/components/scheduler/child/scheduler_helper.cc +++ b/components/scheduler/child/scheduler_helper.cc
@@ -7,7 +7,6 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_argument.h" #include "components/scheduler/child/nestable_single_thread_task_runner.h" -#include "components/scheduler/child/prioritizing_task_queue_selector.h" #include "components/scheduler/child/time_source.h" namespace scheduler { @@ -336,11 +335,6 @@ return idle_period_state_; } -PrioritizingTaskQueueSelector* SchedulerHelper::SchedulerTaskQueueSelector() - const { - return task_queue_selector_.get(); -} - scoped_refptr<base::SingleThreadTaskRunner> SchedulerHelper::TaskRunnerForQueue( size_t queue_index) const { CheckOnValidThread(); @@ -357,6 +351,30 @@ return task_queue_manager_->IsQueueEmpty(queue_index); } +void SchedulerHelper::SetQueuePriority( + size_t queue_index, + PrioritizingTaskQueueSelector::QueuePriority priority) { + CheckOnValidThread(); + return task_queue_selector_->SetQueuePriority(queue_index, priority); +} + +void SchedulerHelper::EnableQueue( + size_t queue_index, + PrioritizingTaskQueueSelector::QueuePriority priority) { + CheckOnValidThread(); + task_queue_selector_->EnableQueue(queue_index, priority); +} + +void SchedulerHelper::DisableQueue(size_t queue_index) { + CheckOnValidThread(); + task_queue_selector_->DisableQueue(queue_index); +} + +bool SchedulerHelper::IsQueueEnabled(size_t queue_index) const { + CheckOnValidThread(); + return task_queue_selector_->IsQueueEnabled(queue_index); +} + // static const char* SchedulerHelper::TaskQueueIdToString(QueueId queue_id) { switch (queue_id) {
diff --git a/components/scheduler/child/scheduler_helper.h b/components/scheduler/child/scheduler_helper.h index 7ace694..3cb6997 100644 --- a/components/scheduler/child/scheduler_helper.h +++ b/components/scheduler/child/scheduler_helper.h
@@ -6,6 +6,7 @@ #define COMPONENTS_SCHEDULER_CHILD_SCHEDULER_HELPER_H_ #include "components/scheduler/child/cancelable_closure_holder.h" +#include "components/scheduler/child/prioritizing_task_queue_selector.h" #include "components/scheduler/child/single_thread_idle_task_runner.h" #include "components/scheduler/child/task_queue_manager.h" #include "components/scheduler/child/time_source.h" @@ -13,7 +14,6 @@ namespace scheduler { -class PrioritizingTaskQueueSelector; class NestableSingleThreadTaskRunner; // Common scheduler functionality for Default and Idle tasks. @@ -159,11 +159,16 @@ // Accessor methods. base::TimeTicks Now() const; IdlePeriodState SchedulerIdlePeriodState() const; - PrioritizingTaskQueueSelector* SchedulerTaskQueueSelector() const; scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerForQueue( size_t queue_index) const; void SetQueueName(size_t queue_index, const char* name); bool IsQueueEmpty(size_t queue_index) const; + void SetQueuePriority(size_t queue_index, + PrioritizingTaskQueueSelector::QueuePriority priority); + void EnableQueue(size_t queue_index, + PrioritizingTaskQueueSelector::QueuePriority priority); + void DisableQueue(size_t queue_index); + bool IsQueueEnabled(size_t queue_index) const; // Test helpers. void SetTimeSourceForTesting(scoped_ptr<TimeSource> time_source);
diff --git a/components/scheduler/renderer/renderer_scheduler_impl.cc b/components/scheduler/renderer/renderer_scheduler_impl.cc index 5ed3d6d..4ca86ec 100644 --- a/components/scheduler/renderer/renderer_scheduler_impl.cc +++ b/components/scheduler/renderer/renderer_scheduler_impl.cc
@@ -362,44 +362,41 @@ new_policy == current_policy_) return; - PrioritizingTaskQueueSelector* task_queue_selector = - helper_.SchedulerTaskQueueSelector(); bool policy_disables_timers = false; switch (new_policy) { case Policy::COMPOSITOR_PRIORITY: - task_queue_selector->SetQueuePriority( - COMPOSITOR_TASK_QUEUE, PrioritizingTaskQueueSelector::HIGH_PRIORITY); + helper_.SetQueuePriority(COMPOSITOR_TASK_QUEUE, + PrioritizingTaskQueueSelector::HIGH_PRIORITY); // TODO(scheduler-dev): Add a task priority between HIGH and BEST_EFFORT // that still has some guarantee of running. - task_queue_selector->SetQueuePriority( + helper_.SetQueuePriority( LOADING_TASK_QUEUE, PrioritizingTaskQueueSelector::BEST_EFFORT_PRIORITY); break; case Policy::TOUCHSTART_PRIORITY: - task_queue_selector->SetQueuePriority( - COMPOSITOR_TASK_QUEUE, PrioritizingTaskQueueSelector::HIGH_PRIORITY); - task_queue_selector->DisableQueue(LOADING_TASK_QUEUE); + helper_.SetQueuePriority(COMPOSITOR_TASK_QUEUE, + PrioritizingTaskQueueSelector::HIGH_PRIORITY); + helper_.DisableQueue(LOADING_TASK_QUEUE); // TODO(alexclarke): Set policy_disables_timers once the blink TimerBase // refactor is safely landed. break; case Policy::NORMAL: - task_queue_selector->SetQueuePriority( - COMPOSITOR_TASK_QUEUE, - PrioritizingTaskQueueSelector::NORMAL_PRIORITY); - task_queue_selector->SetQueuePriority( - LOADING_TASK_QUEUE, PrioritizingTaskQueueSelector::NORMAL_PRIORITY); + helper_.SetQueuePriority(COMPOSITOR_TASK_QUEUE, + PrioritizingTaskQueueSelector::NORMAL_PRIORITY); + helper_.SetQueuePriority(LOADING_TASK_QUEUE, + PrioritizingTaskQueueSelector::NORMAL_PRIORITY); break; } if (timer_queue_suspend_count_ != 0 || policy_disables_timers) { - task_queue_selector->DisableQueue(TIMER_TASK_QUEUE); + helper_.DisableQueue(TIMER_TASK_QUEUE); } else { - helper_.SchedulerTaskQueueSelector()->SetQueuePriority( - TIMER_TASK_QUEUE, PrioritizingTaskQueueSelector::NORMAL_PRIORITY); + helper_.SetQueuePriority(TIMER_TASK_QUEUE, + PrioritizingTaskQueueSelector::NORMAL_PRIORITY); } - DCHECK(task_queue_selector->IsQueueEnabled(COMPOSITOR_TASK_QUEUE)); + DCHECK(helper_.IsQueueEnabled(COMPOSITOR_TASK_QUEUE)); if (new_policy != Policy::TOUCHSTART_PRIORITY) - DCHECK(task_queue_selector->IsQueueEnabled(LOADING_TASK_QUEUE)); + DCHECK(helper_.IsQueueEnabled(LOADING_TASK_QUEUE)); current_policy_ = new_policy; @@ -507,8 +504,7 @@ helper_.CheckOnValidThread(); timer_queue_suspend_count_++; ForceUpdatePolicy(); - DCHECK( - !helper_.SchedulerTaskQueueSelector()->IsQueueEnabled(TIMER_TASK_QUEUE)); + DCHECK(!helper_.IsQueueEnabled(TIMER_TASK_QUEUE)); } void RendererSchedulerImpl::ResumeTimerQueue() {
diff --git a/components/search_engines/default_search_manager.cc b/components/search_engines/default_search_manager.cc index 9adc184..c71ffadf 100644 --- a/components/search_engines/default_search_manager.cc +++ b/components/search_engines/default_search_manager.cc
@@ -100,9 +100,7 @@ // static void DefaultSearchManager::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - kDefaultSearchProviderDataPrefName, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kDefaultSearchProviderDataPrefName); } // static
diff --git a/components/search_engines/template_url_prepopulate_data.cc b/components/search_engines/template_url_prepopulate_data.cc index c1add44..5d79f66 100644 --- a/components/search_engines/template_url_prepopulate_data.cc +++ b/components/search_engines/template_url_prepopulate_data.cc
@@ -1184,16 +1184,9 @@ // Global functions ----------------------------------------------------------- void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterIntegerPref( - prefs::kCountryIDAtInstall, - kCountryIDUnknown, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(prefs::kSearchProviderOverrides, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterIntegerPref( - prefs::kSearchProviderOverridesVersion, - -1, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kCountryIDAtInstall, kCountryIDUnknown); + registry->RegisterListPref(prefs::kSearchProviderOverrides); + registry->RegisterIntegerPref(prefs::kSearchProviderOverridesVersion, -1); } int GetDataVersion(PrefService* prefs) {
diff --git a/components/search_engines/template_url_service_sync_unittest.cc b/components/search_engines/template_url_service_sync_unittest.cc index f0bfd85..d7baad51 100644 --- a/components/search_engines/template_url_service_sync_unittest.cc +++ b/components/search_engines/template_url_service_sync_unittest.cc
@@ -4,7 +4,6 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -18,6 +17,7 @@ #include "components/search_engines/template_url_prepopulate_data.h" #include "components/search_engines/template_url_service.h" #include "components/search_engines/template_url_service_client.h" +#include "content/public/test/test_browser_thread_bundle.h" #include "net/base/net_util.h" #include "sync/api/sync_change_processor_wrapper_for_test.h" #include "sync/api/sync_error_factory.h" @@ -237,7 +237,7 @@ const std::string& guid); protected: - base::MessageLoop message_loop_; + content::TestBrowserThreadBundle thread_bundle_; // We keep two TemplateURLServices to test syncing between them. scoped_ptr<TemplateURLServiceTestUtil> test_util_a_; scoped_ptr<TemplateURLServiceTestUtil> test_util_b_;
diff --git a/components/search_provider_logos/google_logo_api.cc b/components/search_provider_logos/google_logo_api.cc index 0e7501f..f92e679 100644 --- a/components/search_provider_logos/google_logo_api.cc +++ b/components/search_provider_logos/google_logo_api.cc
@@ -94,10 +94,6 @@ logo->encoded_image = encoded_image_string; if (!logo_dict->GetString("mime_type", &logo->metadata.mime_type)) return scoped_ptr<EncodedLogo>(); - - // Existance of url indicates |data| is a call to action image for an - // animated doodle. |url| points to that animated doodle. - logo_dict->GetString("url", &logo->metadata.animated_url); } // Don't check return values since these fields are optional. @@ -105,6 +101,10 @@ logo_dict->GetString("fingerprint", &logo->metadata.fingerprint); logo_dict->GetString("alt", &logo->metadata.alt_text); + // Existance of url indicates |data| is a call to action image for an + // animated doodle. |url| points to that animated doodle. + logo_dict->GetString("url", &logo->metadata.animated_url); + base::TimeDelta time_to_live; int time_to_live_ms; if (logo_dict->GetInteger("time_to_live", &time_to_live_ms)) {
diff --git a/components/search_provider_logos/logo_tracker.cc b/components/search_provider_logos/logo_tracker.cc index 0b60687..855fe1e 100644 --- a/components/search_provider_logos/logo_tracker.cc +++ b/components/search_provider_logos/logo_tracker.cc
@@ -243,6 +243,8 @@ encoded_logo->metadata.fingerprint == cached_logo_->metadata.fingerprint) { // The cached logo was revalidated, i.e. its fingerprint was verified. + // mime_type isn't sent when revalidating, so copy it from the cached logo. + encoded_logo->metadata.mime_type = cached_logo_->metadata.mime_type; SetCachedMetadata(encoded_logo->metadata); } else if (encoded_logo && image.isNull()) { // Image decoding failed. Do nothing.
diff --git a/components/search_provider_logos/logo_tracker_unittest.cc b/components/search_provider_logos/logo_tracker_unittest.cc index 4ae7734..cc7c0c4 100644 --- a/components/search_provider_logos/logo_tracker_unittest.cc +++ b/components/search_provider_logos/logo_tracker_unittest.cc
@@ -111,7 +111,7 @@ logo.metadata.source_url = logo_url.spec(); logo.metadata.on_click_url = "http://example.com/page25"; logo.metadata.alt_text = "The logo for example.com"; - logo.metadata.mime_type = "image/png"; + logo.metadata.mime_type = "image/jpeg"; return logo; } @@ -124,16 +124,15 @@ const std::string& fingerprint, base::TimeDelta time_to_live) { base::DictionaryValue dict; - if (!image.isNull()) { + if (!image.isNull()) dict.SetString("update.logo.data", EncodeBitmapAsPNGBase64(image)); - } dict.SetString("update.logo.target", on_click_url); dict.SetString("update.logo.alt", alt_text); - if (!animated_url.empty()) { + if (!animated_url.empty()) dict.SetString("update.logo.url", animated_url); - } - dict.SetString("update.logo.mime_type", mime_type); + if (!mime_type.empty()) + dict.SetString("update.logo.mime_type", mime_type); dict.SetString("update.logo.fingerprint", fingerprint); if (time_to_live.ToInternalValue() != 0) dict.SetInteger("update.logo.time_to_live", @@ -222,7 +221,11 @@ } void UpdateCachedLogoMetadataInternal(const LogoMetadata& metadata) { + ASSERT_TRUE(logo_.get()); + ASSERT_TRUE(metadata_.get()); + EXPECT_EQ(metadata_->fingerprint, metadata.fingerprint); metadata_.reset(new LogoMetadata(metadata)); + logo_->metadata = metadata; } virtual const LogoMetadata* GetCachedLogoMetadataInternal() { @@ -474,12 +477,14 @@ GetLogo(); } -TEST_F(LogoTrackerTest, ValidateCachedLogoFingerprint) { +TEST_F(LogoTrackerTest, ValidateCachedLogo) { Logo cached_logo = GetSampleLogo(logo_url_, test_clock_->Now()); logo_cache_->EncodeAndSetCachedLogo(cached_logo); + // During revalidation, the image data and mime_type are absent. Logo fresh_logo = cached_logo; fresh_logo.image.reset(); + fresh_logo.metadata.mime_type.clear(); fresh_logo.metadata.expiration_time = test_clock_->Now() + base::TimeDelta::FromDays(8); SetServerResponseWhenFingerprint(fresh_logo.metadata.fingerprint, @@ -489,12 +494,47 @@ EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0); EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1)); observer_.ExpectCachedLogo(&cached_logo); - GetLogo(); EXPECT_TRUE(logo_cache_->GetCachedLogoMetadata() != NULL); - EXPECT_EQ(logo_cache_->GetCachedLogoMetadata()->expiration_time, - fresh_logo.metadata.expiration_time); + EXPECT_EQ(fresh_logo.metadata.expiration_time, + logo_cache_->GetCachedLogoMetadata()->expiration_time); + + // Ensure that cached logo is still returned correctly on subsequent requests. + // In particular, the metadata should stay valid. http://crbug.com/480090 + EXPECT_CALL(*logo_cache_, UpdateCachedLogoMetadata(_)).Times(1); + EXPECT_CALL(*logo_cache_, SetCachedLogo(_)).Times(0); + EXPECT_CALL(*logo_cache_, OnGetCachedLogo()).Times(AtMost(1)); + observer_.ExpectCachedLogo(&cached_logo); + GetLogo(); +} + +TEST_F(LogoTrackerTest, UpdateCachedLogoMetadata) { + Logo cached_logo = GetSampleLogo(logo_url_, test_clock_->Now()); + logo_cache_->EncodeAndSetCachedLogo(cached_logo); + + Logo fresh_logo = cached_logo; + fresh_logo.image.reset(); + fresh_logo.metadata.mime_type.clear(); + fresh_logo.metadata.on_click_url = "http://new.onclick.url"; + fresh_logo.metadata.alt_text = "new alt text"; + fresh_logo.metadata.animated_url = "http://new.animated.url"; + fresh_logo.metadata.expiration_time = + test_clock_->Now() + base::TimeDelta::FromDays(8); + SetServerResponseWhenFingerprint(fresh_logo.metadata.fingerprint, + ServerResponse(fresh_logo)); + + // On the first request, the cached logo should be used. + observer_.ExpectCachedLogo(&cached_logo); + GetLogo(); + + // Subsequently, the cached image should be returned along with the updated + // metadata. + Logo expected_logo = fresh_logo; + expected_logo.image = cached_logo.image; + expected_logo.metadata.mime_type = cached_logo.metadata.mime_type; + observer_.ExpectCachedLogo(&expected_logo); + GetLogo(); } TEST_F(LogoTrackerTest, UpdateCachedLogo) {
diff --git a/components/sessions/content/content_serialized_navigation_builder.cc b/components/sessions/content/content_serialized_navigation_builder.cc index a033c64..b097769b 100644 --- a/components/sessions/content/content_serialized_navigation_builder.cc +++ b/components/sessions/content/content_serialized_navigation_builder.cc
@@ -34,9 +34,6 @@ navigation.is_overriding_user_agent_ = entry.GetIsOverridingUserAgent(); navigation.timestamp_ = entry.GetTimestamp(); navigation.is_restored_ = entry.IsRestored(); - // If you want to navigate a named frame in Chrome, you will first need to - // add support for persisting it. It is currently only used for layout tests. - CHECK(entry.GetFrameToNavigate().empty()); entry.GetExtraData(kSearchTermsKey, &navigation.search_terms_); if (entry.GetFavicon().valid) navigation.favicon_url_ = entry.GetFavicon().url;
diff --git a/components/sessions/ios/ios_serialized_navigation_driver.cc b/components/sessions/ios/ios_serialized_navigation_driver.cc index cbc06a5..9f41d8b 100644 --- a/components/sessions/ios/ios_serialized_navigation_driver.cc +++ b/components/sessions/ios/ios_serialized_navigation_driver.cc
@@ -98,8 +98,8 @@ NOTREACHED(); referrer.policy = web::ReferrerPolicyNever; } - bool is_downgrade = referrer.url.SchemeIsSecure() && - !navigation->virtual_url_.SchemeIsSecure(); + bool is_downgrade = referrer.url.SchemeIsCryptographic() && + !navigation->virtual_url_.SchemeIsCryptographic(); switch (referrer.policy) { case web::ReferrerPolicyDefault: if (is_downgrade)
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc index 81a7e614..74c3979 100644 --- a/components/signin/core/browser/about_signin_internals.cc +++ b/components/signin/core/browser/about_signin_internals.cc
@@ -20,11 +20,6 @@ #include "components/signin/core/browser/signin_manager.h" #include "components/signin/core/common/profile_management_switches.h" #include "components/signin/core/common/signin_switches.h" -#include "google_apis/gaia/gaia_auth_fetcher.h" -#include "google_apis/gaia/gaia_auth_util.h" -#include "google_apis/gaia/gaia_constants.h" -#include "google_apis/gaia/gaia_urls.h" -#include "net/cookies/canonical_cookie.h" using base::Time; using namespace signin_internals_util; @@ -135,12 +130,14 @@ ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker, SigninManagerBase* signin_manager, - SigninErrorController* signin_error_controller) + SigninErrorController* signin_error_controller, + GaiaCookieManagerService* cookie_manager_service) : token_service_(token_service), account_tracker_(account_tracker), signin_manager_(signin_manager), client_(NULL), - signin_error_controller_(signin_error_controller) {} + signin_error_controller_(signin_error_controller), + cookie_manager_service_(cookie_manager_service) {} AboutSigninInternals::~AboutSigninInternals() {} @@ -211,18 +208,14 @@ signin_error_controller_->AddObserver(this); signin_manager_->AddSigninDiagnosticsObserver(this); token_service_->AddDiagnosticsObserver(this); - cookie_changed_subscription_ = client_->AddCookieChangedCallback( - GaiaUrls::GetInstance()->gaia_url(), - "LSID", - base::Bind(&AboutSigninInternals::OnCookieChanged, - base::Unretained(this))); + cookie_manager_service_->AddObserver(this); } void AboutSigninInternals::Shutdown() { signin_error_controller_->RemoveObserver(this); signin_manager_->RemoveSigninDiagnosticsObserver(this); token_service_->RemoveDiagnosticsObserver(this); - cookie_changed_subscription_.reset(); + cookie_manager_service_->RemoveObserver(this); } void AboutSigninInternals::NotifyObservers() { @@ -329,48 +322,10 @@ NotifySigninValueChanged(AUTHENTICATION_RESULT_RECEIVED, status); } -void AboutSigninInternals::OnCookieChanged(const net::CanonicalCookie& cookie, - bool removed) { - DCHECK_EQ("LSID", cookie.Name()); - DCHECK_EQ(GaiaUrls::GetInstance()->gaia_url().host(), cookie.Domain()); - if (cookie.IsSecure() && cookie.IsHttpOnly()) { - GetCookieAccountsAsync(); - } -} - void AboutSigninInternals::OnErrorChanged() { NotifyObservers(); } -void AboutSigninInternals::GetCookieAccountsAsync() { - // Don't bother calling /ListAccounts if no one will observe the response. - if (!gaia_fetcher_ && signin_observers_.might_have_observers()) { - // There is no list account request in flight. - gaia_fetcher_.reset(new GaiaAuthFetcher( - this, GaiaConstants::kChromeSource, client_->GetURLRequestContext())); - gaia_fetcher_->StartListAccounts(); - } -} - -void AboutSigninInternals::OnListAccountsSuccess(const std::string& data) { - gaia_fetcher_.reset(); - - // Get account information from response data. - std::vector<std::pair<std::string, bool> > gaia_accounts; - bool valid_json = gaia::ParseListAccountsData(data, &gaia_accounts); - if (!valid_json) { - VLOG(1) << "AboutSigninInternals::OnListAccountsSuccess: parsing error"; - } else { - OnListAccountsComplete(gaia_accounts); - } -} - -void AboutSigninInternals::OnListAccountsFailure( - const GoogleServiceAuthError& error) { - gaia_fetcher_.reset(); - VLOG(1) << "AboutSigninInternals::OnListAccountsFailure:" << error.ToString(); -} - void AboutSigninInternals::GoogleSigninFailed( const GoogleServiceAuthError& error) { NotifyObservers(); @@ -387,8 +342,12 @@ NotifyObservers(); } -void AboutSigninInternals::OnListAccountsComplete( - std::vector<std::pair<std::string, bool> >& gaia_accounts) { +void AboutSigninInternals::OnGaiaAccountsInCookieUpdated( + const std::vector<std::pair<std::string, bool> >& gaia_accounts, + const GoogleServiceAuthError& error) { + if (error.state() != GoogleServiceAuthError::NONE) + return; + base::DictionaryValue cookie_status; base::ListValue* cookie_info = new base::ListValue(); cookie_status.Set("cookie_info", cookie_info);
diff --git a/components/signin/core/browser/about_signin_internals.h b/components/signin/core/browser/about_signin_internals.h index e5850d1..a2c1d23 100644 --- a/components/signin/core/browser/about_signin_internals.h +++ b/components/signin/core/browser/about_signin_internals.h
@@ -13,11 +13,11 @@ #include "base/observer_list.h" #include "base/values.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_error_controller.h" #include "components/signin/core/browser/signin_internals_util.h" #include "components/signin/core/browser/signin_manager.h" -#include "google_apis/gaia/gaia_auth_consumer.h" #include "google_apis/gaia/oauth2_token_service.h" class AccountTrackerService; @@ -35,7 +35,7 @@ : public KeyedService, public signin_internals_util::SigninDiagnosticsObserver, public OAuth2TokenService::DiagnosticsObserver, - public GaiaAuthConsumer, + public GaiaCookieManagerService::Observer, SigninManagerBase::Observer, SigninErrorController::Observer { public: @@ -52,7 +52,8 @@ AboutSigninInternals(ProfileOAuth2TokenService* token_service, AccountTrackerService* account_tracker, SigninManagerBase* signin_manager, - SigninErrorController* signin_error_controller); + SigninErrorController* signin_error_controller, + GaiaCookieManagerService* cookie_manager_service); ~AboutSigninInternals() override; // Each instance of SigninInternalsUI adds itself as an observer to be @@ -87,9 +88,10 @@ // } scoped_ptr<base::DictionaryValue> GetSigninStatus(); - // Triggers a ListAccounts call to acquire a list of the email addresses - // corresponding to the cookies residing on the current cookie jar. - void GetCookieAccountsAsync(); + // GaiaCookieManagerService::Observer implementations. + void OnGaiaAccountsInCookieUpdated( + const std::vector<std::pair<std::string, bool> >& gaia_accounts, + const GoogleServiceAuthError& error) override; private: // Encapsulates diagnostic information about tokens for different services. @@ -173,10 +175,6 @@ void OnTokenRemoved(const std::string& account_id, const OAuth2TokenService::ScopeSet& scopes) override; - // GaiaAuthConsumer implementations. - void OnListAccountsSuccess(const std::string& data) override; - void OnListAccountsFailure(const GoogleServiceAuthError& error) override; - // SigninManagerBase::Observer implementations. void GoogleSigninFailed(const GoogleServiceAuthError& error) override; void GoogleSigninSucceeded(const std::string& account_id, @@ -187,15 +185,6 @@ void NotifyObservers(); - // Callback for ListAccounts. Once the email addresses are fetched from GAIA, - // they are pushed to the signin_internals_ui. - void OnListAccountsComplete( - std::vector<std::pair<std::string, bool> >& gaia_accounts); - - // Called when a cookie changes. If the cookie relates to a GAIA LSID cookie, - // then we call ListAccounts and update the UI element. - void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed); - // SigninErrorController::Observer implementation void OnErrorChanged() override; @@ -214,8 +203,8 @@ // Weak pointer to the SigninErrorController SigninErrorController* signin_error_controller_; - // Fetcher for information about accounts in the cookie jar from GAIA. - scoped_ptr<GaiaAuthFetcher> gaia_fetcher_; + // Weak pointer to the GaiaCookieManagerService + GaiaCookieManagerService* cookie_manager_service_; // Encapsulates the actual signin and token related values. // Most of the values are mirrored in the prefs for persistence. @@ -223,9 +212,6 @@ ObserverList<Observer> signin_observers_; - scoped_ptr<SigninClient::CookieChangedSubscription> - cookie_changed_subscription_; - DISALLOW_COPY_AND_ASSIGN(AboutSigninInternals); };
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc index efe594db..aecbe9b1 100644 --- a/components/signin/core/browser/account_reconcilor.cc +++ b/components/signin/core/browser/account_reconcilor.cc
@@ -16,12 +16,9 @@ #include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_metrics.h" #include "components/signin/core/common/profile_management_switches.h" -#include "google_apis/gaia/gaia_auth_fetcher.h" #include "google_apis/gaia/gaia_auth_util.h" -#include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_oauth_client.h" #include "google_apis/gaia/gaia_urls.h" -#include "net/cookies/canonical_cookie.h" namespace { @@ -67,7 +64,6 @@ registered_with_content_settings_(false), is_reconcile_started_(false), first_execution_(true), - are_gaia_accounts_set_(false), chrome_accounts_changed_(false) { VLOG(1) << "AccountReconcilor::AccountReconcilor"; } @@ -87,7 +83,6 @@ // wait for signin. if (IsProfileConnected()) { RegisterWithCookieManagerService(); - RegisterForCookieChanges(); RegisterWithContentSettings(); RegisterWithTokenService(); @@ -101,29 +96,12 @@ void AccountReconcilor::Shutdown() { VLOG(1) << "AccountReconcilor::Shutdown"; - gaia_fetcher_.reset(); - get_gaia_accounts_callbacks_.clear(); UnregisterWithCookieManagerService(); UnregisterWithSigninManager(); UnregisterWithTokenService(); - UnregisterForCookieChanges(); UnregisterWithContentSettings(); } -void AccountReconcilor::RegisterForCookieChanges() { - // First clear any existing registration to avoid DCHECKs that can otherwise - // go off in some embedders on reauth (e.g., ChromeSigninClient). - UnregisterForCookieChanges(); - cookie_changed_subscription_ = client_->AddCookieChangedCallback( - GaiaUrls::GetInstance()->gaia_url(), - "LSID", - base::Bind(&AccountReconcilor::OnCookieChanged, base::Unretained(this))); -} - -void AccountReconcilor::UnregisterForCookieChanges() { - cookie_changed_subscription_.reset(); -} - void AccountReconcilor::RegisterWithSigninManager() { signin_manager_->AddObserver(this); } @@ -198,24 +176,6 @@ return signin_manager_->IsAuthenticated(); } -void AccountReconcilor::OnCookieChanged(const net::CanonicalCookie& cookie, - bool removed) { - DCHECK_EQ("LSID", cookie.Name()); - DCHECK_EQ(GaiaUrls::GetInstance()->gaia_url().host(), cookie.Domain()); - if (cookie.IsSecure() && cookie.IsHttpOnly()) { - VLOG(1) << "AccountReconcilor::OnCookieChanged: LSID changed"; - - // It is possible that O2RT is not available at this moment. - if (!token_service_->GetAccounts().size()) { - VLOG(1) << "AccountReconcilor::OnCookieChanged: cookie change is ingored" - "because O2RT is not available yet."; - return; - } - - StartReconcile(); - } -} - void AccountReconcilor::OnContentSettingChanged( const ContentSettingsPattern& primary_pattern, const ContentSettingsPattern& secondary_pattern, @@ -249,7 +209,6 @@ const std::string& password) { VLOG(1) << "AccountReconcilor::GoogleSigninSucceeded: signed in"; RegisterWithCookieManagerService(); - RegisterForCookieChanges(); RegisterWithContentSettings(); RegisterWithTokenService(); } @@ -257,12 +216,9 @@ void AccountReconcilor::GoogleSignedOut(const std::string& account_id, const std::string& username) { VLOG(1) << "AccountReconcilor::GoogleSignedOut: signed out"; - gaia_fetcher_.reset(); - get_gaia_accounts_callbacks_.clear(); AbortReconcile(); UnregisterWithCookieManagerService(); UnregisterWithTokenService(); - UnregisterForCookieChanges(); UnregisterWithContentSettings(); PerformLogoutAllAccountsAction(); } @@ -289,13 +245,12 @@ return; } - if (is_reconcile_started_ || get_gaia_accounts_callbacks_.size() > 0) + if (is_reconcile_started_) return; is_reconcile_started_ = true; // Reset state for validating gaia cookie. - are_gaia_accounts_set_ = false; gaia_accounts_.clear(); // Reset state for validating oauth2 tokens. @@ -304,78 +259,24 @@ add_to_cookie_.clear(); ValidateAccountsFromTokenService(); - GetAccountsFromCookie(base::Bind( - &AccountReconcilor::ContinueReconcileActionAfterGetGaiaAccounts, - base::Unretained(this))); -} - -void AccountReconcilor::GetAccountsFromCookie( - GetAccountsFromCookieCallback callback) { - get_gaia_accounts_callbacks_.push_back(callback); - if (!gaia_fetcher_) - MayBeDoNextListAccounts(); -} - -void AccountReconcilor::OnListAccountsSuccess(const std::string& data) { - gaia_fetcher_.reset(); - - // Get account information from response data. - std::vector<std::pair<std::string, bool> > gaia_accounts; - bool valid_json = gaia::ParseListAccountsData(data, &gaia_accounts); - if (!valid_json) { - VLOG(1) << "AccountReconcilor::OnListAccountsSuccess: parsing error"; - } else if (gaia_accounts.size() > 0) { - VLOG(1) << "AccountReconcilor::OnListAccountsSuccess: " - << "Gaia " << gaia_accounts.size() << " accounts, " - << "Primary is '" << gaia_accounts[0].first << "'"; - } else { - VLOG(1) << "AccountReconcilor::OnListAccountsSuccess: No accounts"; - } - - // There must be at least one callback waiting for result. - DCHECK(!get_gaia_accounts_callbacks_.empty()); - - GoogleServiceAuthError error = - !valid_json ? GoogleServiceAuthError( - GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE) - : GoogleServiceAuthError::AuthErrorNone(); - get_gaia_accounts_callbacks_.front().Run(error, gaia_accounts); - get_gaia_accounts_callbacks_.pop_front(); - - MayBeDoNextListAccounts(); -} - -void AccountReconcilor::OnListAccountsFailure( - const GoogleServiceAuthError& error) { - gaia_fetcher_.reset(); - VLOG(1) << "AccountReconcilor::OnListAccountsFailure: " << error.ToString(); - std::vector<std::pair<std::string, bool> > empty_accounts; - - // There must be at least one callback waiting for result. - DCHECK(!get_gaia_accounts_callbacks_.empty()); - - get_gaia_accounts_callbacks_.front().Run(error, empty_accounts); - get_gaia_accounts_callbacks_.pop_front(); - - MayBeDoNextListAccounts(); -} - -void AccountReconcilor::MayBeDoNextListAccounts() { - if (!get_gaia_accounts_callbacks_.empty()) { - gaia_fetcher_.reset(new GaiaAuthFetcher( - this, GaiaConstants::kReconcilorSource, - client_->GetURLRequestContext())); - gaia_fetcher_->StartListAccounts(); + // Rely on the GCMS to manage calls to and responses from ListAccounts. + if (cookie_manager_service_->ListAccounts(&gaia_accounts_)) { + OnGaiaAccountsInCookieUpdated( + gaia_accounts_, GoogleServiceAuthError(GoogleServiceAuthError::NONE)); } } -void AccountReconcilor::ContinueReconcileActionAfterGetGaiaAccounts( - const GoogleServiceAuthError& error, - const std::vector<std::pair<std::string, bool> >& accounts) { +void AccountReconcilor::OnGaiaAccountsInCookieUpdated( + const std::vector<std::pair<std::string, bool> >& accounts, + const GoogleServiceAuthError& error) { if (error.state() == GoogleServiceAuthError::NONE) { gaia_accounts_ = accounts; - are_gaia_accounts_set_ = true; - FinishReconcile(); + + // It is possible that O2RT is not available at this moment. + if (token_service_->GetAccounts().empty()) + return; + + is_reconcile_started_ ? FinishReconcile() : StartReconcile(); } else { AbortReconcile(); } @@ -407,7 +308,6 @@ void AccountReconcilor::FinishReconcile() { VLOG(1) << "AccountReconcilor::FinishReconcile"; - DCHECK(are_gaia_accounts_set_); DCHECK(add_to_cookie_.empty()); int number_gaia_accounts = gaia_accounts_.size(); bool are_primaries_equal = number_gaia_accounts > 0 &&
diff --git a/components/signin/core/browser/account_reconcilor.h b/components/signin/core/browser/account_reconcilor.h index 1350aa3a..8dbe06c 100644 --- a/components/signin/core/browser/account_reconcilor.h +++ b/components/signin/core/browser/account_reconcilor.h
@@ -23,7 +23,6 @@ #include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "components/signin/core/browser/signin_client.h" #include "components/signin/core/browser/signin_manager.h" -#include "google_apis/gaia/gaia_auth_consumer.h" #include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/oauth2_token_service.h" @@ -37,7 +36,6 @@ class AccountReconcilor : public KeyedService, public content_settings::Observer, - public GaiaAuthConsumer, public GaiaCookieManagerService::Observer, public OAuth2TokenService::Observer, public SigninManagerBase::Observer { @@ -58,23 +56,11 @@ // KeyedService implementation. void Shutdown() override; - protected: - // Used during GetAccountsFromCookie. - // Stores a callback for the next action to perform. - typedef base::Callback< - void(const GoogleServiceAuthError& error, - const std::vector<std::pair<std::string, bool> >&)> - GetAccountsFromCookieCallback; - - virtual void GetAccountsFromCookie(GetAccountsFromCookieCallback callback); - private: bool IsRegisteredWithTokenService() const { return registered_with_token_service_; } - bool AreGaiaAccountsSet() const { return are_gaia_accounts_set_; } - const std::vector<std::pair<std::string, bool> >& GetGaiaAccountsForTesting() const { return gaia_accounts_; @@ -112,8 +98,6 @@ AddAccountToCookieCompletedWithBogusAccount); // Register and unregister with dependent services. - void RegisterForCookieChanges(); - void UnregisterForCookieChanges(); void RegisterWithSigninManager(); void UnregisterWithSigninManager(); void RegisterWithTokenService(); @@ -137,15 +121,10 @@ void CalculateIfReconcileIsDone(); void ScheduleStartReconcileIfChromeAccountsChanged(); - void ContinueReconcileActionAfterGetGaiaAccounts( - const GoogleServiceAuthError& error, - const std::vector<std::pair<std::string, bool> >& accounts); void ValidateAccountsFromTokenService(); // Note internally that this |account_id| is added to the cookie jar. bool MarkAccountAsAddedToCookie(const std::string& account_id); - void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed); - // Overriden from content_settings::Observer. void OnContentSettingChanged( const ContentSettingsPattern& primary_pattern, @@ -153,14 +132,13 @@ ContentSettingsType content_type, std::string resource_identifier) override; - // Overriden from GaiaAuthConsumer. - void OnListAccountsSuccess(const std::string& data) override; - void OnListAccountsFailure(const GoogleServiceAuthError& error) override; - - // Overriden from MergeSessionHelper::Observer. + // Overriden from GaiaGookieManagerService::Observer. void OnAddAccountToCookieCompleted( const std::string& account_id, const GoogleServiceAuthError& error) override; + void OnGaiaAccountsInCookieUpdated( + const std::vector<std::pair<std::string, bool> >& accounts, + const GoogleServiceAuthError& error) override; // Overriden from OAuth2TokenService::Observer. void OnEndBatchChanges() override; @@ -172,8 +150,6 @@ void GoogleSignedOut(const std::string& account_id, const std::string& username) override; - void MayBeDoNextListAccounts(); - // The ProfileOAuth2TokenService associated with this reconcilor. ProfileOAuth2TokenService* token_service_; @@ -186,7 +162,6 @@ // The GaiaCookieManagerService associated with this reconcilor. GaiaCookieManagerService* cookie_manager_service_; - scoped_ptr<GaiaAuthFetcher> gaia_fetcher_; bool registered_with_token_service_; bool registered_with_cookie_manager_service_; bool registered_with_content_settings_; @@ -205,7 +180,6 @@ // a pair that holds the email address of the account and a boolean that // indicates whether the account is valid or not. The accounts in the vector // are ordered the in same way as the gaia cookie. - bool are_gaia_accounts_set_; std::vector<std::pair<std::string, bool> > gaia_accounts_; // Used during reconcile action. @@ -215,11 +189,6 @@ std::vector<std::string> add_to_cookie_; bool chrome_accounts_changed_; - std::deque<GetAccountsFromCookieCallback> get_gaia_accounts_callbacks_; - - scoped_ptr<SigninClient::CookieChangedSubscription> - cookie_changed_subscription_; - DISALLOW_COPY_AND_ASSIGN(AccountReconcilor); };
diff --git a/components/signin/core/browser/account_tracker_service.cc b/components/signin/core/browser/account_tracker_service.cc index 78d942a..5f2c1eb 100644 --- a/components/signin/core/browser/account_tracker_service.cc +++ b/components/signin/core/browser/account_tracker_service.cc
@@ -255,13 +255,15 @@ AccountTrackerService::AccountInfo AccountTrackerService::FindAccountInfoByGaiaId( const std::string& gaia_id) { - for (std::map<std::string, AccountState>::const_iterator it = - accounts_.begin(); - it != accounts_.end(); - ++it) { - const AccountState& state = it->second; - if (state.info.gaia == gaia_id) - return state.info; + if (!gaia_id.empty()) { + for (std::map<std::string, AccountState>::const_iterator it = + accounts_.begin(); + it != accounts_.end(); + ++it) { + const AccountState& state = it->second; + if (state.info.gaia == gaia_id) + return state.info; + } } return AccountInfo(); @@ -270,13 +272,15 @@ AccountTrackerService::AccountInfo AccountTrackerService::FindAccountInfoByEmail( const std::string& email) { - for (std::map<std::string, AccountState>::const_iterator it = - accounts_.begin(); - it != accounts_.end(); - ++it) { - const AccountState& state = it->second; - if (gaia::AreEmailsSame(state.info.email, email)) - return state.info; + if (!email.empty()) { + for (std::map<std::string, AccountState>::const_iterator it = + accounts_.begin(); + it != accounts_.end(); + ++it) { + const AccountState& state = it->second; + if (gaia::AreEmailsSame(state.info.email, email)) + return state.info; + } } return AccountInfo(); @@ -584,7 +588,8 @@ PrefService* pref_service, const std::string& gaia, const std::string& email) { - DCHECK(!gaia.empty()); + DCHECK(!gaia.empty() || + GetMigrationState(pref_service) == MIGRATION_NOT_STARTED); DCHECK(!email.empty()); switch(GetMigrationState(pref_service)) { case MIGRATION_NOT_STARTED: @@ -603,13 +608,11 @@ std::string AccountTrackerService::SeedAccountInfo(const std::string& gaia, const std::string& email) { - DCHECK(!gaia.empty()); - DCHECK(!email.empty()); const std::string account_id = PickAccountIdForAccount(gaia, email); const bool already_exists = ContainsKey(accounts_, account_id); StartTrackingAccount(account_id); AccountState& state = accounts_[account_id]; - DCHECK(!already_exists || state.info.gaia == gaia); + DCHECK(!already_exists || state.info.gaia.empty() || state.info.gaia == gaia); state.info.gaia = gaia; state.info.email = email; SaveToPrefs(state);
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc index 1aef48f..ccea52aa 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -15,6 +15,7 @@ #include "base/values.h" #include "components/signin/core/browser/signin_metrics.h" #include "google_apis/gaia/gaia_auth_fetcher.h" +#include "google_apis/gaia/gaia_auth_util.h" #include "google_apis/gaia/gaia_constants.h" #include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/oauth2_token_service.h" @@ -72,12 +73,9 @@ GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest( GaiaCookieRequestType request_type, - const std::string& account_id, - const GaiaCookieManagerService::ListAccountsCallback& - list_accounts_callback) + const std::string& account_id) : request_type_(request_type), - account_id_(account_id), - list_accounts_callback_(list_accounts_callback) {} + account_id_(account_id) {} GaiaCookieManagerService::GaiaCookieRequest::~GaiaCookieRequest() { } @@ -87,28 +85,21 @@ GaiaCookieManagerService::GaiaCookieRequest::CreateAddAccountRequest( const std::string& account_id) { return GaiaCookieManagerService::GaiaCookieRequest( - GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT, - account_id, - GaiaCookieManagerService::ListAccountsCallback()); + GaiaCookieManagerService::GaiaCookieRequestType::ADD_ACCOUNT, account_id); } // static GaiaCookieManagerService::GaiaCookieRequest GaiaCookieManagerService::GaiaCookieRequest::CreateLogOutRequest() { return GaiaCookieManagerService::GaiaCookieRequest( - GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT, - std::string(), - GaiaCookieManagerService::ListAccountsCallback()); + GaiaCookieManagerService::GaiaCookieRequestType::LOG_OUT, std::string()); } GaiaCookieManagerService::GaiaCookieRequest -GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest( - const GaiaCookieManagerService::ListAccountsCallback& - list_accounts_callback) { +GaiaCookieManagerService::GaiaCookieRequest::CreateListAccountsRequest() { return GaiaCookieManagerService::GaiaCookieRequest( GaiaCookieManagerService::GaiaCookieRequestType::LIST_ACCOUNTS, - std::string(), - list_accounts_callback); + std::string()); } GaiaCookieManagerService::ExternalCcResultFetcher::ExternalCcResultFetcher( @@ -295,7 +286,8 @@ gaia_auth_fetcher_backoff_(&kBackoffPolicy), gaia_auth_fetcher_retries_(0), source_(source), - external_cc_result_fetched_(false) { + external_cc_result_fetched_(false), + list_accounts_fetched_once_(false) { } GaiaCookieManagerService::~GaiaCookieManagerService() { @@ -303,8 +295,26 @@ DCHECK(requests_.empty()); } +void GaiaCookieManagerService::Init() { + cookie_changed_subscription_ = signin_client_->AddCookieChangedCallback( + GaiaUrls::GetInstance()->google_url(), + "APISID", + base::Bind(&GaiaCookieManagerService::OnCookieChanged, + base::Unretained(this))); +} + +void GaiaCookieManagerService::Shutdown() { + cookie_changed_subscription_.reset(); +} + void GaiaCookieManagerService::AddAccountToCookie( const std::string& account_id) { + if (!signin_client_->AreSigninCookiesAllowed()) { + SignalComplete(account_id, + GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED)); + return; + } + DCHECK(!account_id.empty()); VLOG(1) << "GaiaCookieManagerService::AddAccountToCookie: " << account_id; requests_.push_back(GaiaCookieRequest::CreateAddAccountRequest(account_id)); @@ -312,25 +322,26 @@ StartFetchingUbertoken(); } -void GaiaCookieManagerService::ListAccounts( - const ListAccountsCallback& callback) { - // Not implemented yet. - NOTREACHED(); +bool GaiaCookieManagerService::ListAccounts( + std::vector<std::pair<std::string,bool> >* accounts) { + DCHECK(accounts); + accounts->clear(); - // TODO(mlerman): Once this service listens to all GAIA cookie changes, cache - // the results of ListAccounts, and return them here if the GAIA cookie - // hasn't changed since the last call. + // There is a fetch currently executing (the results being provided in the + // parameter don't align with the fetches that have been started), or the list + // of accounts haven't been fetched even once. + if (!requests_.empty()) + return false; - // If there's a GAIA call being executed, wait for it to complete. If it was - // another /ListAccounts then we'll use the results it caches. - if (gaia_auth_fetcher_) - return; + if (!list_accounts_fetched_once_) { + gaia_auth_fetcher_retries_ = 0; + requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest()); + StartFetchingListAccounts(); + return false; + } - VLOG(1) << "GaiaCookieManagerService::ListAccounts"; - gaia_auth_fetcher_.reset( - new GaiaAuthFetcher(this, source_, - signin_client_->GetURLRequestContext())); - gaia_auth_fetcher_->StartListAccounts(); + accounts->assign(listed_accounts_.begin(), listed_accounts_.end()); + return true; } void GaiaCookieManagerService::LogOutAllAccounts() { @@ -394,6 +405,41 @@ gaia_auth_fetcher_timer_.Stop(); } +// It is unknown if the cookie was changed because of processing initiated by +// this class or other (such as the user clearing all cookies or a cookie being +// evicted). +void GaiaCookieManagerService::OnCookieChanged( + const net::CanonicalCookie& cookie, + bool removed) { + DCHECK_EQ("APISID", cookie.Name()); + DCHECK_EQ(GaiaUrls::GetInstance()->google_url().host(), cookie.Domain()); + gaia_auth_fetcher_retries_ = 0; + if (requests_.empty()) { + requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest()); + StartFetchingListAccounts(); + } else { + // Remove all pending ListAccount calls; for efficiency, only call + // after all pending requests are processed. + // Track requests to keep; all other unstarted requests will be removed. + std::vector<GaiaCookieRequest> requests_to_keep; + + // Check all pending, non-executing requests. + for (auto it = requests_.begin() + 1; it != requests_.end(); ++it) { + // Keep all requests except for LIST_ACCOUNTS. + if (it->request_type() != GaiaCookieRequestType::LIST_ACCOUNTS) + requests_to_keep.push_back(*it); + } + + // Remove all but the executing request. Re-add all requests being kept. + if (requests_.size() > 1) { + requests_.erase(requests_.begin() + 1, requests_.end()); + requests_.insert( + requests_.end(), requests_to_keep.begin(), requests_to_keep.end()); + } + requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest()); + } +} + void GaiaCookieManagerService::SignalComplete( const std::string& account_id, const GoogleServiceAuthError& error) { @@ -446,6 +492,8 @@ void GaiaCookieManagerService::OnMergeSessionSuccess(const std::string& data) { VLOG(1) << "MergeSession successful account=" << requests_.front().account_id(); + DCHECK(requests_.front().request_type() == + GaiaCookieRequestType::ADD_ACCOUNT); const std::string account_id = requests_.front().account_id(); HandleNextRequest(); SignalComplete(account_id, GoogleServiceAuthError::AuthErrorNone()); @@ -456,10 +504,11 @@ void GaiaCookieManagerService::OnMergeSessionFailure( const GoogleServiceAuthError& error) { + DCHECK(requests_.front().request_type() == + GaiaCookieRequestType::ADD_ACCOUNT); VLOG(1) << "Failed MergeSession" << " account=" << requests_.front().account_id() << " error=" << error.ToString(); - if (++gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries && IsTransientError(error)) { gaia_auth_fetcher_backoff_.InformOfRequest(false); @@ -475,6 +524,46 @@ SignalComplete(account_id, error); } +void GaiaCookieManagerService::OnListAccountsSuccess(const std::string& data) { + VLOG(1) << "ListAccounts successful"; + DCHECK(requests_.front().request_type() == + GaiaCookieRequestType::LIST_ACCOUNTS); + gaia_auth_fetcher_backoff_.InformOfRequest(true); + + if (!gaia::ParseListAccountsData(data, &listed_accounts_)) { + listed_accounts_.clear(); + OnListAccountsFailure(GoogleServiceAuthError( + GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE)); + return; + } + + list_accounts_fetched_once_ = true; + FOR_EACH_OBSERVER(Observer, observer_list_, + OnGaiaAccountsInCookieUpdated( + listed_accounts_, + GoogleServiceAuthError(GoogleServiceAuthError::NONE))); + HandleNextRequest(); +} + +void GaiaCookieManagerService::OnListAccountsFailure( + const GoogleServiceAuthError& error) { + VLOG(1) << "ListAccounts failed"; + DCHECK(requests_.front().request_type() == + GaiaCookieRequestType::LIST_ACCOUNTS); + if (++gaia_auth_fetcher_retries_ < kMaxGaiaAuthFetcherRetries && + IsTransientError(error)) { + gaia_auth_fetcher_backoff_.InformOfRequest(false); + gaia_auth_fetcher_timer_.Start( + FROM_HERE, gaia_auth_fetcher_backoff_.GetTimeUntilRelease(), this, + &GaiaCookieManagerService::StartFetchingListAccounts); + return; + } + + FOR_EACH_OBSERVER(Observer, observer_list_, + OnGaiaAccountsInCookieUpdated(listed_accounts_, error)); + HandleNextRequest(); +} + void GaiaCookieManagerService::StartFetchingUbertoken() { VLOG(1) << "GaiaCookieManagerService::StartFetching account_id=" << requests_.front().account_id(); @@ -494,6 +583,14 @@ external_cc_result_fetcher_.GetExternalCcResult()); } +void GaiaCookieManagerService::StartFetchingListAccounts() { + VLOG(1) << "GaiaCookieManagerService::ListAccounts"; + gaia_auth_fetcher_.reset( + new GaiaAuthFetcher(this, source_, + signin_client_->GetURLRequestContext())); + gaia_auth_fetcher_->StartListAccounts(); +} + void GaiaCookieManagerService::OnURLFetchComplete( const net::URLFetcher* source) { DCHECK(requests_.front().request_type() == GaiaCookieRequestType::LOG_OUT); @@ -503,8 +600,20 @@ void GaiaCookieManagerService::HandleNextRequest() { VLOG(1) << "GaiaCookieManagerService::HandleNextRequest"; - requests_.pop_front(); + if (requests_.front().request_type() == + GaiaCookieRequestType::LIST_ACCOUNTS) { + // This and any directly subsequent list accounts would return the same. + while (!requests_.empty() && requests_.front().request_type() == + GaiaCookieRequestType::LIST_ACCOUNTS) { + requests_.pop_front(); + } + } else { + // Pop the completed request. + requests_.pop_front(); + } + gaia_auth_fetcher_.reset(); + gaia_auth_fetcher_retries_ = 0; if (requests_.empty()) { VLOG(1) << "GaiaCookieManagerService::HandleNextRequest: no more"; uber_token_fetcher_.reset(); @@ -517,6 +626,8 @@ StartLogOutUrlFetch(); break; case GaiaCookieRequestType::LIST_ACCOUNTS: + uber_token_fetcher_.reset(); + StartFetchingListAccounts(); break; }; }
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.h b/components/signin/core/browser/gaia_cookie_manager_service.h index ff9d4b0..74df85d 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service.h +++ b/components/signin/core/browser/gaia_cookie_manager_service.h
@@ -16,6 +16,7 @@ #include "net/url_request/url_fetcher_delegate.h" class GaiaAuthFetcher; +class GaiaCookieRequest; class GoogleServiceAuthError; class OAuth2TokenService; @@ -36,11 +37,6 @@ public UbertokenConsumer, public net::URLFetcherDelegate { public: - typedef base::Callback<void(const std::string& data, - const GoogleServiceAuthError& error)> - ListAccountsCallback; - - enum GaiaCookieRequestType { ADD_ACCOUNT, LOG_OUT, @@ -54,28 +50,19 @@ GaiaCookieRequestType request_type() const { return request_type_; } const std::string& account_id() const {return account_id_; } - const GaiaCookieManagerService::ListAccountsCallback& - list_accounts_callback() const { - return list_accounts_callback_; - } static GaiaCookieRequest CreateAddAccountRequest( const std::string& account_id); static GaiaCookieRequest CreateLogOutRequest(); - static GaiaCookieRequest CreateListAccountsRequest( - const GaiaCookieManagerService::ListAccountsCallback& - list_accounts_callback); + static GaiaCookieRequest CreateListAccountsRequest(); private: GaiaCookieRequest( GaiaCookieRequestType request_type, - const std::string& account_id, - const GaiaCookieManagerService::ListAccountsCallback& - list_accounts_callback); + const std::string& account_id); GaiaCookieRequestType request_type_; std::string account_id_; - GaiaCookieManagerService::ListAccountsCallback list_accounts_callback_; }; class Observer { @@ -85,7 +72,18 @@ // GoogleServiceAuthError::AuthErrorNone() then the merge succeeeded. virtual void OnAddAccountToCookieCompleted( const std::string& account_id, - const GoogleServiceAuthError& error) = 0; + const GoogleServiceAuthError& error) {} + + // Called whenever the GaiaCookieManagerService's list of GAIA accounts is + // updated. The GCMS monitors the APISID cookie and triggers a /ListAccounts + // call on change. The GCMS will also call ListAccounts upon the first call + // to ListAccounts(). The GCMS will delay calling ListAccounts if other + // requests are in queue that would modify the APISID cookie. + // If the ListAccounts call fails and the GCMS cannot recover, the reason + // is passed in |error|. + virtual void OnGaiaAccountsInCookieUpdated( + const std::vector<std::pair<std::string, bool> >& accounts, + const GoogleServiceAuthError& error) {} protected: virtual ~Observer() {} @@ -158,9 +156,16 @@ SigninClient* signin_client); ~GaiaCookieManagerService() override; + void Init(); + void Shutdown() override; + void AddAccountToCookie(const std::string& account_id); - void ListAccounts(const ListAccountsCallback& callback); + // Returns if the listed accounts are up to date or not (ignore the out + // parameter if return is false). The parameter will be assigned the current + // cached accounts. If the accounts are not up to date, a ListAccounts fetch + // is sent GAIA and Observer::OnGaiaAccountsInCookieUpdated will be called. + bool ListAccounts(std::vector<std::pair<std::string,bool> >* accounts); // Add or remove observers of this helper. void AddObserver(Observer* observer); @@ -186,11 +191,19 @@ return &external_cc_result_fetcher_; } + void set_list_accounts_fetched_once_for_testing(bool fetched) { + list_accounts_fetched_once_ = fetched; + } + private: net::URLRequestContextGetter* request_context() { return signin_client_->GetURLRequestContext(); } + // Called when a cookie changes. If the cookie relates to a GAIA APISID + // cookie, then we call ListAccounts and fire OnGaiaAccountsInCookieUpdated. + void OnCookieChanged(const net::CanonicalCookie& cookie, bool removed); + // Overridden from UbertokenConsumer. void OnUbertokenSuccess(const std::string& token) override; void OnUbertokenFailure(const GoogleServiceAuthError& error) override; @@ -198,6 +211,8 @@ // Overridden from GaiaAuthConsumer. void OnMergeSessionSuccess(const std::string& data) override; void OnMergeSessionFailure(const GoogleServiceAuthError& error) override; + void OnListAccountsSuccess(const std::string& data) override; + void OnListAccountsFailure(const GoogleServiceAuthError& error) override; // Starts the proess of fetching the uber token and performing a merge session // for the next account. Virtual so that it can be overriden in tests. @@ -209,6 +224,9 @@ // Virtual for testing purpose. virtual void StartLogOutUrlFetch(); + // Virtual for testing purposes. + virtual void StartFetchingListAccounts(); + // Start the next request, if needed. void HandleNextRequest(); @@ -229,6 +247,10 @@ // The last fetched ubertoken, for use in MergeSession retries. std::string uber_token_; + // Subscription to be called whenever the GAIA cookies change. + scoped_ptr<SigninClient::CookieChangedSubscription> + cookie_changed_subscription_; + // A worklist for this class. Stores any pending requests that couldn't be // executed right away, since this class only permits one request to be // executed at a time. @@ -244,6 +266,10 @@ // True once the ExternalCCResultFetcher has completed once. bool external_cc_result_fetched_; + std::vector<std::pair<std::string, bool> > listed_accounts_; + + bool list_accounts_fetched_once_; + DISALLOW_COPY_AND_ASSIGN(GaiaCookieManagerService); };
diff --git a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc index cc04452..170a17a 100644 --- a/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc +++ b/components/signin/core/browser/gaia_cookie_manager_service_unittest.cc
@@ -31,8 +31,9 @@ MOCK_METHOD2(OnAddAccountToCookieCompleted, void(const std::string&, const GoogleServiceAuthError&)); - MOCK_METHOD1(GetCheckConnectionInfoCompleted, void(bool)); - + MOCK_METHOD2(OnGaiaAccountsInCookieUpdated, + void(const std::vector<std::pair<std::string, bool> >&, + const GoogleServiceAuthError&)); private: GaiaCookieManagerService* helper_; @@ -59,6 +60,7 @@ virtual ~InstrumentedGaiaCookieManagerService() { total--; } MOCK_METHOD0(StartFetchingUbertoken, void()); + MOCK_METHOD0(StartFetchingListAccounts, void()); MOCK_METHOD0(StartFetchingMergeSession, void()); MOCK_METHOD0(StartLogOutUrlFetch, void()); @@ -74,7 +76,7 @@ canceled_(GoogleServiceAuthError::REQUEST_CANCELED) {} OAuth2TokenService* token_service() { return &token_service_; } - SigninClient* signin_client() { return &signin_client_; } + TestSigninClient* signin_client() { return &signin_client_; } void SimulateUbertokenSuccess(UbertokenConsumer* consumer, const std::string& uber_token) { @@ -96,6 +98,11 @@ consumer->OnMergeSessionFailure(error); } + void SimulateListAccountsSuccess(GaiaAuthConsumer* consumer, + const std::string& data) { + consumer->OnListAccountsSuccess(data); + } + void SimulateLogoutSuccess(net::URLFetcherDelegate* consumer) { consumer->OnURLFetchComplete(NULL); } @@ -164,6 +171,17 @@ DCHECK(!helper.is_running()); } +TEST_F(GaiaCookieManagerServiceTest, AddAccountCookiesDisabled) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + signin_client()->set_are_signin_cookies_allowed(false); + + EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc1@gmail.com", + canceled())); + + helper.AddAccountToCookie("acc1@gmail.com"); +} + TEST_F(GaiaCookieManagerServiceTest, MergeSessionRetried) { InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); @@ -378,7 +396,6 @@ EXPECT_CALL(helper, StartLogOutUrlFetch()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc3@gmail.com", no_error())); - helper.AddAccountToCookie("acc2@gmail.com"); SimulateMergeSessionSuccess(&helper, "token1"); @@ -445,8 +462,6 @@ InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); MockObserver observer(&helper); - std::vector<std::string> current_accounts; - EXPECT_CALL(helper, StartFetchingUbertoken()); EXPECT_CALL(observer, OnAddAccountToCookieCompleted("acc2@gmail.com", canceled())); @@ -462,6 +477,37 @@ SimulateLogoutSuccess(&helper); } +TEST_F(GaiaCookieManagerServiceTest, ListAccountsFirstReturnsEmpty) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + + std::vector<std::pair<std::string, bool> > list_accounts; + + EXPECT_CALL(helper, StartFetchingListAccounts()); + + ASSERT_FALSE(helper.ListAccounts(&list_accounts)); + ASSERT_TRUE(list_accounts.empty()); +} + +TEST_F(GaiaCookieManagerServiceTest, ListAccountsFindsOneAccount) { + InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); + MockObserver observer(&helper); + + std::vector<std::pair<std::string, bool> > list_accounts; + std::vector<std::pair<std::string, bool> > expected_accounts; + expected_accounts.push_back(std::pair<std::string, bool>( + "user@gmail.com", true)); + + EXPECT_CALL(helper, StartFetchingListAccounts()); + EXPECT_CALL(observer, OnGaiaAccountsInCookieUpdated(expected_accounts, + no_error())); + + ASSERT_FALSE(helper.ListAccounts(&list_accounts)); + + SimulateListAccountsSuccess(&helper, + "[\"f\", [[\"b\", 0, \"n\", \"user@gmail.com\", \"p\", 0, 0, 0, 0, 1]]]"); +} + TEST_F(GaiaCookieManagerServiceTest, ExternalCcResultFetcher) { InstrumentedGaiaCookieManagerService helper(token_service(), signin_client()); GaiaCookieManagerService::ExternalCcResultFetcher result_fetcher(&helper);
diff --git a/components/signin/core/browser/signin_manager_base.cc b/components/signin/core/browser/signin_manager_base.cc index f6333a3..1aecaa2 100644 --- a/components/signin/core/browser/signin_manager_base.cc +++ b/components/signin/core/browser/signin_manager_base.cc
@@ -62,31 +62,39 @@ if (account_id.empty()) { std::string pref_account_username = client_->GetPrefs()->GetString(prefs::kGoogleServicesUsername); - std::string pref_gaia_id = - client_->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId); + if (!pref_account_username.empty()) { + // This is an old profile connected to a google account. Migrate from + // kGoogleServicesUsername to kGoogleServicesAccountId. + std::string pref_gaia_id = + client_->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId); - // If kGoogleServicesUserAccountId is empty, then this is either a chromeos - // machine or a really old profile on one of the other platforms. However - // in this case the account tracker should have the gaia_id so fetch it - // from there. - if (!pref_account_username.empty() && pref_gaia_id.empty()) { - AccountTrackerService::AccountInfo info = - account_tracker_service_->GetAccountInfo(pref_account_username); - DCHECK(!info.gaia.empty()); - pref_gaia_id = info.gaia; - } + // If kGoogleServicesUserAccountId is empty, then this is either a cros + // machine or a really old profile on one of the other platforms. However + // in this case the account tracker should have the gaia_id so fetch it + // from there. + if (pref_gaia_id.empty()) { + AccountTrackerService::AccountInfo info = + account_tracker_service_->GetAccountInfo(pref_account_username); + pref_gaia_id = info.gaia; + } - if (!pref_account_username.empty() && !pref_gaia_id.empty()) { + // If |pref_gaia_id| is still empty, this means the profile has been in + // an auth error state for some time (since M39). It could also mean + // a profile that has not been used since M33. Before migration to gaia + // id is complete, the returned value will be the normalized email, which + // is correct. After the migration, the returned value will be empty, + // which means the user is essentially signed out. + // TODO(rogerta): may want to show a toast or something. account_id = account_tracker_service_->SeedAccountInfo( pref_gaia_id, pref_account_username); // Now remove obsolete preferences. client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername); - - // TODO(rogerta): once migration to gaia id is complete, remove - // kGoogleServicesUserAccountId and change all uses of that pref to - // kGoogleServicesAccountId. } + + // TODO(rogerta): once migration to gaia id is complete, remove + // kGoogleServicesUserAccountId and change all uses of that pref to + // kGoogleServicesAccountId. } if (!account_id.empty()) @@ -110,6 +118,9 @@ void SigninManagerBase::SetAuthenticatedAccountInfo(const std::string& gaia_id, const std::string& email) { + DCHECK(!gaia_id.empty()); + DCHECK(!email.empty()); + std::string account_id = account_tracker_service_->SeedAccountInfo(gaia_id, email); SetAuthenticatedAccountId(account_id); @@ -138,9 +149,13 @@ // Gaia id of the signed in user. AccountTrackerService::AccountInfo info = account_tracker_service_->GetAccountInfo(account_id); - DCHECK(!info.gaia.empty()); - client_->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId, - info.gaia); + + // When this function is called from Initialize(), it's possible for + // |info.gaia| to be empty when migrating from a really old profile. + if (!info.gaia.empty()) { + client_->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId, + info.gaia); + } // Go ahead and update the last signed in account info here as well. Once a // user is signed in the two preferences should match. Doing it here as
diff --git a/components/signin/core/browser/signin_tracker.cc b/components/signin/core/browser/signin_tracker.cc index ad5954f6..9e76b86 100644 --- a/components/signin/core/browser/signin_tracker.cc +++ b/components/signin/core/browser/signin_tracker.cc
@@ -4,7 +4,6 @@ #include "components/signin/core/browser/signin_tracker.h" -#include "components/signin/core/browser/account_reconcilor.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_client.h" @@ -12,13 +11,11 @@ SigninTracker::SigninTracker(ProfileOAuth2TokenService* token_service, SigninManagerBase* signin_manager, - AccountReconcilor* account_reconcilor, GaiaCookieManagerService* cookie_manager_service, SigninClient* client, Observer* observer) : token_service_(token_service), signin_manager_(signin_manager), - account_reconcilor_(account_reconcilor), cookie_manager_service_(cookie_manager_service), client_(client), observer_(observer) {
diff --git a/components/signin/core/browser/signin_tracker.h b/components/signin/core/browser/signin_tracker.h index 2dcd5c91..5f82bd00 100644 --- a/components/signin/core/browser/signin_tracker.h +++ b/components/signin/core/browser/signin_tracker.h
@@ -10,7 +10,6 @@ #include "components/signin/core/browser/signin_manager.h" #include "google_apis/gaia/google_service_auth_error.h" -class AccountReconcilor; class ProfileOAuth2TokenService; class SigninClient; @@ -75,7 +74,6 @@ // non-null. SigninTracker(ProfileOAuth2TokenService* token_service, SigninManagerBase* signin_manager, - AccountReconcilor* account_reconcilor, GaiaCookieManagerService* cookie_manager_service, SigninClient* client, Observer* observer); @@ -100,7 +98,6 @@ // The classes whose collective signin status we are tracking. ProfileOAuth2TokenService* token_service_; SigninManagerBase* signin_manager_; - AccountReconcilor* account_reconcilor_; GaiaCookieManagerService* cookie_manager_service_; // The client associated with this instance.
diff --git a/components/signin/ios/browser/merge_session_observer_bridge.h b/components/signin/ios/browser/merge_session_observer_bridge.h index 6703ab72..8137dbbf1 100644 --- a/components/signin/ios/browser/merge_session_observer_bridge.h +++ b/components/signin/ios/browser/merge_session_observer_bridge.h
@@ -12,7 +12,6 @@ #include "base/macros.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h" -class AccountReconcilor; class GoogleServiceAuthError; @protocol MergeSessionObserverBridgeDelegate
diff --git a/components/suggestions/blacklist_store.cc b/components/suggestions/blacklist_store.cc index 304df2f..c9245e7 100644 --- a/components/suggestions/blacklist_store.cc +++ b/components/suggestions/blacklist_store.cc
@@ -212,9 +212,7 @@ // static void BlacklistStore::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kSuggestionsBlacklist, std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kSuggestionsBlacklist, std::string()); }
diff --git a/components/suggestions/suggestions_store.cc b/components/suggestions/suggestions_store.cc index 8685a64..42d6dc50 100644 --- a/components/suggestions/suggestions_store.cc +++ b/components/suggestions/suggestions_store.cc
@@ -99,9 +99,7 @@ // static void SuggestionsStore::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref( - prefs::kSuggestionsData, std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kSuggestionsData, std::string()); } } // namespace suggestions
diff --git a/components/surfaces/BUILD.gn b/components/surfaces/BUILD.gn index c1f8d2e4..9c72d24c 100644 --- a/components/surfaces/BUILD.gn +++ b/components/surfaces/BUILD.gn
@@ -28,6 +28,8 @@ "//cc", "//cc/surfaces", "//cc/surfaces:surface_id", + "//components/gpu/public/interfaces", + "//components/surfaces/public/interfaces", "//gpu/command_buffer/client:gles2_interface", "//mojo/application", "//mojo/common", @@ -39,9 +41,7 @@ "//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/public/cpp/environment", "//third_party/mojo/src/mojo/public/cpp/system", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/gpu/public/interfaces", - "//third_party/mojo_services/src/surfaces/public/interfaces", "//ui/gfx/geometry", + "//ui/mojo/geometry:interfaces", ] }
diff --git a/components/surfaces/DEPS b/components/surfaces/DEPS index cdcf83c..7e211ce 100644 --- a/components/surfaces/DEPS +++ b/components/surfaces/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+cc", + "+components/gpu", "+gpu", "+mojo/application", "+mojo/common",
diff --git a/components/surfaces/OWNERS b/components/surfaces/OWNERS new file mode 100644 index 0000000..e6a7642f --- /dev/null +++ b/components/surfaces/OWNERS
@@ -0,0 +1,4 @@ +ben@chromium.org +erg@chromium.org +msw@chromium.org +sky@chromium.org
diff --git a/components/surfaces/display_factory_impl.h b/components/surfaces/display_factory_impl.h index 6569e55..b208324 100644 --- a/components/surfaces/display_factory_impl.h +++ b/components/surfaces/display_factory_impl.h
@@ -6,8 +6,8 @@ #define COMPONENTS_SURFACES_DISPLAY_FACTORY_IMPL_H_ #include "components/surfaces/display_impl.h" +#include "components/surfaces/public/interfaces/display.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/display.mojom.h" namespace cc { class SurfaceManager;
diff --git a/components/surfaces/display_impl.h b/components/surfaces/display_impl.h index 11a25ef..d10150d9 100644 --- a/components/surfaces/display_impl.h +++ b/components/surfaces/display_impl.h
@@ -9,8 +9,8 @@ #include "cc/surfaces/display_client.h" #include "cc/surfaces/surface_factory.h" #include "cc/surfaces/surface_factory_client.h" +#include "components/surfaces/public/interfaces/display.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/display.mojom.h" namespace cc { class Display;
diff --git a/components/surfaces/public/interfaces/BUILD.gn b/components/surfaces/public/interfaces/BUILD.gn new file mode 100644 index 0000000..7c64300 --- /dev/null +++ b/components/surfaces/public/interfaces/BUILD.gn
@@ -0,0 +1,29 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "display.mojom", + "quads.mojom", + "surfaces.mojom", + ] + + import_dirs = [ get_path_info("../../../", "abspath") ] + + deps = [ + ":surface_id", + "//components/gpu/public/interfaces", + "//components/native_viewport/public/interfaces", + "//ui/mojo/geometry:interfaces", + ] +} + +mojom("surface_id") { + sources = [ + "surface_id.mojom", + ] +}
diff --git a/components/surfaces/public/interfaces/display.mojom b/components/surfaces/public/interfaces/display.mojom new file mode 100644 index 0000000..f38908bd --- /dev/null +++ b/components/surfaces/public/interfaces/display.mojom
@@ -0,0 +1,33 @@ +// 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 mojo; + +import "components/gpu/public/interfaces/context_provider.mojom"; +import "components/gpu/public/interfaces/viewport_parameter_listener.mojom"; +import "components/surfaces/public/interfaces/surfaces.mojom"; + +interface Display { + // Submits a new frame to the display to be drawn when possible. The callback + // will be run after the frame has been issued to the display but possibly + // before the frame is actually visible. + // + // The Display will be resized to the size of the last entry in |frame|'s + // |passes| list (aka the root pass). + // + // Any resources submitted in the frame will be returned via the + // ResourceReturner associated with the Display at construction time. + SubmitFrame(Frame frame) => (); +}; + +// DisplayFactory creates new Display instances. +interface DisplayFactory { + // Create associates a Display that will draw to contexts produced by + // |context_provider|. Any resources submitted to the display will be + // returned via the |returner|, if supplied. + Create(ContextProvider context_provider, + ResourceReturner? returner, + Display& display_request); +}; +
diff --git a/components/surfaces/public/interfaces/quads.mojom b/components/surfaces/public/interfaces/quads.mojom new file mode 100644 index 0000000..95403bb --- /dev/null +++ b/components/surfaces/public/interfaces/quads.mojom
@@ -0,0 +1,212 @@ +// 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 mojo; + +import "surfaces/public/interfaces/surface_id.mojom"; +import "ui/mojo/geometry/geometry.mojom"; + +struct Color { + uint32 rgba; +}; + +// TODO(jamesr): Populate subtype fields. +struct CheckerboardQuadState {}; + +struct DebugBorderQuadState {}; + +struct IoSurfaceContentQuadState {}; + +struct RenderPassId { + int32 layer_id; + int32 index; +}; + +struct RenderPassQuadState { + RenderPassId render_pass_id; + + // If nonzero, resource id of mask to use when drawing this pass. + uint32 mask_resource_id; + PointF mask_uv_scale; + Size mask_texture_size; + + // Post-processing filters, applied to the pixels in the render pass' texture. + // TODO(jamesr): Support + // FilterOperations filters; + + // The scale from layer space of the root layer of the render pass to + // the render pass physical pixels. This scale is applied to the filter + // parameters for pixel-moving filters. This scale should include + // content-to-target-space scale, and device pixel ratio. + PointF filters_scale; + + // Post-processing filters, applied to the pixels showing through the + // background of the render pass, from behind it. + // TODO(jamesr): Support + // FilterOperations background_filters; +}; + +struct SolidColorQuadState { + Color color; + bool force_anti_aliasing_off; +}; + +struct SurfaceQuadState { + SurfaceId surface; +}; + +struct TextureQuadState { + uint32 resource_id; + bool premultiplied_alpha; + PointF uv_top_left; + PointF uv_bottom_right; + Color background_color; + array<float, 4> vertex_opacity; + bool flipped; + bool nearest_neighbor; +}; + +struct TileQuadState { + RectF tex_coord_rect; + Size texture_size; + bool swizzle_contents; + uint32 resource_id; + bool nearest_neighbor; +}; + +struct StreamVideoQuadState {}; + +enum YUVColorSpace { + REC_601, // SDTV standard with restricted "studio swing" color range. + REC_709, // HDTV standard with restricted "studio swing" color range. + JPEG, // Full color range [0, 255] JPEG color space. +}; + +struct YUVVideoQuadState { + RectF tex_coord_rect; + uint32 y_plane_resource_id; + uint32 u_plane_resource_id; + uint32 v_plane_resource_id; + uint32 a_plane_resource_id; + YUVColorSpace color_space; +}; + +enum Material { + CHECKERBOARD = 1, + DEBUG_BORDER, + IO_SURFACE_CONTENT, + PICTURE_CONTENT, + RENDER_PASS, + SOLID_COLOR, + STREAM_VIDEO_CONTENT, + SURFACE_CONTENT, + TEXTURE_CONTENT, + TILED_CONTENT, + YUV_VIDEO_CONTENT, +}; + +struct Quad { + Material material; + + // This rect, after applying the quad_transform(), gives the geometry that + // this quad should draw to. This rect lives in content space. + Rect rect; + + // This specifies the region of the quad that is opaque. This rect lives in + // content space. + Rect opaque_rect; + + // Allows changing the rect that gets drawn to make it smaller. This value + // should be clipped to |rect|. This rect lives in content space. + Rect visible_rect; + + // Allows changing the rect that gets drawn to make it smaller. This value + // should be clipped to |rect|. This rect lives in content space. + bool needs_blending; + + // Index into the containing pass' shared quad state array which has state + // (transforms etc) shared by multiple quads. + uint32 shared_quad_state_index; + + // Only one of the following will be set, depending on the material. + CheckerboardQuadState? checkerboard_quad_state; + DebugBorderQuadState? debug_border_quad_state; + IoSurfaceContentQuadState? io_surface_quad_state; + RenderPassQuadState? render_pass_quad_state; + SolidColorQuadState? solid_color_quad_state; + SurfaceQuadState? surface_quad_state; + TextureQuadState? texture_quad_state; + TileQuadState? tile_quad_state; + StreamVideoQuadState? stream_video_quad_state; + YUVVideoQuadState? yuv_video_quad_state; +}; + +enum SkXfermode { + kClear_Mode = 0, //!< [0, 0] + kSrc_Mode, //!< [Sa, Sc] + kDst_Mode, //!< [Da, Dc] + kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc] + kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc] + kSrcIn_Mode, //!< [Sa * Da, Sc * Da] + kDstIn_Mode, //!< [Sa * Da, Sa * Dc] + kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] + kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] + kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] + kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] + kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] + kPlus_Mode, //!< [Sa + Da, Sc + Dc] + kModulate_Mode, // multiplies all components (= alpha and color) + + // Following blend modes are defined in the CSS Compositing standard: + // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending + kScreen_Mode, + kLastCoeffMode = kScreen_Mode, + + kOverlay_Mode, + kDarken_Mode, + kLighten_Mode, + kColorDodge_Mode, + kColorBurn_Mode, + kHardLight_Mode, + kSoftLight_Mode, + kDifference_Mode, + kExclusion_Mode, + kMultiply_Mode, + kLastSeparableMode = kMultiply_Mode, + + kHue_Mode, + kSaturation_Mode, + kColor_Mode, + kLuminosity_Mode, + kLastMode = kLuminosity_Mode +}; + +struct SharedQuadState { + // Transforms from quad's original content space to its target content space. + Transform content_to_target_transform; + + // This size lives in the content space for the quad's originating layer. + Size content_bounds; + + // This rect lives in the content space for the quad's originating layer. + Rect visible_content_rect; + + // This rect lives in the target content space. + Rect clip_rect; + + bool is_clipped; + float opacity; + SkXfermode blend_mode; + int32 sorting_context_id; +}; + +struct Pass { + RenderPassId id; + Rect output_rect; + Rect damage_rect; + Transform transform_to_root_target; + bool has_transparent_background; + array<Quad> quads; + array<SharedQuadState> shared_quad_states; +};
diff --git a/third_party/mojo_services/src/surfaces/public/interfaces/surface_id.mojom b/components/surfaces/public/interfaces/surface_id.mojom similarity index 100% rename from third_party/mojo_services/src/surfaces/public/interfaces/surface_id.mojom rename to components/surfaces/public/interfaces/surface_id.mojom
diff --git a/components/surfaces/public/interfaces/surfaces.mojom b/components/surfaces/public/interfaces/surfaces.mojom new file mode 100644 index 0000000..d0241d83 --- /dev/null +++ b/components/surfaces/public/interfaces/surfaces.mojom
@@ -0,0 +1,77 @@ +// 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 mojo; + +import "components/surfaces/public/interfaces/quads.mojom"; +import "components/surfaces/public/interfaces/surface_id.mojom"; +import "ui/mojo/geometry/geometry.mojom"; + +enum ResourceFormat { + RGBA_8888, + RGBA_4444, + BGRA_8888, + ALPHA_8, + LUMINANCE_8, + RGB_565, + ETC1, +}; + +struct Mailbox { + array<int8, 64> name; +}; + +struct MailboxHolder { + Mailbox mailbox; + uint32 texture_target; + uint32 sync_point; +}; + +struct TransferableResource { + uint32 id; + ResourceFormat format; + uint32 filter; + Size size; + MailboxHolder mailbox_holder; + bool is_repeated; + bool is_software; +}; + +struct ReturnedResource { + uint32 id; + uint32 sync_point; + int32 count; + bool lost; +}; + +struct Frame { + array<TransferableResource> resources; + array<Pass> passes; +}; + +interface ResourceReturner { + ReturnResources(array<ReturnedResource> resources); +}; + +interface Surface { + // Request the id namespace for this connection. Fully qualified surface ids + // are the combination of the id_namespace for the connection that created the + // surface and the id_local component allocated by the caller. + GetIdNamespace() => (uint32 id_namespace); + + // Sets a ResourceReturner that will receive unused resources. + SetResourceReturner(ResourceReturner returner); + + // Creates a new surface with the given local identifier. Once a surface is + // created the caller may submit frames to it or destroy it using the local + // identifier. The caller can also produce a fully qualified surface id that + // can be embedded in frames produces by different connections. + CreateSurface(uint32 id_local); + + // After the submitted frame is drawn for the first time, the surface will + // respond to the SubmitFrame message. Clients should use this acknowledgement + // to ratelimit frame submissions. + SubmitFrame(uint32 id_local, Frame frame) => (); + DestroySurface(uint32 id_local); +};
diff --git a/components/surfaces/surfaces_impl.h b/components/surfaces/surfaces_impl.h index 36314d2..5ff375d2 100644 --- a/components/surfaces/surfaces_impl.h +++ b/components/surfaces/surfaces_impl.h
@@ -8,12 +8,12 @@ #include "cc/surfaces/display_client.h" #include "cc/surfaces/surface_factory.h" #include "cc/surfaces/surface_factory_client.h" +#include "components/gpu/public/interfaces/command_buffer.mojom.h" +#include "components/gpu/public/interfaces/viewport_parameter_listener.mojom.h" +#include "components/surfaces/public/interfaces/surfaces.mojom.h" #include "mojo/common/weak_binding_set.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/viewport_parameter_listener.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom.h" namespace cc { class Display;
diff --git a/components/surfaces/surfaces_service_application.h b/components/surfaces/surfaces_service_application.h index 89b7cb7..ba55d0c1 100644 --- a/components/surfaces/surfaces_service_application.h +++ b/components/surfaces/surfaces_service_application.h
@@ -7,11 +7,11 @@ #include "base/macros.h" #include "cc/surfaces/surface_manager.h" +#include "components/surfaces/public/interfaces/display.mojom.h" +#include "components/surfaces/public/interfaces/surfaces.mojom.h" #include "mojo/common/tracing_impl.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/interface_factory.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/display.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom.h" namespace mojo { class ApplicationConnection;
diff --git a/components/sync_driver/device_info_sync_service.cc b/components/sync_driver/device_info_sync_service.cc index 76ea831a..fb441a4 100644 --- a/components/sync_driver/device_info_sync_service.cc +++ b/components/sync_driver/device_info_sync_service.cc
@@ -4,6 +4,7 @@ #include "components/sync_driver/device_info_sync_service.h" +#include "base/metrics/histogram_macros.h" #include "base/strings/stringprintf.h" #include "components/sync_driver/local_device_info_provider.h" #include "sync/api/sync_change.h" @@ -21,6 +22,38 @@ using syncer::SyncErrorFactory; using syncer::SyncMergeResult; +namespace { + +// TODO(pavely): Remove histogram once device_id mismatch is understood +// (crbug/481596). +// When signin_scoped_device_id from pref doesn't match the one in +// DeviceInfoSpecfics record histogram telling if sync or pref copy was empty. +// This will indicate how often such mismatch happens and what was the state +// before. +enum DeviceIdMismatchForHistogram { + DEVICE_ID_MISMATCH_BOTH_NONEMPTY = 0, + DEVICE_ID_MISMATCH_SYNC_EMPTY, + DEVICE_ID_MISMATCH_PREF_EMPTY, + DEVICE_ID_MISMATCH_COUNT, +}; + +void RecordDeviceIdChangedHistogram(const std::string& device_id_from_sync, + const std::string& device_id_from_pref) { + DCHECK(device_id_from_sync != device_id_from_pref); + DeviceIdMismatchForHistogram device_id_mismatch_for_histogram = + DEVICE_ID_MISMATCH_BOTH_NONEMPTY; + if (device_id_from_sync.empty()) { + device_id_mismatch_for_histogram = DEVICE_ID_MISMATCH_SYNC_EMPTY; + } else if (device_id_from_pref.empty()) { + device_id_mismatch_for_histogram = DEVICE_ID_MISMATCH_PREF_EMPTY; + } + UMA_HISTOGRAM_ENUMERATION("Sync.DeviceIdMismatchDetails", + device_id_mismatch_for_histogram, + DEVICE_ID_MISMATCH_COUNT); +} + +} // namespace + DeviceInfoSyncService::DeviceInfoSyncService( LocalDeviceInfoProvider* local_device_info_provider) : local_device_backup_time_(-1), @@ -85,6 +118,14 @@ if (!has_local_device_backup_time() && has_synced_backup_time) { set_local_device_backup_time(synced_backup_time); } + // TODO(pavely): Remove histogram once device_id mismatch is understood + // (crbug/481596). + if (synced_local_device_info->signin_scoped_device_id() != + local_device_info->signin_scoped_device_id()) { + RecordDeviceIdChangedHistogram( + synced_local_device_info->signin_scoped_device_id(), + local_device_info->signin_scoped_device_id()); + } // Store the synced device info for the local device only // it is the same as the local info. Otherwise store the local
diff --git a/components/sync_driver/non_ui_data_type_controller.cc b/components/sync_driver/non_ui_data_type_controller.cc index df189b0..eb86a9a 100644 --- a/components/sync_driver/non_ui_data_type_controller.cc +++ b/components/sync_driver/non_ui_data_type_controller.cc
@@ -122,6 +122,7 @@ return; // The datatype was never activated, we're done. case ASSOCIATING: state_ = STOPPING; + StopModels(); // We continue on to deactivate the datatype and stop the local service. break; case MODEL_LOADED:
diff --git a/components/sync_driver/non_ui_data_type_controller_unittest.cc b/components/sync_driver/non_ui_data_type_controller_unittest.cc index 3652407..27fe04e 100644 --- a/components/sync_driver/non_ui_data_type_controller_unittest.cc +++ b/components/sync_driver/non_ui_data_type_controller_unittest.cc
@@ -393,6 +393,7 @@ syncer::SyncError::DATATYPE_ERROR, "Disconnected.", AUTOFILL_PROFILE))); + EXPECT_CALL(*dtc_mock_.get(), StopModels()); EXPECT_CALL(*change_processor_.get(), Disconnect()) .WillOnce(DoAll(SignalEvent(&pause_db_thread), Return(true))); EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state()); @@ -411,7 +412,7 @@ SetStartExpectations(); // We don't expect StopSyncing to be called because local_service_ will never // have been set. - EXPECT_CALL(*change_processor_.get(), Disconnect()).WillOnce(Return(true)); + SetStopExpectations(); EXPECT_EQ(DataTypeController::NOT_RUNNING, non_ui_dtc_->state()); Start(); non_ui_dtc_->Stop();
diff --git a/components/sync_driver/sync_prefs.cc b/components/sync_driver/sync_prefs.cc index 4f1b27fe..c28a213 100644 --- a/components/sync_driver/sync_prefs.cc +++ b/components/sync_driver/sync_prefs.cc
@@ -35,30 +35,15 @@ // static void SyncPrefs::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterBooleanPref( - prefs::kSyncHasSetupCompleted, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterBooleanPref( - prefs::kSyncSuppressStart, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kSyncLastSyncedTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterInt64Pref( - prefs::kSyncFirstSyncTime, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kSyncHasSetupCompleted, false); + registry->RegisterBooleanPref(prefs::kSyncSuppressStart, false); + registry->RegisterInt64Pref(prefs::kSyncLastSyncedTime, 0); + registry->RegisterInt64Pref(prefs::kSyncFirstSyncTime, 0); // All datatypes are on by default, but this gets set explicitly // when you configure sync (when turning it on), in // ProfileSyncService::OnUserChoseDatatypes. - registry->RegisterBooleanPref( - prefs::kSyncKeepEverythingSynced, - true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kSyncKeepEverythingSynced, true); syncer::ModelTypeSet user_types = syncer::UserTypes(); @@ -81,38 +66,20 @@ RegisterDataTypePreferredPref(registry, it.Get(), false); } - registry->RegisterBooleanPref( - prefs::kSyncManaged, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kSyncEncryptionBootstrapToken, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kSyncKeystoreEncryptionBootstrapToken, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kSyncManaged, false); + registry->RegisterStringPref(prefs::kSyncEncryptionBootstrapToken, + std::string()); + registry->RegisterStringPref(prefs::kSyncKeystoreEncryptionBootstrapToken, + std::string()); #if defined(OS_CHROMEOS) - registry->RegisterStringPref( - prefs::kSyncSpareBootstrapToken, - "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kSyncSpareBootstrapToken, ""); #endif - registry->RegisterBooleanPref( - prefs::kSyncHasAuthError, - false, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(prefs::kSyncHasAuthError, false); - registry->RegisterStringPref( - prefs::kSyncSessionsGUID, - std::string(), - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterStringPref(prefs::kSyncSessionsGUID, std::string()); - registry->RegisterIntegerPref( - prefs::kSyncRemainingRollbackTries, 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterIntegerPref(prefs::kSyncRemainingRollbackTries, 0); } void SyncPrefs::AddSyncPrefObserver(SyncPrefObserver* sync_pref_observer) { @@ -394,10 +361,7 @@ NOTREACHED(); return; } - registry->RegisterBooleanPref( - pref_name, - is_preferred, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(pref_name, is_preferred); } bool SyncPrefs::GetDataTypePreferred(syncer::ModelType type) const {
diff --git a/components/test/data/dom_distiller/pinch_tester.html b/components/test/data/dom_distiller/pinch_tester.html new file mode 100644 index 0000000..9dbb48d --- /dev/null +++ b/components/test/data/dom_distiller/pinch_tester.html
@@ -0,0 +1,14 @@ +<html> +<head><title>Test Page for Pinch to Zoom</title></head> +<body> +<div id="contentWrap"> +<p id="showOriginal">Original</p> +</div> +<div id="feedbackContainer"> + <div id="feedbackYes"></div> + <div id="feedbackNo"></div> +</div> +<script src="dom_distiller_viewer.js"></script> +<script src="pinch_tester.js"></script> +</body> +</html>
diff --git a/components/test/data/dom_distiller/pinch_tester.js b/components/test/data/dom_distiller/pinch_tester.js new file mode 100644 index 0000000..e2c1df5 --- /dev/null +++ b/components/test/data/dom_distiller/pinch_tester.js
@@ -0,0 +1,388 @@ +// 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. + +var pinchtest = (function() { + 'use strict'; + + function assertTrue(condition, message) { + if (!condition) { + message = message || "Assertion failed"; + console.trace(); + throw new Error(message); + } + } + + function assertClose(a, b, message) { + if (Math.abs(a-b) > 1e-5) { + message = message || "Assertion failed"; + console.log('"', a, '" and "', b, '" are not close.'); + console.trace(); + throw new Error(message); + } + } + + function isEquivalent(a, b) { + // Create arrays of property names + var aProps = Object.getOwnPropertyNames(a); + var bProps = Object.getOwnPropertyNames(b); + + // If number of properties is different, + // objects are not equivalent + if (aProps.length != bProps.length) { + return false; + } + + for (var i = 0; i < aProps.length; i++) { + var propName = aProps[i]; + + // If values of same property are not equal, + // objects are not equivalent + if (a[propName] !== b[propName]) { + return false; + } + } + + // If we made it this far, objects + // are considered equivalent + return true; + } + + function assertEqual(a, b, message) { + if (!isEquivalent(a, b)) { + message = message || "Assertion failed"; + console.log('"', a, '" and "', b, '" are not equal'); + console.trace(); + throw new Error(message); + } + } + + var touch = (function() { + 'use strict'; + var points = {}; + function lowestID() { + var ans = -1; + for(var key in points) { + ans = Math.max(ans, key); + } + return ans + 1; + } + function changeTouchPoint (key, x, y, offsetX, offsetY) { + var e = { + clientX: x, + clientY: y, + pageX: x, + pageY: y + }; + if (typeof(offsetX) === 'number') { + e.clientX += offsetX; + } + if (typeof(offsetY) === 'number') { + e.clientY += offsetY; + } + points[key] = e; + } + return { + addTouchPoint: function(x, y, offsetX, offsetY) { + changeTouchPoint(lowestID(), x, y, offsetX, offsetY); + }, + updateTouchPoint: changeTouchPoint, + releaseTouchPoint: function(key) { + delete points[key]; + }, + events: function() { + var arr = []; + for(var key in points) { + arr.push(points[key]); + } + return { + touches: arr, + preventDefault: function(){} + }; + } + } + }); + + function testZoomOut() { + pincher.reset(); + var t = new touch(); + + // Make sure start event doesn't change state + var oldState = pincher.status(); + t.addTouchPoint(100, 100); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + t.addTouchPoint(300, 300); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + + // Make sure extra move event doesn't change state + pincher.handleTouchMove(t.events()); + assertEqual(oldState, pincher.status()); + + t.updateTouchPoint(0, 150, 150); + t.updateTouchPoint(1, 250, 250); + pincher.handleTouchMove(t.events()); + assertTrue(pincher.status().clampedScale < 0.9); + + // Make sure end event doesn't change state + oldState = pincher.status(); + t.releaseTouchPoint(1); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + t.releaseTouchPoint(0); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + } + + function testZoomIn() { + pincher.reset(); + var t = new touch(); + + var oldState = pincher.status(); + t.addTouchPoint(150, 150); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + t.addTouchPoint(250, 250); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + + t.updateTouchPoint(0, 100, 100); + t.updateTouchPoint(1, 300, 300); + pincher.handleTouchMove(t.events()); + assertTrue(pincher.status().clampedScale > 1.1); + + oldState = pincher.status(); + t.releaseTouchPoint(1); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + t.releaseTouchPoint(0); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + } + + function testZoomOutAndPan() { + pincher.reset(); + var t = new touch(); + t.addTouchPoint(100, 100); + pincher.handleTouchStart(t.events()); + t.addTouchPoint(300, 300); + pincher.handleTouchStart(t.events()); + t.updateTouchPoint(0, 150, 150); + t.updateTouchPoint(1, 250, 250); + pincher.handleTouchMove(t.events()); + t.updateTouchPoint(0, 150, 150, 10, -5); + t.updateTouchPoint(1, 250, 250, 10, -5); + pincher.handleTouchMove(t.events()); + t.releaseTouchPoint(1); + pincher.handleTouchEnd(t.events()); + t.releaseTouchPoint(0); + pincher.handleTouchEnd(t.events()); + + assertClose(pincher.status().shiftX, 10); + assertClose(pincher.status().shiftY, -5); + assertTrue(pincher.status().clampedScale < 0.9); + } + + function testReversible() { + pincher.reset(); + var t = new touch(); + t.addTouchPoint(100, 100); + pincher.handleTouchStart(t.events()); + t.addTouchPoint(300, 300); + pincher.handleTouchStart(t.events()); + t.updateTouchPoint(0, 0, 0); + t.updateTouchPoint(1, 400, 400); + pincher.handleTouchMove(t.events()); + t.releaseTouchPoint(1); + pincher.handleTouchEnd(t.events()); + t.releaseTouchPoint(0); + pincher.handleTouchEnd(t.events()); + t.addTouchPoint(0, 0); + pincher.handleTouchStart(t.events()); + t.addTouchPoint(400, 400); + pincher.handleTouchStart(t.events()); + t.updateTouchPoint(0, 100, 100); + t.updateTouchPoint(1, 300, 300); + pincher.handleTouchMove(t.events()); + t.releaseTouchPoint(1); + pincher.handleTouchEnd(t.events()); + t.releaseTouchPoint(0); + pincher.handleTouchEnd(t.events()); + assertClose(pincher.status().clampedScale, 1); + } + + function testMultitouchZoomOut() { + pincher.reset(); + var t = new touch(); + + var oldState = pincher.status(); + t.addTouchPoint(100, 100); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + t.addTouchPoint(300, 300); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + t.addTouchPoint(100, 300); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + t.addTouchPoint(300, 100); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + + // Multi-touch zoom out. + t.updateTouchPoint(0, 150, 150); + t.updateTouchPoint(1, 250, 250); + t.updateTouchPoint(2, 150, 250); + t.updateTouchPoint(3, 250, 150); + pincher.handleTouchMove(t.events()); + + oldState = pincher.status(); + t.releaseTouchPoint(3); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + t.releaseTouchPoint(2); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + t.releaseTouchPoint(1); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + t.releaseTouchPoint(0); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + + assertTrue(pincher.status().clampedScale < 0.9); + } + + function testZoomOutThenMulti() { + pincher.reset(); + var t = new touch(); + + var oldState = pincher.status(); + t.addTouchPoint(100, 100); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + t.addTouchPoint(300, 300); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + + // Zoom out. + t.updateTouchPoint(0, 150, 150); + t.updateTouchPoint(1, 250, 250); + pincher.handleTouchMove(t.events()); + assertTrue(pincher.status().clampedScale < 0.9); + + // Make sure adding and removing more point doesn't change state + oldState = pincher.status(); + t.addTouchPoint(600, 600); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + t.releaseTouchPoint(2); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + + // More than two fingers. + t.addTouchPoint(150, 250); + pincher.handleTouchStart(t.events()); + t.addTouchPoint(250, 150); + pincher.handleTouchStart(t.events()); + assertEqual(oldState, pincher.status()); + + t.updateTouchPoint(0, 100, 100); + t.updateTouchPoint(1, 300, 300); + t.updateTouchPoint(2, 100, 300); + t.updateTouchPoint(3, 300, 100); + pincher.handleTouchMove(t.events()); + assertClose(pincher.status().scale, 1); + + oldState = pincher.status(); + t.releaseTouchPoint(3); + t.releaseTouchPoint(2); + t.releaseTouchPoint(1); + t.releaseTouchPoint(0); + pincher.handleTouchEnd(t.events()); + assertEqual(oldState, pincher.status()); + } + + function testCancel() { + pincher.reset(); + var t = new touch(); + + t.addTouchPoint(100, 100); + pincher.handleTouchStart(t.events()); + t.addTouchPoint(300, 300); + pincher.handleTouchStart(t.events()); + t.updateTouchPoint(0, 150, 150); + t.updateTouchPoint(1, 250, 250); + pincher.handleTouchMove(t.events()); + assertTrue(pincher.status().clampedScale < 0.9); + + var oldState = pincher.status(); + t.releaseTouchPoint(1); + t.releaseTouchPoint(0); + pincher.handleTouchCancel(t.events()); + assertEqual(oldState, pincher.status()); + + t.addTouchPoint(150, 150); + pincher.handleTouchStart(t.events()); + t.addTouchPoint(250, 250); + pincher.handleTouchStart(t.events()); + t.updateTouchPoint(0, 100, 100); + t.updateTouchPoint(1, 300, 300); + pincher.handleTouchMove(t.events()); + assertClose(pincher.status().clampedScale, 1); + } + + function testSingularity() { + pincher.reset(); + var t = new touch(); + + t.addTouchPoint(100, 100); + pincher.handleTouchStart(t.events()); + t.addTouchPoint(100, 100); + pincher.handleTouchStart(t.events()); + t.updateTouchPoint(0, 150, 150); + t.updateTouchPoint(1, 50, 50); + pincher.handleTouchMove(t.events()); + assertTrue(pincher.status().clampedScale > 1.1); + assertTrue(pincher.status().clampedScale < 100); + assertTrue(pincher.status().scale < 100); + + pincher.handleTouchCancel(); + } + + function testMinSpan() { + pincher.reset(); + var t = new touch(); + + t.addTouchPoint(50, 50); + pincher.handleTouchStart(t.events()); + t.addTouchPoint(150, 150); + pincher.handleTouchStart(t.events()); + t.updateTouchPoint(0, 100, 100); + t.updateTouchPoint(1, 100, 100); + pincher.handleTouchMove(t.events()); + assertTrue(pincher.status().clampedScale < 0.9); + assertTrue(pincher.status().clampedScale > 0); + assertTrue(pincher.status().scale > 0); + + pincher.handleTouchCancel(); + } + + return { + run: function(){ + testZoomOut(); + testZoomIn(); + testZoomOutAndPan(); + testReversible(); + testMultitouchZoomOut(); + testZoomOutThenMulti(); + testCancel(); + testSingularity(); + testMinSpan(); + pincher.reset(); + + return {success: true}; + } + }; +}());
diff --git a/components/test/data/password_manager/automated_tests/tests.py b/components/test/data/password_manager/automated_tests/tests.py index f8fe6ff..ac5a44a 100644 --- a/components/test/data/password_manager/automated_tests/tests.py +++ b/components/test/data/password_manager/automated_tests/tests.py
@@ -569,6 +569,7 @@ parser.add_argument("--save-only-failures", help="Only save logs for failing tests.", dest="save_only_failures", action="store_true", + default=False) parser.add_argument("website", help="Website test name on which" "tests should be run.") parser.add_argument("--test-cases-to-run", help="Names of test cases which"
diff --git a/components/test/data/password_manager/login_db_v12.sql b/components/test/data/password_manager/login_db_v12.sql new file mode 100644 index 0000000..6f746fe7 --- /dev/null +++ b/components/test/data/password_manager/login_db_v12.sql
@@ -0,0 +1,82 @@ +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); +INSERT INTO "meta" VALUES('last_compatible_version','1'); +INSERT INTO "meta" VALUES('version','12'); +CREATE TABLE logins ( +origin_url VARCHAR NOT NULL, +action_url VARCHAR, +username_element VARCHAR, +username_value VARCHAR, +password_element VARCHAR, +password_value BLOB, +submit_element VARCHAR, +signon_realm VARCHAR NOT NULL, +ssl_valid INTEGER NOT NULL, +preferred INTEGER NOT NULL, +date_created INTEGER NOT NULL, +blacklisted_by_user INTEGER NOT NULL, +scheme INTEGER NOT NULL, +password_type INTEGER, +possible_usernames BLOB, +times_used INTEGER, +form_data BLOB, +date_synced INTEGER, +display_name VARCHAR, +avatar_url VARCHAR, +federation_url VARCHAR, +skip_zero_click INTEGER, +generation_upload_status INTEGER, +UNIQUE (origin_url, username_element, username_value, password_element, signon_realm)); +INSERT INTO "logins" VALUES( +'https://accounts.google.com/ServiceLogin', /* origin_url */ +'https://accounts.google.com/ServiceLoginAuth', /* action_url */ +'Email', /* username_element */ +'theerikchen', /* username_value */ +'Passwd', /* password_element */ +X'', /* password_value */ +'', /* submit_element */ +'https://accounts.google.com/', /* signon_realm */ +1, /* ssl_valid */ +1, /* preferred */ +13047429345000000, /* date_created */ +0, /* blacklisted_by_user */ +0, /* scheme */ +0, /* password_type */ +X'00000000', /* possible_usernames */ +1, /* times_used */ +X'18000000020000000000000000000000000000000000000000000000', /* form_data */ +0, /* date_synced */ +'', /* display_name */ +'', /* avatar_url */ +'', /* federation_url */ +0, /* skip_zero_click */ +0 /* generation_upload_status */ +); +INSERT INTO "logins" VALUES( +'https://accounts.google.com/ServiceLogin', /* origin_url */ +'https://accounts.google.com/ServiceLoginAuth', /* action_url */ +'Email', /* username_element */ +'theerikchen2', /* username_value */ +'Passwd', /* password_element */ +X'', /* password_value */ +'non-empty', /* submit_element */ +'https://accounts.google.com/', /* signon_realm */ +1, /* ssl_valid */ +1, /* preferred */ +13047423600000000, /* date_created */ +0, /* blacklisted_by_user */ +0, /* scheme */ +0, /* password_type */ +X'00000000', /* possible_usernames */ +1, /* times_used */ +X'18000000020000000000000000000000000000000000000000000000', /* form_data */ +0, /* date_synced */ +'', /* display_name */ +'', /* avatar_url */ +'', /* federation_url */ +0, /* skip_zero_click */ +0 /* generation_upload_status */ +); +CREATE INDEX logins_signon ON logins (signon_realm); +COMMIT;
diff --git a/components/translate/core/browser/translate_prefs.cc b/components/translate/core/browser/translate_prefs.cc index a957756..d31dab4 100644 --- a/components/translate/core/browser/translate_prefs.cc +++ b/components/translate/core/browser/translate_prefs.cc
@@ -389,9 +389,7 @@ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterListPref(kPrefTranslateBlockedLanguages, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterDictionaryPref( - kPrefTranslateLastDeniedTimeForLanguage, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kPrefTranslateLastDeniedTimeForLanguage); registry->RegisterDictionaryPref( kPrefTranslateTooOftenDeniedForLanguage, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
diff --git a/components/update_client.gypi b/components/update_client.gypi index d4870a8..c5759d06 100644 --- a/components/update_client.gypi +++ b/components/update_client.gypi
@@ -83,12 +83,12 @@ '..', ], 'sources': [ - 'update_client/test/test_configurator.cc', - 'update_client/test/test_configurator.h', - 'update_client/test/test_installer.cc', - 'update_client/test/test_installer.h', - 'update_client/test/url_request_post_interceptor.cc', - 'update_client/test/url_request_post_interceptor.h', + 'update_client/test_configurator.cc', + 'update_client/test_configurator.h', + 'update_client/test_installer.cc', + 'update_client/test_installer.h', + 'update_client/url_request_post_interceptor.cc', + 'update_client/url_request_post_interceptor.h', ], }, ],
diff --git a/components/update_client/BUILD.gn b/components/update_client/BUILD.gn index 17665721..d4e6125 100644 --- a/components/update_client/BUILD.gn +++ b/components/update_client/BUILD.gn
@@ -65,12 +65,12 @@ source_set("test_support") { testonly = true sources = [ - "test/test_configurator.cc", - "test/test_configurator.h", - "test/test_installer.cc", - "test/test_installer.h", - "test/url_request_post_interceptor.cc", - "test/url_request_post_interceptor.h", + "test_configurator.cc", + "test_configurator.h", + "test_installer.cc", + "test_installer.h", + "url_request_post_interceptor.cc", + "url_request_post_interceptor.h", ] deps = [ @@ -86,13 +86,13 @@ source_set("unit_tests") { testonly = true sources = [ - "test/component_patcher_unittest.cc", - "test/crx_downloader_unittest.cc", - "test/ping_manager_unittest.cc", - "test/request_sender_unittest.cc", - "test/update_checker_unittest.cc", - "test/update_client_unittest.cc", - "test/update_response_unittest.cc", + "component_patcher_unittest.cc", + "crx_downloader_unittest.cc", + "ping_manager_unittest.cc", + "request_sender_unittest.cc", + "update_checker_unittest.cc", + "update_client_unittest.cc", + "update_response_unittest.cc", ] deps = [
diff --git a/components/update_client/DEPS b/components/update_client/DEPS index 79e03498..7fa7165 100644 --- a/components/update_client/DEPS +++ b/components/update_client/DEPS
@@ -8,5 +8,13 @@ "+ui/base/win", "+third_party/libxml", "+third_party/zlib", - "+testing", ] + +# Tests can use things in content. +# TODO(sorin): refactor to eliminate the dependency on content by using +# message loops directly. +specific_include_rules = { + ".*unittest\.cc": [ + "+content", + ] +} \ No newline at end of file
diff --git a/components/update_client/component_patcher_unittest.cc b/components/update_client/component_patcher_unittest.cc new file mode 100644 index 0000000..c398abc --- /dev/null +++ b/components/update_client/component_patcher_unittest.cc
@@ -0,0 +1,200 @@ +// Copyright 2013 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/base_paths.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/macros.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/values.h" +#include "components/update_client/component_patcher.h" +#include "components/update_client/component_patcher_operation.h" +#include "components/update_client/component_patcher_unittest.h" +#include "components/update_client/test_installer.h" +#include "courgette/courgette.h" +#include "courgette/third_party/bsdiff.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class TestCallback { + public: + TestCallback(); + virtual ~TestCallback() {} + void Set(update_client::ComponentUnpacker::Error error, int extra_code); + + int error_; + int extra_code_; + bool called_; + + private: + DISALLOW_COPY_AND_ASSIGN(TestCallback); +}; + +TestCallback::TestCallback() : error_(-1), extra_code_(-1), called_(false) { +} + +void TestCallback::Set(update_client::ComponentUnpacker::Error error, + int extra_code) { + error_ = error; + extra_code_ = extra_code; + called_ = true; +} + +} // namespace + +namespace update_client { + +namespace { + +base::FilePath test_file(const char* file) { + base::FilePath path; + PathService::Get(base::DIR_SOURCE_ROOT, &path); + return path.AppendASCII("components") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("update_client") + .AppendASCII(file); +} + +} // namespace + +ComponentPatcherOperationTest::ComponentPatcherOperationTest() { + EXPECT_TRUE(unpack_dir_.CreateUniqueTempDir()); + EXPECT_TRUE(input_dir_.CreateUniqueTempDir()); + EXPECT_TRUE(installed_dir_.CreateUniqueTempDir()); + installer_ = new ReadOnlyTestInstaller(installed_dir_.path()); + task_runner_ = base::MessageLoop::current()->task_runner(); +} + +ComponentPatcherOperationTest::~ComponentPatcherOperationTest() { +} + +// Verify that a 'create' delta update operation works correctly. +TEST_F(ComponentPatcherOperationTest, CheckCreateOperation) { + EXPECT_TRUE(base::CopyFile( + test_file("binary_output.bin"), + input_dir_.path().Append(FILE_PATH_LITERAL("binary_output.bin")))); + + scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); + command_args->SetString("output", "output.bin"); + command_args->SetString("sha256", binary_output_hash); + command_args->SetString("op", "create"); + command_args->SetString("patch", "binary_output.bin"); + + TestCallback callback; + scoped_refptr<DeltaUpdateOp> op = new DeltaUpdateOpCreate(); + op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), NULL, + base::Bind(&TestCallback::Set, base::Unretained(&callback)), + task_runner_); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(true, callback.called_); + EXPECT_EQ(ComponentUnpacker::kNone, callback.error_); + EXPECT_EQ(0, callback.extra_code_); + EXPECT_TRUE(base::ContentsEqual( + unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), + test_file("binary_output.bin"))); +} + +// Verify that a 'copy' delta update operation works correctly. +TEST_F(ComponentPatcherOperationTest, CheckCopyOperation) { + EXPECT_TRUE(base::CopyFile( + test_file("binary_output.bin"), + installed_dir_.path().Append(FILE_PATH_LITERAL("binary_output.bin")))); + + scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); + command_args->SetString("output", "output.bin"); + command_args->SetString("sha256", binary_output_hash); + command_args->SetString("op", "copy"); + command_args->SetString("input", "binary_output.bin"); + + TestCallback callback; + scoped_refptr<DeltaUpdateOp> op = new DeltaUpdateOpCopy(); + op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), + installer_.get(), + base::Bind(&TestCallback::Set, base::Unretained(&callback)), + task_runner_); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(true, callback.called_); + EXPECT_EQ(ComponentUnpacker::kNone, callback.error_); + EXPECT_EQ(0, callback.extra_code_); + EXPECT_TRUE(base::ContentsEqual( + unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), + test_file("binary_output.bin"))); +} + +// Verify that a 'courgette' delta update operation works correctly. +TEST_F(ComponentPatcherOperationTest, CheckCourgetteOperation) { + EXPECT_TRUE(base::CopyFile( + test_file("binary_input.bin"), + installed_dir_.path().Append(FILE_PATH_LITERAL("binary_input.bin")))); + EXPECT_TRUE(base::CopyFile(test_file("binary_courgette_patch.bin"), + input_dir_.path().Append(FILE_PATH_LITERAL( + "binary_courgette_patch.bin")))); + + scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); + command_args->SetString("output", "output.bin"); + command_args->SetString("sha256", binary_output_hash); + command_args->SetString("op", "courgette"); + command_args->SetString("input", "binary_input.bin"); + command_args->SetString("patch", "binary_courgette_patch.bin"); + + TestCallback callback; + scoped_refptr<DeltaUpdateOp> op = + CreateDeltaUpdateOp("courgette", NULL /* out_of_process_patcher */); + op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), + installer_.get(), + base::Bind(&TestCallback::Set, base::Unretained(&callback)), + task_runner_); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(true, callback.called_); + EXPECT_EQ(ComponentUnpacker::kNone, callback.error_); + EXPECT_EQ(0, callback.extra_code_); + EXPECT_TRUE(base::ContentsEqual( + unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), + test_file("binary_output.bin"))); +} + +// Verify that a 'bsdiff' delta update operation works correctly. +TEST_F(ComponentPatcherOperationTest, CheckBsdiffOperation) { + EXPECT_TRUE(base::CopyFile( + test_file("binary_input.bin"), + installed_dir_.path().Append(FILE_PATH_LITERAL("binary_input.bin")))); + EXPECT_TRUE(base::CopyFile( + test_file("binary_bsdiff_patch.bin"), + input_dir_.path().Append(FILE_PATH_LITERAL("binary_bsdiff_patch.bin")))); + + scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); + command_args->SetString("output", "output.bin"); + command_args->SetString("sha256", binary_output_hash); + command_args->SetString("op", "courgette"); + command_args->SetString("input", "binary_input.bin"); + command_args->SetString("patch", "binary_bsdiff_patch.bin"); + + TestCallback callback; + scoped_refptr<DeltaUpdateOp> op = + CreateDeltaUpdateOp("bsdiff", NULL /* out_of_process_patcher */); + op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), + installer_.get(), + base::Bind(&TestCallback::Set, base::Unretained(&callback)), + task_runner_); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(true, callback.called_); + EXPECT_EQ(ComponentUnpacker::kNone, callback.error_); + EXPECT_EQ(0, callback.extra_code_); + EXPECT_TRUE(base::ContentsEqual( + unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), + test_file("binary_output.bin"))); +} + +} // namespace update_client
diff --git a/components/update_client/component_patcher_unittest.h b/components/update_client/component_patcher_unittest.h new file mode 100644 index 0000000..8b3a797 --- /dev/null +++ b/components/update_client/component_patcher_unittest.h
@@ -0,0 +1,42 @@ +// Copyright 2013 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_UPDATE_CLIENT_COMPONENT_PATCHER_UNITTEST_H_ +#define COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_UNITTEST_H_ + +#include "base/files/file_path.h" +#include "base/files/scoped_temp_dir.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "courgette/courgette.h" +#include "courgette/third_party/bsdiff.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace update_client { + +class MockComponentPatcher; +class ReadOnlyTestInstaller; + +const char binary_output_hash[] = + "599aba6d15a7da390621ef1bacb66601ed6aed04dadc1f9b445dcfe31296142a"; + +class ComponentPatcherOperationTest : public testing::Test { + public: + ComponentPatcherOperationTest(); + ~ComponentPatcherOperationTest() override; + + protected: + base::ScopedTempDir input_dir_; + base::ScopedTempDir installed_dir_; + base::ScopedTempDir unpack_dir_; + scoped_refptr<ReadOnlyTestInstaller> installer_; + scoped_refptr<base::SequencedTaskRunner> task_runner_; + + private: + base::MessageLoopForIO loop_; +}; + +} // namespace update_client + +#endif // COMPONENTS_UPDATE_CLIENT_COMPONENT_PATCHER_UNITTEST_H_
diff --git a/components/update_client/test/crx_downloader_unittest.cc b/components/update_client/crx_downloader_unittest.cc similarity index 100% rename from components/update_client/test/crx_downloader_unittest.cc rename to components/update_client/crx_downloader_unittest.cc
diff --git a/components/update_client/ping_manager_unittest.cc b/components/update_client/ping_manager_unittest.cc new file mode 100644 index 0000000..cfd37e1 --- /dev/null +++ b/components/update_client/ping_manager_unittest.cc
@@ -0,0 +1,178 @@ +// Copyright 2013 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/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/version.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/ping_manager.h" +#include "components/update_client/test_configurator.h" +#include "components/update_client/url_request_post_interceptor.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +using std::string; + +namespace update_client { + +class ComponentUpdaterPingManagerTest : public testing::Test { + public: + ComponentUpdaterPingManagerTest(); + ~ComponentUpdaterPingManagerTest() override {} + + void RunThreadsUntilIdle(); + + // Overrides from testing::Test. + void SetUp() override; + void TearDown() override; + + protected: + scoped_refptr<TestConfigurator> config_; + scoped_ptr<PingManager> ping_manager_; + + private: + base::MessageLoopForIO loop_; +}; + +ComponentUpdaterPingManagerTest::ComponentUpdaterPingManagerTest() { +} + +void ComponentUpdaterPingManagerTest::SetUp() { + config_ = new TestConfigurator(base::MessageLoopProxy::current(), + base::MessageLoopProxy::current()); + ping_manager_.reset(new PingManager(*config_)); +} + +void ComponentUpdaterPingManagerTest::TearDown() { + ping_manager_.reset(); + config_ = nullptr; +} + +void ComponentUpdaterPingManagerTest::RunThreadsUntilIdle() { + base::RunLoop().RunUntilIdle(); +} + +// Test is flaky: http://crbug.com/349547 +TEST_F(ComponentUpdaterPingManagerTest, DISABLED_PingManagerTest) { + scoped_ptr<InterceptorFactory> interceptor_factory( + new InterceptorFactory(base::MessageLoopProxy::current())); + URLRequestPostInterceptor* interceptor = + interceptor_factory->CreateInterceptor(); + EXPECT_TRUE(interceptor); + + // Test eventresult="1" is sent for successful updates. + CrxUpdateItem item; + item.id = "abc"; + item.state = CrxUpdateItem::State::kUpdated; + item.previous_version = base::Version("1.0"); + item.next_version = base::Version("2.0"); + + ping_manager_->OnUpdateComplete(&item); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); + EXPECT_NE(string::npos, + interceptor->GetRequests()[0].find( + "<app appid=\"abc\" version=\"1.0\" nextversion=\"2.0\">" + "<event eventtype=\"3\" eventresult=\"1\"/></app>")) + << interceptor->GetRequestsAsString(); + interceptor->Reset(); + + // Test eventresult="0" is sent for failed updates. + item = CrxUpdateItem(); + item.id = "abc"; + item.state = CrxUpdateItem::State::kNoUpdate; + item.previous_version = base::Version("1.0"); + item.next_version = base::Version("2.0"); + + ping_manager_->OnUpdateComplete(&item); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); + EXPECT_NE(string::npos, + interceptor->GetRequests()[0].find( + "<app appid=\"abc\" version=\"1.0\" nextversion=\"2.0\">" + "<event eventtype=\"3\" eventresult=\"0\"/></app>")) + << interceptor->GetRequestsAsString(); + interceptor->Reset(); + + // Test the error values and the fingerprints. + item = CrxUpdateItem(); + item.id = "abc"; + item.state = CrxUpdateItem::State::kNoUpdate; + item.previous_version = base::Version("1.0"); + item.next_version = base::Version("2.0"); + item.previous_fp = "prev fp"; + item.next_fp = "next fp"; + item.error_category = 1; + item.error_code = 2; + item.extra_code1 = -1; + item.diff_error_category = 10; + item.diff_error_code = 20; + item.diff_extra_code1 = -10; + item.diff_update_failed = true; + item.crx_diffurls.push_back(GURL("http://host/path")); + + ping_manager_->OnUpdateComplete(&item); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); + EXPECT_NE(string::npos, + interceptor->GetRequests()[0].find( + "<app appid=\"abc\" version=\"1.0\" nextversion=\"2.0\">" + "<event eventtype=\"3\" eventresult=\"0\" errorcat=\"1\" " + "errorcode=\"2\" extracode1=\"-1\" diffresult=\"0\" " + "differrorcat=\"10\" " + "differrorcode=\"20\" diffextracode1=\"-10\" " + "previousfp=\"prev fp\" nextfp=\"next fp\"/></app>")) + << interceptor->GetRequestsAsString(); + interceptor->Reset(); + + // Test the download metrics. + item = CrxUpdateItem(); + item.id = "abc"; + item.state = CrxUpdateItem::State::kUpdated; + item.previous_version = base::Version("1.0"); + item.next_version = base::Version("2.0"); + + CrxDownloader::DownloadMetrics download_metrics; + download_metrics.url = GURL("http://host1/path1"); + download_metrics.downloader = CrxDownloader::DownloadMetrics::kUrlFetcher; + download_metrics.error = -1; + download_metrics.downloaded_bytes = 123; + download_metrics.total_bytes = 456; + download_metrics.download_time_ms = 987; + item.download_metrics.push_back(download_metrics); + + download_metrics = CrxDownloader::DownloadMetrics(); + download_metrics.url = GURL("http://host2/path2"); + download_metrics.downloader = CrxDownloader::DownloadMetrics::kBits; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 1230; + download_metrics.total_bytes = 4560; + download_metrics.download_time_ms = 9870; + item.download_metrics.push_back(download_metrics); + + ping_manager_->OnUpdateComplete(&item); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); + EXPECT_NE( + string::npos, + interceptor->GetRequests()[0].find( + "<app appid=\"abc\" version=\"1.0\" nextversion=\"2.0\">" + "<event eventtype=\"3\" eventresult=\"1\"/>" + "<event eventtype=\"14\" eventresult=\"0\" downloader=\"direct\" " + "errorcode=\"-1\" url=\"http://host1/path1\" downloaded=\"123\" " + "total=\"456\" download_time_ms=\"987\"/>" + "<event eventtype=\"14\" eventresult=\"1\" downloader=\"bits\" " + "url=\"http://host2/path2\" downloaded=\"1230\" total=\"4560\" " + "download_time_ms=\"9870\"/></app>")) + << interceptor->GetRequestsAsString(); + interceptor->Reset(); +} + +} // namespace update_client
diff --git a/components/update_client/request_sender_unittest.cc b/components/update_client/request_sender_unittest.cc new file mode 100644 index 0000000..4c8e1db --- /dev/null +++ b/components/update_client/request_sender_unittest.cc
@@ -0,0 +1,206 @@ +// 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 "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "components/update_client/request_sender.h" +#include "components/update_client/test_configurator.h" +#include "components/update_client/url_request_post_interceptor.h" +#include "net/url_request/url_fetcher.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace update_client { + +namespace { + +const char kUrl1[] = "https://localhost2/path1"; +const char kUrl2[] = "https://localhost2/path2"; +const char kUrlPath1[] = "path1"; +const char kUrlPath2[] = "path2"; + +} // namespace + +class RequestSenderTest : public testing::Test { + public: + RequestSenderTest(); + ~RequestSenderTest() override; + + // Overrides from testing::Test. + void SetUp() override; + void TearDown() override; + + void RequestSenderComplete(const net::URLFetcher* source); + + protected: + void Quit(); + void RunThreads(); + void RunThreadsUntilIdle(); + + scoped_refptr<TestConfigurator> config_; + scoped_ptr<RequestSender> request_sender_; + scoped_ptr<InterceptorFactory> interceptor_factory_; + + URLRequestPostInterceptor* post_interceptor_1; // Owned by the factory. + URLRequestPostInterceptor* post_interceptor_2; // Owned by the factory. + + const net::URLFetcher* url_fetcher_source_; + + private: + base::MessageLoopForIO loop_; + base::Closure quit_closure_; + + DISALLOW_COPY_AND_ASSIGN(RequestSenderTest); +}; + +RequestSenderTest::RequestSenderTest() + : post_interceptor_1(NULL), + post_interceptor_2(NULL), + url_fetcher_source_(NULL) { +} + +RequestSenderTest::~RequestSenderTest() { +} + +void RequestSenderTest::SetUp() { + config_ = new TestConfigurator(base::MessageLoopProxy::current(), + base::MessageLoopProxy::current()); + interceptor_factory_.reset( + new InterceptorFactory(base::MessageLoopProxy::current())); + post_interceptor_1 = + interceptor_factory_->CreateInterceptorForPath(kUrlPath1); + post_interceptor_2 = + interceptor_factory_->CreateInterceptorForPath(kUrlPath2); + EXPECT_TRUE(post_interceptor_1); + EXPECT_TRUE(post_interceptor_2); + + request_sender_.reset(); +} + +void RequestSenderTest::TearDown() { + request_sender_.reset(); + + post_interceptor_1 = NULL; + post_interceptor_2 = NULL; + + interceptor_factory_.reset(); + + config_ = nullptr; + + RunThreadsUntilIdle(); +} + +void RequestSenderTest::RunThreads() { + base::RunLoop runloop; + quit_closure_ = runloop.QuitClosure(); + runloop.Run(); + + // Since some tests need to drain currently enqueued tasks such as network + // intercepts on the IO thread, run the threads until they are + // idle. The component updater service won't loop again until the loop count + // is set and the service is started. + RunThreadsUntilIdle(); +} + +void RequestSenderTest::RunThreadsUntilIdle() { + base::RunLoop().RunUntilIdle(); +} + +void RequestSenderTest::Quit() { + if (!quit_closure_.is_null()) + quit_closure_.Run(); +} + +void RequestSenderTest::RequestSenderComplete(const net::URLFetcher* source) { + url_fetcher_source_ = source; + Quit(); +} + +// Tests that when a request to the first url succeeds, the subsequent urls are +// not tried. +TEST_F(RequestSenderTest, RequestSendSuccess) { + EXPECT_TRUE(post_interceptor_1->ExpectRequest(new PartialMatch("test"))); + + std::vector<GURL> urls; + urls.push_back(GURL(kUrl1)); + urls.push_back(GURL(kUrl2)); + request_sender_.reset(new RequestSender(*config_)); + request_sender_->Send("test", urls, + base::Bind(&RequestSenderTest::RequestSenderComplete, + base::Unretained(this))); + RunThreads(); + + EXPECT_EQ(1, post_interceptor_1->GetHitCount()) + << post_interceptor_1->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_1->GetCount()) + << post_interceptor_1->GetRequestsAsString(); + + EXPECT_STREQ("test", post_interceptor_1->GetRequests()[0].c_str()); + EXPECT_EQ(GURL(kUrl1), url_fetcher_source_->GetOriginalURL()); + EXPECT_EQ(200, url_fetcher_source_->GetResponseCode()); +} + +// Tests that the request succeeds using the second url after the first url +// has failed. +TEST_F(RequestSenderTest, RequestSendSuccessWithFallback) { + EXPECT_TRUE(post_interceptor_1->ExpectRequest(new PartialMatch("test"), 403)); + EXPECT_TRUE(post_interceptor_2->ExpectRequest(new PartialMatch("test"))); + + std::vector<GURL> urls; + urls.push_back(GURL(kUrl1)); + urls.push_back(GURL(kUrl2)); + request_sender_.reset(new RequestSender(*config_)); + request_sender_->Send("test", urls, + base::Bind(&RequestSenderTest::RequestSenderComplete, + base::Unretained(this))); + RunThreads(); + + EXPECT_EQ(1, post_interceptor_1->GetHitCount()) + << post_interceptor_1->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_1->GetCount()) + << post_interceptor_1->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_2->GetHitCount()) + << post_interceptor_2->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_2->GetCount()) + << post_interceptor_2->GetRequestsAsString(); + + EXPECT_STREQ("test", post_interceptor_1->GetRequests()[0].c_str()); + EXPECT_STREQ("test", post_interceptor_2->GetRequests()[0].c_str()); + EXPECT_EQ(GURL(kUrl2), url_fetcher_source_->GetOriginalURL()); + EXPECT_EQ(200, url_fetcher_source_->GetResponseCode()); +} + +// Tests that the request fails when both urls have failed. +TEST_F(RequestSenderTest, RequestSendFailed) { + EXPECT_TRUE(post_interceptor_1->ExpectRequest(new PartialMatch("test"), 403)); + EXPECT_TRUE(post_interceptor_2->ExpectRequest(new PartialMatch("test"), 403)); + + std::vector<GURL> urls; + urls.push_back(GURL(kUrl1)); + urls.push_back(GURL(kUrl2)); + request_sender_.reset(new RequestSender(*config_)); + request_sender_->Send("test", urls, + base::Bind(&RequestSenderTest::RequestSenderComplete, + base::Unretained(this))); + RunThreads(); + + EXPECT_EQ(1, post_interceptor_1->GetHitCount()) + << post_interceptor_1->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_1->GetCount()) + << post_interceptor_1->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_2->GetHitCount()) + << post_interceptor_2->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_2->GetCount()) + << post_interceptor_2->GetRequestsAsString(); + + EXPECT_STREQ("test", post_interceptor_1->GetRequests()[0].c_str()); + EXPECT_STREQ("test", post_interceptor_2->GetRequests()[0].c_str()); + EXPECT_EQ(GURL(kUrl2), url_fetcher_source_->GetOriginalURL()); + EXPECT_EQ(403, url_fetcher_source_->GetResponseCode()); +} + +} // namespace update_client
diff --git a/components/update_client/test/DEPS b/components/update_client/test/DEPS deleted file mode 100644 index d0c36c4..0000000 --- a/components/update_client/test/DEPS +++ /dev/null
@@ -1,5 +0,0 @@ -include_rules = [ - "+content", - "+courgette", - "+net", -]
diff --git a/components/update_client/test/component_patcher_unittest.cc b/components/update_client/test/component_patcher_unittest.cc deleted file mode 100644 index 4f5e143..0000000 --- a/components/update_client/test/component_patcher_unittest.cc +++ /dev/null
@@ -1,200 +0,0 @@ -// Copyright 2013 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/base_paths.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" -#include "base/macros.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/values.h" -#include "components/update_client/component_patcher.h" -#include "components/update_client/component_patcher_operation.h" -#include "components/update_client/test/component_patcher_unittest.h" -#include "components/update_client/test/test_installer.h" -#include "courgette/courgette.h" -#include "courgette/third_party/bsdiff.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -class TestCallback { - public: - TestCallback(); - virtual ~TestCallback() {} - void Set(update_client::ComponentUnpacker::Error error, int extra_code); - - int error_; - int extra_code_; - bool called_; - - private: - DISALLOW_COPY_AND_ASSIGN(TestCallback); -}; - -TestCallback::TestCallback() : error_(-1), extra_code_(-1), called_(false) { -} - -void TestCallback::Set(update_client::ComponentUnpacker::Error error, - int extra_code) { - error_ = error; - extra_code_ = extra_code; - called_ = true; -} - -} // namespace - -namespace update_client { - -namespace { - -base::FilePath test_file(const char* file) { - base::FilePath path; - PathService::Get(base::DIR_SOURCE_ROOT, &path); - return path.AppendASCII("components") - .AppendASCII("test") - .AppendASCII("data") - .AppendASCII("update_client") - .AppendASCII(file); -} - -} // namespace - -ComponentPatcherOperationTest::ComponentPatcherOperationTest() { - EXPECT_TRUE(unpack_dir_.CreateUniqueTempDir()); - EXPECT_TRUE(input_dir_.CreateUniqueTempDir()); - EXPECT_TRUE(installed_dir_.CreateUniqueTempDir()); - installer_ = new ReadOnlyTestInstaller(installed_dir_.path()); - task_runner_ = base::MessageLoop::current()->task_runner(); -} - -ComponentPatcherOperationTest::~ComponentPatcherOperationTest() { -} - -// Verify that a 'create' delta update operation works correctly. -TEST_F(ComponentPatcherOperationTest, CheckCreateOperation) { - EXPECT_TRUE(base::CopyFile( - test_file("binary_output.bin"), - input_dir_.path().Append(FILE_PATH_LITERAL("binary_output.bin")))); - - scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); - command_args->SetString("output", "output.bin"); - command_args->SetString("sha256", binary_output_hash); - command_args->SetString("op", "create"); - command_args->SetString("patch", "binary_output.bin"); - - TestCallback callback; - scoped_refptr<DeltaUpdateOp> op = new DeltaUpdateOpCreate(); - op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), NULL, - base::Bind(&TestCallback::Set, base::Unretained(&callback)), - task_runner_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(true, callback.called_); - EXPECT_EQ(ComponentUnpacker::kNone, callback.error_); - EXPECT_EQ(0, callback.extra_code_); - EXPECT_TRUE(base::ContentsEqual( - unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), - test_file("binary_output.bin"))); -} - -// Verify that a 'copy' delta update operation works correctly. -TEST_F(ComponentPatcherOperationTest, CheckCopyOperation) { - EXPECT_TRUE(base::CopyFile( - test_file("binary_output.bin"), - installed_dir_.path().Append(FILE_PATH_LITERAL("binary_output.bin")))); - - scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); - command_args->SetString("output", "output.bin"); - command_args->SetString("sha256", binary_output_hash); - command_args->SetString("op", "copy"); - command_args->SetString("input", "binary_output.bin"); - - TestCallback callback; - scoped_refptr<DeltaUpdateOp> op = new DeltaUpdateOpCopy(); - op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), - installer_.get(), - base::Bind(&TestCallback::Set, base::Unretained(&callback)), - task_runner_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(true, callback.called_); - EXPECT_EQ(ComponentUnpacker::kNone, callback.error_); - EXPECT_EQ(0, callback.extra_code_); - EXPECT_TRUE(base::ContentsEqual( - unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), - test_file("binary_output.bin"))); -} - -// Verify that a 'courgette' delta update operation works correctly. -TEST_F(ComponentPatcherOperationTest, CheckCourgetteOperation) { - EXPECT_TRUE(base::CopyFile( - test_file("binary_input.bin"), - installed_dir_.path().Append(FILE_PATH_LITERAL("binary_input.bin")))); - EXPECT_TRUE(base::CopyFile(test_file("binary_courgette_patch.bin"), - input_dir_.path().Append(FILE_PATH_LITERAL( - "binary_courgette_patch.bin")))); - - scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); - command_args->SetString("output", "output.bin"); - command_args->SetString("sha256", binary_output_hash); - command_args->SetString("op", "courgette"); - command_args->SetString("input", "binary_input.bin"); - command_args->SetString("patch", "binary_courgette_patch.bin"); - - TestCallback callback; - scoped_refptr<DeltaUpdateOp> op = - CreateDeltaUpdateOp("courgette", NULL /* out_of_process_patcher */); - op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), - installer_.get(), - base::Bind(&TestCallback::Set, base::Unretained(&callback)), - task_runner_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(true, callback.called_); - EXPECT_EQ(ComponentUnpacker::kNone, callback.error_); - EXPECT_EQ(0, callback.extra_code_); - EXPECT_TRUE(base::ContentsEqual( - unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), - test_file("binary_output.bin"))); -} - -// Verify that a 'bsdiff' delta update operation works correctly. -TEST_F(ComponentPatcherOperationTest, CheckBsdiffOperation) { - EXPECT_TRUE(base::CopyFile( - test_file("binary_input.bin"), - installed_dir_.path().Append(FILE_PATH_LITERAL("binary_input.bin")))); - EXPECT_TRUE(base::CopyFile( - test_file("binary_bsdiff_patch.bin"), - input_dir_.path().Append(FILE_PATH_LITERAL("binary_bsdiff_patch.bin")))); - - scoped_ptr<base::DictionaryValue> command_args(new base::DictionaryValue()); - command_args->SetString("output", "output.bin"); - command_args->SetString("sha256", binary_output_hash); - command_args->SetString("op", "courgette"); - command_args->SetString("input", "binary_input.bin"); - command_args->SetString("patch", "binary_bsdiff_patch.bin"); - - TestCallback callback; - scoped_refptr<DeltaUpdateOp> op = - CreateDeltaUpdateOp("bsdiff", NULL /* out_of_process_patcher */); - op->Run(command_args.get(), input_dir_.path(), unpack_dir_.path(), - installer_.get(), - base::Bind(&TestCallback::Set, base::Unretained(&callback)), - task_runner_); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(true, callback.called_); - EXPECT_EQ(ComponentUnpacker::kNone, callback.error_); - EXPECT_EQ(0, callback.extra_code_); - EXPECT_TRUE(base::ContentsEqual( - unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")), - test_file("binary_output.bin"))); -} - -} // namespace update_client
diff --git a/components/update_client/test/component_patcher_unittest.h b/components/update_client/test/component_patcher_unittest.h deleted file mode 100644 index 2fcd5f5..0000000 --- a/components/update_client/test/component_patcher_unittest.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2013 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_UPDATE_CLIENT_TEST_COMPONENT_PATCHER_UNITTEST_H_ -#define COMPONENTS_UPDATE_CLIENT_TEST_COMPONENT_PATCHER_UNITTEST_H_ - -#include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "courgette/courgette.h" -#include "courgette/third_party/bsdiff.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace update_client { - -class MockComponentPatcher; -class ReadOnlyTestInstaller; - -const char binary_output_hash[] = - "599aba6d15a7da390621ef1bacb66601ed6aed04dadc1f9b445dcfe31296142a"; - -class ComponentPatcherOperationTest : public testing::Test { - public: - ComponentPatcherOperationTest(); - ~ComponentPatcherOperationTest() override; - - protected: - base::ScopedTempDir input_dir_; - base::ScopedTempDir installed_dir_; - base::ScopedTempDir unpack_dir_; - scoped_refptr<ReadOnlyTestInstaller> installer_; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - - private: - base::MessageLoopForIO loop_; -}; - -} // namespace update_client - -#endif // COMPONENTS_UPDATE_CLIENT_TEST_COMPONENT_PATCHER_UNITTEST_H_
diff --git a/components/update_client/test/ping_manager_unittest.cc b/components/update_client/test/ping_manager_unittest.cc deleted file mode 100644 index 23308ac..0000000 --- a/components/update_client/test/ping_manager_unittest.cc +++ /dev/null
@@ -1,178 +0,0 @@ -// Copyright 2013 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/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/version.h" -#include "components/update_client/crx_update_item.h" -#include "components/update_client/ping_manager.h" -#include "components/update_client/test/test_configurator.h" -#include "components/update_client/test/url_request_post_interceptor.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -using std::string; - -namespace update_client { - -class ComponentUpdaterPingManagerTest : public testing::Test { - public: - ComponentUpdaterPingManagerTest(); - ~ComponentUpdaterPingManagerTest() override {} - - void RunThreadsUntilIdle(); - - // Overrides from testing::Test. - void SetUp() override; - void TearDown() override; - - protected: - scoped_refptr<TestConfigurator> config_; - scoped_ptr<PingManager> ping_manager_; - - private: - base::MessageLoopForIO loop_; -}; - -ComponentUpdaterPingManagerTest::ComponentUpdaterPingManagerTest() { -} - -void ComponentUpdaterPingManagerTest::SetUp() { - config_ = new TestConfigurator(base::MessageLoopProxy::current(), - base::MessageLoopProxy::current()); - ping_manager_.reset(new PingManager(*config_)); -} - -void ComponentUpdaterPingManagerTest::TearDown() { - ping_manager_.reset(); - config_ = nullptr; -} - -void ComponentUpdaterPingManagerTest::RunThreadsUntilIdle() { - base::RunLoop().RunUntilIdle(); -} - -// Test is flaky: http://crbug.com/349547 -TEST_F(ComponentUpdaterPingManagerTest, DISABLED_PingManagerTest) { - scoped_ptr<InterceptorFactory> interceptor_factory( - new InterceptorFactory(base::MessageLoopProxy::current())); - URLRequestPostInterceptor* interceptor = - interceptor_factory->CreateInterceptor(); - EXPECT_TRUE(interceptor); - - // Test eventresult="1" is sent for successful updates. - CrxUpdateItem item; - item.id = "abc"; - item.state = CrxUpdateItem::State::kUpdated; - item.previous_version = base::Version("1.0"); - item.next_version = base::Version("2.0"); - - ping_manager_->OnUpdateComplete(&item); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); - EXPECT_NE(string::npos, - interceptor->GetRequests()[0].find( - "<app appid=\"abc\" version=\"1.0\" nextversion=\"2.0\">" - "<event eventtype=\"3\" eventresult=\"1\"/></app>")) - << interceptor->GetRequestsAsString(); - interceptor->Reset(); - - // Test eventresult="0" is sent for failed updates. - item = CrxUpdateItem(); - item.id = "abc"; - item.state = CrxUpdateItem::State::kNoUpdate; - item.previous_version = base::Version("1.0"); - item.next_version = base::Version("2.0"); - - ping_manager_->OnUpdateComplete(&item); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); - EXPECT_NE(string::npos, - interceptor->GetRequests()[0].find( - "<app appid=\"abc\" version=\"1.0\" nextversion=\"2.0\">" - "<event eventtype=\"3\" eventresult=\"0\"/></app>")) - << interceptor->GetRequestsAsString(); - interceptor->Reset(); - - // Test the error values and the fingerprints. - item = CrxUpdateItem(); - item.id = "abc"; - item.state = CrxUpdateItem::State::kNoUpdate; - item.previous_version = base::Version("1.0"); - item.next_version = base::Version("2.0"); - item.previous_fp = "prev fp"; - item.next_fp = "next fp"; - item.error_category = 1; - item.error_code = 2; - item.extra_code1 = -1; - item.diff_error_category = 10; - item.diff_error_code = 20; - item.diff_extra_code1 = -10; - item.diff_update_failed = true; - item.crx_diffurls.push_back(GURL("http://host/path")); - - ping_manager_->OnUpdateComplete(&item); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); - EXPECT_NE(string::npos, - interceptor->GetRequests()[0].find( - "<app appid=\"abc\" version=\"1.0\" nextversion=\"2.0\">" - "<event eventtype=\"3\" eventresult=\"0\" errorcat=\"1\" " - "errorcode=\"2\" extracode1=\"-1\" diffresult=\"0\" " - "differrorcat=\"10\" " - "differrorcode=\"20\" diffextracode1=\"-10\" " - "previousfp=\"prev fp\" nextfp=\"next fp\"/></app>")) - << interceptor->GetRequestsAsString(); - interceptor->Reset(); - - // Test the download metrics. - item = CrxUpdateItem(); - item.id = "abc"; - item.state = CrxUpdateItem::State::kUpdated; - item.previous_version = base::Version("1.0"); - item.next_version = base::Version("2.0"); - - CrxDownloader::DownloadMetrics download_metrics; - download_metrics.url = GURL("http://host1/path1"); - download_metrics.downloader = CrxDownloader::DownloadMetrics::kUrlFetcher; - download_metrics.error = -1; - download_metrics.downloaded_bytes = 123; - download_metrics.total_bytes = 456; - download_metrics.download_time_ms = 987; - item.download_metrics.push_back(download_metrics); - - download_metrics = CrxDownloader::DownloadMetrics(); - download_metrics.url = GURL("http://host2/path2"); - download_metrics.downloader = CrxDownloader::DownloadMetrics::kBits; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 1230; - download_metrics.total_bytes = 4560; - download_metrics.download_time_ms = 9870; - item.download_metrics.push_back(download_metrics); - - ping_manager_->OnUpdateComplete(&item); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(1, interceptor->GetCount()) << interceptor->GetRequestsAsString(); - EXPECT_NE( - string::npos, - interceptor->GetRequests()[0].find( - "<app appid=\"abc\" version=\"1.0\" nextversion=\"2.0\">" - "<event eventtype=\"3\" eventresult=\"1\"/>" - "<event eventtype=\"14\" eventresult=\"0\" downloader=\"direct\" " - "errorcode=\"-1\" url=\"http://host1/path1\" downloaded=\"123\" " - "total=\"456\" download_time_ms=\"987\"/>" - "<event eventtype=\"14\" eventresult=\"1\" downloader=\"bits\" " - "url=\"http://host2/path2\" downloaded=\"1230\" total=\"4560\" " - "download_time_ms=\"9870\"/></app>")) - << interceptor->GetRequestsAsString(); - interceptor->Reset(); -} - -} // namespace update_client
diff --git a/components/update_client/test/request_sender_unittest.cc b/components/update_client/test/request_sender_unittest.cc deleted file mode 100644 index 35d4487..0000000 --- a/components/update_client/test/request_sender_unittest.cc +++ /dev/null
@@ -1,206 +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 "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "components/update_client/request_sender.h" -#include "components/update_client/test/test_configurator.h" -#include "components/update_client/test/url_request_post_interceptor.h" -#include "net/url_request/url_fetcher.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace update_client { - -namespace { - -const char kUrl1[] = "https://localhost2/path1"; -const char kUrl2[] = "https://localhost2/path2"; -const char kUrlPath1[] = "path1"; -const char kUrlPath2[] = "path2"; - -} // namespace - -class RequestSenderTest : public testing::Test { - public: - RequestSenderTest(); - ~RequestSenderTest() override; - - // Overrides from testing::Test. - void SetUp() override; - void TearDown() override; - - void RequestSenderComplete(const net::URLFetcher* source); - - protected: - void Quit(); - void RunThreads(); - void RunThreadsUntilIdle(); - - scoped_refptr<TestConfigurator> config_; - scoped_ptr<RequestSender> request_sender_; - scoped_ptr<InterceptorFactory> interceptor_factory_; - - URLRequestPostInterceptor* post_interceptor_1; // Owned by the factory. - URLRequestPostInterceptor* post_interceptor_2; // Owned by the factory. - - const net::URLFetcher* url_fetcher_source_; - - private: - base::MessageLoopForIO loop_; - base::Closure quit_closure_; - - DISALLOW_COPY_AND_ASSIGN(RequestSenderTest); -}; - -RequestSenderTest::RequestSenderTest() - : post_interceptor_1(NULL), - post_interceptor_2(NULL), - url_fetcher_source_(NULL) { -} - -RequestSenderTest::~RequestSenderTest() { -} - -void RequestSenderTest::SetUp() { - config_ = new TestConfigurator(base::MessageLoopProxy::current(), - base::MessageLoopProxy::current()); - interceptor_factory_.reset( - new InterceptorFactory(base::MessageLoopProxy::current())); - post_interceptor_1 = - interceptor_factory_->CreateInterceptorForPath(kUrlPath1); - post_interceptor_2 = - interceptor_factory_->CreateInterceptorForPath(kUrlPath2); - EXPECT_TRUE(post_interceptor_1); - EXPECT_TRUE(post_interceptor_2); - - request_sender_.reset(); -} - -void RequestSenderTest::TearDown() { - request_sender_.reset(); - - post_interceptor_1 = NULL; - post_interceptor_2 = NULL; - - interceptor_factory_.reset(); - - config_ = nullptr; - - RunThreadsUntilIdle(); -} - -void RequestSenderTest::RunThreads() { - base::RunLoop runloop; - quit_closure_ = runloop.QuitClosure(); - runloop.Run(); - - // Since some tests need to drain currently enqueued tasks such as network - // intercepts on the IO thread, run the threads until they are - // idle. The component updater service won't loop again until the loop count - // is set and the service is started. - RunThreadsUntilIdle(); -} - -void RequestSenderTest::RunThreadsUntilIdle() { - base::RunLoop().RunUntilIdle(); -} - -void RequestSenderTest::Quit() { - if (!quit_closure_.is_null()) - quit_closure_.Run(); -} - -void RequestSenderTest::RequestSenderComplete(const net::URLFetcher* source) { - url_fetcher_source_ = source; - Quit(); -} - -// Tests that when a request to the first url succeeds, the subsequent urls are -// not tried. -TEST_F(RequestSenderTest, RequestSendSuccess) { - EXPECT_TRUE(post_interceptor_1->ExpectRequest(new PartialMatch("test"))); - - std::vector<GURL> urls; - urls.push_back(GURL(kUrl1)); - urls.push_back(GURL(kUrl2)); - request_sender_.reset(new RequestSender(*config_)); - request_sender_->Send("test", urls, - base::Bind(&RequestSenderTest::RequestSenderComplete, - base::Unretained(this))); - RunThreads(); - - EXPECT_EQ(1, post_interceptor_1->GetHitCount()) - << post_interceptor_1->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_1->GetCount()) - << post_interceptor_1->GetRequestsAsString(); - - EXPECT_STREQ("test", post_interceptor_1->GetRequests()[0].c_str()); - EXPECT_EQ(GURL(kUrl1), url_fetcher_source_->GetOriginalURL()); - EXPECT_EQ(200, url_fetcher_source_->GetResponseCode()); -} - -// Tests that the request succeeds using the second url after the first url -// has failed. -TEST_F(RequestSenderTest, RequestSendSuccessWithFallback) { - EXPECT_TRUE(post_interceptor_1->ExpectRequest(new PartialMatch("test"), 403)); - EXPECT_TRUE(post_interceptor_2->ExpectRequest(new PartialMatch("test"))); - - std::vector<GURL> urls; - urls.push_back(GURL(kUrl1)); - urls.push_back(GURL(kUrl2)); - request_sender_.reset(new RequestSender(*config_)); - request_sender_->Send("test", urls, - base::Bind(&RequestSenderTest::RequestSenderComplete, - base::Unretained(this))); - RunThreads(); - - EXPECT_EQ(1, post_interceptor_1->GetHitCount()) - << post_interceptor_1->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_1->GetCount()) - << post_interceptor_1->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_2->GetHitCount()) - << post_interceptor_2->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_2->GetCount()) - << post_interceptor_2->GetRequestsAsString(); - - EXPECT_STREQ("test", post_interceptor_1->GetRequests()[0].c_str()); - EXPECT_STREQ("test", post_interceptor_2->GetRequests()[0].c_str()); - EXPECT_EQ(GURL(kUrl2), url_fetcher_source_->GetOriginalURL()); - EXPECT_EQ(200, url_fetcher_source_->GetResponseCode()); -} - -// Tests that the request fails when both urls have failed. -TEST_F(RequestSenderTest, RequestSendFailed) { - EXPECT_TRUE(post_interceptor_1->ExpectRequest(new PartialMatch("test"), 403)); - EXPECT_TRUE(post_interceptor_2->ExpectRequest(new PartialMatch("test"), 403)); - - std::vector<GURL> urls; - urls.push_back(GURL(kUrl1)); - urls.push_back(GURL(kUrl2)); - request_sender_.reset(new RequestSender(*config_)); - request_sender_->Send("test", urls, - base::Bind(&RequestSenderTest::RequestSenderComplete, - base::Unretained(this))); - RunThreads(); - - EXPECT_EQ(1, post_interceptor_1->GetHitCount()) - << post_interceptor_1->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_1->GetCount()) - << post_interceptor_1->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_2->GetHitCount()) - << post_interceptor_2->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_2->GetCount()) - << post_interceptor_2->GetRequestsAsString(); - - EXPECT_STREQ("test", post_interceptor_1->GetRequests()[0].c_str()); - EXPECT_STREQ("test", post_interceptor_2->GetRequests()[0].c_str()); - EXPECT_EQ(GURL(kUrl2), url_fetcher_source_->GetOriginalURL()); - EXPECT_EQ(403, url_fetcher_source_->GetResponseCode()); -} - -} // namespace update_client
diff --git a/components/update_client/test/test_configurator.cc b/components/update_client/test/test_configurator.cc deleted file mode 100644 index 23eaeff..0000000 --- a/components/update_client/test/test_configurator.cc +++ /dev/null
@@ -1,158 +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/update_client/test/test_configurator.h" - -#include "base/run_loop.h" -#include "base/version.h" -#include "components/update_client/component_patcher_operation.h" -#include "url/gurl.h" - -namespace update_client { - -namespace { - -std::vector<GURL> MakeDefaultUrls() { - std::vector<GURL> urls; - urls.push_back(GURL(POST_INTERCEPT_SCHEME - "://" POST_INTERCEPT_HOSTNAME POST_INTERCEPT_PATH)); - return urls; -} - -} // namespace - -TestConfigurator::TestConfigurator( - const scoped_refptr<base::SequencedTaskRunner>& worker_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner) - : worker_task_runner_(worker_task_runner), - initial_time_(0), - times_(1), - recheck_time_(0), - ondemand_time_(0), - context_(new net::TestURLRequestContextGetter(network_task_runner)) { -} - -TestConfigurator::~TestConfigurator() { -} - -int TestConfigurator::InitialDelay() const { - return initial_time_; -} - -int TestConfigurator::NextCheckDelay() { - // This is called when a new full cycle of checking for updates is going - // to happen. In test we normally only test one cycle so it is a good - // time to break from the test messageloop Run() method so the test can - // finish. - if (--times_ <= 0) { - quit_closure_.Run(); - return 0; - } - return 1; -} - -int TestConfigurator::StepDelay() const { - return 0; -} - -int TestConfigurator::StepDelayMedium() { - return NextCheckDelay(); -} - -int TestConfigurator::MinimumReCheckWait() const { - return recheck_time_; -} - -int TestConfigurator::OnDemandDelay() const { - return ondemand_time_; -} - -int TestConfigurator::UpdateDelay() const { - return 1; -} - -std::vector<GURL> TestConfigurator::UpdateUrl() const { - return MakeDefaultUrls(); -} - -std::vector<GURL> TestConfigurator::PingUrl() const { - return UpdateUrl(); -} - -base::Version TestConfigurator::GetBrowserVersion() const { - // Needs to be larger than the required version in tested component manifests. - return base::Version("30.0"); -} - -std::string TestConfigurator::GetChannel() const { - return "fake_channel_string"; -} - -std::string TestConfigurator::GetLang() const { - return "fake_lang"; -} - -std::string TestConfigurator::GetOSLongName() const { - return "Fake Operating System"; -} - -std::string TestConfigurator::ExtraRequestParams() const { - return "extra=\"foo\""; -} - -size_t TestConfigurator::UrlSizeLimit() const { - return 256; -} - -net::URLRequestContextGetter* TestConfigurator::RequestContext() const { - return context_.get(); -} - -scoped_refptr<OutOfProcessPatcher> TestConfigurator::CreateOutOfProcessPatcher() - const { - return NULL; -} - -bool TestConfigurator::DeltasEnabled() const { - return true; -} - -bool TestConfigurator::UseBackgroundDownloader() const { - return false; -} - -// Set how many update checks are called, the default value is just once. -void TestConfigurator::SetLoopCount(int times) { - times_ = times; -} - -void TestConfigurator::SetRecheckTime(int seconds) { - recheck_time_ = seconds; -} - -void TestConfigurator::SetOnDemandTime(int seconds) { - ondemand_time_ = seconds; -} - -void TestConfigurator::SetQuitClosure(const base::Closure& quit_closure) { - quit_closure_ = quit_closure; -} - -void TestConfigurator::SetInitialDelay(int seconds) { - initial_time_ = seconds; -} - -scoped_refptr<base::SequencedTaskRunner> -TestConfigurator::GetSequencedTaskRunner() const { - DCHECK(worker_task_runner_.get()); - return worker_task_runner_; -} - -scoped_refptr<base::SingleThreadTaskRunner> -TestConfigurator::GetSingleThreadTaskRunner() const { - // This is NULL because tests do not use the background downloader. - return NULL; -} - -} // namespace update_client
diff --git a/components/update_client/test/test_configurator.h b/components/update_client/test/test_configurator.h deleted file mode 100644 index 6c2ed0e..0000000 --- a/components/update_client/test/test_configurator.h +++ /dev/null
@@ -1,111 +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_UPDATE_CLIENT_TEST_TEST_CONFIGURATOR_H_ -#define COMPONENTS_UPDATE_CLIENT_TEST_TEST_CONFIGURATOR_H_ - -#include <string> -#include <utility> -#include <vector> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "components/update_client/configurator.h" -#include "net/url_request/url_request_test_util.h" - -class GURL; - -namespace base { -class SequencedTaskRunner; -class SingleThreadTaskRunner; -} // namespace base - -namespace update_client { - -#define POST_INTERCEPT_SCHEME "https" -#define POST_INTERCEPT_HOSTNAME "localhost2" -#define POST_INTERCEPT_PATH "/update2" - -struct CrxComponent; - -// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and -// the RSA public key the following hash: -const uint8_t jebg_hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec, - 0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5, - 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4, - 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40}; -// component 2 has extension id "abagagagagagagagagagagagagagagag", and -// the RSA public key the following hash: -const uint8_t abag_hash[] = {0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01}; -// component 3 has extension id "ihfokbkgjpifnbbojhneepfflplebdkc", and -// the RSA public key the following hash: -const uint8_t ihfo_hash[] = {0x87, 0x5e, 0xa1, 0xa6, 0x9f, 0x85, 0xd1, 0x1e, - 0x97, 0xd4, 0x4f, 0x55, 0xbf, 0xb4, 0x13, 0xa2, - 0xe7, 0xc5, 0xc8, 0xf5, 0x60, 0x19, 0x78, 0x1b, - 0x6d, 0xe9, 0x4c, 0xeb, 0x96, 0x05, 0x42, 0x17}; - -class TestConfigurator : public Configurator { - public: - TestConfigurator( - const scoped_refptr<base::SequencedTaskRunner>& worker_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner); - - // Overrrides for Configurator. - int InitialDelay() const override; - int NextCheckDelay() override; - int StepDelay() const override; - int StepDelayMedium() override; - int MinimumReCheckWait() const override; - int OnDemandDelay() const override; - int UpdateDelay() const override; - std::vector<GURL> UpdateUrl() const override; - std::vector<GURL> PingUrl() const override; - base::Version GetBrowserVersion() const override; - std::string GetChannel() const override; - std::string GetLang() const override; - std::string GetOSLongName() const override; - std::string ExtraRequestParams() const override; - size_t UrlSizeLimit() const override; - net::URLRequestContextGetter* RequestContext() const override; - scoped_refptr<OutOfProcessPatcher> CreateOutOfProcessPatcher() const override; - bool DeltasEnabled() const override; - bool UseBackgroundDownloader() const override; - scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() - const override; - scoped_refptr<base::SingleThreadTaskRunner> GetSingleThreadTaskRunner() - const override; - - void SetLoopCount(int times); - void SetRecheckTime(int seconds); - void SetOnDemandTime(int seconds); - void SetQuitClosure(const base::Closure& quit_closure); - void SetInitialDelay(int seconds); - - private: - friend class base::RefCountedThreadSafe<TestConfigurator>; - - ~TestConfigurator() override; - - scoped_refptr<base::SequencedTaskRunner> worker_task_runner_; - scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; - - int initial_time_; - int times_; - int recheck_time_; - int ondemand_time_; - - scoped_refptr<net::TestURLRequestContextGetter> context_; - base::Closure quit_closure_; - - DISALLOW_COPY_AND_ASSIGN(TestConfigurator); -}; - -} // namespace update_client - -#endif // COMPONENTS_UPDATE_CLIENT_TEST_TEST_CONFIGURATOR_H_
diff --git a/components/update_client/test/test_installer.cc b/components/update_client/test/test_installer.cc deleted file mode 100644 index 6c03f49..0000000 --- a/components/update_client/test/test_installer.cc +++ /dev/null
@@ -1,85 +0,0 @@ -// Copyright 2013 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/update_client/test/test_installer.h" - -#include <string> - -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/values.h" - -namespace update_client { - -TestInstaller::TestInstaller() : error_(0), install_count_(0) { -} - -void TestInstaller::OnUpdateError(int error) { - error_ = error; -} - -bool TestInstaller::Install(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) { - ++install_count_; - return base::DeleteFile(unpack_path, true); -} - -bool TestInstaller::GetInstalledFile(const std::string& file, - base::FilePath* installed_file) { - return false; -} - -TestInstaller::~TestInstaller() { -} - -bool TestInstaller::Uninstall() { - return false; -} - -ReadOnlyTestInstaller::ReadOnlyTestInstaller(const base::FilePath& install_dir) - : install_directory_(install_dir) { -} - -ReadOnlyTestInstaller::~ReadOnlyTestInstaller() { -} - -bool ReadOnlyTestInstaller::GetInstalledFile(const std::string& file, - base::FilePath* installed_file) { - *installed_file = install_directory_.AppendASCII(file); - return true; -} - -VersionedTestInstaller::VersionedTestInstaller() { - base::CreateNewTempDirectory(FILE_PATH_LITERAL("TEST_"), &install_directory_); -} - -VersionedTestInstaller::~VersionedTestInstaller() { - base::DeleteFile(install_directory_, true); -} - -bool VersionedTestInstaller::Install(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) { - std::string version_string; - manifest.GetStringASCII("version", &version_string); - Version version(version_string.c_str()); - - base::FilePath path; - path = install_directory_.AppendASCII(version.GetString()); - base::CreateDirectory(path.DirName()); - if (!base::Move(unpack_path, path)) - return false; - current_version_ = version; - ++install_count_; - return true; -} - -bool VersionedTestInstaller::GetInstalledFile(const std::string& file, - base::FilePath* installed_file) { - base::FilePath path; - path = install_directory_.AppendASCII(current_version_.GetString()); - *installed_file = path.Append(base::FilePath::FromUTF8Unsafe(file)); - return true; -} - -} // namespace update_client
diff --git a/components/update_client/test/test_installer.h b/components/update_client/test/test_installer.h deleted file mode 100644 index e15ae0a..0000000 --- a/components/update_client/test/test_installer.h +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2013 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_UPDATE_CLIENT_TEST_TEST_INSTALLER_H_ -#define COMPONENTS_UPDATE_CLIENT_TEST_TEST_INSTALLER_H_ - -#include <string> - -#include "base/compiler_specific.h" -#include "base/files/file_path.h" -#include "components/update_client/update_client.h" - -namespace base { -class DictionaryValue; -} - -namespace update_client { - -// TODO(sorin): consider reducing the number of the installer mocks. -// A TestInstaller is an installer that does nothing for installation except -// increment a counter. -class TestInstaller : public CrxInstaller { - public: - TestInstaller(); - - void OnUpdateError(int error) override; - - bool Install(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) override; - - bool GetInstalledFile(const std::string& file, - base::FilePath* installed_file) override; - - bool Uninstall() override; - - int error() const { - return error_; - } - - int install_count() const { - return install_count_; - } - - protected: - ~TestInstaller() override; - - int error_; - int install_count_; -}; - -// A ReadOnlyTestInstaller is an installer that knows about files in an existing -// directory. It will not write to the directory. -class ReadOnlyTestInstaller : public TestInstaller { - public: - explicit ReadOnlyTestInstaller(const base::FilePath& installed_path); - - bool GetInstalledFile(const std::string& file, - base::FilePath* installed_file) override; - - private: - ~ReadOnlyTestInstaller() override; - - base::FilePath install_directory_; -}; - -// A VersionedTestInstaller is an installer that installs files into versioned -// directories (e.g. somedir/25.23.89.141/<files>). -class VersionedTestInstaller : public TestInstaller { - public: - VersionedTestInstaller(); - - bool Install(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) override; - - bool GetInstalledFile(const std::string& file, - base::FilePath* installed_file) override; - - private: - ~VersionedTestInstaller() override; - - base::FilePath install_directory_; - Version current_version_; -}; - -} // namespace update_client - -#endif // COMPONENTS_UPDATE_CLIENT_TEST_TEST_INSTALLER_H_
diff --git a/components/update_client/test/update_checker_unittest.cc b/components/update_client/test/update_checker_unittest.cc deleted file mode 100644 index ce6922a..0000000 --- a/components/update_client/test/update_checker_unittest.cc +++ /dev/null
@@ -1,237 +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 "base/bind.h" -#include "base/bind_helpers.h" -#include "base/compiler_specific.h" -#include "base/files/file_util.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/version.h" -#include "components/update_client/crx_update_item.h" -#include "components/update_client/test/test_configurator.h" -#include "components/update_client/test/url_request_post_interceptor.h" -#include "components/update_client/update_checker.h" -#include "net/url_request/url_request_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -using std::string; - -namespace update_client { - -namespace { - -base::FilePath test_file(const char* file) { - base::FilePath path; - PathService::Get(base::DIR_SOURCE_ROOT, &path); - return path.AppendASCII("components") - .AppendASCII("test") - .AppendASCII("data") - .AppendASCII("update_client") - .AppendASCII(file); -} - -} // namespace - -class UpdateCheckerTest : public testing::Test { - public: - UpdateCheckerTest(); - ~UpdateCheckerTest() override; - - // Overrides from testing::Test. - void SetUp() override; - void TearDown() override; - - void UpdateCheckComplete(const GURL& original_url, - int error, - const std::string& error_message, - const UpdateResponse::Results& results); - - protected: - void Quit(); - void RunThreads(); - void RunThreadsUntilIdle(); - - CrxUpdateItem BuildCrxUpdateItem(); - - scoped_refptr<TestConfigurator> config_; - - scoped_ptr<UpdateChecker> update_checker_; - - scoped_ptr<InterceptorFactory> interceptor_factory_; - URLRequestPostInterceptor* post_interceptor_; // Owned by the factory. - - GURL original_url_; - int error_; - std::string error_message_; - UpdateResponse::Results results_; - - private: - base::MessageLoopForIO loop_; - base::Closure quit_closure_; - - DISALLOW_COPY_AND_ASSIGN(UpdateCheckerTest); -}; - -UpdateCheckerTest::UpdateCheckerTest() : post_interceptor_(NULL), error_(0) { -} - -UpdateCheckerTest::~UpdateCheckerTest() { -} - -void UpdateCheckerTest::SetUp() { - config_ = new TestConfigurator(base::MessageLoopProxy::current(), - base::MessageLoopProxy::current()); - interceptor_factory_.reset( - new InterceptorFactory(base::MessageLoopProxy::current())); - post_interceptor_ = interceptor_factory_->CreateInterceptor(); - EXPECT_TRUE(post_interceptor_); - - update_checker_.reset(); - - error_ = 0; - error_message_.clear(); - results_ = UpdateResponse::Results(); -} - -void UpdateCheckerTest::TearDown() { - update_checker_.reset(); - - post_interceptor_ = NULL; - interceptor_factory_.reset(); - - config_ = nullptr; - - // The PostInterceptor requires the message loop to run to destruct correctly. - // TODO(sorin): This is fragile and should be fixed. - RunThreadsUntilIdle(); -} - -void UpdateCheckerTest::RunThreads() { - base::RunLoop runloop; - quit_closure_ = runloop.QuitClosure(); - runloop.Run(); - - // Since some tests need to drain currently enqueued tasks such as network - // intercepts on the IO thread, run the threads until they are - // idle. The component updater service won't loop again until the loop count - // is set and the service is started. - RunThreadsUntilIdle(); -} - -void UpdateCheckerTest::RunThreadsUntilIdle() { - base::RunLoop().RunUntilIdle(); -} - -void UpdateCheckerTest::Quit() { - if (!quit_closure_.is_null()) - quit_closure_.Run(); -} - -void UpdateCheckerTest::UpdateCheckComplete( - const GURL& original_url, - int error, - const std::string& error_message, - const UpdateResponse::Results& results) { - original_url_ = original_url; - error_ = error; - error_message_ = error_message; - results_ = results; - Quit(); -} - -CrxUpdateItem UpdateCheckerTest::BuildCrxUpdateItem() { - CrxComponent crx_component; - crx_component.name = "test_jebg"; - crx_component.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); - crx_component.installer = NULL; - crx_component.version = base::Version("0.9"); - crx_component.fingerprint = "fp1"; - - CrxUpdateItem crx_update_item; - crx_update_item.state = CrxUpdateItem::State::kNew; - crx_update_item.id = "jebgalgnebhfojomionfpkfelancnnkf"; - crx_update_item.component = crx_component; - - return crx_update_item; -} - -TEST_F(UpdateCheckerTest, UpdateCheckSuccess) { - EXPECT_TRUE(post_interceptor_->ExpectRequest( - new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); - - update_checker_ = UpdateChecker::Create(*config_).Pass(); - - CrxUpdateItem item(BuildCrxUpdateItem()); - std::vector<CrxUpdateItem*> items_to_check; - items_to_check.push_back(&item); - - update_checker_->CheckForUpdates( - items_to_check, "extra=\"params\"", - base::Bind(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - - RunThreads(); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - // Sanity check the request. - EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( - "request protocol=\"3.0\" extra=\"params\"")); - EXPECT_NE( - string::npos, - post_interceptor_->GetRequests()[0].find( - "app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" - "<updatecheck /><packages><package fp=\"fp1\"/></packages></app>")); - - EXPECT_NE(string::npos, - post_interceptor_->GetRequests()[0].find("<hw physmemory=")); - - // Sanity check the arguments of the callback after parsing. - EXPECT_EQ(config_->UpdateUrl().front(), original_url_); - EXPECT_EQ(0, error_); - EXPECT_TRUE(error_message_.empty()); - EXPECT_EQ(1ul, results_.list.size()); - EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", - results_.list[0].extension_id.c_str()); - EXPECT_STREQ("1.0", results_.list[0].manifest.version.c_str()); -} - -// Simulates a 403 server response error. -TEST_F(UpdateCheckerTest, UpdateCheckError) { - EXPECT_TRUE( - post_interceptor_->ExpectRequest(new PartialMatch("updatecheck"), 403)); - - update_checker_ = UpdateChecker::Create(*config_).Pass(); - - CrxUpdateItem item(BuildCrxUpdateItem()); - std::vector<CrxUpdateItem*> items_to_check; - items_to_check.push_back(&item); - - update_checker_->CheckForUpdates( - items_to_check, "", base::Bind(&UpdateCheckerTest::UpdateCheckComplete, - base::Unretained(this))); - - RunThreads(); - - EXPECT_EQ(1, post_interceptor_->GetHitCount()) - << post_interceptor_->GetRequestsAsString(); - EXPECT_EQ(1, post_interceptor_->GetCount()) - << post_interceptor_->GetRequestsAsString(); - - EXPECT_EQ(config_->UpdateUrl().front(), original_url_); - EXPECT_EQ(403, error_); - EXPECT_STREQ("network error", error_message_.c_str()); - EXPECT_EQ(0ul, results_.list.size()); -} - -} // namespace update_client
diff --git a/components/update_client/test/update_client_unittest.cc b/components/update_client/test/update_client_unittest.cc deleted file mode 100644 index 602fb96..0000000 --- a/components/update_client/test/update_client_unittest.cc +++ /dev/null
@@ -1,1422 +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 "base/bind.h" -#include "base/bind_helpers.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/location.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/thread_task_runner_handle.h" -#include "base/values.h" -#include "base/version.h" -#include "components/update_client/crx_update_item.h" -#include "components/update_client/ping_manager.h" -#include "components/update_client/test/test_configurator.h" -#include "components/update_client/test/test_installer.h" -#include "components/update_client/update_checker.h" -#include "components/update_client/update_client_internal.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace update_client { - -namespace { - -using base::FilePath; - -// Makes a copy of the file specified by |from_path| in a temporary directory -// and returns the path of the copy. Returns true if successful. Cleans up if -// there was an error creating the copy. -bool MakeTestFile(const FilePath& from_path, FilePath* to_path) { - FilePath temp_dir; - bool result = - CreateNewTempDirectory(FILE_PATH_LITERAL("update_client"), &temp_dir); - if (!result) - return false; - - FilePath temp_file; - result = CreateTemporaryFileInDir(temp_dir, &temp_file); - if (!result) - return false; - - result = CopyFile(from_path, temp_file); - if (!result) { - DeleteFile(temp_file, false); - return false; - } - - *to_path = temp_file; - return true; -} - -using Events = UpdateClient::Observer::Events; - -class MockObserver : public UpdateClient::Observer { - public: - MOCK_METHOD2(OnEvent, void(Events event, const std::string&)); -}; - -class FakePingManagerImpl : public PingManager { - public: - explicit FakePingManagerImpl(const Configurator& config); - ~FakePingManagerImpl() override; - - void OnUpdateComplete(const CrxUpdateItem* item) override; - - const std::vector<CrxUpdateItem>& items() const; - - private: - std::vector<CrxUpdateItem> items_; - DISALLOW_COPY_AND_ASSIGN(FakePingManagerImpl); -}; - -FakePingManagerImpl::FakePingManagerImpl(const Configurator& config) - : PingManager(config) { -} - -FakePingManagerImpl::~FakePingManagerImpl() { -} - -void FakePingManagerImpl::OnUpdateComplete(const CrxUpdateItem* item) { - items_.push_back(*item); -} - -const std::vector<CrxUpdateItem>& FakePingManagerImpl::items() const { - return items_; -} - -} // namespace - -using ::testing::_; -using ::testing::AnyNumber; -using ::testing::DoAll; -using ::testing::InSequence; -using ::testing::Invoke; -using ::testing::Mock; -using ::testing::Return; - -using content::BrowserThread; - -using std::string; - -class UpdateClientTest : public testing::Test { - public: - UpdateClientTest(); - ~UpdateClientTest() override; - - void SetUp() override; - void TearDown() override; - - protected: - void RunThreads(); - - // Returns the full path to a test file. - static base::FilePath TestFilePath(const char* file); - - content::TestBrowserThreadBundle thread_bundle_; - - base::RunLoop runloop_; - base::Closure quit_closure_; - - scoped_refptr<update_client::TestConfigurator> config_; - - private: - DISALLOW_COPY_AND_ASSIGN(UpdateClientTest); -}; - -UpdateClientTest::UpdateClientTest() - : config_(new TestConfigurator( - BrowserThread::GetBlockingPool() - ->GetSequencedTaskRunnerWithShutdownBehavior( - BrowserThread::GetBlockingPool()->GetSequenceToken(), - base::SequencedWorkerPool::SKIP_ON_SHUTDOWN), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) { -} - -UpdateClientTest::~UpdateClientTest() { -} - -void UpdateClientTest::SetUp() { - quit_closure_ = runloop_.QuitClosure(); -} - -void UpdateClientTest::TearDown() { -} - -void UpdateClientTest::RunThreads() { - runloop_.Run(); -} - -base::FilePath UpdateClientTest::TestFilePath(const char* file) { - base::FilePath path; - PathService::Get(base::DIR_SOURCE_ROOT, &path); - return path.AppendASCII("components") - .AppendASCII("test") - .AppendASCII("data") - .AppendASCII("update_client") - .AppendASCII(file); -} - -// Tests the scenario where one update check is done for one CRX. The CRX -// has no update. -TEST_F(UpdateClientTest, OneCrxNoUpdate) { - class DataCallbackFake { - public: - static void Callback(const std::vector<std::string>& ids, - std::vector<CrxComponent>* components) { - CrxComponent crx; - crx.name = "test_jebg"; - crx.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); - crx.version = Version("0.9"); - crx.installer = new TestInstaller; - components->push_back(crx); - } - }; - - class CompletionCallbackFake { - public: - static void Callback(const base::Closure& quit_closure, int error) { - EXPECT_EQ(0, error); - quit_closure.Run(); - } - }; - - class FakeUpdateChecker : public UpdateChecker { - public: - static scoped_ptr<UpdateChecker> Create(const Configurator& config) { - return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); - } - - bool CheckForUpdates( - const std::vector<CrxUpdateItem*>& items_to_check, - const std::string& additional_attributes, - const UpdateCheckCallback& update_check_callback) override { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", - UpdateResponse::Results())); - return true; - } - }; - - class FakeCrxDownloader : public CrxDownloader { - public: - static scoped_ptr<CrxDownloader> Create( - bool is_background_download, - net::URLRequestContextGetter* context_getter, - const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& - background_task_runner) { - return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); - } - - private: - FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} - ~FakeCrxDownloader() override {} - - void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); } - }; - - class FakePingManager : public FakePingManagerImpl { - public: - explicit FakePingManager(const Configurator& config) - : FakePingManagerImpl(config) {} - ~FakePingManager() override { EXPECT_TRUE(items().empty()); } - }; - - scoped_ptr<PingManager> ping_manager(new FakePingManager(*config_)); - scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( - config_, ping_manager.Pass(), &FakeUpdateChecker::Create, - &FakeCrxDownloader::Create)); - - MockObserver observer; - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - - update_client->AddObserver(&observer); - - std::vector<std::string> ids; - ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf")); - - update_client->Update( - ids, base::Bind(&DataCallbackFake::Callback), - base::Bind(&CompletionCallbackFake::Callback, quit_closure_)); - - RunThreads(); - - update_client->RemoveObserver(&observer); -} - -// Tests the scenario where two CRXs are checked for updates. On CRX has -// an update, the other CRX does not. -TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) { - class DataCallbackFake { - public: - static void Callback(const std::vector<std::string>& ids, - std::vector<CrxComponent>* components) { - CrxComponent crx1; - crx1.name = "test_jebg"; - crx1.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); - crx1.version = Version("0.9"); - crx1.installer = new TestInstaller; - - CrxComponent crx2; - crx2.name = "test_abag"; - crx2.pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); - crx2.version = Version("2.2"); - crx2.installer = new TestInstaller; - - components->push_back(crx1); - components->push_back(crx2); - } - }; - - class CompletionCallbackFake { - public: - static void Callback(const base::Closure& quit_closure, int error) { - EXPECT_EQ(0, error); - quit_closure.Run(); - } - }; - - class FakeUpdateChecker : public UpdateChecker { - public: - static scoped_ptr<UpdateChecker> Create(const Configurator& config) { - return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); - } - - bool CheckForUpdates( - const std::vector<CrxUpdateItem*>& items_to_check, - const std::string& additional_attributes, - const UpdateCheckCallback& update_check_callback) override { - /* - Fake the following response: - - <?xml version='1.0' encoding='UTF-8'?> - <response protocol='3.0'> - <app appid='jebgalgnebhfojomionfpkfelancnnkf'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> - </packages> - </manifest> - </updatecheck> - </app> - </response> - */ - UpdateResponse::Result::Manifest::Package package; - package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx"; - - UpdateResponse::Result result; - result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf"; - result.crx_urls.push_back(GURL("http://localhost/download/")); - result.manifest.version = "1.0"; - result.manifest.browser_min_version = "11.0.1.0"; - result.manifest.packages.push_back(package); - - UpdateResponse::Results results; - results.list.push_back(result); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); - return true; - } - }; - - class FakeCrxDownloader : public CrxDownloader { - public: - static scoped_ptr<CrxDownloader> Create( - bool is_background_download, - net::URLRequestContextGetter* context_getter, - const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& - background_task_runner) { - return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); - } - - private: - FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} - ~FakeCrxDownloader() override {} - - void DoStartDownload(const GURL& url) override { - DownloadMetrics download_metrics; - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 1843; - download_metrics.total_bytes = 1843; - download_metrics.download_time_ms = 1000; - - FilePath path; - EXPECT_TRUE(MakeTestFile( - TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path)); - - Result result; - result.error = 0; - result.response = path; - result.downloaded_bytes = 1843; - result.total_bytes = 1843; - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, - base::Unretained(this), result)); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&FakeCrxDownloader::OnDownloadComplete, - base::Unretained(this), true, result, download_metrics)); - } - }; - - class FakePingManager : public FakePingManagerImpl { - public: - explicit FakePingManager(const Configurator& config) - : FakePingManagerImpl(config) {} - ~FakePingManager() override { - const auto& ping_items = items(); - EXPECT_EQ(1U, ping_items.size()); - EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id); - EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version)); - EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); - EXPECT_EQ(0, ping_items[0].error_category); - EXPECT_EQ(0, ping_items[0].error_code); - } - }; - - scoped_ptr<PingManager> ping_manager(new FakePingManager(*config_)); - scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( - config_, ping_manager.Pass(), &FakeUpdateChecker::Create, - &FakeCrxDownloader::Create)); - - MockObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - } - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "abagagagagagagagagagagagagagagag")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "abagagagagagagagagagagagagagagag")).Times(1); - } - - update_client->AddObserver(&observer); - - std::vector<std::string> ids; - ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf")); - ids.push_back(std::string("abagagagagagagagagagagagagagagag")); - - update_client->Update( - ids, base::Bind(&DataCallbackFake::Callback), - base::Bind(&CompletionCallbackFake::Callback, quit_closure_)); - - RunThreads(); - - update_client->RemoveObserver(&observer); -} - -// Tests the update check for two CRXs scenario. Both CRXs have updates. -TEST_F(UpdateClientTest, TwoCrxUpdate) { - class DataCallbackFake { - public: - static void Callback(const std::vector<std::string>& ids, - std::vector<CrxComponent>* components) { - CrxComponent crx1; - crx1.name = "test_jebg"; - crx1.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); - crx1.version = Version("0.9"); - crx1.installer = new TestInstaller; - - CrxComponent crx2; - crx2.name = "test_ihfo"; - crx2.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); - crx2.version = Version("0.8"); - crx2.installer = new TestInstaller; - - components->push_back(crx1); - components->push_back(crx2); - } - }; - - class CompletionCallbackFake { - public: - static void Callback(const base::Closure& quit_closure, int error) { - EXPECT_EQ(0, error); - quit_closure.Run(); - } - }; - - class FakeUpdateChecker : public UpdateChecker { - public: - static scoped_ptr<UpdateChecker> Create(const Configurator& config) { - return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); - } - - bool CheckForUpdates( - const std::vector<CrxUpdateItem*>& items_to_check, - const std::string& additional_attributes, - const UpdateCheckCallback& update_check_callback) override { - /* - Fake the following response: - - <?xml version='1.0' encoding='UTF-8'?> - <response protocol='3.0'> - <app appid='jebgalgnebhfojomionfpkfelancnnkf'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> - </packages> - </manifest> - </updatecheck> - </app> - <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/> - </packages> - </manifest> - </updatecheck> - </app> - </response> - */ - UpdateResponse::Result::Manifest::Package package1; - package1.name = "jebgalgnebhfojomionfpkfelancnnkf.crx"; - - UpdateResponse::Result result1; - result1.extension_id = "jebgalgnebhfojomionfpkfelancnnkf"; - result1.crx_urls.push_back(GURL("http://localhost/download/")); - result1.manifest.version = "1.0"; - result1.manifest.browser_min_version = "11.0.1.0"; - result1.manifest.packages.push_back(package1); - - UpdateResponse::Result::Manifest::Package package2; - package2.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"; - - UpdateResponse::Result result2; - result2.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; - result2.crx_urls.push_back(GURL("http://localhost/download/")); - result2.manifest.version = "1.0"; - result2.manifest.browser_min_version = "11.0.1.0"; - result2.manifest.packages.push_back(package2); - - UpdateResponse::Results results; - results.list.push_back(result1); - results.list.push_back(result2); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); - return true; - } - }; - - class FakeCrxDownloader : public CrxDownloader { - public: - static scoped_ptr<CrxDownloader> Create( - bool is_background_download, - net::URLRequestContextGetter* context_getter, - const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& - background_task_runner) { - return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); - } - - private: - FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} - ~FakeCrxDownloader() override {} - - void DoStartDownload(const GURL& url) override { - DownloadMetrics download_metrics; - FilePath path; - Result result; - if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") { - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 1843; - download_metrics.total_bytes = 1843; - download_metrics.download_time_ms = 1000; - - EXPECT_TRUE(MakeTestFile( - TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path)); - - result.error = 0; - result.response = path; - result.downloaded_bytes = 1843; - result.total_bytes = 1843; - } else if (url.path() == - "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") { - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 53638; - download_metrics.total_bytes = 53638; - download_metrics.download_time_ms = 2000; - - EXPECT_TRUE(MakeTestFile( - TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path)); - - result.error = 0; - result.response = path; - result.downloaded_bytes = 53638; - result.total_bytes = 53638; - } else { - NOTREACHED(); - } - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, - base::Unretained(this), result)); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&FakeCrxDownloader::OnDownloadComplete, - base::Unretained(this), true, result, download_metrics)); - } - }; - - class FakePingManager : public FakePingManagerImpl { - public: - explicit FakePingManager(const Configurator& config) - : FakePingManagerImpl(config) {} - ~FakePingManager() override { - const auto& ping_items = items(); - EXPECT_EQ(2U, ping_items.size()); - EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id); - EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version)); - EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); - EXPECT_EQ(0, ping_items[0].error_category); - EXPECT_EQ(0, ping_items[0].error_code); - EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id); - EXPECT_TRUE(base::Version("0.8").Equals(ping_items[1].previous_version)); - EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].next_version)); - EXPECT_EQ(0, ping_items[1].error_category); - EXPECT_EQ(0, ping_items[1].error_code); - } - }; - - scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config_)); - scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( - config_, ping_manager.Pass(), &FakeUpdateChecker::Create, - &FakeCrxDownloader::Create)); - - MockObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - } - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_WAIT, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - } - - update_client->AddObserver(&observer); - - std::vector<std::string> ids; - ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf")); - ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc")); - - update_client->Update( - ids, base::Bind(&DataCallbackFake::Callback), - base::Bind(&CompletionCallbackFake::Callback, quit_closure_)); - - RunThreads(); - - update_client->RemoveObserver(&observer); -} - -// Tests the differential update scenario for one CRX. -TEST_F(UpdateClientTest, OneCrxDiffUpdate) { - class DataCallbackFake { - public: - static void Callback(const std::vector<std::string>& ids, - std::vector<CrxComponent>* components) { - static int num_calls = 0; - - // Must use the same stateful installer object. - static scoped_refptr<CrxInstaller> installer( - new VersionedTestInstaller()); - - ++num_calls; - - CrxComponent crx; - crx.name = "test_ihfo"; - crx.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); - crx.installer = installer; - if (num_calls == 1) { - crx.version = Version("0.8"); - } else if (num_calls == 2) { - crx.version = Version("1.0"); - } else { - NOTREACHED(); - } - - components->push_back(crx); - } - }; - - class CompletionCallbackFake { - public: - static void Callback(const base::Closure& quit_closure, int error) { - EXPECT_EQ(0, error); - quit_closure.Run(); - } - }; - - class FakeUpdateChecker : public UpdateChecker { - public: - static scoped_ptr<UpdateChecker> Create(const Configurator& config) { - return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); - } - - bool CheckForUpdates( - const std::vector<CrxUpdateItem*>& items_to_check, - const std::string& additional_attributes, - const UpdateCheckCallback& update_check_callback) override { - static int num_call = 0; - ++num_call; - - UpdateResponse::Results results; - - if (num_call == 1) { - /* - Fake the following response: - <?xml version='1.0' encoding='UTF-8'?> - <response protocol='3.0'> - <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/> - </packages> - </manifest> - </updatecheck> - </app> - </response> - */ - UpdateResponse::Result::Manifest::Package package; - package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"; - package.fingerprint = "1"; - UpdateResponse::Result result; - result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; - result.crx_urls.push_back(GURL("http://localhost/download/")); - result.manifest.version = "1.0"; - result.manifest.browser_min_version = "11.0.1.0"; - result.manifest.packages.push_back(package); - results.list.push_back(result); - } else if (num_call == 2) { - /* - Fake the following response: - <?xml version='1.0' encoding='UTF-8'?> - <response protocol='3.0'> - <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - <url codebasediff='http://localhost/download/'/> - </urls> - <manifest version='2.0' prodversionmin='11.0.1.0'> - <packages> - <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx' - namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx' - fp='22'/> - </packages> - </manifest> - </updatecheck> - </app> - </response> - */ - UpdateResponse::Result::Manifest::Package package; - package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"; - package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"; - package.fingerprint = "22"; - UpdateResponse::Result result; - result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; - result.crx_urls.push_back(GURL("http://localhost/download/")); - result.crx_diffurls.push_back(GURL("http://localhost/download/")); - result.manifest.version = "2.0"; - result.manifest.browser_min_version = "11.0.1.0"; - result.manifest.packages.push_back(package); - results.list.push_back(result); - } else { - NOTREACHED(); - } - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); - return true; - } - }; - - class FakeCrxDownloader : public CrxDownloader { - public: - static scoped_ptr<CrxDownloader> Create( - bool is_background_download, - net::URLRequestContextGetter* context_getter, - const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& - background_task_runner) { - return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); - } - - private: - FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} - ~FakeCrxDownloader() override {} - - void DoStartDownload(const GURL& url) override { - DownloadMetrics download_metrics; - FilePath path; - Result result; - if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") { - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 53638; - download_metrics.total_bytes = 53638; - download_metrics.download_time_ms = 2000; - - EXPECT_TRUE(MakeTestFile( - TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path)); - - result.error = 0; - result.response = path; - result.downloaded_bytes = 53638; - result.total_bytes = 53638; - } else if (url.path() == - "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") { - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 2105; - download_metrics.total_bytes = 2105; - download_metrics.download_time_ms = 1000; - - EXPECT_TRUE(MakeTestFile( - TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), &path)); - - result.error = 0; - result.response = path; - result.downloaded_bytes = 2105; - result.total_bytes = 2105; - } else { - NOTREACHED(); - } - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, - base::Unretained(this), result)); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&FakeCrxDownloader::OnDownloadComplete, - base::Unretained(this), true, result, download_metrics)); - } - }; - - class FakePingManager : public FakePingManagerImpl { - public: - explicit FakePingManager(const Configurator& config) - : FakePingManagerImpl(config) {} - ~FakePingManager() override { - const auto& ping_items = items(); - EXPECT_EQ(2U, ping_items.size()); - EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[0].id); - EXPECT_TRUE(base::Version("0.8").Equals(ping_items[0].previous_version)); - EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); - EXPECT_EQ(0, ping_items[0].error_category); - EXPECT_EQ(0, ping_items[0].error_code); - EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id); - EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].previous_version)); - EXPECT_TRUE(base::Version("2.0").Equals(ping_items[1].next_version)); - EXPECT_EQ(0, ping_items[1].diff_error_category); - EXPECT_EQ(0, ping_items[1].diff_error_code); - } - }; - - scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config_)); - scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( - config_, ping_manager.Pass(), &FakeUpdateChecker::Create, - &FakeCrxDownloader::Create)); - - MockObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - } - - update_client->AddObserver(&observer); - - std::vector<std::string> ids; - ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc")); - - { - base::RunLoop runloop; - update_client->Update( - ids, base::Bind(&DataCallbackFake::Callback), - base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure())); - runloop.Run(); - } - - { - base::RunLoop runloop; - update_client->Update( - ids, base::Bind(&DataCallbackFake::Callback), - base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure())); - runloop.Run(); - } - - update_client->RemoveObserver(&observer); -} - -// Tests the update scenario for one CRX where the CRX installer returns -// an error. -TEST_F(UpdateClientTest, OneCrxInstallError) { - class MockInstaller : public CrxInstaller { - public: - MOCK_METHOD1(OnUpdateError, void(int error)); - MOCK_METHOD2(Install, - bool(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path)); - MOCK_METHOD2(GetInstalledFile, - bool(const std::string& file, base::FilePath* installed_file)); - MOCK_METHOD0(Uninstall, bool()); - - static void OnInstall(const base::DictionaryValue& manifest, - const base::FilePath& unpack_path) { - base::DeleteFile(unpack_path, true); - } - - protected: - ~MockInstaller() override {} - }; - - class DataCallbackFake { - public: - static void Callback(const std::vector<std::string>& ids, - std::vector<CrxComponent>* components) { - scoped_refptr<MockInstaller> installer(new MockInstaller()); - - EXPECT_CALL(*installer, OnUpdateError(_)).Times(0); - EXPECT_CALL(*installer, Install(_, _)) - .WillOnce(DoAll(Invoke(MockInstaller::OnInstall), Return(false))); - EXPECT_CALL(*installer, GetInstalledFile(_, _)).Times(0); - EXPECT_CALL(*installer, Uninstall()).Times(0); - - CrxComponent crx; - crx.name = "test_jebg"; - crx.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); - crx.version = Version("0.9"); - crx.installer = installer; - components->push_back(crx); - } - }; - - class CompletionCallbackFake { - public: - static void Callback(const base::Closure& quit_closure, int error) { - EXPECT_EQ(0, error); - quit_closure.Run(); - } - }; - - class FakeUpdateChecker : public UpdateChecker { - public: - static scoped_ptr<UpdateChecker> Create(const Configurator& config) { - return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); - } - - bool CheckForUpdates( - const std::vector<CrxUpdateItem*>& items_to_check, - const std::string& additional_attributes, - const UpdateCheckCallback& update_check_callback) override { - /* - Fake the following response: - - <?xml version='1.0' encoding='UTF-8'?> - <response protocol='3.0'> - <app appid='jebgalgnebhfojomionfpkfelancnnkf'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> - </packages> - </manifest> - </updatecheck> - </app> - </response> - */ - UpdateResponse::Result::Manifest::Package package; - package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx"; - - UpdateResponse::Result result; - result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf"; - result.crx_urls.push_back(GURL("http://localhost/download/")); - result.manifest.version = "1.0"; - result.manifest.browser_min_version = "11.0.1.0"; - result.manifest.packages.push_back(package); - - UpdateResponse::Results results; - results.list.push_back(result); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); - return true; - } - }; - - class FakeCrxDownloader : public CrxDownloader { - public: - static scoped_ptr<CrxDownloader> Create( - bool is_background_download, - net::URLRequestContextGetter* context_getter, - const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& - background_task_runner) { - return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); - } - - private: - FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} - ~FakeCrxDownloader() override {} - - void DoStartDownload(const GURL& url) override { - DownloadMetrics download_metrics; - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 1843; - download_metrics.total_bytes = 1843; - download_metrics.download_time_ms = 1000; - - FilePath path; - EXPECT_TRUE(MakeTestFile( - TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path)); - - Result result; - result.error = 0; - result.response = path; - result.downloaded_bytes = 1843; - result.total_bytes = 1843; - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, - base::Unretained(this), result)); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&FakeCrxDownloader::OnDownloadComplete, - base::Unretained(this), true, result, download_metrics)); - } - }; - - class FakePingManager : public FakePingManagerImpl { - public: - explicit FakePingManager(const Configurator& config) - : FakePingManagerImpl(config) {} - ~FakePingManager() override { - const auto& ping_items = items(); - EXPECT_EQ(1U, ping_items.size()); - EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id); - EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version)); - EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); - EXPECT_EQ(3, ping_items[0].error_category); // kInstallError. - EXPECT_EQ(9, ping_items[0].error_code); // kInstallerError. - } - }; - - scoped_ptr<PingManager> ping_manager(new FakePingManager(*config_)); - scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( - config_, ping_manager.Pass(), &FakeUpdateChecker::Create, - &FakeCrxDownloader::Create)); - - MockObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, - "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); - } - - update_client->AddObserver(&observer); - - std::vector<std::string> ids; - ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf")); - - update_client->Update( - ids, base::Bind(&DataCallbackFake::Callback), - base::Bind(&CompletionCallbackFake::Callback, quit_closure_)); - - RunThreads(); - - update_client->RemoveObserver(&observer); -} - -// Tests the fallback from differential to full update scenario for one CRX. -TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) { - class DataCallbackFake { - public: - static void Callback(const std::vector<std::string>& ids, - std::vector<CrxComponent>* components) { - static int num_calls = 0; - - // Must use the same stateful installer object. - static scoped_refptr<CrxInstaller> installer( - new VersionedTestInstaller()); - - ++num_calls; - - CrxComponent crx; - crx.name = "test_ihfo"; - crx.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); - crx.installer = installer; - if (num_calls == 1) { - crx.version = Version("0.8"); - } else if (num_calls == 2) { - crx.version = Version("1.0"); - } else { - NOTREACHED(); - } - - components->push_back(crx); - } - }; - - class CompletionCallbackFake { - public: - static void Callback(const base::Closure& quit_closure, int error) { - EXPECT_EQ(0, error); - quit_closure.Run(); - } - }; - - class FakeUpdateChecker : public UpdateChecker { - public: - static scoped_ptr<UpdateChecker> Create(const Configurator& config) { - return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); - } - - bool CheckForUpdates( - const std::vector<CrxUpdateItem*>& items_to_check, - const std::string& additional_attributes, - const UpdateCheckCallback& update_check_callback) override { - static int num_call = 0; - ++num_call; - - UpdateResponse::Results results; - - if (num_call == 1) { - /* - Fake the following response: - <?xml version='1.0' encoding='UTF-8'?> - <response protocol='3.0'> - <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - </urls> - <manifest version='1.0' prodversionmin='11.0.1.0'> - <packages> - <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/> - </packages> - </manifest> - </updatecheck> - </app> - </response> - */ - UpdateResponse::Result::Manifest::Package package; - package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"; - package.fingerprint = "1"; - UpdateResponse::Result result; - result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; - result.crx_urls.push_back(GURL("http://localhost/download/")); - result.manifest.version = "1.0"; - result.manifest.browser_min_version = "11.0.1.0"; - result.manifest.packages.push_back(package); - results.list.push_back(result); - } else if (num_call == 2) { - /* - Fake the following response: - <?xml version='1.0' encoding='UTF-8'?> - <response protocol='3.0'> - <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> - <updatecheck status='ok'> - <urls> - <url codebase='http://localhost/download/'/> - <url codebasediff='http://localhost/download/'/> - </urls> - <manifest version='2.0' prodversionmin='11.0.1.0'> - <packages> - <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx' - namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx' - fp='22'/> - </packages> - </manifest> - </updatecheck> - </app> - </response> - */ - UpdateResponse::Result::Manifest::Package package; - package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"; - package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"; - package.fingerprint = "22"; - UpdateResponse::Result result; - result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; - result.crx_urls.push_back(GURL("http://localhost/download/")); - result.crx_diffurls.push_back(GURL("http://localhost/download/")); - result.manifest.version = "2.0"; - result.manifest.browser_min_version = "11.0.1.0"; - result.manifest.packages.push_back(package); - results.list.push_back(result); - } else { - NOTREACHED(); - } - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); - return true; - } - }; - - class FakeCrxDownloader : public CrxDownloader { - public: - static scoped_ptr<CrxDownloader> Create( - bool is_background_download, - net::URLRequestContextGetter* context_getter, - const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, - const scoped_refptr<base::SingleThreadTaskRunner>& - background_task_runner) { - return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); - } - - private: - FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} - ~FakeCrxDownloader() override {} - - void DoStartDownload(const GURL& url) override { - DownloadMetrics download_metrics; - FilePath path; - Result result; - if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") { - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 53638; - download_metrics.total_bytes = 53638; - download_metrics.download_time_ms = 2000; - - EXPECT_TRUE(MakeTestFile( - TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path)); - - result.error = 0; - result.response = path; - result.downloaded_bytes = 53638; - result.total_bytes = 53638; - } else if (url.path() == - "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") { - // A download error is injected on this execution path. - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = -1; - download_metrics.downloaded_bytes = 0; - download_metrics.total_bytes = 2105; - download_metrics.download_time_ms = 1000; - - EXPECT_TRUE(MakeTestFile( - TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), &path)); - - result.error = -1; - result.response = path; - result.downloaded_bytes = 0; - result.total_bytes = 2105; - } else if (url.path() == - "/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx") { - download_metrics.url = url; - download_metrics.downloader = DownloadMetrics::kNone; - download_metrics.error = 0; - download_metrics.downloaded_bytes = 53855; - download_metrics.total_bytes = 53855; - download_metrics.download_time_ms = 1000; - - EXPECT_TRUE(MakeTestFile( - TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), &path)); - - result.error = 0; - result.response = path; - result.downloaded_bytes = 53855; - result.total_bytes = 53855; - } - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, - base::Unretained(this), result)); - - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&FakeCrxDownloader::OnDownloadComplete, - base::Unretained(this), true, result, download_metrics)); - } - }; - - class FakePingManager : public FakePingManagerImpl { - public: - explicit FakePingManager(const Configurator& config) - : FakePingManagerImpl(config) {} - ~FakePingManager() override { - const auto& ping_items = items(); - EXPECT_EQ(2U, ping_items.size()); - EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[0].id); - EXPECT_TRUE(base::Version("0.8").Equals(ping_items[0].previous_version)); - EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); - EXPECT_EQ(0, ping_items[0].error_category); - EXPECT_EQ(0, ping_items[0].error_code); - EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id); - EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].previous_version)); - EXPECT_TRUE(base::Version("2.0").Equals(ping_items[1].next_version)); - EXPECT_TRUE(ping_items[1].diff_update_failed); - EXPECT_EQ(1, ping_items[1].diff_error_category); // kNetworkError. - EXPECT_EQ(-1, ping_items[1].diff_error_code); - } - }; - - scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config_)); - scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( - config_, ping_manager.Pass(), &FakeUpdateChecker::Create, - &FakeCrxDownloader::Create)); - - MockObserver observer; - { - InSequence seq; - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, - "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); - } - - update_client->AddObserver(&observer); - - std::vector<std::string> ids; - ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc")); - - { - base::RunLoop runloop; - update_client->Update( - ids, base::Bind(&DataCallbackFake::Callback), - base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure())); - runloop.Run(); - } - - { - base::RunLoop runloop; - update_client->Update( - ids, base::Bind(&DataCallbackFake::Callback), - base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure())); - runloop.Run(); - } - - update_client->RemoveObserver(&observer); -} - -} // namespace update_client
diff --git a/components/update_client/test/url_request_post_interceptor.cc b/components/update_client/test/url_request_post_interceptor.cc deleted file mode 100644 index 4aeb7a7..0000000 --- a/components/update_client/test/url_request_post_interceptor.cc +++ /dev/null
@@ -1,301 +0,0 @@ -// Copyright 2013 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/update_client/test/url_request_post_interceptor.h" - -#include "base/files/file_util.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/strings/stringprintf.h" -#include "components/update_client/test/test_configurator.h" -#include "net/base/upload_bytes_element_reader.h" -#include "net/base/upload_data_stream.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_filter.h" -#include "net/url_request/url_request_interceptor.h" -#include "net/url_request/url_request_simple_job.h" -#include "net/url_request/url_request_test_util.h" - -namespace update_client { - -// Returns a canned response. -class URLRequestMockJob : public net::URLRequestSimpleJob { - public: - URLRequestMockJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - int response_code, - const std::string& response_body) - : net::URLRequestSimpleJob(request, network_delegate), - response_code_(response_code), - response_body_(response_body) {} - - protected: - int GetResponseCode() const override { return response_code_; } - - int GetData(std::string* mime_type, - std::string* charset, - std::string* data, - const net::CompletionCallback& callback) const override { - mime_type->assign("text/plain"); - charset->assign("US-ASCII"); - data->assign(response_body_); - return net::OK; - } - - private: - ~URLRequestMockJob() override {} - - int response_code_; - std::string response_body_; - DISALLOW_COPY_AND_ASSIGN(URLRequestMockJob); -}; - -URLRequestPostInterceptor::URLRequestPostInterceptor( - const GURL& url, - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) - : url_(url), io_task_runner_(io_task_runner), hit_count_(0) { -} - -URLRequestPostInterceptor::~URLRequestPostInterceptor() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - ClearExpectations(); -} - -void URLRequestPostInterceptor::ClearExpectations() { - while (!expectations_.empty()) { - Expectation expectation(expectations_.front()); - delete expectation.first; - expectations_.pop(); - } -} - -GURL URLRequestPostInterceptor::GetUrl() const { - return url_; -} - -bool URLRequestPostInterceptor::ExpectRequest( - class RequestMatcher* request_matcher) { - expectations_.push(std::make_pair(request_matcher, - ExpectationResponse(kResponseCode200, ""))); - return true; -} - -bool URLRequestPostInterceptor::ExpectRequest( - class RequestMatcher* request_matcher, - int response_code) { - expectations_.push( - std::make_pair(request_matcher, ExpectationResponse(response_code, ""))); - return true; -} - -bool URLRequestPostInterceptor::ExpectRequest( - class RequestMatcher* request_matcher, - const base::FilePath& filepath) { - std::string response; - if (filepath.empty() || !base::ReadFileToString(filepath, &response)) - return false; - - expectations_.push(std::make_pair( - request_matcher, ExpectationResponse(kResponseCode200, response))); - return true; -} - -int URLRequestPostInterceptor::GetHitCount() const { - base::AutoLock auto_lock(interceptor_lock_); - return hit_count_; -} - -int URLRequestPostInterceptor::GetCount() const { - base::AutoLock auto_lock(interceptor_lock_); - return static_cast<int>(requests_.size()); -} - -std::vector<std::string> URLRequestPostInterceptor::GetRequests() const { - base::AutoLock auto_lock(interceptor_lock_); - return requests_; -} - -std::string URLRequestPostInterceptor::GetRequestsAsString() const { - std::vector<std::string> requests(GetRequests()); - - std::string s = "Requests are:"; - - int i = 0; - for (std::vector<std::string>::const_iterator it = requests.begin(); - it != requests.end(); ++it) { - s.append(base::StringPrintf("\n (%d): %s", ++i, it->c_str())); - } - - return s; -} - -void URLRequestPostInterceptor::Reset() { - base::AutoLock auto_lock(interceptor_lock_); - hit_count_ = 0; - requests_.clear(); - ClearExpectations(); -} - -class URLRequestPostInterceptor::Delegate : public net::URLRequestInterceptor { - public: - Delegate(const std::string& scheme, - const std::string& hostname, - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) - : scheme_(scheme), hostname_(hostname), io_task_runner_(io_task_runner) {} - - void Register() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( - scheme_, hostname_, scoped_ptr<net::URLRequestInterceptor>(this)); - } - - void Unregister() { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - for (InterceptorMap::iterator it = interceptors_.begin(); - it != interceptors_.end(); ++it) - delete (*it).second; - net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme_, - hostname_); - } - - void OnCreateInterceptor(URLRequestPostInterceptor* interceptor) { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - DCHECK(interceptors_.find(interceptor->GetUrl()) == interceptors_.end()); - - interceptors_.insert(std::make_pair(interceptor->GetUrl(), interceptor)); - } - - private: - ~Delegate() override {} - - net::URLRequestJob* MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { - DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); - - // Only intercepts POST. - if (!request->has_upload()) - return NULL; - - GURL url = request->url(); - if (url.has_query()) { - GURL::Replacements replacements; - replacements.ClearQuery(); - url = url.ReplaceComponents(replacements); - } - - InterceptorMap::const_iterator it(interceptors_.find(url)); - if (it == interceptors_.end()) - return NULL; - - // There is an interceptor hooked up for this url. Read the request body, - // check the existing expectations, and handle the matching case by - // popping the expectation off the queue, counting the match, and - // returning a mock object to serve the canned response. - URLRequestPostInterceptor* interceptor(it->second); - - const net::UploadDataStream* stream = request->get_upload(); - const net::UploadBytesElementReader* reader = - (*stream->GetElementReaders())[0]->AsBytesReader(); - const int size = reader->length(); - scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size)); - const std::string request_body(reader->bytes()); - - { - base::AutoLock auto_lock(interceptor->interceptor_lock_); - interceptor->requests_.push_back(request_body); - if (interceptor->expectations_.empty()) - return NULL; - const URLRequestPostInterceptor::Expectation& expectation( - interceptor->expectations_.front()); - if (expectation.first->Match(request_body)) { - const int response_code(expectation.second.response_code); - const std::string response_body(expectation.second.response_body); - delete expectation.first; - interceptor->expectations_.pop(); - ++interceptor->hit_count_; - - return new URLRequestMockJob(request, network_delegate, response_code, - response_body); - } - } - - return NULL; - } - - typedef std::map<GURL, URLRequestPostInterceptor*> InterceptorMap; - InterceptorMap interceptors_; - - const std::string scheme_; - const std::string hostname_; - scoped_refptr<base::SequencedTaskRunner> io_task_runner_; - - DISALLOW_COPY_AND_ASSIGN(Delegate); -}; - -URLRequestPostInterceptorFactory::URLRequestPostInterceptorFactory( - const std::string& scheme, - const std::string& hostname, - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) - : scheme_(scheme), - hostname_(hostname), - io_task_runner_(io_task_runner), - delegate_(new URLRequestPostInterceptor::Delegate(scheme, - hostname, - io_task_runner)) { - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&URLRequestPostInterceptor::Delegate::Register, - base::Unretained(delegate_))); -} - -URLRequestPostInterceptorFactory::~URLRequestPostInterceptorFactory() { - io_task_runner_->PostTask( - FROM_HERE, base::Bind(&URLRequestPostInterceptor::Delegate::Unregister, - base::Unretained(delegate_))); -} - -URLRequestPostInterceptor* URLRequestPostInterceptorFactory::CreateInterceptor( - const base::FilePath& filepath) { - const GURL base_url( - base::StringPrintf("%s://%s", scheme_.c_str(), hostname_.c_str())); - GURL absolute_url(base_url.Resolve(filepath.MaybeAsASCII())); - URLRequestPostInterceptor* interceptor( - new URLRequestPostInterceptor(absolute_url, io_task_runner_)); - bool res = io_task_runner_->PostTask( - FROM_HERE, - base::Bind(&URLRequestPostInterceptor::Delegate::OnCreateInterceptor, - base::Unretained(delegate_), base::Unretained(interceptor))); - if (!res) { - delete interceptor; - return NULL; - } - - return interceptor; -} - -bool PartialMatch::Match(const std::string& actual) const { - return actual.find(expected_) != std::string::npos; -} - -InterceptorFactory::InterceptorFactory( - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) - : URLRequestPostInterceptorFactory(POST_INTERCEPT_SCHEME, - POST_INTERCEPT_HOSTNAME, - io_task_runner) { -} - -InterceptorFactory::~InterceptorFactory() { -} - -URLRequestPostInterceptor* InterceptorFactory::CreateInterceptor() { - return CreateInterceptorForPath(POST_INTERCEPT_PATH); -} - -URLRequestPostInterceptor* InterceptorFactory::CreateInterceptorForPath( - const char* url_path) { - return URLRequestPostInterceptorFactory::CreateInterceptor( - base::FilePath::FromUTF8Unsafe(url_path)); -} - -} // namespace update_client
diff --git a/components/update_client/test/url_request_post_interceptor.h b/components/update_client/test/url_request_post_interceptor.h deleted file mode 100644 index d261160..0000000 --- a/components/update_client/test/url_request_post_interceptor.h +++ /dev/null
@@ -1,165 +0,0 @@ -// Copyright 2013 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_UPDATE_CLIENT_TEST_URL_REQUEST_POST_INTERCEPTOR_H_ -#define COMPONENTS_UPDATE_CLIENT_TEST_URL_REQUEST_POST_INTERCEPTOR_H_ - -#include <stdint.h> -#include <map> -#include <queue> -#include <string> -#include <utility> -#include <vector> - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#include "url/gurl.h" - -namespace base { -class FilePath; -class SequencedTaskRunner; -} - -namespace net { -class URLRequest; -} - -namespace update_client { - -// Intercepts requests to a file path, counts them, and captures the body of -// the requests. Optionally, for each request, it can return a canned response -// from a given file. The class maintains a queue of expectations, and returns -// one and only one response for each request that matches and it is -// intercepted. -class URLRequestPostInterceptor { - public: - // Allows a generic string maching interface when setting up expectations. - class RequestMatcher { - public: - virtual bool Match(const std::string& actual) const = 0; - virtual ~RequestMatcher() {} - }; - - // Returns the url that is intercepted. - GURL GetUrl() const; - - // Sets an expection for the body of the POST request and optionally, - // provides a canned response identified by a |file_path| to be returned when - // the expectation is met. If no |file_path| is provided, then an empty - // response body is served. If |response_code| is provided, then an empty - // response body with that response code is returned. - // Returns |true| if the expectation was set. This class takes ownership of - // the |request_matcher| object. - bool ExpectRequest(class RequestMatcher* request_matcher); - bool ExpectRequest(class RequestMatcher* request_matcher, int response_code); - bool ExpectRequest(class RequestMatcher* request_matcher, - const base::FilePath& filepath); - - // Returns how many requests have been intercepted and matched by - // an expectation. One expectation can only be matched by one request. - int GetHitCount() const; - - // Returns how many requests in total have been captured by the interceptor. - int GetCount() const; - - // Returns all requests that have been intercepted, matched or not. - std::vector<std::string> GetRequests() const; - - // Returns all requests as a string for debugging purposes. - std::string GetRequestsAsString() const; - - // Resets the state of the interceptor so that new expectations can be set. - void Reset(); - - class Delegate; - - private: - friend class URLRequestPostInterceptorFactory; - - static const int kResponseCode200 = 200; - - struct ExpectationResponse { - ExpectationResponse(int code, const std::string& body) - : response_code(code), response_body(body) {} - const int response_code; - const std::string response_body; - }; - typedef std::pair<const RequestMatcher*, ExpectationResponse> Expectation; - - URLRequestPostInterceptor( - const GURL& url, - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner); - ~URLRequestPostInterceptor(); - - void ClearExpectations(); - - const GURL url_; - scoped_refptr<base::SequencedTaskRunner> io_task_runner_; - - mutable base::Lock interceptor_lock_; - mutable int hit_count_; - mutable std::vector<std::string> requests_; - mutable std::queue<Expectation> expectations_; - - DISALLOW_COPY_AND_ASSIGN(URLRequestPostInterceptor); -}; - -class URLRequestPostInterceptorFactory { - public: - URLRequestPostInterceptorFactory( - const std::string& scheme, - const std::string& hostname, - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner); - ~URLRequestPostInterceptorFactory(); - - // Creates an interceptor object for the specified url path. Returns NULL - // in case of errors or a valid interceptor object otherwise. The caller - // does not own the returned object. - URLRequestPostInterceptor* CreateInterceptor(const base::FilePath& filepath); - - private: - const std::string scheme_; - const std::string hostname_; - scoped_refptr<base::SequencedTaskRunner> io_task_runner_; - - // After creation, |delegate_| lives on the IO thread and it is owned by - // a URLRequestFilter after registration. A task to unregister it and - // implicitly destroy it is posted from ~URLRequestPostInterceptorFactory(). - URLRequestPostInterceptor::Delegate* delegate_; - - DISALLOW_COPY_AND_ASSIGN(URLRequestPostInterceptorFactory); -}; - -// Intercepts HTTP POST requests sent to "localhost2". -class InterceptorFactory : public URLRequestPostInterceptorFactory { - public: - explicit InterceptorFactory( - const scoped_refptr<base::SequencedTaskRunner>& io_task_runner); - ~InterceptorFactory(); - - // Creates an interceptor for the url path defined by POST_INTERCEPT_PATH. - URLRequestPostInterceptor* CreateInterceptor(); - - // Creates an interceptor for the given url path. - URLRequestPostInterceptor* CreateInterceptorForPath(const char* url_path); - - private: - DISALLOW_COPY_AND_ASSIGN(InterceptorFactory); -}; - -class PartialMatch : public URLRequestPostInterceptor::RequestMatcher { - public: - explicit PartialMatch(const std::string& expected) : expected_(expected) {} - bool Match(const std::string& actual) const override; - - private: - const std::string expected_; - - DISALLOW_COPY_AND_ASSIGN(PartialMatch); -}; - -} // namespace update_client - -#endif // COMPONENTS_UPDATE_CLIENT_TEST_URL_REQUEST_POST_INTERCEPTOR_H_
diff --git a/components/update_client/test_configurator.cc b/components/update_client/test_configurator.cc new file mode 100644 index 0000000..9cd59e4 --- /dev/null +++ b/components/update_client/test_configurator.cc
@@ -0,0 +1,158 @@ +// 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/update_client/test_configurator.h" + +#include "base/run_loop.h" +#include "base/version.h" +#include "components/update_client/component_patcher_operation.h" +#include "url/gurl.h" + +namespace update_client { + +namespace { + +std::vector<GURL> MakeDefaultUrls() { + std::vector<GURL> urls; + urls.push_back(GURL(POST_INTERCEPT_SCHEME + "://" POST_INTERCEPT_HOSTNAME POST_INTERCEPT_PATH)); + return urls; +} + +} // namespace + +TestConfigurator::TestConfigurator( + const scoped_refptr<base::SequencedTaskRunner>& worker_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner) + : worker_task_runner_(worker_task_runner), + initial_time_(0), + times_(1), + recheck_time_(0), + ondemand_time_(0), + context_(new net::TestURLRequestContextGetter(network_task_runner)) { +} + +TestConfigurator::~TestConfigurator() { +} + +int TestConfigurator::InitialDelay() const { + return initial_time_; +} + +int TestConfigurator::NextCheckDelay() { + // This is called when a new full cycle of checking for updates is going + // to happen. In test we normally only test one cycle so it is a good + // time to break from the test messageloop Run() method so the test can + // finish. + if (--times_ <= 0) { + quit_closure_.Run(); + return 0; + } + return 1; +} + +int TestConfigurator::StepDelay() const { + return 0; +} + +int TestConfigurator::StepDelayMedium() { + return NextCheckDelay(); +} + +int TestConfigurator::MinimumReCheckWait() const { + return recheck_time_; +} + +int TestConfigurator::OnDemandDelay() const { + return ondemand_time_; +} + +int TestConfigurator::UpdateDelay() const { + return 1; +} + +std::vector<GURL> TestConfigurator::UpdateUrl() const { + return MakeDefaultUrls(); +} + +std::vector<GURL> TestConfigurator::PingUrl() const { + return UpdateUrl(); +} + +base::Version TestConfigurator::GetBrowserVersion() const { + // Needs to be larger than the required version in tested component manifests. + return base::Version("30.0"); +} + +std::string TestConfigurator::GetChannel() const { + return "fake_channel_string"; +} + +std::string TestConfigurator::GetLang() const { + return "fake_lang"; +} + +std::string TestConfigurator::GetOSLongName() const { + return "Fake Operating System"; +} + +std::string TestConfigurator::ExtraRequestParams() const { + return "extra=\"foo\""; +} + +size_t TestConfigurator::UrlSizeLimit() const { + return 256; +} + +net::URLRequestContextGetter* TestConfigurator::RequestContext() const { + return context_.get(); +} + +scoped_refptr<OutOfProcessPatcher> TestConfigurator::CreateOutOfProcessPatcher() + const { + return NULL; +} + +bool TestConfigurator::DeltasEnabled() const { + return true; +} + +bool TestConfigurator::UseBackgroundDownloader() const { + return false; +} + +// Set how many update checks are called, the default value is just once. +void TestConfigurator::SetLoopCount(int times) { + times_ = times; +} + +void TestConfigurator::SetRecheckTime(int seconds) { + recheck_time_ = seconds; +} + +void TestConfigurator::SetOnDemandTime(int seconds) { + ondemand_time_ = seconds; +} + +void TestConfigurator::SetQuitClosure(const base::Closure& quit_closure) { + quit_closure_ = quit_closure; +} + +void TestConfigurator::SetInitialDelay(int seconds) { + initial_time_ = seconds; +} + +scoped_refptr<base::SequencedTaskRunner> +TestConfigurator::GetSequencedTaskRunner() const { + DCHECK(worker_task_runner_.get()); + return worker_task_runner_; +} + +scoped_refptr<base::SingleThreadTaskRunner> +TestConfigurator::GetSingleThreadTaskRunner() const { + // This is NULL because tests do not use the background downloader. + return NULL; +} + +} // namespace update_client
diff --git a/components/update_client/test_configurator.h b/components/update_client/test_configurator.h new file mode 100644 index 0000000..6e441e76 --- /dev/null +++ b/components/update_client/test_configurator.h
@@ -0,0 +1,111 @@ +// 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_UPDATE_CLIENT_TEST_CONFIGURATOR_H_ +#define COMPONENTS_UPDATE_CLIENT_TEST_CONFIGURATOR_H_ + +#include <string> +#include <utility> +#include <vector> + +#include "base/callback.h" +#include "base/compiler_specific.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "components/update_client/configurator.h" +#include "net/url_request/url_request_test_util.h" + +class GURL; + +namespace base { +class SequencedTaskRunner; +class SingleThreadTaskRunner; +} // namespace base + +namespace update_client { + +#define POST_INTERCEPT_SCHEME "https" +#define POST_INTERCEPT_HOSTNAME "localhost2" +#define POST_INTERCEPT_PATH "/update2" + +struct CrxComponent; + +// component 1 has extension id "jebgalgnebhfojomionfpkfelancnnkf", and +// the RSA public key the following hash: +const uint8_t jebg_hash[] = {0x94, 0x16, 0x0b, 0x6d, 0x41, 0x75, 0xe9, 0xec, + 0x8e, 0xd5, 0xfa, 0x54, 0xb0, 0xd2, 0xdd, 0xa5, + 0x6e, 0x05, 0x6b, 0xe8, 0x73, 0x47, 0xf6, 0xc4, + 0x11, 0x9f, 0xbc, 0xb3, 0x09, 0xb3, 0x5b, 0x40}; +// component 2 has extension id "abagagagagagagagagagagagagagagag", and +// the RSA public key the following hash: +const uint8_t abag_hash[] = {0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, + 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01}; +// component 3 has extension id "ihfokbkgjpifnbbojhneepfflplebdkc", and +// the RSA public key the following hash: +const uint8_t ihfo_hash[] = {0x87, 0x5e, 0xa1, 0xa6, 0x9f, 0x85, 0xd1, 0x1e, + 0x97, 0xd4, 0x4f, 0x55, 0xbf, 0xb4, 0x13, 0xa2, + 0xe7, 0xc5, 0xc8, 0xf5, 0x60, 0x19, 0x78, 0x1b, + 0x6d, 0xe9, 0x4c, 0xeb, 0x96, 0x05, 0x42, 0x17}; + +class TestConfigurator : public Configurator { + public: + TestConfigurator( + const scoped_refptr<base::SequencedTaskRunner>& worker_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner); + + // Overrrides for Configurator. + int InitialDelay() const override; + int NextCheckDelay() override; + int StepDelay() const override; + int StepDelayMedium() override; + int MinimumReCheckWait() const override; + int OnDemandDelay() const override; + int UpdateDelay() const override; + std::vector<GURL> UpdateUrl() const override; + std::vector<GURL> PingUrl() const override; + base::Version GetBrowserVersion() const override; + std::string GetChannel() const override; + std::string GetLang() const override; + std::string GetOSLongName() const override; + std::string ExtraRequestParams() const override; + size_t UrlSizeLimit() const override; + net::URLRequestContextGetter* RequestContext() const override; + scoped_refptr<OutOfProcessPatcher> CreateOutOfProcessPatcher() const override; + bool DeltasEnabled() const override; + bool UseBackgroundDownloader() const override; + scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() + const override; + scoped_refptr<base::SingleThreadTaskRunner> GetSingleThreadTaskRunner() + const override; + + void SetLoopCount(int times); + void SetRecheckTime(int seconds); + void SetOnDemandTime(int seconds); + void SetQuitClosure(const base::Closure& quit_closure); + void SetInitialDelay(int seconds); + + private: + friend class base::RefCountedThreadSafe<TestConfigurator>; + + ~TestConfigurator() override; + + scoped_refptr<base::SequencedTaskRunner> worker_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; + + int initial_time_; + int times_; + int recheck_time_; + int ondemand_time_; + + scoped_refptr<net::TestURLRequestContextGetter> context_; + base::Closure quit_closure_; + + DISALLOW_COPY_AND_ASSIGN(TestConfigurator); +}; + +} // namespace update_client + +#endif // COMPONENTS_UPDATE_CLIENT_TEST_CONFIGURATOR_H_
diff --git a/components/update_client/test_installer.cc b/components/update_client/test_installer.cc new file mode 100644 index 0000000..ad6015b9 --- /dev/null +++ b/components/update_client/test_installer.cc
@@ -0,0 +1,85 @@ +// Copyright 2013 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/update_client/test_installer.h" + +#include <string> + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/values.h" + +namespace update_client { + +TestInstaller::TestInstaller() : error_(0), install_count_(0) { +} + +void TestInstaller::OnUpdateError(int error) { + error_ = error; +} + +bool TestInstaller::Install(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) { + ++install_count_; + return base::DeleteFile(unpack_path, true); +} + +bool TestInstaller::GetInstalledFile(const std::string& file, + base::FilePath* installed_file) { + return false; +} + +TestInstaller::~TestInstaller() { +} + +bool TestInstaller::Uninstall() { + return false; +} + +ReadOnlyTestInstaller::ReadOnlyTestInstaller(const base::FilePath& install_dir) + : install_directory_(install_dir) { +} + +ReadOnlyTestInstaller::~ReadOnlyTestInstaller() { +} + +bool ReadOnlyTestInstaller::GetInstalledFile(const std::string& file, + base::FilePath* installed_file) { + *installed_file = install_directory_.AppendASCII(file); + return true; +} + +VersionedTestInstaller::VersionedTestInstaller() { + base::CreateNewTempDirectory(FILE_PATH_LITERAL("TEST_"), &install_directory_); +} + +VersionedTestInstaller::~VersionedTestInstaller() { + base::DeleteFile(install_directory_, true); +} + +bool VersionedTestInstaller::Install(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) { + std::string version_string; + manifest.GetStringASCII("version", &version_string); + Version version(version_string.c_str()); + + base::FilePath path; + path = install_directory_.AppendASCII(version.GetString()); + base::CreateDirectory(path.DirName()); + if (!base::Move(unpack_path, path)) + return false; + current_version_ = version; + ++install_count_; + return true; +} + +bool VersionedTestInstaller::GetInstalledFile(const std::string& file, + base::FilePath* installed_file) { + base::FilePath path; + path = install_directory_.AppendASCII(current_version_.GetString()); + *installed_file = path.Append(base::FilePath::FromUTF8Unsafe(file)); + return true; +} + +} // namespace update_client
diff --git a/components/update_client/test_installer.h b/components/update_client/test_installer.h new file mode 100644 index 0000000..44a6f28 --- /dev/null +++ b/components/update_client/test_installer.h
@@ -0,0 +1,84 @@ +// Copyright 2013 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_UPDATE_CLIENT_TEST_INSTALLER_H_ +#define COMPONENTS_UPDATE_CLIENT_TEST_INSTALLER_H_ + +#include <string> + +#include "base/compiler_specific.h" +#include "base/files/file_path.h" +#include "components/update_client/update_client.h" + +namespace base { +class DictionaryValue; +} + +namespace update_client { + +// TODO(sorin): consider reducing the number of the installer mocks. +// A TestInstaller is an installer that does nothing for installation except +// increment a counter. +class TestInstaller : public CrxInstaller { + public: + TestInstaller(); + + void OnUpdateError(int error) override; + + bool Install(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) override; + + bool GetInstalledFile(const std::string& file, + base::FilePath* installed_file) override; + + bool Uninstall() override; + + int error() const { return error_; } + + int install_count() const { return install_count_; } + + protected: + ~TestInstaller() override; + + int error_; + int install_count_; +}; + +// A ReadOnlyTestInstaller is an installer that knows about files in an existing +// directory. It will not write to the directory. +class ReadOnlyTestInstaller : public TestInstaller { + public: + explicit ReadOnlyTestInstaller(const base::FilePath& installed_path); + + bool GetInstalledFile(const std::string& file, + base::FilePath* installed_file) override; + + private: + ~ReadOnlyTestInstaller() override; + + base::FilePath install_directory_; +}; + +// A VersionedTestInstaller is an installer that installs files into versioned +// directories (e.g. somedir/25.23.89.141/<files>). +class VersionedTestInstaller : public TestInstaller { + public: + VersionedTestInstaller(); + + bool Install(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) override; + + bool GetInstalledFile(const std::string& file, + base::FilePath* installed_file) override; + + private: + ~VersionedTestInstaller() override; + + base::FilePath install_directory_; + Version current_version_; +}; + +} // namespace update_client + +#endif // COMPONENTS_UPDATE_CLIENT_TEST_INSTALLER_H_
diff --git a/components/update_client/update_checker_unittest.cc b/components/update_client/update_checker_unittest.cc new file mode 100644 index 0000000..01fd5ef --- /dev/null +++ b/components/update_client/update_checker_unittest.cc
@@ -0,0 +1,237 @@ +// 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 "base/bind.h" +#include "base/bind_helpers.h" +#include "base/compiler_specific.h" +#include "base/files/file_util.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/version.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/test_configurator.h" +#include "components/update_client/update_checker.h" +#include "components/update_client/url_request_post_interceptor.h" +#include "net/url_request/url_request_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +using std::string; + +namespace update_client { + +namespace { + +base::FilePath test_file(const char* file) { + base::FilePath path; + PathService::Get(base::DIR_SOURCE_ROOT, &path); + return path.AppendASCII("components") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("update_client") + .AppendASCII(file); +} + +} // namespace + +class UpdateCheckerTest : public testing::Test { + public: + UpdateCheckerTest(); + ~UpdateCheckerTest() override; + + // Overrides from testing::Test. + void SetUp() override; + void TearDown() override; + + void UpdateCheckComplete(const GURL& original_url, + int error, + const std::string& error_message, + const UpdateResponse::Results& results); + + protected: + void Quit(); + void RunThreads(); + void RunThreadsUntilIdle(); + + CrxUpdateItem BuildCrxUpdateItem(); + + scoped_refptr<TestConfigurator> config_; + + scoped_ptr<UpdateChecker> update_checker_; + + scoped_ptr<InterceptorFactory> interceptor_factory_; + URLRequestPostInterceptor* post_interceptor_; // Owned by the factory. + + GURL original_url_; + int error_; + std::string error_message_; + UpdateResponse::Results results_; + + private: + base::MessageLoopForIO loop_; + base::Closure quit_closure_; + + DISALLOW_COPY_AND_ASSIGN(UpdateCheckerTest); +}; + +UpdateCheckerTest::UpdateCheckerTest() : post_interceptor_(NULL), error_(0) { +} + +UpdateCheckerTest::~UpdateCheckerTest() { +} + +void UpdateCheckerTest::SetUp() { + config_ = new TestConfigurator(base::MessageLoopProxy::current(), + base::MessageLoopProxy::current()); + interceptor_factory_.reset( + new InterceptorFactory(base::MessageLoopProxy::current())); + post_interceptor_ = interceptor_factory_->CreateInterceptor(); + EXPECT_TRUE(post_interceptor_); + + update_checker_.reset(); + + error_ = 0; + error_message_.clear(); + results_ = UpdateResponse::Results(); +} + +void UpdateCheckerTest::TearDown() { + update_checker_.reset(); + + post_interceptor_ = NULL; + interceptor_factory_.reset(); + + config_ = nullptr; + + // The PostInterceptor requires the message loop to run to destruct correctly. + // TODO(sorin): This is fragile and should be fixed. + RunThreadsUntilIdle(); +} + +void UpdateCheckerTest::RunThreads() { + base::RunLoop runloop; + quit_closure_ = runloop.QuitClosure(); + runloop.Run(); + + // Since some tests need to drain currently enqueued tasks such as network + // intercepts on the IO thread, run the threads until they are + // idle. The component updater service won't loop again until the loop count + // is set and the service is started. + RunThreadsUntilIdle(); +} + +void UpdateCheckerTest::RunThreadsUntilIdle() { + base::RunLoop().RunUntilIdle(); +} + +void UpdateCheckerTest::Quit() { + if (!quit_closure_.is_null()) + quit_closure_.Run(); +} + +void UpdateCheckerTest::UpdateCheckComplete( + const GURL& original_url, + int error, + const std::string& error_message, + const UpdateResponse::Results& results) { + original_url_ = original_url; + error_ = error; + error_message_ = error_message; + results_ = results; + Quit(); +} + +CrxUpdateItem UpdateCheckerTest::BuildCrxUpdateItem() { + CrxComponent crx_component; + crx_component.name = "test_jebg"; + crx_component.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + crx_component.installer = NULL; + crx_component.version = base::Version("0.9"); + crx_component.fingerprint = "fp1"; + + CrxUpdateItem crx_update_item; + crx_update_item.state = CrxUpdateItem::State::kNew; + crx_update_item.id = "jebgalgnebhfojomionfpkfelancnnkf"; + crx_update_item.component = crx_component; + + return crx_update_item; +} + +TEST_F(UpdateCheckerTest, UpdateCheckSuccess) { + EXPECT_TRUE(post_interceptor_->ExpectRequest( + new PartialMatch("updatecheck"), test_file("updatecheck_reply_1.xml"))); + + update_checker_ = UpdateChecker::Create(*config_).Pass(); + + CrxUpdateItem item(BuildCrxUpdateItem()); + std::vector<CrxUpdateItem*> items_to_check; + items_to_check.push_back(&item); + + update_checker_->CheckForUpdates( + items_to_check, "extra=\"params\"", + base::Bind(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + + RunThreads(); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + // Sanity check the request. + EXPECT_NE(string::npos, post_interceptor_->GetRequests()[0].find( + "request protocol=\"3.0\" extra=\"params\"")); + EXPECT_NE( + string::npos, + post_interceptor_->GetRequests()[0].find( + "app appid=\"jebgalgnebhfojomionfpkfelancnnkf\" version=\"0.9\">" + "<updatecheck /><packages><package fp=\"fp1\"/></packages></app>")); + + EXPECT_NE(string::npos, + post_interceptor_->GetRequests()[0].find("<hw physmemory=")); + + // Sanity check the arguments of the callback after parsing. + EXPECT_EQ(config_->UpdateUrl().front(), original_url_); + EXPECT_EQ(0, error_); + EXPECT_TRUE(error_message_.empty()); + EXPECT_EQ(1ul, results_.list.size()); + EXPECT_STREQ("jebgalgnebhfojomionfpkfelancnnkf", + results_.list[0].extension_id.c_str()); + EXPECT_STREQ("1.0", results_.list[0].manifest.version.c_str()); +} + +// Simulates a 403 server response error. +TEST_F(UpdateCheckerTest, UpdateCheckError) { + EXPECT_TRUE( + post_interceptor_->ExpectRequest(new PartialMatch("updatecheck"), 403)); + + update_checker_ = UpdateChecker::Create(*config_).Pass(); + + CrxUpdateItem item(BuildCrxUpdateItem()); + std::vector<CrxUpdateItem*> items_to_check; + items_to_check.push_back(&item); + + update_checker_->CheckForUpdates( + items_to_check, "", base::Bind(&UpdateCheckerTest::UpdateCheckComplete, + base::Unretained(this))); + + RunThreads(); + + EXPECT_EQ(1, post_interceptor_->GetHitCount()) + << post_interceptor_->GetRequestsAsString(); + EXPECT_EQ(1, post_interceptor_->GetCount()) + << post_interceptor_->GetRequestsAsString(); + + EXPECT_EQ(config_->UpdateUrl().front(), original_url_); + EXPECT_EQ(403, error_); + EXPECT_STREQ("network error", error_message_.c_str()); + EXPECT_EQ(0ul, results_.list.size()); +} + +} // namespace update_client
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc new file mode 100644 index 0000000..3cc3c4f1 --- /dev/null +++ b/components/update_client/update_client_unittest.cc
@@ -0,0 +1,1422 @@ +// 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/bind.h" +#include "base/bind_helpers.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/location.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/thread_task_runner_handle.h" +#include "base/values.h" +#include "base/version.h" +#include "components/update_client/crx_update_item.h" +#include "components/update_client/ping_manager.h" +#include "components/update_client/test_configurator.h" +#include "components/update_client/test_installer.h" +#include "components/update_client/update_checker.h" +#include "components/update_client/update_client_internal.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace update_client { + +namespace { + +using base::FilePath; + +// Makes a copy of the file specified by |from_path| in a temporary directory +// and returns the path of the copy. Returns true if successful. Cleans up if +// there was an error creating the copy. +bool MakeTestFile(const FilePath& from_path, FilePath* to_path) { + FilePath temp_dir; + bool result = + CreateNewTempDirectory(FILE_PATH_LITERAL("update_client"), &temp_dir); + if (!result) + return false; + + FilePath temp_file; + result = CreateTemporaryFileInDir(temp_dir, &temp_file); + if (!result) + return false; + + result = CopyFile(from_path, temp_file); + if (!result) { + DeleteFile(temp_file, false); + return false; + } + + *to_path = temp_file; + return true; +} + +using Events = UpdateClient::Observer::Events; + +class MockObserver : public UpdateClient::Observer { + public: + MOCK_METHOD2(OnEvent, void(Events event, const std::string&)); +}; + +class FakePingManagerImpl : public PingManager { + public: + explicit FakePingManagerImpl(const Configurator& config); + ~FakePingManagerImpl() override; + + void OnUpdateComplete(const CrxUpdateItem* item) override; + + const std::vector<CrxUpdateItem>& items() const; + + private: + std::vector<CrxUpdateItem> items_; + DISALLOW_COPY_AND_ASSIGN(FakePingManagerImpl); +}; + +FakePingManagerImpl::FakePingManagerImpl(const Configurator& config) + : PingManager(config) { +} + +FakePingManagerImpl::~FakePingManagerImpl() { +} + +void FakePingManagerImpl::OnUpdateComplete(const CrxUpdateItem* item) { + items_.push_back(*item); +} + +const std::vector<CrxUpdateItem>& FakePingManagerImpl::items() const { + return items_; +} + +} // namespace + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::Mock; +using ::testing::Return; + +using content::BrowserThread; + +using std::string; + +class UpdateClientTest : public testing::Test { + public: + UpdateClientTest(); + ~UpdateClientTest() override; + + void SetUp() override; + void TearDown() override; + + protected: + void RunThreads(); + + // Returns the full path to a test file. + static base::FilePath TestFilePath(const char* file); + + content::TestBrowserThreadBundle thread_bundle_; + + base::RunLoop runloop_; + base::Closure quit_closure_; + + scoped_refptr<update_client::TestConfigurator> config_; + + private: + DISALLOW_COPY_AND_ASSIGN(UpdateClientTest); +}; + +UpdateClientTest::UpdateClientTest() + : config_(new TestConfigurator( + BrowserThread::GetBlockingPool() + ->GetSequencedTaskRunnerWithShutdownBehavior( + BrowserThread::GetBlockingPool()->GetSequenceToken(), + base::SequencedWorkerPool::SKIP_ON_SHUTDOWN), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) { +} + +UpdateClientTest::~UpdateClientTest() { +} + +void UpdateClientTest::SetUp() { + quit_closure_ = runloop_.QuitClosure(); +} + +void UpdateClientTest::TearDown() { +} + +void UpdateClientTest::RunThreads() { + runloop_.Run(); +} + +base::FilePath UpdateClientTest::TestFilePath(const char* file) { + base::FilePath path; + PathService::Get(base::DIR_SOURCE_ROOT, &path); + return path.AppendASCII("components") + .AppendASCII("test") + .AppendASCII("data") + .AppendASCII("update_client") + .AppendASCII(file); +} + +// Tests the scenario where one update check is done for one CRX. The CRX +// has no update. +TEST_F(UpdateClientTest, OneCrxNoUpdate) { + class DataCallbackFake { + public: + static void Callback(const std::vector<std::string>& ids, + std::vector<CrxComponent>* components) { + CrxComponent crx; + crx.name = "test_jebg"; + crx.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + crx.version = Version("0.9"); + crx.installer = new TestInstaller; + components->push_back(crx); + } + }; + + class CompletionCallbackFake { + public: + static void Callback(const base::Closure& quit_closure, int error) { + EXPECT_EQ(0, error); + quit_closure.Run(); + } + }; + + class FakeUpdateChecker : public UpdateChecker { + public: + static scoped_ptr<UpdateChecker> Create(const Configurator& config) { + return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); + } + + bool CheckForUpdates( + const std::vector<CrxUpdateItem*>& items_to_check, + const std::string& additional_attributes, + const UpdateCheckCallback& update_check_callback) override { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", + UpdateResponse::Results())); + return true; + } + }; + + class FakeCrxDownloader : public CrxDownloader { + public: + static scoped_ptr<CrxDownloader> Create( + bool is_background_download, + net::URLRequestContextGetter* context_getter, + const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& + background_task_runner) { + return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); + } + + private: + FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} + ~FakeCrxDownloader() override {} + + void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); } + }; + + class FakePingManager : public FakePingManagerImpl { + public: + explicit FakePingManager(const Configurator& config) + : FakePingManagerImpl(config) {} + ~FakePingManager() override { EXPECT_TRUE(items().empty()); } + }; + + scoped_ptr<PingManager> ping_manager(new FakePingManager(*config_)); + scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( + config_, ping_manager.Pass(), &FakeUpdateChecker::Create, + &FakeCrxDownloader::Create)); + + MockObserver observer; + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + + update_client->AddObserver(&observer); + + std::vector<std::string> ids; + ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf")); + + update_client->Update( + ids, base::Bind(&DataCallbackFake::Callback), + base::Bind(&CompletionCallbackFake::Callback, quit_closure_)); + + RunThreads(); + + update_client->RemoveObserver(&observer); +} + +// Tests the scenario where two CRXs are checked for updates. On CRX has +// an update, the other CRX does not. +TEST_F(UpdateClientTest, TwoCrxUpdateNoUpdate) { + class DataCallbackFake { + public: + static void Callback(const std::vector<std::string>& ids, + std::vector<CrxComponent>* components) { + CrxComponent crx1; + crx1.name = "test_jebg"; + crx1.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + crx1.version = Version("0.9"); + crx1.installer = new TestInstaller; + + CrxComponent crx2; + crx2.name = "test_abag"; + crx2.pk_hash.assign(abag_hash, abag_hash + arraysize(abag_hash)); + crx2.version = Version("2.2"); + crx2.installer = new TestInstaller; + + components->push_back(crx1); + components->push_back(crx2); + } + }; + + class CompletionCallbackFake { + public: + static void Callback(const base::Closure& quit_closure, int error) { + EXPECT_EQ(0, error); + quit_closure.Run(); + } + }; + + class FakeUpdateChecker : public UpdateChecker { + public: + static scoped_ptr<UpdateChecker> Create(const Configurator& config) { + return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); + } + + bool CheckForUpdates( + const std::vector<CrxUpdateItem*>& items_to_check, + const std::string& additional_attributes, + const UpdateCheckCallback& update_check_callback) override { + /* + Fake the following response: + + <?xml version='1.0' encoding='UTF-8'?> + <response protocol='3.0'> + <app appid='jebgalgnebhfojomionfpkfelancnnkf'> + <updatecheck status='ok'> + <urls> + <url codebase='http://localhost/download/'/> + </urls> + <manifest version='1.0' prodversionmin='11.0.1.0'> + <packages> + <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> + </packages> + </manifest> + </updatecheck> + </app> + </response> + */ + UpdateResponse::Result::Manifest::Package package; + package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx"; + + UpdateResponse::Result result; + result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf"; + result.crx_urls.push_back(GURL("http://localhost/download/")); + result.manifest.version = "1.0"; + result.manifest.browser_min_version = "11.0.1.0"; + result.manifest.packages.push_back(package); + + UpdateResponse::Results results; + results.list.push_back(result); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); + return true; + } + }; + + class FakeCrxDownloader : public CrxDownloader { + public: + static scoped_ptr<CrxDownloader> Create( + bool is_background_download, + net::URLRequestContextGetter* context_getter, + const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& + background_task_runner) { + return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); + } + + private: + FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} + ~FakeCrxDownloader() override {} + + void DoStartDownload(const GURL& url) override { + DownloadMetrics download_metrics; + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 1843; + download_metrics.total_bytes = 1843; + download_metrics.download_time_ms = 1000; + + FilePath path; + EXPECT_TRUE(MakeTestFile( + TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path)); + + Result result; + result.error = 0; + result.response = path; + result.downloaded_bytes = 1843; + result.total_bytes = 1843; + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, + base::Unretained(this), result)); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&FakeCrxDownloader::OnDownloadComplete, + base::Unretained(this), true, result, download_metrics)); + } + }; + + class FakePingManager : public FakePingManagerImpl { + public: + explicit FakePingManager(const Configurator& config) + : FakePingManagerImpl(config) {} + ~FakePingManager() override { + const auto& ping_items = items(); + EXPECT_EQ(1U, ping_items.size()); + EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id); + EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version)); + EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); + EXPECT_EQ(0, ping_items[0].error_category); + EXPECT_EQ(0, ping_items[0].error_code); + } + }; + + scoped_ptr<PingManager> ping_manager(new FakePingManager(*config_)); + scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( + config_, ping_manager.Pass(), &FakeUpdateChecker::Create, + &FakeCrxDownloader::Create)); + + MockObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + } + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "abagagagagagagagagagagagagagagag")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "abagagagagagagagagagagagagagagag")).Times(1); + } + + update_client->AddObserver(&observer); + + std::vector<std::string> ids; + ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf")); + ids.push_back(std::string("abagagagagagagagagagagagagagagag")); + + update_client->Update( + ids, base::Bind(&DataCallbackFake::Callback), + base::Bind(&CompletionCallbackFake::Callback, quit_closure_)); + + RunThreads(); + + update_client->RemoveObserver(&observer); +} + +// Tests the update check for two CRXs scenario. Both CRXs have updates. +TEST_F(UpdateClientTest, TwoCrxUpdate) { + class DataCallbackFake { + public: + static void Callback(const std::vector<std::string>& ids, + std::vector<CrxComponent>* components) { + CrxComponent crx1; + crx1.name = "test_jebg"; + crx1.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + crx1.version = Version("0.9"); + crx1.installer = new TestInstaller; + + CrxComponent crx2; + crx2.name = "test_ihfo"; + crx2.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); + crx2.version = Version("0.8"); + crx2.installer = new TestInstaller; + + components->push_back(crx1); + components->push_back(crx2); + } + }; + + class CompletionCallbackFake { + public: + static void Callback(const base::Closure& quit_closure, int error) { + EXPECT_EQ(0, error); + quit_closure.Run(); + } + }; + + class FakeUpdateChecker : public UpdateChecker { + public: + static scoped_ptr<UpdateChecker> Create(const Configurator& config) { + return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); + } + + bool CheckForUpdates( + const std::vector<CrxUpdateItem*>& items_to_check, + const std::string& additional_attributes, + const UpdateCheckCallback& update_check_callback) override { + /* + Fake the following response: + + <?xml version='1.0' encoding='UTF-8'?> + <response protocol='3.0'> + <app appid='jebgalgnebhfojomionfpkfelancnnkf'> + <updatecheck status='ok'> + <urls> + <url codebase='http://localhost/download/'/> + </urls> + <manifest version='1.0' prodversionmin='11.0.1.0'> + <packages> + <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> + </packages> + </manifest> + </updatecheck> + </app> + <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> + <updatecheck status='ok'> + <urls> + <url codebase='http://localhost/download/'/> + </urls> + <manifest version='1.0' prodversionmin='11.0.1.0'> + <packages> + <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/> + </packages> + </manifest> + </updatecheck> + </app> + </response> + */ + UpdateResponse::Result::Manifest::Package package1; + package1.name = "jebgalgnebhfojomionfpkfelancnnkf.crx"; + + UpdateResponse::Result result1; + result1.extension_id = "jebgalgnebhfojomionfpkfelancnnkf"; + result1.crx_urls.push_back(GURL("http://localhost/download/")); + result1.manifest.version = "1.0"; + result1.manifest.browser_min_version = "11.0.1.0"; + result1.manifest.packages.push_back(package1); + + UpdateResponse::Result::Manifest::Package package2; + package2.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"; + + UpdateResponse::Result result2; + result2.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; + result2.crx_urls.push_back(GURL("http://localhost/download/")); + result2.manifest.version = "1.0"; + result2.manifest.browser_min_version = "11.0.1.0"; + result2.manifest.packages.push_back(package2); + + UpdateResponse::Results results; + results.list.push_back(result1); + results.list.push_back(result2); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); + return true; + } + }; + + class FakeCrxDownloader : public CrxDownloader { + public: + static scoped_ptr<CrxDownloader> Create( + bool is_background_download, + net::URLRequestContextGetter* context_getter, + const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& + background_task_runner) { + return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); + } + + private: + FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} + ~FakeCrxDownloader() override {} + + void DoStartDownload(const GURL& url) override { + DownloadMetrics download_metrics; + FilePath path; + Result result; + if (url.path() == "/download/jebgalgnebhfojomionfpkfelancnnkf.crx") { + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 1843; + download_metrics.total_bytes = 1843; + download_metrics.download_time_ms = 1000; + + EXPECT_TRUE(MakeTestFile( + TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path)); + + result.error = 0; + result.response = path; + result.downloaded_bytes = 1843; + result.total_bytes = 1843; + } else if (url.path() == + "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") { + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 53638; + download_metrics.total_bytes = 53638; + download_metrics.download_time_ms = 2000; + + EXPECT_TRUE(MakeTestFile( + TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path)); + + result.error = 0; + result.response = path; + result.downloaded_bytes = 53638; + result.total_bytes = 53638; + } else { + NOTREACHED(); + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, + base::Unretained(this), result)); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&FakeCrxDownloader::OnDownloadComplete, + base::Unretained(this), true, result, download_metrics)); + } + }; + + class FakePingManager : public FakePingManagerImpl { + public: + explicit FakePingManager(const Configurator& config) + : FakePingManagerImpl(config) {} + ~FakePingManager() override { + const auto& ping_items = items(); + EXPECT_EQ(2U, ping_items.size()); + EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id); + EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version)); + EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); + EXPECT_EQ(0, ping_items[0].error_category); + EXPECT_EQ(0, ping_items[0].error_code); + EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id); + EXPECT_TRUE(base::Version("0.8").Equals(ping_items[1].previous_version)); + EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].next_version)); + EXPECT_EQ(0, ping_items[1].error_category); + EXPECT_EQ(0, ping_items[1].error_code); + } + }; + + scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config_)); + scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( + config_, ping_manager.Pass(), &FakeUpdateChecker::Create, + &FakeCrxDownloader::Create)); + + MockObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + } + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_WAIT, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + } + + update_client->AddObserver(&observer); + + std::vector<std::string> ids; + ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf")); + ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc")); + + update_client->Update( + ids, base::Bind(&DataCallbackFake::Callback), + base::Bind(&CompletionCallbackFake::Callback, quit_closure_)); + + RunThreads(); + + update_client->RemoveObserver(&observer); +} + +// Tests the differential update scenario for one CRX. +TEST_F(UpdateClientTest, OneCrxDiffUpdate) { + class DataCallbackFake { + public: + static void Callback(const std::vector<std::string>& ids, + std::vector<CrxComponent>* components) { + static int num_calls = 0; + + // Must use the same stateful installer object. + static scoped_refptr<CrxInstaller> installer( + new VersionedTestInstaller()); + + ++num_calls; + + CrxComponent crx; + crx.name = "test_ihfo"; + crx.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); + crx.installer = installer; + if (num_calls == 1) { + crx.version = Version("0.8"); + } else if (num_calls == 2) { + crx.version = Version("1.0"); + } else { + NOTREACHED(); + } + + components->push_back(crx); + } + }; + + class CompletionCallbackFake { + public: + static void Callback(const base::Closure& quit_closure, int error) { + EXPECT_EQ(0, error); + quit_closure.Run(); + } + }; + + class FakeUpdateChecker : public UpdateChecker { + public: + static scoped_ptr<UpdateChecker> Create(const Configurator& config) { + return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); + } + + bool CheckForUpdates( + const std::vector<CrxUpdateItem*>& items_to_check, + const std::string& additional_attributes, + const UpdateCheckCallback& update_check_callback) override { + static int num_call = 0; + ++num_call; + + UpdateResponse::Results results; + + if (num_call == 1) { + /* + Fake the following response: + <?xml version='1.0' encoding='UTF-8'?> + <response protocol='3.0'> + <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> + <updatecheck status='ok'> + <urls> + <url codebase='http://localhost/download/'/> + </urls> + <manifest version='1.0' prodversionmin='11.0.1.0'> + <packages> + <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/> + </packages> + </manifest> + </updatecheck> + </app> + </response> + */ + UpdateResponse::Result::Manifest::Package package; + package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"; + package.fingerprint = "1"; + UpdateResponse::Result result; + result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; + result.crx_urls.push_back(GURL("http://localhost/download/")); + result.manifest.version = "1.0"; + result.manifest.browser_min_version = "11.0.1.0"; + result.manifest.packages.push_back(package); + results.list.push_back(result); + } else if (num_call == 2) { + /* + Fake the following response: + <?xml version='1.0' encoding='UTF-8'?> + <response protocol='3.0'> + <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> + <updatecheck status='ok'> + <urls> + <url codebase='http://localhost/download/'/> + <url codebasediff='http://localhost/download/'/> + </urls> + <manifest version='2.0' prodversionmin='11.0.1.0'> + <packages> + <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx' + namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx' + fp='22'/> + </packages> + </manifest> + </updatecheck> + </app> + </response> + */ + UpdateResponse::Result::Manifest::Package package; + package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"; + package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"; + package.fingerprint = "22"; + UpdateResponse::Result result; + result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; + result.crx_urls.push_back(GURL("http://localhost/download/")); + result.crx_diffurls.push_back(GURL("http://localhost/download/")); + result.manifest.version = "2.0"; + result.manifest.browser_min_version = "11.0.1.0"; + result.manifest.packages.push_back(package); + results.list.push_back(result); + } else { + NOTREACHED(); + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); + return true; + } + }; + + class FakeCrxDownloader : public CrxDownloader { + public: + static scoped_ptr<CrxDownloader> Create( + bool is_background_download, + net::URLRequestContextGetter* context_getter, + const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& + background_task_runner) { + return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); + } + + private: + FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} + ~FakeCrxDownloader() override {} + + void DoStartDownload(const GURL& url) override { + DownloadMetrics download_metrics; + FilePath path; + Result result; + if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") { + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 53638; + download_metrics.total_bytes = 53638; + download_metrics.download_time_ms = 2000; + + EXPECT_TRUE(MakeTestFile( + TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path)); + + result.error = 0; + result.response = path; + result.downloaded_bytes = 53638; + result.total_bytes = 53638; + } else if (url.path() == + "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") { + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 2105; + download_metrics.total_bytes = 2105; + download_metrics.download_time_ms = 1000; + + EXPECT_TRUE(MakeTestFile( + TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), &path)); + + result.error = 0; + result.response = path; + result.downloaded_bytes = 2105; + result.total_bytes = 2105; + } else { + NOTREACHED(); + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, + base::Unretained(this), result)); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&FakeCrxDownloader::OnDownloadComplete, + base::Unretained(this), true, result, download_metrics)); + } + }; + + class FakePingManager : public FakePingManagerImpl { + public: + explicit FakePingManager(const Configurator& config) + : FakePingManagerImpl(config) {} + ~FakePingManager() override { + const auto& ping_items = items(); + EXPECT_EQ(2U, ping_items.size()); + EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[0].id); + EXPECT_TRUE(base::Version("0.8").Equals(ping_items[0].previous_version)); + EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); + EXPECT_EQ(0, ping_items[0].error_category); + EXPECT_EQ(0, ping_items[0].error_code); + EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id); + EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].previous_version)); + EXPECT_TRUE(base::Version("2.0").Equals(ping_items[1].next_version)); + EXPECT_EQ(0, ping_items[1].diff_error_category); + EXPECT_EQ(0, ping_items[1].diff_error_code); + } + }; + + scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config_)); + scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( + config_, ping_manager.Pass(), &FakeUpdateChecker::Create, + &FakeCrxDownloader::Create)); + + MockObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + } + + update_client->AddObserver(&observer); + + std::vector<std::string> ids; + ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc")); + + { + base::RunLoop runloop; + update_client->Update( + ids, base::Bind(&DataCallbackFake::Callback), + base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure())); + runloop.Run(); + } + + { + base::RunLoop runloop; + update_client->Update( + ids, base::Bind(&DataCallbackFake::Callback), + base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure())); + runloop.Run(); + } + + update_client->RemoveObserver(&observer); +} + +// Tests the update scenario for one CRX where the CRX installer returns +// an error. +TEST_F(UpdateClientTest, OneCrxInstallError) { + class MockInstaller : public CrxInstaller { + public: + MOCK_METHOD1(OnUpdateError, void(int error)); + MOCK_METHOD2(Install, + bool(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path)); + MOCK_METHOD2(GetInstalledFile, + bool(const std::string& file, base::FilePath* installed_file)); + MOCK_METHOD0(Uninstall, bool()); + + static void OnInstall(const base::DictionaryValue& manifest, + const base::FilePath& unpack_path) { + base::DeleteFile(unpack_path, true); + } + + protected: + ~MockInstaller() override {} + }; + + class DataCallbackFake { + public: + static void Callback(const std::vector<std::string>& ids, + std::vector<CrxComponent>* components) { + scoped_refptr<MockInstaller> installer(new MockInstaller()); + + EXPECT_CALL(*installer, OnUpdateError(_)).Times(0); + EXPECT_CALL(*installer, Install(_, _)) + .WillOnce(DoAll(Invoke(MockInstaller::OnInstall), Return(false))); + EXPECT_CALL(*installer, GetInstalledFile(_, _)).Times(0); + EXPECT_CALL(*installer, Uninstall()).Times(0); + + CrxComponent crx; + crx.name = "test_jebg"; + crx.pk_hash.assign(jebg_hash, jebg_hash + arraysize(jebg_hash)); + crx.version = Version("0.9"); + crx.installer = installer; + components->push_back(crx); + } + }; + + class CompletionCallbackFake { + public: + static void Callback(const base::Closure& quit_closure, int error) { + EXPECT_EQ(0, error); + quit_closure.Run(); + } + }; + + class FakeUpdateChecker : public UpdateChecker { + public: + static scoped_ptr<UpdateChecker> Create(const Configurator& config) { + return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); + } + + bool CheckForUpdates( + const std::vector<CrxUpdateItem*>& items_to_check, + const std::string& additional_attributes, + const UpdateCheckCallback& update_check_callback) override { + /* + Fake the following response: + + <?xml version='1.0' encoding='UTF-8'?> + <response protocol='3.0'> + <app appid='jebgalgnebhfojomionfpkfelancnnkf'> + <updatecheck status='ok'> + <urls> + <url codebase='http://localhost/download/'/> + </urls> + <manifest version='1.0' prodversionmin='11.0.1.0'> + <packages> + <package name='jebgalgnebhfojomionfpkfelancnnkf.crx'/> + </packages> + </manifest> + </updatecheck> + </app> + </response> + */ + UpdateResponse::Result::Manifest::Package package; + package.name = "jebgalgnebhfojomionfpkfelancnnkf.crx"; + + UpdateResponse::Result result; + result.extension_id = "jebgalgnebhfojomionfpkfelancnnkf"; + result.crx_urls.push_back(GURL("http://localhost/download/")); + result.manifest.version = "1.0"; + result.manifest.browser_min_version = "11.0.1.0"; + result.manifest.packages.push_back(package); + + UpdateResponse::Results results; + results.list.push_back(result); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); + return true; + } + }; + + class FakeCrxDownloader : public CrxDownloader { + public: + static scoped_ptr<CrxDownloader> Create( + bool is_background_download, + net::URLRequestContextGetter* context_getter, + const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& + background_task_runner) { + return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); + } + + private: + FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} + ~FakeCrxDownloader() override {} + + void DoStartDownload(const GURL& url) override { + DownloadMetrics download_metrics; + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 1843; + download_metrics.total_bytes = 1843; + download_metrics.download_time_ms = 1000; + + FilePath path; + EXPECT_TRUE(MakeTestFile( + TestFilePath("jebgalgnebhfojomionfpkfelancnnkf.crx"), &path)); + + Result result; + result.error = 0; + result.response = path; + result.downloaded_bytes = 1843; + result.total_bytes = 1843; + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, + base::Unretained(this), result)); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&FakeCrxDownloader::OnDownloadComplete, + base::Unretained(this), true, result, download_metrics)); + } + }; + + class FakePingManager : public FakePingManagerImpl { + public: + explicit FakePingManager(const Configurator& config) + : FakePingManagerImpl(config) {} + ~FakePingManager() override { + const auto& ping_items = items(); + EXPECT_EQ(1U, ping_items.size()); + EXPECT_EQ("jebgalgnebhfojomionfpkfelancnnkf", ping_items[0].id); + EXPECT_TRUE(base::Version("0.9").Equals(ping_items[0].previous_version)); + EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); + EXPECT_EQ(3, ping_items[0].error_category); // kInstallError. + EXPECT_EQ(9, ping_items[0].error_code); // kInstallerError. + } + }; + + scoped_ptr<PingManager> ping_manager(new FakePingManager(*config_)); + scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( + config_, ping_manager.Pass(), &FakeUpdateChecker::Create, + &FakeCrxDownloader::Create)); + + MockObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_NOT_UPDATED, + "jebgalgnebhfojomionfpkfelancnnkf")).Times(1); + } + + update_client->AddObserver(&observer); + + std::vector<std::string> ids; + ids.push_back(std::string("jebgalgnebhfojomionfpkfelancnnkf")); + + update_client->Update( + ids, base::Bind(&DataCallbackFake::Callback), + base::Bind(&CompletionCallbackFake::Callback, quit_closure_)); + + RunThreads(); + + update_client->RemoveObserver(&observer); +} + +// Tests the fallback from differential to full update scenario for one CRX. +TEST_F(UpdateClientTest, OneCrxDiffUpdateFailsFullUpdateSucceeds) { + class DataCallbackFake { + public: + static void Callback(const std::vector<std::string>& ids, + std::vector<CrxComponent>* components) { + static int num_calls = 0; + + // Must use the same stateful installer object. + static scoped_refptr<CrxInstaller> installer( + new VersionedTestInstaller()); + + ++num_calls; + + CrxComponent crx; + crx.name = "test_ihfo"; + crx.pk_hash.assign(ihfo_hash, ihfo_hash + arraysize(ihfo_hash)); + crx.installer = installer; + if (num_calls == 1) { + crx.version = Version("0.8"); + } else if (num_calls == 2) { + crx.version = Version("1.0"); + } else { + NOTREACHED(); + } + + components->push_back(crx); + } + }; + + class CompletionCallbackFake { + public: + static void Callback(const base::Closure& quit_closure, int error) { + EXPECT_EQ(0, error); + quit_closure.Run(); + } + }; + + class FakeUpdateChecker : public UpdateChecker { + public: + static scoped_ptr<UpdateChecker> Create(const Configurator& config) { + return scoped_ptr<UpdateChecker>(new FakeUpdateChecker()); + } + + bool CheckForUpdates( + const std::vector<CrxUpdateItem*>& items_to_check, + const std::string& additional_attributes, + const UpdateCheckCallback& update_check_callback) override { + static int num_call = 0; + ++num_call; + + UpdateResponse::Results results; + + if (num_call == 1) { + /* + Fake the following response: + <?xml version='1.0' encoding='UTF-8'?> + <response protocol='3.0'> + <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> + <updatecheck status='ok'> + <urls> + <url codebase='http://localhost/download/'/> + </urls> + <manifest version='1.0' prodversionmin='11.0.1.0'> + <packages> + <package name='ihfokbkgjpifnbbojhneepfflplebdkc_1.crx'/> + </packages> + </manifest> + </updatecheck> + </app> + </response> + */ + UpdateResponse::Result::Manifest::Package package; + package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"; + package.fingerprint = "1"; + UpdateResponse::Result result; + result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; + result.crx_urls.push_back(GURL("http://localhost/download/")); + result.manifest.version = "1.0"; + result.manifest.browser_min_version = "11.0.1.0"; + result.manifest.packages.push_back(package); + results.list.push_back(result); + } else if (num_call == 2) { + /* + Fake the following response: + <?xml version='1.0' encoding='UTF-8'?> + <response protocol='3.0'> + <app appid='ihfokbkgjpifnbbojhneepfflplebdkc'> + <updatecheck status='ok'> + <urls> + <url codebase='http://localhost/download/'/> + <url codebasediff='http://localhost/download/'/> + </urls> + <manifest version='2.0' prodversionmin='11.0.1.0'> + <packages> + <package name='ihfokbkgjpifnbbojhneepfflplebdkc_2.crx' + namediff='ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx' + fp='22'/> + </packages> + </manifest> + </updatecheck> + </app> + </response> + */ + UpdateResponse::Result::Manifest::Package package; + package.name = "ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"; + package.namediff = "ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"; + package.fingerprint = "22"; + UpdateResponse::Result result; + result.extension_id = "ihfokbkgjpifnbbojhneepfflplebdkc"; + result.crx_urls.push_back(GURL("http://localhost/download/")); + result.crx_diffurls.push_back(GURL("http://localhost/download/")); + result.manifest.version = "2.0"; + result.manifest.browser_min_version = "11.0.1.0"; + result.manifest.packages.push_back(package); + results.list.push_back(result); + } else { + NOTREACHED(); + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(update_check_callback, GURL(), 0, "", results)); + return true; + } + }; + + class FakeCrxDownloader : public CrxDownloader { + public: + static scoped_ptr<CrxDownloader> Create( + bool is_background_download, + net::URLRequestContextGetter* context_getter, + const scoped_refptr<base::SequencedTaskRunner>& url_fetcher_task_runner, + const scoped_refptr<base::SingleThreadTaskRunner>& + background_task_runner) { + return scoped_ptr<CrxDownloader>(new FakeCrxDownloader()); + } + + private: + FakeCrxDownloader() : CrxDownloader(scoped_ptr<CrxDownloader>().Pass()) {} + ~FakeCrxDownloader() override {} + + void DoStartDownload(const GURL& url) override { + DownloadMetrics download_metrics; + FilePath path; + Result result; + if (url.path() == "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1.crx") { + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 53638; + download_metrics.total_bytes = 53638; + download_metrics.download_time_ms = 2000; + + EXPECT_TRUE(MakeTestFile( + TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1.crx"), &path)); + + result.error = 0; + result.response = path; + result.downloaded_bytes = 53638; + result.total_bytes = 53638; + } else if (url.path() == + "/download/ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx") { + // A download error is injected on this execution path. + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = -1; + download_metrics.downloaded_bytes = 0; + download_metrics.total_bytes = 2105; + download_metrics.download_time_ms = 1000; + + EXPECT_TRUE(MakeTestFile( + TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_1to2.crx"), &path)); + + result.error = -1; + result.response = path; + result.downloaded_bytes = 0; + result.total_bytes = 2105; + } else if (url.path() == + "/download/ihfokbkgjpifnbbojhneepfflplebdkc_2.crx") { + download_metrics.url = url; + download_metrics.downloader = DownloadMetrics::kNone; + download_metrics.error = 0; + download_metrics.downloaded_bytes = 53855; + download_metrics.total_bytes = 53855; + download_metrics.download_time_ms = 1000; + + EXPECT_TRUE(MakeTestFile( + TestFilePath("ihfokbkgjpifnbbojhneepfflplebdkc_2.crx"), &path)); + + result.error = 0; + result.response = path; + result.downloaded_bytes = 53855; + result.total_bytes = 53855; + } + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(&FakeCrxDownloader::OnDownloadProgress, + base::Unretained(this), result)); + + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&FakeCrxDownloader::OnDownloadComplete, + base::Unretained(this), true, result, download_metrics)); + } + }; + + class FakePingManager : public FakePingManagerImpl { + public: + explicit FakePingManager(const Configurator& config) + : FakePingManagerImpl(config) {} + ~FakePingManager() override { + const auto& ping_items = items(); + EXPECT_EQ(2U, ping_items.size()); + EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[0].id); + EXPECT_TRUE(base::Version("0.8").Equals(ping_items[0].previous_version)); + EXPECT_TRUE(base::Version("1.0").Equals(ping_items[0].next_version)); + EXPECT_EQ(0, ping_items[0].error_category); + EXPECT_EQ(0, ping_items[0].error_code); + EXPECT_EQ("ihfokbkgjpifnbbojhneepfflplebdkc", ping_items[1].id); + EXPECT_TRUE(base::Version("1.0").Equals(ping_items[1].previous_version)); + EXPECT_TRUE(base::Version("2.0").Equals(ping_items[1].next_version)); + EXPECT_TRUE(ping_items[1].diff_update_failed); + EXPECT_EQ(1, ping_items[1].diff_error_category); // kNetworkError. + EXPECT_EQ(-1, ping_items[1].diff_error_code); + } + }; + + scoped_ptr<FakePingManager> ping_manager(new FakePingManager(*config_)); + scoped_ptr<UpdateClient> update_client(new UpdateClientImpl( + config_, ping_manager.Pass(), &FakeUpdateChecker::Create, + &FakeCrxDownloader::Create)); + + MockObserver observer; + { + InSequence seq; + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_CHECKING_FOR_UPDATES, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_FOUND, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_DOWNLOADING, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATE_READY, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + EXPECT_CALL(observer, OnEvent(Events::COMPONENT_UPDATED, + "ihfokbkgjpifnbbojhneepfflplebdkc")).Times(1); + } + + update_client->AddObserver(&observer); + + std::vector<std::string> ids; + ids.push_back(std::string("ihfokbkgjpifnbbojhneepfflplebdkc")); + + { + base::RunLoop runloop; + update_client->Update( + ids, base::Bind(&DataCallbackFake::Callback), + base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure())); + runloop.Run(); + } + + { + base::RunLoop runloop; + update_client->Update( + ids, base::Bind(&DataCallbackFake::Callback), + base::Bind(&CompletionCallbackFake::Callback, runloop.QuitClosure())); + runloop.Run(); + } + + update_client->RemoveObserver(&observer); +} + +} // namespace update_client
diff --git a/components/update_client/test/update_response_unittest.cc b/components/update_client/update_response_unittest.cc similarity index 100% rename from components/update_client/test/update_response_unittest.cc rename to components/update_client/update_response_unittest.cc
diff --git a/components/update_client/url_request_post_interceptor.cc b/components/update_client/url_request_post_interceptor.cc new file mode 100644 index 0000000..caf179a --- /dev/null +++ b/components/update_client/url_request_post_interceptor.cc
@@ -0,0 +1,301 @@ +// Copyright 2013 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/update_client/url_request_post_interceptor.h" + +#include "base/files/file_util.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/stringprintf.h" +#include "components/update_client/test_configurator.h" +#include "net/base/upload_bytes_element_reader.h" +#include "net/base/upload_data_stream.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_filter.h" +#include "net/url_request/url_request_interceptor.h" +#include "net/url_request/url_request_simple_job.h" +#include "net/url_request/url_request_test_util.h" + +namespace update_client { + +// Returns a canned response. +class URLRequestMockJob : public net::URLRequestSimpleJob { + public: + URLRequestMockJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + int response_code, + const std::string& response_body) + : net::URLRequestSimpleJob(request, network_delegate), + response_code_(response_code), + response_body_(response_body) {} + + protected: + int GetResponseCode() const override { return response_code_; } + + int GetData(std::string* mime_type, + std::string* charset, + std::string* data, + const net::CompletionCallback& callback) const override { + mime_type->assign("text/plain"); + charset->assign("US-ASCII"); + data->assign(response_body_); + return net::OK; + } + + private: + ~URLRequestMockJob() override {} + + int response_code_; + std::string response_body_; + DISALLOW_COPY_AND_ASSIGN(URLRequestMockJob); +}; + +URLRequestPostInterceptor::URLRequestPostInterceptor( + const GURL& url, + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) + : url_(url), io_task_runner_(io_task_runner), hit_count_(0) { +} + +URLRequestPostInterceptor::~URLRequestPostInterceptor() { + DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); + ClearExpectations(); +} + +void URLRequestPostInterceptor::ClearExpectations() { + while (!expectations_.empty()) { + Expectation expectation(expectations_.front()); + delete expectation.first; + expectations_.pop(); + } +} + +GURL URLRequestPostInterceptor::GetUrl() const { + return url_; +} + +bool URLRequestPostInterceptor::ExpectRequest( + class RequestMatcher* request_matcher) { + expectations_.push(std::make_pair(request_matcher, + ExpectationResponse(kResponseCode200, ""))); + return true; +} + +bool URLRequestPostInterceptor::ExpectRequest( + class RequestMatcher* request_matcher, + int response_code) { + expectations_.push( + std::make_pair(request_matcher, ExpectationResponse(response_code, ""))); + return true; +} + +bool URLRequestPostInterceptor::ExpectRequest( + class RequestMatcher* request_matcher, + const base::FilePath& filepath) { + std::string response; + if (filepath.empty() || !base::ReadFileToString(filepath, &response)) + return false; + + expectations_.push(std::make_pair( + request_matcher, ExpectationResponse(kResponseCode200, response))); + return true; +} + +int URLRequestPostInterceptor::GetHitCount() const { + base::AutoLock auto_lock(interceptor_lock_); + return hit_count_; +} + +int URLRequestPostInterceptor::GetCount() const { + base::AutoLock auto_lock(interceptor_lock_); + return static_cast<int>(requests_.size()); +} + +std::vector<std::string> URLRequestPostInterceptor::GetRequests() const { + base::AutoLock auto_lock(interceptor_lock_); + return requests_; +} + +std::string URLRequestPostInterceptor::GetRequestsAsString() const { + std::vector<std::string> requests(GetRequests()); + + std::string s = "Requests are:"; + + int i = 0; + for (std::vector<std::string>::const_iterator it = requests.begin(); + it != requests.end(); ++it) { + s.append(base::StringPrintf("\n (%d): %s", ++i, it->c_str())); + } + + return s; +} + +void URLRequestPostInterceptor::Reset() { + base::AutoLock auto_lock(interceptor_lock_); + hit_count_ = 0; + requests_.clear(); + ClearExpectations(); +} + +class URLRequestPostInterceptor::Delegate : public net::URLRequestInterceptor { + public: + Delegate(const std::string& scheme, + const std::string& hostname, + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) + : scheme_(scheme), hostname_(hostname), io_task_runner_(io_task_runner) {} + + void Register() { + DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); + net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( + scheme_, hostname_, scoped_ptr<net::URLRequestInterceptor>(this)); + } + + void Unregister() { + DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); + for (InterceptorMap::iterator it = interceptors_.begin(); + it != interceptors_.end(); ++it) + delete (*it).second; + net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme_, + hostname_); + } + + void OnCreateInterceptor(URLRequestPostInterceptor* interceptor) { + DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(interceptors_.find(interceptor->GetUrl()) == interceptors_.end()); + + interceptors_.insert(std::make_pair(interceptor->GetUrl(), interceptor)); + } + + private: + ~Delegate() override {} + + net::URLRequestJob* MaybeInterceptRequest( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) const override { + DCHECK(io_task_runner_->RunsTasksOnCurrentThread()); + + // Only intercepts POST. + if (!request->has_upload()) + return NULL; + + GURL url = request->url(); + if (url.has_query()) { + GURL::Replacements replacements; + replacements.ClearQuery(); + url = url.ReplaceComponents(replacements); + } + + InterceptorMap::const_iterator it(interceptors_.find(url)); + if (it == interceptors_.end()) + return NULL; + + // There is an interceptor hooked up for this url. Read the request body, + // check the existing expectations, and handle the matching case by + // popping the expectation off the queue, counting the match, and + // returning a mock object to serve the canned response. + URLRequestPostInterceptor* interceptor(it->second); + + const net::UploadDataStream* stream = request->get_upload(); + const net::UploadBytesElementReader* reader = + (*stream->GetElementReaders())[0]->AsBytesReader(); + const int size = reader->length(); + scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size)); + const std::string request_body(reader->bytes()); + + { + base::AutoLock auto_lock(interceptor->interceptor_lock_); + interceptor->requests_.push_back(request_body); + if (interceptor->expectations_.empty()) + return NULL; + const URLRequestPostInterceptor::Expectation& expectation( + interceptor->expectations_.front()); + if (expectation.first->Match(request_body)) { + const int response_code(expectation.second.response_code); + const std::string response_body(expectation.second.response_body); + delete expectation.first; + interceptor->expectations_.pop(); + ++interceptor->hit_count_; + + return new URLRequestMockJob(request, network_delegate, response_code, + response_body); + } + } + + return NULL; + } + + typedef std::map<GURL, URLRequestPostInterceptor*> InterceptorMap; + InterceptorMap interceptors_; + + const std::string scheme_; + const std::string hostname_; + scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + + DISALLOW_COPY_AND_ASSIGN(Delegate); +}; + +URLRequestPostInterceptorFactory::URLRequestPostInterceptorFactory( + const std::string& scheme, + const std::string& hostname, + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) + : scheme_(scheme), + hostname_(hostname), + io_task_runner_(io_task_runner), + delegate_(new URLRequestPostInterceptor::Delegate(scheme, + hostname, + io_task_runner)) { + io_task_runner_->PostTask( + FROM_HERE, base::Bind(&URLRequestPostInterceptor::Delegate::Register, + base::Unretained(delegate_))); +} + +URLRequestPostInterceptorFactory::~URLRequestPostInterceptorFactory() { + io_task_runner_->PostTask( + FROM_HERE, base::Bind(&URLRequestPostInterceptor::Delegate::Unregister, + base::Unretained(delegate_))); +} + +URLRequestPostInterceptor* URLRequestPostInterceptorFactory::CreateInterceptor( + const base::FilePath& filepath) { + const GURL base_url( + base::StringPrintf("%s://%s", scheme_.c_str(), hostname_.c_str())); + GURL absolute_url(base_url.Resolve(filepath.MaybeAsASCII())); + URLRequestPostInterceptor* interceptor( + new URLRequestPostInterceptor(absolute_url, io_task_runner_)); + bool res = io_task_runner_->PostTask( + FROM_HERE, + base::Bind(&URLRequestPostInterceptor::Delegate::OnCreateInterceptor, + base::Unretained(delegate_), base::Unretained(interceptor))); + if (!res) { + delete interceptor; + return NULL; + } + + return interceptor; +} + +bool PartialMatch::Match(const std::string& actual) const { + return actual.find(expected_) != std::string::npos; +} + +InterceptorFactory::InterceptorFactory( + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) + : URLRequestPostInterceptorFactory(POST_INTERCEPT_SCHEME, + POST_INTERCEPT_HOSTNAME, + io_task_runner) { +} + +InterceptorFactory::~InterceptorFactory() { +} + +URLRequestPostInterceptor* InterceptorFactory::CreateInterceptor() { + return CreateInterceptorForPath(POST_INTERCEPT_PATH); +} + +URLRequestPostInterceptor* InterceptorFactory::CreateInterceptorForPath( + const char* url_path) { + return URLRequestPostInterceptorFactory::CreateInterceptor( + base::FilePath::FromUTF8Unsafe(url_path)); +} + +} // namespace update_client
diff --git a/components/update_client/url_request_post_interceptor.h b/components/update_client/url_request_post_interceptor.h new file mode 100644 index 0000000..15672bcf --- /dev/null +++ b/components/update_client/url_request_post_interceptor.h
@@ -0,0 +1,165 @@ +// Copyright 2013 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_UPDATE_CLIENT_URL_REQUEST_POST_INTERCEPTOR_H_ +#define COMPONENTS_UPDATE_CLIENT_URL_REQUEST_POST_INTERCEPTOR_H_ + +#include <stdint.h> +#include <map> +#include <queue> +#include <string> +#include <utility> +#include <vector> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/synchronization/lock.h" +#include "url/gurl.h" + +namespace base { +class FilePath; +class SequencedTaskRunner; +} + +namespace net { +class URLRequest; +} + +namespace update_client { + +// Intercepts requests to a file path, counts them, and captures the body of +// the requests. Optionally, for each request, it can return a canned response +// from a given file. The class maintains a queue of expectations, and returns +// one and only one response for each request that matches and it is +// intercepted. +class URLRequestPostInterceptor { + public: + // Allows a generic string maching interface when setting up expectations. + class RequestMatcher { + public: + virtual bool Match(const std::string& actual) const = 0; + virtual ~RequestMatcher() {} + }; + + // Returns the url that is intercepted. + GURL GetUrl() const; + + // Sets an expection for the body of the POST request and optionally, + // provides a canned response identified by a |file_path| to be returned when + // the expectation is met. If no |file_path| is provided, then an empty + // response body is served. If |response_code| is provided, then an empty + // response body with that response code is returned. + // Returns |true| if the expectation was set. This class takes ownership of + // the |request_matcher| object. + bool ExpectRequest(class RequestMatcher* request_matcher); + bool ExpectRequest(class RequestMatcher* request_matcher, int response_code); + bool ExpectRequest(class RequestMatcher* request_matcher, + const base::FilePath& filepath); + + // Returns how many requests have been intercepted and matched by + // an expectation. One expectation can only be matched by one request. + int GetHitCount() const; + + // Returns how many requests in total have been captured by the interceptor. + int GetCount() const; + + // Returns all requests that have been intercepted, matched or not. + std::vector<std::string> GetRequests() const; + + // Returns all requests as a string for debugging purposes. + std::string GetRequestsAsString() const; + + // Resets the state of the interceptor so that new expectations can be set. + void Reset(); + + class Delegate; + + private: + friend class URLRequestPostInterceptorFactory; + + static const int kResponseCode200 = 200; + + struct ExpectationResponse { + ExpectationResponse(int code, const std::string& body) + : response_code(code), response_body(body) {} + const int response_code; + const std::string response_body; + }; + typedef std::pair<const RequestMatcher*, ExpectationResponse> Expectation; + + URLRequestPostInterceptor( + const GURL& url, + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner); + ~URLRequestPostInterceptor(); + + void ClearExpectations(); + + const GURL url_; + scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + + mutable base::Lock interceptor_lock_; + mutable int hit_count_; + mutable std::vector<std::string> requests_; + mutable std::queue<Expectation> expectations_; + + DISALLOW_COPY_AND_ASSIGN(URLRequestPostInterceptor); +}; + +class URLRequestPostInterceptorFactory { + public: + URLRequestPostInterceptorFactory( + const std::string& scheme, + const std::string& hostname, + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner); + ~URLRequestPostInterceptorFactory(); + + // Creates an interceptor object for the specified url path. Returns NULL + // in case of errors or a valid interceptor object otherwise. The caller + // does not own the returned object. + URLRequestPostInterceptor* CreateInterceptor(const base::FilePath& filepath); + + private: + const std::string scheme_; + const std::string hostname_; + scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + + // After creation, |delegate_| lives on the IO thread and it is owned by + // a URLRequestFilter after registration. A task to unregister it and + // implicitly destroy it is posted from ~URLRequestPostInterceptorFactory(). + URLRequestPostInterceptor::Delegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(URLRequestPostInterceptorFactory); +}; + +// Intercepts HTTP POST requests sent to "localhost2". +class InterceptorFactory : public URLRequestPostInterceptorFactory { + public: + explicit InterceptorFactory( + const scoped_refptr<base::SequencedTaskRunner>& io_task_runner); + ~InterceptorFactory(); + + // Creates an interceptor for the url path defined by POST_INTERCEPT_PATH. + URLRequestPostInterceptor* CreateInterceptor(); + + // Creates an interceptor for the given url path. + URLRequestPostInterceptor* CreateInterceptorForPath(const char* url_path); + + private: + DISALLOW_COPY_AND_ASSIGN(InterceptorFactory); +}; + +class PartialMatch : public URLRequestPostInterceptor::RequestMatcher { + public: + explicit PartialMatch(const std::string& expected) : expected_(expected) {} + bool Match(const std::string& actual) const override; + + private: + const std::string expected_; + + DISALLOW_COPY_AND_ASSIGN(PartialMatch); +}; + +} // namespace update_client + +#endif // COMPONENTS_UPDATE_CLIENT_URL_REQUEST_POST_INTERCEPTOR_H_
diff --git a/components/view_manager/BUILD.gn b/components/view_manager/BUILD.gn index 9ae3c4d0..d6c95459 100644 --- a/components/view_manager/BUILD.gn +++ b/components/view_manager/BUILD.gn
@@ -3,8 +3,8 @@ # found in the LICENSE file. import("//build/config/ui.gni") -import("//third_party/mojo/src/mojo/public/mojo_application.gni") import("//testing/test.gni") +import("//third_party/mojo/src/mojo/public/mojo_application.gni") mojo_native_application("view_manager") { sources = [ @@ -16,13 +16,13 @@ deps = [ ":view_manager_lib", "//base", + "//components/view_manager/public/interfaces", + "//components/window_manager/public/interfaces", "//mojo/application", "//mojo/common:tracing_impl", - "//mojo/environment:chromium", "//mojo/converters/geometry", + "//mojo/environment:chromium", "//third_party/mojo/src/mojo/public/cpp/bindings:bindings", - "//third_party/mojo_services/src/view_manager/public/interfaces", - "//third_party/mojo_services/src/window_manager/public/interfaces", ] } @@ -42,6 +42,8 @@ "default_access_policy.h", "display_manager.cc", "display_manager.h", + "event_dispatcher.cc", + "event_dispatcher.h", "focus_controller.cc", "focus_controller.h", "focus_controller_delegate.h", @@ -68,13 +70,18 @@ ] public_deps = [ - "//third_party/mojo_services/src/view_manager/public/cpp", + "//components/view_manager/public/cpp", ] deps = [ "//base", "//cc/surfaces", "//cc/surfaces:surface_id", + "//components/native_viewport/public/interfaces", + "//components/surfaces/public/interfaces", + "//components/view_manager/public/cpp:common", + "//components/view_manager/public/interfaces", + "//components/window_manager/public/interfaces", "//mojo/application", "//mojo/common", "//mojo/converters/geometry", @@ -83,13 +90,8 @@ "//third_party/mojo/src/mojo/public/cpp/bindings:bindings", "//third_party/mojo/src/mojo/public/cpp/bindings:callback", "//third_party/mojo/src/mojo/public/interfaces/application", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/input_events/public/interfaces", - "//third_party/mojo_services/src/native_viewport/public/interfaces", - "//third_party/mojo_services/src/surfaces/public/interfaces", - "//third_party/mojo_services/src/view_manager/public/interfaces", - "//third_party/mojo_services/src/view_manager/public/cpp:common", - "//third_party/mojo_services/src/window_manager/public/interfaces", + "//ui/mojo/geometry:interfaces", + "//ui/mojo/events:interfaces", "//ui/gfx", "//ui/gfx/geometry", ] @@ -105,12 +107,12 @@ deps = [ "//base", + "//components/view_manager/public/cpp", + "//components/view_manager/public/cpp:common", + "//components/view_manager/public/interfaces", "//mojo/common", "//third_party/mojo/src/mojo/public/cpp/bindings:bindings", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/view_manager/public/cpp", - "//third_party/mojo_services/src/view_manager/public/cpp:common", - "//third_party/mojo_services/src/view_manager/public/interfaces", + "//ui/mojo/geometry:interfaces", ] } @@ -132,18 +134,18 @@ ":view_manager_lib", "//base", "//base/test:test_config", + "//components/native_viewport/public/cpp:args", + "//components/view_manager/public/cpp:common", + "//components/view_manager/public/interfaces", + "//components/window_manager/public/interfaces", "//mojo/converters/geometry", "//mojo/converters/input_events", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//mojo/environment:chromium", + "//third_party/mojo/src/mojo/edk/test:run_all_unittests", "//third_party/mojo/src/mojo/public/cpp/bindings:bindings", "//third_party/mojo/src/mojo/public/interfaces/application", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/input_events/public/interfaces", - "//third_party/mojo_services/src/native_viewport/public/cpp:args", - "//third_party/mojo_services/src/view_manager/public/cpp", - "//third_party/mojo_services/src/view_manager/public/interfaces", - "//third_party/mojo_services/src/window_manager/public/interfaces", + "//ui/mojo/geometry:interfaces", + "//ui/mojo/events:interfaces", "//testing/gtest", "//ui/gfx", "//ui/gfx:test_support", @@ -168,14 +170,14 @@ ":test_support", "//base", "//base/test:test_config", + "//components/view_manager/public/cpp", + "//components/view_manager/public/interfaces", + "//components/window_manager/public/interfaces", "//mojo/application", "//mojo/application:test_support", "//mojo/common", "//third_party/mojo/src/mojo/public/cpp/bindings:bindings", - "//third_party/mojo_services/src/geometry/public/cpp:cpp", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/view_manager/public/cpp", - "//third_party/mojo_services/src/view_manager/public/interfaces", - "//third_party/mojo_services/src/window_manager/public/interfaces", + "//ui/mojo/geometry:interfaces", + "//ui/mojo/geometry:util", ] }
diff --git a/components/view_manager/DEPS b/components/view_manager/DEPS index 69acc37..adc0571 100644 --- a/components/view_manager/DEPS +++ b/components/view_manager/DEPS
@@ -1,5 +1,9 @@ include_rules = [ "+cc", + "+components/gpu", + "+components/native_viewport", + "+components/surfaces", + "+components/window_manager", "+mojo/application", "+mojo/common", "+mojo/converters",
diff --git a/components/view_manager/OWNERS b/components/view_manager/OWNERS new file mode 100644 index 0000000..e6a7642f --- /dev/null +++ b/components/view_manager/OWNERS
@@ -0,0 +1,4 @@ +ben@chromium.org +erg@chromium.org +msw@chromium.org +sky@chromium.org
diff --git a/components/view_manager/access_policy.h b/components/view_manager/access_policy.h index eb5815b..1d9148ec 100644 --- a/components/view_manager/access_policy.h +++ b/components/view_manager/access_policy.h
@@ -6,7 +6,7 @@ #define COMPONENTS_VIEW_MANAGER_ACCESS_POLICY_H_ #include "components/view_manager/ids.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager_constants.mojom.h" +#include "components/view_manager/public/interfaces/view_manager_constants.mojom.h" namespace view_manager { @@ -37,6 +37,7 @@ virtual bool CanSetViewSurfaceId(const ServerView* view) const = 0; virtual bool CanSetViewBounds(const ServerView* view) const = 0; virtual bool CanSetViewProperties(const ServerView* view) const = 0; + virtual bool CanSetFocus(const ServerView* view) const = 0; // Returns whether the connection should notify on a hierarchy change. // |new_parent| and |old_parent| are initially set to the new and old parents @@ -45,6 +46,10 @@ const ServerView* view, const ServerView** new_parent, const ServerView** old_parent) const = 0; + + // Returns the view to supply to the client when focus changes to |focused|. + virtual const ServerView* GetViewForFocusChange( + const ServerView* focused) = 0; }; } // namespace view_manager
diff --git a/components/view_manager/animation_runner_unittest.cc b/components/view_manager/animation_runner_unittest.cc index 6de5686..d04ad6be 100644 --- a/components/view_manager/animation_runner_unittest.cc +++ b/components/view_manager/animation_runner_unittest.cc
@@ -6,13 +6,13 @@ #include "base/strings/stringprintf.h" #include "components/view_manager/animation_runner_observer.h" +#include "components/view_manager/public/interfaces/view_manager_constants.mojom.h" #include "components/view_manager/scheduled_animation_group.h" #include "components/view_manager/server_view.h" #include "components/view_manager/test_server_view_delegate.h" #include "mojo/converters/geometry/geometry_type_converters.h" #include "mojo/converters/transform/transform_type_converters.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager_constants.mojom.h" using base::TimeDelta; using mojo::ANIMATION_PROPERTY_NONE;
diff --git a/components/view_manager/client_connection.h b/components/view_manager/client_connection.h index 2589204..a43e0c8 100644 --- a/components/view_manager/client_connection.h +++ b/components/view_manager/client_connection.h
@@ -6,9 +6,9 @@ #define COMPONENTS_VIEW_MANAGER_CLIENT_CONNECTION_H_ #include "base/memory/scoped_ptr.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" namespace view_manager {
diff --git a/components/view_manager/connection_manager.cc b/components/view_manager/connection_manager.cc index a7e1f5f..5a9657c 100644 --- a/components/view_manager/connection_manager.cc +++ b/components/view_manager/connection_manager.cc
@@ -9,6 +9,7 @@ #include "components/view_manager/client_connection.h" #include "components/view_manager/connection_manager_delegate.h" #include "components/view_manager/display_manager.h" +#include "components/view_manager/focus_controller.h" #include "components/view_manager/server_view.h" #include "components/view_manager/view_coordinate_conversions.h" #include "components/view_manager/view_manager_service_impl.h" @@ -120,15 +121,26 @@ wm_internal_(wm_internal), current_change_(nullptr), in_destructor_(false), - animation_runner_(base::TimeTicks::Now()) { + animation_runner_(base::TimeTicks::Now()), + event_dispatcher_(this), + event_dispatcher_binding_(&event_dispatcher_), + focus_controller_(new FocusController(this, root_.get())) { root_->SetBounds(gfx::Rect(800, 600)); root_->SetVisible(true); - display_manager_->Init(this); + + mojo::NativeViewportEventDispatcherPtr event_dispatcher_ptr; + event_dispatcher_binding_.Bind(GetProxy(&event_dispatcher_ptr)); + display_manager_->Init(this, event_dispatcher_ptr.Pass()); } ConnectionManager::~ConnectionManager() { in_destructor_ = true; + // Deleting views will attempt to advance focus. When we're being destroyed + // that is not necessary. Additionally |focus_controller_| needs to be + // destroyed before |root_|. + focus_controller_.reset(); + STLDeleteValues(&connection_map_); // All the connections should have been destroyed. DCHECK(connection_map_.empty()); @@ -159,6 +171,9 @@ connection_map_.erase(connection->service()->id()); + // TODO(sky): I may want to advance focus differently if focus is in + // |connection|. + // Notify remaining connections so that they can cleanup. for (auto& pair : connection_map_) { pair.second->service()->OnWillDestroyViewManagerServiceImpl( @@ -220,6 +235,18 @@ return service ? service->GetView(id) : nullptr; } +void ConnectionManager::SetFocusedView(ServerView* view) { + ServerView* old_focused = GetFocusedView(); + if (old_focused == view) + return; + focus_controller_->SetFocusedView(view); + OnFocusChanged(old_focused, view); +} + +ServerView* ConnectionManager::GetFocusedView() { + return focus_controller_->GetFocusedView(); +} + void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) { if (current_change_) current_change_->MarkConnectionAsMessaged(id); @@ -269,6 +296,22 @@ return true; } +void ConnectionManager::ProcessEvent(mojo::EventPtr event) { + event_dispatcher_.OnEvent(event.Pass(), EventDispatcher::OnEventCallback()); +} + +void ConnectionManager::DispatchInputEventToView(const ServerView* view, + mojo::EventPtr event) { + // If the view is an embed root, forward to the embedded view, not the owner. + ViewManagerServiceImpl* connection = GetConnectionWithRoot(view->id()); + if (!connection) + connection = GetConnection(view->id().connection_id); + CHECK(connection); + connection->client()->OnViewInputEvent(ViewIdToTransportId(view->id()), + event.Pass(), + base::Bind(&base::DoNothing)); +} + void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) { @@ -482,8 +525,13 @@ } } -void ConnectionManager::DispatchInputEventToView(mojo::Id transport_view_id, - mojo::EventPtr event) { +void ConnectionManager::SetViewportSize(mojo::SizePtr size) { + display_manager_->SetViewportSize(size.To<gfx::Size>()); +} + +void ConnectionManager::DispatchInputEventToViewDEPRECATED( + mojo::Id transport_view_id, + mojo::EventPtr event) { const ViewId view_id(ViewIdFromTransportId(transport_view_id)); ViewManagerServiceImpl* connection = GetConnectionWithRoot(view_id); @@ -495,13 +543,76 @@ } } -void ConnectionManager::SetViewportSize(mojo::SizePtr size) { - gfx::Size new_size = size.To<gfx::Size>(); - display_manager_->SetViewportSize(new_size); -} - void ConnectionManager::CloneAndAnimate(mojo::Id transport_view_id) { CloneAndAnimate(ViewIdFromTransportId(transport_view_id)); } +void ConnectionManager::AddAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) { + event_dispatcher_.AddAccelerator(keyboard_code, flags); +} + +void ConnectionManager::RemoveAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) { + event_dispatcher_.RemoveAccelerator(keyboard_code, flags); +} + +void ConnectionManager::OnFocusChanged(ServerView* old_focused_view, + ServerView* new_focused_view) { + // There are up to four connections that need to be notified: + // . the connection containing |old_focused_view|. + // . the connection with |old_focused_view| as its root. + // . the connection containing |new_focused_view|. + // . the connection with |new_focused_view| as its root. + // Some of these connections may be the same. The following takes care to + // notify each only once. + ViewManagerServiceImpl* owning_connection_old = nullptr; + ViewManagerServiceImpl* embedded_connection_old = nullptr; + + if (old_focused_view) { + owning_connection_old = GetConnection(old_focused_view->id().connection_id); + if (owning_connection_old) { + owning_connection_old->ProcessFocusChanged(old_focused_view, + new_focused_view); + } + embedded_connection_old = GetConnectionWithRoot(old_focused_view->id()); + if (embedded_connection_old) { + DCHECK_NE(owning_connection_old, embedded_connection_old); + embedded_connection_old->ProcessFocusChanged(old_focused_view, + new_focused_view); + } + } + ViewManagerServiceImpl* owning_connection_new = nullptr; + ViewManagerServiceImpl* embedded_connection_new = nullptr; + if (new_focused_view) { + owning_connection_new = GetConnection(new_focused_view->id().connection_id); + if (owning_connection_new && + owning_connection_new != owning_connection_old && + owning_connection_new != embedded_connection_old) { + owning_connection_new->ProcessFocusChanged(old_focused_view, + new_focused_view); + } + embedded_connection_new = GetConnectionWithRoot(new_focused_view->id()); + if (embedded_connection_new && + embedded_connection_new != owning_connection_old && + embedded_connection_new != embedded_connection_old) { + DCHECK_NE(owning_connection_new, embedded_connection_new); + embedded_connection_new->ProcessFocusChanged(old_focused_view, + new_focused_view); + } + } + + if (has_window_manager_client_connection()) { + // Window manager should always be notified of focus change. + ViewManagerServiceImpl* wm_connection = + window_manager_client_connection_->service(); + if (wm_connection != owning_connection_old && + wm_connection != embedded_connection_old && + wm_connection != owning_connection_new && + wm_connection != embedded_connection_new) { + wm_connection->ProcessFocusChanged(old_focused_view, new_focused_view); + } + } +} + } // namespace view_manager
diff --git a/components/view_manager/connection_manager.h b/components/view_manager/connection_manager.h index e7b3347..ae5cf06 100644 --- a/components/view_manager/connection_manager.h +++ b/components/view_manager/connection_manager.h
@@ -11,19 +11,24 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/timer/timer.h" +#include "components/native_viewport/public/interfaces/native_viewport.mojom.h" #include "components/view_manager/animation_runner.h" +#include "components/view_manager/event_dispatcher.h" +#include "components/view_manager/focus_controller_delegate.h" #include "components/view_manager/ids.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" #include "components/view_manager/server_view_delegate.h" #include "components/view_manager/server_view_observer.h" +#include "components/window_manager/public/interfaces/window_manager_internal.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" namespace view_manager { class ClientConnection; class ConnectionManagerDelegate; class DisplayManager; +class FocusController; class ServerView; class ViewManagerServiceImpl; @@ -31,7 +36,8 @@ // ViewManagerServiceImpls) as well as providing the root of the hierarchy. class ConnectionManager : public ServerViewDelegate, public ServerViewObserver, - public mojo::WindowManagerInternalClient { + public mojo::WindowManagerInternalClient, + public FocusControllerDelegate { public: // Create when a ViewManagerServiceImpl is about to make a change. Ensures // clients are notified correctly. @@ -99,6 +105,9 @@ // Returns the View identified by |id|. ServerView* GetView(const ViewId& id); + void SetFocusedView(ServerView* view); + ServerView* GetFocusedView(); + ServerView* root() { return root_.get(); } DisplayManager* display_manager() { return display_manager_.get(); } @@ -135,6 +144,12 @@ // WindowManagerInternalClient implementation helper; see mojom for details. bool CloneAndAnimate(const ViewId& view_id); + // Processes an event, potentially changing focus. + void ProcessEvent(mojo::EventPtr event); + + // Dispatches |event| directly to the appropriate connection for |view|. + void DispatchInputEventToView(const ServerView* view, mojo::EventPtr event); + // These functions trivially delegate to all ViewManagerServiceImpls, which in // term notify their clients. void ProcessViewDestroyed(ServerView* view); @@ -209,10 +224,18 @@ const std::vector<uint8_t>* new_data) override; // WindowManagerInternalClient: - void DispatchInputEventToView(mojo::Id transport_view_id, - mojo::EventPtr event) override; + void DispatchInputEventToViewDEPRECATED(mojo::Id transport_view_id, + mojo::EventPtr event) override; void SetViewportSize(mojo::SizePtr size) override; void CloneAndAnimate(mojo::Id transport_view_id) override; + void AddAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) override; + void RemoveAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) override; + + // FocusControllerDelegate: + void OnFocusChanged(ServerView* old_focused_view, + ServerView* new_focused_view) override; ConnectionManagerDelegate* delegate_; @@ -244,6 +267,12 @@ AnimationRunner animation_runner_; + EventDispatcher event_dispatcher_; + + mojo::Binding<mojo::NativeViewportEventDispatcher> event_dispatcher_binding_; + + scoped_ptr<FocusController> focus_controller_; + DISALLOW_COPY_AND_ASSIGN(ConnectionManager); };
diff --git a/components/view_manager/connection_manager_delegate.h b/components/view_manager/connection_manager_delegate.h index 0d06f94..60acf18f 100644 --- a/components/view_manager/connection_manager_delegate.h +++ b/components/view_manager/connection_manager_delegate.h
@@ -7,9 +7,9 @@ #include <string> +#include "components/view_manager/public/cpp/types.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/types.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" namespace mojo { class ViewManagerService;
diff --git a/components/view_manager/default_access_policy.cc b/components/view_manager/default_access_policy.cc index ed0a6b6..4127e149 100644 --- a/components/view_manager/default_access_policy.cc +++ b/components/view_manager/default_access_policy.cc
@@ -85,6 +85,11 @@ return WasCreatedByThisConnection(view); } +bool DefaultAccessPolicy::CanSetFocus(const ServerView* view) const { + return WasCreatedByThisConnection(view) || + delegate_->IsRootForAccessPolicy(view->id()); +} + bool DefaultAccessPolicy::ShouldNotifyOnHierarchyChange( const ServerView* view, const ServerView** new_parent, @@ -104,6 +109,14 @@ return true; } +const ServerView* DefaultAccessPolicy::GetViewForFocusChange( + const ServerView* focused) { + if (WasCreatedByThisConnection(focused) || + delegate_->IsRootForAccessPolicy(focused->id())) + return focused; + return nullptr; +} + bool DefaultAccessPolicy::WasCreatedByThisConnection( const ServerView* view) const { return view->id().connection_id == connection_id_;
diff --git a/components/view_manager/default_access_policy.h b/components/view_manager/default_access_policy.h index 5c23118..b9e782b 100644 --- a/components/view_manager/default_access_policy.h +++ b/components/view_manager/default_access_policy.h
@@ -34,10 +34,12 @@ bool CanSetViewSurfaceId(const ServerView* view) const override; bool CanSetViewBounds(const ServerView* view) const override; bool CanSetViewProperties(const ServerView* view) const override; + bool CanSetFocus(const ServerView* view) const override; bool ShouldNotifyOnHierarchyChange( const ServerView* view, const ServerView** new_parent, const ServerView** old_parent) const override; + const ServerView* GetViewForFocusChange(const ServerView* focused) override; private: bool WasCreatedByThisConnection(const ServerView* view) const;
diff --git a/components/view_manager/display_manager.cc b/components/view_manager/display_manager.cc index 05eafc1..716bb82 100644 --- a/components/view_manager/display_manager.cc +++ b/components/view_manager/display_manager.cc
@@ -5,6 +5,9 @@ #include "components/view_manager/display_manager.h" #include "base/numerics/safe_conversions.h" +#include "components/gpu/public/interfaces/gpu.mojom.h" +#include "components/surfaces/public/interfaces/quads.mojom.h" +#include "components/surfaces/public/interfaces/surfaces.mojom.h" #include "components/view_manager/connection_manager.h" #include "components/view_manager/server_view.h" #include "components/view_manager/view_coordinate_conversions.h" @@ -14,9 +17,6 @@ #include "mojo/converters/transform/transform_type_converters.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/gpu.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/quads.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom.h" using mojo::Rect; using mojo::Size; @@ -74,10 +74,8 @@ DefaultDisplayManager::DefaultDisplayManager( mojo::ApplicationImpl* app_impl, - mojo::ApplicationConnection* app_connection, const mojo::Callback<void()>& native_viewport_closed_callback) : app_impl_(app_impl), - app_connection_(app_connection), connection_manager_(nullptr), draw_timer_(false, false), frame_pending_(false), @@ -88,7 +86,9 @@ metrics_.size->height = 600; } -void DefaultDisplayManager::Init(ConnectionManager* connection_manager) { +void DefaultDisplayManager::Init( + ConnectionManager* connection_manager, + mojo::NativeViewportEventDispatcherPtr event_dispatcher) { connection_manager_ = connection_manager; app_impl_->ConnectToService("mojo:native_viewport_service", &native_viewport_); @@ -106,8 +106,6 @@ nullptr, // returner - we never submit resources. GetProxy(&display_)); - mojo::NativeViewportEventDispatcherPtr event_dispatcher; - app_connection_->ConnectToService(&event_dispatcher); native_viewport_->SetEventDispatcher(event_dispatcher.Pass()); }
diff --git a/components/view_manager/display_manager.h b/components/view_manager/display_manager.h index 92026eb..f82591dc 100644 --- a/components/view_manager/display_manager.h +++ b/components/view_manager/display_manager.h
@@ -11,10 +11,10 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" +#include "components/native_viewport/public/interfaces/native_viewport.mojom.h" +#include "components/surfaces/public/interfaces/display.mojom.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/callback.h" -#include "third_party/mojo_services/src/native_viewport/public/interfaces/native_viewport.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/display.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" #include "ui/gfx/geometry/rect.h" namespace cc { @@ -22,7 +22,6 @@ } namespace mojo { -class ApplicationConnection; class ApplicationImpl; } @@ -36,7 +35,9 @@ public: virtual ~DisplayManager() {} - virtual void Init(ConnectionManager* connection_manager) = 0; + virtual void Init( + ConnectionManager* connection_manager, + mojo::NativeViewportEventDispatcherPtr event_dispatcher) = 0; // Schedules a paint for the specified region in the coordinates of |view|. virtual void SchedulePaint(const ServerView* view, @@ -54,12 +55,12 @@ public: DefaultDisplayManager( mojo::ApplicationImpl* app_impl, - mojo::ApplicationConnection* app_connection, const mojo::Callback<void()>& native_viewport_closed_callback); ~DefaultDisplayManager() override; // DisplayManager: - void Init(ConnectionManager* connection_manager) override; + void Init(ConnectionManager* connection_manager, + mojo::NativeViewportEventDispatcherPtr event_dispatcher) override; void SchedulePaint(const ServerView* view, const gfx::Rect& bounds) override; void SetViewportSize(const gfx::Size& size) override; const mojo::ViewportMetrics& GetViewportMetrics() override; @@ -75,7 +76,6 @@ void OnConnectionError() override; mojo::ApplicationImpl* app_impl_; - mojo::ApplicationConnection* app_connection_; ConnectionManager* connection_manager_; mojo::ViewportMetrics metrics_;
diff --git a/components/view_manager/event_dispatcher.cc b/components/view_manager/event_dispatcher.cc new file mode 100644 index 0000000..6cc8b85 --- /dev/null +++ b/components/view_manager/event_dispatcher.cc
@@ -0,0 +1,64 @@ +// 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/view_manager/event_dispatcher.h" + +#include "components/view_manager/connection_manager.h" +#include "components/view_manager/server_view.h" +#include "components/view_manager/view_coordinate_conversions.h" +#include "components/view_manager/view_locator.h" +#include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/point_f.h" + +namespace view_manager { + +EventDispatcher::EventDispatcher(ConnectionManager* connection_manager) + : connection_manager_(connection_manager) { +} + +EventDispatcher::~EventDispatcher() { +} + +void EventDispatcher::AddAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) { + accelerators_.insert(Accelerator(keyboard_code, flags)); +} + +void EventDispatcher::RemoveAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) { + accelerators_.erase(Accelerator(keyboard_code, flags)); +} + +void EventDispatcher::OnEvent(mojo::EventPtr event, + const OnEventCallback& callback) { + callback.Run(); + + if (event->pointer_data) { + const gfx::Point root_point(static_cast<int>(event->pointer_data->x), + static_cast<int>(event->pointer_data->y)); + ServerView* target = connection_manager_->GetFocusedView(); + ; + if (event->action == mojo::EVENT_TYPE_POINTER_DOWN || !target) { + target = FindDeepestVisibleView(connection_manager_->root(), root_point); + CHECK(target); + connection_manager_->SetFocusedView(target); + } + const gfx::PointF local_point(ConvertPointFBetweenViews( + connection_manager_->root(), target, + gfx::PointF(event->pointer_data->x, event->pointer_data->y))); + event->pointer_data->x = local_point.x(); + event->pointer_data->y = local_point.y(); + connection_manager_->DispatchInputEventToView(target, event.Pass()); + } else if (event->action == mojo::EVENT_TYPE_KEY_PRESSED && + accelerators_.count(Accelerator(event->key_data->windows_key_code, + event->flags))) { + connection_manager_->wm_internal()->OnAccelerator(event.Pass()); + } else { + ServerView* focused_view = connection_manager_->GetFocusedView(); + if (focused_view) + connection_manager_->DispatchInputEventToView(focused_view, event.Pass()); + } +} + +} // namespace view_manager
diff --git a/components/view_manager/event_dispatcher.h b/components/view_manager/event_dispatcher.h new file mode 100644 index 0000000..006edc0 --- /dev/null +++ b/components/view_manager/event_dispatcher.h
@@ -0,0 +1,56 @@ +// 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_VIEW_MANAGER_EVENT_DISPATCHER_H_ +#define COMPONENTS_VIEW_MANAGER_EVENT_DISPATCHER_H_ + +#include <set> + +#include "base/basictypes.h" +#include "components/native_viewport/public/interfaces/native_viewport.mojom.h" +#include "components/window_manager/public/interfaces/window_manager_internal.mojom.h" + +namespace view_manager { + +class ConnectionManager; + +// Handles dispatching events to the right location as well as updating focus. +class EventDispatcher : public mojo::NativeViewportEventDispatcher { + public: + explicit EventDispatcher(ConnectionManager* connection_manager); + ~EventDispatcher() override; + + void AddAccelerator(mojo::KeyboardCode keyboard_code, mojo::EventFlags flags); + void RemoveAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags); + + // NativeViewportEventDispatcher: + void OnEvent(mojo::EventPtr event, const OnEventCallback& callback) override; + + private: + struct Accelerator { + Accelerator(mojo::KeyboardCode keyboard_code, mojo::EventFlags flags) + : keyboard_code(keyboard_code), flags(flags) {} + + // So we can use this in a set. + bool operator<(const Accelerator& other) const { + if (keyboard_code == other.keyboard_code) + return flags < other.flags; + return keyboard_code < other.keyboard_code; + } + + mojo::KeyboardCode keyboard_code; + mojo::EventFlags flags; + }; + + ConnectionManager* connection_manager_; + + std::set<Accelerator> accelerators_; + + DISALLOW_COPY_AND_ASSIGN(EventDispatcher); +}; + +} // namespace view_manager + +#endif // COMPONENTS_VIEW_MANAGER_EVENT_DISPATCHER_H_
diff --git a/components/view_manager/gesture_manager.cc b/components/view_manager/gesture_manager.cc index 399ee33..37bb4b0 100644 --- a/components/view_manager/gesture_manager.cc +++ b/components/view_manager/gesture_manager.cc
@@ -7,12 +7,12 @@ #include <algorithm> #include "components/view_manager/gesture_manager_delegate.h" +#include "components/view_manager/public/cpp/keys.h" #include "components/view_manager/server_view.h" #include "components/view_manager/view_coordinate_conversions.h" #include "components/view_manager/view_locator.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/keys.h" #include "ui/gfx/geometry/point_f.h" +#include "ui/mojo/events/input_events.mojom.h" namespace view_manager {
diff --git a/components/view_manager/gesture_manager_delegate.h b/components/view_manager/gesture_manager_delegate.h index 685458e..55b1ea28 100644 --- a/components/view_manager/gesture_manager_delegate.h +++ b/components/view_manager/gesture_manager_delegate.h
@@ -7,8 +7,8 @@ #include <set> -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/types.h" +#include "components/view_manager/public/cpp/types.h" +#include "ui/mojo/events/input_events.mojom.h" namespace view_manager {
diff --git a/components/view_manager/gesture_manager_unittest.cc b/components/view_manager/gesture_manager_unittest.cc index e65f2ae5..403e6f0 100644 --- a/components/view_manager/gesture_manager_unittest.cc +++ b/components/view_manager/gesture_manager_unittest.cc
@@ -7,11 +7,11 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "components/view_manager/gesture_manager_delegate.h" +#include "components/view_manager/public/cpp/keys.h" #include "components/view_manager/server_view.h" #include "components/view_manager/test_server_view_delegate.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/keys.h" +#include "ui/mojo/events/input_events.mojom.h" namespace view_manager { namespace {
diff --git a/components/view_manager/ids.h b/components/view_manager/ids.h index 727ae05..9e49645 100644 --- a/components/view_manager/ids.h +++ b/components/view_manager/ids.h
@@ -5,8 +5,8 @@ #ifndef COMPONENTS_VIEW_MANAGER_IDS_H_ #define COMPONENTS_VIEW_MANAGER_IDS_H_ -#include "third_party/mojo_services/src/view_manager/public/cpp/types.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/util.h" +#include "components/view_manager/public/cpp/types.h" +#include "components/view_manager/public/cpp/util.h" namespace view_manager {
diff --git a/components/view_manager/public/cpp/BUILD.gn b/components/view_manager/public/cpp/BUILD.gn new file mode 100644 index 0000000..e1bd479 --- /dev/null +++ b/components/view_manager/public/cpp/BUILD.gn
@@ -0,0 +1,59 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/mojo_sdk.gni") + +mojo_sdk_source_set("cpp") { + restrict_external_deps = false + sources = [ + "lib/view.cc", + "lib/view_manager_client_factory.cc", + "lib/view_manager_client_impl.cc", + "lib/view_manager_client_impl.h", + "lib/view_manager_context.cc", + "lib/view_observer.cc", + "lib/view_private.cc", + "lib/view_private.h", + "view.h", + "view_manager.h", + "view_manager_client_factory.h", + "view_manager_context.h", + "view_manager_delegate.h", + "view_observer.h", + "view_property.h", + "view_tracker.cc", + "view_tracker.h", + ] + + public_deps = [ + ":common", + ] + + deps = [ + "../interfaces", + "//components/surfaces/public/interfaces:surface_id", + "//components/window_manager/public/interfaces", + "//ui/mojo/events:interfaces", + "//ui/mojo/geometry:interfaces", + "//base", + ] + + mojo_sdk_deps = [ + "mojo/public/c/gles2:headers", + "mojo/public/cpp/application", + "mojo/public/cpp/bindings:bindings", + "mojo/public/cpp/system", + "mojo/public/interfaces/application", + ] +} + +source_set("common") { + sources = [ + "keys.cc", + "keys.h", + "types.h", + "util.h", + ] +}
diff --git a/components/view_manager/public/cpp/keys.cc b/components/view_manager/public/cpp/keys.cc new file mode 100644 index 0000000..4a2af70 --- /dev/null +++ b/components/view_manager/public/cpp/keys.cc
@@ -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. + +#include "components/view_manager/public/cpp/keys.h" + +namespace mojo { + +extern const char kViewManagerKeyWantsTouchEvents[] = + "view-manager-key-wants-touch-events"; + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/keys.h b/components/view_manager/public/cpp/keys.h new file mode 100644 index 0000000..ee6bcfe --- /dev/null +++ b/components/view_manager/public/cpp/keys.h
@@ -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. + +#ifndef COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_KEYS_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_KEYS_H_ + +namespace mojo { + +extern const char kViewManagerKeyWantsTouchEvents[]; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_KEYS_H_
diff --git a/components/view_manager/public/cpp/lib/view.cc b/components/view_manager/public/cpp/lib/view.cc new file mode 100644 index 0000000..1cde9e8 --- /dev/null +++ b/components/view_manager/public/cpp/lib/view.cc
@@ -0,0 +1,589 @@ +// 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/view_manager/public/cpp/view.h" + +#include <set> +#include <string> + +#include "components/view_manager/public/cpp/lib/view_manager_client_impl.h" +#include "components/view_manager/public/cpp/lib/view_private.h" +#include "components/view_manager/public/cpp/view_observer.h" +#include "components/view_manager/public/cpp/view_tracker.h" +#include "third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h" + +namespace mojo { + +namespace { + +void NotifyViewTreeChangeAtReceiver( + View* receiver, + const ViewObserver::TreeChangeParams& params, + bool change_applied) { + ViewObserver::TreeChangeParams local_params = params; + local_params.receiver = receiver; + if (change_applied) { + FOR_EACH_OBSERVER(ViewObserver, + *ViewPrivate(receiver).observers(), + OnTreeChanged(local_params)); + } else { + FOR_EACH_OBSERVER(ViewObserver, + *ViewPrivate(receiver).observers(), + OnTreeChanging(local_params)); + } +} + +void NotifyViewTreeChangeUp( + View* start_at, + const ViewObserver::TreeChangeParams& params, + bool change_applied) { + for (View* current = start_at; current; current = current->parent()) + NotifyViewTreeChangeAtReceiver(current, params, change_applied); +} + +void NotifyViewTreeChangeDown( + View* start_at, + const ViewObserver::TreeChangeParams& params, + bool change_applied) { + NotifyViewTreeChangeAtReceiver(start_at, params, change_applied); + View::Children::const_iterator it = start_at->children().begin(); + for (; it != start_at->children().end(); ++it) + NotifyViewTreeChangeDown(*it, params, change_applied); +} + +void NotifyViewTreeChange( + const ViewObserver::TreeChangeParams& params, + bool change_applied) { + NotifyViewTreeChangeDown(params.target, params, change_applied); + if (params.old_parent) + NotifyViewTreeChangeUp(params.old_parent, params, change_applied); + if (params.new_parent) + NotifyViewTreeChangeUp(params.new_parent, params, change_applied); +} + +class ScopedTreeNotifier { + public: + ScopedTreeNotifier(View* target, View* old_parent, View* new_parent) { + params_.target = target; + params_.old_parent = old_parent; + params_.new_parent = new_parent; + NotifyViewTreeChange(params_, false); + } + ~ScopedTreeNotifier() { + NotifyViewTreeChange(params_, true); + } + + private: + ViewObserver::TreeChangeParams params_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier); +}; + +void RemoveChildImpl(View* child, View::Children* children) { + View::Children::iterator it = + std::find(children->begin(), children->end(), child); + if (it != children->end()) { + children->erase(it); + ViewPrivate(child).ClearParent(); + } +} + +class ScopedOrderChangedNotifier { + public: + ScopedOrderChangedNotifier(View* view, + View* relative_view, + OrderDirection direction) + : view_(view), + relative_view_(relative_view), + direction_(direction) { + FOR_EACH_OBSERVER(ViewObserver, + *ViewPrivate(view_).observers(), + OnViewReordering(view_, relative_view_, direction_)); + } + ~ScopedOrderChangedNotifier() { + FOR_EACH_OBSERVER(ViewObserver, + *ViewPrivate(view_).observers(), + OnViewReordered(view_, relative_view_, direction_)); + } + + private: + View* view_; + View* relative_view_; + OrderDirection direction_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedOrderChangedNotifier); +}; + +// Returns true if the order actually changed. +bool ReorderImpl(View::Children* children, + View* view, + View* relative, + OrderDirection direction) { + DCHECK(relative); + DCHECK_NE(view, relative); + DCHECK_EQ(view->parent(), relative->parent()); + + const size_t child_i = + std::find(children->begin(), children->end(), view) - children->begin(); + const size_t target_i = + std::find(children->begin(), children->end(), relative) - + children->begin(); + if ((direction == ORDER_DIRECTION_ABOVE && child_i == target_i + 1) || + (direction == ORDER_DIRECTION_BELOW && child_i + 1 == target_i)) { + return false; + } + + ScopedOrderChangedNotifier notifier(view, relative, direction); + + const size_t dest_i = direction == ORDER_DIRECTION_ABOVE + ? (child_i < target_i ? target_i : target_i + 1) + : (child_i < target_i ? target_i - 1 : target_i); + children->erase(children->begin() + child_i); + children->insert(children->begin() + dest_i, view); + + return true; +} + +class ScopedSetBoundsNotifier { + public: + ScopedSetBoundsNotifier(View* view, + const Rect& old_bounds, + const Rect& new_bounds) + : view_(view), + old_bounds_(old_bounds), + new_bounds_(new_bounds) { + FOR_EACH_OBSERVER(ViewObserver, + *ViewPrivate(view_).observers(), + OnViewBoundsChanging(view_, old_bounds_, new_bounds_)); + } + ~ScopedSetBoundsNotifier() { + FOR_EACH_OBSERVER(ViewObserver, + *ViewPrivate(view_).observers(), + OnViewBoundsChanged(view_, old_bounds_, new_bounds_)); + } + + private: + View* view_; + const Rect old_bounds_; + const Rect new_bounds_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsNotifier); +}; + +// Some operations are only permitted in the connection that created the view. +bool OwnsView(ViewManager* manager, View* view) { + return !manager || + static_cast<ViewManagerClientImpl*>(manager)->OwnsView(view->id()); +} + +} // namespace + +//////////////////////////////////////////////////////////////////////////////// +// View, public: + +void View::Destroy() { + if (!OwnsView(manager_, this)) + return; + + if (manager_) + static_cast<ViewManagerClientImpl*>(manager_)->DestroyView(id_); + while (!children_.empty()) { + View* child = children_.front(); + if (!OwnsView(manager_, child)) { + ViewPrivate(child).ClearParent(); + children_.erase(children_.begin()); + } else { + child->Destroy(); + DCHECK(std::find(children_.begin(), children_.end(), child) == + children_.end()); + } + } + LocalDestroy(); +} + +void View::SetBounds(const Rect& bounds) { + if (!OwnsView(manager_, this)) + return; + + if (bounds_.Equals(bounds)) + return; + + if (manager_) + static_cast<ViewManagerClientImpl*>(manager_)->SetBounds(id_, bounds); + LocalSetBounds(bounds_, bounds); +} + +void View::SetVisible(bool value) { + if (visible_ == value) + return; + + if (manager_) + static_cast<ViewManagerClientImpl*>(manager_)->SetVisible(id_, value); + LocalSetVisible(value); +} + +void View::SetSharedProperty(const std::string& name, + const std::vector<uint8_t>* value) { + std::vector<uint8_t> old_value; + std::vector<uint8_t>* old_value_ptr = nullptr; + auto it = properties_.find(name); + if (it != properties_.end()) { + old_value = it->second; + old_value_ptr = &old_value; + + if (value && old_value == *value) + return; + } else if (!value) { + // This property isn't set in |properties_| and |value| is NULL, so there's + // no change. + return; + } + + if (value) { + properties_[name] = *value; + } else if (it != properties_.end()) { + properties_.erase(it); + } + + // TODO: add test coverage of this (450303). + if (manager_) { + Array<uint8_t> transport_value; + if (value) { + transport_value.resize(value->size()); + if (value->size()) + memcpy(&transport_value.front(), &(value->front()), value->size()); + } + static_cast<ViewManagerClientImpl*>(manager_)->SetProperty( + id_, name, transport_value.Pass()); + } + + FOR_EACH_OBSERVER( + ViewObserver, observers_, + OnViewSharedPropertyChanged(this, name, old_value_ptr, value)); +} + +bool View::IsDrawn() const { + if (!visible_) + return false; + return parent_ ? parent_->IsDrawn() : drawn_; +} + +void View::AddObserver(ViewObserver* observer) { + observers_.AddObserver(observer); +} + +void View::RemoveObserver(ViewObserver* observer) { + observers_.RemoveObserver(observer); +} + +const View* View::GetRoot() const { + const View* root = this; + for (const View* parent = this; parent; parent = parent->parent()) + root = parent; + return root; +} + +void View::AddChild(View* child) { + // TODO(beng): not necessarily valid to all connections, but possibly to the + // embeddee in an embedder-embeddee relationship. + if (manager_) + CHECK_EQ(child->view_manager(), manager_); + LocalAddChild(child); + if (manager_) + static_cast<ViewManagerClientImpl*>(manager_)->AddChild(child->id(), id_); +} + +void View::RemoveChild(View* child) { + // TODO(beng): not necessarily valid to all connections, but possibly to the + // embeddee in an embedder-embeddee relationship. + if (manager_) + CHECK_EQ(child->view_manager(), manager_); + LocalRemoveChild(child); + if (manager_) { + static_cast<ViewManagerClientImpl*>(manager_)->RemoveChild(child->id(), + id_); + } +} + +void View::MoveToFront() { + if (!parent_ || parent_->children_.back() == this) + return; + Reorder(parent_->children_.back(), ORDER_DIRECTION_ABOVE); +} + +void View::MoveToBack() { + if (!parent_ || parent_->children_.front() == this) + return; + Reorder(parent_->children_.front(), ORDER_DIRECTION_BELOW); +} + +void View::Reorder(View* relative, OrderDirection direction) { + if (!LocalReorder(relative, direction)) + return; + if (manager_) { + static_cast<ViewManagerClientImpl*>(manager_)->Reorder(id_, + relative->id(), + direction); + } +} + +bool View::Contains(View* child) const { + if (!child) + return false; + if (child == this) + return true; + if (manager_) + CHECK_EQ(child->view_manager(), manager_); + for (View* p = child->parent(); p; p = p->parent()) { + if (p == this) + return true; + } + return false; +} + +View* View::GetChildById(Id id) { + if (id == id_) + return this; + // TODO(beng): this could be improved depending on how we decide to own views. + Children::const_iterator it = children_.begin(); + for (; it != children_.end(); ++it) { + View* view = (*it)->GetChildById(id); + if (view) + return view; + } + return NULL; +} + +void View::SetSurfaceId(SurfaceIdPtr id) { + if (manager_) { + static_cast<ViewManagerClientImpl*>(manager_)->SetSurfaceId(id_, id.Pass()); + } +} + +void View::SetFocus() { + if (manager_) + static_cast<ViewManagerClientImpl*>(manager_)->SetFocus(id_); +} + +void View::Embed(const String& url) { + static_cast<ViewManagerClientImpl*>(manager_)->Embed(url, id_); +} + +void View::Embed(const String& url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { + static_cast<ViewManagerClientImpl*>(manager_) + ->Embed(url, id_, services.Pass(), exposed_services.Pass()); +} + +void View::Embed(ViewManagerClientPtr client) { + static_cast<ViewManagerClientImpl*>(manager_)->Embed(id_, client.Pass()); +} + +//////////////////////////////////////////////////////////////////////////////// +// View, protected: + +namespace { + +ViewportMetricsPtr CreateEmptyViewportMetrics() { + ViewportMetricsPtr metrics = ViewportMetrics::New(); + metrics->size = Size::New(); + // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it + // once that's fixed. + return metrics.Pass(); +} + +} // namespace + +View::View() + : manager_(NULL), + id_(static_cast<Id>(-1)), + parent_(NULL), + viewport_metrics_(CreateEmptyViewportMetrics()), + visible_(true), + drawn_(false) { +} + +View::~View() { + FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDestroying(this)); + if (parent_) + parent_->LocalRemoveChild(this); + + // We may still have children. This can happen if the embedder destroys the + // root while we're still alive. + while (!children_.empty()) { + View* child = children_.front(); + LocalRemoveChild(child); + DCHECK(children_.empty() || children_.front() != child); + } + + // TODO(beng): It'd be better to do this via a destruction observer in the + // ViewManagerClientImpl. + if (manager_) + static_cast<ViewManagerClientImpl*>(manager_)->RemoveView(id_); + + // Clear properties. + for (auto& pair : prop_map_) { + if (pair.second.deallocator) + (*pair.second.deallocator)(pair.second.value); + } + prop_map_.clear(); + + FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDestroyed(this)); +} + +//////////////////////////////////////////////////////////////////////////////// +// View, private: + +View::View(ViewManager* manager, Id id) + : manager_(manager), + id_(id), + parent_(nullptr), + viewport_metrics_(CreateEmptyViewportMetrics()), + visible_(false), + drawn_(false) { +} + +int64 View::SetLocalPropertyInternal(const void* key, + const char* name, + PropertyDeallocator deallocator, + int64 value, + int64 default_value) { + int64 old = GetLocalPropertyInternal(key, default_value); + if (value == default_value) { + prop_map_.erase(key); + } else { + Value prop_value; + prop_value.name = name; + prop_value.value = value; + prop_value.deallocator = deallocator; + prop_map_[key] = prop_value; + } + FOR_EACH_OBSERVER(ViewObserver, observers_, + OnViewLocalPropertyChanged(this, key, old)); + return old; +} + +int64 View::GetLocalPropertyInternal(const void* key, + int64 default_value) const { + std::map<const void*, Value>::const_iterator iter = prop_map_.find(key); + if (iter == prop_map_.end()) + return default_value; + return iter->second.value; +} + +void View::LocalDestroy() { + delete this; +} + +void View::LocalAddChild(View* child) { + ScopedTreeNotifier notifier(child, child->parent(), this); + if (child->parent()) + RemoveChildImpl(child, &child->parent_->children_); + children_.push_back(child); + child->parent_ = this; +} + +void View::LocalRemoveChild(View* child) { + DCHECK_EQ(this, child->parent()); + ScopedTreeNotifier notifier(child, this, NULL); + RemoveChildImpl(child, &children_); +} + +bool View::LocalReorder(View* relative, OrderDirection direction) { + return ReorderImpl(&parent_->children_, this, relative, direction); +} + +void View::LocalSetBounds(const Rect& old_bounds, + const Rect& new_bounds) { + DCHECK(old_bounds.x == bounds_.x); + DCHECK(old_bounds.y == bounds_.y); + DCHECK(old_bounds.width == bounds_.width); + DCHECK(old_bounds.height == bounds_.height); + ScopedSetBoundsNotifier notifier(this, old_bounds, new_bounds); + bounds_ = new_bounds; +} + +void View::LocalSetViewportMetrics(const ViewportMetrics& old_metrics, + const ViewportMetrics& new_metrics) { + // TODO(eseidel): We could check old_metrics against viewport_metrics_. + viewport_metrics_ = new_metrics.Clone(); + FOR_EACH_OBSERVER( + ViewObserver, observers_, + OnViewViewportMetricsChanged(this, old_metrics, new_metrics)); +} + +void View::LocalSetDrawn(bool value) { + if (drawn_ == value) + return; + + // As IsDrawn() is derived from |visible_| and |drawn_|, only send drawn + // notification is the value of IsDrawn() is really changing. + if (IsDrawn() == value) { + drawn_ = value; + return; + } + FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDrawnChanging(this)); + drawn_ = value; + FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDrawnChanged(this)); +} + +void View::LocalSetVisible(bool visible) { + if (visible_ == visible) + return; + + FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanging(this)); + visible_ = visible; + NotifyViewVisibilityChanged(this); +} + +void View::NotifyViewVisibilityChanged(View* target) { + if (!NotifyViewVisibilityChangedDown(target)) { + return; // |this| has been deleted. + } + NotifyViewVisibilityChangedUp(target); +} + +bool View::NotifyViewVisibilityChangedAtReceiver(View* target) { + // |this| may be deleted during a call to OnViewVisibilityChanged() on one + // of the observers. We create an local observer for that. In that case we + // exit without further access to any members. + ViewTracker tracker; + tracker.Add(this); + FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanged(target)); + return tracker.Contains(this); +} + +bool View::NotifyViewVisibilityChangedDown(View* target) { + if (!NotifyViewVisibilityChangedAtReceiver(target)) + return false; // |this| was deleted. + std::set<const View*> child_already_processed; + bool child_destroyed = false; + do { + child_destroyed = false; + for (View::Children::const_iterator it = children_.begin(); + it != children_.end(); ++it) { + if (!child_already_processed.insert(*it).second) + continue; + if (!(*it)->NotifyViewVisibilityChangedDown(target)) { + // |*it| was deleted, |it| is invalid and |children_| has changed. We + // exit the current for-loop and enter a new one. + child_destroyed = true; + break; + } + } + } while (child_destroyed); + return true; +} + +void View::NotifyViewVisibilityChangedUp(View* target) { + // Start with the parent as we already notified |this| + // in NotifyViewVisibilityChangedDown. + for (View* view = parent(); view; view = view->parent()) { + bool ret = view->NotifyViewVisibilityChangedAtReceiver(target); + DCHECK(ret); + } +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/lib/view_manager_client_factory.cc b/components/view_manager/public/cpp/lib/view_manager_client_factory.cc new file mode 100644 index 0000000..81eccbcf --- /dev/null +++ b/components/view_manager/public/cpp/lib/view_manager_client_factory.cc
@@ -0,0 +1,42 @@ +// 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/view_manager/public/cpp/view_manager_client_factory.h" + +#include "components/view_manager/public/cpp/lib/view_manager_client_impl.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h" + +namespace mojo { + +ViewManagerClientFactory::ViewManagerClientFactory( + Shell* shell, + ViewManagerDelegate* delegate) + : shell_(shell), delegate_(delegate) { +} + +ViewManagerClientFactory::~ViewManagerClientFactory() { +} + +// static +ViewManagerClient* ViewManagerClientFactory::WeakBindViewManagerToPipe( + InterfaceRequest<ViewManagerClient> request, + ViewManagerServicePtr view_manager_service, + Shell* shell, + ViewManagerDelegate* delegate) { + const bool delete_on_error = false; + auto client = new ViewManagerClientImpl(delegate, shell, request.Pass(), + delete_on_error); + client->SetViewManagerService(view_manager_service.Pass()); + return client; +} + +// InterfaceFactory<ViewManagerClient> implementation. +void ViewManagerClientFactory::Create( + ApplicationConnection* connection, + InterfaceRequest<ViewManagerClient> request) { + const bool delete_on_error = true; + new ViewManagerClientImpl(delegate_, shell_, request.Pass(), delete_on_error); +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/lib/view_manager_client_impl.cc b/components/view_manager/public/cpp/lib/view_manager_client_impl.cc new file mode 100644 index 0000000..e22b4d7 --- /dev/null +++ b/components/view_manager/public/cpp/lib/view_manager_client_impl.cc
@@ -0,0 +1,445 @@ +// 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/view_manager/public/cpp/lib/view_manager_client_impl.h" + +#include "components/view_manager/public/cpp/lib/view_private.h" +#include "components/view_manager/public/cpp/util.h" +#include "components/view_manager/public/cpp/view_manager_delegate.h" +#include "components/view_manager/public/cpp/view_observer.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/application/connect.h" +#include "third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h" + +namespace mojo { + +Id MakeTransportId(ConnectionSpecificId connection_id, + ConnectionSpecificId local_id) { + return (connection_id << 16) | local_id; +} + +// Helper called to construct a local view object from transport data. +View* AddViewToViewManager(ViewManagerClientImpl* client, + View* parent, + const ViewDataPtr& view_data) { + // We don't use the ctor that takes a ViewManager here, since it will call + // back to the service and attempt to create a new view. + View* view = ViewPrivate::LocalCreate(); + ViewPrivate private_view(view); + private_view.set_view_manager(client); + private_view.set_id(view_data->view_id); + private_view.set_visible(view_data->visible); + private_view.set_drawn(view_data->drawn); + private_view.LocalSetViewportMetrics(ViewportMetrics(), + *view_data->viewport_metrics); + private_view.set_properties( + view_data->properties.To<std::map<std::string, std::vector<uint8_t>>>()); + client->AddView(view); + private_view.LocalSetBounds(Rect(), *view_data->bounds); + if (parent) + ViewPrivate(parent).LocalAddChild(view); + return view; +} + +View* BuildViewTree(ViewManagerClientImpl* client, + const Array<ViewDataPtr>& views, + View* initial_parent) { + std::vector<View*> parents; + View* root = NULL; + View* last_view = NULL; + if (initial_parent) + parents.push_back(initial_parent); + for (size_t i = 0; i < views.size(); ++i) { + if (last_view && views[i]->parent_id == last_view->id()) { + parents.push_back(last_view); + } else if (!parents.empty()) { + while (parents.back()->id() != views[i]->parent_id) + parents.pop_back(); + } + View* view = AddViewToViewManager( + client, !parents.empty() ? parents.back() : NULL, views[i]); + if (!last_view) + root = view; + last_view = view; + } + return root; +} + +// Responsible for removing a root from the ViewManager when that view is +// destroyed. +class RootObserver : public ViewObserver { + public: + explicit RootObserver(View* root) : root_(root) {} + ~RootObserver() override {} + + private: + // Overridden from ViewObserver: + void OnViewDestroyed(View* view) override { + DCHECK_EQ(view, root_); + static_cast<ViewManagerClientImpl*>(root_->view_manager()) + ->RootDestroyed(root_); + view->RemoveObserver(this); + delete this; + } + + View* root_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(RootObserver); +}; + +ViewManagerClientImpl::ViewManagerClientImpl( + ViewManagerDelegate* delegate, + Shell* shell, + InterfaceRequest<ViewManagerClient> request, + bool delete_on_error) + : connection_id_(0), + next_id_(1), + delegate_(delegate), + root_(nullptr), + capture_view_(nullptr), + focused_view_(nullptr), + activated_view_(nullptr), + binding_(this, request.Pass()), + delete_on_error_(delete_on_error) { +} + +ViewManagerClientImpl::~ViewManagerClientImpl() { + std::vector<View*> non_owned; + while (!views_.empty()) { + IdToViewMap::iterator it = views_.begin(); + if (OwnsView(it->second->id())) { + it->second->Destroy(); + } else { + non_owned.push_back(it->second); + views_.erase(it); + } + } + // Delete the non-owned views last. In the typical case these are roots. The + // exception is the window manager, which may know aboutother random views + // that it doesn't own. + // NOTE: we manually delete as we're a friend. + for (size_t i = 0; i < non_owned.size(); ++i) + delete non_owned[i]; + + delegate_->OnViewManagerDisconnected(this); +} + +void ViewManagerClientImpl::DestroyView(Id view_id) { + DCHECK(service_); + service_->DeleteView(view_id, ActionCompletedCallback()); +} + +void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) { + DCHECK(service_); + service_->AddView(parent_id, child_id, ActionCompletedCallback()); +} + +void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) { + DCHECK(service_); + service_->RemoveViewFromParent(child_id, ActionCompletedCallback()); +} + +void ViewManagerClientImpl::Reorder( + Id view_id, + Id relative_view_id, + OrderDirection direction) { + DCHECK(service_); + service_->ReorderView(view_id, relative_view_id, direction, + ActionCompletedCallback()); +} + +bool ViewManagerClientImpl::OwnsView(Id id) const { + return HiWord(id) == connection_id_; +} + +void ViewManagerClientImpl::SetBounds(Id view_id, const Rect& bounds) { + DCHECK(service_); + service_->SetViewBounds(view_id, bounds.Clone(), ActionCompletedCallback()); +} + +void ViewManagerClientImpl::SetSurfaceId(Id view_id, SurfaceIdPtr surface_id) { + DCHECK(service_); + if (surface_id.is_null()) + return; + service_->SetViewSurfaceId( + view_id, surface_id.Pass(), ActionCompletedCallback()); +} + +void ViewManagerClientImpl::SetFocus(Id view_id) { + // In order for us to get here we had to have exposed a view, which implies we + // got a connection. + DCHECK(service_); + service_->SetFocus(view_id, ActionCompletedCallback()); +} + +void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) { + DCHECK(service_); + service_->SetViewVisibility(view_id, visible, ActionCompletedCallback()); +} + +void ViewManagerClientImpl::SetProperty( + Id view_id, + const std::string& name, + const std::vector<uint8_t>& data) { + DCHECK(service_); + service_->SetViewProperty(view_id, + String(name), + Array<uint8_t>::From(data), + ActionCompletedCallback()); +} + +void ViewManagerClientImpl::Embed(const String& url, Id view_id) { + Embed(url, view_id, nullptr, nullptr); +} + +void ViewManagerClientImpl::Embed(const String& url, + Id view_id, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { + DCHECK(service_); + service_->EmbedUrl(url, view_id, services.Pass(), exposed_services.Pass(), + ActionCompletedCallback()); +} + +void ViewManagerClientImpl::Embed(Id view_id, ViewManagerClientPtr client) { + DCHECK(service_); + service_->Embed(view_id, client.Pass(), ActionCompletedCallback()); +} + +void ViewManagerClientImpl::AddView(View* view) { + DCHECK(views_.find(view->id()) == views_.end()); + views_[view->id()] = view; +} + +void ViewManagerClientImpl::RemoveView(Id view_id) { + if (focused_view_ && focused_view_->id() == view_id) + OnViewFocused(0); + + IdToViewMap::iterator it = views_.find(view_id); + if (it != views_.end()) + views_.erase(it); +} + +void ViewManagerClientImpl::SetViewManagerService( + ViewManagerServicePtr service) { + DCHECK(!service_); + DCHECK(service); + service_ = service.Pass(); +} +//////////////////////////////////////////////////////////////////////////////// +// ViewManagerClientImpl, ViewManager implementation: + +Id ViewManagerClientImpl::CreateViewOnServer() { + DCHECK(service_); + const Id view_id = MakeTransportId(connection_id_, ++next_id_); + service_->CreateView(view_id, [this](ErrorCode code) { + OnActionCompleted(code == ERROR_CODE_NONE); + }); + return view_id; +} + +const std::string& ViewManagerClientImpl::GetEmbedderURL() const { + return creator_url_; +} + +View* ViewManagerClientImpl::GetRoot() { + return root_; +} + +View* ViewManagerClientImpl::GetViewById(Id id) { + IdToViewMap::const_iterator it = views_.find(id); + return it != views_.end() ? it->second : NULL; +} + +View* ViewManagerClientImpl::GetFocusedView() { + return focused_view_; +} + +View* ViewManagerClientImpl::CreateView() { + View* view = new View(this, CreateViewOnServer()); + AddView(view); + return view; +} + +//////////////////////////////////////////////////////////////////////////////// +// ViewManagerClientImpl, ViewManagerClient implementation: + +void ViewManagerClientImpl::OnEmbed(ConnectionSpecificId connection_id, + const String& creator_url, + ViewDataPtr root_data, + ViewManagerServicePtr view_manager_service, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + Id focused_view_id) { + if (view_manager_service) { + DCHECK(!service_); + service_ = view_manager_service.Pass(); + } + connection_id_ = connection_id; + creator_url_ = String::From(creator_url); + + DCHECK(!root_); + root_ = AddViewToViewManager(this, nullptr, root_data); + root_->AddObserver(new RootObserver(root_)); + + focused_view_ = GetViewById(focused_view_id); + + delegate_->OnEmbed(root_, services.Pass(), exposed_services.Pass()); +} + +void ViewManagerClientImpl::OnEmbeddedAppDisconnected(Id view_id) { + View* view = GetViewById(view_id); + if (view) { + FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(), + OnViewEmbeddedAppDisconnected(view)); + } +} + +void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id, + RectPtr old_bounds, + RectPtr new_bounds) { + View* view = GetViewById(view_id); + ViewPrivate(view).LocalSetBounds(*old_bounds, *new_bounds); +} + +namespace { + +void SetViewportMetricsOnDecendants(View* root, + const ViewportMetrics& old_metrics, + const ViewportMetrics& new_metrics) { + ViewPrivate(root).LocalSetViewportMetrics(old_metrics, new_metrics); + const View::Children& children = root->children(); + for (size_t i = 0; i < children.size(); ++i) + SetViewportMetricsOnDecendants(children[i], old_metrics, new_metrics); +} +} + +void ViewManagerClientImpl::OnViewViewportMetricsChanged( + ViewportMetricsPtr old_metrics, + ViewportMetricsPtr new_metrics) { + View* view = GetRoot(); + if (view) + SetViewportMetricsOnDecendants(view, *old_metrics, *new_metrics); +} + +void ViewManagerClientImpl::OnViewHierarchyChanged( + Id view_id, + Id new_parent_id, + Id old_parent_id, + mojo::Array<ViewDataPtr> views) { + View* initial_parent = views.size() ? + GetViewById(views[0]->parent_id) : NULL; + + BuildViewTree(this, views, initial_parent); + + View* new_parent = GetViewById(new_parent_id); + View* old_parent = GetViewById(old_parent_id); + View* view = GetViewById(view_id); + if (new_parent) + ViewPrivate(new_parent).LocalAddChild(view); + else + ViewPrivate(old_parent).LocalRemoveChild(view); +} + +void ViewManagerClientImpl::OnViewReordered(Id view_id, + Id relative_view_id, + OrderDirection direction) { + View* view = GetViewById(view_id); + View* relative_view = GetViewById(relative_view_id); + if (view && relative_view) + ViewPrivate(view).LocalReorder(relative_view, direction); +} + +void ViewManagerClientImpl::OnViewDeleted(Id view_id) { + View* view = GetViewById(view_id); + if (view) + ViewPrivate(view).LocalDestroy(); +} + +void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) { + // TODO(sky): there is a race condition here. If this client and another + // client change the visibility at the same time the wrong value may be set. + // Deal with this some how. + View* view = GetViewById(view_id); + if (view) + ViewPrivate(view).LocalSetVisible(visible); +} + +void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) { + View* view = GetViewById(view_id); + if (view) + ViewPrivate(view).LocalSetDrawn(drawn); +} + +void ViewManagerClientImpl::OnViewSharedPropertyChanged( + Id view_id, + const String& name, + Array<uint8_t> new_data) { + View* view = GetViewById(view_id); + if (view) { + std::vector<uint8_t> data; + std::vector<uint8_t>* data_ptr = NULL; + if (!new_data.is_null()) { + data = new_data.To<std::vector<uint8_t>>(); + data_ptr = &data; + } + + view->SetSharedProperty(name, data_ptr); + } +} + +void ViewManagerClientImpl::OnViewInputEvent( + Id view_id, + EventPtr event, + const Callback<void()>& ack_callback) { + View* view = GetViewById(view_id); + if (view) { + FOR_EACH_OBSERVER(ViewObserver, + *ViewPrivate(view).observers(), + OnViewInputEvent(view, event)); + } + ack_callback.Run(); +} + +void ViewManagerClientImpl::OnViewFocused(Id focused_view_id) { + View* focused = GetViewById(focused_view_id); + View* blurred = focused_view_; + if (blurred) { + FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(blurred).observers(), + OnViewFocusChanged(focused, blurred)); + } + focused_view_ = focused; + if (focused) { + FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(focused).observers(), + OnViewFocusChanged(focused, blurred)); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// OnConnectionError, private: +void ViewManagerClientImpl::OnConnectionError() { + if (delete_on_error_) + delete this; +} + +//////////////////////////////////////////////////////////////////////////////// +// ViewManagerClientImpl, private: + +void ViewManagerClientImpl::RootDestroyed(View* root) { + DCHECK_EQ(root, root_); + root_ = nullptr; +} + +void ViewManagerClientImpl::OnActionCompleted(bool success) { + if (!change_acked_callback_.is_null()) + change_acked_callback_.Run(); +} + +Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() { + return [this](bool success) { OnActionCompleted(success); }; +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/lib/view_manager_client_impl.h b/components/view_manager/public/cpp/lib/view_manager_client_impl.h new file mode 100644 index 0000000..04bc121a --- /dev/null +++ b/components/view_manager/public/cpp/lib/view_manager_client_impl.h
@@ -0,0 +1,157 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_MANAGER_CLIENT_IMPL_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_MANAGER_CLIENT_IMPL_H_ + +#include "components/view_manager/public/cpp/types.h" +#include "components/view_manager/public/cpp/view.h" +#include "components/view_manager/public/cpp/view_manager.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" + +namespace mojo { +class Shell; +class ViewManager; +class ViewManagerDelegate; +class ViewManagerTransaction; + +// Manages the connection with the View Manager service. +class ViewManagerClientImpl : public ViewManager, + public ViewManagerClient, + public ErrorHandler { + public: + ViewManagerClientImpl(ViewManagerDelegate* delegate, + Shell* shell, + InterfaceRequest<ViewManagerClient> request, + bool delete_on_error); + ~ViewManagerClientImpl() override; + + bool connected() const { return service_; } + ConnectionSpecificId connection_id() const { return connection_id_; } + + // API exposed to the view implementations that pushes local changes to the + // service. + void DestroyView(Id view_id); + + // These methods take TransportIds. For views owned by the current connection, + // the connection id high word can be zero. In all cases, the TransportId 0x1 + // refers to the root view. + void AddChild(Id child_id, Id parent_id); + void RemoveChild(Id child_id, Id parent_id); + + void Reorder(Id view_id, Id relative_view_id, OrderDirection direction); + + // Returns true if the specified view was created by this connection. + bool OwnsView(Id id) const; + + void SetBounds(Id view_id, const Rect& bounds); + void SetSurfaceId(Id view_id, SurfaceIdPtr surface_id); + void SetFocus(Id view_id); + void SetVisible(Id view_id, bool visible); + void SetProperty(Id view_id, + const std::string& name, + const std::vector<uint8_t>& data); + + void Embed(const String& url, Id view_id); + void Embed(const String& url, + Id view_id, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services); + void Embed(Id view_id, ViewManagerClientPtr client); + + void set_change_acked_callback(const Callback<void(void)>& callback) { + change_acked_callback_ = callback; + } + void ClearChangeAckedCallback() { change_acked_callback_.reset(); } + + // Start/stop tracking views. While tracked, they can be retrieved via + // ViewManager::GetViewById. + void AddView(View* view); + void RemoveView(Id view_id); + + void SetViewManagerService(ViewManagerServicePtr service); + + private: + friend class RootObserver; + + typedef std::map<Id, View*> IdToViewMap; + + Id CreateViewOnServer(); + + // Overridden from ViewManager: + const std::string& GetEmbedderURL() const override; + View* GetRoot() override; + View* GetViewById(Id id) override; + View* GetFocusedView() override; + View* CreateView() override; + + // Overridden from ViewManagerClient: + void OnEmbed(ConnectionSpecificId connection_id, + const String& creator_url, + ViewDataPtr root, + ViewManagerServicePtr view_manager_service, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + Id focused_view_id) override; + void OnEmbeddedAppDisconnected(Id view_id) override; + void OnViewBoundsChanged(Id view_id, + RectPtr old_bounds, + RectPtr new_bounds) override; + void OnViewViewportMetricsChanged(ViewportMetricsPtr old_metrics, + ViewportMetricsPtr new_metrics) override; + void OnViewHierarchyChanged(Id view_id, + Id new_parent_id, + Id old_parent_id, + Array<ViewDataPtr> views) override; + void OnViewReordered(Id view_id, + Id relative_view_id, + OrderDirection direction) override; + void OnViewDeleted(Id view_id) override; + void OnViewVisibilityChanged(Id view_id, bool visible) override; + void OnViewDrawnStateChanged(Id view_id, bool drawn) override; + void OnViewSharedPropertyChanged(Id view_id, + const String& name, + Array<uint8_t> new_data) override; + void OnViewInputEvent(Id view_id, + EventPtr event, + const Callback<void()>& callback) override; + void OnViewFocused(Id focused_view_id) override; + + // ErrorHandler implementation. + void OnConnectionError() override; + + void RootDestroyed(View* root); + + void OnActionCompleted(bool success); + + Callback<void(bool)> ActionCompletedCallback(); + + ConnectionSpecificId connection_id_; + ConnectionSpecificId next_id_; + + std::string creator_url_; + + Callback<void(void)> change_acked_callback_; + + ViewManagerDelegate* delegate_; + + View* root_; + + IdToViewMap views_; + + View* capture_view_; + View* focused_view_; + View* activated_view_; + + Binding<ViewManagerClient> binding_; + ViewManagerServicePtr service_; + const bool delete_on_error_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerClientImpl); +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_MANAGER_CLIENT_IMPL_H_
diff --git a/components/view_manager/public/cpp/lib/view_manager_context.cc b/components/view_manager/public/cpp/lib/view_manager_context.cc new file mode 100644 index 0000000..f1fdd4f2 --- /dev/null +++ b/components/view_manager/public/cpp/lib/view_manager_context.cc
@@ -0,0 +1,45 @@ +// 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/view_manager/public/cpp/view_manager_context.h" + +#include "components/window_manager/public/interfaces/window_manager.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" + +namespace mojo { +class ApplicationImpl; + +class ViewManagerContext::InternalState { + public: + explicit InternalState(ApplicationImpl* application_impl) { + application_impl->ConnectToService("mojo:window_manager", &wm_); + } + ~InternalState() {} + + WindowManager* wm() { return wm_.get(); } + + private: + WindowManagerPtr wm_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(InternalState); +}; + +ViewManagerContext::ViewManagerContext(ApplicationImpl* application_impl) + : state_(new InternalState(application_impl)) {} +ViewManagerContext::~ViewManagerContext() { + delete state_; +} + +void ViewManagerContext::Embed(const String& url) { + Embed(url, nullptr, nullptr); +} + +void ViewManagerContext::Embed(const String& url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { + state_->wm()->Embed(url, services.Pass(), exposed_services.Pass()); +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/lib/view_observer.cc b/components/view_manager/public/cpp/lib/view_observer.cc new file mode 100644 index 0000000..8c6fcaa --- /dev/null +++ b/components/view_manager/public/cpp/lib/view_observer.cc
@@ -0,0 +1,19 @@ +// 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/view_manager/public/cpp/view_observer.h" + +namespace mojo { + +//////////////////////////////////////////////////////////////////////////////// +// ViewObserver, public: + +ViewObserver::TreeChangeParams::TreeChangeParams() + : target(nullptr), + old_parent(nullptr), + new_parent(nullptr), + receiver(nullptr) { +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/lib/view_private.cc b/components/view_manager/public/cpp/lib/view_private.cc new file mode 100644 index 0000000..c1a8ed842 --- /dev/null +++ b/components/view_manager/public/cpp/lib/view_private.cc
@@ -0,0 +1,22 @@ +// 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/view_manager/public/cpp/lib/view_private.h" + +namespace mojo { + +ViewPrivate::ViewPrivate(View* view) + : view_(view) { + CHECK(view); +} + +ViewPrivate::~ViewPrivate() { +} + +// static +View* ViewPrivate::LocalCreate() { + return new View; +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/lib/view_private.h b/components/view_manager/public/cpp/lib/view_private.h new file mode 100644 index 0000000..a63711e7 --- /dev/null +++ b/components/view_manager/public/cpp/lib/view_private.h
@@ -0,0 +1,72 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_PRIVATE_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_PRIVATE_H_ + +#include "components/view_manager/public/cpp/view.h" + +namespace mojo { + +// This class is a friend of a View and contains functions to mutate internal +// state of View. +class ViewPrivate { + public: + explicit ViewPrivate(View* view); + ~ViewPrivate(); + + // Creates and returns a new View. Caller owns the return value. + static View* LocalCreate(); + + ObserverList<ViewObserver>* observers() { return &view_->observers_; } + + void ClearParent() { view_->parent_ = NULL; } + + void set_visible(bool visible) { view_->visible_ = visible; } + + void set_drawn(bool drawn) { view_->drawn_ = drawn; } + + void set_id(Id id) { view_->id_ = id; } + + void set_view_manager(ViewManager* manager) { + view_->manager_ = manager; + } + + void set_properties(const std::map<std::string, std::vector<uint8_t>>& data) { + view_->properties_ = data; + } + + void LocalSetViewportMetrics(const ViewportMetrics& old_metrics, + const ViewportMetrics& new_metrics) { + view_->LocalSetViewportMetrics(new_metrics, new_metrics); + } + + void LocalDestroy() { + view_->LocalDestroy(); + } + void LocalAddChild(View* child) { + view_->LocalAddChild(child); + } + void LocalRemoveChild(View* child) { + view_->LocalRemoveChild(child); + } + void LocalReorder(View* relative, OrderDirection direction) { + view_->LocalReorder(relative, direction); + } + void LocalSetBounds(const Rect& old_bounds, + const Rect& new_bounds) { + view_->LocalSetBounds(old_bounds, new_bounds); + } + void LocalSetDrawn(bool drawn) { view_->LocalSetDrawn(drawn); } + void LocalSetVisible(bool visible) { view_->LocalSetVisible(visible); } + + private: + View* view_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ViewPrivate); +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_PRIVATE_H_
diff --git a/components/view_manager/public/cpp/tests/BUILD.gn b/components/view_manager/public/cpp/tests/BUILD.gn new file mode 100644 index 0000000..393b0e29 --- /dev/null +++ b/components/view_manager/public/cpp/tests/BUILD.gn
@@ -0,0 +1,36 @@ +# 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. + +import("//build/config/ui.gni") +import("//testing/test.gni") + +test("mojo_view_manager_lib_unittests") { + sources = [ + "run_all_unittests.cc", + "view_manager_test_suite.cc", + "view_manager_test_suite.h", + "view_unittest.cc", + ] + + deps = [ + "//base", + "//base/test:test_support", + + # TODO(vtl): These non-public deps are illegal here. This should be + # converted to an apptest. + "//mojo/application", + "//mojo/edk/system", + "//mojo/environment:chromium", + "//mojo/public/cpp/application", + "//mojo/public/cpp/system", + "//mojo/services/geometry/public/cpp", + "//mojo/services/geometry/public/interfaces", + "//mojo/services/view_manager/public/cpp", + "//testing/gtest", + ] + + if (use_x11) { + deps += [ "//ui/gfx/x" ] + } +}
diff --git a/components/view_manager/public/cpp/tests/run_all_unittests.cc b/components/view_manager/public/cpp/tests/run_all_unittests.cc new file mode 100644 index 0000000..9d2bf13 --- /dev/null +++ b/components/view_manager/public/cpp/tests/run_all_unittests.cc
@@ -0,0 +1,14 @@ +// 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 "base/bind.h" +#include "base/test/launcher/unit_test_launcher.h" +#include "components/view_manager/public/cpp/tests/view_manager_test_suite.h" + +int main(int argc, char** argv) { + mojo::ViewManagerTestSuite test_suite(argc, argv); + + return base::LaunchUnitTests( + argc, argv, base::Bind(&TestSuite::Run, base::Unretained(&test_suite))); +}
diff --git a/components/view_manager/public/cpp/tests/view_manager_test_suite.cc b/components/view_manager/public/cpp/tests/view_manager_test_suite.cc new file mode 100644 index 0000000..ea3d965 --- /dev/null +++ b/components/view_manager/public/cpp/tests/view_manager_test_suite.cc
@@ -0,0 +1,34 @@ +// 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/view_manager/public/cpp/tests/view_manager_test_suite.h" + +#include "base/i18n/icu_util.h" + +#if defined(USE_X11) +#include "ui/gfx/x/x11_connection.h" +#endif + +namespace mojo { + +ViewManagerTestSuite::ViewManagerTestSuite(int argc, char** argv) + : TestSuite(argc, argv) {} + +ViewManagerTestSuite::~ViewManagerTestSuite() { +} + +void ViewManagerTestSuite::Initialize() { +#if defined(USE_X11) + // Each test ends up creating a new thread for the native viewport service. + // In other words we'll use X on different threads, so tell it that. + gfx::InitializeThreadedX11(); +#endif + + base::TestSuite::Initialize(); + + // base::TestSuite and ViewsInit both try to load icu. That's ok for tests. + base::i18n::AllowMultipleInitializeCallsForTesting(); +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/tests/view_manager_test_suite.h b/components/view_manager/public/cpp/tests/view_manager_test_suite.h new file mode 100644 index 0000000..1df8743 --- /dev/null +++ b/components/view_manager/public/cpp/tests/view_manager_test_suite.h
@@ -0,0 +1,27 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_TESTS_VIEW_MANAGER_TEST_SUITE_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_TESTS_VIEW_MANAGER_TEST_SUITE_H_ + +#include "base/test/test_suite.h" +#include "third_party/mojo/src/mojo/public/cpp/system/macros.h" + +namespace mojo { + +class ViewManagerTestSuite : public base::TestSuite { + public: + ViewManagerTestSuite(int argc, char** argv); + ~ViewManagerTestSuite() override; + + protected: + void Initialize() override; + + private: + MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerTestSuite); +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_TESTS_VIEW_MANAGER_TEST_SUITE_H_
diff --git a/components/view_manager/public/cpp/tests/view_unittest.cc b/components/view_manager/public/cpp/tests/view_unittest.cc new file mode 100644 index 0000000..51c6b5e --- /dev/null +++ b/components/view_manager/public/cpp/tests/view_unittest.cc
@@ -0,0 +1,884 @@ +// 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/view_manager/public/cpp/view.h" + +#include "base/logging.h" +#include "base/strings/stringprintf.h" +#include "components/view_manager/public/cpp/lib/view_private.h" +#include "components/view_manager/public/cpp/util.h" +#include "components/view_manager/public/cpp/view_observer.h" +#include "components/view_manager/public/cpp/view_property.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { + +// View ------------------------------------------------------------------------ + +typedef testing::Test ViewTest; + +// Subclass with public ctor/dtor. +class TestView : public View { + public: + TestView() { + ViewPrivate(this).set_id(1); + } + ~TestView() {} + + private: + MOJO_DISALLOW_COPY_AND_ASSIGN(TestView); +}; + +TEST_F(ViewTest, AddChild) { + TestView v1; + TestView v11; + v1.AddChild(&v11); + EXPECT_EQ(1U, v1.children().size()); +} + +TEST_F(ViewTest, RemoveChild) { + TestView v1; + TestView v11; + v1.AddChild(&v11); + EXPECT_EQ(1U, v1.children().size()); + v1.RemoveChild(&v11); + EXPECT_EQ(0U, v1.children().size()); +} + +TEST_F(ViewTest, Reparent) { + TestView v1; + TestView v2; + TestView v11; + v1.AddChild(&v11); + EXPECT_EQ(1U, v1.children().size()); + v2.AddChild(&v11); + EXPECT_EQ(1U, v2.children().size()); + EXPECT_EQ(0U, v1.children().size()); +} + +TEST_F(ViewTest, Contains) { + TestView v1; + + // Direct descendant. + TestView v11; + v1.AddChild(&v11); + EXPECT_TRUE(v1.Contains(&v11)); + + // Indirect descendant. + TestView v111; + v11.AddChild(&v111); + EXPECT_TRUE(v1.Contains(&v111)); +} + +TEST_F(ViewTest, GetChildById) { + TestView v1; + ViewPrivate(&v1).set_id(1); + TestView v11; + ViewPrivate(&v11).set_id(11); + v1.AddChild(&v11); + TestView v111; + ViewPrivate(&v111).set_id(111); + v11.AddChild(&v111); + + // Find direct & indirect descendents. + EXPECT_EQ(&v11, v1.GetChildById(v11.id())); + EXPECT_EQ(&v111, v1.GetChildById(v111.id())); +} + +TEST_F(ViewTest, DrawnAndVisible) { + TestView v1; + EXPECT_TRUE(v1.visible()); + EXPECT_FALSE(v1.IsDrawn()); + + ViewPrivate(&v1).set_drawn(true); + + TestView v11; + v1.AddChild(&v11); + EXPECT_TRUE(v11.visible()); + EXPECT_TRUE(v11.IsDrawn()); + + v1.RemoveChild(&v11); + EXPECT_TRUE(v11.visible()); + EXPECT_FALSE(v11.IsDrawn()); +} + +namespace { +DEFINE_VIEW_PROPERTY_KEY(int, kIntKey, -2); +DEFINE_VIEW_PROPERTY_KEY(const char*, kStringKey, "squeamish"); +} + +TEST_F(ViewTest, Property) { + TestView v; + + // Non-existent properties should return the default values. + EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); + EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); + + // A set property value should be returned again (even if it's the default + // value). + v.SetLocalProperty(kIntKey, INT_MAX); + EXPECT_EQ(INT_MAX, v.GetLocalProperty(kIntKey)); + v.SetLocalProperty(kIntKey, -2); + EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); + v.SetLocalProperty(kIntKey, INT_MIN); + EXPECT_EQ(INT_MIN, v.GetLocalProperty(kIntKey)); + + v.SetLocalProperty(kStringKey, static_cast<const char*>(NULL)); + EXPECT_EQ(NULL, v.GetLocalProperty(kStringKey)); + v.SetLocalProperty(kStringKey, "squeamish"); + EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); + v.SetLocalProperty(kStringKey, "ossifrage"); + EXPECT_EQ(std::string("ossifrage"), v.GetLocalProperty(kStringKey)); + + // ClearProperty should restore the default value. + v.ClearLocalProperty(kIntKey); + EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); + v.ClearLocalProperty(kStringKey); + EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); +} + +namespace { + +class TestProperty { + public: + TestProperty() {} + virtual ~TestProperty() { last_deleted_ = this; } + static TestProperty* last_deleted() { return last_deleted_; } + + private: + static TestProperty* last_deleted_; + MOJO_DISALLOW_COPY_AND_ASSIGN(TestProperty); +}; + +TestProperty* TestProperty::last_deleted_ = NULL; + +DEFINE_OWNED_VIEW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL); + +} // namespace + +TEST_F(ViewTest, OwnedProperty) { + TestProperty* p3 = NULL; + { + TestView v; + EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey)); + TestProperty* p1 = new TestProperty(); + v.SetLocalProperty(kOwnedKey, p1); + EXPECT_EQ(p1, v.GetLocalProperty(kOwnedKey)); + EXPECT_EQ(NULL, TestProperty::last_deleted()); + + TestProperty* p2 = new TestProperty(); + v.SetLocalProperty(kOwnedKey, p2); + EXPECT_EQ(p2, v.GetLocalProperty(kOwnedKey)); + EXPECT_EQ(p1, TestProperty::last_deleted()); + + v.ClearLocalProperty(kOwnedKey); + EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey)); + EXPECT_EQ(p2, TestProperty::last_deleted()); + + p3 = new TestProperty(); + v.SetLocalProperty(kOwnedKey, p3); + EXPECT_EQ(p3, v.GetLocalProperty(kOwnedKey)); + EXPECT_EQ(p2, TestProperty::last_deleted()); + } + + EXPECT_EQ(p3, TestProperty::last_deleted()); +} + +// ViewObserver -------------------------------------------------------- + +typedef testing::Test ViewObserverTest; + +bool TreeChangeParamsMatch(const ViewObserver::TreeChangeParams& lhs, + const ViewObserver::TreeChangeParams& rhs) { + return lhs.target == rhs.target && lhs.old_parent == rhs.old_parent && + lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver; +} + +class TreeChangeObserver : public ViewObserver { + public: + explicit TreeChangeObserver(View* observee) : observee_(observee) { + observee_->AddObserver(this); + } + ~TreeChangeObserver() override { observee_->RemoveObserver(this); } + + void Reset() { + received_params_.clear(); + } + + const std::vector<TreeChangeParams>& received_params() { + return received_params_; + } + + private: + // Overridden from ViewObserver: + void OnTreeChanging(const TreeChangeParams& params) override { + received_params_.push_back(params); + } + void OnTreeChanged(const TreeChangeParams& params) override { + received_params_.push_back(params); + } + + View* observee_; + std::vector<TreeChangeParams> received_params_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver); +}; + +// Adds/Removes v11 to v1. +TEST_F(ViewObserverTest, TreeChange_SimpleAddRemove) { + TestView v1; + TreeChangeObserver o1(&v1); + EXPECT_TRUE(o1.received_params().empty()); + + TestView v11; + TreeChangeObserver o11(&v11); + EXPECT_TRUE(o11.received_params().empty()); + + // Add. + + v1.AddChild(&v11); + + EXPECT_EQ(2U, o1.received_params().size()); + ViewObserver::TreeChangeParams p1; + p1.target = &v11; + p1.receiver = &v1; + p1.old_parent = NULL; + p1.new_parent = &v1; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); + + EXPECT_EQ(2U, o11.received_params().size()); + ViewObserver::TreeChangeParams p11 = p1; + p11.receiver = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); + + o1.Reset(); + o11.Reset(); + EXPECT_TRUE(o1.received_params().empty()); + EXPECT_TRUE(o11.received_params().empty()); + + // Remove. + + v1.RemoveChild(&v11); + + EXPECT_EQ(2U, o1.received_params().size()); + p1.target = &v11; + p1.receiver = &v1; + p1.old_parent = &v1; + p1.new_parent = NULL; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); + + EXPECT_EQ(2U, o11.received_params().size()); + p11 = p1; + p11.receiver = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); +} + +// Creates these two trees: +// v1 +// +- v11 +// v111 +// +- v1111 +// +- v1112 +// Then adds/removes v111 from v11. +TEST_F(ViewObserverTest, TreeChange_NestedAddRemove) { + TestView v1, v11, v111, v1111, v1112; + + // Root tree. + v1.AddChild(&v11); + + // Tree to be attached. + v111.AddChild(&v1111); + v111.AddChild(&v1112); + + TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111), + o1112(&v1112); + ViewObserver::TreeChangeParams p1, p11, p111, p1111, p1112; + + // Add. + + v11.AddChild(&v111); + + EXPECT_EQ(2U, o1.received_params().size()); + p1.target = &v111; + p1.receiver = &v1; + p1.old_parent = NULL; + p1.new_parent = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); + + EXPECT_EQ(2U, o11.received_params().size()); + p11 = p1; + p11.receiver = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); + + EXPECT_EQ(2U, o111.received_params().size()); + p111 = p11; + p111.receiver = &v111; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); + + EXPECT_EQ(2U, o1111.received_params().size()); + p1111 = p111; + p1111.receiver = &v1111; + EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); + + EXPECT_EQ(2U, o1112.received_params().size()); + p1112 = p111; + p1112.receiver = &v1112; + EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); + + // Remove. + o1.Reset(); + o11.Reset(); + o111.Reset(); + o1111.Reset(); + o1112.Reset(); + EXPECT_TRUE(o1.received_params().empty()); + EXPECT_TRUE(o11.received_params().empty()); + EXPECT_TRUE(o111.received_params().empty()); + EXPECT_TRUE(o1111.received_params().empty()); + EXPECT_TRUE(o1112.received_params().empty()); + + v11.RemoveChild(&v111); + + EXPECT_EQ(2U, o1.received_params().size()); + p1.target = &v111; + p1.receiver = &v1; + p1.old_parent = &v11; + p1.new_parent = NULL; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); + + EXPECT_EQ(2U, o11.received_params().size()); + p11 = p1; + p11.receiver = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); + + EXPECT_EQ(2U, o111.received_params().size()); + p111 = p11; + p111.receiver = &v111; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); + + EXPECT_EQ(2U, o1111.received_params().size()); + p1111 = p111; + p1111.receiver = &v1111; + EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); + + EXPECT_EQ(2U, o1112.received_params().size()); + p1112 = p111; + p1112.receiver = &v1112; + EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); +} + +TEST_F(ViewObserverTest, TreeChange_Reparent) { + TestView v1, v11, v12, v111; + v1.AddChild(&v11); + v1.AddChild(&v12); + v11.AddChild(&v111); + + TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111); + + // Reparent. + v12.AddChild(&v111); + + // v1 (root) should see both changing and changed notifications. + EXPECT_EQ(4U, o1.received_params().size()); + ViewObserver::TreeChangeParams p1; + p1.target = &v111; + p1.receiver = &v1; + p1.old_parent = &v11; + p1.new_parent = &v12; + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); + + // v11 should see changing notifications. + EXPECT_EQ(2U, o11.received_params().size()); + ViewObserver::TreeChangeParams p11; + p11 = p1; + p11.receiver = &v11; + EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); + + // v12 should see changed notifications. + EXPECT_EQ(2U, o12.received_params().size()); + ViewObserver::TreeChangeParams p12; + p12 = p1; + p12.receiver = &v12; + EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back())); + + // v111 should see both changing and changed notifications. + EXPECT_EQ(2U, o111.received_params().size()); + ViewObserver::TreeChangeParams p111; + p111 = p1; + p111.receiver = &v111; + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); + EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); +} + +namespace { + +class OrderChangeObserver : public ViewObserver { + public: + struct Change { + View* view; + View* relative_view; + OrderDirection direction; + }; + typedef std::vector<Change> Changes; + + explicit OrderChangeObserver(View* observee) : observee_(observee) { + observee_->AddObserver(this); + } + ~OrderChangeObserver() override { observee_->RemoveObserver(this); } + + Changes GetAndClearChanges() { + Changes changes; + changes_.swap(changes); + return changes; + } + + private: + // Overridden from ViewObserver: + void OnViewReordering(View* view, + View* relative_view, + OrderDirection direction) override { + OnViewReordered(view, relative_view, direction); + } + + void OnViewReordered(View* view, + View* relative_view, + OrderDirection direction) override { + Change change; + change.view = view; + change.relative_view = relative_view; + change.direction = direction; + changes_.push_back(change); + } + + View* observee_; + Changes changes_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver); +}; + +} // namespace + +TEST_F(ViewObserverTest, Order) { + TestView v1, v11, v12, v13; + v1.AddChild(&v11); + v1.AddChild(&v12); + v1.AddChild(&v13); + + // Order: v11, v12, v13 + EXPECT_EQ(3U, v1.children().size()); + EXPECT_EQ(&v11, v1.children().front()); + EXPECT_EQ(&v13, v1.children().back()); + + { + OrderChangeObserver observer(&v11); + + // Move v11 to front. + // Resulting order: v12, v13, v11 + v11.MoveToFront(); + EXPECT_EQ(&v12, v1.children().front()); + EXPECT_EQ(&v11, v1.children().back()); + + OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(2U, changes.size()); + EXPECT_EQ(&v11, changes[0].view); + EXPECT_EQ(&v13, changes[0].relative_view); + EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[0].direction); + + EXPECT_EQ(&v11, changes[1].view); + EXPECT_EQ(&v13, changes[1].relative_view); + EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[1].direction); + } + + { + OrderChangeObserver observer(&v11); + + // Move v11 to back. + // Resulting order: v11, v12, v13 + v11.MoveToBack(); + EXPECT_EQ(&v11, v1.children().front()); + EXPECT_EQ(&v13, v1.children().back()); + + OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(2U, changes.size()); + EXPECT_EQ(&v11, changes[0].view); + EXPECT_EQ(&v12, changes[0].relative_view); + EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[0].direction); + + EXPECT_EQ(&v11, changes[1].view); + EXPECT_EQ(&v12, changes[1].relative_view); + EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[1].direction); + } + + { + OrderChangeObserver observer(&v11); + + // Move v11 above v12. + // Resulting order: v12. v11, v13 + v11.Reorder(&v12, ORDER_DIRECTION_ABOVE); + EXPECT_EQ(&v12, v1.children().front()); + EXPECT_EQ(&v13, v1.children().back()); + + OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(2U, changes.size()); + EXPECT_EQ(&v11, changes[0].view); + EXPECT_EQ(&v12, changes[0].relative_view); + EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[0].direction); + + EXPECT_EQ(&v11, changes[1].view); + EXPECT_EQ(&v12, changes[1].relative_view); + EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[1].direction); + } + + { + OrderChangeObserver observer(&v11); + + // Move v11 below v12. + // Resulting order: v11, v12, v13 + v11.Reorder(&v12, ORDER_DIRECTION_BELOW); + EXPECT_EQ(&v11, v1.children().front()); + EXPECT_EQ(&v13, v1.children().back()); + + OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(2U, changes.size()); + EXPECT_EQ(&v11, changes[0].view); + EXPECT_EQ(&v12, changes[0].relative_view); + EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[0].direction); + + EXPECT_EQ(&v11, changes[1].view); + EXPECT_EQ(&v12, changes[1].relative_view); + EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[1].direction); + } +} + +namespace { + +typedef std::vector<std::string> Changes; + +std::string ViewIdToString(Id id) { + return (id == 0) ? "null" : + base::StringPrintf("%d,%d", HiWord(id), LoWord(id)); +} + +std::string RectToString(const Rect& rect) { + return base::StringPrintf("%d,%d %dx%d", + rect.x, rect.y, rect.width, rect.height); +} + +class BoundsChangeObserver : public ViewObserver { + public: + explicit BoundsChangeObserver(View* view) : view_(view) { + view_->AddObserver(this); + } + ~BoundsChangeObserver() override { view_->RemoveObserver(this); } + + Changes GetAndClearChanges() { + Changes changes; + changes.swap(changes_); + return changes; + } + + private: + // Overridden from ViewObserver: + void OnViewBoundsChanging(View* view, + const Rect& old_bounds, + const Rect& new_bounds) override { + changes_.push_back( + base::StringPrintf( + "view=%s old_bounds=%s new_bounds=%s phase=changing", + ViewIdToString(view->id()).c_str(), + RectToString(old_bounds).c_str(), + RectToString(new_bounds).c_str())); + } + void OnViewBoundsChanged(View* view, + const Rect& old_bounds, + const Rect& new_bounds) override { + changes_.push_back( + base::StringPrintf( + "view=%s old_bounds=%s new_bounds=%s phase=changed", + ViewIdToString(view->id()).c_str(), + RectToString(old_bounds).c_str(), + RectToString(new_bounds).c_str())); + } + + View* view_; + Changes changes_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver); +}; + +} // namespace + +TEST_F(ViewObserverTest, SetBounds) { + TestView v1; + { + BoundsChangeObserver observer(&v1); + Rect rect; + rect.width = rect.height = 100; + v1.SetBounds(rect); + + Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(2U, changes.size()); + EXPECT_EQ( + "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing", + changes[0]); + EXPECT_EQ( + "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed", + changes[1]); + } +} + +namespace { + +class VisibilityChangeObserver : public ViewObserver { + public: + explicit VisibilityChangeObserver(View* view) : view_(view) { + view_->AddObserver(this); + } + ~VisibilityChangeObserver() override { view_->RemoveObserver(this); } + + Changes GetAndClearChanges() { + Changes changes; + changes.swap(changes_); + return changes; + } + + private: + // Overridden from ViewObserver: + void OnViewVisibilityChanging(View* view) override { + changes_.push_back( + base::StringPrintf("view=%s phase=changing visibility=%s", + ViewIdToString(view->id()).c_str(), + view->visible() ? "true" : "false")); + } + void OnViewVisibilityChanged(View* view) override { + changes_.push_back(base::StringPrintf("view=%s phase=changed visibility=%s", + ViewIdToString(view->id()).c_str(), + view->visible() ? "true" : "false")); + } + + View* view_; + Changes changes_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver); +}; + +} // namespace + +TEST_F(ViewObserverTest, SetVisible) { + TestView v1; + EXPECT_TRUE(v1.visible()); + { + // Change visibility from true to false and make sure we get notifications. + VisibilityChangeObserver observer(&v1); + v1.SetVisible(false); + + Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(2U, changes.size()); + EXPECT_EQ("view=0,1 phase=changing visibility=true", changes[0]); + EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[1]); + } + { + // Set visible to existing value and verify no notifications. + VisibilityChangeObserver observer(&v1); + v1.SetVisible(false); + EXPECT_TRUE(observer.GetAndClearChanges().empty()); + } +} + +TEST_F(ViewObserverTest, SetVisibleParent) { + TestView parent; + ViewPrivate(&parent).set_id(1); + TestView child; + ViewPrivate(&child).set_id(2); + parent.AddChild(&child); + EXPECT_TRUE(parent.visible()); + EXPECT_TRUE(child.visible()); + { + // Change visibility from true to false and make sure we get notifications + // on the parent. + VisibilityChangeObserver observer(&parent); + child.SetVisible(false); + + Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(1U, changes.size()); + EXPECT_EQ("view=0,2 phase=changed visibility=false", changes[0]); + } +} + +TEST_F(ViewObserverTest, SetVisibleChild) { + TestView parent; + ViewPrivate(&parent).set_id(1); + TestView child; + ViewPrivate(&child).set_id(2); + parent.AddChild(&child); + EXPECT_TRUE(parent.visible()); + EXPECT_TRUE(child.visible()); + { + // Change visibility from true to false and make sure we get notifications + // on the child. + VisibilityChangeObserver observer(&child); + parent.SetVisible(false); + + Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(1U, changes.size()); + EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[0]); + } +} + +namespace { + +class SharedPropertyChangeObserver : public ViewObserver { + public: + explicit SharedPropertyChangeObserver(View* view) : view_(view) { + view_->AddObserver(this); + } + ~SharedPropertyChangeObserver() override { view_->RemoveObserver(this); } + + Changes GetAndClearChanges() { + Changes changes; + changes.swap(changes_); + return changes; + } + + private: + // Overridden from ViewObserver: + void OnViewSharedPropertyChanged( + View* view, + const std::string& name, + const std::vector<uint8_t>* old_data, + const std::vector<uint8_t>* new_data) override { + changes_.push_back(base::StringPrintf( + "view=%s shared property changed key=%s old_value=%s new_value=%s", + ViewIdToString(view->id()).c_str(), name.c_str(), + VectorToString(old_data).c_str(), VectorToString(new_data).c_str())); + } + + std::string VectorToString(const std::vector<uint8_t>* data) { + if (!data) + return "NULL"; + std::string s; + for (char c : *data) + s += c; + return s; + } + + View* view_; + Changes changes_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver); +}; + +} // namespace + +TEST_F(ViewObserverTest, SetLocalProperty) { + TestView v1; + std::vector<uint8_t> one(1, '1'); + + { + // Change visibility from true to false and make sure we get notifications. + SharedPropertyChangeObserver observer(&v1); + v1.SetSharedProperty("one", &one); + Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(1U, changes.size()); + EXPECT_EQ( + "view=0,1 shared property changed key=one old_value=NULL new_value=1", + changes[0]); + EXPECT_EQ(1U, v1.shared_properties().size()); + } + { + // Set visible to existing value and verify no notifications. + SharedPropertyChangeObserver observer(&v1); + v1.SetSharedProperty("one", &one); + EXPECT_TRUE(observer.GetAndClearChanges().empty()); + EXPECT_EQ(1U, v1.shared_properties().size()); + } + { + // Set the value to NULL to delete it. + // Change visibility from true to false and make sure we get notifications. + SharedPropertyChangeObserver observer(&v1); + v1.SetSharedProperty("one", NULL); + Changes changes = observer.GetAndClearChanges(); + ASSERT_EQ(1U, changes.size()); + EXPECT_EQ( + "view=0,1 shared property changed key=one old_value=1 new_value=NULL", + changes[0]); + EXPECT_EQ(0U, v1.shared_properties().size()); + } + { + // Setting a null property to null shouldn't update us. + SharedPropertyChangeObserver observer(&v1); + v1.SetSharedProperty("one", NULL); + EXPECT_TRUE(observer.GetAndClearChanges().empty()); + EXPECT_EQ(0U, v1.shared_properties().size()); + } +} + +namespace { + +typedef std::pair<const void*, intptr_t> PropertyChangeInfo; + +class LocalPropertyChangeObserver : public ViewObserver { + public: + explicit LocalPropertyChangeObserver(View* view) + : view_(view), + property_key_(nullptr), + old_property_value_(-1) { + view_->AddObserver(this); + } + ~LocalPropertyChangeObserver() override { view_->RemoveObserver(this); } + + PropertyChangeInfo PropertyChangeInfoAndClear() { + PropertyChangeInfo result(property_key_, old_property_value_); + property_key_ = NULL; + old_property_value_ = -3; + return result; + } + + private: + void OnViewLocalPropertyChanged(View* window, + const void* key, + intptr_t old) override { + property_key_ = key; + old_property_value_ = old; + } + + View* view_; + const void* property_key_; + intptr_t old_property_value_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver); +}; + +} // namespace + +TEST_F(ViewObserverTest, LocalPropertyChanged) { + TestView v1; + LocalPropertyChangeObserver o(&v1); + + static const ViewProperty<int> prop = {-2}; + + v1.SetLocalProperty(&prop, 1); + EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear()); + v1.SetLocalProperty(&prop, -2); + EXPECT_EQ(PropertyChangeInfo(&prop, 1), o.PropertyChangeInfoAndClear()); + v1.SetLocalProperty(&prop, 3); + EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear()); + v1.ClearLocalProperty(&prop); + EXPECT_EQ(PropertyChangeInfo(&prop, 3), o.PropertyChangeInfoAndClear()); + + // Sanity check to see if |PropertyChangeInfoAndClear| really clears. + EXPECT_EQ(PropertyChangeInfo( + reinterpret_cast<const void*>(NULL), -3), o.PropertyChangeInfoAndClear()); +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/types.h b/components/view_manager/public/cpp/types.h new file mode 100644 index 0000000..c8e55a7b --- /dev/null +++ b/components/view_manager/public/cpp/types.h
@@ -0,0 +1,25 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_TYPES_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_TYPES_H_ + +#include <stdint.h> + +// Typedefs for the transport types. These typedefs match that of the mojom +// file, see it for specifics. + +namespace mojo { + +// Used to identify views and change ids. +typedef uint32_t Id; + +// Used to identify a connection as well as a connection specific view id. For +// example, the Id for a view consists of the ConnectionSpecificId of the +// connection and the ConnectionSpecificId of the view. +typedef uint16_t ConnectionSpecificId; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_TYPES_H_
diff --git a/components/view_manager/public/cpp/util.h b/components/view_manager/public/cpp/util.h new file mode 100644 index 0000000..78a717c --- /dev/null +++ b/components/view_manager/public/cpp/util.h
@@ -0,0 +1,30 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_UTIL_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_UTIL_H_ + +#include "components/view_manager/public/cpp/types.h" + +// TODO(beng): #$*&@#(@ MacOSX SDK! +#if defined(HiWord) +#undef HiWord +#endif +#if defined(LoWord) +#undef LoWord +#endif + +namespace mojo { + +inline uint16_t HiWord(uint32_t id) { + return static_cast<uint16_t>((id >> 16) & 0xFFFF); +} + +inline uint16_t LoWord(uint32_t id) { + return static_cast<uint16_t>(id & 0xFFFF); +} + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_UTIL_H_
diff --git a/components/view_manager/public/cpp/view.h b/components/view_manager/public/cpp/view.h new file mode 100644 index 0000000..e2e81cf --- /dev/null +++ b/components/view_manager/public/cpp/view.h
@@ -0,0 +1,210 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_VIEW_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_H_ + +#include <stdint.h> +#include <vector> + +#include "base/observer_list.h" +#include "components/surfaces/public/interfaces/surface_id.mojom.h" +#include "components/view_manager/public/cpp/types.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" +#include "components/view_manager/public/interfaces/view_manager_constants.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" +#include "third_party/mojo/src/mojo/public/cpp/system/macros.h" +#include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" +#include "ui/mojo/geometry/geometry.mojom.h" + +namespace mojo { + +class ServiceProviderImpl; +class View; +class ViewManager; +class ViewObserver; + +// Defined in view_property.h (which we do not include) +template <typename T> +struct ViewProperty; + +// Views are owned by the ViewManager. +// TODO(beng): Right now, you'll have to implement a ViewObserver to track +// destruction and NULL any pointers you have. +// Investigate some kind of smart pointer or weak pointer for these. +class View { + public: + using Children = std::vector<View*>; + using SharedProperties = std::map<std::string, std::vector<uint8_t>>; + + // Destroys this view and all its children. + void Destroy(); + + ViewManager* view_manager() { return manager_; } + + // Configuration. + Id id() const { return id_; } + + // Geometric disposition. + const Rect& bounds() const { return bounds_; } + void SetBounds(const Rect& bounds); + + // Visibility (also see IsDrawn()). When created views are hidden. + bool visible() const { return visible_; } + void SetVisible(bool value); + + const ViewportMetrics& viewport_metrics() { return *viewport_metrics_; } + + // Returns the set of string to bag of byte properties. These properties are + // shared with the view manager. + const SharedProperties& shared_properties() const { return properties_; } + // Sets a property. If |data| is null, this property is deleted. + void SetSharedProperty(const std::string& name, + const std::vector<uint8_t>* data); + + // Sets the |value| of the given window |property|. Setting to the default + // value (e.g., NULL) removes the property. The caller is responsible for the + // lifetime of any object set as a property on the View. + // + // These properties are not visible to the view manager. + template <typename T> + void SetLocalProperty(const ViewProperty<T>* property, T value); + + // Returns the value of the given window |property|. Returns the + // property-specific default value if the property was not previously set. + // + // These properties are only visible in the current process and are not + // shared with other mojo services. + template <typename T> + T GetLocalProperty(const ViewProperty<T>* property) const; + + // Sets the |property| to its default value. Useful for avoiding a cast when + // setting to NULL. + // + // These properties are only visible in the current process and are not + // shared with other mojo services. + template <typename T> + void ClearLocalProperty(const ViewProperty<T>* property); + + // Type of a function to delete a property that this view owns. + typedef void (*PropertyDeallocator)(int64_t value); + + // A View is drawn if the View and all its ancestors are visible and the + // View is attached to the root. + bool IsDrawn() const; + + // Observation. + void AddObserver(ViewObserver* observer); + void RemoveObserver(ViewObserver* observer); + + // Tree. + View* parent() { return parent_; } + const View* parent() const { return parent_; } + const Children& children() const { return children_; } + View* GetRoot() { + return const_cast<View*>(const_cast<const View*>(this)->GetRoot()); + } + const View* GetRoot() const; + + void AddChild(View* child); + void RemoveChild(View* child); + + void Reorder(View* relative, OrderDirection direction); + void MoveToFront(); + void MoveToBack(); + + bool Contains(View* child) const; + + View* GetChildById(Id id); + + void SetSurfaceId(SurfaceIdPtr id); + + // Focus. + void SetFocus(); + + // Embedding. See view_manager.mojom for details. + void Embed(const String& url); + void Embed(const String& url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services); + void Embed(ViewManagerClientPtr client); + + protected: + // This class is subclassed only by test classes that provide a public ctor. + View(); + ~View(); + + private: + friend class ViewPrivate; + friend class ViewManagerClientImpl; + + View(ViewManager* manager, Id id); + + // Called by the public {Set,Get,Clear}Property functions. + int64_t SetLocalPropertyInternal(const void* key, + const char* name, + PropertyDeallocator deallocator, + int64_t value, + int64_t default_value); + int64_t GetLocalPropertyInternal(const void* key, + int64_t default_value) const; + + void LocalDestroy(); + void LocalAddChild(View* child); + void LocalRemoveChild(View* child); + // Returns true if the order actually changed. + bool LocalReorder(View* relative, OrderDirection direction); + void LocalSetBounds(const Rect& old_bounds, const Rect& new_bounds); + void LocalSetViewportMetrics(const ViewportMetrics& old_metrics, + const ViewportMetrics& new_metrics); + void LocalSetDrawn(bool drawn); + void LocalSetVisible(bool visible); + + // Methods implementing visibility change notifications. See ViewObserver + // for more details. + void NotifyViewVisibilityChanged(View* target); + // Notifies this view's observers. Returns false if |this| was deleted during + // the call (by an observer), otherwise true. + bool NotifyViewVisibilityChangedAtReceiver(View* target); + // Notifies this view and its child hierarchy. Returns false if |this| was + // deleted during the call (by an observer), otherwise true. + bool NotifyViewVisibilityChangedDown(View* target); + // Notifies this view and its parent hierarchy. + void NotifyViewVisibilityChangedUp(View* target); + + ViewManager* manager_; + Id id_; + View* parent_; + Children children_; + + ObserverList<ViewObserver> observers_; + + Rect bounds_; + ViewportMetricsPtr viewport_metrics_; + + bool visible_; + + SharedProperties properties_; + + // Drawn state is derived from the visible state and the parent's visible + // state. This field is only used if the view has no parent (eg it's a root). + bool drawn_; + + // Value struct to keep the name and deallocator for this property. + // Key cannot be used for this purpose because it can be char* or + // WindowProperty<>. + struct Value { + const char* name; + int64_t value; + PropertyDeallocator deallocator; + }; + + std::map<const void*, Value> prop_map_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(View); +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_H_
diff --git a/components/view_manager/public/cpp/view_manager.h b/components/view_manager/public/cpp/view_manager.h new file mode 100644 index 0000000..ee0b563 --- /dev/null +++ b/components/view_manager/public/cpp/view_manager.h
@@ -0,0 +1,42 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_H_ + +#include <string> + +#include "components/view_manager/public/cpp/types.h" + +namespace mojo { +class View; + +// Encapsulates a connection to the view manager service. A unique connection +// is made every time an app is embedded. +class ViewManager { + public: + // Returns the URL of the application that embedded this application. + virtual const std::string& GetEmbedderURL() const = 0; + + // Returns the root of this connection. + virtual View* GetRoot() = 0; + + // Returns a View known to this connection. + virtual View* GetViewById(Id id) = 0; + + // Returns the focused view; null if focus is not yet known or another app is + // focused. + virtual View* GetFocusedView() = 0; + + // Creates and returns a new View (which is owned by the ViewManager). Views + // are initially hidden, use SetVisible(true) to show. + virtual View* CreateView() = 0; + + protected: + virtual ~ViewManager() {} +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_H_
diff --git a/components/view_manager/public/cpp/view_manager_client_factory.h b/components/view_manager/public/cpp/view_manager_client_factory.h new file mode 100644 index 0000000..eaf42a4 --- /dev/null +++ b/components/view_manager/public/cpp/view_manager_client_factory.h
@@ -0,0 +1,43 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CLIENT_FACTORY_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CLIENT_FACTORY_H_ + +#include "components/view_manager/public/interfaces/view_manager.mojom.h" +#include "third_party/mojo/src/mojo/public/cpp/application/interface_factory.h" + +namespace mojo { + +class ViewManagerDelegate; +class Shell; + +// Add an instance of this class to an incoming connection to allow it to +// instantiate ViewManagerClient implementations in response to +// ViewManagerClient requests. +class ViewManagerClientFactory : public InterfaceFactory<ViewManagerClient> { + public: + ViewManagerClientFactory(Shell* shell, ViewManagerDelegate* delegate); + ~ViewManagerClientFactory() override; + + // Creates a ViewManagerClient from the supplied arguments. Returns ownership + // to the caller. + static ViewManagerClient* WeakBindViewManagerToPipe( + InterfaceRequest<ViewManagerClient> request, + ViewManagerServicePtr view_manager_service, + Shell* shell, + ViewManagerDelegate* delegate); + + // InterfaceFactory<ViewManagerClient> implementation. + void Create(ApplicationConnection* connection, + InterfaceRequest<ViewManagerClient> request) override; + + private: + Shell* shell_; + ViewManagerDelegate* delegate_; +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CLIENT_FACTORY_H_
diff --git a/components/view_manager/public/cpp/view_manager_context.h b/components/view_manager/public/cpp/view_manager_context.h new file mode 100644 index 0000000..09b1ce38 --- /dev/null +++ b/components/view_manager/public/cpp/view_manager_context.h
@@ -0,0 +1,46 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CONTEXT_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CONTEXT_H_ + +#include <string> +#include <vector> + +#include "third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h" +#include "third_party/mojo/src/mojo/public/cpp/system/macros.h" + +namespace mojo { +class ApplicationImpl; + +class ViewManagerContext { + public: + explicit ViewManagerContext(ApplicationImpl* application_impl); + ~ViewManagerContext(); + + // Embed an application @ |url| at an appropriate View. + // The first time this method is called in the life time of the View Manager + // service the "appropriate View" is defined as being the service' root View. + // Subsequent times, the implementation of this method is delegated to the + // application embedded at the service root View. This application will have a + // specific definition of where within its View hierarchy to embed an + // un-parented URL. + // |services| encapsulates services offered by the embedder to the embedded + // app alongside this Embed() call. |exposed_services| provides a means for + // the embedder to connect to services exposed by the embedded app. + void Embed(const String& url); + void Embed(const String& url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_Services); + + private: + class InternalState; + InternalState* state_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerContext); +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CONTEXT_H_
diff --git a/components/view_manager/public/cpp/view_manager_delegate.h b/components/view_manager/public/cpp/view_manager_delegate.h new file mode 100644 index 0000000..738502f1 --- /dev/null +++ b/components/view_manager/public/cpp/view_manager_delegate.h
@@ -0,0 +1,48 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_DELEGATE_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_DELEGATE_H_ + +#include <string> + +#include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" + +namespace mojo { + +class View; +class ViewManager; + +// Interface implemented by an application using the view manager. +class ViewManagerDelegate { + public: + // Called when the application implementing this interface is embedded at + // |root|. Every embed results in a new ViewManager and root View being + // created. |root| and it's corresponding ViewManager are valid until + // OnViewManagerDisconnected() is called with the same object. + // + // |services| exposes the services offered by the embedder to the delegate. + // + // |exposed_services| is an object that the delegate can add services to + // expose to the embedder. + // + // Note that if a different application is subsequently embedded at |root|, + // the pipes connecting |services| and |exposed_services| to the embedder and + // any services obtained from them are not broken and will continue to be + // valid. + virtual void OnEmbed(View* root, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) = 0; + + // Called when a connection to the view manager service is closed. + // |view_manager| is not valid after this function returns. + virtual void OnViewManagerDisconnected(ViewManager* view_manager) = 0; + + protected: + virtual ~ViewManagerDelegate() {} +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_DELEGATE_H_
diff --git a/components/view_manager/public/cpp/view_observer.h b/components/view_manager/public/cpp/view_observer.h new file mode 100644 index 0000000..997a9aa --- /dev/null +++ b/components/view_manager/public/cpp/view_observer.h
@@ -0,0 +1,103 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_VIEW_OBSERVER_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_OBSERVER_H_ + +#include <vector> + +#include "components/view_manager/public/cpp/view.h" +#include "ui/mojo/events/input_events.mojom.h" + +namespace mojo { + +class View; + +// A note on -ing and -ed suffixes: +// +// -ing methods are called before changes are applied to the local view model. +// -ed methods are called after changes are applied to the local view model. +// +// If the change originated from another connection to the view manager, it's +// possible that the change has already been applied to the service-side model +// prior to being called, so for example in the case of OnViewDestroying(), it's +// possible the view has already been destroyed on the service side. + +class ViewObserver { + public: + struct TreeChangeParams { + TreeChangeParams(); + View* target; + View* old_parent; + View* new_parent; + View* receiver; + }; + + virtual void OnTreeChanging(const TreeChangeParams& params) {} + virtual void OnTreeChanged(const TreeChangeParams& params) {} + + virtual void OnViewReordering(View* view, + View* relative_view, + OrderDirection direction) {} + virtual void OnViewReordered(View* view, + View* relative_view, + OrderDirection direction) {} + + virtual void OnViewDestroying(View* view) {} + virtual void OnViewDestroyed(View* view) {} + + virtual void OnViewBoundsChanging(View* view, + const Rect& old_bounds, + const Rect& new_bounds) {} + virtual void OnViewBoundsChanged(View* view, + const Rect& old_bounds, + const Rect& new_bounds) {} + + virtual void OnViewViewportMetricsChanged(View* view, + const ViewportMetrics& old_bounds, + const ViewportMetrics& new_bounds) { + } + + virtual void OnViewFocusChanged(View* gained_focus, View* lost_focus) {} + + virtual void OnViewInputEvent(View* view, const EventPtr& event) {} + + virtual void OnViewVisibilityChanging(View* view) {} + virtual void OnViewVisibilityChanged(View* view) {} + + // Invoked when this View's shared properties have changed. This can either + // be caused by SetSharedProperty() being called locally, or by us receiving + // a mojo message that this property has changed. If this property has been + // added, |old_data| is null. If this property was removed, |new_data| is + // null. + virtual void OnViewSharedPropertyChanged( + View* view, + const std::string& name, + const std::vector<uint8_t>* old_data, + const std::vector<uint8_t>* new_data) {} + + // Invoked when SetProperty() or ClearProperty() is called on the window. + // |key| is either a WindowProperty<T>* (SetProperty, ClearProperty). Either + // way, it can simply be compared for equality with the property + // constant. |old| is the old property value, which must be cast to the + // appropriate type before use. + virtual void OnViewLocalPropertyChanged( + View* view, + const void* key, + intptr_t old) {} + + virtual void OnViewEmbeddedAppDisconnected(View* view) {} + + // Sent when the drawn state changes. This is only sent for the root nodes + // when embedded. + virtual void OnViewDrawnChanging(View* view) {} + virtual void OnViewDrawnChanged(View* view) {} + + protected: + virtual ~ViewObserver() {} +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_OBSERVER_H_
diff --git a/components/view_manager/public/cpp/view_property.h b/components/view_manager/public/cpp/view_property.h new file mode 100644 index 0000000..2f10aff --- /dev/null +++ b/components/view_manager/public/cpp/view_property.h
@@ -0,0 +1,140 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_VIEW_PROPERTY_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_PROPERTY_H_ + +#include <stdint.h> + +// This header should be included by code that defines ViewProperties. It +// should not be included by code that only gets and sets ViewProperties. +// +// To define a new ViewProperty: +// +// #include "components/view_manager/public/cpp/view_property.h" +// +// DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(FOO_EXPORT, MyType); +// namespace foo { +// // Use this to define an exported property that is premitive, +// // or a pointer you don't want automatically deleted. +// DEFINE_VIEW_PROPERTY_KEY(MyType, kMyKey, MyDefault); +// +// // Use this to define an exported property whose value is a heap +// // allocated object, and has to be owned and freed by the view. +// DEFINE_OWNED_VIEW_PROPERTY_KEY(gfx::Rect, kRestoreBoundsKey, nullptr); +// +// // Use this to define a non exported property that is primitive, +// // or a pointer you don't want to automatically deleted, and is used +// // only in a specific file. This will define the property in an unnamed +// // namespace which cannot be accessed from another file. +// DEFINE_LOCAL_VIEW_PROPERTY_KEY(MyType, kMyKey, MyDefault); +// +// } // foo namespace +// +// To define a new type used for ViewProperty. +// +// // outside all namespaces: +// DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(FOO_EXPORT, MyType) +// +// If a property type is not exported, use DECLARE_VIEW_PROPERTY_TYPE(MyType) +// which is a shorthand for DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(, MyType). + +namespace mojo { +namespace { + +// No single new-style cast works for every conversion to/from int64_t, so we +// need this helper class. A third specialization is needed for bool because +// MSVC warning C4800 (forcing value to bool) is not suppressed by an explicit +// cast (!). +template <typename T> +class ViewPropertyCaster { + public: + static int64_t ToInt64(T x) { return static_cast<int64_t>(x); } + static T FromInt64(int64_t x) { return static_cast<T>(x); } +}; +template <typename T> +class ViewPropertyCaster<T*> { + public: + static int64_t ToInt64(T* x) { return reinterpret_cast<int64_t>(x); } + static T* FromInt64(int64_t x) { return reinterpret_cast<T*>(x); } +}; +template <> +class ViewPropertyCaster<bool> { + public: + static int64_t ToInt64(bool x) { return static_cast<int64_t>(x); } + static bool FromInt64(int64_t x) { return x != 0; } +}; + +} // namespace + +template <typename T> +struct ViewProperty { + T default_value; + const char* name; + View::PropertyDeallocator deallocator; +}; + +template <typename T> +void View::SetLocalProperty(const ViewProperty<T>* property, T value) { + int64_t old = SetLocalPropertyInternal( + property, property->name, + value == property->default_value ? nullptr : property->deallocator, + ViewPropertyCaster<T>::ToInt64(value), + ViewPropertyCaster<T>::ToInt64(property->default_value)); + if (property->deallocator && + old != ViewPropertyCaster<T>::ToInt64(property->default_value)) { + (*property->deallocator)(old); + } +} + +template <typename T> +T View::GetLocalProperty(const ViewProperty<T>* property) const { + return ViewPropertyCaster<T>::FromInt64(GetLocalPropertyInternal( + property, ViewPropertyCaster<T>::ToInt64(property->default_value))); +} + +template <typename T> +void View::ClearLocalProperty(const ViewProperty<T>* property) { + SetLocalProperty(property, property->default_value); +} + +} // namespace mojo + +// Macros to instantiate the property getter/setter template functions. +#define DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(EXPORT, T) \ + template EXPORT void mojo::View::SetLocalProperty( \ + const mojo::ViewProperty<T>*, T); \ + template EXPORT T mojo::View::GetLocalProperty(const mojo::ViewProperty<T>*) \ + const; \ + template EXPORT void mojo::View::ClearLocalProperty( \ + const mojo::ViewProperty<T>*); +#define DECLARE_VIEW_PROPERTY_TYPE(T) DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(, T) + +#define DEFINE_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ + COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64_t), property_type_too_large); \ + namespace { \ + const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \ + } \ + const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value; + +#define DEFINE_LOCAL_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ + COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64_t), property_type_too_large); \ + namespace { \ + const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \ + const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value; \ + } + +#define DEFINE_OWNED_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ + namespace { \ + void Deallocator##NAME(int64_t p) { \ + enum { type_must_be_complete = sizeof(TYPE) }; \ + delete mojo::ViewPropertyCaster<TYPE*>::FromInt64(p); \ + } \ + const mojo::ViewProperty<TYPE*> NAME##_Value = {DEFAULT, \ + #NAME, \ + &Deallocator##NAME}; \ + } \ + const mojo::ViewProperty<TYPE*>* const NAME = &NAME##_Value; + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_PROPERTY_H_
diff --git a/components/view_manager/public/cpp/view_tracker.cc b/components/view_manager/public/cpp/view_tracker.cc new file mode 100644 index 0000000..84550ba --- /dev/null +++ b/components/view_manager/public/cpp/view_tracker.cc
@@ -0,0 +1,41 @@ +// 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/view_manager/public/cpp/view_tracker.h" + +namespace mojo { + +ViewTracker::ViewTracker() { +} + +ViewTracker::~ViewTracker() { + for (Views::iterator i = views_.begin(); i != views_.end(); ++i) + (*i)->RemoveObserver(this); +} + +void ViewTracker::Add(View* view) { + if (views_.count(view)) + return; + + view->AddObserver(this); + views_.insert(view); +} + +void ViewTracker::Remove(View* view) { + if (views_.count(view)) { + views_.erase(view); + view->RemoveObserver(this); + } +} + +bool ViewTracker::Contains(View* view) { + return views_.count(view) > 0; +} + +void ViewTracker::OnViewDestroying(View* view) { + DCHECK_GT(views_.count(view), 0u); + Remove(view); +} + +} // namespace mojo
diff --git a/components/view_manager/public/cpp/view_tracker.h b/components/view_manager/public/cpp/view_tracker.h new file mode 100644 index 0000000..ed1a0d287 --- /dev/null +++ b/components/view_manager/public/cpp/view_tracker.h
@@ -0,0 +1,47 @@ +// 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_VIEW_MANAGER_PUBLIC_CPP_VIEW_TRACKER_H_ +#define COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_TRACKER_H_ + +#include <stdint.h> +#include <set> + +#include "components/view_manager/public/cpp/view_observer.h" +#include "third_party/mojo/src/mojo/public/cpp/system/macros.h" + +namespace mojo { + +class ViewTracker : public ViewObserver { + public: + using Views = std::set<View*>; + + ViewTracker(); + ~ViewTracker() override; + + // Returns the set of views being observed. + const std::set<View*>& views() const { return views_; } + + // Adds |view| to the set of Views being tracked. + void Add(View* view); + + // Removes |view| from the set of views being tracked. + void Remove(View* view); + + // Returns true if |view| was previously added and has not been removed or + // deleted. + bool Contains(View* view); + + // ViewObserver overrides: + void OnViewDestroying(View* view) override; + + private: + Views views_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ViewTracker); +}; + +} // namespace mojo + +#endif // COMPONENTS_VIEW_MANAGER_PUBLIC_CPP_VIEW_TRACKER_H_
diff --git a/components/view_manager/public/interfaces/BUILD.gn b/components/view_manager/public/interfaces/BUILD.gn new file mode 100644 index 0000000..982c363 --- /dev/null +++ b/components/view_manager/public/interfaces/BUILD.gn
@@ -0,0 +1,25 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "animations.mojom", + "view_manager.mojom", + "view_manager_constants.mojom", + ] + + import_dirs = [ get_path_info("../../../..", "abspath") ] + + mojo_sdk_deps = [ "mojo/public/interfaces/application" ] + + deps = [ + "//components/native_viewport/public/interfaces", + "//components/surfaces/public/interfaces:surface_id", + "//ui/mojo/events:interfaces", + "//ui/mojo/geometry:interfaces", + ] +}
diff --git a/components/view_manager/public/interfaces/animations.mojom b/components/view_manager/public/interfaces/animations.mojom new file mode 100644 index 0000000..6a4e5598 --- /dev/null +++ b/components/view_manager/public/interfaces/animations.mojom
@@ -0,0 +1,61 @@ +// 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 mojo; + +import "ui/mojo/geometry/geometry.mojom"; + +enum AnimationTweenType { + LINEAR, + EASE_IN, + EASE_OUT, + EASE_IN_OUT, +}; + +enum AnimationProperty { + // Used for pausing. + NONE, + OPACITY, + TRANSFORM, +}; + +struct AnimationValue { + float float_value; + Transform transform; +}; + +// Identifies how a particular property should be animated between a start and +// target value. +struct AnimationElement { + AnimationProperty property; + + // Duration is in microseconds. + int64 duration; + + AnimationTweenType tween_type; + + // If not specified the start value is taken from either the current value + // (for the first element) or the target_value of the previous element. + AnimationValue? start_value; + + // target_value may be null when property is NONE. + AnimationValue? target_value; +}; + +// An AnimationSequence consists of a number of AnimationElements to animate. +// Each element is animated serially. +struct AnimationSequence { + // Number of times to run the sequence. Value of 0 means run until + // explicitly stopped. + uint32 cycle_count; + + array<AnimationElement> elements; +}; + +// AnimationGroup identifies a view and a set of AnimationSequences to apply +// to the view. Each sequence is run in parallel. +struct AnimationGroup { + uint32 view_id; + array<AnimationSequence> sequences; +};
diff --git a/components/view_manager/public/interfaces/view_manager.mojom b/components/view_manager/public/interfaces/view_manager.mojom new file mode 100644 index 0000000..cb02ea6 --- /dev/null +++ b/components/view_manager/public/interfaces/view_manager.mojom
@@ -0,0 +1,220 @@ +// 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 mojo; + +import "components/native_viewport/public/interfaces/native_viewport.mojom"; +import "components/surfaces/public/interfaces/surface_id.mojom"; +import "components/view_manager/public/interfaces/view_manager_constants.mojom"; +import "mojo/public/interfaces/application/service_provider.mojom"; +import "ui/mojo/events/input_events.mojom"; +import "ui/mojo/geometry/geometry.mojom"; + +struct ViewData { + uint32 parent_id; + uint32 view_id; + mojo.Rect bounds; + map<string, array<uint8>> properties; + // True if this view is visible. The view may not be drawn on screen (see + // drawn for specifics). + bool visible; + // True if this view is drawn on screen. A view is drawn if attached to the + // root and all ancestors (including this view) are visible. + bool drawn; + ViewportMetrics viewport_metrics; +}; + +enum ErrorCode { + NONE, + VALUE_IN_USE, + ILLEGAL_ARGUMENT, +}; + +// Views are identified by a uint32. The upper 16 bits are the connection id, +// and the lower 16 the id assigned by the client. +// +// The root view is identified with a connection id of 0, and value of 1. +interface ViewManagerService { + // Creates a new view with the specified id. It is up to the client to ensure + // the id is unique to the connection (the id need not be globally unique). + // Additionally the connection id (embedded in |view_id|) must match that of + // the connection. + // Errors: + // ERROR_CODE_VALUE_IN_USE: a view already exists with the specified id. + // ERROR_CODE_ILLEGAL_ARGUMENT: The connection part of |view_id| does not + // match the connection id of the client. + // + // TODO(erg): Once we have default values in mojo, make this take a map of + // properties. + CreateView(uint32 view_id) => (ErrorCode error_code); + + // Deletes a view. This does not recurse. No hierarchy change notifications + // are sent as a result of this. Only the connection that created the view can + // delete it. + DeleteView(uint32 view_id) => (bool success); + + // Sets the specified bounds of the specified view. + SetViewBounds(uint32 view_id, mojo.Rect bounds) => (bool success); + + // Sets the visibility of the specified view to |visible|. Connections are + // allowed to change the visibility of any view they have created, as well as + // any of their roots. + SetViewVisibility(uint32 view_id, bool visible) => (bool success); + + // Sets an individual named property. Setting an individual property to null + // deletes the property. + SetViewProperty(uint32 view_id, + string name, + array<uint8>? value) => (bool success); + + // Reparents a view. + // This fails for any of the following reasons: + // . |parent| or |child| does not identify a valid view. + // . |child| is an ancestor of |parent|. + // . |child| is already a child of |parent|. + // + // This may result in a connection getting OnViewDeleted(). See + // RemoveViewFromParent for details. + AddView(uint32 parent, uint32 child) => (bool success); + + // Removes a view from its current parent. This fails if the view is not + // valid or the view already has no parent. + // + // Removing a view from a parent may result in OnViewDeleted() being sent to + // other connections. For example, connection A has views 1 and 2, with 2 a + // child of 1. Connection B has a root 1. If 2 is removed from 1 then B gets + // OnViewDeleted(). This is done as view 2 is effectively no longer visible to + // connection B. + RemoveViewFromParent(uint32 view_id) => (bool success); + + // Reorders a view in its parent, relative to |relative_view_id| according to + // |direction|. + // Only the connection that created the view's parent can reorder its + // children. + ReorderView(uint32 view_id, + uint32 relative_view_id, + OrderDirection direction) => (bool success); + + // Returns the views comprising the tree starting at |view_id|. |view_id| is + // the first result in the return value, unless |view_id| is invalid, in which + // case an empty vector is returned. The views are visited using a depth first + // search (pre-order). + GetViewTree(uint32 view_id) => (array<ViewData> views); + + // Shows the surface in the specified view. + SetViewSurfaceId(uint32 view_id, SurfaceId surface_id) => (bool success); + + // A connection may grant access to a view from another connection by way of + // the embed functions. There are two variants of this call: + // + // . EmbedUrl: the ViewManager connects to the app at the supplied url and + // asks it for a ViewManagerClient. + // . With the second variant a ViewManagerClient is directly supplied. + // + // In both cases the new ViewManagerClient is configured with a root of + // |view_id|. + // + // The caller must have created |view_id|. If not the request fails and the + // response is false. + // + // A view may only be a root of one connection at a time. Subsequent calls to + // Embed() for the same view result in the view being removed from the + // currently embedded app. The embedded app is told this by way of + // OnViewDeleted(). + // + // The embedder can detect when the embedded app disconnects by way of + // OnEmbeddedAppDisconnected(). + // + // When a connection embeds an app the connection no longer has priviledges + // to access or see any of the children of the view. If the view had existing + // children the children are removed. The one exception is the root + // connection. + // + // |services| encapsulates services offered by the embedder to the embedded + // app alongside this Embed() call. |exposed_services| provides a means for + // the embedder to connect to services exposed by the embedded app. Note that + // if a different app is subsequently embedded at |view_id| the + // ServiceProvider connections to its client in the embedded app and any + // services it provided are not broken and continue to be valid. + EmbedUrl(string url, + uint32 view_id, + ServiceProvider&? services, + ServiceProvider? exposed_services) => (bool success); + Embed(uint32 view_id, ViewManagerClient client) => (bool success); + + SetFocus(uint32 view_id) => (bool success); +}; + +// Changes to views are not sent to the connection that originated the +// change. For example, if connection 1 changes the bounds of a view by calling +// SetBounds(), connection 1 does not receive OnViewBoundsChanged(). +interface ViewManagerClient { + // Invoked when the client application has been embedded at |root|. + // See Embed() on ViewManagerService for more details. |view_manager_service| + // will be a handle back to the view manager service, unless the connection is + // to the WindowManager in which case it will be null. + OnEmbed(uint16 connection_id, + string embedder_url, + ViewData root, + ViewManagerService? view_manager_service, + ServiceProvider&? services, + ServiceProvider? exposed_services, + uint32 focused_view); + + // Invoked when the application embedded at |view| is disconnected. + OnEmbeddedAppDisconnected(uint32 view); + + // Invoked when a view's bounds have changed. + OnViewBoundsChanged(uint32 view, + mojo.Rect old_bounds, + mojo.Rect new_bounds); + + // Invoked when the viewport metrics for the view have changed. + // Clients are expected to propagate this to the view tree. + OnViewViewportMetricsChanged(mojo.ViewportMetrics old_metrics, + mojo.ViewportMetrics new_metrics); + + // Invoked when a change is done to the hierarchy. A value of 0 is used to + // identify a null view. For example, if the old_parent is NULL, 0 is + // supplied. + // |views| contains any views that are that the client has not been told + // about. This is not sent for hierarchy changes of views not known to this + // client or not attached to the tree. + OnViewHierarchyChanged(uint32 view, + uint32 new_parent, + uint32 old_parent, + array<ViewData> views); + + // Invoked when the order of views within a parent changes. + OnViewReordered(uint32 view_id, + uint32 relative_view_id, + OrderDirection direction); + + // Invoked when a view is deleted. + OnViewDeleted(uint32 view); + + // Invoked when the visibility of the specified view changes. + OnViewVisibilityChanged(uint32 view, bool visible); + + // Invoked when a change to the visibility of |view| or one if it's ancestors + // is done such that the drawn state changes. This is only invoked for the + // top most view of a particular connection. For example, if you have the + // hierarchy: A -> B1 -> B2 (B2 is a child of B1 and B1 a child of A), B1/B2 + // are from connection 2 and A from connection 1 with all views visible and + // drawn and the visiblity of A changes to false, then connection 2 is told + // the drawn state of B1 has changed (to false), but is not told anything + // about B2 as it's drawn state can be calculated from that of B1. + // + // NOTE: This is not invoked if OnViewVisibilityChanged() is invoked. + OnViewDrawnStateChanged(uint32 view, bool drawn); + + // Invoked when a view property is changed. If this change is a removal, + // |new_data| is null. + OnViewSharedPropertyChanged(uint32 view, string name, array<uint8>? new_data); + + // Invoked when an event is targeted at the specified view. + OnViewInputEvent(uint32 view, mojo.Event event) => (); + + OnViewFocused(uint32 focused_view_id); +};
diff --git a/third_party/mojo_services/src/view_manager/public/interfaces/view_manager_constants.mojom b/components/view_manager/public/interfaces/view_manager_constants.mojom similarity index 100% rename from third_party/mojo_services/src/view_manager/public/interfaces/view_manager_constants.mojom rename to components/view_manager/public/interfaces/view_manager_constants.mojom
diff --git a/components/view_manager/scheduled_animation_group.h b/components/view_manager/scheduled_animation_group.h index 274912d6..f46abf0 100644 --- a/components/view_manager/scheduled_animation_group.h +++ b/components/view_manager/scheduled_animation_group.h
@@ -9,7 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time/time.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/animations.mojom.h" +#include "components/view_manager/public/interfaces/animations.mojom.h" #include "ui/gfx/animation/tween.h" #include "ui/gfx/transform.h"
diff --git a/components/view_manager/scheduled_animation_group_unittest.cc b/components/view_manager/scheduled_animation_group_unittest.cc index ec30493..4c80179 100644 --- a/components/view_manager/scheduled_animation_group_unittest.cc +++ b/components/view_manager/scheduled_animation_group_unittest.cc
@@ -4,12 +4,12 @@ #include "components/view_manager/scheduled_animation_group.h" +#include "components/view_manager/public/interfaces/animations.mojom.h" #include "components/view_manager/server_view.h" #include "components/view_manager/test_server_view_delegate.h" #include "mojo/converters/geometry/geometry_type_converters.h" #include "mojo/converters/transform/transform_type_converters.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/animations.mojom.h" using mojo::ANIMATION_PROPERTY_NONE; using mojo::ANIMATION_PROPERTY_OPACITY;
diff --git a/components/view_manager/server_view.h b/components/view_manager/server_view.h index 12d3107..b307ffd 100644 --- a/components/view_manager/server_view.h +++ b/components/view_manager/server_view.h
@@ -11,7 +11,7 @@ #include "base/observer_list.h" #include "cc/surfaces/surface_id.h" #include "components/view_manager/ids.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/transform.h"
diff --git a/components/view_manager/server_view_delegate.h b/components/view_manager/server_view_delegate.h index 71a8750..c815f9f 100644 --- a/components/view_manager/server_view_delegate.h +++ b/components/view_manager/server_view_delegate.h
@@ -5,7 +5,7 @@ #ifndef COMPONENTS_VIEW_MANAGER_SERVER_VIEW_DELEGATE_H_ #define COMPONENTS_VIEW_MANAGER_SERVER_VIEW_DELEGATE_H_ -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager_constants.mojom.h" +#include "components/view_manager/public/interfaces/view_manager_constants.mojom.h" namespace gfx { class Rect;
diff --git a/components/view_manager/server_view_observer.h b/components/view_manager/server_view_observer.h index b686a2b..71ebcdd 100644 --- a/components/view_manager/server_view_observer.h +++ b/components/view_manager/server_view_observer.h
@@ -5,7 +5,7 @@ #ifndef COMPONENTS_VIEW_MANAGER_SERVER_VIEW_OBSERVER_H_ #define COMPONENTS_VIEW_MANAGER_SERVER_VIEW_OBSERVER_H_ -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager_constants.mojom.h" +#include "components/view_manager/public/interfaces/view_manager_constants.mojom.h" namespace gfx { class Rect;
diff --git a/components/view_manager/test_change_tracker.cc b/components/view_manager/test_change_tracker.cc index 217ddcaa9..f061b9d0 100644 --- a/components/view_manager/test_change_tracker.cc +++ b/components/view_manager/test_change_tracker.cc
@@ -6,8 +6,8 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "components/view_manager/public/cpp/util.h" #include "mojo/common/common_type_converters.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/util.h" using mojo::Array; using mojo::Id; @@ -94,6 +94,10 @@ case CHANGE_TYPE_DELEGATE_EMBED: return base::StringPrintf("DelegateEmbed url=%s", change.embed_url.data()); + + case CHANGE_TYPE_FOCUSED: + return base::StringPrintf("Focused id=%s", + ViewIdToString(change.view_id).c_str()); } return std::string(); } @@ -280,6 +284,13 @@ AddChange(change); } +void TestChangeTracker::OnViewFocused(mojo::Id view_id) { + Change change; + change.type = CHANGE_TYPE_FOCUSED; + change.view_id = view_id; + AddChange(change); +} + void TestChangeTracker::DelegateEmbed(const String& url) { Change change; change.type = CHANGE_TYPE_DELEGATE_EMBED;
diff --git a/components/view_manager/test_change_tracker.h b/components/view_manager/test_change_tracker.h index bb1b55e..2312828 100644 --- a/components/view_manager/test_change_tracker.h +++ b/components/view_manager/test_change_tracker.h
@@ -9,17 +9,17 @@ #include <vector> #include "base/basictypes.h" +#include "components/view_manager/public/cpp/types.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" -#include "third_party/mojo_services/src/geometry/public/interfaces/geometry.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/types.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" +#include "ui/mojo/geometry/geometry.mojom.h" namespace view_manager { enum ChangeType { CHANGE_TYPE_EMBED, CHANGE_TYPE_EMBEDDED_APP_DISCONNECTED, - // TODO(sky): NODE->VIEW. + // TODO(sky): nuke NODE. CHANGE_TYPE_NODE_BOUNDS_CHANGED, CHANGE_TYPE_NODE_VIEWPORT_METRICS_CHANGED, CHANGE_TYPE_NODE_HIERARCHY_CHANGED, @@ -30,6 +30,7 @@ CHANGE_TYPE_INPUT_EVENT, CHANGE_TYPE_PROPERTY_CHANGED, CHANGE_TYPE_DELEGATE_EMBED, + CHANGE_TYPE_FOCUSED, }; // TODO(sky): consider nuking and converting directly to ViewData. @@ -141,6 +142,7 @@ void OnViewSharedPropertyChanged(mojo::Id view_id, mojo::String name, mojo::Array<uint8_t> data); + void OnViewFocused(mojo::Id view_id); void DelegateEmbed(const mojo::String& url); private:
diff --git a/components/view_manager/view_manager_app.cc b/components/view_manager/view_manager_app.cc index a37119c43a..a068d2a4 100644 --- a/components/view_manager/view_manager_app.cc +++ b/components/view_manager/view_manager_app.cc
@@ -51,9 +51,8 @@ wm_internal_.set_error_handler(this); scoped_ptr<DefaultDisplayManager> display_manager(new DefaultDisplayManager( - app_impl_, connection, - base::Bind(&ViewManagerApp::OnLostConnectionToWindowManager, - base::Unretained(this)))); + app_impl_, base::Bind(&ViewManagerApp::OnLostConnectionToWindowManager, + base::Unretained(this)))); connection_manager_.reset( new ConnectionManager(this, display_manager.Pass(), wm_internal_.get())); return true;
diff --git a/components/view_manager/view_manager_app.h b/components/view_manager/view_manager_app.h index 3039a8a..fc16a0c 100644 --- a/components/view_manager/view_manager_app.h +++ b/components/view_manager/view_manager_app.h
@@ -7,13 +7,13 @@ #include "base/memory/scoped_ptr.h" #include "components/view_manager/connection_manager_delegate.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" +#include "components/window_manager/public/interfaces/window_manager_internal.mojom.h" #include "mojo/common/tracing_impl.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/interface_factory.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom.h" namespace mojo { class ApplicationImpl;
diff --git a/components/view_manager/view_manager_client_apptest.cc b/components/view_manager/view_manager_client_apptest.cc index 2131a88..0002b9f 100644 --- a/components/view_manager/view_manager_client_apptest.cc +++ b/components/view_manager/view_manager_client_apptest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager.h" +#include "components/view_manager/public/cpp/view_manager.h" #include "base/bind.h" #include "base/location.h" @@ -11,17 +11,17 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/test_timeouts.h" +#include "components/view_manager/public/cpp/lib/view_manager_client_impl.h" +#include "components/view_manager/public/cpp/view_manager_client_factory.h" +#include "components/view_manager/public/cpp/view_manager_context.h" +#include "components/view_manager/public/cpp/view_manager_delegate.h" +#include "components/view_manager/public/cpp/view_observer.h" #include "mojo/application/application_test_base_chromium.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" #include "third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h" -#include "third_party/mojo_services/src/geometry/public/cpp/geometry_util.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_observer.h" +#include "ui/mojo/geometry/geometry_util.h" namespace mojo {
diff --git a/components/view_manager/view_manager_service_apptest.cc b/components/view_manager/view_manager_service_apptest.cc index 7be0716..bb533c7 100644 --- a/components/view_manager/view_manager_service_apptest.cc +++ b/components/view_manager/view_manager_service_apptest.cc
@@ -6,13 +6,13 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "components/view_manager/ids.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" #include "components/view_manager/test_change_tracker.h" +#include "components/window_manager/public/interfaces/window_manager.mojom.h" +#include "components/window_manager/public/interfaces/window_manager_internal.mojom.h" #include "mojo/application/application_test_base_chromium.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager.mojom.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom.h" using mojo::ApplicationConnection; using mojo::ApplicationDelegate; @@ -290,7 +290,8 @@ mojo::ViewManagerServicePtr view_manager_service, InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services, - mojo::ScopedMessagePipeHandle window_manager_pipe) override { + mojo::Id focused_view_id) override { + // TODO(sky): add coverage of |focused_view_id|. service_ = view_manager_service.Pass(); tracker()->OnEmbed(connection_id, creator_url, root.Pass()); if (embed_run_loop_) @@ -340,9 +341,8 @@ Array<uint8_t> new_data) override { tracker_.OnViewSharedPropertyChanged(view, name, new_data.Pass()); } - void OnPerformAction(uint32_t view, - const String& name, - const Callback<void(bool)>& callback) override {} + // TODO(sky): add testing coverage. + void OnViewFocused(uint32_t focused_view_id) override {} TestChangeTracker tracker_; @@ -502,9 +502,6 @@ } // mojo::WindowManagerInternal implementation. - void CreateWindowManagerForViewManagerClient( - uint16_t connection_id, - mojo::ScopedMessagePipeHandle window_manager_pipe) override {} void SetViewManagerClient( mojo::ScopedMessagePipeHandle view_manager_client_request) override { auto typed_request = mojo::MakeRequest<mojo::ViewManagerClient>( @@ -512,6 +509,7 @@ vm_client1_.Bind(typed_request.Pass()); view_manager_setup_run_loop_->Quit(); } + void OnAccelerator(mojo::EventPtr event) override {} mojo::Binding<mojo::WindowManagerInternal> wm_internal_binding_; mojo::WindowManagerInternalClientPtr wm_internal_client_; @@ -1099,22 +1097,6 @@ EXPECT_EQ("view=1,1 parent=null", views[0].ToString()); } -TEST_F(ViewManagerServiceAppTest, OnViewInputEvent) { - ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); - changes2()->clear(); - - // Dispatch an event to the view and verify it's received. - { - EventPtr event(mojo::Event::New()); - event->action = static_cast<mojo::EventType>(1); - wm_internal_client_->DispatchInputEventToView(BuildViewId(1, 1), - event.Pass()); - vm_client2_->WaitForChangeCount(1); - EXPECT_EQ("InputEvent view=1,1 event_action=1", - SingleChangeToDescription(*changes2())); - } -} - TEST_F(ViewManagerServiceAppTest, EmbedWithSameViewId) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); changes2()->clear();
diff --git a/components/view_manager/view_manager_service_impl.cc b/components/view_manager/view_manager_service_impl.cc index 1283fca..823a2e9 100644 --- a/components/view_manager/view_manager_service_impl.cc +++ b/components/view_manager/view_manager_service_impl.cc
@@ -11,10 +11,10 @@ #include "components/view_manager/display_manager.h" #include "components/view_manager/server_view.h" #include "components/view_manager/window_manager_access_policy.h" +#include "components/window_manager/public/interfaces/window_manager_internal.mojom.h" #include "mojo/converters/geometry/geometry_type_converters.h" #include "mojo/converters/input_events/input_events_type_converters.h" #include "mojo/converters/surfaces/surfaces_type_converters.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom.h" using mojo::Array; using mojo::Callback; @@ -63,12 +63,15 @@ if (root_.get()) GetUnknownViewsFrom(GetView(*root_), &to_send); - mojo::MessagePipe pipe; - connection_manager_->wm_internal()->CreateWindowManagerForViewManagerClient( - id_, pipe.handle1.Pass()); + const ServerView* focused_view = connection_manager_->GetFocusedView(); + if (focused_view) + focused_view = access_policy_->GetViewForFocusChange(focused_view); + const mojo::Id focused_view_transport_id( + ViewIdToTransportId(focused_view ? focused_view->id() : ViewId())); + client->OnEmbed(id_, creator_url_, ViewToViewData(to_send.front()), service_ptr.Pass(), services.Pass(), exposed_services.Pass(), - pipe.handle0.Pass()); + focused_view_transport_id); } const ServerView* ViewManagerServiceImpl::GetView(const ViewId& id) const { @@ -302,6 +305,16 @@ NotifyDrawnStateChanged(view, view_target_drawn_state); } +void ViewManagerServiceImpl::ProcessFocusChanged( + const ServerView* old_focused_view, + const ServerView* new_focused_view) { + const ServerView* view = + new_focused_view ? access_policy_->GetViewForFocusChange(new_focused_view) + : nullptr; + client()->OnViewFocused(view ? ViewIdToTransportId(view->id()) + : ViewIdToTransportId(ViewId())); +} + bool ViewManagerServiceImpl::IsViewKnown(const ServerView* view) const { return known_views_.count(ViewIdToTransportId(view->id())) > 0; } @@ -627,12 +640,16 @@ callback.Run(Embed(ViewIdFromTransportId(transport_view_id), client.Pass())); } -void ViewManagerServiceImpl::PerformAction( - mojo::Id transport_view_id, - const mojo::String& action, - const mojo::Callback<void(bool)>& callback) { - connection_manager_->GetWindowManagerViewManagerClient()->OnPerformAction( - transport_view_id, action, callback); +void ViewManagerServiceImpl::SetFocus(uint32_t view_id, + const SetFocusCallback& callback) { + ServerView* view = GetView(ViewIdFromTransportId(view_id)); + bool success = view && view->IsDrawn(connection_manager_->root()) && + access_policy_->CanSetFocus(view); + if (success) { + ConnectionManager::ScopedChange change(this, connection_manager_, false); + connection_manager_->SetFocusedView(view); + } + callback.Run(success); } bool ViewManagerServiceImpl::IsRootForAccessPolicy(const ViewId& id) const {
diff --git a/components/view_manager/view_manager_service_impl.h b/components/view_manager/view_manager_service_impl.h index 0341b7e..63e7e3a 100644 --- a/components/view_manager/view_manager_service_impl.h +++ b/components/view_manager/view_manager_service_impl.h
@@ -12,10 +12,10 @@ #include "base/basictypes.h" #include "base/containers/hash_tables.h" #include "base/memory/scoped_ptr.h" +#include "components/surfaces/public/interfaces/surface_id.mojom.h" #include "components/view_manager/access_policy_delegate.h" #include "components/view_manager/ids.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surface_id.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" namespace gfx { class Rect; @@ -115,8 +115,8 @@ void ProcessViewDeleted(const ViewId& view, bool originated_change); void ProcessWillChangeViewVisibility(const ServerView* view, bool originated_change); - void ProcessViewPropertiesChanged(const ServerView* view, - bool originated_change); + void ProcessFocusChanged(const ServerView* old_focused_view, + const ServerView* new_focused_view); private: typedef std::map<mojo::ConnectionSpecificId, ServerView*> ViewMap; @@ -210,9 +210,7 @@ void Embed(mojo::Id transport_view_id, mojo::ViewManagerClientPtr client, const mojo::Callback<void(bool)>& callback) override; - void PerformAction(mojo::Id transport_view_id, - const mojo::String& action, - const mojo::Callback<void(bool)>& callback) override; + void SetFocus(uint32_t view_id, const SetFocusCallback& callback) override; // AccessPolicyDelegate: bool IsRootForAccessPolicy(const ViewId& id) const override;
diff --git a/components/view_manager/view_manager_service_unittest.cc b/components/view_manager/view_manager_service_unittest.cc index b51e8f51..43274be 100644 --- a/components/view_manager/view_manager_service_unittest.cc +++ b/components/view_manager/view_manager_service_unittest.cc
@@ -11,17 +11,17 @@ #include "components/view_manager/connection_manager_delegate.h" #include "components/view_manager/display_manager.h" #include "components/view_manager/ids.h" +#include "components/view_manager/public/cpp/types.h" +#include "components/view_manager/public/cpp/util.h" +#include "components/view_manager/public/interfaces/view_manager.mojom.h" #include "components/view_manager/server_view.h" #include "components/view_manager/test_change_tracker.h" #include "components/view_manager/view_manager_service_impl.h" +#include "components/window_manager/public/interfaces/window_manager.mojom.h" +#include "components/window_manager/public/interfaces/window_manager_internal.mojom.h" #include "mojo/converters/geometry/geometry_type_converters.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/types.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/util.h" -#include "third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager.mojom.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom.h" #include "ui/gfx/geometry/rect.h" using mojo::Array; @@ -54,7 +54,8 @@ mojo::ViewManagerServicePtr view_manager_service, InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services, - mojo::ScopedMessagePipeHandle window_manager_pipe) override { + mojo::Id focused_view_id) override { + // TODO(sky): add test coverage of |focused_view_id|. tracker_.OnEmbed(connection_id, embedder_url, root.Pass()); } void OnEmbeddedAppDisconnected(uint32_t view) override { @@ -99,9 +100,9 @@ const mojo::Callback<void()>& callback) override { tracker_.OnViewInputEvent(view, event.Pass()); } - void OnPerformAction(uint32_t view_id, - const String& name, - const mojo::Callback<void(bool)>& callback) override {} + void OnViewFocused(uint32_t focused_view_id) override { + tracker_.OnViewFocused(focused_view_id); + } TestChangeTracker tracker_; @@ -180,7 +181,8 @@ ~TestDisplayManager() override {} // DisplayManager: - void Init(ConnectionManager* connection_manager) override {} + void Init(ConnectionManager* connection_manager, + mojo::NativeViewportEventDispatcherPtr event_dispatcher) override {} void SchedulePaint(const ServerView* view, const gfx::Rect& bounds) override { } void SetViewportSize(const gfx::Size& size) override {} @@ -203,15 +205,33 @@ ~TestWindowManagerInternal() override {} // WindowManagerInternal: - void CreateWindowManagerForViewManagerClient( - uint16_t connection_id, - mojo::ScopedMessagePipeHandle window_manager_pipe) override {} void SetViewManagerClient(mojo::ScopedMessagePipeHandle) override {} + void OnAccelerator(mojo::EventPtr event) override {} private: DISALLOW_COPY_AND_ASSIGN(TestWindowManagerInternal); }; +mojo::EventPtr CreatePointerDownEvent(int x, int y) { + mojo::EventPtr event(mojo::Event::New()); + event->action = mojo::EVENT_TYPE_POINTER_DOWN; + event->pointer_data = mojo::PointerData::New(); + event->pointer_data->pointer_id = 1u; + event->pointer_data->x = x; + event->pointer_data->y = y; + return event.Pass(); +} + +mojo::EventPtr CreatePointerUpEvent(int x, int y) { + mojo::EventPtr event(mojo::Event::New()); + event->action = mojo::EVENT_TYPE_POINTER_UP; + event->pointer_data = mojo::PointerData::New(); + event->pointer_data->pointer_id = 1u; + event->pointer_data->x = x; + event->pointer_data->y = y; + return event.Pass(); +} + } // namespace // ----------------------------------------------------------------------------- @@ -468,4 +488,79 @@ EXPECT_TRUE(cloned_view_child->id() == ClonedViewId()); } +// Verifies focus correctly changes on pointer events. +TEST_F(ViewManagerServiceTest, FocusOnPointer) { + const ViewId embed_view_id(wm_connection()->id(), 1); + EXPECT_EQ(ERROR_CODE_NONE, wm_connection()->CreateView(embed_view_id)); + EXPECT_TRUE(wm_connection()->SetViewVisibility(embed_view_id, true)); + EXPECT_TRUE( + wm_connection()->AddView(*(wm_connection()->root()), embed_view_id)); + connection_manager()->root()->SetBounds(gfx::Rect(0, 0, 100, 100)); + wm_connection()->EmbedUrl(std::string(), embed_view_id, nullptr, nullptr); + ViewManagerServiceImpl* connection1 = + connection_manager()->GetConnectionWithRoot(embed_view_id); + ASSERT_TRUE(connection1 != nullptr); + ASSERT_NE(connection1, wm_connection()); + + connection_manager() + ->GetView(embed_view_id) + ->SetBounds(gfx::Rect(0, 0, 50, 50)); + + const ViewId child1(connection1->id(), 1); + EXPECT_EQ(ERROR_CODE_NONE, connection1->CreateView(child1)); + EXPECT_TRUE(connection1->AddView(embed_view_id, child1)); + ServerView* v1 = connection1->GetView(child1); + v1->SetVisible(true); + v1->SetBounds(gfx::Rect(20, 20, 20, 20)); + + TestViewManagerClient* connection1_client = last_view_manager_client(); + connection1_client->tracker()->changes()->clear(); + wm_client()->tracker()->changes()->clear(); + + connection_manager()->ProcessEvent(CreatePointerDownEvent(21, 22)); + // Focus should go to child1. This results in notifying both the window + // manager and client connection being notified. + EXPECT_EQ(v1, connection_manager()->GetFocusedView()); + ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u); + EXPECT_EQ("Focused id=2,1", + ChangesToDescription1(*wm_client()->tracker()->changes())[0]); + ASSERT_GE(connection1_client->tracker()->changes()->size(), 1u); + EXPECT_EQ( + "Focused id=2,1", + ChangesToDescription1(*connection1_client->tracker()->changes())[0]); + + connection_manager()->ProcessEvent(CreatePointerUpEvent(21, 22)); + wm_client()->tracker()->changes()->clear(); + connection1_client->tracker()->changes()->clear(); + + // Press outside of the embedded view. Focus should go to the root. Notice + // the client1 doesn't see who has focus as the focused view (root) isn't + // visible to it. + connection_manager()->ProcessEvent(CreatePointerDownEvent(61, 22)); + EXPECT_EQ(connection_manager()->root(), + connection_manager()->GetFocusedView()); + ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u); + EXPECT_EQ("Focused id=0,1", + ChangesToDescription1(*wm_client()->tracker()->changes())[0]); + ASSERT_GE(connection1_client->tracker()->changes()->size(), 1u); + EXPECT_EQ( + "Focused id=null", + ChangesToDescription1(*connection1_client->tracker()->changes())[0]); + + connection_manager()->ProcessEvent(CreatePointerUpEvent(21, 22)); + wm_client()->tracker()->changes()->clear(); + connection1_client->tracker()->changes()->clear(); + + // Press in the same location. Should not get a focus change event (only input + // event). + connection_manager()->ProcessEvent(CreatePointerDownEvent(61, 22)); + EXPECT_EQ(connection_manager()->root(), + connection_manager()->GetFocusedView()); + ASSERT_EQ(wm_client()->tracker()->changes()->size(), 1u); + EXPECT_EQ("InputEvent view=0,1 event_action=4", + ChangesToDescription1(*wm_client()->tracker()->changes())[0]); + EXPECT_TRUE(connection1_client->tracker()->changes()->empty()); + ; +} + } // namespace view_manager
diff --git a/components/view_manager/window_manager_access_policy.cc b/components/view_manager/window_manager_access_policy.cc index 600a4f6..280a73c 100644 --- a/components/view_manager/window_manager_access_policy.cc +++ b/components/view_manager/window_manager_access_policy.cc
@@ -77,6 +77,10 @@ return view->id().connection_id == connection_id_; } +bool WindowManagerAccessPolicy::CanSetFocus(const ServerView* view) const { + return true; +} + bool WindowManagerAccessPolicy::ShouldNotifyOnHierarchyChange( const ServerView* view, const ServerView** new_parent, @@ -90,6 +94,11 @@ return IsViewKnown(view) || (*new_parent && IsViewKnown(*new_parent)); } +const ServerView* WindowManagerAccessPolicy::GetViewForFocusChange( + const ServerView* focused) { + return focused; +} + bool WindowManagerAccessPolicy::IsViewKnown(const ServerView* view) const { return delegate_->IsViewKnownForAccessPolicy(view); }
diff --git a/components/view_manager/window_manager_access_policy.h b/components/view_manager/window_manager_access_policy.h index 94cda10..9e09409 100644 --- a/components/view_manager/window_manager_access_policy.h +++ b/components/view_manager/window_manager_access_policy.h
@@ -33,10 +33,12 @@ bool CanSetViewSurfaceId(const ServerView* view) const override; bool CanSetViewBounds(const ServerView* view) const override; bool CanSetViewProperties(const ServerView* view) const override; + bool CanSetFocus(const ServerView* view) const override; bool ShouldNotifyOnHierarchyChange( const ServerView* view, const ServerView** new_parent, const ServerView** old_parent) const override; + const ServerView* GetViewForFocusChange(const ServerView* focused) override; private: bool IsViewKnown(const ServerView* view) const;
diff --git a/components/window_manager/BUILD.gn b/components/window_manager/BUILD.gn index 74259dc..d30da10d 100644 --- a/components/window_manager/BUILD.gn +++ b/components/window_manager/BUILD.gn
@@ -8,28 +8,8 @@ source_set("lib") { sources = [ - "basic_focus_rules.cc", - "basic_focus_rules.h", - "capture_controller.cc", - "capture_controller.h", - "capture_controller_observer.h", - "focus_controller.cc", - "focus_controller.h", - "focus_controller_observer.h", - "focus_rules.h", - "native_viewport_event_dispatcher_impl.cc", - "native_viewport_event_dispatcher_impl.h", - "view_event_dispatcher.cc", - "view_event_dispatcher.h", - "view_target.cc", - "view_target.h", - "view_targeter.cc", - "view_targeter.h", "window_manager_app.cc", "window_manager_app.h", - "window_manager_app_android.cc", - "window_manager_app_linux.cc", - "window_manager_app_win.cc", "window_manager_delegate.h", "window_manager_impl.cc", "window_manager_impl.h", @@ -37,57 +17,18 @@ deps = [ "//base", - "//ui/base", - "//ui/events", - "//ui/gfx", - "//ui/gfx/geometry", + "//components/view_manager/public/cpp", + "//components/window_manager/public/interfaces", "//mojo/application", "//mojo/common", "//mojo/converters/geometry", - "//mojo/converters/input_events", "//third_party/mojo/src/mojo/public/cpp/bindings:bindings", "//third_party/mojo/src/mojo/public/interfaces/application", - "//third_party/mojo_services/src/native_viewport/public/interfaces", - "//third_party/mojo_services/src/view_manager/public/cpp", - "//third_party/mojo_services/src/window_manager/public/interfaces", + "//ui/gfx/geometry", + "//ui/mojo/events:interfaces", ] } -test("window_manager_unittests") { - sources = [ - "focus_controller_unittest.cc", - "run_all_unittests.cc", - "view_target_unittest.cc", - "view_targeter_unittest.cc", - "window_manager_test_util.cc", - "window_manager_test_util.h", - ] - - public_deps = [ - ":lib", - ] - - deps = [ - "//base/test:test_support", - "//mojo/converters/geometry", - "//third_party/mojo/src/mojo/edk/system", - "//mojo/environment:chromium", - "//third_party/mojo/src/mojo/public/cpp/application", - "//third_party/mojo_services/src/view_manager/public/cpp", - "//third_party/mojo_services/src/view_manager/public/interfaces", - "//third_party/mojo_services/src/window_manager/public/interfaces", - "//testing/gtest", - "//ui/events:test_support", - "//ui/gfx", - "//ui/gfx:test_support", - "//ui/gl", - ] - - if (use_x11) { - deps += [ "//ui/gfx/x" ] - } -} - # A basic window manager with a default delegate used for testing. mojo_native_application("test_window_manager") { sources = [ @@ -100,9 +41,9 @@ deps = [ "//base", + "//components/view_manager/public/cpp", "//mojo/application", "//mojo/common:tracing_impl", - "//third_party/mojo_services/src/view_manager/public/cpp", ] } @@ -116,12 +57,12 @@ deps = [ "//base", + "//components/view_manager/public/cpp", + "//components/window_manager/public/interfaces", "//mojo/application", "//mojo/application:test_support", "//mojo/environment:chromium", "//third_party/mojo/src/mojo/public/cpp/system:system", - "//third_party/mojo_services/src/view_manager/public/cpp", - "//third_party/mojo_services/src/window_manager/public/interfaces", ] data_deps = [ ":test_window_manager($default_toolchain)" ]
diff --git a/components/window_manager/DEPS b/components/window_manager/DEPS index 0f0ab412..deb2e50 100644 --- a/components/window_manager/DEPS +++ b/components/window_manager/DEPS
@@ -1,4 +1,6 @@ include_rules = [ + "+components/native_viewport", + "+components/view_manager", "+mojo/application", "+mojo/common", "+mojo/converters",
diff --git a/components/window_manager/basic_focus_rules.cc b/components/window_manager/basic_focus_rules.cc deleted file mode 100644 index 924a1105..0000000 --- a/components/window_manager/basic_focus_rules.cc +++ /dev/null
@@ -1,171 +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/window_manager/basic_focus_rules.h" - -#include "base/macros.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" - -using mojo::View; - -namespace window_manager { - -BasicFocusRules::BasicFocusRules(View* window_container) - : window_container_(window_container) { -} - -BasicFocusRules::~BasicFocusRules() {} - -bool BasicFocusRules::SupportsChildActivation(View* view) const { - return true; -} - -bool BasicFocusRules::IsToplevelView(View* view) const { - if (!IsViewParentedToWindowContainer(view)) - return false; - - // The window must exist within a container that supports activation. - // The window cannot be blocked by a modal transient. - return SupportsChildActivation(view->parent()); -} - -bool BasicFocusRules::CanActivateView(View* view) const { - if (!view) - return true; - - // Only toplevel windows can be activated - if (!IsToplevelView(view)) - return false; - - // The view must be visible. - if (!view->visible()) - return false; - - // TODO(erg): The aura version of this class asks the aura::Window's - // ActivationDelegate whether the window is activatable. - - // A window must be focusable to be activatable. We don't call - // CanFocusWindow() from here because it will call back to us via - // GetActivatableWindow(). - if (!CanFocusViewImpl(view)) - return false; - - // TODO(erg): In the aura version, we also check whether the window is - // blocked by a modal transient window. - - return true; -} - -bool BasicFocusRules::CanFocusView(View* view) const { - // It is possible to focus a NULL window, it is equivalent to clearing focus. - if (!view) - return true; - - // The focused view is always inside the active view, so views that aren't - // activatable can't contain the focused view. - View* activatable = GetActivatableView(view); - if (!activatable || !activatable->Contains(view)) - return false; - return CanFocusViewImpl(view); -} - -View* BasicFocusRules::GetToplevelView(View* view) const { - View* parent = view->parent(); - View* child = view; - while (parent) { - if (IsToplevelView(child)) - return child; - - parent = parent->parent(); - child = child->parent(); - } - - return nullptr; -} - -View* BasicFocusRules::GetActivatableView(View* view) const { - View* parent = view->parent(); - View* child = view; - while (parent) { - if (CanActivateView(child)) - return child; - - // TODO(erg): In the aura version of this class, we have a whole bunch of - // checks to support modal transient windows, and transient parents. - - parent = parent->parent(); - child = child->parent(); - } - - return nullptr; -} - -View* BasicFocusRules::GetFocusableView(View* view) const { - if (CanFocusView(view)) - return view; - - // |view| may be in a hierarchy that is non-activatable, in which case we - // need to cut over to the activatable hierarchy. - View* activatable = GetActivatableView(view); - if (!activatable) { - // There may not be a related activatable hierarchy to cut over to, in which - // case we try an unrelated one. - View* toplevel = GetToplevelView(view); - if (toplevel) - activatable = GetNextActivatableView(toplevel); - if (!activatable) - return nullptr; - } - - if (!activatable->Contains(view)) { - // If there's already a child window focused in the activatable hierarchy, - // just use that (i.e. don't shift focus), otherwise we need to at least cut - // over to the activatable hierarchy. - View* focused = GetFocusableView(activatable); - return activatable->Contains(focused) ? focused : activatable; - } - - while (view && !CanFocusView(view)) - view = view->parent(); - return view; -} - -View* BasicFocusRules::GetNextActivatableView(View* activatable) const { - DCHECK(activatable); - - // In the basic scenarios handled by BasicFocusRules, the pool of activatable - // windows is limited to the |ignore|'s siblings. - const View::Children& siblings = activatable->parent()->children(); - DCHECK(!siblings.empty()); - - for (auto rit = siblings.rbegin(); rit != siblings.rend(); ++rit) { - View* cur = *rit; - if (cur == activatable) - continue; - if (CanActivateView(cur)) - return cur; - } - return nullptr; -} - -// TODO(erg): aura::Window::CanFocus() exists. View::CanFocus() does -// not. This is a hack that does everything that Window::CanFocus() currently -// does that doesn't require a delegate or an EventClient. -bool BasicFocusRules::CanFocusViewImpl(View* view) const { - // TODO(erg): In unit tests, views will never be drawn, so we can't rely on - // IsDrawn() here. - if (IsViewParentedToWindowContainer(view)) - return view->visible(); - - // TODO(erg): Add the intermediary delegate and event client checks once we - // have those. - - return CanFocusViewImpl(view->parent()); -} - -bool BasicFocusRules::IsViewParentedToWindowContainer(View* view) const { - return view->parent() == window_container_; -} - -} // namespace mojo
diff --git a/components/window_manager/basic_focus_rules.h b/components/window_manager/basic_focus_rules.h deleted file mode 100644 index 6f31b4c..0000000 --- a/components/window_manager/basic_focus_rules.h +++ /dev/null
@@ -1,49 +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_WINDOW_MANAGER_BASIC_FOCUS_RULES_H_ -#define COMPONENTS_WINDOW_MANAGER_BASIC_FOCUS_RULES_H_ - -#include "components/window_manager/focus_rules.h" - -namespace mojo { -class View; -} - -namespace window_manager { - -// The focusing rules used inside a window manager. -// -// This is intended to be a user supplyable, subclassable component passed to -// WindowManagerApp, allowing for the creation of other window managers. -class BasicFocusRules : public FocusRules { - public: - BasicFocusRules(mojo::View* window_container); - ~BasicFocusRules() override; - - protected: - // Overridden from mojo::FocusRules: - bool SupportsChildActivation(mojo::View* view) const override; - bool IsToplevelView(mojo::View* view) const override; - bool CanActivateView(mojo::View* view) const override; - bool CanFocusView(mojo::View* view) const override; - mojo::View* GetToplevelView(mojo::View* view) const override; - mojo::View* GetActivatableView(mojo::View* view) const override; - mojo::View* GetFocusableView(mojo::View* view) const override; - mojo::View* GetNextActivatableView(mojo::View* activatable) const override; - - private: - bool CanFocusViewImpl(mojo::View* view) const; - - // Tests to see if |view| is in |window_container_|. - bool IsViewParentedToWindowContainer(mojo::View* view) const; - - mojo::View* window_container_; - - DISALLOW_COPY_AND_ASSIGN(BasicFocusRules); -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_BASIC_FOCUS_RULES_H_
diff --git a/components/window_manager/capture_controller.cc b/components/window_manager/capture_controller.cc deleted file mode 100644 index f8902b9..0000000 --- a/components/window_manager/capture_controller.cc +++ /dev/null
@@ -1,103 +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/window_manager/capture_controller.h" - -#include "components/window_manager/capture_controller_observer.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_property.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h" - -DECLARE_VIEW_PROPERTY_TYPE(window_manager::CaptureController*); - -namespace window_manager { - -namespace { -DEFINE_VIEW_PROPERTY_KEY(CaptureController*, - kRootViewCaptureController, - nullptr); -} // namespace - -CaptureController::CaptureController() - : capture_view_(nullptr) {} - -CaptureController::~CaptureController() {} - -void CaptureController::AddObserver(CaptureControllerObserver* observer) { - capture_controller_observers_.AddObserver(observer); -} - -void CaptureController::RemoveObserver(CaptureControllerObserver* observer) { - capture_controller_observers_.RemoveObserver(observer); -} - -void CaptureController::SetCapture(mojo::View* view) { - if (capture_view_ == view) - return; - - if (capture_view_) - capture_view_->RemoveObserver(this); - - mojo::View* old_capture_view = capture_view_; - capture_view_ = view; - - if (capture_view_) - capture_view_->AddObserver(this); - - NotifyCaptureChange(capture_view_, old_capture_view); -} - -void CaptureController::ReleaseCapture(mojo::View* view) { - if (capture_view_ != view) - return; - SetCapture(nullptr); -} - -mojo::View* CaptureController::GetCapture() { - return capture_view_; -} - -void CaptureController::NotifyCaptureChange(mojo::View* new_capture, - mojo::View* old_capture) { - mojo::ViewTracker view_tracker; - if (new_capture) - view_tracker.Add(new_capture); - if (old_capture) - view_tracker.Add(old_capture); - - FOR_EACH_OBSERVER( - CaptureControllerObserver, capture_controller_observers_, - OnCaptureChanged(view_tracker.Contains(new_capture) ? new_capture - : nullptr)); -} - -void CaptureController::OnViewDestroying(mojo::View* view) { - if (view == capture_view_) { - view->RemoveObserver(this); - NotifyCaptureChange(nullptr, view); - capture_view_ = nullptr; - } -} - -void SetCaptureController(mojo::View* root_view, - CaptureController* capture_controller) { - DCHECK_EQ(root_view->GetRoot(), root_view); - root_view->SetLocalProperty(kRootViewCaptureController, capture_controller); -} - -CaptureController* GetCaptureController(mojo::View* root_view) { - if (root_view) - DCHECK_EQ(root_view->GetRoot(), root_view); - return root_view ? - root_view->GetLocalProperty(kRootViewCaptureController) : nullptr; -} - -mojo::View* GetCaptureView(mojo::View* view) { - mojo::View* root = view->GetRoot(); - if (!root) - return nullptr; - CaptureController* controller = GetCaptureController(root); - return controller ? controller->GetCapture() : nullptr; -} - -} // namespace window_manager
diff --git a/components/window_manager/capture_controller.h b/components/window_manager/capture_controller.h deleted file mode 100644 index 761bc278..0000000 --- a/components/window_manager/capture_controller.h +++ /dev/null
@@ -1,49 +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_WINDOW_MANAGER_CAPTURE_CONTROLLER_H_ -#define COMPONENTS_WINDOW_MANAGER_CAPTURE_CONTROLLER_H_ - -#include "base/observer_list.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_observer.h" - -namespace window_manager { - -class CaptureControllerObserver; - -// Manages input capture. A view which has capture will take all input events. -class CaptureController : public mojo::ViewObserver { - public: - CaptureController(); - ~CaptureController() override; - - void AddObserver(CaptureControllerObserver* observer); - void RemoveObserver(CaptureControllerObserver* observer); - - void SetCapture(mojo::View* view); - void ReleaseCapture(mojo::View* view); - mojo::View* GetCapture(); - - private: - void NotifyCaptureChange(mojo::View* new_capture, mojo::View* old_capture); - - // Overridden from ViewObserver: - void OnViewDestroying(mojo::View* view) override; - - // The current capture view. Null if there is no capture view. - mojo::View* capture_view_; - - ObserverList<CaptureControllerObserver> capture_controller_observers_; - - DISALLOW_COPY_AND_ASSIGN(CaptureController); -}; - -void SetCaptureController(mojo::View* view, - CaptureController* capture_controller); -CaptureController* GetCaptureController(mojo::View* view); -mojo::View* GetCaptureView(mojo::View* view); - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_CAPTURE_CONTROLLER_H_
diff --git a/components/window_manager/capture_controller_observer.h b/components/window_manager/capture_controller_observer.h deleted file mode 100644 index 6072622..0000000 --- a/components/window_manager/capture_controller_observer.h +++ /dev/null
@@ -1,24 +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_WINDOW_MANAGER_CAPTURE_CONTROLLER_OBSERVER_H_ -#define COMPONENTS_WINDOW_MANAGER_CAPTURE_CONTROLLER_OBSERVER_H_ - -namespace mojo { -class View; -} - -namespace window_manager { - -class CaptureControllerObserver { - public: - virtual void OnCaptureChanged(mojo::View* gained_capture) = 0; - - protected: - virtual ~CaptureControllerObserver() {} -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_CAPTURE_CONTROLLER_OBSERVER_H_
diff --git a/components/window_manager/focus_controller.cc b/components/window_manager/focus_controller.cc deleted file mode 100644 index 1eb41549..0000000 --- a/components/window_manager/focus_controller.cc +++ /dev/null
@@ -1,317 +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/window_manager/focus_controller.h" - -#include "base/auto_reset.h" -#include "components/window_manager/focus_controller_observer.h" -#include "components/window_manager/focus_rules.h" -#include "components/window_manager/view_target.h" -#include "components/window_manager/window_manager_app.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_property.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h" -#include "ui/events/event.h" - -DECLARE_VIEW_PROPERTY_TYPE(window_manager::FocusController*); - -using mojo::View; - -namespace window_manager { - -namespace { -DEFINE_VIEW_PROPERTY_KEY(FocusController*, kRootViewFocusController, nullptr); -} // namespace - -FocusController::FocusController(scoped_ptr<FocusRules> rules) - : active_view_(nullptr), - focused_view_(nullptr), - updating_focus_(false), - updating_activation_(false), - rules_(rules.Pass()), - observer_manager_(this) { - DCHECK(rules_); -} - -FocusController::~FocusController() {} - -void FocusController::AddObserver(FocusControllerObserver* observer) { - focus_controller_observers_.AddObserver(observer); -} - -void FocusController::RemoveObserver(FocusControllerObserver* observer) { - focus_controller_observers_.RemoveObserver(observer); -} - -void FocusController::ActivateView(View* view) { - FocusView(view); -} - -void FocusController::DeactivateView(View* view) { - if (view) - FocusView(rules_->GetNextActivatableView(view)); -} - -View* FocusController::GetActiveView() { - return active_view_; -} - -View* FocusController::GetActivatableView(View* view) { - return rules_->GetActivatableView(view); -} - -View* FocusController::GetToplevelView(View* view) { - return rules_->GetToplevelView(view); -} - -bool FocusController::CanActivateView(View* view) const { - return rules_->CanActivateView(view); -} - -void FocusController::FocusView(View* view) { - if (view && - (view->Contains(focused_view_) || view->Contains(active_view_))) { - return; - } - - // Focusing a window also activates its containing activatable window. Note - // that the rules could redirect activation activation and/or focus. - View* focusable = rules_->GetFocusableView(view); - View* activatable = - focusable ? rules_->GetActivatableView(focusable) : nullptr; - - // We need valid focusable/activatable windows in the event we're not clearing - // focus. "Clearing focus" is inferred by whether or not |window| passed to - // this function is non-null. - if (view && (!focusable || !activatable)) - return; - DCHECK((focusable && activatable) || !view); - - // Activation change observers may change the focused window. If this happens - // we must not adjust the focus below since this will clobber that change. - View* last_focused_view = focused_view_; - if (!updating_activation_) - SetActiveView(view, activatable); - - // If the window's ActivationChangeObserver shifted focus to a valid window, - // we don't want to focus the window we thought would be focused by default. - bool activation_changed_focus = last_focused_view != focused_view_; - if (!updating_focus_ && (!activation_changed_focus || !focused_view_)) { - if (active_view_ && focusable) - DCHECK(active_view_->Contains(focusable)); - SetFocusedView(focusable); - } -} - -void FocusController::ResetFocusWithinActiveView(View* view) { - DCHECK(view); - if (!active_view_) - return; - if (!active_view_->Contains(view)) - return; - SetFocusedView(view); -} - -View* FocusController::GetFocusedView() { - return focused_view_; -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, ui::EventHandler implementation: - -void FocusController::OnKeyEvent(ui::KeyEvent* event) { -} - -void FocusController::OnMouseEvent(ui::MouseEvent* event) { - if (event->type() == ui::ET_MOUSE_PRESSED && !event->handled()) { - View* view = static_cast<ViewTarget*>(event->target())->view(); - ViewFocusedFromInputEvent(view); - } -} - -void FocusController::OnScrollEvent(ui::ScrollEvent* event) { -} - -void FocusController::OnTouchEvent(ui::TouchEvent* event) { - if (event->type() == ui::ET_TOUCH_PRESSED && !event->handled()) { - View* view = static_cast<ViewTarget*>(event->target())->view(); - ViewFocusedFromInputEvent(view); - } -} - -void FocusController::OnGestureEvent(ui::GestureEvent* event) { - if (event->type() == ui::ET_GESTURE_BEGIN && - event->details().touch_points() == 1 && - !event->handled()) { - View* view = static_cast<ViewTarget*>(event->target())->view(); - ViewFocusedFromInputEvent(view); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, mojo::ViewObserver implementation: - -void FocusController::OnViewVisibilityChanged(View* view) { - bool visible = view->visible(); - if (!visible) - ViewLostFocusFromDispositionChange(view, view->parent()); -} - -void FocusController::OnViewDestroying(View* view) { - ViewLostFocusFromDispositionChange(view, view->parent()); -} - -void FocusController::OnTreeChanging(const TreeChangeParams& params) { - // TODO(erg): In the aura version, you could get into a situation where you - // have different focus clients, so you had to check for that. Does that - // happen here? Could we get away with not checking if it does? - if (params.receiver == active_view_ && - params.target->Contains(params.receiver) && - (!params.new_parent || - /* different_focus_clients */ false)) { - ViewLostFocusFromDispositionChange(params.receiver, params.old_parent); - } -} - -void FocusController::OnTreeChanged(const TreeChangeParams& params) { - // TODO(erg): Same as Changing version. - if (params.receiver == focused_view_ && - params.target->Contains(params.receiver) && - (!params.new_parent || - /* different_focus_clients */ false)) { - ViewLostFocusFromDispositionChange(params.receiver, params.old_parent); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// FocusController, private: - -void FocusController::SetFocusedView(View* view) { - if (updating_focus_ || view == focused_view_) - return; - DCHECK(rules_->CanFocusView(view)); - if (view) - DCHECK_EQ(view, rules_->GetFocusableView(view)); - - base::AutoReset<bool> updating_focus(&updating_focus_, true); - View* lost_focus = focused_view_; - - // TODO(erg): In the aura version, we reset the text input client here. Do - // that if we bring in something like the TextInputClient. - - // Allow for the window losing focus to be deleted during dispatch. If it is - // deleted pass null to observers instead of a deleted window. - mojo::ViewTracker view_tracker; - if (lost_focus) - view_tracker.Add(lost_focus); - if (focused_view_ && observer_manager_.IsObserving(focused_view_) && - focused_view_ != active_view_) { - observer_manager_.Remove(focused_view_); - } - focused_view_ = view; - if (focused_view_ && !observer_manager_.IsObserving(focused_view_)) - observer_manager_.Add(focused_view_); - - FOR_EACH_OBSERVER(FocusControllerObserver, focus_controller_observers_, - OnFocused(focused_view_)); - - // TODO(erg): In aura, there's a concept of a single FocusChangeObserver that - // is attached to an aura::Window. We don't currently have this in - // mojo::View, but if we add it later, we should make something analogous - // here. - - // TODO(erg): In the aura version, we reset the TextInputClient here, too. -} - -void FocusController::SetActiveView(View* requested_view, View* view) { - if (updating_activation_) - return; - - if (view == active_view_) { - if (requested_view) { - FOR_EACH_OBSERVER(FocusControllerObserver, - focus_controller_observers_, - OnAttemptToReactivateView(requested_view, - active_view_)); - } - return; - } - - DCHECK(rules_->CanActivateView(view)); - if (view) - DCHECK_EQ(view, rules_->GetActivatableView(view)); - - base::AutoReset<bool> updating_activation(&updating_activation_, true); - View* lost_activation = active_view_; - // Allow for the window losing activation to be deleted during dispatch. If - // it is deleted pass null to observers instead of a deleted window. - mojo::ViewTracker view_tracker; - if (lost_activation) - view_tracker.Add(lost_activation); - if (active_view_ && observer_manager_.IsObserving(active_view_) && - focused_view_ != active_view_) { - observer_manager_.Remove(active_view_); - } - active_view_ = view; - if (active_view_ && !observer_manager_.IsObserving(active_view_)) - observer_manager_.Add(active_view_); - - if (active_view_) { - // TODO(erg): Reenable this when we have modal windows. - // StackTransientParentsBelowModalWindow(active_view_); - - active_view_->MoveToFront(); - } - - // TODO(erg): Individual windows can have a single ActivationChangeObserver - // set on them. In the aura version of this code, it sends an - // OnWindowActivated message to both the window that lost activation, and the - // window that gained it. - - FOR_EACH_OBSERVER(FocusControllerObserver, focus_controller_observers_, - OnActivated(active_view_)); -} - -void FocusController::ViewLostFocusFromDispositionChange( - View* view, - View* next) { - // TODO(erg): We clear the modality state here in the aura::Window version of - // this class, and should probably do the same once we have modal windows. - - // TODO(beng): See if this function can be replaced by a call to - // FocusWindow(). - // Activation adjustments are handled first in the event of a disposition - // changed. If an activation change is necessary, focus is reset as part of - // that process so there's no point in updating focus independently. - if (view == active_view_) { - View* next_activatable = rules_->GetNextActivatableView(view); - SetActiveView(nullptr, next_activatable); - if (!(active_view_ && active_view_->Contains(focused_view_))) - SetFocusedView(next_activatable); - } else if (view->Contains(focused_view_)) { - // Active window isn't changing, but focused window might be. - SetFocusedView(rules_->GetFocusableView(next)); - } -} - -void FocusController::ViewFocusedFromInputEvent(View* view) { - // Only focus |window| if it or any of its parents can be focused. Otherwise - // FocusWindow() will focus the topmost window, which may not be the - // currently focused one. - if (rules_->CanFocusView(GetToplevelView(view))) - FocusView(view); -} - -void SetFocusController(View* root_view, FocusController* focus_controller) { - DCHECK_EQ(root_view->GetRoot(), root_view); - root_view->SetLocalProperty(kRootViewFocusController, focus_controller); -} - -FocusController* GetFocusController(View* root_view) { - if (root_view) - DCHECK_EQ(root_view->GetRoot(), root_view); - return root_view ? - root_view->GetLocalProperty(kRootViewFocusController) : nullptr; -} - -} // namespace window_manager
diff --git a/components/window_manager/focus_controller.h b/components/window_manager/focus_controller.h deleted file mode 100644 index 39d7d8d..0000000 --- a/components/window_manager/focus_controller.h +++ /dev/null
@@ -1,102 +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_WINDOW_MANAGER_FOCUS_CONTROLLER_H_ -#define COMPONENTS_WINDOW_MANAGER_FOCUS_CONTROLLER_H_ - -#include "base/compiler_specific.h" -#include "base/memory/scoped_ptr.h" -#include "base/observer_list.h" -#include "base/scoped_observer.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_observer.h" -#include "ui/events/event_handler.h" - -namespace window_manager { - -class FocusControllerObserver; -class FocusRules; - -// FocusController handles focus and activation changes in a mojo window -// manager. Within the window manager, there can only be one focused and one -// active window at a time. When focus or activation changes, notifications are -// sent using the FocusControllerObserver interface. -class FocusController : public ui::EventHandler, public mojo::ViewObserver { - public: - // |rules| cannot be null. - explicit FocusController(scoped_ptr<FocusRules> rules); - ~FocusController() override; - - void AddObserver(FocusControllerObserver* observer); - void RemoveObserver(FocusControllerObserver* observer); - - void ActivateView(mojo::View* view); - void DeactivateView(mojo::View* view); - mojo::View* GetActiveView(); - mojo::View* GetActivatableView(mojo::View* view); - mojo::View* GetToplevelView(mojo::View* view); - bool CanActivateView(mojo::View* view) const; - - void FocusView(mojo::View* view); - - void ResetFocusWithinActiveView(mojo::View* view); - mojo::View* GetFocusedView(); - - // Overridden from ui::EventHandler: - void OnKeyEvent(ui::KeyEvent* event) override; - void OnMouseEvent(ui::MouseEvent* event) override; - void OnScrollEvent(ui::ScrollEvent* event) override; - void OnTouchEvent(ui::TouchEvent* event) override; - void OnGestureEvent(ui::GestureEvent* event) override; - - // Overridden from ViewObserver: - void OnTreeChanging(const TreeChangeParams& params) override; - void OnTreeChanged(const TreeChangeParams& params) override; - void OnViewVisibilityChanged(mojo::View* view) override; - void OnViewDestroying(mojo::View* view) override; - - private: - // Internal implementation that sets the focused view, fires events etc. - // This function must be called with a valid focusable view. - void SetFocusedView(mojo::View* view); - - // Internal implementation that sets the active window, fires events etc. - // This function must be called with a valid |activatable_window|. - // |requested window| refers to the window that was passed in to an external - // request (e.g. FocusWindow or ActivateWindow). It may be null, e.g. if - // SetActiveWindow was not called by an external request. |activatable_window| - // refers to the actual window to be activated, which may be different. - void SetActiveView(mojo::View* requested_view, mojo::View* activatable_view); - - // Called when a window's disposition changed such that it and its hierarchy - // are no longer focusable/activatable. |next| is a valid window that is used - // as a starting point for finding a window to focus next based on rules. - void ViewLostFocusFromDispositionChange(mojo::View* view, mojo::View* next); - - // Called when an attempt is made to focus or activate a window via an input - // event targeted at that window. Rules determine the best focusable window - // for the input window. - void ViewFocusedFromInputEvent(mojo::View* view); - - mojo::View* active_view_; - mojo::View* focused_view_; - - bool updating_focus_; - bool updating_activation_; - - scoped_ptr<FocusRules> rules_; - - ObserverList<FocusControllerObserver> focus_controller_observers_; - - ScopedObserver<mojo::View, ViewObserver> observer_manager_; - - DISALLOW_COPY_AND_ASSIGN(FocusController); -}; - -// Sets/Gets the focus controller for a view. -void SetFocusController(mojo::View* view, FocusController* focus_controller); -FocusController* GetFocusController(mojo::View* view); - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_FOCUS_CONTROLLER_H_
diff --git a/components/window_manager/focus_controller_observer.h b/components/window_manager/focus_controller_observer.h deleted file mode 100644 index 7f37f8c..0000000 --- a/components/window_manager/focus_controller_observer.h +++ /dev/null
@@ -1,35 +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_WINDOW_MANAGER_FOCUS_CONTROLLER_OBSERVER_H_ -#define COMPONENTS_WINDOW_MANAGER_FOCUS_CONTROLLER_OBSERVER_H_ - -namespace mojo { -class View; -} - -namespace window_manager { - -class FocusControllerObserver { - public: - // Called when |active| gains focus, or there is no active view - // (|active| is null in this case.). - virtual void OnActivated(mojo::View* gained_active) = 0; - - // Called when focus moves to |gained_focus|. - virtual void OnFocused(mojo::View* gained_focus) = 0; - - // Called when during view activation the currently active view is - // selected for activation. This can happen when a view requested for - // activation cannot be activated because a system modal view is active. - virtual void OnAttemptToReactivateView(mojo::View* request_active, - mojo::View* actual_active) {} - - protected: - virtual ~FocusControllerObserver() {} -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_FOCUS_CONTROLLER_OBSERVER_H_
diff --git a/components/window_manager/focus_controller_unittest.cc b/components/window_manager/focus_controller_unittest.cc deleted file mode 100644 index 9c888140a..0000000 --- a/components/window_manager/focus_controller_unittest.cc +++ /dev/null
@@ -1,1197 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/window_manager/focus_controller.h" - -#include "components/window_manager/basic_focus_rules.h" -#include "components/window_manager/capture_controller.h" -#include "components/window_manager/focus_controller_observer.h" -#include "components/window_manager/view_event_dispatcher.h" -#include "components/window_manager/view_targeter.h" -#include "components/window_manager/window_manager_test_util.h" -#include "mojo/converters/geometry/geometry_type_converters.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/event_utils.h" -#include "ui/gfx/geometry/rect.h" - -using mojo::View; - -namespace window_manager { - -// Counts the number of events that occur. -class FocusNotificationObserver : public FocusControllerObserver { - public: - FocusNotificationObserver() - : activation_changed_count_(0), - focus_changed_count_(0), - reactivation_count_(0), - reactivation_requested_view_(NULL), - reactivation_actual_view_(NULL) {} - ~FocusNotificationObserver() override {} - - void ExpectCounts(int activation_changed_count, int focus_changed_count) { - EXPECT_EQ(activation_changed_count, activation_changed_count_); - EXPECT_EQ(focus_changed_count, focus_changed_count_); - } - int reactivation_count() const { return reactivation_count_; } - View* reactivation_requested_view() const { - return reactivation_requested_view_; - } - View* reactivation_actual_view() const { - return reactivation_actual_view_; - } - - protected: - // Overridden from FocusControllerObserver: - void OnActivated(View* gained_active) override { - ++activation_changed_count_; - } - - void OnFocused(View* gained_focus) override { ++focus_changed_count_; } - - void OnAttemptToReactivateView(View* request_active, - View* actual_active) override { - ++reactivation_count_; - reactivation_requested_view_ = request_active; - reactivation_actual_view_ = actual_active; - } - - private: - int activation_changed_count_; - int focus_changed_count_; - int reactivation_count_; - View* reactivation_requested_view_; - View* reactivation_actual_view_; - - DISALLOW_COPY_AND_ASSIGN(FocusNotificationObserver); -}; - -class ViewDestroyer { - public: - virtual View* GetDestroyedView() = 0; - - protected: - virtual ~ViewDestroyer() {} -}; - -// FocusNotificationObserver that keeps track of whether it was notified about -// activation changes or focus changes with a destroyed view. -class RecordingFocusNotificationObserver : public FocusNotificationObserver { - public: - RecordingFocusNotificationObserver(FocusController* focus_controller, - ViewDestroyer* destroyer) - : focus_controller_(focus_controller), - destroyer_(destroyer), - active_(nullptr), - focus_(nullptr), - was_notified_with_destroyed_view_(false) { - focus_controller_->AddObserver(this); - } - ~RecordingFocusNotificationObserver() override { - focus_controller_->RemoveObserver(this); - } - - bool was_notified_with_destroyed_view() const { - return was_notified_with_destroyed_view_; - } - - // Overridden from FocusNotificationObserver: - void OnActivated(View* gained_active) override { - if (active_ && active_ == destroyer_->GetDestroyedView()) - was_notified_with_destroyed_view_ = true; - active_ = gained_active; - } - - void OnFocused(View* gained_focus) override { - if (focus_ && focus_ == destroyer_->GetDestroyedView()) - was_notified_with_destroyed_view_ = true; - focus_ = gained_focus; - } - - private: - FocusController* focus_controller_; - - // Not owned. - ViewDestroyer* destroyer_; - View* active_; - View* focus_; - - // Whether the observer was notified about the loss of activation or the - // loss of focus with a view already destroyed by |destroyer_| as the - // |lost_active| or |lost_focus| parameter. - bool was_notified_with_destroyed_view_; - - DISALLOW_COPY_AND_ASSIGN(RecordingFocusNotificationObserver); -}; - -class DestroyOnLoseActivationFocusNotificationObserver - : public FocusNotificationObserver, - public ViewDestroyer { - public: - DestroyOnLoseActivationFocusNotificationObserver( - FocusController* focus_controller, - View* view_to_destroy, - View* initial_active) - : focus_controller_(focus_controller), - view_to_destroy_(view_to_destroy), - active_(initial_active), - did_destroy_(false) { - focus_controller_->AddObserver(this); - } - ~DestroyOnLoseActivationFocusNotificationObserver() override { - focus_controller_->RemoveObserver(this); - } - - // Overridden from FocusNotificationObserver: - void OnActivated(View* gained_active) override { - if (view_to_destroy_ && active_ == view_to_destroy_) { - view_to_destroy_->Destroy(); - did_destroy_ = true; - } - active_ = gained_active; - } - - // Overridden from ViewDestroyer: - View* GetDestroyedView() override { - return did_destroy_ ? view_to_destroy_ : nullptr; - } - - private: - FocusController* focus_controller_; - View* view_to_destroy_; - View* active_; - bool did_destroy_; - - DISALLOW_COPY_AND_ASSIGN(DestroyOnLoseActivationFocusNotificationObserver); -}; - -class ScopedFocusNotificationObserver : public FocusNotificationObserver { - public: - ScopedFocusNotificationObserver(FocusController* focus_controller) - : focus_controller_(focus_controller) { - focus_controller_->AddObserver(this); - } - ~ScopedFocusNotificationObserver() override { - focus_controller_->RemoveObserver(this); - } - - private: - FocusController* focus_controller_; - - DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver); -}; - -// Only responds to events if a message contains |target| as a parameter. -class ScopedFilteringFocusNotificationObserver - : public FocusNotificationObserver { - public: - ScopedFilteringFocusNotificationObserver(FocusController* focus_controller, - View* target, - View* initial_active, - View* initial_focus) - : focus_controller_(focus_controller), - target_(target), - active_(initial_active), - focus_(initial_focus) { - focus_controller_->AddObserver(this); - } - ~ScopedFilteringFocusNotificationObserver() override { - focus_controller_->RemoveObserver(this); - } - - private: - // Overridden from FocusControllerObserver: - void OnActivated(View* gained_active) override { - if (gained_active == target_ || active_ == target_) - FocusNotificationObserver::OnActivated(gained_active); - active_ = gained_active; - } - - void OnFocused(View* gained_focus) override { - if (gained_focus == target_ || focus_ == target_) - FocusNotificationObserver::OnFocused(gained_focus); - focus_ = gained_focus; - } - - void OnAttemptToReactivateView(View* request_active, - View* actual_active) override { - if (request_active == target_ || actual_active == target_) { - FocusNotificationObserver::OnAttemptToReactivateView(request_active, - actual_active); - } - } - - FocusController* focus_controller_; - View* target_; - View* active_; - View* focus_; - - DISALLOW_COPY_AND_ASSIGN(ScopedFilteringFocusNotificationObserver); -}; - -// Used to fake the handling of events in the pre-target phase. -class SimpleEventHandler : public ui::EventHandler { - public: - SimpleEventHandler() {} - ~SimpleEventHandler() override {} - - // Overridden from ui::EventHandler: - void OnMouseEvent(ui::MouseEvent* event) override { - event->SetHandled(); - } - void OnGestureEvent(ui::GestureEvent* event) override { - event->SetHandled(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(SimpleEventHandler); -}; - -class FocusShiftingActivationObserver - : public FocusControllerObserver { - public: - explicit FocusShiftingActivationObserver(FocusController* focus_controller, - View* activated_view) - : focus_controller_(focus_controller), - activated_view_(activated_view), - shift_focus_to_(NULL) {} - ~FocusShiftingActivationObserver() override {} - - void set_shift_focus_to(View* shift_focus_to) { - shift_focus_to_ = shift_focus_to; - } - - private: - // Overridden from FocusControllerObserver: - void OnActivated(View* gained_active) override { - // Shift focus to a child. This should prevent the default focusing from - // occurring in FocusController::FocusView(). - if (gained_active == activated_view_) - focus_controller_->FocusView(shift_focus_to_); - } - - void OnFocused(View* gained_focus) override {} - - FocusController* focus_controller_; - View* activated_view_; - View* shift_focus_to_; - - DISALLOW_COPY_AND_ASSIGN(FocusShiftingActivationObserver); -}; - -// BasicFocusRules subclass that allows basic overrides of focus/activation to -// be tested. This is intended more as a test that the override system works at -// all, rather than as an exhaustive set of use cases, those should be covered -// in tests for those FocusRules implementations. -class TestFocusRules : public BasicFocusRules { - public: - TestFocusRules(View* root) - : BasicFocusRules(root), focus_restriction_(NULL) {} - - // Restricts focus and activation to this view and its child hierarchy. - void set_focus_restriction(View* focus_restriction) { - focus_restriction_ = focus_restriction; - } - - // Overridden from BasicFocusRules: - bool SupportsChildActivation(View* view) const override { - // In FocusControllerTests, only the Root has activatable children. - return view->GetRoot() == view; - } - bool CanActivateView(View* view) const override { - // Restricting focus to a non-activatable child view means the activatable - // parent outside the focus restriction is activatable. - bool can_activate = - CanFocusOrActivate(view) || view->Contains(focus_restriction_); - return can_activate ? BasicFocusRules::CanActivateView(view) : false; - } - bool CanFocusView(View* view) const override { - return CanFocusOrActivate(view) ? BasicFocusRules::CanFocusView(view) - : false; - } - View* GetActivatableView(View* view) const override { - return BasicFocusRules::GetActivatableView( - CanFocusOrActivate(view) ? view : focus_restriction_); - } - View* GetFocusableView(View* view) const override { - return BasicFocusRules::GetFocusableView( - CanFocusOrActivate(view) ? view : focus_restriction_); - } - View* GetNextActivatableView(View* ignore) const override { - View* next_activatable = BasicFocusRules::GetNextActivatableView(ignore); - return CanFocusOrActivate(next_activatable) - ? next_activatable - : GetActivatableView(focus_restriction_); - } - - private: - bool CanFocusOrActivate(View* view) const { - return !focus_restriction_ || focus_restriction_->Contains(view); - } - - View* focus_restriction_; - - DISALLOW_COPY_AND_ASSIGN(TestFocusRules); -}; - -// Common infrastructure shared by all FocusController test types. -class FocusControllerTestBase : public testing::Test { - protected: - // Hierarchy used by all tests: - // root_view - // +-- w1 - // | +-- w11 - // | +-- w12 - // +-- w2 - // | +-- w21 - // | +-- w211 - // +-- w3 - FocusControllerTestBase() - : root_view_(TestView::Build(0, gfx::Rect(0, 0, 800, 600))), - v1(TestView::Build(1, gfx::Rect(0, 0, 50, 50), root_view())), - v11(TestView::Build(11, gfx::Rect(5, 5, 10, 10), v1)), - v12(TestView::Build(12, gfx::Rect(15, 15, 10, 10), v1)), - v2(TestView::Build(2, gfx::Rect(75, 75, 50, 50), root_view())), - v21(TestView::Build(21, gfx::Rect(5, 5, 10, 10), v2)), - v211(TestView::Build(211, gfx::Rect(1, 1, 5, 5), v21)), - v3(TestView::Build(3, gfx::Rect(125, 125, 50, 50), root_view())) {} - - // Overridden from testing::Test: - void SetUp() override { - testing::Test::SetUp(); - - test_focus_rules_ = new TestFocusRules(root_view()); - focus_controller_.reset( - new FocusController(scoped_ptr<FocusRules>(test_focus_rules_))); - SetFocusController(root_view(), focus_controller_.get()); - - capture_controller_.reset(new CaptureController); - SetCaptureController(root_view(), capture_controller_.get()); - - ViewTarget* root_target = root_view_->target(); - root_target->SetEventTargeter(scoped_ptr<ViewTargeter>(new ViewTargeter())); - view_event_dispatcher_.reset(new ViewEventDispatcher()); - view_event_dispatcher_->SetRootViewTarget(root_target); - - GetRootViewTarget()->AddPreTargetHandler(focus_controller_.get()); - } - - void TearDown() override { - GetRootViewTarget()->RemovePreTargetHandler(focus_controller_.get()); - view_event_dispatcher_.reset(); - - root_view_->Destroy(); - - capture_controller_.reset(); - test_focus_rules_ = nullptr; // Owned by FocusController. - focus_controller_.reset(); - - testing::Test::TearDown(); - } - - void FocusView(View* view) { focus_controller_->FocusView(view); } - View* GetFocusedView() { return focus_controller_->GetFocusedView(); } - int GetFocusedViewId() { - View* focused_view = GetFocusedView(); - return focused_view ? focused_view->id() : -1; - } - void ActivateView(View* view) { focus_controller_->ActivateView(view); } - void DeactivateView(View* view) { focus_controller_->DeactivateView(view); } - View* GetActiveView() { return focus_controller_->GetActiveView(); } - int GetActiveViewId() { - View* active_view = GetActiveView(); - return active_view ? active_view->id() : -1; - } - - View* GetViewById(int id) { return root_view_->GetChildById(id); } - - void ClickLeftButton(View* view) { - // Get the center bounds of |target| in |root_view_| coordinate space. - gfx::Point center = - gfx::Rect(view->bounds().To<gfx::Rect>().size()).CenterPoint(); - ViewTarget::ConvertPointToTarget(ViewTarget::TargetFromView(view), - root_view_->target(), ¢er); - - ui::MouseEvent button_down(ui::ET_MOUSE_PRESSED, center, center, - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_NONE); - ui::EventDispatchDetails details = - view_event_dispatcher_->OnEventFromSource(&button_down); - CHECK(!details.dispatcher_destroyed); - - ui::MouseEvent button_up(ui::ET_MOUSE_RELEASED, center, center, - ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, - ui::EF_NONE); - details = view_event_dispatcher_->OnEventFromSource(&button_up); - CHECK(!details.dispatcher_destroyed); - } - - ViewTarget* GetRootViewTarget() { - return ViewTarget::TargetFromView(root_view()); - } - - View* root_view() { return root_view_; } - TestFocusRules* test_focus_rules() { return test_focus_rules_; } - FocusController* focus_controller() { return focus_controller_.get(); } - CaptureController* capture_controller() { return capture_controller_.get(); } - - // Test functions. - virtual void BasicFocus() = 0; - virtual void BasicActivation() = 0; - virtual void FocusEvents() = 0; - virtual void DuplicateFocusEvents() {} - virtual void ActivationEvents() = 0; - virtual void ReactivationEvents() {} - virtual void DuplicateActivationEvents() {} - virtual void ShiftFocusWithinActiveView() {} - virtual void ShiftFocusToChildOfInactiveView() {} - virtual void ShiftFocusToParentOfFocusedView() {} - virtual void FocusRulesOverride() = 0; - virtual void ActivationRulesOverride() = 0; - virtual void ShiftFocusOnActivation() {} - virtual void ShiftFocusOnActivationDueToHide() {} - virtual void NoShiftActiveOnActivation() {} - virtual void ChangeFocusWhenNothingFocusedAndCaptured() {} - virtual void DontPassDestroyedView() {} - // TODO(erg): Also, void FocusedTextInputClient() once we build the IME. - - private: - TestView* root_view_; - scoped_ptr<FocusController> focus_controller_; - TestFocusRules* test_focus_rules_; - scoped_ptr<CaptureController> capture_controller_; - // TODO(erg): The aura version of this class also keeps track of WMState. Do - // we need something analogous here? - - scoped_ptr<ViewEventDispatcher> view_event_dispatcher_; - - TestView* v1; - TestView* v11; - TestView* v12; - TestView* v2; - TestView* v21; - TestView* v211; - TestView* v3; - - DISALLOW_COPY_AND_ASSIGN(FocusControllerTestBase); -}; - -// Test base for tests where focus is directly set to a target view. -class FocusControllerDirectTestBase : public FocusControllerTestBase { - protected: - FocusControllerDirectTestBase() {} - - // Different test types shift focus in different ways. - virtual void FocusViewDirect(View* view) = 0; - virtual void ActivateViewDirect(View* view) = 0; - virtual void DeactivateViewDirect(View* view) = 0; - - // Input events do not change focus if the view can not be focused. - virtual bool IsInputEvent() = 0; - - void FocusViewById(int id) { - View* view = root_view()->GetChildById(id); - DCHECK(view); - FocusViewDirect(view); - } - void ActivateViewById(int id) { - View* view = root_view()->GetChildById(id); - DCHECK(view); - ActivateViewDirect(view); - } - - // Overridden from FocusControllerTestBase: - void BasicFocus() override { - EXPECT_EQ(nullptr, GetFocusedView()); - FocusViewById(1); - EXPECT_EQ(1, GetFocusedViewId()); - FocusViewById(2); - EXPECT_EQ(2, GetFocusedViewId()); - } - void BasicActivation() override { - EXPECT_EQ(nullptr, GetActiveView()); - ActivateViewById(1); - EXPECT_EQ(1, GetActiveViewId()); - ActivateViewById(2); - EXPECT_EQ(2, GetActiveViewId()); - // Verify that attempting to deactivate NULL does not crash and does not - // change activation. - DeactivateView(nullptr); - EXPECT_EQ(2, GetActiveViewId()); - DeactivateView(GetActiveView()); - EXPECT_EQ(1, GetActiveViewId()); - } - void FocusEvents() override { - ScopedFocusNotificationObserver root_observer(focus_controller()); - ScopedFilteringFocusNotificationObserver observer1( - focus_controller(), GetViewById(1), GetActiveView(), GetFocusedView()); - ScopedFilteringFocusNotificationObserver observer2( - focus_controller(), GetViewById(2), GetActiveView(), GetFocusedView()); - - { - SCOPED_TRACE("initial state"); - root_observer.ExpectCounts(0, 0); - observer1.ExpectCounts(0, 0); - observer2.ExpectCounts(0, 0); - } - - FocusViewById(1); - { - SCOPED_TRACE("FocusViewById(1)"); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - observer2.ExpectCounts(0, 0); - } - - FocusViewById(2); - { - SCOPED_TRACE("FocusViewById(2)"); - root_observer.ExpectCounts(2, 2); - observer1.ExpectCounts(2, 2); - observer2.ExpectCounts(1, 1); - } - } - void DuplicateFocusEvents() override { - // Focusing an existing focused view should not resend focus events. - ScopedFocusNotificationObserver root_observer(focus_controller()); - ScopedFilteringFocusNotificationObserver observer1( - focus_controller(), GetViewById(1), GetActiveView(), GetFocusedView()); - - root_observer.ExpectCounts(0, 0); - observer1.ExpectCounts(0, 0); - - FocusViewById(1); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - - FocusViewById(1); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - } - void ActivationEvents() override { - ActivateViewById(1); - - ScopedFocusNotificationObserver root_observer(focus_controller()); - ScopedFilteringFocusNotificationObserver observer1( - focus_controller(), GetViewById(1), GetActiveView(), GetFocusedView()); - ScopedFilteringFocusNotificationObserver observer2( - focus_controller(), GetViewById(2), GetActiveView(), GetFocusedView()); - - root_observer.ExpectCounts(0, 0); - observer1.ExpectCounts(0, 0); - observer2.ExpectCounts(0, 0); - - ActivateViewById(2); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - observer2.ExpectCounts(1, 1); - } - void ReactivationEvents() override { - ActivateViewById(1); - ScopedFocusNotificationObserver root_observer(focus_controller()); - EXPECT_EQ(0, root_observer.reactivation_count()); - GetViewById(2)->SetVisible(false); - // When we attempt to activate "2", which cannot be activated because it - // is not visible, "1" will be reactivated. - ActivateViewById(2); - EXPECT_EQ(1, root_observer.reactivation_count()); - EXPECT_EQ(GetViewById(2), - root_observer.reactivation_requested_view()); - EXPECT_EQ(GetViewById(1), - root_observer.reactivation_actual_view()); - } - void DuplicateActivationEvents() override { - ActivateViewById(1); - - ScopedFocusNotificationObserver root_observer(focus_controller()); - ScopedFilteringFocusNotificationObserver observer1( - focus_controller(), GetViewById(1), GetActiveView(), GetFocusedView()); - ScopedFilteringFocusNotificationObserver observer2( - focus_controller(), GetViewById(2), GetActiveView(), GetFocusedView()); - - root_observer.ExpectCounts(0, 0); - observer1.ExpectCounts(0, 0); - observer2.ExpectCounts(0, 0); - - ActivateViewById(2); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - observer2.ExpectCounts(1, 1); - - // Activating an existing active view should not resend activation events. - ActivateViewById(2); - root_observer.ExpectCounts(1, 1); - observer1.ExpectCounts(1, 1); - observer2.ExpectCounts(1, 1); - } - void ShiftFocusWithinActiveView() override { - ActivateViewById(1); - EXPECT_EQ(1, GetActiveViewId()); - EXPECT_EQ(1, GetFocusedViewId()); - FocusViewById(11); - EXPECT_EQ(11, GetFocusedViewId()); - FocusViewById(12); - EXPECT_EQ(12, GetFocusedViewId()); - } - void ShiftFocusToChildOfInactiveView() override { - ActivateViewById(2); - EXPECT_EQ(2, GetActiveViewId()); - EXPECT_EQ(2, GetFocusedViewId()); - FocusViewById(11); - EXPECT_EQ(1, GetActiveViewId()); - EXPECT_EQ(11, GetFocusedViewId()); - } - void ShiftFocusToParentOfFocusedView() override { - ActivateViewById(1); - EXPECT_EQ(1, GetFocusedViewId()); - FocusViewById(11); - EXPECT_EQ(11, GetFocusedViewId()); - FocusViewById(1); - // Focus should _not_ shift to the parent of the already-focused view. - EXPECT_EQ(11, GetFocusedViewId()); - } - void FocusRulesOverride() override { - EXPECT_EQ(NULL, GetFocusedView()); - FocusViewById(11); - EXPECT_EQ(11, GetFocusedViewId()); - - test_focus_rules()->set_focus_restriction(GetViewById(211)); - FocusViewById(12); - // Input events leave focus unchanged; direct API calls will change focus - // to the restricted view. - int focused_view = IsInputEvent() ? 11 : 211; - EXPECT_EQ(focused_view, GetFocusedViewId()); - - test_focus_rules()->set_focus_restriction(NULL); - FocusViewById(12); - EXPECT_EQ(12, GetFocusedViewId()); - } - void ActivationRulesOverride() override { - ActivateViewById(1); - EXPECT_EQ(1, GetActiveViewId()); - EXPECT_EQ(1, GetFocusedViewId()); - - View* v3 = GetViewById(3); - test_focus_rules()->set_focus_restriction(v3); - - ActivateViewById(2); - // Input events leave activation unchanged; direct API calls will activate - // the restricted view. - int active_view = IsInputEvent() ? 1 : 3; - EXPECT_EQ(active_view, GetActiveViewId()); - EXPECT_EQ(active_view, GetFocusedViewId()); - - test_focus_rules()->set_focus_restriction(NULL); - ActivateViewById(2); - EXPECT_EQ(2, GetActiveViewId()); - EXPECT_EQ(2, GetFocusedViewId()); - } - void ShiftFocusOnActivation() override { - // When a view is activated, by default that view is also focused. - // An ActivationChangeObserver may shift focus to another view within the - // same activatable view. - ActivateViewById(2); - EXPECT_EQ(2, GetFocusedViewId()); - ActivateViewById(1); - EXPECT_EQ(1, GetFocusedViewId()); - - ActivateViewById(2); - - View* target = GetViewById(1); - - scoped_ptr<FocusShiftingActivationObserver> observer( - new FocusShiftingActivationObserver(focus_controller(), target)); - observer->set_shift_focus_to(target->GetChildById(11)); - focus_controller()->AddObserver(observer.get()); - - ActivateViewById(1); - - // w1's ActivationChangeObserver shifted focus to this child, pre-empting - // FocusController's default setting. - EXPECT_EQ(11, GetFocusedViewId()); - - ActivateViewById(2); - EXPECT_EQ(2, GetFocusedViewId()); - - // Simulate a focus reset by the ActivationChangeObserver. This should - // trigger the default setting in FocusController. - observer->set_shift_focus_to(nullptr); - ActivateViewById(1); - EXPECT_EQ(1, GetFocusedViewId()); - - focus_controller()->RemoveObserver(observer.get()); - - ActivateViewById(2); - EXPECT_EQ(2, GetFocusedViewId()); - ActivateViewById(1); - EXPECT_EQ(1, GetFocusedViewId()); - } - void ShiftFocusOnActivationDueToHide() override { - // Similar to ShiftFocusOnActivation except the activation change is - // triggered by hiding the active view. - ActivateViewById(1); - EXPECT_EQ(1, GetFocusedViewId()); - - // Removes view 3 as candidate for next activatable view. - root_view()->GetChildById(3)->SetVisible(false); - EXPECT_EQ(1, GetFocusedViewId()); - - View* target = root_view()->GetChildById(2); - - scoped_ptr<FocusShiftingActivationObserver> observer( - new FocusShiftingActivationObserver(focus_controller(), target)); - observer->set_shift_focus_to(target->GetChildById(21)); - focus_controller()->AddObserver(observer.get()); - - // Hide the active view. - root_view()->GetChildById(1)->SetVisible(false); - - EXPECT_EQ(21, GetFocusedViewId()); - - focus_controller()->RemoveObserver(observer.get()); - } - void NoShiftActiveOnActivation() override { - // When a view is activated, we need to prevent any change to activation - // from being made in response to an activation change notification. - } - - // Verifies focus change is honored while capture held. - void ChangeFocusWhenNothingFocusedAndCaptured() override { - View* v1 = root_view()->GetChildById(1); - capture_controller()->SetCapture(v1); - - EXPECT_EQ(-1, GetActiveViewId()); - EXPECT_EQ(-1, GetFocusedViewId()); - - FocusViewById(1); - - EXPECT_EQ(1, GetActiveViewId()); - EXPECT_EQ(1, GetFocusedViewId()); - - capture_controller()->ReleaseCapture(v1); - } - - // Verifies if a view that loses activation or focus is destroyed during - // observer notification we don't pass the destroyed view to other observers. - void DontPassDestroyedView() override { - FocusViewById(1); - - EXPECT_EQ(1, GetActiveViewId()); - EXPECT_EQ(1, GetFocusedViewId()); - - { - View* to_destroy = root_view()->GetChildById(1); - DestroyOnLoseActivationFocusNotificationObserver observer1( - focus_controller(), to_destroy, GetActiveView()); - RecordingFocusNotificationObserver observer2(focus_controller(), - &observer1); - - FocusViewById(2); - - EXPECT_EQ(2, GetActiveViewId()); - EXPECT_EQ(2, GetFocusedViewId()); - - EXPECT_EQ(to_destroy, observer1.GetDestroyedView()); - EXPECT_FALSE(observer2.was_notified_with_destroyed_view()); - } - - { - View* to_destroy = root_view()->GetChildById(2); - DestroyOnLoseActivationFocusNotificationObserver observer1( - focus_controller(), to_destroy, GetActiveView()); - RecordingFocusNotificationObserver observer2(focus_controller(), - &observer1); - - FocusViewById(3); - - EXPECT_EQ(3, GetActiveViewId()); - EXPECT_EQ(3, GetFocusedViewId()); - - EXPECT_EQ(to_destroy, observer1.GetDestroyedView()); - EXPECT_FALSE(observer2.was_notified_with_destroyed_view()); - } - } - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); -}; - -// Focus and Activation changes via the FocusController API. -class FocusControllerApiTest : public FocusControllerDirectTestBase { - public: - FocusControllerApiTest() {} - - private: - // Overridden from FocusControllerTestBase: - void FocusViewDirect(View* view) override { FocusView(view); } - void ActivateViewDirect(View* view) override { ActivateView(view); } - void DeactivateViewDirect(View* view) override { DeactivateView(view); } - bool IsInputEvent() override { return false; } - - DISALLOW_COPY_AND_ASSIGN(FocusControllerApiTest); -}; - -// Focus and Activation changes via input events. -class FocusControllerMouseEventTest : public FocusControllerDirectTestBase { - public: - FocusControllerMouseEventTest() {} - - // Tests that a handled mouse event does not trigger a view activation. - void IgnoreHandledEvent() { - EXPECT_EQ(NULL, GetActiveView()); - View* v1 = root_view()->GetChildById(1); - SimpleEventHandler handler; - GetRootViewTarget()->PrependPreTargetHandler(&handler); - ClickLeftButton(v1); - EXPECT_EQ(NULL, GetActiveView()); - // TODO(erg): Add gesture testing when we get gestures working. - GetRootViewTarget()->RemovePreTargetHandler(&handler); - ClickLeftButton(v1); - EXPECT_EQ(1, GetActiveViewId()); - } - - private: - // Overridden from FocusControllerTestBase: - void FocusViewDirect(View* view) override { ClickLeftButton(view); } - void ActivateViewDirect(View* view) override { ClickLeftButton(view); } - void DeactivateViewDirect(View* view) override { - View* next_activatable = test_focus_rules()->GetNextActivatableView(view); - ClickLeftButton(next_activatable); - } - bool IsInputEvent() override { return true; } - - DISALLOW_COPY_AND_ASSIGN(FocusControllerMouseEventTest); -}; - -// TODO(erg): Add a FocusControllerGestureEventTest once we have working -// gesture forwarding and handling. - -// Test base for tests where focus is implicitly set to a window as the result -// of a disposition change to the focused window or the hierarchy that contains -// it. -class FocusControllerImplicitTestBase : public FocusControllerTestBase { - protected: - explicit FocusControllerImplicitTestBase(bool parent) : parent_(parent) {} - - View* GetDispositionView(View* view) { - return parent_ ? view->parent() : view; - } - - // Change the disposition of |view| in such a way as it will lose focus. - virtual void ChangeViewDisposition(View* view) = 0; - - // Allow each disposition change test to add additional post-disposition - // change expectations. - virtual void PostDispostionChangeExpectations() {} - - // Overridden from FocusControllerTestBase: - void BasicFocus() override { - EXPECT_EQ(NULL, GetFocusedView()); - - View* w211 = root_view()->GetChildById(211); - FocusView(w211); - EXPECT_EQ(211, GetFocusedViewId()); - - ChangeViewDisposition(w211); - // BasicFocusRules passes focus to the parent. - EXPECT_EQ(parent_ ? 2 : 21, GetFocusedViewId()); - } - - void BasicActivation() override { - DCHECK(!parent_) << "Activation tests don't support parent changes."; - - EXPECT_EQ(NULL, GetActiveView()); - - View* w2 = root_view()->GetChildById(2); - ActivateView(w2); - EXPECT_EQ(2, GetActiveViewId()); - - ChangeViewDisposition(w2); - EXPECT_EQ(3, GetActiveViewId()); - PostDispostionChangeExpectations(); - } - - void FocusEvents() override { - View* w211 = root_view()->GetChildById(211); - FocusView(w211); - - ScopedFocusNotificationObserver root_observer(focus_controller()); - ScopedFilteringFocusNotificationObserver observer211( - focus_controller(), GetViewById(211), GetActiveView(), - GetFocusedView()); - - { - SCOPED_TRACE("first"); - root_observer.ExpectCounts(0, 0); - observer211.ExpectCounts(0, 0); - } - - ChangeViewDisposition(w211); - { - SCOPED_TRACE("second"); - { - SCOPED_TRACE("root_observer"); - root_observer.ExpectCounts(0, 1); - } - { - SCOPED_TRACE("observer211"); - observer211.ExpectCounts(0, 1); - } - } - } - - void ActivationEvents() override { - DCHECK(!parent_) << "Activation tests don't support parent changes."; - - View* w2 = root_view()->GetChildById(2); - ActivateView(w2); - - ScopedFocusNotificationObserver root_observer(focus_controller()); - ScopedFilteringFocusNotificationObserver observer2( - focus_controller(), GetViewById(2), GetActiveView(), GetFocusedView()); - ScopedFilteringFocusNotificationObserver observer3( - focus_controller(), GetViewById(3), GetActiveView(), GetFocusedView()); - root_observer.ExpectCounts(0, 0); - observer2.ExpectCounts(0, 0); - observer3.ExpectCounts(0, 0); - - ChangeViewDisposition(w2); - root_observer.ExpectCounts(1, 1); - observer2.ExpectCounts(1, 1); - observer3.ExpectCounts(1, 1); - } - - void FocusRulesOverride() override { - EXPECT_EQ(NULL, GetFocusedView()); - View* w211 = root_view()->GetChildById(211); - FocusView(w211); - EXPECT_EQ(211, GetFocusedViewId()); - - test_focus_rules()->set_focus_restriction(root_view()->GetChildById(11)); - ChangeViewDisposition(w211); - // Normally, focus would shift to the parent (w21) but the override shifts - // it to 11. - EXPECT_EQ(11, GetFocusedViewId()); - - test_focus_rules()->set_focus_restriction(NULL); - } - - void ActivationRulesOverride() override { - DCHECK(!parent_) << "Activation tests don't support parent changes."; - - View* w1 = root_view()->GetChildById(1); - ActivateView(w1); - - EXPECT_EQ(1, GetActiveViewId()); - EXPECT_EQ(1, GetFocusedViewId()); - - View* w3 = root_view()->GetChildById(3); - test_focus_rules()->set_focus_restriction(w3); - - // Normally, activation/focus would move to w2, but since we have a focus - // restriction, it should move to w3 instead. - ChangeViewDisposition(w1); - EXPECT_EQ(3, GetActiveViewId()); - EXPECT_EQ(3, GetFocusedViewId()); - - test_focus_rules()->set_focus_restriction(NULL); - ActivateView(root_view()->GetChildById(2)); - EXPECT_EQ(2, GetActiveViewId()); - EXPECT_EQ(2, GetFocusedViewId()); - } - - private: - // When true, the disposition change occurs to the parent of the window - // instead of to the window. This verifies that changes occurring in the - // hierarchy that contains the window affect the window's focus. - bool parent_; - - DISALLOW_COPY_AND_ASSIGN(FocusControllerImplicitTestBase); -}; - -// Focus and Activation changes in response to window visibility changes. -class FocusControllerHideTest : public FocusControllerImplicitTestBase { - public: - FocusControllerHideTest() : FocusControllerImplicitTestBase(false) {} - - protected: - FocusControllerHideTest(bool parent) - : FocusControllerImplicitTestBase(parent) {} - - // Overridden from FocusControllerImplicitTestBase: - void ChangeViewDisposition(View* view) override { - GetDispositionView(view)->SetVisible(false); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerHideTest); -}; - -// Focus and Activation changes in response to window parent visibility -// changes. -class FocusControllerParentHideTest : public FocusControllerHideTest { - public: - FocusControllerParentHideTest() : FocusControllerHideTest(true) {} - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerParentHideTest); -}; - -// Focus and Activation changes in response to window destruction. -class FocusControllerDestructionTest : public FocusControllerImplicitTestBase { - public: - FocusControllerDestructionTest() : FocusControllerImplicitTestBase(false) {} - - protected: - FocusControllerDestructionTest(bool parent) - : FocusControllerImplicitTestBase(parent) {} - - // Overridden from FocusControllerImplicitTestBase: - void ChangeViewDisposition(View* view) override { - GetDispositionView(view)->Destroy(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerDestructionTest); -}; - -// Focus and Activation changes in response to window removal. -class FocusControllerRemovalTest : public FocusControllerImplicitTestBase { - public: - FocusControllerRemovalTest() - : FocusControllerImplicitTestBase(false), - window_to_destroy_(nullptr) {} - - protected: - FocusControllerRemovalTest(bool parent) - : FocusControllerImplicitTestBase(parent), - window_to_destroy_(nullptr) {} - - // Overridden from FocusControllerImplicitTestBase: - void ChangeViewDisposition(View* view) override { - View* disposition_view = GetDispositionView(view); - disposition_view->parent()->RemoveChild(disposition_view); - window_to_destroy_ = disposition_view; - } - void TearDown() override { - if (window_to_destroy_) - window_to_destroy_->Destroy(); - - FocusControllerImplicitTestBase::TearDown(); - } - - private: - View* window_to_destroy_; - - DISALLOW_COPY_AND_ASSIGN(FocusControllerRemovalTest); -}; - -// Focus and Activation changes in response to window parent removal. -class FocusControllerParentRemovalTest : public FocusControllerRemovalTest { - public: - FocusControllerParentRemovalTest() : FocusControllerRemovalTest(true) {} - - private: - DISALLOW_COPY_AND_ASSIGN(FocusControllerParentRemovalTest); -}; - -#define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \ - TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); } - -// Runs direct focus change tests (input events and API calls). -// -// TODO(erg): Enable gesture events in the future. -#define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME) - -// Runs implicit focus change tests for disposition changes to target. -#define IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerHideTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerDestructionTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerRemovalTest, TESTNAME) - -// Runs implicit focus change tests for disposition changes to target's parent -// hierarchy. -#define IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest, TESTNAME) \ - FOCUS_CONTROLLER_TEST(FocusControllerParentRemovalTest, TESTNAME) -// TODO(erg): FocusControllerParentDestructionTest were commented out in the -// aura version of this file, and don't work when I tried porting things over. - -// Runs all implicit focus change tests (changes to the target and target's -// parent hierarchy) -#define IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) \ - IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \ - IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) - -// Runs all possible focus change tests. -#define ALL_FOCUS_TESTS(TESTNAME) \ - DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ - IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) - -// Runs focus change tests that apply only to the target. For example, -// implicit activation changes caused by window disposition changes do not -// occur when changes to the containing hierarchy happen. -#define TARGET_FOCUS_TESTS(TESTNAME) \ - DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ - IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) - -// - Focuses a window, verifies that focus changed. -ALL_FOCUS_TESTS(BasicFocus); - -// - Activates a window, verifies that activation changed. -TARGET_FOCUS_TESTS(BasicActivation); - -// - Focuses a window, verifies that focus events were dispatched. -ALL_FOCUS_TESTS(FocusEvents); - -// - Focuses or activates a window multiple times, verifies that events are only -// dispatched when focus/activation actually changes. -DIRECT_FOCUS_CHANGE_TESTS(DuplicateFocusEvents); -DIRECT_FOCUS_CHANGE_TESTS(DuplicateActivationEvents); - -// - Activates a window, verifies that activation events were dispatched. -TARGET_FOCUS_TESTS(ActivationEvents); - -// - Attempts to active a hidden view, verifies that current view is -// attempted to be reactivated and the appropriate event dispatched. -FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ReactivationEvents); - -// - Input events/API calls shift focus between focusable views within the -// active view. -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveView); - -// - Input events/API calls to a child view of an inactive view shifts -// activation to the activatable parent and focuses the child. -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveView); - -// - Input events/API calls to focus the parent of the focused view do not -// shift focus away from the child. -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedView); - -// - Verifies that FocusRules determine what can be focused. -ALL_FOCUS_TESTS(FocusRulesOverride); - -// - Verifies that FocusRules determine what can be activated. -TARGET_FOCUS_TESTS(ActivationRulesOverride); - -// - Verifies that attempts to change focus or activation from a focus or -// activation change observer are ignored. -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivation); -DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivationDueToHide); -DIRECT_FOCUS_CHANGE_TESTS(NoShiftActiveOnActivation); - -FOCUS_CONTROLLER_TEST(FocusControllerApiTest, - ChangeFocusWhenNothingFocusedAndCaptured); - -// See description above DontPassDestroyedView() for details. -FOCUS_CONTROLLER_TEST(FocusControllerApiTest, DontPassDestroyedView); - -// TODO(erg): Add the TextInputClient tests here. - -// If a mouse event was handled, it should not activate a view. -FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, IgnoreHandledEvent); - -} // namespace window_manager
diff --git a/components/window_manager/focus_rules.h b/components/window_manager/focus_rules.h deleted file mode 100644 index 3514c7f..0000000 --- a/components/window_manager/focus_rules.h +++ /dev/null
@@ -1,65 +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_WINDOW_MANAGER_FOCUS_RULES_H_ -#define COMPONENTS_WINDOW_MANAGER_FOCUS_RULES_H_ - -#include "third_party/mojo_services/src/view_manager/public/cpp/types.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" - -namespace window_manager { - -// Implemented by an object that establishes the rules about what can be -// focused or activated. -class FocusRules { - public: - virtual ~FocusRules() {} - - // Returns true if the children of |window| can be activated. - virtual bool SupportsChildActivation(mojo::View* window) const = 0; - - // Returns true if |view| is a toplevel view. Whether or not a view - // is considered toplevel is determined by a similar set of rules that - // govern activation and focus. Not all toplevel views are activatable, - // call CanActivateView() to determine if a view can be activated. - virtual bool IsToplevelView(mojo::View* view) const = 0; - // Returns true if |view| can be activated or focused. - virtual bool CanActivateView(mojo::View* view) const = 0; - // For CanFocusView(), null is supported, because null is a valid focusable - // view (in the case of clearing focus). - virtual bool CanFocusView(mojo::View* view) const = 0; - - // Returns the toplevel view containing |view|. Not all toplevel views - // are activatable, call GetActivatableView() instead to return the - // activatable view, which might be in a different hierarchy. - // Will return null if |view| is not contained by a view considered to be - // a toplevel view. - virtual mojo::View* GetToplevelView(mojo::View* view) const = 0; - // Returns the activatable or focusable view given an attempt to activate or - // focus |view|. Some possible scenarios (not intended to be exhaustive): - // - |view| is a child of a non-focusable view and so focus must be set - // according to rules defined by the delegate, e.g. to a parent. - // - |view| is an activatable view that is the transient parent of a modal - // view, so attempts to activate |view| should result in the modal - // transient being activated instead. - // These methods may return null if they are unable to find an activatable - // or focusable view given |view|. - virtual mojo::View* GetActivatableView(mojo::View* view) const = 0; - virtual mojo::View* GetFocusableView(mojo::View* view) const = 0; - - // Returns the next view to activate in the event that |ignore| is no longer - // activatable. This function is called when something is happening to - // |ignore| that means it can no longer have focus or activation, including - // but not limited to: - // - it or its parent hierarchy is being hidden, or removed from the - // RootView. - // - it is being destroyed. - // - it is being explicitly deactivated. - // |ignore| cannot be null. - virtual mojo::View* GetNextActivatableView(mojo::View* ignore) const = 0; -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_FOCUS_RULES_H_
diff --git a/components/window_manager/hit_test.h b/components/window_manager/hit_test.h deleted file mode 100644 index 37a7ea5..0000000 --- a/components/window_manager/hit_test.h +++ /dev/null
@@ -1,45 +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. - -#ifndef COMPONENTS_WINDOW_MANAGER_HIT_TEST_H_ -#define COMPONENTS_WINDOW_MANAGER_HIT_TEST_H_ - -#if !defined(OS_WIN) - -// Defines the same symbolic names used by the WM_NCHITTEST Notification under -// win32 (the integer values are not guaranteed to be equivalent). We do this -// because we have a whole bunch of code that deals with window resizing and -// such that requires these values. -enum HitTestCompat { - HTNOWHERE = 0, - HTBORDER, - HTBOTTOM, - HTBOTTOMLEFT, - HTBOTTOMRIGHT, - HTCAPTION, - HTCLIENT, - HTCLOSE, - HTERROR, - HTGROWBOX, - HTHELP, - HTHSCROLL, - HTLEFT, - HTMENU, - HTMAXBUTTON, - HTMINBUTTON, - HTREDUCE, - HTRIGHT, - HTSIZE, - HTSYSMENU, - HTTOP, - HTTOPLEFT, - HTTOPRIGHT, - HTTRANSPARENT, - HTVSCROLL, - HTZOOM -}; - -#endif // !defined(OS_WIN) - -#endif // COMPONENTS_WINDOW_MANAGER_HIT_TEST_H_
diff --git a/components/window_manager/main.cc b/components/window_manager/main.cc index 5edfec9..5f500264 100644 --- a/components/window_manager/main.cc +++ b/components/window_manager/main.cc
@@ -3,7 +3,8 @@ // found in the LICENSE file. #include "base/memory/scoped_ptr.h" -#include "components/window_manager/basic_focus_rules.h" +#include "components/view_manager/public/cpp/view_manager.h" +#include "components/view_manager/public/cpp/view_manager_delegate.h" #include "components/window_manager/window_manager_app.h" #include "components/window_manager/window_manager_delegate.h" #include "mojo/application/application_runner_chromium.h" @@ -11,8 +12,6 @@ #include "third_party/mojo/src/mojo/public/c/system/main.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h" // ApplicationDelegate implementation file for WindowManager users (e.g. // core window manager tests) that do not want to provide their own @@ -51,8 +50,6 @@ mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::ServiceProviderPtr exposed_services) override { root_ = root; - window_manager_app_->InitFocus( - make_scoped_ptr(new window_manager::BasicFocusRules(root_))); } void OnViewManagerDisconnected(ViewManager* view_manager) override {}
diff --git a/components/window_manager/native_viewport_event_dispatcher_impl.cc b/components/window_manager/native_viewport_event_dispatcher_impl.cc deleted file mode 100644 index 4c77e96..0000000 --- a/components/window_manager/native_viewport_event_dispatcher_impl.cc +++ /dev/null
@@ -1,36 +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/window_manager/native_viewport_event_dispatcher_impl.h" - -#include "components/window_manager/view_event_dispatcher.h" -#include "components/window_manager/window_manager_app.h" -#include "mojo/converters/input_events/input_events_type_converters.h" - -namespace window_manager { - -NativeViewportEventDispatcherImpl::NativeViewportEventDispatcherImpl( - WindowManagerApp* app, - mojo::InterfaceRequest<mojo::NativeViewportEventDispatcher> request) - : app_(app), binding_(this, request.Pass()) { -} -NativeViewportEventDispatcherImpl::~NativeViewportEventDispatcherImpl() { -} - -ui::EventProcessor* NativeViewportEventDispatcherImpl::GetEventProcessor() { - return app_->event_dispatcher(); -} - -void NativeViewportEventDispatcherImpl::OnEvent( - mojo::EventPtr event, - const mojo::Callback<void()>& callback) { - scoped_ptr<ui::Event> ui_event = event.To<scoped_ptr<ui::Event>>(); - - if (ui_event) - SendEventToProcessor(ui_event.get()); - - callback.Run(); -} - -} // namespace window_manager
diff --git a/components/window_manager/native_viewport_event_dispatcher_impl.h b/components/window_manager/native_viewport_event_dispatcher_impl.h deleted file mode 100644 index ac90837..0000000 --- a/components/window_manager/native_viewport_event_dispatcher_impl.h +++ /dev/null
@@ -1,42 +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_WINDOW_MANAGER_NATIVE_VIEWPORT_EVENT_DISPATCHER_IMPL_H_ -#define COMPONENTS_WINDOW_MANAGER_NATIVE_VIEWPORT_EVENT_DISPATCHER_IMPL_H_ - -#include "base/basictypes.h" -#include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" -#include "third_party/mojo_services/src/native_viewport/public/interfaces/native_viewport.mojom.h" -#include "ui/events/event_source.h" - -namespace window_manager { - -class WindowManagerApp; - -class NativeViewportEventDispatcherImpl - : public ui::EventSource, - public mojo::NativeViewportEventDispatcher { - public: - NativeViewportEventDispatcherImpl( - WindowManagerApp* app, - mojo::InterfaceRequest<mojo::NativeViewportEventDispatcher> request); - ~NativeViewportEventDispatcherImpl() override; - - private: - // ui::EventSource: - ui::EventProcessor* GetEventProcessor() override; - - // NativeViewportEventDispatcher: - void OnEvent(mojo::EventPtr event, - const mojo::Callback<void()>& callback) override; - - WindowManagerApp* app_; - - mojo::StrongBinding<mojo::NativeViewportEventDispatcher> binding_; - DISALLOW_COPY_AND_ASSIGN(NativeViewportEventDispatcherImpl); -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_NATIVE_VIEWPORT_EVENT_DISPATCHER_IMPL_H_
diff --git a/components/window_manager/public/interfaces/BUILD.gn b/components/window_manager/public/interfaces/BUILD.gn new file mode 100644 index 0000000..9d1df9e --- /dev/null +++ b/components/window_manager/public/interfaces/BUILD.gn
@@ -0,0 +1,20 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "window_manager.mojom", + "window_manager_internal.mojom", + ] + + mojo_sdk_deps = [ "mojo/public/interfaces/application" ] + + deps = [ + "//ui/mojo/events:interfaces", + "//ui/mojo/geometry:interfaces", + ] +}
diff --git a/components/window_manager/public/interfaces/window_manager.mojom b/components/window_manager/public/interfaces/window_manager.mojom new file mode 100644 index 0000000..0ff82fe --- /dev/null +++ b/components/window_manager/public/interfaces/window_manager.mojom
@@ -0,0 +1,16 @@ +// 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 mojo; + +import "mojo/public/interfaces/application/service_provider.mojom"; + +interface WindowManager { + // Requests the WindowManager to embed the app for |url| at an appropriate + // View. See ViewMangerService::Embed() for details on |services| and + // |exposed_services|. + Embed(string url, + ServiceProvider&? services, + ServiceProvider? exposed_services); +};
diff --git a/components/window_manager/public/interfaces/window_manager_internal.mojom b/components/window_manager/public/interfaces/window_manager_internal.mojom new file mode 100644 index 0000000..e987189 --- /dev/null +++ b/components/window_manager/public/interfaces/window_manager_internal.mojom
@@ -0,0 +1,45 @@ +// 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 mojo; + +import "ui/mojo/events/input_event_constants.mojom"; +import "ui/mojo/events/input_events.mojom"; +import "ui/mojo/events/input_key_codes.mojom"; +import "ui/mojo/geometry/geometry.mojom"; + +// WindowManagerInternal is an interface provided by the WindowManager +// exclusively to the ViewManager. +interface WindowManagerInternal { + SetViewManagerClient(handle<message_pipe> view_manager_client_request); + + // An accelerator registered via AddAccelerator() has been triggered. + OnAccelerator(mojo.Event event); +}; + +// WindowManagerInternalClient is an interface provide by the ViewManager +// exclusively to the WindowManager. It provides functionality only available +// to the WindowManager. +interface WindowManagerInternalClient { + // TODO(sky): this is only used by sky's testing harness. It should be + // removed. + DispatchInputEventToViewDEPRECATED(uint32 view_id, mojo.Event event); + + // Sets the native viewport size. + SetViewportSize(mojo.Size size); + + // Clones the tree rooted at |view_id|. When the animation completes the clone + // is destroyed. + // TODO(sky): add actual animation. + // TODO(sky): I think this only makes sense when destroying (view is + // already visible), should it be named to indicate this? + CloneAndAnimate(uint32 view_id); + + // Adds or removes an accelerators. When the ViewManager receives a key event + // it checks if an accelerator has been registered. If it has, the event is + // sent to the window manager (OnAccelerator()), if not, the event is sent to + // the focused view. + AddAccelerator(mojo.KeyboardCode keyboard_code, mojo.EventFlags flags); + RemoveAccelerator(mojo.KeyboardCode keyboard_code, mojo.EventFlags flags); +};
diff --git a/components/window_manager/run_all_unittests.cc b/components/window_manager/run_all_unittests.cc deleted file mode 100644 index 51fd967..0000000 --- a/components/window_manager/run_all_unittests.cc +++ /dev/null
@@ -1,43 +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 "base/bind.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "ui/gl/gl_surface.h" - -#if defined(USE_X11) -#include "ui/gfx/x/x11_connection.h" -#endif - -namespace window_manager { - -class WindowManagerTestSuite : public base::TestSuite { - public: - WindowManagerTestSuite(int argc, char** argv) : TestSuite(argc, argv) {} - ~WindowManagerTestSuite() override {} - - protected: - void Initialize() override { -#if defined(USE_X11) - // Each test ends up creating a new thread for the native viewport service. - // In other words we'll use X on different threads, so tell it that. - gfx::InitializeThreadedX11(); -#endif - base::TestSuite::Initialize(); - gfx::GLSurface::InitializeOneOffForTests(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(WindowManagerTestSuite); -}; - -} // namespace window_manager - -int main(int argc, char** argv) { - window_manager::WindowManagerTestSuite test_suite(argc, argv); - - return base::LaunchUnitTests( - argc, argv, base::Bind(&TestSuite::Run, base::Unretained(&test_suite))); -}
diff --git a/components/window_manager/view_event_dispatcher.cc b/components/window_manager/view_event_dispatcher.cc deleted file mode 100644 index b09caa8..0000000 --- a/components/window_manager/view_event_dispatcher.cc +++ /dev/null
@@ -1,55 +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/window_manager/view_event_dispatcher.h" - -#include "components/window_manager/view_target.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" - -namespace window_manager { - -ViewEventDispatcher::ViewEventDispatcher() - : event_dispatch_target_(nullptr), - old_dispatch_target_(nullptr) { -} - -ViewEventDispatcher::~ViewEventDispatcher() {} - -void ViewEventDispatcher::SetRootViewTarget(ViewTarget* root_view_target) { - root_view_target_ = root_view_target; -} - -ui::EventTarget* ViewEventDispatcher::GetRootTarget() { - return root_view_target_; -} - -void ViewEventDispatcher::OnEventProcessingStarted(ui::Event* event) { -} - -bool ViewEventDispatcher::CanDispatchToTarget(ui::EventTarget* target) { - return event_dispatch_target_ == target; -} - -ui::EventDispatchDetails ViewEventDispatcher::PreDispatchEvent( - ui::EventTarget* target, - ui::Event* event) { - // TODO(erg): PreDispatch in aura::WindowEventDispatcher does many, many - // things. It, and the functions split off for different event types, are - // most of the file. - old_dispatch_target_ = event_dispatch_target_; - event_dispatch_target_ = static_cast<ViewTarget*>(target); - return ui::EventDispatchDetails(); -} - -ui::EventDispatchDetails ViewEventDispatcher::PostDispatchEvent( - ui::EventTarget* target, - const ui::Event& event) { - // TODO(erg): Not at all as long as PreDispatchEvent, but still missing core - // details. - event_dispatch_target_ = old_dispatch_target_; - old_dispatch_target_ = nullptr; - return ui::EventDispatchDetails(); -} - -} // namespace window_manager
diff --git a/components/window_manager/view_event_dispatcher.h b/components/window_manager/view_event_dispatcher.h deleted file mode 100644 index 8757e638..0000000 --- a/components/window_manager/view_event_dispatcher.h +++ /dev/null
@@ -1,47 +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_WINDOW_MANAGER_VIEW_EVENT_DISPATCHER_H_ -#define COMPONENTS_WINDOW_MANAGER_VIEW_EVENT_DISPATCHER_H_ - -#include "base/memory/scoped_ptr.h" -#include "ui/events/event_processor.h" -#include "ui/events/event_target.h" - -namespace window_manager { - -class ViewTarget; - -class ViewEventDispatcher : public ui::EventProcessor { - public: - ViewEventDispatcher(); - ~ViewEventDispatcher() override; - - void SetRootViewTarget(ViewTarget* root_view_target); - - private: - // Overridden from ui::EventProcessor: - ui::EventTarget* GetRootTarget() override; - void OnEventProcessingStarted(ui::Event* event) override; - - // Overridden from ui::EventDispatcherDelegate. - bool CanDispatchToTarget(ui::EventTarget* target) override; - ui::EventDispatchDetails PreDispatchEvent(ui::EventTarget* target, - ui::Event* event) override; - ui::EventDispatchDetails PostDispatchEvent( - ui::EventTarget* target, const ui::Event& event) override; - - // We keep a weak reference to ViewTarget*, which corresponds to the root of - // the mojo::View tree. - ViewTarget* root_view_target_; - - ViewTarget* event_dispatch_target_; - ViewTarget* old_dispatch_target_; - - DISALLOW_COPY_AND_ASSIGN(ViewEventDispatcher); -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_VIEW_EVENT_DISPATCHER_H_
diff --git a/components/window_manager/view_target.cc b/components/window_manager/view_target.cc deleted file mode 100644 index 0f9d1a2d..0000000 --- a/components/window_manager/view_target.cc +++ /dev/null
@@ -1,192 +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/window_manager/view_target.h" - -#include "components/window_manager/view_targeter.h" -#include "components/window_manager/window_manager_app.h" -#include "mojo/converters/geometry/geometry_type_converters.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_property.h" -#include "ui/events/event.h" -#include "ui/events/event_target_iterator.h" -#include "ui/events/event_targeter.h" -#include "ui/gfx/geometry/point3_f.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/transform.h" - -namespace window_manager { - -namespace { - -DEFINE_OWNED_VIEW_PROPERTY_KEY(ViewTarget, kViewTargetKey, nullptr); - -// Provides a version which keeps a copy of the data (for when it has to be -// derived instead of pointed at). -template <typename T> -class CopyingEventTargetIteratorImpl : public ui::EventTargetIterator { - public: - explicit CopyingEventTargetIteratorImpl(const std::vector<T*>& children) - : children_(children), - begin_(children_.rbegin()), - end_(children_.rend()) {} - ~CopyingEventTargetIteratorImpl() override {} - - ui::EventTarget* GetNextTarget() override { - if (begin_ == end_) - return nullptr; - ui::EventTarget* target = *(begin_); - ++begin_; - return target; - } - - private: - typename std::vector<T*> children_; - typename std::vector<T*>::const_reverse_iterator begin_; - typename std::vector<T*>::const_reverse_iterator end_; -}; - -} // namespace - -ViewTarget::~ViewTarget() { -} - -// static -ViewTarget* ViewTarget::TargetFromView(mojo::View* view) { - if (!view) - return nullptr; - - ViewTarget* target = view->GetLocalProperty(kViewTargetKey); - if (target) - return target; - - return new ViewTarget(view); -} - -void ViewTarget::ConvertPointToTarget(const ViewTarget* source, - const ViewTarget* target, - gfx::Point* point) { - // TODO(erg): Do we need to deal with |source| and |target| being in - // different trees? - DCHECK_EQ(source->GetRoot(), target->GetRoot()); - if (source == target) - return; - - const ViewTarget* root_target = source->GetRoot(); - CHECK_EQ(root_target, target->GetRoot()); - - if (source != root_target) - source->ConvertPointForAncestor(root_target, point); - if (target != root_target) - target->ConvertPointFromAncestor(root_target, point); -} - -std::vector<ViewTarget*> ViewTarget::GetChildren() const { - std::vector<ViewTarget*> targets; - for (mojo::View* child : view_->children()) - targets.push_back(TargetFromView(child)); - return targets; -} - -const ViewTarget* ViewTarget::GetParent() const { - return TargetFromView(view_->parent()); -} - -gfx::Rect ViewTarget::GetBounds() const { - return view_->bounds().To<gfx::Rect>(); -} - -bool ViewTarget::HasParent() const { - return !!view_->parent(); -} - -bool ViewTarget::IsVisible() const { - return view_->visible(); -} - -const ViewTarget* ViewTarget::GetRoot() const { - const ViewTarget* root = this; - for (const ViewTarget* parent = this; parent; parent = parent->GetParent()) - root = parent; - return root; -} - -scoped_ptr<ViewTargeter> ViewTarget::SetEventTargeter( - scoped_ptr<ViewTargeter> targeter) { - scoped_ptr<ViewTargeter> old_targeter = targeter_.Pass(); - targeter_ = targeter.Pass(); - return old_targeter.Pass(); -} - -bool ViewTarget::CanAcceptEvent(const ui::Event& event) { - // We need to make sure that a touch cancel event and any gesture events it - // creates can always reach the window. This ensures that we receive a valid - // touch / gesture stream. - if (event.IsEndingEvent()) - return true; - - if (!view_->visible()) - return false; - - // The top-most window can always process an event. - if (!view_->parent()) - return true; - - // In aura, we only accept events if this is a key event or if the user - // supplied a TargetHandler, usually the aura::WindowDelegate. Here, we're - // just forwarding events to other Views which may be in other processes, so - // always accept. - return true; -} - -ui::EventTarget* ViewTarget::GetParentTarget() { - return TargetFromView(view_->parent()); -} - -scoped_ptr<ui::EventTargetIterator> ViewTarget::GetChildIterator() const { - return scoped_ptr<ui::EventTargetIterator>( - new CopyingEventTargetIteratorImpl<ViewTarget>(GetChildren())); -} - -ui::EventTargeter* ViewTarget::GetEventTargeter() { - return targeter_.get(); -} - -void ViewTarget::ConvertEventToTarget(ui::EventTarget* target, - ui::LocatedEvent* event) { - event->ConvertLocationToTarget(this, static_cast<ViewTarget*>(target)); -} - -ViewTarget::ViewTarget(mojo::View* view_to_wrap) : view_(view_to_wrap) { - DCHECK(view_->GetLocalProperty(kViewTargetKey) == nullptr); - view_->SetLocalProperty(kViewTargetKey, this); -} - -bool ViewTarget::ConvertPointForAncestor(const ViewTarget* ancestor, - gfx::Point* point) const { - gfx::Vector2d offset; - bool result = GetTargetOffsetRelativeTo(ancestor, &offset); - *point += offset; - return result; -} - -bool ViewTarget::ConvertPointFromAncestor(const ViewTarget* ancestor, - gfx::Point* point) const { - gfx::Vector2d offset; - bool result = GetTargetOffsetRelativeTo(ancestor, &offset); - *point -= offset; - return result; -} - -bool ViewTarget::GetTargetOffsetRelativeTo(const ViewTarget* ancestor, - gfx::Vector2d* offset) const { - const ViewTarget* v = this; - for (; v && v != ancestor; v = v->GetParent()) { - gfx::Rect bounds = v->GetBounds(); - *offset += gfx::Vector2d(bounds.x(), bounds.y()); - } - return v == ancestor; -} - -} // namespace window_manager
diff --git a/components/window_manager/view_target.h b/components/window_manager/view_target.h deleted file mode 100644 index 5bfa4da..0000000 --- a/components/window_manager/view_target.h +++ /dev/null
@@ -1,100 +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_WINDOW_MANAGER_VIEW_TARGET_H_ -#define COMPONENTS_WINDOW_MANAGER_VIEW_TARGET_H_ - -#include "ui/events/event_target.h" - -namespace gfx { -class Point; -class Rect; -class Vector2d; -} - -namespace ui { -class EventTargeter; -} - -namespace mojo { -class View; -} - -namespace window_manager { - -class TestView; -class ViewTargeter; -class WindowManagerApp; - -// A wrapper class around mojo::View; we can't subclass View to implement the -// event targeting interfaces, so we create a separate object which observes -// the View and ties its lifetime to it. -// -// We set ourselves as a property of the view passed in, and we are owned by -// said View. -class ViewTarget : public ui::EventTarget { - public: - ~ViewTarget() override; - - // Returns the ViewTarget for a View. ViewTargets are owned by the |view| - // passed in, and are created on demand. - static ViewTarget* TargetFromView(mojo::View* view); - - // Converts |point| from |source|'s coordinates to |target|'s. If |source| is - // NULL, the function returns without modifying |point|. |target| cannot be - // NULL. - static void ConvertPointToTarget(const ViewTarget* source, - const ViewTarget* target, - gfx::Point* point); - - mojo::View* view() { return view_; } - - // TODO(erg): Make this const once we've removed aura from the tree and it's - // feasible to change all callers of the EventTargeter interface to pass and - // accept const objects. (When that gets done, re-const the - // EventTargetIterator::GetNextTarget and EventTarget::GetChildIterator - // interfaces.) - std::vector<ViewTarget*> GetChildren() const; - - const ViewTarget* GetParent() const; - gfx::Rect GetBounds() const; - bool HasParent() const; - bool IsVisible() const; - - const ViewTarget* GetRoot() const; - - // Sets a new ViewTargeter for the view, and returns the previous - // ViewTargeter. - scoped_ptr<ViewTargeter> SetEventTargeter(scoped_ptr<ViewTargeter> targeter); - - // Overridden from ui::EventTarget: - bool CanAcceptEvent(const ui::Event& event) override; - EventTarget* GetParentTarget() override; - scoped_ptr<ui::EventTargetIterator> GetChildIterator() const override; - ui::EventTargeter* GetEventTargeter() override; - void ConvertEventToTarget(ui::EventTarget* target, - ui::LocatedEvent* event) override; - - private: - friend class TestView; - explicit ViewTarget(mojo::View* view_to_wrap); - - bool ConvertPointForAncestor(const ViewTarget* ancestor, - gfx::Point* point) const; - bool ConvertPointFromAncestor(const ViewTarget* ancestor, - gfx::Point* point) const; - bool GetTargetOffsetRelativeTo(const ViewTarget* ancestor, - gfx::Vector2d* offset) const; - - // The mojo::View that we dispatch to. - mojo::View* view_; - - scoped_ptr<ViewTargeter> targeter_; - - DISALLOW_COPY_AND_ASSIGN(ViewTarget); -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_VIEW_TARGET_H_
diff --git a/components/window_manager/view_target_unittest.cc b/components/window_manager/view_target_unittest.cc deleted file mode 100644 index 3f334dc..0000000 --- a/components/window_manager/view_target_unittest.cc +++ /dev/null
@@ -1,81 +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/window_manager/view_target.h" - -#include <set> - -#include "components/window_manager/window_manager_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" -#include "ui/gfx/geometry/rect.h" - -namespace window_manager { - -using ViewTargetTest = testing::Test; - -// V1 -// +-- V2 -// +-- V3 -TEST_F(ViewTargetTest, GetRoot) { - TestView v1(1, gfx::Rect(20, 20, 400, 400)); - TestView v2(2, gfx::Rect(10, 10, 350, 350)); - TestView v3(3, gfx::Rect(10, 10, 100, 100)); - v1.AddChild(&v2); - v2.AddChild(&v3); - - EXPECT_EQ(ViewTarget::TargetFromView(&v1), - ViewTarget::TargetFromView(&v1)->GetRoot()); - EXPECT_EQ(ViewTarget::TargetFromView(&v1), - ViewTarget::TargetFromView(&v2)->GetRoot()); - EXPECT_EQ(ViewTarget::TargetFromView(&v1), - ViewTarget::TargetFromView(&v3)->GetRoot()); -} - -// V1 -// +-- V2 -TEST_F(ViewTargetTest, ConvertPointToTarget_Simple) { - TestView v1(1, gfx::Rect(20, 20, 400, 400)); - TestView v2(2, gfx::Rect(10, 10, 350, 350)); - v1.AddChild(&v2); - - ViewTarget* t1 = v1.target(); - ViewTarget* t2 = v2.target(); - - gfx::Point point1_in_t2_coords(5, 5); - ViewTarget::ConvertPointToTarget(t2, t1, &point1_in_t2_coords); - gfx::Point point1_in_t1_coords(15, 15); - EXPECT_EQ(point1_in_t1_coords, point1_in_t2_coords); - - gfx::Point point2_in_t1_coords(5, 5); - ViewTarget::ConvertPointToTarget(t1, t2, &point2_in_t1_coords); - gfx::Point point2_in_t2_coords(-5, -5); - EXPECT_EQ(point2_in_t2_coords, point2_in_t1_coords); -} - -// V1 -// +-- V2 -// +-- V3 -TEST_F(ViewTargetTest, ConvertPointToTarget_Medium) { - TestView v1(1, gfx::Rect(20, 20, 400, 400)); - TestView v2(2, gfx::Rect(10, 10, 350, 350)); - TestView v3(3, gfx::Rect(10, 10, 100, 100)); - v1.AddChild(&v2); - v2.AddChild(&v3); - - ViewTarget* t1 = v1.target(); - ViewTarget* t3 = v3.target(); - - gfx::Point point1_in_t3_coords(5, 5); - ViewTarget::ConvertPointToTarget(t3, t1, &point1_in_t3_coords); - gfx::Point point1_in_t1_coords(25, 25); - EXPECT_EQ(point1_in_t1_coords, point1_in_t3_coords); - - gfx::Point point2_in_t1_coords(5, 5); - ViewTarget::ConvertPointToTarget(t1, t3, &point2_in_t1_coords); - gfx::Point point2_in_t3_coords(-15, -15); - EXPECT_EQ(point2_in_t3_coords, point2_in_t1_coords); -} - -} // namespace window_manager
diff --git a/components/window_manager/view_targeter.cc b/components/window_manager/view_targeter.cc deleted file mode 100644 index 96c8fb9..0000000 --- a/components/window_manager/view_targeter.cc +++ /dev/null
@@ -1,109 +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/window_manager/view_targeter.h" - -#include "components/window_manager/capture_controller.h" -#include "components/window_manager/focus_controller.h" -#include "components/window_manager/view_target.h" - -namespace window_manager { - -ViewTargeter::ViewTargeter() {} - -ViewTargeter::~ViewTargeter() {} - -ui::EventTarget* ViewTargeter::FindTargetForEvent(ui::EventTarget* root, - ui::Event* event) { - ViewTarget* view = static_cast<ViewTarget*>(root); - ViewTarget* target = - event->IsKeyEvent() - ? FindTargetForKeyEvent(view, *static_cast<ui::KeyEvent*>(event)) - : static_cast<ViewTarget*>( - EventTargeter::FindTargetForEvent(root, event)); - - // TODO(erg): The aura version of this method does a lot of work to handle - // dispatching to a target that isn't a child of |view|. For now, punt on - // this. - DCHECK_EQ(view->GetRoot(), target->GetRoot()); - - return target; -} - -ui::EventTarget* ViewTargeter::FindTargetForLocatedEvent( - ui::EventTarget* root, - ui::LocatedEvent* event) { - ViewTarget* view = static_cast<ViewTarget*>(root); - if (!view->HasParent()) { - ViewTarget* target = FindTargetInRootView(view, *event); - if (target) { - view->ConvertEventToTarget(target, event); - return target; - } - } - return EventTargeter::FindTargetForLocatedEvent(view, event); -} - -bool ViewTargeter::SubtreeCanAcceptEvent(ui::EventTarget* target, - const ui::LocatedEvent& event) const { - ViewTarget* view = static_cast<ViewTarget*>(target); - - if (!view->IsVisible()) - return false; - - // TODO(erg): We may need to keep track of the parent on ViewTarget, because - // we have a check here about - // WindowDelegate::ShouldDescendIntoChildForEventHandling(). - - // TODO(sky): decide if we really want this. If we do, it should be a public - // constant and documented. - if (view->view()->shared_properties().count("deliver-events-to-parent")) - return false; - - return true; -} - -bool ViewTargeter::EventLocationInsideBounds( - ui::EventTarget* target, - const ui::LocatedEvent& event) const { - ViewTarget* view = static_cast<ViewTarget*>(target); - gfx::Point point = event.location(); - const ViewTarget* parent = view->GetParent(); - if (parent) - ViewTarget::ConvertPointToTarget(parent, view, &point); - return gfx::Rect(view->GetBounds().size()).Contains(point); -} - -ViewTarget* ViewTargeter::FindTargetForKeyEvent(ViewTarget* view_target, - const ui::KeyEvent& key) { - FocusController* focus_controller = GetFocusController(view_target->view()); - if (focus_controller) { - mojo::View* focused_view = focus_controller->GetFocusedView(); - if (focused_view) - return ViewTarget::TargetFromView(focused_view); - } - return view_target; -} - -ViewTarget* ViewTargeter::FindTargetInRootView(ViewTarget* root_view, - const ui::LocatedEvent& event) { - // TODO(erg): This here is important because it resolves - // mouse_pressed_handler() in the aura version. This is what makes sure - // that a view gets both the mouse down and up. - - CaptureController* capture_controller = - GetCaptureController(root_view->view()); - if (capture_controller) { - mojo::View* capture_view = capture_controller->GetCapture(); - if (capture_view) - return ViewTarget::TargetFromView(capture_view); - } - - // TODO(erg): There's a whole bunch of junk about handling touch events - // here. Handle later. - - return nullptr; -} - -} // namespace window_manager
diff --git a/components/window_manager/view_targeter.h b/components/window_manager/view_targeter.h deleted file mode 100644 index 75ca1de..0000000 --- a/components/window_manager/view_targeter.h +++ /dev/null
@@ -1,44 +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_WINDOW_MANAGER_VIEW_TARGETER_H_ -#define COMPONENTS_WINDOW_MANAGER_VIEW_TARGETER_H_ - -#include "ui/events/event_targeter.h" - -namespace window_manager { - -class ViewTarget; - -class ViewTargeter : public ui::EventTargeter { - public: - ViewTargeter(); - ~ViewTargeter() override; - - protected: - // ui::EventTargeter: - ui::EventTarget* FindTargetForEvent(ui::EventTarget* root, - ui::Event* event) override; - ui::EventTarget* FindTargetForLocatedEvent(ui::EventTarget* root, - ui::LocatedEvent* event) override; - bool SubtreeCanAcceptEvent(ui::EventTarget* target, - const ui::LocatedEvent& event) const override; - bool EventLocationInsideBounds(ui::EventTarget* target, - const ui::LocatedEvent& event) const override; - - private: - // Targets either the root View or the currently focused view. - ViewTarget* FindTargetForKeyEvent(ViewTarget* view, const ui::KeyEvent& key); - - // Deals with cases where the |root_view| needs to change how things are - // dispatched. (For example, in the case of capture.) - ViewTarget* FindTargetInRootView(ViewTarget* root_view, - const ui::LocatedEvent& event); - - DISALLOW_COPY_AND_ASSIGN(ViewTargeter); -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_VIEW_TARGETER_H_
diff --git a/components/window_manager/view_targeter_unittest.cc b/components/window_manager/view_targeter_unittest.cc deleted file mode 100644 index 12a36d0..0000000 --- a/components/window_manager/view_targeter_unittest.cc +++ /dev/null
@@ -1,114 +0,0 @@ -// Copyright (c) 2013 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/window_manager/view_targeter.h" - -#include "components/window_manager/basic_focus_rules.h" -#include "components/window_manager/capture_controller.h" -#include "components/window_manager/focus_controller.h" -#include "components/window_manager/view_event_dispatcher.h" -#include "components/window_manager/window_manager_test_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/events/event_utils.h" -#include "ui/events/test/test_event_handler.h" - -namespace window_manager { - -class ViewTargeterTest : public testing::Test { - public: - ViewTargeterTest() {} - ~ViewTargeterTest() override {} - - void SetUp() override { - view_event_dispatcher_.reset(new ViewEventDispatcher()); - } - - void TearDown() override { - view_event_dispatcher_.reset(); - testing::Test::TearDown(); - } - - protected: - scoped_ptr<ViewEventDispatcher> view_event_dispatcher_; - - private: - DISALLOW_COPY_AND_ASSIGN(ViewTargeterTest); -}; - -TEST_F(ViewTargeterTest, Basic) { - // The dispatcher will take ownership of the tree root. - TestView root(1, gfx::Rect(0, 0, 100, 100)); - ViewTarget* root_target = root.target(); - root_target->SetEventTargeter(scoped_ptr<ViewTargeter>(new ViewTargeter())); - view_event_dispatcher_->SetRootViewTarget(root_target); - - CaptureController capture_controller; - SetCaptureController(&root, &capture_controller); - - TestView one(2, gfx::Rect(0, 0, 500, 100)); - TestView two(3, gfx::Rect(501, 0, 500, 1000)); - - root.AddChild(&one); - root.AddChild(&two); - - ui::test::TestEventHandler handler; - one.target()->AddPreTargetHandler(&handler); - - ui::MouseEvent press(ui::ET_MOUSE_PRESSED, gfx::Point(20, 20), - gfx::Point(20, 20), ui::EventTimeForNow(), ui::EF_NONE, - ui::EF_NONE); - ui::EventDispatchDetails details = - view_event_dispatcher_->OnEventFromSource(&press); - ASSERT_FALSE(details.dispatcher_destroyed); - - EXPECT_EQ(1, handler.num_mouse_events()); - - one.target()->RemovePreTargetHandler(&handler); -} - -TEST_F(ViewTargeterTest, KeyTest) { - // The dispatcher will take ownership of the tree root. - TestView root(1, gfx::Rect(0, 0, 100, 100)); - ViewTarget* root_target = root.target(); - root_target->SetEventTargeter(scoped_ptr<ViewTargeter>(new ViewTargeter())); - view_event_dispatcher_->SetRootViewTarget(root_target); - - CaptureController capture_controller; - SetCaptureController(&root, &capture_controller); - - TestView one(2, gfx::Rect(0, 0, 500, 100)); - TestView two(3, gfx::Rect(501, 0, 500, 1000)); - - root.AddChild(&one); - root.AddChild(&two); - - ui::test::TestEventHandler one_handler; - one.target()->AddPreTargetHandler(&one_handler); - - ui::test::TestEventHandler two_handler; - two.target()->AddPreTargetHandler(&two_handler); - - FocusController focus_controller(make_scoped_ptr(new BasicFocusRules(&root))); - SetFocusController(&root, &focus_controller); - - // Focus |one|. Then test that it receives a key event. - focus_controller.FocusView(&one); - ui::KeyEvent key_event_one(ui::ET_KEY_PRESSED, ui::VKEY_A, 0); - ui::EventDispatchDetails details = - view_event_dispatcher_->OnEventFromSource(&key_event_one); - ASSERT_FALSE(details.dispatcher_destroyed); - EXPECT_EQ(1, one_handler.num_key_events()); - - // Focus |two|. Then test that it receives a key event. - focus_controller.FocusView(&two); - ui::KeyEvent key_event_two(ui::ET_KEY_PRESSED, ui::VKEY_A, 0); - details = view_event_dispatcher_->OnEventFromSource(&key_event_two); - ASSERT_FALSE(details.dispatcher_destroyed); - EXPECT_EQ(1, two_handler.num_key_events()); - - two.target()->RemovePreTargetHandler(&two_handler); - one.target()->RemovePreTargetHandler(&one_handler); -} - -} // namespace window_manager
diff --git a/components/window_manager/window_manager_app.cc b/components/window_manager/window_manager_app.cc index 3c3668f..da40ef77 100644 --- a/components/window_manager/window_manager_app.cc +++ b/components/window_manager/window_manager_app.cc
@@ -6,21 +6,13 @@ #include "base/message_loop/message_loop.h" #include "base/stl_util.h" -#include "components/window_manager/capture_controller.h" -#include "components/window_manager/focus_controller.h" -#include "components/window_manager/focus_rules.h" -#include "components/window_manager/hit_test.h" -#include "components/window_manager/view_event_dispatcher.h" -#include "components/window_manager/view_target.h" -#include "components/window_manager/view_targeter.h" +#include "components/view_manager/public/cpp/view.h" +#include "components/view_manager/public/cpp/view_manager.h" #include "components/window_manager/window_manager_delegate.h" #include "mojo/converters/geometry/geometry_type_converters.h" -#include "mojo/converters/input_events/input_events_type_converters.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_connection.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" #include "third_party/mojo/src/mojo/public/interfaces/application/shell.mojom.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager.h" using mojo::ApplicationConnection; using mojo::Id; @@ -30,14 +22,6 @@ namespace window_manager { -namespace { - -Id GetIdForView(View* view) { - return view ? view->id() : 0; -} - -} // namespace - // Used for calls to Embed() that occur before we've connected to the // ViewManager. struct WindowManagerApp::PendingEmbed { @@ -60,17 +44,8 @@ WindowManagerApp::~WindowManagerApp() { // TODO(msw|sky): Should this destructor explicitly delete the ViewManager? - mojo::ViewManager* cached_view_manager = view_manager(); - for (RegisteredViewIdSet::const_iterator it = registered_view_id_set_.begin(); - cached_view_manager && it != registered_view_id_set_.end(); ++it) { - View* view = cached_view_manager->GetViewById(*it); - if (view && view == root_) - root_ = nullptr; - if (view) - view->RemoveObserver(this); - } - registered_view_id_set_.clear(); - DCHECK(!root_); + if (root_) + root_->RemoveObserver(this); STLDeleteElements(&connections_); } @@ -85,35 +60,13 @@ connections_.erase(connection); } -bool WindowManagerApp::SetCapture(Id view_id) { - View* view = view_manager()->GetViewById(view_id); - return view && SetCaptureImpl(view); -} - -bool WindowManagerApp::FocusWindow(Id view_id) { - View* view = view_manager()->GetViewById(view_id); - return view && FocusWindowImpl(view); -} - -bool WindowManagerApp::ActivateWindow(Id view_id) { - View* view = view_manager()->GetViewById(view_id); - return view && ActivateWindowImpl(view); -} - bool WindowManagerApp::IsReady() const { return !!root_; } -void WindowManagerApp::InitFocus(scoped_ptr<FocusRules> rules) { - DCHECK(root_); - - focus_controller_.reset(new FocusController(rules.Pass())); - focus_controller_->AddObserver(this); - SetFocusController(root_, focus_controller_.get()); - - capture_controller_.reset(new CaptureController); - capture_controller_->AddObserver(this); - SetCaptureController(root_, capture_controller_.get()); +void WindowManagerApp::AddAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) { + window_manager_client_->AddAccelerator(keyboard_code, flags); } void WindowManagerApp::Embed( @@ -156,9 +109,7 @@ DCHECK(!root_); root_ = root; - view_event_dispatcher_.reset(new ViewEventDispatcher); - - RegisterSubtree(root_); + root_->AddObserver(this); if (wrapped_view_manager_delegate_) { wrapped_view_manager_delegate_->OnEmbed(root, services.Pass(), @@ -182,172 +133,23 @@ message_loop->Quit(); } -bool WindowManagerApp::OnPerformAction(mojo::View* view, - const std::string& action) { - if (!view) - return false; - if (action == "capture") - return SetCaptureImpl(view); - if (action == "focus") - return FocusWindowImpl(view); - else if (action == "activate") - return ActivateWindowImpl(view); - return false; -} - //////////////////////////////////////////////////////////////////////////////// // WindowManagerApp, ViewObserver implementation: -void WindowManagerApp::OnTreeChanged( - const ViewObserver::TreeChangeParams& params) { - if (params.receiver != root_) - return; - DCHECK(params.old_parent || params.new_parent); - if (!params.target) - return; - - if (params.new_parent) { - if (registered_view_id_set_.find(params.target->id()) == - registered_view_id_set_.end()) { - RegisteredViewIdSet::const_iterator it = - registered_view_id_set_.find(params.new_parent->id()); - DCHECK(it != registered_view_id_set_.end()); - RegisterSubtree(params.target); - } - } else if (params.old_parent) { - UnregisterSubtree(params.target); - } -} - void WindowManagerApp::OnViewDestroying(View* view) { - Unregister(view); - if (view == root_) { - root_ = nullptr; - if (focus_controller_) - focus_controller_->RemoveObserver(this); - if (capture_controller_) - capture_controller_->RemoveObserver(this); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// WindowManagerApp, ui::EventHandler implementation: - -void WindowManagerApp::OnEvent(ui::Event* event) { - if (!window_manager_client_) - return; - - View* view = static_cast<ViewTarget*>(event->target())->view(); - if (!view) - return; - - if (event->IsKeyEvent()) { - const ui::KeyEvent* key_event = static_cast<const ui::KeyEvent*>(event); - if (key_event->type() == ui::ET_KEY_PRESSED) { - ui::Accelerator accelerator = ConvertEventToAccelerator(key_event); - if (accelerator_manager_.Process(accelerator)) - return; - } - } - - if (focus_controller_) - focus_controller_->OnEvent(event); - - window_manager_client_->DispatchInputEventToView(view->id(), - mojo::Event::From(*event)); -} - -//////////////////////////////////////////////////////////////////////////////// -// WindowManagerApp, mojo::FocusControllerObserver implementation: - -void WindowManagerApp::OnFocused(View* gained_focus) { - for (Connections::const_iterator it = connections_.begin(); - it != connections_.end(); ++it) { - (*it)->NotifyViewFocused(GetIdForView(gained_focus)); - } -} - -void WindowManagerApp::OnActivated(View* gained_active) { - for (Connections::const_iterator it = connections_.begin(); - it != connections_.end(); ++it) { - (*it)->NotifyWindowActivated(GetIdForView(gained_active)); - } - if (gained_active) - gained_active->MoveToFront(); -} - -//////////////////////////////////////////////////////////////////////////////// -// WindowManagerApp, mojo::CaptureControllerObserver implementation: - -void WindowManagerApp::OnCaptureChanged(View* gained_capture) { - for (Connections::const_iterator it = connections_.begin(); - it != connections_.end(); ++it) { - (*it)->NotifyCaptureChanged(GetIdForView(gained_capture)); - } - if (gained_capture) - gained_capture->MoveToFront(); + DCHECK_EQ(root_, view); + root_->RemoveObserver(this); + root_ = nullptr; } //////////////////////////////////////////////////////////////////////////////// // WindowManagerApp, private: -bool WindowManagerApp::SetCaptureImpl(View* view) { - CHECK(view); - capture_controller_->SetCapture(view); - return capture_controller_->GetCapture() == view; -} - -bool WindowManagerApp::FocusWindowImpl(View* view) { - CHECK(view); - focus_controller_->FocusView(view); - return focus_controller_->GetFocusedView() == view; -} - -bool WindowManagerApp::ActivateWindowImpl(View* view) { - CHECK(view); - focus_controller_->ActivateView(view); - return focus_controller_->GetActiveView() == view; -} - -void WindowManagerApp::RegisterSubtree(View* view) { - view->AddObserver(this); - DCHECK(registered_view_id_set_.find(view->id()) == - registered_view_id_set_.end()); - // All events pass through the root during dispatch, so we only need a handler - // installed there. - if (view == root_) { - ViewTarget* target = ViewTarget::TargetFromView(view); - target->SetEventTargeter(scoped_ptr<ViewTargeter>(new ViewTargeter())); - target->AddPreTargetHandler(this); - view_event_dispatcher_->SetRootViewTarget(target); - } - registered_view_id_set_.insert(view->id()); - View::Children::const_iterator it = view->children().begin(); - for (; it != view->children().end(); ++it) - RegisterSubtree(*it); -} - -void WindowManagerApp::UnregisterSubtree(View* view) { - for (View* child : view->children()) - UnregisterSubtree(child); - Unregister(view); -} - -void WindowManagerApp::Unregister(View* view) { - RegisteredViewIdSet::iterator it = registered_view_id_set_.find(view->id()); - if (it == registered_view_id_set_.end()) { - // Because we unregister in OnViewDestroying() we can still get a subsequent - // OnTreeChanged for the same view. Ignore this one. - return; - } - view->RemoveObserver(this); - DCHECK(it != registered_view_id_set_.end()); - registered_view_id_set_.erase(it); -} - -void WindowManagerApp::DispatchInputEventToView(View* view, - mojo::EventPtr event) { - window_manager_client_->DispatchInputEventToView(view->id(), event.Pass()); +void WindowManagerApp::DispatchInputEventToViewDEPRECATED( + View* view, + mojo::EventPtr event) { + window_manager_client_->DispatchInputEventToViewDEPRECATED(view->id(), + event.Pass()); } void WindowManagerApp::SetViewportSize(const gfx::Size& size) { @@ -364,7 +166,6 @@ view_manager_app->ConnectToService(&view_manager_service_); view_manager_app->AddService<WindowManagerInternal>(this); - view_manager_app->AddService<mojo::NativeViewportEventDispatcher>(this); view_manager_app->ConnectToService(&window_manager_client_); } @@ -389,22 +190,6 @@ // destructor. } -void WindowManagerApp::Create( - mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<mojo::NativeViewportEventDispatcher> request) { - new NativeViewportEventDispatcherImpl(this, request.Pass()); -} - -void WindowManagerApp::CreateWindowManagerForViewManagerClient( - uint16_t connection_id, - mojo::ScopedMessagePipeHandle window_manager_pipe) { - // TODO(sky): pass in |connection_id| for validation. - WindowManagerImpl* wm = new WindowManagerImpl(this, true); - wm->Bind(window_manager_pipe.Pass()); - // WindowManagerImpl is deleted when the connection has an error, or from our - // destructor. -} - void WindowManagerApp::SetViewManagerClient( mojo::ScopedMessagePipeHandle view_manager_client_request) { view_manager_client_.reset( @@ -414,4 +199,10 @@ view_manager_service_.Pass(), shell_, this)); } +void WindowManagerApp::OnAccelerator(mojo::EventPtr event) { + window_manager_delegate_->OnAcceleratorPressed( + root_->view_manager()->GetFocusedView(), + event->key_data->windows_key_code, event->flags); +} + } // namespace window_manager
diff --git a/components/window_manager/window_manager_app.h b/components/window_manager/window_manager_app.h index ff81f3d7..81a2e4633b 100644 --- a/components/window_manager/window_manager_app.h +++ b/components/window_manager/window_manager_app.h
@@ -9,22 +9,18 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" -#include "components/window_manager/capture_controller_observer.h" -#include "components/window_manager/focus_controller_observer.h" -#include "components/window_manager/native_viewport_event_dispatcher_impl.h" -#include "components/window_manager/view_target.h" +#include "components/view_manager/public/cpp/types.h" +#include "components/view_manager/public/cpp/view_manager_client_factory.h" +#include "components/view_manager/public/cpp/view_manager_delegate.h" +#include "components/view_manager/public/cpp/view_observer.h" +#include "components/window_manager/public/interfaces/window_manager_internal.mojom.h" #include "components/window_manager/window_manager_impl.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/interface_factory_impl.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/string.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/types.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_observer.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom.h" -#include "ui/base/accelerators/accelerator_manager.h" -#include "ui/events/event_handler.h" +#include "ui/mojo/events/input_events.mojom.h" +#include "ui/mojo/events/input_key_codes.mojom.h" namespace gfx { class Size; @@ -32,10 +28,6 @@ namespace window_manager { -class CaptureController; -class FocusController; -class FocusRules; -class ViewEventDispatcher; class WindowManagerDelegate; class WindowManagerImpl; @@ -51,44 +43,27 @@ : public mojo::ApplicationDelegate, public mojo::ViewManagerDelegate, public mojo::ViewObserver, - public ui::EventHandler, - public FocusControllerObserver, - public CaptureControllerObserver, public mojo::InterfaceFactory<mojo::WindowManager>, public mojo::InterfaceFactory<mojo::WindowManagerInternal>, - public mojo::InterfaceFactory<mojo::NativeViewportEventDispatcher>, public mojo::WindowManagerInternal { public: WindowManagerApp(ViewManagerDelegate* view_manager_delegate, WindowManagerDelegate* window_manager_delegate); ~WindowManagerApp() override; - ViewEventDispatcher* event_dispatcher() { - return view_event_dispatcher_.get(); - } - // Register/deregister new connections to the window manager service. void AddConnection(WindowManagerImpl* connection); void RemoveConnection(WindowManagerImpl* connection); - // These are canonical implementations of the window manager API methods. - bool SetCapture(mojo::Id view); - bool FocusWindow(mojo::Id view); - bool ActivateWindow(mojo::Id view); - - void DispatchInputEventToView(mojo::View* view, mojo::EventPtr event); + void DispatchInputEventToViewDEPRECATED(mojo::View* view, + mojo::EventPtr event); void SetViewportSize(const gfx::Size& size); bool IsReady() const; - FocusController* focus_controller() { return focus_controller_.get(); } - CaptureController* capture_controller() { return capture_controller_.get(); } - - void InitFocus(scoped_ptr<FocusRules> rules); - - ui::AcceleratorManager* accelerator_manager() { - return &accelerator_manager_; - } + void AddAccelerator(mojo::KeyboardCode keyboard_code, mojo::EventFlags flags); + void RemoveAccelerator(mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags); // WindowManagerImpl::Embed() forwards to this. If connected to ViewManager // then forwards to delegate, otherwise waits for connection to establish then @@ -105,55 +80,22 @@ private: // TODO(sky): rename this. Connections is ambiguous. typedef std::set<WindowManagerImpl*> Connections; - typedef std::set<mojo::Id> RegisteredViewIdSet; struct PendingEmbed; - class WindowManagerInternalImpl; mojo::ViewManager* view_manager() { return root_ ? root_->view_manager() : nullptr; } - bool SetCaptureImpl(mojo::View* view); - bool FocusWindowImpl(mojo::View* view); - bool ActivateWindowImpl(mojo::View* view); - - ui::Accelerator ConvertEventToAccelerator(const ui::KeyEvent* event); - - // Creates an ViewTarget for every view in the hierarchy beneath |view|, - // and adds to the registry so that it can be retrieved later via - // GetViewTargetForViewId(). - // TODO(beng): perhaps View should have a property bag. - void RegisterSubtree(mojo::View* view); - - // Recursively invokes Unregister() for |view| and all its descendants. - void UnregisterSubtree(mojo::View* view); - - // Deletes the ViewTarget associated with the hierarchy beneath |id|, - // and removes from the registry. - void Unregister(mojo::View* view); - // Overridden from ViewManagerDelegate: void OnEmbed(mojo::View* root, mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::ServiceProviderPtr exposed_services) override; void OnViewManagerDisconnected(mojo::ViewManager* view_manager) override; - bool OnPerformAction(mojo::View* view, const std::string& action) override; // Overridden from ViewObserver: - void OnTreeChanged(const ViewObserver::TreeChangeParams& params) override; void OnViewDestroying(mojo::View* view) override; - // Overridden from ui::EventHandler: - void OnEvent(ui::Event* event) override; - - // Overridden from mojo::FocusControllerObserver: - void OnFocused(mojo::View* gained_focus) override; - void OnActivated(mojo::View* gained_active) override; - - // Overridden from mojo::CaptureControllerObserver: - void OnCaptureChanged(mojo::View* gained_capture) override; - // Creates the connection to the ViewManager. void LaunchViewManager(mojo::ApplicationImpl* app); @@ -166,17 +108,10 @@ void Create(mojo::ApplicationConnection* connection, mojo::InterfaceRequest<mojo::WindowManager> request) override; - // InterfaceFactory<NativeViewportEventDispatcher>: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<mojo::NativeViewportEventDispatcher> - request) override; - // WindowManagerInternal: - void CreateWindowManagerForViewManagerClient( - uint16_t connection_id, - mojo::ScopedMessagePipeHandle window_manager_pipe) override; void SetViewManagerClient( mojo::ScopedMessagePipeHandle view_manager_client_request) override; + void OnAccelerator(mojo::EventPtr event) override; mojo::Shell* shell_; @@ -185,15 +120,10 @@ mojo::ViewManagerServicePtr view_manager_service_; scoped_ptr<mojo::ViewManagerClientFactory> view_manager_client_factory_; + mojo::View* root_; - scoped_ptr<FocusController> focus_controller_; - scoped_ptr<CaptureController> capture_controller_; - - ui::AcceleratorManager accelerator_manager_; - Connections connections_; - RegisteredViewIdSet registered_view_id_set_; mojo::WindowManagerInternalClientPtr window_manager_client_; @@ -201,8 +131,6 @@ scoped_ptr<mojo::ViewManagerClient> view_manager_client_; - scoped_ptr<ViewEventDispatcher> view_event_dispatcher_; - scoped_ptr<mojo::Binding<WindowManagerInternal>> wm_internal_binding_; DISALLOW_COPY_AND_ASSIGN(WindowManagerApp);
diff --git a/components/window_manager/window_manager_app_android.cc b/components/window_manager/window_manager_app_android.cc deleted file mode 100644 index 3ec92c3..0000000 --- a/components/window_manager/window_manager_app_android.cc +++ /dev/null
@@ -1,20 +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 "components/window_manager/window_manager_app.h" - -#include <android/keycodes.h> - -#include "ui/events/keycodes/keyboard_codes_posix.h" - -namespace window_manager { - -ui::Accelerator WindowManagerApp::ConvertEventToAccelerator( - const ui::KeyEvent* event) { - if (event->platform_keycode() == AKEYCODE_BACK) - return ui::Accelerator(ui::VKEY_BROWSER_BACK, 0); - return ui::Accelerator(event->key_code(), event->flags()); -} - -} // namespace window_manager
diff --git a/components/window_manager/window_manager_app_linux.cc b/components/window_manager/window_manager_app_linux.cc deleted file mode 100644 index effb54c..0000000 --- a/components/window_manager/window_manager_app_linux.cc +++ /dev/null
@@ -1,14 +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 "components/window_manager/window_manager_app.h" - -namespace window_manager { - -ui::Accelerator WindowManagerApp::ConvertEventToAccelerator( - const ui::KeyEvent* event) { - return ui::Accelerator(event->key_code(), event->flags()); -} - -} // namespace window_manager
diff --git a/components/window_manager/window_manager_app_win.cc b/components/window_manager/window_manager_app_win.cc deleted file mode 100644 index effb54c..0000000 --- a/components/window_manager/window_manager_app_win.cc +++ /dev/null
@@ -1,14 +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 "components/window_manager/window_manager_app.h" - -namespace window_manager { - -ui::Accelerator WindowManagerApp::ConvertEventToAccelerator( - const ui::KeyEvent* event) { - return ui::Accelerator(event->key_code(), event->flags()); -} - -} // namespace window_manager
diff --git a/components/window_manager/window_manager_apptest.cc b/components/window_manager/window_manager_apptest.cc index 41164f2..f7915fdc 100644 --- a/components/window_manager/window_manager_apptest.cc +++ b/components/window_manager/window_manager_apptest.cc
@@ -4,15 +4,15 @@ #include "base/bind.h" #include "base/run_loop.h" +#include "components/view_manager/public/cpp/view.h" +#include "components/view_manager/public/cpp/view_manager_client_factory.h" +#include "components/view_manager/public/cpp/view_manager_delegate.h" +#include "components/window_manager/public/interfaces/window_manager.mojom.h" #include "mojo/application/application_test_base_chromium.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" #include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" #include "third_party/mojo/src/mojo/public/cpp/application/service_provider_impl.h" #include "third_party/mojo/src/mojo/public/cpp/system/macros.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager.mojom.h" namespace mojo { namespace { @@ -57,24 +57,6 @@ MOJO_DISALLOW_COPY_AND_ASSIGN(TestApplication); }; -class TestWindowManagerObserver : public WindowManagerObserver { - public: - explicit TestWindowManagerObserver( - InterfaceRequest<WindowManagerObserver> observer_request) - : binding_(this, observer_request.Pass()) {} - ~TestWindowManagerObserver() override {} - - private: - // Overridden from WindowManagerClient: - void OnCaptureChanged(Id new_capture_node_id) override {} - void OnFocusChanged(Id focused_node_id) override {} - void OnActiveWindowChanged(Id active_window) override {} - - Binding<WindowManagerObserver> binding_; - - DISALLOW_COPY_AND_ASSIGN(TestWindowManagerObserver); -}; - class WindowManagerApplicationTest : public test::ApplicationTestBase { public: WindowManagerApplicationTest() {} @@ -112,101 +94,5 @@ EXPECT_NE(nullptr, test_application_.root()); } -struct BoolCallback { - BoolCallback(bool* bool_value, base::RunLoop* run_loop) - : bool_value(bool_value), run_loop(run_loop) {} - - void Run(bool value) const { - *bool_value = value; - run_loop->Quit(); - } - - bool* bool_value; - base::RunLoop* run_loop; -}; - -TEST_F(WindowManagerApplicationTest, SetCaptureFailsFromNonVM) { - EmbedApplicationWithURL(application_impl()->url()); - bool callback_value = true; - base::RunLoop run_loop; - window_manager_->SetCapture(test_application_.root()->id(), - BoolCallback(&callback_value, &run_loop)); - run_loop.Run(); - // This call only succeeds for WindowManager connections from the ViewManager. - EXPECT_FALSE(callback_value); -} - -TEST_F(WindowManagerApplicationTest, FocusWindowFailsFromNonVM) { - EmbedApplicationWithURL(application_impl()->url()); - bool callback_value = true; - base::RunLoop run_loop; - window_manager_->FocusWindow(test_application_.root()->id(), - BoolCallback(&callback_value, &run_loop)); - run_loop.Run(); - // This call only succeeds for WindowManager connections from the ViewManager. - EXPECT_FALSE(callback_value); -} - -TEST_F(WindowManagerApplicationTest, ActivateWindowFailsFromNonVM) { - EmbedApplicationWithURL(application_impl()->url()); - bool callback_value = true; - base::RunLoop run_loop; - window_manager_->ActivateWindow(test_application_.root()->id(), - BoolCallback(&callback_value, &run_loop)); - run_loop.Run(); - // This call only succeeds for WindowManager connections from the ViewManager. - EXPECT_FALSE(callback_value); -} - -struct FocusedAndActiveViewsCallback { - FocusedAndActiveViewsCallback(uint32* capture_view_id, - uint32* focused_view_id, - uint32* active_view_id, - base::RunLoop* run_loop) - : capture_view_id(capture_view_id), - focused_view_id(focused_view_id), - active_view_id(active_view_id), - run_loop(run_loop) { - } - - void Run(uint32 capture, uint32 focused, uint32 active) const { - *capture_view_id = capture; - *focused_view_id = focused; - *active_view_id = active; - run_loop->Quit(); - } - - uint32* capture_view_id; - uint32* focused_view_id; - uint32* active_view_id; - base::RunLoop* run_loop; -}; - -TEST_F(WindowManagerApplicationTest, GetFocusedAndActiveViewsFailsWithoutFC) { - EmbedApplicationWithURL(application_impl()->url()); - uint32 capture_view_id = static_cast<uint32>(-1); - uint32 focused_view_id = static_cast<uint32>(-1); - uint32 active_view_id = static_cast<uint32>(-1); - base::RunLoop run_loop; - - WindowManagerObserverPtr observer; - scoped_ptr<TestWindowManagerObserver> window_manager_observer( - new TestWindowManagerObserver(GetProxy(&observer))); - - window_manager_->GetFocusedAndActiveViews( - observer.Pass(), - FocusedAndActiveViewsCallback(&capture_view_id, - &focused_view_id, - &active_view_id, - &run_loop)); - run_loop.Run(); - // This call fails if the WindowManager does not have a FocusController. - EXPECT_EQ(0u, capture_view_id); - EXPECT_EQ(0u, focused_view_id); - EXPECT_EQ(0u, active_view_id); -} - -// TODO(msw): Write tests exercising other WindowManager functionality. - } // namespace } // namespace mojo
diff --git a/components/window_manager/window_manager_delegate.h b/components/window_manager/window_manager_delegate.h index bbfeefe5..71e154c 100644 --- a/components/window_manager/window_manager_delegate.h +++ b/components/window_manager/window_manager_delegate.h
@@ -7,6 +7,8 @@ #include "third_party/mojo/src/mojo/public/cpp/bindings/string.h" #include "third_party/mojo/src/mojo/public/interfaces/application/service_provider.mojom.h" +#include "ui/mojo/events/input_events.mojom.h" +#include "ui/mojo/events/input_key_codes.mojom.h" namespace window_manager { @@ -17,6 +19,10 @@ mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::ServiceProviderPtr exposed_services) = 0; + virtual void OnAcceleratorPressed(mojo::View* view, + mojo::KeyboardCode keyboard_code, + mojo::EventFlags flags) {} + protected: virtual ~WindowManagerDelegate() {} };
diff --git a/components/window_manager/window_manager_impl.cc b/components/window_manager/window_manager_impl.cc index 4a218d9..9e0a1658 100644 --- a/components/window_manager/window_manager_impl.cc +++ b/components/window_manager/window_manager_impl.cc
@@ -4,13 +4,7 @@ #include "components/window_manager/window_manager_impl.h" -#include "components/window_manager/capture_controller.h" -#include "components/window_manager/focus_controller.h" #include "components/window_manager/window_manager_app.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" - -using mojo::Callback; -using mojo::Id; namespace window_manager { @@ -30,21 +24,6 @@ binding_.Bind(window_manager_pipe.Pass()); } -void WindowManagerImpl::NotifyViewFocused(Id focused_id) { - if (from_vm_ && observer_) - observer_->OnFocusChanged(focused_id); -} - -void WindowManagerImpl::NotifyWindowActivated(Id active_id) { - if (from_vm_ && observer_) - observer_->OnActiveWindowChanged(active_id); -} - -void WindowManagerImpl::NotifyCaptureChanged(Id capture_id) { - if (from_vm_ && observer_) - observer_->OnCaptureChanged(capture_id); -} - void WindowManagerImpl::Embed( const mojo::String& url, mojo::InterfaceRequest<mojo::ServiceProvider> services, @@ -52,45 +31,6 @@ window_manager_->Embed(url, services.Pass(), exposed_services.Pass()); } -void WindowManagerImpl::SetCapture(Id view, - const Callback<void(bool)>& callback) { - callback.Run(from_vm_ && window_manager_->IsReady() && - window_manager_->SetCapture(view)); -} - -void WindowManagerImpl::FocusWindow(Id view, - const Callback<void(bool)>& callback) { - callback.Run(from_vm_ && window_manager_->IsReady() && - window_manager_->FocusWindow(view)); -} - -void WindowManagerImpl::ActivateWindow(Id view, - const Callback<void(bool)>& callback) { - callback.Run(from_vm_ && window_manager_->IsReady() && - window_manager_->ActivateWindow(view)); -} - -void WindowManagerImpl::GetFocusedAndActiveViews( - mojo::WindowManagerObserverPtr observer, - const mojo::WindowManager::GetFocusedAndActiveViewsCallback& callback) { - observer_ = observer.Pass(); - if (!window_manager_->focus_controller()) { - // TODO(sky): add typedef for 0. - callback.Run(0, 0, 0); - return; - } - mojo::View* capture_view = - window_manager_->capture_controller()->GetCapture(); - mojo::View* active_view = - window_manager_->focus_controller()->GetActiveView(); - mojo::View* focused_view = - window_manager_->focus_controller()->GetFocusedView(); - // TODO(sky): sanitize ids for client. - callback.Run(capture_view ? capture_view->id() : 0, - focused_view ? focused_view->id() : 0, - active_view ? active_view->id() : 0); -} - void WindowManagerImpl::OnConnectionError() { delete this; }
diff --git a/components/window_manager/window_manager_impl.h b/components/window_manager/window_manager_impl.h index c6c5a17..0ee6f88 100644 --- a/components/window_manager/window_manager_impl.h +++ b/components/window_manager/window_manager_impl.h
@@ -7,10 +7,10 @@ #include "base/basictypes.h" #include "base/logging.h" +#include "components/view_manager/public/cpp/types.h" +#include "components/window_manager/public/interfaces/window_manager.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/error_handler.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/types.h" -#include "third_party/mojo_services/src/window_manager/public/interfaces/window_manager.mojom.h" namespace window_manager { @@ -27,25 +27,11 @@ void Bind(mojo::ScopedMessagePipeHandle window_manager_pipe); - void NotifyViewFocused(mojo::Id focused_id); - void NotifyWindowActivated(mojo::Id active_id); - void NotifyCaptureChanged(mojo::Id capture_id); - private: // mojo::WindowManager: void Embed(const mojo::String& url, mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::ServiceProviderPtr exposed_services) override; - void SetCapture(uint32_t view_id, - const mojo::Callback<void(bool)>& callback) override; - void FocusWindow(uint32_t view_id, - const mojo::Callback<void(bool)>& callback) override; - void ActivateWindow(uint32_t view_id, - const mojo::Callback<void(bool)>& callback) override; - void GetFocusedAndActiveViews( - mojo::WindowManagerObserverPtr observer, - const mojo::WindowManager::GetFocusedAndActiveViewsCallback& callback) - override; // mojo::ErrorHandler: void OnConnectionError() override; @@ -58,7 +44,6 @@ const bool from_vm_; mojo::Binding<mojo::WindowManager> binding_; - mojo::WindowManagerObserverPtr observer_; DISALLOW_COPY_AND_ASSIGN(WindowManagerImpl); };
diff --git a/components/window_manager/window_manager_test_util.cc b/components/window_manager/window_manager_test_util.cc deleted file mode 100644 index e1b6ca0f..0000000 --- a/components/window_manager/window_manager_test_util.cc +++ /dev/null
@@ -1,39 +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/window_manager/window_manager_test_util.h" - -#include "base/stl_util.h" -#include "mojo/converters/geometry/geometry_type_converters.h" -#include "ui/gfx/geometry/rect.h" - -namespace window_manager { - -TestView::TestView(int id, const gfx::Rect& rect) - : target_(new ViewTarget(this)) { - mojo::ViewPrivate(this).set_id(id); - - mojo::Rect mojo_rect = *mojo::Rect::From(rect); - SetBounds(mojo_rect); -} - -TestView::TestView(int id, const gfx::Rect& rect, View* parent) - : TestView(id, rect) { - parent->AddChild(this); -} - -TestView::~TestView() { -} - -// static -TestView* TestView::Build(int id, const gfx::Rect& rect) { - return new TestView(id, rect); -} - -// static -TestView* TestView::Build(int id, const gfx::Rect& rect, mojo::View* parent) { - return new TestView(id, rect, parent); -} - -} // namespace window_manager
diff --git a/components/window_manager/window_manager_test_util.h b/components/window_manager/window_manager_test_util.h deleted file mode 100644 index 3289429..0000000 --- a/components/window_manager/window_manager_test_util.h +++ /dev/null
@@ -1,43 +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_WINDOW_MANAGER_WINDOW_MANAGER_TEST_UTIL_H_ -#define COMPONENTS_WINDOW_MANAGER_WINDOW_MANAGER_TEST_UTIL_H_ - -#include <set> - -#include "components/window_manager/view_target.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h" -#include "third_party/mojo_services/src/view_manager/public/cpp/view.h" - -namespace gfx { -class Rect; -} - -namespace window_manager { - -// A wrapper around View so we can instantiate these directly without a -// ViewManager. -class TestView : public mojo::View { - public: - TestView(int id, const gfx::Rect& rect); - TestView(int id, const gfx::Rect& rect, mojo::View* parent); - ~TestView(); - - // Builds a child view as a pointer. The caller is responsible for making - // sure that the root of any tree allocated this way is Destroy()ed. - static TestView* Build(int id, const gfx::Rect& rect); - static TestView* Build(int id, const gfx::Rect& rect, View* parent); - - ViewTarget* target() { return target_; } - - private: - ViewTarget* target_; - - DISALLOW_COPY_AND_ASSIGN(TestView); -}; - -} // namespace window_manager - -#endif // COMPONENTS_WINDOW_MANAGER_WINDOW_MANAGER_TEST_UTIL_H_
diff --git a/content/BUILD.gn b/content/BUILD.gn index e31ea82..802ab2b 100644 --- a/content/BUILD.gn +++ b/content/BUILD.gn
@@ -38,7 +38,7 @@ # when doing a component build). content_shared_components = [ - "//content/gpu", + "//content/gpu:gpu_sources", "//content/public/browser:browser_sources", "//content/public/child:child_sources", "//content/public/common:common_sources", @@ -48,7 +48,7 @@ ] if (enable_plugins) { - content_shared_components += [ "//content/ppapi_plugin" ] + content_shared_components += [ "//content/ppapi_plugin:ppapi_plugin_sources" ] } if (is_component_build) {
diff --git a/content/app/BUILD.gn b/content/app/BUILD.gn index 4e48811..f6c72b9 100644 --- a/content/app/BUILD.gn +++ b/content/app/BUILD.gn
@@ -72,7 +72,7 @@ ] if (!is_chrome_multiple_dll) { - content_app_deps += [ "//content/gpu" ] + content_app_deps += [ "//content/gpu:gpu_sources" ] } # This includes the app sources for both the browser and child processes.
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 3ee0cac..5accb52 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -89,8 +89,6 @@ "$root_gen_dir/blink/grit/devtools_resources.h", "$root_gen_dir/blink/grit/devtools_resources_map.cc", "$root_gen_dir/blink/grit/devtools_resources_map.h", - "$root_gen_dir/content/browser/devtools/protocol/devtools_protocol_dispatcher.cc", - "$root_gen_dir/content/browser/devtools/protocol/devtools_protocol_dispatcher.h", "$root_gen_dir/content/browser/tracing/grit/tracing_resources.h", "$root_gen_dir/ui/resources/grit/webui_resources_map.cc", ], @@ -103,6 +101,7 @@ "//components/scheduler:common", "//content/app/resources", "//content/app/strings", + "//content/browser/devtools:gen_devtools_protocol_handler", "//content/browser/devtools:resources", "//content/common:mojo_bindings", "//content/public/common:mojo_bindings", @@ -293,6 +292,7 @@ # android, chromeos, linux and use_dbus. if (is_android) { sources -= [ "geolocation/wifi_data_provider_common.cc" ] + deps += [ "//webkit/common/gpu" ] } if (is_chromeos || (is_linux && !use_dbus)) { sources -= [ "geolocation/wifi_data_provider_linux.cc" ]
diff --git a/content/browser/accessibility/accessibility_tree_formatter.cc b/content/browser/accessibility/accessibility_tree_formatter.cc index 1f56cd4..2ca2a854 100644 --- a/content/browser/accessibility/accessibility_tree_formatter.cc +++ b/content/browser/accessibility/accessibility_tree_formatter.cc
@@ -20,6 +20,7 @@ const char kIndentSymbol = '+'; const int kIndentSymbolCount = 2; const char* kSkipString = "@NO_DUMP"; +const char* kSkipChildren = "@NO_CHILDREN_DUMP"; const char* kChildrenDictAttr = "children"; } @@ -84,6 +85,9 @@ return; *contents += line + base::ASCIIToUTF16("\n"); + if (line.find(base::ASCIIToUTF16(kSkipChildren)) != base::string16::npos) + return; + const base::ListValue* children; dict.GetList(kChildrenDictAttr, &children); const base::DictionaryValue* child_dict;
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 89213b5..d333ae1 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -773,35 +773,49 @@ - (NSArray*)selectedChildren { NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease]; - BrowserAccessibilityManager* manager = browserAccessibility_->manager(); - BrowserAccessibility* focusedChild = - manager->GetFocus(browserAccessibility_); - if (focusedChild && focusedChild != browserAccessibility_) { + BrowserAccessibility* focusedChild = manager->GetFocus(browserAccessibility_); + + // If it's not multiselectable, try to skip iterating over the + // children. + if (!GetState(browserAccessibility_, ui::AX_STATE_MULTISELECTABLE)) { // First try the focused child. - [ret addObject:focusedChild->ToBrowserAccessibilityCocoa()]; - } else { + if (focusedChild && focusedChild != browserAccessibility_) { + [ret addObject:focusedChild->ToBrowserAccessibilityCocoa()]; + return ret; + } + // Next try the active descendant. int activeDescendantId; if (browserAccessibility_->GetIntAttribute( ui::AX_ATTR_ACTIVEDESCENDANT_ID, &activeDescendantId)) { BrowserAccessibility* activeDescendant = manager->GetFromID(activeDescendantId); - if (activeDescendant) + if (activeDescendant) { [ret addObject:activeDescendant->ToBrowserAccessibilityCocoa()]; - } else { - // Otherwise return any children with the "selected" state, which - // may come from aria-selected. - uint32 childCount = browserAccessibility_->PlatformChildCount(); - for (uint32 index = 0; index < childCount; ++index) { - BrowserAccessibility* child = - browserAccessibility_->PlatformGetChild(index); - if (child->HasState(ui::AX_STATE_SELECTED)) - [ret addObject:child->ToBrowserAccessibilityCocoa()]; + return ret; } } } + // If it's multiselectable or if the previous attempts failed, + // return any children with the "selected" state, which may + // come from aria-selected. + uint32 childCount = browserAccessibility_->PlatformChildCount(); + for (uint32 index = 0; index < childCount; ++index) { + BrowserAccessibility* child = + browserAccessibility_->PlatformGetChild(index); + if (child->HasState(ui::AX_STATE_SELECTED)) + [ret addObject:child->ToBrowserAccessibilityCocoa()]; + } + + // And if nothing's selected but one has focus, use the focused one. + if ([ret count] == 0 && + focusedChild && + focusedChild != browserAccessibility_) { + [ret addObject:focusedChild->ToBrowserAccessibilityCocoa()]; + } + return ret; }
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm index 1361164..8f6b2185 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.mm +++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -44,8 +44,14 @@ BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus( BrowserAccessibility* root) { - BrowserAccessibility* node = GetActiveDescendantFocus(root); - return node; + // On Mac, list boxes should always get focus on the whole list, otherwise + // information about the number of selected items will never be reported. + BrowserAccessibility* node = BrowserAccessibilityManager::GetFocus(root); + if (node && node->GetRole() == ui::AX_ROLE_LIST_BOX) + return node; + + // For other roles, follow the active descendant. + return GetActiveDescendantFocus(root); } void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent( @@ -54,6 +60,15 @@ if (!node->IsNative()) return; + if (event_type == ui::AX_EVENT_FOCUS && + node->GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && + node->HasState(ui::AX_STATE_SELECTED) && + node->GetParent() && + node->GetParent()->GetRole() == ui::AX_ROLE_LIST_BOX) { + node = node->GetParent(); + SetFocus(node, false); + } + // Refer to AXObjectCache.mm (webkit). NSString* event_id = @""; switch (event_type) { @@ -139,6 +154,7 @@ LOG(WARNING) << "Unknown accessibility event: " << event_type; return; } + BrowserAccessibilityCocoa* native_node = node->ToBrowserAccessibilityCocoa(); DCHECK(native_node); NSAccessibilityPostNotification(native_node, event_id);
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc index 750d1311..24a30896 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.cc +++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -261,12 +261,6 @@ case ui::AX_EVENT_LOAD_COMPLETE: event_id = IA2_EVENT_DOCUMENT_LOAD_COMPLETE; break; - case ui::AX_EVENT_MENU_LIST_ITEM_SELECTED: - event_id = EVENT_OBJECT_FOCUS; - break; - case ui::AX_EVENT_MENU_LIST_VALUE_CHANGED: - event_id = EVENT_OBJECT_VALUECHANGE; - break; case ui::AX_EVENT_SCROLL_POSITION_CHANGED: event_id = EVENT_SYSTEM_SCROLLINGEND; break;
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.h b/content/browser/accessibility/browser_accessibility_manager_win.h index 24c0b77e..c33f5923 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.h +++ b/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -23,7 +23,7 @@ BrowserAccessibilityDelegate* delegate, BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory()); - virtual ~BrowserAccessibilityManagerWin(); + ~BrowserAccessibilityManagerWin() override; static ui::AXTreeUpdate GetEmptyDocument(); @@ -37,8 +37,8 @@ void MaybeCallNotifyWinEvent(DWORD event, BrowserAccessibility* node); // AXTree methods - virtual void OnNodeWillBeDeleted(ui::AXNode* node) override; - virtual void OnNodeCreated(ui::AXNode* node) override; + void OnNodeWillBeDeleted(ui::AXNode* node) override; + void OnNodeCreated(ui::AXNode* node) override; // BrowserAccessibilityManager methods void OnWindowFocused() override;
diff --git a/content/browser/accessibility/browser_accessibility_win.cc b/content/browser/accessibility/browser_accessibility_win.cc index b61f2f9c2..c6c7788d 100644 --- a/content/browser/accessibility/browser_accessibility_win.cc +++ b/content/browser/accessibility/browser_accessibility_win.cc
@@ -3179,9 +3179,9 @@ // WebKit stores the main accessible text in the "value" - swap it so // that it's the "name". if (name.empty() && - (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION || - GetRole() == ui::AX_ROLE_STATIC_TEXT || - GetRole() == ui::AX_ROLE_LIST_MARKER)) { + (GetRole() == ui::AX_ROLE_STATIC_TEXT || + GetRole() == ui::AX_ROLE_LIST_MARKER || + IsListBoxOptionOrMenuListOption())) { base::string16 tmp = value; value = name; name = tmp; @@ -3298,10 +3298,22 @@ bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0; bool was_selected_before = (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0; - if (is_selected_now && !was_selected_before) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); - } else if (!is_selected_now && was_selected_before) { - manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); + if (is_selected_now || was_selected_before) { + bool multiselect = false; + if (GetParent() && GetParent()->HasState(ui::AX_STATE_MULTISELECTABLE)) + multiselect = true; + + if (multiselect) { + // In a multi-select box, fire SELECTIONADD and SELECTIONREMOVE events. + if (is_selected_now && !was_selected_before) { + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); + } else if (!is_selected_now && was_selected_before) { + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); + } + } else if (is_selected_now && !was_selected_before) { + // In a single-select box, only fire SELECTION events. + manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTION, this); + } } // Fire an event if this container object has scrolled. @@ -3461,7 +3473,7 @@ } base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { - if (IsEditableText()) + if (IsEditableText() || GetRole() == ui::AX_ROLE_MENU_LIST_OPTION) return value(); return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext(); } @@ -3587,6 +3599,26 @@ return manager()->GetFromID(id)->ToBrowserAccessibilityWin(); } +bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() { + if (!GetParent()) + return false; + + int32 role = GetRole(); + int32 parent_role = GetParent()->GetRole(); + + if (role == ui::AX_ROLE_LIST_BOX_OPTION && + parent_role == ui::AX_ROLE_LIST_BOX) { + return true; + } + + if (role == ui::AX_ROLE_MENU_LIST_OPTION && + parent_role == ui::AX_ROLE_MENU_LIST_POPUP) { + return true; + } + + return false; +} + void BrowserAccessibilityWin::InitRoleAndState() { int32 ia_role = 0; int32 ia_state = 0; @@ -3909,10 +3941,12 @@ ia2_role = IA2_ROLE_RADIO_MENU_ITEM; break; case ui::AX_ROLE_MENU_LIST_POPUP: - ia_role = ROLE_SYSTEM_CLIENT; + ia_role = ROLE_SYSTEM_LIST; + ia2_state &= ~(IA2_STATE_EDITABLE); break; case ui::AX_ROLE_MENU_LIST_OPTION: ia_role = ROLE_SYSTEM_LISTITEM; + ia2_state &= ~(IA2_STATE_EDITABLE); if (ia_state & STATE_SYSTEM_SELECTABLE) { ia_state |= STATE_SYSTEM_FOCUSABLE; if (HasState(ui::AX_STATE_FOCUSED))
diff --git a/content/browser/accessibility/browser_accessibility_win.h b/content/browser/accessibility/browser_accessibility_win.h index c5da6082..646d1f7 100644 --- a/content/browser/accessibility/browser_accessibility_win.h +++ b/content/browser/accessibility/browser_accessibility_win.h
@@ -91,7 +91,7 @@ CONTENT_EXPORT BrowserAccessibilityWin(); - CONTENT_EXPORT virtual ~BrowserAccessibilityWin(); + CONTENT_EXPORT ~BrowserAccessibilityWin() override; // The Windows-specific unique ID, used as the child ID for MSAA methods // like NotifyWinEvent, and as the unique ID for IAccessible2 and ISimpleDOM. @@ -108,11 +108,11 @@ // // BrowserAccessibility methods. // - CONTENT_EXPORT virtual void OnSubtreeWillBeDeleted() override; - CONTENT_EXPORT virtual void NativeAddReference() override; - CONTENT_EXPORT virtual void NativeReleaseReference() override; - CONTENT_EXPORT virtual bool IsNative() const override; - CONTENT_EXPORT virtual void OnLocationChanged() override; + CONTENT_EXPORT void OnSubtreeWillBeDeleted() override; + CONTENT_EXPORT void NativeAddReference() override; + CONTENT_EXPORT void NativeReleaseReference() override; + CONTENT_EXPORT bool IsNative() const override; + CONTENT_EXPORT void OnLocationChanged() override; // // IAccessible methods. @@ -873,6 +873,10 @@ // does not make a new reference. BrowserAccessibilityWin* GetFromID(int32 id); + // Returns true if this is a list box option with a parent of type list box, + // or a menu list option with a parent of type menu list popup. + bool IsListBoxOptionOrMenuListOption(); + // Windows-specific unique ID (unique within the browser process), // used for get_accChild, NotifyWinEvent, and as the unique ID for // IAccessible2 and ISimpleDOM.
diff --git a/content/browser/accessibility/browser_accessibility_win_unittest.cc b/content/browser/accessibility/browser_accessibility_win_unittest.cc index 2235b24..72f4450 100644 --- a/content/browser/accessibility/browser_accessibility_win_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -57,9 +57,9 @@ CountedBrowserAccessibilityFactory(); private: - virtual ~CountedBrowserAccessibilityFactory(); + ~CountedBrowserAccessibilityFactory() override; - virtual BrowserAccessibility* Create() override; + BrowserAccessibility* Create() override; DISALLOW_COPY_AND_ASSIGN(CountedBrowserAccessibilityFactory); }; @@ -87,10 +87,10 @@ class BrowserAccessibilityTest : public testing::Test { public: BrowserAccessibilityTest(); - virtual ~BrowserAccessibilityTest(); + ~BrowserAccessibilityTest() override; private: - virtual void SetUp() override; + void SetUp() override; DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityTest); };
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc index 6d198fb..3a9f62a 100644 --- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -205,6 +205,26 @@ } IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, + AccessibilityEventsListboxFocus) { + RunEventTest(FILE_PATH_LITERAL("listbox-focus.html")); +} + +IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, + AccessibilityEventsListboxNext) { + RunEventTest(FILE_PATH_LITERAL("listbox-next.html")); +} + +IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, + AccessibilityEventsMenuListFocus) { + RunEventTest(FILE_PATH_LITERAL("menulist-focus.html")); +} + +IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, + AccessibilityEventsMenuListNext) { + RunEventTest(FILE_PATH_LITERAL("menulist-next.html")); +} + +IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, AccessibilityEventsNameChange) { RunEventTest(FILE_PATH_LITERAL("name-change.html")); }
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 1057e4cd..bae4365e 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -846,9 +846,7 @@ } #endif -// crbug.com/84250 -IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, - DISABLED_AccessibilityInputPassword) { +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputPassword) { RunHtmlTest(FILE_PATH_LITERAL("input-password.html")); }
diff --git a/content/browser/android/java/gin_java_method_invocation_helper.cc b/content/browser/android/java/gin_java_method_invocation_helper.cc index ae1c798..93ab2e6 100644 --- a/content/browser/android/java/gin_java_method_invocation_helper.cc +++ b/content/browser/android/java/gin_java_method_invocation_helper.cc
@@ -6,10 +6,11 @@ #include <unistd.h> +#include <cmath> + #include "base/android/event_log.h" #include "base/android/jni_android.h" #include "base/android/jni_string.h" -#include "base/float_util.h" #include "content/browser/android/java/gin_java_script_to_java_types_coercion.h" #include "content/browser/android/java/java_method.h" #include "content/browser/android/java/jni_helper.h" @@ -256,7 +257,7 @@ float result = object ? env->CallFloatMethodA(object, id, parameters) : env->CallStaticFloatMethodA(clazz, id, parameters); - if (base::IsFinite(result)) { + if (std::isfinite(result)) { result_wrapper.AppendDouble(result); } else { result_wrapper.Append( @@ -268,7 +269,7 @@ double result = object ? env->CallDoubleMethodA(object, id, parameters) : env->CallStaticDoubleMethodA(clazz, id, parameters); - if (base::IsFinite(result)) { + if (std::isfinite(result)) { result_wrapper.AppendDouble(result); } else { result_wrapper.Append(
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 3dfc8bd..f5b0f18 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -14,6 +14,7 @@ #include "base/power_monitor/power_monitor.h" #include "base/power_monitor/power_monitor_device_source.h" #include "base/process/process_metrics.h" +#include "base/profiler/scoped_profile.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/system_monitor/system_monitor.h" @@ -381,6 +382,8 @@ void BrowserMainLoop::Init() { TRACE_EVENT0("startup", "BrowserMainLoop::Init"); + TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::Init"); + parts_.reset( GetContentClient()->browser()->CreateBrowserMainParts(parameters_)); } @@ -389,6 +392,7 @@ void BrowserMainLoop::EarlyInitialization() { TRACE_EVENT0("startup", "BrowserMainLoop::EarlyInitialization"); + TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::EarlyInitialization"); #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) // No thread should be created before this call, as SetupSandbox() @@ -471,6 +475,8 @@ void BrowserMainLoop::MainMessageLoopStart() { TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart"); + TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::MainMessageLoopStart"); + if (parts_) { TRACE_EVENT0("startup", "BrowserMainLoop::MainMessageLoopStart:PreMainMessageLoopStart"); @@ -588,6 +594,8 @@ if (parts_) { TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads:PreCreateThreads"); + TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::PreCreateThreads"); + result_code_ = parts_->PreCreateThreads(); } @@ -640,6 +648,7 @@ void BrowserMainLoop::CreateStartupTasks() { TRACE_EVENT0("startup", "BrowserMainLoop::CreateStartupTasks"); + TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::CreateStartupTasks"); // First time through, we really want to create all the tasks if (!startup_task_runner_.get()) { @@ -690,6 +699,7 @@ int BrowserMainLoop::CreateThreads() { TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads"); + TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::CreateThreads"); base::Thread::Options io_message_loop_options; io_message_loop_options.message_loop_type = base::MessageLoop::TYPE_IO; @@ -786,6 +796,9 @@ if (parts_) { TRACE_EVENT0("startup", "BrowserMainLoop::CreateThreads:PreMainMessageLoopRun"); + TRACK_SCOPED_REGION( + "Startup", "BrowserMainLoop::PreMainMessageLoopRun"); + parts_->PreMainMessageLoopRun(); } @@ -1186,6 +1199,8 @@ bool BrowserMainLoop::InitializeToolkit() { TRACE_EVENT0("startup", "BrowserMainLoop::InitializeToolkit"); + TRACK_SCOPED_REGION("Startup", "BrowserMainLoop::InitializeToolkit"); + // TODO(evan): this function is rather subtle, due to the variety // of intersecting ifdefs we have. To keep it easy to follow, there // are no #else branches on any #ifs.
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc index 524bdfb2..f98ece3 100644 --- a/content/browser/browser_main_runner.cc +++ b/content/browser/browser_main_runner.cc
@@ -10,6 +10,7 @@ #include "base/logging.h" #include "base/metrics/histogram.h" #include "base/metrics/statistics_recorder.h" +#include "base/profiler/scoped_profile.h" #include "base/profiler/scoped_tracker.h" #include "base/trace_event/trace_event.h" #include "base/tracked_objects.h" @@ -131,9 +132,8 @@ // TODO(vadimt, yiyaoliu): Remove all tracked_objects references below once // crbug.com/453640 is fixed. tracked_objects::ThreadData::InitializeThreadContext("CrBrowserMain"); - tracked_objects::ScopedTracker tracking_profile( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "453640 BrowserMainRunnerImpl::Initialize")); + TRACK_SCOPED_REGION( + "Startup", "BrowserMainRunnerImpl::Initialize"); TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize"); // On Android we normally initialize the browser in a series of UI thread
diff --git a/content/browser/browser_url_handler_impl.cc b/content/browser/browser_url_handler_impl.cc index 438feb3..63ddf492 100644 --- a/content/browser/browser_url_handler_impl.cc +++ b/content/browser/browser_url_handler_impl.cc
@@ -89,7 +89,7 @@ } BrowserURLHandlerImpl::BrowserURLHandlerImpl() : - fixup_handler_(null_handler()) { + fixup_handler_(nullptr) { AddHandlerPair(&DebugURLHandler, BrowserURLHandlerImpl::null_handler()); GetContentClient()->browser()->BrowserURLHandlerCreated(this); @@ -102,7 +102,7 @@ } void BrowserURLHandlerImpl::SetFixupHandler(URLHandler handler) { - DCHECK_EQ(null_handler(), fixup_handler_); + DCHECK(fixup_handler_ == nullptr); fixup_handler_ = handler; }
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index e7c079e..07275552 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -15,6 +15,7 @@ #include "content/browser/cache_storage/cache_storage_scheduler.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/referrer.h" +#include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/disk_cache/disk_cache.h" @@ -30,7 +31,6 @@ namespace { -typedef base::Callback<void(bool)> BoolCallback; typedef base::Callback<void(disk_cache::ScopedEntryPtr, bool)> EntryBoolCallback; typedef base::Callback<void(scoped_ptr<CacheMetadata>)> MetadataCallback; @@ -273,7 +273,7 @@ // The state needed to pass between CacheStorageCache::Keys callbacks. struct CacheStorageCache::KeysContext { - KeysContext(const CacheStorageCache::RequestsCallback& callback) + explicit KeysContext(const CacheStorageCache::RequestsCallback& callback) : original_callback(callback), out_keys(new CacheStorageCache::Requests()), enumerated_entry(NULL) {}
diff --git a/content/browser/cache_storage/cache_storage_cache.h b/content/browser/cache_storage/cache_storage_cache.h index beb7fdd..e63cac4 100644 --- a/content/browser/cache_storage/cache_storage_cache.h +++ b/content/browser/cache_storage/cache_storage_cache.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_CACHE_H_ #define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_CACHE_H_ -#include <list> +#include <vector> #include "base/callback.h" #include "base/files/file_path.h" @@ -13,7 +13,6 @@ #include "base/memory/weak_ptr.h" #include "content/common/cache_storage/cache_storage_types.h" #include "content/common/service_worker/service_worker_types.h" -#include "net/base/completion_callback.h" #include "net/disk_cache/disk_cache.h" namespace net { @@ -22,14 +21,13 @@ } namespace storage { -class BlobDataBuilder; class BlobDataHandle; class BlobStorageContext; class QuotaManagerProxy; } namespace content { -class ChromeBlobStorageContext; + class CacheMetadata; class CacheStorageScheduler; class TestCacheStorageCache; @@ -51,7 +49,6 @@ ERROR_TYPE_LAST = ERROR_TYPE_NOT_FOUND }; - enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY }; typedef base::Callback<void(ErrorType)> ErrorCallback; typedef base::Callback<void(ErrorType, scoped_ptr<ServiceWorkerResponse>,
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/content/browser/cache_storage/cache_storage_dispatcher_host.cc index 93151dd..84d695b 100644 --- a/content/browser/cache_storage/cache_storage_dispatcher_host.cc +++ b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -5,10 +5,15 @@ #include "content/browser/cache_storage/cache_storage_dispatcher_host.h" #include "base/logging.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" #include "content/browser/cache_storage/cache_storage_context_impl.h" #include "content/browser/cache_storage/cache_storage_listener.h" +#include "content/browser/cache_storage/cache_storage_manager.h" #include "content/common/cache_storage/cache_storage_messages.h" #include "content/public/browser/content_browser_client.h" +#include "storage/browser/blob/blob_data_handle.h" +#include "third_party/WebKit/public/platform/WebServiceWorkerCacheError.h" namespace content { @@ -16,6 +21,52 @@ const uint32 kFilteredMessageClasses[] = {CacheStorageMsgStart}; +blink::WebServiceWorkerCacheError ToWebServiceWorkerCacheError( + CacheStorage::CacheStorageError err) { + switch (err) { + case CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR: + NOTREACHED(); + return blink::WebServiceWorkerCacheErrorNotImplemented; + case CacheStorage::CACHE_STORAGE_ERROR_NOT_IMPLEMENTED: + return blink::WebServiceWorkerCacheErrorNotImplemented; + case CacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND: + return blink::WebServiceWorkerCacheErrorNotFound; + case CacheStorage::CACHE_STORAGE_ERROR_EXISTS: + return blink::WebServiceWorkerCacheErrorExists; + case CacheStorage::CACHE_STORAGE_ERROR_STORAGE: + // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's + // added. + return blink::WebServiceWorkerCacheErrorNotFound; + case CacheStorage::CACHE_STORAGE_ERROR_CLOSING: + // TODO(jkarlin): Update this to CACHE_STORAGE_ERROR_CLOSING once that's + // added. + return blink::WebServiceWorkerCacheErrorNotFound; + } + NOTREACHED(); + return blink::WebServiceWorkerCacheErrorNotImplemented; +} + +// TODO(jkarlin): CacheStorageCache and CacheStorage should share +// an error enum type. +blink::WebServiceWorkerCacheError CacheErrorToWebServiceWorkerCacheError( + CacheStorageCache::ErrorType err) { + switch (err) { + case CacheStorageCache::ERROR_TYPE_OK: + NOTREACHED(); + return blink::WebServiceWorkerCacheErrorNotImplemented; + case CacheStorageCache::ERROR_TYPE_EXISTS: + return blink::WebServiceWorkerCacheErrorExists; + case CacheStorageCache::ERROR_TYPE_STORAGE: + // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's + // added. + return blink::WebServiceWorkerCacheErrorNotFound; + case CacheStorageCache::ERROR_TYPE_NOT_FOUND: + return blink::WebServiceWorkerCacheErrorNotFound; + } + NOTREACHED(); + return blink::WebServiceWorkerCacheErrorNotImplemented; +} + } // namespace CacheStorageDispatcherHost::CacheStorageDispatcherHost() @@ -41,8 +92,23 @@ bool CacheStorageDispatcherHost::OnMessageReceived( const IPC::Message& message) { DCHECK_CURRENTLY_ON(BrowserThread::IO); + + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(CacheStorageDispatcherHost, message) + IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageHas, OnCacheStorageHas) + IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageOpen, OnCacheStorageOpen) + IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageDelete, + OnCacheStorageDelete) + IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageKeys, OnCacheStorageKeys) + IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageMatch, + OnCacheStorageMatch) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + if (handled) + return handled; + DCHECK(cache_listener_); - bool handled = cache_listener_->OnMessageReceived(message); + handled = cache_listener_->OnMessageReceived(message); if (!handled) BadMessageReceived(); return handled; @@ -52,6 +118,168 @@ CacheStorageContextImpl* context) { DCHECK_CURRENTLY_ON(BrowserThread::IO); cache_listener_.reset(new CacheStorageListener(this, context)); + context_ = context; +} + +void CacheStorageDispatcherHost::OnCacheStorageHas( + int thread_id, + int request_id, + const GURL& origin, + const base::string16& cache_name) { + TRACE_EVENT0("CacheStorage", "CacheStorageDispatcherHost::OnCacheStorageHas"); + context_->cache_manager()->HasCache( + origin, base::UTF16ToUTF8(cache_name), + base::Bind(&CacheStorageDispatcherHost::OnCacheStorageHasCallback, this, + thread_id, request_id)); +} + +void CacheStorageDispatcherHost::OnCacheStorageOpen( + int thread_id, + int request_id, + const GURL& origin, + const base::string16& cache_name) { + TRACE_EVENT0("CacheStorage", + "CacheStorageDispatcherHost::OnCacheStorageOpen"); + context_->cache_manager()->OpenCache( + origin, base::UTF16ToUTF8(cache_name), + base::Bind(&CacheStorageDispatcherHost::OnCacheStorageOpenCallback, this, + thread_id, request_id)); +} + +void CacheStorageDispatcherHost::OnCacheStorageDelete( + int thread_id, + int request_id, + const GURL& origin, + const base::string16& cache_name) { + TRACE_EVENT0("CacheStorage", + "CacheStorageDispatcherHost::OnCacheStorageDelete"); + context_->cache_manager()->DeleteCache( + origin, base::UTF16ToUTF8(cache_name), + base::Bind(&CacheStorageDispatcherHost::OnCacheStorageDeleteCallback, + this, thread_id, request_id)); +} + +void CacheStorageDispatcherHost::OnCacheStorageKeys(int thread_id, + int request_id, + const GURL& origin) { + TRACE_EVENT0("CacheStorage", + "CacheStorageDispatcherHost::OnCacheStorageKeys"); + context_->cache_manager()->EnumerateCaches( + origin, + base::Bind(&CacheStorageDispatcherHost::OnCacheStorageKeysCallback, this, + thread_id, request_id)); +} + +void CacheStorageDispatcherHost::OnCacheStorageMatch( + int thread_id, + int request_id, + const GURL& origin, + const ServiceWorkerFetchRequest& request, + const CacheStorageCacheQueryParams& match_params) { + TRACE_EVENT0("CacheStorage", + "CacheStorageDispatcherHost::OnCacheStorageMatch"); + + scoped_ptr<ServiceWorkerFetchRequest> scoped_request( + new ServiceWorkerFetchRequest(request.url, request.method, + request.headers, request.referrer, + request.is_reload)); + + if (match_params.cache_name.empty()) { + context_->cache_manager()->MatchAllCaches( + origin, scoped_request.Pass(), + base::Bind(&CacheStorageDispatcherHost::OnCacheStorageMatchCallback, + this, thread_id, request_id)); + return; + } + context_->cache_manager()->MatchCache( + origin, base::UTF16ToUTF8(match_params.cache_name), scoped_request.Pass(), + base::Bind(&CacheStorageDispatcherHost::OnCacheStorageMatchCallback, this, + thread_id, request_id)); +} + +void CacheStorageDispatcherHost::OnCacheStorageHasCallback( + int thread_id, + int request_id, + bool has_cache, + CacheStorage::CacheStorageError error) { + if (error != CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) { + Send(new CacheStorageMsg_CacheStorageHasError( + thread_id, request_id, ToWebServiceWorkerCacheError(error))); + return; + } + if (!has_cache) { + Send(new CacheStorageMsg_CacheStorageHasError( + thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound)); + return; + } + Send(new CacheStorageMsg_CacheStorageHasSuccess(thread_id, request_id)); +} + +void CacheStorageDispatcherHost::OnCacheStorageOpenCallback( + int thread_id, + int request_id, + const scoped_refptr<CacheStorageCache>& cache, + CacheStorage::CacheStorageError error) { + if (error != CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) { + Send(new CacheStorageMsg_CacheStorageOpenError( + thread_id, request_id, ToWebServiceWorkerCacheError(error))); + return; + } + CacheStorageListener::CacheID cache_id = + cache_listener_->StoreCacheReference(cache); + Send(new CacheStorageMsg_CacheStorageOpenSuccess(thread_id, request_id, + cache_id)); +} + +void CacheStorageDispatcherHost::OnCacheStorageDeleteCallback( + int thread_id, + int request_id, + bool deleted, + CacheStorage::CacheStorageError error) { + if (!deleted || error != CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) { + Send(new CacheStorageMsg_CacheStorageDeleteError( + thread_id, request_id, ToWebServiceWorkerCacheError(error))); + return; + } + Send(new CacheStorageMsg_CacheStorageDeleteSuccess(thread_id, request_id)); +} + +void CacheStorageDispatcherHost::OnCacheStorageKeysCallback( + int thread_id, + int request_id, + const std::vector<std::string>& strings, + CacheStorage::CacheStorageError error) { + if (error != CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) { + Send(new CacheStorageMsg_CacheStorageKeysError( + thread_id, request_id, ToWebServiceWorkerCacheError(error))); + return; + } + + std::vector<base::string16> string16s; + for (size_t i = 0, max = strings.size(); i < max; ++i) { + string16s.push_back(base::UTF8ToUTF16(strings[i])); + } + Send(new CacheStorageMsg_CacheStorageKeysSuccess(thread_id, request_id, + string16s)); +} + +void CacheStorageDispatcherHost::OnCacheStorageMatchCallback( + int thread_id, + int request_id, + CacheStorageCache::ErrorType error, + scoped_ptr<ServiceWorkerResponse> response, + scoped_ptr<storage::BlobDataHandle> blob_data_handle) { + if (error != CacheStorageCache::ERROR_TYPE_OK) { + Send(new CacheStorageMsg_CacheStorageMatchError( + thread_id, request_id, CacheErrorToWebServiceWorkerCacheError(error))); + return; + } + + if (blob_data_handle) + cache_listener_->StoreBlobDataHandle(blob_data_handle.Pass()); + + Send(new CacheStorageMsg_CacheStorageMatchSuccess(thread_id, request_id, + *response)); } } // namespace content
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.h b/content/browser/cache_storage/cache_storage_dispatcher_host.h index b922f23..ed10561 100644 --- a/content/browser/cache_storage/cache_storage_dispatcher_host.h +++ b/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -5,6 +5,7 @@ #ifndef CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_DISPATCHER_HOST_H_ #define CONTENT_BROWSER_CACHE_STORAGE_CACHE_STORAGE_DISPATCHER_HOST_H_ +#include "content/browser/cache_storage/cache_storage.h" #include "content/public/browser/browser_message_filter.h" namespace content { @@ -40,7 +41,52 @@ // Called by Init() on IO thread. void CreateCacheListener(CacheStorageContextImpl* context); + // The message receiver functions for the CacheStorage API: + void OnCacheStorageHas(int thread_id, + int request_id, + const GURL& origin, + const base::string16& cache_name); + void OnCacheStorageOpen(int thread_id, + int request_id, + const GURL& origin, + const base::string16& cache_name); + void OnCacheStorageDelete(int thread_id, + int request_id, + const GURL& origin, + const base::string16& cache_name); + void OnCacheStorageKeys(int thread_id, int request_id, const GURL& origin); + void OnCacheStorageMatch(int thread_id, + int request_id, + const GURL& origin, + const ServiceWorkerFetchRequest& request, + const CacheStorageCacheQueryParams& match_params); + + // CacheStorageManager callbacks + void OnCacheStorageHasCallback(int thread_id, + int request_id, + bool has_cache, + CacheStorage::CacheStorageError error); + void OnCacheStorageOpenCallback(int thread_id, + int request_id, + const scoped_refptr<CacheStorageCache>& cache, + CacheStorage::CacheStorageError error); + void OnCacheStorageDeleteCallback(int thread_id, + int request_id, + bool deleted, + CacheStorage::CacheStorageError error); + void OnCacheStorageKeysCallback(int thread_id, + int request_id, + const std::vector<std::string>& strings, + CacheStorage::CacheStorageError error); + void OnCacheStorageMatchCallback( + int thread_id, + int request_id, + CacheStorageCache::ErrorType error, + scoped_ptr<ServiceWorkerResponse> response, + scoped_ptr<storage::BlobDataHandle> blob_data_handle); + scoped_ptr<CacheStorageListener> cache_listener_; + scoped_refptr<CacheStorageContextImpl> context_; DISALLOW_COPY_AND_ASSIGN(CacheStorageDispatcherHost); };
diff --git a/content/browser/cache_storage/cache_storage_listener.cc b/content/browser/cache_storage/cache_storage_listener.cc index 7392df6..4b98b3c 100644 --- a/content/browser/cache_storage/cache_storage_listener.cc +++ b/content/browser/cache_storage/cache_storage_listener.cc
@@ -21,33 +21,9 @@ namespace { -WebServiceWorkerCacheError ToWebServiceWorkerCacheError( - CacheStorage::CacheStorageError err) { - switch (err) { - case CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR: - NOTREACHED(); - return blink::WebServiceWorkerCacheErrorNotImplemented; - case CacheStorage::CACHE_STORAGE_ERROR_NOT_IMPLEMENTED: - return blink::WebServiceWorkerCacheErrorNotImplemented; - case CacheStorage::CACHE_STORAGE_ERROR_NOT_FOUND: - return blink::WebServiceWorkerCacheErrorNotFound; - case CacheStorage::CACHE_STORAGE_ERROR_EXISTS: - return blink::WebServiceWorkerCacheErrorExists; - case CacheStorage::CACHE_STORAGE_ERROR_STORAGE: - // TODO(jkarlin): Change this to CACHE_STORAGE_ERROR_STORAGE once that's - // added. - return blink::WebServiceWorkerCacheErrorNotFound; - case CacheStorage::CACHE_STORAGE_ERROR_CLOSING: - // TODO(jkarlin): Update this to CACHE_STORAGE_ERROR_CLOSING once that's - // added. - return blink::WebServiceWorkerCacheErrorNotFound; - } - NOTREACHED(); - return blink::WebServiceWorkerCacheErrorNotImplemented; -} - -// TODO(jkarlin): CacheStorageCache and CacheStorage should share -// an error enum type. +// TODO(nhiroki): The same function exists in cache_storage_dispatcher_host.cc. +// This should be removed when this listenr class is merged into the dispatcher. +// (http://crbug.com/474233) WebServiceWorkerCacheError CacheErrorToWebServiceWorkerCacheError( CacheStorageCache::ErrorType err) { switch (err) { @@ -81,16 +57,6 @@ bool CacheStorageListener::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(CacheStorageListener, message) - IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageHas, - OnCacheStorageHas) - IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageOpen, - OnCacheStorageOpen) - IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageDelete, - OnCacheStorageDelete) - IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageKeys, - OnCacheStorageKeys) - IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheStorageMatch, - OnCacheStorageMatch) IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheMatch, OnCacheMatch) IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheMatchAll, OnCacheMatchAll) IPC_MESSAGE_HANDLER(CacheStorageHostMsg_CacheKeys, OnCacheKeys) @@ -104,76 +70,6 @@ return handled; } -void CacheStorageListener::OnCacheStorageHas(int thread_id, - int request_id, - const GURL& origin, - const base::string16& cache_name) { - TRACE_EVENT0("CacheStorage", "CacheStorageListener::OnCacheStorageHas"); - context_->cache_manager()->HasCache( - origin, base::UTF16ToUTF8(cache_name), - base::Bind(&CacheStorageListener::OnCacheStorageHasCallback, - weak_factory_.GetWeakPtr(), thread_id, request_id)); -} - -void CacheStorageListener::OnCacheStorageOpen( - int thread_id, - int request_id, - const GURL& origin, - const base::string16& cache_name) { - TRACE_EVENT0("CacheStorage", "CacheStorageListener::OnCacheStorageOpen"); - context_->cache_manager()->OpenCache( - origin, base::UTF16ToUTF8(cache_name), - base::Bind(&CacheStorageListener::OnCacheStorageOpenCallback, - weak_factory_.GetWeakPtr(), thread_id, request_id)); -} - -void CacheStorageListener::OnCacheStorageDelete( - int thread_id, - int request_id, - const GURL& origin, - const base::string16& cache_name) { - TRACE_EVENT0("CacheStorage", "CacheStorageListener::OnCacheStorageDelete"); - context_->cache_manager()->DeleteCache( - origin, base::UTF16ToUTF8(cache_name), - base::Bind(&CacheStorageListener::OnCacheStorageDeleteCallback, - weak_factory_.GetWeakPtr(), thread_id, request_id)); -} - -void CacheStorageListener::OnCacheStorageKeys(int thread_id, - int request_id, - const GURL& origin) { - TRACE_EVENT0("CacheStorage", "CacheStorageListener::OnCacheStorageKeys"); - context_->cache_manager()->EnumerateCaches( - origin, base::Bind(&CacheStorageListener::OnCacheStorageKeysCallback, - weak_factory_.GetWeakPtr(), thread_id, request_id)); -} - -void CacheStorageListener::OnCacheStorageMatch( - int thread_id, - int request_id, - const GURL& origin, - const ServiceWorkerFetchRequest& request, - const CacheStorageCacheQueryParams& match_params) { - TRACE_EVENT0("CacheStorage", "CacheStorageListener::OnCacheStorageMatch"); - - scoped_ptr<ServiceWorkerFetchRequest> scoped_request( - new ServiceWorkerFetchRequest(request.url, request.method, - request.headers, request.referrer, - request.is_reload)); - - if (match_params.cache_name.empty()) { - context_->cache_manager()->MatchAllCaches( - origin, scoped_request.Pass(), - base::Bind(&CacheStorageListener::OnCacheStorageMatchCallback, - weak_factory_.GetWeakPtr(), thread_id, request_id)); - return; - } - context_->cache_manager()->MatchCache( - origin, base::UTF16ToUTF8(match_params.cache_name), scoped_request.Pass(), - base::Bind(&CacheStorageListener::OnCacheStorageMatchCallback, - weak_factory_.GetWeakPtr(), thread_id, request_id)); -} - void CacheStorageListener::OnCacheMatch( int thread_id, int request_id, @@ -297,90 +193,6 @@ dispatcher_->Send(message); } -void CacheStorageListener::OnCacheStorageHasCallback( - int thread_id, - int request_id, - bool has_cache, - CacheStorage::CacheStorageError error) { - if (error != CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) { - Send(new CacheStorageMsg_CacheStorageHasError( - thread_id, request_id, ToWebServiceWorkerCacheError(error))); - return; - } - if (!has_cache) { - Send(new CacheStorageMsg_CacheStorageHasError( - thread_id, request_id, blink::WebServiceWorkerCacheErrorNotFound)); - return; - } - Send(new CacheStorageMsg_CacheStorageHasSuccess(thread_id, request_id)); -} - -void CacheStorageListener::OnCacheStorageOpenCallback( - int thread_id, - int request_id, - const scoped_refptr<CacheStorageCache>& cache, - CacheStorage::CacheStorageError error) { - if (error != CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) { - Send(new CacheStorageMsg_CacheStorageOpenError( - thread_id, request_id, ToWebServiceWorkerCacheError(error))); - return; - } - CacheID cache_id = StoreCacheReference(cache); - Send(new CacheStorageMsg_CacheStorageOpenSuccess(thread_id, request_id, - cache_id)); -} - -void CacheStorageListener::OnCacheStorageDeleteCallback( - int thread_id, - int request_id, - bool deleted, - CacheStorage::CacheStorageError error) { - if (!deleted || error != CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) { - Send(new CacheStorageMsg_CacheStorageDeleteError( - thread_id, request_id, ToWebServiceWorkerCacheError(error))); - return; - } - Send(new CacheStorageMsg_CacheStorageDeleteSuccess(thread_id, request_id)); -} - -void CacheStorageListener::OnCacheStorageKeysCallback( - int thread_id, - int request_id, - const std::vector<std::string>& strings, - CacheStorage::CacheStorageError error) { - if (error != CacheStorage::CACHE_STORAGE_ERROR_NO_ERROR) { - Send(new CacheStorageMsg_CacheStorageKeysError( - thread_id, request_id, ToWebServiceWorkerCacheError(error))); - return; - } - - std::vector<base::string16> string16s; - for (size_t i = 0, max = strings.size(); i < max; ++i) { - string16s.push_back(base::UTF8ToUTF16(strings[i])); - } - Send(new CacheStorageMsg_CacheStorageKeysSuccess(thread_id, request_id, - string16s)); -} - -void CacheStorageListener::OnCacheStorageMatchCallback( - int thread_id, - int request_id, - CacheStorageCache::ErrorType error, - scoped_ptr<ServiceWorkerResponse> response, - scoped_ptr<storage::BlobDataHandle> blob_data_handle) { - if (error != CacheStorageCache::ERROR_TYPE_OK) { - Send(new CacheStorageMsg_CacheStorageMatchError( - thread_id, request_id, CacheErrorToWebServiceWorkerCacheError(error))); - return; - } - - if (blob_data_handle) - StoreBlobDataHandle(blob_data_handle.Pass()); - - Send(new CacheStorageMsg_CacheStorageMatchSuccess(thread_id, request_id, - *response)); -} - void CacheStorageListener::OnCacheMatchCallback( int thread_id, int request_id,
diff --git a/content/browser/cache_storage/cache_storage_listener.h b/content/browser/cache_storage/cache_storage_listener.h index a60e7a681..f13b40f7 100644 --- a/content/browser/cache_storage/cache_storage_listener.h +++ b/content/browser/cache_storage/cache_storage_listener.h
@@ -32,34 +32,6 @@ bool OnMessageReceived(const IPC::Message& message); private: - // The message receiver functions for the CacheStorage API: - void OnCacheStorageGet(int thread_id, - int request_id, - const GURL& origin, - const base::string16& cache_name); - void OnCacheStorageHas(int thread_id, - int request_id, - const GURL& origin, - const base::string16& cache_name); - void OnCacheStorageCreate(int thread_id, - int request_id, - const GURL& origin, - const base::string16& cache_name); - void OnCacheStorageOpen(int thread_id, - int request_id, - const GURL& origin, - const base::string16& cache_name); - void OnCacheStorageDelete(int thread_id, - int request_id, - const GURL& origin, - const base::string16& cache_name); - void OnCacheStorageKeys(int thread_id, int request_id, const GURL& origin); - void OnCacheStorageMatch(int thread_id, - int request_id, - const GURL& origin, - const ServiceWorkerFetchRequest& request, - const CacheStorageCacheQueryParams& match_params); - // The message receiver functions for the Cache API: void OnCacheMatch(int thread_id, int request_id, @@ -84,6 +56,8 @@ void OnBlobDataHandled(const std::string& uuid); private: + friend class CacheStorageDispatcherHost; + typedef int32_t CacheID; // TODO(jkarlin): Bump to 64 bit. typedef std::map<CacheID, scoped_refptr<CacheStorageCache>> IDToCacheMap; typedef std::map<std::string, std::list<storage::BlobDataHandle>> @@ -91,39 +65,6 @@ void Send(IPC::Message* message); - // CacheStorageManager callbacks - void OnCacheStorageGetCallback(int thread_id, - int request_id, - const scoped_refptr<CacheStorageCache>& cache, - CacheStorage::CacheStorageError error); - void OnCacheStorageHasCallback(int thread_id, - int request_id, - bool has_cache, - CacheStorage::CacheStorageError error); - void OnCacheStorageCreateCallback( - int thread_id, - int request_id, - const scoped_refptr<CacheStorageCache>& cache, - CacheStorage::CacheStorageError error); - void OnCacheStorageOpenCallback(int thread_id, - int request_id, - const scoped_refptr<CacheStorageCache>& cache, - CacheStorage::CacheStorageError error); - void OnCacheStorageDeleteCallback(int thread_id, - int request_id, - bool deleted, - CacheStorage::CacheStorageError error); - void OnCacheStorageKeysCallback(int thread_id, - int request_id, - const std::vector<std::string>& strings, - CacheStorage::CacheStorageError error); - void OnCacheStorageMatchCallback( - int thread_id, - int request_id, - CacheStorageCache::ErrorType error, - scoped_ptr<ServiceWorkerResponse> response, - scoped_ptr<storage::BlobDataHandle> blob_data_handle); - // Cache callbacks void OnCacheMatchCallback( int thread_id,
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc index f2d1b39..7d85348 100644 --- a/content/browser/compositor/gpu_process_transport_factory.cc +++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -256,7 +256,7 @@ context_provider = ContextProviderCommandBuffer::Create( GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host, data->surface_id), - "Compositor"); + BROWSER_COMPOSITOR_ONSCREEN_CONTEXT); if (context_provider && !context_provider->BindToCurrentThread()) context_provider = nullptr; } @@ -504,7 +504,7 @@ // context so that skia and gl_helper don't step on each other. shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create( GpuProcessTransportFactory::CreateOffscreenCommandBufferContext(), - "Offscreen-MainThread"); + BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT); if (shared_main_thread_contexts_.get()) { shared_main_thread_contexts_->SetLostContextCallback(
diff --git a/content/browser/compositor/reflector_impl_unittest.cc b/content/browser/compositor/reflector_impl_unittest.cc index 2f0c299..867a9de1 100644 --- a/content/browser/compositor/reflector_impl_unittest.cc +++ b/content/browser/compositor/reflector_impl_unittest.cc
@@ -91,8 +91,7 @@ gfx::Size SurfaceSize() const override { return gfx::Size(256, 256); } }; -const gfx::Rect kSubRect = gfx::Rect(0, 0, 64, 64); -const SkIRect kSkSubRect = SkIRect::MakeXYWH(0, 0, 64, 64); +const gfx::Rect kSubRect(0, 0, 64, 64); } // namespace @@ -161,10 +160,10 @@ SetUpReflector(); UpdateTexture(); EXPECT_TRUE(mirroring_layer_->TextureFlipped()); - EXPECT_EQ(SkRegion(SkIRect::MakeXYWH( - 0, output_surface_->SurfaceSize().height() - kSubRect.height(), - kSubRect.width(), kSubRect.height())), - mirroring_layer_->damaged_region()); + gfx::Rect expected_rect = + kSubRect + gfx::Vector2d(0, output_surface_->SurfaceSize().height()) - + gfx::Vector2d(0, kSubRect.height()); + EXPECT_EQ(expected_rect, mirroring_layer_->damaged_region()); } TEST_F(ReflectorImplTest, CheckInvertedOutputSurface) { @@ -172,7 +171,7 @@ SetUpReflector(); UpdateTexture(); EXPECT_FALSE(mirroring_layer_->TextureFlipped()); - EXPECT_EQ(SkRegion(kSkSubRect), mirroring_layer_->damaged_region()); + EXPECT_EQ(kSubRect, mirroring_layer_->damaged_region()); } #if defined(USE_OZONE)
diff --git a/content/browser/compositor/software_output_device_win.h b/content/browser/compositor/software_output_device_win.h index 85873fb..a171e8e0 100644 --- a/content/browser/compositor/software_output_device_win.h +++ b/content/browser/compositor/software_output_device_win.h
@@ -23,13 +23,13 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice { public: explicit SoftwareOutputDeviceWin(ui::Compositor* compositor); - virtual ~SoftwareOutputDeviceWin(); + ~SoftwareOutputDeviceWin() override; - virtual void Resize(const gfx::Size& viewport_pixel_size, - float scale_factor) override; - virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override; - virtual void EndPaint(cc::SoftwareFrameData* frame_data) override; - virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) override; + void Resize(const gfx::Size& viewport_pixel_size, + float scale_factor) override; + SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override; + void EndPaint(cc::SoftwareFrameData* frame_data) override; + void CopyToPixels(const gfx::Rect& rect, void* pixels) override; private: HWND hwnd_;
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn index a44c55ad..e65cfe7 100644 --- a/content/browser/devtools/BUILD.gn +++ b/content/browser/devtools/BUILD.gn
@@ -8,7 +8,6 @@ group("resources") { deps = [ ":devtools_resources", - ":devtools_protocol_handler", ] } @@ -36,7 +35,7 @@ } action("gen_devtools_protocol_handler") { - visibility = [ ":devtools_protocol_handler" ] + visibility = [ "//content/browser" ] script = "//content/browser/devtools/protocol/" + "devtools_protocol_handler_generator.py" @@ -56,8 +55,3 @@ args = rebase_path(inputs, root_build_dir) + rebase_path(outputs, root_build_dir) } - -source_set("devtools_protocol_handler") { - visibility = [ ":resources" ] - sources = get_target_outputs(":gen_devtools_protocol_handler") -}
diff --git a/content/browser/devtools/devtools_manager_unittest.cc b/content/browser/devtools/devtools_manager_unittest.cc index 5231d5e1..7dcb3a7 100644 --- a/content/browser/devtools/devtools_manager_unittest.cc +++ b/content/browser/devtools/devtools_manager_unittest.cc
@@ -251,9 +251,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int pending_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate( - contents()->GetMainFrame(), 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(contents()->GetMainFrame(), 1, pending_id, true, + url, ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); TestDevToolsClientHost client_host; @@ -272,9 +273,10 @@ // Interrupt pending navigation and navigate back to the original site. controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + pending_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate( - contents()->GetMainFrame(), 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(contents()->GetMainFrame(), 1, pending_id, false, + url, ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(client_host.agent_host(), DevToolsAgentHost::GetOrCreateFor(web_contents()).get());
diff --git a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py index 3f539ec..cc2aa13 100755 --- a/content/browser/devtools/protocol/devtools_protocol_handler_generator.py +++ b/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -207,7 +207,7 @@ class Client : public DevToolsProtocolClient { public: explicit Client(const RawMessageCallback& raw_message_callback); - virtual ~Client(); + ~Client() override; ${methods}\ };
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc index 6f426f4..887300c6 100644 --- a/content/browser/devtools/protocol/service_worker_handler.cc +++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -170,11 +170,11 @@ } } -Response CreateContextErrorResoponse() { +Response CreateContextErrorResponse() { return Response::InternalError("Could not connect to the context"); } -Response CreateInvalidVersionIdErrorResoponse() { +Response CreateInvalidVersionIdErrorResponse() { return Response::InternalError("Invalid version ID"); } @@ -302,7 +302,7 @@ if (!enabled_) return Response::OK(); if (!context_) - return CreateContextErrorResoponse(); + return CreateContextErrorResponse(); context_->UnregisterServiceWorker(GURL(scope_url), base::Bind(&ResultNoOp)); return Response::OK(); } @@ -311,7 +311,7 @@ if (!enabled_) return Response::OK(); if (!context_) - return CreateContextErrorResoponse(); + return CreateContextErrorResponse(); context_->StartServiceWorker(GURL(scope_url), base::Bind(&StatusNoOp)); return Response::OK(); } @@ -320,10 +320,10 @@ if (!enabled_) return Response::OK(); if (!context_) - return CreateContextErrorResoponse(); + return CreateContextErrorResponse(); int64 id = 0; if (!base::StringToInt64(version_id, &id)) - return CreateInvalidVersionIdErrorResoponse(); + return CreateInvalidVersionIdErrorResponse(); BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(&StopServiceWorkerOnIO, context_, id)); return Response::OK(); @@ -334,7 +334,7 @@ if (!enabled_) return Response::OK(); if (!context_) - return CreateContextErrorResoponse(); + return CreateContextErrorResponse(); context_->UpdateRegistration(GURL(scope_url)); return Response::OK(); } @@ -343,11 +343,11 @@ if (!enabled_) return Response::OK(); if (!context_) - return CreateContextErrorResoponse(); + return CreateContextErrorResponse(); int64 id = 0; if (!base::StringToInt64(version_id, &id)) - return CreateInvalidVersionIdErrorResoponse(); + return CreateInvalidVersionIdErrorResponse(); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(&GetDevToolsRouteInfoOnIO, context_, id, @@ -356,6 +356,19 @@ return Response::OK(); } +Response ServiceWorkerHandler::SkipWaiting(const std::string& version_id) { + if (!enabled_) + return Response::OK(); + if (!context_) + return CreateContextErrorResponse(); + + int64 id = 0; + if (!base::StringToInt64(version_id, &id)) + return CreateInvalidVersionIdErrorResponse(); + context_->SimulateSkipWaiting(id); + return Response::OK(); +} + Response ServiceWorkerHandler::SetDebugOnStart(bool debug_on_start) { ServiceWorkerDevToolsManager::GetInstance() ->set_debug_service_worker_on_start(debug_on_start); @@ -369,10 +382,10 @@ if (!enabled_) return Response::OK(); if (!render_frame_host_) - return CreateContextErrorResoponse(); + return CreateContextErrorResponse(); int64 id = 0; if (!base::StringToInt64(registration_id, &id)) - return CreateInvalidVersionIdErrorResoponse(); + return CreateInvalidVersionIdErrorResponse(); BrowserContext::DeliverPushMessage( render_frame_host_->GetProcess()->GetBrowserContext(), GURL(origin), id, data, base::Bind(&PushDeliveryNoOp));
diff --git a/content/browser/devtools/protocol/service_worker_handler.h b/content/browser/devtools/protocol/service_worker_handler.h index 57a2a210..e277871 100644 --- a/content/browser/devtools/protocol/service_worker_handler.h +++ b/content/browser/devtools/protocol/service_worker_handler.h
@@ -54,6 +54,7 @@ Response StopWorker(const std::string& version_id); Response UpdateRegistration(const std::string& scope_url); Response InspectWorker(const std::string& version_id); + Response SkipWaiting(const std::string& version_id); Response SetDebugOnStart(bool debug_on_start); Response DeliverPushMessage(const std::string& origin, const std::string& registration_id,
diff --git a/content/browser/frame_host/debug_urls.cc b/content/browser/frame_host/debug_urls.cc index 29915ef9..3f6769ba 100644 --- a/content/browser/frame_host/debug_urls.cc +++ b/content/browser/frame_host/debug_urls.cc
@@ -15,6 +15,7 @@ #include "base/debug/profiler.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" +#include "base/threading/thread_restrictions.h" #include "cc/base/switches.h" #include "content/browser/gpu/gpu_process_host_ui_shim.h" #include "content/public/browser/browser_thread.h" @@ -150,6 +151,11 @@ } // namespace +class ScopedAllowWaitForDebugURL { + private: + base::ThreadRestrictions::ScopedAllowWait wait; +}; + bool HandleDebugURL(const GURL& url, ui::PageTransition transition) { // Ensure that the user explicitly navigated to this URL, unless // kEnableGpuBenchmarking is enabled by Telemetry. @@ -177,6 +183,7 @@ } if (url == GURL(kChromeUIBrowserUIHang)) { + ScopedAllowWaitForDebugURL allow_wait; base::WaitableEvent(false, false).Wait(); return true; }
diff --git a/content/browser/frame_host/frame_tree.cc b/content/browser/frame_host/frame_tree.cc index 332524e7..5ed55e6 100644 --- a/content/browser/frame_host/frame_tree.cc +++ b/content/browser/frame_host/frame_tree.cc
@@ -23,7 +23,7 @@ namespace { // Used with FrameTree::ForEach() to search for the FrameTreeNode -// corresponding to |frame_tree_node_id| whithin a specific FrameTree. +// corresponding to |frame_tree_node_id| within a specific FrameTree. bool FrameTreeNodeForId(int64 frame_tree_node_id, FrameTreeNode** out_node, FrameTreeNode* node) { @@ -35,6 +35,19 @@ return true; } +// Used with FrameTree::ForEach() to search for the FrameTreeNode with the given +// |name| within a specific FrameTree. +bool FrameTreeNodeForName(const std::string& name, + FrameTreeNode** out_node, + FrameTreeNode* node) { + if (node->frame_name() == name) { + *out_node = node; + // Terminate iteration once the node has been found. + return false; + } + return true; +} + bool CreateProxyForSiteInstance(const scoped_refptr<SiteInstance>& instance, FrameTreeNode* node) { // If a new frame is created in the current SiteInstance, other frames in @@ -104,7 +117,7 @@ } FrameTreeNode* FrameTree::FindByID(int64 frame_tree_node_id) { - FrameTreeNode* node = NULL; + FrameTreeNode* node = nullptr; ForEach(base::Bind(&FrameTreeNodeForId, frame_tree_node_id, &node)); return node; } @@ -126,12 +139,21 @@ return result; } - return NULL; + return nullptr; +} + +FrameTreeNode* FrameTree::FindByName(const std::string& name) { + if (name.empty()) + return root_.get(); + + FrameTreeNode* node = nullptr; + ForEach(base::Bind(&FrameTreeNodeForName, name, &node)); + return node; } void FrameTree::ForEach( const base::Callback<bool(FrameTreeNode*)>& on_node) const { - ForEach(on_node, NULL); + ForEach(on_node, nullptr); } void FrameTree::ForEach( @@ -213,11 +235,6 @@ ForEach(base::Bind(&CreateProxyForSiteInstance, instance), source); } -void FrameTree::ResetForMainFrameSwap() { - root_->ResetForNewProcess(); - focused_frame_tree_node_id_ = -1; -} - RenderFrameHostImpl* FrameTree::GetMainFrame() const { return root_->current_frame_host(); } @@ -277,7 +294,7 @@ render_view_host_map_.find(site_instance->GetId()); // TODO(creis): Mirror the frame tree so this check can't fail. if (iter == render_view_host_map_.end()) - return NULL; + return nullptr; return iter->second; } @@ -336,6 +353,9 @@ } void FrameTree::FrameRemoved(FrameTreeNode* frame) { + if (frame->frame_tree_node_id() == focused_frame_tree_node_id_) + focused_frame_tree_node_id_ = -1; + // No notification for the root frame. if (!frame->parent()) { CHECK_EQ(frame, root_.get());
diff --git a/content/browser/frame_host/frame_tree.h b/content/browser/frame_host/frame_tree.h index ce34bc2..179fcb3b 100644 --- a/content/browser/frame_host/frame_tree.h +++ b/content/browser/frame_host/frame_tree.h
@@ -59,6 +59,12 @@ // Returns the FrameTreeNode with the given renderer-specific |routing_id|. FrameTreeNode* FindByRoutingID(int process_id, int routing_id); + // Returns the first frame in this tree with the given |name|, or the main + // frame if |name| is empty. + // Note that this does NOT support pseudo-names like _self, _top, and _blank, + // nor searching other FrameTrees (unlike blink::WebView::findFrameByName). + FrameTreeNode* FindByName(const std::string& name); + // Executes |on_node| on each node in the frame tree. If |on_node| returns // false, terminates the iteration immediately. Returning false is useful // if |on_node| is just doing a search over the tree. The iteration proceeds @@ -85,13 +91,6 @@ FrameTreeNode* source, SiteInstance* site_instance); - // Clears process specific-state after a main frame process swap. - // This destroys most of the frame tree but retains the root node so that - // navigation state may be kept on it between process swaps. Used to - // support bookkeeping for top-level navigations. - // TODO(creis): Look into how we can remove the need for this method. - void ResetForMainFrameSwap(); - // Convenience accessor for the main frame's RenderFrameHostImpl. RenderFrameHostImpl* GetMainFrame() const; @@ -143,6 +142,7 @@ bool IsLoading(); private: + FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest, RemoveFocusedFrame); typedef base::hash_map<int, RenderViewHostImpl*> RenderViewHostMap; typedef std::multimap<int, RenderViewHostImpl*> RenderViewHostMultiMap;
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc index 1567980..cabc819 100644 --- a/content/browser/frame_host/frame_tree_node.cc +++ b/content/browser/frame_host/frame_tree_node.cc
@@ -135,11 +135,16 @@ old_children.clear(); // May notify observers. } -void FrameTreeNode::SetFrameName(const std::string& name) { - replication_state_.name = name; +void FrameTreeNode::SetCurrentOrigin(const url::Origin& origin) { + if (!origin.IsSameAs(replication_state_.origin)) + render_manager_.OnDidUpdateOrigin(origin); + replication_state_.origin = origin; +} - // Notify this frame's proxies about the updated name. - render_manager_.OnDidUpdateName(name); +void FrameTreeNode::SetFrameName(const std::string& name) { + if (name != replication_state_.name) + render_manager_.OnDidUpdateName(name); + replication_state_.name = name; } bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h index 7e1add123..bcb77802 100644 --- a/content/browser/frame_host/frame_tree_node.h +++ b/content/browser/frame_host/frame_tree_node.h
@@ -93,10 +93,10 @@ current_url_ = url; } - void set_current_origin(const url::Origin& origin) { - replication_state_.origin = origin; - } + // Set the current origin and notify proxies about the update. + void SetCurrentOrigin(const url::Origin& origin); + // Set the current name and notify proxies about the update. void SetFrameName(const std::string& name); SandboxFlags effective_sandbox_flags() { return effective_sandbox_flags_; }
diff --git a/content/browser/frame_host/frame_tree_unittest.cc b/content/browser/frame_host/frame_tree_unittest.cc index f2481414..7f43f68 100644 --- a/content/browser/frame_host/frame_tree_unittest.cc +++ b/content/browser/frame_host/frame_tree_unittest.cc
@@ -201,6 +201,49 @@ GetTreeState(frame_tree)); } +// Ensure frames can be found by frame_tree_node_id, routing ID, or name. +TEST_F(FrameTreeTest, FindFrames) { + // Add a few child frames to the main frame. + FrameTree* frame_tree = contents()->GetFrameTree(); + FrameTreeNode* root = frame_tree->root(); + main_test_rfh()->OnCreateChildFrame(22, "child0", SandboxFlags::NONE); + main_test_rfh()->OnCreateChildFrame(23, "child1", SandboxFlags::NONE); + main_test_rfh()->OnCreateChildFrame(24, std::string(), SandboxFlags::NONE); + FrameTreeNode* child0 = root->child_at(0); + FrameTreeNode* child1 = root->child_at(1); + FrameTreeNode* child2 = root->child_at(2); + + // Add one grandchild frame. + child1->current_frame_host()->OnCreateChildFrame(33, "grandchild", + SandboxFlags::NONE); + FrameTreeNode* grandchild = child1->child_at(0); + + // Ensure they can be found by FTN id. + EXPECT_EQ(root, frame_tree->FindByID(root->frame_tree_node_id())); + EXPECT_EQ(child0, frame_tree->FindByID(child0->frame_tree_node_id())); + EXPECT_EQ(child1, frame_tree->FindByID(child1->frame_tree_node_id())); + EXPECT_EQ(child2, frame_tree->FindByID(child2->frame_tree_node_id())); + EXPECT_EQ(grandchild, frame_tree->FindByID(grandchild->frame_tree_node_id())); + EXPECT_EQ(nullptr, frame_tree->FindByID(-1)); + + // Ensure they can be found by routing id. + int process_id = main_test_rfh()->GetProcess()->GetID(); + EXPECT_EQ(root, frame_tree->FindByRoutingID(process_id, + main_test_rfh()->GetRoutingID())); + EXPECT_EQ(child0, frame_tree->FindByRoutingID(process_id, 22)); + EXPECT_EQ(child1, frame_tree->FindByRoutingID(process_id, 23)); + EXPECT_EQ(child2, frame_tree->FindByRoutingID(process_id, 24)); + EXPECT_EQ(grandchild, frame_tree->FindByRoutingID(process_id, 33)); + EXPECT_EQ(nullptr, frame_tree->FindByRoutingID(process_id, 37)); + + // Ensure they can be found by name, if they have one. + EXPECT_EQ(root, frame_tree->FindByName(std::string())); + EXPECT_EQ(child0, frame_tree->FindByName("child0")); + EXPECT_EQ(child1, frame_tree->FindByName("child1")); + EXPECT_EQ(grandchild, frame_tree->FindByName("grandchild")); + EXPECT_EQ(nullptr, frame_tree->FindByName("no such frame")); +} + // Do some simple manipulations of the frame tree, making sure that // WebContentsObservers see a consistent view of the tree as we go. TEST_F(FrameTreeTest, ObserverWalksTreeDuringFrameCreation) {
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc index 55811739..455ac74 100644 --- a/content/browser/frame_host/interstitial_page_impl.cc +++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -245,7 +245,6 @@ DCHECK(!render_view_host_); render_view_host_ = CreateRenderViewHost(); - render_view_host_->AttachToFrameTree(); CreateWebContentsView(); std::string data_url = "data:text/html;charset=utf-8," + @@ -295,7 +294,7 @@ base::Bind(&InterstitialPageImpl::Shutdown, weak_ptr_factory_.GetWeakPtr())); render_view_host_ = NULL; - frame_tree_.ResetForMainFrameSwap(); + frame_tree_.root()->ResetForNewProcess(); controller_->delegate()->DetachInterstitialPage(); // Let's revert to the original title if necessary. NavigationEntry* entry = controller_->GetVisibleEntry();
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h index f8aa8a7..a509c1b 100644 --- a/content/browser/frame_host/interstitial_page_impl.h +++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -145,7 +145,7 @@ bool* is_keyboard_shortcut) override; void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override; #if defined(OS_WIN) - virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() override; + gfx::NativeViewAccessible GetParentNativeViewAccessible() override; #endif bool enabled() const { return enabled_; }
diff --git a/content/browser/frame_host/navigation_controller_delegate.h b/content/browser/frame_host/navigation_controller_delegate.h index e578a84e..97896890 100644 --- a/content/browser/frame_host/navigation_controller_delegate.h +++ b/content/browser/frame_host/navigation_controller_delegate.h
@@ -15,6 +15,7 @@ struct LoadCommittedDetails; struct LoadNotificationDetails; struct NativeWebKeyboardEvent; +class FrameTree; class InterstitialPage; class InterstitialPageImpl; class RenderFrameHost; @@ -46,6 +47,7 @@ // Methods from WebContentsImpl that NavigationControllerImpl needs to // call. + virtual FrameTree* GetFrameTree() = 0; virtual void NotifyBeforeFormRepostWarningShow() = 0; virtual void NotifyNavigationEntryCommitted( const LoadCommittedDetails& load_details) = 0;
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 01ab901..1953f512 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -731,6 +731,13 @@ params.is_renderer_initiated, params.extra_headers, browser_context_)); + if (!params.frame_name.empty()) { + // This is only used for navigating subframes in tests. + FrameTreeNode* named_frame = + delegate_->GetFrameTree()->FindByName(params.frame_name); + if (named_frame) + entry->set_frame_tree_node_id(named_frame->frame_tree_node_id()); + } if (params.frame_tree_node_id != -1) entry->set_frame_tree_node_id(params.frame_tree_node_id); entry->set_source_site_instance( @@ -745,7 +752,6 @@ entry->SetIsOverridingUserAgent(override); entry->set_transferred_global_request_id( params.transferred_global_request_id); - entry->SetFrameToNavigate(params.frame_name); #if defined(OS_ANDROID) if (params.intent_received_timestamp > 0) { @@ -813,6 +819,13 @@ // Do navigation-type specific actions. These will make and commit an entry. details->type = ClassifyNavigation(rfh, params); + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) { + // For site-per-process, both ClassifyNavigation methods get it wrong (see + // http://crbug.com/464014) so don't worry about a mismatch if that's the + // case. + DCHECK_EQ(details->type, ClassifyNavigationWithoutPageID(rfh, params)); + } // is_in_page must be computed before the entry gets committed. details->is_in_page = AreURLsInPageNavigation(rfh->GetLastCommittedURL(), @@ -1057,6 +1070,121 @@ return NAVIGATION_TYPE_EXISTING_PAGE; } +NavigationType NavigationControllerImpl::ClassifyNavigationWithoutPageID( + RenderFrameHostImpl* rfh, + const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const { + if (params.did_create_new_entry) { + // A new entry. We may or may not have a pending entry for the page, and + // this may or may not be the main frame. + if (ui::PageTransitionIsMainFrame(params.transition)) { + // TODO(avi): I want to use |if (!rfh->GetParent())| here but lots of unit + // tests fake auto subframe commits by sending the main frame a + // PAGE_TRANSITION_AUTO_SUBFRAME transition. Fix those, and adjust here. + return NAVIGATION_TYPE_NEW_PAGE; + } + + // When this is a new subframe navigation, we should have a committed page + // in which it's a subframe. This may not be the case when an iframe is + // navigated on a popup navigated to about:blank (the iframe would be + // written into the popup by script on the main page). For these cases, + // there isn't any navigation stuff we can do, so just ignore it. + if (!GetLastCommittedEntry()) + return NAVIGATION_TYPE_NAV_IGNORE; + + // Valid subframe navigation. + return NAVIGATION_TYPE_NEW_SUBFRAME; + } + + // We only clear the session history when navigating to a new page. + DCHECK(!params.history_list_was_cleared); + + if (!ui::PageTransitionIsMainFrame(params.transition)) { + // All manual subframes would be did_create_new_entry and handled above, so + // we know this is auto. + if (GetLastCommittedEntry()) { + return NAVIGATION_TYPE_AUTO_SUBFRAME; + } else { + // We ignore subframes created in non-committed pages; we'd appreciate if + // people stopped doing that. + return NAVIGATION_TYPE_NAV_IGNORE; + } + } + + if (params.nav_entry_id == 0) { + // This is a renderer-initiated navigation (nav_entry_id == 0), but didn't + // create a new page. + + // Just like above in the did_create_new_entry case, it's possible to + // scribble onto an uncommitted page. Again, there isn't any navigation + // stuff that we can do, so ignore it here as well. + if (!GetLastCommittedEntry()) + return NAVIGATION_TYPE_NAV_IGNORE; + + if (params.was_within_same_page) { + // This is history.replaceState(), which is renderer-initiated yet within + // the same page. + return NAVIGATION_TYPE_IN_PAGE; + } else { + // This is history.reload() or a client-side redirect. + return NAVIGATION_TYPE_EXISTING_PAGE; + } + } + + if (pending_entry_ && pending_entry_index_ == -1 && + pending_entry_->GetUniqueID() == params.nav_entry_id) { + // In this case, we have a pending entry for a load of a new URL but Blink + // didn't do a new navigation (params.did_create_new_entry). This happens + // when you press enter in the URL bar to reload. We will create a pending + // entry, but Blink will convert it to a reload since it's the same page and + // not create a new entry for it (the user doesn't want to have a new + // back/forward entry when they do this). Therefore we want to just ignore + // the pending entry and go back to where we were (the "existing entry"). + return NAVIGATION_TYPE_SAME_PAGE; + } + + if (params.intended_as_new_entry) { + // This was intended to be a navigation to a new entry but the pending entry + // got cleared in the meanwhile. Classify as EXISTING_PAGE because we may or + // may not have a pending entry. + return NAVIGATION_TYPE_EXISTING_PAGE; + } + + if (params.url_is_unreachable && failed_pending_entry_id_ != 0 && + params.nav_entry_id == failed_pending_entry_id_) { + // If the renderer was going to a new pending entry that got cleared because + // of an error, this is the case of the user trying to retry a failed load + // by pressing return. Classify as EXISTING_PAGE because we probably don't + // have a pending entry. + return NAVIGATION_TYPE_EXISTING_PAGE; + } + + // Now we know that the notification is for an existing page. Find that entry. + int existing_entry_index = GetEntryIndexWithUniqueID(params.nav_entry_id); + if (existing_entry_index == -1) { + // The page was not found. It could have been pruned because of the limit on + // back/forward entries (not likely since we'll usually tell it to navigate + // to such entries). It could also mean that the renderer is smoking crack. + // TODO(avi): Crash the renderer like we do in the old ClassifyNavigation? + NOTREACHED() << "Could not find nav entry with id " << params.nav_entry_id; + return NAVIGATION_TYPE_NAV_IGNORE; + } + + // Any top-level navigations with the same base (minus the reference fragment) + // are in-page navigations. (We weeded out subframe navigations above.) Most + // of the time this doesn't matter since Blink doesn't tell us about subframe + // navigations that don't actually navigate, but it can happen when there is + // an encoding override (it always sends a navigation request). + NavigationEntryImpl* existing_entry = entries_[existing_entry_index].get(); + if (AreURLsInPageNavigation(existing_entry->GetURL(), params.url, + params.was_within_same_page, rfh)) { + return NAVIGATION_TYPE_IN_PAGE; + } + + // Since we weeded out "new" navigations above, we know this is an existing + // (back/forward) navigation. + return NAVIGATION_TYPE_EXISTING_PAGE; +} + void NavigationControllerImpl::RendererDidNavigateToNewPage( RenderFrameHostImpl* rfh, const FrameHostMsg_DidCommitProvisionalLoad_Params& params, @@ -1818,6 +1946,15 @@ return -1; } +int NavigationControllerImpl::GetEntryIndexWithUniqueID( + int nav_entry_id) const { + for (int i = static_cast<int>(entries_.size()) - 1; i >= 0; --i) { + if (entries_[i]->GetUniqueID() == nav_entry_id) + return i; + } + return -1; +} + NavigationEntryImpl* NavigationControllerImpl::GetTransientEntry() const { if (transient_entry_index_ == -1) return NULL;
diff --git a/content/browser/frame_host/navigation_controller_impl.h b/content/browser/frame_host/navigation_controller_impl.h index da3bbd3..85469401 100644 --- a/content/browser/frame_host/navigation_controller_impl.h +++ b/content/browser/frame_host/navigation_controller_impl.h
@@ -107,6 +107,9 @@ int GetEntryIndexWithPageID(SiteInstance* instance, int32 page_id) const; + // Return the index of the entry with the given unique id, or -1 if not found. + int GetEntryIndexWithUniqueID(int nav_entry_id) const; + // Return the entry with the corresponding instance and page_id, or NULL if // not found. NavigationEntryImpl* GetEntryWithPageID( @@ -231,6 +234,12 @@ NavigationType ClassifyNavigation( RenderFrameHostImpl* rfh, const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const; + // This does the same as above (hopefully), but does so without any use of + // deprecated page id values. Once it bakes and is verified to behave the + // same, it will replace it. http://crbug.com/369661 + NavigationType ClassifyNavigationWithoutPageID( + RenderFrameHostImpl* rfh, + const FrameHostMsg_DidCommitProvisionalLoad_Params& params) const; // Causes the controller to load the specified entry. The function assumes // ownership of the pointer since it is put in the navigation list.
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index 7a89b26c..01d1c34 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -1070,4 +1070,96 @@ ResourceDispatcherHost::Get()->SetDelegate(nullptr); } +namespace { + +class FailureWatcher : public WebContentsObserver { + public: + // Observes failure for the specified |node|. + explicit FailureWatcher(FrameTreeNode* node) + : WebContentsObserver( + node->current_frame_host()->delegate()->GetAsWebContents()), + frame_tree_node_id_(node->frame_tree_node_id()), + message_loop_runner_(new MessageLoopRunner) {} + + void Wait() { + message_loop_runner_->Run(); + } + + private: + void DidFailLoad(RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code, + const base::string16& error_description) override { + RenderFrameHostImpl* rfh = + static_cast<RenderFrameHostImpl*>(render_frame_host); + if (rfh->frame_tree_node()->frame_tree_node_id() != frame_tree_node_id_) + return; + + message_loop_runner_->Quit(); + } + + void DidFailProvisionalLoad( + RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code, + const base::string16& error_description) override { + RenderFrameHostImpl* rfh = + static_cast<RenderFrameHostImpl*>(render_frame_host); + if (rfh->frame_tree_node()->frame_tree_node_id() != frame_tree_node_id_) + return; + + message_loop_runner_->Quit(); + } + + // The id of the FrameTreeNode whose navigations to observe. + int frame_tree_node_id_; + + // The MessageLoopRunner used to spin the message loop. + scoped_refptr<MessageLoopRunner> message_loop_runner_; +}; + +} // namespace + +IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, + StopCausesFailureDespiteJavaScriptURL) { + NavigationControllerImpl& controller = + static_cast<NavigationControllerImpl&>( + shell()->web_contents()->GetController()); + + FrameTreeNode* root = + static_cast<WebContentsImpl*>(shell()->web_contents())-> + GetFrameTree()->root(); + + // Start with a normal page. + GURL url1(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_1.html")); + EXPECT_TRUE(NavigateToURL(shell(), url1)); + + // Have the user decide to go to a different page which is very slow. + StallDelegate stall_delegate; + ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate); + GURL url2(embedded_test_server()->GetURL( + "/navigation_controller/simple_page_2.html")); + controller.LoadURL(url2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + + // That should be the pending entry. + NavigationEntryImpl* entry = controller.GetPendingEntry(); + ASSERT_NE(nullptr, entry); + EXPECT_EQ(url2, entry->GetURL()); + + // Loading a JavaScript URL shouldn't affect the ability to stop. + { + FailureWatcher watcher(root); + GURL js("javascript:(function(){})()"); + controller.LoadURL(js, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + // This LoadURL ends up purging the pending entry, which is why this is + // tricky. + EXPECT_EQ(nullptr, controller.GetPendingEntry()); + shell()->web_contents()->Stop(); + watcher.Wait(); + } + + ResourceDispatcherHost::Get()->SetDelegate(nullptr); +} + } // namespace content
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index b44a1b0..4a27b9ad 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -317,7 +317,7 @@ main_test_rfh()->SendRendererInitiatedNavigationRequest(urls[0], true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, urls[0]); + main_test_rfh()->SendNavigate(0, 0, true, urls[0]); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; EXPECT_EQ(urls[0], controller.GetVisibleEntry()->GetVirtualURL()); @@ -328,7 +328,7 @@ for (int i = 1; i <= 4; ++i) { main_test_rfh()->SendRendererInitiatedNavigationRequest(urls[i], true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(i, urls[i]); + main_test_rfh()->SendNavigate(i, 0, true, urls[i]); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; EXPECT_EQ(urls[i], controller.GetVisibleEntry()->GetVirtualURL()); @@ -360,11 +360,12 @@ for (int test = 0; test < NUM_TESTS; ++test) { int offset = test_offsets[test]; controller.GoToOffset(offset); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); url_index += offset; // Check that the GoToOffset will land on the expected page. EXPECT_EQ(urls[url_index], controller.GetPendingEntry()->GetVirtualURL()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(url_index, urls[url_index]); + main_test_rfh()->SendNavigate(url_index, entry_id, false, urls[url_index]); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; // Check that we can go to any valid offset into the history. @@ -386,6 +387,7 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); // Creating a pending notification should not have issued any of the // notifications we're listening for. EXPECT_EQ(0U, notifications.size()); @@ -409,7 +411,7 @@ EXPECT_EQ(0U, notifications.size()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -431,6 +433,7 @@ // Load another... controller.LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); // The load should now be pending. EXPECT_EQ(controller.GetEntryCount(), 1); @@ -449,7 +452,7 @@ // Simulate the beforeunload ack for the cross-site transition, and then the // commit. main_test_rfh()->PrepareForCommit(); - contents()->GetPendingMainFrame()->SendNavigate(1, url2); + contents()->GetPendingMainFrame()->SendNavigate(1, entry_id, true, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -489,20 +492,22 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; // Load another... controller.LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); // Simulate the beforeunload ack for the cross-site transition, and then the // commit. main_test_rfh()->PrepareForCommit(); - contents()->GetPendingMainFrame()->SendNavigate(1, url2); + contents()->GetPendingMainFrame()->SendNavigate(1, entry_id, true, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -619,9 +624,10 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(0U, notifications.size()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -631,9 +637,10 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(0U, notifications.size()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, false, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -667,6 +674,8 @@ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 0; + params.nav_entry_id = controller.GetPendingEntry()->GetUniqueID(); + params.did_create_new_entry = true; params.url = url1; params.transition = ui::PAGE_TRANSITION_TYPED; params.is_post = true; @@ -684,7 +693,8 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, controller.GetPendingEntry()->GetUniqueID(), + false, url1); // We should not have produced a new session history entry. ASSERT_EQ(controller.GetVisibleEntry(), entry); @@ -705,9 +715,10 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(0U, notifications.size()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -745,16 +756,17 @@ const GURL kExistingURL1("http://eh"); controller.LoadURL( kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, kExistingURL1); + main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; // Do a new navigation without making a pending one. const GURL kNewURL("http://see"); - main_test_rfh()->NavigateAndCommitRendererInitiated(99, kNewURL); + main_test_rfh()->NavigateAndCommitRendererInitiated(99, true, kNewURL); - // There should no longer be any pending entry, and the third navigation we + // There should no longer be any pending entry, and the second navigation we // just made should be committed. EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -776,8 +788,9 @@ const GURL kExistingURL1("http://eh"); controller.LoadURL( kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, kExistingURL1); + main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -794,7 +807,7 @@ const GURL kNewURL("http://see"); main_test_rfh()->SendRendererInitiatedNavigationRequest(kNewURL, true); main_test_rfh()->PrepareForCommit(); - contents()->GetMainFrame()->SendNavigate(3, kNewURL); + contents()->GetMainFrame()->SendNavigate(3, 0, true, kNewURL); // There should no longer be any pending entry, and the third navigation we // just made should be committed. @@ -817,16 +830,18 @@ const GURL kExistingURL1("http://foo/eh"); controller.LoadURL( kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, kExistingURL1); + main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; const GURL kExistingURL2("http://foo/bee"); controller.LoadURL( kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, kExistingURL2); + main_test_rfh()->SendNavigate(1, entry_id, true, kExistingURL2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -841,9 +856,9 @@ const GURL kNewURL("http://foo/see"); main_test_rfh()->SendRendererInitiatedNavigationRequest(kNewURL, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(3, kNewURL); + main_test_rfh()->SendNavigate(3, 0, true, kNewURL); - // There should no longer be any pending entry, and the third navigation we + // There should no longer be any pending entry, and the new navigation we // just made should be committed. EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -864,10 +879,11 @@ const GURL kExistingURL1("http://privileged"); controller.LoadURL( kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); // Pretend it has bindings so we can tell if we incorrectly copy it. main_test_rfh()->GetRenderViewHost()->AllowBindings(2); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, kExistingURL1); + main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -875,9 +891,10 @@ const GURL kExistingURL2("http://foo/eh"); controller.LoadURL( kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); TestRenderFrameHost* foo_rfh = contents()->GetPendingMainFrame(); - foo_rfh->SendNavigate(1, kExistingURL2); + foo_rfh->SendNavigate(1, entry_id, true, kExistingURL2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -894,9 +911,9 @@ const GURL kNewURL("http://foo/bee"); foo_rfh->SendRendererInitiatedNavigationRequest(kNewURL, true); foo_rfh->PrepareForCommit(); - foo_rfh->SendNavigate(3, kNewURL); + foo_rfh->SendNavigate(3, 0, true, kNewURL); - // There should no longer be any pending entry, and the third navigation we + // There should no longer be any pending entry, and the new navigation we // just made should be committed. EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -918,21 +935,24 @@ const GURL kExistingURL1("http://foo/eh"); controller.LoadURL( kExistingURL1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, kExistingURL1); + main_test_rfh()->SendNavigate(0, entry_id, true, kExistingURL1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; const GURL kExistingURL2("http://foo/bee"); controller.LoadURL( kExistingURL2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, kExistingURL2); + main_test_rfh()->SendNavigate(1, entry_id, true, kExistingURL2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; // A back navigation comes in from the renderer... controller.GoToOffset(-1); + entry_id = controller.GetPendingEntry()->GetUniqueID(); // ...while the user tries to navigate to a new page... const GURL kNewURL("http://foo/see"); @@ -944,7 +964,7 @@ // ...and the back navigation commits. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, kExistingURL1); + main_test_rfh()->SendNavigate(0, entry_id, false, kExistingURL1); // There should no longer be any pending entry, and the back navigation should // be committed. @@ -982,10 +1002,10 @@ EXPECT_EQ(1, delegate->navigation_state_change_count()); // Before that commits, a document.write and location.reload can cause the - // renderer to send a FrameNavigate with page_id -1. + // renderer to send a FrameNavigate with page_id -1 and nav_entry_id 0. main_test_rfh()->SendRendererInitiatedNavigationRequest(kExistingURL, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(-1, kExistingURL); + main_test_rfh()->SendNavigate(-1, 0, false, kExistingURL); // This should clear the pending entry and notify of a navigation state // change, so that we do not keep displaying kNewURL. @@ -1061,8 +1081,9 @@ const GURL kExistingURL("http://foo/eh"); controller.LoadURL(kExistingURL, content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, kExistingURL); + main_test_rfh()->SendNavigate(1, entry_id, true, kExistingURL); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1134,14 +1155,16 @@ url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); EXPECT_EQ(NavigationEntryImpl::kInvalidBindings, controller.GetPendingEntry()->bindings()); + int entry1_id = controller.GetPendingEntry()->GetUniqueID(); // Commit. TestRenderFrameHost* orig_rfh = contents()->GetMainFrame(); orig_rfh->PrepareForCommit(); - orig_rfh->SendNavigate(0, url1); + orig_rfh->SendNavigate(0, entry1_id, true, url1); EXPECT_EQ(controller.GetEntryCount(), 1); EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); EXPECT_EQ(0, controller.GetLastCommittedEntry()->bindings()); + entry1_id = controller.GetLastCommittedEntry()->GetUniqueID(); // Manually increase the number of active frames in the SiteInstance // that orig_rfh belongs to, to prevent it from being destroyed when @@ -1154,10 +1177,11 @@ // privileged url. controller.LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); TestRenderFrameHost* new_rfh = contents()->GetPendingMainFrame(); new_rfh->GetRenderViewHost()->AllowBindings(1); - new_rfh->SendNavigate(1, url2); + new_rfh->SendNavigate(1, entry_id, true, url2); // The second load should be committed, and bindings should be remembered. EXPECT_EQ(controller.GetEntryCount(), 2); @@ -1168,7 +1192,7 @@ // Going back, the first entry should still appear unprivileged. controller.GoBack(); new_rfh->PrepareForCommit(); - orig_rfh->SendNavigate(0, url1); + orig_rfh->SendNavigate(0, entry1_id, false, url1); EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); EXPECT_EQ(0, controller.GetLastCommittedEntry()->bindings()); } @@ -1182,13 +1206,16 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(0U, notifications.size()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; ASSERT_TRUE(controller.GetVisibleEntry()); controller.GetVisibleEntry()->SetTitle(base::ASCIIToUTF16("Title")); + entry_id = controller.GetLastCommittedEntry()->GetUniqueID(); + controller.Reload(true); EXPECT_EQ(0U, notifications.size()); @@ -1209,7 +1236,7 @@ EXPECT_TRUE(controller.GetVisibleEntry()->GetTitle().empty()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, false, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1238,16 +1265,18 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; + entry_id = controller.GetLastCommittedEntry()->GetUniqueID(); controller.Reload(true); EXPECT_EQ(0U, notifications.size()); main_test_rfh()->PrepareForCommitWithServerRedirect(url2); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, entry_id, true, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1270,8 +1299,9 @@ const GURL url1("http://foo1"); controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); ASSERT_TRUE(controller.GetVisibleEntry()); // Make the entry believe its RenderProcessHost is a guest. @@ -1304,12 +1334,14 @@ // Load up the original URL, but get redirected. controller.LoadURL( original_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(0U, notifications.size()); main_test_rfh()->PrepareForCommitWithServerRedirect(final_url); - main_test_rfh()->SendNavigateWithOriginalRequestURL( - 0, final_url, original_url); + main_test_rfh()->SendNavigateWithOriginalRequestURL(0, entry_id, true, + final_url, original_url); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; + entry_id = controller.GetLastCommittedEntry()->GetUniqueID(); // The NavigationEntry should save both the original URL and the final // redirected URL. @@ -1339,7 +1371,7 @@ // Send that the navigation has proceeded; say it got redirected again. main_test_rfh()->PrepareForCommitWithServerRedirect(final_url); - main_test_rfh()->SendNavigate(0, final_url); + main_test_rfh()->SendNavigate(0, entry_id, false, final_url); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1365,13 +1397,15 @@ const GURL url0("http://foo/0"); controller.LoadURL( url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url0); + main_test_rfh()->SendNavigate(0, entry_id, true, url0); // Set up the pending entry. const GURL url1("http://foo/1"); controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); // Set up some sample values. const unsigned char* raw_data = @@ -1397,7 +1431,7 @@ // Fake a commit response. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url1); + main_test_rfh()->SendNavigate(1, entry_id, true, url1); // Certain values that are only used for pending entries get reset after // commit. @@ -1417,6 +1451,7 @@ const GURL url2("http://foo2"); controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); // Set up some redirect values. std::vector<GURL> redirects; @@ -1430,7 +1465,8 @@ // Normal navigation will preserve redirects in the committed entry. main_test_rfh()->PrepareForCommitWithServerRedirect(url2); - main_test_rfh()->SendNavigateWithRedirects(0, url1, redirects); + main_test_rfh()->SendNavigateWithRedirects(0, entry_id, true, url1, + redirects); NavigationEntryImpl* committed_entry = controller.GetLastCommittedEntry(); ASSERT_EQ(1U, committed_entry->GetRedirectChain().size()); EXPECT_EQ(url2, committed_entry->GetRedirectChain()[0]); @@ -1443,16 +1479,17 @@ RegisterForAllNavNotifications(¬ifications, &controller); const GURL url1("http://foo1"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; const GURL url2("http://foo2"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url2); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; controller.GoBack(); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(0U, notifications.size()); // We should now have a pending navigation to go back. @@ -1465,14 +1502,14 @@ EXPECT_FALSE(controller.CanGoToOffset(-1)); EXPECT_TRUE(controller.CanGoForward()); EXPECT_TRUE(controller.CanGoToOffset(1)); - EXPECT_FALSE(controller.CanGoToOffset(2)); // Cannot go foward 2 steps. + EXPECT_FALSE(controller.CanGoToOffset(2)); // Cannot go forward 2 steps. // Timestamp for entry 1 should be on or after that of entry 0. EXPECT_FALSE(controller.GetEntryAtIndex(0)->GetTimestamp().is_null()); EXPECT_GE(controller.GetEntryAtIndex(1)->GetTimestamp(), controller.GetEntryAtIndex(0)->GetTimestamp()); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url2); + main_test_rfh()->SendNavigate(0, entry_id, false, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1506,15 +1543,18 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry1_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry1_id, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; + entry1_id = controller.GetLastCommittedEntry()->GetUniqueID(); controller.LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, entry_id, true, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1531,7 +1571,7 @@ EXPECT_TRUE(controller.CanGoForward()); main_test_rfh()->PrepareForCommitWithServerRedirect(url3); - main_test_rfh()->SendNavigate(2, url3); + main_test_rfh()->SendNavigate(2, entry1_id, true, url3); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1557,12 +1597,12 @@ const GURL kUrl3("http://foo3"); // First navigate two places so we have some back history. - main_test_rfh()->NavigateAndCommitRendererInitiated(0, kUrl1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, kUrl1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; // controller.LoadURL(kUrl2, ui::PAGE_TRANSITION_TYPED); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, kUrl2); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, kUrl2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1590,19 +1630,20 @@ // First navigate three places so we have some back history. main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, kUrl1); + main_test_rfh()->SendNavigate(0, 0, true, kUrl1); main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl2, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, kUrl2); + main_test_rfh()->SendNavigate(1, 0, true, kUrl2); main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl3, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(2, kUrl3); + main_test_rfh()->SendNavigate(2, 0, true, kUrl3); // With nothing pending, say we get a renderer back navigation request to the // second entry. controller.GoToOffset(-1); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, kUrl2); + main_test_rfh()->SendNavigate(1, entry_id, false, kUrl2); // We know all the entries have the same site instance, so we can just grab // a random one for looking up other entries. @@ -1617,8 +1658,9 @@ // Now go forward to the last item again and say it was committed. controller.GoForward(); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(2, kUrl3); + main_test_rfh()->SendNavigate(2, entry_id, false, kUrl3); // Now start going back one to the second page. It will be pending. controller.GoBack(); @@ -1628,8 +1670,9 @@ // Now have the renderer request a navigation back to the first page. This // will not match the pending one. controller.GoToOffset(-2); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, kUrl1); + main_test_rfh()->SendNavigate(0, entry_id, false, kUrl1); // The committed navigation should clear the pending entry. EXPECT_EQ(-1, controller.GetPendingEntryIndex()); @@ -1650,19 +1693,21 @@ main_test_rfh()->SendRendererInitiatedNavigationRequest(url1, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, 0, true, url1); + NavigationEntry* entry1 = controller.GetLastCommittedEntry(); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, 0, true, url2); + NavigationEntry* entry2 = controller.GetLastCommittedEntry(); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; controller.GoBack(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry1->GetUniqueID(), false, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1687,7 +1732,7 @@ controller.GetEntryAtIndex(1)->GetTimestamp()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, entry2->GetUniqueID(), false, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1721,18 +1766,20 @@ main_test_rfh()->SendRendererInitiatedNavigationRequest(url1, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, 0, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); + NavigationEntry* entry1 = controller.GetLastCommittedEntry(); navigation_entry_committed_counter_ = 0; main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, 0, true, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); + NavigationEntry* entry2 = controller.GetLastCommittedEntry(); navigation_entry_committed_counter_ = 0; controller.GoBack(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry1->GetUniqueID(), false, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1749,7 +1796,7 @@ EXPECT_FALSE(controller.CanGoForward()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(2, url3); + main_test_rfh()->SendNavigate(2, entry2->GetUniqueID(), true, url3); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; EXPECT_TRUE(notifications.Check1AndReset(NOTIFICATION_NAV_LIST_PRUNED)); @@ -1776,11 +1823,14 @@ // First request. controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(0U, notifications.size()); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 0; + params.nav_entry_id = entry_id; + params.did_create_new_entry = true; params.url = url2; params.transition = ui::PAGE_TRANSITION_SERVER_REDIRECT; params.redirects.push_back(GURL("http://foo1")); @@ -1800,10 +1850,15 @@ // Second request. controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(controller.GetPendingEntryIndex(), -1); EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL()); + + params.nav_entry_id = entry_id; + params.did_create_new_entry = false; + EXPECT_EQ(0U, notifications.size()); EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params, &details)); @@ -1836,12 +1891,15 @@ // First request as POST. controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); controller.GetVisibleEntry()->SetHasPostData(true); EXPECT_EQ(0U, notifications.size()); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 0; + params.nav_entry_id = entry_id; + params.did_create_new_entry = true; params.url = url2; params.transition = ui::PAGE_TRANSITION_SERVER_REDIRECT; params.redirects.push_back(GURL("http://foo1")); @@ -1861,11 +1919,14 @@ // Second request. controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(controller.GetPendingEntryIndex(), -1); EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL()); + params.nav_entry_id = entry_id; + params.did_create_new_entry = false; params.is_post = false; EXPECT_EQ(0U, notifications.size()); @@ -1899,6 +1960,7 @@ // First request controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(controller.GetPendingEntryIndex(), -1); @@ -1906,6 +1968,8 @@ FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 0; + params.nav_entry_id = entry_id; + params.did_create_new_entry = true; params.url = url2; params.transition = ui::PAGE_TRANSITION_SERVER_REDIRECT; params.redirects.push_back(GURL("http://foo1")); @@ -1943,13 +2007,15 @@ RegisterForAllNavNotifications(¬ifications, &controller); const GURL url1("http://foo1"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; const GURL url2("http://foo2"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 1; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url2; params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME; params.should_update_history = false; @@ -1985,7 +2051,7 @@ RegisterForAllNavNotifications(¬ifications, &controller); const GURL url1("http://foo/1"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -1998,6 +2064,8 @@ { FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 1; + params.nav_entry_id = 0; + params.did_create_new_entry = false; params.url = url2; params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME; params.should_update_history = false; @@ -2084,14 +2152,17 @@ // Main page. const GURL url1("http://foo1"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); + NavigationEntry* entry1 = controller.GetLastCommittedEntry(); navigation_entry_committed_counter_ = 0; // First manual subframe navigation. const GURL url2("http://foo2"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 1; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url2; params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME; params.should_update_history = false; @@ -2103,6 +2174,7 @@ LoadCommittedDetails details; EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params, &details)); + NavigationEntry* entry2 = controller.GetLastCommittedEntry(); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; EXPECT_EQ(2, controller.GetEntryCount()); @@ -2110,6 +2182,8 @@ // Second manual subframe navigation should also make a new entry. const GURL url3("http://foo3"); params.page_id = 2; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url3; params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME; EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params, @@ -2122,6 +2196,8 @@ // Go back one. controller.GoBack(); params.page_id = 1; + params.nav_entry_id = entry2->GetUniqueID(); + params.did_create_new_entry = false; params.url = url2; params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME; EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params, @@ -2136,6 +2212,8 @@ // Go back one more. controller.GoBack(); params.page_id = 0; + params.nav_entry_id = entry1->GetUniqueID(); + params.did_create_new_entry = false; params.url = url1; params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME; EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params, @@ -2156,15 +2234,15 @@ const GURL url1("http://foo1"); const GURL url2("http://foo2"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url2); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; - // Should not have produced a new session history entry. + // Should have produced a new session history entry. EXPECT_EQ(controller.GetEntryCount(), 2); EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 1); EXPECT_EQ(controller.GetPendingEntryIndex(), -1); @@ -2181,7 +2259,7 @@ // Main page. const GURL url1("http://foo"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -2189,6 +2267,8 @@ // hint provided in the params. FrameHostMsg_DidCommitProvisionalLoad_Params self_params; self_params.page_id = 0; + self_params.nav_entry_id = 0; + self_params.did_create_new_entry = false; self_params.url = url1; self_params.transition = ui::PAGE_TRANSITION_LINK; self_params.should_update_history = false; @@ -2200,6 +2280,7 @@ LoadCommittedDetails details; EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), self_params, &details)); + NavigationEntry* entry1 = controller.GetLastCommittedEntry(); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; EXPECT_TRUE(details.is_in_page); @@ -2210,6 +2291,8 @@ const GURL url2("http://foo#a"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 1; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url2; params.transition = ui::PAGE_TRANSITION_LINK; params.should_update_history = false; @@ -2221,6 +2304,7 @@ // This should generate a new entry. EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params, &details)); + NavigationEntry* entry2 = controller.GetLastCommittedEntry(); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; EXPECT_TRUE(details.is_in_page); @@ -2232,6 +2316,8 @@ controller.GoBack(); back_params.url = url1; back_params.page_id = 0; + back_params.nav_entry_id = entry1->GetUniqueID(); + back_params.did_create_new_entry = false; EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), back_params, &details)); EXPECT_EQ(1U, navigation_entry_committed_counter_); @@ -2241,11 +2327,13 @@ EXPECT_EQ(0, controller.GetCurrentEntryIndex()); EXPECT_EQ(back_params.url, controller.GetVisibleEntry()->GetURL()); - // Go forward + // Go forward. FrameHostMsg_DidCommitProvisionalLoad_Params forward_params(params); controller.GoForward(); forward_params.url = url2; forward_params.page_id = 1; + forward_params.nav_entry_id = entry2->GetUniqueID(); + forward_params.did_create_new_entry = false; EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), forward_params, &details)); EXPECT_EQ(1U, navigation_entry_committed_counter_); @@ -2272,6 +2360,8 @@ // Finally, navigate to an unrelated URL to make sure in_page is not sticky. const GURL url3("http://bar"); params.page_id = 2; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url3; navigation_entry_committed_counter_ = 0; EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params, @@ -2290,7 +2380,7 @@ // Main page. const GURL url1("http://foo"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -2298,6 +2388,8 @@ const GURL url2("http://foo#a"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 0; // Same page_id + params.nav_entry_id = 0; + params.did_create_new_entry = false; params.url = url2; params.transition = ui::PAGE_TRANSITION_LINK; params.should_update_history = false; @@ -2331,7 +2423,7 @@ // Load an initial page. { const GURL url("http://foo/"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; } @@ -2339,7 +2431,7 @@ // Navigate to a new page. { const GURL url("http://foo2/"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; } @@ -2349,6 +2441,8 @@ const GURL url("http://foo2/#a"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 1; // Same page_id + params.nav_entry_id = 0; + params.did_create_new_entry = false; params.url = url; params.transition = ui::PAGE_TRANSITION_LINK; params.redirects.push_back(url); @@ -2374,6 +2468,8 @@ const GURL url("http://foo3/"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 2; // New page_id + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url; params.transition = ui::PAGE_TRANSITION_CLIENT_REDIRECT; params.redirects.push_back(GURL("http://foo2/#a")); @@ -2397,8 +2493,9 @@ { const GURL url("http://foo2/"); controller.GoBack(); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url); + main_test_rfh()->SendNavigate(1, entry_id, false, url); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL()); @@ -2411,6 +2508,8 @@ FrameHostMsg_DidCommitProvisionalLoad_Params params; GURL url("http://foo"); params.page_id = 1; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url; params.page_state = PageState::CreateFromURL(url); params.was_within_same_page = true; @@ -2465,8 +2564,9 @@ GURL url(base::StringPrintf("http://www.a.com/%d", url_index)); controller.LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(url_index, url); + main_test_rfh()->SendNavigate(url_index, entry_id, true, url); } EXPECT_EQ(controller.GetEntryCount(), kMaxEntryCount); @@ -2478,8 +2578,9 @@ GURL url(base::StringPrintf("http://www.a.com/%d", url_index)); controller.LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(url_index, url); + main_test_rfh()->SendNavigate(url_index, entry_id, true, url); url_index++; // We should have got a pruned navigation. @@ -2490,20 +2591,21 @@ // We expect http://www.a.com/0 to be gone. EXPECT_EQ(controller.GetEntryCount(), kMaxEntryCount); EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), - GURL("http:////www.a.com/1")); + GURL("http://www.a.com/1")); // More navigations. for (int i = 0; i < 3; i++) { - url = GURL(base::StringPrintf("http:////www.a.com/%d", url_index)); + url = GURL(base::StringPrintf("http://www.a.com/%d", url_index)); controller.LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(url_index, url); + main_test_rfh()->SendNavigate(url_index, entry_id, true, url); url_index++; } EXPECT_EQ(controller.GetEntryCount(), kMaxEntryCount); EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), - GURL("http:////www.a.com/4")); + GURL("http://www.a.com/4")); NavigationControllerImpl::set_max_entry_count_for_testing(original_count); } @@ -2557,6 +2659,8 @@ // Say we navigated to that entry. FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 0; + params.nav_entry_id = our_controller.GetPendingEntry()->GetUniqueID(); + params.did_create_new_entry = false; params.url = url; params.transition = ui::PAGE_TRANSITION_LINK; params.should_update_history = false; @@ -2605,6 +2709,7 @@ // Before navigating to the restored entry, it should have a restore_type // and no SiteInstance. + entry = our_controller.GetEntryAtIndex(0); EXPECT_EQ(NavigationEntryImpl::RESTORE_LAST_SESSION_EXITED_CLEANLY, our_controller.GetEntryAtIndex(0)->restore_type()); EXPECT_FALSE(our_controller.GetEntryAtIndex(0)->site_instance()); @@ -2634,6 +2739,8 @@ // Now the pending restored entry commits. FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 0; + params.nav_entry_id = entry->GetUniqueID(); + params.did_create_new_entry = false; params.url = url; params.transition = ui::PAGE_TRANSITION_LINK; params.should_update_history = false; @@ -2662,19 +2769,21 @@ const GURL url1("http://foo"); controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); // Now navigate somewhere with an interstitial. const GURL url2("http://bar"); controller.LoadURL(url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); controller.GetPendingEntry()->set_page_type(PAGE_TYPE_INTERSTITIAL); // At this point the interstitial will be displayed and the load will still // be pending. If the user continues, the load will commit. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, entry_id, true, url2); // The page should be a normal page again. EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL()); @@ -2694,24 +2803,29 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); controller.LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, entry_id, true, url2); controller.LoadURL( url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(2, url3); + main_test_rfh()->SendNavigate(2, entry_id, true, url3); controller.LoadURL( url4, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(3, url4); + main_test_rfh()->SendNavigate(3, entry_id, true, url4); controller.LoadURL( url5, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(4, url5); + main_test_rfh()->SendNavigate(4, entry_id, true, url5); // Try to remove the last entry. Will fail because it is the current entry. EXPECT_FALSE(controller.RemoveEntryAtIndex(controller.GetEntryCount() - 1)); @@ -2721,12 +2835,13 @@ // Go back, but don't commit yet. Check that we can't delete the current // and pending entries. controller.GoBack(); + entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_FALSE(controller.RemoveEntryAtIndex(controller.GetEntryCount() - 1)); EXPECT_FALSE(controller.RemoveEntryAtIndex(controller.GetEntryCount() - 2)); // Now commit and delete the last entry. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(3, url4); + main_test_rfh()->SendNavigate(3, entry_id, false, url4); EXPECT_TRUE(controller.RemoveEntryAtIndex(controller.GetEntryCount() - 1)); EXPECT_EQ(4, controller.GetEntryCount()); EXPECT_EQ(3, controller.GetLastCommittedEntryIndex()); @@ -2756,20 +2871,24 @@ controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); controller.LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, entry_id, true, url2); controller.LoadURL( url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(2, url3); + main_test_rfh()->SendNavigate(2, entry_id, true, url3); // Go back, but don't commit yet. Check that we can't delete the current // and pending entries. controller.GoBack(); + entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_FALSE(controller.RemoveEntryAtIndex(2)); EXPECT_FALSE(controller.RemoveEntryAtIndex(1)); @@ -2784,7 +2903,7 @@ // Now commit and ensure we land on the right entry. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url2); + main_test_rfh()->SendNavigate(1, entry_id, false, url2); EXPECT_EQ(2, controller.GetEntryCount()); EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); EXPECT_FALSE(controller.GetPendingEntry()); @@ -2806,12 +2925,14 @@ controller.LoadURL( url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url0); + main_test_rfh()->SendNavigate(0, entry_id, true, url0); controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url1); + main_test_rfh()->SendNavigate(1, entry_id, true, url1); notifications.Reset(); @@ -2837,8 +2958,9 @@ // Navigate. controller.LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(2, url2); + main_test_rfh()->SendNavigate(2, entry_id, true, url2); // We should have navigated, transient entry should be gone. EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL()); @@ -2851,7 +2973,7 @@ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL()); main_test_rfh()->SendRendererInitiatedNavigationRequest(url3, true); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(3, url3); + main_test_rfh()->SendNavigate(3, 0, true, url3); // Transient entry should be gone. EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL()); EXPECT_EQ(controller.GetEntryCount(), 4); @@ -2859,12 +2981,13 @@ // Initiate a navigation, add a transient then commit navigation. controller.LoadURL( url4, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller.GetPendingEntry()->GetUniqueID(); transient_entry = new NavigationEntryImpl; transient_entry->SetURL(transient_url); controller.SetTransientEntry(transient_entry); EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(4, url4); + main_test_rfh()->SendNavigate(4, entry_id, true, url4); EXPECT_EQ(url4, controller.GetVisibleEntry()->GetURL()); EXPECT_EQ(controller.GetEntryCount(), 5); @@ -2882,8 +3005,9 @@ // Suppose the page requested a history navigation backward. controller.GoToOffset(-1); + entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(3, url3); + main_test_rfh()->SendNavigate(3, entry_id, false, url3); // Add a transient and go to an entry before the current one. transient_entry = new NavigationEntryImpl; @@ -2891,13 +3015,14 @@ controller.SetTransientEntry(transient_entry); EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL()); controller.GoToIndex(1); + entry_id = controller.GetPendingEntry()->GetUniqueID(); // The navigation should have been initiated, transient entry should be gone. EXPECT_FALSE(controller.GetTransientEntry()); EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL()); // Visible entry does not update for history navigations until commit. EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url1); + main_test_rfh()->SendNavigate(1, entry_id, false, url1); EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL()); // Add a transient and go to an entry after the current one. @@ -2906,13 +3031,14 @@ controller.SetTransientEntry(transient_entry); EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL()); controller.GoToIndex(3); + entry_id = controller.GetPendingEntry()->GetUniqueID(); // The navigation should have been initiated, transient entry should be gone. // Because of the transient entry that is removed, going to index 3 makes us // land on url2 (which is visible after the commit). EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL()); EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(2, url2); + main_test_rfh()->SendNavigate(2, entry_id, false, url2); EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL()); // Add a transient and go forward. @@ -2922,12 +3048,13 @@ EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL()); EXPECT_TRUE(controller.CanGoForward()); controller.GoForward(); + entry_id = controller.GetPendingEntry()->GetUniqueID(); // We should have navigated, transient entry should be gone. EXPECT_FALSE(controller.GetTransientEntry()); EXPECT_EQ(url3, controller.GetPendingEntry()->GetURL()); EXPECT_EQ(url2, controller.GetVisibleEntry()->GetURL()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(3, url3); + main_test_rfh()->SendNavigate(3, entry_id, false, url3); EXPECT_EQ(url3, controller.GetVisibleEntry()->GetURL()); // Add a transient and do an in-page navigation, replacing the current entry. @@ -2938,7 +3065,7 @@ main_test_rfh()->SendRendererInitiatedNavigationRequest(url3_ref, false); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(3, url3_ref); + main_test_rfh()->SendNavigate(3, 0, false, url3_ref); // Transient entry should be gone. EXPECT_FALSE(controller.GetTransientEntry()); EXPECT_EQ(url3_ref, controller.GetVisibleEntry()->GetURL()); @@ -2962,8 +3089,9 @@ // Load |url0|, and start a pending navigation to |url1|. controller.LoadURL( url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url0); + main_test_rfh()->SendNavigate(0, entry_id, true, url0); controller.LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); @@ -2978,6 +3106,7 @@ // the transient entry for |transient_url|, and start a navigation to // |transient_url|. controller.Reload(true); + entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_FALSE(controller.GetTransientEntry()); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(transient_url, controller.GetVisibleEntry()->GetURL()); @@ -2986,7 +3115,7 @@ // Load of |transient_url| completes. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, transient_url); + main_test_rfh()->SendNavigate(1, entry_id, true, transient_url); ASSERT_EQ(controller.GetEntryCount(), 2); EXPECT_EQ(controller.GetEntryAtIndex(0)->GetURL(), url0); EXPECT_EQ(controller.GetEntryAtIndex(1)->GetURL(), transient_url); @@ -3025,7 +3154,7 @@ EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL()); // Once it commits, the URL and virtual URL should reflect the actual page. - main_test_rfh()->SendNavigate(0, url2); + main_test_rfh()->SendNavigate(0, 0, true, url2); EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL()); EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL()); @@ -3045,7 +3174,7 @@ main_test_rfh()->PrepareForCommit(); navigator->DidStartProvisionalLoad(main_test_rfh(), url2, false); EXPECT_TRUE(controller.GetPendingEntry()->should_replace_entry()); - main_test_rfh()->SendNavigate(0, url2); + main_test_rfh()->SendNavigate(0, 0, false, url2); EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL()); } @@ -3064,16 +3193,18 @@ // should update before commit. controller.LoadURL( url0, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(url0, controller.GetPendingEntry()->GetURL()); EXPECT_EQ(url0, controller.GetVisibleEntry()->GetURL()); main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url0); + main_test_rfh()->SendNavigate(0, entry_id, true, url0); // For link clicks (renderer-initiated navigations), the pending entry should // update before commit but the visible should not. NavigationController::LoadURLParams load_url_params(url1); load_url_params.is_renderer_initiated = true; controller.LoadURLWithParams(load_url_params); + entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(url0, controller.GetVisibleEntry()->GetURL()); EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL()); EXPECT_TRUE(controller.GetPendingEntry()->is_renderer_initiated()); @@ -3081,7 +3212,7 @@ // After commit, both visible should be updated, there should be no pending // entry, and we should no longer treat the entry as renderer-initiated. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(1, url1); + main_test_rfh()->SendNavigate(1, entry_id, true, url1); EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL()); EXPECT_FALSE(controller.GetPendingEntry()); EXPECT_FALSE(controller.GetLastCommittedEntry()->is_renderer_initiated()); @@ -3239,6 +3370,7 @@ load_url_params.transition_type = ui::PAGE_TRANSITION_LINK; load_url_params.is_renderer_initiated = true; controller.LoadURLWithParams(load_url_params); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_EQ(url1, controller.GetVisibleEntry()->GetURL()); EXPECT_TRUE(controller.GetPendingEntry()->is_renderer_initiated()); EXPECT_TRUE(controller.IsInitialNavigation()); @@ -3246,7 +3378,7 @@ // Simulate a commit and then starting a new pending navigation. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(0, url1); + main_test_rfh()->SendNavigate(0, entry_id, true, url1); NavigationController::LoadURLParams load_url2_params(url2); load_url2_params.transition_type = ui::PAGE_TRANSITION_LINK; load_url2_params.is_renderer_initiated = true; @@ -3276,16 +3408,15 @@ // was the first document in the given frame, but we don't have enough // information to identify that case currently. const GURL blank_url(url::kAboutBlankURL); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, blank_url); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, blank_url); EXPECT_TRUE(controller.IsURLInPageNavigation(url, true, main_test_rfh())); // Navigate to URL with no refs. - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, false, url); // Reloading the page is not an in-page navigation. - EXPECT_FALSE(controller.IsURLInPageNavigation(url, false, - main_test_rfh())); + EXPECT_FALSE(controller.IsURLInPageNavigation(url, false, main_test_rfh())); const GURL other_url("http://www.google.com/add.html"); EXPECT_FALSE(controller.IsURLInPageNavigation(other_url, false, main_test_rfh())); @@ -3294,7 +3425,7 @@ main_test_rfh())); // Navigate to URL with refs. - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url_with_ref); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url_with_ref); // Reloading the page is not an in-page navigation. EXPECT_FALSE(controller.IsURLInPageNavigation(url_with_ref, false, @@ -3332,14 +3463,14 @@ EXPECT_TRUE(prefs.allow_universal_access_from_file_urls); // Allow in page navigation if existing URL is file scheme. const GURL file_url("file:///foo/index.html"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, file_url); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, false, file_url); 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 // not file scheme. - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, false, url); EXPECT_FALSE(controller.IsURLInPageNavigation(different_origin_url, true, main_test_rfh())); EXPECT_EQ(1, rph->bad_msg_count()); @@ -3366,7 +3497,7 @@ NavigationControllerImpl& controller = controller_impl(); // Navigate the main frame. const GURL url("http://www.google.com/"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url); // We should be at the first navigation entry. EXPECT_EQ(controller.GetEntryCount(), 1); @@ -3376,6 +3507,8 @@ const GURL subframe("http://www.google.com/#"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 0; + params.nav_entry_id = 0; + params.did_create_new_entry = false; params.url = subframe; params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME; params.should_update_history = false; @@ -3521,6 +3654,8 @@ const GURL url1_sub("http://foo/subframe"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = controller.GetLastCommittedEntry()->GetPageID(); + params.nav_entry_id = 0; + params.did_create_new_entry = false; params.url = url1_sub; params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME; params.should_update_history = false; @@ -3818,8 +3953,8 @@ // Simulate a client redirect, which has the same page ID as entry 2a. other_controller.LoadURL( url2b, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); - other_controller.GetPendingEntry()->SetPageID( - other_controller.GetLastCommittedEntry()->GetPageID()); + NavigationEntry* entry = other_controller.GetPendingEntry(); + entry->SetPageID(other_controller.GetLastCommittedEntry()->GetPageID()); other_contents->ExpectSetHistoryOffsetAndLength(1, 2); other_controller.CopyStateFromAndPrune(&controller, false); @@ -3838,7 +3973,9 @@ EXPECT_EQ(url2b, other_controller.GetPendingEntry()->GetURL()); // Let the pending entry commit. - other_contents->CommitPendingNavigation(); + other_contents->TestDidNavigate(other_contents->GetMainFrame(), + entry->GetPageID(), 0, false, url2b, + ui::PAGE_TRANSITION_LINK); // The max page ID map should be copied over and updated with the max page ID // from the current tab. @@ -4199,6 +4336,7 @@ // Create a pending entry that is not in the entry list. controller.LoadURL( url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller.GetPendingEntry()->GetUniqueID(); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(2, controller.GetEntryCount()); @@ -4215,7 +4353,7 @@ // Try to commit the pending entry. main_test_rfh()->PrepareForCommit(); - main_test_rfh()->SendNavigate(2, url3); + main_test_rfh()->SendNavigate(2, entry_id, true, url3); EXPECT_EQ(-1, controller.GetPendingEntryIndex()); EXPECT_FALSE(controller.GetPendingEntry()); EXPECT_EQ(2, controller.GetEntryCount()); @@ -4257,7 +4395,7 @@ // After commit, it stays false. const GURL url1("http://foo1"); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, url1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; EXPECT_FALSE(controller.IsInitialNavigation()); @@ -4280,7 +4418,8 @@ TestNotificationTracker notifications; RegisterForAllNavNotifications(¬ifications, &controller); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, kPageWithFavicon); + main_test_rfh()->NavigateAndCommitRendererInitiated( + 0, true, kPageWithFavicon); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -4299,9 +4438,10 @@ false); main_test_rfh()->PrepareForCommit(); main_test_rfh()->SendNavigateWithTransition( - 0, // same page ID. - kPageWithoutFavicon, - ui::PAGE_TRANSITION_CLIENT_REDIRECT); + 0, // same page ID. + 0, // nav_entry_id + false, // no new entry + kPageWithoutFavicon, ui::PAGE_TRANSITION_CLIENT_REDIRECT); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -4323,7 +4463,7 @@ TestNotificationTracker notifications; RegisterForAllNavNotifications(¬ifications, &controller); - main_test_rfh()->NavigateAndCommitRendererInitiated(0, kUrl1); + main_test_rfh()->NavigateAndCommitRendererInitiated(0, true, kUrl1); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -4337,14 +4477,13 @@ favicon_status.valid = true; // Navigate to another page and go back to the original page. - main_test_rfh()->NavigateAndCommitRendererInitiated(1, kUrl2); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, kUrl2); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; main_test_rfh()->SendRendererInitiatedNavigationRequest(kUrl1, false); main_test_rfh()->PrepareForCommit(); main_test_rfh()->SendNavigateWithTransition( - 0, - kUrl1, + 0, controller.GetEntryAtIndex(0)->GetUniqueID(), false, kUrl1, ui::PAGE_TRANSITION_FORWARD_BACK); EXPECT_EQ(1U, navigation_entry_committed_counter_); navigation_entry_committed_counter_ = 0; @@ -4445,7 +4584,8 @@ TEST_F(NavigationControllerTest, PushStateUpdatesTitleAndFavicon) { // Navigate. - main_test_rfh()->NavigateAndCommitRendererInitiated(1, GURL("http://foo")); + main_test_rfh()->NavigateAndCommitRendererInitiated( + 1, true, GURL("http://foo")); // Set title and favicon. base::string16 title(base::ASCIIToUTF16("Title")); @@ -4459,6 +4599,8 @@ FrameHostMsg_DidCommitProvisionalLoad_Params params; GURL kUrl2("http://foo#foo"); params.page_id = 2; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = kUrl2; params.page_state = PageState::CreateFromURL(kUrl2); params.was_within_same_page = true; @@ -4537,6 +4679,8 @@ GURL url("http://foo"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 1; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url; params.transition = ui::PAGE_TRANSITION_FORM_SUBMIT; params.gesture = NavigationGestureUser; @@ -4551,6 +4695,8 @@ // history.replaceState() is called. GURL replace_url("http://foo#foo"); params.page_id = 1; + params.nav_entry_id = 0; + params.did_create_new_entry = false; params.url = replace_url; params.transition = ui::PAGE_TRANSITION_LINK; params.gesture = NavigationGestureUser; @@ -4572,6 +4718,8 @@ GURL url("http://foo"); FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = 1; + params.nav_entry_id = 0; + params.did_create_new_entry = true; params.url = url; params.transition = ui::PAGE_TRANSITION_LINK; params.gesture = NavigationGestureUser; @@ -4580,7 +4728,8 @@ params.is_post = true; params.post_id = 2; params.url_is_unreachable = true; - // Navigate to new page + + // Navigate to new page. { LoadCommittedDetails details; controller_impl().RendererDidNavigate(main_test_rfh(), params, &details); @@ -4591,6 +4740,7 @@ // Navigate to existing page. { + params.did_create_new_entry = false; LoadCommittedDetails details; controller_impl().RendererDidNavigate(main_test_rfh(), params, &details); EXPECT_EQ(PAGE_TYPE_ERROR, @@ -4603,6 +4753,7 @@ // same-page transition. controller_impl().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + params.nav_entry_id = controller_impl().GetPendingEntry()->GetUniqueID(); params.transition = ui::PAGE_TRANSITION_TYPED; { LoadCommittedDetails details;
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index 12cafa65..fb0d41f 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -313,14 +313,6 @@ return can_load_local_resources_; } -void NavigationEntryImpl::SetFrameToNavigate(const std::string& frame_name) { - frame_to_navigate_ = frame_name; -} - -const std::string& NavigationEntryImpl::GetFrameToNavigate() const { - return frame_to_navigate_; -} - void NavigationEntryImpl::SetExtraData(const std::string& key, const base::string16& data) { extra_data_[key] = data; @@ -378,7 +370,6 @@ // ResetForCommit: should_replace_entry_ copy->redirect_chain_ = redirect_chain_; // ResetForCommit: should_clear_history_list_ - copy->frame_to_navigate_ = frame_to_navigate_; // ResetForCommit: frame_tree_node_id_ // ResetForCommit: intent_received_timestamp_ copy->extra_data_ = extra_data_; @@ -421,6 +412,7 @@ RequestNavigationParams NavigationEntryImpl::ConstructRequestNavigationParams( base::TimeTicks navigation_start, + bool intended_as_new_entry, int pending_history_list_offset, int current_history_list_offset, int current_history_list_length) const { @@ -444,8 +436,8 @@ } return RequestNavigationParams( GetIsOverridingUserAgent(), navigation_start, redirects, - GetCanLoadLocalResources(), GetFrameToNavigate(), base::Time::Now(), - GetPageState(), GetPageID(), pending_offset_to_send, + GetCanLoadLocalResources(), base::Time::Now(), GetPageState(), + GetPageID(), GetUniqueID(), intended_as_new_entry, pending_offset_to_send, current_offset_to_send, current_length_to_send, should_clear_history_list()); }
diff --git a/content/browser/frame_host/navigation_entry_impl.h b/content/browser/frame_host/navigation_entry_impl.h index 9bebe15..f665819 100644 --- a/content/browser/frame_host/navigation_entry_impl.h +++ b/content/browser/frame_host/navigation_entry_impl.h
@@ -104,8 +104,6 @@ base::Time GetTimestamp() const override; void SetCanLoadLocalResources(bool allow) override; bool GetCanLoadLocalResources() const override; - void SetFrameToNavigate(const std::string& frame_name) override; - const std::string& GetFrameToNavigate() const override; void SetExtraData(const std::string& key, const base::string16& data) override; bool GetExtraData(const std::string& key, @@ -133,6 +131,7 @@ StartNavigationParams ConstructStartNavigationParams() const; RequestNavigationParams ConstructRequestNavigationParams( base::TimeTicks navigation_start, + bool intended_as_new_entry, int pending_offset_to_send, int current_offset_to_send, int current_length_to_send) const; @@ -415,10 +414,6 @@ // value is not needed after the entry commits and is not persisted. bool can_load_local_resources_; - // If not empty, the name of the frame to navigate. This field is not - // persisted, because it is currently only used in tests. - std::string frame_to_navigate_; - // If not -1, this indicates which FrameTreeNode to navigate. This field is // not persisted because it is experimental and only used when the // --site-per-process flag is passed. It is cleared in |ResetForCommit|
diff --git a/content/browser/frame_host/navigation_entry_impl_unittest.cc b/content/browser/frame_host/navigation_entry_impl_unittest.cc index 274676d..3aec358 100644 --- a/content/browser/frame_host/navigation_entry_impl_unittest.cc +++ b/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -207,10 +207,6 @@ entry2_->SetBrowserInitiatedPostData(post_data.get()); EXPECT_EQ(post_data->front(), entry2_->GetBrowserInitiatedPostData()->front()); - - // Frame to navigate. - EXPECT_TRUE(entry1_->GetFrameToNavigate().empty()); - EXPECT_TRUE(entry2_->GetFrameToNavigate().empty()); } // Test basic Clone behavior.
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index f46eecb..cd443ded 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -90,7 +90,9 @@ BeginNavigationParams(method, headers.ToString(), LoadFlagFromNavigationType(navigation_type), false), entry.ConstructRequestNavigationParams( - navigation_start, controller->GetIndexOfEntry(&entry), + navigation_start, + controller->GetPendingEntryIndex() == -1, + controller->GetIndexOfEntry(&entry), controller->GetLastCommittedEntryIndex(), controller->GetEntryCount()), request_body, true, &entry));
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h index 3a27601e..8771dd2 100644 --- a/content/browser/frame_host/navigator.h +++ b/content/browser/frame_host/navigator.h
@@ -101,7 +101,6 @@ const GURL& url, SiteInstance* source_site_instance, const Referrer& referrer, - ui::PageTransition page_transition, WindowOpenDisposition disposition, bool should_replace_current_entry, bool user_gesture) {}
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index a00f9723d..d3f94c72a 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -328,7 +328,9 @@ entry.ConstructCommonNavigationParams(navigation_type), entry.ConstructStartNavigationParams(), entry.ConstructRequestNavigationParams( - navigation_start, controller_->GetIndexOfEntry(&entry), + navigation_start, + controller_->GetPendingEntryIndex() == -1, + controller_->GetIndexOfEntry(&entry), controller_->GetLastCommittedEntryIndex(), controller_->GetEntryCount())); } else { @@ -414,7 +416,7 @@ // origin because it creates a RenderFrameProxy that needs this to initialize // its security context. This origin will also be sent to RenderFrameProxies // created via ViewMsg_New and FrameMsg_NewFrameProxy. - render_frame_host->frame_tree_node()->set_current_origin(params.origin); + render_frame_host->frame_tree_node()->SetCurrentOrigin(params.origin); // When using --site-per-process, we notify the RFHM for all navigations, // not just main frame navigations. @@ -518,7 +520,6 @@ const GURL& url, SiteInstance* source_site_instance, const Referrer& referrer, - ui::PageTransition page_transition, WindowOpenDisposition disposition, bool should_replace_current_entry, bool user_gesture) { @@ -540,9 +541,9 @@ // redirects. http://crbug.com/311721. std::vector<GURL> redirect_chain; RequestTransferURL(render_frame_host, url, source_site_instance, - redirect_chain, referrer, page_transition, disposition, - GlobalRequestID(), should_replace_current_entry, - user_gesture); + redirect_chain, referrer, ui::PAGE_TRANSITION_LINK, + disposition, GlobalRequestID(), + should_replace_current_entry, user_gesture); } void NavigatorImpl::RequestTransferURL(
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h index 95ad6a7..7dd2a02 100644 --- a/content/browser/frame_host/navigator_impl.h +++ b/content/browser/frame_host/navigator_impl.h
@@ -57,7 +57,6 @@ const GURL& url, SiteInstance* source_site_instance, const Referrer& referrer, - ui::PageTransition page_transition, WindowOpenDisposition disposition, bool should_replace_current_entry, bool user_gesture) override;
diff --git a/content/browser/frame_host/navigator_impl_unittest.cc b/content/browser/frame_host/navigator_impl_unittest.cc index d265010d..8dc64af6 100644 --- a/content/browser/frame_host/navigator_impl_unittest.cc +++ b/content/browser/frame_host/navigator_impl_unittest.cc
@@ -50,12 +50,17 @@ return static_cast<TestNavigationURLLoader*>(request->loader_for_testing()); } - void RequestNavigation(FrameTreeNode* node, const GURL& url) { - RequestNavigationWithParameters(node, url, Referrer(), - ui::PAGE_TRANSITION_LINK); + // Requests a navigation of the specified FrameTreeNode to the specified URL; + // returns the unique ID of the pending NavigationEntry. + int RequestNavigation(FrameTreeNode* node, const GURL& url) { + return RequestNavigationWithParameters(node, url, Referrer(), + ui::PAGE_TRANSITION_LINK); } - void RequestNavigationWithParameters( + // Requests a navigation of the specified FrameTreeNode to the specified URL, + // using other specified parameters; returns the unique ID of the pending + // NavigationEntry. + int RequestNavigationWithParameters( FrameTreeNode* node, const GURL& url, const Referrer& referrer, @@ -66,6 +71,7 @@ load_params.transition_type = transition_type; controller().LoadURLWithParams(load_params); + return controller().GetPendingEntry()->GetUniqueID(); } TestRenderFrameHost* GetSpeculativeRenderFrameHost(FrameTreeNode* node) { @@ -105,7 +111,7 @@ // Start a browser-initiated navigation. int32 site_instance_id = main_test_rfh()->GetSiteInstance()->GetId(); FrameTreeNode* node = main_test_rfh()->frame_tree_node(); - RequestNavigation(node, kUrl); + int entry_id = RequestNavigation(node, kUrl); NavigationRequest* request = node->navigation_request(); ASSERT_TRUE(request); EXPECT_EQ(kUrl, request->common_params().url); @@ -126,7 +132,7 @@ EXPECT_EQ(NavigationRequest::RESPONSE_STARTED, request->state()); // Commit the navigation. - main_test_rfh()->SendNavigate(0, kUrl); + main_test_rfh()->SendNavigate(0, entry_id, true, kUrl); EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state()); EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl), main_test_rfh()->GetSiteInstance()->GetSiteURL()); @@ -179,7 +185,7 @@ EXPECT_EQ(NavigationRequest::RESPONSE_STARTED, request->state()); // Commit the navigation. - main_test_rfh()->SendNavigate(0, kUrl2); + main_test_rfh()->SendNavigate(1, 0, true, kUrl2); EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state()); EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2), main_test_rfh()->GetSiteInstance()->GetSiteURL()); @@ -224,7 +230,7 @@ EXPECT_EQ(NavigationRequest::RESPONSE_STARTED, request->state()); // Commit the navigation. - main_test_rfh()->SendNavigate(0, kUrl2); + main_test_rfh()->SendNavigate(1, 0, true, kUrl2); EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state()); EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL()); EXPECT_FALSE(node->navigation_request()); @@ -414,7 +420,7 @@ // Navigate to a different site. process()->sink().ClearMessages(); - RequestNavigation(node, kUrl2); + int entry_id = RequestNavigation(node, kUrl2); NavigationRequest* main_request = node->navigation_request(); ASSERT_TRUE(main_request); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)); @@ -433,7 +439,7 @@ EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh())); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); - speculative_rfh->SendNavigate(0, kUrl2); + speculative_rfh->SendNavigate(0, entry_id, true, kUrl2); RenderFrameHostImpl* final_rfh = main_test_rfh(); EXPECT_EQ(speculative_rfh, final_rfh); @@ -455,7 +461,7 @@ // Navigate to a URL on the same site. process()->sink().ClearMessages(); - RequestNavigation(node, kUrl1); + int entry_id = RequestNavigation(node, kUrl1); main_test_rfh()->SendBeforeUnloadACK(true); NavigationRequest* main_request = node->navigation_request(); ASSERT_TRUE(main_request); @@ -478,7 +484,7 @@ EXPECT_TRUE(DidRenderFrameHostRequestCommit(final_speculative_rfh)); // Commit the navigation. - final_speculative_rfh->SendNavigate(0, kUrl2); + final_speculative_rfh->SendNavigate(0, entry_id, true, kUrl2); RenderFrameHostImpl* final_rfh = main_test_rfh(); ASSERT_TRUE(final_rfh); EXPECT_NE(rfh, final_rfh); @@ -523,7 +529,7 @@ // Request navigation to the 2nd URL; the NavigationRequest must have been // replaced by a new one with a different URL. - RequestNavigation(node, kUrl2); + int entry_id = RequestNavigation(node, kUrl2); main_test_rfh()->SendBeforeUnloadACK(true); NavigationRequest* request2 = node->navigation_request(); ASSERT_TRUE(request2); @@ -547,7 +553,7 @@ EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh())); // Commit the navigation. - speculative_rfh->SendNavigate(0, kUrl2); + speculative_rfh->SendNavigate(0, entry_id, true, kUrl2); // Confirm that the commit corresponds to the new request. ASSERT_TRUE(main_test_rfh()); @@ -608,7 +614,7 @@ EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh())); // Commit the navigation. - main_test_rfh()->SendNavigate(0, kUrl2); + main_test_rfh()->SendNavigate(1, 0, true, kUrl2); // Confirm that the commit corresponds to the new request. ASSERT_TRUE(main_test_rfh()); @@ -656,7 +662,7 @@ EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh())); // Commit the navigation. - main_test_rfh()->SendNavigate(0, kUrl1); + main_test_rfh()->SendNavigate(1, 0, true, kUrl1); EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL()); } @@ -674,7 +680,7 @@ // Start a browser-initiated navigation to the 1st URL. process()->sink().ClearMessages(); - RequestNavigation(node, kUrl1); + int entry_id = RequestNavigation(node, kUrl1); NavigationRequest* request1 = node->navigation_request(); ASSERT_TRUE(request1); EXPECT_EQ(kUrl1, request1->common_params().url); @@ -704,7 +710,7 @@ EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh())); // Commit the navigation. - speculative_rfh->SendNavigate(0, kUrl1); + speculative_rfh->SendNavigate(0, entry_id, true, kUrl1); EXPECT_EQ(kUrl1, contents()->GetLastCommittedURL()); } @@ -752,7 +758,7 @@ EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh())); // Commit the navigation. - main_test_rfh()->SendNavigate(0, kUrl2); + main_test_rfh()->SendNavigate(1, 0, true, kUrl2); EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL()); // The SiteInstance did not change. @@ -768,6 +774,7 @@ FrameTreeNode* node = main_test_rfh()->frame_tree_node(); controller().Reload(false); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); // A NavigationRequest should have been generated. NavigationRequest* main_request = node->navigation_request(); ASSERT_TRUE(main_request != NULL); @@ -776,7 +783,7 @@ main_test_rfh()->PrepareForCommit(); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)); - main_test_rfh()->SendNavigate(0, kUrl); + main_test_rfh()->SendNavigate(0, entry_id, false, kUrl); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)); // Now do a shift+reload. @@ -802,7 +809,7 @@ // Begin navigating to another site. const GURL kUrl("http://google.com/"); process()->sink().ClearMessages(); - RequestNavigation(node, kUrl); + int entry_id = RequestNavigation(node, kUrl); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)); // Receive the beforeUnload ACK. @@ -827,7 +834,7 @@ EXPECT_FALSE(node->render_manager()->pending_frame_host()); // Invoke OnDidCommitProvisionalLoad. - speculative_rfh->SendNavigate(0, kUrl); + speculative_rfh->SendNavigate(0, entry_id, true, kUrl); EXPECT_EQ(site_instance_id, main_test_rfh()->GetSiteInstance()->GetId()); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)); EXPECT_FALSE(node->render_manager()->pending_frame_host()); @@ -846,7 +853,7 @@ // Begin navigating to another site. const GURL kUrl("http://google.com/"); process()->sink().ClearMessages(); - RequestNavigation(node, kUrl); + int entry_id = RequestNavigation(node, kUrl); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)); // Receive the beforeUnload ACK. @@ -895,7 +902,7 @@ EXPECT_NE(site_instance_id, redirect_site_instance_id); // Invoke OnDidCommitProvisionalLoad. - speculative_rfh->SendNavigate(0, kUrlRedirect); + speculative_rfh->SendNavigate(0, entry_id, true, kUrlRedirect); // Check that the speculative RenderFrameHost was swapped in. EXPECT_EQ(redirect_site_instance_id, @@ -931,7 +938,7 @@ // should be reused. process()->sink().ClearMessages(); rfh1->GetProcess()->sink().ClearMessages(); - RequestNavigation(node, kUrl1); + int entry_id = RequestNavigation(node, kUrl1); EXPECT_FALSE(GetSpeculativeRenderFrameHost(node)); main_test_rfh()->SendBeforeUnloadACK(true); @@ -948,7 +955,7 @@ EXPECT_TRUE(DidRenderFrameHostRequestCommit(rfh1)); EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh())); - rfh1->SendNavigate(1, kUrl1); + rfh1->SendNavigate(1, entry_id, true, kUrl1); EXPECT_EQ(rfh1, main_test_rfh()); EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state()); EXPECT_FALSE(rfhm->IsOnSwappedOutList(rfh1)); @@ -964,7 +971,7 @@ FrameTreeNode* node = main_test_rfh()->frame_tree_node(); // Navigate to a data url. - RequestNavigation(node, kUrl2); + int entry_id = RequestNavigation(node, kUrl2); NavigationRequest* navigation_request = node->navigation_request(); ASSERT_TRUE(navigation_request); EXPECT_EQ(NavigationRequest::WAITING_FOR_RENDERER_RESPONSE, @@ -978,7 +985,7 @@ EXPECT_FALSE(navigation_request->loader_for_testing()); TestRenderFrameHost* speculative_rfh = GetSpeculativeRenderFrameHost(node); ASSERT_TRUE(speculative_rfh); - speculative_rfh->SendNavigate(0, kUrl2); + speculative_rfh->SendNavigate(0, entry_id, true, kUrl2); EXPECT_EQ(main_test_rfh(), speculative_rfh); // Go back to the initial site.
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 57ba8e25..b7b4ee8e 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -1672,14 +1672,8 @@ TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url", validated_url.possibly_invalid_spec()); - ui::PageTransition transition = ui::PAGE_TRANSITION_LINK; - if (frame_tree_node_->parent()) { - transition = params.should_replace_current_entry - ? ui::PAGE_TRANSITION_AUTO_SUBFRAME - : ui::PAGE_TRANSITION_MANUAL_SUBFRAME; - } frame_tree_node_->navigator()->RequestOpenURL( - this, validated_url, source_site_instance, params.referrer, transition, + this, validated_url, source_site_instance, params.referrer, params.disposition, params.should_replace_current_entry, params.user_gesture); }
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc index a704d16c..9344c92 100644 --- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" @@ -87,6 +88,38 @@ } } +// Tests focus behavior when the focused frame is removed from the frame tree. +IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, RemoveFocusedFrame) { + EXPECT_TRUE( + NavigateToURL(shell(), GetTestUrl("render_frame_host", "focus.html"))); + + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + + ExecuteScriptAndGetValue(web_contents->GetMainFrame(), "focusframe4()"); + + // TODO(nick,mlamouri): Add calls to RFHI::IsFocused here once they're not + // flaky. See http://crbug.com/452631, http://crbug.com/464033, etc. + EXPECT_NE(web_contents->GetMainFrame(), web_contents->GetFocusedFrame()); + EXPECT_EQ("frame4", web_contents->GetFocusedFrame()->GetFrameName()); + EXPECT_EQ("frame3", + web_contents->GetFocusedFrame()->GetParent()->GetFrameName()); + EXPECT_NE(-1, web_contents->GetFrameTree()->focused_frame_tree_node_id_); + + ExecuteScriptAndGetValue(web_contents->GetMainFrame(), "detachframe(3)"); + EXPECT_EQ(nullptr, web_contents->GetFocusedFrame()); + EXPECT_EQ(-1, web_contents->GetFrameTree()->focused_frame_tree_node_id_); + + ExecuteScriptAndGetValue(web_contents->GetMainFrame(), "focusframe2()"); + EXPECT_NE(nullptr, web_contents->GetFocusedFrame()); + EXPECT_NE(web_contents->GetMainFrame(), web_contents->GetFocusedFrame()); + EXPECT_NE(-1, web_contents->GetFrameTree()->focused_frame_tree_node_id_); + + ExecuteScriptAndGetValue(web_contents->GetMainFrame(), "detachframe(2)"); + EXPECT_EQ(nullptr, web_contents->GetFocusedFrame()); + EXPECT_EQ(-1, web_contents->GetFrameTree()->focused_frame_tree_node_id_); +} + // Test that even if the frame is focused in the frame tree but its // RenderWidgetHost is not focused, it is not considered as focused. IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, IsFocused_Widget) {
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc index b134423..c9eadcd 100644 --- a/content/browser/frame_host/render_frame_host_manager.cc +++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -663,6 +663,7 @@ // Any currently suspended navigations are no longer needed. render_frame_host->CancelSuspendedNavigations(); + CHECK(!GetRenderFrameProxyHost(site_instance)); RenderFrameProxyHost* proxy = new RenderFrameProxyHost(site_instance, frame_tree_node_); proxy_hosts_[site_instance->GetId()] = proxy; @@ -888,6 +889,17 @@ } } +void RenderFrameHostManager::OnDidUpdateOrigin(const url::Origin& origin) { + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kSitePerProcess)) + return; + + for (const auto& pair : proxy_hosts_) { + pair.second->Send( + new FrameMsg_DidUpdateOrigin(pair.second->GetRoutingID(), origin)); + } +} + void RenderFrameHostManager::Observe( int type, const NotificationSource& source, @@ -1737,8 +1749,8 @@ SetRenderFrameHost(speculative_render_frame_host_.Pass()); } - if (is_main_frame) - render_frame_host_->render_view_host()->AttachToFrameTree(); + // Remove the children of the old frame from the tree. + frame_tree_node_->ResetForNewProcess(); // The process will no longer try to exit, so we can decrement the count. render_frame_host_->GetProcess()->RemovePendingView();
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h index f8004d9..086dea5 100644 --- a/content/browser/frame_host/render_frame_host_manager.h +++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -19,6 +19,7 @@ #include "content/public/browser/notification_registrar.h" #include "content/public/common/referrer.h" #include "ui/base/page_transition_types.h" +#include "url/origin.h" namespace content { class BrowserContext; @@ -417,6 +418,10 @@ // window.name property. void OnDidUpdateName(const std::string& name); + // Send updated origin to all frame proxies when the frame navigates to a new + // origin. + void OnDidUpdateOrigin(const url::Origin& origin); + void EnsureRenderViewInitialized(FrameTreeNode* source, RenderViewHostImpl* render_view_host, SiteInstance* instance);
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc index c5ea0e6..8088ea85 100644 --- a/content/browser/frame_host/render_frame_host_manager_unittest.cc +++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -262,6 +262,7 @@ // for us. controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); // Simulate the BeforeUnload_ACK that is received from the current renderer // for a cross-site navigation. @@ -288,7 +289,7 @@ // state is being checked. RenderFrameHostDeletedObserver rfh_observer(old_rfh); RenderViewHostDeletedObserver rvh_observer(old_rfh->GetRenderViewHost()); - active_rfh->SendNavigate(max_page_id + 1, url); + active_rfh->SendNavigate(max_page_id + 1, entry_id, true, url); // Make sure that we start to run the unload handler at the time of commit. bool expecting_rfh_shutdown = false; @@ -351,6 +352,7 @@ // Navigate to a cross-site URL. contents()->GetController().LoadURL( kDestUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + int entry_id = contents()->GetController().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); @@ -366,7 +368,7 @@ // BeforeUnload finishes. ntp_rfh->SendBeforeUnloadACK(true); - dest_rfh->SendNavigate(101, kDestUrl); + dest_rfh->SendNavigate(101, entry_id, true, kDestUrl); ntp_rfh->OnSwappedOut(); EXPECT_TRUE(ntp_rfh->is_swapped_out()); @@ -435,21 +437,23 @@ // we use the committed one. contents2->GetController().LoadURL( kChromeUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + int entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID(); contents2->GetMainFrame()->PrepareForCommit(); TestRenderFrameHost* ntp_rfh2 = contents2->GetMainFrame(); EXPECT_FALSE(contents2->CrossProcessNavigationPending()); - ntp_rfh2->SendNavigate(100, kChromeUrl); + ntp_rfh2->SendNavigate(100, entry_id, true, kChromeUrl); // The second one is the opposite, creating a cross-site transition and // requiring a beforeunload ack. contents2->GetController().LoadURL( kDestUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID(); contents2->GetMainFrame()->PrepareForCommit(); EXPECT_TRUE(contents2->CrossProcessNavigationPending()); TestRenderFrameHost* dest_rfh2 = contents2->GetPendingMainFrame(); ASSERT_TRUE(dest_rfh2); - dest_rfh2->SendNavigate(101, kDestUrl); + dest_rfh2->SendNavigate(101, entry_id, true, kDestUrl); // The two RFH's should be different in every way. EXPECT_NE(contents()->GetMainFrame()->GetProcess(), dest_rfh2->GetProcess()); @@ -465,8 +469,10 @@ contents2->GetController().LoadURL( kChromeUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID(); contents2->GetMainFrame()->PrepareForCommit(); - contents2->GetPendingMainFrame()->SendNavigate(102, kChromeUrl); + contents2->GetPendingMainFrame()->SendNavigate(102, entry_id, true, + kChromeUrl); EXPECT_NE(contents()->GetMainFrame()->GetSiteInstance(), contents2->GetMainFrame()->GetSiteInstance()); @@ -597,9 +603,11 @@ // Navigate to a cross-site URL and commit the new page. controller().LoadURL( kDestUrl, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame(); - contents()->TestDidNavigate(rfh2, 1, kDestUrl, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(rfh2, 1, entry_id, true, kDestUrl, + ui::PAGE_TRANSITION_TYPED); EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state()); EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state()); @@ -853,6 +861,7 @@ // GetURL() call. controller().LoadURL( kViewSourceUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); // Simulate response from RenderFrame for DispatchBeforeUnload. contents()->GetMainFrame()->PrepareForCommit(); @@ -861,7 +870,7 @@ RenderFrameHost* last_rfh = contents()->GetPendingMainFrame(); int32 new_id = contents()->GetMaxPageIDForSiteInstance(last_rfh->GetSiteInstance()) + 1; - contents()->GetPendingMainFrame()->SendNavigate(new_id, kUrl); + contents()->GetPendingMainFrame()->SendNavigate(new_id, entry_id, true, kUrl); EXPECT_EQ(1, controller().GetLastCommittedEntryIndex()); NavigationEntry* last_committed = controller().GetLastCommittedEntry(); @@ -879,6 +888,7 @@ // Navigate, again. controller().LoadURL( kViewSourceUrl, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); // The same RenderViewHost should be reused. @@ -886,7 +896,7 @@ EXPECT_EQ(last_rfh, contents()->GetMainFrame()); // The renderer sends a commit. - contents()->GetMainFrame()->SendNavigate(new_id, kUrl); + contents()->GetMainFrame()->SendNavigate(new_id, entry_id, false, kUrl); EXPECT_EQ(1, controller().GetLastCommittedEntryIndex()); EXPECT_FALSE(controller().GetPendingEntry()); @@ -1187,7 +1197,9 @@ // Before that RFH has committed, the evil page reloads itself. FrameHostMsg_DidCommitProvisionalLoad_Params params; - params.page_id = 1; + params.page_id = 0; + params.nav_entry_id = 0; + params.did_create_new_entry = false; params.url = kUrl2; params.transition = ui::PAGE_TRANSITION_CLIENT_REDIRECT; params.should_update_history = false; @@ -1267,7 +1279,8 @@ // The back navigation commits. const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry(); - rfh1->SendNavigate(entry1->GetPageID(), entry1->GetURL()); + rfh1->SendNavigate(entry1->GetPageID(), entry1->GetUniqueID(), false, + entry1->GetURL()); EXPECT_TRUE(rfh2->IsWaitingForUnloadACK()); EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh2->rfh_state()); @@ -1275,7 +1288,8 @@ contents()->GetController().GoForward(); contents()->GetMainFrame()->PrepareForCommit(); const NavigationEntry* entry2 = contents()->GetController().GetPendingEntry(); - rfh2->SendNavigate(entry2->GetPageID(), entry2->GetURL()); + rfh2->SendNavigate(entry2->GetPageID(), entry2->GetUniqueID(), false, + entry2->GetURL()); EXPECT_EQ(rfh2, main_test_rfh()); EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state()); EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state()); @@ -1454,7 +1468,8 @@ // The back navigation commits. const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry(); - rfh1->SendNavigate(entry1->GetPageID(), entry1->GetURL()); + rfh1->SendNavigate(entry1->GetPageID(), entry1->GetUniqueID(), false, + entry1->GetURL()); // Ensure the opener is still cleared. EXPECT_FALSE(contents()->HasOpener()); @@ -1487,7 +1502,8 @@ contents()->GetController().GoBack(); contents()->GetMainFrame()->PrepareForCommit(); const NavigationEntry* entry1 = contents()->GetController().GetPendingEntry(); - rfh1->SendNavigate(entry1->GetPageID(), entry1->GetURL()); + rfh1->SendNavigate(entry1->GetPageID(), entry1->GetUniqueID(), false, + entry1->GetURL()); // Disown the opener from rfh2. rfh2->DidDisownOpener(); @@ -1761,6 +1777,7 @@ // Navigate to new site, simulating onbeforeunload approval. controller().LoadURL( kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state()); @@ -1773,7 +1790,8 @@ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state()); // The new page commits. - contents()->TestDidNavigate(rfh2, 1, kUrl2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(rfh2, 1, entry_id, true, kUrl2, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(rfh2, contents()->GetMainFrame()); EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL); @@ -1809,13 +1827,15 @@ // Navigate to new site, simulating onbeforeunload approval. controller().LoadURL( kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state()); TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame(); // The new page commits. - contents()->TestDidNavigate(rfh2, 1, kUrl2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(rfh2, 1, entry_id, true, kUrl2, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(rfh2, contents()->GetMainFrame()); EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL); @@ -1852,12 +1872,14 @@ // Navigate to new site, simulating onbeforeunload approval. controller().LoadURL( kUrl2, Referrer(), ui::PAGE_TRANSITION_LINK, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); rfh1->PrepareForCommit(); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame(); // The new page commits. - contents()->TestDidNavigate(rfh2, 1, kUrl2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(rfh2, 1, entry_id, true, kUrl2, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(rfh2, contents()->GetMainFrame()); EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
diff --git a/content/browser/frame_host/render_widget_host_view_child_frame.h b/content/browser/frame_host/render_widget_host_view_child_frame.h index 84835a8..7e55f0a 100644 --- a/content/browser/frame_host/render_widget_host_view_child_frame.h +++ b/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -125,9 +125,9 @@ #endif // defined(OS_ANDROID) #if defined(OS_WIN) - virtual void SetParentNativeViewAccessible( + void SetParentNativeViewAccessible( gfx::NativeViewAccessible accessible_parent) override; - virtual gfx::NativeViewId GetParentForWindowlessPlugin() const override; + gfx::NativeViewId GetParentForWindowlessPlugin() const override; #endif BrowserAccessibilityManager* CreateBrowserAccessibilityManager( BrowserAccessibilityDelegate* delegate) override;
diff --git a/content/browser/frame_host/render_widget_host_view_guest.h b/content/browser/frame_host/render_widget_host_view_guest.h index c5a6e72..03094865 100644 --- a/content/browser/frame_host/render_widget_host_view_guest.h +++ b/content/browser/frame_host/render_widget_host_view_guest.h
@@ -129,9 +129,9 @@ #endif // defined(OS_ANDROID) #if defined(OS_WIN) - virtual void SetParentNativeViewAccessible( + void SetParentNativeViewAccessible( gfx::NativeViewAccessible accessible_parent) override; - virtual gfx::NativeViewId GetParentForWindowlessPlugin() const override; + gfx::NativeViewId GetParentForWindowlessPlugin() const override; #endif // Overridden from ui::GestureEventHelper.
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_win.h b/content/browser/gamepad/gamepad_platform_data_fetcher_win.h index d5cf2207..33dab0ca2 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_win.h +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
@@ -32,10 +32,10 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher { public: GamepadPlatformDataFetcherWin(); - virtual ~GamepadPlatformDataFetcherWin(); - virtual void GetGamepadData(blink::WebGamepads* pads, - bool devices_changed_hint) override; - virtual void PauseHint(bool paused) override; + ~GamepadPlatformDataFetcherWin() override; + void GetGamepadData(blink::WebGamepads* pads, + bool devices_changed_hint) override; + void PauseHint(bool paused) override; private: // XInput-specific implementation for GetGamepadData.
diff --git a/content/browser/gamepad/raw_input_data_fetcher_win.h b/content/browser/gamepad/raw_input_data_fetcher_win.h index 16908c1..73ade8b 100644 --- a/content/browser/gamepad/raw_input_data_fetcher_win.h +++ b/content/browser/gamepad/raw_input_data_fetcher_win.h
@@ -59,7 +59,7 @@ ~RawInputDataFetcher(); // DestructionObserver overrides. - virtual void WillDestroyCurrentMessageLoop() override; + void WillDestroyCurrentMessageLoop() override; bool Available() { return rawinput_available_; } void StartMonitor();
diff --git a/content/browser/geolocation/geolocation_provider_impl_unittest.cc b/content/browser/geolocation/geolocation_provider_impl_unittest.cc index f201f48..685818b 100644 --- a/content/browser/geolocation/geolocation_provider_impl_unittest.cc +++ b/content/browser/geolocation/geolocation_provider_impl_unittest.cc
@@ -78,8 +78,8 @@ explicit GeopositionEqMatcher(const Geoposition& expected) : expected_(expected) {} - virtual bool MatchAndExplain(const Geoposition& actual, - MatchResultListener* listener) const override { + bool MatchAndExplain(const Geoposition& actual, + MatchResultListener* listener) const override { return actual.latitude == expected_.latitude && actual.longitude == expected_.longitude && actual.altitude == expected_.altitude && @@ -92,11 +92,11 @@ actual.error_message == expected_.error_message; } - virtual void DescribeTo(::std::ostream* os) const override { + void DescribeTo(::std::ostream* os) const override { *os << "which matches the expected position"; } - virtual void DescribeNegationTo(::std::ostream* os) const override { + void DescribeNegationTo(::std::ostream* os) const override { *os << "which does not match the expected position"; }
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc index 1eeb2ee..7154c2ee 100644 --- a/content/browser/gpu/gpu_ipc_browsertests.cc +++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -209,7 +209,7 @@ scoped_refptr<ContextProviderCommandBuffer> provider = ContextProviderCommandBuffer::Create(CreateContext(), - "BrowserGpuChannelHostFactoryTest"); + OFFSCREEN_CONTEXT_FOR_TESTING); base::RunLoop run_loop; int counter = 0; provider->SetLostContextCallback(
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index be14374..8c1f8c12 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -158,7 +158,7 @@ ~GpuSandboxedProcessLauncherDelegate() override {} #if defined(OS_WIN) - virtual bool ShouldSandbox() override { + bool ShouldSandbox() override { bool sandbox = !cmd_line_->HasSwitch(switches::kDisableGpuSandbox); if(! sandbox) { DVLOG(1) << "GPU sandbox is disabled"; @@ -166,8 +166,8 @@ return sandbox; } - virtual void PreSandbox(bool* disable_default_policy, - base::FilePath* exposed_dir) override { + void PreSandbox(bool* disable_default_policy, + base::FilePath* exposed_dir) override { *disable_default_policy = true; } @@ -175,8 +175,7 @@ // which is USER_RESTRICTED breaks both the DirectX backend and the OpenGL // backend. Note that the GPU process is connected to the interactive // desktop. - virtual void PreSpawnTarget(sandbox::TargetPolicy* policy, - bool* success) { + void PreSpawnTarget(sandbox::TargetPolicy* policy, bool* success) override { if (base::win::GetVersion() > base::win::VERSION_XP) { if (cmd_line_->GetSwitchValueASCII(switches::kUseGL) == gfx::kGLImplementationDesktopName) {
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index e7107c5..5000e50 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -2242,8 +2242,7 @@ : waiting_for_callback_(false), database_id_(database_id), backing_store_(backing_store), - callback_(callback), - aborted_(false) { + callback_(callback) { blobs_.swap(*blobs); iter_ = blobs_.begin(); backing_store->task_runner()->PostTask( @@ -2261,8 +2260,8 @@ if (delegate_.get()) // Only present for Blob, not File. content::BrowserThread::DeleteSoon( content::BrowserThread::IO, FROM_HERE, delegate_.release()); - if (aborted_) { - self_ref_ = NULL; + if (aborted_self_ref_.get()) { + aborted_self_ref_ = NULL; return; } if (iter_->size() != -1 && iter_->size() != bytes_written) @@ -2278,38 +2277,36 @@ void Abort() override { if (!waiting_for_callback_) return; - self_ref_ = this; - aborted_ = true; + aborted_self_ref_ = this; } private: - ~ChainedBlobWriterImpl() override {} + ~ChainedBlobWriterImpl() override { DCHECK(!waiting_for_callback_); } void WriteNextFile() { DCHECK(!waiting_for_callback_); - DCHECK(!aborted_); + DCHECK(!aborted_self_ref_.get()); if (iter_ == blobs_.end()) { - DCHECK(!self_ref_.get()); callback_->Run(true); return; } else { + waiting_for_callback_ = true; if (!backing_store_->WriteBlobFile(database_id_, *iter_, this)) { + waiting_for_callback_ = false; callback_->Run(false); return; } - waiting_for_callback_ = true; } } bool waiting_for_callback_; - scoped_refptr<ChainedBlobWriterImpl> self_ref_; + scoped_refptr<ChainedBlobWriterImpl> aborted_self_ref_; WriteDescriptorVec blobs_; WriteDescriptorVec::const_iterator iter_; int64 database_id_; IndexedDBBackingStore* backing_store_; scoped_refptr<IndexedDBBackingStore::BlobWriteCallback> callback_; scoped_ptr<FileWriterDelegate> delegate_; - bool aborted_; DISALLOW_COPY_AND_ASSIGN(ChainedBlobWriterImpl); };
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc index 9ad5b4d..21f6ad6 100644 --- a/content/browser/indexed_db/indexed_db_browsertest.cc +++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -492,14 +492,22 @@ // => IndexedDBBackingStore::SetUpMetadata // #2: IndexedDBBackingStore::OpenBackingStore // => IndexedDBBackingStore::CleanUpBlobJournal (no-op) - // * The test calls open(), to create a new database: - // #3: IndexedDBFactoryImpl::Open + // * Then deletes the database: + // #3: IndexedDBFactoryImpl::DeleteDatabase // => IndexedDBDatabase::Create // => IndexedDBBackingStore::CreateIDBDatabaseMetaData - // #4: IndexedDBTransaction::Commit - initial "versionchange" transaction + // #4: IndexedDBFactoryImpl::DeleteDatabase + // => IndexedDBDatabase::DeleteDatabase + // => IndexedDBBackingStore::DeleteDatabase + // => IndexedDBBackingStore::CleanUpBlobJournal (no-op) + // * The test calls open(), to create a new database: + // #5: IndexedDBFactoryImpl::Open + // => IndexedDBDatabase::Create + // => IndexedDBBackingStore::CreateIDBDatabaseMetaData + // #6: IndexedDBTransaction::Commit - initial "versionchange" transaction // * Once the connection is opened, the test runs: - // #5: IndexedDBTransaction::Commit - the test's "readwrite" transaction) - const int instance_num = 5; + // #7: IndexedDBTransaction::Commit - the test's "readwrite" transaction) + const int instance_num = 7; const int call_num = 1; FailOperation(FAIL_CLASS_LEVELDB_TRANSACTION, FAIL_METHOD_COMMIT_DISK_FULL, instance_num, call_num);
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc index 039cbddf..f818f3f 100644 --- a/content/browser/indexed_db/indexed_db_factory_impl.cc +++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -257,26 +257,6 @@ return; } - std::vector<base::string16> names = backing_store->GetDatabaseNames(&s); - if (!s.ok()) { - DLOG(ERROR) << "Internal error getting database names"; - IndexedDBDatabaseError error(blink::WebIDBDatabaseExceptionUnknownError, - "Internal error opening backing store for " - "indexedDB.deleteDatabase."); - callbacks->OnError(error); - backing_store = NULL; - if (s.IsCorruption()) - HandleBackingStoreCorruption(origin_url, error); - return; - } - if (!ContainsValue(names, name)) { - const int64 version = 0; - callbacks->OnSuccess(version); - backing_store = NULL; - ReleaseBackingStore(origin_url, false /* immediate */); - return; - } - scoped_refptr<IndexedDBDatabase> database = IndexedDBDatabase::Create( name, backing_store.get(), this, unique_identifier, &s); if (!database.get()) {
diff --git a/content/browser/indexed_db/indexed_db_quota_client.h b/content/browser/indexed_db/indexed_db_quota_client.h index 7894a65..b9e9bce 100644 --- a/content/browser/indexed_db/indexed_db_quota_client.h +++ b/content/browser/indexed_db/indexed_db_quota_client.h
@@ -22,8 +22,7 @@ // A QuotaClient implementation to integrate IndexedDB // with the quota management system. This interface is used // on the IO thread by the quota manager. -class IndexedDBQuotaClient : public storage::QuotaClient, - public storage::QuotaTaskObserver { +class IndexedDBQuotaClient : public storage::QuotaClient { public: CONTENT_EXPORT explicit IndexedDBQuotaClient( IndexedDBContextImpl* indexed_db_context);
diff --git a/content/browser/indexed_db/mock_indexed_db_factory.h b/content/browser/indexed_db/mock_indexed_db_factory.h index 9c4e3f40..b480758 100644 --- a/content/browser/indexed_db/mock_indexed_db_factory.h +++ b/content/browser/indexed_db/mock_indexed_db_factory.h
@@ -41,8 +41,7 @@ const IndexedDBDatabaseError& error)); // The Android NDK implements a subset of STL, and the gtest templates can't // deal with std::pair's. This means we can't use GoogleMock for this method - virtual OriginDBs GetOpenDatabasesForOrigin( - const GURL& origin_url) const override; + OriginDBs GetOpenDatabasesForOrigin(const GURL& origin_url) const override; MOCK_METHOD1(ForceClose, void(const GURL& origin_url)); MOCK_METHOD0(ContextDestroyed, void()); MOCK_METHOD1(DatabaseDeleted,
diff --git a/content/browser/media/capture/animated_content_sampler.cc b/content/browser/media/capture/animated_content_sampler.cc new file mode 100644 index 0000000..a30364b0 --- /dev/null +++ b/content/browser/media/capture/animated_content_sampler.cc
@@ -0,0 +1,222 @@ +// Copyright (c) 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/media/capture/animated_content_sampler.h" + +#include <algorithm> + +namespace content { + +namespace { + +// These specify the minimum/maximum amount of recent event history to examine +// to detect animated content. If the values are too low, there is a greater +// risk of false-positive detections and low accuracy. If they are too high, +// the the implementation will be slow to lock-in/out, and also will not react +// well to mildly-variable frame rate content (e.g., 25 +/- 1 FPS). +// +// These values were established by experimenting with a wide variety of +// scenarios, including 24/25/30 FPS videos, 60 FPS WebGL demos, and the +// transitions between static and animated content. +const int kMinObservationWindowMillis = 1000; +const int kMaxObservationWindowMillis = 2000; + +// The maximum amount of time that can elapse before declaring two subsequent +// events as "not animating." This is the same value found in +// cc::FrameRateCounter. +const int kNonAnimatingThresholdMillis = 250; // 4 FPS + +// The slowest that content can be animating in order for AnimatedContentSampler +// to lock-in. This is the threshold at which the "smoothness" problem is no +// longer relevant. +const int kMaxLockInPeriodMicros = 83333; // 12 FPS + +// The amount of time over which to fully correct the drift of the rewritten +// frame timestamps from the presentation event timestamps. The lower the +// value, the higher the variance in frame timestamps. +const int kDriftCorrectionMillis = 2000; + +} // anonymous namespace + +AnimatedContentSampler::AnimatedContentSampler( + base::TimeDelta min_capture_period) + : min_capture_period_(min_capture_period) {} + +AnimatedContentSampler::~AnimatedContentSampler() {} + +void AnimatedContentSampler::ConsiderPresentationEvent( + const gfx::Rect& damage_rect, base::TimeTicks event_time) { + AddObservation(damage_rect, event_time); + + if (AnalyzeObservations(event_time, &detected_region_, &detected_period_) && + detected_period_ > base::TimeDelta() && + detected_period_ <= + base::TimeDelta::FromMicroseconds(kMaxLockInPeriodMicros)) { + if (damage_rect == detected_region_) + UpdateFrameTimestamp(event_time); + else + frame_timestamp_ = base::TimeTicks(); + } else { + detected_region_ = gfx::Rect(); + detected_period_ = base::TimeDelta(); + frame_timestamp_ = base::TimeTicks(); + } +} + +bool AnimatedContentSampler::HasProposal() const { + return detected_period_ > base::TimeDelta(); +} + +bool AnimatedContentSampler::ShouldSample() const { + return !frame_timestamp_.is_null(); +} + +void AnimatedContentSampler::RecordSample(base::TimeTicks frame_timestamp) { + recorded_frame_timestamp_ = + HasProposal() ? frame_timestamp : base::TimeTicks(); + sequence_offset_ = base::TimeDelta(); +} + +void AnimatedContentSampler::AddObservation(const gfx::Rect& damage_rect, + base::TimeTicks event_time) { + if (damage_rect.IsEmpty()) + return; // Useless observation. + + // Add the observation to the FIFO queue. + if (!observations_.empty() && observations_.back().event_time > event_time) + return; // The implementation assumes chronological order. + observations_.push_back(Observation(damage_rect, event_time)); + + // Prune-out old observations. + const base::TimeDelta threshold = + base::TimeDelta::FromMilliseconds(kMaxObservationWindowMillis); + while ((event_time - observations_.front().event_time) > threshold) + observations_.pop_front(); +} + +gfx::Rect AnimatedContentSampler::ElectMajorityDamageRect() const { + // This is an derivative of the Boyer-Moore Majority Vote Algorithm where each + // pixel in a candidate gets one vote, as opposed to each candidate getting + // one vote. + const gfx::Rect* candidate = NULL; + int64 votes = 0; + for (ObservationFifo::const_iterator i = observations_.begin(); + i != observations_.end(); ++i) { + DCHECK_GT(i->damage_rect.size().GetArea(), 0); + if (votes == 0) { + candidate = &(i->damage_rect); + votes = candidate->size().GetArea(); + } else if (i->damage_rect == *candidate) { + votes += i->damage_rect.size().GetArea(); + } else { + votes -= i->damage_rect.size().GetArea(); + if (votes < 0) { + candidate = &(i->damage_rect); + votes = -votes; + } + } + } + return (votes > 0) ? *candidate : gfx::Rect(); +} + +bool AnimatedContentSampler::AnalyzeObservations( + base::TimeTicks event_time, + gfx::Rect* rect, + base::TimeDelta* period) const { + const gfx::Rect elected_rect = ElectMajorityDamageRect(); + if (elected_rect.IsEmpty()) + return false; // There is no regular animation present. + + // Scan |observations_|, gathering metrics about the ones having a damage Rect + // equivalent to the |elected_rect|. Along the way, break early whenever the + // event times reveal a non-animating period. + int64 num_pixels_damaged_in_all = 0; + int64 num_pixels_damaged_in_chosen = 0; + base::TimeDelta sum_frame_durations; + size_t count_frame_durations = 0; + base::TimeTicks first_event_time; + base::TimeTicks last_event_time; + for (ObservationFifo::const_reverse_iterator i = observations_.rbegin(); + i != observations_.rend(); ++i) { + const int area = i->damage_rect.size().GetArea(); + num_pixels_damaged_in_all += area; + if (i->damage_rect != elected_rect) + continue; + num_pixels_damaged_in_chosen += area; + if (last_event_time.is_null()) { + last_event_time = i->event_time; + if ((event_time - last_event_time) >= + base::TimeDelta::FromMilliseconds(kNonAnimatingThresholdMillis)) { + return false; // Content animation has recently ended. + } + } else { + const base::TimeDelta frame_duration = first_event_time - i->event_time; + if (frame_duration >= + base::TimeDelta::FromMilliseconds(kNonAnimatingThresholdMillis)) { + break; // Content not animating before this point. + } + sum_frame_durations += frame_duration; + ++count_frame_durations; + } + first_event_time = i->event_time; + } + + if ((last_event_time - first_event_time) < + base::TimeDelta::FromMilliseconds(kMinObservationWindowMillis)) { + return false; // Content has not animated for long enough for accuracy. + } + if (num_pixels_damaged_in_chosen <= (num_pixels_damaged_in_all * 2 / 3)) + return false; // Animation is not damaging a supermajority of pixels. + + *rect = elected_rect; + DCHECK_GT(count_frame_durations, 0u); + *period = sum_frame_durations / count_frame_durations; + return true; +} + +void AnimatedContentSampler::UpdateFrameTimestamp(base::TimeTicks event_time) { + // This is how much time to advance from the last frame timestamp. Never + // advance by less than |min_capture_period_| because the downstream consumer + // cannot handle the higher frame rate. If |detected_period_| is less than + // |min_capture_period_|, excess frames should be dropped. + const base::TimeDelta advancement = + std::max(detected_period_, min_capture_period_); + + // Compute the |timebase| upon which to determine the |frame_timestamp_|. + // Ideally, this would always equal the timestamp of the last recorded frame + // sampling. Determine how much drift from the ideal is present, then adjust + // the timebase by a small amount to spread out the entire correction over + // many frame timestamps. + // + // This accounts for two main sources of drift: 1) The clock drift of the + // system clock relative to the video hardware, which affects the event times; + // and 2) The small error introduced by this frame timestamp rewriting, as it + // is based on averaging over recent events. + base::TimeTicks timebase = event_time - sequence_offset_ - advancement; + if (!recorded_frame_timestamp_.is_null()) { + const base::TimeDelta drift = recorded_frame_timestamp_ - timebase; + const int64 correct_over_num_frames = + base::TimeDelta::FromMilliseconds(kDriftCorrectionMillis) / + detected_period_; + DCHECK_GT(correct_over_num_frames, 0); + timebase = recorded_frame_timestamp_ - (drift / correct_over_num_frames); + } + + // Compute |frame_timestamp_|. Whenever |detected_period_| is less than + // |min_capture_period_|, some extra time is "borrowed" to be able to advance + // by the full |min_capture_period_|. Then, whenever the total amount of + // borrowed time reaches a full |min_capture_period_|, drop a frame. Note + // that when |detected_period_| is greater or equal to |min_capture_period_|, + // this logic is effectively disabled. + borrowed_time_ += advancement - detected_period_; + if (borrowed_time_ >= min_capture_period_) { + borrowed_time_ -= min_capture_period_; + frame_timestamp_ = base::TimeTicks(); + } else { + sequence_offset_ += advancement; + frame_timestamp_ = timebase + sequence_offset_; + } +} + +} // namespace content
diff --git a/content/browser/media/capture/animated_content_sampler.h b/content/browser/media/capture/animated_content_sampler.h new file mode 100644 index 0000000..de7b3016 --- /dev/null +++ b/content/browser/media/capture/animated_content_sampler.h
@@ -0,0 +1,127 @@ +// Copyright (c) 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_MEDIA_CAPTURE_ANIMATED_CONTENT_SAMPLER_H_ +#define CONTENT_BROWSER_MEDIA_CAPTURE_ANIMATED_CONTENT_SAMPLER_H_ + +#include <deque> + +#include "base/time/time.h" +#include "content/common/content_export.h" +#include "ui/gfx/geometry/rect.h" + +namespace content { + +// Analyzes a sequence of events to detect the presence of constant frame rate +// animated content. In the case where there are multiple regions of animated +// content, AnimatedContentSampler will propose sampling the one having the +// largest "smoothness" impact, according to human perception (e.g., a 24 FPS +// video versus a 60 FPS busy spinner). +// +// In addition, AnimatedContentSampler will provide rewritten frame timestamps, +// for downstream consumers, that are "truer" to the source content than to the +// local presentation hardware. +class CONTENT_EXPORT AnimatedContentSampler { + public: + explicit AnimatedContentSampler(base::TimeDelta min_capture_period); + ~AnimatedContentSampler(); + + // Examines the given presentation event metadata, along with recent history, + // to detect animated content, updating the state of this sampler. + // |damage_rect| is the region of a frame about to be drawn, while + // |event_time| refers to the frame's estimated presentation time. + void ConsiderPresentationEvent(const gfx::Rect& damage_rect, + base::TimeTicks event_time); + + // Returns true if animated content has been detected and a decision has been + // made about whether to sample the last event. + bool HasProposal() const; + + // Returns true if the last event considered should be sampled. + bool ShouldSample() const; + + // Returns a frame timestamp to provide to consumers of the sampled frame. + // Only valid when should_sample() returns true. + base::TimeTicks frame_timestamp() const { return frame_timestamp_; } + + // Accessors to currently-detected animating region/period, for logging. + const gfx::Rect& detected_region() const { return detected_region_; } + base::TimeDelta detected_period() const { return detected_period_; } + + // Records that a frame with the given |frame_timestamp| was sampled. This + // method should be called when *any* sampling is taken, even if it was not + // proposed by AnimatedContentSampler. + void RecordSample(base::TimeTicks frame_timestamp); + + private: + friend class AnimatedContentSamplerTest; + + // Data structure for efficient online analysis of recent event history. + struct Observation { + gfx::Rect damage_rect; + base::TimeTicks event_time; + + Observation(const gfx::Rect& d, base::TimeTicks e) + : damage_rect(d), event_time(e) {} + }; + typedef std::deque<Observation> ObservationFifo; + + // Adds an observation to |observations_|, and prunes-out the old ones. + void AddObservation(const gfx::Rect& damage_rect, base::TimeTicks event_time); + + // Returns the damage Rect that is responsible for the majority of the pixel + // damage in recent event history, if there is such a Rect. If there isn't, + // this method could still return any Rect, so the caller must confirm the + // returned Rect really is responsible for the majority of pixel damage. + gfx::Rect ElectMajorityDamageRect() const; + + // Analyzes the observations relative to the current |event_time| to detect + // stable animating content. If detected, returns true and sets the output + // arguments to the region of the animating content and its mean frame + // duration. + bool AnalyzeObservations(base::TimeTicks event_time, + gfx::Rect* rect, + base::TimeDelta* period) const; + + // Called by ConsiderPresentationEvent() when the current event is part of a + // detected animation, to update |frame_timestamp_|. + void UpdateFrameTimestamp(base::TimeTicks event_time); + + // The client expects frame timestamps to be at least this far apart. + const base::TimeDelta min_capture_period_; + + // A recent history of observations in chronological order, maintained by + // AddObservation(). + ObservationFifo observations_; + + // The region of currently-detected animated content. If empty, that means + // "not detected." + gfx::Rect detected_region_; + + // The mean frame duration of currently-detected animated content. If zero, + // that means "not detected." + base::TimeDelta detected_period_; + + // The rewritten frame timestamp for the latest event. + base::TimeTicks frame_timestamp_; + + // The frame timestamp provided in the last call to RecordSample(). This + // timestamp may or may not have been one proposed by AnimatedContentSampler. + base::TimeTicks recorded_frame_timestamp_; + + // Accumulates all the time advancements since the last call to + // RecordSample(). When this is greater than zero, there have been one or + // more events proposed for sampling, but not yet recorded. This accounts for + // the cases where AnimatedContentSampler indicates a frame should be sampled, + // but the client chooses not to do so. + base::TimeDelta sequence_offset_; + + // A token bucket that is used to decide which frames to drop whenever + // |detected_period_| is less than |min_capture_period_|. + base::TimeDelta borrowed_time_; +}; + +} // namespace content + +#endif // CONTENT_BROWSER_MEDIA_CAPTURE_ANIMATED_CONTENT_SAMPLER_H_
diff --git a/content/browser/media/capture/animated_content_sampler_unittest.cc b/content/browser/media/capture/animated_content_sampler_unittest.cc new file mode 100644 index 0000000..a101737 --- /dev/null +++ b/content/browser/media/capture/animated_content_sampler_unittest.cc
@@ -0,0 +1,641 @@ +// Copyright (c) 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/media/capture/animated_content_sampler.h" + +#include <cstdlib> +#include <utility> +#include <vector> + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/time/time.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/rect.h" + +namespace content { + +namespace { + +base::TimeTicks InitialTestTimeTicks() { + return base::TimeTicks() + base::TimeDelta::FromSeconds(1); +} + +} // namespace + +class AnimatedContentSamplerTest : public ::testing::Test { + public: + AnimatedContentSamplerTest() {} + ~AnimatedContentSamplerTest() override {} + + void SetUp() override { + const base::TimeDelta since_epoch = + InitialTestTimeTicks() - base::TimeTicks::UnixEpoch(); + rand_seed_ = abs(static_cast<int>(since_epoch.InMicroseconds())); + sampler_.reset(new AnimatedContentSampler(GetMinCapturePeriod())); + } + + protected: + // Overridden by subclass for parameterized tests. + virtual base::TimeDelta GetMinCapturePeriod() const { + return base::TimeDelta::FromSeconds(1) / 30; + } + + AnimatedContentSampler* sampler() const { + return sampler_.get(); + } + + int GetRandomInRange(int begin, int end) { + const int len = end - begin; + const int rand_offset = (len == 0) ? 0 : (NextRandomInt() % (end - begin)); + return begin + rand_offset; + } + + gfx::Rect GetRandomDamageRect() { + return gfx::Rect(0, 0, GetRandomInRange(1, 100), GetRandomInRange(1, 100)); + } + + gfx::Rect GetContentDamageRect() { + // This must be distinct from anything GetRandomDamageRect() could return. + return gfx::Rect(0, 0, 1280, 720); + } + + // Directly inject an observation. Only used to test + // ElectMajorityDamageRect(). + void ObserveDamageRect(const gfx::Rect& damage_rect) { + sampler_->observations_.push_back( + AnimatedContentSampler::Observation(damage_rect, base::TimeTicks())); + } + + gfx::Rect ElectMajorityDamageRect() const { + return sampler_->ElectMajorityDamageRect(); + } + + private: + // Note: Not using base::RandInt() because it is horribly slow on debug + // builds. The following is a very simple, deterministic LCG: + int NextRandomInt() { + rand_seed_ = (1103515245 * rand_seed_ + 12345) % (1 << 31); + return rand_seed_; + } + + int rand_seed_; + scoped_ptr<AnimatedContentSampler> sampler_; +}; + +TEST_F(AnimatedContentSamplerTest, ElectsNoneFromZeroDamageRects) { + EXPECT_EQ(gfx::Rect(), ElectMajorityDamageRect()); +} + +TEST_F(AnimatedContentSamplerTest, ElectsMajorityFromOneDamageRect) { + const gfx::Rect the_one_rect(0, 0, 1, 1); + ObserveDamageRect(the_one_rect); + EXPECT_EQ(the_one_rect, ElectMajorityDamageRect()); +} + +TEST_F(AnimatedContentSamplerTest, ElectsNoneFromTwoDamageRectsOfSameArea) { + const gfx::Rect one_rect(0, 0, 1, 1); + const gfx::Rect another_rect(1, 1, 1, 1); + ObserveDamageRect(one_rect); + ObserveDamageRect(another_rect); + EXPECT_EQ(gfx::Rect(), ElectMajorityDamageRect()); +} + +TEST_F(AnimatedContentSamplerTest, ElectsLargerOfTwoDamageRects_1) { + const gfx::Rect one_rect(0, 0, 1, 1); + const gfx::Rect another_rect(0, 0, 2, 2); + ObserveDamageRect(one_rect); + ObserveDamageRect(another_rect); + EXPECT_EQ(another_rect, ElectMajorityDamageRect()); +} + +TEST_F(AnimatedContentSamplerTest, ElectsLargerOfTwoDamageRects_2) { + const gfx::Rect one_rect(0, 0, 2, 2); + const gfx::Rect another_rect(0, 0, 1, 1); + ObserveDamageRect(one_rect); + ObserveDamageRect(another_rect); + EXPECT_EQ(one_rect, ElectMajorityDamageRect()); +} + +TEST_F(AnimatedContentSamplerTest, ElectsSameAsMooreDemonstration) { + // A more complex sequence (from Moore's web site): Three different Rects with + // the same area, but occurring a different number of times. C should win the + // vote. + const gfx::Rect rect_a(0, 0, 1, 4); + const gfx::Rect rect_b(1, 1, 4, 1); + const gfx::Rect rect_c(2, 2, 2, 2); + for (int i = 0; i < 3; ++i) + ObserveDamageRect(rect_a); + for (int i = 0; i < 2; ++i) + ObserveDamageRect(rect_c); + for (int i = 0; i < 2; ++i) + ObserveDamageRect(rect_b); + for (int i = 0; i < 3; ++i) + ObserveDamageRect(rect_c); + ObserveDamageRect(rect_b); + for (int i = 0; i < 2; ++i) + ObserveDamageRect(rect_c); + EXPECT_EQ(rect_c, ElectMajorityDamageRect()); +} + +TEST_F(AnimatedContentSamplerTest, Elects24FpsVideoInsteadOf48FpsSpinner) { + // Scenario: 24 FPS 720x480 Video versus 48 FPS 96x96 "Busy Spinner" + const gfx::Rect video_rect(100, 100, 720, 480); + const gfx::Rect spinner_rect(360, 0, 96, 96); + for (int i = 0; i < 100; ++i) { + // |video_rect| occurs once for every two |spinner_rect|. Vary the order + // of events between the two: + ObserveDamageRect(video_rect); + ObserveDamageRect(spinner_rect); + ObserveDamageRect(spinner_rect); + ObserveDamageRect(video_rect); + ObserveDamageRect(spinner_rect); + ObserveDamageRect(spinner_rect); + ObserveDamageRect(spinner_rect); + ObserveDamageRect(video_rect); + ObserveDamageRect(spinner_rect); + ObserveDamageRect(spinner_rect); + ObserveDamageRect(video_rect); + ObserveDamageRect(spinner_rect); + } + EXPECT_EQ(video_rect, ElectMajorityDamageRect()); +} + +namespace { + +// A test scenario for AnimatedContentSamplerParameterizedTest. +struct Scenario { + base::TimeDelta vsync_interval; // Reflects compositor's update rate. + base::TimeDelta min_capture_period; // Reflects maximum capture rate. + base::TimeDelta content_period; // Reflects content animation rate. + + Scenario(base::TimeDelta v, base::TimeDelta m, base::TimeDelta c) + : vsync_interval(v), min_capture_period(m), content_period(c) { + CHECK(content_period >= vsync_interval) + << "Bad test params: Impossible to animate faster than the compositor."; + } +}; + +// Value printer for Scenario. +::std::ostream& operator<<(::std::ostream& os, const Scenario& s) { + return os << "{ vsync_interval=" << s.vsync_interval.InMicroseconds() + << ", min_capture_period=" << s.min_capture_period.InMicroseconds() + << ", content_period=" << s.content_period.InMicroseconds() + << " }"; +} + +base::TimeDelta FpsAsPeriod(int frame_rate) { + return base::TimeDelta::FromSeconds(1) / frame_rate; +} + +} // namespace + +class AnimatedContentSamplerParameterizedTest + : public AnimatedContentSamplerTest, + public ::testing::WithParamInterface<Scenario> { + public: + AnimatedContentSamplerParameterizedTest() + : count_dropped_frames_(0), count_sampled_frames_(0) {} + virtual ~AnimatedContentSamplerParameterizedTest() {} + + protected: + typedef std::pair<gfx::Rect, base::TimeTicks> Event; + + base::TimeDelta GetMinCapturePeriod() const override { + return GetParam().min_capture_period; + } + + // Generate a sequence of events from the compositor pipeline. The event + // times will all be at compositor vsync boundaries. + std::vector<Event> GenerateEventSequence(base::TimeTicks begin, + base::TimeTicks end, + bool include_content_frame_events, + bool include_random_events) { + DCHECK(GetParam().content_period >= GetParam().vsync_interval); + base::TimeTicks next_content_time = begin - GetParam().content_period; + std::vector<Event> events; + for (base::TimeTicks compositor_time = begin; compositor_time < end; + compositor_time += GetParam().vsync_interval) { + if (include_content_frame_events && next_content_time < compositor_time) { + events.push_back(Event(GetContentDamageRect(), compositor_time)); + next_content_time += GetParam().content_period; + } else if (include_random_events && GetRandomInRange(0, 1) == 0) { + events.push_back(Event(GetRandomDamageRect(), compositor_time)); + } + } + + DCHECK(!events.empty()); + return events; + } + + // Feed |events| through the sampler, and detect whether the expected + // lock-in/out transition occurs. Also, track and measure the frame drop + // ratio and check it against the expected drop rate. + void RunEventSequence(const std::vector<Event> events, + bool was_detecting_before, + bool is_detecting_after, + bool simulate_pipeline_back_pressure) { + gfx::Rect first_detected_region; + + EXPECT_EQ(was_detecting_before, sampler()->HasProposal()); + bool has_detection_switched = false; + ResetFrameCounters(); + for (std::vector<Event>::const_iterator i = events.begin(); + i != events.end(); ++i) { + sampler()->ConsiderPresentationEvent(i->first, i->second); + + // Detect when the sampler locks in/out, and that it stays that way for + // all further iterations of this loop. + if (!has_detection_switched && + was_detecting_before != sampler()->HasProposal()) { + has_detection_switched = true; + } + ASSERT_EQ( + has_detection_switched ? is_detecting_after : was_detecting_before, + sampler()->HasProposal()); + + if (sampler()->HasProposal()) { + // Make sure the sampler doesn't flip-flop and keep proposing sampling + // based on locking into different regions. + if (first_detected_region.IsEmpty()) { + first_detected_region = sampler()->detected_region(); + ASSERT_FALSE(first_detected_region.IsEmpty()); + } else { + EXPECT_EQ(first_detected_region, sampler()->detected_region()); + } + + if (simulate_pipeline_back_pressure && GetRandomInRange(0, 2) == 0) + ClientCannotSampleFrame(*i); + else + ClientDoesWhatSamplerProposes(*i); + } else { + EXPECT_FALSE(sampler()->ShouldSample()); + if (!simulate_pipeline_back_pressure || GetRandomInRange(0, 2) == 1) + sampler()->RecordSample(i->second); + } + } + EXPECT_EQ(is_detecting_after, sampler()->HasProposal()); + ExpectFrameDropRatioIsCorrect(); + } + + void ResetFrameCounters() { + count_dropped_frames_ = 0; + count_sampled_frames_ = 0; + } + + // Keep track what the sampler is proposing, and call RecordSample() if it + // proposes sampling |event|. + void ClientDoesWhatSamplerProposes(const Event& event) { + if (sampler()->ShouldSample()) { + EXPECT_EQ(GetContentDamageRect(), event.first); + sampler()->RecordSample(sampler()->frame_timestamp()); + ++count_sampled_frames_; + } else if (event.first == GetContentDamageRect()) { + ++count_dropped_frames_; + } + } + + // RecordSample() is not called, but for testing, keep track of what the + // sampler is proposing for |event|. + void ClientCannotSampleFrame(const Event& event) { + if (sampler()->ShouldSample()) { + EXPECT_EQ(GetContentDamageRect(), event.first); + ++count_sampled_frames_; + } else if (event.first == GetContentDamageRect()) { + ++count_dropped_frames_; + } + } + + // Confirm the AnimatedContentSampler is not dropping more frames than + // expected, given current test parameters. + void ExpectFrameDropRatioIsCorrect() { + if (count_sampled_frames_ == 0) { + EXPECT_EQ(0, count_dropped_frames_); + return; + } + const double content_framerate = + 1000000.0 / GetParam().content_period.InMicroseconds(); + const double capture_framerate = + 1000000.0 / GetParam().min_capture_period.InMicroseconds(); + const double expected_drop_rate = std::max( + 0.0, (content_framerate - capture_framerate) / capture_framerate); + const double actual_drop_rate = + static_cast<double>(count_dropped_frames_) / count_sampled_frames_; + EXPECT_NEAR(expected_drop_rate, actual_drop_rate, 0.015); + } + + private: + // These counters only include the frames with the desired content. + int count_dropped_frames_; + int count_sampled_frames_; +}; + +// Tests that the implementation locks in/out of frames containing stable +// animated content, whether or not random events are also simultaneously +// present. +TEST_P(AnimatedContentSamplerParameterizedTest, DetectsAnimatedContent) { + // |begin| refers to the start of an event sequence in terms of the + // Compositor's clock. + base::TimeTicks begin = InitialTestTimeTicks(); + + // Provide random events and expect no lock-in. + base::TimeTicks end = begin + base::TimeDelta::FromSeconds(5); + RunEventSequence(GenerateEventSequence(begin, end, false, true), + false, + false, + false); + begin = end; + + // Provide content frame events with some random events mixed-in, and expect + // the sampler to lock-in. + end = begin + base::TimeDelta::FromSeconds(5); + RunEventSequence(GenerateEventSequence(begin, end, true, true), + false, + true, + false); + begin = end; + + // Continue providing content frame events without the random events mixed-in + // and expect the lock-in to hold. + end = begin + base::TimeDelta::FromSeconds(5); + RunEventSequence(GenerateEventSequence(begin, end, true, false), + true, + true, + false); + begin = end; + + // Continue providing just content frame events and expect the lock-in to + // hold. Also simulate the capture pipeline experiencing back pressure. + end = begin + base::TimeDelta::FromSeconds(20); + RunEventSequence(GenerateEventSequence(begin, end, true, false), + true, + true, + true); + begin = end; + + // Provide a half-second of random events only, and expect the lock-in to be + // broken. + end = begin + base::TimeDelta::FromMilliseconds(500); + RunEventSequence(GenerateEventSequence(begin, end, false, true), + true, + false, + false); + begin = end; + + // Now, go back to providing content frame events, and expect the sampler to + // lock-in once again. + end = begin + base::TimeDelta::FromSeconds(5); + RunEventSequence(GenerateEventSequence(begin, end, true, false), + false, + true, + false); + begin = end; +} + +// Tests that AnimatedContentSampler won't lock in to, nor flip-flop between, +// two animations of the same pixel change rate. VideoCaptureOracle should +// revert to using the SmoothEventSampler for these kinds of situations, as +// there is no "right answer" as to which animation to lock into. +TEST_P(AnimatedContentSamplerParameterizedTest, + DoesNotLockInToTwoCompetingAnimations) { + // Don't test when the event stream cannot indicate two separate content + // animations under the current test parameters. + if (GetParam().content_period < 2 * GetParam().vsync_interval) + return; + + // Start the first animation and run for a bit, and expect the sampler to + // lock-in. + base::TimeTicks begin = InitialTestTimeTicks(); + base::TimeTicks end = begin + base::TimeDelta::FromSeconds(5); + RunEventSequence(GenerateEventSequence(begin, end, true, false), + false, + true, + false); + begin = end; + + // Now, keep the first animation and blend in an second animation of the same + // size and frame rate, but at a different position. This will should cause + // the sampler to enter an "undetected" state since it's unclear which + // animation should be locked into. + end = begin + base::TimeDelta::FromSeconds(20); + std::vector<Event> first_animation_events = + GenerateEventSequence(begin, end, true, false); + gfx::Rect second_animation_rect( + gfx::Point(0, GetContentDamageRect().height()), + GetContentDamageRect().size()); + std::vector<Event> both_animations_events; + base::TimeDelta second_animation_offset = GetParam().vsync_interval; + for (std::vector<Event>::const_iterator i = first_animation_events.begin(); + i != first_animation_events.end(); ++i) { + both_animations_events.push_back(*i); + both_animations_events.push_back( + Event(second_animation_rect, i->second + second_animation_offset)); + } + RunEventSequence(both_animations_events, true, false, false); + begin = end; + + // Now, run just the first animation, and expect the sampler to lock-in once + // again. + end = begin + base::TimeDelta::FromSeconds(5); + RunEventSequence(GenerateEventSequence(begin, end, true, false), + false, + true, + false); + begin = end; + + // Now, blend in the second animation again, but it has half the frame rate of + // the first animation and damage Rects with twice the area. This will should + // cause the sampler to enter an "undetected" state again. This tests that + // pixel-weighting is being accounted for in the sampler's logic. + end = begin + base::TimeDelta::FromSeconds(20); + first_animation_events = GenerateEventSequence(begin, end, true, false); + second_animation_rect.set_width(second_animation_rect.width() * 2); + both_animations_events.clear(); + bool include_second_animation_frame = true; + for (std::vector<Event>::const_iterator i = first_animation_events.begin(); + i != first_animation_events.end(); ++i) { + both_animations_events.push_back(*i); + if (include_second_animation_frame) { + both_animations_events.push_back( + Event(second_animation_rect, i->second + second_animation_offset)); + } + include_second_animation_frame = !include_second_animation_frame; + } + RunEventSequence(both_animations_events, true, false, false); + begin = end; +} + +// Tests that the frame timestamps are smooth; meaning, that when run through a +// simulated compositor, each frame is held displayed for the right number of +// v-sync intervals. +TEST_P(AnimatedContentSamplerParameterizedTest, FrameTimestampsAreSmooth) { + // Generate 30 seconds of animated content events, run the events through + // AnimatedContentSampler, and record all frame timestamps being proposed + // once lock-in is continuous. + base::TimeTicks begin = InitialTestTimeTicks(); + std::vector<Event> events = GenerateEventSequence( + begin, + begin + base::TimeDelta::FromSeconds(20), + true, + false); + typedef std::vector<base::TimeTicks> Timestamps; + Timestamps frame_timestamps; + for (std::vector<Event>::const_iterator i = events.begin(); i != events.end(); + ++i) { + sampler()->ConsiderPresentationEvent(i->first, i->second); + if (sampler()->HasProposal()) { + if (sampler()->ShouldSample()) { + frame_timestamps.push_back(sampler()->frame_timestamp()); + sampler()->RecordSample(sampler()->frame_timestamp()); + } + } else { + frame_timestamps.clear(); // Reset until continuous lock-in. + } + } + ASSERT_LE(2u, frame_timestamps.size()); + + // Iterate through the |frame_timestamps|, building a histogram counting the + // number of times each frame was displayed k times. For example, 10 frames + // of 30 Hz content on a 60 Hz v-sync interval should result in + // display_counts[2] == 10. Quit early if any one frame was obviously + // repeated too many times. + const int64 max_expected_repeats_per_frame = 1 + + std::max(GetParam().min_capture_period, GetParam().content_period) / + GetParam().vsync_interval; + std::vector<size_t> display_counts(max_expected_repeats_per_frame + 1, 0); + base::TimeTicks last_present_time = frame_timestamps.front(); + for (Timestamps::const_iterator i = frame_timestamps.begin() + 1; + i != frame_timestamps.end(); ++i) { + const size_t num_vsync_intervals = static_cast<size_t>( + (*i - last_present_time) / GetParam().vsync_interval); + ASSERT_LT(0u, num_vsync_intervals); + ASSERT_GT(display_counts.size(), num_vsync_intervals); // Quit early. + ++display_counts[num_vsync_intervals]; + last_present_time += num_vsync_intervals * GetParam().vsync_interval; + } + + // Analyze the histogram for an expected result pattern. If the frame + // timestamps are smooth, there should only be one or two buckets with + // non-zero counts and they should be next to each other. Because the clock + // precision for the event_times provided to the sampler is very granular + // (i.e., the vsync_interval), it's okay if other buckets have a tiny "stray" + // count in this test. + size_t highest_count = 0; + size_t second_highest_count = 0; + for (size_t repeats = 1; repeats < display_counts.size(); ++repeats) { + DVLOG(1) << "display_counts[" << repeats << "] is " + << display_counts[repeats]; + if (display_counts[repeats] >= highest_count) { + second_highest_count = highest_count; + highest_count = display_counts[repeats]; + } else if (display_counts[repeats] > second_highest_count) { + second_highest_count = display_counts[repeats]; + } + } + size_t stray_count_remaining = + (frame_timestamps.size() - 1) - (highest_count + second_highest_count); + // Expect no more than 0.75% of frames fall outside the two main buckets. + EXPECT_GT(frame_timestamps.size() * 75 / 10000, stray_count_remaining); + for (size_t repeats = 1; repeats < display_counts.size() - 1; ++repeats) { + if (display_counts[repeats] == highest_count) { + EXPECT_EQ(second_highest_count, display_counts[repeats + 1]); + ++repeats; + } else if (display_counts[repeats] == second_highest_count) { + EXPECT_EQ(highest_count, display_counts[repeats + 1]); + ++repeats; + } else { + EXPECT_GE(stray_count_remaining, display_counts[repeats]); + stray_count_remaining -= display_counts[repeats]; + } + } +} + +// Tests that frame timestamps are "lightly pushed" back towards the original +// presentation event times, which tells us the AnimatedContentSampler can +// account for sources of timestamp drift and correct the drift. +TEST_P(AnimatedContentSamplerParameterizedTest, + FrameTimestampsConvergeTowardsEventTimes) { + const int max_drift_increment_millis = 3; + + // Generate a full minute of events. + const base::TimeTicks begin = InitialTestTimeTicks(); + const base::TimeTicks end = begin + base::TimeDelta::FromMinutes(1); + std::vector<Event> events = GenerateEventSequence(begin, end, true, false); + + // Modify the event sequence so that 1-3 ms of additional drift is suddenly + // present every 100 events. This is meant to simulate that, external to + // AnimatedContentSampler, the video hardware vsync timebase is being + // refreshed and is showing severe drift from the system clock. + base::TimeDelta accumulated_drift; + for (size_t i = 1; i < events.size(); ++i) { + if (i % 100 == 0) { + accumulated_drift += base::TimeDelta::FromMilliseconds( + GetRandomInRange(1, max_drift_increment_millis + 1)); + } + events[i].second += accumulated_drift; + } + + // Run all the events through the sampler and track the last rewritten frame + // timestamp. + base::TimeTicks last_frame_timestamp; + for (std::vector<Event>::const_iterator i = events.begin(); i != events.end(); + ++i) { + sampler()->ConsiderPresentationEvent(i->first, i->second); + if (sampler()->ShouldSample()) + last_frame_timestamp = sampler()->frame_timestamp(); + } + + // If drift was accounted for, the |last_frame_timestamp| should be close to + // the last event's timestamp. + const base::TimeDelta total_error = + events.back().second - last_frame_timestamp; + const base::TimeDelta max_acceptable_error = GetParam().min_capture_period + + base::TimeDelta::FromMilliseconds(max_drift_increment_millis); + EXPECT_NEAR(0.0, + total_error.InMicroseconds(), + max_acceptable_error.InMicroseconds()); +} + +INSTANTIATE_TEST_CASE_P( + , + AnimatedContentSamplerParameterizedTest, + ::testing::Values( + // Typical frame rate content: Compositor runs at 60 Hz, capture at 30 + // Hz, and content video animates at 30, 25, or 24 Hz. + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(30)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(25)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(24)), + + // High frame rate content that leverages the Compositor's + // capabilities, but capture is still at 30 Hz. + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(60)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(50)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(48)), + + // High frame rate content that leverages the Compositor's + // capabilities, and capture is also a buttery 60 Hz. + Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(60)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(50)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(48)), + + // On some platforms, the Compositor runs at 50 Hz. + Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(30)), + Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(25)), + Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(24)), + Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(50)), + Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(48)), + + // Stable, but non-standard content frame rates. + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(16)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(20)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(23)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(26)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(27)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(28)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(29)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(31)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(32)), + Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(33)))); + +} // namespace content
diff --git a/content/browser/media/capture/smooth_event_sampler.cc b/content/browser/media/capture/smooth_event_sampler.cc new file mode 100644 index 0000000..6d7c8a08 --- /dev/null +++ b/content/browser/media/capture/smooth_event_sampler.cc
@@ -0,0 +1,95 @@ +// Copyright (c) 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/media/capture/smooth_event_sampler.h" + +#include <algorithm> + +#include "base/trace_event/trace_event.h" + +namespace content { + +namespace { + +// The maximum amount of time that can elapse before considering unchanged +// content as dirty for the purposes of timer-based overdue sampling. This is +// the same value found in cc::FrameRateCounter. +const int kOverdueDirtyThresholdMillis = 250; // 4 FPS + +} // anonymous namespace + +SmoothEventSampler::SmoothEventSampler(base::TimeDelta min_capture_period, + int redundant_capture_goal) + : min_capture_period_(min_capture_period), + redundant_capture_goal_(redundant_capture_goal), + token_bucket_capacity_(min_capture_period + min_capture_period / 2), + overdue_sample_count_(0), + token_bucket_(token_bucket_capacity_) { + DCHECK_GT(min_capture_period_.InMicroseconds(), 0); +} + +void SmoothEventSampler::ConsiderPresentationEvent(base::TimeTicks event_time) { + DCHECK(!event_time.is_null()); + + // Add tokens to the bucket based on advancement in time. Then, re-bound the + // number of tokens in the bucket. Overflow occurs when there is too much + // time between events (a common case), or when RecordSample() is not being + // called often enough (a bug). On the other hand, if RecordSample() is being + // called too often (e.g., as a reaction to IsOverdueForSamplingAt()), the + // bucket will underflow. + if (!current_event_.is_null()) { + if (current_event_ < event_time) { + token_bucket_ += event_time - current_event_; + if (token_bucket_ > token_bucket_capacity_) + token_bucket_ = token_bucket_capacity_; + } + TRACE_COUNTER1("gpu.capture", + "MirroringTokenBucketUsec", + std::max<int64>(0, token_bucket_.InMicroseconds())); + } + current_event_ = event_time; +} + +bool SmoothEventSampler::ShouldSample() const { + return token_bucket_ >= min_capture_period_; +} + +void SmoothEventSampler::RecordSample() { + token_bucket_ -= min_capture_period_; + if (token_bucket_ < base::TimeDelta()) + token_bucket_ = base::TimeDelta(); + TRACE_COUNTER1("gpu.capture", + "MirroringTokenBucketUsec", + std::max<int64>(0, token_bucket_.InMicroseconds())); + + if (HasUnrecordedEvent()) { + last_sample_ = current_event_; + overdue_sample_count_ = 0; + } else { + ++overdue_sample_count_; + } +} + +bool SmoothEventSampler::IsOverdueForSamplingAt(base::TimeTicks event_time) + const { + DCHECK(!event_time.is_null()); + + if (!HasUnrecordedEvent() && overdue_sample_count_ >= redundant_capture_goal_) + return false; // Not dirty. + + if (last_sample_.is_null()) + return true; + + // If we're dirty but not yet old, then we've recently gotten updates, so we + // won't request a sample just yet. + base::TimeDelta dirty_interval = event_time - last_sample_; + return dirty_interval >= + base::TimeDelta::FromMilliseconds(kOverdueDirtyThresholdMillis); +} + +bool SmoothEventSampler::HasUnrecordedEvent() const { + return !current_event_.is_null() && current_event_ != last_sample_; +} + +} // namespace content
diff --git a/content/browser/media/capture/smooth_event_sampler.h b/content/browser/media/capture/smooth_event_sampler.h new file mode 100644 index 0000000..dabd551 --- /dev/null +++ b/content/browser/media/capture/smooth_event_sampler.h
@@ -0,0 +1,57 @@ +// Copyright (c) 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_MEDIA_CAPTURE_SMOOTH_EVENT_SAMPLER_H_ +#define CONTENT_BROWSER_MEDIA_CAPTURE_SMOOTH_EVENT_SAMPLER_H_ + +#include "base/time/time.h" +#include "content/common/content_export.h" + +namespace content { + +// Filters a sequence of events to achieve a target frequency. +class CONTENT_EXPORT SmoothEventSampler { + public: + SmoothEventSampler(base::TimeDelta min_capture_period, + int redundant_capture_goal); + + base::TimeDelta min_capture_period() const { return min_capture_period_; } + + // Add a new event to the event history, and consider whether it ought to be + // sampled. The event is not recorded as a sample until RecordSample() is + // called. + void ConsiderPresentationEvent(base::TimeTicks event_time); + + // Returns true if the last event considered should be sampled. + bool ShouldSample() const; + + // Operates on the last event added by ConsiderPresentationEvent(), marking + // it as sampled. After this point we are current in the stream of events, as + // we have sampled the most recent event. + void RecordSample(); + + // Returns true if, at time |event_time|, sampling should occur because too + // much time will have passed relative to the last event and/or sample. + bool IsOverdueForSamplingAt(base::TimeTicks event_time) const; + + // Returns true if ConsiderPresentationEvent() has been called since the last + // call to RecordSample(). + bool HasUnrecordedEvent() const; + + private: + const base::TimeDelta min_capture_period_; + const int redundant_capture_goal_; + const base::TimeDelta token_bucket_capacity_; + + base::TimeTicks current_event_; + base::TimeTicks last_sample_; + int overdue_sample_count_; + base::TimeDelta token_bucket_; + + DISALLOW_COPY_AND_ASSIGN(SmoothEventSampler); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_MEDIA_CAPTURE_SMOOTH_EVENT_SAMPLER_H_
diff --git a/content/browser/media/capture/smooth_event_sampler_unittest.cc b/content/browser/media/capture/smooth_event_sampler_unittest.cc new file mode 100644 index 0000000..fbf81df --- /dev/null +++ b/content/browser/media/capture/smooth_event_sampler_unittest.cc
@@ -0,0 +1,436 @@ +// Copyright (c) 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/media/capture/smooth_event_sampler.h" + +#include "base/strings/stringprintf.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace content { + +namespace { + +bool AddEventAndConsiderSampling(SmoothEventSampler* sampler, + base::TimeTicks event_time) { + sampler->ConsiderPresentationEvent(event_time); + return sampler->ShouldSample(); +} + +void SteadyStateSampleAndAdvance(base::TimeDelta vsync, + SmoothEventSampler* sampler, + base::TimeTicks* t) { + ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); + ASSERT_TRUE(sampler->HasUnrecordedEvent()); + sampler->RecordSample(); + ASSERT_FALSE(sampler->HasUnrecordedEvent()); + ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); + *t += vsync; + ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); +} + +void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync, + SmoothEventSampler* sampler, + base::TimeTicks* t) { + ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t)); + ASSERT_TRUE(sampler->HasUnrecordedEvent()); + ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); + *t += vsync; + ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); +} + +base::TimeTicks InitialTestTimeTicks() { + return base::TimeTicks() + base::TimeDelta::FromSeconds(1); +} + +void TestRedundantCaptureStrategy(base::TimeDelta capture_period, + int redundant_capture_goal, + SmoothEventSampler* sampler, + base::TimeTicks* t) { + // Before any events have been considered, we're overdue for sampling. + ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t)); + + // Consider the first event. We want to sample that. + ASSERT_FALSE(sampler->HasUnrecordedEvent()); + ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); + ASSERT_TRUE(sampler->HasUnrecordedEvent()); + sampler->RecordSample(); + ASSERT_FALSE(sampler->HasUnrecordedEvent()); + + // After more than 250 ms has passed without considering an event, we should + // repeatedly be overdue for sampling. However, once the redundant capture + // goal is achieved, we should no longer be overdue for sampling. + *t += base::TimeDelta::FromMilliseconds(250); + for (int i = 0; i < redundant_capture_goal; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + ASSERT_FALSE(sampler->HasUnrecordedEvent()); + ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t)) + << "Should sample until redundant capture goal is hit"; + sampler->RecordSample(); + *t += capture_period; // Timer fires once every capture period. + } + ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)) + << "Should not be overdue once redundant capture goal achieved."; +} + +} // namespace + +// 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains +// much more comprehensive before/after/edge-case scenarios than the others. +TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) { + const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; + const int redundant_capture_goal = 200; + const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60; + + SmoothEventSampler sampler(capture_period, redundant_capture_goal); + base::TimeTicks t = InitialTestTimeTicks(); + + TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, + &sampler, &t); + + // Steady state, we should capture every other vsync, indefinitely. + for (int i = 0; i < 100; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + } + + // Now pretend we're limited by backpressure in the pipeline. In this scenario + // case we are adding events but not sampling them. + for (int i = 0; i < 20; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + ASSERT_EQ(i >= 14, sampler.IsOverdueForSamplingAt(t)); + ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); + ASSERT_TRUE(sampler.HasUnrecordedEvent()); + t += vsync; + } + + // Now suppose we can sample again. We should be back in the steady state, + // but at a different phase. + ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); + for (int i = 0; i < 100; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + } +} + +// 50Hz sampled at 30Hz should produce a sequence where some frames are skipped. +TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) { + const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; + const int redundant_capture_goal = 2; + const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50; + + SmoothEventSampler sampler(capture_period, redundant_capture_goal); + base::TimeTicks t = InitialTestTimeTicks(); + + TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, + &sampler, &t); + + // Steady state, we should capture 1st, 2nd and 4th frames out of every five + // frames, indefinitely. + for (int i = 0; i < 100; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + } + + // Now pretend we're limited by backpressure in the pipeline. In this scenario + // case we are adding events but not sampling them. + for (int i = 0; i < 20; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + ASSERT_EQ(i >= 11, sampler.IsOverdueForSamplingAt(t)); + ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); + t += vsync; + } + + // Now suppose we can sample again. We should be back in the steady state + // again. + ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); + for (int i = 0; i < 100; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + } +} + +// 75Hz sampled at 30Hz should produce a sequence where some frames are skipped. +TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) { + const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; + const int redundant_capture_goal = 32; + const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75; + + SmoothEventSampler sampler(capture_period, redundant_capture_goal); + base::TimeTicks t = InitialTestTimeTicks(); + + TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, + &sampler, &t); + + // Steady state, we should capture 1st and 3rd frames out of every five + // frames, indefinitely. + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + for (int i = 0; i < 100; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + } + + // Now pretend we're limited by backpressure in the pipeline. In this scenario + // case we are adding events but not sampling them. + for (int i = 0; i < 20; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + ASSERT_EQ(i >= 16, sampler.IsOverdueForSamplingAt(t)); + ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); + t += vsync; + } + + // Now suppose we can sample again. We capture the next frame, and not the one + // after that, and then we're back in the steady state again. + ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + for (int i = 0; i < 100; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); + } +} + +// 30Hz sampled at 30Hz should produce 30Hz. +TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) { + const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; + const int redundant_capture_goal = 1; + const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30; + + SmoothEventSampler sampler(capture_period, redundant_capture_goal); + base::TimeTicks t = InitialTestTimeTicks(); + + TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, + &sampler, &t); + + // Steady state, we should capture every vsync, indefinitely. + for (int i = 0; i < 200; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + } + + // Now pretend we're limited by backpressure in the pipeline. In this scenario + // case we are adding events but not sampling them. + for (int i = 0; i < 10; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t)); + ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); + t += vsync; + } + + // Now suppose we can sample again. We should be back in the steady state. + ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); + for (int i = 0; i < 100; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + } +} + +// 24Hz sampled at 30Hz should produce 24Hz. +TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) { + const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; + const int redundant_capture_goal = 333; + const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24; + + SmoothEventSampler sampler(capture_period, redundant_capture_goal); + base::TimeTicks t = InitialTestTimeTicks(); + + TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, + &sampler, &t); + + // Steady state, we should capture every vsync, indefinitely. + for (int i = 0; i < 200; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + } + + // Now pretend we're limited by backpressure in the pipeline. In this scenario + // case we are adding events but not sampling them. + for (int i = 0; i < 10; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + ASSERT_EQ(i >= 6, sampler.IsOverdueForSamplingAt(t)); + ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); + t += vsync; + } + + // Now suppose we can sample again. We should be back in the steady state. + ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); + for (int i = 0; i < 100; i++) { + SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); + SteadyStateSampleAndAdvance(vsync, &sampler, &t); + } +} + +TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) { + const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; + const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1); + + SmoothEventSampler sampler(capture_period, 1); + base::TimeTicks t = InitialTestTimeTicks(); + + ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); + sampler.RecordSample(); + ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t)) + << "Sampled last event; should not be dirty."; + t += overdue_period; + + // Now simulate 2 events with the same clock value. + ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); + sampler.RecordSample(); + ASSERT_FALSE(AddEventAndConsiderSampling(&sampler, t)) + << "Two events at same time -- expected second not to be sampled."; + ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t + overdue_period)) + << "Second event should dirty the capture state."; + sampler.RecordSample(); + ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t + overdue_period)); +} + +namespace { + +struct DataPoint { + bool should_capture; + double increment_ms; +}; + +void ReplayCheckingSamplerDecisions(const DataPoint* data_points, + size_t num_data_points, + SmoothEventSampler* sampler) { + base::TimeTicks t = InitialTestTimeTicks(); + for (size_t i = 0; i < num_data_points; ++i) { + t += base::TimeDelta::FromMicroseconds( + static_cast<int64>(data_points[i].increment_ms * 1000)); + ASSERT_EQ(data_points[i].should_capture, + AddEventAndConsiderSampling(sampler, t)) + << "at data_points[" << i << ']'; + if (data_points[i].should_capture) + sampler->RecordSample(); + } +} + +} // namespace + +TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) { + // Actual capturing of timing data: Initial instability as a 24 FPS video was + // started from a still screen, then clearly followed by steady-state. + static const DataPoint data_points[] = { + { true, 1437.93 }, { true, 150.484 }, { true, 217.362 }, { true, 50.161 }, + { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 66.88 }, + { true, 50.161 }, { false, 0 }, { false, 0 }, { true, 50.16 }, + { true, 33.441 }, { true, 16.72 }, { false, 16.72 }, { true, 117.041 }, + { true, 16.72 }, { false, 16.72 }, { true, 50.161 }, { true, 50.16 }, + { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 16.72 }, + { false, 0 }, { true, 50.161 }, { false, 0 }, { true, 33.44 }, + { true, 16.72 }, { false, 16.721 }, { true, 66.881 }, { false, 0 }, + { true, 33.441 }, { true, 16.72 }, { true, 50.16 }, { true, 16.72 }, + { false, 16.721 }, { true, 50.161 }, { true, 50.16 }, { false, 0 }, + { true, 33.441 }, { true, 50.337 }, { true, 50.183 }, { true, 16.722 }, + { true, 50.161 }, { true, 33.441 }, { true, 50.16 }, { true, 33.441 }, + { true, 50.16 }, { true, 33.441 }, { true, 50.16 }, { true, 33.44 }, + { true, 50.161 }, { true, 50.16 }, { true, 33.44 }, { true, 33.441 }, + { true, 50.16 }, { true, 50.161 }, { true, 33.44 }, { true, 33.441 }, + { true, 50.16 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 }, + { true, 50.161 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 }, + { true, 83.601 }, { true, 16.72 }, { true, 33.44 }, { false, 0 } + }; + + SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); + ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); +} + +TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) { + // Actual capturing of timing data: Initial instability as a 30 FPS video was + // started from a still screen, then followed by steady-state. Drawing + // framerate from the video rendering was a bit volatile, but averaged 30 FPS. + static const DataPoint data_points[] = { + { true, 2407.69 }, { true, 16.733 }, { true, 217.362 }, { true, 33.441 }, + { true, 33.44 }, { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, + { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, + { true, 16.721 }, { true, 33.44 }, { false, 0 }, { true, 50.161 }, + { true, 50.16 }, { false, 0 }, { true, 50.161 }, { true, 33.44 }, + { true, 16.72 }, { false, 0 }, { false, 16.72 }, { true, 66.881 }, + { false, 0 }, { true, 33.44 }, { true, 16.72 }, { true, 50.161 }, + { false, 0 }, { true, 33.538 }, { true, 33.526 }, { true, 33.447 }, + { true, 33.445 }, { true, 33.441 }, { true, 16.721 }, { true, 33.44 }, + { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, { true, 33.44 }, + { true, 33.441 }, { true, 33.44 }, { false, 0 }, { false, 16.72 }, + { true, 66.881 }, { true, 16.72 }, { false, 16.72 }, { true, 50.16 }, + { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 33.44 }, + { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { false, 0 }, + { true, 33.44 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, + { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 66.88 }, + { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 }, + { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 }, + { true, 16.72 }, { true, 50.161 }, { false, 0 }, { true, 50.16 }, + { false, 0.001 }, { true, 16.721 }, { true, 66.88 }, { true, 33.44 }, + { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, + { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 66.881 }, + { true, 33.44 }, { true, 16.72 }, { true, 33.441 }, { false, 16.72 }, + { true, 66.88 }, { true, 16.721 }, { true, 50.16 }, { true, 33.44 }, + { true, 16.72 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 } + }; + + SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); + ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); +} + +TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) { + // Actual capturing of timing data: WebGL Acquarium demo + // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran + // between 55-60 FPS in the steady-state. + static const DataPoint data_points[] = { + { true, 16.72 }, { true, 16.72 }, { true, 4163.29 }, { true, 50.193 }, + { true, 117.041 }, { true, 50.161 }, { true, 50.16 }, { true, 33.441 }, + { true, 50.16 }, { true, 33.44 }, { false, 0 }, { false, 0 }, + { true, 50.161 }, { true, 83.601 }, { true, 50.16 }, { true, 16.72 }, + { true, 33.441 }, { false, 16.72 }, { true, 50.16 }, { true, 16.72 }, + { false, 0.001 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, + { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, + { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 }, + { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 }, + { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 }, + { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, + { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 33.44 }, + { false, 0 }, { true, 16.721 }, { true, 50.161 }, { false, 0 }, + { true, 33.44 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, + { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 }, + { true, 50.16 }, { false, 0 }, { true, 16.721 }, { true, 33.44 }, + { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 }, + { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 }, + { false, 0 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, + { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, + { true, 33.44 }, { false, 0 }, { true, 33.44 }, { true, 33.441 }, + { false, 0 }, { true, 33.44 }, { true, 33.441 }, { false, 0 }, + { true, 33.44 }, { false, 0 }, { true, 33.44 }, { false, 16.72 }, + { true, 16.721 }, { true, 50.161 }, { false, 0 }, { true, 16.72 }, + { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 33.44 }, + { true, 33.44 }, { false, 0 }, { true, 33.441 }, { false, 16.72 }, + { true, 16.72 }, { true, 50.16 }, { false, 0 }, { true, 16.72 }, + { true, 33.441 }, { false, 0 }, { true, 33.44 }, { false, 16.72 }, + { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 50.161 }, + { false, 0 }, { true, 16.72 }, { true, 33.44 }, { false, 0 }, + { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, { true, 50.16 } + }; + + SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); + ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); +} + +} // namespace content
diff --git a/content/browser/media/capture/video_capture_oracle.cc b/content/browser/media/capture/video_capture_oracle.cc index 3cddc38..0b67507 100644 --- a/content/browser/media/capture/video_capture_oracle.cc +++ b/content/browser/media/capture/video_capture_oracle.cc
@@ -8,7 +8,6 @@ #include "base/format_macros.h" #include "base/strings/stringprintf.h" -#include "base/trace_event/trace_event.h" namespace content { @@ -25,33 +24,6 @@ // further into the WebRTC encoding stack. const int kNumRedundantCapturesOfStaticContent = 200; -// These specify the minimum/maximum amount of recent event history to examine -// to detect animated content. If the values are too low, there is a greater -// risk of false-positive detections and low accuracy. If they are too high, -// the the implementation will be slow to lock-in/out, and also will not react -// well to mildly-variable frame rate content (e.g., 25 +/- 1 FPS). -// -// These values were established by experimenting with a wide variety of -// scenarios, including 24/25/30 FPS videos, 60 FPS WebGL demos, and the -// transitions between static and animated content. -const int kMinObservationWindowMillis = 1000; -const int kMaxObservationWindowMillis = 2000; - -// The maximum amount of time that can elapse before declaring two subsequent -// events as "not animating." This is the same value found in -// cc::FrameRateCounter. -const int kNonAnimatingThresholdMillis = 250; // 4 FPS - -// The slowest that content can be animating in order for AnimatedContentSampler -// to lock-in. This is the threshold at which the "smoothness" problem is no -// longer relevant. -const int kMaxLockInPeriodMicros = 83333; // 12 FPS - -// The amount of time over which to fully correct the drift of the rewritten -// frame timestamps from the presentation event timestamps. The lower the -// value, the higher the variance in frame timestamps. -const int kDriftCorrectionMillis = 2000; - // Given the amount of time between frames, compare to the expected amount of // time between frames at |frame_rate| and return the fractional difference. double FractionFromExpectedFrameRate(base::TimeDelta delta, int frame_rate) { @@ -172,257 +144,4 @@ frame_timestamps_[frame_number % kMaxFrameTimestamps] = timestamp; } -SmoothEventSampler::SmoothEventSampler(base::TimeDelta min_capture_period, - int redundant_capture_goal) - : min_capture_period_(min_capture_period), - redundant_capture_goal_(redundant_capture_goal), - token_bucket_capacity_(min_capture_period + min_capture_period / 2), - overdue_sample_count_(0), - token_bucket_(token_bucket_capacity_) { - DCHECK_GT(min_capture_period_.InMicroseconds(), 0); -} - -void SmoothEventSampler::ConsiderPresentationEvent(base::TimeTicks event_time) { - DCHECK(!event_time.is_null()); - - // Add tokens to the bucket based on advancement in time. Then, re-bound the - // number of tokens in the bucket. Overflow occurs when there is too much - // time between events (a common case), or when RecordSample() is not being - // called often enough (a bug). On the other hand, if RecordSample() is being - // called too often (e.g., as a reaction to IsOverdueForSamplingAt()), the - // bucket will underflow. - if (!current_event_.is_null()) { - if (current_event_ < event_time) { - token_bucket_ += event_time - current_event_; - if (token_bucket_ > token_bucket_capacity_) - token_bucket_ = token_bucket_capacity_; - } - TRACE_COUNTER1("gpu.capture", - "MirroringTokenBucketUsec", - std::max<int64>(0, token_bucket_.InMicroseconds())); - } - current_event_ = event_time; -} - -bool SmoothEventSampler::ShouldSample() const { - return token_bucket_ >= min_capture_period_; -} - -void SmoothEventSampler::RecordSample() { - token_bucket_ -= min_capture_period_; - if (token_bucket_ < base::TimeDelta()) - token_bucket_ = base::TimeDelta(); - TRACE_COUNTER1("gpu.capture", - "MirroringTokenBucketUsec", - std::max<int64>(0, token_bucket_.InMicroseconds())); - - if (HasUnrecordedEvent()) { - last_sample_ = current_event_; - overdue_sample_count_ = 0; - } else { - ++overdue_sample_count_; - } -} - -bool SmoothEventSampler::IsOverdueForSamplingAt(base::TimeTicks event_time) - const { - DCHECK(!event_time.is_null()); - - if (!HasUnrecordedEvent() && overdue_sample_count_ >= redundant_capture_goal_) - return false; // Not dirty. - - if (last_sample_.is_null()) - return true; - - // If we're dirty but not yet old, then we've recently gotten updates, so we - // won't request a sample just yet. - base::TimeDelta dirty_interval = event_time - last_sample_; - return dirty_interval >= - base::TimeDelta::FromMilliseconds(kNonAnimatingThresholdMillis); -} - -bool SmoothEventSampler::HasUnrecordedEvent() const { - return !current_event_.is_null() && current_event_ != last_sample_; -} - -AnimatedContentSampler::AnimatedContentSampler( - base::TimeDelta min_capture_period) - : min_capture_period_(min_capture_period) {} - -AnimatedContentSampler::~AnimatedContentSampler() {} - -void AnimatedContentSampler::ConsiderPresentationEvent( - const gfx::Rect& damage_rect, base::TimeTicks event_time) { - AddObservation(damage_rect, event_time); - - if (AnalyzeObservations(event_time, &detected_region_, &detected_period_) && - detected_period_ > base::TimeDelta() && - detected_period_ <= - base::TimeDelta::FromMicroseconds(kMaxLockInPeriodMicros)) { - if (damage_rect == detected_region_) - UpdateFrameTimestamp(event_time); - else - frame_timestamp_ = base::TimeTicks(); - } else { - detected_region_ = gfx::Rect(); - detected_period_ = base::TimeDelta(); - frame_timestamp_ = base::TimeTicks(); - } -} - -bool AnimatedContentSampler::HasProposal() const { - return detected_period_ > base::TimeDelta(); -} - -bool AnimatedContentSampler::ShouldSample() const { - return !frame_timestamp_.is_null(); -} - -void AnimatedContentSampler::RecordSample(base::TimeTicks frame_timestamp) { - recorded_frame_timestamp_ = - HasProposal() ? frame_timestamp : base::TimeTicks(); - sequence_offset_ = base::TimeDelta(); -} - -void AnimatedContentSampler::AddObservation(const gfx::Rect& damage_rect, - base::TimeTicks event_time) { - if (damage_rect.IsEmpty()) - return; // Useless observation. - - // Add the observation to the FIFO queue. - if (!observations_.empty() && observations_.back().event_time > event_time) - return; // The implementation assumes chronological order. - observations_.push_back(Observation(damage_rect, event_time)); - - // Prune-out old observations. - const base::TimeDelta threshold = - base::TimeDelta::FromMilliseconds(kMaxObservationWindowMillis); - while ((event_time - observations_.front().event_time) > threshold) - observations_.pop_front(); -} - -gfx::Rect AnimatedContentSampler::ElectMajorityDamageRect() const { - // This is an derivative of the Boyer-Moore Majority Vote Algorithm where each - // pixel in a candidate gets one vote, as opposed to each candidate getting - // one vote. - const gfx::Rect* candidate = NULL; - int64 votes = 0; - for (ObservationFifo::const_iterator i = observations_.begin(); - i != observations_.end(); ++i) { - DCHECK_GT(i->damage_rect.size().GetArea(), 0); - if (votes == 0) { - candidate = &(i->damage_rect); - votes = candidate->size().GetArea(); - } else if (i->damage_rect == *candidate) { - votes += i->damage_rect.size().GetArea(); - } else { - votes -= i->damage_rect.size().GetArea(); - if (votes < 0) { - candidate = &(i->damage_rect); - votes = -votes; - } - } - } - return (votes > 0) ? *candidate : gfx::Rect(); -} - -bool AnimatedContentSampler::AnalyzeObservations( - base::TimeTicks event_time, - gfx::Rect* rect, - base::TimeDelta* period) const { - const gfx::Rect elected_rect = ElectMajorityDamageRect(); - if (elected_rect.IsEmpty()) - return false; // There is no regular animation present. - - // Scan |observations_|, gathering metrics about the ones having a damage Rect - // equivalent to the |elected_rect|. Along the way, break early whenever the - // event times reveal a non-animating period. - int64 num_pixels_damaged_in_all = 0; - int64 num_pixels_damaged_in_chosen = 0; - base::TimeDelta sum_frame_durations; - size_t count_frame_durations = 0; - base::TimeTicks first_event_time; - base::TimeTicks last_event_time; - for (ObservationFifo::const_reverse_iterator i = observations_.rbegin(); - i != observations_.rend(); ++i) { - const int area = i->damage_rect.size().GetArea(); - num_pixels_damaged_in_all += area; - if (i->damage_rect != elected_rect) - continue; - num_pixels_damaged_in_chosen += area; - if (last_event_time.is_null()) { - last_event_time = i->event_time; - if ((event_time - last_event_time) >= - base::TimeDelta::FromMilliseconds(kNonAnimatingThresholdMillis)) { - return false; // Content animation has recently ended. - } - } else { - const base::TimeDelta frame_duration = first_event_time - i->event_time; - if (frame_duration >= - base::TimeDelta::FromMilliseconds(kNonAnimatingThresholdMillis)) { - break; // Content not animating before this point. - } - sum_frame_durations += frame_duration; - ++count_frame_durations; - } - first_event_time = i->event_time; - } - - if ((last_event_time - first_event_time) < - base::TimeDelta::FromMilliseconds(kMinObservationWindowMillis)) { - return false; // Content has not animated for long enough for accuracy. - } - if (num_pixels_damaged_in_chosen <= (num_pixels_damaged_in_all * 2 / 3)) - return false; // Animation is not damaging a supermajority of pixels. - - *rect = elected_rect; - DCHECK_GT(count_frame_durations, 0u); - *period = sum_frame_durations / count_frame_durations; - return true; -} - -void AnimatedContentSampler::UpdateFrameTimestamp(base::TimeTicks event_time) { - // This is how much time to advance from the last frame timestamp. Never - // advance by less than |min_capture_period_| because the downstream consumer - // cannot handle the higher frame rate. If |detected_period_| is less than - // |min_capture_period_|, excess frames should be dropped. - const base::TimeDelta advancement = - std::max(detected_period_, min_capture_period_); - - // Compute the |timebase| upon which to determine the |frame_timestamp_|. - // Ideally, this would always equal the timestamp of the last recorded frame - // sampling. Determine how much drift from the ideal is present, then adjust - // the timebase by a small amount to spread out the entire correction over - // many frame timestamps. - // - // This accounts for two main sources of drift: 1) The clock drift of the - // system clock relative to the video hardware, which affects the event times; - // and 2) The small error introduced by this frame timestamp rewriting, as it - // is based on averaging over recent events. - base::TimeTicks timebase = event_time - sequence_offset_ - advancement; - if (!recorded_frame_timestamp_.is_null()) { - const base::TimeDelta drift = recorded_frame_timestamp_ - timebase; - const int64 correct_over_num_frames = - base::TimeDelta::FromMilliseconds(kDriftCorrectionMillis) / - detected_period_; - DCHECK_GT(correct_over_num_frames, 0); - timebase = recorded_frame_timestamp_ - (drift / correct_over_num_frames); - } - - // Compute |frame_timestamp_|. Whenever |detected_period_| is less than - // |min_capture_period_|, some extra time is "borrowed" to be able to advance - // by the full |min_capture_period_|. Then, whenever the total amount of - // borrowed time reaches a full |min_capture_period_|, drop a frame. Note - // that when |detected_period_| is greater or equal to |min_capture_period_|, - // this logic is effectively disabled. - borrowed_time_ += advancement - detected_period_; - if (borrowed_time_ >= min_capture_period_) { - borrowed_time_ -= min_capture_period_; - frame_timestamp_ = base::TimeTicks(); - } else { - sequence_offset_ += advancement; - frame_timestamp_ = timebase + sequence_offset_; - } -} - } // namespace content
diff --git a/content/browser/media/capture/video_capture_oracle.h b/content/browser/media/capture/video_capture_oracle.h index db98b49..706f4a9 100644 --- a/content/browser/media/capture/video_capture_oracle.h +++ b/content/browser/media/capture/video_capture_oracle.h
@@ -5,167 +5,16 @@ #ifndef CONTENT_BROWSER_MEDIA_CAPTURE_VIDEO_CAPTURE_ORACLE_H_ #define CONTENT_BROWSER_MEDIA_CAPTURE_VIDEO_CAPTURE_ORACLE_H_ -#include <deque> - #include "base/callback_forward.h" #include "base/memory/scoped_ptr.h" #include "base/time/time.h" +#include "content/browser/media/capture/animated_content_sampler.h" +#include "content/browser/media/capture/smooth_event_sampler.h" #include "content/common/content_export.h" #include "ui/gfx/geometry/rect.h" namespace content { -// Filters a sequence of events to achieve a target frequency. -class CONTENT_EXPORT SmoothEventSampler { - public: - SmoothEventSampler(base::TimeDelta min_capture_period, - int redundant_capture_goal); - - base::TimeDelta min_capture_period() const { return min_capture_period_; } - - // Add a new event to the event history, and consider whether it ought to be - // sampled. The event is not recorded as a sample until RecordSample() is - // called. - void ConsiderPresentationEvent(base::TimeTicks event_time); - - // Returns true if the last event considered should be sampled. - bool ShouldSample() const; - - // Operates on the last event added by ConsiderPresentationEvent(), marking - // it as sampled. After this point we are current in the stream of events, as - // we have sampled the most recent event. - void RecordSample(); - - // Returns true if, at time |event_time|, sampling should occur because too - // much time will have passed relative to the last event and/or sample. - bool IsOverdueForSamplingAt(base::TimeTicks event_time) const; - - // Returns true if ConsiderPresentationEvent() has been called since the last - // call to RecordSample(). - bool HasUnrecordedEvent() const; - - private: - const base::TimeDelta min_capture_period_; - const int redundant_capture_goal_; - const base::TimeDelta token_bucket_capacity_; - - base::TimeTicks current_event_; - base::TimeTicks last_sample_; - int overdue_sample_count_; - base::TimeDelta token_bucket_; - - DISALLOW_COPY_AND_ASSIGN(SmoothEventSampler); -}; - -// Analyzes a sequence of events to detect the presence of constant frame rate -// animated content. In the case where there are multiple regions of animated -// content, AnimatedContentSampler will propose sampling the one having the -// largest "smoothness" impact, according to human perception (e.g., a 24 FPS -// video versus a 60 FPS busy spinner). -// -// In addition, AnimatedContentSampler will provide rewritten frame timestamps, -// for downstream consumers, that are "truer" to the source content than to the -// local presentation hardware. -class CONTENT_EXPORT AnimatedContentSampler { - public: - explicit AnimatedContentSampler(base::TimeDelta min_capture_period); - ~AnimatedContentSampler(); - - // Examines the given presentation event metadata, along with recent history, - // to detect animated content, updating the state of this sampler. - // |damage_rect| is the region of a frame about to be drawn, while - // |event_time| refers to the frame's estimated presentation time. - void ConsiderPresentationEvent(const gfx::Rect& damage_rect, - base::TimeTicks event_time); - - // Returns true if animated content has been detected and a decision has been - // made about whether to sample the last event. - bool HasProposal() const; - - // Returns true if the last event considered should be sampled. - bool ShouldSample() const; - - // Returns a frame timestamp to provide to consumers of the sampled frame. - // Only valid when should_sample() returns true. - base::TimeTicks frame_timestamp() const { return frame_timestamp_; } - - // Accessors to currently-detected animating region/period, for logging. - const gfx::Rect& detected_region() const { return detected_region_; } - base::TimeDelta detected_period() const { return detected_period_; } - - // Records that a frame with the given |frame_timestamp| was sampled. This - // method should be called when *any* sampling is taken, even if it was not - // proposed by AnimatedContentSampler. - void RecordSample(base::TimeTicks frame_timestamp); - - private: - friend class AnimatedContentSamplerTest; - - // Data structure for efficient online analysis of recent event history. - struct Observation { - gfx::Rect damage_rect; - base::TimeTicks event_time; - - Observation(const gfx::Rect& d, base::TimeTicks e) - : damage_rect(d), event_time(e) {} - }; - typedef std::deque<Observation> ObservationFifo; - - // Adds an observation to |observations_|, and prunes-out the old ones. - void AddObservation(const gfx::Rect& damage_rect, base::TimeTicks event_time); - - // Returns the damage Rect that is responsible for the majority of the pixel - // damage in recent event history, if there is such a Rect. If there isn't, - // this method could still return any Rect, so the caller must confirm the - // returned Rect really is responsible for the majority of pixel damage. - gfx::Rect ElectMajorityDamageRect() const; - - // Analyzes the observations relative to the current |event_time| to detect - // stable animating content. If detected, returns true and sets the output - // arguments to the region of the animating content and its mean frame - // duration. - bool AnalyzeObservations(base::TimeTicks event_time, - gfx::Rect* rect, - base::TimeDelta* period) const; - - // Called by ConsiderPresentationEvent() when the current event is part of a - // detected animation, to update |frame_timestamp_|. - void UpdateFrameTimestamp(base::TimeTicks event_time); - - // The client expects frame timestamps to be at least this far apart. - const base::TimeDelta min_capture_period_; - - // A recent history of observations in chronological order, maintained by - // AddObservation(). - ObservationFifo observations_; - - // The region of currently-detected animated content. If empty, that means - // "not detected." - gfx::Rect detected_region_; - - // The mean frame duration of currently-detected animated content. If zero, - // that means "not detected." - base::TimeDelta detected_period_; - - // The rewritten frame timestamp for the latest event. - base::TimeTicks frame_timestamp_; - - // The frame timestamp provided in the last call to RecordSample(). This - // timestamp may or may not have been one proposed by AnimatedContentSampler. - base::TimeTicks recorded_frame_timestamp_; - - // Accumulates all the time advancements since the last call to - // RecordSample(). When this is greater than zero, there have been one or - // more events proposed for sampling, but not yet recorded. This accounts for - // the cases where AnimatedContentSampler indicates a frame should be sampled, - // but the client chooses not to do so. - base::TimeDelta sequence_offset_; - - // A token bucket that is used to decide which frames to drop whenever - // |detected_period_| is less than |min_capture_period_|. - base::TimeDelta borrowed_time_; -}; - // VideoCaptureOracle manages the producer-side throttling of captured frames // from a video capture device. It is informed of every update by the device; // this empowers it to look into the future and decide if a particular frame
diff --git a/content/browser/media/capture/video_capture_oracle_unittest.cc b/content/browser/media/capture/video_capture_oracle_unittest.cc index 630e081..456bc515 100644 --- a/content/browser/media/capture/video_capture_oracle_unittest.cc +++ b/content/browser/media/capture/video_capture_oracle_unittest.cc
@@ -4,1055 +4,19 @@ #include "content/browser/media/capture/video_capture_oracle.h" -#include <cstdlib> -#include <utility> -#include <vector> - -#include "base/logging.h" #include "base/strings/stringprintf.h" -#include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/geometry/rect.h" namespace content { + namespace { -bool AddEventAndConsiderSampling(SmoothEventSampler* sampler, - base::TimeTicks event_time) { - sampler->ConsiderPresentationEvent(event_time); - return sampler->ShouldSample(); -} - -void SteadyStateSampleAndAdvance(base::TimeDelta vsync, - SmoothEventSampler* sampler, - base::TimeTicks* t) { - ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); - ASSERT_TRUE(sampler->HasUnrecordedEvent()); - sampler->RecordSample(); - ASSERT_FALSE(sampler->HasUnrecordedEvent()); - ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); - *t += vsync; - ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); -} - -void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync, - SmoothEventSampler* sampler, - base::TimeTicks* t) { - ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t)); - ASSERT_TRUE(sampler->HasUnrecordedEvent()); - ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); - *t += vsync; - ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); -} - base::TimeTicks InitialTestTimeTicks() { return base::TimeTicks() + base::TimeDelta::FromSeconds(1); } -void TestRedundantCaptureStrategy(base::TimeDelta capture_period, - int redundant_capture_goal, - SmoothEventSampler* sampler, - base::TimeTicks* t) { - // Before any events have been considered, we're overdue for sampling. - ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t)); - - // Consider the first event. We want to sample that. - ASSERT_FALSE(sampler->HasUnrecordedEvent()); - ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); - ASSERT_TRUE(sampler->HasUnrecordedEvent()); - sampler->RecordSample(); - ASSERT_FALSE(sampler->HasUnrecordedEvent()); - - // After more than 250 ms has passed without considering an event, we should - // repeatedly be overdue for sampling. However, once the redundant capture - // goal is achieved, we should no longer be overdue for sampling. - *t += base::TimeDelta::FromMilliseconds(250); - for (int i = 0; i < redundant_capture_goal; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - ASSERT_FALSE(sampler->HasUnrecordedEvent()); - ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t)) - << "Should sample until redundant capture goal is hit"; - sampler->RecordSample(); - *t += capture_period; // Timer fires once every capture period. - } - ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)) - << "Should not be overdue once redundant capture goal achieved."; -} - } // namespace -// 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains -// much more comprehensive before/after/edge-case scenarios than the others. -TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) { - const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; - const int redundant_capture_goal = 200; - const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60; - - SmoothEventSampler sampler(capture_period, redundant_capture_goal); - base::TimeTicks t = InitialTestTimeTicks(); - - TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, - &sampler, &t); - - // Steady state, we should capture every other vsync, indefinitely. - for (int i = 0; i < 100; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - } - - // Now pretend we're limited by backpressure in the pipeline. In this scenario - // case we are adding events but not sampling them. - for (int i = 0; i < 20; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - ASSERT_EQ(i >= 14, sampler.IsOverdueForSamplingAt(t)); - ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); - ASSERT_TRUE(sampler.HasUnrecordedEvent()); - t += vsync; - } - - // Now suppose we can sample again. We should be back in the steady state, - // but at a different phase. - ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); - for (int i = 0; i < 100; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - } -} - -// 50Hz sampled at 30Hz should produce a sequence where some frames are skipped. -TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) { - const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; - const int redundant_capture_goal = 2; - const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50; - - SmoothEventSampler sampler(capture_period, redundant_capture_goal); - base::TimeTicks t = InitialTestTimeTicks(); - - TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, - &sampler, &t); - - // Steady state, we should capture 1st, 2nd and 4th frames out of every five - // frames, indefinitely. - for (int i = 0; i < 100; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - } - - // Now pretend we're limited by backpressure in the pipeline. In this scenario - // case we are adding events but not sampling them. - for (int i = 0; i < 20; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - ASSERT_EQ(i >= 11, sampler.IsOverdueForSamplingAt(t)); - ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); - t += vsync; - } - - // Now suppose we can sample again. We should be back in the steady state - // again. - ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); - for (int i = 0; i < 100; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - } -} - -// 75Hz sampled at 30Hz should produce a sequence where some frames are skipped. -TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) { - const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; - const int redundant_capture_goal = 32; - const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75; - - SmoothEventSampler sampler(capture_period, redundant_capture_goal); - base::TimeTicks t = InitialTestTimeTicks(); - - TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, - &sampler, &t); - - // Steady state, we should capture 1st and 3rd frames out of every five - // frames, indefinitely. - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - for (int i = 0; i < 100; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - } - - // Now pretend we're limited by backpressure in the pipeline. In this scenario - // case we are adding events but not sampling them. - for (int i = 0; i < 20; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - ASSERT_EQ(i >= 16, sampler.IsOverdueForSamplingAt(t)); - ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); - t += vsync; - } - - // Now suppose we can sample again. We capture the next frame, and not the one - // after that, and then we're back in the steady state again. - ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - for (int i = 0; i < 100; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); - } -} - -// 30Hz sampled at 30Hz should produce 30Hz. -TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) { - const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; - const int redundant_capture_goal = 1; - const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30; - - SmoothEventSampler sampler(capture_period, redundant_capture_goal); - base::TimeTicks t = InitialTestTimeTicks(); - - TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, - &sampler, &t); - - // Steady state, we should capture every vsync, indefinitely. - for (int i = 0; i < 200; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - } - - // Now pretend we're limited by backpressure in the pipeline. In this scenario - // case we are adding events but not sampling them. - for (int i = 0; i < 10; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t)); - ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); - t += vsync; - } - - // Now suppose we can sample again. We should be back in the steady state. - ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); - for (int i = 0; i < 100; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - } -} - -// 24Hz sampled at 30Hz should produce 24Hz. -TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) { - const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; - const int redundant_capture_goal = 333; - const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24; - - SmoothEventSampler sampler(capture_period, redundant_capture_goal); - base::TimeTicks t = InitialTestTimeTicks(); - - TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, - &sampler, &t); - - // Steady state, we should capture every vsync, indefinitely. - for (int i = 0; i < 200; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - } - - // Now pretend we're limited by backpressure in the pipeline. In this scenario - // case we are adding events but not sampling them. - for (int i = 0; i < 10; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - ASSERT_EQ(i >= 6, sampler.IsOverdueForSamplingAt(t)); - ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); - t += vsync; - } - - // Now suppose we can sample again. We should be back in the steady state. - ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); - for (int i = 0; i < 100; i++) { - SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); - SteadyStateSampleAndAdvance(vsync, &sampler, &t); - } -} - -TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) { - const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; - const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1); - - SmoothEventSampler sampler(capture_period, 1); - base::TimeTicks t = InitialTestTimeTicks(); - - ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); - sampler.RecordSample(); - ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t)) - << "Sampled last event; should not be dirty."; - t += overdue_period; - - // Now simulate 2 events with the same clock value. - ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); - sampler.RecordSample(); - ASSERT_FALSE(AddEventAndConsiderSampling(&sampler, t)) - << "Two events at same time -- expected second not to be sampled."; - ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t + overdue_period)) - << "Second event should dirty the capture state."; - sampler.RecordSample(); - ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t + overdue_period)); -} - -namespace { - -struct DataPoint { - bool should_capture; - double increment_ms; -}; - -void ReplayCheckingSamplerDecisions(const DataPoint* data_points, - size_t num_data_points, - SmoothEventSampler* sampler) { - base::TimeTicks t = InitialTestTimeTicks(); - for (size_t i = 0; i < num_data_points; ++i) { - t += base::TimeDelta::FromMicroseconds( - static_cast<int64>(data_points[i].increment_ms * 1000)); - ASSERT_EQ(data_points[i].should_capture, - AddEventAndConsiderSampling(sampler, t)) - << "at data_points[" << i << ']'; - if (data_points[i].should_capture) - sampler->RecordSample(); - } -} - -} // namespace - -TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) { - // Actual capturing of timing data: Initial instability as a 24 FPS video was - // started from a still screen, then clearly followed by steady-state. - static const DataPoint data_points[] = { - { true, 1437.93 }, { true, 150.484 }, { true, 217.362 }, { true, 50.161 }, - { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 66.88 }, - { true, 50.161 }, { false, 0 }, { false, 0 }, { true, 50.16 }, - { true, 33.441 }, { true, 16.72 }, { false, 16.72 }, { true, 117.041 }, - { true, 16.72 }, { false, 16.72 }, { true, 50.161 }, { true, 50.16 }, - { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 16.72 }, - { false, 0 }, { true, 50.161 }, { false, 0 }, { true, 33.44 }, - { true, 16.72 }, { false, 16.721 }, { true, 66.881 }, { false, 0 }, - { true, 33.441 }, { true, 16.72 }, { true, 50.16 }, { true, 16.72 }, - { false, 16.721 }, { true, 50.161 }, { true, 50.16 }, { false, 0 }, - { true, 33.441 }, { true, 50.337 }, { true, 50.183 }, { true, 16.722 }, - { true, 50.161 }, { true, 33.441 }, { true, 50.16 }, { true, 33.441 }, - { true, 50.16 }, { true, 33.441 }, { true, 50.16 }, { true, 33.44 }, - { true, 50.161 }, { true, 50.16 }, { true, 33.44 }, { true, 33.441 }, - { true, 50.16 }, { true, 50.161 }, { true, 33.44 }, { true, 33.441 }, - { true, 50.16 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 }, - { true, 50.161 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 }, - { true, 83.601 }, { true, 16.72 }, { true, 33.44 }, { false, 0 } - }; - - SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); - ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); -} - -TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) { - // Actual capturing of timing data: Initial instability as a 30 FPS video was - // started from a still screen, then followed by steady-state. Drawing - // framerate from the video rendering was a bit volatile, but averaged 30 FPS. - static const DataPoint data_points[] = { - { true, 2407.69 }, { true, 16.733 }, { true, 217.362 }, { true, 33.441 }, - { true, 33.44 }, { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, - { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, - { true, 16.721 }, { true, 33.44 }, { false, 0 }, { true, 50.161 }, - { true, 50.16 }, { false, 0 }, { true, 50.161 }, { true, 33.44 }, - { true, 16.72 }, { false, 0 }, { false, 16.72 }, { true, 66.881 }, - { false, 0 }, { true, 33.44 }, { true, 16.72 }, { true, 50.161 }, - { false, 0 }, { true, 33.538 }, { true, 33.526 }, { true, 33.447 }, - { true, 33.445 }, { true, 33.441 }, { true, 16.721 }, { true, 33.44 }, - { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, { true, 33.44 }, - { true, 33.441 }, { true, 33.44 }, { false, 0 }, { false, 16.72 }, - { true, 66.881 }, { true, 16.72 }, { false, 16.72 }, { true, 50.16 }, - { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 33.44 }, - { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { false, 0 }, - { true, 33.44 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, - { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 66.88 }, - { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 }, - { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 }, - { true, 16.72 }, { true, 50.161 }, { false, 0 }, { true, 50.16 }, - { false, 0.001 }, { true, 16.721 }, { true, 66.88 }, { true, 33.44 }, - { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, - { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 66.881 }, - { true, 33.44 }, { true, 16.72 }, { true, 33.441 }, { false, 16.72 }, - { true, 66.88 }, { true, 16.721 }, { true, 50.16 }, { true, 33.44 }, - { true, 16.72 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 } - }; - - SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); - ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); -} - -TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) { - // Actual capturing of timing data: WebGL Acquarium demo - // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran - // between 55-60 FPS in the steady-state. - static const DataPoint data_points[] = { - { true, 16.72 }, { true, 16.72 }, { true, 4163.29 }, { true, 50.193 }, - { true, 117.041 }, { true, 50.161 }, { true, 50.16 }, { true, 33.441 }, - { true, 50.16 }, { true, 33.44 }, { false, 0 }, { false, 0 }, - { true, 50.161 }, { true, 83.601 }, { true, 50.16 }, { true, 16.72 }, - { true, 33.441 }, { false, 16.72 }, { true, 50.16 }, { true, 16.72 }, - { false, 0.001 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, - { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, - { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 }, - { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 }, - { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 }, - { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, - { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 33.44 }, - { false, 0 }, { true, 16.721 }, { true, 50.161 }, { false, 0 }, - { true, 33.44 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, - { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 }, - { true, 50.16 }, { false, 0 }, { true, 16.721 }, { true, 33.44 }, - { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 }, - { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 }, - { false, 0 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, - { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, - { true, 33.44 }, { false, 0 }, { true, 33.44 }, { true, 33.441 }, - { false, 0 }, { true, 33.44 }, { true, 33.441 }, { false, 0 }, - { true, 33.44 }, { false, 0 }, { true, 33.44 }, { false, 16.72 }, - { true, 16.721 }, { true, 50.161 }, { false, 0 }, { true, 16.72 }, - { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 33.44 }, - { true, 33.44 }, { false, 0 }, { true, 33.441 }, { false, 16.72 }, - { true, 16.72 }, { true, 50.16 }, { false, 0 }, { true, 16.72 }, - { true, 33.441 }, { false, 0 }, { true, 33.44 }, { false, 16.72 }, - { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 50.161 }, - { false, 0 }, { true, 16.72 }, { true, 33.44 }, { false, 0 }, - { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, { true, 50.16 } - }; - - SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); - ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); -} - -class AnimatedContentSamplerTest : public ::testing::Test { - public: - AnimatedContentSamplerTest() {} - ~AnimatedContentSamplerTest() override {} - - void SetUp() override { - const base::TimeDelta since_epoch = - InitialTestTimeTicks() - base::TimeTicks::UnixEpoch(); - rand_seed_ = abs(static_cast<int>(since_epoch.InMicroseconds())); - sampler_.reset(new AnimatedContentSampler(GetMinCapturePeriod())); - } - - protected: - // Overridden by subclass for parameterized tests. - virtual base::TimeDelta GetMinCapturePeriod() const { - return base::TimeDelta::FromSeconds(1) / 30; - } - - AnimatedContentSampler* sampler() const { - return sampler_.get(); - } - - int GetRandomInRange(int begin, int end) { - const int len = end - begin; - const int rand_offset = (len == 0) ? 0 : (NextRandomInt() % (end - begin)); - return begin + rand_offset; - } - - gfx::Rect GetRandomDamageRect() { - return gfx::Rect(0, 0, GetRandomInRange(1, 100), GetRandomInRange(1, 100)); - } - - gfx::Rect GetContentDamageRect() { - // This must be distinct from anything GetRandomDamageRect() could return. - return gfx::Rect(0, 0, 1280, 720); - } - - // Directly inject an observation. Only used to test - // ElectMajorityDamageRect(). - void ObserveDamageRect(const gfx::Rect& damage_rect) { - sampler_->observations_.push_back( - AnimatedContentSampler::Observation(damage_rect, base::TimeTicks())); - } - - gfx::Rect ElectMajorityDamageRect() const { - return sampler_->ElectMajorityDamageRect(); - } - - private: - // Note: Not using base::RandInt() because it is horribly slow on debug - // builds. The following is a very simple, deterministic LCG: - int NextRandomInt() { - rand_seed_ = (1103515245 * rand_seed_ + 12345) % (1 << 31); - return rand_seed_; - } - - int rand_seed_; - scoped_ptr<AnimatedContentSampler> sampler_; -}; - -TEST_F(AnimatedContentSamplerTest, ElectsNoneFromZeroDamageRects) { - EXPECT_EQ(gfx::Rect(), ElectMajorityDamageRect()); -} - -TEST_F(AnimatedContentSamplerTest, ElectsMajorityFromOneDamageRect) { - const gfx::Rect the_one_rect(0, 0, 1, 1); - ObserveDamageRect(the_one_rect); - EXPECT_EQ(the_one_rect, ElectMajorityDamageRect()); -} - -TEST_F(AnimatedContentSamplerTest, ElectsNoneFromTwoDamageRectsOfSameArea) { - const gfx::Rect one_rect(0, 0, 1, 1); - const gfx::Rect another_rect(1, 1, 1, 1); - ObserveDamageRect(one_rect); - ObserveDamageRect(another_rect); - EXPECT_EQ(gfx::Rect(), ElectMajorityDamageRect()); -} - -TEST_F(AnimatedContentSamplerTest, ElectsLargerOfTwoDamageRects_1) { - const gfx::Rect one_rect(0, 0, 1, 1); - const gfx::Rect another_rect(0, 0, 2, 2); - ObserveDamageRect(one_rect); - ObserveDamageRect(another_rect); - EXPECT_EQ(another_rect, ElectMajorityDamageRect()); -} - -TEST_F(AnimatedContentSamplerTest, ElectsLargerOfTwoDamageRects_2) { - const gfx::Rect one_rect(0, 0, 2, 2); - const gfx::Rect another_rect(0, 0, 1, 1); - ObserveDamageRect(one_rect); - ObserveDamageRect(another_rect); - EXPECT_EQ(one_rect, ElectMajorityDamageRect()); -} - -TEST_F(AnimatedContentSamplerTest, ElectsSameAsMooreDemonstration) { - // A more complex sequence (from Moore's web site): Three different Rects with - // the same area, but occurring a different number of times. C should win the - // vote. - const gfx::Rect rect_a(0, 0, 1, 4); - const gfx::Rect rect_b(1, 1, 4, 1); - const gfx::Rect rect_c(2, 2, 2, 2); - for (int i = 0; i < 3; ++i) - ObserveDamageRect(rect_a); - for (int i = 0; i < 2; ++i) - ObserveDamageRect(rect_c); - for (int i = 0; i < 2; ++i) - ObserveDamageRect(rect_b); - for (int i = 0; i < 3; ++i) - ObserveDamageRect(rect_c); - ObserveDamageRect(rect_b); - for (int i = 0; i < 2; ++i) - ObserveDamageRect(rect_c); - EXPECT_EQ(rect_c, ElectMajorityDamageRect()); -} - -TEST_F(AnimatedContentSamplerTest, Elects24FpsVideoInsteadOf48FpsSpinner) { - // Scenario: 24 FPS 720x480 Video versus 48 FPS 96x96 "Busy Spinner" - const gfx::Rect video_rect(100, 100, 720, 480); - const gfx::Rect spinner_rect(360, 0, 96, 96); - for (int i = 0; i < 100; ++i) { - // |video_rect| occurs once for every two |spinner_rect|. Vary the order - // of events between the two: - ObserveDamageRect(video_rect); - ObserveDamageRect(spinner_rect); - ObserveDamageRect(spinner_rect); - ObserveDamageRect(video_rect); - ObserveDamageRect(spinner_rect); - ObserveDamageRect(spinner_rect); - ObserveDamageRect(spinner_rect); - ObserveDamageRect(video_rect); - ObserveDamageRect(spinner_rect); - ObserveDamageRect(spinner_rect); - ObserveDamageRect(video_rect); - ObserveDamageRect(spinner_rect); - } - EXPECT_EQ(video_rect, ElectMajorityDamageRect()); -} - -namespace { - -// A test scenario for AnimatedContentSamplerParameterizedTest. -struct Scenario { - base::TimeDelta vsync_interval; // Reflects compositor's update rate. - base::TimeDelta min_capture_period; // Reflects maximum capture rate. - base::TimeDelta content_period; // Reflects content animation rate. - - Scenario(base::TimeDelta v, base::TimeDelta m, base::TimeDelta c) - : vsync_interval(v), min_capture_period(m), content_period(c) { - CHECK(content_period >= vsync_interval) - << "Bad test params: Impossible to animate faster than the compositor."; - } -}; - -// Value printer for Scenario. -::std::ostream& operator<<(::std::ostream& os, const Scenario& s) { - return os << "{ vsync_interval=" << s.vsync_interval.InMicroseconds() - << ", min_capture_period=" << s.min_capture_period.InMicroseconds() - << ", content_period=" << s.content_period.InMicroseconds() - << " }"; -} - -base::TimeDelta FpsAsPeriod(int frame_rate) { - return base::TimeDelta::FromSeconds(1) / frame_rate; -} - -} // namespace - -class AnimatedContentSamplerParameterizedTest - : public AnimatedContentSamplerTest, - public ::testing::WithParamInterface<Scenario> { - public: - AnimatedContentSamplerParameterizedTest() - : count_dropped_frames_(0), count_sampled_frames_(0) {} - virtual ~AnimatedContentSamplerParameterizedTest() {} - - protected: - typedef std::pair<gfx::Rect, base::TimeTicks> Event; - - base::TimeDelta GetMinCapturePeriod() const override { - return GetParam().min_capture_period; - } - - // Generate a sequence of events from the compositor pipeline. The event - // times will all be at compositor vsync boundaries. - std::vector<Event> GenerateEventSequence(base::TimeTicks begin, - base::TimeTicks end, - bool include_content_frame_events, - bool include_random_events) { - DCHECK(GetParam().content_period >= GetParam().vsync_interval); - base::TimeTicks next_content_time = begin - GetParam().content_period; - std::vector<Event> events; - for (base::TimeTicks compositor_time = begin; compositor_time < end; - compositor_time += GetParam().vsync_interval) { - if (include_content_frame_events && next_content_time < compositor_time) { - events.push_back(Event(GetContentDamageRect(), compositor_time)); - next_content_time += GetParam().content_period; - } else if (include_random_events && GetRandomInRange(0, 1) == 0) { - events.push_back(Event(GetRandomDamageRect(), compositor_time)); - } - } - - DCHECK(!events.empty()); - return events; - } - - // Feed |events| through the sampler, and detect whether the expected - // lock-in/out transition occurs. Also, track and measure the frame drop - // ratio and check it against the expected drop rate. - void RunEventSequence(const std::vector<Event> events, - bool was_detecting_before, - bool is_detecting_after, - bool simulate_pipeline_back_pressure) { - gfx::Rect first_detected_region; - - EXPECT_EQ(was_detecting_before, sampler()->HasProposal()); - bool has_detection_switched = false; - ResetFrameCounters(); - for (std::vector<Event>::const_iterator i = events.begin(); - i != events.end(); ++i) { - sampler()->ConsiderPresentationEvent(i->first, i->second); - - // Detect when the sampler locks in/out, and that it stays that way for - // all further iterations of this loop. - if (!has_detection_switched && - was_detecting_before != sampler()->HasProposal()) { - has_detection_switched = true; - } - ASSERT_EQ( - has_detection_switched ? is_detecting_after : was_detecting_before, - sampler()->HasProposal()); - - if (sampler()->HasProposal()) { - // Make sure the sampler doesn't flip-flop and keep proposing sampling - // based on locking into different regions. - if (first_detected_region.IsEmpty()) { - first_detected_region = sampler()->detected_region(); - ASSERT_FALSE(first_detected_region.IsEmpty()); - } else { - EXPECT_EQ(first_detected_region, sampler()->detected_region()); - } - - if (simulate_pipeline_back_pressure && GetRandomInRange(0, 2) == 0) - ClientCannotSampleFrame(*i); - else - ClientDoesWhatSamplerProposes(*i); - } else { - EXPECT_FALSE(sampler()->ShouldSample()); - if (!simulate_pipeline_back_pressure || GetRandomInRange(0, 2) == 1) - sampler()->RecordSample(i->second); - } - } - EXPECT_EQ(is_detecting_after, sampler()->HasProposal()); - ExpectFrameDropRatioIsCorrect(); - } - - void ResetFrameCounters() { - count_dropped_frames_ = 0; - count_sampled_frames_ = 0; - } - - // Keep track what the sampler is proposing, and call RecordSample() if it - // proposes sampling |event|. - void ClientDoesWhatSamplerProposes(const Event& event) { - if (sampler()->ShouldSample()) { - EXPECT_EQ(GetContentDamageRect(), event.first); - sampler()->RecordSample(sampler()->frame_timestamp()); - ++count_sampled_frames_; - } else if (event.first == GetContentDamageRect()) { - ++count_dropped_frames_; - } - } - - // RecordSample() is not called, but for testing, keep track of what the - // sampler is proposing for |event|. - void ClientCannotSampleFrame(const Event& event) { - if (sampler()->ShouldSample()) { - EXPECT_EQ(GetContentDamageRect(), event.first); - ++count_sampled_frames_; - } else if (event.first == GetContentDamageRect()) { - ++count_dropped_frames_; - } - } - - // Confirm the AnimatedContentSampler is not dropping more frames than - // expected, given current test parameters. - void ExpectFrameDropRatioIsCorrect() { - if (count_sampled_frames_ == 0) { - EXPECT_EQ(0, count_dropped_frames_); - return; - } - const double content_framerate = - 1000000.0 / GetParam().content_period.InMicroseconds(); - const double capture_framerate = - 1000000.0 / GetParam().min_capture_period.InMicroseconds(); - const double expected_drop_rate = std::max( - 0.0, (content_framerate - capture_framerate) / capture_framerate); - const double actual_drop_rate = - static_cast<double>(count_dropped_frames_) / count_sampled_frames_; - EXPECT_NEAR(expected_drop_rate, actual_drop_rate, 0.015); - } - - private: - // These counters only include the frames with the desired content. - int count_dropped_frames_; - int count_sampled_frames_; -}; - -// Tests that the implementation locks in/out of frames containing stable -// animated content, whether or not random events are also simultaneously -// present. -TEST_P(AnimatedContentSamplerParameterizedTest, DetectsAnimatedContent) { - // |begin| refers to the start of an event sequence in terms of the - // Compositor's clock. - base::TimeTicks begin = InitialTestTimeTicks(); - - // Provide random events and expect no lock-in. - base::TimeTicks end = begin + base::TimeDelta::FromSeconds(5); - RunEventSequence(GenerateEventSequence(begin, end, false, true), - false, - false, - false); - begin = end; - - // Provide content frame events with some random events mixed-in, and expect - // the sampler to lock-in. - end = begin + base::TimeDelta::FromSeconds(5); - RunEventSequence(GenerateEventSequence(begin, end, true, true), - false, - true, - false); - begin = end; - - // Continue providing content frame events without the random events mixed-in - // and expect the lock-in to hold. - end = begin + base::TimeDelta::FromSeconds(5); - RunEventSequence(GenerateEventSequence(begin, end, true, false), - true, - true, - false); - begin = end; - - // Continue providing just content frame events and expect the lock-in to - // hold. Also simulate the capture pipeline experiencing back pressure. - end = begin + base::TimeDelta::FromSeconds(20); - RunEventSequence(GenerateEventSequence(begin, end, true, false), - true, - true, - true); - begin = end; - - // Provide a half-second of random events only, and expect the lock-in to be - // broken. - end = begin + base::TimeDelta::FromMilliseconds(500); - RunEventSequence(GenerateEventSequence(begin, end, false, true), - true, - false, - false); - begin = end; - - // Now, go back to providing content frame events, and expect the sampler to - // lock-in once again. - end = begin + base::TimeDelta::FromSeconds(5); - RunEventSequence(GenerateEventSequence(begin, end, true, false), - false, - true, - false); - begin = end; -} - -// Tests that AnimatedContentSampler won't lock in to, nor flip-flop between, -// two animations of the same pixel change rate. VideoCaptureOracle should -// revert to using the SmoothEventSampler for these kinds of situations, as -// there is no "right answer" as to which animation to lock into. -TEST_P(AnimatedContentSamplerParameterizedTest, - DoesNotLockInToTwoCompetingAnimations) { - // Don't test when the event stream cannot indicate two separate content - // animations under the current test parameters. - if (GetParam().content_period < 2 * GetParam().vsync_interval) - return; - - // Start the first animation and run for a bit, and expect the sampler to - // lock-in. - base::TimeTicks begin = InitialTestTimeTicks(); - base::TimeTicks end = begin + base::TimeDelta::FromSeconds(5); - RunEventSequence(GenerateEventSequence(begin, end, true, false), - false, - true, - false); - begin = end; - - // Now, keep the first animation and blend in an second animation of the same - // size and frame rate, but at a different position. This will should cause - // the sampler to enter an "undetected" state since it's unclear which - // animation should be locked into. - end = begin + base::TimeDelta::FromSeconds(20); - std::vector<Event> first_animation_events = - GenerateEventSequence(begin, end, true, false); - gfx::Rect second_animation_rect( - gfx::Point(0, GetContentDamageRect().height()), - GetContentDamageRect().size()); - std::vector<Event> both_animations_events; - base::TimeDelta second_animation_offset = GetParam().vsync_interval; - for (std::vector<Event>::const_iterator i = first_animation_events.begin(); - i != first_animation_events.end(); ++i) { - both_animations_events.push_back(*i); - both_animations_events.push_back( - Event(second_animation_rect, i->second + second_animation_offset)); - } - RunEventSequence(both_animations_events, true, false, false); - begin = end; - - // Now, run just the first animation, and expect the sampler to lock-in once - // again. - end = begin + base::TimeDelta::FromSeconds(5); - RunEventSequence(GenerateEventSequence(begin, end, true, false), - false, - true, - false); - begin = end; - - // Now, blend in the second animation again, but it has half the frame rate of - // the first animation and damage Rects with twice the area. This will should - // cause the sampler to enter an "undetected" state again. This tests that - // pixel-weighting is being accounted for in the sampler's logic. - end = begin + base::TimeDelta::FromSeconds(20); - first_animation_events = GenerateEventSequence(begin, end, true, false); - second_animation_rect.set_width(second_animation_rect.width() * 2); - both_animations_events.clear(); - bool include_second_animation_frame = true; - for (std::vector<Event>::const_iterator i = first_animation_events.begin(); - i != first_animation_events.end(); ++i) { - both_animations_events.push_back(*i); - if (include_second_animation_frame) { - both_animations_events.push_back( - Event(second_animation_rect, i->second + second_animation_offset)); - } - include_second_animation_frame = !include_second_animation_frame; - } - RunEventSequence(both_animations_events, true, false, false); - begin = end; -} - -// Tests that the frame timestamps are smooth; meaning, that when run through a -// simulated compositor, each frame is held displayed for the right number of -// v-sync intervals. -TEST_P(AnimatedContentSamplerParameterizedTest, FrameTimestampsAreSmooth) { - // Generate 30 seconds of animated content events, run the events through - // AnimatedContentSampler, and record all frame timestamps being proposed - // once lock-in is continuous. - base::TimeTicks begin = InitialTestTimeTicks(); - std::vector<Event> events = GenerateEventSequence( - begin, - begin + base::TimeDelta::FromSeconds(20), - true, - false); - typedef std::vector<base::TimeTicks> Timestamps; - Timestamps frame_timestamps; - for (std::vector<Event>::const_iterator i = events.begin(); i != events.end(); - ++i) { - sampler()->ConsiderPresentationEvent(i->first, i->second); - if (sampler()->HasProposal()) { - if (sampler()->ShouldSample()) { - frame_timestamps.push_back(sampler()->frame_timestamp()); - sampler()->RecordSample(sampler()->frame_timestamp()); - } - } else { - frame_timestamps.clear(); // Reset until continuous lock-in. - } - } - ASSERT_LE(2u, frame_timestamps.size()); - - // Iterate through the |frame_timestamps|, building a histogram counting the - // number of times each frame was displayed k times. For example, 10 frames - // of 30 Hz content on a 60 Hz v-sync interval should result in - // display_counts[2] == 10. Quit early if any one frame was obviously - // repeated too many times. - const int64 max_expected_repeats_per_frame = 1 + - std::max(GetParam().min_capture_period, GetParam().content_period) / - GetParam().vsync_interval; - std::vector<size_t> display_counts(max_expected_repeats_per_frame + 1, 0); - base::TimeTicks last_present_time = frame_timestamps.front(); - for (Timestamps::const_iterator i = frame_timestamps.begin() + 1; - i != frame_timestamps.end(); ++i) { - const size_t num_vsync_intervals = static_cast<size_t>( - (*i - last_present_time) / GetParam().vsync_interval); - ASSERT_LT(0u, num_vsync_intervals); - ASSERT_GT(display_counts.size(), num_vsync_intervals); // Quit early. - ++display_counts[num_vsync_intervals]; - last_present_time += num_vsync_intervals * GetParam().vsync_interval; - } - - // Analyze the histogram for an expected result pattern. If the frame - // timestamps are smooth, there should only be one or two buckets with - // non-zero counts and they should be next to each other. Because the clock - // precision for the event_times provided to the sampler is very granular - // (i.e., the vsync_interval), it's okay if other buckets have a tiny "stray" - // count in this test. - size_t highest_count = 0; - size_t second_highest_count = 0; - for (size_t repeats = 1; repeats < display_counts.size(); ++repeats) { - DVLOG(1) << "display_counts[" << repeats << "] is " - << display_counts[repeats]; - if (display_counts[repeats] >= highest_count) { - second_highest_count = highest_count; - highest_count = display_counts[repeats]; - } else if (display_counts[repeats] > second_highest_count) { - second_highest_count = display_counts[repeats]; - } - } - size_t stray_count_remaining = - (frame_timestamps.size() - 1) - (highest_count + second_highest_count); - // Expect no more than 0.75% of frames fall outside the two main buckets. - EXPECT_GT(frame_timestamps.size() * 75 / 10000, stray_count_remaining); - for (size_t repeats = 1; repeats < display_counts.size() - 1; ++repeats) { - if (display_counts[repeats] == highest_count) { - EXPECT_EQ(second_highest_count, display_counts[repeats + 1]); - ++repeats; - } else if (display_counts[repeats] == second_highest_count) { - EXPECT_EQ(highest_count, display_counts[repeats + 1]); - ++repeats; - } else { - EXPECT_GE(stray_count_remaining, display_counts[repeats]); - stray_count_remaining -= display_counts[repeats]; - } - } -} - -// Tests that frame timestamps are "lightly pushed" back towards the original -// presentation event times, which tells us the AnimatedContentSampler can -// account for sources of timestamp drift and correct the drift. -TEST_P(AnimatedContentSamplerParameterizedTest, - FrameTimestampsConvergeTowardsEventTimes) { - const int max_drift_increment_millis = 3; - - // Generate a full minute of events. - const base::TimeTicks begin = InitialTestTimeTicks(); - const base::TimeTicks end = begin + base::TimeDelta::FromMinutes(1); - std::vector<Event> events = GenerateEventSequence(begin, end, true, false); - - // Modify the event sequence so that 1-3 ms of additional drift is suddenly - // present every 100 events. This is meant to simulate that, external to - // AnimatedContentSampler, the video hardware vsync timebase is being - // refreshed and is showing severe drift from the system clock. - base::TimeDelta accumulated_drift; - for (size_t i = 1; i < events.size(); ++i) { - if (i % 100 == 0) { - accumulated_drift += base::TimeDelta::FromMilliseconds( - GetRandomInRange(1, max_drift_increment_millis + 1)); - } - events[i].second += accumulated_drift; - } - - // Run all the events through the sampler and track the last rewritten frame - // timestamp. - base::TimeTicks last_frame_timestamp; - for (std::vector<Event>::const_iterator i = events.begin(); i != events.end(); - ++i) { - sampler()->ConsiderPresentationEvent(i->first, i->second); - if (sampler()->ShouldSample()) - last_frame_timestamp = sampler()->frame_timestamp(); - } - - // If drift was accounted for, the |last_frame_timestamp| should be close to - // the last event's timestamp. - const base::TimeDelta total_error = - events.back().second - last_frame_timestamp; - const base::TimeDelta max_acceptable_error = GetParam().min_capture_period + - base::TimeDelta::FromMilliseconds(max_drift_increment_millis); - EXPECT_NEAR(0.0, - total_error.InMicroseconds(), - max_acceptable_error.InMicroseconds()); -} - -INSTANTIATE_TEST_CASE_P( - , - AnimatedContentSamplerParameterizedTest, - ::testing::Values( - // Typical frame rate content: Compositor runs at 60 Hz, capture at 30 - // Hz, and content video animates at 30, 25, or 24 Hz. - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(30)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(25)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(24)), - - // High frame rate content that leverages the Compositor's - // capabilities, but capture is still at 30 Hz. - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(60)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(50)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(48)), - - // High frame rate content that leverages the Compositor's - // capabilities, and capture is also a buttery 60 Hz. - Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(60)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(50)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(60), FpsAsPeriod(48)), - - // On some platforms, the Compositor runs at 50 Hz. - Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(30)), - Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(25)), - Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(24)), - Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(50)), - Scenario(FpsAsPeriod(50), FpsAsPeriod(30), FpsAsPeriod(48)), - - // Stable, but non-standard content frame rates. - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(16)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(20)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(23)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(26)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(27)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(28)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(29)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(31)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(32)), - Scenario(FpsAsPeriod(60), FpsAsPeriod(30), FpsAsPeriod(33)))); - // Tests that VideoCaptureOracle filters out events whose timestamps are // decreasing. TEST(VideoCaptureOracleTest, EnforcesEventTimeMonotonicity) {
diff --git a/content/browser/media/cdm/browser_cdm_manager.cc b/content/browser/media/cdm/browser_cdm_manager.cc index 88cf526..8f1e78a 100644 --- a/content/browser/media/cdm/browser_cdm_manager.cc +++ b/content/browser/media/cdm/browser_cdm_manager.cc
@@ -324,8 +324,7 @@ return; } - cdm->SetServerCertificate(&certificate[0], certificate.size(), - promise.Pass()); + cdm->SetServerCertificate(certificate, promise.Pass()); } void BrowserCdmManager::OnCreateSessionAndGenerateRequest( @@ -405,7 +404,7 @@ return; } - cdm->UpdateSession(session_id, &response[0], response.size(), promise.Pass()); + cdm->UpdateSession(session_id, response, promise.Pass()); } void BrowserCdmManager::OnCloseSession(int render_frame_id, @@ -577,8 +576,8 @@ // Only the temporary session type is supported in browser CDM path. // TODO(xhwang): Add SessionType support if needed. cdm->CreateSessionAndGenerateRequest(media::MediaKeys::TEMPORARY_SESSION, - init_data_type, &init_data[0], - init_data.size(), promise.Pass()); + init_data_type, init_data, + promise.Pass()); } } // namespace content
diff --git a/content/browser/media/encrypted_media_browsertest.cc b/content/browser/media/encrypted_media_browsertest.cc index 7d58aca..b606730 100644 --- a/content/browser/media/encrypted_media_browsertest.cc +++ b/content/browser/media/encrypted_media_browsertest.cc
@@ -197,11 +197,6 @@ } IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) { - // Times out on Windows XP. http://crbug.com/171937 -#if defined(OS_WIN) - if (base::win::GetVersion() < base::win::VERSION_VISTA) - return; -#endif TestFrameSizeChange(); }
diff --git a/content/browser/net/sqlite_persistent_cookie_store.cc b/content/browser/net/sqlite_persistent_cookie_store.cc index 5da609b..61cb329 100644 --- a/content/browser/net/sqlite_persistent_cookie_store.cc +++ b/content/browser/net/sqlite_persistent_cookie_store.cc
@@ -432,9 +432,15 @@ if (!db->Execute("CREATE INDEX domain ON cookies(host_key)")) return false; +#if defined(OS_IOS) + // iOS 8.1 and older doesn't support partial indices. iOS 8.2 supports + // partial indices. + if (!db->Execute("CREATE INDEX is_transient ON cookies(persistent)")) { +#else if (!db->Execute( "CREATE INDEX is_transient ON cookies(persistent) " "where persistent != 1")) { +#endif return false; } @@ -701,6 +707,9 @@ 50); initialized_ = true; + + if (!restore_old_session_cookies_) + DeleteSessionCookiesOnStartup(); return true; } @@ -981,9 +990,16 @@ return false; } +#if defined(OS_IOS) + // iOS 8.1 and older doesn't support partial indices. iOS 8.2 supports + // partial indices. if (!db_->Execute( - "CREATE INDEX IF NOT EXISTS is_transient ON cookies(persistent) " - "where persistent != 1")) { + "CREATE INDEX IF NOT EXISTS is_transient ON cookies(persistent)")) { +#else + if (!db_->Execute( + "CREATE INDEX IF NOT EXISTS is_transient ON cookies(persistent) " + "where persistent != 1")) { +#endif LOG(WARNING) << "Unable to create index is_transient in update to version 9."; return false; @@ -1296,7 +1312,7 @@ void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() { DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); - if (!db_->Execute("DELETE FROM cookies WHERE persistent == 0")) + if (!db_->Execute("DELETE FROM cookies WHERE persistent != 1")) LOG(WARNING) << "Unable to delete session cookies."; } @@ -1321,8 +1337,6 @@ bool success) { PostClientTask(FROM_HERE, base::Bind(&Backend::CompleteLoadInForeground, this, loaded_callback, success)); - if (success && !restore_old_session_cookies_) - DeleteSessionCookiesOnStartup(); } SQLitePersistentCookieStore::SQLitePersistentCookieStore(
diff --git a/content/browser/net/sqlite_persistent_cookie_store_unittest.cc b/content/browser/net/sqlite_persistent_cookie_store_unittest.cc index 41d20a8..af7859a 100644 --- a/content/browser/net/sqlite_persistent_cookie_store_unittest.cc +++ b/content/browser/net/sqlite_persistent_cookie_store_unittest.cc
@@ -164,6 +164,17 @@ false, false, net::COOKIE_PRIORITY_DEFAULT)); } + void AddCookieWithExpiration(const std::string& name, + const std::string& value, + const std::string& domain, + const std::string& path, + const base::Time& creation, + const base::Time& expiration) { + store_->AddCookie(net::CanonicalCookie( + GURL(), name, value, domain, path, creation, expiration, creation, + false, false, false, net::COOKIE_PRIORITY_DEFAULT)); + } + std::string ReadRawDBContents() { std::string contents; if (!base::ReadFileToString(temp_dir_.path().Append(kCookieFilename), @@ -257,6 +268,82 @@ ASSERT_EQ(0U, cookies.size()); } +TEST_F(SQLitePersistentCookieStoreTest, TestSessionCookiesDeletedOnStartup) { + // Initialize the cookie store with 3 persistent cookies, 5 transient + // cookies. + InitializeStore(false, false); + + // Add persistent cookies. + base::Time t = base::Time::Now(); + AddCookie("A", "B", "a1.com", "/", t); + t += base::TimeDelta::FromInternalValue(10); + AddCookie("A", "B", "a2.com", "/", t); + t += base::TimeDelta::FromInternalValue(10); + AddCookie("A", "B", "a3.com", "/", t); + + // Add transient cookies. + t += base::TimeDelta::FromInternalValue(10); + AddCookieWithExpiration("A", "B", "b1.com", "/", t, base::Time()); + t += base::TimeDelta::FromInternalValue(10); + AddCookieWithExpiration("A", "B", "b2.com", "/", t, base::Time()); + t += base::TimeDelta::FromInternalValue(10); + AddCookieWithExpiration("A", "B", "b3.com", "/", t, base::Time()); + t += base::TimeDelta::FromInternalValue(10); + AddCookieWithExpiration("A", "B", "b4.com", "/", t, base::Time()); + t += base::TimeDelta::FromInternalValue(10); + AddCookieWithExpiration("A", "B", "b5.com", "/", t, base::Time()); + DestroyStore(); + + // Load the store a second time. Before the store finishes loading, add a + // transient cookie and flush it to disk. + store_ = new SQLitePersistentCookieStore( + temp_dir_.path().Append(kCookieFilename), + client_task_runner(), + background_task_runner(), + false, NULL, NULL); + + // Posting a blocking task to db_thread_ makes sure that the DB thread waits + // until both Load and Flush have been posted to its task queue. + background_task_runner()->PostTask( + FROM_HERE, + base::Bind(&SQLitePersistentCookieStoreTest::WaitOnDBEvent, + base::Unretained(this))); + store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, + base::Unretained(this))); + t += base::TimeDelta::FromInternalValue(10); + AddCookieWithExpiration("A", "B", "c.com", "/", t, base::Time()); + base::WaitableEvent event(false, false); + store_->Flush(base::Bind(&base::WaitableEvent::Signal, + base::Unretained(&event))); + + // Now the DB-thread queue contains: + // (active:) + // 1. Wait (on db_event) + // (pending:) + // 2. "Init And Chain-Load First Domain" + // 3. Add Cookie (c.com) + // 4. Flush Cookie (c.com) + db_thread_event_.Signal(); + event.Wait(); + loaded_event_.Wait(); + STLDeleteElements(&cookies_); + DestroyStore(); + + // Load the store a third time, this time restoring session cookies. The + // store should contain exactly 4 cookies: the 3 persistent, and "c.com", + // which was added during the second cookie store load. + store_ = new SQLitePersistentCookieStore( + temp_dir_.path().Append(kCookieFilename), + client_task_runner(), + background_task_runner(), + true, NULL, NULL); + store_->Load(base::Bind(&SQLitePersistentCookieStoreTest::OnLoaded, + base::Unretained(this))); + loaded_event_.Wait(); + ASSERT_EQ(4u, cookies_.size()); + STLDeleteElements(&cookies_); +} + // Test that priority load of cookies for a specfic domain key could be // completed before the entire store is loaded TEST_F(SQLitePersistentCookieStoreTest, TestLoadCookiesForKey) {
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc index 78d2a85e..b135177f 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.cc +++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -51,6 +51,7 @@ case SERVICE_WORKER_ERROR_STATE: case SERVICE_WORKER_ERROR_TIMEOUT: case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: + case SERVICE_WORKER_ERROR_DISK_CACHE: case SERVICE_WORKER_ERROR_MAX_VALUE: status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR; break; @@ -103,6 +104,7 @@ case SERVICE_WORKER_ERROR_STATE: case SERVICE_WORKER_ERROR_TIMEOUT: case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: + case SERVICE_WORKER_ERROR_DISK_CACHE: case SERVICE_WORKER_ERROR_MAX_VALUE: status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR; break;
diff --git a/content/browser/plugin_process_host.cc b/content/browser/plugin_process_host.cc index 4b6f361..d33b89b97 100644 --- a/content/browser/plugin_process_host.cc +++ b/content/browser/plugin_process_host.cc
@@ -106,7 +106,7 @@ ~PluginSandboxedProcessLauncherDelegate() override {} #if defined(OS_WIN) - virtual bool ShouldSandbox() override { + bool ShouldSandbox() override { return false; }
diff --git a/content/browser/plugin_service_impl.h b/content/browser/plugin_service_impl.h index fae8dda..1d419e0 100644 --- a/content/browser/plugin_service_impl.h +++ b/content/browser/plugin_service_impl.h
@@ -111,9 +111,9 @@ #if defined(OS_MACOSX) void AppActivated() override; #elif defined(OS_WIN) - virtual bool GetPluginInfoFromWindow(HWND window, - base::string16* plugin_name, - base::string16* plugin_version) override; + bool GetPluginInfoFromWindow(HWND window, + base::string16* plugin_name, + base::string16* plugin_version) override; // Returns true iff the given HWND is a plugin. bool IsPluginWindow(HWND window);
diff --git a/content/browser/plugin_service_impl_browsertest.cc b/content/browser/plugin_service_impl_browsertest.cc index b81b78c..e60516e6 100644 --- a/content/browser/plugin_service_impl_browsertest.cc +++ b/content/browser/plugin_service_impl_browsertest.cc
@@ -181,11 +181,11 @@ get_resource_context_called_(false) { } - virtual ~MockCanceledPluginServiceClient() {} + ~MockCanceledPluginServiceClient() override {} // Client implementation. MOCK_METHOD0(ID, int()); - virtual ResourceContext* GetResourceContext() override { + ResourceContext* GetResourceContext() override { get_resource_context_called_ = true; return context_; }
diff --git a/content/browser/power_profiler/power_data_provider_ia_win.h b/content/browser/power_profiler/power_data_provider_ia_win.h index 427a5fa2..68d220d 100644 --- a/content/browser/power_profiler/power_data_provider_ia_win.h +++ b/content/browser/power_profiler/power_data_provider_ia_win.h
@@ -15,12 +15,14 @@ public: PowerDataProviderIA(); - virtual ~PowerDataProviderIA(); + ~PowerDataProviderIA() override; bool Initialize(); - virtual PowerEventVector GetData() override; - virtual base::TimeDelta GetSamplingRate() override; - virtual AccuracyLevel GetAccuracyLevel() override { return High; } + + // PowerDataProvider: + PowerEventVector GetData() override; + base::TimeDelta GetSamplingRate() override; + AccuracyLevel GetAccuracyLevel() override { return High; } private: CIntelPowerGadgetLib energy_lib_;
diff --git a/content/browser/ppapi_plugin_process_host.cc b/content/browser/ppapi_plugin_process_host.cc index fe10276..c59b70c 100644 --- a/content/browser/ppapi_plugin_process_host.cc +++ b/content/browser/ppapi_plugin_process_host.cc
@@ -51,12 +51,11 @@ ~PpapiPluginSandboxedProcessLauncherDelegate() override {} #if defined(OS_WIN) - virtual bool ShouldSandbox() override { + bool ShouldSandbox() override { return !is_broker_; } - virtual void PreSpawnTarget(sandbox::TargetPolicy* policy, - bool* success) { + void PreSpawnTarget(sandbox::TargetPolicy* policy, bool* success) override { if (is_broker_) return; // The Pepper process as locked-down as a renderer execpt that it can
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc index 2d6769e0..e22e914 100644 --- a/content/browser/presentation/presentation_service_impl.cc +++ b/content/browser/presentation/presentation_service_impl.cc
@@ -23,23 +23,24 @@ WebContents* web_contents, PresentationServiceDelegate* delegate) : WebContentsObserver(web_contents), - render_frame_host_(render_frame_host), delegate_(delegate), is_start_session_pending_(false), next_request_session_id_(0), weak_factory_(this) { - DCHECK(render_frame_host_); + DCHECK(render_frame_host); DCHECK(web_contents); + + render_process_id_ = render_frame_host->GetProcess()->GetID(); + render_frame_id_ = render_frame_host->GetRoutingID(); DVLOG(2) << "PresentationServiceImpl: " - << render_frame_host_->GetProcess()->GetID() << ", " - << render_frame_host_->GetRoutingID(); + << render_process_id_ << ", " << render_frame_id_; if (delegate_) - delegate_->AddObserver(this); + delegate_->AddObserver(render_process_id_, render_frame_id_, this); } PresentationServiceImpl::~PresentationServiceImpl() { if (delegate_) - delegate_->RemoveObserver(this); + delegate_->RemoveObserver(render_process_id_, render_frame_id_); FlushNewSessionCallbacks(); } @@ -83,9 +84,7 @@ linked_ptr<ScreenAvailabilityContext> context( new ScreenAvailabilityContext(presentation_url)); if (!delegate_->AddScreenAvailabilityListener( - render_frame_host_->GetProcess()->GetID(), - render_frame_host_->GetRoutingID(), - context.get())) { + render_process_id_, render_frame_id_, context.get())) { DVLOG(1) << "AddScreenAvailabilityListener failed. Ignoring request."; return nullptr; } @@ -125,9 +124,7 @@ return; delegate_->RemoveScreenAvailabilityListener( - render_frame_host_->GetProcess()->GetID(), - render_frame_host_->GetRoutingID(), - it->second.get()); + render_process_id_, render_frame_id_, it->second.get()); // Resolve the context's pending callbacks before removing it. it->second->OnScreenAvailabilityChanged(false); availability_contexts_.erase(it); @@ -135,7 +132,9 @@ void PresentationServiceImpl::ListenForDefaultSessionStart( const DefaultSessionMojoCallback& callback) { - NOTIMPLEMENTED(); + if (!default_session_start_context_.get()) + default_session_start_context_.reset(new DefaultSessionStartContext); + default_session_start_context_->AddCallback(callback); } void PresentationServiceImpl::StartSession( @@ -169,8 +168,8 @@ int request_session_id = RegisterNewSessionCallback(callback); delegate_->JoinSession( - render_frame_host_->GetProcess()->GetID(), - render_frame_host_->GetRoutingID(), + render_process_id_, + render_frame_id_, presentation_url, presentation_id, base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded, @@ -214,8 +213,8 @@ int request_session_id = RegisterNewSessionCallback(callback); is_start_session_pending_ = true; delegate_->StartSession( - render_frame_host_->GetProcess()->GetID(), - render_frame_host_->GetRoutingID(), + render_process_id_, + render_frame_id_, presentation_url, presentation_id, base::Bind(&PresentationServiceImpl::OnStartOrJoinSessionSucceeded, @@ -266,8 +265,8 @@ const std::string& default_presentation_id) { DCHECK(delegate_); delegate_->SetDefaultPresentationUrl( - render_frame_host_->GetProcess()->GetID(), - render_frame_host_->GetRoutingID(), + render_process_id_, + render_frame_id_, default_presentation_url, default_presentation_id); default_presentation_url_ = default_presentation_url; @@ -307,8 +306,8 @@ // Remove listener for old default presentation URL. delegate_->RemoveScreenAvailabilityListener( - render_frame_host_->GetProcess()->GetID(), - render_frame_host_->GetRoutingID(), + render_process_id_, + render_frame_id_, old_it->second.get()); availability_contexts_.erase(old_it); DoSetDefaultPresentationUrl(new_default_url, default_presentation_id); @@ -325,12 +324,21 @@ NOTIMPLEMENTED(); } +bool PresentationServiceImpl::FrameMatches( + content::RenderFrameHost* render_frame_host) const { + if (!render_frame_host) + return false; + + return render_frame_host->GetProcess()->GetID() == render_process_id_ && + render_frame_host->GetRoutingID() == render_frame_id_; +} + void PresentationServiceImpl::DidNavigateAnyFrame( content::RenderFrameHost* render_frame_host, const content::LoadCommittedDetails& details, const content::FrameNavigateParams& params) { DVLOG(2) << "PresentationServiceImpl::DidNavigateAnyFrame"; - if (render_frame_host_ != render_frame_host) + if (!FrameMatches(render_frame_host)) return; std::string prev_url_host = details.previous_url.host(); @@ -355,29 +363,26 @@ void PresentationServiceImpl::RenderFrameDeleted( content::RenderFrameHost* render_frame_host) { DVLOG(2) << "PresentationServiceImpl::RenderFrameDeleted"; - if (render_frame_host_ != render_frame_host) + if (!FrameMatches(render_frame_host)) return; - // RenderFrameDeleted means |render_frame_host_| is going to be deleted soon. + // RenderFrameDeleted means the associated RFH is going to be deleted soon. // This object should also be deleted. Reset(); - render_frame_host_ = nullptr; delete this; } void PresentationServiceImpl::Reset() { DVLOG(2) << "PresentationServiceImpl::Reset"; - if (delegate_) { - delegate_->Reset( - render_frame_host_->GetProcess()->GetID(), - render_frame_host_->GetRoutingID()); - } + if (delegate_) + delegate_->Reset(render_process_id_, render_frame_id_); default_presentation_url_.clear(); default_presentation_id_.clear(); availability_contexts_.clear(); queued_start_session_requests_.clear(); FlushNewSessionCallbacks(); + default_session_start_context_.reset(); } // static @@ -395,6 +400,12 @@ Reset(); } +void PresentationServiceImpl::OnDefaultPresentationStarted( + const PresentationSessionInfo& session) { + if (default_session_start_context_.get()) + default_session_start_context_->set_session(session); +} + PresentationServiceImpl::ScreenAvailabilityContext::ScreenAvailabilityContext( const std::string& presentation_url) : presentation_url_(presentation_url) { @@ -478,5 +489,46 @@ return callback; } +PresentationServiceImpl::DefaultSessionStartContext +::DefaultSessionStartContext() { +} + +PresentationServiceImpl::DefaultSessionStartContext +::~DefaultSessionStartContext() { + Reset(); +} + +void PresentationServiceImpl::DefaultSessionStartContext::AddCallback( + const DefaultSessionMojoCallback& callback) { + if (session_.get()) { + DCHECK(callbacks_.empty()); + callback.Run(presentation::PresentationSessionInfo::From(*session_)); + session_.reset(); + } else { + callbacks_.push_back(new DefaultSessionMojoCallback(callback)); + } +} + +void PresentationServiceImpl::DefaultSessionStartContext::set_session( + const PresentationSessionInfo& session) { + if (callbacks_.empty()) { + session_.reset(new PresentationSessionInfo(session)); + } else { + DCHECK(!session_.get()); + ScopedVector<DefaultSessionMojoCallback> callbacks; + callbacks.swap(callbacks_); + for (const auto& callback : callbacks) + callback->Run(presentation::PresentationSessionInfo::From(session)); + } +} + +void PresentationServiceImpl::DefaultSessionStartContext::Reset() { + ScopedVector<DefaultSessionMojoCallback> callbacks; + callbacks.swap(callbacks_); + for (const auto& callback : callbacks) + callback->Run(presentation::PresentationSessionInfoPtr()); + session_.reset(); +} + } // namespace content
diff --git a/content/browser/presentation/presentation_service_impl.h b/content/browser/presentation/presentation_service_impl.h index 84962e7..21de733 100644 --- a/content/browser/presentation/presentation_service_impl.h +++ b/content/browser/presentation/presentation_service_impl.h
@@ -109,6 +109,27 @@ scoped_ptr<bool> available_ptr_; }; + class CONTENT_EXPORT DefaultSessionStartContext { + public: + DefaultSessionStartContext(); + ~DefaultSessionStartContext(); + + // Adds a callback. May invoke the callback immediately if |session| using + // default presentation URL was already started. + void AddCallback(const DefaultSessionMojoCallback& callback); + + // Sets the session info. Maybe invoke callbacks queued with AddCallback(). + void set_session(const PresentationSessionInfo& session); + + private: + // Flush all queued callbacks by invoking them with null + // PresentationSessionInfoPtr. + void Reset(); + + ScopedVector<DefaultSessionMojoCallback> callbacks_; + scoped_ptr<PresentationSessionInfo> session_; + }; + // Context for a StartSession request. class CONTENT_EXPORT StartSessionRequest { public: @@ -146,6 +167,12 @@ SetSameDefaultPresentationUrl); FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest, ClearDefaultPresentationUrl); + FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest, + ListenForDefaultSessionStart); + FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest, + ListenForDefaultSessionStartAfterSet); + FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest, + DefaultSessionStartReset); // |render_frame_host|: The RFH this instance is associated with. // |web_contents|: The WebContents to observe. @@ -197,6 +224,8 @@ // PresentationServiceDelegate::Observer void OnDelegateDestroyed() override; + void OnDefaultPresentationStarted(const PresentationSessionInfo& session) + override; // Finds the callback from |pending_session_cbs_| using |request_session_id|. // If it exists, invoke it with |session| and |error|, then erase it from @@ -256,7 +285,9 @@ ScreenAvailabilityContext* GetOrCreateAvailabilityContext( const std::string& presentation_url); - RenderFrameHost* render_frame_host_; + // Returns true if this object is associated with |render_frame_host|. + bool FrameMatches(content::RenderFrameHost* render_frame_host) const; + PresentationServiceDelegate* delegate_; // Map from presentation URL to its ScreenAvailabilityContext state machine. @@ -277,10 +308,16 @@ int next_request_session_id_; base::hash_map<int, linked_ptr<NewSessionMojoCallback>> pending_session_cbs_; + scoped_ptr<DefaultSessionStartContext> default_session_start_context_; + // RAII binding of |this| to an Presentation interface request. // The binding is removed when binding_ is cleared or goes out of scope. scoped_ptr<mojo::Binding<presentation::PresentationService>> binding_; + // ID of the RenderFrameHost this object is associated with. + int render_process_id_; + int render_frame_id_; + // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<PresentationServiceImpl> weak_factory_;
diff --git a/content/browser/presentation/presentation_service_impl_unittest.cc b/content/browser/presentation/presentation_service_impl_unittest.cc index 1f7f758..2f25256 100644 --- a/content/browser/presentation/presentation_service_impl_unittest.cc +++ b/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -5,6 +5,7 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" +#include "base/test/test_timeouts.h" #include "content/browser/presentation/presentation_service_impl.h" #include "content/public/browser/presentation_service_delegate.h" #include "content/public/browser/presentation_session.h" @@ -23,12 +24,23 @@ namespace content { +namespace { + +bool ArePresentationSessionsEqual( + const presentation::PresentationSessionInfo& expected, + const presentation::PresentationSessionInfo& actual) { + return expected.url == actual.url && expected.id == actual.id; +} +} // namespace + class MockPresentationServiceDelegate : public PresentationServiceDelegate { public: - MOCK_METHOD1(AddObserver, - void(PresentationServiceDelegate::Observer* observer)); - MOCK_METHOD1(RemoveObserver, - void(PresentationServiceDelegate::Observer* observer)); + MOCK_METHOD3(AddObserver, + void(int render_process_id, + int render_frame_id, + PresentationServiceDelegate::Observer* observer)); + MOCK_METHOD2(RemoveObserver, + void(int render_process_id, int render_frame_id)); MOCK_METHOD3(AddScreenAvailabilityListener, bool( int render_process_id, @@ -69,13 +81,15 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness { public: - PresentationServiceImplTest() : callback_count_(0) {} + PresentationServiceImplTest() + : callback_count_(0), default_session_started_count_(0) {} void SetUp() override { RenderViewHostImplTestHarness::SetUp(); auto request = mojo::GetProxy(&service_ptr_); - EXPECT_CALL(mock_delegate_, AddObserver(_)).Times(1); + + EXPECT_CALL(mock_delegate_, AddObserver(_, _, _)).Times(1); service_impl_.reset(new PresentationServiceImpl( contents()->GetMainFrame(), contents(), &mock_delegate_)); service_impl_->Bind(request.Pass()); @@ -84,11 +98,9 @@ void TearDown() override { service_ptr_.reset(); if (service_impl_.get()) { - EXPECT_CALL(mock_delegate_, RemoveObserver(Eq(service_impl_.get()))) - .Times(1); + EXPECT_CALL(mock_delegate_, RemoveObserver(_, _)).Times(1); service_impl_.reset(); } - RenderViewHostImplTestHarness::TearDown(); } @@ -155,8 +167,7 @@ } void ExpectReset() { - EXPECT_CALL(mock_delegate_, Reset(_, _)) - .Times(1); + EXPECT_CALL(mock_delegate_, Reset(_, _)).Times(1); } void ExpectCleanState() { @@ -164,6 +175,7 @@ EXPECT_TRUE(service_impl_->default_presentation_url_.empty()); EXPECT_TRUE(service_impl_->default_presentation_id_.empty()); EXPECT_TRUE(service_impl_->queued_start_session_requests_.empty()); + EXPECT_FALSE(service_impl_->default_session_start_context_.get()); } void ExpectNewSessionMojoCallbackSuccess( @@ -184,11 +196,31 @@ run_loop_quit_closure_.Run(); } + void ExpectDefaultSessionStarted( + const presentation::PresentationSessionInfo& expected_session, + presentation::PresentationSessionInfoPtr actual_session) { + ASSERT_TRUE(!actual_session.is_null()); + EXPECT_TRUE(ArePresentationSessionsEqual( + expected_session, *actual_session)); + ++default_session_started_count_; + if (!run_loop_quit_closure_.is_null()) + run_loop_quit_closure_.Run(); + } + + void ExpectDefaultSessionNull( + presentation::PresentationSessionInfoPtr actual_session) { + EXPECT_TRUE(actual_session.is_null()); + ++default_session_started_count_; + if (!run_loop_quit_closure_.is_null()) + run_loop_quit_closure_.Run(); + } + MockPresentationServiceDelegate mock_delegate_; scoped_ptr<PresentationServiceImpl> service_impl_; mojo::InterfacePtr<presentation::PresentationService> service_ptr_; base::Closure run_loop_quit_closure_; int callback_count_; + int default_session_started_count_; }; TEST_F(PresentationServiceImplTest, ListenForScreenAvailability) { @@ -294,7 +326,7 @@ // Since the frame matched the service, |service_impl_| will be deleted. PresentationServiceImpl* service = service_impl_.release(); - EXPECT_CALL(mock_delegate_, RemoveObserver(Eq(service))).Times(1); + EXPECT_CALL(mock_delegate_, RemoveObserver(_, _)).Times(1); service->RenderFrameDeleted(contents()->GetMainFrame()); } @@ -581,4 +613,59 @@ SaveQuitClosureAndRunLoop(); } +TEST_F(PresentationServiceImplTest, ListenForDefaultSessionStart) { + std::string presentation_url1("http://fooUrl1"); + std::string presentation_id1("presentationId1"); + presentation::PresentationSessionInfo expected_session; + expected_session.url = presentation_url1; + expected_session.id = presentation_id1; + service_ptr_->ListenForDefaultSessionStart( + base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionStarted, + base::Unretained(this), + expected_session)); + RunLoopFor(base::TimeDelta::FromMilliseconds(50)); + service_impl_->OnDefaultPresentationStarted( + content::PresentationSessionInfo(presentation_url1, presentation_id1)); + SaveQuitClosureAndRunLoop(); + EXPECT_EQ(1, default_session_started_count_); +} + +TEST_F(PresentationServiceImplTest, ListenForDefaultSessionStartAfterSet) { + // Note that the callback will only pick up presentation_url2/id2 since + // ListenForDefaultSessionStart wasn't called yet when the DPU was still + // presentation_url1. + std::string presentation_url1("http://fooUrl1"); + std::string presentation_id1("presentationId1"); + std::string presentation_url2("http://fooUrl2"); + std::string presentation_id2("presentationId2"); + service_impl_->OnDefaultPresentationStarted( + content::PresentationSessionInfo(presentation_url1, presentation_id1)); + + presentation::PresentationSessionInfo expected_session; + expected_session.url = presentation_url2; + expected_session.id = presentation_id2; + service_ptr_->ListenForDefaultSessionStart( + base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionStarted, + base::Unretained(this), + expected_session)); + RunLoopFor(base::TimeDelta::FromMilliseconds(50)); + service_impl_->OnDefaultPresentationStarted( + content::PresentationSessionInfo(presentation_url2, presentation_id2)); + SaveQuitClosureAndRunLoop(); + EXPECT_EQ(1, default_session_started_count_); +} + +TEST_F(PresentationServiceImplTest, DefaultSessionStartReset) { + service_ptr_->ListenForDefaultSessionStart( + base::Bind(&PresentationServiceImplTest::ExpectDefaultSessionNull, + base::Unretained(this))); + RunLoopFor(TestTimeouts::tiny_timeout()); + + ExpectReset(); + service_impl_->Reset(); + ExpectCleanState(); + SaveQuitClosureAndRunLoop(); + EXPECT_EQ(1, default_session_started_count_); +} + } // namespace content
diff --git a/content/browser/profiler_controller_impl.cc b/content/browser/profiler_controller_impl.cc index 98fd2c0..7427d15 100644 --- a/content/browser/profiler_controller_impl.cc +++ b/content/browser/profiler_controller_impl.cc
@@ -72,7 +72,8 @@ } void ProfilerControllerImpl::GetProfilerDataFromChildProcesses( - int sequence_number) { + int sequence_number, + int current_profiling_phase) { DCHECK_CURRENTLY_ON(BrowserThread::IO); int pending_processes = 0; @@ -85,8 +86,10 @@ continue; ++pending_processes; - if (!iter.Send(new ChildProcessMsg_GetChildProfilerData(sequence_number))) + if (!iter.Send(new ChildProcessMsg_GetChildProfilerData( + sequence_number, current_profiling_phase))) { --pending_processes; + } } BrowserThread::PostTask( @@ -100,26 +103,66 @@ true)); } -void ProfilerControllerImpl::GetProfilerData(int sequence_number) { +// static +void ProfilerControllerImpl::NotifyChildProcessesOfProfilingPhaseCompletion( + int profiling_phase) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) { + // In some cases, there may be no child process of the given type (for + // example, the GPU process may not exist and there may instead just be a + // GPU thread in the browser process). If that's the case, then the process + // handle will be base::kNullProcessHandle and we shouldn't send it a + // message. + if (iter.GetData().handle == base::kNullProcessHandle) + continue; + + iter.Send(new ChildProcessMsg_ProfilingPhaseCompleted(profiling_phase)); + } +} + +void ProfilerControllerImpl::GetProfilerData(int sequence_number, + int current_profiling_phase) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + // Iterates through renderers in UI thread, and through other child processes + // in IO thread, and send them GetChildProfilerData message. Renderers have to + // be contacted from UI thread, and other processes - from IO thread. int pending_processes = 0; for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); !it.IsAtEnd(); it.Advance()) { ++pending_processes; - if (!it.GetCurrentValue()->Send( - new ChildProcessMsg_GetChildProfilerData(sequence_number))) { + if (!it.GetCurrentValue()->Send(new ChildProcessMsg_GetChildProfilerData( + sequence_number, current_profiling_phase))) { --pending_processes; } } OnPendingProcesses(sequence_number, pending_processes, false); BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, + BrowserThread::IO, FROM_HERE, base::Bind(&ProfilerControllerImpl::GetProfilerDataFromChildProcesses, - base::Unretained(this), - sequence_number)); + base::Unretained(this), sequence_number, + current_profiling_phase)); +} + +void ProfilerControllerImpl::OnProfilingPhaseCompleted(int profiling_phase) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // Iterates through renderers in UI thread, and through other child processes + // in IO thread, and send them OnProfilingPhase message. Renderers have to be + // contacted from UI thread, and other processes - from IO thread. + for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); + !it.IsAtEnd(); it.Advance()) { + it.GetCurrentValue()->Send( + new ChildProcessMsg_ProfilingPhaseCompleted(profiling_phase)); + } + + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&ProfilerControllerImpl:: + NotifyChildProcessesOfProfilingPhaseCompletion, + profiling_phase)); } } // namespace content
diff --git a/content/browser/profiler_controller_impl.h b/content/browser/profiler_controller_impl.h index d62f389..cf2c10c 100644 --- a/content/browser/profiler_controller_impl.h +++ b/content/browser/profiler_controller_impl.h
@@ -44,13 +44,20 @@ // ProfilerController implementation: void Register(ProfilerSubscriber* subscriber) override; void Unregister(const ProfilerSubscriber* subscriber) override; - void GetProfilerData(int sequence_number) override; + void GetProfilerData(int sequence_number, + int current_profiling_phase) override; + void OnProfilingPhaseCompleted(int profiling_phase) override; private: friend struct DefaultSingletonTraits<ProfilerControllerImpl>; // Contact child processes and get their profiler data. - void GetProfilerDataFromChildProcesses(int sequence_number); + void GetProfilerDataFromChildProcesses(int sequence_number, + int current_profiling_phase); + + // Contact child processes and notify them of a profiling phase completion. + static void NotifyChildProcessesOfProfilingPhaseCompletion( + int profiling_phase); ProfilerSubscriber* subscriber_;
diff --git a/content/browser/push_messaging/push_messaging_message_filter.cc b/content/browser/push_messaging/push_messaging_message_filter.cc index 939a761..cd2403e 100644 --- a/content/browser/push_messaging/push_messaging_message_filter.cc +++ b/content/browser/push_messaging/push_messaging_message_filter.cc
@@ -559,6 +559,7 @@ case SERVICE_WORKER_ERROR_STATE: case SERVICE_WORKER_ERROR_TIMEOUT: case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: + case SERVICE_WORKER_ERROR_DISK_CACHE: case SERVICE_WORKER_ERROR_MAX_VALUE: NOTREACHED() << "Got unexpected error code: " << service_worker_status << " " << ServiceWorkerStatusToString(service_worker_status); @@ -734,6 +735,7 @@ case SERVICE_WORKER_ERROR_STATE: case SERVICE_WORKER_ERROR_TIMEOUT: case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: + case SERVICE_WORKER_ERROR_DISK_CACHE: case SERVICE_WORKER_ERROR_MAX_VALUE: NOTREACHED() << "Got unexpected error code: " << service_worker_status << " " << ServiceWorkerStatusToString(service_worker_status);
diff --git a/content/browser/push_messaging/push_messaging_router.cc b/content/browser/push_messaging/push_messaging_router.cc index 76de068a..905db119 100644 --- a/content/browser/push_messaging/push_messaging_router.cc +++ b/content/browser/push_messaging/push_messaging_router.cc
@@ -109,6 +109,7 @@ case SERVICE_WORKER_ERROR_IPC_FAILED: case SERVICE_WORKER_ERROR_TIMEOUT: case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: + case SERVICE_WORKER_ERROR_DISK_CACHE: delivery_status = PUSH_DELIVERY_STATUS_SERVICE_WORKER_ERROR; break; case SERVICE_WORKER_ERROR_EXISTS:
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc index 41c4acb..7f9f4bf 100644 --- a/content/browser/renderer_host/compositor_impl_android.cc +++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -58,7 +58,6 @@ #include "ui/android/window_android.h" #include "ui/gfx/android/device_display_info.h" #include "ui/gfx/frame_time.h" -#include "webkit/common/gpu/context_provider_in_process.h" namespace content { @@ -470,7 +469,6 @@ CreateLayerTreeHost(); ui_resource_provider_.SetLayerTreeHost(host_.get()); } - root_window_->OnVisibilityChanged(visible); } void CompositorImpl::setDeviceScaleFactor(float factor) { @@ -606,7 +604,7 @@ scoped_refptr<ContextProviderCommandBuffer> context_provider( ContextProviderCommandBuffer::Create( CreateGpuProcessViewContext(gpu_channel_host, attrs, surface_id_), - "BrowserCompositor")); + BROWSER_COMPOSITOR_ONSCREEN_CONTEXT)); DCHECK(context_provider.get()); scoped_ptr<cc::OutputSurface> real_output_surface(
diff --git a/content/browser/renderer_host/delegated_frame_evictor.cc b/content/browser/renderer_host/delegated_frame_evictor.cc index 65ae4832..33d6b2c 100644 --- a/content/browser/renderer_host/delegated_frame_evictor.cc +++ b/content/browser/renderer_host/delegated_frame_evictor.cc
@@ -10,13 +10,11 @@ DelegatedFrameEvictor::DelegatedFrameEvictor( DelegatedFrameEvictorClient* client) - : client_(client), has_frame_(false), visible_(false) { -} + : client_(client), has_frame_(false) {} DelegatedFrameEvictor::~DelegatedFrameEvictor() { DiscardedFrame(); } void DelegatedFrameEvictor::SwappedFrame(bool visible) { - visible_ = visible; has_frame_ = true; RendererFrameManager::GetInstance()->AddFrame(this, visible); } @@ -27,14 +25,11 @@ } void DelegatedFrameEvictor::SetVisible(bool visible) { - if (visible_ == visible) - return; - visible_ = visible; if (has_frame_) { if (visible) { - LockFrame(); + RendererFrameManager::GetInstance()->LockFrame(this); } else { - UnlockFrame(); + RendererFrameManager::GetInstance()->UnlockFrame(this); } } }
diff --git a/content/browser/renderer_host/delegated_frame_evictor.h b/content/browser/renderer_host/delegated_frame_evictor.h index 9e9f68a61..796b6c2 100644 --- a/content/browser/renderer_host/delegated_frame_evictor.h +++ b/content/browser/renderer_host/delegated_frame_evictor.h
@@ -35,7 +35,6 @@ DelegatedFrameEvictorClient* client_; bool has_frame_; - bool visible_; DISALLOW_COPY_AND_ASSIGN(DelegatedFrameEvictor); };
diff --git a/content/browser/renderer_host/input/motion_event_android.cc b/content/browser/renderer_host/input/motion_event_android.cc index 3f18f95..5a437f4e 100644 --- a/content/browser/renderer_host/input/motion_event_android.cc +++ b/content/browser/renderer_host/input/motion_event_android.cc
@@ -6,8 +6,9 @@ #include <android/input.h> +#include <cmath> + #include "base/android/jni_android.h" -#include "base/float_util.h" #include "jni/MotionEvent_jni.h" #include "ui/events/event_constants.h" @@ -92,7 +93,7 @@ } float ToValidFloat(float x) { - if (base::IsNaN(x)) + if (std::isnan(x)) return 0.f; // Wildly large orientation values have been observed in the wild after device
diff --git a/content/browser/renderer_host/input/motion_event_android_unittest.cc b/content/browser/renderer_host/input/motion_event_android_unittest.cc index 20b9a52..9a33b31 100644 --- a/content/browser/renderer_host/input/motion_event_android_unittest.cc +++ b/content/browser/renderer_host/input/motion_event_android_unittest.cc
@@ -5,7 +5,6 @@ #include <android/input.h> #include "base/android/jni_android.h" -#include "base/float_util.h" #include "content/browser/renderer_host/input/motion_event_android.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/event_constants.h"
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc index 3569b40b..2ca7f74 100644 --- a/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc +++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
@@ -135,6 +135,12 @@ } } +// Touch to scroll latency that is mostly under 1 second. +#define UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY(name, start, end) \ + UMA_HISTOGRAM_CUSTOM_COUNTS( \ + name, (end.event_time - start.event_time).InMicroseconds(), 1, 1000000, \ + 100) + // Long scroll latency component that is mostly under 200ms. #define UMA_HISTOGRAM_SCROLL_LATENCY_LONG(name, start, end) \ UMA_HISTOGRAM_CUSTOM_COUNTS( \ @@ -150,10 +156,12 @@ 1, 50000, 50) void ComputeScrollLatencyHistograms( - const LatencyInfo::LatencyComponent& gpu_swap_component, + const LatencyInfo::LatencyComponent& gpu_swap_begin_component, + const LatencyInfo::LatencyComponent& gpu_swap_end_component, int64 latency_component_id, const LatencyInfo& latency) { - DCHECK(!gpu_swap_component.event_time.is_null()); + DCHECK(!gpu_swap_begin_component.event_time.is_null()); + DCHECK(!gpu_swap_end_component.event_time.is_null()); LatencyInfo::LatencyComponent first_original_component, original_component; if (latency.FindLatency( ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT, @@ -162,11 +170,14 @@ // first scroll event in a sequence and the original timestamp of that // scroll event's underlying touch event. for (size_t i = 0; i < first_original_component.event_count; i++) { - UMA_HISTOGRAM_CUSTOM_COUNTS( + UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY( + "Event.Latency.TouchToFirstScrollUpdateSwapBegin", + first_original_component, gpu_swap_begin_component); + // TODO(brianderson): Remove this version once we have enough overlapping + // data with the metric above. crbug.com/478845 + UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY( "Event.Latency.TouchToFirstScrollUpdateSwap", - (gpu_swap_component.event_time - first_original_component.event_time) - .InMicroseconds(), - 1, 1000000, 100); + first_original_component, gpu_swap_end_component); } original_component = first_original_component; } else if (!latency.FindLatency( @@ -179,11 +190,14 @@ // created (averaged if there are multiple) to when the scroll gesture // results in final frame swap. for (size_t i = 0; i < original_component.event_count; i++) { - UMA_HISTOGRAM_CUSTOM_COUNTS( - "Event.Latency.TouchToScrollUpdateSwap", - (gpu_swap_component.event_time - original_component.event_time) - .InMicroseconds(), - 1, 1000000, 100); + UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY( + "Event.Latency.TouchToScrollUpdateSwapBegin", original_component, + gpu_swap_begin_component); + // TODO(brianderson): Remove this version once we have enough overlapping + // data with the metric above. crbug.com/478845 + UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY( + "Event.Latency.TouchToScrollUpdateSwap", original_component, + gpu_swap_end_component); } // TODO(miletus): Add validation for making sure the following components @@ -237,17 +251,11 @@ UMA_HISTOGRAM_SCROLL_LATENCY_LONG( "Event.Latency.ScrollUpdate.BrowserNotifiedToBeforeGpuSwap", - browser_received_swap_component, gpu_swap_component); - - LatencyInfo::LatencyComponent gpu_swap_ack_component; - if (!latency.FindLatency( - ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, - &gpu_swap_ack_component)) - return; + browser_received_swap_component, gpu_swap_begin_component); UMA_HISTOGRAM_SCROLL_LATENCY_SHORT("Event.Latency.ScrollUpdate.GpuSwap", - gpu_swap_component, - gpu_swap_ack_component); + gpu_swap_begin_component, + gpu_swap_end_component); } // LatencyComponents generated in the renderer must have component IDs @@ -405,9 +413,16 @@ void RenderWidgetHostLatencyTracker::OnFrameSwapped( const LatencyInfo& latency) { - LatencyInfo::LatencyComponent gpu_swap_component; + LatencyInfo::LatencyComponent gpu_swap_end_component; + if (!latency.FindLatency( + ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, + &gpu_swap_end_component)) { + return; + } + + LatencyInfo::LatencyComponent gpu_swap_begin_component; if (!latency.FindLatency(ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, - &gpu_swap_component)) { + &gpu_swap_begin_component)) { return; } @@ -415,7 +430,7 @@ if (latency.FindLatency(ui::TAB_SHOW_COMPONENT, latency_component_id_, &tab_switch_component)) { base::TimeDelta delta = - gpu_swap_component.event_time - tab_switch_component.event_time; + gpu_swap_end_component.event_time - tab_switch_component.event_time; for (size_t i = 0; i < tab_switch_component.event_count; i++) { UMA_HISTOGRAM_TIMES("MPArch.RWH_TabSwitchPaintDuration", delta); } @@ -426,7 +441,8 @@ return; } - ComputeScrollLatencyHistograms(gpu_swap_component, latency_component_id_, + ComputeScrollLatencyHistograms(gpu_swap_begin_component, + gpu_swap_end_component, latency_component_id_, latency); LatencyInfo::LatencyComponent browser_swap_component; @@ -434,7 +450,7 @@ ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0, &browser_swap_component)) { base::TimeDelta delta = - gpu_swap_component.event_time - browser_swap_component.event_time; + gpu_swap_begin_component.event_time - browser_swap_component.event_time; browser_composite_latency_history_.InsertSample(delta); } }
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.h b/content/browser/renderer_host/legacy_render_widget_host_win.h index e3006a1..a1e952d 100644 --- a/content/browser/renderer_host/legacy_render_widget_host_win.h +++ b/content/browser/renderer_host/legacy_render_widget_host_win.h
@@ -107,11 +107,11 @@ } protected: - virtual void OnFinalMessage(HWND hwnd) override; + void OnFinalMessage(HWND hwnd) override; private: LegacyRenderWidgetHostHWND(HWND parent); - ~LegacyRenderWidgetHostHWND(); + ~LegacyRenderWidgetHostHWND() override; bool Init();
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc index 9b3d22f..848f78c4 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -115,12 +115,12 @@ StreamDeviceInfoArray enumerated_devices_; private: - virtual ~MockMediaStreamDispatcherHost() {} + ~MockMediaStreamDispatcherHost() override {} // This method is used to dispatch IPC messages to the renderer. We intercept // these messages here and dispatch to our mock methods to verify the // conversation between this object and the renderer. - virtual bool Send(IPC::Message* message) override { + bool Send(IPC::Message* message) override { CHECK(message); current_ipc_ = message;
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc index ab3814ae..147aefa 100644 --- a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" #include "cc/test/test_context_provider.h" #include "cc/test/test_web_graphics_context_3d.h" #include "content/browser/compositor/buffer_queue.h" @@ -156,6 +157,7 @@ new Buffer(pool_, buffer_handle.Pass(), buffer_id)); } + base::MessageLoop loop_; int expected_dropped_id_; scoped_refptr<VideoCaptureBufferPool> pool_;
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc index ad9ecd4..24f20737 100644 --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -43,7 +43,7 @@ explicit MockVideoCaptureControllerEventHandler( VideoCaptureController* controller) : controller_(controller) {} - virtual ~MockVideoCaptureControllerEventHandler() {} + ~MockVideoCaptureControllerEventHandler() override {} // These mock methods are delegated to by our fake implementation of // VideoCaptureControllerEventHandler, to be used in EXPECT_CALL(). @@ -54,19 +54,18 @@ MOCK_METHOD1(DoEnded, void(VideoCaptureControllerID)); MOCK_METHOD1(DoError, void(VideoCaptureControllerID)); - virtual void OnError(VideoCaptureControllerID id) override { + void OnError(VideoCaptureControllerID id) override { DoError(id); } - virtual void OnBufferCreated(VideoCaptureControllerID id, - base::SharedMemoryHandle handle, - int length, int buffer_id) override { + void OnBufferCreated(VideoCaptureControllerID id, + base::SharedMemoryHandle handle, + int length, int buffer_id) override { DoBufferCreated(id); } - virtual void OnBufferDestroyed(VideoCaptureControllerID id, - int buffer_id) override { + void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override { DoBufferDestroyed(id); } - virtual void OnBufferReady( + void OnBufferReady( VideoCaptureControllerID id, int buffer_id, const gfx::Size& coded_size, @@ -83,7 +82,7 @@ buffer_id, 0)); } - virtual void OnMailboxBufferReady( + void OnMailboxBufferReady( VideoCaptureControllerID id, int buffer_id, const gpu::MailboxHolder& mailbox_holder, @@ -100,7 +99,7 @@ buffer_id, mailbox_holder.sync_point)); } - virtual void OnEnded(VideoCaptureControllerID id) override { + void OnEnded(VideoCaptureControllerID id) override { DoEnded(id); // OnEnded() must respond by (eventually) unregistering the client. base::MessageLoop::current()->PostTask(FROM_HERE,
diff --git a/content/browser/renderer_host/media/video_capture_device_client.cc b/content/browser/renderer_host/media/video_capture_device_client.cc index 7310963..3fdbca2 100644 --- a/content/browser/renderer_host/media/video_capture_device_client.cc +++ b/content/browser/renderer_host/media/video_capture_device_client.cc
@@ -90,7 +90,7 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); #if !defined(OS_ANDROID) bottom_half.Run(ContextProviderCommandBuffer::Create( - CreateOffscreenCommandBufferContext(), "Offscreen-CaptureThread")); + CreateOffscreenCommandBufferContext(), OFFSCREEN_VIDEO_CAPTURE_CONTEXT)); return; #endif }
diff --git a/content/browser/renderer_host/media/video_capture_host_unittest.cc b/content/browser/renderer_host/media/video_capture_host_unittest.cc index dd9ba73..763ed1f 100644 --- a/content/browser/renderer_host/media/video_capture_host_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_host_unittest.cc
@@ -180,7 +180,7 @@ } private: - virtual ~MockVideoCaptureHost() { + ~MockVideoCaptureHost() override { STLDeleteContainerPairSecondPointers(filled_dib_.begin(), filled_dib_.end()); } @@ -188,7 +188,7 @@ // This method is used to dispatch IPC messages to the renderer. We intercept // these messages here and dispatch to our mock methods to verify the // conversation between this object and the renderer. - virtual bool Send(IPC::Message* message) override { + bool Send(IPC::Message* message) override { CHECK(message); // In this method we dispatch the messages to the according handlers as if @@ -286,7 +286,7 @@ message_loop_(base::MessageLoopProxy::current()), opened_session_id_(kInvalidMediaCaptureSessionId) {} - virtual void SetUp() override { + void SetUp() override { SetBrowserClientForTesting(&browser_client_); #if defined(OS_CHROMEOS) @@ -309,7 +309,7 @@ OpenSession(); } - virtual void TearDown() override { + void TearDown() override { // Verifies and removes the expectations on host_ and // returns true iff successful. Mock::VerifyAndClearExpectations(host_.get());
diff --git a/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/content/browser/renderer_host/media/video_capture_manager_unittest.cc index a52ff6c7..a8e45add 100644 --- a/content/browser/renderer_host/media/video_capture_manager_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -46,26 +46,25 @@ public: MOCK_METHOD1(OnError, void(VideoCaptureControllerID id)); - virtual void OnBufferCreated(VideoCaptureControllerID id, - base::SharedMemoryHandle handle, - int length, int buffer_id) override {} - virtual void OnBufferDestroyed(VideoCaptureControllerID id, - int buffer_id) override {} - virtual void OnBufferReady( + void OnBufferCreated(VideoCaptureControllerID id, + base::SharedMemoryHandle handle, + int length, int buffer_id) override {} + void OnBufferDestroyed(VideoCaptureControllerID id, int buffer_id) override {} + void OnBufferReady( VideoCaptureControllerID id, int buffer_id, const gfx::Size& coded_size, const gfx::Rect& visible_rect, const base::TimeTicks& timestamp, scoped_ptr<base::DictionaryValue> metadata) override {} - virtual void OnMailboxBufferReady( + void OnMailboxBufferReady( VideoCaptureControllerID id, int buffer_id, const gpu::MailboxHolder& mailbox_holder, const gfx::Size& packed_frame_size, const base::TimeTicks& timestamp, scoped_ptr<base::DictionaryValue> metadata) override {} - virtual void OnEnded(VideoCaptureControllerID id) override {} + void OnEnded(VideoCaptureControllerID id) override {} void OnGotControllerCallback(VideoCaptureControllerID) {} };
diff --git a/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc b/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc index 6eb36a1..633a326 100644 --- a/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc +++ b/content/browser/renderer_host/pepper/pepper_truetype_font_win.cc
@@ -26,16 +26,15 @@ PepperTrueTypeFontWin(); // PepperTrueTypeFont implementation. - virtual int32_t Initialize( - ppapi::proxy::SerializedTrueTypeFontDesc* desc) override; - virtual int32_t GetTableTags(std::vector<uint32_t>* tags) override; - virtual int32_t GetTable(uint32_t table_tag, - int32_t offset, - int32_t max_data_length, - std::string* data) override; + int32_t Initialize(ppapi::proxy::SerializedTrueTypeFontDesc* desc) override; + int32_t GetTableTags(std::vector<uint32_t>* tags) override; + int32_t GetTable(uint32_t table_tag, + int32_t offset, + int32_t max_data_length, + std::string* data) override; private: - virtual ~PepperTrueTypeFontWin(); + ~PepperTrueTypeFontWin() override; DWORD GetFontData(HDC hdc, DWORD table,
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc index e63e8107..126d933c 100644 --- a/content/browser/renderer_host/render_process_host_browsertest.cc +++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -204,10 +204,10 @@ public: Win32KLockdownRendererProcessHostTest() {} - virtual ~Win32KLockdownRendererProcessHostTest() {} + ~Win32KLockdownRendererProcessHostTest() override {} protected: - virtual void SetUp() override { + void SetUp() override { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitch(switches::kEnableWin32kRendererLockDown); RenderProcessHostTest::SetUp();
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 467adf90..4652840 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -1325,6 +1325,7 @@ switches::kStatsCollectionController, switches::kTestType, switches::kTouchEvents, + switches::kTouchTextSelectionStrategy, switches::kTraceToConsole, // This flag needs to be propagated to the renderer process for // --in-process-webgl.
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 325f9645..b0ddbde 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -1419,12 +1419,6 @@ } } -void RenderViewHostImpl::AttachToFrameTree() { - FrameTree* frame_tree = delegate_->GetFrameTree(); - - frame_tree->ResetForMainFrameSwap(); -} - void RenderViewHostImpl::SelectWordAroundCaret() { Send(new ViewMsg_SelectWordAroundCaret(GetRoutingID())); }
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index ad98b92..2b031ff7 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -295,13 +295,6 @@ size_t start_offset, size_t end_offset); - // Update the FrameTree to use this RenderViewHost's main frame - // RenderFrameHost. Called when the RenderViewHost is committed. - // - // TODO(ajwong): Remove once RenderViewHost no longer owns the main frame - // RenderFrameHost. - void AttachToFrameTree(); - // Increases the refcounting on this RVH. This is done by the FrameTree on // creation of a RenderFrameHost. void increment_ref_count() { ++frames_ref_count_; }
diff --git a/content/browser/renderer_host/render_view_host_unittest.cc b/content/browser/renderer_host/render_view_host_unittest.cc index 39930dc9..d3bb34a8 100644 --- a/content/browser/renderer_host/render_view_host_unittest.cc +++ b/content/browser/renderer_host/render_view_host_unittest.cc
@@ -64,7 +64,8 @@ // All about URLs reported by the renderer should get rewritten to about:blank. // See RenderViewHost::OnNavigate for a discussion. TEST_F(RenderViewHostTest, FilterAbout) { - main_test_rfh()->NavigateAndCommitRendererInitiated(1, GURL("about:cache")); + main_test_rfh()->NavigateAndCommitRendererInitiated( + 1, true, GURL("about:cache")); ASSERT_TRUE(controller().GetVisibleEntry()); EXPECT_EQ(GURL(url::kAboutBlankURL), controller().GetVisibleEntry()->GetURL()); @@ -234,15 +235,14 @@ EXPECT_EQ(0, process()->bad_msg_count()); main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false); main_test_rfh()->PrepareForCommit(); - contents()->GetMainFrame()->SendNavigateWithFile(1, url, file_path); + contents()->GetMainFrame()->SendNavigateWithFile(1, 1, true, url, file_path); EXPECT_EQ(1, process()->bad_msg_count()); ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile( process()->GetID(), file_path); main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false); main_test_rfh()->PrepareForCommit(); - contents()->GetMainFrame()->SendNavigateWithFile(process()->GetID(), url, - file_path); + contents()->GetMainFrame()->SendNavigateWithFile(2, 2, true, url, file_path); EXPECT_EQ(1, process()->bad_msg_count()); }
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 f687931..cbd5f87 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -129,7 +129,7 @@ void Initialize(); // WebGraphicsContextLostCallback implementation. - virtual void onContextLost() override; + void onContextLost() override; GLHelper* GetGLHelper() { return gl_helper_.get(); } bool IsLost() { return !context_.get() || context_->isContextLost(); } @@ -328,22 +328,6 @@ } // anonymous namespace -ReadbackRequest::ReadbackRequest(float scale, - SkColorType color_type, - gfx::Rect src_subrect, - ReadbackRequestCallback& result_callback) - : scale_(scale), - color_type_(color_type), - src_subrect_(src_subrect), - result_callback_(result_callback) { -} - -ReadbackRequest::ReadbackRequest() { -} - -ReadbackRequest::~ReadbackRequest() { -} - RenderWidgetHostViewAndroid::LastFrameInfo::LastFrameInfo( uint32 output_id, scoped_ptr<cc::CompositorFrame> output_frame) @@ -387,7 +371,6 @@ RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() { SetContentViewCore(NULL); DCHECK(ack_callbacks_.empty()); - DCHECK(readbacks_waiting_for_frame_.empty()); if (resource_collection_.get()) resource_collection_->SetClient(NULL); DCHECK(!surface_factory_); @@ -448,32 +431,15 @@ SetSize(rect.size()); } -void RenderWidgetHostViewAndroid::AbortPendingReadbackRequests() { - while (!readbacks_waiting_for_frame_.empty()) { - ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front(); - readback_request.GetResultCallback().Run(SkBitmap(), READBACK_FAILED); - readbacks_waiting_for_frame_.pop(); - } -} - void RenderWidgetHostViewAndroid::GetScaledContentBitmap( float scale, SkColorType color_type, gfx::Rect src_subrect, ReadbackRequestCallback& result_callback) { - if (!host_ || host_->is_hidden()) { + if (!host_ || host_->is_hidden() || !IsSurfaceAvailableForCopy()) { result_callback.Run(SkBitmap(), READBACK_NOT_SUPPORTED); return; } - if (!IsSurfaceAvailableForCopy()) { - // The view is visible, probably the frame has not yet arrived. - // Just add the ReadbackRequest to queue and wait for frame arrival - // to get this request processed. - readbacks_waiting_for_frame_.push( - ReadbackRequest(scale, color_type, src_subrect, result_callback)); - return; - } - gfx::Size bounds = layer_->bounds(); if (src_subrect.IsEmpty()) src_subrect = gfx::Rect(bounds); @@ -583,7 +549,23 @@ return; is_showing_ = true; - ShowInternal(); + if (layer_.get()) + layer_->SetHideLayerAndSubtree(false); + + if (overscroll_controller_) + overscroll_controller_->Enable(); + + frame_evictor_->SetVisible(true); + + if (!host_ || !host_->is_hidden()) + return; + + host_->WasShown(ui::LatencyInfo()); + + if (content_view_core_) { + StartObservingRootWindow(); + RequestVSyncUpdate(BEGIN_FRAME); + } } void RenderWidgetHostViewAndroid::Hide() { @@ -591,10 +573,24 @@ return; is_showing_ = false; + if (layer_.get() && locks_on_frame_count_ == 0) + layer_->SetHideLayerAndSubtree(true); - bool hide_frontbuffer = true; - bool stop_observing_root_window = true; - HideInternal(hide_frontbuffer, stop_observing_root_window); + if (overscroll_controller_) + overscroll_controller_->Disable(); + + frame_evictor_->SetVisible(false); + + RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED); + + if (!host_ || host_->is_hidden()) + return; + + // Inform the renderer that we are being hidden so it can reduce its resource + // utilization. + host_->WasHidden(); + + StopObservingRootWindow(); } bool RenderWidgetHostViewAndroid::IsShowing() { @@ -726,15 +722,6 @@ void RenderWidgetHostViewAndroid::OnTextInputStateChanged( const ViewHostMsg_TextInputState_Params& params) { - if (selection_controller_) { - // This call is semi-redundant with that in |OnFocusedNodeChanged|. The - // latter is guaranteed to be called before |OnSelectionBoundsChanged|, - // while this call is present to ensure consistency with IME after - // navigation and tab focus changes - const bool is_editable_node = params.type != ui::TEXT_INPUT_TYPE_NONE; - selection_controller_->OnSelectionEditable(is_editable_node); - } - // If the change is not originated from IME (e.g. Javascript, autofill), // send back the renderer an acknowledgement, regardless of how we exit from // this method. @@ -859,8 +846,6 @@ void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) { ime_adapter_android_.FocusedNodeChanged(is_editable_node); - if (selection_controller_) - selection_controller_->OnSelectionEditable(is_editable_node); } void RenderWidgetHostViewAndroid::RenderProcessGone( @@ -895,9 +880,6 @@ const gfx::Range& range) { RenderWidgetHostViewBase::SelectionChanged(text, offset, range); - if (selection_controller_) - selection_controller_->OnSelectionEmpty(text.empty()); - if (!content_view_core_) return; if (range.is_empty()) { @@ -1068,9 +1050,6 @@ surface_id_ = cc::SurfaceId(); } layer_ = NULL; - // This gets called when ever any eviction, loosing resources, swapping - // problems are encountered and so we abort any pending readbacks here. - AbortPendingReadbackRequests(); } void RenderWidgetHostViewAndroid::CheckOutputSurfaceChanged( @@ -1226,18 +1205,6 @@ // As the metadata update may trigger view invalidation, always call it after // any potential compositor scheduling. OnFrameMetadataUpdated(frame->metadata); - // Check if we have any pending readbacks, see if we have a frame available - // and process them here. - if (!readbacks_waiting_for_frame_.empty()) { - while (!readbacks_waiting_for_frame_.empty()) { - ReadbackRequest& readback_request = readbacks_waiting_for_frame_.front(); - GetScaledContentBitmap(readback_request.GetScale(), - readback_request.GetColorFormat(), - readback_request.GetCaptureRect(), - readback_request.GetResultCallback()); - readbacks_waiting_for_frame_.pop(); - } - } } void RenderWidgetHostViewAndroid::OnSwapCompositorFrame( @@ -1407,9 +1374,13 @@ overscroll_controller_->OnFrameMetadataUpdated(frame_metadata); if (selection_controller_) { + selection_controller_->OnSelectionEditable( + frame_metadata.selection.is_editable); + selection_controller_->OnSelectionEmpty( + frame_metadata.selection.is_empty_text_form_control); selection_controller_->OnSelectionBoundsChanged( - ConvertSelectionBound(frame_metadata.selection_start), - ConvertSelectionBound(frame_metadata.selection_end)); + ConvertSelectionBound(frame_metadata.selection.start), + ConvertSelectionBound(frame_metadata.selection.end)); } // All offsets and sizes are in CSS pixels. @@ -1440,57 +1411,6 @@ accelerated_surface_route_id_ = route_id; } -void RenderWidgetHostViewAndroid::ShowInternal() { - DCHECK(is_showing_); - if (!host_ || !host_->is_hidden()) - return; - - if (layer_.get()) - layer_->SetHideLayerAndSubtree(false); - - frame_evictor_->SetVisible(true); - - if (overscroll_controller_) - overscroll_controller_->Enable(); - - host_->WasShown(ui::LatencyInfo()); - - if (content_view_core_) { - StartObservingRootWindow(); - RequestVSyncUpdate(BEGIN_FRAME); - } -} - -void RenderWidgetHostViewAndroid::HideInternal( - bool hide_frontbuffer, - bool stop_observing_root_window) { - if (hide_frontbuffer) { - if (layer_.get() && locks_on_frame_count_ == 0) - layer_->SetHideLayerAndSubtree(true); - - frame_evictor_->SetVisible(false); - } - - if (stop_observing_root_window) - StopObservingRootWindow(); - - if (!host_ || host_->is_hidden()) - return; - - if (overscroll_controller_) - overscroll_controller_->Disable(); - - // We don't know if we will ever get a frame if we are hiding the renderer, so - // we need to cancel all requests - AbortPendingReadbackRequests(); - - RunAckCallbacks(cc::SurfaceDrawStatus::DRAW_SKIPPED); - - // Inform the renderer that we are being hidden so it can reduce its resource - // utilization. - host_->WasHidden(); -} - void RenderWidgetHostViewAndroid::AttachLayers() { if (!content_view_core_) return; @@ -1518,12 +1438,6 @@ void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32 requests) { bool should_request_vsync = !outstanding_vsync_requests_ && requests; outstanding_vsync_requests_ |= requests; - - // If the host has been hidden, defer vsync requests until it is shown - // again via |Show()|. - if (!host_ || host_->is_hidden()) - return; - // Note that if we're not currently observing the root window, outstanding // vsync requests will be pushed if/when we resume observing in // |StartObservingRootWindow()|. @@ -1533,7 +1447,6 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() { DCHECK(content_view_core_); - DCHECK(is_showing_); if (observing_root_window_) return; @@ -1602,9 +1515,6 @@ if (layer_.get()) DestroyDelegatedContent(); frame_evictor_->DiscardedFrame(); - // We are evicting the delegated frame, - // so there should be no pending readback requests - DCHECK(readbacks_waiting_for_frame_.empty()); } bool RenderWidgetHostViewAndroid::HasAcceleratedSurface( @@ -1850,8 +1760,7 @@ if (!content_view_core_) return; - if (is_showing_) - StartObservingRootWindow(); + StartObservingRootWindow(); if (resize) WasResized(); @@ -1892,17 +1801,6 @@ RunAckCallbacks(cc::SurfaceDrawStatus::DRAWN); } -void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) { - DCHECK(is_showing_); - if (visible) { - ShowInternal(); - } else { - bool hide_frontbuffer = true; - bool stop_observing_root_window = false; - HideInternal(hide_frontbuffer, stop_observing_root_window); - } -} - void RenderWidgetHostViewAndroid::OnAttachCompositor() { DCHECK(content_view_core_); if (!overscroll_controller_) @@ -1919,7 +1817,7 @@ void RenderWidgetHostViewAndroid::OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period) { TRACE_EVENT0("cc,benchmark", "RenderWidgetHostViewAndroid::OnVSync"); - if (!host_ || host_->is_hidden()) + if (!host_) return; if (outstanding_vsync_requests_ & FLUSH_INPUT) { @@ -1945,38 +1843,22 @@ SetNeedsAnimate(); } -void RenderWidgetHostViewAndroid::OnActivityPaused() { - TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityPaused"); - DCHECK(is_showing_); - bool hide_frontbuffer = false; - bool stop_observing_root_window = false; - HideInternal(hide_frontbuffer, stop_observing_root_window); -} - -void RenderWidgetHostViewAndroid::OnActivityResumed() { - TRACE_EVENT0("browser", "RenderWidgetHostViewAndroid::OnActivityResumed"); - DCHECK(is_showing_); - ShowInternal(); -} - void RenderWidgetHostViewAndroid::OnLostResources() { ReleaseLocksOnSurface(); if (layer_.get()) DestroyDelegatedContent(); DCHECK(ack_callbacks_.empty()); - // We should not loose a frame if we have readback requests pending. - DCHECK(readbacks_waiting_for_frame_.empty()); } // static -void -RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResultForDelegatedReadback( - const gfx::Size& dst_size_in_pixel, - const SkColorType color_type, - const base::TimeTicks& start_time, - scoped_refptr<cc::Layer> readback_layer, - ReadbackRequestCallback& callback, - scoped_ptr<cc::CopyOutputResult> result) { +void RenderWidgetHostViewAndroid:: + PrepareTextureCopyOutputResultForDelegatedReadback( + const gfx::Size& dst_size_in_pixel, + SkColorType color_type, + const base::TimeTicks& start_time, + scoped_refptr<cc::Layer> readback_layer, + ReadbackRequestCallback& callback, + scoped_ptr<cc::CopyOutputResult> result) { readback_layer->RemoveFromParent(); PrepareTextureCopyOutputResult( dst_size_in_pixel, color_type, start_time, callback, result.Pass()); @@ -1985,7 +1867,7 @@ // static void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult( const gfx::Size& dst_size_in_pixel, - const SkColorType color_type, + SkColorType color_type, const base::TimeTicks& start_time, ReadbackRequestCallback& callback, scoped_ptr<cc::CopyOutputResult> result) { @@ -2003,6 +1885,11 @@ else output_size_in_pixel = dst_size_in_pixel; + GLHelper* gl_helper = GetPostReadbackGLHelper(); + if (!gl_helper) + return; + if (!gl_helper->IsReadbackConfigSupported(color_type)) + color_type = kRGBA_8888_SkColorType; scoped_ptr<SkBitmap> bitmap(new SkBitmap); if (!bitmap->tryAllocPixels(SkImageInfo::Make(output_size_in_pixel.width(), output_size_in_pixel.height(), @@ -2011,9 +1898,6 @@ return; } - GLHelper* gl_helper = GetPostReadbackGLHelper(); - if (!gl_helper || !gl_helper->IsReadbackConfigSupported(color_type)) - return; scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock( new SkAutoLockPixels(*bitmap)); @@ -2045,21 +1929,6 @@ GLHelper::SCALER_QUALITY_GOOD); } -SkColorType RenderWidgetHostViewAndroid::PreferredReadbackFormat() { - // Define the criteria here. If say the 16 texture readback is - // supported we should go with that (this degrades quality) - // or stick back to the default format. - if (base::SysInfo::IsLowEndDevice()) { - // TODO(sievers): Cannot use GLHelper here. Instead remove this API - // and have CopyFromCompositingSurface() fall back to RGB8 if 565 was - // requested but is not supported. - GLHelper* gl_helper = GetPostReadbackGLHelper(); - if (gl_helper && gl_helper->IsReadbackConfigSupported(kRGB_565_SkColorType)) - return kRGB_565_SkColorType; - } - return kN32_SkColorType; -} - void RenderWidgetHostViewAndroid::OnStylusSelectBegin(float x0, float y0, float x1,
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index def6e915..462cabde 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -60,26 +60,6 @@ struct DidOverscrollParams; struct NativeWebKeyboardEvent; -class ReadbackRequest { - public: - explicit ReadbackRequest(float scale, - SkColorType color_type, - gfx::Rect src_subrect, - ReadbackRequestCallback& result_callback); - ~ReadbackRequest(); - float GetScale() { return scale_; } - SkColorType GetColorFormat() { return color_type_; } - const gfx::Rect GetCaptureRect() { return src_subrect_; } - ReadbackRequestCallback& GetResultCallback() { return result_callback_; } - - private: - ReadbackRequest(); - float scale_; - SkColorType color_type_; - gfx::Rect src_subrect_; - ReadbackRequestCallback result_callback_; -}; - // ----------------------------------------------------------------------------- // See comments in render_widget_host_view.h about this class and its members. // ----------------------------------------------------------------------------- @@ -193,20 +173,15 @@ // ui::WindowAndroidObserver implementation. void OnCompositingDidCommit() override; - void OnRootWindowVisibilityChanged(bool visible) override; void OnAttachCompositor() override; void OnDetachCompositor() override; void OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period) override; void OnAnimate(base::TimeTicks begin_frame_time) override; - void OnActivityPaused() override; - void OnActivityResumed() override; // DelegatedFrameEvictor implementation void EvictDelegatedFrame() override; - SkColorType PreferredReadbackFormat() override; - // StylusTextSelectorClient implementation. void OnStylusSelectBegin(float x0, float y0, float x1, float y1) override; void OnStylusSelectUpdate(float x, float y) override; @@ -292,8 +267,6 @@ const cc::CompositorFrameMetadata& frame_metadata); void ComputeContentsSize(const cc::CompositorFrameMetadata& frame_metadata); - void ShowInternal(); - void HideInternal(bool hide_frontbuffer, bool stop_observing_root_window); void AttachLayers(); void RemoveLayers(); @@ -301,13 +274,13 @@ // of the copy. static void PrepareTextureCopyOutputResult( const gfx::Size& dst_size_in_pixel, - const SkColorType color_type, + SkColorType color_type, const base::TimeTicks& start_time, ReadbackRequestCallback& callback, scoped_ptr<cc::CopyOutputResult> result); static void PrepareTextureCopyOutputResultForDelegatedReadback( const gfx::Size& dst_size_in_pixel, - const SkColorType color_type, + SkColorType color_type, const base::TimeTicks& start_time, scoped_refptr<cc::Layer> readback_layer, ReadbackRequestCallback& callback, @@ -344,9 +317,6 @@ void SendBeginFrame(base::TimeTicks frame_time, base::TimeDelta vsync_period); bool Animate(base::TimeTicks frame_time); - // Handles all unprocessed and pending readback requests. - void AbortPendingReadbackRequests(); - // The model object. RenderWidgetHostImpl* host_; @@ -425,9 +395,6 @@ TextSurroundingSelectionCallback text_surrounding_selection_callback_; - // List of readbackrequests waiting for arrival of a valid frame. - std::queue<ReadbackRequest> readbacks_waiting_for_frame_; - // The last scroll offset of the view. gfx::Vector2dF last_scroll_offset_;
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index d9e1201..69fe6612 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -226,9 +226,9 @@ void OnDidNavigateMainFrameToNewPage() override; #if defined(OS_WIN) - virtual void SetParentNativeViewAccessible( + void SetParentNativeViewAccessible( gfx::NativeViewAccessible accessible_parent) override; - virtual gfx::NativeViewId GetParentForWindowlessPlugin() const override; + gfx::NativeViewId GetParentForWindowlessPlugin() const override; #endif // Overridden from ui::TextInputClient:
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index 0044aa4..62d3b62c 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -70,7 +70,7 @@ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents()); wc->GetFrameTree()->root()->navigator()->RequestOpenURL( wc->GetFrameTree()->root()->current_frame_host(), extension_url, nullptr, - Referrer(), ui::PAGE_TRANSITION_LINK, CURRENT_TAB, false, true); + Referrer(), CURRENT_TAB, false, true); // Since the navigation above requires a cross-process swap, there will be a // pending RenderViewHost. Ensure it exists and is in a different process
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index db72622..7d20899 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -275,6 +275,29 @@ pattern, base::Bind(&StartActiveWorkerOnIO, callback)); } +void ServiceWorkerContextWrapper::SimulateSkipWaiting(int64_t version_id) { + if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&ServiceWorkerContextWrapper::SimulateSkipWaiting, this, + version_id)); + return; + } + if (!context_core_.get()) { + LOG(ERROR) << "ServiceWorkerContextCore is no longer alive."; + return; + } + ServiceWorkerVersion* version = GetLiveVersion(version_id); + if (!version || version->skip_waiting()) + return; + ServiceWorkerRegistration* registration = + GetLiveRegistration(version->registration_id()); + if (!registration || version != registration->waiting_version()) + return; + version->set_skip_waiting(true); + registration->ActivateWaitingVersionWhenReady(); +} + static void DidFindRegistrationForDocument( const net::CompletionCallback& callback, ServiceWorkerStatusCode status,
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index eca4a36..6c3befa 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -124,6 +124,7 @@ void StartServiceWorker(const GURL& pattern, const StatusCallback& callback); void UpdateRegistration(const GURL& pattern); + void SimulateSkipWaiting(int64_t version_id); void AddObserver(ServiceWorkerContextObserver* observer); void RemoveObserver(ServiceWorkerContextObserver* observer);
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc index 5e75c4e..94bb891d 100644 --- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc +++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -103,7 +103,7 @@ // Store an activated worker. version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - registration_->SetActiveVersion(version_.get()); + registration_->SetActiveVersion(version_); context()->storage()->StoreRegistration( registration_.get(), version_.get(), @@ -146,7 +146,7 @@ TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) { // Store a registration that is installed but not activated yet. version_->SetStatus(ServiceWorkerVersion::INSTALLED); - registration_->SetWaitingVersion(version_.get()); + registration_->SetWaitingVersion(version_); context()->storage()->StoreRegistration( registration_.get(), version_.get(), @@ -195,7 +195,7 @@ // Store a registration so the call to FindRegistrationForDocument will read // from the database. version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - registration_->SetActiveVersion(version_.get()); + registration_->SetActiveVersion(version_); context()->storage()->StoreRegistration( registration_.get(), version_.get(),
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc index 3340f87..977df98 100644 --- a/content/browser/service_worker/service_worker_dispatcher_host.cc +++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -22,6 +22,7 @@ #include "content/common/service_worker/service_worker_types.h" #include "content/public/browser/content_browser_client.h" #include "content/public/common/content_client.h" +#include "content/public/common/origin_util.h" #include "ipc/ipc_message_macros.h" #include "net/base/net_util.h" #include "third_party/WebKit/public/platform/WebServiceWorkerError.h" @@ -50,12 +51,8 @@ url_a.GetOrigin() == url_c.GetOrigin(); } -// TODO(dominicc): When crbug.com/362214 is fixed use that to be -// consistent with Blink's -// SecurityOrigin::canAccessFeatureRequiringSecureOrigin. bool OriginCanAccessServiceWorkers(const GURL& url) { - return url.SchemeIsHTTPOrHTTPS() && - (url.SchemeIsSecure() || net::IsLocalhost(url.host())); + return url.SchemeIsHTTPOrHTTPS() && IsOriginSecure(url); } bool CanRegisterServiceWorker(const GURL& document_url,
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc index 2c936f2..9e1b187 100644 --- a/content/browser/service_worker/service_worker_job_unittest.cc +++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -648,7 +648,7 @@ ASSERT_EQ(SERVICE_WORKER_OK, status); version->SetStatus(ServiceWorkerVersion::INSTALLED); - registration->SetWaitingVersion(version.get()); + registration->SetWaitingVersion(version); EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status()); EXPECT_EQ(ServiceWorkerVersion::INSTALLED, version->status()); @@ -1030,7 +1030,7 @@ GURL("http://www.example.com/new_worker.js"), 2L /* dummy version id */, helper_->context()->AsWeakPtr()); - registration->SetWaitingVersion(version.get()); + registration->SetWaitingVersion(version); base::RunLoop().RunUntilIdle();
diff --git a/content/browser/service_worker/service_worker_metrics.cc b/content/browser/service_worker/service_worker_metrics.cc index 69f0d858..dc3c157 100644 --- a/content/browser/service_worker/service_worker_metrics.cc +++ b/content/browser/service_worker/service_worker_metrics.cc
@@ -95,4 +95,16 @@ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartNewWorker.Time", time); } +void ServiceWorkerMetrics::RecordActivateEventStatus( + ServiceWorkerStatusCode status) { + UMA_HISTOGRAM_ENUMERATION("ServiceWorker.ActivateEventStatus", status, + SERVICE_WORKER_ERROR_MAX_VALUE); +} + +void ServiceWorkerMetrics::RecordInstallEventStatus( + ServiceWorkerStatusCode status) { + UMA_HISTOGRAM_ENUMERATION("ServiceWorker.InstallEventStatus", status, + SERVICE_WORKER_ERROR_MAX_VALUE); +} + } // namespace content
diff --git a/content/browser/service_worker/service_worker_metrics.h b/content/browser/service_worker/service_worker_metrics.h index 705deb7..7b477af 100644 --- a/content/browser/service_worker/service_worker_metrics.h +++ b/content/browser/service_worker/service_worker_metrics.h
@@ -62,6 +62,9 @@ static void RecordStartWorkerTime(const base::TimeDelta& time, bool is_installed); + static void RecordActivateEventStatus(ServiceWorkerStatusCode status); + static void RecordInstallEventStatus(ServiceWorkerStatusCode status); + private: DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceWorkerMetrics); };
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 06816617..094bd73 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
@@ -151,7 +151,7 @@ DCHECK_LT(result, 0); ServiceWorkerMetrics::CountReadResponseResult( ServiceWorkerMetrics::READ_HEADERS_ERROR); - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + Done(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); return; } DCHECK_GE(result, 0); @@ -192,14 +192,22 @@ range_requested_, resource_size, true /* replace status line */); } +void ServiceWorkerReadFromCacheJob::Done(const net::URLRequestStatus& status) { + if (!status.is_success()) { + version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_DISK_CACHE); + // TODO(falken): Retry and evict the SW if it fails again. + } + NotifyDone(status); +} + void ServiceWorkerReadFromCacheJob::OnReadComplete(int result) { ServiceWorkerMetrics::ReadResponseResult check_result; if (result == 0) { check_result = ServiceWorkerMetrics::READ_OK; - NotifyDone(net::URLRequestStatus()); + Done(net::URLRequestStatus()); } else if (result < 0) { check_result = ServiceWorkerMetrics::READ_DATA_ERROR; - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); + Done(net::URLRequestStatus(net::URLRequestStatus::FAILED, result)); } else { check_result = ServiceWorkerMetrics::READ_OK; SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
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 48c2aa5..82d9d5f 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
@@ -55,6 +55,7 @@ const net::HttpResponseInfo* http_info() const; bool is_range_request() const { return range_requested_.IsValid(); } void SetupRangeResponse(int response_data_size); + void Done(const net::URLRequestStatus& status); base::WeakPtr<ServiceWorkerContextCore> context_; scoped_refptr<ServiceWorkerVersion> version_;
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc index 3435177..4e36b0f 100644 --- a/content/browser/service_worker/service_worker_register_job.cc +++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -9,6 +9,7 @@ #include "base/message_loop/message_loop.h" #include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_job_coordinator.h" +#include "content/browser/service_worker/service_worker_metrics.h" #include "content/browser/service_worker/service_worker_registration.h" #include "content/browser/service_worker/service_worker_storage.h" #include "content/browser/service_worker/service_worker_utils.h" @@ -385,6 +386,8 @@ void ServiceWorkerRegisterJob::OnInstallFinished( ServiceWorkerStatusCode status) { + ServiceWorkerMetrics::RecordInstallEventStatus(status); + if (status != SERVICE_WORKER_OK) { // "8. If installFailed is true, then:..." Complete(status); @@ -450,7 +453,9 @@ if (should_uninstall_on_failure_) registration()->ClearWhenReady(); if (new_version()) { - if (status != SERVICE_WORKER_ERROR_EXISTS) + if (status == SERVICE_WORKER_ERROR_EXISTS) + new_version()->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS); + else new_version()->ReportError(status, status_message); registration()->UnsetVersion(new_version()); new_version()->Doom();
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc index d2b5833..4f5e6113 100644 --- a/content/browser/service_worker/service_worker_registration.cc +++ b/content/browser/service_worker/service_worker_registration.cc
@@ -6,6 +6,7 @@ #include "content/browser/service_worker/service_worker_context_core.h" #include "content/browser/service_worker/service_worker_info.h" +#include "content/browser/service_worker/service_worker_metrics.h" #include "content/browser/service_worker/service_worker_register_job.h" #include "content/browser/service_worker/service_worker_utils.h" #include "content/public/browser/browser_thread.h" @@ -84,23 +85,54 @@ } void ServiceWorkerRegistration::SetActiveVersion( - ServiceWorkerVersion* version) { + const scoped_refptr<ServiceWorkerVersion>& version) { should_activate_when_ready_ = false; - SetVersionInternal(version, &active_version_, - ChangedVersionAttributesMask::ACTIVE_VERSION); + if (active_version_ == version) + return; + + ChangedVersionAttributesMask mask; + if (version) + UnsetVersionInternal(version.get(), &mask); + if (active_version_) + active_version_->RemoveListener(this); + active_version_ = version; + if (active_version_) + active_version_->AddListener(this); + mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION); + + FOR_EACH_OBSERVER(Listener, listeners_, + OnVersionAttributesChanged(this, mask, GetInfo())); } void ServiceWorkerRegistration::SetWaitingVersion( - ServiceWorkerVersion* version) { + const scoped_refptr<ServiceWorkerVersion>& version) { should_activate_when_ready_ = false; - SetVersionInternal(version, &waiting_version_, - ChangedVersionAttributesMask::WAITING_VERSION); + if (waiting_version_ == version) + return; + + ChangedVersionAttributesMask mask; + if (version) + UnsetVersionInternal(version.get(), &mask); + waiting_version_ = version; + mask.add(ChangedVersionAttributesMask::WAITING_VERSION); + + FOR_EACH_OBSERVER(Listener, listeners_, + OnVersionAttributesChanged(this, mask, GetInfo())); } void ServiceWorkerRegistration::SetInstallingVersion( - ServiceWorkerVersion* version) { - SetVersionInternal(version, &installing_version_, - ChangedVersionAttributesMask::INSTALLING_VERSION); + const scoped_refptr<ServiceWorkerVersion>& version) { + if (installing_version_ == version) + return; + + ChangedVersionAttributesMask mask; + if (version) + UnsetVersionInternal(version.get(), &mask); + installing_version_ = version; + mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION); + + FOR_EACH_OBSERVER(Listener, listeners_, + OnVersionAttributesChanged(this, mask, GetInfo())); } void ServiceWorkerRegistration::UnsetVersion(ServiceWorkerVersion* version) { @@ -115,27 +147,6 @@ } } -void ServiceWorkerRegistration::SetVersionInternal( - ServiceWorkerVersion* version, - scoped_refptr<ServiceWorkerVersion>* data_member, - int change_flag) { - if (version == data_member->get()) - return; - scoped_refptr<ServiceWorkerVersion> protect(version); - ChangedVersionAttributesMask mask; - if (version) - UnsetVersionInternal(version, &mask); - if (*data_member && *data_member == active_version_) - active_version_->RemoveListener(this); - *data_member = version; - if (active_version_.get() && active_version_.get() == version) - active_version_->AddListener(this); - mask.add(change_flag); - ServiceWorkerRegistrationInfo info = GetInfo(); - FOR_EACH_OBSERVER(Listener, listeners_, - OnVersionAttributesChanged(this, mask, info)); -} - void ServiceWorkerRegistration::UnsetVersionInternal( ServiceWorkerVersion* version, ChangedVersionAttributesMask* mask) { @@ -276,7 +287,7 @@ // "6. Set serviceWorkerRegistration.activeWorker to activatingWorker." // "7. Set serviceWorkerRegistration.waitingWorker to null." - SetActiveVersion(activating_version.get()); + SetActiveVersion(activating_version); // "8. Run the [[UpdateState]] algorithm passing registration.activeWorker and // "activating" as arguments." @@ -296,6 +307,8 @@ ServiceWorkerStatusCode status) { if (!context_ || activating_version != active_version()) return; + ServiceWorkerMetrics::RecordActivateEventStatus(status); + // "If activateFailed is true, then:..." if (status != SERVICE_WORKER_OK) { // "Set registration's active worker to null." (The spec's step order may
diff --git a/content/browser/service_worker/service_worker_registration.h b/content/browser/service_worker/service_worker_registration.h index 69e0720e..3a7740b 100644 --- a/content/browser/service_worker/service_worker_registration.h +++ b/content/browser/service_worker/service_worker_registration.h
@@ -94,9 +94,9 @@ // Sets the corresposding version attribute and resets the position // (if any) left vacant (ie. by a waiting version being promoted). // Also notifies listeners via OnVersionAttributesChanged. - void SetActiveVersion(ServiceWorkerVersion* version); - void SetWaitingVersion(ServiceWorkerVersion* version); - void SetInstallingVersion(ServiceWorkerVersion* version); + void SetActiveVersion(const scoped_refptr<ServiceWorkerVersion>& version); + void SetWaitingVersion(const scoped_refptr<ServiceWorkerVersion>& version); + void SetInstallingVersion(const scoped_refptr<ServiceWorkerVersion>& version); // If version is the installing, waiting, active version of this // registation, the method will reset that field to NULL, and notify @@ -142,10 +142,6 @@ ~ServiceWorkerRegistration() override; - void SetVersionInternal( - ServiceWorkerVersion* version, - scoped_refptr<ServiceWorkerVersion>* data_member, - int change_flag); void UnsetVersionInternal( ServiceWorkerVersion* version, ChangedVersionAttributesMask* mask);
diff --git a/content/browser/service_worker/service_worker_registration_status.cc b/content/browser/service_worker/service_worker_registration_status.cc index 2904db9..cce28d7 100644 --- a/content/browser/service_worker/service_worker_registration_status.cc +++ b/content/browser/service_worker/service_worker_registration_status.cc
@@ -59,6 +59,7 @@ case SERVICE_WORKER_ERROR_EXISTS: case SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED: case SERVICE_WORKER_ERROR_STATE: + case SERVICE_WORKER_ERROR_DISK_CACHE: case SERVICE_WORKER_ERROR_MAX_VALUE: // Unexpected, or should have bailed out before calling this, or we don't // have a corresponding blink error code yet.
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc index 1965496..d61ec06 100644 --- a/content/browser/service_worker/service_worker_registration_unittest.cc +++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -105,7 +105,7 @@ RegistrationListener listener; registration->AddListener(&listener); - registration->SetActiveVersion(version_1.get()); + registration->SetActiveVersion(version_1); EXPECT_EQ(version_1.get(), registration->active_version()); EXPECT_EQ(registration, listener.observed_registration_); @@ -120,7 +120,7 @@ kInvalidServiceWorkerVersionId); listener.Reset(); - registration->SetInstallingVersion(version_2.get()); + registration->SetInstallingVersion(version_2); EXPECT_EQ(version_2.get(), registration->installing_version()); EXPECT_EQ(ChangedVersionAttributesMask::INSTALLING_VERSION, @@ -132,7 +132,7 @@ kInvalidServiceWorkerVersionId); listener.Reset(); - registration->SetWaitingVersion(version_2.get()); + registration->SetWaitingVersion(version_2); EXPECT_EQ(version_2.get(), registration->waiting_version()); EXPECT_FALSE(registration->installing_version());
diff --git a/content/browser/service_worker/service_worker_request_handler_unittest.cc b/content/browser/service_worker/service_worker_request_handler_unittest.cc index 4ab7994..4d12e994 100644 --- a/content/browser/service_worker/service_worker_request_handler_unittest.cc +++ b/content/browser/service_worker/service_worker_request_handler_unittest.cc
@@ -61,7 +61,7 @@ base::RunLoop().RunUntilIdle(); version_->SetStatus(ServiceWorkerVersion::ACTIVATED); - registration_->SetActiveVersion(version_.get()); + registration_->SetActiveVersion(version_); context()->storage()->StoreRegistration( registration_.get(), version_.get(),
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc index e3667294..87b5d07 100644 --- a/content/browser/service_worker/service_worker_storage.cc +++ b/content/browser/service_worker/service_worker_storage.cc
@@ -1297,9 +1297,9 @@ } if (version->status() == ServiceWorkerVersion::ACTIVATED) - registration->SetActiveVersion(version.get()); + registration->SetActiveVersion(version); else if (version->status() == ServiceWorkerVersion::INSTALLED) - registration->SetWaitingVersion(version.get()); + registration->SetWaitingVersion(version); else NOTREACHED();
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc index aa07b5b3..8f9b7cee 100644 --- a/content/browser/service_worker/service_worker_storage_unittest.cc +++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -526,7 +526,7 @@ live_registration.get(), kScript, kVersionId, context_ptr_); live_version->SetStatus(ServiceWorkerVersion::INSTALLED); live_version->script_cache_map()->SetResources(resources); - live_registration->SetWaitingVersion(live_version.get()); + live_registration->SetWaitingVersion(live_version); live_registration->set_last_update_check(kYesterday); EXPECT_EQ(SERVICE_WORKER_OK, StoreRegistration(live_registration, live_version)); @@ -617,7 +617,7 @@ scoped_refptr<ServiceWorkerVersion> temp_version = found_registration->waiting_version(); temp_version->SetStatus(ServiceWorkerVersion::ACTIVATED); - found_registration->SetActiveVersion(temp_version.get()); + found_registration->SetActiveVersion(temp_version); temp_version = NULL; EXPECT_EQ(SERVICE_WORKER_OK, UpdateToActiveState(found_registration)); found_registration->set_last_update_check(kToday); @@ -683,7 +683,7 @@ new ServiceWorkerVersion( live_registration.get(), kScript, kVersionId, context_ptr_); live_version->SetStatus(ServiceWorkerVersion::INSTALLING); - live_registration->SetWaitingVersion(live_version.get()); + live_registration->SetWaitingVersion(live_version); // Should not be findable, including by GetAllRegistrations. EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, @@ -805,7 +805,7 @@ new ServiceWorkerVersion( live_registration.get(), kScript, kVersionId, context_ptr_); live_version->SetStatus(ServiceWorkerVersion::INSTALLED); - live_registration->SetWaitingVersion(live_version.get()); + live_registration->SetWaitingVersion(live_version); EXPECT_EQ(SERVICE_WORKER_OK, StoreRegistration(live_registration, live_version)); @@ -1256,7 +1256,7 @@ scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion( registration_.get(), script_, storage()->NewVersionId(), context_ptr_); live_version->SetStatus(ServiceWorkerVersion::NEW); - registration_->SetWaitingVersion(live_version.get()); + registration_->SetWaitingVersion(live_version); // Writing the registration should move the old version's resources to the // purgeable list but keep them available. @@ -1310,7 +1310,7 @@ new ServiceWorkerVersion( live_registration1.get(), kScript1, kVersionId1, context_ptr_); live_version1->SetStatus(ServiceWorkerVersion::INSTALLED); - live_registration1->SetWaitingVersion(live_version1.get()); + live_registration1->SetWaitingVersion(live_version1); // Registration for "/scope/foo". const GURL kScope2("http://www.example.com/scope/foo"); @@ -1324,7 +1324,7 @@ new ServiceWorkerVersion( live_registration2.get(), kScript2, kVersionId2, context_ptr_); live_version2->SetStatus(ServiceWorkerVersion::INSTALLED); - live_registration2->SetWaitingVersion(live_version2.get()); + live_registration2->SetWaitingVersion(live_version2); // Registration for "/scope/foobar". const GURL kScope3("http://www.example.com/scope/foobar"); @@ -1338,7 +1338,7 @@ new ServiceWorkerVersion( live_registration3.get(), kScript3, kVersionId3, context_ptr_); live_version3->SetStatus(ServiceWorkerVersion::INSTALLED); - live_registration3->SetWaitingVersion(live_version3.get()); + live_registration3->SetWaitingVersion(live_version3); // Notify storage of they being installed. storage()->NotifyInstallingRegistration(live_registration1.get());
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc index c004bf0..f0adb9e 100644 --- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc +++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -158,7 +158,7 @@ provider_host->SetDocumentUrl(GURL("http://example.com/")); provider_host->AssociateRegistration(registration_.get(), false /* notify_controllerchange */); - registration_->SetActiveVersion(version_.get()); + registration_->SetActiveVersion(version_); ChromeBlobStorageContext* chrome_blob_storage_context = ChromeBlobStorageContext::GetFor(browser_context_.get());
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index de905b67..9504bef 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -348,12 +348,14 @@ switch (status) { case ServiceWorkerVersion::NEW: case ServiceWorkerVersion::INSTALLING: - case ServiceWorkerVersion::REDUNDANT: return false; case ServiceWorkerVersion::INSTALLED: case ServiceWorkerVersion::ACTIVATING: case ServiceWorkerVersion::ACTIVATED: return true; + case ServiceWorkerVersion::REDUNDANT: + NOTREACHED() << "Cannot use REDUNDANT here."; + return false; } NOTREACHED() << "Unexpected status: " << status; return false; @@ -370,8 +372,9 @@ int64 version_id, base::WeakPtr<ServiceWorkerContextCore> context) : version_id_(version_id), - registration_id_(kInvalidServiceWorkerVersionId), + registration_id_(registration->id()), script_url_(script_url), + scope_(registration->pattern()), status_(NEW), context_(context), script_cache_map_(this, context), @@ -379,10 +382,6 @@ weak_factory_(this) { DCHECK(context_); DCHECK(registration); - if (registration) { - registration_id_ = registration->id(); - scope_ = registration->pattern(); - } context_->AddLiveVersion(this); embedded_worker_ = context_->embedded_worker_registry()->CreateWorker(); embedded_worker_->AddListener(this); @@ -455,6 +454,11 @@ RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_ABORT)); return; } + if (status_ == REDUNDANT) { + RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); + return; + } + prestart_status_ = status_; // Ensure the live registration during starting worker so that the worker can // get associated with it in SWDispatcherHost::OnSetHostedVersionId(). @@ -840,6 +844,11 @@ } } +void ServiceWorkerVersion::SetStartWorkerStatusCode( + ServiceWorkerStatusCode status) { + start_worker_status_ = status; +} + void ServiceWorkerVersion::Doom() { DCHECK(!HasControllee()); SetStatus(REDUNDANT); @@ -1517,11 +1526,16 @@ const StatusCallback& callback, ServiceWorkerStatusCode status, const scoped_refptr<ServiceWorkerRegistration>& protect) { - if (status != SERVICE_WORKER_OK || is_redundant()) { + if (status != SERVICE_WORKER_OK) { RecordStartWorkerResult(status); RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); return; } + if (is_redundant()) { + RecordStartWorkerResult(SERVICE_WORKER_ERROR_NOT_FOUND); + RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED)); + return; + } switch (running_status()) { case RUNNING: @@ -1745,17 +1759,13 @@ base::TimeTicks start_time = start_time_; ClearTick(&start_time_); - // Failing to start a redundant worker isn't interesting and very common when - // update dooms because the script is byte-to-byte identical. - if (is_redundant()) - return; - - ServiceWorkerMetrics::RecordStartWorkerStatus(status, IsInstalled(status_)); + ServiceWorkerMetrics::RecordStartWorkerStatus(status, + IsInstalled(prestart_status_)); if (status == SERVICE_WORKER_OK && !start_time.is_null() && !skip_recording_startup_time_) { ServiceWorkerMetrics::RecordStartWorkerTime(GetTickDuration(start_time), - IsInstalled(status_)); + IsInstalled(prestart_status_)); } if (status != SERVICE_WORKER_ERROR_TIMEOUT) @@ -1854,6 +1864,9 @@ if (ping_state_ == PING_TIMED_OUT) return SERVICE_WORKER_ERROR_TIMEOUT; + if (start_worker_status_ != SERVICE_WORKER_OK) + return start_worker_status_; + const net::URLRequestStatus& main_script_status = script_cache_map()->main_script_status(); if (main_script_status.status() != net::URLRequestStatus::SUCCESS) {
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index ba13327..b020c25214 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h
@@ -286,12 +286,16 @@ void ReportError(ServiceWorkerStatusCode status, const std::string& status_message); + // Sets the status code to pass to StartWorker callbacks if start fails. + void SetStartWorkerStatusCode(ServiceWorkerStatusCode status); + // Sets this version's status to REDUNDANT and deletes its resources. // The version must not have controllees. void Doom(); bool is_redundant() const { return status_ == REDUNDANT; } bool skip_waiting() const { return skip_waiting_; } + void set_skip_waiting(bool skip_waiting) { skip_waiting_ = skip_waiting; } bool force_bypass_cache_for_scripts() { return force_bypass_cache_for_scripts_; @@ -312,11 +316,11 @@ private: friend class base::RefCounted<ServiceWorkerVersion>; friend class ServiceWorkerURLRequestJobTest; + friend class ServiceWorkerVersionBrowserTest; + FRIEND_TEST_ALL_PREFIXES(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion); FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, IdleTimeout); - FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, KeepAlive); - FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, ListenerAvailability); FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, SetDevToolsAttached); FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWaitForeverInFetchTest, RequestTimeout); FRIEND_TEST_ALL_PREFIXES(ServiceWorkerFailToStartTest, Timeout); @@ -324,7 +328,6 @@ TimeoutStartingWorker); FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent); - friend class ServiceWorkerVersionBrowserTest; typedef ServiceWorkerVersion self; using ServiceWorkerClients = std::vector<ServiceWorkerClientInfo>; @@ -489,9 +492,10 @@ ServiceWorkerStatusCode default_code); const int64 version_id_; - int64 registration_id_; - GURL script_url_; - GURL scope_; + const int64 registration_id_; + const GURL script_url_; + const GURL scope_; + Status status_; scoped_ptr<EmbeddedWorkerInstance> embedded_worker_; std::vector<StatusCallback> start_callbacks_; @@ -543,6 +547,12 @@ std::vector<int> pending_skip_waiting_requests_; scoped_ptr<net::HttpResponseInfo> main_script_http_info_; + // The status when StartWorker was invoked. Used for UMA. + Status prestart_status_ = NEW; + // If not OK, the reason that StartWorker failed. Used for + // running |start_callbacks_|. + ServiceWorkerStatusCode start_worker_status_ = SERVICE_WORKER_OK; + base::WeakPtrFactory<ServiceWorkerVersion> weak_factory_; DISALLOW_COPY_AND_ASSIGN(ServiceWorkerVersion);
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 29ee0e1d..3660abd 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -18,7 +18,6 @@ #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/common/frame_messages.h" -#include "content/public/browser/navigation_details.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" @@ -163,6 +162,58 @@ } } +// A WebContentsDelegate that catches messages sent to the console. +class ConsoleObserverDelegate : public WebContentsDelegate { + public: + ConsoleObserverDelegate(WebContents* web_contents, const std::string& filter) + : web_contents_(web_contents), + filter_(filter), + message_(""), + message_loop_runner_(new MessageLoopRunner) {} + + ~ConsoleObserverDelegate() override {} + + bool AddMessageToConsole(WebContents* source, + int32 level, + const base::string16& message, + int32 line_no, + const base::string16& source_id) override; + + std::string message() { return message_; } + + void Wait(); + + private: + WebContents* web_contents_; + std::string filter_; + std::string message_; + + // The MessageLoopRunner used to spin the message loop. + scoped_refptr<MessageLoopRunner> message_loop_runner_; + + DISALLOW_COPY_AND_ASSIGN(ConsoleObserverDelegate); +}; + +void ConsoleObserverDelegate::Wait() { + message_loop_runner_->Run(); +} + +bool ConsoleObserverDelegate::AddMessageToConsole( + WebContents* source, + int32 level, + const base::string16& message, + int32 line_no, + const base::string16& source_id) { + DCHECK(source == web_contents_); + + std::string ascii_message = base::UTF16ToASCII(message); + if (MatchPattern(ascii_message, filter_)) { + message_ = ascii_message; + message_loop_runner_->Quit(); + } + return false; +} + // // SitePerProcessBrowserTest // @@ -435,10 +486,6 @@ bar_child->current_frame_host()->GetSiteInstance(); EXPECT_NE(shell()->web_contents()->GetSiteInstance(), bar_site_instance); -// TODO(nick): The following EXPECTs are disabled because of -// http://crbug.com/476628, where the Site C node sometimes (flakily) has -// children even though it's committed a nav to a page with no iframes. -#if 0 EXPECT_EQ( " Site A ------------ proxies for B C\n" " |--Site B ------- proxies for A C\n" @@ -447,7 +494,6 @@ " B = http://foo.com/\n" " C = http://bar.com/", DepictFrameTree(root)); -#endif // Simulate an attempt to detach the root frame from foo_site_instance. This // should kill foo_site_instance's process. @@ -461,7 +507,6 @@ foo_mainframe_rfph->GetProcess()->GetChannel(), evil_msg2); foo_terminated.Wait(); -#if 0 EXPECT_EQ( " Site A ------------ proxies for B C\n" " |--Site B ------- proxies for A C\n" @@ -470,10 +515,8 @@ " B = http://foo.com/ (no process)\n" " C = http://bar.com/", DepictFrameTree(root)); -#endif } -// Disabled for flaky crashing: crbug.com/446575 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateRemoteFrame) { GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); @@ -530,7 +573,7 @@ } #if defined(OS_WIN) -// http://crbug.com/446575 +// http://crbug.com/465722 #define MAYBE_NavigateRemoteFrameToBlankAndDataURLs \ DISABLED_NavigateRemoteFrameToBlankAndDataURLs #else @@ -1160,16 +1203,8 @@ // Ensure that when navigating a frame cross-process RenderFrameProxyHosts are // created in the FrameTree skipping the subtree of the navigating frame. -// -// Disabled on Mac due to flakiness on ASAN. http://crbug.com/425248 -// Disabled on Windows due to flakiness on Win 7 bot. http://crbug.com/444563 -#if defined(OS_MACOSX) || defined(OS_WIN) -#define MAYBE_ProxyCreationSkipsSubtree DISABLED_ProxyCreationSkipsSubtree -#else -#define MAYBE_ProxyCreationSkipsSubtree ProxyCreationSkipsSubtree -#endif IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, - MAYBE_ProxyCreationSkipsSubtree) { + ProxyCreationSkipsSubtree) { GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); NavigateToURL(shell(), main_url); @@ -1238,6 +1273,14 @@ EXPECT_FALSE(child->render_manager()->pending_frame_host()); EXPECT_TRUE(observer.last_navigation_succeeded()); EXPECT_EQ(cross_site_url, observer.last_navigation_url()); + + EXPECT_EQ( + " Site A ------------ proxies for B\n" + " |--Site A ------- proxies for B\n" + " +--Site B ------- proxies for A\n" + "Where A = http://127.0.0.1/\n" + " B = http://foo.com/", + DepictFrameTree(root)); } // Load another cross-site page into the same iframe. @@ -1265,9 +1308,6 @@ " Site A ------------ proxies for B C\n" " |--Site A ------- proxies for B C\n" " +--Site B (C pending) -- proxies for A\n" - " |--Site A\n" - " +--Site A\n" - " +--Site A\n" "Where A = http://127.0.0.1/\n" " B = http://foo.com/\n" " C = http://bar.com/", @@ -1797,6 +1837,61 @@ EXPECT_EQ(foo_url, root->child_at(0)->current_url()); } +// Verify that when a frame is navigated to a new origin, the origin update +// propagates to the frame's proxies. +IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OriginUpdatesReachProxies) { + GURL main_url( + embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + // It is safe to obtain the root frame tree node here, as it doesn't change. + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) + ->GetFrameTree() + ->root(); + TestNavigationObserver observer(shell()->web_contents()); + + EXPECT_EQ( + " Site A ------------ proxies for B\n" + " |--Site B ------- proxies for A\n" + " +--Site A ------- proxies for B\n" + "Where A = http://127.0.0.1/\n" + " B = http://bar.com/", + DepictFrameTree(root)); + + // Navigate second subframe to a baz.com. This should send an origin update + // to the frame's proxy in the bar.com (first frame's) process. + GURL frame_url = embedded_test_server()->GetURL("baz.com", "/title2.html"); + NavigateFrameToURL(root->child_at(1), frame_url); + EXPECT_TRUE(observer.last_navigation_succeeded()); + EXPECT_EQ(frame_url, observer.last_navigation_url()); + + // The first frame can't directly observe the second frame's origin with + // JavaScript. Instead, try to navigate the second frame from the first + // frame. This should fail with a console error message, which should + // contain the second frame's updated origin (see blink::Frame::canNavigate). + scoped_ptr<ConsoleObserverDelegate> console_delegate( + new ConsoleObserverDelegate( + shell()->web_contents(), + "Unsafe JavaScript attempt to initiate navigation*")); + shell()->web_contents()->SetDelegate(console_delegate.get()); + + // frames[1] can't be used due to a bug where RemoteFrames are created out of + // order (https://crbug.com/478792). Instead, target second frame by name. + EXPECT_TRUE(ExecuteScript( + root->child_at(0)->current_frame_host(), + "window.domAutomationController.send(" + " parent.frames['frame2'].location.href = 'data:text/html,foo');")); + console_delegate->Wait(); + + std::string frame_origin = + root->child_at(1)->current_replication_state().origin.string(); + EXPECT_EQ(frame_origin + "/", frame_url.GetOrigin().spec()); + EXPECT_TRUE( + MatchPattern(console_delegate->message(), "*" + frame_origin + "*")) + << "Error message does not contain the frame's latest origin (" + << frame_origin << ")"; +} + // Ensure that navigating subframes in --site-per-process mode properly fires // the DidStopLoading event on WebContentsObserver. IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteDidStopLoading) { @@ -2045,33 +2140,4 @@ DepictFrameTree(root)); } -IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, - PageTransitionForSecondaryIframeNavigation) { - GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); - NavigateToURL(shell(), main_url); - - // It is safe to obtain the root frame tree node here, as it doesn't change. - FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) - ->GetFrameTree() - ->root(); - - TestNavigationObserver observer(shell()->web_contents()); - - // Load same-site page into iframe. - FrameTreeNode* child = root->child_at(0); - GURL http_url(embedded_test_server()->GetURL("/title1.html")); - NavigateFrameToURL(child, http_url); - EXPECT_EQ(http_url, observer.last_navigation_url()); - EXPECT_TRUE(observer.last_navigation_succeeded()); - - // Load cross-site page into iframe. - TestFrameNavigationObserver frame_observer(child, 1); - GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html"); - NavigateIframeToURL(shell()->web_contents(), "test", url); - frame_observer.Wait(); - - EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, - frame_observer.load_committed_details().type); -} - } // namespace content
diff --git a/content/browser/system_message_window_win_unittest.cc b/content/browser/system_message_window_win_unittest.cc index f317f7b..fac8f2b 100644 --- a/content/browser/system_message_window_win_unittest.cc +++ b/content/browser/system_message_window_win_unittest.cc
@@ -18,10 +18,10 @@ class SystemMessageWindowWinTest : public testing::Test { public: - virtual ~SystemMessageWindowWinTest() { } + ~SystemMessageWindowWinTest() override {} protected: - virtual void SetUp() override { + void SetUp() override { system_monitor_.AddDevicesChangedObserver(&observer_); }
diff --git a/content/browser/time_zone_monitor_win.cc b/content/browser/time_zone_monitor_win.cc index 2e8f9a56..f9205bc7 100644 --- a/content/browser/time_zone_monitor_win.cc +++ b/content/browser/time_zone_monitor_win.cc
@@ -18,15 +18,15 @@ gfx::SingletonHwnd::GetInstance()->AddObserver(this); } - virtual ~TimeZoneMonitorWin() { + ~TimeZoneMonitorWin() override { gfx::SingletonHwnd::GetInstance()->RemoveObserver(this); } // gfx::SingletonHwnd::Observer implementation. - virtual void OnWndProc(HWND hwnd, - UINT message, - WPARAM wparam, - LPARAM lparam) override { + void OnWndProc(HWND hwnd, + UINT message, + WPARAM wparam, + LPARAM lparam) override { if (message != WM_TIMECHANGE) { return; }
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc index de6c4dc3..7042db67 100644 --- a/content/browser/tracing/tracing_controller_browsertest.cc +++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -5,6 +5,7 @@ #include "base/files/file_util.h" #include "base/memory/ref_counted_memory.h" #include "base/run_loop.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/tracing_controller.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" @@ -18,6 +19,37 @@ namespace content { +class TracingControllerTestEndpoint + : public TracingController::TraceDataEndpoint { + public: + TracingControllerTestEndpoint( + base::Callback<void(base::RefCountedString*)> done_callback) + : done_callback_(done_callback) {} + + void ReceiveTraceChunk(const std::string& chunk) override { + EXPECT_FALSE(chunk.empty()); + trace_ += chunk; + } + + void ReceiveTraceFinalContents(const std::string& contents) override { + EXPECT_EQ(trace_, contents); + + std::string tmp = contents; + scoped_refptr<base::RefCountedString> chunk_ptr = + base::RefCountedString::TakeString(&tmp); + + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(done_callback_, chunk_ptr)); + } + + protected: + ~TracingControllerTestEndpoint() override {} + + std::string trace_; + base::Callback<void(base::RefCountedString*)> done_callback_; +}; + class TracingControllerTest : public ContentBrowserTest { public: TracingControllerTest() {} @@ -153,6 +185,37 @@ } } + void TestEnableAndDisableRecordingCompressed() { + Navigate(shell()); + + TracingController* controller = TracingController::GetInstance(); + + { + base::RunLoop run_loop; + TracingController::EnableRecordingDoneCallback callback = + base::Bind(&TracingControllerTest::EnableRecordingDoneCallbackTest, + base::Unretained(this), run_loop.QuitClosure()); + bool result = controller->EnableRecording(CategoryFilter(), + TraceOptions(), callback); + ASSERT_TRUE(result); + run_loop.Run(); + EXPECT_EQ(enable_recording_done_callback_count(), 1); + } + + { + base::RunLoop run_loop; + base::Callback<void(base::RefCountedString*)> callback = base::Bind( + &TracingControllerTest::DisableRecordingStringDoneCallbackTest, + base::Unretained(this), run_loop.QuitClosure()); + bool result = controller->DisableRecording( + TracingController::CreateCompressedStringSink( + new TracingControllerTestEndpoint(callback))); + ASSERT_TRUE(result); + run_loop.Run(); + EXPECT_EQ(disable_recording_done_callback_count(), 1); + } + } + void TestEnableAndDisableRecordingFile( const base::FilePath& result_file_path) { Navigate(shell()); @@ -317,6 +380,11 @@ } IN_PROC_BROWSER_TEST_F(TracingControllerTest, + EnableAndDisableRecordingWithCompression) { + TestEnableAndDisableRecordingCompressed(); +} + +IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecordingWithEmptyFileAndNullCallback) { Navigate(shell());
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 68984fa..3a235fe 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -35,127 +35,6 @@ base::LazyInstance<TracingControllerImpl>::Leaky g_controller = LAZY_INSTANCE_INITIALIZER; -class FileTraceDataSink : public TracingController::TraceDataSink { - public: - explicit FileTraceDataSink(const base::FilePath& trace_file_path, - const base::Closure& callback) - : file_path_(trace_file_path), - completion_callback_(callback), - file_(NULL) {} - - void AddTraceChunk(const std::string& chunk) override { - std::string tmp = chunk; - scoped_refptr<base::RefCountedString> chunk_ptr = - base::RefCountedString::TakeString(&tmp); - BrowserThread::PostTask( - BrowserThread::FILE, - FROM_HERE, - base::Bind( - &FileTraceDataSink::AddTraceChunkOnFileThread, this, chunk_ptr)); - } - void SetSystemTrace(const std::string& data) override { - system_trace_ = data; - } - void Close() override { - BrowserThread::PostTask( - BrowserThread::FILE, - FROM_HERE, - base::Bind(&FileTraceDataSink::CloseOnFileThread, this)); - } - - private: - ~FileTraceDataSink() override { DCHECK(file_ == NULL); } - - void AddTraceChunkOnFileThread( - const scoped_refptr<base::RefCountedString> chunk) { - if (file_ != NULL) - fputc(',', file_); - else if (!OpenFileIfNeededOnFileThread()) - return; - ignore_result(fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()), - 1, file_)); - } - - bool OpenFileIfNeededOnFileThread() { - if (file_ != NULL) - return true; - file_ = base::OpenFile(file_path_, "w"); - if (file_ == NULL) { - LOG(ERROR) << "Failed to open " << file_path_.value(); - return false; - } - const char preamble[] = "{\"traceEvents\": ["; - ignore_result(fwrite(preamble, strlen(preamble), 1, file_)); - return true; - } - - void CloseOnFileThread() { - if (OpenFileIfNeededOnFileThread()) { - fputc(']', file_); - if (!system_trace_.empty()) { - const char systemTraceEvents[] = ",\"systemTraceEvents\": "; - ignore_result(fwrite(systemTraceEvents, strlen(systemTraceEvents), - 1, file_)); - ignore_result(fwrite(system_trace_.c_str(), - strlen(system_trace_.c_str()), 1, file_)); - } - fputc('}', file_); - base::CloseFile(file_); - file_ = NULL; - } - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&FileTraceDataSink::FinalizeOnUIThread, this)); - } - - void FinalizeOnUIThread() { completion_callback_.Run(); } - - base::FilePath file_path_; - base::Closure completion_callback_; - FILE* file_; - std::string system_trace_; - - DISALLOW_COPY_AND_ASSIGN(FileTraceDataSink); -}; - -class StringTraceDataSink : public TracingController::TraceDataSink { - public: - typedef base::Callback<void(base::RefCountedString*)> CompletionCallback; - - explicit StringTraceDataSink(CompletionCallback callback) - : completion_callback_(callback) {} - - // TracingController::TraceDataSink implementation - void AddTraceChunk(const std::string& chunk) override { - if (!trace_.empty()) - trace_ += ","; - trace_ += chunk; - } - void SetSystemTrace(const std::string& data) override { - system_trace_ = data; - } - void Close() override { - std::string result = "{\"traceEvents\":[" + trace_ + "]"; - if (!system_trace_.empty()) - result += ",\"systemTraceEvents\": " + system_trace_; - result += "}"; - - scoped_refptr<base::RefCountedString> str = - base::RefCountedString::TakeString(&result); - completion_callback_.Run(str.get()); - } - - private: - ~StringTraceDataSink() override {} - - std::string trace_; - std::string system_trace_; - CompletionCallback completion_callback_; - - DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink); -}; - } // namespace TracingController* TracingController::GetInstance() { @@ -427,18 +306,6 @@ return true; } -scoped_refptr<TracingController::TraceDataSink> -TracingController::CreateStringSink( - const base::Callback<void(base::RefCountedString*)>& callback) { - return new StringTraceDataSink(callback); -} - -scoped_refptr<TracingController::TraceDataSink> -TracingController::CreateFileSink(const base::FilePath& file_path, - const base::Closure& callback) { - return new FileTraceDataSink(file_path, callback); -} - void TracingControllerImpl::OnDisableMonitoringDone( const DisableMonitoringDoneCallback& callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/content/browser/tracing/tracing_controller_impl_data_sinks.cc b/content/browser/tracing/tracing_controller_impl_data_sinks.cc new file mode 100644 index 0000000..8a2a2bf --- /dev/null +++ b/content/browser/tracing/tracing_controller_impl_data_sinks.cc
@@ -0,0 +1,280 @@ +// 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/tracing/tracing_controller_impl.h" + +#include "base/bind.h" +#include "base/files/file_util.h" +#include "content/public/browser/browser_thread.h" +#include "third_party/zlib/zlib.h" + +namespace content { + +namespace { + +class FileTraceDataSink : public TracingController::TraceDataSink { + public: + explicit FileTraceDataSink(const base::FilePath& trace_file_path, + const base::Closure& callback) + : file_path_(trace_file_path), + completion_callback_(callback), + file_(NULL) {} + + void AddTraceChunk(const std::string& chunk) override { + std::string tmp = chunk; + scoped_refptr<base::RefCountedString> chunk_ptr = + base::RefCountedString::TakeString(&tmp); + BrowserThread::PostTask( + BrowserThread::FILE, + FROM_HERE, + base::Bind( + &FileTraceDataSink::AddTraceChunkOnFileThread, this, chunk_ptr)); + } + void SetSystemTrace(const std::string& data) override { + system_trace_ = data; + } + void Close() override { + BrowserThread::PostTask( + BrowserThread::FILE, + FROM_HERE, + base::Bind(&FileTraceDataSink::CloseOnFileThread, this)); + } + + private: + ~FileTraceDataSink() override { DCHECK(file_ == NULL); } + + void AddTraceChunkOnFileThread( + const scoped_refptr<base::RefCountedString> chunk) { + if (file_ != NULL) + fputc(',', file_); + else if (!OpenFileIfNeededOnFileThread()) + return; + ignore_result(fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()), + 1, file_)); + } + + bool OpenFileIfNeededOnFileThread() { + if (file_ != NULL) + return true; + file_ = base::OpenFile(file_path_, "w"); + if (file_ == NULL) { + LOG(ERROR) << "Failed to open " << file_path_.value(); + return false; + } + const char preamble[] = "{\"traceEvents\": ["; + ignore_result(fwrite(preamble, strlen(preamble), 1, file_)); + return true; + } + + void CloseOnFileThread() { + if (OpenFileIfNeededOnFileThread()) { + fputc(']', file_); + if (!system_trace_.empty()) { + const char systemTraceEvents[] = ",\"systemTraceEvents\": "; + ignore_result(fwrite(systemTraceEvents, strlen(systemTraceEvents), + 1, file_)); + ignore_result(fwrite(system_trace_.c_str(), + strlen(system_trace_.c_str()), 1, file_)); + } + fputc('}', file_); + base::CloseFile(file_); + file_ = NULL; + } + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind(&FileTraceDataSink::FinalizeOnUIThread, this)); + } + + void FinalizeOnUIThread() { completion_callback_.Run(); } + + base::FilePath file_path_; + base::Closure completion_callback_; + FILE* file_; + std::string system_trace_; + + DISALLOW_COPY_AND_ASSIGN(FileTraceDataSink); +}; + +class StringTraceDataSink : public TracingController::TraceDataSink { + public: + typedef base::Callback<void(base::RefCountedString*)> CompletionCallback; + + explicit StringTraceDataSink(CompletionCallback callback) + : completion_callback_(callback) {} + + // TracingController::TraceDataSink implementation + void AddTraceChunk(const std::string& chunk) override { + if (!trace_.empty()) + trace_ += ","; + trace_ += chunk; + } + void SetSystemTrace(const std::string& data) override { + system_trace_ = data; + } + void Close() override { + std::string result = "{\"traceEvents\":[" + trace_ + "]"; + if (!system_trace_.empty()) + result += ",\"systemTraceEvents\": " + system_trace_; + result += "}"; + + scoped_refptr<base::RefCountedString> str = + base::RefCountedString::TakeString(&result); + completion_callback_.Run(str.get()); + } + + private: + ~StringTraceDataSink() override {} + + std::string trace_; + std::string system_trace_; + CompletionCallback completion_callback_; + + DISALLOW_COPY_AND_ASSIGN(StringTraceDataSink); +}; + +class CompressedStringTraceDataSink : public TracingController::TraceDataSink { + public: + explicit CompressedStringTraceDataSink( + scoped_refptr<TracingController::TraceDataEndpoint> endpoint) + : endpoint_(endpoint), already_tried_open_(false) {} + + void AddTraceChunk(const std::string& chunk) override { + std::string tmp = chunk; + scoped_refptr<base::RefCountedString> chunk_ptr = + base::RefCountedString::TakeString(&tmp); + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&CompressedStringTraceDataSink::AddTraceChunkOnFileThread, + this, chunk_ptr)); + } + + void SetSystemTrace(const std::string& data) override { + system_trace_ = data; + } + + void Close() override { + BrowserThread::PostTask( + BrowserThread::FILE, FROM_HERE, + base::Bind(&CompressedStringTraceDataSink::CloseOnFileThread, this)); + } + + private: + ~CompressedStringTraceDataSink() override {} + + bool OpenZStreamOnFileThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + if (stream_) + return true; + + if (already_tried_open_) + return false; + + already_tried_open_ = true; + stream_.reset(new z_stream); + *stream_ = {0}; + stream_->zalloc = Z_NULL; + stream_->zfree = Z_NULL; + stream_->opaque = Z_NULL; + + int result = deflateInit2(stream_.get(), Z_DEFAULT_COMPRESSION, Z_DEFLATED, + // 16 is added to produce a gzip header + trailer. + MAX_WBITS + 16, + 8, // memLevel = 8 is default. + Z_DEFAULT_STRATEGY); + return result == 0; + } + + void AddTraceChunkOnFileThread( + const scoped_refptr<base::RefCountedString> chunk_ptr) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + std::string trace; + if (compressed_trace_data_.empty()) + trace = "{\"traceEvents\":["; + else + trace = ","; + trace += chunk_ptr->data(); + AddTraceChunkAndCompressOnFileThread(trace, false); + } + + void AddTraceChunkAndCompressOnFileThread(const std::string& chunk, + bool finished) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + if (!OpenZStreamOnFileThread()) + return; + + const int kChunkSize = 0x4000; + + char buffer[kChunkSize]; + int err; + stream_->avail_in = chunk.size(); + stream_->next_in = (unsigned char*)chunk.data(); + do { + stream_->avail_out = kChunkSize; + stream_->next_out = (unsigned char*)buffer; + err = deflate(stream_.get(), finished ? Z_FINISH : Z_NO_FLUSH); + if (err != Z_OK && (err != Z_STREAM_END && finished)) { + stream_.reset(); + return; + } + + int bytes = kChunkSize - stream_->avail_out; + if (bytes) { + std::string compressed_chunk = std::string(buffer, bytes); + compressed_trace_data_ += compressed_chunk; + endpoint_->ReceiveTraceChunk(compressed_chunk); + } + } while (stream_->avail_out == 0); + } + + void CloseOnFileThread() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + if (!OpenZStreamOnFileThread()) + return; + + if (compressed_trace_data_.empty()) + AddTraceChunkAndCompressOnFileThread("{\"traceEvents\":[", false); + + AddTraceChunkAndCompressOnFileThread("]", false); + if (!system_trace_.empty()) { + AddTraceChunkAndCompressOnFileThread( + ",\"systemTraceEvents\": " + system_trace_, false); + } + AddTraceChunkAndCompressOnFileThread("}", true); + + deflateEnd(stream_.get()); + stream_.reset(); + + endpoint_->ReceiveTraceFinalContents(compressed_trace_data_); + } + + scoped_refptr<TracingController::TraceDataEndpoint> endpoint_; + scoped_ptr<z_stream> stream_; + bool already_tried_open_; + std::string compressed_trace_data_; + std::string system_trace_; + + DISALLOW_COPY_AND_ASSIGN(CompressedStringTraceDataSink); +}; + +} // namespace + +scoped_refptr<TracingController::TraceDataSink> +TracingController::CreateStringSink( + const base::Callback<void(base::RefCountedString*)>& callback) { + return new StringTraceDataSink(callback); +} + +scoped_refptr<TracingController::TraceDataSink> +TracingController::CreateCompressedStringSink( + scoped_refptr<TracingController::TraceDataEndpoint> endpoint) { + return new CompressedStringTraceDataSink(endpoint); +} + +scoped_refptr<TracingController::TraceDataSink> +TracingController::CreateFileSink(const base::FilePath& file_path, + const base::Closure& callback) { + return new FileTraceDataSink(file_path, callback); +} + +} // namespace content
diff --git a/content/browser/web_contents/aura/gesture_nav_simple.cc b/content/browser/web_contents/aura/gesture_nav_simple.cc index 4e83fdc..46ff45a 100644 --- a/content/browser/web_contents/aura/gesture_nav_simple.cc +++ b/content/browser/web_contents/aura/gesture_nav_simple.cc
@@ -54,10 +54,10 @@ private: friend class base::DeleteHelper<DeleteAfterAnimation<T> >; - virtual ~DeleteAfterAnimation() {} + ~DeleteAfterAnimation() override {} // ui::ImplicitAnimationObserver: - virtual void OnImplicitAnimationsCompleted() override { + void OnImplicitAnimationsCompleted() override { // Deleting an observer when a ScopedLayerAnimationSettings is iterating // over them can cause a crash (which can happen during tests). So instead, // schedule this observer to be deleted soon.
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc index 8b6c784..9844e6c 100644 --- a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc +++ b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -253,8 +253,9 @@ EXPECT_EQ(GetOverlay()->direction_, OverscrollNavigationOverlay::NONE); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); + NavigationEntry* pending = contents()->GetController().GetPendingEntry(); main_test_rfh()->SendNavigate( - 1, contents()->GetController().GetPendingEntry()->GetURL()); + 0, pending->GetUniqueID(), false, pending->GetURL()); EXPECT_EQ(contents()->GetURL(), third()); } @@ -268,8 +269,9 @@ // for the previous page, so we should still be observing. EXPECT_TRUE(GetOverlay()->web_contents()); + NavigationEntry* pending = contents()->GetController().GetPendingEntry(); main_test_rfh()->SendNavigate( - 1, contents()->GetController().GetPendingEntry()->GetURL()); + 0, pending->GetUniqueID(), false, pending->GetURL()); ReceivePaintUpdate(); // Navigation was committed and the paint update was received - we should no @@ -291,8 +293,9 @@ contents()->TestSetIsLoading(true); contents()->TestSetIsLoading(false); EXPECT_FALSE(GetOverlay()->web_contents()); + NavigationEntry* pending = contents()->GetController().GetPendingEntry(); main_test_rfh()->SendNavigate( - 1, contents()->GetController().GetPendingEntry()->GetURL()); + 0, pending->GetUniqueID(), false, pending->GetURL()); EXPECT_EQ(contents()->GetURL(), third()); }
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 3ce4b68..59791b5 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -383,7 +383,7 @@ NotificationService::NoDetails()); // Destroy all frame tree nodes except for the root; this notifies observers. - frame_tree_.ResetForMainFrameSwap(); + frame_tree_.root()->ResetForNewProcess(); GetRenderManager()->ResetProxyHosts(); // Manually call the observer methods for the root frame tree node. @@ -643,10 +643,11 @@ return frame_tree_.root()->current_frame_host(); } -RenderFrameHost* WebContentsImpl::GetFocusedFrame() { - if (!frame_tree_.GetFocusedFrame()) - return NULL; - return frame_tree_.GetFocusedFrame()->current_frame_host(); +RenderFrameHostImpl* WebContentsImpl::GetFocusedFrame() { + FrameTreeNode* focused_node = frame_tree_.GetFocusedFrame(); + if (!focused_node) + return nullptr; + return focused_node->current_frame_host(); } void WebContentsImpl::ForEachFrame( @@ -659,7 +660,7 @@ delete message; } -RenderViewHost* WebContentsImpl::GetRenderViewHost() const { +RenderViewHostImpl* WebContentsImpl::GetRenderViewHost() const { return GetRenderManager()->current_host(); } @@ -791,7 +792,7 @@ void WebContentsImpl::SetParentNativeViewAccessible( gfx::NativeViewAccessible accessible_parent) { accessible_parent_ = accessible_parent; - RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame()); + RenderFrameHostImpl* rfh = GetMainFrame(); if (rfh) rfh->SetParentNativeViewAccessible(accessible_parent); } @@ -1068,11 +1069,9 @@ // The resize rect might have changed while this was inactive -- send the new // one to make sure it's up to date. - RenderViewHostImpl* rvh = - static_cast<RenderViewHostImpl*>(GetRenderViewHost()); - if (rvh) { + RenderViewHostImpl* rvh = GetRenderViewHost(); + if (rvh) rvh->ResizeRectChanged(GetRootWindowResizerRect()); - } // Restore power save blocker if there are active video players running. if (!active_video_players_.empty() && !video_power_save_blocker_) @@ -1126,15 +1125,12 @@ bool WebContentsImpl::NeedToFireBeforeUnload() { // TODO(creis): Should we fire even for interstitial pages? - return WillNotifyDisconnection() && - !ShowingInterstitialPage() && - !static_cast<RenderViewHostImpl*>( - GetRenderViewHost())->SuddenTerminationAllowed(); + return WillNotifyDisconnection() && !ShowingInterstitialPage() && + !GetRenderViewHost()->SuddenTerminationAllowed(); } void WebContentsImpl::DispatchBeforeUnload(bool for_cross_site_transition) { - static_cast<RenderFrameHostImpl*>(GetMainFrame())->DispatchBeforeUnload( - for_cross_site_transition); + GetMainFrame()->DispatchBeforeUnload(for_cross_site_transition); } void WebContentsImpl::Stop() { @@ -1383,7 +1379,7 @@ void WebContentsImpl::RenderWidgetWasResized( RenderWidgetHostImpl* render_widget_host, bool width_changed) { - RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame()); + RenderFrameHostImpl* rfh = GetMainFrame(); if (!rfh || render_widget_host != rfh->GetRenderWidgetHost()) return; @@ -1795,8 +1791,8 @@ // Resume blocked requests for both the RenderViewHost and RenderFrameHost. // TODO(brettw): It seems bogus to reach into here and initialize the host. - static_cast<RenderViewHostImpl*>(new_contents->GetRenderViewHost())->Init(); - static_cast<RenderFrameHostImpl*>(new_contents->GetMainFrame())->Init(); + new_contents->GetRenderViewHost()->Init(); + new_contents->GetMainFrame()->Init(); return new_contents; } @@ -1918,14 +1914,14 @@ BrowserAccessibilityManager* WebContentsImpl::GetRootBrowserAccessibilityManager() { - RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame()); - return rfh ? rfh->browser_accessibility_manager() : NULL; + RenderFrameHostImpl* rfh = GetMainFrame(); + return rfh ? rfh->browser_accessibility_manager() : nullptr; } BrowserAccessibilityManager* WebContentsImpl::GetOrCreateRootBrowserAccessibilityManager() { - RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(GetMainFrame()); - return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : NULL; + RenderFrameHostImpl* rfh = GetMainFrame(); + return rfh ? rfh->GetOrCreateBrowserAccessibilityManager() : nullptr; } void WebContentsImpl::UpdatePreferredSize(const gfx::Size& pref_size) { @@ -2211,7 +2207,7 @@ fullscreen_view->Focus(); return; } - GetRenderViewHostImpl()->SetInitialFocus(reverse); + GetRenderViewHost()->SetInitialFocus(reverse); } bool WebContentsImpl::ShowingInterstitialPage() const { @@ -2351,8 +2347,8 @@ browser_plugin_embedder_->DragSourceEndedAt(client_x, client_y, screen_x, screen_y, operation); if (GetRenderViewHost()) - GetRenderViewHostImpl()->DragSourceEndedAt(client_x, client_y, - screen_x, screen_y, operation); + GetRenderViewHost()->DragSourceEndedAt(client_x, client_y, screen_x, + screen_y, operation); } void WebContentsImpl::DidGetResourceResponseStart( @@ -2392,7 +2388,7 @@ void WebContentsImpl::SystemDragEnded() { if (GetRenderViewHost()) - GetRenderViewHostImpl()->DragSourceSystemDragEnded(); + GetRenderViewHost()->DragSourceSystemDragEnded(); if (browser_plugin_embedder_.get()) browser_plugin_embedder_->SystemDragEnded(); } @@ -2448,8 +2444,9 @@ if (GetBrowserPluginGuest()) return GetBrowserPluginGuest()->LockMouse(allowed); - return GetRenderViewHost() ? - GetRenderViewHostImpl()->GotResponseToLockMouseRequest(allowed) : false; + return GetRenderViewHost() + ? GetRenderViewHost()->GotResponseToLockMouseRequest(allowed) + : false; } bool WebContentsImpl::HasOpener() const { @@ -2539,7 +2536,7 @@ void WebContentsImpl::ExitFullscreen() { // Clean up related state and initiate the fullscreen exit. - GetRenderViewHostImpl()->RejectMouseLockOrUnlockIfNecessary(); + GetRenderViewHost()->RejectMouseLockOrUnlockIfNecessary(); ExitFullscreenMode(); } @@ -4009,7 +4006,7 @@ return; } - if (!GetRenderViewHostImpl() || !GetRenderViewHostImpl()->IsRenderViewLive()) + if (!GetRenderViewHost() || !GetRenderViewHost()->IsRenderViewLive()) return; if (delegate_) @@ -4320,10 +4317,6 @@ return frame_tree_.root()->render_manager(); } -RenderViewHostImpl* WebContentsImpl::GetRenderViewHostImpl() { - return static_cast<RenderViewHostImpl*>(GetRenderViewHost()); -} - BrowserPluginGuest* WebContentsImpl::GetBrowserPluginGuest() const { return browser_plugin_guest_.get(); }
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index dc1eede..86e987f 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -24,6 +24,7 @@ #include "content/browser/frame_host/render_frame_host_manager.h" #include "content/browser/media/audio_state_provider.h" #include "content/browser/renderer_host/render_view_host_delegate.h" +#include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" #include "content/common/accessibility_mode_enums.h" #include "content/common/content_export.h" @@ -59,7 +60,6 @@ class PowerSaveBlocker; class RenderViewHost; class RenderViewHostDelegateView; -class RenderViewHostImpl; class RenderWidgetHostImpl; class SavePackage; class ScreenOrientationDispatcherHost; @@ -228,11 +228,11 @@ const GURL& GetLastCommittedURL() const override; RenderProcessHost* GetRenderProcessHost() const override; RenderFrameHostImpl* GetMainFrame() override; - RenderFrameHost* GetFocusedFrame() override; + RenderFrameHostImpl* GetFocusedFrame() override; void ForEachFrame( const base::Callback<void(RenderFrameHost*)>& on_frame) override; void SendToAllFrames(IPC::Message* message) override; - RenderViewHost* GetRenderViewHost() const override; + RenderViewHostImpl* GetRenderViewHost() const override; int GetRoutingID() const override; RenderWidgetHostView* GetRenderWidgetHostView() const override; RenderWidgetHostView* GetFullscreenRenderWidgetHostView() const override; @@ -246,7 +246,7 @@ bool IsTreeOnlyAccessibilityModeForTesting() const override; bool IsFullAccessibilityModeForTesting() const override; #if defined(OS_WIN) - virtual void SetParentNativeViewAccessible( + void SetParentNativeViewAccessible( gfx::NativeViewAccessible accessible_parent) override; #endif const base::string16& GetTitle() const override; @@ -431,7 +431,7 @@ const IPC::Message& message) override; // RenderFrameHostDelegate has the same method, so list it there because this // interface is going away. - // virtual WebContents* GetAsWebContents() override; + // WebContents* GetAsWebContents() override; gfx::Rect GetRootWindowResizerRect() const override; void RenderViewCreated(RenderViewHost* render_view_host) override; void RenderViewReady(RenderViewHost* render_view_host) override; @@ -942,8 +942,6 @@ // render manager to return. For now, we just return the root's. RenderFrameHostManager* GetRenderManager() const; - RenderViewHostImpl* GetRenderViewHostImpl(); - // Removes browser plugin embedder if there is one. void RemoveBrowserPluginEmbedder();
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index 3a82a88..bc0a10ab 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -159,9 +159,13 @@ CommandReceived(); } - void TestDidNavigate(int page_id, const GURL& url) { + void TestDidNavigate(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url) { FrameHostMsg_DidCommitProvisionalLoad_Params params; - InitNavigateParams(¶ms, page_id, url, ui::PAGE_TRANSITION_TYPED); + InitNavigateParams(¶ms, page_id, nav_entry_id, did_create_new_entry, + url, ui::PAGE_TRANSITION_TYPED); DidNavigate(GetMainFrame()->GetRenderViewHost(), params); } @@ -350,8 +354,8 @@ NavigationControllerImpl& cont = static_cast<NavigationControllerImpl&>(controller()); FrameHostMsg_DidCommitProvisionalLoad_Params params; - InitNavigateParams( - ¶ms, 0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED); + InitNavigateParams(¶ms, 0, 0, true, GURL(url::kAboutBlankURL), + ui::PAGE_TRANSITION_TYPED); LoadCommittedDetails details; cont.RendererDidNavigate(contents()->GetMainFrame(), params, &details); @@ -393,13 +397,15 @@ cont.LoadURL( kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = cont.GetPendingEntry()->GetUniqueID(); rvh()->GetDelegate()->RenderViewCreated(rvh()); // Did we get the expected message? EXPECT_TRUE(process()->sink().GetFirstMessageMatching( ViewMsg_EnableViewSourceMode::ID)); FrameHostMsg_DidCommitProvisionalLoad_Params params; - InitNavigateParams(¶ms, 0, kGURL, ui::PAGE_TRANSITION_TYPED); + InitNavigateParams(¶ms, 0, entry_id, true, kGURL, + ui::PAGE_TRANSITION_TYPED); LoadCommittedDetails details; cont.RendererDidNavigate(contents()->GetMainFrame(), params, &details); // Also check title and url. @@ -439,6 +445,7 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(instance1, orig_rfh->GetSiteInstance()); @@ -450,7 +457,8 @@ site_instance()); // DidNavigate from the page - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); EXPECT_EQ(instance1, orig_rfh->GetSiteInstance()); @@ -485,8 +493,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); // Keep the number of active frames in orig_rfh's SiteInstance non-zero so // that orig_rfh doesn't get deleted when it gets swapped out. @@ -501,6 +511,7 @@ const GURL url2("http://www.yahoo.com"); controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBrowserSideNavigation)) { orig_rfh->PrepareForCommit(); @@ -522,8 +533,8 @@ } // DidNavigate from the pending page - contents()->TestDidNavigate( - pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); SiteInstance* instance2 = contents()->GetSiteInstance(); // Keep the number of active frames in pending_rfh's SiteInstance @@ -546,6 +557,7 @@ // stored in the NavigationEntry, so it should be the same as at the start. // We should use the same RFH as before, swapping it back in. controller().GoBack(); + entry_id = controller().GetPendingEntry()->GetUniqueID(); if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBrowserSideNavigation)) { contents()->GetMainFrame()->PrepareForCommit(); @@ -563,7 +575,8 @@ } // DidNavigate from the back action - contents()->TestDidNavigate(goback_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(goback_rfh, 1, entry_id, false, url2, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(goback_rfh, contents()->GetMainFrame()); EXPECT_EQ(instance1, contents()->GetSiteInstance()); @@ -592,8 +605,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh->GetRenderViewHost(), contents()->GetRenderViewHost()); @@ -607,6 +622,7 @@ const GURL url2("http://www.yahoo.com"); controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); TestRenderFrameHost* new_rfh = contents()->GetMainFrame(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); @@ -615,7 +631,8 @@ EXPECT_EQ(orig_rvh_delete_count, 1); // DidNavigate from the new page - contents()->TestDidNavigate(new_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(new_rfh, 1, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); SiteInstance* instance2 = contents()->GetSiteInstance(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); @@ -639,8 +656,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); // Open a new contents with the same SiteInstance, navigated to the same site. scoped_ptr<TestWebContents> contents2( @@ -648,20 +667,22 @@ contents2->GetController().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID(); contents2->GetMainFrame()->PrepareForCommit(); // Need this page id to be 2 since the site instance is the same (which is the // scope of page IDs) and we want to consider this a new page. - contents2->TestDidNavigate( - contents2->GetMainFrame(), 2, url, ui::PAGE_TRANSITION_TYPED); + contents2->TestDidNavigate(contents2->GetMainFrame(), 2, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); // Navigate first contents to a new site. const GURL url2a("http://www.yahoo.com"); controller().LoadURL( url2a, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); TestRenderFrameHost* pending_rfh_a = contents()->GetPendingMainFrame(); - contents()->TestDidNavigate( - pending_rfh_a, 1, url2a, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(pending_rfh_a, 1, entry_id, true, url2a, + ui::PAGE_TRANSITION_TYPED); SiteInstance* instance2a = contents()->GetSiteInstance(); EXPECT_NE(instance1, instance2a); @@ -670,6 +691,7 @@ contents2->GetController().LoadURL(url2b, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID(); TestRenderFrameHost* rfh2 = contents2->GetMainFrame(); rfh2->PrepareForCommit(); TestRenderFrameHost* pending_rfh_b = contents2->GetPendingMainFrame(); @@ -679,8 +701,8 @@ // NOTE(creis): We used to be in danger of showing a crash page here if the // second contents hadn't navigated somewhere first (bug 1145430). That case // is now covered by the CrossSiteBoundariesAfterCrash test. - contents2->TestDidNavigate( - pending_rfh_b, 2, url2b, ui::PAGE_TRANSITION_TYPED); + contents2->TestDidNavigate(pending_rfh_b, 2, entry_id, true, url2b, + ui::PAGE_TRANSITION_TYPED); SiteInstance* instance2b = contents2->GetSiteInstance(); EXPECT_NE(instance1, instance2b); @@ -706,9 +728,10 @@ const GURL native_url("non-site-url://stuffandthings"); controller().LoadURL( native_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate( - orig_rfh, 1, native_url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, native_url, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); @@ -723,12 +746,14 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(native_url, contents()->GetLastCommittedURL()); EXPECT_EQ(url, contents()->GetVisibleURL()); EXPECT_FALSE(contents()->GetPendingMainFrame()); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); // Keep the number of active frames in orig_rfh's SiteInstance // non-zero so that orig_rfh doesn't get deleted when it gets @@ -744,6 +769,7 @@ const GURL url2("http://www.yahoo.com"); controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBrowserSideNavigation)) { orig_rfh->PrepareForCommit(); @@ -765,8 +791,8 @@ } // DidNavigate from the pending page. - contents()->TestDidNavigate( - pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); SiteInstance* new_instance = contents()->GetSiteInstance(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); @@ -813,9 +839,10 @@ ASSERT_EQ(0u, entries.size()); ASSERT_EQ(1, controller().GetEntryCount()); controller().GoToIndex(0); + entry = controller().GetPendingEntry(); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate( - orig_rfh, 0, native_url, ui::PAGE_TRANSITION_RELOAD); + contents()->TestDidNavigate(orig_rfh, 0, entry->GetUniqueID(), false, + native_url, ui::PAGE_TRANSITION_RELOAD); EXPECT_EQ(orig_instance, contents()->GetSiteInstance()); EXPECT_EQ(GURL(), contents()->GetSiteInstance()->GetSiteURL()); EXPECT_FALSE(orig_instance->HasSite()); @@ -825,8 +852,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry = controller().GetPendingEntry(); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 2, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 2, entry->GetUniqueID(), true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_EQ(orig_instance, contents()->GetSiteInstance()); // Cleanup. @@ -858,9 +887,10 @@ ASSERT_EQ(0u, entries.size()); ASSERT_EQ(1, controller().GetEntryCount()); controller().GoToIndex(0); + entry = controller().GetPendingEntry(); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate( - orig_rfh, 0, regular_url, ui::PAGE_TRANSITION_RELOAD); + contents()->TestDidNavigate(orig_rfh, 0, entry->GetUniqueID(), false, + regular_url, ui::PAGE_TRANSITION_RELOAD); EXPECT_EQ(orig_instance, contents()->GetSiteInstance()); EXPECT_TRUE(orig_instance->HasSite()); @@ -868,9 +898,11 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry = controller().GetPendingEntry(); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate( - contents()->GetPendingMainFrame(), 2, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(contents()->GetPendingMainFrame(), 2, + entry->GetUniqueID(), true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_NE(orig_instance, contents()->GetSiteInstance()); // Cleanup. @@ -886,8 +918,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); // Start to navigate first tab to a new site, so that it has a pending RVH. const GURL url2("http://www.yahoo.com"); @@ -917,9 +951,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate( - orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); // Open a related contents to a second site. scoped_ptr<TestWebContents> contents2( @@ -928,12 +963,15 @@ contents2->GetController().LoadURL(url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = contents2->GetController().GetPendingEntry()->GetUniqueID(); contents2->GetMainFrame()->PrepareForCommit(); + // The first RVH in contents2 isn't live yet, so we shortcut the cross site // pending. TestRenderFrameHost* rfh2 = contents2->GetMainFrame(); EXPECT_FALSE(contents2->CrossProcessNavigationPending()); - contents2->TestDidNavigate(rfh2, 2, url2, ui::PAGE_TRANSITION_TYPED); + contents2->TestDidNavigate(rfh2, 2, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); SiteInstance* instance2 = contents2->GetSiteInstance(); EXPECT_NE(instance1, instance2); EXPECT_FALSE(contents2->CrossProcessNavigationPending()); @@ -942,8 +980,8 @@ // SiteInstances, because we don't intercept Blink navigations. orig_rfh->SendRendererInitiatedNavigationRequest(url2, true); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate( - orig_rfh, 2, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 2, 0, true, url2, + ui::PAGE_TRANSITION_TYPED); SiteInstance* instance3 = contents()->GetSiteInstance(); EXPECT_EQ(instance1, instance3); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); @@ -953,10 +991,11 @@ const GURL url3("http://mail.yahoo.com"); controller().LoadURL( url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate( - orig_rfh, 3, url3, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 3, entry_id, true, url3, + ui::PAGE_TRANSITION_TYPED); SiteInstance* instance4 = contents()->GetSiteInstance(); EXPECT_EQ(instance1, instance4); } @@ -971,8 +1010,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); @@ -991,6 +1032,7 @@ // Navigate again, but simulate an onbeforeunload approval. controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); EXPECT_TRUE(orig_rfh->IsWaitingForBeforeUnloadACK()); now = base::TimeTicks::Now(); orig_rfh->PrepareForCommit(); @@ -1001,8 +1043,8 @@ // We won't hear DidNavigate until the onunload handler has finished running. // DidNavigate from the pending page. - contents()->TestDidNavigate( - pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); SiteInstance* instance2 = contents()->GetSiteInstance(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(pending_rfh, contents()->GetMainFrame()); @@ -1021,8 +1063,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); @@ -1035,7 +1079,7 @@ EXPECT_TRUE(contents()->CrossProcessNavigationPending()); // Suppose the original renderer navigates before the new one is ready. - orig_rfh->SendNavigate(2, GURL("http://www.google.com/foo")); + orig_rfh->SendNavigate(2, 0, true, GURL("http://www.google.com/foo")); // Verify that the pending navigation is cancelled. EXPECT_FALSE(orig_rfh->IsWaitingForBeforeUnloadACK()); @@ -1051,9 +1095,11 @@ const GURL url1("chrome://blah"); controller().LoadURL( url1, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); TestRenderFrameHost* ntp_rfh = contents()->GetMainFrame(); ntp_rfh->PrepareForCommit(); - contents()->TestDidNavigate(ntp_rfh, 1, url1, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(ntp_rfh, 1, entry_id, true, url1, + ui::PAGE_TRANSITION_TYPED); NavigationEntry* entry1 = controller().GetLastCommittedEntry(); SiteInstance* instance1 = contents()->GetSiteInstance(); @@ -1069,6 +1115,7 @@ const GURL url2("http://www.google.com"); controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); TestRenderFrameHost* google_rfh = contents()->GetPendingMainFrame(); @@ -1078,8 +1125,8 @@ ntp_rfh->PrepareForCommit(); // DidNavigate from the pending page. - contents()->TestDidNavigate( - google_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(google_rfh, 1, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); NavigationEntry* entry2 = controller().GetLastCommittedEntry(); SiteInstance* instance2 = contents()->GetSiteInstance(); @@ -1097,10 +1144,11 @@ const GURL url3("http://news.google.com"); controller().LoadURL( url3, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate( - google_rfh, 2, url3, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(google_rfh, 2, entry_id, true, url3, + ui::PAGE_TRANSITION_TYPED); NavigationEntry* entry3 = controller().GetLastCommittedEntry(); SiteInstance* instance3 = contents()->GetSiteInstance(); @@ -1114,6 +1162,7 @@ // Go back within the site. controller().GoBack(); + NavigationEntry* goback_entry = controller().GetPendingEntry(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(entry2, controller().GetPendingEntry()); @@ -1131,7 +1180,8 @@ FrameHostMsg_BeforeUnload_ACK(0, true, now, now)); // DidNavigate from the first back. This aborts the second back's pending RFH. - contents()->TestDidNavigate(google_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(google_rfh, 1, goback_entry->GetUniqueID(), false, + url2, ui::PAGE_TRANSITION_TYPED); // We should commit this page and forget about the second back. EXPECT_FALSE(contents()->CrossProcessNavigationPending()); @@ -1158,8 +1208,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); @@ -1171,8 +1223,9 @@ // Simulate a sub-frame navigation arriving and ensure the RVH is still // waiting for a before unload response. TestRenderFrameHost* child_rfh = orig_rfh->AppendChild("subframe"); - child_rfh->SendNavigateWithTransition( - 1, GURL("http://google.com/frame"), ui::PAGE_TRANSITION_AUTO_SUBFRAME); + child_rfh->SendNavigateWithTransition(1, 0, false, + GURL("http://google.com/frame"), + ui::PAGE_TRANSITION_AUTO_SUBFRAME); EXPECT_TRUE(orig_rfh->IsWaitingForBeforeUnloadACK()); // Now simulate the onbeforeunload approval and verify the navigation is @@ -1191,6 +1244,7 @@ const GURL url("chrome://blah"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry1_id = controller().GetPendingEntry()->GetUniqueID(); TestRenderFrameHost* orig_rfh = contents()->GetMainFrame(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); @@ -1198,6 +1252,7 @@ const GURL url2("http://www.yahoo.com"); controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry2_id = controller().GetPendingEntry()->GetUniqueID(); TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame(); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); EXPECT_TRUE(orig_rfh->IsWaitingForBeforeUnloadACK()); @@ -1205,13 +1260,14 @@ // Suppose the first navigation tries to commit now, with a // FrameMsg_Stop in flight. This should not cancel the pending navigation, // but it should act as if the beforeunload ack arrived. - orig_rfh->SendNavigate(1, GURL("chrome://blah")); + orig_rfh->SendNavigate(1, entry1_id, true, GURL("chrome://blah")); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); EXPECT_FALSE(orig_rfh->IsWaitingForBeforeUnloadACK()); // The pending navigation should be able to commit successfully. - contents()->TestDidNavigate(pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(pending_rfh, 1, entry2_id, true, url2, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(pending_rfh, contents()->GetMainFrame()); } @@ -1225,12 +1281,14 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); NavigationEntry* entry = controller().GetLastCommittedEntry(); EXPECT_EQ(nullptr, entry); // Committed entry should have page state after DidNavigate. orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); entry = controller().GetLastCommittedEntry(); EXPECT_TRUE(entry->GetPageState().IsValid()); @@ -1238,19 +1296,23 @@ const GURL url2("http://images.google.com"); controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); entry = controller().GetLastCommittedEntry(); EXPECT_TRUE(entry->GetPageState().IsValid()); // Committed entry should have page state after DidNavigate. orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 2, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); entry = controller().GetLastCommittedEntry(); EXPECT_TRUE(entry->GetPageState().IsValid()); // Now go back. Committed entry should still have page state. controller().GoBack(); + entry_id = controller().GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, false, url, + ui::PAGE_TRANSITION_TYPED); entry = controller().GetLastCommittedEntry(); EXPECT_TRUE(entry->GetPageState().IsValid()); } @@ -1261,15 +1323,12 @@ TEST_F(WebContentsImplTest, NavigationEntryContentStateNewWindow) { TestRenderFrameHost* orig_rfh = contents()->GetMainFrame(); - // When opening a new window, it is navigated to about:blank internally. - // Currently, this results in two DidNavigate events. + // Navigate to about:blank. const GURL url(url::kAboutBlankURL); orig_rfh->SendRendererInitiatedNavigationRequest(url, false); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); - orig_rfh->SendRendererInitiatedNavigationRequest(url, false); - orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, 0, true, url, + ui::PAGE_TRANSITION_TYPED); // Should have a page state here. NavigationEntry* entry = controller().GetLastCommittedEntry(); @@ -1285,10 +1344,12 @@ const GURL new_url("http://www.google.com"); controller().LoadURL(new_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry = controller().GetPendingEntry(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, new_url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 2, entry->GetUniqueID(), true, new_url, + ui::PAGE_TRANSITION_TYPED); NavigationEntryImpl* entry_impl2 = NavigationEntryImpl::FromNavigationEntry( controller().GetLastCommittedEntry()); EXPECT_EQ(site_instance_id, entry_impl2->site_instance()->GetId()); @@ -1307,8 +1368,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); // Toggle fullscreen mode on (as if initiated via IPC from renderer). @@ -1325,10 +1388,11 @@ const GURL url2("http://www.yahoo.com"); controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); contents()->GetMainFrame()->PrepareForCommit(); TestRenderFrameHost* const pending_rfh = contents()->GetPendingMainFrame(); - contents()->TestDidNavigate( - pending_rfh, 1, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); // Confirm fullscreen has exited. EXPECT_FALSE(orig_rvh->IsFullscreenGranted()); @@ -1350,17 +1414,21 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); - contents()->TestDidNavigate(orig_rfh, 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, url, + ui::PAGE_TRANSITION_TYPED); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); // Now, navigate to another page on the same site. const GURL url2("http://www.google.com/search?q=kittens"); controller().LoadURL( url2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + entry_id = controller().GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); - contents()->TestDidNavigate(orig_rfh, 2, url2, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 2, entry_id, true, url2, + ui::PAGE_TRANSITION_TYPED); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); // Sanity-check: Confirm we're not starting out in fullscreen mode. @@ -1381,11 +1449,12 @@ controller().GoBack(); else controller().GoForward(); + entry_id = controller().GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); - contents()->TestDidNavigate( - orig_rfh, i + 1, url, ui::PAGE_TRANSITION_FORWARD_BACK); + contents()->TestDidNavigate(orig_rfh, i + 1, entry_id, false, url, + ui::PAGE_TRANSITION_FORWARD_BACK); // Confirm fullscreen has exited. EXPECT_FALSE(orig_rvh->IsFullscreenGranted()); @@ -1420,9 +1489,10 @@ const GURL url("http://www.google.com"); controller().LoadURL( url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); - contents()->TestDidNavigate( - contents()->GetMainFrame(), 1, url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(contents()->GetMainFrame(), 1, entry_id, true, + url, ui::PAGE_TRANSITION_TYPED); // Toggle fullscreen mode on (as if initiated via IPC from renderer). EXPECT_FALSE(test_rvh()->IsFullscreenGranted()); @@ -1456,12 +1526,13 @@ ShowInterstitialFromBrowserWithNewNavigationDontProceed) { // Navigate to a page. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); - // Initiate a browser navigation that will trigger the interstitial + // Initiate a browser navigation that will trigger the interstitial. controller().LoadURL(GURL("http://www.evil.com"), Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + NavigationEntry* entry = controller().GetPendingEntry(); // Show an interstitial. TestInterstitialPage::InterstitialState state = @@ -1472,16 +1543,17 @@ new TestInterstitialPage(contents(), true, url2, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); // The interstitial should not show until its navigation has committed. EXPECT_FALSE(interstitial->is_showing()); EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2); EXPECT_TRUE(interstitial->is_showing()); EXPECT_TRUE(contents()->ShowingInterstitialPage()); EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial); - NavigationEntry* entry = controller().GetVisibleEntry(); + entry = controller().GetVisibleEntry(); ASSERT_NE(nullptr, entry); EXPECT_TRUE(entry->GetURL() == url2); @@ -1503,10 +1575,10 @@ // as when clicking on a link in the page) that shows an interstitial and // creates a new navigation entry, then hiding it without proceeding. TEST_F(WebContentsImplTest, - ShowInterstitiaFromRendererlWithNewNavigationDontProceed) { + ShowInterstitialFromRendererWithNewNavigationDontProceed) { // Navigate to a page. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); // Show an interstitial (no pending entry, the interstitial would have been @@ -1519,12 +1591,13 @@ new TestInterstitialPage(contents(), true, url2, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); // The interstitial should not show until its navigation has committed. EXPECT_FALSE(interstitial->is_showing()); EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2); EXPECT_TRUE(interstitial->is_showing()); EXPECT_TRUE(contents()->ShowingInterstitialPage()); EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial); @@ -1552,7 +1625,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationDontProceed) { // Navigate to a page. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); // Show an interstitial. @@ -1569,7 +1642,7 @@ EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); + interstitial->TestDidNavigate(1, 0, true, url2); EXPECT_TRUE(interstitial->is_showing()); EXPECT_TRUE(contents()->ShowingInterstitialPage()); EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial); @@ -1599,7 +1672,7 @@ ShowInterstitialFromBrowserNewNavigationProceed) { // Navigate to a page. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); // Initiate a browser navigation that will trigger the interstitial @@ -1615,12 +1688,13 @@ new TestInterstitialPage(contents(), true, url2, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); // The interstitial should not show until its navigation has committed. EXPECT_FALSE(interstitial->is_showing()); EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2); EXPECT_TRUE(interstitial->is_showing()); EXPECT_TRUE(contents()->ShowingInterstitialPage()); EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial); @@ -1640,7 +1714,7 @@ // Simulate the navigation to the page, that's when the interstitial gets // hidden. GURL url3("http://www.thepage.com"); - contents()->GetMainFrame()->SendNavigate(2, url3); + contents()->GetMainFrame()->SendNavigate(2, 0, true, url3); EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); @@ -1661,7 +1735,7 @@ ShowInterstitialFromRendererNewNavigationProceed) { // Navigate to a page. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); // Show an interstitial. @@ -1673,12 +1747,13 @@ new TestInterstitialPage(contents(), true, url2, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); // The interstitial should not show until its navigation has committed. EXPECT_FALSE(interstitial->is_showing()); EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2); EXPECT_TRUE(interstitial->is_showing()); EXPECT_TRUE(contents()->ShowingInterstitialPage()); EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial); @@ -1698,7 +1773,7 @@ // Simulate the navigation to the page, that's when the interstitial gets // hidden. GURL url3("http://www.thepage.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(2, url3); + main_test_rfh()->NavigateAndCommitRendererInitiated(2, true, url3); EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); @@ -1718,7 +1793,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialNoNewNavigationProceed) { // Navigate to a page so we have a navigation entry in the controller. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); // Show an interstitial. @@ -1735,7 +1810,7 @@ EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); // Let's commit the interstitial navigation. - interstitial->TestDidNavigate(1, url2); + interstitial->TestDidNavigate(1, 0, true, url2); EXPECT_TRUE(interstitial->is_showing()); EXPECT_TRUE(contents()->ShowingInterstitialPage()); EXPECT_TRUE(contents()->GetInterstitialPage() == interstitial); @@ -1772,11 +1847,12 @@ new TestInterstitialPage(contents(), true, url, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(1, url); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url); // While interstitial showing, navigate to a new URL. const GURL url2("http://www.yahoo.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url2); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url2); EXPECT_EQ(TestInterstitialPage::CANCELED, state); @@ -1788,8 +1864,9 @@ TEST_F(WebContentsImplTest, ShowInterstitialThenGoBack) { // Navigate to a page so we have a navigation entry in the controller. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); + NavigationEntry* entry = controller().GetLastCommittedEntry(); // Show interstitial. TestInterstitialPage::InterstitialState state = @@ -1801,17 +1878,20 @@ &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(2, interstitial_url); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(2, interstitial_entry_id, true, + interstitial_url); // While the interstitial is showing, go back. controller().GoBack(); main_test_rfh()->PrepareForCommit(); - contents()->GetMainFrame()->SendNavigate(1, url1); + contents()->GetMainFrame()->SendNavigate(1, entry->GetUniqueID(), false, + url1); // Make sure we are back to the original page and that the interstitial is // gone. EXPECT_EQ(TestInterstitialPage::CANCELED, state); - NavigationEntry* entry = controller().GetVisibleEntry(); + entry = controller().GetVisibleEntry(); ASSERT_TRUE(entry); EXPECT_EQ(url1.spec(), entry->GetURL().spec()); @@ -1824,8 +1904,9 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenGoBack) { // Navigate to a page so we have a navigation entry in the controller. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); + NavigationEntry* entry = controller().GetLastCommittedEntry(); // Show interstitial. TestInterstitialPage::InterstitialState state = @@ -1837,7 +1918,9 @@ &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(2, interstitial_url); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(2, interstitial_entry_id, true, + interstitial_url); // Crash the renderer contents()->GetMainFrame()->GetProcess()->SimulateCrash(); @@ -1845,12 +1928,13 @@ // While the interstitial is showing, go back. controller().GoBack(); main_test_rfh()->PrepareForCommit(); - contents()->GetMainFrame()->SendNavigate(1, url1); + contents()->GetMainFrame()->SendNavigate(1, entry->GetUniqueID(), false, + url1); // Make sure we are back to the original page and that the interstitial is // gone. EXPECT_EQ(TestInterstitialPage::CANCELED, state); - NavigationEntry* entry = controller().GetVisibleEntry(); + entry = controller().GetVisibleEntry(); ASSERT_TRUE(entry); EXPECT_EQ(url1.spec(), entry->GetURL().spec()); @@ -1863,7 +1947,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialCrashRendererThenNavigate) { // Navigate to a page so we have a navigation entry in the controller. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); // Show interstitial. @@ -1876,11 +1960,13 @@ &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); // Crash the renderer contents()->GetMainFrame()->GetProcess()->SimulateCrash(); - interstitial->TestDidNavigate(2, interstitial_url); + interstitial->TestDidNavigate(2, interstitial_entry_id, true, + interstitial_url); } // Test navigating to a page that shows an interstitial, then close the @@ -1895,7 +1981,8 @@ new TestInterstitialPage(contents(), true, url, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(1, url); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url); // Now close the contents. DeleteContents(); @@ -1917,7 +2004,8 @@ new TestInterstitialPage(contents(), true, url, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(1, url); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url); TestRenderFrameHost* rfh = static_cast<TestRenderFrameHost*>(interstitial->GetMainFrame()); @@ -1939,7 +2027,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedMultipleCommands) { // Navigate to a page so we have a navigation entry in the controller. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); // Show an interstitial. @@ -1951,7 +2039,8 @@ new TestInterstitialPage(contents(), true, url2, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(1, url2); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2); // Run a command. EXPECT_EQ(0, interstitial->command_received_count()); @@ -1974,7 +2063,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialOnInterstitial) { // Navigate to a page so we have a navigation entry in the controller. GURL start_url("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, start_url); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, start_url); EXPECT_EQ(1, controller().GetEntryCount()); // Show an interstitial. @@ -1986,7 +2075,8 @@ new TestInterstitialPage(contents(), true, url1, &state1, &deleted1); TestInterstitialPageStateGuard state_guard1(interstitial1); interstitial1->Show(); - interstitial1->TestDidNavigate(1, url1); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial1->TestDidNavigate(1, interstitial_entry_id, true, url1); // Now show another interstitial. TestInterstitialPage::InterstitialState state2 = @@ -1997,7 +2087,8 @@ new TestInterstitialPage(contents(), true, url2, &state2, &deleted2); TestInterstitialPageStateGuard state_guard2(interstitial2); interstitial2->Show(); - interstitial2->TestDidNavigate(1, url2); + interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial2->TestDidNavigate(1, interstitial_entry_id, true, url2); // Showing interstitial2 should have caused interstitial1 to go away. EXPECT_EQ(TestInterstitialPage::CANCELED, state1); @@ -2010,7 +2101,7 @@ // Let's make sure interstitial2 is working as intended. interstitial2->Proceed(); GURL landing_url("http://www.thepage.com"); - contents()->GetMainFrame()->SendNavigate(2, landing_url); + contents()->GetMainFrame()->SendNavigate(2, 0, true, landing_url); EXPECT_FALSE(contents()->ShowingInterstitialPage()); EXPECT_EQ(nullptr, contents()->GetInterstitialPage()); @@ -2027,7 +2118,7 @@ TEST_F(WebContentsImplTest, ShowInterstitialProceedShowInterstitial) { // Navigate to a page so we have a navigation entry in the controller. GURL start_url("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, start_url); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, start_url); EXPECT_EQ(1, controller().GetEntryCount()); // Show an interstitial. @@ -2039,7 +2130,8 @@ new TestInterstitialPage(contents(), true, url1, &state1, &deleted1); TestInterstitialPageStateGuard state_guard1(interstitial1); interstitial1->Show(); - interstitial1->TestDidNavigate(1, url1); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial1->TestDidNavigate(1, interstitial_entry_id, true, url1); // Take action. The interstitial won't be hidden until the navigation is // committed. @@ -2056,7 +2148,8 @@ new TestInterstitialPage(contents(), true, url2, &state2, &deleted2); TestInterstitialPageStateGuard state_guard2(interstitial2); interstitial2->Show(); - interstitial2->TestDidNavigate(1, url2); + interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial2->TestDidNavigate(1, interstitial_entry_id, true, url2); // Showing interstitial2 should have caused interstitial1 to go away. EXPECT_EQ(TestInterstitialPage::UNDECIDED, state2); @@ -2067,7 +2160,7 @@ // Let's make sure interstitial2 is working as intended. interstitial2->Proceed(); GURL landing_url("http://www.thepage.com"); - contents()->GetMainFrame()->SendNavigate(2, landing_url); + contents()->GetMainFrame()->SendNavigate(2, 0, true, landing_url); RunAllPendingInMessageLoop(); EXPECT_TRUE(deleted2); @@ -2092,6 +2185,7 @@ &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); // Let's simulate a navigation initiated from the browser before the // interstitial finishes loading. @@ -2103,7 +2197,8 @@ ASSERT_FALSE(deleted); // Now let's make the interstitial navigation commit. - interstitial->TestDidNavigate(1, interstitial_url); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, + interstitial_url); // After it loaded the interstitial should be gone. EXPECT_EQ(TestInterstitialPage::CANCELED, state); @@ -2137,6 +2232,7 @@ &state2, &deleted2); TestInterstitialPageStateGuard state_guard2(interstitial2); interstitial2->Show(); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); // The first interstitial should have been closed and deleted. EXPECT_EQ(TestInterstitialPage::CANCELED, state1); @@ -2148,7 +2244,8 @@ ASSERT_FALSE(deleted2); // Make the interstitial navigation commit it should be showing. - interstitial2->TestDidNavigate(1, interstitial_url); + interstitial2->TestDidNavigate(1, interstitial_entry_id, true, + interstitial_url); EXPECT_EQ(interstitial2, contents()->GetInterstitialPage()); } @@ -2175,7 +2272,8 @@ interstitial = new TestInterstitialPage(contents(), true, url, &state, &deleted); interstitial->Show(); - interstitial->TestDidNavigate(1, url); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url); // Simulate a renderer crash. interstitial->TestRenderViewTerminated( base::TERMINATION_STATUS_PROCESS_CRASHED, -1); @@ -2204,7 +2302,8 @@ new TestInterstitialPage(contents(), true, kGURL, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(1, kGURL); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, kGURL); // Initiate a new navigation from the browser that also triggers an // interstitial. @@ -2217,7 +2316,8 @@ new TestInterstitialPage(contents(), true, kGURL, &state2, &deleted2); TestInterstitialPageStateGuard state_guard2(interstitial2); interstitial2->Show(); - interstitial2->TestDidNavigate(1, kGURL); + interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial2->TestDidNavigate(1, interstitial_entry_id, true, kGURL); // Make sure we still have an entry. NavigationEntry* entry = contents()->GetController().GetPendingEntry(); @@ -2241,10 +2341,11 @@ // Start a navigation to a page contents()->GetController().LoadURL( kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); main_test_rfh()->PrepareForCommit(); // DidNavigate from the page - contents()->TestDidNavigate( - contents()->GetMainFrame(), 1, kGURL, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(contents()->GetMainFrame(), 1, entry_id, true, + kGURL, ui::PAGE_TRANSITION_TYPED); // Simulate showing an interstitial while the page is showing. TestInterstitialPage::InterstitialState state = @@ -2254,7 +2355,8 @@ new TestInterstitialPage(contents(), true, kGURL, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(1, kGURL); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, kGURL); // While the interstitial is showing, let's simulate the hidden page // attempting to show a JS message. @@ -2271,7 +2373,7 @@ TEST_F(WebContentsImplTest, CopyStateFromAndPruneSourceInterstitial) { // Navigate to a page. GURL url1("http://www.google.com"); - main_test_rfh()->NavigateAndCommitRendererInitiated(1, url1); + main_test_rfh()->NavigateAndCommitRendererInitiated(1, true, url1); EXPECT_EQ(1, controller().GetEntryCount()); // Initiate a browser navigation that will trigger the interstitial @@ -2287,7 +2389,8 @@ new TestInterstitialPage(contents(), true, url2, &state, &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(1, url2); + int interstitial_entry_id = controller().GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url2); EXPECT_TRUE(interstitial->is_showing()); EXPECT_EQ(2, controller().GetEntryCount()); @@ -2336,7 +2439,9 @@ &deleted); TestInterstitialPageStateGuard state_guard(interstitial); interstitial->Show(); - interstitial->TestDidNavigate(1, url3); + int interstitial_entry_id = + other_controller.GetTransientEntry()->GetUniqueID(); + interstitial->TestDidNavigate(1, interstitial_entry_id, true, url3); EXPECT_TRUE(interstitial->is_showing()); EXPECT_EQ(2, other_controller.GetEntryCount()); @@ -2670,13 +2775,14 @@ Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = contents->GetController().GetPendingEntry()->GetUniqueID(); if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBrowserSideNavigation)) { contents->GetMainFrame()->PrepareForCommit(); } EXPECT_TRUE(contents->CrossProcessNavigationPending()); EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount()); - contents->GetPendingMainFrame()->SendNavigate(1, kUrl); + contents->GetPendingMainFrame()->SendNavigate(1, entry_id, true, kUrl); EXPECT_EQ(1u, instance->GetRelatedActiveContentsCount()); contents.reset(); @@ -2705,6 +2811,7 @@ Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = contents->GetController().GetPendingEntry()->GetUniqueID(); contents->GetMainFrame()->PrepareForCommit(); EXPECT_TRUE(contents->CrossProcessNavigationPending()); scoped_refptr<SiteInstance> instance_webui( @@ -2716,7 +2823,7 @@ EXPECT_EQ(0u, instance_webui->GetRelatedActiveContentsCount()); // Commit and contents counts for the new one. - contents->GetPendingMainFrame()->SendNavigate(1, kWebUIUrl); + contents->GetPendingMainFrame()->SendNavigate(1, entry_id, true, kWebUIUrl); EXPECT_EQ(0u, instance->GetRelatedActiveContentsCount()); EXPECT_EQ(1u, instance_webui->GetRelatedActiveContentsCount()); @@ -2772,10 +2879,12 @@ // The frame should still be loading. controller().LoadURL( main_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); orig_rfh->PrepareForCommit(); orig_rfh->OnMessageReceived( FrameHostMsg_DidStartLoading(orig_rfh->GetRoutingID(), false)); - contents()->TestDidNavigate(orig_rfh, 1, main_url, ui::PAGE_TRANSITION_TYPED); + contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, main_url, + ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->CrossProcessNavigationPending()); EXPECT_EQ(orig_rfh, contents()->GetMainFrame()); EXPECT_TRUE(contents()->IsLoading()); @@ -2791,7 +2900,7 @@ subframe->PrepareForCommit(); subframe->OnMessageReceived( FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true)); - subframe->SendNavigateWithTransition(1, initial_url, + subframe->SendNavigateWithTransition(1, 0, false, initial_url, ui::PAGE_TRANSITION_AUTO_SUBFRAME); subframe->OnMessageReceived( FrameHostMsg_DidStopLoading(subframe->GetRoutingID())); @@ -2804,8 +2913,8 @@ subframe->PrepareForCommit(); subframe->OnMessageReceived( FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true)); - subframe->SendNavigateWithTransition( - 1, foo_url, ui::PAGE_TRANSITION_AUTO_SUBFRAME); + subframe->SendNavigateWithTransition(1, 0, false, foo_url, + ui::PAGE_TRANSITION_AUTO_SUBFRAME); subframe->OnMessageReceived( FrameHostMsg_DidStopLoading(subframe->GetRoutingID())); } @@ -2830,6 +2939,7 @@ load_params.frame_tree_node_id = subframe->frame_tree_node()->frame_tree_node_id(); controller().LoadURLWithParams(load_params); + entry_id = controller().GetPendingEntry()->GetUniqueID(); subframe->OnMessageReceived( FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true)); @@ -2837,8 +2947,8 @@ // Commit the navigation in the child frame and send the DidStopLoading // message. subframe->PrepareForCommit(); - contents()->TestDidNavigate( - subframe, 3, bar_url, ui::PAGE_TRANSITION_MANUAL_SUBFRAME); + contents()->TestDidNavigate(subframe, 3, entry_id, true, bar_url, + ui::PAGE_TRANSITION_MANUAL_SUBFRAME); subframe->OnMessageReceived( FrameHostMsg_DidStopLoading(subframe->GetRoutingID())); } @@ -2874,6 +2984,7 @@ // be a pending RenderFrameHost and the WebContents should be loading. controller().LoadURL( kUrl2, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string()); + int entry_id = controller().GetPendingEntry()->GetUniqueID(); EXPECT_TRUE(contents()->CrossProcessNavigationPending()); TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame(); ASSERT_TRUE(pending_rfh); @@ -2897,7 +3008,7 @@ // Simulate the commit and DidStopLoading from the renderer-initiated // navigation in the current RenderFrameHost. There should still be a pending // RenderFrameHost and the WebContents should still be loading. - current_rfh->SendNavigate(1, kUrl3); + current_rfh->SendNavigate(1, 0, true, kUrl3); current_rfh->OnMessageReceived( FrameHostMsg_DidStopLoading(current_rfh->GetRoutingID())); EXPECT_EQ(contents()->GetPendingMainFrame(), pending_rfh); @@ -2905,7 +3016,7 @@ // Commit the navigation. The formerly pending RenderFrameHost should now be // the current RenderFrameHost and the WebContents should still be loading. - contents()->TestDidNavigate(pending_rfh, 1, kUrl2, + contents()->TestDidNavigate(pending_rfh, 1, entry_id, true, kUrl2, ui::PAGE_TRANSITION_TYPED); EXPECT_FALSE(contents()->GetPendingMainFrame()); TestRenderFrameHost* new_current_rfh = contents()->GetMainFrame();
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc index 5d46e43..705fbb9 100644 --- a/content/browser/web_contents/web_contents_view_aura.cc +++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -435,7 +435,7 @@ // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is // going to be deprecated in a year, this is ok for now. The test for this is // PrintPreviewTest.WindowedNPAPIPluginHidden. - virtual void OnWindowAdded(aura::Window* new_window) override { + void OnWindowAdded(aura::Window* new_window) override { if (!new_window->Contains(view_->window_.get())) { // Skip the case when the parent moves to the root window. if (new_window != host_window_) { @@ -453,7 +453,7 @@ } } - virtual void OnWillRemoveWindow(aura::Window* window) override { + void OnWillRemoveWindow(aura::Window* window) override { if (window == view_->window_) return; @@ -461,8 +461,7 @@ UpdateConstrainedWindows(window); } - virtual void OnWindowVisibilityChanged(aura::Window* window, - bool visible) override { + void OnWindowVisibilityChanged(aura::Window* window, bool visible) override { if (window == view_->window_ || window->parent() == host_window_ || window->parent() == view_->window_->GetRootWindow()) {
diff --git a/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm b/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm index 5d21e729..b614fb1 100644 --- a/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm +++ b/content/browser/web_contents/web_contents_view_overscroll_animator_slider_mac.mm
@@ -72,7 +72,7 @@ OverscrollAnimatorSliderView* slider_view) : WebContentsObserver(web_contents), slider_view_(slider_view) {} - virtual void DidFirstVisuallyNonEmptyPaint() override { + void DidFirstVisuallyNonEmptyPaint() override { [slider_view_ webContentsFinishedNonEmptyPaint]; }
diff --git a/content/child/blink_platform_impl_unittest.cc b/content/child/blink_platform_impl_unittest.cc index c1b6a8e..01a3b91 100644 --- a/content/child/blink_platform_impl_unittest.cc +++ b/content/child/blink_platform_impl_unittest.cc
@@ -19,7 +19,7 @@ TestBlinkPlatformImpl() : mock_monotonically_increasing_time_(0) {} // Returns mock time when enabled. - virtual double monotonicallyIncreasingTime() override { + double monotonicallyIncreasingTime() override { if (mock_monotonically_increasing_time_ > 0.0) return mock_monotonically_increasing_time_; return BlinkPlatformImpl::monotonicallyIncreasingTime();
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index d2f1791b..f988ee6 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -567,6 +567,8 @@ OnSetProfilerStatus) IPC_MESSAGE_HANDLER(ChildProcessMsg_GetChildProfilerData, OnGetChildProfilerData) + IPC_MESSAGE_HANDLER(ChildProcessMsg_ProfilingPhaseCompleted, + OnProfilingPhaseCompleted) IPC_MESSAGE_HANDLER(ChildProcessMsg_DumpHandles, OnDumpHandles) IPC_MESSAGE_HANDLER(ChildProcessMsg_SetProcessBackgrounded, OnProcessBackgrounded) @@ -606,14 +608,19 @@ ThreadData::InitializeAndSetTrackingStatus(status); } -void ChildThreadImpl::OnGetChildProfilerData(int sequence_number) { +void ChildThreadImpl::OnGetChildProfilerData(int sequence_number, + int current_profiling_phase) { tracked_objects::ProcessDataSnapshot process_data; - ThreadData::Snapshot(&process_data); + ThreadData::Snapshot(current_profiling_phase, &process_data); Send( new ChildProcessHostMsg_ChildProfilerData(sequence_number, process_data)); } +void ChildThreadImpl::OnProfilingPhaseCompleted(int profiling_phase) { + ThreadData::OnProfilingPhaseCompleted(profiling_phase); +} + void ChildThreadImpl::OnDumpHandles() { #if defined(OS_WIN) scoped_refptr<HandleEnumerator> handle_enum(
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h index 821ca4e..2310c306 100644 --- a/content/child/child_thread_impl.h +++ b/content/child/child_thread_impl.h
@@ -223,7 +223,8 @@ // IPC message handlers. void OnShutdown(); void OnSetProfilerStatus(tracked_objects::ThreadData::Status status); - void OnGetChildProfilerData(int sequence_number); + void OnGetChildProfilerData(int sequence_number, int current_profiling_phase); + void OnProfilingPhaseCompleted(int profiling_phase); void OnDumpHandles(); void OnProcessBackgrounded(bool background); #ifdef IPC_MESSAGE_LOG_ENABLED
diff --git a/content/child/indexed_db/indexed_db_dispatcher_unittest.cc b/content/child/indexed_db/indexed_db_dispatcher_unittest.cc index 4f29998..04a47e7 100644 --- a/content/child/indexed_db/indexed_db_dispatcher_unittest.cc +++ b/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
@@ -140,13 +140,12 @@ explicit CursorCallbacks(scoped_ptr<WebIDBCursor>* cursor) : cursor_(cursor) {} - virtual void onSuccess(const WebData&, - const WebVector<WebBlobInfo>&) override {} - virtual void onSuccess(WebIDBCursor* cursor, - const WebIDBKey& key, - const WebIDBKey& primaryKey, - const WebData& value, - const WebVector<WebBlobInfo>&) override { + void onSuccess(const WebData&, const WebVector<WebBlobInfo>&) override {} + void onSuccess(WebIDBCursor* cursor, + const WebIDBKey& key, + const WebIDBKey& primaryKey, + const WebData& value, + const WebVector<WebBlobInfo>&) override { cursor_->reset(cursor); }
diff --git a/content/child/indexed_db/webidbcursor_impl_unittest.cc b/content/child/indexed_db/webidbcursor_impl_unittest.cc index 95d187b7..c7908ff 100644 --- a/content/child/indexed_db/webidbcursor_impl_unittest.cc +++ b/content/child/indexed_db/webidbcursor_impl_unittest.cc
@@ -99,10 +99,10 @@ WebVector<WebBlobInfo>* webBlobInfo = 0) : key_(key), web_blob_info_(webBlobInfo) {} - virtual void onSuccess(const WebIDBKey& key, - const WebIDBKey& primaryKey, - const WebData& value, - const WebVector<WebBlobInfo>& webBlobInfo) override { + void onSuccess(const WebIDBKey& key, + const WebIDBKey& primaryKey, + const WebData& value, + const WebVector<WebBlobInfo>& webBlobInfo) override { if (key_) *key_ = IndexedDBKeyBuilder::Build(key); if (web_blob_info_)
diff --git a/content/child/npapi/plugin_url_fetcher.cc b/content/child/npapi/plugin_url_fetcher.cc index 372c3b5..b4ef677 100644 --- a/content/child/npapi/plugin_url_fetcher.cc +++ b/content/child/npapi/plugin_url_fetcher.cc
@@ -43,9 +43,8 @@ : byte_range_lower_bound_(0), plugin_stream_(plugin_stream) {} // blink::WebURLLoaderClient implementation: - virtual void didReceiveResponse( - blink::WebURLLoader* loader, - const blink::WebURLResponse& response) override { + void didReceiveResponse(blink::WebURLLoader* loader, + const blink::WebURLResponse& response) override { int64 byte_range_upper_bound, instance_size; if (!MultipartResponseDelegate::ReadContentRanges(response, &byte_range_lower_bound_, @@ -54,10 +53,10 @@ NOTREACHED(); } } - virtual void didReceiveData(blink::WebURLLoader* loader, - const char* data, - int data_length, - int encoded_data_length) override { + void didReceiveData(blink::WebURLLoader* loader, + const char* data, + int data_length, + int encoded_data_length) override { // TODO(ananta) // We should defer further loads on multipart resources on the same lines // as regular resources requested by plugins to prevent reentrancy.
diff --git a/content/child/npapi/webplugin_delegate_impl.h b/content/child/npapi/webplugin_delegate_impl.h index 91eddfa..96d4a1e 100644 --- a/content/child/npapi/webplugin_delegate_impl.h +++ b/content/child/npapi/webplugin_delegate_impl.h
@@ -437,10 +437,6 @@ // This flag indicates whether we started tracking a user gesture message. bool user_gesture_message_posted_; - // Runnable Method Factory used to invoke the OnUserGestureEnd method - // asynchronously. - base::WeakPtrFactory<WebPluginDelegateImpl> user_gesture_msg_factory_; - // Handle to the mouse hook installed for certain windowed plugins like // flash. HHOOK mouse_hook_; @@ -470,6 +466,12 @@ // True if NPP_New did not return an error. bool creation_succeeded_; +#if defined(OS_WIN) + // Runnable Method Factory used to invoke the OnUserGestureEnd method + // asynchronously. + base::WeakPtrFactory<WebPluginDelegateImpl> user_gesture_msg_factory_; +#endif + DISALLOW_COPY_AND_ASSIGN(WebPluginDelegateImpl); };
diff --git a/content/child/npapi/webplugin_delegate_impl_win.cc b/content/child/npapi/webplugin_delegate_impl_win.cc index c7efff72..897745b 100644 --- a/content/child/npapi/webplugin_delegate_impl_win.cc +++ b/content/child/npapi/webplugin_delegate_impl_win.cc
@@ -239,14 +239,14 @@ handle_event_message_filter_hook_(NULL), handle_event_pump_messages_event_(NULL), user_gesture_message_posted_(false), - user_gesture_msg_factory_(this), handle_event_depth_(0), mouse_hook_(NULL), first_set_window_call_(true), plugin_has_focus_(false), has_webkit_focus_(false), containing_view_has_focus_(true), - creation_succeeded_(false) { + creation_succeeded_(false), + user_gesture_msg_factory_(this) { memset(&window_, 0, sizeof(window_)); const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info();
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc index cf56a77c..baa6f6f 100644 --- a/content/child/resource_dispatcher.cc +++ b/content/child/resource_dispatcher.cc
@@ -766,8 +766,8 @@ if ((request_info.referrer.policy == blink::WebReferrerPolicyDefault || request_info.referrer.policy == blink::WebReferrerPolicyNoReferrerWhenDowngrade) && - request_info.referrer.url.SchemeIsSecure() && - !request_info.url.SchemeIsSecure()) { + request_info.referrer.url.SchemeIsCryptographic() && + !request_info.url.SchemeIsCryptographic()) { LOG(FATAL) << "Trying to send secure referrer for insecure request " << "without an appropriate referrer policy.\n" << "URL = " << request_info.url << "\n"
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index b4d5df5..7fae742 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -100,9 +100,6 @@ if (command_line.HasSwitch(scheduler::switches::kDisableBlinkScheduler)) WebRuntimeFeatures::enableBlinkScheduler(false); - if (command_line.HasSwitch(switches::kDisableLocalStorage)) - WebRuntimeFeatures::enableLocalStorage(false); - if (command_line.HasSwitch(switches::kDisableMediaSource)) WebRuntimeFeatures::enableMediaSource(false);
diff --git a/content/child/v8_value_converter_impl.cc b/content/child/v8_value_converter_impl.cc index 6ff8797..9efd429 100644 --- a/content/child/v8_value_converter_impl.cc +++ b/content/child/v8_value_converter_impl.cc
@@ -4,11 +4,11 @@ #include "content/child/v8_value_converter_impl.h" +#include <cmath> #include <string> #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/float_util.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" @@ -309,7 +309,7 @@ if (val->IsNumber()) { double val_as_double = val.As<v8::Number>()->Value(); - if (!base::IsFinite(val_as_double)) + if (!std::isfinite(val_as_double)) return NULL; return new base::FundamentalValue(val_as_double); }
diff --git a/content/child/web_url_loader_impl.h b/content/child/web_url_loader_impl.h index 8c1447b..9d85d06a 100644 --- a/content/child/web_url_loader_impl.h +++ b/content/child/web_url_loader_impl.h
@@ -38,7 +38,7 @@ explicit WebURLLoaderImpl( ResourceDispatcher* resource_dispatcher, scoped_refptr<base::SingleThreadTaskRunner> task_runner); - virtual ~WebURLLoaderImpl(); + ~WebURLLoaderImpl() override; static void PopulateURLResponse( const GURL& url, @@ -46,19 +46,19 @@ blink::WebURLResponse* response); // WebURLLoader methods: - virtual void loadSynchronously( + void loadSynchronously( const blink::WebURLRequest& request, blink::WebURLResponse& response, blink::WebURLError& error, blink::WebData& data) override; - virtual void loadAsynchronously( + void loadAsynchronously( const blink::WebURLRequest& request, blink::WebURLLoaderClient* client) override; - virtual void cancel() override; - virtual void setDefersLoading(bool value) override; - virtual void didChangePriority(blink::WebURLRequest::Priority new_priority, - int intra_priority_value) override; - virtual bool attachThreadedDataReceiver( + void cancel() override; + void setDefersLoading(bool value) override; + void didChangePriority(blink::WebURLRequest::Priority new_priority, + int intra_priority_value) override; + bool attachThreadedDataReceiver( blink::WebThreadedDataReceiver* threaded_data_receiver) override; private:
diff --git a/content/child/web_url_loader_impl_unittest.cc b/content/child/web_url_loader_impl_unittest.cc index f1321696..7a48565 100644 --- a/content/child/web_url_loader_impl_unittest.cc +++ b/content/child/web_url_loader_impl_unittest.cc
@@ -115,10 +115,10 @@ did_receive_response_(false), did_finish_(false) {} - virtual ~TestWebURLLoaderClient() {} + ~TestWebURLLoaderClient() override {} // blink::WebURLLoaderClient implementation: - virtual void willSendRequest( + void willSendRequest( blink::WebURLLoader* loader, blink::WebURLRequest& newRequest, const blink::WebURLResponse& redirectResponse) override { @@ -132,14 +132,14 @@ loader_.reset(); } - virtual void didSendData(blink::WebURLLoader* loader, - unsigned long long bytesSent, - unsigned long long totalBytesToBeSent) override { + void didSendData(blink::WebURLLoader* loader, + unsigned long long bytesSent, + unsigned long long totalBytesToBeSent) override { EXPECT_TRUE(loader_); EXPECT_EQ(loader_.get(), loader); } - virtual void didReceiveResponse( + void didReceiveResponse( blink::WebURLLoader* loader, const blink::WebURLResponse& response) override { EXPECT_TRUE(loader_); @@ -154,17 +154,17 @@ loader_.reset(); } - virtual void didDownloadData(blink::WebURLLoader* loader, - int dataLength, - int encodedDataLength) override { + void didDownloadData(blink::WebURLLoader* loader, + int dataLength, + int encodedDataLength) override { EXPECT_TRUE(loader_); EXPECT_EQ(loader_.get(), loader); } - virtual void didReceiveData(blink::WebURLLoader* loader, - const char* data, - int dataLength, - int encodedDataLength) override { + void didReceiveData(blink::WebURLLoader* loader, + const char* data, + int dataLength, + int encodedDataLength) override { EXPECT_TRUE(loader_); EXPECT_EQ(loader_.get(), loader); // The response should have started, but must not have finished, or failed. @@ -179,15 +179,15 @@ loader_.reset(); } - virtual void didReceiveCachedMetadata(blink::WebURLLoader* loader, - const char* data, - int dataLength) override { + void didReceiveCachedMetadata(blink::WebURLLoader* loader, + const char* data, + int dataLength) override { EXPECT_EQ(loader_.get(), loader); } - virtual void didFinishLoading(blink::WebURLLoader* loader, - double finishTime, - int64_t totalEncodedDataLength) override { + void didFinishLoading(blink::WebURLLoader* loader, + double finishTime, + int64_t totalEncodedDataLength) override { EXPECT_TRUE(loader_); EXPECT_EQ(loader_.get(), loader); EXPECT_TRUE(did_receive_response_); @@ -198,8 +198,8 @@ loader_.reset(); } - virtual void didFail(blink::WebURLLoader* loader, - const blink::WebURLError& error) override { + void didFail(blink::WebURLLoader* loader, + const blink::WebURLError& error) override { EXPECT_TRUE(loader_); EXPECT_EQ(loader_.get(), loader); EXPECT_FALSE(did_finish_);
diff --git a/content/child/websocket_bridge.h b/content/child/websocket_bridge.h index e863ad1..cff76f4 100644 --- a/content/child/websocket_bridge.h +++ b/content/child/websocket_bridge.h
@@ -31,26 +31,25 @@ bool OnMessageReceived(const IPC::Message& message); // WebSocketHandle functions. - virtual void connect(const blink::WebURL& url, - const blink::WebVector<blink::WebString>& protocols, - const blink::WebSerializedOrigin& origin, - blink::WebSocketHandleClient* client) override; - virtual void send(bool fin, - WebSocketHandle::MessageType type, - const char* data, - size_t size) override; - virtual void flowControl(int64_t quota) override; - virtual void close(unsigned short code, - const blink::WebString& reason) override; + void connect(const blink::WebURL& url, + const blink::WebVector<blink::WebString>& protocols, + const blink::WebSerializedOrigin& origin, + blink::WebSocketHandleClient* client) override; + void send(bool fin, + WebSocketHandle::MessageType type, + const char* data, + size_t size) override; + void flowControl(int64_t quota) override; + void close(unsigned short code, const blink::WebString& reason) override; - virtual void Disconnect(); + void Disconnect(); void set_render_frame_id(int id) { render_frame_id_ = id; } private: - virtual ~WebSocketBridge(); + ~WebSocketBridge() override; void DidConnect(const std::string& selected_protocol, const std::string& extensions);
diff --git a/content/common/android/gin_java_bridge_value_unittest.cc b/content/common/android/gin_java_bridge_value_unittest.cc index 72a0ea8..0276848 100644 --- a/content/common/android/gin_java_bridge_value_unittest.cc +++ b/content/common/android/gin_java_bridge_value_unittest.cc
@@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <cmath> + #include "base/basictypes.h" -#include "base/float_util.h" #include "base/memory/scoped_ptr.h" #include "content/common/android/gin_java_bridge_value.h" #include "testing/gtest/include/gtest/gtest.h" @@ -40,8 +41,7 @@ ASSERT_TRUE(float_infinity_value.get()); EXPECT_TRUE(float_infinity_value->IsType(GinJavaBridgeValue::TYPE_NONFINITE)); EXPECT_TRUE(float_infinity_value->GetAsNonFinite(&native_float)); - EXPECT_FALSE(base::IsFinite(native_float)); - EXPECT_FALSE(base::IsNaN(native_float)); + EXPECT_TRUE(std::isinf(native_float)); EXPECT_FALSE(undefined_value->GetAsObjectID(&native_object_id)); @@ -57,8 +57,7 @@ EXPECT_TRUE( double_infinity_value->IsType(GinJavaBridgeValue::TYPE_NONFINITE)); EXPECT_TRUE(double_infinity_value->GetAsNonFinite(&native_float)); - EXPECT_FALSE(base::IsFinite(native_float)); - EXPECT_FALSE(base::IsNaN(native_float)); + EXPECT_TRUE(std::isinf(native_float)); EXPECT_FALSE(undefined_value->GetAsObjectID(&native_object_id));
diff --git a/content/common/bluetooth/bluetooth_messages.h b/content/common/bluetooth/bluetooth_messages.h index f496f9d..dda97d4 100644 --- a/content/common/bluetooth/bluetooth_messages.h +++ b/content/common/bluetooth/bluetooth_messages.h
@@ -56,8 +56,8 @@ // From: Device Discovery: requestDevice // http://webbluetoothcg.github.io/web-bluetooth/#device-discovery // """ -// Display a prompt to the user requesting that the user specify some devices -// from the result of the scan. The UA should show the user the human-readable +// Even if scanResult is empty, display a prompt to the user requesting that the +// user select a device from it. The UA should show the user the human-readable // name of each device. If this name is not available because the UA's Bluetooth // system doesn't support privacy-enabled scans, the UA should allow the user to // indicate interest and then perform a privacy-disabled scan to retrieve the @@ -66,20 +66,16 @@ // The UA may allow the user to select a nearby device that does not match // filters. // -// Wait for the user to have made their selection. +// Wait for the user to have selected a device or cancelled the prompt. // -// If the user cancels the prompt, reject the Promise with a NotFoundError and -// abort these steps. +// If the user cancels the prompt, reject promise with a NotFoundError and abort +// these steps. // -// Record the selected device in the origin's allowed devices list and the union -// of the service UUIDs from filters and options.optionalServices in the device -// and origin's allowed services list. +// Add device to the origin's allowed devices map. with the union of the service +// UUIDs from filters and options.optionalServices as allowed services. // -// Connect to the device. ([BLUETOOTH41] 3.G.6.2.1) If the connection fails, -// reject the Promise with a NetworkError and abort these steps. -// -// Resolve the Promise with a BluetoothDevice instance representing the selected -// device. +// Get the BluetoothDevice representing device and resolve promise with the +// result. // """ #include "ipc/ipc_message_macros.h"
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h index a26f7e3..2d08afa 100644 --- a/content/common/cc_messages.h +++ b/content/common/cc_messages.h
@@ -274,6 +274,13 @@ IPC_STRUCT_TRAITS_MEMBER(visible) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(cc::ViewportSelection) + IPC_STRUCT_TRAITS_MEMBER(start) + IPC_STRUCT_TRAITS_MEMBER(end) + IPC_STRUCT_TRAITS_MEMBER(is_editable) + IPC_STRUCT_TRAITS_MEMBER(is_empty_text_form_control) +IPC_STRUCT_TRAITS_END() + IPC_ENUM_TRAITS_MAX_VALUE( \ cc::BeginFrameArgs::BeginFrameArgsType, \ cc::BeginFrameArgs::BEGIN_FRAME_ARGS_TYPE_MAX - 1) @@ -297,8 +304,7 @@ IPC_STRUCT_TRAITS_MEMBER(root_overflow_y_hidden) IPC_STRUCT_TRAITS_MEMBER(location_bar_offset) IPC_STRUCT_TRAITS_MEMBER(location_bar_content_translation) - IPC_STRUCT_TRAITS_MEMBER(selection_start) - IPC_STRUCT_TRAITS_MEMBER(selection_end) + IPC_STRUCT_TRAITS_MEMBER(selection) IPC_STRUCT_TRAITS_MEMBER(latency_info) IPC_STRUCT_TRAITS_MEMBER(satisfies_sequences) IPC_STRUCT_TRAITS_END()
diff --git a/content/common/child_process_messages.h b/content/common/child_process_messages.h index 830cd62..f90e2e1 100644 --- a/content/common/child_process_messages.h +++ b/content/common/child_process_messages.h
@@ -58,7 +58,7 @@ IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(tracked_objects::ProcessDataSnapshot) - IPC_STRUCT_TRAITS_MEMBER(phased_process_data_snapshots) + IPC_STRUCT_TRAITS_MEMBER(phased_snapshots) IPC_STRUCT_TRAITS_MEMBER(process_id) IPC_STRUCT_TRAITS_END() @@ -103,8 +103,14 @@ // Send to all the child processes to send back profiler data (ThreadData in // tracked_objects). -IPC_MESSAGE_CONTROL1(ChildProcessMsg_GetChildProfilerData, - int /* sequence_number */) +IPC_MESSAGE_CONTROL2(ChildProcessMsg_GetChildProfilerData, + int /* sequence_number */, + int /* current_profiling_phase */) + +// Send to all the child processes to mark the current profiling phase as +// finished and start a new phase. +IPC_MESSAGE_CONTROL1(ChildProcessMsg_ProfilingPhaseCompleted, + int /* profiling_phase */) // Send to all the child processes to send back histogram data. IPC_MESSAGE_CONTROL1(ChildProcessMsg_GetChildHistogramData,
diff --git a/content/common/dwrite_font_platform_win.cc b/content/common/dwrite_font_platform_win.cc index 3a9deaac..d80b618 100644 --- a/content/common/dwrite_font_platform_win.cc +++ b/content/common/dwrite_font_platform_win.cc
@@ -153,19 +153,18 @@ : in_collection_building_mode_(false), create_static_cache_(false) {} - virtual ~FontCollectionLoader(); + ~FontCollectionLoader() override; HRESULT RuntimeClassInitialize() { return S_OK; } // IDWriteFontCollectionLoader methods. - virtual HRESULT STDMETHODCALLTYPE - CreateEnumeratorFromKey( - IDWriteFactory* factory, - void const* key, - UINT32 key_size, - IDWriteFontFileEnumerator** file_enumerator) override; + HRESULT STDMETHODCALLTYPE + CreateEnumeratorFromKey(IDWriteFactory* factory, + void const* key, + UINT32 key_size, + IDWriteFontFileEnumerator** file_enumerator) override; // Does all the initialization for required loading fonts from registry. static HRESULT Initialize(IDWriteFactory* factory); @@ -493,7 +492,7 @@ IDWriteFontFileStream> { public: // IDWriteFontFileStream methods. - virtual HRESULT STDMETHODCALLTYPE ReadFileFragment( + HRESULT STDMETHODCALLTYPE ReadFileFragment( void const** fragment_start, UINT64 file_offset, UINT64 fragment_size, @@ -526,9 +525,9 @@ return S_OK; } - virtual void STDMETHODCALLTYPE ReleaseFileFragment(void* context) override {} + void STDMETHODCALLTYPE ReleaseFileFragment(void* context) override {} - virtual HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* file_size) override { + HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* file_size) override { if (cached_data_) { *file_size = g_font_loader->GetCachedFileSize(font_key_); return S_OK; @@ -541,8 +540,7 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime( - UINT64* last_write_time) override { + HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* last_write_time) override { if (cached_data_) { *last_write_time = 0; return S_OK; @@ -623,7 +621,7 @@ IDWriteFontFileLoader> { public: // IDWriteFontFileLoader methods. - virtual HRESULT STDMETHODCALLTYPE + HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const* ref_key, UINT32 ref_key_size, IDWriteFontFileStream** stream) override { @@ -642,7 +640,7 @@ } FontFileLoader() {} - virtual ~FontFileLoader() {} + ~FontFileLoader() override {} private: DISALLOW_COPY_AND_ASSIGN(FontFileLoader); @@ -654,7 +652,7 @@ IDWriteFontFileEnumerator> { public: // IDWriteFontFileEnumerator methods. - virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* has_current_file) override { + HRESULT STDMETHODCALLTYPE MoveNext(BOOL* has_current_file) override { *has_current_file = FALSE; if (current_file_) @@ -673,7 +671,7 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE + HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** font_file) override { if (!current_file_) { *font_file = NULL; @@ -690,7 +688,7 @@ IDWriteFontFileLoader* file_loader) : factory_(factory), file_loader_(file_loader), font_idx_(0) {} - virtual ~FontFileEnumerator() {} + ~FontFileEnumerator() override {} mswr::ComPtr<IDWriteFactory> factory_; mswr::ComPtr<IDWriteFontFile> current_file_;
diff --git a/content/common/font_cache_dispatcher_win.h b/content/common/font_cache_dispatcher_win.h index 357aed6..3d3d370 100644 --- a/content/common/font_cache_dispatcher_win.h +++ b/content/common/font_cache_dispatcher_win.h
@@ -20,16 +20,16 @@ class FontCacheDispatcher : public IPC::MessageFilter, public IPC::Sender { public: FontCacheDispatcher(); - virtual ~FontCacheDispatcher(); + ~FontCacheDispatcher() override; // IPC::Sender implementation: - virtual bool Send(IPC::Message* message) override; + bool Send(IPC::Message* message) override; private: // IPC::MessageFilter implementation: - virtual void OnFilterAdded(IPC::Sender* sender) override; - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void OnChannelClosing() override; + void OnFilterAdded(IPC::Sender* sender) override; + bool OnMessageReceived(const IPC::Message& message) override; + void OnChannelClosing() override; // Message handlers. void OnPreCacheFont(const LOGFONT& font);
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 8b195e2..cd8dfdc 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -124,6 +124,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::FrameNavigateParams) IPC_STRUCT_TRAITS_MEMBER(page_id) + IPC_STRUCT_TRAITS_MEMBER(nav_entry_id) IPC_STRUCT_TRAITS_MEMBER(url) IPC_STRUCT_TRAITS_MEMBER(base_url) IPC_STRUCT_TRAITS_MEMBER(referrer) @@ -142,6 +143,15 @@ content::FrameNavigateParams) IPC_STRUCT_TRAITS_PARENT(content::FrameNavigateParams) + // This is the value from the browser indicated whether it intended to make a + // new entry. TODO(avi): Remove this when the pending entry situation is made + // sane and the browser keeps them around long enough to match them via + // nav_entry_id. + IPC_STRUCT_MEMBER(bool, intended_as_new_entry) + + // Whether this commit created a new entry. + IPC_STRUCT_MEMBER(bool, did_create_new_entry) + // Information regarding the security of the connection (empty if the // connection was not secure). IPC_STRUCT_MEMBER(std::string, security_info) @@ -270,10 +280,11 @@ IPC_STRUCT_TRAITS_MEMBER(browser_navigation_start) IPC_STRUCT_TRAITS_MEMBER(redirects) IPC_STRUCT_TRAITS_MEMBER(can_load_local_resources) - IPC_STRUCT_TRAITS_MEMBER(frame_to_navigate) IPC_STRUCT_TRAITS_MEMBER(request_time) IPC_STRUCT_TRAITS_MEMBER(page_state) IPC_STRUCT_TRAITS_MEMBER(page_id) + IPC_STRUCT_TRAITS_MEMBER(nav_entry_id) + IPC_STRUCT_TRAITS_MEMBER(intended_as_new_entry) IPC_STRUCT_TRAITS_MEMBER(pending_history_list_offset) IPC_STRUCT_TRAITS_MEMBER(current_history_list_offset) IPC_STRUCT_TRAITS_MEMBER(current_history_list_length) @@ -535,6 +546,10 @@ // changed in another process. IPC_MESSAGE_ROUTED1(FrameMsg_DidUpdateName, std::string /* name */) +// Update a proxy's replicated origin. Used when the frame is navigated to a +// new origin. +IPC_MESSAGE_ROUTED1(FrameMsg_DidUpdateOrigin, url::Origin /* origin */) + // Send to the RenderFrame to set text track style settings. // Sent for top-level frames. IPC_MESSAGE_ROUTED1(FrameMsg_SetTextTrackSettings,
diff --git a/content/common/frame_replication_state.h b/content/common/frame_replication_state.h index f6cfa94..77ec859 100644 --- a/content/common/frame_replication_state.h +++ b/content/common/frame_replication_state.h
@@ -48,15 +48,42 @@ FrameReplicationState(const std::string& name); ~FrameReplicationState(); - // Current serialized security origin of the frame. Unique origins are - // represented as the string "null" per RFC 6454. + // Current serialized security origin of the frame. Unique origins are + // represented as the string "null" per RFC 6454. This field is updated + // whenever a frame navigation commits. + // + // TODO(alexmos): For now, |origin| updates are immediately sent to all frame + // proxies when in --site-per-process mode. This isn't ideal, since Blink + // typically needs a proxy's origin only when performing security checks on + // the ancestors of a local frame. So, as a future improvement, we could + // delay sending origin updates to proxies until they have a local descendant + // (if ever). This would reduce leaking a user's browsing history into a + // compromized renderer. url::Origin origin; - // Current sandbox flags of the frame. + // Current sandbox flags of the frame. |sandbox_flags| are initialized for + // new child frames using the value of the <iframe> element's "sandbox" + // attribute. They are updated dynamically whenever a parent frame updates an + // <iframe>'s sandbox attribute via JavaScript. + // + // Updates to |sandbox_flags| are sent to proxies, but only after a + // subsequent navigation of the (sandboxed) frame, since the flags only take + // effect on navigation (see also FrameTreeNode::effective_sandbox_flags_). + // The proxies need updated flags so that they can be inherited properly if a + // proxy ever becomes a parent of a local frame. SandboxFlags sandbox_flags; // The assigned name of the frame. This name can be empty, unlike the unique // name generated internally in the DOM tree. + // + // |name| is set when a new child frame is created using the value of the + // <iframe> element's "name" attribute (see + // RenderFrameHostImpl::OnCreateChildFrame), and it is updated dynamically + // whenever a frame sets its window.name. + // + // |name| updates are immediately sent to all frame proxies (when in + // --site-per-process mode), so that other frames can look up or navigate a + // frame using its updated name (e.g., using window.open(url, frame_name)). std::string name; // TODO(alexmos): Eventually, this structure can also hold other state that
diff --git a/content/common/gpu/client/command_buffer_metrics.cc b/content/common/gpu/client/command_buffer_metrics.cc new file mode 100644 index 0000000..d16f276 --- /dev/null +++ b/content/common/gpu/client/command_buffer_metrics.cc
@@ -0,0 +1,153 @@ +// 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/gpu/client/command_buffer_metrics.h" + +#include "base/metrics/histogram.h" + +namespace content { + +namespace { + +enum CommandBufferContextLostReason { + // Don't add new values here. + CONTEXT_INIT_FAILED, + CONTEXT_LOST_GPU_CHANNEL_ERROR, + CONTEXT_PARSE_ERROR_INVALID_SIZE, + CONTEXT_PARSE_ERROR_OUT_OF_BOUNDS, + CONTEXT_PARSE_ERROR_UNKNOWN_COMMAND, + CONTEXT_PARSE_ERROR_INVALID_ARGS, + CONTEXT_PARSE_ERROR_GENERIC_ERROR, + CONTEXT_LOST_GUILTY, + CONTEXT_LOST_INNOCENT, + CONTEXT_LOST_UNKNOWN, + CONTEXT_LOST_OUT_OF_MEMORY, + CONTEXT_LOST_MAKECURRENT_FAILED, + // Add new values here and update _MAX_ENUM. + CONTEXT_LOST_REASON_MAX_ENUM = CONTEXT_LOST_MAKECURRENT_FAILED +}; + +CommandBufferContextLostReason GetContextLostReason( + gpu::error::Error error, + gpu::error::ContextLostReason reason) { + if (error == gpu::error::kLostContext) { + switch (reason) { + case gpu::error::kGuilty: + return CONTEXT_LOST_GUILTY; + case gpu::error::kInnocent: + return CONTEXT_LOST_INNOCENT; + case gpu::error::kUnknown: + return CONTEXT_LOST_UNKNOWN; + case gpu::error::kOutOfMemory: + return CONTEXT_LOST_OUT_OF_MEMORY; + case gpu::error::kMakeCurrentFailed: + return CONTEXT_LOST_MAKECURRENT_FAILED; + case gpu::error::kGpuChannelLost: + return CONTEXT_LOST_GPU_CHANNEL_ERROR; + } + } + switch (error) { + case gpu::error::kInvalidSize: + return CONTEXT_PARSE_ERROR_INVALID_SIZE; + case gpu::error::kOutOfBounds: + return CONTEXT_PARSE_ERROR_OUT_OF_BOUNDS; + case gpu::error::kUnknownCommand: + return CONTEXT_PARSE_ERROR_UNKNOWN_COMMAND; + case gpu::error::kInvalidArguments: + return CONTEXT_PARSE_ERROR_INVALID_ARGS; + case gpu::error::kGenericError: + return CONTEXT_PARSE_ERROR_GENERIC_ERROR; + case gpu::error::kDeferCommandUntilLater: + case gpu::error::kNoError: + case gpu::error::kLostContext: + NOTREACHED(); + return CONTEXT_LOST_UNKNOWN; + } + NOTREACHED(); + return CONTEXT_LOST_UNKNOWN; +} + +void RecordContextLost(CommandBufferContextType type, + CommandBufferContextLostReason reason) { + switch (type) { + case BROWSER_COMPOSITOR_ONSCREEN_CONTEXT: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.BrowserCompositor", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + case BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.BrowserMainThread", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + case RENDER_COMPOSITOR_CONTEXT: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.RenderCompositor", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + case RENDER_WORKER_CONTEXT: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.RenderWorker", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + case RENDERER_MAINTHREAD_CONTEXT: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.RenderMainThread", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + case GPU_VIDEO_ACCELERATOR_CONTEXT: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.VideoAccelerator", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + case OFFSCREEN_VIDEO_CAPTURE_CONTEXT: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.VideoCapture", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + case OFFSCREEN_CONTEXT_FOR_WEBGL: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.WebGL", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + case CONTEXT_TYPE_UNKNOWN: + UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.Unknown", reason, + CONTEXT_LOST_REASON_MAX_ENUM); + break; + } +} + +} // anonymous namespace + +std::string CommandBufferContextTypeToString(CommandBufferContextType type) { + switch (type) { + case OFFSCREEN_CONTEXT_FOR_TESTING: + return "Context-For-Testing"; + case BROWSER_COMPOSITOR_ONSCREEN_CONTEXT: + return "Compositor"; + case BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT: + return "Offscreen-MainThread"; + case RENDER_COMPOSITOR_CONTEXT: + return "RenderCompositor"; + case RENDER_WORKER_CONTEXT: + return "RenderWorker"; + case RENDERER_MAINTHREAD_CONTEXT: + return "Offscreen-MainThread"; + case GPU_VIDEO_ACCELERATOR_CONTEXT: + return "GPU-VideoAccelerator-Offscreen"; + case OFFSCREEN_VIDEO_CAPTURE_CONTEXT: + return "Offscreen-CaptureThread"; + case OFFSCREEN_CONTEXT_FOR_WEBGL: + return "Offscreen-For-WebGL"; + default: + NOTREACHED(); + return "unknown"; + } +} + +void UmaRecordContextInitFailed(CommandBufferContextType type) { + RecordContextLost(type, CONTEXT_INIT_FAILED); +} + +void UmaRecordContextLost(CommandBufferContextType type, + gpu::error::Error error, + gpu::error::ContextLostReason reason) { + CommandBufferContextLostReason converted_reason = + GetContextLostReason(error, reason); + RecordContextLost(type, converted_reason); +} + +} // namespace content
diff --git a/content/common/gpu/client/command_buffer_metrics.h b/content/common/gpu/client/command_buffer_metrics.h new file mode 100644 index 0000000..e198d8579 --- /dev/null +++ b/content/common/gpu/client/command_buffer_metrics.h
@@ -0,0 +1,37 @@ +// 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_GPU_CLIENT_COMMAND_BUFFER_METRICS_H_ +#define CONTENT_COMMON_GPU_CLIENT_COMMAND_BUFFER_METRICS_H_ + +#include <string> + +#include "gpu/command_buffer/common/constants.h" + +namespace content { + +enum CommandBufferContextType { + BROWSER_COMPOSITOR_ONSCREEN_CONTEXT, + BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT, + RENDER_COMPOSITOR_CONTEXT, + RENDER_WORKER_CONTEXT, + RENDERER_MAINTHREAD_CONTEXT, + GPU_VIDEO_ACCELERATOR_CONTEXT, + OFFSCREEN_VIDEO_CAPTURE_CONTEXT, + OFFSCREEN_CONTEXT_FOR_WEBGL, + CONTEXT_TYPE_UNKNOWN, + OFFSCREEN_CONTEXT_FOR_TESTING = CONTEXT_TYPE_UNKNOWN, +}; + +std::string CommandBufferContextTypeToString(CommandBufferContextType type); + +void UmaRecordContextInitFailed(CommandBufferContextType type); + +void UmaRecordContextLost(CommandBufferContextType type, + gpu::error::Error error, + gpu::error::ContextLostReason reason); + +} // namespace content + +#endif // CONTENT_COMMON_GPU_CLIENT_COMMAND_BUFFER_METRICS_H_
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc index 257e084..8ca94b32 100644 --- a/content/common/gpu/client/command_buffer_proxy_impl.cc +++ b/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -71,23 +71,24 @@ scoped_ptr<base::AutoLock> lock; if (lock_) lock.reset(new base::AutoLock(*lock_)); - OnDestroyed(gpu::error::kUnknown); + OnDestroyed(gpu::error::kGpuChannelLost, gpu::error::kLostContext); } -void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason) { +void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason, + gpu::error::Error error) { CheckLock(); // Prevent any further messages from being sent. channel_ = NULL; // When the client sees that the context is lost, they should delete this // CommandBufferProxyImpl and create a new one. - last_state_.error = gpu::error::kLostContext; + last_state_.error = error; last_state_.context_lost_reason = reason; - if (!channel_error_callback_.is_null()) { - channel_error_callback_.Run(); + if (!context_lost_callback_.is_null()) { + context_lost_callback_.Run(); // Avoid calling the error callback more than once. - channel_error_callback_.Reset(); + context_lost_callback_.Reset(); } } @@ -134,10 +135,10 @@ callback.Run(); } -void CommandBufferProxyImpl::SetChannelErrorCallback( +void CommandBufferProxyImpl::SetContextLostCallback( const base::Closure& callback) { CheckLock(); - channel_error_callback_ = callback; + context_lost_callback_ = callback; } bool CommandBufferProxyImpl::Initialize() {
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.h b/content/common/gpu/client/command_buffer_proxy_impl.h index 2da5bbc2..6e73c82 100644 --- a/content/common/gpu/client/command_buffer_proxy_impl.h +++ b/content/common/gpu/client/command_buffer_proxy_impl.h
@@ -120,7 +120,7 @@ int GetRouteID() const; bool ProduceFrontBuffer(const gpu::Mailbox& mailbox); - void SetChannelErrorCallback(const base::Closure& callback); + void SetContextLostCallback(const base::Closure& callback); typedef base::Callback<void(const gpu::MemoryAllocation&)> MemoryAllocationChangedCallback; @@ -175,7 +175,8 @@ // Message handlers: void OnUpdateState(const gpu::CommandBuffer::State& state); - void OnDestroyed(gpu::error::ContextLostReason reason); + void OnDestroyed(gpu::error::ContextLostReason reason, + gpu::error::Error error); void OnConsoleMessage(const GPUCommandBufferConsoleMessage& message); void OnSetMemoryAllocation(const gpu::MemoryAllocation& allocation); void OnSignalSyncPointAck(uint32 id); @@ -208,7 +209,7 @@ int32 last_put_offset_; int32 last_barrier_put_offset_; - base::Closure channel_error_callback_; + base::Closure context_lost_callback_; MemoryAllocationChangedCallback memory_allocation_changed_callback_;
diff --git a/content/common/gpu/client/context_provider_command_buffer.cc b/content/common/gpu/client/context_provider_command_buffer.cc index 439e14f4..8bfdc09 100644 --- a/content/common/gpu/client/context_provider_command_buffer.cc +++ b/content/common/gpu/client/context_provider_command_buffer.cc
@@ -39,18 +39,19 @@ scoped_refptr<ContextProviderCommandBuffer> ContextProviderCommandBuffer::Create( scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d, - const std::string& debug_name) { + CommandBufferContextType type) { if (!context3d) return NULL; - return new ContextProviderCommandBuffer(context3d.Pass(), debug_name); + return new ContextProviderCommandBuffer(context3d.Pass(), type); } ContextProviderCommandBuffer::ContextProviderCommandBuffer( scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d, - const std::string& debug_name) + CommandBufferContextType type) : context3d_(context3d.Pass()), - debug_name_(debug_name), + context_type_(type), + debug_name_(CommandBufferContextTypeToString(type)), destroyed_(false) { DCHECK(main_thread_checker_.CalledOnValidThread()); DCHECK(context3d_); @@ -93,6 +94,7 @@ if (lost_context_callback_proxy_) return true; + context3d_->SetContextType(context_type_); if (!context3d_->InitializeOnCurrentThread()) return false;
diff --git a/content/common/gpu/client/context_provider_command_buffer.h b/content/common/gpu/client/context_provider_command_buffer.h index 101c0a0..ee10bf1 100644 --- a/content/common/gpu/client/context_provider_command_buffer.h +++ b/content/common/gpu/client/context_provider_command_buffer.h
@@ -12,6 +12,7 @@ #include "cc/blink/context_provider_web_context.h" #include "cc/output/context_provider.h" #include "content/common/content_export.h" +#include "content/common/gpu/client/command_buffer_metrics.h" #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" namespace webkit { @@ -29,7 +30,7 @@ public: static scoped_refptr<ContextProviderCommandBuffer> Create( scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d, - const std::string& debug_name); + CommandBufferContextType type); CommandBufferProxyImpl* GetCommandBufferProxy(); @@ -58,7 +59,7 @@ protected: ContextProviderCommandBuffer( scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d, - const std::string& debug_name); + CommandBufferContextType type); ~ContextProviderCommandBuffer() override; void OnLostContext(); @@ -74,6 +75,7 @@ scoped_ptr<webkit::gpu::GrContextForWebGraphicsContext3D> gr_context_; cc::ContextProvider::Capabilities capabilities_; + CommandBufferContextType context_type_; std::string debug_name_; LostContextCallback lost_context_callback_;
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc index 0cf028f7..b06b06ec 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
@@ -97,10 +97,13 @@ host_(host), surface_id_(surface_id), active_url_(active_url), + context_type_(CONTEXT_TYPE_UNKNOWN), gpu_preference_(attributes.preferDiscreteGPU ? gfx::PreferDiscreteGpu : gfx::PreferIntegratedGpu), mem_limits_(limits), weak_ptr_factory_(this) { + if (attributes_.webGL) + context_type_ = OFFSCREEN_CONTEXT_FOR_WEBGL; if (share_context) { DCHECK(!attributes_.shareResources); share_group_ = share_context->share_group_; @@ -145,8 +148,8 @@ if (gl_ && attributes_.webGL) gl_->EnableFeatureCHROMIUM("webgl_enable_glsl_webgl_validation"); - command_buffer_->SetChannelErrorCallback( - base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnGpuChannelLost, + command_buffer_->SetContextLostCallback( + base::Bind(&WebGraphicsContext3DCommandBufferImpl::OnContextLost, weak_ptr_factory_.GetWeakPtr())); command_buffer_->SetOnConsoleMessageCallback( @@ -198,6 +201,7 @@ if (!command_buffer_) { DLOG(ERROR) << "GpuChannelHost failed to create command buffer."; + UmaRecordContextInitFailed(context_type_); return false; } @@ -207,6 +211,8 @@ // Initialize the command buffer. bool result = command_buffer_->Initialize(); LOG_IF(ERROR, !result) << "CommandBufferProxy::Initialize failed."; + if (!result) + UmaRecordContextInitFailed(context_type_); return result; } @@ -351,7 +357,7 @@ if (host_.get() && host_->IsLost()) return true; gpu::CommandBuffer::State state = command_buffer_->GetLastState(); - return state.error == gpu::error::kLostContext; + return gpu::error::IsError(state.error); } // static @@ -387,7 +393,10 @@ return GL_GUILTY_CONTEXT_RESET_ARB; case gpu::error::kInnocent: return GL_INNOCENT_CONTEXT_RESET_ARB; + case gpu::error::kOutOfMemory: + case gpu::error::kMakeCurrentFailed: case gpu::error::kUnknown: + case gpu::error::kGpuChannelLost: return GL_UNKNOWN_CONTEXT_RESET_ARB; } @@ -397,9 +406,9 @@ } // anonymous namespace -void WebGraphicsContext3DCommandBufferImpl::OnGpuChannelLost() { - context_lost_reason_ = convertReason( - command_buffer_->GetLastState().context_lost_reason); +void WebGraphicsContext3DCommandBufferImpl::OnContextLost() { + context_lost_reason_ = + convertReason(command_buffer_->GetLastState().context_lost_reason); if (context_lost_callback_) { context_lost_callback_->onContextLost(); } @@ -411,6 +420,9 @@ base::AutoLock lock(g_default_share_groups_lock.Get()); g_default_share_groups.Get().erase(host_.get()); } + + gpu::CommandBuffer::State state = command_buffer_->GetLastState(); + UmaRecordContextLost(context_type_, state.error, state.context_lost_reason); } } // namespace content
diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h index ea14d7f0..115e167d 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
@@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "content/common/content_export.h" +#include "content/common/gpu/client/command_buffer_metrics.h" #include "content/common/gpu/client/command_buffer_proxy_impl.h" #include "gpu/blink/webgraphicscontext3d_impl.h" #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h" @@ -150,6 +151,9 @@ virtual blink::WGC3Denum getGraphicsResetStatusARB(); + void SetContextType(CommandBufferContextType type) { + context_type_ = type; + } private: // These are the same error codes as used by EGL. enum Error { @@ -184,7 +188,7 @@ // unnecessary complexity at the moment. bool CreateContext(bool onscreen); - virtual void OnGpuChannelLost(); + virtual void OnContextLost(); bool lose_context_when_out_of_memory_; blink::WebGraphicsContext3D::Attributes attributes_; @@ -195,6 +199,7 @@ scoped_refptr<GpuChannelHost> host_; int32 surface_id_; GURL active_url_; + CommandBufferContextType context_type_; gfx::GpuPreference gpu_preference_;
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc index e14cf98..fd344da 100644 --- a/content/common/gpu/gpu_command_buffer_stub.cc +++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -201,6 +201,14 @@ use_virtualized_gl_context_ |= context_group_->feature_info()->workarounds().use_virtualized_gl_contexts; + + bool is_offscreen = surface_id_ == 0; + if (is_offscreen && initial_size_.IsEmpty()) { + // If we're an offscreen surface with zero width and/or height, set to a + // non-zero size so that we have a complete framebuffer for operations like + // glClear. + initial_size_ = gfx::Size(1, 1); + } } GpuCommandBufferStub::~GpuCommandBufferStub() { @@ -421,9 +429,11 @@ scheduler_.reset(); bool have_context = false; - if (decoder_ && command_buffer_ && - command_buffer_->GetLastState().error != gpu::error::kLostContext) - have_context = decoder_->MakeCurrent(); + if (decoder_) { + // Try to make the context current regardless of whether it was lost, so we + // don't leak resources. + have_context = decoder_->GetGLContext()->MakeCurrent(surface_.get()); + } FOR_EACH_OBSERVER(DestructionObserver, destruction_observers_, OnWillDestroyStub()); @@ -671,7 +681,7 @@ DCHECK(command_buffer_.get()); gpu::CommandBuffer::State state = command_buffer_->GetLastState(); IPC::Message* msg = new GpuCommandBufferMsg_Destroyed( - route_id_, state.context_lost_reason); + route_id_, state.context_lost_reason, state.error); msg->set_unblock(true); Send(msg); @@ -1089,7 +1099,7 @@ command_buffer_->SetContextLostReason(gpu::error::kUnknown); if (decoder_) - decoder_->LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB); + decoder_->MarkContextLost(gpu::error::kUnknown); command_buffer_->SetParseError(gpu::error::kLostContext); }
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h index d984ac39..6bdec50 100644 --- a/content/common/gpu/gpu_messages.h +++ b/content/common/gpu/gpu_messages.h
@@ -54,6 +54,7 @@ gfx::SURFACE_TYPE_LAST) IPC_ENUM_TRAITS_MAX_VALUE(gpu::MemoryAllocation::PriorityCutoff, gpu::MemoryAllocation::CUTOFF_LAST) +IPC_ENUM_TRAITS_MAX_VALUE(gpu::error::Error, gpu::error::kErrorLast) IPC_ENUM_TRAITS_MAX_VALUE(gpu::error::ContextLostReason, gpu::error::kContextLostReasonLast) IPC_ENUM_TRAITS_MAX_VALUE(media::VideoEncodeAccelerator::Error, @@ -552,8 +553,9 @@ // Tells the proxy that there was an error and the command buffer had to be // destroyed for some reason. -IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_Destroyed, - gpu::error::ContextLostReason /* reason */) +IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_Destroyed, + gpu::error::ContextLostReason, /* reason */ + gpu::error::Error /* error */) // Tells the browser that SwapBuffers returned and passes latency info IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SwapBuffersCompleted,
diff --git a/content/common/gpu/media/dxva_video_decode_accelerator.cc b/content/common/gpu/media/dxva_video_decode_accelerator.cc index 9431e71..e4bf077 100644 --- a/content/common/gpu/media/dxva_video_decode_accelerator.cc +++ b/content/common/gpu/media/dxva_video_decode_accelerator.cc
@@ -522,12 +522,12 @@ make_context_current_(make_context_current), codec_(media::kUnknownVideoCodec), decoder_thread_("DXVAVideoDecoderThread"), - weak_this_factory_(this), weak_ptr_(weak_this_factory_.GetWeakPtr()), pending_flush_(false), use_dx11_(false), dx11_video_format_converter_media_type_needs_init_(true), - gl_context_(gl_context) { + gl_context_(gl_context), + weak_this_factory_(this) { memset(&input_stream_info_, 0, sizeof(input_stream_info_)); memset(&output_stream_info_, 0, sizeof(output_stream_info_)); }
diff --git a/content/common/gpu/media/rendering_helper.cc b/content/common/gpu/media/rendering_helper.cc index 26d91244..f428ed6 100644 --- a/content/common/gpu/media/rendering_helper.cc +++ b/content/common/gpu/media/rendering_helper.cc
@@ -181,7 +181,7 @@ done->Signal(); } -RenderingHelper::RenderingHelper() { +RenderingHelper::RenderingHelper() : ignore_vsync_(false) { window_ = gfx::kNullAcceleratedWidget; Clear(); } @@ -241,6 +241,9 @@ platform_window_delegate_.reset(new RenderingHelper::StubOzoneDelegate()); window_ = platform_window_delegate_->accelerated_widget(); gfx::Size window_size(800, 600); + // Ignore the vsync provider by default. On ChromeOS this will be set + // accordingly based on the display configuration. + ignore_vsync_ = true; #if defined(OS_CHROMEOS) // We hold onto the main loop here to wait for the DisplayController // to give us the size of the display so we can create a window of @@ -257,9 +260,14 @@ display_configurator_->RemoveObserver(&display_setup_observer); gfx::Size framebuffer_size = display_configurator_->framebuffer_size(); - if (!framebuffer_size.IsEmpty()) + if (!framebuffer_size.IsEmpty()) { window_size = framebuffer_size; + ignore_vsync_ = false; + } #endif + if (ignore_vsync_) + DVLOG(1) << "Ignoring vsync provider"; + platform_window_delegate_->platform_window()->SetBounds( gfx::Rect(window_size)); @@ -471,7 +479,11 @@ // in VideoDecodeAcceleratorTest.TearDown(), while the |rendering_helper_| is // a member of that class. (See video_decode_accelerator_unittest.cc.) gfx::VSyncProvider* vsync_provider = gl_surface_->GetVSyncProvider(); - if (vsync_provider && frame_duration_ != base::TimeDelta()) + + // VSync providers rely on the underlying CRTC to get the timing. In headless + // mode the surface isn't associated with a CRTC so the vsync provider can not + // get the timing, meaning it will not call UpdateVsyncParameters() ever. + if (!ignore_vsync_ && vsync_provider && frame_duration_ != base::TimeDelta()) vsync_provider->GetVSyncParameters(base::Bind( &RenderingHelper::UpdateVSyncParameters, base::Unretained(this), done)); else @@ -703,7 +715,7 @@ // in VideoDecodeAcceleratorTest.TearDown(), while the |rendering_helper_| is // a member of that class. (See video_decode_accelerator_unittest.cc.) gfx::VSyncProvider* vsync_provider = gl_surface_->GetVSyncProvider(); - if (vsync_provider) { + if (vsync_provider && !ignore_vsync_) { vsync_provider->GetVSyncParameters(base::Bind( &RenderingHelper::UpdateVSyncParameters, base::Unretained(this), static_cast<base::WaitableEvent*>(NULL)));
diff --git a/content/common/gpu/media/rendering_helper.h b/content/common/gpu/media/rendering_helper.h index 4292c747..31e5f7e 100644 --- a/content/common/gpu/media/rendering_helper.h +++ b/content/common/gpu/media/rendering_helper.h
@@ -197,6 +197,8 @@ #endif #endif + bool ignore_vsync_; + gfx::AcceleratedWidget window_; gfx::Size screen_size_;
diff --git a/content/common/gpu/media/video_encode_accelerator_unittest.cc b/content/common/gpu/media/video_encode_accelerator_unittest.cc index 73e319af..c0f4508 100644 --- a/content/common/gpu/media/video_encode_accelerator_unittest.cc +++ b/content/common/gpu/media/video_encode_accelerator_unittest.cc
@@ -52,9 +52,6 @@ // Maximum delay between requesting a keyframe and receiving one, in frames. // Arbitrarily chosen as a reasonable requirement. const unsigned int kMaxKeyframeDelay = 4; -// Value to use as max frame number for keyframe detection. -const unsigned int kMaxFrameNum = - std::numeric_limits<unsigned int>::max() - kMaxKeyframeDelay; // Default initial bitrate. const uint32 kDefaultBitrate = 2000000; // Default ratio of requested_subsequent_bitrate to initial_bitrate @@ -301,7 +298,6 @@ 0U) << "Stream byte size is not a product of calculated frame byte size"; CHECK_GT(test_stream->num_frames, 0UL); - CHECK_LE(test_stream->num_frames, kMaxFrameNum); } // Parse |data| into its constituent parts, set the various output fields @@ -709,7 +705,7 @@ save_to_file_(save_to_file), keyframe_period_(keyframe_period), num_keyframes_requested_(0), - next_keyframe_at_(kMaxFrameNum), + next_keyframe_at_(0), force_bitrate_(force_bitrate), current_requested_bitrate_(0), current_framerate_(0), @@ -1101,15 +1097,18 @@ // earlier than we requested one (in time), and not later than // kMaxKeyframeDelay frames after the frame, for which we requested // it, comes back encoded. - EXPECT_LE(num_encoded_frames_, next_keyframe_at_ + kMaxKeyframeDelay); - if (keyframe) { - if (num_keyframes_requested_ > 0) + if (num_keyframes_requested_ > 0 && + num_encoded_frames_ > next_keyframe_at_) { --num_keyframes_requested_; - next_keyframe_at_ += keyframe_period_; + next_keyframe_at_ += keyframe_period_; + } seen_keyframe_in_this_buffer_ = true; } + if (num_keyframes_requested_ > 0) + EXPECT_LE(num_encoded_frames_, next_keyframe_at_ + kMaxKeyframeDelay); + if (num_encoded_frames_ == num_frames_to_encode_ / 2) { VerifyStreamProperties(); if (requested_subsequent_bitrate_ != current_requested_bitrate_ ||
diff --git a/content/common/navigation_params.cc b/content/common/navigation_params.cc index 0e8df3c9..57149de 100644 --- a/content/common/navigation_params.cc +++ b/content/common/navigation_params.cc
@@ -84,6 +84,8 @@ can_load_local_resources(false), request_time(base::Time::Now()), page_id(-1), + nav_entry_id(0), + intended_as_new_entry(false), pending_history_list_offset(-1), current_history_list_offset(-1), current_history_list_length(0), @@ -95,10 +97,11 @@ base::TimeTicks navigation_start, const std::vector<GURL>& redirects, bool can_load_local_resources, - const std::string& frame_to_navigate, base::Time request_time, const PageState& page_state, int32 page_id, + int nav_entry_id, + bool intended_as_new_entry, int pending_history_list_offset, int current_history_list_offset, int current_history_list_length, @@ -107,10 +110,11 @@ browser_navigation_start(navigation_start), redirects(redirects), can_load_local_resources(can_load_local_resources), - frame_to_navigate(frame_to_navigate), request_time(request_time), page_state(page_state), page_id(page_id), + nav_entry_id(nav_entry_id), + intended_as_new_entry(intended_as_new_entry), pending_history_list_offset(pending_history_list_offset), current_history_list_offset(current_history_list_offset), current_history_list_length(current_history_list_length),
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h index ce34bcc..90eb70e 100644 --- a/content/common/navigation_params.h +++ b/content/common/navigation_params.h
@@ -166,10 +166,11 @@ base::TimeTicks navigation_start, const std::vector<GURL>& redirects, bool can_load_local_resources, - const std::string& frame_to_navigate, base::Time request_time, const PageState& page_state, int32 page_id, + int nav_entry_id, + bool intended_as_new_entry, int pending_history_list_offset, int current_history_list_offset, int current_history_list_length, @@ -190,9 +191,6 @@ // resources. bool can_load_local_resources; - // If not empty, which frame to navigate. - std::string frame_to_navigate; - // The time the request was created. This is used by the old performance // infrastructure to set up DocumentState associated with the RenderView. // TODO(ppi): make it go away. @@ -207,6 +205,18 @@ // FrameHostMsg_DidCommitProvisionalLoad message. int32 page_id; + // For browser-initiated navigations, this is the unique id of the + // NavigationEntry being navigated to. (For renderer-initiated navigations it + // is 0.) If the load succeeds, then this nav_entry_id will be reflected in + // the resulting FrameHostMsg_DidCommitProvisionalLoad message. + int nav_entry_id; + + // For browser-initiated navigations, this is true if this is a new entry + // being navigated to. This is false otherwise. TODO(avi): Remove this when + // the pending entry situation is made sane and the browser keeps them around + // long enough to match them via nav_entry_id, above. + bool intended_as_new_entry; + // For history navigations, this is the offset in the history list of the // pending load. For non-history navigations, this will be ignored. int pending_history_list_offset;
diff --git a/content/common/origin_util.cc b/content/common/origin_util.cc new file mode 100644 index 0000000..8ae7bec --- /dev/null +++ b/content/common/origin_util.cc
@@ -0,0 +1,62 @@ +// 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/public/common/origin_util.h" + +#include "base/lazy_instance.h" +#include "base/stl_util.h" +#include "content/public/common/content_client.h" +#include "net/base/net_util.h" +#include "url/gurl.h" + +namespace content { + +namespace { + +class SecureSchemeAndOriginSet { + public: + SecureSchemeAndOriginSet() { Reset(); } + ~SecureSchemeAndOriginSet() {} + + void Reset() { + GetContentClient()->AddSecureSchemesAndOrigins(&schemes_, &origins_); + } + + const std::set<std::string>& schemes() const { return schemes_; } + const std::set<GURL>& origins() const { return origins_; } + + private: + std::set<std::string> schemes_; + std::set<GURL> origins_; + DISALLOW_COPY_AND_ASSIGN(SecureSchemeAndOriginSet); +}; + +base::LazyInstance<SecureSchemeAndOriginSet>::Leaky g_trustworthy_whitelist = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +bool IsOriginSecure(const GURL& url) { + if (url.SchemeIsCryptographic() || url.SchemeIsFile()) + return true; + + if (url.SchemeIsFileSystem() && url.inner_url() && + IsOriginSecure(*url.inner_url())) { + return true; + } + + std::string hostname = url.HostNoBrackets(); + if (net::IsLocalhost(hostname)) + return true; + + if (ContainsKey(g_trustworthy_whitelist.Get().schemes(), url.scheme())) + return true; + + if (ContainsKey(g_trustworthy_whitelist.Get().origins(), url.GetOrigin())) + return true; + + return false; +} + +} // namespace content
diff --git a/content/common/origin_util_unittest.cc b/content/common/origin_util_unittest.cc new file mode 100644 index 0000000..2991a9d9 --- /dev/null +++ b/content/common/origin_util_unittest.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 "base/basictypes.h" +#include "content/public/common/origin_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace content { + +TEST(URLSchemesTest, IsOriginSecure) { + EXPECT_TRUE(IsOriginSecure(GURL("file:///test/fun.html"))); + EXPECT_TRUE(IsOriginSecure(GURL("file:///test/"))); + + EXPECT_TRUE(IsOriginSecure(GURL("https://example.com/fun.html"))); + EXPECT_FALSE(IsOriginSecure(GURL("http://example.com/fun.html"))); + + EXPECT_TRUE(IsOriginSecure(GURL("wss://example.com/fun.html"))); + EXPECT_FALSE(IsOriginSecure(GURL("ws://example.com/fun.html"))); + + EXPECT_TRUE(IsOriginSecure(GURL("http://localhost/fun.html"))); + EXPECT_FALSE(IsOriginSecure(GURL("http://localhost.com/fun.html"))); + EXPECT_TRUE(IsOriginSecure(GURL("https://localhost.com/fun.html"))); + + EXPECT_TRUE(IsOriginSecure(GURL("http://127.0.0.1/fun.html"))); + EXPECT_TRUE(IsOriginSecure(GURL("ftp://127.0.0.1/fun.html"))); + EXPECT_TRUE(IsOriginSecure(GURL("http://127.3.0.1/fun.html"))); + EXPECT_FALSE(IsOriginSecure(GURL("http://127.example.com/fun.html"))); + EXPECT_TRUE(IsOriginSecure(GURL("https://127.example.com/fun.html"))); + + EXPECT_TRUE(IsOriginSecure(GURL("http://[::1]/fun.html"))); + EXPECT_FALSE(IsOriginSecure(GURL("http://[::2]/fun.html"))); + EXPECT_FALSE(IsOriginSecure(GURL("http://[::1].example.com/fun.html"))); + + EXPECT_FALSE( + IsOriginSecure(GURL("filesystem:http://www.example.com/temporary/"))); + EXPECT_FALSE( + IsOriginSecure(GURL("filesystem:ftp://www.example.com/temporary/"))); + EXPECT_TRUE(IsOriginSecure(GURL("filesystem:ftp://127.0.0.1/temporary/"))); + EXPECT_TRUE( + IsOriginSecure(GURL("filesystem:https://www.example.com/temporary/"))); +} + +} // namespace content
diff --git a/content/common/page_state_serialization_unittest.cc b/content/common/page_state_serialization_unittest.cc index 6dc775a..38f04f8 100644 --- a/content/common/page_state_serialization_unittest.cc +++ b/content/common/page_state_serialization_unittest.cc
@@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <math.h> +#include <cmath> #include "base/base64.h" #include "base/files/file_util.h" -#include "base/float_util.h" #include "base/path_service.h" #include "base/pickle.h" #include "base/strings/string_util.h" @@ -47,8 +46,8 @@ EXPECT_EQ(a.filesystem_url, b.filesystem_url); EXPECT_EQ(a.file_start, b.file_start); EXPECT_EQ(a.file_length, b.file_length); - if (!(base::IsNaN(a.file_modification_time) && - base::IsNaN(b.file_modification_time))) { + if (!(std::isnan(a.file_modification_time) && + std::isnan(b.file_modification_time))) { EXPECT_DOUBLE_EQ(a.file_modification_time, b.file_modification_time); } EXPECT_EQ(a.blob_uuid, b.blob_uuid);
diff --git a/content/common/presentation/presentation_service.mojom b/content/common/presentation/presentation_service.mojom index 36756e2..91da501 100644 --- a/content/common/presentation/presentation_service.mojom +++ b/content/common/presentation/presentation_service.mojom
@@ -52,7 +52,7 @@ // call, the embedder may queue it and run the callback when the call is // performed. ListenForDefaultSessionStart() - => (PresentationSessionInfo defaultSessionInfo); + => (PresentationSessionInfo? defaultSessionInfo); // Called when startSession() is called by the frame. The result callback // will return a non-null and valid PresentationSessionInfo if starting the
diff --git a/content/common/sandbox_mac_system_access_unittest.mm b/content/common/sandbox_mac_system_access_unittest.mm index 1d5f1d4..8a6c1d3 100644 --- a/content/common/sandbox_mac_system_access_unittest.mm +++ b/content/common/sandbox_mac_system_access_unittest.mm
@@ -156,7 +156,7 @@ // Test case for checking sandboxing of NSS initialization. class MacSandboxedNSSTestCase : public MacSandboxTestCase { public: - virtual bool SandboxedTest() override; + bool SandboxedTest() override; }; REGISTER_SANDBOX_TEST_CASE(MacSandboxedNSSTestCase);
diff --git a/content/common/service_worker/service_worker_status_code.cc b/content/common/service_worker/service_worker_status_code.cc index 589cb2b..51a58b0 100644 --- a/content/common/service_worker/service_worker_status_code.cc +++ b/content/common/service_worker/service_worker_status_code.cc
@@ -43,6 +43,8 @@ return "The ServiceWorker timed out"; case SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED: return "ServiceWorker script evaluation failed"; + case SERVICE_WORKER_ERROR_DISK_CACHE: + return "Disk cache error"; case SERVICE_WORKER_ERROR_MAX_VALUE: NOTREACHED(); }
diff --git a/content/common/service_worker/service_worker_status_code.h b/content/common/service_worker/service_worker_status_code.h index a923ceb..88c06098 100644 --- a/content/common/service_worker/service_worker_status_code.h +++ b/content/common/service_worker/service_worker_status_code.h
@@ -63,6 +63,9 @@ // An error occurred during initial script evaluation. SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED, + // Generic error to indicate failure to read/write the disk cache. + SERVICE_WORKER_ERROR_DISK_CACHE, + SERVICE_WORKER_ERROR_MAX_VALUE };
diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 87c7a71a..ee1d740 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi
@@ -966,10 +966,14 @@ 'browser/media/audio_state_provider.h', 'browser/media/audio_stream_monitor.cc', 'browser/media/audio_stream_monitor.h', + 'browser/media/capture/animated_content_sampler.cc', + 'browser/media/capture/animated_content_sampler.h', 'browser/media/capture/audio_mirroring_manager.cc', 'browser/media/capture/audio_mirroring_manager.h', 'browser/media/capture/content_video_capture_device_core.cc', 'browser/media/capture/content_video_capture_device_core.h', + 'browser/media/capture/smooth_event_sampler.cc', + 'browser/media/capture/smooth_event_sampler.h', 'browser/media/capture/video_capture_oracle.cc', 'browser/media/capture/video_capture_oracle.h', 'browser/media/capture/web_contents_audio_input_stream.cc', @@ -1441,6 +1445,8 @@ 'browser/tracing/trace_message_filter.h', 'browser/tracing/tracing_controller_impl.cc', 'browser/tracing/tracing_controller_impl.h', + 'browser/tracing/tracing_controller_impl_data_sinks.cc', + 'browser/tracing/tracing_controller_impl_data_sinks.h', 'browser/tracing/tracing_ui.cc', 'browser/tracing/tracing_ui.h', 'browser/transition_request_manager.cc', @@ -1893,6 +1899,7 @@ '../media/media.gyp:media', '../mojo/mojo_base.gyp:libmojo_system_java', '../ui/android/ui_android.gyp:ui_android', + '../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu', 'content.gyp:content_jni_headers', ], 'defines': ['APPCACHE_USE_SIMPLE_CACHE'],
diff --git a/content/content_common.gypi b/content/content_common.gypi index c380dfb..d4ef54f 100644 --- a/content/content_common.gypi +++ b/content/content_common.gypi
@@ -89,6 +89,7 @@ 'public/common/mojo_channel_switches.h', 'public/common/navigator_connect_client.cc', 'public/common/navigator_connect_client.h', + 'public/common/origin_util.h', 'public/common/page_state.cc', 'public/common/page_state.h', 'public/common/page_type.h', @@ -266,6 +267,8 @@ 'common/gin_java_bridge_messages.h', 'common/gpu/client/command_buffer_proxy_impl.cc', 'common/gpu/client/command_buffer_proxy_impl.h', + 'common/gpu/client/command_buffer_metrics.cc', + 'common/gpu/client/command_buffer_metrics.h', 'common/gpu/client/context_provider_command_buffer.cc', 'common/gpu/client/context_provider_command_buffer.h', 'common/gpu/client/gl_helper.cc', @@ -436,6 +439,7 @@ 'common/one_writer_seqlock.cc', 'common/one_writer_seqlock.h', 'common/p2p_messages.h', + 'common/origin_util.cc', 'common/page_state_serialization.cc', 'common/page_state_serialization.h', 'common/page_zoom.cc',
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index fb2a7cf..b4afefe 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi
@@ -36,7 +36,6 @@ '../ui/native_theme/native_theme.gyp:native_theme', '../ui/surface/surface.gyp:surface', '../v8/tools/gyp/v8.gyp:v8', - '../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu', 'content_common_mojo_bindings.gyp:content_common_mojo_bindings', ], 'include_dirs': [
diff --git a/content/content_tests.gypi b/content/content_tests.gypi index 660e674..1e2390a0 100644 --- a/content/content_tests.gypi +++ b/content/content_tests.gypi
@@ -468,7 +468,9 @@ 'browser/loader/upload_data_stream_builder_unittest.cc', 'browser/mach_broker_mac_unittest.cc', 'browser/media/audio_stream_monitor_unittest.cc', + 'browser/media/capture/animated_content_sampler_unittest.cc', 'browser/media/capture/audio_mirroring_manager_unittest.cc', + 'browser/media/capture/smooth_event_sampler_unittest.cc', 'browser/media/capture/video_capture_oracle_unittest.cc', 'browser/media/capture/web_contents_audio_input_stream_unittest.cc', 'browser/media/capture/web_contents_video_capture_device_unittest.cc', @@ -617,6 +619,7 @@ 'common/inter_process_time_ticks_converter_unittest.cc', 'common/mac/attributed_string_coder_unittest.mm', 'common/mac/font_descriptor_unittest.mm', + 'common/origin_util_unittest.cc', 'common/one_writer_seqlock_unittest.cc', 'common/page_state_serialization_unittest.cc', 'common/page_zoom_unittest.cc', @@ -876,7 +879,6 @@ '../ui/compositor/compositor.gyp:compositor_test_support', '../ui/surface/surface.gyp:surface', '../v8/tools/gyp/v8.gyp:v8', - '../webkit/common/gpu/webkit_gpu.gyp:webkit_gpu', ], 'export_dependent_settings': [ '../third_party/WebKit/public/blink.gyp:blink', @@ -1966,6 +1968,8 @@ '../net/net.gyp:net_java', '../net/net.gyp:net_javatests', '../net/net.gyp:net_java_test_support', + '../testing/android/on_device_instrumentation.gyp:broker_java', + '../testing/android/on_device_instrumentation.gyp:require_driver_apk', '../third_party/mojo/mojo_public.gyp:mojo_public_test_interfaces', ], 'variables': {
diff --git a/content/gpu/BUILD.gn b/content/gpu/BUILD.gn index d43bb82..5ef0014e 100644 --- a/content/gpu/BUILD.gn +++ b/content/gpu/BUILD.gn
@@ -5,7 +5,22 @@ import("//build/config/ui.gni") import("//content/content.gni") -source_set("gpu") { +# See //content/BUILD.gn for how this works. +group("gpu") { + visibility = [ "//content/*" ] + + if (is_component_build) { + public_deps = [ + "//content", + ] + } else { + public_deps = [ + ":gpu_sources", + ] + } +} + +source_set("gpu_sources") { visibility = [ "//content/*" ] sources = [
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc index d17c9a09..1b16afe 100644 --- a/content/gpu/gpu_main.cc +++ b/content/gpu/gpu_main.cc
@@ -155,16 +155,9 @@ bool dead_on_arrival = false; #if defined(OS_WIN) - base::MessageLoop::Type message_loop_type = base::MessageLoop::TYPE_IO; - // Unless we're running on desktop GL, we don't need a UI message - // loop, so avoid its use to work around apparent problems with some - // third-party software. - if (command_line.HasSwitch(switches::kUseGL) && - command_line.GetSwitchValueASCII(switches::kUseGL) == - gfx::kGLImplementationDesktopName) { - message_loop_type = base::MessageLoop::TYPE_UI; - } - base::MessageLoop main_message_loop(message_loop_type); + // Use a UI message loop because ANGLE and the desktop GL platform can + // create child windows to render to. + base::MessageLoop main_message_loop(base::MessageLoop::TYPE_UI); #elif defined(OS_LINUX) && defined(USE_X11) // We need a UI loop so that we can grab the Expose events. See GLSurfaceGLX // and https://crbug.com/326995.
diff --git a/content/ppapi_plugin/BUILD.gn b/content/ppapi_plugin/BUILD.gn index 971a0604..b4a6704 100644 --- a/content/ppapi_plugin/BUILD.gn +++ b/content/ppapi_plugin/BUILD.gn
@@ -2,7 +2,21 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -source_set("ppapi_plugin") { +group("ppapi_plugin") { + visibility = [ "//content/*" ] + + if (is_component_build) { + public_deps = [ + "//content", + ] + } else { + public_deps = [ + ":ppapi_plugin_sources", + ] + } +} + +source_set("ppapi_plugin_sources") { visibility = [ "//content/*" ] sources = [
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ServiceRegistryTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ServiceRegistryTest.java index a0b8d42..4947f26 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ServiceRegistryTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ServiceRegistryTest.java
@@ -136,7 +136,7 @@ // Perform a few operations on the Calculator. Calculator.Proxy calculator = requestPair.first; CalcConnectionErrorHandler errorHandler = new CalcConnectionErrorHandler(); - calculator.setErrorHandler(errorHandler); + calculator.getProxyHandler().setErrorHandler(errorHandler); CalcCallback callback = new CalcCallback(); calculator.add(21, callback); @@ -163,7 +163,7 @@ Calculator.MANAGER.getInterfaceRequest(mCore); Calculator.Proxy calculator = requestPair.first; CalcConnectionErrorHandler errorHandler = new CalcConnectionErrorHandler(); - calculator.setErrorHandler(errorHandler); + calculator.getProxyHandler().setErrorHandler(errorHandler); mCloseablesToClose.add(calculator); serviceRegistryB.connectToRemoteService(Calculator.MANAGER, requestPair.second); @@ -192,7 +192,7 @@ requestPair = Calculator.MANAGER.getInterfaceRequest(mCore); calculator = requestPair.first; errorHandler = new CalcConnectionErrorHandler(); - calculator.setErrorHandler(errorHandler); + calculator.getProxyHandler().setErrorHandler(errorHandler); mCloseablesToClose.add(calculator); serviceRegistryB.connectToRemoteService(Calculator.MANAGER, requestPair.second);
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/VSyncMonitorTest.java b/content/public/android/javatests/src/org/chromium/content/browser/VSyncMonitorTest.java index eca3f1c3..61b9dfe 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/VSyncMonitorTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/VSyncMonitorTest.java
@@ -20,6 +20,8 @@ * Tests VSyncMonitor to make sure it generates correct VSync timestamps. */ public class VSyncMonitorTest extends InstrumentationTestCase { + private static final int FRAME_COUNT = 60; + private static class VSyncDataCollector implements VSyncMonitor.Listener { public long mFramePeriods[]; public int mFrameCount; @@ -69,28 +71,22 @@ // The vsync monitor must be created on the UI thread to avoid associating the underlying // Choreographer with the Looper from the test runner thread. - private VSyncMonitor createVSyncMonitor( - final VSyncMonitor.Listener listener, final boolean enableJBVSync) { + private VSyncMonitor createVSyncMonitor(final VSyncMonitor.Listener listener) { return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<VSyncMonitor>() { @Override public VSyncMonitor call() { Context context = getInstrumentation().getContext(); - return new VSyncMonitor(context, listener, enableJBVSync); + return new VSyncMonitor(context, listener); } }); } // Check that the vsync period roughly matches the timestamps that the monitor generates. - private void performVSyncPeriodTest(boolean enableJBVSync) throws InterruptedException { + @MediumTest + public void testVSyncPeriod() throws InterruptedException { // Collect roughly one second of data on a 60 fps display. - collectAndCheckVSync(enableJBVSync, 60); - } - - private void collectAndCheckVSync( - boolean enableJBVSync, final int totalFrames) - throws InterruptedException { - VSyncDataCollector collector = new VSyncDataCollector(totalFrames); - VSyncMonitor monitor = createVSyncMonitor(collector, enableJBVSync); + VSyncDataCollector collector = new VSyncDataCollector(FRAME_COUNT); + VSyncMonitor monitor = createVSyncMonitor(collector); long reportedFramePeriod = monitor.getVSyncPeriodInMicroseconds(); assertTrue(reportedFramePeriod > 0); @@ -101,7 +97,7 @@ assertTrue(collector.isDone()); // Check that the median frame rate is within 10% of the reported frame period. - assertTrue(collector.mFrameCount == totalFrames - 1); + assertTrue(collector.mFrameCount == FRAME_COUNT - 1); Arrays.sort(collector.mFramePeriods, 0, collector.mFramePeriods.length); long medianFramePeriod = collector.mFramePeriods[collector.mFramePeriods.length / 2]; if (Math.abs(medianFramePeriod - reportedFramePeriod) > reportedFramePeriod * .1) { @@ -110,34 +106,21 @@ + reportedFramePeriod + " for requested frames"); } - if (enableJBVSync) { - Context context = getInstrumentation().getContext(); - float refreshRate = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)) - .getDefaultDisplay().getRefreshRate(); - if (refreshRate < 30.0f) { - // Reported refresh rate is most likely incorrect. - // Estimated vsync period is expected to be lower than (1000000 / 30) microseconds - assertTrue(monitor.getVSyncPeriodInMicroseconds() < 1000000 / 30); - } + Context context = getInstrumentation().getContext(); + float refreshRate = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)) + .getDefaultDisplay().getRefreshRate(); + if (refreshRate < 30.0f) { + // Reported refresh rate is most likely incorrect. + // Estimated vsync period is expected to be lower than (1000000 / 30) microseconds + assertTrue(monitor.getVSyncPeriodInMicroseconds() < 1000000 / 30); } } - // Check that the vsync period roughly matches the timestamps that the monitor generates. @MediumTest - public void testVSyncPeriodAllowJBVSync() throws InterruptedException { - performVSyncPeriodTest(true); - } - - // Check that the vsync period roughly matches the timestamps that the monitor generates. - @MediumTest - public void testVSyncPeriodDisallowJBVSync() throws InterruptedException { - performVSyncPeriodTest(false); - } - - // Check that the vsync period roughly matches the timestamps that the monitor generates. - private void performVSyncActivationFromIdle(boolean enableJBVSync) throws InterruptedException { + public void testVSyncActivationFromIdle() throws InterruptedException { + // Check that the vsync period roughly matches the timestamps that the monitor generates. VSyncDataCollector collector = new VSyncDataCollector(1); - VSyncMonitor monitor = createVSyncMonitor(collector, enableJBVSync); + VSyncMonitor monitor = createVSyncMonitor(collector); monitor.requestUpdate(); collector.waitTillDone(); @@ -149,14 +132,4 @@ // The VSync should have activated immediately instead of at the next real vsync. assertTrue(delay < period); } - - @MediumTest - public void testVSyncActivationFromIdleAllowJBVSync() throws InterruptedException { - performVSyncActivationFromIdle(true); - } - - @MediumTest - public void testVSyncActivationFromIdleDisallowJBVSync() throws InterruptedException { - performVSyncActivationFromIdle(false); - } }
diff --git a/content/public/browser/navigation_entry.h b/content/public/browser/navigation_entry.h index 480fa6b..08fe6604 100644 --- a/content/public/browser/navigation_entry.h +++ b/content/public/browser/navigation_entry.h
@@ -183,12 +183,6 @@ virtual void SetCanLoadLocalResources(bool allow) = 0; virtual bool GetCanLoadLocalResources() const = 0; - // Used to specify which frame to navigate. If empty, the main frame is - // navigated. This is currently not persisted in session restore, because it - // is currently only used in tests. - virtual void SetFrameToNavigate(const std::string& frame_name) = 0; - virtual const std::string& GetFrameToNavigate() const = 0; - // Set extra data on this NavigationEntry according to the specified |key|. // This data is not persisted by default. virtual void SetExtraData(const std::string& key,
diff --git a/content/public/browser/presentation_service_delegate.h b/content/public/browser/presentation_service_delegate.h index 817cd28..fd82045 100644 --- a/content/public/browser/presentation_service_delegate.h +++ b/content/public/browser/presentation_service_delegate.h
@@ -23,6 +23,13 @@ // Called when the PresentationServiceDelegate is being destroyed. virtual void OnDelegateDestroyed() = 0; + // Called when the default presentation has been started outside of a + // Presentation API context (e.g., browser action). This will not be called + // if the session was created as a result of Presentation API's + // StartSession()/JoinSession(). + virtual void OnDefaultPresentationStarted( + const PresentationSessionInfo& session) = 0; + protected: virtual ~Observer() {} }; @@ -34,12 +41,19 @@ virtual ~PresentationServiceDelegate() {} - // Registers an observer with this class to listen for updates to this class. + // Registers an observer associated with frame with |render_process_id| + // and |render_frame_id| with this class to listen for updates. // This class does not own the observer. - // It is an error to add an observer if it has already been added before. - virtual void AddObserver(Observer* observer) = 0; - // Unregisters an observer with this class. - virtual void RemoveObserver(Observer* observer) = 0; + // It is an error to add an observer if there is already an observer for that + // frame. + virtual void AddObserver(int render_process_id, + int render_frame_id, + Observer* observer) = 0; + + // Unregisters the observer associated with the frame with |render_process_id| + // and |render_frame_id|. + // The observer will no longer receive updates. + virtual void RemoveObserver(int render_process_id, int render_frame_id) = 0; // Registers |listener| to continuously listen for // availability updates for a presentation URL, originated from the frame
diff --git a/content/public/browser/profiler_controller.h b/content/public/browser/profiler_controller.h index 25d4351e..34ac03f 100644 --- a/content/public/browser/profiler_controller.h +++ b/content/public/browser/profiler_controller.h
@@ -42,7 +42,14 @@ virtual void Unregister(const ProfilerSubscriber* subscriber) = 0; // Contact all processes and get their profiler data. - virtual void GetProfilerData(int sequence_number) = 0; + // |current_profiling_phase| is the 0-indexed identifier of the current + // profiling phase. + virtual void GetProfilerData(int sequence_number, + int current_profiling_phase) = 0; + + // Contact child processes and notify them that the |profiling_phase| has + // completed. + virtual void OnProfilingPhaseCompleted(int profiling_phase) = 0; }; } // namespace content
diff --git a/content/public/browser/tracing_controller.h b/content/public/browser/tracing_controller.h index 0cbed70..37ac2f75 100644 --- a/content/public/browser/tracing_controller.h +++ b/content/public/browser/tracing_controller.h
@@ -45,11 +45,29 @@ virtual ~TraceDataSink() {} }; + // An implementation of this interface is passed when constructing a + // TraceDataSink, and receives chunks of the final trace data as it's being + // constructed. + // Methods may be called from any thread. + class CONTENT_EXPORT TraceDataEndpoint + : public base::RefCountedThreadSafe<TraceDataEndpoint> { + public: + virtual void ReceiveTraceChunk(const std::string& chunk) {} + virtual void ReceiveTraceFinalContents(const std::string& contents) {} + + protected: + friend class base::RefCountedThreadSafe<TraceDataEndpoint>; + virtual ~TraceDataEndpoint() {} + }; + // Create a trace sink that may be supplied to DisableRecording or // CaptureMonitoringSnapshot to capture the trace data as a string. CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateStringSink( const base::Callback<void(base::RefCountedString*)>& callback); + CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateCompressedStringSink( + scoped_refptr<TraceDataEndpoint> endpoint); + // Create a trace sink that may be supplied to DisableRecording or // CaptureMonitoringSnapshot to dump the trace data to a file. CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateFileSink(
diff --git a/content/public/common/content_client.cc b/content/public/common/content_client.cc index 425c40ff2..421a0a3 100644 --- a/content/public/common/content_client.cc +++ b/content/public/common/content_client.cc
@@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/strings/string_piece.h" +#include "content/public/common/origin_util.h" #include "content/public/common/user_agent.h" #include "ui/gfx/image/image.h"
diff --git a/content/public/common/content_client.h b/content/public/common/content_client.h index 13f0d5c..9b9ceba 100644 --- a/content/public/common/content_client.h +++ b/content/public/common/content_client.h
@@ -5,6 +5,7 @@ #ifndef CONTENT_PUBLIC_COMMON_CONTENT_CLIENT_H_ #define CONTENT_PUBLIC_COMMON_CONTENT_CLIENT_H_ +#include <set> #include <string> #include <vector> @@ -134,6 +135,12 @@ int* sandbox_profile_resource_id) const; #endif + // Gives the embedder a chance to register additional schemes and origins + // that need to be considered trustworthy. + // See https://www.w3.org/TR/powerful-features/#is-origin-trustworthy. + virtual void AddSecureSchemesAndOrigins(std::set<std::string>* schemes, + std::set<GURL>* origins) {} + private: friend class ContentClientInitializer; // To set these pointers. friend class InternalTestInitializer;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 6672723..4bdb420 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -785,6 +785,11 @@ // Type of the current test harness ("browser" or "ui"). const char kTestType[] = "test-type"; +// Controls how text selection granularity changes when touch text selection +// handles are dragged. Should be "character" or "direction". If not specified, +// the platform default is used. +const char kTouchTextSelectionStrategy[] = "touch-selection-strategy"; + // Causes TRACE_EVENT flags to be recorded beginning with shutdown. Optionally, // can specify the specific trace categories to include (e.g. // --trace-shutdown=base,net) otherwise, all events are recorded.
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index a183e70e..ae8a2c6 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -217,6 +217,7 @@ CONTENT_EXPORT extern const char kTestingFixedHttpPort[]; CONTENT_EXPORT extern const char kTestingFixedHttpsPort[]; CONTENT_EXPORT extern const char kTestType[]; +CONTENT_EXPORT extern const char kTouchTextSelectionStrategy[]; CONTENT_EXPORT extern const char kTraceShutdown[]; extern const char kTraceShutdownFile[]; extern const char kTraceStartup[];
diff --git a/content/public/common/frame_navigate_params.cc b/content/public/common/frame_navigate_params.cc index 637cec53..1aef9e5 100644 --- a/content/public/common/frame_navigate_params.cc +++ b/content/public/common/frame_navigate_params.cc
@@ -8,6 +8,7 @@ FrameNavigateParams::FrameNavigateParams() : page_id(0), + nav_entry_id(0), transition(ui::PAGE_TRANSITION_LINK), should_update_history(false) { }
diff --git a/content/public/common/frame_navigate_params.h b/content/public/common/frame_navigate_params.h index b704b8e9..884a1d1 100644 --- a/content/public/common/frame_navigate_params.h +++ b/content/public/common/frame_navigate_params.h
@@ -27,6 +27,12 @@ // iframes are loaded automatically. int32 page_id; + // The unique ID of the NavigationEntry for browser-initiated navigations. + // This value was given to the render process in the HistoryNavigationParams + // and is being returned by the renderer without it having any idea what it + // means. If the navigation was renderer-initiated, this value is 0. + int nav_entry_id; + // URL of the page being loaded. GURL url;
diff --git a/content/public/common/origin_util.h b/content/public/common/origin_util.h new file mode 100644 index 0000000..c45977d9 --- /dev/null +++ b/content/public/common/origin_util.h
@@ -0,0 +1,23 @@ +// 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_PUBLIC_COMMON_ORIGIN_UTIL_H_ +#define CONTENT_PUBLIC_COMMON_ORIGIN_UTIL_H_ + +#include "content/common/content_export.h" + +class GURL; + +namespace content { + +// Returns true if the origin is trustworthy: that is, if its contents can be +// said to have been transferred to the browser in a way that a network attacker +// cannot tamper with or observe. +// +// See https://www.w3.org/TR/powerful-features/#is-origin-trustworthy. +bool CONTENT_EXPORT IsOriginSecure(const GURL& url); + +} // namespace content + +#endif // CONTENT_PUBLIC_COMMON_ORIGIN_UTIL_H_
diff --git a/content/public/common/referrer.cc b/content/public/common/referrer.cc index 225df96c..183c950 100644 --- a/content/public/common/referrer.cc +++ b/content/public/common/referrer.cc
@@ -19,8 +19,8 @@ return sanitized_referrer; } - bool is_downgrade = - sanitized_referrer.url.SchemeIsSecure() && !request.SchemeIsSecure(); + bool is_downgrade = sanitized_referrer.url.SchemeIsCryptographic() && + !request.SchemeIsCryptographic(); if (sanitized_referrer.policy < 0 || sanitized_referrer.policy > blink::WebReferrerPolicyLast) {
diff --git a/content/public/common/top_controls_state.h b/content/public/common/top_controls_state.h index 7f71e6e4..4223b63 100644 --- a/content/public/common/top_controls_state.h +++ b/content/public/common/top_controls_state.h
@@ -13,6 +13,8 @@ TOP_CONTROLS_STATE_SHOWN = 1, TOP_CONTROLS_STATE_HIDDEN = 2, TOP_CONTROLS_STATE_BOTH = 3, + + TOP_CONTROLS_STATE_LAST = TOP_CONTROLS_STATE_BOTH, }; } // namespace content
diff --git a/content/public/renderer/platform_event_observer.h b/content/public/renderer/platform_event_observer.h index 825c0fe..083007cf 100644 --- a/content/public/renderer/platform_event_observer.h +++ b/content/public/renderer/platform_event_observer.h
@@ -63,7 +63,7 @@ // The observer must automatically stop observing when destroyed in case it // did not stop before. Implementations of PlatformEventObserver must do // so by calling StopIfObserving() from their destructors. - virtual ~PlatformEventObserver() { + ~PlatformEventObserver() override { // If this assert fails, the derived destructor failed to invoke // StopIfObserving(). DCHECK(!is_observing()); @@ -71,7 +71,7 @@ // Called when a new IPC message is received. Must be used to listen to the // responses from the browser process if any expected. - virtual bool OnControlMessageReceived(const IPC::Message& msg) override { + bool OnControlMessageReceived(const IPC::Message& msg) override { return false; }
diff --git a/content/public/renderer/render_view_observer.h b/content/public/renderer/render_view_observer.h index 966a72c..6345aea5 100644 --- a/content/public/renderer/render_view_observer.h +++ b/content/public/renderer/render_view_observer.h
@@ -81,7 +81,6 @@ // These match the RenderView methods. virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) {} - virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) {} virtual void DidHandleGestureEvent(const blink::WebGestureEvent& event) {} // These match incoming IPCs.
diff --git a/content/public/test/content_test_suite_base.cc b/content/public/test/content_test_suite_base.cc index 0238a22..7598b0d 100644 --- a/content/public/test/content_test_suite_base.cc +++ b/content/public/test/content_test_suite_base.cc
@@ -53,7 +53,7 @@ public: ContentTestSuiteBaseListener() { } - virtual void OnTestEnd(const testing::TestInfo& test_info) override { + void OnTestEnd(const testing::TestInfo& test_info) override { BrowserThreadImpl::FlushThreadPoolHelperForTesting(); } private:
diff --git a/content/public/test/mock_download_item.h b/content/public/test/mock_download_item.h index 19ebe62..2b1f8b7 100644 --- a/content/public/test/mock_download_item.h +++ b/content/public/test/mock_download_item.h
@@ -19,13 +19,13 @@ class MockDownloadItem : public DownloadItem { public: MockDownloadItem(); - virtual ~MockDownloadItem(); + ~MockDownloadItem() override; // Management of observer lists is common in tests. So Add/RemoveObserver // methods are not mocks. In addition, any registered observers will receive a // OnDownloadDestroyed() notification when the mock is destroyed. - virtual void AddObserver(Observer* observer) override; - virtual void RemoveObserver(Observer* observer) override; + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; // Dispatches an OnDownloadOpened() notification to observers. void NotifyObserversDownloadOpened();
diff --git a/content/public/test/mock_download_manager.h b/content/public/test/mock_download_manager.h index b2e3ef1..a67c2e8 100644 --- a/content/public/test/mock_download_manager.h +++ b/content/public/test/mock_download_manager.h
@@ -71,7 +71,7 @@ }; MockDownloadManager(); - virtual ~MockDownloadManager(); + ~MockDownloadManager() override; // DownloadManager: MOCK_METHOD1(SetDelegate, void(DownloadManagerDelegate* delegate)); @@ -81,7 +81,7 @@ MOCK_METHOD1(Init, bool(BrowserContext* browser_context)); // Gasket for handling scoped_ptr arguments. - virtual void StartDownload( + void StartDownload( scoped_ptr<DownloadCreateInfo> info, scoped_ptr<ByteStreamReader> stream, const DownloadUrlParameters::OnStartedCallback& callback) override; @@ -93,14 +93,14 @@ MOCK_METHOD1(RemoveDownloads, int(base::Time remove_begin)); MOCK_METHOD0(RemoveAllDownloads, int()); MOCK_METHOD1(DownloadUrlMock, void(DownloadUrlParameters*)); - virtual void DownloadUrl(scoped_ptr<DownloadUrlParameters> params) override { + void DownloadUrl(scoped_ptr<DownloadUrlParameters> params) override { DownloadUrlMock(params.get()); } MOCK_METHOD1(AddObserver, void(Observer* observer)); MOCK_METHOD1(RemoveObserver, void(Observer* observer)); // Redirects to mock method to get around gmock 10 argument limit. - virtual DownloadItem* CreateDownloadItem( + DownloadItem* CreateDownloadItem( uint32 id, const base::FilePath& current_path, const base::FilePath& target_path,
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h index 95d7be88..3623ab59 100644 --- a/content/public/test/mock_render_thread.h +++ b/content/public/test/mock_render_thread.h
@@ -71,8 +71,8 @@ bool ResolveProxy(const GURL& url, std::string* proxy_list) override; base::WaitableEvent* GetShutdownEvent() override; #if defined(OS_WIN) - virtual void PreCacheFont(const LOGFONT& log_font) override; - virtual void ReleaseCachedFonts() override; + void PreCacheFont(const LOGFONT& log_font) override; + void ReleaseCachedFonts() override; #endif ServiceRegistry* GetServiceRegistry() override;
diff --git a/content/public/test/ppapi_test_utils.cc b/content/public/test/ppapi_test_utils.cc index 5717eda..7852d31 100644 --- a/content/public/test/ppapi_test_utils.cc +++ b/content/public/test/ppapi_test_utils.cc
@@ -9,9 +9,35 @@ #include "base/macros.h" #include "base/path_service.h" #include "content/public/common/content_switches.h" +#include "ppapi/shared_impl/ppapi_constants.h" namespace ppapi { +namespace { + +bool RegisterPlugin( + base::CommandLine* command_line, + const base::FilePath::StringType& library_name, + const base::FilePath::StringType& extra_registration_parameters) { + base::FilePath plugin_dir; + if (!PathService::Get(base::DIR_MODULE, &plugin_dir)) + return false; + + base::FilePath plugin_path = plugin_dir.Append(library_name); + + // Append the switch to register the pepper plugin. + if (!base::PathExists(plugin_path)) + return false; + base::FilePath::StringType pepper_plugin = plugin_path.value(); + pepper_plugin.append(extra_registration_parameters); + pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests")); + command_line->AppendSwitchNative(switches::kRegisterPepperPlugins, + pepper_plugin); + return true; +} + +} // namespace + std::string StripTestPrefixes(const std::string& test_name) { if (test_name.find("DISABLED_") == 0) return test_name.substr(strlen("DISABLED_")); @@ -26,27 +52,21 @@ bool RegisterTestPluginWithExtraParameters( base::CommandLine* command_line, const base::FilePath::StringType& extra_registration_parameters) { - base::FilePath plugin_dir; - if (!PathService::Get(base::DIR_MODULE, &plugin_dir)) - return false; - #if defined(OS_WIN) - base::FilePath plugin_path = plugin_dir.Append(L"ppapi_tests.dll"); + base::FilePath::StringType plugin_library = L"ppapi_tests.dll"; #elif defined(OS_MACOSX) - base::FilePath plugin_path = plugin_dir.Append("ppapi_tests.plugin"); + base::FilePath::StringType plugin_library = "ppapi_tests.plugin"; #elif defined(OS_POSIX) - base::FilePath plugin_path = plugin_dir.Append("libppapi_tests.so"); + base::FilePath::StringType plugin_library = "libppapi_tests.so"; #endif + return RegisterPlugin(command_line, plugin_library, + extra_registration_parameters); +} - // Append the switch to register the pepper plugin. - if (!base::PathExists(plugin_path)) - return false; - base::FilePath::StringType pepper_plugin = plugin_path.value(); - pepper_plugin.append(extra_registration_parameters); - pepper_plugin.append(FILE_PATH_LITERAL(";application/x-ppapi-tests")); - command_line->AppendSwitchNative(switches::kRegisterPepperPlugins, - pepper_plugin); - return true; +bool RegisterPowerSaverTestPlugin(base::CommandLine* command_line) { + base::FilePath::StringType library_name = + base::FilePath::FromUTF8Unsafe(ppapi::kPowerSaverTestPluginName).value(); + return RegisterPlugin(command_line, library_name, FILE_PATH_LITERAL("")); } } // namespace ppapi
diff --git a/content/public/test/ppapi_test_utils.h b/content/public/test/ppapi_test_utils.h index c5701bf..a57d62f 100644 --- a/content/public/test/ppapi_test_utils.h +++ b/content/public/test/ppapi_test_utils.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/compiler_specific.h" #include "base/files/file_path.h" namespace base { @@ -22,13 +23,19 @@ // Registers the PPAPI test plugin to application/x-ppapi-tests. Returns true // on success, and false otherwise. -bool RegisterTestPlugin(base::CommandLine* command_line); +bool RegisterTestPlugin(base::CommandLine* command_line) WARN_UNUSED_RESULT; // Registers the PPAPI test plugin with some some extra parameters. Returns true // on success and false otherwise. bool RegisterTestPluginWithExtraParameters( base::CommandLine* command_line, - const base::FilePath::StringType& extra_registration_parameters); + const base::FilePath::StringType& extra_registration_parameters) + WARN_UNUSED_RESULT; + +// Registers the Power Saver test plugin to application/x-ppapi-tests. +// Returns true on success, and false otherwise. +bool RegisterPowerSaverTestPlugin(base::CommandLine* command_line) + WARN_UNUSED_RESULT; } // namespace ppapi
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc index 1e1a048..1df34a8 100644 --- a/content/public/test/render_view_test.cc +++ b/content/public/test/render_view_test.cc
@@ -4,6 +4,8 @@ #include "content/public/test/render_view_test.h" +#include <cctype> + #include "base/run_loop.h" #include "components/scheduler/renderer/renderer_scheduler.h" #include "content/common/dom_storage/dom_storage_types.h" @@ -27,13 +29,16 @@ #include "content/test/test_content_client.h" #include "third_party/WebKit/public/platform/WebScreenInfo.h" #include "third_party/WebKit/public/platform/WebURLRequest.h" +#include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebHistoryItem.h" +#include "third_party/WebKit/public/web/WebInputElement.h" #include "third_party/WebKit/public/web/WebInputEvent.h" #include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebScriptSource.h" #include "third_party/WebKit/public/web/WebView.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/events/keycodes/keyboard_codes.h" #include "v8/include/v8.h" #if defined(OS_MACOSX) @@ -49,6 +54,7 @@ using blink::WebURLRequest; namespace { + const int32 kOpenerId = -2; const int32 kRouteId = 5; const int32 kMainFrameRouteId = 6; @@ -56,6 +62,32 @@ const int32 kNewFrameRouteId = 10; const int32 kSurfaceId = 42; +// Converts |ascii_character| into |key_code| and returns true on success. +// Handles only the characters needed by tests. +bool GetWindowsKeyCode(char ascii_character, int* key_code) { + if (isalnum(ascii_character)) { + *key_code = base::ToUpperASCII(ascii_character); + return true; + } + + switch (ascii_character) { + case '@': + *key_code = '2'; + return true; + case '_': + *key_code = ui::VKEY_OEM_MINUS; + return true; + case '.': + *key_code = ui::VKEY_OEM_PERIOD; + return true; + case ui::VKEY_BACK: + *key_code = ui::VKEY_BACK; + return true; + default: + return false; + } +} + } // namespace namespace content { @@ -395,6 +427,55 @@ OnMessageReceived(*resize_message); } +void RenderViewTest::SimulateUserTypingASCIICharacter(char ascii_character, + bool flush_message_loop) { + blink::WebKeyboardEvent event; + event.text[0] = ascii_character; + ASSERT_TRUE(GetWindowsKeyCode(ascii_character, &event.windowsKeyCode)); + if (isupper(ascii_character) || ascii_character == '@' || + ascii_character == '_') { + event.modifiers = blink::WebKeyboardEvent::ShiftKey; + } + + event.type = blink::WebKeyboardEvent::RawKeyDown; + SendWebKeyboardEvent(event); + + event.type = blink::WebKeyboardEvent::Char; + SendWebKeyboardEvent(event); + + event.type = blink::WebKeyboardEvent::KeyUp; + SendWebKeyboardEvent(event); + + if (flush_message_loop) { + // Processing is delayed because of a Blink bug: + // https://bugs.webkit.org/show_bug.cgi?id=16976 See + // PasswordAutofillAgent::TextDidChangeInTextField() for details. + base::MessageLoop::current()->RunUntilIdle(); + } +} + +void RenderViewTest::SimulateUserInputChangeForElement( + blink::WebInputElement* input, + const std::string& new_value) { + ASSERT_TRUE(base::IsStringASCII(new_value)); + while (!input->focused()) + input->document().frame()->view()->advanceFocus(false); + + size_t previous_length = input->value().length(); + for (size_t i = 0; i < previous_length; ++i) + SimulateUserTypingASCIICharacter(ui::VKEY_BACK, false); + + EXPECT_TRUE(input->value().utf8().empty()); + for (size_t i = 0; i < new_value.size(); ++i) + SimulateUserTypingASCIICharacter(new_value[i], false); + + // Compare only beginning, because autocomplete may have filled out the + // form. + EXPECT_EQ(new_value, input->value().utf8().substr(0, new_value.length())); + + base::MessageLoop::current()->RunUntilIdle(); +} + bool RenderViewTest::OnMessageReceived(const IPC::Message& msg) { RenderViewImpl* impl = static_cast<RenderViewImpl*>(view_); return impl->OnMessageReceived(msg); @@ -453,6 +534,7 @@ RequestNavigationParams request_params; request_params.page_state = state; request_params.page_id = impl->page_id_ + offset; + request_params.nav_entry_id = pending_offset + 1; request_params.pending_history_list_offset = pending_offset; request_params.current_history_list_offset = impl->history_list_offset_; request_params.current_history_list_length = history_list_length;
diff --git a/content/public/test/render_view_test.h b/content/public/test/render_view_test.h index d3fd776e..91d0df6 100644 --- a/content/public/test/render_view_test.h +++ b/content/public/test/render_view_test.h
@@ -22,6 +22,7 @@ struct ViewMsg_Resize_Params; namespace blink { +class WebInputElement; class WebWidget; } @@ -99,7 +100,7 @@ void SendWebKeyboardEvent(const blink::WebKeyboardEvent& key_event); // Send a raw mouse event to the renderer. - void SendWebMouseEvent(const blink::WebMouseEvent& key_event); + void SendWebMouseEvent(const blink::WebMouseEvent& mouse_event); // Returns the bounds (coordinates and size) of the element with id // |element_id|. Returns an empty rect if such an element was not found. @@ -130,6 +131,18 @@ gfx::Rect resizer_rect, bool is_fullscreen); + // Simulates typing the |ascii_character| into this render view. Also accepts + // ui::VKEY_BACK for backspace. Will flush the message loop if + // |flush_message_loop| is true. + void SimulateUserTypingASCIICharacter(char ascii_character, + bool flush_message_loop); + + // Simulates user focusing |input|, erasing all text, and typing the + // |new_value| instead. Will process input events for autofill. This is a user + // gesture. + void SimulateUserInputChangeForElement(blink::WebInputElement* input, + const std::string& new_value); + // These are all methods from RenderViewImpl that we expose to testing code. bool OnMessageReceived(const IPC::Message& msg); void DidNavigateWithinPage(blink::WebLocalFrame* frame,
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc index fea075d..b233e8ad 100644 --- a/content/public/test/test_renderer_host.cc +++ b/content/public/test/test_renderer_host.cc
@@ -163,16 +163,19 @@ NavigationEntry* entry = controller().GetLastCommittedEntry(); DCHECK(entry); controller().Reload(false); - RenderFrameHostTester::For(main_rfh())->SendNavigateWithTransition( - entry->GetPageID(), entry->GetURL(), ui::PAGE_TRANSITION_RELOAD); + RenderFrameHostTester::For(main_rfh()) + ->SendNavigateWithTransition(entry->GetPageID(), entry->GetUniqueID(), + false, entry->GetURL(), + ui::PAGE_TRANSITION_RELOAD); } void RenderViewHostTestHarness::FailedReload() { NavigationEntry* entry = controller().GetLastCommittedEntry(); DCHECK(entry); controller().Reload(false); - RenderFrameHostTester::For(main_rfh())->SendFailedNavigate(entry->GetPageID(), - entry->GetURL()); + RenderFrameHostTester::For(main_rfh()) + ->SendFailedNavigate(entry->GetPageID(), entry->GetUniqueID(), false, + entry->GetURL()); } void RenderViewHostTestHarness::SetUp() {
diff --git a/content/public/test/test_renderer_host.h b/content/public/test/test_renderer_host.h index 029b70e..001a48e 100644 --- a/content/public/test/test_renderer_host.h +++ b/content/public/test/test_renderer_host.h
@@ -71,17 +71,27 @@ virtual RenderFrameHost* AppendChild(const std::string& frame_name) = 0; // Calls OnDidCommitProvisionalLoad on the RenderFrameHost with the given - // information. Sets the rest of the parameters in the message to the - // "typical" values. This is a helper function for simulating the most common - // types of loads. - virtual void SendNavigate(int page_id, const GURL& url) = 0; - virtual void SendFailedNavigate(int page_id, const GURL& url) = 0; - - // Calls OnDidCommitProvisionalLoad on the RenderFrameHost with the given - // information, including a custom PageTransition. Sets the rest of the - // parameters in the message to the "typical" values. This is a helper - // function for simulating the most common types of loads. + // information with various sets of parameters. These are helper functions for + // simulating the most common types of loads. + // + // Guidance for calling these: + // - nav_entry_id should be 0 if simulating a renderer-initiated navigation; + // if simulating a browser-initiated one, pass the GetUniqueID() value of + // the NavigationController's PendingEntry. + // - did_create_new_entry should be true if simulating a navigation that + // created a new navigation entry; false for history navigations, reloads, + // and other navigations that don't affect the history list. + virtual void SendNavigate(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url) = 0; + virtual void SendFailedNavigate(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url) = 0; virtual void SendNavigateWithTransition(int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition) = 0; @@ -231,6 +241,9 @@ void SetRenderProcessHostFactory(RenderProcessHostFactory* factory); private: + int thread_bundle_options_; + scoped_ptr<TestBrowserThreadBundle> thread_bundle_; + scoped_ptr<ContentBrowserSanityChecker> sanity_checker_; scoped_ptr<BrowserContext> browser_context_; @@ -244,9 +257,6 @@ #endif RenderViewHostTestEnabler rvh_test_enabler_; - int thread_bundle_options_; - scoped_ptr<TestBrowserThreadBundle> thread_bundle_; - DISALLOW_COPY_AND_ASSIGN(RenderViewHostTestHarness); };
diff --git a/content/public/test/web_contents_tester.h b/content/public/test/web_contents_tester.h index a96d86d..77ef2cc 100644 --- a/content/public/test/web_contents_tester.h +++ b/content/public/test/web_contents_tester.h
@@ -78,17 +78,28 @@ // Does nothing if no cross-navigation is pending. virtual void ProceedWithCrossSiteNavigation() = 0; + // Simulates a navigation with the given information. + // + // Guidance for calling these: + // - nav_entry_id should be 0 if simulating a renderer-initiated navigation; + // if simulating a browser-initiated one, pass the GetUniqueID() value of + // the NavigationController's PendingEntry. + // - did_create_new_entry should be true if simulating a navigation that + // created a new navigation entry; false for history navigations, reloads, + // and other navigations that don't affect the history list. virtual void TestDidNavigate(RenderFrameHost* render_frame_host, int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition) = 0; - - virtual void TestDidNavigateWithReferrer( - RenderFrameHost* render_frame_host, - int page_id, - const GURL& url, - const Referrer& referrer, - ui::PageTransition transition) = 0; + virtual void TestDidNavigateWithReferrer(RenderFrameHost* render_frame_host, + int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url, + const Referrer& referrer, + ui::PageTransition transition) = 0; }; } // namespace content
diff --git a/content/renderer/BUILD.gn b/content/renderer/BUILD.gn index d4a17fb..ce60fa3 100644 --- a/content/renderer/BUILD.gn +++ b/content/renderer/BUILD.gn
@@ -62,7 +62,6 @@ "//ui/native_theme", "//ui/surface", "//v8", - "//webkit/common/gpu", ] if (is_mac) {
diff --git a/content/renderer/accessibility/blink_ax_enum_conversion.cc b/content/renderer/accessibility/blink_ax_enum_conversion.cc index b7b54ee..10e2388 100644 --- a/content/renderer/accessibility/blink_ax_enum_conversion.cc +++ b/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -360,8 +360,10 @@ return ui::AX_EVENT_LOCATION_CHANGED; case blink::WebAXEventMenuListItemSelected: return ui::AX_EVENT_MENU_LIST_ITEM_SELECTED; + case blink::WebAXEventMenuListItemUnselected: + return ui::AX_EVENT_MENU_LIST_ITEM_SELECTED; case blink::WebAXEventMenuListValueChanged: - return ui::AX_EVENT_MENU_LIST_VALUE_CHANGED; + return ui::AX_EVENT_MENU_LIST_VALUE_CHANGED; case blink::WebAXEventRowCollapsed: return ui::AX_EVENT_ROW_COLLAPSED; case blink::WebAXEventRowCountChanged:
diff --git a/content/renderer/accessibility/renderer_accessibility.cc b/content/renderer/accessibility/renderer_accessibility.cc index 12a59d3..8e3b41c4 100644 --- a/content/renderer/accessibility/renderer_accessibility.cc +++ b/content/renderer/accessibility/renderer_accessibility.cc
@@ -253,13 +253,6 @@ if (!tree_source_.IsInTree(obj)) continue; - // When we get a "selected children changed" event, Blink - // doesn't also send us events for each child that changed - // selection state, so make sure we re-send that whole subtree. - if (event.event_type == ui::AX_EVENT_SELECTED_CHILDREN_CHANGED) { - serializer_.DeleteClientSubtree(obj); - } - AccessibilityHostMsg_EventParams event_msg; tree_source_.CollectChildFrameIdMapping( &event_msg.node_to_frame_routing_id_map,
diff --git a/content/renderer/device_sensors/device_sensor_event_pump.h b/content/renderer/device_sensors/device_sensor_event_pump.h index 43e0f64..45e028d 100644 --- a/content/renderer/device_sensors/device_sensor_event_pump.h +++ b/content/renderer/device_sensors/device_sensor_event_pump.h
@@ -22,7 +22,7 @@ base::Time::kMicrosecondsPerSecond / kDefaultPumpFrequencyHz; // PlatformEventObserver - virtual void Start(blink::WebPlatformEventListener* listener) override { + void Start(blink::WebPlatformEventListener* listener) override { DVLOG(2) << "requested start"; if (state_ != STOPPED) @@ -34,7 +34,7 @@ state_ = PENDING_START; } - virtual void Stop() override { + void Stop() override { DVLOG(2) << "stop"; if (state_ == STOPPED) @@ -55,7 +55,7 @@ pump_delay_microseconds_(kDefaultPumpDelayMicroseconds), state_(STOPPED) {} - virtual ~DeviceSensorEventPump() { + ~DeviceSensorEventPump() override { PlatformEventObserver<ListenerType>::StopIfObserving(); }
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc index 0264aa5..f3f6489 100644 --- a/content/renderer/gpu/render_widget_compositor.cc +++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -37,10 +37,10 @@ #include "content/renderer/input/input_handler_manager.h" #include "gpu/command_buffer/client/gles2_interface.h" #include "third_party/WebKit/public/platform/WebCompositeAndReadbackAsyncCallback.h" -#include "third_party/WebKit/public/platform/WebSelectionBound.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" +#include "third_party/WebKit/public/web/WebSelection.h" #include "third_party/WebKit/public/web/WebWidget.h" #include "ui/gfx/frame_time.h" #include "ui/gl/gl_switches.h" @@ -62,7 +62,7 @@ using blink::WebBeginFrameArgs; using blink::WebFloatPoint; using blink::WebRect; -using blink::WebSelectionBound; +using blink::WebSelection; using blink::WebSize; using blink::WebTopControlsState; @@ -88,20 +88,24 @@ } cc::LayerSelectionBound ConvertWebSelectionBound( - const WebSelectionBound& web_bound) { - DCHECK(web_bound.layerId); - + const WebSelection& web_selection, + bool is_start) { cc::LayerSelectionBound cc_bound; - switch (web_bound.type) { - case blink::WebSelectionBound::Caret: - cc_bound.type = cc::SELECTION_BOUND_CENTER; - break; - case blink::WebSelectionBound::SelectionLeft: - cc_bound.type = cc::SELECTION_BOUND_LEFT; - break; - case blink::WebSelectionBound::SelectionRight: - cc_bound.type = cc::SELECTION_BOUND_RIGHT; - break; + if (web_selection.isNone()) + return cc_bound; + + const blink::WebSelectionBound& web_bound = + is_start ? web_selection.start() : web_selection.end(); + DCHECK(web_bound.layerId); + cc_bound.type = cc::SELECTION_BOUND_CENTER; + if (web_selection.isRange()) { + if (is_start) { + cc_bound.type = web_bound.isTextDirectionRTL ? cc::SELECTION_BOUND_RIGHT + : cc::SELECTION_BOUND_LEFT; + } else { + cc_bound.type = web_bound.isTextDirectionRTL ? cc::SELECTION_BOUND_LEFT + : cc::SELECTION_BOUND_RIGHT; + } } cc_bound.layer_id = web_bound.layerId; cc_bound.edge_top = gfx::Point(web_bound.edgeTopInLayer); @@ -109,6 +113,16 @@ return cc_bound; } +cc::LayerSelection ConvertWebSelection(const WebSelection& web_selection) { + cc::LayerSelection cc_selection; + cc_selection.start = ConvertWebSelectionBound(web_selection, true); + cc_selection.end = ConvertWebSelectionBound(web_selection, false); + cc_selection.is_editable = web_selection.isEditable(); + cc_selection.is_empty_text_form_control = + web_selection.isEmptyTextFormControl(); + return cc_selection; +} + gfx::Size CalculateDefaultTileSize(RenderWidget* widget) { int default_tile_size = 256; #if defined(OS_ANDROID) @@ -207,8 +221,6 @@ settings.throttle_frame_production = !cmd->HasSwitch(switches::kDisableGpuVsync); - settings.use_external_begin_frame_source = - cmd->HasSwitch(switches::kEnableBeginFrameScheduling); settings.main_frame_before_activation_enabled = cmd->HasSwitch(cc::switches::kEnableMainFrameBeforeActivation) && !cmd->HasSwitch(cc::switches::kDisableMainFrameBeforeActivation); @@ -221,6 +233,12 @@ settings.use_compositor_animation_timelines = true; blink::WebRuntimeFeatures::enableCompositorAnimationTimelines(true); } + if (cmd->HasSwitch(switches::kEnableBeginFrameScheduling) && + !widget_->for_oopif()) { + // TODO(simonhong): Apply BeginFrame scheduling for OOPIF. + // See crbug.com/471411. + settings.use_external_begin_frame_source = true; + } settings.default_tile_size = CalculateDefaultTileSize(widget_); if (cmd->HasSwitch(switches::kDefaultTileWidth)) { @@ -514,10 +532,6 @@ layer_tree_host_->QueueSwapPromise(swap_promise.Pass()); } -int RenderWidgetCompositor::GetLayerTreeId() const { - return layer_tree_host_->id(); -} - int RenderWidgetCompositor::GetSourceFrameNumber() const { return layer_tree_host_->source_frame_number(); } @@ -681,15 +695,13 @@ } void RenderWidgetCompositor::registerSelection( - const blink::WebSelectionBound& start, - const blink::WebSelectionBound& end) { - layer_tree_host_->RegisterSelection(ConvertWebSelectionBound(start), - ConvertWebSelectionBound(end)); + const blink::WebSelection& selection) { + layer_tree_host_->RegisterSelection(ConvertWebSelection(selection)); } void RenderWidgetCompositor::clearSelection() { - cc::LayerSelectionBound empty_selection; - layer_tree_host_->RegisterSelection(empty_selection, empty_selection); + cc::LayerSelection empty_selection; + layer_tree_host_->RegisterSelection(empty_selection); } void CompositeAndReadbackAsyncCallback( @@ -729,6 +741,10 @@ layer_tree_host_->SetDeferCommits(defer_commits); } +int RenderWidgetCompositor::layerTreeId() const { + return layer_tree_host_->id(); +} + void RenderWidgetCompositor::setShowFPSCounter(bool show) { cc::LayerTreeDebugState debug_state = layer_tree_host_->debug_state(); debug_state.show_fps_counter = show;
diff --git a/content/renderer/gpu/render_widget_compositor.h b/content/renderer/gpu/render_widget_compositor.h index ae79a308..32999e2 100644 --- a/content/renderer/gpu/render_widget_compositor.h +++ b/content/renderer/gpu/render_widget_compositor.h
@@ -66,7 +66,6 @@ // Calling QueueSwapPromise() to directly queue a SwapPromise into // LayerTreeHost. void QueueSwapPromise(scoped_ptr<cc::SwapPromise> swap_promise); - int GetLayerTreeId() const; int GetSourceFrameNumber() const; void SetNeedsUpdateLayers(); void SetNeedsCommit(); @@ -117,9 +116,9 @@ const blink::WebLayer* innerViewportScrollLayer, const blink::WebLayer* outerViewportScrollLayer) override; virtual void clearViewportLayers() override; - virtual void registerSelection(const blink::WebSelectionBound& start, - const blink::WebSelectionBound& end) override; + virtual void registerSelection(const blink::WebSelection& selection) override; virtual void clearSelection() override; + virtual int layerTreeId() const; virtual void setShowFPSCounter(bool show); virtual void setShowPaintRects(bool show); virtual void setShowDebugBorders(bool show);
diff --git a/content/renderer/gpu/render_widget_compositor_unittest.cc b/content/renderer/gpu/render_widget_compositor_unittest.cc index 6becdf51..e42fb584 100644 --- a/content/renderer/gpu/render_widget_compositor_unittest.cc +++ b/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -57,6 +57,7 @@ ~RenderWidgetCompositorTest() override {} protected: + base::MessageLoop loop_; MockRenderThread render_thread_; scoped_refptr<TestRenderWidget> render_widget_; scoped_ptr<FakeCompositorDependencies> compositor_deps_;
diff --git a/content/renderer/input/input_handler_proxy_unittest.cc b/content/renderer/input/input_handler_proxy_unittest.cc index 3825366..7994914 100644 --- a/content/renderer/input/input_handler_proxy_unittest.cc +++ b/content/renderer/input/input_handler_proxy_unittest.cc
@@ -75,7 +75,7 @@ class MockInputHandler : public cc::InputHandler { public: MockInputHandler() {} - virtual ~MockInputHandler() {} + ~MockInputHandler() override {} MOCK_METHOD0(PinchGestureBegin, void()); MOCK_METHOD2(PinchGestureUpdate, @@ -100,18 +100,18 @@ MOCK_METHOD0(ScrollEnd, void()); MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus()); - virtual scoped_ptr<cc::SwapPromiseMonitor> - CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) override { - return scoped_ptr<cc::SwapPromiseMonitor>(); + scoped_ptr<cc::SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( + ui::LatencyInfo* latency) override { + return scoped_ptr<cc::SwapPromiseMonitor>(); } cc::ScrollElasticityHelper* CreateScrollElasticityHelper() override { return NULL; } - virtual void BindToClient(cc::InputHandlerClient* client) override {} + void BindToClient(cc::InputHandlerClient* client) override {} - virtual void MouseMoveAt(const gfx::Point& mouse_position) override {} + void MouseMoveAt(const gfx::Point& mouse_position) override {} MOCK_METHOD2(IsCurrentlyScrollingLayerAt, bool(const gfx::Point& point, @@ -120,11 +120,11 @@ MOCK_METHOD1(HaveWheelEventHandlersAt, bool(const gfx::Point& point)); MOCK_METHOD1(DoTouchEventsBlockScrollAt, bool(const gfx::Point& point)); - virtual void SetRootLayerScrollOffsetDelegate( + void SetRootLayerScrollOffsetDelegate( cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) override {} - virtual void OnRootLayerDelegatedScrollOffsetChanged() override {} + void OnRootLayerDelegatedScrollOffsetChanged() override {} DISALLOW_COPY_AND_ASSIGN(MockInputHandler); }; @@ -163,14 +163,14 @@ : public content::InputHandlerProxyClient { public: MockInputHandlerProxyClient() {} - virtual ~MockInputHandlerProxyClient() {} + ~MockInputHandlerProxyClient() override {} - virtual void WillShutdown() override {} + void WillShutdown() override {} MOCK_METHOD1(TransferActiveWheelFlingAnimation, void(const WebActiveWheelFlingParameters&)); - virtual blink::WebGestureCurve* CreateFlingAnimationCurve( + blink::WebGestureCurve* CreateFlingAnimationCurve( WebGestureDevice deviceSource, const WebFloatPoint& velocity, const WebSize& cumulative_scroll) override { @@ -180,9 +180,9 @@ } MOCK_METHOD1(DidOverscroll, void(const DidOverscrollParams&)); - virtual void DidStopFlinging() override {} - virtual void DidReceiveInputEvent(const blink::WebInputEvent&) override {} - virtual void DidAnimateForInput() override {} + void DidStopFlinging() override {} + void DidReceiveInputEvent(const blink::WebInputEvent&) override {} + void DidAnimateForInput() override {} private: DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient); @@ -192,7 +192,7 @@ : public MockInputHandlerProxyClient { public: MockInputHandlerProxyClientWithDidReceiveInputEvent() {} - virtual ~MockInputHandlerProxyClientWithDidReceiveInputEvent() {} + ~MockInputHandlerProxyClientWithDidReceiveInputEvent() override {} MOCK_METHOD1(DidReceiveInputEvent, void(const blink::WebInputEvent&)); MOCK_METHOD0(DidAnimateForInput, void());
diff --git a/content/renderer/java/gin_java_bridge_object.h b/content/renderer/java/gin_java_bridge_object.h index da7460f9c..a498e14 100644 --- a/content/renderer/java/gin_java_bridge_object.h +++ b/content/renderer/java/gin_java_bridge_object.h
@@ -59,7 +59,7 @@ base::WeakPtr<GinJavaBridgeDispatcher> dispatcher_; GinJavaBridgeDispatcher::ObjectID object_id_; std::map<std::string, bool> known_methods_; - v8::StdPersistentValueMap<std::string, v8::FunctionTemplate> template_cache_; + v8::StdGlobalValueMap<std::string, v8::FunctionTemplate> template_cache_; DISALLOW_COPY_AND_ASSIGN(GinJavaBridgeObject); };
diff --git a/content/renderer/java/gin_java_bridge_value_converter.cc b/content/renderer/java/gin_java_bridge_value_converter.cc index c1727a42..c8bd877 100644 --- a/content/renderer/java/gin_java_bridge_value_converter.cc +++ b/content/renderer/java/gin_java_bridge_value_converter.cc
@@ -4,7 +4,8 @@ #include "content/renderer/java/gin_java_bridge_value_converter.h" -#include "base/float_util.h" +#include <cmath> + #include "base/values.h" #include "content/common/android/gin_java_bridge_value.h" #include "content/renderer/java/gin_java_bridge_object.h" @@ -72,7 +73,7 @@ new TypedArraySerializerImpl<ElementType, ListType>(typed_array)); } - virtual void serializeTo(char* data, + void serializeTo(char* data, size_t data_length, base::ListValue* out) override { DCHECK_EQ(data_length, typed_array_->Length() * sizeof(ElementType)); @@ -148,7 +149,7 @@ bool GinJavaBridgeValueConverter::FromV8Number(v8::Handle<v8::Number> value, base::Value** out) const { double double_value = value->Value(); - if (base::IsFinite(double_value)) + if (std::isfinite(double_value)) return false; *out = GinJavaBridgeValue::CreateNonFiniteValue(double_value).release(); return true;
diff --git a/content/renderer/java/gin_java_bridge_value_converter_unittest.cc b/content/renderer/java/gin_java_bridge_value_converter_unittest.cc index edffce7..b0ef27a 100644 --- a/content/renderer/java/gin_java_bridge_value_converter_unittest.cc +++ b/content/renderer/java/gin_java_bridge_value_converter_unittest.cc
@@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <cmath> + #include "base/basictypes.h" -#include "base/float_util.h" #include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "content/common/android/gin_java_bridge_value.h" @@ -67,8 +68,7 @@ EXPECT_TRUE( infinity_value->IsType(GinJavaBridgeValue::TYPE_NONFINITE)); EXPECT_TRUE(infinity_value->GetAsNonFinite(&native_float)); - EXPECT_FALSE(base::IsFinite(native_float)); - EXPECT_FALSE(base::IsNaN(native_float)); + EXPECT_TRUE(std::isinf(native_float)); } TEST_F(GinJavaBridgeValueConverterTest, ArrayBuffer) {
diff --git a/content/renderer/media/crypto/ppapi_decryptor.cc b/content/renderer/media/crypto/ppapi_decryptor.cc index a70249a..d50e911da 100644 --- a/content/renderer/media/crypto/ppapi_decryptor.cc +++ b/content/renderer/media/crypto/ppapi_decryptor.cc
@@ -90,8 +90,7 @@ } void PpapiDecryptor::SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) { DVLOG(2) << __FUNCTION__; DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -101,15 +100,13 @@ return; } - CdmDelegate()->SetServerCertificate( - certificate_data, certificate_data_length, promise.Pass()); + CdmDelegate()->SetServerCertificate(certificate, promise.Pass()); } void PpapiDecryptor::CreateSessionAndGenerateRequest( SessionType session_type, media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) { DVLOG(2) << __FUNCTION__; DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -120,8 +117,7 @@ } CdmDelegate()->CreateSessionAndGenerateRequest(session_type, init_data_type, - init_data, init_data_length, - promise.Pass()); + init_data, promise.Pass()); } void PpapiDecryptor::LoadSession( @@ -140,8 +136,7 @@ void PpapiDecryptor::UpdateSession( const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); @@ -149,8 +144,7 @@ promise->reject(INVALID_STATE_ERROR, 0, "CdmDelegate() does not exist."); return; } - CdmDelegate()->UpdateSession(session_id, response, response_length, - promise.Pass()); + CdmDelegate()->UpdateSession(session_id, response, promise.Pass()); } void PpapiDecryptor::CloseSession(const std::string& session_id, @@ -393,7 +387,7 @@ void PpapiDecryptor::OnSessionMessage(const std::string& session_id, MessageType message_type, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& legacy_destination_url) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); session_message_cb_.Run(session_id, message_type, message, @@ -429,7 +423,7 @@ void PpapiDecryptor::OnLegacySessionError( const std::string& session_id, MediaKeys::Exception exception_code, - uint32 system_code, + uint32_t system_code, const std::string& error_description) { DCHECK(render_loop_proxy_->BelongsToCurrentThread()); legacy_session_error_cb_.Run(session_id, exception_code, system_code,
diff --git a/content/renderer/media/crypto/ppapi_decryptor.h b/content/renderer/media/crypto/ppapi_decryptor.h index ed4523f..374b5c18 100644 --- a/content/renderer/media/crypto/ppapi_decryptor.h +++ b/content/renderer/media/crypto/ppapi_decryptor.h
@@ -50,21 +50,18 @@ // media::MediaKeys implementation. void SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) override; void CreateSessionAndGenerateRequest( SessionType session_type, media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) override; void LoadSession(SessionType session_type, const std::string& session_id, scoped_ptr<media::NewSessionCdmPromise> promise) override; void UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) override; void CloseSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) override; @@ -113,7 +110,7 @@ // Callbacks for |plugin_cdm_delegate_| to fire session events. void OnSessionMessage(const std::string& session_id, MediaKeys::MessageType message_type, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& legacy_destination_url); void OnSessionKeysChange(const std::string& session_id, bool has_additional_usable_key, @@ -123,7 +120,7 @@ void OnSessionClosed(const std::string& session_id); void OnLegacySessionError(const std::string& session_id, MediaKeys::Exception exception_code, - uint32 system_code, + uint32_t system_code, const std::string& error_description); void AttemptToResumePlayback();
diff --git a/content/renderer/media/crypto/proxy_media_keys.cc b/content/renderer/media/crypto/proxy_media_keys.cc index 9dd2de67..9f121fe 100644 --- a/content/renderer/media/crypto/proxy_media_keys.cc +++ b/content/renderer/media/crypto/proxy_media_keys.cc
@@ -40,21 +40,16 @@ } void ProxyMediaKeys::SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) { uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); - manager_->SetServerCertificate( - cdm_id_, promise_id, - std::vector<uint8>(certificate_data, - certificate_data + certificate_data_length)); + manager_->SetServerCertificate(cdm_id_, promise_id, certificate); } void ProxyMediaKeys::CreateSessionAndGenerateRequest( SessionType session_type, media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) { if (session_type != media::MediaKeys::TEMPORARY_SESSION) { promise->reject(NOT_SUPPORTED_ERROR, 0, @@ -83,8 +78,7 @@ uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); manager_->CreateSessionAndGenerateRequest( - cdm_id_, promise_id, create_session_init_data_type, - std::vector<uint8>(init_data, init_data + init_data_length)); + cdm_id_, promise_id, create_session_init_data_type, init_data); } void ProxyMediaKeys::LoadSession( @@ -99,13 +93,10 @@ void ProxyMediaKeys::UpdateSession( const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) { uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); - manager_->UpdateSession( - cdm_id_, promise_id, session_id, - std::vector<uint8>(response, response + response_length)); + manager_->UpdateSession(cdm_id_, promise_id, session_id, response); } void ProxyMediaKeys::CloseSession(const std::string& session_id, @@ -137,7 +128,7 @@ void ProxyMediaKeys::OnSessionMessage( const std::string& session_id, media::MediaKeys::MessageType message_type, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& legacy_destination_url) { session_message_cb_.Run(session_id, message_type, message, legacy_destination_url); @@ -149,7 +140,7 @@ void ProxyMediaKeys::OnLegacySessionError(const std::string& session_id, media::MediaKeys::Exception exception, - uint32 system_code, + uint32_t system_code, const std::string& error_message) { legacy_session_error_cb_.Run(session_id, exception, system_code, error_message);
diff --git a/content/renderer/media/crypto/proxy_media_keys.h b/content/renderer/media/crypto/proxy_media_keys.h index e13fc3d..979de0a 100644 --- a/content/renderer/media/crypto/proxy_media_keys.h +++ b/content/renderer/media/crypto/proxy_media_keys.h
@@ -7,6 +7,7 @@ #include <map> #include <string> +#include <vector> #include "base/basictypes.h" #include "base/containers/hash_tables.h" @@ -39,21 +40,18 @@ // MediaKeys implementation. void SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) override; void CreateSessionAndGenerateRequest( SessionType session_type, media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) override; void LoadSession(SessionType session_type, const std::string& session_id, scoped_ptr<media::NewSessionCdmPromise> promise) override; void UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) override; void CloseSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) override; @@ -68,12 +66,12 @@ // Callbacks. void OnSessionMessage(const std::string& session_id, media::MediaKeys::MessageType message_type, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& legacy_destination_url); void OnSessionClosed(const std::string& session_id); void OnLegacySessionError(const std::string& session_id, media::MediaKeys::Exception exception, - uint32 system_code, + uint32_t system_code, const std::string& error_message); void OnSessionKeysChange(const std::string& session_id, bool has_additional_usable_key,
diff --git a/content/renderer/media/media_stream_audio_level_calculator.cc b/content/renderer/media/media_stream_audio_level_calculator.cc index 320b1ab7..ad76a43 100644 --- a/content/renderer/media/media_stream_audio_level_calculator.cc +++ b/content/renderer/media/media_stream_audio_level_calculator.cc
@@ -4,7 +4,8 @@ #include "content/renderer/media/media_stream_audio_level_calculator.h" -#include "base/float_util.h" +#include <cmath> + #include "base/logging.h" #include "base/stl_util.h" #include "media/base/audio_bus.h" @@ -21,7 +22,7 @@ if (absolute > max) max = absolute; } - DCHECK(base::IsFinite(max)); + DCHECK(std::isfinite(max)); return max; }
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc index 78237d98c..d22cf5e 100644 --- a/content/renderer/media/media_stream_audio_processor.cc +++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -537,10 +537,10 @@ std::vector<webrtc::Point> geometry(1, webrtc::Point(0.f, 0.f, 0.f)); #if defined(OS_CHROMEOS) const std::string board = base::SysInfo::GetLsbReleaseBoard(); - if (board == "peach_pi") { + if (board.find("peach_pi") != std::string::npos) { enabled = true; geometry.push_back(webrtc::Point(0.050f, 0.f, 0.f)); - } else if (board == "swanky") { + } else if (board.find("swanky") != std::string::npos) { enabled = true; geometry.push_back(webrtc::Point(0.052f, 0.f, 0.f)); }
diff --git a/content/renderer/media/media_stream_audio_processor_options.cc b/content/renderer/media/media_stream_audio_processor_options.cc index c39b154..8029b25d 100644 --- a/content/renderer/media/media_stream_audio_processor_options.cc +++ b/content/renderer/media/media_stream_audio_processor_options.cc
@@ -222,12 +222,20 @@ } EchoInformation::EchoInformation() - : num_chunks_(0) {} + : num_chunks_(0), echo_frames_received_(false) { +} EchoInformation::~EchoInformation() {} void EchoInformation::UpdateAecDelayStats( webrtc::EchoCancellation* echo_cancellation) { + // Only start collecting stats if we know echo cancellation has measured an + // echo. Otherwise we clutter the stats with for example cases where only the + // microphone is used. + if (!echo_frames_received_ & !echo_cancellation->stream_has_echo()) + return; + + echo_frames_received_ = true; // In WebRTC, three echo delay metrics are calculated and updated every // five seconds. We use one of them, |fraction_poor_delays| to log in a UMA // histogram an Echo Cancellation quality metric. The stat in WebRTC has a
diff --git a/content/renderer/media/media_stream_audio_processor_options.h b/content/renderer/media/media_stream_audio_processor_options.h index e5d0be5..8484b08 100644 --- a/content/renderer/media/media_stream_audio_processor_options.h +++ b/content/renderer/media/media_stream_audio_processor_options.h
@@ -101,6 +101,7 @@ // Counter to track 5 seconds of processed 10 ms chunks in order to query a // new metric from webrtc::EchoCancellation::GetEchoDelayMetrics(). int num_chunks_; + bool echo_frames_received_; DISALLOW_COPY_AND_ASSIGN(EchoInformation); };
diff --git a/content/renderer/media/media_stream_center.h b/content/renderer/media/media_stream_center.h index ef4fbaa..d3627557 100644 --- a/content/renderer/media/media_stream_center.h +++ b/content/renderer/media/media_stream_center.h
@@ -30,37 +30,32 @@ public: MediaStreamCenter(blink::WebMediaStreamCenterClient* client, PeerConnectionDependencyFactory* factory); - virtual ~MediaStreamCenter(); + ~MediaStreamCenter() override; private: - virtual void didCreateMediaStreamTrack( + void didCreateMediaStreamTrack( const blink::WebMediaStreamTrack& track) override; - virtual void didEnableMediaStreamTrack( + void didEnableMediaStreamTrack( const blink::WebMediaStreamTrack& track) override; - virtual void didDisableMediaStreamTrack( + void didDisableMediaStreamTrack( const blink::WebMediaStreamTrack& track) override; - virtual void didStopLocalMediaStream( - const blink::WebMediaStream& stream) override; + void didStopLocalMediaStream(const blink::WebMediaStream& stream) override; - virtual bool didStopMediaStreamTrack( + bool didStopMediaStreamTrack( const blink::WebMediaStreamTrack& track) override; - virtual blink::WebAudioSourceProvider* - createWebAudioSourceFromMediaStreamTrack( - const blink::WebMediaStreamTrack& track) override; - - - virtual void didCreateMediaStream( - blink::WebMediaStream& stream) override; - - virtual bool didAddMediaStreamTrack( - const blink::WebMediaStream& stream, + blink::WebAudioSourceProvider* createWebAudioSourceFromMediaStreamTrack( const blink::WebMediaStreamTrack& track) override; - virtual bool didRemoveMediaStreamTrack( + void didCreateMediaStream(blink::WebMediaStream& stream) override; + + bool didAddMediaStreamTrack(const blink::WebMediaStream& stream, + const blink::WebMediaStreamTrack& track) override; + + bool didRemoveMediaStreamTrack( const blink::WebMediaStream& stream, const blink::WebMediaStreamTrack& track) override;
diff --git a/content/renderer/media/mock_media_stream_video_sink.h b/content/renderer/media/mock_media_stream_video_sink.h index e82020b5..a7ca3500 100644 --- a/content/renderer/media/mock_media_stream_video_sink.h +++ b/content/renderer/media/mock_media_stream_video_sink.h
@@ -17,11 +17,11 @@ class MockMediaStreamVideoSink : public MediaStreamVideoSink { public: MockMediaStreamVideoSink(); - virtual ~MockMediaStreamVideoSink(); + ~MockMediaStreamVideoSink() override; - virtual void OnReadyStateChanged( + void OnReadyStateChanged( blink::WebMediaStreamSource::ReadyState state) override; - virtual void OnEnabledChanged(bool enabled) override; + void OnEnabledChanged(bool enabled) override; // Triggered when OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame) // is called.
diff --git a/content/renderer/media/mock_media_stream_video_source.h b/content/renderer/media/mock_media_stream_video_source.h index 0ae7507..d00a5feb 100644 --- a/content/renderer/media/mock_media_stream_video_source.h +++ b/content/renderer/media/mock_media_stream_video_source.h
@@ -44,22 +44,22 @@ int max_requested_width() const { return max_requested_width_; } double max_requested_frame_rate() const { return max_requested_frame_rate_; } - virtual void SetMutedState(bool muted_state) override { + void SetMutedState(bool muted_state) override { MediaStreamVideoSource::SetMutedState(muted_state); DoSetMutedState(muted_state); } protected: // Implements MediaStreamVideoSource. - virtual void GetCurrentSupportedFormats( + void GetCurrentSupportedFormats( int max_requested_height, int max_requested_width, double max_requested_frame_rate, const VideoCaptureDeviceFormatsCB& callback) override; - virtual void StartSourceImpl( + void StartSourceImpl( const media::VideoCaptureFormat& format, const VideoCaptureDeliverFrameCB& frame_callback) override; - virtual void StopSourceImpl() override; + void StopSourceImpl() override; private: media::VideoCaptureFormat format_;
diff --git a/content/renderer/media/mock_peer_connection_impl.h b/content/renderer/media/mock_peer_connection_impl.h index 5e89294..ef7d63b 100644 --- a/content/renderer/media/mock_peer_connection_impl.h +++ b/content/renderer/media/mock_peer_connection_impl.h
@@ -25,61 +25,55 @@ webrtc::PeerConnectionObserver* observer); // PeerConnectionInterface implementation. - virtual rtc::scoped_refptr<webrtc::StreamCollectionInterface> + rtc::scoped_refptr<webrtc::StreamCollectionInterface> local_streams() override; - virtual rtc::scoped_refptr<webrtc::StreamCollectionInterface> + rtc::scoped_refptr<webrtc::StreamCollectionInterface> remote_streams() override; - virtual bool AddStream( + bool AddStream( webrtc::MediaStreamInterface* local_stream) override; - virtual void RemoveStream( + void RemoveStream( webrtc::MediaStreamInterface* local_stream) override; - virtual rtc::scoped_refptr<webrtc::DtmfSenderInterface> + rtc::scoped_refptr<webrtc::DtmfSenderInterface> CreateDtmfSender(webrtc::AudioTrackInterface* track) override; - virtual rtc::scoped_refptr<webrtc::DataChannelInterface> + rtc::scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(const std::string& label, const webrtc::DataChannelInit* config) override; - - virtual bool GetStats(webrtc::StatsObserver* observer, - webrtc::MediaStreamTrackInterface* track) { - return false; - } - virtual bool GetStats(webrtc::StatsObserver* observer, - webrtc::MediaStreamTrackInterface* track, - StatsOutputLevel level) override; + bool GetStats(webrtc::StatsObserver* observer, + webrtc::MediaStreamTrackInterface* track, + StatsOutputLevel level) override; // Set Call this function to make sure next call to GetStats fail. void SetGetStatsResult(bool result) { getstats_result_ = result; } - virtual SignalingState signaling_state() override { + SignalingState signaling_state() override { NOTIMPLEMENTED(); return PeerConnectionInterface::kStable; } - virtual IceState ice_state() override { + IceState ice_state() override { NOTIMPLEMENTED(); return PeerConnectionInterface::kIceNew; } - virtual IceConnectionState ice_connection_state() override { + IceConnectionState ice_connection_state() override { NOTIMPLEMENTED(); return PeerConnectionInterface::kIceConnectionNew; } - virtual IceGatheringState ice_gathering_state() override { + IceGatheringState ice_gathering_state() override { NOTIMPLEMENTED(); return PeerConnectionInterface::kIceGatheringNew; } - virtual void Close() override { + void Close() override { NOTIMPLEMENTED(); } - virtual const webrtc::SessionDescriptionInterface* local_description() - const override; - virtual const webrtc::SessionDescriptionInterface* remote_description() + const webrtc::SessionDescriptionInterface* local_description() const override; + const webrtc::SessionDescriptionInterface* remote_description() const override; // JSEP01 APIs - virtual void CreateOffer( + void CreateOffer( webrtc::CreateSessionDescriptionObserver* observer, const webrtc::MediaConstraintsInterface* constraints) override; - virtual void CreateAnswer( + void CreateAnswer( webrtc::CreateSessionDescriptionObserver* observer, const webrtc::MediaConstraintsInterface* constraints) override; MOCK_METHOD2(SetLocalDescription, @@ -94,12 +88,10 @@ void SetRemoteDescriptionWorker( webrtc::SetSessionDescriptionObserver* observer, webrtc::SessionDescriptionInterface* desc); - virtual bool UpdateIce( - const IceServers& configuration, - const webrtc::MediaConstraintsInterface* constraints) override; - virtual bool AddIceCandidate( - const webrtc::IceCandidateInterface* candidate) override; - virtual void RegisterUMAObserver(webrtc::UMAObserver* observer) override; + bool UpdateIce(const IceServers& configuration, + const webrtc::MediaConstraintsInterface* constraints) override; + bool AddIceCandidate(const webrtc::IceCandidateInterface* candidate) override; + void RegisterUMAObserver(webrtc::UMAObserver* observer) override; void AddRemoteStream(webrtc::MediaStreamInterface* stream);
diff --git a/content/renderer/media/rtc_data_channel_handler.h b/content/renderer/media/rtc_data_channel_handler.h index 40cc19d..c1ae1336 100644 --- a/content/renderer/media/rtc_data_channel_handler.h +++ b/content/renderer/media/rtc_data_channel_handler.h
@@ -37,26 +37,24 @@ RtcDataChannelHandler( const scoped_refptr<base::SingleThreadTaskRunner>& main_thread, webrtc::DataChannelInterface* channel); - virtual ~RtcDataChannelHandler(); + ~RtcDataChannelHandler() override; // blink::WebRTCDataChannelHandler implementation. - virtual void setClient( + void setClient( blink::WebRTCDataChannelHandlerClient* client) override; - virtual blink::WebString label() override; - virtual bool isReliable() override; - virtual bool ordered() const override; - virtual unsigned short maxRetransmitTime() const override; - virtual unsigned short maxRetransmits() const override; - virtual blink::WebString protocol() const override; - virtual bool negotiated() const override; - virtual unsigned short id() const override; - // TODO(bemasc): Mark |state()| as |override| once https://codereview.chromium.org/782843003/ - // lands in Blink and rolls into Chromium. - virtual blink::WebRTCDataChannelHandlerClient::ReadyState state() const; - virtual unsigned long bufferedAmount() override; - virtual bool sendStringData(const blink::WebString& data) override; - virtual bool sendRawData(const char* data, size_t length) override; - virtual void close() override; + blink::WebString label() override; + bool isReliable() override; + bool ordered() const override; + unsigned short maxRetransmitTime() const override; + unsigned short maxRetransmits() const override; + blink::WebString protocol() const override; + bool negotiated() const override; + unsigned short id() const override; + blink::WebRTCDataChannelHandlerClient::ReadyState state() const override; + unsigned long bufferedAmount() override; + bool sendStringData(const blink::WebString& data) override; + bool sendRawData(const char* data, size_t length) override; + void close() override; const scoped_refptr<webrtc::DataChannelInterface>& channel() const;
diff --git a/content/renderer/media/video_capture_message_filter_unittest.cc b/content/renderer/media/video_capture_message_filter_unittest.cc index 72fd235..e2660b9 100644 --- a/content/renderer/media/video_capture_message_filter_unittest.cc +++ b/content/renderer/media/video_capture_message_filter_unittest.cc
@@ -50,7 +50,7 @@ MOCK_METHOD1(OnDeviceFormatsInUseReceived, void(const media::VideoCaptureFormats& formats_in_use)); - virtual void OnDelegateAdded(int32 device_id) override { + void OnDelegateAdded(int32 device_id) override { ASSERT_TRUE(device_id != 0); ASSERT_TRUE(device_id_ == 0); device_id_ = device_id;
diff --git a/content/renderer/media/webaudio_capturer_source.h b/content/renderer/media/webaudio_capturer_source.h index 94e8a8477..1e682576a 100644 --- a/content/renderer/media/webaudio_capturer_source.h +++ b/content/renderer/media/webaudio_capturer_source.h
@@ -35,11 +35,11 @@ // WebAudioDestinationConsumer implementation. // setFormat() is called early on, so that we can configure the audio track. - virtual void setFormat(size_t number_of_channels, float sample_rate) override; + void setFormat(size_t number_of_channels, float sample_rate) override; // MediaStreamAudioDestinationNode periodically calls consumeAudio(). // Called on the WebAudio audio thread. - virtual void consumeAudio(const blink::WebVector<const float*>& audio_data, - size_t number_of_frames) override; + void consumeAudio(const blink::WebVector<const float*>& audio_data, + size_t number_of_frames) override; // Called when the WebAudioCapturerSource is hooking to a media audio track. // |track| is the sink of the data flow. |source_provider| is the source of @@ -52,7 +52,7 @@ protected: friend class base::RefCountedThreadSafe<WebAudioCapturerSource>; - virtual ~WebAudioCapturerSource(); + ~WebAudioCapturerSource() override; private: // Removes this object from a blink::WebMediaStreamSource with which it
diff --git a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc index 370de9a..14cbf28 100644 --- a/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc +++ b/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -119,6 +119,15 @@ DCHECK(input_frame == &captured_frame_); DCHECK(frame_.get()); + const int64_t timestamp_ns = frame_->timestamp().InMicroseconds() * + base::Time::kNanosecondsPerMicrosecond; + + if (frame_->format() == media::VideoFrame::NATIVE_TEXTURE) { + return new cricket::WebRtcVideoFrame( + new rtc::RefCountedObject<VideoFrameWrapper>(frame_), + captured_frame_.elapsed_time, timestamp_ns); + } + // Create a centered cropped visible rect that preservers aspect ratio for // cropped natural size. gfx::Rect visible_rect = frame_->visible_rect(); @@ -132,9 +141,6 @@ frame_, visible_rect, output_size, base::Bind(&ReleaseOriginalFrame, frame_)); - const int64_t timestamp_ns = frame_->timestamp().InMicroseconds() * - base::Time::kNanosecondsPerMicrosecond; - // If no scaling is needed, return a wrapped version of |frame_| directly. if (video_frame->natural_size() == video_frame->visible_rect().size()) { return new cricket::WebRtcVideoFrame( @@ -257,10 +263,8 @@ DCHECK(thread_checker_.CalledOnValidThread()); TRACE_EVENT0("video", "WebRtcVideoCapturerAdapter::OnFrameCaptured"); if (!(media::VideoFrame::I420 == frame->format() || - media::VideoFrame::YV12 == frame->format())) { - // Some types of sources support textures as output. Since connecting - // sources and sinks do not check the format, we need to just ignore - // formats that we can not handle. + media::VideoFrame::YV12 == frame->format() || + media::VideoFrame::NATIVE_TEXTURE == frame->format())) { NOTREACHED(); return; }
diff --git a/content/renderer/media/webrtc_audio_capturer_unittest.cc b/content/renderer/media/webrtc_audio_capturer_unittest.cc index 43c6e026..92d291f 100644 --- a/content/renderer/media/webrtc_audio_capturer_unittest.cc +++ b/content/renderer/media/webrtc_audio_capturer_unittest.cc
@@ -33,22 +33,22 @@ MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); protected: - virtual ~MockCapturerSource() {} + ~MockCapturerSource() override {} }; class MockMediaStreamAudioSink : public MediaStreamAudioSink { public: MockMediaStreamAudioSink() {} - ~MockMediaStreamAudioSink() {} - virtual void OnData(const media::AudioBus& audio_bus, - base::TimeTicks estimated_capture_time) override { + ~MockMediaStreamAudioSink() override {} + void OnData(const media::AudioBus& audio_bus, + base::TimeTicks estimated_capture_time) override { EXPECT_EQ(audio_bus.channels(), params_.channels()); EXPECT_EQ(audio_bus.frames(), params_.frames_per_buffer()); EXPECT_FALSE(estimated_capture_time.is_null()); OnDataCallback(); } MOCK_METHOD0(OnDataCallback, void()); - virtual void OnSetFormat(const media::AudioParameters& params) override { + void OnSetFormat(const media::AudioParameters& params) override { params_ = params; FormatIsSet(); }
diff --git a/content/renderer/media/webrtc_local_audio_source_provider.h b/content/renderer/media/webrtc_local_audio_source_provider.h index 4bb8e59..12c51d0 100644 --- a/content/renderer/media/webrtc_local_audio_source_provider.h +++ b/content/renderer/media/webrtc_local_audio_source_provider.h
@@ -50,7 +50,7 @@ explicit WebRtcLocalAudioSourceProvider( const blink::WebMediaStreamTrack& track); - virtual ~WebRtcLocalAudioSourceProvider(); + ~WebRtcLocalAudioSourceProvider() override; // MediaStreamAudioSink implementation. void OnData(const media::AudioBus& audio_bus, @@ -60,9 +60,9 @@ blink::WebMediaStreamSource::ReadyState state) override; // blink::WebAudioSourceProvider implementation. - virtual void setClient(blink::WebAudioSourceProviderClient* client) override; - virtual void provideInput(const blink::WebVector<float*>& audio_data, - size_t number_of_frames) override; + void setClient(blink::WebAudioSourceProviderClient* client) override; + void provideInput(const blink::WebVector<float*>& audio_data, + size_t number_of_frames) override; // media::AudioConverter::Inputcallback implementation. // This function is triggered by provideInput()on the WebAudio audio thread,
diff --git a/content/renderer/media/webrtc_local_audio_track_unittest.cc b/content/renderer/media/webrtc_local_audio_track_unittest.cc index b27c222..4eae198de 100644 --- a/content/renderer/media/webrtc_local_audio_track_unittest.cc +++ b/content/renderer/media/webrtc_local_audio_track_unittest.cc
@@ -96,25 +96,25 @@ MOCK_METHOD1(SetVolume, void(double volume)); MOCK_METHOD1(SetAutomaticGainControl, void(bool enable)); - virtual void Initialize(const media::AudioParameters& params, - CaptureCallback* callback, - int session_id) override { + void Initialize(const media::AudioParameters& params, + CaptureCallback* callback, + int session_id) override { DCHECK(params.IsValid()); params_ = params; OnInitialize(params, callback, session_id); } - virtual void Start() override { + void Start() override { audio_thread_.reset(new FakeAudioThread(capturer_, params_)); audio_thread_->Start(); OnStart(); } - virtual void Stop() override { + void Stop() override { audio_thread_->Stop(); audio_thread_.reset(); OnStop(); } protected: - virtual ~MockCapturerSource() {} + ~MockCapturerSource() override {} private: scoped_ptr<FakeAudioThread> audio_thread_;
diff --git a/content/renderer/pepper/content_decryptor_delegate.cc b/content/renderer/pepper/content_decryptor_delegate.cc index e8dc612..0cf812d 100644 --- a/content/renderer/pepper/content_decryptor_delegate.cc +++ b/content/renderer/pepper/content_decryptor_delegate.cc
@@ -8,6 +8,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/metrics/sparse_histogram.h" #include "base/numerics/safe_conversions.h" +#include "base/stl_util.h" #include "base/trace_event/trace_event.h" #include "content/renderer/pepper/ppb_buffer_impl.h" #include "media/base/audio_buffer.h" @@ -53,7 +54,7 @@ // reference-count of 0. If |data| is NULL, sets |*resource| to NULL. Returns // true upon success and false if any error happened. bool MakeBufferResource(PP_Instance instance, - const uint8* data, + const uint8_t* data, uint32_t size, scoped_refptr<PPB_Buffer_Impl>* resource) { TRACE_EVENT0("media", "ContentDecryptorDelegate - MakeBufferResource"); @@ -83,7 +84,7 @@ // Returns true if copy succeeded. Returns false if copy failed, e.g. if the // |array_size| is smaller than the |str| length. template <uint32_t array_size> -bool CopyStringToArray(const std::string& str, uint8 (&array)[array_size]) { +bool CopyStringToArray(const std::string& str, uint8_t(&array)[array_size]) { if (array_size < str.size()) return false; @@ -345,7 +346,7 @@ // TODO(xhwang): Unify EME UMA reporting code when prefixed EME is deprecated. // See http://crbug.com/412987 for details. -void ReportSystemCodeUMA(const std::string& key_system, uint32 system_code) { +void ReportSystemCodeUMA(const std::string& key_system, uint32_t system_code) { // Sparse histogram macro does not cache the histogram, so it's safe to use // macro with non-static histogram name here. UMA_HISTOGRAM_SPARSE_SLOWLY( @@ -405,12 +406,10 @@ } void ContentDecryptorDelegate::SetServerCertificate( - const uint8_t* certificate, - uint32_t certificate_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) { - if (!certificate || - certificate_length < media::limits::kMinCertificateLength || - certificate_length > media::limits::kMaxCertificateLength) { + if (certificate.size() < media::limits::kMinCertificateLength || + certificate.size() > media::limits::kMaxCertificateLength) { promise->reject( media::MediaKeys::INVALID_ACCESS_ERROR, 0, "Incorrect certificate."); return; @@ -419,7 +418,8 @@ uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); PP_Var certificate_array = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( - certificate_length, certificate); + base::checked_cast<uint32>(certificate.size()), + vector_as_array(&certificate)); plugin_decryption_interface_->SetServerCertificate( pp_instance_, promise_id, certificate_array); } @@ -427,13 +427,13 @@ void ContentDecryptorDelegate::CreateSessionAndGenerateRequest( MediaKeys::SessionType session_type, media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<NewSessionCdmPromise> promise) { uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); PP_Var init_data_array = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( - init_data_length, init_data); + base::checked_cast<uint32>(init_data.size()), + vector_as_array(&init_data)); plugin_decryption_interface_->CreateSessionAndGenerateRequest( pp_instance_, promise_id, MediaSessionTypeToPpSessionType(session_type), MediaInitDataTypeToPpInitDataType(init_data_type), init_data_array); @@ -451,13 +451,13 @@ void ContentDecryptorDelegate::UpdateSession( const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<SimpleCdmPromise> promise) { uint32_t promise_id = cdm_promise_adapter_.SavePromise(promise.Pass()); PP_Var response_array = PpapiGlobals::Get()->GetVarTracker()->MakeArrayBufferPPVar( - response_length, response); + base::checked_cast<uint32>(response.size()), + vector_as_array(&response)); plugin_decryption_interface_->UpdateSession( pp_instance_, promise_id, StringVar::StringToPPVar(session_id), response_array); @@ -734,11 +734,11 @@ return true; } -void ContentDecryptorDelegate::OnPromiseResolved(uint32 promise_id) { +void ContentDecryptorDelegate::OnPromiseResolved(uint32_t promise_id) { cdm_promise_adapter_.ResolvePromise(promise_id); } -void ContentDecryptorDelegate::OnPromiseResolvedWithSession(uint32 promise_id, +void ContentDecryptorDelegate::OnPromiseResolvedWithSession(uint32_t promise_id, PP_Var session_id) { StringVar* session_id_string = StringVar::FromPPVar(session_id); DCHECK(session_id_string); @@ -746,9 +746,9 @@ } void ContentDecryptorDelegate::OnPromiseRejected( - uint32 promise_id, + uint32_t promise_id, PP_CdmExceptionCode exception_code, - uint32 system_code, + uint32_t system_code, PP_Var error_description) { ReportSystemCodeUMA(key_system_, system_code); @@ -770,9 +770,10 @@ DCHECK(session_id_string); ArrayBufferVar* message_array_buffer = ArrayBufferVar::FromPPVar(message); - std::vector<uint8> message_vector; + std::vector<uint8_t> message_vector; if (message_array_buffer) { - const uint8* data = static_cast<const uint8*>(message_array_buffer->Map()); + const uint8_t* data = + static_cast<const uint8_t*>(message_array_buffer->Map()); message_vector.assign(data, data + message_array_buffer->ByteLength()); } @@ -849,7 +850,7 @@ void ContentDecryptorDelegate::OnLegacySessionError( PP_Var session_id, PP_CdmExceptionCode exception_code, - uint32 system_code, + uint32_t system_code, PP_Var error_description) { ReportSystemCodeUMA(key_system_, system_code); @@ -949,7 +950,7 @@ // TODO(tomfinegan): Find a way to take ownership of the shared memory // managed by the PPB_Buffer_Dev, and avoid the extra copy. scoped_refptr<media::DecoderBuffer> decrypted_buffer( - media::DecoderBuffer::CopyFrom(static_cast<uint8*>(mapper.data()), + media::DecoderBuffer::CopyFrom(static_cast<uint8_t*>(mapper.data()), block_info->data_size)); decrypted_buffer->set_timestamp( base::TimeDelta::FromMicroseconds(block_info->tracking_info.timestamp)); @@ -968,13 +969,13 @@ // Enters |resource|, maps shared memory and returns pointer of mapped data. // Returns NULL if any error occurs. -static uint8* GetMappedBuffer(PP_Resource resource, - scoped_refptr<PPB_Buffer_Impl>* ppb_buffer) { +static uint8_t* GetMappedBuffer(PP_Resource resource, + scoped_refptr<PPB_Buffer_Impl>* ppb_buffer) { EnterResourceNoLock<PPB_Buffer_API> enter(resource, true); if (!enter.succeeded()) return NULL; - uint8* mapped_data = static_cast<uint8*>(enter.object()->Map()); + uint8_t* mapped_data = static_cast<uint8_t*>(enter.object()->Map()); if (!enter.object()->IsMapped() || !mapped_data) return NULL; @@ -1018,7 +1019,7 @@ } scoped_refptr<PPB_Buffer_Impl> ppb_buffer; - uint8* frame_data = GetMappedBuffer(decrypted_frame, &ppb_buffer); + uint8_t* frame_data = GetMappedBuffer(decrypted_frame, &ppb_buffer); if (!frame_data) { FreeBuffer(frame_info->tracking_info.buffer_id); video_decode_cb.Run(Decryptor::kError, NULL); @@ -1208,7 +1209,7 @@ // TODO(jrummell): Pass ownership of data() directly to AudioBuffer to avoid // the copy. Since it is possible to get multiple buffers, it would need to be // sliced and ref counted appropriately. http://crbug.com/255576. - const uint8* cur = static_cast<uint8*>(mapper.data()); + const uint8_t* cur = static_cast<uint8_t*>(mapper.data()); size_t bytes_left = data_size; const int audio_bytes_per_frame = @@ -1218,8 +1219,7 @@ return false; // Allocate space for the channel pointers given to AudioBuffer. - std::vector<const uint8*> channel_ptrs(audio_channel_count_, - static_cast<const uint8*>(NULL)); + std::vector<const uint8_t*> channel_ptrs(audio_channel_count_, nullptr); do { int64 timestamp = 0; int64 frame_size = -1;
diff --git a/content/renderer/pepper/content_decryptor_delegate.h b/content/renderer/pepper/content_decryptor_delegate.h index 1fbeddba5..cb3791d 100644 --- a/content/renderer/pepper/content_decryptor_delegate.h +++ b/content/renderer/pepper/content_decryptor_delegate.h
@@ -8,6 +8,7 @@ #include <map> #include <queue> #include <string> +#include <vector> #include "base/basictypes.h" #include "base/callback_helpers.h" @@ -60,21 +61,18 @@ void InstanceCrashed(); // Provides access to PPP_ContentDecryptor_Private. - void SetServerCertificate(const uint8_t* certificate, - uint32_t certificate_length, + void SetServerCertificate(const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise); void CreateSessionAndGenerateRequest( media::MediaKeys::SessionType session_type, media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise); void LoadSession(media::MediaKeys::SessionType session_type, const std::string& session_id, scoped_ptr<media::NewSessionCdmPromise> promise); void UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise); void CloseSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise); @@ -103,11 +101,11 @@ const media::Decryptor::VideoDecodeCB& video_decode_cb); // PPB_ContentDecryptor_Private dispatching methods. - void OnPromiseResolved(uint32 promise_id); - void OnPromiseResolvedWithSession(uint32 promise_id, PP_Var session_id); - void OnPromiseRejected(uint32 promise_id, + void OnPromiseResolved(uint32_t promise_id); + void OnPromiseResolvedWithSession(uint32_t promise_id, PP_Var session_id); + void OnPromiseRejected(uint32_t promise_id, PP_CdmExceptionCode exception_code, - uint32 system_code, + uint32_t system_code, PP_Var error_description); void OnSessionMessage(PP_Var session_id, PP_CdmMessageType message_type, @@ -121,7 +119,7 @@ void OnSessionClosed(PP_Var session_id); void OnLegacySessionError(PP_Var session_id, PP_CdmExceptionCode exception_code, - uint32 system_code, + uint32_t system_code, PP_Var error_description); void DeliverBlock(PP_Resource decrypted_block, const PP_DecryptedBlockInfo* block_info);
diff --git a/content/renderer/pepper/message_channel.h b/content/renderer/pepper/message_channel.h index c3776e922..3445077 100644 --- a/content/renderer/pepper/message_channel.h +++ b/content/renderer/pepper/message_channel.h
@@ -192,7 +192,7 @@ // Observers for sync messages. base::Closure unregister_observer_callback_; - v8::StdPersistentValueMap<std::string, v8::FunctionTemplate> template_cache_; + v8::StdGlobalValueMap<std::string, v8::FunctionTemplate> template_cache_; // This is used to ensure pending tasks will not fire after this object is // destroyed.
diff --git a/content/renderer/pepper/pepper_video_encoder_host.cc b/content/renderer/pepper/pepper_video_encoder_host.cc index 39292bbc..7c0b9fd0 100644 --- a/content/renderer/pepper/pepper_video_encoder_host.cc +++ b/content/renderer/pepper/pepper_video_encoder_host.cc
@@ -513,7 +513,7 @@ return false; } - command_buffer_->SetChannelErrorCallback(media::BindToCurrentLoop( + command_buffer_->SetContextLostCallback(media::BindToCurrentLoop( base::Bind(&PepperVideoEncoderHost::NotifyPepperError, weak_ptr_factory_.GetWeakPtr(), PP_ERROR_RESOURCE_FAILED))); if (!command_buffer_->Initialize()) {
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl.cc b/content/renderer/pepper/plugin_instance_throttler_impl.cc index a79201cb..593fb99 100644 --- a/content/renderer/pepper/plugin_instance_throttler_impl.cc +++ b/content/renderer/pepper/plugin_instance_throttler_impl.cc
@@ -8,7 +8,12 @@ #include "base/time/time.h" #include "content/public/common/content_constants.h" #include "content/public/renderer/render_thread.h" +#include "content/renderer/pepper/pepper_plugin_instance_impl.h" +#include "content/renderer/pepper/pepper_webplugin_impl.h" #include "content/renderer/render_frame_impl.h" +#include "ppapi/shared_impl/ppapi_constants.h" +#include "ppapi/shared_impl/scoped_pp_var.h" +#include "ppapi/shared_impl/var.h" #include "third_party/WebKit/public/platform/WebRect.h" #include "third_party/WebKit/public/web/WebInputEvent.h" #include "third_party/WebKit/public/web/WebPluginParams.h" @@ -98,6 +103,14 @@ if (was_throttled) FOR_EACH_OBSERVER(Observer, observer_list_, OnThrottleStateChange()); + + // Notify the Power Saver test plugin of a peripheral status change. + if (web_plugin_ && web_plugin_->instance() && + plugin_module_name_ == ppapi::kPowerSaverTestPluginName) { + web_plugin_->instance()->HandleMessage(ppapi::ScopedPPVar( + ppapi::ScopedPPVar::PassRef(), + ppapi::StringVar::StringToPPVar("peripheralStatusChange"))); + } } void PluginInstanceThrottlerImpl::SetHiddenForPlaceholder(bool hidden) { @@ -119,7 +132,8 @@ audio_throttled_frame_timeout_.Reset(); } -void PluginInstanceThrottlerImpl::SetWebPlugin(blink::WebPlugin* web_plugin) { +void PluginInstanceThrottlerImpl::SetWebPlugin( + PepperWebPluginImpl* web_plugin) { DCHECK(!web_plugin_); web_plugin_ = web_plugin; } @@ -129,6 +143,7 @@ const GURL& content_origin, const std::string& plugin_module_name, const gfx::Size& unobscured_size) { + plugin_module_name_ = plugin_module_name; unobscured_size_ = unobscured_size; // |frame| may be nullptr in tests.
diff --git a/content/renderer/pepper/plugin_instance_throttler_impl.h b/content/renderer/pepper/plugin_instance_throttler_impl.h index b33db8e..13fe1aef8 100644 --- a/content/renderer/pepper/plugin_instance_throttler_impl.h +++ b/content/renderer/pepper/plugin_instance_throttler_impl.h
@@ -22,6 +22,7 @@ namespace content { +class PepperWebPluginImpl; class RenderFrameImpl; class CONTENT_EXPORT PluginInstanceThrottlerImpl @@ -42,7 +43,7 @@ const gfx::Size& GetSize() const override; void NotifyAudioThrottled() override; - void SetWebPlugin(blink::WebPlugin* web_plugin); + void SetWebPlugin(PepperWebPluginImpl* web_plugin); bool needs_representative_keyframe() const { return state_ == THROTTLER_STATE_AWAITING_KEYFRAME; @@ -88,7 +89,7 @@ bool is_hidden_for_placeholder_; - blink::WebPlugin* web_plugin_; + PepperWebPluginImpl* web_plugin_; // Holds a reference to the last received frame. This doesn't actually copy // the pixel data, but rather increments the reference count to the pixels. @@ -100,6 +101,9 @@ // Number of frames we've examined to find a keyframe. int frames_examined_; + // Plugin module name as of initialization. + std::string plugin_module_name_; + // Plugin's unobscured dimensions as of initialization. gfx::Size unobscured_size_;
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc index 6d0a03c..1cbdcaf 100644 --- a/content/renderer/pepper/plugin_module.cc +++ b/content/renderer/pepper/plugin_module.cc
@@ -21,6 +21,7 @@ #include "content/renderer/pepper/pepper_hung_plugin_filter.h" #include "content/renderer/pepper/pepper_plugin_instance_impl.h" #include "content/renderer/pepper/pepper_plugin_registry.h" +#include "content/renderer/pepper/plugin_instance_throttler_impl.h" #include "content/renderer/pepper/ppapi_preferences_builder.h" #include "content/renderer/pepper/ppb_image_data_impl.h" #include "content/renderer/pepper/ppb_proxy_impl.h" @@ -245,6 +246,14 @@ PP_Bool IsOutOfProcess() { return PP_FALSE; } +PP_Bool IsPeripheral(PP_Instance instance_id) { + PepperPluginInstanceImpl* plugin_instance = + host_globals->GetInstance(instance_id); + if (!plugin_instance || !plugin_instance->throttler()) + return PP_FALSE; + return PP_FromBool(plugin_instance->throttler()->power_saver_enabled()); +} + void SimulateInputEvent(PP_Instance instance, PP_Resource input_event) { PepperPluginInstanceImpl* plugin_instance = host_globals->GetInstance(instance); @@ -288,11 +297,17 @@ } const PPB_Testing_Private testing_interface = { - &ReadImageData, &RunMessageLoop, - &QuitMessageLoop, &GetLiveObjectsForInstance, - &IsOutOfProcess, &SimulateInputEvent, - &GetDocumentURL, &GetLiveVars, - &SetMinimumArrayBufferSizeForShmem,&RunV8GC}; + &ReadImageData, + &RunMessageLoop, + &QuitMessageLoop, + &GetLiveObjectsForInstance, + &IsOutOfProcess, + &IsPeripheral, + &SimulateInputEvent, + &GetDocumentURL, + &GetLiveVars, + &SetMinimumArrayBufferSizeForShmem, + &RunV8GC}; // GetInterface ----------------------------------------------------------------
diff --git a/content/renderer/pepper/plugin_object.h b/content/renderer/pepper/plugin_object.h index 88b608e..85c86aa 100644 --- a/content/renderer/pepper/plugin_object.h +++ b/content/renderer/pepper/plugin_object.h
@@ -84,7 +84,7 @@ const PPP_Class_Deprecated* ppp_class_; void* ppp_class_data_; - v8::StdPersistentValueMap<std::string, v8::FunctionTemplate> template_cache_; + v8::StdGlobalValueMap<std::string, v8::FunctionTemplate> template_cache_; base::WeakPtrFactory<PluginObject> weak_factory_;
diff --git a/content/renderer/pepper/plugin_power_saver_helper.cc b/content/renderer/pepper/plugin_power_saver_helper.cc index 2891980..3e6fd759 100644 --- a/content/renderer/pepper/plugin_power_saver_helper.cc +++ b/content/renderer/pepper/plugin_power_saver_helper.cc
@@ -9,6 +9,7 @@ #include "content/common/frame_messages.h" #include "content/public/common/content_constants.h" #include "content/public/renderer/render_frame.h" +#include "ppapi/shared_impl/ppapi_constants.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebPluginParams.h" @@ -121,8 +122,11 @@ *cross_origin_main_content = false; // This feature has only been tested throughly with Flash thus far. - if (plugin_module_name != content::kFlashPluginName) + // It is also enabled for the Power Saver test plugin for browser tests. + if (plugin_module_name != content::kFlashPluginName && + plugin_module_name != ppapi::kPowerSaverTestPluginName) { return false; + } if (width <= 0 || height <= 0) return false;
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc index b703cef..2de5e109 100644 --- a/content/renderer/pepper/ppb_graphics_3d_impl.cc +++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -312,7 +312,7 @@ return false; sync_point_ = command_buffer_->InsertSyncPoint(); - command_buffer_->SetChannelErrorCallback(base::Bind( + command_buffer_->SetContextLostCallback(base::Bind( &PPB_Graphics3D_Impl::OnContextLost, weak_ptr_factory_.GetWeakPtr())); command_buffer_->SetOnConsoleMessageCallback(base::Bind(
diff --git a/content/renderer/presentation/presentation_dispatcher.cc b/content/renderer/presentation/presentation_dispatcher.cc index 39e5238b..c074df3d 100644 --- a/content/renderer/presentation/presentation_dispatcher.cc +++ b/content/renderer/presentation/presentation_dispatcher.cc
@@ -172,9 +172,10 @@ &PresentationDispatcher::OnDefaultSessionStarted, base::Unretained(this))); - DCHECK(!session_info.is_null()); - controller_->didStartDefaultSession( - new PresentationSessionClient(session_info.Pass())); + if (!session_info.is_null()) { + controller_->didStartDefaultSession( + new PresentationSessionClient(session_info.Pass())); + } } void PresentationDispatcher::OnSessionCreated(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 1e7ead7..dfa09aa 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1091,29 +1091,6 @@ GetContentClient()->SetActiveURL(common_params.url); - WebFrame* frame = frame_; - if (!request_params.frame_to_navigate.empty()) { - // TODO(nasko): Move this lookup to the browser process. - frame = render_view_->webview()->findFrameByName( - WebString::fromUTF8(request_params.frame_to_navigate)); - CHECK(frame) << "Invalid frame name passed: " - << request_params.frame_to_navigate; - } - - // If this frame isn't in the same process as its parent, it will naively - // assume that this is the first navigation in the iframe, but this may not - // actually be the case. The PageTransition differentiates between the first - // navigation in a subframe and subsequent navigations, so if this is a - // subsequent navigation, force the frame's state machine forward. - if (ui::PageTransitionCoreTypeIs(common_params.transition, - ui::PAGE_TRANSITION_MANUAL_SUBFRAME)) { - CHECK(frame_->parent()); - if (frame_->parent()->isWebRemoteFrame()) { - CHECK_EQ(frame, frame_); - frame_->setCommittedFirstRealLoad(); - } - } - if (is_reload && !render_view_->history_controller()->GetCurrentEntry()) { // We cannot reload if we do not have any history state. This happens, for // example, when recovering from a crash. @@ -1136,12 +1113,16 @@ FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE); if (reload_original_url) - frame->reloadWithOverrideURL(common_params.url, true); + frame_->reloadWithOverrideURL(common_params.url, true); else - frame->reload(ignore_cache); + frame_->reload(ignore_cache); } else if (is_history_navigation) { // We must know the page ID of the page we are navigating back to. DCHECK_NE(request_params.page_id, -1); + // We must know the nav entry ID of the page we are navigating back to, + // which should be the case because history navigations are routed via the + // browser. + DCHECK_NE(0, request_params.nav_entry_id); scoped_ptr<HistoryEntry> entry = PageStateToHistoryEntry(request_params.page_state); if (entry) { @@ -1154,12 +1135,12 @@ entry.Pass(), navigation_params.Pass(), cache_policy); } } else if (!common_params.base_url_for_data_url.is_empty()) { - LoadDataURL(common_params, frame); + LoadDataURL(common_params, frame_); } else { // Navigate to the given URL. WebURLRequest request = CreateURLRequestForNavigation( common_params, scoped_ptr<StreamOverrideParameters>(), - frame->isViewSourceModeEnabled()); + frame_->isViewSourceModeEnabled()); if (!start_params.extra_headers.empty()) { for (net::HttpUtil::HeadersIterator i(start_params.extra_headers.begin(), @@ -1193,9 +1174,9 @@ // Record this before starting the load, we need a lower bound of this time // to sanitize the navigationStart override set below. base::TimeTicks renderer_navigation_start = base::TimeTicks::Now(); - frame->loadRequest(request); + frame_->loadRequest(request); - UpdateFrameNavigationTiming(frame, request_params.browser_navigation_start, + UpdateFrameNavigationTiming(frame_, request_params.browser_navigation_start, renderer_navigation_start); } @@ -2568,8 +2549,6 @@ document_state->set_start_load_time(Time::Now()); bool is_top_most = !frame->parent(); - NavigationStateImpl* navigation_state = - static_cast<NavigationStateImpl*>(document_state->navigation_state()); if (is_top_most) { render_view_->set_navigation_gesture( WebUserGestureIndicator::isProcessingUserGesture() ? @@ -2578,17 +2557,8 @@ // Subframe navigations that don't add session history items must be // marked with AUTO_SUBFRAME. See also didFailProvisionalLoad for how we // handle loading of error pages. - navigation_state->set_transition_type(ui::PAGE_TRANSITION_AUTO_SUBFRAME); - } else if (ui::PageTransitionCoreTypeIs(navigation_state->GetTransitionType(), - ui::PAGE_TRANSITION_LINK)) { - // Subframe navigations that are creating a new history item should be - // marked MANUAL_SUBFRAME, unless it has already been marked as a - // FORM_SUBMIT. This state will be attached to a main resource request - // in the process that began the request. If the request is transferred - // to a different process, this state will be used in - // RenderFrameImpl::OnNavigate() in the new process (as well as in the - // browser process). - navigation_state->set_transition_type(ui::PAGE_TRANSITION_MANUAL_SUBFRAME); + static_cast<NavigationStateImpl*>(document_state->navigation_state()) + ->set_transition_type(ui::PAGE_TRANSITION_AUTO_SUBFRAME); } FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(), @@ -2617,6 +2587,10 @@ const WebURLRequest& failed_request = ds->request(); + DocumentState* document_state = DocumentState::FromDataSource(ds); + NavigationStateImpl* navigation_state = + static_cast<NavigationStateImpl*>(document_state->navigation_state()); + // Notify the browser that we failed a provisional load with an error. // // Note: It is important this notification occur before DidStopLoading so the @@ -2636,10 +2610,6 @@ // Make sure we never show errors in view source mode. frame->enableViewSourceMode(false); - DocumentState* document_state = DocumentState::FromDataSource(ds); - NavigationStateImpl* navigation_state = - static_cast<NavigationStateImpl*>(document_state->navigation_state()); - // If this is a failed back/forward/reload navigation, then we need to do a // 'replace' load. This is necessary to avoid messing up session history. // Otherwise, we do a normal load, which simulates a 'go' navigation as far @@ -2726,18 +2696,7 @@ render_view_->history_list_offset_ + 1; } } else { - // Inspect the navigation_state on this frame to see if the navigation - // corresponds to a session history navigation... Note: |frame| may or - // may not be the toplevel frame, but for the case of capturing session - // history, the first committed frame suffices. We keep track of whether - // we've seen this commit before so that only capture session history once - // per navigation. - // - // Note that we need to check if the page ID changed. In the case of a - // reload, the page ID doesn't change, and UpdateSessionHistory gets the - // previous URL and the current page ID, which would be wrong. - if (navigation_state->request_params().page_id != -1 && - navigation_state->request_params().page_id != render_view_->page_id_) { + if (navigation_state->request_params().page_id != -1) { // This is a successful session history navigation! render_view_->page_id_ = navigation_state->request_params().page_id; @@ -3172,9 +3131,16 @@ } } - WebDataSource* provisional_data_source = frame->provisionalDataSource(); + WebFrame* top_frame = frame->top(); + // TODO(nasko): Hack around asking about top-frame data source. This means + // for out-of-process iframes we are treating the current frame as the + // top-level frame, which is wrong. + if (!top_frame || top_frame->isWebRemoteFrame()) + top_frame = frame; + WebDataSource* provisional_data_source = top_frame->provisionalDataSource(); + WebDataSource* top_data_source = top_frame->dataSource(); WebDataSource* data_source = - provisional_data_source ? provisional_data_source : frame->dataSource(); + provisional_data_source ? provisional_data_source : top_data_source; DocumentState* document_state = DocumentState::FromDataSource(data_source); DCHECK(document_state); @@ -3313,14 +3279,8 @@ extra_data->set_stream_override(stream_override.Pass()); request.setExtraData(extra_data); - WebFrame* top_frame = frame->top(); - // TODO(nasko): Hack around asking about top-frame data source. This means - // for out-of-process iframes we are treating the current frame as the - // top-level frame, which is wrong. - if (!top_frame || top_frame->isWebRemoteFrame()) - top_frame = frame; DocumentState* top_document_state = - DocumentState::FromDataSource(top_frame->dataSource()); + DocumentState::FromDataSource(top_data_source); if (top_document_state) { // TODO(gavinp): separate out prefetching and prerender field trials // if the rel=prerender rel type is sticking around. @@ -3894,8 +3854,12 @@ params.http_status_code = response.httpStatusCode(); params.url_is_unreachable = ds->hasUnreachableURL(); params.is_post = false; + params.intended_as_new_entry = + navigation_state->request_params().intended_as_new_entry; + params.did_create_new_entry = commit_type == blink::WebStandardCommit; params.post_id = -1; params.page_id = render_view_->page_id_; + params.nav_entry_id = navigation_state->request_params().nav_entry_id; // We need to track the RenderViewHost routing_id because of downstream // dependencies (crbug.com/392171 DownloadRequestHandle, SaveFileManager, // ResourceDispatcherHostImpl, MediaStreamUIProxy,
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index f433733..558c391 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -211,6 +211,7 @@ IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateSandboxFlags, OnDidUpdateSandboxFlags) IPC_MESSAGE_HANDLER(FrameMsg_DispatchLoad, OnDispatchLoad) IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateName, OnDidUpdateName) + IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateOrigin, OnDidUpdateOrigin) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -303,6 +304,11 @@ web_frame_->setReplicatedName(blink::WebString::fromUTF8(name)); } +void RenderFrameProxy::OnDidUpdateOrigin(const url::Origin& origin) { + web_frame_->setReplicatedOrigin(blink::WebSecurityOrigin::createFromString( + blink::WebString::fromUTF8(origin.string()))); +} + void RenderFrameProxy::frameDetached() { if (web_frame_->parent()) { web_frame_->parent()->removeChild(web_frame_);
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index 19a94f68..fba8c9a 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -12,6 +12,7 @@ #include "ipc/ipc_sender.h" #include "third_party/WebKit/public/web/WebRemoteFrame.h" #include "third_party/WebKit/public/web/WebRemoteFrameClient.h" +#include "url/origin.h" struct FrameMsg_BuffersSwapped_Params; struct FrameMsg_CompositorFrameSwapped_Params; @@ -144,6 +145,7 @@ void OnDidUpdateSandboxFlags(SandboxFlags flags); void OnDispatchLoad(); void OnDidUpdateName(const std::string& name); + void OnDidUpdateOrigin(const url::Origin& origin); // The routing ID by which this RenderFrameProxy is known. const int routing_id_;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 61fd840..acda8a7 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -1294,7 +1294,7 @@ GURL("chrome://gpu/RenderThreadImpl::GetGpuVDAContext3D"), WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL)), - "GPU-VideoAccelerator-Offscreen"); + GPU_VIDEO_ACCELERATOR_CONTEXT); } } if (gpu_va_context_provider_.get()) { @@ -1336,7 +1336,7 @@ #endif if (!shared_main_thread_contexts_.get()) { shared_main_thread_contexts_ = ContextProviderCommandBuffer::Create( - CreateOffscreenContext3d(), "Offscreen-MainThread"); + CreateOffscreenContext3d(), RENDERER_MAINTHREAD_CONTEXT); } if (shared_main_thread_contexts_.get() && !shared_main_thread_contexts_->BindToCurrentThread())
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index f01c892..13d0952 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -285,17 +285,24 @@ view()->OnSetZoomLevelForView(false, level); } - void NavigateFrame(const CommonNavigationParams& common_params, + void NavigateMainFrame(const CommonNavigationParams& common_params, + const StartNavigationParams& start_params, + const RequestNavigationParams& request_params) { + NavigateFrame(frame(), common_params, start_params, request_params); + } + + void NavigateFrame(RenderFrameImpl* frame, + const CommonNavigationParams& common_params, const StartNavigationParams& start_params, const RequestNavigationParams& request_params) { // PlzNavigate if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kEnableBrowserSideNavigation)) { - frame()->OnCommitNavigation(ResourceResponseHead(), common_params.url, - common_params, request_params); + frame->OnCommitNavigation(ResourceResponseHead(), common_params.url, + common_params, request_params); return; } - frame()->OnNavigate(common_params, start_params, request_params); + frame->OnNavigate(common_params, start_params, request_params); } void SwapOut(RenderFrameImpl* frame, @@ -473,7 +480,7 @@ start_params.is_post = true; start_params.browser_initiated_post_data = post_data; - NavigateFrame(common_params, start_params, request_params); + NavigateMainFrame(common_params, start_params, request_params); ProcessPendingMessages(); const IPC::Message* frame_navigate_msg = @@ -672,7 +679,7 @@ request_params.current_history_list_offset = 0; request_params.pending_history_list_offset = 1; request_params.page_id = -1; - NavigateFrame(common_params, StartNavigationParams(), request_params); + NavigateMainFrame(common_params, StartNavigationParams(), request_params); ProcessPendingMessages(); const IPC::Message* msg3 = render_thread_->sink().GetUniqueMessageMatching( ViewHostMsg_UpdateState::ID); @@ -709,8 +716,9 @@ request_params_A.current_history_list_offset = 1; request_params_A.pending_history_list_offset = 0; request_params_A.page_id = 1; + request_params_A.nav_entry_id = 1; request_params_A.page_state = state_A; - NavigateFrame(common_params_A, StartNavigationParams(), request_params_A); + NavigateMainFrame(common_params_A, StartNavigationParams(), request_params_A); EXPECT_EQ(1, view()->historyBackListCount()); EXPECT_EQ(2, view()->historyBackListCount() + view()->historyForwardListCount() + 1); @@ -738,8 +746,9 @@ request_params.current_history_list_offset = 0; request_params.pending_history_list_offset = 0; request_params.page_id = 1; + request_params.nav_entry_id = 1; request_params.page_state = state_A; - NavigateFrame(common_params, StartNavigationParams(), request_params); + NavigateMainFrame(common_params, StartNavigationParams(), request_params); ProcessPendingMessages(); // Verify page A committed, not swappedout://. @@ -857,7 +866,7 @@ request_params_C.pending_history_list_offset = 2; request_params_C.page_id = 3; request_params_C.page_state = state_C; - NavigateFrame(common_params_C, StartNavigationParams(), request_params_C); + NavigateMainFrame(common_params_C, StartNavigationParams(), request_params_C); ProcessPendingMessages(); render_thread_->sink().ClearMessages(); @@ -875,7 +884,7 @@ request_params_B.pending_history_list_offset = 1; request_params_B.page_id = 2; request_params_B.page_state = state_B; - NavigateFrame(common_params_B, StartNavigationParams(), request_params_B); + NavigateMainFrame(common_params_B, StartNavigationParams(), request_params_B); // Back to page A (page_id 1) and commit. CommonNavigationParams common_params; @@ -887,7 +896,7 @@ request_params.pending_history_list_offset = 0; request_params.page_id = 1; request_params.page_state = state_A; - NavigateFrame(common_params, StartNavigationParams(), request_params); + NavigateMainFrame(common_params, StartNavigationParams(), request_params); ProcessPendingMessages(); // Now ensure that the UpdateState message we receive is consistent @@ -908,12 +917,12 @@ // ignored. See http://crbug.com/86758. TEST_F(RenderViewImplTest, StaleNavigationsIgnored) { // Load page A. - LoadHTML("<div>Page A</div>"); + LoadHTML("<div id=pagename>Page A</div>"); EXPECT_EQ(1, view()->history_list_length_); EXPECT_EQ(0, view()->history_list_offset_); // Load page B, which will trigger an UpdateState message for page A. - LoadHTML("<div>Page B</div>"); + LoadHTML("<div id=pagename>Page B</div>"); EXPECT_EQ(2, view()->history_list_length_); EXPECT_EQ(1, view()->history_list_offset_); @@ -929,7 +938,7 @@ EXPECT_EQ(1, page_id_A); render_thread_->sink().ClearMessages(); - // Back to page A (page_id 1) and commit. + // Back to page A (nav_entry_id 1) and commit. CommonNavigationParams common_params_A; RequestNavigationParams request_params_A; common_params_A.navigation_type = FrameMsg_Navigate_Type::NORMAL; @@ -938,15 +947,21 @@ request_params_A.current_history_list_offset = 1; request_params_A.pending_history_list_offset = 0; request_params_A.page_id = 1; + request_params_A.nav_entry_id = 1; request_params_A.page_state = state_A; - NavigateFrame(common_params_A, StartNavigationParams(), request_params_A); + NavigateMainFrame(common_params_A, StartNavigationParams(), request_params_A); ProcessPendingMessages(); // A new navigation commits, clearing the forward history. - LoadHTML("<div>Page C</div>"); + LoadHTML("<div id=pagename>Page C</div>"); EXPECT_EQ(2, view()->history_list_length_); EXPECT_EQ(1, view()->history_list_offset_); EXPECT_EQ(3, view()->page_id_); // page C is now page id 3 + int was_page_c = -1; + base::string16 check_page_c = base::ASCIIToUTF16( + "Number(document.getElementById('pagename').innerHTML == 'Page C')"); + EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c)); + EXPECT_EQ(1, was_page_c); // The browser then sends a stale navigation to B, which should be ignored. CommonNavigationParams common_params_B; @@ -957,14 +972,18 @@ request_params_B.current_history_list_offset = 0; request_params_B.pending_history_list_offset = 1; request_params_B.page_id = 2; + request_params_B.nav_entry_id = 2; request_params_B.page_state = state_A; // Doesn't matter, just has to be present. - NavigateFrame(common_params_B, StartNavigationParams(), request_params_B); + NavigateMainFrame(common_params_B, StartNavigationParams(), request_params_B); // State should be unchanged. EXPECT_EQ(2, view()->history_list_length_); EXPECT_EQ(1, view()->history_list_offset_); EXPECT_EQ(3, view()->page_id_); // page C, not page B + was_page_c = -1; + EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c)); + EXPECT_EQ(1, was_page_c); // Check for a valid DidDropNavigation message. ProcessPendingMessages(); @@ -1674,8 +1693,8 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; common_params.url = GURL("data:text/html,test data"); - NavigateFrame(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateMainFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); // An error occurred. view()->GetMainRenderFrame()->didFailProvisionalLoad( @@ -1697,8 +1716,8 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; common_params.url = GURL("data:text/html,test data"); - NavigateFrame(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateMainFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); // A cancellation occurred. view()->GetMainRenderFrame()->didFailProvisionalLoad( @@ -1895,8 +1914,8 @@ CommonNavigationParams common_params; common_params.url = GURL("data:text/html,min_zoomlimit_test"); view()->OnSetZoomLevelForLoadingURL(common_params.url, kMinZoomLevel); - NavigateFrame(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateMainFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); ProcessPendingMessages(); EXPECT_DOUBLE_EQ(kMinZoomLevel, view()->GetWebView()->zoomLevel()); @@ -1905,8 +1924,8 @@ ZoomFactorToZoomLevel(1.0)); common_params.url = GURL("data:text/html,max_zoomlimit_test"); view()->OnSetZoomLevelForLoadingURL(common_params.url, kMaxZoomLevel); - NavigateFrame(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateMainFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); ProcessPendingMessages(); EXPECT_DOUBLE_EQ(kMaxZoomLevel, view()->GetWebView()->zoomLevel()); } @@ -1961,7 +1980,7 @@ } // Test that the navigating specific frames works correctly. -TEST_F(RenderViewImplTest, NavigateFrame) { +TEST_F(RenderViewImplTest, NavigateSubframe) { // Load page A. LoadHTML("hello <iframe srcdoc='fail' name='frame'></iframe>"); @@ -1975,12 +1994,14 @@ request_params.current_history_list_offset = 0; request_params.pending_history_list_offset = 1; request_params.page_id = -1; - request_params.frame_to_navigate = "frame"; request_params.browser_navigation_start = base::TimeTicks::FromInternalValue(1); - NavigateFrame(common_params, StartNavigationParams(), request_params); - FrameLoadWaiter( - RenderFrame::FromWebFrame(frame()->GetWebFrame()->firstChild())).Wait(); + + RenderFrameImpl* subframe = RenderFrameImpl::FromWebFrame( + view()->webview()->findFrameByName("frame")); + NavigateFrame(subframe, common_params, StartNavigationParams(), + request_params); + FrameLoadWaiter(subframe).Wait(); // Copy the document content to std::wstring and compare with the // expected result. @@ -2095,8 +2116,8 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; common_params.url = GURL("data:text/html,test data"); - NavigateFrame(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateMainFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); // An error occurred. view()->GetMainRenderFrame()->didFailProvisionalLoad( @@ -2125,8 +2146,8 @@ CommonNavigationParams common_params; common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL; common_params.url = GURL("data:text/html,test data"); - NavigateFrame(common_params, StartNavigationParams(), - RequestNavigationParams()); + NavigateMainFrame(common_params, StartNavigationParams(), + RequestNavigationParams()); // An error occurred. view()->GetMainRenderFrame()->didFailProvisionalLoad( @@ -2336,7 +2357,8 @@ early_request_params.browser_navigation_start = base::TimeTicks::FromInternalValue(1); - NavigateFrame(early_common_params, early_start_params, early_request_params); + NavigateMainFrame(early_common_params, early_start_params, + early_request_params); ProcessPendingMessages(); base::Time early_nav_reported_start = @@ -2356,7 +2378,7 @@ late_request_params.browser_navigation_start = base::TimeTicks::Now() + base::TimeDelta::FromDays(42); - NavigateFrame(late_common_params, late_start_params, late_request_params); + NavigateMainFrame(late_common_params, late_start_params, late_request_params); ProcessPendingMessages(); base::Time after_navigation = base::Time::Now() + base::TimeDelta::FromDays(1); @@ -2393,8 +2415,8 @@ request_params.current_history_list_offset = 1; request_params.pending_history_list_offset = 2; request_params.page_id = -1; - NavigateFrame(CommonNavigationParams(), StartNavigationParams(), - request_params); + NavigateMainFrame(CommonNavigationParams(), StartNavigationParams(), + request_params); // The history list in RenderView should have been updated. EXPECT_EQ(1, view()->historyBackListCount());
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 66d2c0d..eb997132 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -134,7 +134,6 @@ #include "third_party/WebKit/public/web/WebDataSource.h" #include "third_party/WebKit/public/web/WebDateTimeChooserCompletion.h" #include "third_party/WebKit/public/web/WebDateTimeChooserParams.h" -#include "third_party/WebKit/public/web/WebDevToolsAgent.h" #include "third_party/WebKit/public/web/WebDocument.h" #include "third_party/WebKit/public/web/WebElement.h" #include "third_party/WebKit/public/web/WebFileChooserParams.h" @@ -402,12 +401,6 @@ sizes->push_back(gfx::Size(web_sizes[i])); } -static blink::WebDevToolsAgent* GetWebDevToolsAgent(WebView* webview) { - if (!webview || !webview->mainFrame()->isWebLocalFrame()) - return nullptr; - return webview->mainFrame()->toWebLocalFrame()->devToolsAgent(); -} - /////////////////////////////////////////////////////////////////////////////// struct RenderViewImpl::PendingFileChooser { @@ -762,6 +755,25 @@ if (switches::IsTouchEditingEnabled()) webview()->settings()->setTouchEditingEnabled(true); +#if defined(OS_ANDROID) + WebSettings::SelectionStrategyType selection_strategy_default = + WebSettings::SelectionStrategyType::Direction; +#else + WebSettings::SelectionStrategyType selection_strategy_default = + WebSettings::SelectionStrategyType::Character; +#endif + + WebSettings::SelectionStrategyType selection_strategy = + selection_strategy_default; + const std::string selection_strategy_str = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kTouchTextSelectionStrategy); + if (selection_strategy_str == "character") + selection_strategy = WebSettings::SelectionStrategyType::Character; + else if (selection_strategy_str == "direction") + selection_strategy = WebSettings::SelectionStrategyType::Direction; + webview()->settings()->setSelectionStrategy(selection_strategy); + if (!params.frame_name.empty()) webview()->mainFrame()->setName(params.frame_name); @@ -784,12 +796,6 @@ new TextInputClientObserver(this); #endif // defined(OS_MACOSX) - // TODO(dgozman): do this not for main frame, but for local frame roots. - if (blink::WebDevToolsAgent* devToolsAgent = GetWebDevToolsAgent(webview())) { - if (RenderWidgetCompositor* rwc = compositor()) - devToolsAgent->setLayerTreeId(rwc->GetLayerTreeId()); - } - // The next group of objects all implement RenderViewObserver, so are deleted // along with the RenderView automatically. mouse_lock_dispatcher_ = new RenderViewMouseLockDispatcher(this); @@ -2029,9 +2035,6 @@ RenderWidgetCompositor* rwc = compositor(); if (!rwc) return; - // TODO(dgozman): do this not for main frame, but for local frame roots. - if (blink::WebDevToolsAgent* devToolsAgent = GetWebDevToolsAgent(webview())) - devToolsAgent->setLayerTreeId(rwc->GetLayerTreeId()); bool use_threaded_event_handling = true; #if defined(OS_MACOSX) && !defined(OS_IOS) @@ -3075,10 +3078,6 @@ FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleMouseEvent(event)); } -void RenderViewImpl::DidHandleTouchEvent(const WebTouchEvent& event) { - FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidHandleTouchEvent(event)); -} - bool RenderViewImpl::HasTouchEventHandlersAt(const gfx::Point& point) const { if (!webview()) return false;
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 97b2606e..da62fb79 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -467,7 +467,6 @@ bool WillHandleMouseEvent(const blink::WebMouseEvent& event) override; bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override; void DidHandleMouseEvent(const blink::WebMouseEvent& event) override; - void DidHandleTouchEvent(const blink::WebTouchEvent& event) override; bool HasTouchEventHandlersAt(const gfx::Point& point) const override; void OnSetFocus(bool enable) override; void OnWasHidden() override;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 1aab8b4..94d484f 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -496,6 +496,7 @@ closing_(false), host_closing_(false), is_swapped_out_(swapped_out), + for_oopif_(false), input_method_is_active_(false), text_input_type_(ui::TEXT_INPUT_TYPE_NONE), text_input_mode_(ui::TEXT_INPUT_MODE_DEFAULT), @@ -560,6 +561,7 @@ widget->routing_id_ = routing_id; widget->surface_id_ = surface_id; widget->compositor_deps_ = compositor_deps; + widget->for_oopif_ = true; // DoInit increments the reference count on |widget|, keeping it alive after // this function returns. if (widget->DoInit(MSG_ROUTING_NONE, compositor_deps, @@ -1011,14 +1013,14 @@ scoped_refptr<ContextProviderCommandBuffer> worker_context_provider; if (!use_software) { context_provider = ContextProviderCommandBuffer::Create( - CreateGraphicsContext3D(), "RenderCompositor"); + CreateGraphicsContext3D(), RENDER_COMPOSITOR_CONTEXT); if (!context_provider.get()) { // Cause the compositor to wait and try again. return scoped_ptr<cc::OutputSurface>(); } worker_context_provider = ContextProviderCommandBuffer::Create( - CreateGraphicsContext3D(), "RenderWorker"); + CreateGraphicsContext3D(), RENDER_WORKER_CONTEXT); if (!worker_context_provider.get()) { // Cause the compositor to wait and try again. return scoped_ptr<cc::OutputSurface>(); @@ -1289,8 +1291,6 @@ DidHandleKeyEvent(); if (WebInputEvent::isMouseEventType(input_event->type)) DidHandleMouseEvent(*(static_cast<const WebMouseEvent*>(input_event))); - if (WebInputEvent::isTouchEventType(input_event->type)) - DidHandleTouchEvent(*(static_cast<const WebTouchEvent*>(input_event))); } // TODO(rouslan): Fix ChromeOS and Windows 8 behavior of autofill popup with
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index ecd41bb..a09da9bd 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -131,6 +131,7 @@ // Temporary for debugging purposes... bool closing() const { return closing_; } bool is_swapped_out() { return is_swapped_out_; } + bool for_oopif() { return for_oopif_; } ui::MenuSourceType context_menu_source_type() { return context_menu_source_type_; } @@ -561,10 +562,6 @@ // just handled. virtual void DidHandleMouseEvent(const blink::WebMouseEvent& event) {} - // Called by OnHandleInputEvent() to notify subclasses that a touch event was - // just handled. - virtual void DidHandleTouchEvent(const blink::WebTouchEvent& event) {} - // Called by OnHandleInputEvent() to forward a mouse wheel event to the // compositor thread, to effect the elastic overscroll effect. void ObserveWheelEventAndResult(const blink::WebMouseWheelEvent& wheel_event, @@ -695,6 +692,11 @@ // swapped out, the process can exit. bool is_swapped_out_; + // TODO(simonhong): Remove this when we enable BeginFrame scheduling for + // OOPIF(crbug.com/471411). + // Whether this RenderWidget is for an out-of-process iframe or not. + bool for_oopif_; + // Indicates if an input method is active in the browser process. bool input_method_is_active_;
diff --git a/content/shell/android/BUILD.gn b/content/shell/android/BUILD.gn index 3ad831e..96a88727 100644 --- a/content/shell/android/BUILD.gn +++ b/content/shell/android/BUILD.gn
@@ -153,9 +153,11 @@ "//content/public/android:content_javatests", "//base:base_javatests", "//net/android:net_javatests", + "//testing/android/broker:broker_java", ] datadeps = [ ":content_shell_apk", + "//testing/android/driver:driver_apk", ] apk_under_test = ":content_shell_apk" apk_name = "ContentShellTest"
diff --git a/content/shell/android/javatests/AndroidManifest.xml b/content/shell/android/javatests/AndroidManifest.xml index 5f50ead..a249ba15 100644 --- a/content/shell/android/javatests/AndroidManifest.xml +++ b/content/shell/android/javatests/AndroidManifest.xml
@@ -11,9 +11,11 @@ needed when building test cases. --> <application> <uses-library android:name="android.test.runner" /> + <activity android:name="org.chromium.test.broker.OnDeviceInstrumentationBroker" + android:exported="true"/> </application> <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" /> - <instrumentation android:name="android.test.InstrumentationTestRunner" + <instrumentation android:name="org.chromium.base.test.BaseInstrumentationTestRunner" android:targetPackage="org.chromium.content_shell_apk" android:label="Tests for org.chromium.content_shell_apk"/> <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" />
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java index a5a94719..bc460bf 100644 --- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
@@ -71,8 +71,7 @@ setContentView(R.layout.content_shell_activity); mShellManager = (ShellManager) findViewById(R.id.shell_container); - final boolean listenToActivityState = true; - mWindowAndroid = new ActivityWindowAndroid(this, listenToActivityState); + mWindowAndroid = new ActivityWindowAndroid(this); mWindowAndroid.restoreInstanceState(savedInstanceState); mShellManager.setWindow(mWindowAndroid); // Set up the animation placeholder to be the SurfaceView. This disables the @@ -184,6 +183,14 @@ } @Override + protected void onStop() { + super.onStop(); + + ContentViewCore contentViewCore = getActiveContentViewCore(); + if (contentViewCore != null) contentViewCore.onHide(); + } + + @Override protected void onStart() { super.onStart();
diff --git a/content/shell/app/shell_crash_reporter_client.h b/content/shell/app/shell_crash_reporter_client.h index 5a211eb9..882ecf0 100644 --- a/content/shell/app/shell_crash_reporter_client.h +++ b/content/shell/app/shell_crash_reporter_client.h
@@ -18,11 +18,11 @@ #if defined(OS_WIN) // Returns a textual description of the product type and version to include // in the crash report. - virtual void GetProductNameAndVersion(const base::FilePath& exe_path, - base::string16* product_name, - base::string16* version, - base::string16* special_build, - base::string16* channel_name) override; + void GetProductNameAndVersion(const base::FilePath& exe_path, + base::string16* product_name, + base::string16* version, + base::string16* special_build, + base::string16* channel_name) override; #endif #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS)
diff --git a/content/shell/browser/layout_test/layout_test_message_filter.cc b/content/shell/browser/layout_test/layout_test_message_filter.cc index 6b9eaf6..dd09baa 100644 --- a/content/shell/browser/layout_test/layout_test_message_filter.cc +++ b/content/shell/browser/layout_test/layout_test_message_filter.cc
@@ -60,10 +60,6 @@ IPC_MESSAGE_HANDLER(LayoutTestHostMsg_ClearAllDatabases, OnClearAllDatabases) IPC_MESSAGE_HANDLER(LayoutTestHostMsg_SetDatabaseQuota, OnSetDatabaseQuota) - IPC_MESSAGE_HANDLER(LayoutTestHostMsg_GrantWebNotificationPermission, - OnGrantWebNotificationPermission) - IPC_MESSAGE_HANDLER(LayoutTestHostMsg_ClearWebNotificationPermissions, - OnClearWebNotificationPermissions) IPC_MESSAGE_HANDLER(LayoutTestHostMsg_SimulateWebNotificationClick, OnSimulateWebNotificationClick) IPC_MESSAGE_HANDLER(LayoutTestHostMsg_AcceptAllCookies, OnAcceptAllCookies) @@ -110,24 +106,6 @@ storage::QuotaCallback()); } -void LayoutTestMessageFilter::OnGrantWebNotificationPermission( - const GURL& origin, bool permission_granted) { - LayoutTestNotificationManager* manager = - LayoutTestContentBrowserClient::Get()->GetLayoutTestNotificationManager(); - if (manager) { - manager->SetPermission(origin, permission_granted ? - blink::WebNotificationPermissionAllowed : - blink::WebNotificationPermissionDenied); - } -} - -void LayoutTestMessageFilter::OnClearWebNotificationPermissions() { - LayoutTestNotificationManager* manager = - LayoutTestContentBrowserClient::Get()->GetLayoutTestNotificationManager(); - if (manager) - manager->ClearPermissions(); -} - void LayoutTestMessageFilter::OnSimulateWebNotificationClick( const std::string& title) { LayoutTestNotificationManager* manager =
diff --git a/content/shell/browser/layout_test/layout_test_notification_manager.cc b/content/shell/browser/layout_test/layout_test_notification_manager.cc index 27b6a446..a30c719 100644 --- a/content/shell/browser/layout_test/layout_test_notification_manager.cc +++ b/content/shell/browser/layout_test/layout_test_notification_manager.cc
@@ -9,8 +9,12 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/desktop_notification_delegate.h" #include "content/public/browser/notification_event_dispatcher.h" +#include "content/public/browser/permission_type.h" #include "content/public/common/persistent_notification_status.h" #include "content/public/common/platform_notification_data.h" +#include "content/shell/browser/layout_test/layout_test_browser_context.h" +#include "content/shell/browser/layout_test/layout_test_content_browser_client.h" +#include "content/shell/browser/layout_test/layout_test_permission_manager.h" namespace content { namespace { @@ -19,6 +23,21 @@ // Service Worker when a notificationclick event has been dispatched. void OnEventDispatchComplete(PersistentNotificationStatus status) {} +blink::WebNotificationPermission ToWebNotificationPermission( + PermissionStatus status) { + switch (status) { + case PERMISSION_STATUS_GRANTED: + return blink::WebNotificationPermissionAllowed; + case PERMISSION_STATUS_DENIED: + return blink::WebNotificationPermissionDenied; + case PERMISSION_STATUS_ASK: + return blink::WebNotificationPermissionDefault; + } + + NOTREACHED(); + return blink::WebNotificationPermissionLast; +} + } // namespace LayoutTestNotificationManager::LayoutTestNotificationManager() @@ -26,37 +45,6 @@ LayoutTestNotificationManager::~LayoutTestNotificationManager() {} -PermissionStatus LayoutTestNotificationManager::RequestPermission( - const GURL& origin) { - return GetPermissionStatus(origin); -} - -blink::WebNotificationPermission -LayoutTestNotificationManager::CheckPermission(const GURL& origin) { - base::AutoLock lock(permission_lock_); - const auto& iter = permission_map_.find(origin); - if (iter != permission_map_.end()) - return iter->second; - - return blink::WebNotificationPermissionDefault; -} - -void LayoutTestNotificationManager::SetPermission( - const GURL& origin, - blink::WebNotificationPermission permission) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - base::AutoLock lock(permission_lock_); - - permission_map_[origin] = permission; -} - -void LayoutTestNotificationManager::ClearPermissions() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - base::AutoLock lock(permission_lock_); - - permission_map_.clear(); -} - void LayoutTestNotificationManager::DisplayNotification( BrowserContext* browser_context, const GURL& origin, @@ -133,21 +121,6 @@ base::Bind(&OnEventDispatchComplete)); } -PermissionStatus LayoutTestNotificationManager::GetPermissionStatus( - const GURL& origin) { - switch (CheckPermission(origin)) { - case blink::WebNotificationPermissionAllowed: - return PERMISSION_STATUS_GRANTED; - case blink::WebNotificationPermissionDenied: - return PERMISSION_STATUS_DENIED; - case blink::WebNotificationPermissionDefault: - return PERMISSION_STATUS_ASK; - } - - NOTREACHED(); - return PERMISSION_STATUS_DENIED; -} - blink::WebNotificationPermission LayoutTestNotificationManager::CheckPermissionOnUIThread( BrowserContext* browser_context, @@ -206,4 +179,14 @@ replacements_[tag] = base::UTF16ToUTF8(notification_data.title); } +blink::WebNotificationPermission +LayoutTestNotificationManager::CheckPermission(const GURL& origin) { + return ToWebNotificationPermission(LayoutTestContentBrowserClient::Get() + ->GetLayoutTestBrowserContext() + ->GetLayoutTestPermissionManager() + ->GetPermissionStatus(PermissionType::NOTIFICATIONS, + origin, + origin)); +} + } // namespace content
diff --git a/content/shell/browser/layout_test/layout_test_notification_manager.h b/content/shell/browser/layout_test/layout_test_notification_manager.h index d2cd2f5a..ac51c5c 100644 --- a/content/shell/browser/layout_test/layout_test_notification_manager.h +++ b/content/shell/browser/layout_test/layout_test_notification_manager.h
@@ -11,9 +11,7 @@ #include "base/callback.h" #include "base/memory/weak_ptr.h" -#include "base/synchronization/lock.h" #include "content/public/browser/platform_notification_service.h" -#include "content/public/common/permission_status.mojom.h" #include "third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h" #include "url/gurl.h" @@ -29,26 +27,6 @@ LayoutTestNotificationManager(); ~LayoutTestNotificationManager() override; - // Requests permission for |origin| to display notifications in layout tests. - // Must be called on the IO thread. - // Returns whether the permission is granted. - PermissionStatus RequestPermission(const GURL& origin); - - // Checks if |origin| has permission to display notifications. May be called - // on both the IO and the UI threads. - blink::WebNotificationPermission CheckPermission(const GURL& origin); - - // Similar to CheckPermission() above but returns a PermissionStatus object. - PermissionStatus GetPermissionStatus(const GURL& origin); - - // Sets the permission to display notifications for |origin| to |permission|. - // Must be called on the IO thread. - void SetPermission(const GURL& origin, - blink::WebNotificationPermission permission); - - // Clears the currently granted permissions. Must be called on the IO thread. - void ClearPermissions(); - // Simulates a click on the notification titled |title|. Must be called on the // UI thread. void SimulateClick(const std::string& title); @@ -79,6 +57,13 @@ int64_t persistent_notification_id) override; private: + // Structure to represent the information of a persistent notification. + struct PersistentNotification { + BrowserContext* browser_context = nullptr; + GURL origin; + int64_t persistent_id = 0; + }; + // Closes the notification titled |title|. Must be called on the UI thread. void Close(const std::string& title); @@ -88,15 +73,9 @@ void ReplaceNotificationIfNeeded( const PlatformNotificationData& notification_data); - // Structure to represent the information of a persistent notification. - struct PersistentNotification { - BrowserContext* browser_context = nullptr; - GURL origin; - int64_t persistent_id = 0; - }; - - std::map<GURL, blink::WebNotificationPermission> permission_map_; - base::Lock permission_lock_; + // Checks if |origin| has permission to display notifications. May be called + // on both the IO and the UI threads. + blink::WebNotificationPermission CheckPermission(const GURL& origin); std::map<std::string, DesktopNotificationDelegate*> page_notifications_; std::map<std::string, PersistentNotification> persistent_notifications_;
diff --git a/content/shell/browser/layout_test/layout_test_permission_manager.cc b/content/shell/browser/layout_test/layout_test_permission_manager.cc index 36c96c8..8445e68b 100644 --- a/content/shell/browser/layout_test/layout_test_permission_manager.cc +++ b/content/shell/browser/layout_test/layout_test_permission_manager.cc
@@ -4,6 +4,8 @@ #include "content/shell/browser/layout_test/layout_test_permission_manager.h" +#include <list> + #include "base/bind.h" #include "base/callback.h" #include "content/public/browser/browser_thread.h" @@ -14,26 +16,11 @@ namespace content { -namespace { - -void RequestDesktopNotificationPermissionOnIO( - const GURL& origin, - const base::Callback<void(PermissionStatus)>& callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - LayoutTestNotificationManager* manager = - LayoutTestContentBrowserClient::Get()->GetLayoutTestNotificationManager(); - PermissionStatus result = manager ? manager->RequestPermission(origin) - : PERMISSION_STATUS_GRANTED; - - // The callback came from the UI thread, we need to run it from there again. - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(callback, result)); -} - -} // anonymous namespace +struct LayoutTestPermissionManager::Subscription { + PermissionDescription permission; + base::Callback<void(content::PermissionStatus)> callback; + PermissionStatus current_value; +}; LayoutTestPermissionManager::PermissionDescription::PermissionDescription( PermissionType type, @@ -51,6 +38,11 @@ embedding_origin == other.embedding_origin; } +bool LayoutTestPermissionManager::PermissionDescription::operator!=( + const PermissionDescription& other) const { + return !this->operator==(other); +} + size_t LayoutTestPermissionManager::PermissionDescription::Hash::operator()( const PermissionDescription& description) const { size_t hash = BASE_HASH_NAMESPACE::hash<int>()(static_cast<int>( @@ -78,16 +70,6 @@ const base::Callback<void(PermissionStatus)>& callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (permission == PermissionType::NOTIFICATIONS) { - BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&RequestDesktopNotificationPermissionOnIO, - requesting_origin, - callback)); - return; - } - callback.Run(GetPermissionStatus( permission, requesting_origin, web_contents->GetLastCommittedURL().GetOrigin())); @@ -98,12 +80,17 @@ WebContents* web_contents, int request_id, const GURL& requesting_origin) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); } void LayoutTestPermissionManager::ResetPermission( PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + base::AutoLock lock(permissions_lock_); + auto it = permissions_.find( PermissionDescription(permission, requesting_origin, embedding_origin)); if (it == permissions_.end()) @@ -115,6 +102,10 @@ PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || + BrowserThread::CurrentlyOn(BrowserThread::IO)); + + base::AutoLock lock(permissions_lock_); auto it = permissions_.find( PermissionDescription(permission, requesting_origin, embedding_origin)); @@ -127,6 +118,7 @@ PermissionType permission, const GURL& requesting_origin, const GURL& embedding_origin) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); } int LayoutTestPermissionManager::SubscribePermissionStatusChange( @@ -134,21 +126,38 @@ const GURL& requesting_origin, const GURL& embedding_origin, const base::Callback<void(PermissionStatus)>& callback) { - // TODO(mlamouri): to be implemented, see https://crbug.com/475141 - return -1; + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + Subscription* subscription = new Subscription(); + subscription->permission = + PermissionDescription(permission, requesting_origin, embedding_origin); + subscription->callback = callback; + subscription->current_value = + GetPermissionStatus(permission, + subscription->permission.origin, + subscription->permission.embedding_origin); + + return subscriptions_.Add(subscription); } void LayoutTestPermissionManager::UnsubscribePermissionStatusChange( int subscription_id) { - // TODO(mlamouri): to be implemented, see https://crbug.com/475141 + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // Whether |subscription_id| is known will be checked by the Remove() call. + subscriptions_.Remove(subscription_id); } void LayoutTestPermissionManager::SetPermission(PermissionType permission, PermissionStatus status, const GURL& origin, const GURL& embedding_origin) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + PermissionDescription description(permission, origin, embedding_origin); + base::AutoLock lock(permissions_lock_); + auto it = permissions_.find(description); if (it == permissions_.end()) { permissions_.insert(std::pair<PermissionDescription, PermissionStatus>( @@ -156,10 +165,40 @@ } else { it->second = status; } + + OnPermissionChanged(description, status); } void LayoutTestPermissionManager::ResetPermissions() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + base::AutoLock lock(permissions_lock_); permissions_.clear(); } +void LayoutTestPermissionManager::OnPermissionChanged( + const PermissionDescription& permission, + PermissionStatus status) { + std::list<base::Closure> callbacks; + + for (SubscriptionsMap::iterator iter(&subscriptions_); + !iter.IsAtEnd(); iter.Advance()) { + Subscription* subscription = iter.GetCurrentValue(); + if (subscription->permission != permission) + continue; + + if (subscription->current_value == status) + continue; + + subscription->current_value = status; + + // Add the callback to |callbacks| which will be run after the loop to + // prevent re-entrance issues. + callbacks.push_back(base::Bind(subscription->callback, status)); + } + + for (const auto& callback : callbacks) + callback.Run(); +} + } // namespace content
diff --git a/content/shell/browser/layout_test/layout_test_permission_manager.h b/content/shell/browser/layout_test/layout_test_permission_manager.h index e1cf5c1..8aa905e 100644 --- a/content/shell/browser/layout_test/layout_test_permission_manager.h +++ b/content/shell/browser/layout_test/layout_test_permission_manager.h
@@ -7,7 +7,9 @@ #include "base/callback_forward.h" #include "base/containers/hash_tables.h" +#include "base/id_map.h" #include "base/macros.h" +#include "base/synchronization/lock.h" #include "content/public/browser/permission_manager.h" #include "url/gurl.h" @@ -55,10 +57,12 @@ private: // Representation of a permission for the LayoutTestPermissionManager. struct PermissionDescription { + PermissionDescription() = default; PermissionDescription(PermissionType type, const GURL& origin, const GURL& embedding_origin); bool operator==(const PermissionDescription& other) const; + bool operator!=(const PermissionDescription& other) const; // Hash operator for hash maps. struct Hash { @@ -70,14 +74,26 @@ GURL embedding_origin; }; + struct Subscription; + using SubscriptionsMap = IDMap<Subscription, IDMapOwnPointer>; using PermissionsMap = base::hash_map<PermissionDescription, PermissionStatus, PermissionDescription::Hash>; + void OnPermissionChanged(const PermissionDescription& permission, + PermissionStatus status); + + // Mutex for permissions access. Unfortunately, the permissions can be + // accessed from the IO thread because of Notifications' synchronous IPC. + base::Lock permissions_lock_; + // List of permissions currently known by the LayoutTestPermissionManager and // their associated |PermissionStatus|. PermissionsMap permissions_; + // List of subscribers currently listening to permission changes. + SubscriptionsMap subscriptions_; + DISALLOW_COPY_AND_ASSIGN(LayoutTestPermissionManager); };
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h index dd25767..0dc59b2 100644 --- a/content/shell/browser/shell_content_browser_client.h +++ b/content/shell/browser/shell_content_browser_client.h
@@ -78,8 +78,7 @@ FileDescriptorInfo* mappings) override; #endif #if defined(OS_WIN) - virtual void PreSpawnRenderer(sandbox::TargetPolicy* policy, - bool* success) override; + void PreSpawnRenderer(sandbox::TargetPolicy* policy, bool* success) override; #endif ShellBrowserContext* browser_context();
diff --git a/content/shell/browser/shell_net_log.cc b/content/shell/browser/shell_net_log.cc index eb5b0cb..2a21b8e 100644 --- a/content/shell/browser/shell_net_log.cc +++ b/content/shell/browser/shell_net_log.cc
@@ -63,17 +63,17 @@ << " for net logging"; } else { scoped_ptr<base::Value> constants(GetShellConstants(app_name)); - net_log_logger_.reset(new net::WriteToFileNetLogObserver()); - net_log_logger_->StartObserving(this, file.Pass(), constants.get(), - nullptr); + write_to_file_observer_.reset(new net::WriteToFileNetLogObserver()); + write_to_file_observer_->StartObserving(this, file.Pass(), + constants.get(), nullptr); } } } ShellNetLog::~ShellNetLog() { // Remove the observer we own before we're destroyed. - if (net_log_logger_) - net_log_logger_->StopObserving(nullptr); + if (write_to_file_observer_) + write_to_file_observer_->StopObserving(nullptr); } } // namespace content
diff --git a/content/shell/browser/shell_net_log.h b/content/shell/browser/shell_net_log.h index 8a74e3d..58edf1f 100644 --- a/content/shell/browser/shell_net_log.h +++ b/content/shell/browser/shell_net_log.h
@@ -18,7 +18,7 @@ ~ShellNetLog() override; private: - scoped_ptr<net::WriteToFileNetLogObserver> net_log_logger_; + scoped_ptr<net::WriteToFileNetLogObserver> write_to_file_observer_; DISALLOW_COPY_AND_ASSIGN(ShellNetLog); };
diff --git a/content/shell/common/layout_test/layout_test_messages.h b/content/shell/common/layout_test/layout_test_messages.h index 15160744..7ab85bf1 100644 --- a/content/shell/common/layout_test/layout_test_messages.h +++ b/content/shell/common/layout_test/layout_test_messages.h
@@ -27,10 +27,6 @@ IPC_MESSAGE_ROUTED0(LayoutTestHostMsg_ClearAllDatabases) IPC_MESSAGE_ROUTED1(LayoutTestHostMsg_SetDatabaseQuota, int /* quota */) -IPC_MESSAGE_ROUTED2(LayoutTestHostMsg_GrantWebNotificationPermission, - GURL /* origin */, - bool /* permission_granted */) -IPC_MESSAGE_ROUTED0(LayoutTestHostMsg_ClearWebNotificationPermissions) IPC_MESSAGE_ROUTED1(LayoutTestHostMsg_SimulateWebNotificationClick, std::string /* title */) IPC_MESSAGE_ROUTED1(LayoutTestHostMsg_AcceptAllCookies,
diff --git a/content/shell/renderer/layout_test/webkit_test_runner.cc b/content/shell/renderer/layout_test/webkit_test_runner.cc index 97222a9..99e15e2 100644 --- a/content/shell/renderer/layout_test/webkit_test_runner.cc +++ b/content/shell/renderer/layout_test/webkit_test_runner.cc
@@ -425,16 +425,6 @@ Send(new LayoutTestHostMsg_SetDatabaseQuota(routing_id(), quota)); } -void WebKitTestRunner::GrantWebNotificationPermission(const GURL& origin, - bool permission_granted) { - Send(new LayoutTestHostMsg_GrantWebNotificationPermission( - routing_id(), origin, permission_granted)); -} - -void WebKitTestRunner::ClearWebNotificationPermissions() { - Send(new LayoutTestHostMsg_ClearWebNotificationPermissions(routing_id())); -} - void WebKitTestRunner::SimulateWebNotificationClick(const std::string& title) { Send(new LayoutTestHostMsg_SimulateWebNotificationClick(routing_id(), title)); }
diff --git a/content/shell/renderer/layout_test/webkit_test_runner.h b/content/shell/renderer/layout_test/webkit_test_runner.h index a8271459..396b2ce 100644 --- a/content/shell/renderer/layout_test/webkit_test_runner.h +++ b/content/shell/renderer/layout_test/webkit_test_runner.h
@@ -88,9 +88,6 @@ void EvaluateInWebInspector(long call_id, const std::string& script) override; void ClearAllDatabases() override; void SetDatabaseQuota(int quota) override; - void GrantWebNotificationPermission(const GURL& origin, - bool permission_granted) override; - void ClearWebNotificationPermissions() override; void SimulateWebNotificationClick(const std::string& title) override; void SetDeviceScaleFactor(float factor) override; void SetDeviceColorProfile(const std::string& name) override;
diff --git a/content/shell/renderer/test_runner/test_plugin.cc b/content/shell/renderer/test_runner/test_plugin.cc index e5e0e8e..e47d7142 100644 --- a/content/shell/renderer/test_runner/test_plugin.cc +++ b/content/shell/renderer/test_runner/test_plugin.cc
@@ -152,6 +152,7 @@ print_event_details_(false), print_user_gesture_status_(false), can_process_drag_(false), + supports_keyboard_focus_(false), is_persistent_(params.mimeType == PluginPersistsMimeType()), can_create_without_renderer_(params.mimeType == CanCreateWithoutRendererMimeType()) { @@ -172,6 +173,9 @@ const CR_DEFINE_STATIC_LOCAL( blink::WebString, kAttributeCanProcessDrag, ("can-process-drag")); const CR_DEFINE_STATIC_LOCAL(blink::WebString, + kAttributeSupportsKeyboardFocus, + ("supports-keyboard-focus")); + const CR_DEFINE_STATIC_LOCAL(blink::WebString, kAttributePrintUserGestureStatus, ("print-user-gesture-status")); @@ -197,6 +201,8 @@ print_event_details_ = ParseBoolean(attribute_value); else if (attribute_name == kAttributeCanProcessDrag) can_process_drag_ = ParseBoolean(attribute_value); + else if (attribute_name == kAttributeSupportsKeyboardFocus) + supports_keyboard_focus_ = ParseBoolean(attribute_value); else if (attribute_name == kAttributePrintUserGestureStatus) print_user_gesture_status_ = ParseBoolean(attribute_value); } @@ -259,6 +265,10 @@ return can_process_drag_; } +bool TestPlugin::supportsKeyboardFocus() const { + return supports_keyboard_focus_; +} + void TestPlugin::updateGeometry( const blink::WebRect& window_rect, const blink::WebRect& clip_rect,
diff --git a/content/shell/renderer/test_runner/test_plugin.h b/content/shell/renderer/test_runner/test_plugin.h index 446739e..d636c1b 100644 --- a/content/shell/renderer/test_runner/test_plugin.h +++ b/content/shell/renderer/test_runner/test_plugin.h
@@ -63,6 +63,7 @@ virtual void destroy(); virtual NPObject* scriptableObject(); virtual bool canProcessDrag() const; + virtual bool supportsKeyboardFocus() const; virtual void paint(blink::WebCanvas* canvas, const blink::WebRect& rect) {} virtual void updateGeometry( const blink::WebRect& window_rect, @@ -170,6 +171,7 @@ bool print_event_details_; bool print_user_gesture_status_; bool can_process_drag_; + bool supports_keyboard_focus_; bool is_persistent_; bool can_create_without_renderer_;
diff --git a/content/shell/renderer/test_runner/test_runner.cc b/content/shell/renderer/test_runner/test_runner.cc index 3b017d9..4fd27cf 100644 --- a/content/shell/renderer/test_runner/test_runner.cc +++ b/content/shell/renderer/test_runner/test_runner.cc
@@ -276,9 +276,6 @@ v8::Handle<v8::Function> callback); void SetPOSIXLocale(const std::string& locale); void SetMIDIAccessorResult(bool result); - void SetMIDISysexPermission(bool value); - void GrantWebNotificationPermission(gin::Arguments* args); - void ClearWebNotificationPermissions(); void SimulateWebNotificationClick(const std::string& title); void AddMockSpeechRecognitionResult(const std::string& transcript, double confidence); @@ -523,12 +520,6 @@ .SetMethod("setPOSIXLocale", &TestRunnerBindings::SetPOSIXLocale) .SetMethod("setMIDIAccessorResult", &TestRunnerBindings::SetMIDIAccessorResult) - .SetMethod("setMIDISysexPermission", - &TestRunnerBindings::SetMIDISysexPermission) - .SetMethod("grantWebNotificationPermission", - &TestRunnerBindings::GrantWebNotificationPermission) - .SetMethod("clearWebNotificationPermissions", - &TestRunnerBindings::ClearWebNotificationPermissions) .SetMethod("simulateWebNotificationClick", &TestRunnerBindings::SimulateWebNotificationClick) .SetMethod("addMockSpeechRecognitionResult", @@ -1323,25 +1314,6 @@ runner_->SetMIDIAccessorResult(result); } -void TestRunnerBindings::SetMIDISysexPermission(bool value) { -} - -void TestRunnerBindings::GrantWebNotificationPermission(gin::Arguments* args) { - if (runner_) { - std::string origin; - bool permission_granted = true; - args->GetNext(&origin); - args->GetNext(&permission_granted); - return runner_->GrantWebNotificationPermission(GURL(origin), - permission_granted); - } -} - -void TestRunnerBindings::ClearWebNotificationPermissions() { - if (runner_) - runner_->ClearWebNotificationPermissions(); -} - void TestRunnerBindings::SimulateWebNotificationClick( const std::string& title) { if (runner_) @@ -2829,15 +2801,6 @@ midi_accessor_result_ = result; } -void TestRunner::GrantWebNotificationPermission(const GURL& origin, - bool permission_granted) { - delegate_->GrantWebNotificationPermission(origin, permission_granted); -} - -void TestRunner::ClearWebNotificationPermissions() { - delegate_->ClearWebNotificationPermissions(); -} - void TestRunner::SimulateWebNotificationClick(const std::string& title) { delegate_->SimulateWebNotificationClick(title); }
diff --git a/content/shell/renderer/test_runner/test_runner.h b/content/shell/renderer/test_runner/test_runner.h index c55ab4b..493471f 100644 --- a/content/shell/renderer/test_runner/test_runner.h +++ b/content/shell/renderer/test_runner/test_runner.h
@@ -548,13 +548,6 @@ // MIDI function to control permission handling. void SetMIDIAccessorResult(bool result); - // Grants permission for desktop notifications to an origin - void GrantWebNotificationPermission(const GURL& origin, - bool permission_granted); - - // Clears all previously granted Web Notification permissions. - void ClearWebNotificationPermissions(); - // Simulates a click on a Web Notification. void SimulateWebNotificationClick(const std::string& title);
diff --git a/content/shell/renderer/test_runner/web_frame_test_proxy.h b/content/shell/renderer/test_runner/web_frame_test_proxy.h index 8d860ff..a2c71d0 100644 --- a/content/shell/renderer/test_runner/web_frame_test_proxy.h +++ b/content/shell/renderer/test_runner/web_frame_test_proxy.h
@@ -285,8 +285,7 @@ private: #if defined(ENABLE_WEBRTC) - virtual scoped_ptr<MediaStreamRendererFactory> CreateRendererFactory() - override { + scoped_ptr<MediaStreamRendererFactory> CreateRendererFactory() override { return scoped_ptr<MediaStreamRendererFactory>( new TestMediaStreamRendererFactory()); }
diff --git a/content/shell/renderer/test_runner/web_test_delegate.h b/content/shell/renderer/test_runner/web_test_delegate.h index ee03798..e847d44 100644 --- a/content/shell/renderer/test_runner/web_test_delegate.h +++ b/content/shell/renderer/test_runner/web_test_delegate.h
@@ -135,9 +135,6 @@ virtual void SetDatabaseQuota(int quota) = 0; // Controls Web Notifications. - virtual void GrantWebNotificationPermission(const GURL& origin, - bool permission_granted) = 0; - virtual void ClearWebNotificationPermissions() = 0; virtual void SimulateWebNotificationClick(const std::string& title) = 0; // Controls the device scale factor of the main WebView for hidpi tests.
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 81823f0..3064d04 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -25,8 +25,8 @@ deps = [ "//cc/blink", "//content/public/app:both", - "//content/public/browser:browser_sources", - "//content/public/common:common_sources", + "//content/public/browser", + "//content/public/common", "//net:test_support", "//skia", "//storage/common", @@ -56,11 +56,11 @@ deps += [ "//components/scheduler:scheduler", "//content/browser/speech/proto", - "//content/public/child:child_sources", + "//content/public/child", "//content/gpu", - "//content/public/plugin:plugin_sources", - "//content/public/renderer:renderer_sources", - "//content/public/utility:utility_sources", + "//content/public/plugin", + "//content/public/renderer", + "//content/public/utility", "//content/shell:pak", "//cc", "//cc:test_support", @@ -75,7 +75,6 @@ "//storage/common", "//ui/surface", "//v8", - "//webkit/common/gpu", ] if (enable_plugins) { @@ -453,6 +452,7 @@ "//content/browser/notifications:notification_proto", "//content/browser/service_worker:service_worker_proto", "//content/browser/speech/proto", + "//content/common:mojo_bindings", "//content/public/browser", "//content/public/common", "//content/public/common:mojo_bindings",
diff --git a/content/test/content_test_suite.cc b/content/test/content_test_suite.cc index 18a116f..42cb92b 100644 --- a/content/test/content_test_suite.cc +++ b/content/test/content_test_suite.cc
@@ -52,12 +52,12 @@ TestInitializationListener() : test_content_client_initializer_(NULL) { } - virtual void OnTestStart(const testing::TestInfo& test_info) override { + void OnTestStart(const testing::TestInfo& test_info) override { test_content_client_initializer_ = new content::TestContentClientInitializer(); } - virtual void OnTestEnd(const testing::TestInfo& test_info) override { + void OnTestEnd(const testing::TestInfo& test_info) override { delete test_content_client_initializer_; }
diff --git a/content/test/data/accessibility/event/listbox-focus-expected-mac.txt b/content/test/data/accessibility/event/listbox-focus-expected-mac.txt new file mode 100644 index 0000000..7843b85 --- /dev/null +++ b/content/test/data/accessibility/event/listbox-focus-expected-mac.txt
@@ -0,0 +1 @@ +AXFocusedUIElementChanged on AXList
diff --git a/content/test/data/accessibility/event/listbox-focus-expected-win.txt b/content/test/data/accessibility/event/listbox-focus-expected-win.txt new file mode 100644 index 0000000..ac94789 --- /dev/null +++ b/content/test/data/accessibility/event/listbox-focus-expected-win.txt
@@ -0,0 +1 @@ +EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Apple" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE
diff --git a/content/test/data/accessibility/event/listbox-focus.html b/content/test/data/accessibility/event/listbox-focus.html new file mode 100644 index 0000000..8ed51e5 --- /dev/null +++ b/content/test/data/accessibility/event/listbox-focus.html
@@ -0,0 +1,18 @@ +<!-- +@MAC-DENY:AXLayoutComplete* +--> +<!DOCTYPE html> +<html> +<body> +<select size=3> + <option selected>Apple</option> + <option>Orange</option> + <option>Banana</option> +</select> +<script> + function go() { + document.querySelector('select').focus(); + } +</script> +</body> +</html>
diff --git a/content/test/data/accessibility/event/listbox-next-expected-mac.txt b/content/test/data/accessibility/event/listbox-next-expected-mac.txt new file mode 100644 index 0000000..b194e92 --- /dev/null +++ b/content/test/data/accessibility/event/listbox-next-expected-mac.txt
@@ -0,0 +1,2 @@ +AXSelectedChildrenChanged on AXList +AXFocusedUIElementChanged on AXList
diff --git a/content/test/data/accessibility/event/listbox-next-expected-win.txt b/content/test/data/accessibility/event/listbox-next-expected-win.txt new file mode 100644 index 0000000..5321639 --- /dev/null +++ b/content/test/data/accessibility/event/listbox-next-expected-win.txt
@@ -0,0 +1,6 @@ +EVENT_OBJECT_STATECHANGE on role=ROLE_SYSTEM_LISTITEM name="Orange" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE +EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Orange" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE +EVENT_OBJECT_SELECTION on role=ROLE_SYSTEM_LISTITEM name="Orange" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE +EVENT_OBJECT_STATECHANGE on role=ROLE_SYSTEM_LISTITEM name="Apple" FOCUSABLE,SELECTABLE +EVENT_OBJECT_SELECTIONWITHIN on role=ROLE_SYSTEM_LIST FOCUSED,FOCUSABLE IA2_STATE_VERTICAL +EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Orange" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE
diff --git a/content/test/data/accessibility/event/listbox-next.html b/content/test/data/accessibility/event/listbox-next.html new file mode 100644 index 0000000..ab447af --- /dev/null +++ b/content/test/data/accessibility/event/listbox-next.html
@@ -0,0 +1,19 @@ +<!-- +@MAC-DENY:AXLayoutComplete* +--> +<!DOCTYPE html> +<html> +<body> +<select size=3> + <option selected>Apple</option> + <option>Orange</option> + <option>Banana</option> +</select> +<script> + document.querySelector('select').focus(); + function go() { + document.querySelector('select').selectedIndex = 1; + } +</script> +</body> +</html>
diff --git a/content/test/data/accessibility/event/menulist-focus-expected-mac.txt b/content/test/data/accessibility/event/menulist-focus-expected-mac.txt new file mode 100644 index 0000000..b1cdd1c --- /dev/null +++ b/content/test/data/accessibility/event/menulist-focus-expected-mac.txt
@@ -0,0 +1 @@ +AXFocusedUIElementChanged on AXPopUpButton AXValue="Apple"
diff --git a/content/test/data/accessibility/event/menulist-focus-expected-win.txt b/content/test/data/accessibility/event/menulist-focus-expected-win.txt new file mode 100644 index 0000000..0c551a5 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-focus-expected-win.txt
@@ -0,0 +1 @@ +EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_COMBOBOX value="Apple" FOCUSED,COLLAPSED,FOCUSABLE,HASPOPUP
diff --git a/content/test/data/accessibility/event/menulist-focus.html b/content/test/data/accessibility/event/menulist-focus.html new file mode 100644 index 0000000..09b7eabc --- /dev/null +++ b/content/test/data/accessibility/event/menulist-focus.html
@@ -0,0 +1,18 @@ +<!-- +@MAC-DENY:AXLayoutComplete* +--> +<!DOCTYPE html> +<html> +<body> +<select> + <option selected>Apple</option> + <option>Orange</option> + <option>Banana</option> +</select> +<script> + function go() { + document.querySelector('select').focus(); + } +</script> +</body> +</html>
diff --git a/content/test/data/accessibility/event/menulist-next-expected-mac.txt b/content/test/data/accessibility/event/menulist-next-expected-mac.txt new file mode 100644 index 0000000..5cb11e09 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-next-expected-mac.txt
@@ -0,0 +1 @@ +AXFocusedUIElementChanged on AXMenuItem AXValue="Orange"
diff --git a/content/test/data/accessibility/event/menulist-next-expected-win.txt b/content/test/data/accessibility/event/menulist-next-expected-win.txt new file mode 100644 index 0000000..8e6d5392 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-next-expected-win.txt
@@ -0,0 +1,5 @@ +EVENT_OBJECT_VALUECHANGE on role=ROLE_SYSTEM_COMBOBOX value="Orange" FOCUSED,COLLAPSED,FOCUSABLE,HASPOPUP +EVENT_OBJECT_STATECHANGE on role=ROLE_SYSTEM_LISTITEM name="Apple" INVISIBLE,FOCUSABLE,SELECTABLE +EVENT_OBJECT_STATECHANGE on role=ROLE_SYSTEM_LISTITEM name="Orange" SELECTED,FOCUSABLE,SELECTABLE +EVENT_OBJECT_SELECTION on role=ROLE_SYSTEM_LISTITEM name="Orange" SELECTED,FOCUSABLE,SELECTABLE +EVENT_OBJECT_FOCUS on role=ROLE_SYSTEM_LISTITEM name="Orange" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE
diff --git a/content/test/data/accessibility/event/menulist-next.html b/content/test/data/accessibility/event/menulist-next.html new file mode 100644 index 0000000..98d7f33 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-next.html
@@ -0,0 +1,19 @@ +<!-- +@MAC-DENY:AXLayoutComplete* +--> +<!DOCTYPE html> +<html> +<body> +<select> + <option selected>Apple</option> + <option>Orange</option> + <option>Banana</option> +</select> +<script> + document.querySelector('select').focus(); + function go() { + document.querySelector('select').selectedIndex = 1; + } +</script> +</body> +</html>
diff --git a/content/test/data/accessibility/html/input-date-expected-android.txt b/content/test/data/accessibility/html/input-date-expected-android.txt index 30dea11..cea0932 100644 --- a/content/test/data/accessibility/html/input-date-expected-android.txt +++ b/content/test/data/accessibility/html/input-date-expected-android.txt
@@ -1,3 +1,3 @@ android.webkit.WebView focusable focused scrollable ++android.view.View -++++android.widget.Spinner clickable focusable name='2008-09-01' input_type=20 +++++android.widget.Spinner clickable focusable name='@NO_CHILDREN_DUMP' input_type=20
diff --git a/content/test/data/accessibility/html/input-date-expected-win.txt b/content/test/data/accessibility/html/input-date-expected-win.txt index 79f3ccf..f8879c9 100644 --- a/content/test/data/accessibility/html/input-date-expected-win.txt +++ b/content/test/data/accessibility/html/input-date-expected-win.txt
@@ -1,14 +1,3 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ++IA2_ROLE_SECTION -++++IA2_ROLE_DATE_EDITOR FOCUSABLE -++++++IA2_ROLE_SECTION -++++++++IA2_ROLE_SECTION -++++++++++ROLE_SYSTEM_SPINBUTTON name='Month' FOCUSABLE -++++++++++ROLE_SYSTEM_STATICTEXT name='/' -++++++++++ROLE_SYSTEM_SPINBUTTON name='Day' FOCUSABLE -++++++++++ROLE_SYSTEM_STATICTEXT name='/' -++++++++++ROLE_SYSTEM_SPINBUTTON name='Year' FOCUSABLE -++++++ROLE_SYSTEM_BUTTONMENU FOCUSABLE -++++++ROLE_SYSTEM_SPINBUTTON -++++++++ROLE_SYSTEM_PUSHBUTTON -++++++++ROLE_SYSTEM_PUSHBUTTON +++++IA2_ROLE_DATE_EDITOR name='@NO_CHILDREN_DUMP' FOCUSABLE
diff --git a/content/test/data/accessibility/html/input-date.html b/content/test/data/accessibility/html/input-date.html index 3546b0a..ca24acb 100644 --- a/content/test/data/accessibility/html/input-date.html +++ b/content/test/data/accessibility/html/input-date.html
@@ -5,7 +5,7 @@ <html> <body> - <input type="date" value="2008-09-01"> + <input aria-label="@NO_CHILDREN_DUMP" type="date" value="2008-09-01"> </body> </html>
diff --git a/content/test/data/accessibility/html/input-password-expected-android.txt b/content/test/data/accessibility/html/input-password-expected-android.txt index d985dde0..8e2fdd19 100644 --- a/content/test/data/accessibility/html/input-password-expected-android.txt +++ b/content/test/data/accessibility/html/input-password-expected-android.txt
@@ -1,3 +1,3 @@ -android.webkit.WebView focusable focused scrollable +android.webkit.WebView focusable scrollable ++android.view.View -++++android.widget.EditText clickable editable_text focusable password input_type=225 +++++android.widget.EditText clickable editable_text focusable focused password name='secret' input_type=225
diff --git a/content/test/data/accessibility/html/input-password-expected-mac.txt b/content/test/data/accessibility/html/input-password-expected-mac.txt index a063f77f..85742c1 100644 --- a/content/test/data/accessibility/html/input-password-expected-mac.txt +++ b/content/test/data/accessibility/html/input-password-expected-mac.txt
@@ -1,3 +1,3 @@ AXWebArea AXRoleDescription='HTML content' ++AXGroup AXRoleDescription='group' -++++AXTextField AXSubrole=AXSecureTextField AXRoleDescription='text field' +++++AXTextField AXSubrole=AXSecureTextField AXRoleDescription='text field' AXValue='••••••'
diff --git a/content/test/data/accessibility/html/input-password-expected-win.txt b/content/test/data/accessibility/html/input-password-expected-win.txt index b37f3b330..5da92cb 100644 --- a/content/test/data/accessibility/html/input-password-expected-win.txt +++ b/content/test/data/accessibility/html/input-password-expected-win.txt
@@ -1,3 +1,3 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ++IA2_ROLE_SECTION -++++ROLE_SYSTEM_TEXT FOCUSABLE PROTECTED IA2_STATE_EDITABLE IA2_STATE_SELECTABLE_TEXT IA2_STATE_SINGLE_LINE text-input-type:password +++++ROLE_SYSTEM_TEXT value='••••••' FOCUSABLE PROTECTED IA2_STATE_EDITABLE IA2_STATE_SELECTABLE_TEXT IA2_STATE_SINGLE_LINE text-input-type:password caret_offset=6
diff --git a/content/test/data/accessibility/html/input-password.html b/content/test/data/accessibility/html/input-password.html index e6d23eb..31666fd4 100644 --- a/content/test/data/accessibility/html/input-password.html +++ b/content/test/data/accessibility/html/input-password.html
@@ -4,10 +4,17 @@ @WIN-ALLOW:PROTECTED @WIN-ALLOW:IA2_STATE* @WIN-ALLOW:text-input-type* +@WIN-ALLOW:value='•* +@WIN-ALLOW:caret_offset* --> <!DOCTYPE html> <html> <body> - <input type="password"> + <input type="password" value="secret"> + <script> + var input = document.querySelector("input"); + input.focus(); + input.setSelectionRange(6, 6); + </script> </body> </html>
diff --git a/content/test/data/accessibility/html/keygen-expected-win.txt b/content/test/data/accessibility/html/keygen-expected-win.txt index 225d505..5f5869c 100644 --- a/content/test/data/accessibility/html/keygen-expected-win.txt +++ b/content/test/data/accessibility/html/keygen-expected-win.txt
@@ -2,6 +2,6 @@ ++IA2_ROLE_SECTION role_name='body' ++++IA2_ROLE_SECTION FOCUSABLE invalid:false role_name='keygen' ++++++ROLE_SYSTEM_COMBOBOX COLLAPSED FOCUSABLE HASPOPUP invalid:false -++++++++ROLE_SYSTEM_CLIENT INVISIBLE +++++++++ROLE_SYSTEM_LIST INVISIBLE ++++++++++ROLE_SYSTEM_LISTITEM SELECTED FOCUSABLE SELECTABLE ++++++++++ROLE_SYSTEM_LISTITEM INVISIBLE FOCUSABLE SELECTABLE
diff --git a/content/test/data/accessibility/html/keygen.html b/content/test/data/accessibility/html/keygen.html index 2863421..0e3d0a1 100644 --- a/content/test/data/accessibility/html/keygen.html +++ b/content/test/data/accessibility/html/keygen.html
@@ -6,6 +6,7 @@ @WIN-ALLOW:COLLAPSED @WIN-ALLOW:INVISIBLE @WIN-ALLOW:HASPOPUP +@WIN-DENY:name='* --> <!DOCTYPE html> <html>
diff --git a/content/test/data/accessibility/html/modal-dialog-closed-expected-win.txt b/content/test/data/accessibility/html/modal-dialog-closed-expected-win.txt index c714f818..fba5e92a7 100644 --- a/content/test/data/accessibility/html/modal-dialog-closed-expected-win.txt +++ b/content/test/data/accessibility/html/modal-dialog-closed-expected-win.txt
@@ -3,7 +3,7 @@ ++++ROLE_SYSTEM_STATICTEXT name='Test that elements respawn in the accessibility tree after a modal dialog closes.' ++IA2_ROLE_SECTION ++++ROLE_SYSTEM_COMBOBOX FOCUSABLE -++++++ROLE_SYSTEM_CLIENT -++++++++ROLE_SYSTEM_LISTITEM FOCUSABLE +++++++ROLE_SYSTEM_LIST +++++++++ROLE_SYSTEM_LISTITEM name='This should be in the tree.' FOCUSABLE ++IA2_ROLE_SECTION ++++IA2_ROLE_COLOR_CHOOSER FOCUSABLE
diff --git a/content/test/data/accessibility/html/select-expected-win.txt b/content/test/data/accessibility/html/select-expected-win.txt index 42de879c..1baabf2 100644 --- a/content/test/data/accessibility/html/select-expected-win.txt +++ b/content/test/data/accessibility/html/select-expected-win.txt
@@ -1,20 +1,20 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ++IA2_ROLE_SECTION ++++ROLE_SYSTEM_COMBOBOX FOCUSABLE HASPOPUP -++++++ROLE_SYSTEM_CLIENT -++++++++ROLE_SYSTEM_LISTITEM SELECTED FOCUSABLE SELECTABLE -++++++++ROLE_SYSTEM_LISTITEM FOCUSABLE SELECTABLE -++++++++ROLE_SYSTEM_LISTITEM FOCUSABLE SELECTABLE +++++++ROLE_SYSTEM_LIST +++++++++ROLE_SYSTEM_LISTITEM name='Placeholder option' SELECTED FOCUSABLE SELECTABLE +++++++++ROLE_SYSTEM_LISTITEM name='Option 1' FOCUSABLE SELECTABLE +++++++++ROLE_SYSTEM_LISTITEM name='Option 2' FOCUSABLE SELECTABLE ++++ROLE_SYSTEM_COMBOBOX FOCUSABLE HASPOPUP -++++++ROLE_SYSTEM_CLIENT -++++++++ROLE_SYSTEM_LISTITEM FOCUSABLE SELECTABLE -++++++++ROLE_SYSTEM_LISTITEM SELECTED FOCUSABLE SELECTABLE -++++++++ROLE_SYSTEM_LISTITEM FOCUSABLE SELECTABLE +++++++ROLE_SYSTEM_LIST +++++++++ROLE_SYSTEM_LISTITEM name='Option 1' FOCUSABLE SELECTABLE +++++++++ROLE_SYSTEM_LISTITEM name='Option 2' SELECTED FOCUSABLE SELECTABLE +++++++++ROLE_SYSTEM_LISTITEM name='Option 3' FOCUSABLE SELECTABLE ++++ROLE_SYSTEM_COMBOBOX FOCUSABLE HASPOPUP -++++++ROLE_SYSTEM_CLIENT -++++++++ROLE_SYSTEM_LISTITEM SELECTED FOCUSABLE SELECTABLE -++++++++ROLE_SYSTEM_LISTITEM FOCUSABLE SELECTABLE -++++++++ROLE_SYSTEM_LISTITEM FOCUSABLE SELECTABLE +++++++ROLE_SYSTEM_LIST +++++++++ROLE_SYSTEM_LISTITEM name='Option 1' SELECTED FOCUSABLE SELECTABLE +++++++++ROLE_SYSTEM_LISTITEM name='Option 2' FOCUSABLE SELECTABLE +++++++++ROLE_SYSTEM_LISTITEM name='Option 3' FOCUSABLE SELECTABLE ++++ROLE_SYSTEM_LIST FOCUSABLE MULTISELECTABLE EXTSELECTABLE ++++++ROLE_SYSTEM_LISTITEM name='Option 1' FOCUSABLE SELECTABLE ++++++ROLE_SYSTEM_LISTITEM name='Option 2' FOCUSABLE SELECTABLE
diff --git a/content/test/data/frame_tree/page_with_two_frames.html b/content/test/data/frame_tree/page_with_two_frames.html index 3313ce4..c6323ad 100644 --- a/content/test/data/frame_tree/page_with_two_frames.html +++ b/content/test/data/frame_tree/page_with_two_frames.html
@@ -3,8 +3,8 @@ </head> <body> This page has two iframes: one is cross-site, the other is same-site. - <iframe src="/cross-site/bar.com/title1.html"></iframe> - <iframe src="../title1.html"></iframe> + <iframe name="frame1" src="/cross-site/bar.com/title1.html"></iframe> + <iframe name="frame2" src="../title1.html"></iframe> </body> </html>
diff --git a/content/test/data/media/webrtc_test_audio.js b/content/test/data/media/webrtc_test_audio.js index f765e8db..1e69211 100644 --- a/content/test/data/media/webrtc_test_audio.js +++ b/content/test/data/media/webrtc_test_audio.js
@@ -34,6 +34,20 @@ }, 500); } +// Not sure if this is a bug, but sometimes we get several audio ssrc's where +// just reports audio level zero. Think of the nonzero level as the more +// credible one here. http://crbug.com/479147. +function workAroundSeveralReportsIssue(audioOutputLevels) { + if (audioOutputLevels.length == 1) { + return audioOutputLevels[0]; + } + + console.log("Hit issue where one report batch returns two or more reports " + + "with audioReportLevel; got " + audioOutputLevels); + + return Math.max(audioOutputLevels[0], audioOutputLevels[1]); +} + // Gathers |numSamples| samples at |frequency| number of times per second and // calls back |callback| with an array with numbers in the [0, 32768] range. function gatherAudioLevelSamples(peerConnection, numSamples, frequency, @@ -50,10 +64,8 @@ // The call probably isn't up yet. return; } - - // If more than one audio level is reported we get confused. - assertEquals(1, audioOutputLevels.length); - audioLevelSamples.push(audioOutputLevels[0]); + var outputLevel = workAroundSeveralReportsIssue(audioOutputLevels); + audioLevelSamples.push(outputLevel); if (audioLevelSamples.length == numSamples) { console.log('Gathered all samples.');
diff --git a/content/test/data/render_frame_host/focus.html b/content/test/data/render_frame_host/focus.html index 27e5841d..08fd9d5 100644 --- a/content/test/data/render_frame_host/focus.html +++ b/content/test/data/render_frame_host/focus.html
@@ -5,6 +5,7 @@ <body> <iframe name='frame1' src='data:text/html,<input><div>frame1</div>'></iframe> <iframe name='frame2' src='data:text/html,<input><div>frame2</div>'></iframe> + <iframe name='frame3' src='data:text/html,<iframe%20name=%27frame4%27%20src=%27data:text/html,<input><div>frame4</div>%27></iframe>'></iframe> </body> <script> function focusframe1() { @@ -13,5 +14,12 @@ function focusframe2() { frames[1].focus(); } + function focusframe4() { + frames[2][0].focus(); + } + function detachframe(i) { + var iframes = document.getElementsByTagName('iframe'); + iframes[i - 1].parentNode.removeChild(iframes[i - 1]); + } </script> </html>
diff --git a/content/test/gpu/gpu_tests/context_lost_expectations.py b/content/test/gpu/gpu_tests/context_lost_expectations.py index 6f7ecaad..9f4e6a9 100644 --- a/content/test/gpu/gpu_tests/context_lost_expectations.py +++ b/content/test/gpu/gpu_tests/context_lost_expectations.py
@@ -11,4 +11,7 @@ # Sample Usage: # self.Fail('ContextLost.WebGLContextLostFromGPUProcessExit', # ['mac', 'amd', ('nvidia', 0x1234)], bug=123) - pass + + # AMD Radeon 6450 + self.Fail('ContextLost.WebGLContextLostFromGPUProcessExit', + ['linux', ('amd', 0x6779)], bug=479975)
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 522911e0..89e3e86 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -198,6 +198,12 @@ ['linux', ('amd', 0x6779)], bug=436212) self.Fail('conformance/more/functions/uniformf.html', ['linux', ('amd', 0x6779)], bug=436212) + self.Fail('conformance/glsl/misc/shaders-with-invariance.html', + ['linux', ('amd', 0x6779)], bug=479952) + self.Fail('conformance/textures/texture-mips.html', + ['linux', ('amd', 0x6779)], bug=479981) + self.Fail('conformance/textures/texture-size-cube-maps.html', + ['linux', ('amd', 0x6779)], bug=479983) # Android failures self.Fail('deqp/data/gles2/shaders/constants.html',
diff --git a/content/test/ppapi/ppapi_test.h b/content/test/ppapi/ppapi_test.h index a1a3597..92d5f8b 100644 --- a/content/test/ppapi/ppapi_test.h +++ b/content/test/ppapi/ppapi_test.h
@@ -28,8 +28,8 @@ public: PPAPITestMessageHandler(); - virtual MessageResponse HandleMessage(const std::string& json) override; - virtual void Reset() override; + MessageResponse HandleMessage(const std::string& json) override; + void Reset() override; const std::string& message() const { return message_; @@ -46,7 +46,7 @@ PPAPITestBase(); // ContentBrowserTest overrides. - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; virtual std::string BuildQuery(const std::string& base, const std::string& test_case) = 0; @@ -71,10 +71,11 @@ public: PPAPITest(); - virtual void SetUpCommandLine(base::CommandLine* command_line) override; + void SetUpCommandLine(base::CommandLine* command_line) override; - virtual std::string BuildQuery(const std::string& base, - const std::string& test_case) override; + std::string BuildQuery(const std::string& base, + const std::string& test_case) override; + protected: bool in_process_; // Controls the --ppapi-in-process switch. }; @@ -85,8 +86,8 @@ public: OutOfProcessPPAPITest(); - virtual void SetUp() override; - virtual void TearDown() override; + void SetUp() override; + void TearDown() override; }; } // namespace
diff --git a/content/test/test_frame_navigation_observer.cc b/content/test/test_frame_navigation_observer.cc index e3cbccecd..c6d151bc 100644 --- a/content/test/test_frame_navigation_observer.cc +++ b/content/test/test_frame_navigation_observer.cc
@@ -67,7 +67,6 @@ ++navigations_completed_; if (navigations_completed_ == number_of_navigations_) { - load_committed_details_ = details; navigation_started_ = false; message_loop_runner_->Quit(); }
diff --git a/content/test/test_frame_navigation_observer.h b/content/test/test_frame_navigation_observer.h index 5330c48..9ff42c53 100644 --- a/content/test/test_frame_navigation_observer.h +++ b/content/test/test_frame_navigation_observer.h
@@ -10,7 +10,6 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" -#include "content/public/browser/navigation_details.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/test/test_utils.h" @@ -20,6 +19,7 @@ class FrameTreeNode; class RenderFrameHostImpl; class WebContents; +struct LoadCommittedDetails; // For content_browsertests, which run on the UI thread, run a second // MessageLoop and quit when the navigation in a specific frame completes @@ -38,11 +38,6 @@ // navigations are complete. void Wait(); - // Returns the LoadCommittedDetails for the last navigation to commit. - const LoadCommittedDetails& load_committed_details() const { - return load_committed_details_; - } - private: // WebContentsObserver void DidStartProvisionalLoadForFrame(RenderFrameHost* render_frame_host, @@ -65,8 +60,6 @@ // The number of navigations to wait for. int number_of_navigations_; - LoadCommittedDetails load_committed_details_; - // The MessageLoopRunner used to spin the message loop. scoped_refptr<MessageLoopRunner> message_loop_runner_;
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index bc54c3c..838c4235 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -79,13 +79,6 @@ child_creation_observer_.last_created_frame()); } -void TestRenderFrameHost::SendNavigateWithTransition( - int page_id, - const GURL& url, - ui::PageTransition transition) { - SendNavigateWithTransitionAndResponseCode(page_id, url, transition, 200); -} - void TestRenderFrameHost::SetContentsMimeType(const std::string& mime_type) { contents_mime_type_ = mime_type; } @@ -99,18 +92,39 @@ OnSwappedOut(); } -void TestRenderFrameHost::SendNavigate(int page_id, const GURL& url) { - SendNavigateWithTransition(page_id, url, ui::PAGE_TRANSITION_LINK); +void TestRenderFrameHost::SendNavigate(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url) { + SendNavigateWithTransition(page_id, nav_entry_id, did_create_new_entry, url, + ui::PAGE_TRANSITION_LINK); } -void TestRenderFrameHost::SendFailedNavigate(int page_id, const GURL& url) { +void TestRenderFrameHost::SendFailedNavigate(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url) { + SendNavigateWithTransitionAndResponseCode(page_id, nav_entry_id, + did_create_new_entry, url, + ui::PAGE_TRANSITION_RELOAD, 500); +} + +void TestRenderFrameHost::SendNavigateWithTransition( + int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url, + ui::PageTransition transition) { SendNavigateWithTransitionAndResponseCode( - page_id, url, ui::PAGE_TRANSITION_RELOAD, 500); + page_id, nav_entry_id, did_create_new_entry, url, transition, 200); } void TestRenderFrameHost::SendNavigateWithTransitionAndResponseCode( int page_id, - const GURL& url, ui::PageTransition transition, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url, + ui::PageTransition transition, int response_code) { // DidStartProvisionalLoad may delete the pending entry that holds |url|, // so we keep a copy of it to use in SendNavigateWithParameters. @@ -121,12 +135,15 @@ SetRenderFrameCreated(true); OnDidStartProvisionalLoadForFrame(url_copy, false); - SendNavigateWithParameters(page_id, url_copy, transition, url_copy, - response_code, 0, std::vector<GURL>()); + SendNavigateWithParameters(page_id, nav_entry_id, did_create_new_entry, + url_copy, transition, url_copy, response_code, 0, + std::vector<GURL>()); } void TestRenderFrameHost::SendNavigateWithOriginalRequestURL( int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, const GURL& original_request_url) { // Ensure that the RenderFrameCreated notification has been sent to observers @@ -134,16 +151,20 @@ SetRenderFrameCreated(true); OnDidStartProvisionalLoadForFrame(url, false); - SendNavigateWithParameters(page_id, url, ui::PAGE_TRANSITION_LINK, - original_request_url, 200, 0, std::vector<GURL>()); + SendNavigateWithParameters(page_id, nav_entry_id, did_create_new_entry, url, + ui::PAGE_TRANSITION_LINK, original_request_url, + 200, 0, std::vector<GURL>()); } void TestRenderFrameHost::SendNavigateWithFile( int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, const base::FilePath& file_path) { - SendNavigateWithParameters(page_id, url, ui::PAGE_TRANSITION_LINK, url, 200, - &file_path, std::vector<GURL>()); + SendNavigateWithParameters(page_id, nav_entry_id, did_create_new_entry, url, + ui::PAGE_TRANSITION_LINK, url, 200, &file_path, + std::vector<GURL>()); } void TestRenderFrameHost::SendNavigateWithParams( @@ -154,14 +175,18 @@ void TestRenderFrameHost::SendNavigateWithRedirects( int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, const std::vector<GURL>& redirects) { - SendNavigateWithParameters( - page_id, url, ui::PAGE_TRANSITION_LINK, url, 200, 0, redirects); + SendNavigateWithParameters(page_id, nav_entry_id, did_create_new_entry, url, + ui::PAGE_TRANSITION_LINK, url, 200, 0, redirects); } void TestRenderFrameHost::SendNavigateWithParameters( int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition, const GURL& original_request_url, @@ -170,6 +195,7 @@ const std::vector<GURL>& redirects) { FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = page_id; + params.nav_entry_id = nav_entry_id; params.url = url; params.referrer = Referrer(); params.transition = transition; @@ -177,6 +203,7 @@ params.should_update_history = true; params.searchable_form_url = GURL(); params.searchable_form_encoding = std::string(); + params.did_create_new_entry = did_create_new_entry; params.security_info = std::string(); params.gesture = NavigationGestureUser; params.contents_mime_type = contents_mime_type_; @@ -204,11 +231,13 @@ OnDidCommitProvisionalLoad(msg); } -void TestRenderFrameHost::NavigateAndCommitRendererInitiated(int page_id, - const GURL& url) { +void TestRenderFrameHost::NavigateAndCommitRendererInitiated( + int page_id, + bool did_create_new_entry, + const GURL& url) { SendRendererInitiatedNavigationRequest(url, false); PrepareForCommit(); - SendNavigate(page_id, url); + SendNavigate(page_id, 0, did_create_new_entry, url); } void TestRenderFrameHost::SendRendererInitiatedNavigationRequest(
diff --git a/content/test/test_render_frame_host.h b/content/test/test_render_frame_host.h index 798479fc..3b0c9ae 100644 --- a/content/test/test_render_frame_host.h +++ b/content/test/test_render_frame_host.h
@@ -52,35 +52,50 @@ // RenderFrameHostTester implementation. TestRenderFrameHost* AppendChild(const std::string& frame_name) override; - void SendNavigate(int page_id, const GURL& url) override; - void SendFailedNavigate(int page_id, const GURL& url) override; + void SendNavigate(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url) override; + void SendFailedNavigate(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url) override; void SendNavigateWithTransition(int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition) override; void SetContentsMimeType(const std::string& mime_type) override; void SendBeforeUnloadACK(bool proceed) override; void SimulateSwapOutACK() override; - void SendNavigateWithTransitionAndResponseCode( - int page_id, - const GURL& url, ui::PageTransition transition, - int response_code); - void SendNavigateWithOriginalRequestURL( - int page_id, - const GURL& url, - const GURL& original_request_url); - void SendNavigateWithFile( - int page_id, - const GURL& url, - const base::FilePath& file_path); + void SendNavigateWithTransitionAndResponseCode(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url, + ui::PageTransition transition, + int response_code); + void SendNavigateWithOriginalRequestURL(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url, + const GURL& original_request_url); + void SendNavigateWithFile(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url, + const base::FilePath& file_path); void SendNavigateWithParams( FrameHostMsg_DidCommitProvisionalLoad_Params* params); - void SendNavigateWithRedirects( - int page_id, - const GURL& url, - const std::vector<GURL>& redirects); + void SendNavigateWithRedirects(int page_id, + int nav_entry_id, + bool did_create_new_entry, + const GURL& url, + const std::vector<GURL>& redirects); void SendNavigateWithParameters( int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition, const GURL& original_request_url, @@ -89,7 +104,9 @@ const std::vector<GURL>& redirects); // Simulate a renderer-initiated navigation up until commit. - void NavigateAndCommitRendererInitiated(int page_id, const GURL& url); + void NavigateAndCommitRendererInitiated(int page_id, + bool did_create_new_entry, + const GURL& url); // With the current navigation logic this method is a no-op. // PlzNavigate: this method simulates receiving a BeginNavigation IPC.
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc index b6f7a86eb..bedb4b8 100644 --- a/content/test/test_render_view_host.cc +++ b/content/test/test_render_view_host.cc
@@ -28,9 +28,12 @@ void InitNavigateParams(FrameHostMsg_DidCommitProvisionalLoad_Params* params, int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition) { params->page_id = page_id; + params->nav_entry_id = nav_entry_id; params->url = url; params->referrer = Referrer(); params->transition = transition; @@ -38,6 +41,7 @@ params->should_update_history = false; params->searchable_form_url = GURL(); params->searchable_form_encoding = std::string(); + params->did_create_new_entry = did_create_new_entry; params->security_info = std::string(); params->gesture = NavigationGestureUser; params->was_within_same_page = false;
diff --git a/content/test/test_render_view_host.h b/content/test/test_render_view_host.h index ad4ca65..13bc0fb 100644 --- a/content/test/test_render_view_host.h +++ b/content/test/test_render_view_host.h
@@ -40,10 +40,12 @@ class TestRenderFrameHost; class TestWebContents; -// Utility function to initialize ViewHostMsg_NavigateParams_Params -// with given |page_id|, |url| and |transition_type|. +// Utility function to initialize FrameHostMsg_DidCommitProvisionalLoad_Params +// with given parameters. void InitNavigateParams(FrameHostMsg_DidCommitProvisionalLoad_Params* params, int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition_type);
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc index 9032fc4..28c3980 100644 --- a/content/test/test_web_contents.cc +++ b/content/test/test_web_contents.cc
@@ -67,10 +67,14 @@ void TestWebContents::TestDidNavigate(RenderFrameHost* render_frame_host, int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition) { TestDidNavigateWithReferrer(render_frame_host, page_id, + nav_entry_id, + did_create_new_entry, url, Referrer(), transition); @@ -79,12 +83,15 @@ void TestWebContents::TestDidNavigateWithReferrer( RenderFrameHost* render_frame_host, int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, const Referrer& referrer, ui::PageTransition transition) { FrameHostMsg_DidCommitProvisionalLoad_Params params; params.page_id = page_id; + params.nav_entry_id = nav_entry_id; params.url = url; params.referrer = referrer; params.transition = transition; @@ -92,6 +99,7 @@ params.should_update_history = false; params.searchable_form_url = GURL(); params.searchable_form_encoding = std::string(); + params.did_create_new_entry = did_create_new_entry; params.security_info = std::string(); params.gesture = NavigationGestureUser; params.was_within_same_page = false; @@ -182,7 +190,9 @@ page_id = GetMaxPageIDForSiteInstance(rfh->GetSiteInstance()) + 1; } - rfh->SendNavigate(page_id, entry->GetURL()); + rfh->SendNavigate(page_id, entry->GetUniqueID(), + GetController().GetPendingEntryIndex() == -1, + entry->GetURL()); // Simulate the SwapOut_ACK. This is needed when cross-site navigation // happens. if (old_rfh != rfh)
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h index 66bef97..632d57f 100644 --- a/content/test/test_web_contents.h +++ b/content/test/test_web_contents.h
@@ -40,10 +40,14 @@ void ProceedWithCrossSiteNavigation() override; void TestDidNavigate(RenderFrameHost* render_frame_host, int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, ui::PageTransition transition) override; void TestDidNavigateWithReferrer(RenderFrameHost* render_frame_host, int page_id, + int nav_entry_id, + bool did_create_new_entry, const GURL& url, const Referrer& referrer, ui::PageTransition transition) override;
diff --git a/content/test/web_layer_tree_view_impl_for_testing.cc b/content/test/web_layer_tree_view_impl_for_testing.cc index 20da3cd6..1b2f5f6e 100644 --- a/content/test/web_layer_tree_view_impl_for_testing.cc +++ b/content/test/web_layer_tree_view_impl_for_testing.cc
@@ -190,8 +190,7 @@ } void WebLayerTreeViewImplForTesting::registerSelection( - const blink::WebSelectionBound& start, - const blink::WebSelectionBound& end) { + const blink::WebSelection& selection) { } void WebLayerTreeViewImplForTesting::clearSelection() {
diff --git a/content/test/web_layer_tree_view_impl_for_testing.h b/content/test/web_layer_tree_view_impl_for_testing.h index 6ff82f9..db28812 100644 --- a/content/test/web_layer_tree_view_impl_for_testing.h +++ b/content/test/web_layer_tree_view_impl_for_testing.h
@@ -59,9 +59,7 @@ const blink::WebLayer* innerViewportScrollLayer, const blink::WebLayer* outerViewportScrollLayer) override; virtual void clearViewportLayers() override; - virtual void registerSelection( - const blink::WebSelectionBound& start, - const blink::WebSelectionBound& end) override; + virtual void registerSelection(const blink::WebSelection& selection) override; virtual void clearSelection() override; // cc::LayerTreeHostClient implementation.
diff --git a/courgette/disassembler_elf_32_x86.h b/courgette/disassembler_elf_32_x86.h index bc83a04..913e93f 100644 --- a/courgette/disassembler_elf_32_x86.h +++ b/courgette/disassembler_elf_32_x86.h
@@ -21,17 +21,17 @@ explicit TypedRVAX86(RVA rva) : TypedRVA(rva) { } - virtual CheckBool ComputeRelativeTarget(const uint8* op_pointer) override { + CheckBool ComputeRelativeTarget(const uint8* op_pointer) override { set_relative_target(Read32LittleEndian(op_pointer) + 4); return true; } - virtual CheckBool EmitInstruction(AssemblyProgram* program, - RVA target_rva) override { + CheckBool EmitInstruction(AssemblyProgram* program, + RVA target_rva) override { return program->EmitRel32(program->FindOrMakeRel32Label(target_rva)); } - virtual uint16 op_size() const override { return 4; } + uint16 op_size() const override { return 4; } }; explicit DisassemblerElf32X86(const void* start, size_t length);
diff --git a/crypto/BUILD.gn b/crypto/BUILD.gn index 27e786c..c1eabe6 100644 --- a/crypto/BUILD.gn +++ b/crypto/BUILD.gn
@@ -8,6 +8,8 @@ component("crypto") { output_name = "crcrypto" # Avoid colliding with OpenSSL's libcrypto. sources = [ + "aead_openssl.cc", + "aead_openssl.h", "apple_keychain.h", "apple_keychain_ios.mm", "apple_keychain_mac.mm", @@ -151,6 +153,8 @@ } else { # Remove OpenSSL when using NSS. sources -= [ + "aead_openssl.cc", + "aead_openssl.h", "ec_private_key_openssl.cc", "ec_signature_creator_openssl.cc", "encryptor_openssl.cc",
diff --git a/crypto/aead_openssl.cc b/crypto/aead_openssl.cc new file mode 100644 index 0000000..e32168a --- /dev/null +++ b/crypto/aead_openssl.cc
@@ -0,0 +1,125 @@ +// 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 "crypto/aead_openssl.h" + +#if defined(USE_OPENSSL) + +#include <openssl/aes.h> +#include <openssl/evp.h> +#include <string> + +#include "base/basictypes.h" +#include "base/strings/string_util.h" +#include "crypto/openssl_util.h" + +namespace crypto { + +Aead::Aead(AeadAlgorithm algorithm) : key_(nullptr) { + EnsureOpenSSLInit(); + switch (algorithm) { + case AES_128_CTR_HMAC_SHA256: + aead_ = EVP_aead_aes_128_ctr_hmac_sha256(); + break; + } +} + +Aead::~Aead() { +} + +void Aead::Init(const std::string* key) { + DCHECK(!key_); + DCHECK_EQ(KeyLength(), key->size()); + key_ = key; +} + +bool Aead::Seal(const base::StringPiece& plaintext, + const base::StringPiece& nonce, + const base::StringPiece& additional_data, + std::string* ciphertext) const { + DCHECK(key_); + DCHECK_EQ(NonceLength(), nonce.size()); + EVP_AEAD_CTX ctx; + + if (!EVP_AEAD_CTX_init(&ctx, aead_, + reinterpret_cast<const uint8*>(key_->data()), + key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) { + return false; + } + + std::string result; + const size_t max_output_length = + EVP_AEAD_max_overhead(aead_) + plaintext.size(); + size_t output_length; + uint8* out_ptr = + reinterpret_cast<uint8*>(WriteInto(&result, max_output_length + 1)); + + if (!EVP_AEAD_CTX_seal( + &ctx, out_ptr, &output_length, max_output_length, + reinterpret_cast<const uint8*>(nonce.data()), nonce.size(), + reinterpret_cast<const uint8*>(plaintext.data()), plaintext.size(), + reinterpret_cast<const uint8*>(additional_data.data()), + additional_data.size())) { + EVP_AEAD_CTX_cleanup(&ctx); + return false; + } + + DCHECK_LE(output_length, max_output_length); + result.resize(output_length); + + ciphertext->swap(result); + EVP_AEAD_CTX_cleanup(&ctx); + + return true; +} + +bool Aead::Open(const base::StringPiece& ciphertext, + const base::StringPiece& nonce, + const base::StringPiece& additional_data, + std::string* plaintext) const { + DCHECK(key_); + EVP_AEAD_CTX ctx; + + if (!EVP_AEAD_CTX_init(&ctx, aead_, + reinterpret_cast<const uint8*>(key_->data()), + key_->size(), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) { + return false; + } + + std::string result; + const size_t max_output_length = ciphertext.size(); + size_t output_length; + uint8* out_ptr = + reinterpret_cast<uint8*>(WriteInto(&result, max_output_length + 1)); + + if (!EVP_AEAD_CTX_open( + &ctx, out_ptr, &output_length, max_output_length, + reinterpret_cast<const uint8*>(nonce.data()), nonce.size(), + reinterpret_cast<const uint8*>(ciphertext.data()), ciphertext.size(), + reinterpret_cast<const uint8*>(additional_data.data()), + additional_data.size())) { + EVP_AEAD_CTX_cleanup(&ctx); + return false; + } + + DCHECK_LE(output_length, max_output_length); + result.resize(output_length); + + plaintext->swap(result); + EVP_AEAD_CTX_cleanup(&ctx); + + return true; +} + +size_t Aead::KeyLength() const { + return EVP_AEAD_key_length(aead_); +} + +size_t Aead::NonceLength() const { + return EVP_AEAD_nonce_length(aead_); +} + +} // namespace + +#endif
diff --git a/crypto/aead_openssl.h b/crypto/aead_openssl.h new file mode 100644 index 0000000..773cce1 --- /dev/null +++ b/crypto/aead_openssl.h
@@ -0,0 +1,48 @@ +// 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 CRYPTO_AEAD_H_ +#define CRYPTO_AEAD_H_ + +#include "base/strings/string_piece.h" +#include "crypto/crypto_export.h" + +struct evp_aead_st; + +namespace crypto { + +// This class exposes the AES-128-CTR-HMAC-SHA256 AEAD, currently only +// for OpenSSL builds. +class CRYPTO_EXPORT Aead { + public: + enum AeadAlgorithm { AES_128_CTR_HMAC_SHA256 }; + + explicit Aead(AeadAlgorithm algorithm); + + ~Aead(); + + void Init(const std::string* key); + + bool Seal(const base::StringPiece& plaintext, + const base::StringPiece& nonce, + const base::StringPiece& additional_data, + std::string* ciphertext) const; + + bool Open(const base::StringPiece& ciphertext, + const base::StringPiece& nonce, + const base::StringPiece& additional_data, + std::string* plaintext) const; + + size_t KeyLength() const; + + size_t NonceLength() const; + + private: + const std::string* key_; + const evp_aead_st* aead_; +}; + +} // namespace crypto + +#endif // CRYPTO_ENCRYPTOR_H_
diff --git a/crypto/aead_openssl_unittest.cc b/crypto/aead_openssl_unittest.cc new file mode 100644 index 0000000..446bca2 --- /dev/null +++ b/crypto/aead_openssl_unittest.cc
@@ -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. + +#include "crypto/aead_openssl.h" + +#include <string> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +#if defined(USE_OPENSSL) + +TEST(AeadTest, SealOpen) { + crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256); + std::string key(aead.KeyLength(), 0); + aead.Init(&key); + std::string nonce(aead.NonceLength(), 0); + std::string plaintext("this is the plaintext"); + std::string ad("this is the additional data"); + std::string ciphertext; + EXPECT_TRUE(aead.Seal(plaintext, nonce, ad, &ciphertext)); + EXPECT_LT(0U, ciphertext.size()); + + std::string decrypted; + EXPECT_TRUE(aead.Open(ciphertext, nonce, ad, &decrypted)); + + EXPECT_EQ(plaintext, decrypted); +} + +TEST(AeadTest, SealOpenWrongKey) { + crypto::Aead aead(crypto::Aead::AES_128_CTR_HMAC_SHA256); + std::string key(aead.KeyLength(), 0); + std::string wrong_key(aead.KeyLength(), 1); + aead.Init(&key); + crypto::Aead aead_wrong_key(crypto::Aead::AES_128_CTR_HMAC_SHA256); + aead_wrong_key.Init(&wrong_key); + + std::string nonce(aead.NonceLength(), 0); + std::string plaintext("this is the plaintext"); + std::string ad("this is the additional data"); + std::string ciphertext; + EXPECT_TRUE(aead.Seal(plaintext, nonce, ad, &ciphertext)); + EXPECT_LT(0U, ciphertext.size()); + + std::string decrypted; + EXPECT_FALSE(aead_wrong_key.Open(ciphertext, nonce, ad, &decrypted)); + EXPECT_EQ(0U, decrypted.size()); +} + +#endif + +} // namespace
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp index a9cff553..00b59b5 100644 --- a/crypto/crypto.gyp +++ b/crypto/crypto.gyp
@@ -125,6 +125,8 @@ ], }, { 'sources!': [ + 'aead_openssl.cc', + 'aead_openssl.h', 'ec_private_key_openssl.cc', 'ec_signature_creator_openssl.cc', 'encryptor_openssl.cc', @@ -158,6 +160,7 @@ 'target_name': 'crypto_unittests', 'type': 'executable', 'sources': [ + 'aead_openssl_unittest.cc', 'curve25519_unittest.cc', 'ec_private_key_unittest.cc', 'ec_signature_creator_unittest.cc',
diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi index 6fdbdf49..4456b10 100644 --- a/crypto/crypto.gypi +++ b/crypto/crypto.gypi
@@ -27,6 +27,8 @@ # NOTE: all transitive dependencies of HMAC on windows need # to be placed in the source list above. '<@(hmac_win64_related_sources)', + 'aead_openssl.cc', + 'aead_openssl.h', 'apple_keychain.h', 'apple_keychain_ios.mm', 'apple_keychain_mac.mm',
diff --git a/dbus/file_descriptor.cc b/dbus/file_descriptor.cc index d2d6a31..e607fc0 100644 --- a/dbus/file_descriptor.cc +++ b/dbus/file_descriptor.cc
@@ -2,12 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/bind.h" #include "base/files/file.h" +#include "base/location.h" #include "base/logging.h" +#include "base/threading/worker_pool.h" #include "dbus/file_descriptor.h" namespace dbus { +void CHROME_DBUS_EXPORT FileDescriptor::Deleter::operator()( + FileDescriptor* fd) { + base::WorkerPool::PostTask( + FROM_HERE, base::Bind(&base::DeletePointer<FileDescriptor>, fd), false); +} + FileDescriptor::~FileDescriptor() { if (owner_) base::File auto_closer(value_);
diff --git a/dbus/file_descriptor.h b/dbus/file_descriptor.h index 19e0b1ab..a01ee6e 100644 --- a/dbus/file_descriptor.h +++ b/dbus/file_descriptor.h
@@ -6,6 +6,7 @@ #define DBUS_FILE_DESCRIPTOR_H_ #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "dbus/dbus_export.h" namespace dbus { @@ -33,6 +34,12 @@ // with i/o restrictions. class CHROME_DBUS_EXPORT FileDescriptor { public: + // This provides a simple way to pass around file descriptors since they must + // be closed on a thread that is allowed to perform I/O. + struct Deleter { + void CHROME_DBUS_EXPORT operator()(FileDescriptor* fd); + }; + // Permits initialization without a value for passing to // dbus::MessageReader::PopFileDescriptor to fill in and from int values. FileDescriptor() : value_(-1), owner_(false), valid_(false) {} @@ -70,6 +77,9 @@ DISALLOW_COPY_AND_ASSIGN(FileDescriptor); }; +using ScopedFileDescriptor = + scoped_ptr<FileDescriptor, FileDescriptor::Deleter>; + } // namespace dbus #endif // DBUS_FILE_DESCRIPTOR_H_
diff --git a/dbus/values_util_unittest.cc b/dbus/values_util_unittest.cc index 336d7714..27ec2d0 100644 --- a/dbus/values_util_unittest.cc +++ b/dbus/values_util_unittest.cc
@@ -4,9 +4,9 @@ #include "dbus/values_util.h" +#include <cmath> #include <vector> -#include "base/float_util.h" #include "base/json/json_writer.h" #include "base/memory/scoped_ptr.h" #include "base/values.h" @@ -358,7 +358,7 @@ const std::vector<int32> values(kValues, kValues + arraysize(kValues)); std::vector<double> keys(values.size()); for (size_t i = 0; i != values.size(); ++i) - keys[i] = sqrt(values[i]); + keys[i] = std::sqrt(values[i]); // Append a dictionary. scoped_ptr<Response> response(Response::CreateEmpty());
diff --git a/device/BUILD.gn b/device/BUILD.gn index 3bf6fa7..ba522909 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -5,6 +5,10 @@ import("//build/config/features.gni") import("//testing/test.gni") +if (is_mac) { + import("//build/config/mac/mac_sdk.gni") +} + is_linux_without_udev = is_linux && !use_udev is_linux_without_dbus = is_linux && !use_dbus @@ -112,5 +116,13 @@ if (is_mac) { libs = [ "IOBluetooth.framework" ] + + # In the OSX 10.10 SDK, CoreBluetooth became a top level framework. + # Previously, it was nested in IOBluetooth. In order for Chrome to run on + # OSes older than OSX 10.10, the top level CoreBluetooth framework must be + # weakly linked. + if (mac_sdk_version == "10.10") { + ldflags = [ "-weak_framework CoreBluetooth" ] + } } }
diff --git a/device/battery/battery_status_manager_win.cc b/device/battery/battery_status_manager_win.cc index 6ad13da8..50ceac7 100644 --- a/device/battery/battery_status_manager_win.cc +++ b/device/battery/battery_status_manager_win.cc
@@ -160,18 +160,16 @@ public: explicit BatteryStatusManagerWin(const BatteryCallback& callback) : battery_observer_(new BatteryStatusObserver(callback)) {} - virtual ~BatteryStatusManagerWin() { battery_observer_->Stop(); } + ~BatteryStatusManagerWin() override { battery_observer_->Stop(); } public: // BatteryStatusManager: - virtual bool StartListeningBatteryChange() override { + bool StartListeningBatteryChange() override { battery_observer_->Start(); return true; } - virtual void StopListeningBatteryChange() override { - battery_observer_->Stop(); - } + void StopListeningBatteryChange() override { battery_observer_->Stop(); } private: scoped_ptr<BatteryStatusObserver> battery_observer_;
diff --git a/device/bluetooth/bluetooth.gyp b/device/bluetooth/bluetooth.gyp index 1e4f7ed..a74cc4bd 100644 --- a/device/bluetooth/bluetooth.gyp +++ b/device/bluetooth/bluetooth.gyp
@@ -152,11 +152,25 @@ 'libraries': [ '$(SDKROOT)/System/Library/Frameworks/IOBluetooth.framework', ], + 'conditions': [ + ['mac_sdk == "10.10"', { + 'xcode_settings': { + # In the OSX 10.10 SDK, CoreBluetooth became a top level + # framework. Previously, it was nested in IOBluetooth. In + # order for Chrome to run on OSes older than OSX 10.10, the + # top level CoreBluetooth framework must be weakly linked. + 'OTHER_LDFLAGS': [ + '-weak_framework CoreBluetooth', + ], + }, + }], + ], }, }], ], }, { + # GN version: //device/bluetooth/uribeacon 'target_name': 'uribeacon', 'type': 'static_library', 'dependencies': [
diff --git a/device/bluetooth/bluetooth_adapter.cc b/device/bluetooth/bluetooth_adapter.cc index 23fde08..80c107c 100644 --- a/device/bluetooth/bluetooth_adapter.cc +++ b/device/bluetooth/bluetooth_adapter.cc
@@ -54,7 +54,8 @@ scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, const DiscoverySessionCallback& callback, const ErrorCallback& error_callback) { - AddDiscoverySession(discovery_filter.get(), + BluetoothDiscoveryFilter* ptr = discovery_filter.get(); + AddDiscoverySession(ptr, base::Bind(&BluetoothAdapter::OnStartDiscoverySession, weak_ptr_factory_.GetWeakPtr(), base::Passed(&discovery_filter), callback),
diff --git a/device/bluetooth/bluetooth_adapter_win.h b/device/bluetooth/bluetooth_adapter_win.h index 3bb26c9..9419373 100644 --- a/device/bluetooth/bluetooth_adapter_win.h +++ b/device/bluetooth/bluetooth_adapter_win.h
@@ -41,30 +41,28 @@ const InitCallback& init_callback); // BluetoothAdapter: - virtual std::string GetAddress() const override; - virtual std::string GetName() const override; - virtual void SetName(const std::string& name, + std::string GetAddress() const override; + std::string GetName() const override; + void SetName(const std::string& name, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + bool IsInitialized() const override; + bool IsPresent() const override; + bool IsPowered() const override; + void SetPowered(bool discoverable, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + bool IsDiscoverable() const override; + void SetDiscoverable(bool discoverable, const base::Closure& callback, const ErrorCallback& error_callback) override; - virtual bool IsInitialized() const override; - virtual bool IsPresent() const override; - virtual bool IsPowered() const override; - virtual void SetPowered( - bool discoverable, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - virtual bool IsDiscoverable() const override; - virtual void SetDiscoverable( - bool discoverable, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - virtual bool IsDiscovering() const override; - virtual void CreateRfcommService( + bool IsDiscovering() const override; + void CreateRfcommService( const BluetoothUUID& uuid, const ServiceOptions& options, const CreateServiceCallback& callback, const CreateServiceErrorCallback& error_callback) override; - virtual void CreateL2capService( + void CreateL2capService( const BluetoothUUID& uuid, const ServiceOptions& options, const CreateServiceCallback& callback, @@ -75,12 +73,12 @@ const BluetoothAudioSink::ErrorCallback& error_callback) override; // BluetoothTaskManagerWin::Observer override - virtual void AdapterStateChanged( + void AdapterStateChanged( const BluetoothTaskManagerWin::AdapterState& state) override; - virtual void DiscoveryStarted(bool success) override; - virtual void DiscoveryStopped() override; - virtual void DevicesPolled(const ScopedVector< - BluetoothTaskManagerWin::DeviceState>& devices) override; + void DiscoveryStarted(bool success) override; + void DiscoveryStopped() override; + void DevicesPolled(const ScopedVector<BluetoothTaskManagerWin::DeviceState>& + devices) override; const scoped_refptr<base::SequencedTaskRunner>& ui_task_runner() const { return ui_task_runner_; @@ -91,7 +89,7 @@ protected: // BluetoothAdapter: - virtual void RemovePairingDelegateInternal( + void RemovePairingDelegateInternal( device::BluetoothDevice::PairingDelegate* pairing_delegate) override; private: @@ -105,21 +103,18 @@ }; explicit BluetoothAdapterWin(const InitCallback& init_callback); - virtual ~BluetoothAdapterWin(); + ~BluetoothAdapterWin() override; // BluetoothAdapter: - virtual void AddDiscoverySession( - BluetoothDiscoveryFilter* discovery_filter, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - virtual void RemoveDiscoverySession( - BluetoothDiscoveryFilter* discovery_filter, - const base::Closure& callback, - const ErrorCallback& error_callback) override; - virtual void SetDiscoveryFilter( - scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, - const base::Closure& callback, - const ErrorCallback& error_callback) override; + void AddDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void RemoveDiscoverySession(BluetoothDiscoveryFilter* discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; + void SetDiscoveryFilter(scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, + const base::Closure& callback, + const ErrorCallback& error_callback) override; void Init(); void InitForTest(
diff --git a/device/bluetooth/bluetooth_adapter_win_unittest.cc b/device/bluetooth/bluetooth_adapter_win_unittest.cc index 670a03dc2..df445f8 100644 --- a/device/bluetooth/bluetooth_adapter_win_unittest.cc +++ b/device/bluetooth/bluetooth_adapter_win_unittest.cc
@@ -50,34 +50,33 @@ num_device_changed_ = 0; } - virtual void AdapterPresentChanged( - device::BluetoothAdapter* adapter, bool present) override { + void AdapterPresentChanged(device::BluetoothAdapter* adapter, + bool present) override { num_present_changed_++; } - virtual void AdapterPoweredChanged( - device::BluetoothAdapter* adapter, bool powered) override { + void AdapterPoweredChanged(device::BluetoothAdapter* adapter, + bool powered) override { num_powered_changed_++; } - virtual void AdapterDiscoveringChanged( - device::BluetoothAdapter* adapter, bool discovering) override { + void AdapterDiscoveringChanged(device::BluetoothAdapter* adapter, + bool discovering) override { num_discovering_changed_++; } - virtual void DeviceAdded( - device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) override { + void DeviceAdded(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override { num_device_added_++; } - virtual void DeviceRemoved(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) override { + void DeviceRemoved(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override { num_device_removed_++; } - virtual void DeviceChanged(device::BluetoothAdapter* adapter, - device::BluetoothDevice* device) override { + void DeviceChanged(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override { num_device_changed_++; } @@ -119,7 +118,7 @@ adapter_win_->InitForTest(ui_task_runner_, bluetooth_task_runner_); } - virtual void SetUp() override { + void SetUp() override { adapter_win_->AddObserver(&adapter_observer_); num_start_discovery_callbacks_ = 0; num_start_discovery_error_callbacks_ = 0; @@ -127,9 +126,7 @@ num_stop_discovery_error_callbacks_ = 0; } - virtual void TearDown() override { - adapter_win_->RemoveObserver(&adapter_observer_); - } + void TearDown() override { adapter_win_->RemoveObserver(&adapter_observer_); } void RunInitCallback() { init_callback_called_ = true;
diff --git a/device/bluetooth/bluetooth_device_win.h b/device/bluetooth/bluetooth_device_win.h index 9a6edd5..d4442e6 100644 --- a/device/bluetooth/bluetooth_device_win.h +++ b/device/bluetooth/bluetooth_device_win.h
@@ -28,47 +28,44 @@ const scoped_refptr<BluetoothSocketThread>& socket_thread, net::NetLog* net_log, const net::NetLog::Source& net_log_source); - virtual ~BluetoothDeviceWin(); + ~BluetoothDeviceWin() override; // BluetoothDevice override - virtual uint32 GetBluetoothClass() const override; - virtual std::string GetAddress() const override; - virtual VendorIDSource GetVendorIDSource() const override; - virtual uint16 GetVendorID() const override; - virtual uint16 GetProductID() const override; - virtual uint16 GetDeviceID() const override; - virtual bool IsPaired() const override; - virtual bool IsConnected() const override; - virtual bool IsConnectable() const override; - virtual bool IsConnecting() const override; - virtual UUIDList GetUUIDs() const override; - virtual bool ExpectingPinCode() const override; - virtual bool ExpectingPasskey() const override; - virtual bool ExpectingConfirmation() const override; - virtual void GetConnectionInfo( - const ConnectionInfoCallback& callback) override; - virtual void Connect( - PairingDelegate* pairing_delegate, - const base::Closure& callback, - const ConnectErrorCallback& error_callback) override; - virtual void SetPinCode(const std::string& pincode) override; - virtual void SetPasskey(uint32 passkey) override; - virtual void ConfirmPairing() override; - virtual void RejectPairing() override; - virtual void CancelPairing() override; - virtual void Disconnect( - const base::Closure& callback, - const ErrorCallback& error_callback) override; - virtual void Forget(const ErrorCallback& error_callback) override; - virtual void ConnectToService( + uint32 GetBluetoothClass() const override; + std::string GetAddress() const override; + VendorIDSource GetVendorIDSource() const override; + uint16 GetVendorID() const override; + uint16 GetProductID() const override; + uint16 GetDeviceID() const override; + bool IsPaired() const override; + bool IsConnected() const override; + bool IsConnectable() const override; + bool IsConnecting() const override; + UUIDList GetUUIDs() const override; + bool ExpectingPinCode() const override; + bool ExpectingPasskey() const override; + bool ExpectingConfirmation() const override; + void GetConnectionInfo(const ConnectionInfoCallback& callback) override; + void Connect(PairingDelegate* pairing_delegate, + const base::Closure& callback, + const ConnectErrorCallback& error_callback) override; + void SetPinCode(const std::string& pincode) override; + void SetPasskey(uint32 passkey) override; + void ConfirmPairing() override; + void RejectPairing() override; + void CancelPairing() override; + void Disconnect(const base::Closure& callback, + const ErrorCallback& error_callback) override; + void Forget(const ErrorCallback& error_callback) override; + void ConnectToService( const BluetoothUUID& uuid, const ConnectToServiceCallback& callback, const ConnectToServiceErrorCallback& error_callback) override; - virtual void ConnectToServiceInsecurely( + void ConnectToServiceInsecurely( const BluetoothUUID& uuid, const ConnectToServiceCallback& callback, const ConnectToServiceErrorCallback& error_callback) override; - virtual void CreateGattConnection( + void CreateGattConnection( const GattConnectionCallback& callback, const ConnectErrorCallback& error_callback) override; @@ -87,7 +84,7 @@ protected: // BluetoothDevice override - virtual std::string GetDeviceName() const override; + std::string GetDeviceName() const override; private: friend class BluetoothAdapterWin;
diff --git a/device/bluetooth/bluetooth_socket_win.h b/device/bluetooth/bluetooth_socket_win.h index 38c1664..b5d3ef8d 100644 --- a/device/bluetooth/bluetooth_socket_win.h +++ b/device/bluetooth/bluetooth_socket_win.h
@@ -54,11 +54,11 @@ void ResetData(); // BluetoothSocket: - virtual void Accept(const AcceptCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) override; + void Accept(const AcceptCompletionCallback& success_callback, + const ErrorCompletionCallback& error_callback) override; protected: - virtual ~BluetoothSocketWin(); + ~BluetoothSocketWin() override; private: struct ServiceRegData;
diff --git a/device/bluetooth/bluetooth_task_manager_win_unittest.cc b/device/bluetooth/bluetooth_task_manager_win_unittest.cc index 226db7bd..0a82c7d 100644 --- a/device/bluetooth/bluetooth_task_manager_win_unittest.cc +++ b/device/bluetooth/bluetooth_task_manager_win_unittest.cc
@@ -20,21 +20,16 @@ num_discovery_stopped_(0) { } - virtual ~BluetoothTaskObserver() { - } + ~BluetoothTaskObserver() override {} - virtual void AdapterStateChanged( - const device::BluetoothTaskManagerWin::AdapterState& state) override { + void AdapterStateChanged( + const device::BluetoothTaskManagerWin::AdapterState& state) override { num_adapter_state_changed_++; } - virtual void DiscoveryStarted(bool success) override { - num_discovery_started_++; - } + void DiscoveryStarted(bool success) override { num_discovery_started_++; } - virtual void DiscoveryStopped() override { - num_discovery_stopped_++; - } + void DiscoveryStopped() override { num_discovery_stopped_++; } int num_adapter_state_changed() const { return num_adapter_state_changed_; @@ -68,13 +63,9 @@ task_manager_->InitializeWithBluetoothTaskRunner(bluetooth_task_runner_); } - virtual void SetUp() { - task_manager_->AddObserver(&observer_); - } + void SetUp() override { task_manager_->AddObserver(&observer_); } - virtual void TearDown() { - task_manager_->RemoveObserver(&observer_); - } + void TearDown() override { task_manager_->RemoveObserver(&observer_); } int GetPollingIntervalMs() const { return BluetoothTaskManagerWin::kPollIntervalMs;
diff --git a/device/bluetooth/uribeacon/BUILD.gn b/device/bluetooth/uribeacon/BUILD.gn index 0c7d1d80..484e2727 100644 --- a/device/bluetooth/uribeacon/BUILD.gn +++ b/device/bluetooth/uribeacon/BUILD.gn
@@ -2,7 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -component("uribeacon") { +source_set("uribeacon") { sources = [ "uri_encoder.cc", "uri_encoder.h",
diff --git a/device/hid/hid_connection_win.cc b/device/hid/hid_connection_win.cc index 47571c78..2e5eab2 100644 --- a/device/hid/hid_connection_win.cc +++ b/device/hid/hid_connection_win.cc
@@ -40,10 +40,10 @@ OVERLAPPED* GetOverlapped() { return &overlapped_; } // Implements base::win::ObjectWatcher::Delegate. - virtual void OnObjectSignaled(HANDLE object) override; + void OnObjectSignaled(HANDLE object) override; // Implements base::MessageLoop::DestructionObserver - virtual void WillDestroyCurrentMessageLoop() override; + void WillDestroyCurrentMessageLoop() override; // The buffer isn't used by this object but it's important that a reference // to it is held until the transfer completes. @@ -56,7 +56,7 @@ private: friend class base::RefCounted<PendingHidTransfer>; - virtual ~PendingHidTransfer(); + ~PendingHidTransfer() override; DISALLOW_COPY_AND_ASSIGN(PendingHidTransfer); };
diff --git a/device/hid/hid_connection_win.h b/device/hid/hid_connection_win.h index 5830c21..b1c4bf84 100644 --- a/device/hid/hid_connection_win.h +++ b/device/hid/hid_connection_win.h
@@ -25,20 +25,19 @@ friend class HidServiceWin; friend struct PendingHidTransfer; - ~HidConnectionWin(); + ~HidConnectionWin() override; // HidConnection implementation. - virtual void PlatformClose() override; - virtual void PlatformRead(const ReadCallback& callback) override; - virtual void PlatformWrite(scoped_refptr<net::IOBuffer> buffer, - size_t size, - const WriteCallback& callback) override; - virtual void PlatformGetFeatureReport(uint8_t report_id, - const ReadCallback& callback) override; - virtual void PlatformSendFeatureReport( - scoped_refptr<net::IOBuffer> buffer, - size_t size, - const WriteCallback& callback) override; + void PlatformClose() override; + void PlatformRead(const ReadCallback& callback) override; + void PlatformWrite(scoped_refptr<net::IOBuffer> buffer, + size_t size, + const WriteCallback& callback) override; + void PlatformGetFeatureReport(uint8_t report_id, + const ReadCallback& callback) override; + void PlatformSendFeatureReport(scoped_refptr<net::IOBuffer> buffer, + size_t size, + const WriteCallback& callback) override; void OnReadComplete(scoped_refptr<net::IOBuffer> buffer, const ReadCallback& callback,
diff --git a/device/hid/hid_service_win.h b/device/hid/hid_service_win.h index ea370057..b5b081d 100644 --- a/device/hid/hid_service_win.h +++ b/device/hid/hid_service_win.h
@@ -33,11 +33,11 @@ public: HidServiceWin(scoped_refptr<base::SingleThreadTaskRunner> file_task_runner); - virtual void Connect(const HidDeviceId& device_id, - const ConnectCallback& callback) override; + void Connect(const HidDeviceId& device_id, + const ConnectCallback& callback) override; private: - virtual ~HidServiceWin(); + ~HidServiceWin() override; static void EnumerateOnFileThread( base::WeakPtr<HidServiceWin> service,
diff --git a/device/serial/serial_connection_factory.cc b/device/serial/serial_connection_factory.cc index 85a3e2e..654b3e8 100644 --- a/device/serial/serial_connection_factory.cc +++ b/device/serial/serial_connection_factory.cc
@@ -61,9 +61,9 @@ SerialConnectionFactory::SerialConnectionFactory( const IoHandlerFactory& io_handler_factory, - scoped_refptr<base::MessageLoopProxy> connect_message_loop) + scoped_refptr<base::SingleThreadTaskRunner> connect_task_runner) : io_handler_factory_(io_handler_factory), - connect_message_loop_(connect_message_loop) { + connect_task_runner_(connect_task_runner) { } void SerialConnectionFactory::CreateConnection( @@ -104,7 +104,7 @@ } void SerialConnectionFactory::ConnectTask::Run() { - factory_->connect_message_loop_->PostTask( + factory_->connect_task_runner_->PostTask( FROM_HERE, base::Bind(&SerialConnectionFactory::ConnectTask::Connect, this)); }
diff --git a/device/serial/serial_connection_factory.h b/device/serial/serial_connection_factory.h index befb209c..6d22fff 100644 --- a/device/serial/serial_connection_factory.h +++ b/device/serial/serial_connection_factory.h
@@ -9,7 +9,8 @@ #include "base/callback.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop_proxy.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" #include "device/serial/data_stream.mojom.h" #include "device/serial/serial.mojom.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" @@ -25,7 +26,7 @@ SerialConnectionFactory( const IoHandlerFactory& io_handler_factory, - scoped_refptr<base::MessageLoopProxy> connect_message_loop); + scoped_refptr<base::SingleThreadTaskRunner> connect_task_runner); void CreateConnection( const std::string& path, @@ -42,7 +43,7 @@ virtual ~SerialConnectionFactory(); const IoHandlerFactory io_handler_factory_; - scoped_refptr<base::MessageLoopProxy> connect_message_loop_; + scoped_refptr<base::SingleThreadTaskRunner> connect_task_runner_; DISALLOW_COPY_AND_ASSIGN(SerialConnectionFactory); };
diff --git a/device/serial/serial_connection_unittest.cc b/device/serial/serial_connection_unittest.cc index 84ccf24..7992b49 100644 --- a/device/serial/serial_connection_unittest.cc +++ b/device/serial/serial_connection_unittest.cc
@@ -70,7 +70,7 @@ new SerialConnectionFactory( base::Bind(&SerialConnectionTest::CreateIoHandler, base::Unretained(this)), - base::MessageLoopProxy::current()), + base::ThreadTaskRunnerHandle::Get()), scoped_ptr<SerialDeviceEnumerator>(new FakeSerialDeviceEnumerator)), &service); service.set_error_handler(this);
diff --git a/device/serial/serial_device_enumerator_win.h b/device/serial/serial_device_enumerator_win.h index b1a8f16..541a2bf 100644 --- a/device/serial/serial_device_enumerator_win.h +++ b/device/serial/serial_device_enumerator_win.h
@@ -13,10 +13,10 @@ class SerialDeviceEnumeratorWin : public SerialDeviceEnumerator { public: SerialDeviceEnumeratorWin(); - virtual ~SerialDeviceEnumeratorWin(); + ~SerialDeviceEnumeratorWin() override; // Implementation for SerialDeviceEnumerator. - virtual mojo::Array<serial::DeviceInfoPtr> GetDevices() override; + mojo::Array<serial::DeviceInfoPtr> GetDevices() override; private: DISALLOW_COPY_AND_ASSIGN(SerialDeviceEnumeratorWin);
diff --git a/device/serial/serial_io_handler.cc b/device/serial/serial_io_handler.cc index 288e761..4a244b1 100644 --- a/device/serial/serial_io_handler.cc +++ b/device/serial/serial_io_handler.cc
@@ -12,10 +12,10 @@ namespace device { SerialIoHandler::SerialIoHandler( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop) - : file_thread_message_loop_(file_thread_message_loop), - ui_thread_message_loop_(ui_thread_message_loop) { + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) + : file_thread_task_runner_(file_thread_task_runner), + ui_thread_task_runner_(ui_thread_task_runner) { options_.bitrate = 9600; options_.data_bits = serial::DATA_BITS_EIGHT; options_.parity_bit = serial::PARITY_BIT_NO; @@ -35,16 +35,16 @@ DCHECK(CalledOnValidThread()); DCHECK(open_complete_.is_null()); open_complete_ = callback; - DCHECK(file_thread_message_loop_.get()); - DCHECK(ui_thread_message_loop_.get()); + DCHECK(file_thread_task_runner_.get()); + DCHECK(ui_thread_task_runner_.get()); MergeConnectionOptions(options); - RequestAccess(port, file_thread_message_loop_, ui_thread_message_loop_); + RequestAccess(port, file_thread_task_runner_, ui_thread_task_runner_); } void SerialIoHandler::RequestAccess( const std::string& port, - scoped_refptr<base::MessageLoopProxy> file_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_message_loop) { + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { OnRequestAccessComplete(port, true /* success */); } @@ -52,13 +52,10 @@ bool success) { DCHECK(CalledOnValidThread()); if (success) { - DCHECK(file_thread_message_loop_.get()); - file_thread_message_loop_->PostTask( - FROM_HERE, - base::Bind(&SerialIoHandler::StartOpen, - this, - port, - base::MessageLoopProxy::current())); + DCHECK(file_thread_task_runner_.get()); + file_thread_task_runner_->PostTask( + FROM_HERE, base::Bind(&SerialIoHandler::StartOpen, this, port, + base::ThreadTaskRunnerHandle::Get())); return; } else { DCHECK(!open_complete_.is_null()); @@ -91,9 +88,9 @@ void SerialIoHandler::StartOpen( const std::string& port, - scoped_refptr<base::MessageLoopProxy> io_message_loop) { + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) { DCHECK(!open_complete_.is_null()); - DCHECK(file_thread_message_loop_->RunsTasksOnCurrentThread()); + DCHECK(file_thread_task_runner_->RunsTasksOnCurrentThread()); DCHECK(!file_.IsValid()); // It's the responsibility of the API wrapper around SerialIoHandler to // validate the supplied path against the set of valid port names, and @@ -105,9 +102,8 @@ base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_ASYNC | base::File::FLAG_TERMINAL_DEVICE; base::File file(path, flags); - io_message_loop->PostTask( - FROM_HERE, - base::Bind(&SerialIoHandler::FinishOpen, this, Passed(file.Pass()))); + io_task_runner->PostTask(FROM_HERE, base::Bind(&SerialIoHandler::FinishOpen, + this, Passed(file.Pass()))); } void SerialIoHandler::FinishOpen(base::File file) { @@ -139,8 +135,8 @@ void SerialIoHandler::Close() { if (file_.IsValid()) { - DCHECK(file_thread_message_loop_.get()); - file_thread_message_loop_->PostTask( + DCHECK(file_thread_task_runner_.get()); + file_thread_task_runner_->PostTask( FROM_HERE, base::Bind(&SerialIoHandler::DoClose, Passed(file_.Pass()))); } }
diff --git a/device/serial/serial_io_handler.h b/device/serial/serial_io_handler.h index 5f93d632..1b2a8c4 100644 --- a/device/serial/serial_io_handler.h +++ b/device/serial/serial_io_handler.h
@@ -8,7 +8,8 @@ #include "base/callback.h" #include "base/files/file.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop_proxy.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" #include "base/threading/non_thread_safe.h" #include "device/serial/buffer.h" #include "device/serial/serial.mojom.h" @@ -24,8 +25,8 @@ public: // Constructs an instance of some platform-specific subclass. static scoped_refptr<SerialIoHandler> Create( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop); + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); typedef base::Callback<void(bool success)> OpenCompleteCallback; @@ -84,8 +85,8 @@ protected: explicit SerialIoHandler( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop); + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); virtual ~SerialIoHandler(); // Performs a platform-specific read operation. This must guarantee that @@ -114,8 +115,8 @@ // Requests access to the underlying serial device, if needed. virtual void RequestAccess( const std::string& port, - scoped_refptr<base::MessageLoopProxy> file_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_message_loop); + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); // Performs platform-specific, one-time port configuration on open. virtual bool PostOpen(); @@ -180,7 +181,7 @@ // Continues an Open operation on the FILE thread. void StartOpen(const std::string& port, - scoped_refptr<base::MessageLoopProxy> io_message_loop); + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner); // Finalizes an Open operation (continued from StartOpen) on the IO thread. void FinishOpen(base::File file); @@ -208,9 +209,9 @@ // Callback to handle the completion of a pending Open() request. OpenCompleteCallback open_complete_; - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop_; + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner_; // On Chrome OS, PermissionBrokerClient should be called on the UI thread. - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop_; + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_; DISALLOW_COPY_AND_ASSIGN(SerialIoHandler); };
diff --git a/device/serial/serial_io_handler_posix.cc b/device/serial/serial_io_handler_posix.cc index 5b3b335..471b0b8 100644 --- a/device/serial/serial_io_handler_posix.cc +++ b/device/serial/serial_io_handler_posix.cc
@@ -129,16 +129,16 @@ // static scoped_refptr<SerialIoHandler> SerialIoHandler::Create( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop) { - return new SerialIoHandlerPosix(file_thread_message_loop, - ui_thread_message_loop); + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) { + return new SerialIoHandlerPosix(file_thread_task_runner, + ui_thread_task_runner); } void SerialIoHandlerPosix::RequestAccess( const std::string& port, - scoped_refptr<base::MessageLoopProxy> file_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_message_loop) { + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) { #if defined(OS_LINUX) && defined(OS_CHROMEOS) if (base::SysInfo::IsRunningOnChromeOS()) { chromeos::PermissionBrokerClient* client = @@ -149,13 +149,11 @@ return; } // PermissionBrokerClient should be called on the UI thread. - ui_message_loop->PostTask( + ui_task_runner->PostTask( FROM_HERE, base::Bind( &chromeos::PermissionBrokerClient::RequestPathAccess, - base::Unretained(client), - port, - -1, + base::Unretained(client), port, -1, base::Bind(&SerialIoHandler::OnRequestAccessComplete, this, port))); } else { OnRequestAccessComplete(port, true /* success */); @@ -279,9 +277,9 @@ } SerialIoHandlerPosix::SerialIoHandlerPosix( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop) - : SerialIoHandler(file_thread_message_loop, ui_thread_message_loop), + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) + : SerialIoHandler(file_thread_task_runner, ui_thread_task_runner), is_watching_reads_(false), is_watching_writes_(false) { }
diff --git a/device/serial/serial_io_handler_posix.h b/device/serial/serial_io_handler_posix.h index a124cf0..9a5b832 100644 --- a/device/serial/serial_io_handler_posix.h +++ b/device/serial/serial_io_handler_posix.h
@@ -6,6 +6,8 @@ #define DEVICE_SERIAL_SERIAL_IO_HANDLER_POSIX_H_ #include "base/message_loop/message_loop.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" #include "device/serial/serial_io_handler.h" namespace device { @@ -26,15 +28,15 @@ serial::ConnectionInfoPtr GetPortInfo() const override; void RequestAccess( const std::string& port, - scoped_refptr<base::MessageLoopProxy> file_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_message_loop) override; + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) override; private: friend class SerialIoHandler; SerialIoHandlerPosix( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop); + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); ~SerialIoHandlerPosix() override; // base::MessageLoopForIO::Watcher implementation.
diff --git a/device/serial/serial_io_handler_win.cc b/device/serial/serial_io_handler_win.cc index 40f5023..d6bddb2 100644 --- a/device/serial/serial_io_handler_win.cc +++ b/device/serial/serial_io_handler_win.cc
@@ -134,10 +134,9 @@ // static scoped_refptr<SerialIoHandler> SerialIoHandler::Create( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop) { - return new SerialIoHandlerWin(file_thread_message_loop, - ui_thread_message_loop); + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) { + return new SerialIoHandlerWin(file_thread_task_runner, ui_thread_task_runner); } bool SerialIoHandlerWin::PostOpen() { @@ -275,9 +274,9 @@ } SerialIoHandlerWin::SerialIoHandlerWin( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop) - : SerialIoHandler(file_thread_message_loop, ui_thread_message_loop), + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) + : SerialIoHandler(file_thread_task_runner, ui_thread_task_runner), event_mask_(0), is_comm_pending_(false) { }
diff --git a/device/serial/serial_io_handler_win.h b/device/serial/serial_io_handler_win.h index 6cdbedc0..d2c14212 100644 --- a/device/serial/serial_io_handler_win.h +++ b/device/serial/serial_io_handler_win.h
@@ -7,6 +7,8 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" #include "device/serial/serial_io_handler.h" namespace device { @@ -15,30 +17,30 @@ public base::MessageLoopForIO::IOHandler { protected: // SerialIoHandler implementation. - virtual void ReadImpl() override; - virtual void WriteImpl() override; - virtual void CancelReadImpl() override; - virtual void CancelWriteImpl() override; - virtual bool ConfigurePortImpl() override; - virtual bool Flush() const override; - virtual serial::DeviceControlSignalsPtr GetControlSignals() const override; - virtual bool SetControlSignals( + void ReadImpl() override; + void WriteImpl() override; + void CancelReadImpl() override; + void CancelWriteImpl() override; + bool ConfigurePortImpl() override; + bool Flush() const override; + serial::DeviceControlSignalsPtr GetControlSignals() const override; + bool SetControlSignals( const serial::HostControlSignals& control_signals) override; - virtual serial::ConnectionInfoPtr GetPortInfo() const override; - virtual bool PostOpen() override; + serial::ConnectionInfoPtr GetPortInfo() const override; + bool PostOpen() override; private: friend class SerialIoHandler; explicit SerialIoHandlerWin( - scoped_refptr<base::MessageLoopProxy> file_thread_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_thread_message_loop); - virtual ~SerialIoHandlerWin(); + scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner); + ~SerialIoHandlerWin() override; // base::MessageLoopForIO::IOHandler implementation. - virtual void OnIOCompleted(base::MessageLoopForIO::IOContext* context, - DWORD bytes_transfered, - DWORD error) override; + void OnIOCompleted(base::MessageLoopForIO::IOContext* context, + DWORD bytes_transfered, + DWORD error) override; // Context used for asynchronous WaitCommEvent calls. scoped_ptr<base::MessageLoopForIO::IOContext> comm_context_;
diff --git a/device/serial/serial_service_impl.cc b/device/serial/serial_service_impl.cc index 5fc886df..22734c8 100644 --- a/device/serial/serial_service_impl.cc +++ b/device/serial/serial_service_impl.cc
@@ -27,28 +27,26 @@ // static void SerialServiceImpl::Create( - scoped_refptr<base::MessageLoopProxy> io_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_message_loop, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, mojo::InterfaceRequest<serial::SerialService> request) { - mojo::BindToRequest(new SerialServiceImpl(new SerialConnectionFactory( - base::Bind(SerialIoHandler::Create, - base::MessageLoopProxy::current(), - ui_message_loop), - io_message_loop)), - &request); + mojo::BindToRequest( + new SerialServiceImpl(new SerialConnectionFactory( + base::Bind(SerialIoHandler::Create, + base::ThreadTaskRunnerHandle::Get(), ui_task_runner), + io_task_runner)), + &request); } // static void SerialServiceImpl::CreateOnMessageLoop( - scoped_refptr<base::MessageLoopProxy> message_loop, - scoped_refptr<base::MessageLoopProxy> io_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_message_loop, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, mojo::InterfaceRequest<serial::SerialService> request) { - message_loop->PostTask(FROM_HERE, - base::Bind(&SerialServiceImpl::Create, - io_message_loop, - ui_message_loop, - base::Passed(&request))); + task_runner->PostTask(FROM_HERE, + base::Bind(&SerialServiceImpl::Create, io_task_runner, + ui_task_runner, base::Passed(&request))); } void SerialServiceImpl::GetDevices(
diff --git a/device/serial/serial_service_impl.h b/device/serial/serial_service_impl.h index b6387a8..9ac5a10 100644 --- a/device/serial/serial_service_impl.h +++ b/device/serial/serial_service_impl.h
@@ -6,7 +6,8 @@ #define DEVICE_SERIAL_SERIAL_SERVICE_IMPL_H_ #include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop_proxy.h" +#include "base/single_thread_task_runner.h" +#include "base/thread_task_runner_handle.h" #include "device/serial/data_stream.mojom.h" #include "device/serial/serial.mojom.h" #include "device/serial/serial_connection_factory.h" @@ -23,13 +24,13 @@ scoped_ptr<SerialDeviceEnumerator> device_enumerator); ~SerialServiceImpl() override; - static void Create(scoped_refptr<base::MessageLoopProxy> io_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_message_loop, + static void Create(scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, mojo::InterfaceRequest<serial::SerialService> request); static void CreateOnMessageLoop( - scoped_refptr<base::MessageLoopProxy> message_loop, - scoped_refptr<base::MessageLoopProxy> io_message_loop, - scoped_refptr<base::MessageLoopProxy> ui_message_loop, + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, + scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, mojo::InterfaceRequest<serial::SerialService> request); // mojo::InterfaceImpl<SerialService> overrides.
diff --git a/device/serial/serial_service_unittest.cc b/device/serial/serial_service_unittest.cc index 265b0b5..a996cd87 100644 --- a/device/serial/serial_service_unittest.cc +++ b/device/serial/serial_service_unittest.cc
@@ -79,7 +79,7 @@ new SerialConnectionFactory( base::Bind(&SerialServiceTest::ReturnIoHandler, base::Unretained(this)), - base::MessageLoopProxy::current()), + base::ThreadTaskRunnerHandle::Get()), scoped_ptr<SerialDeviceEnumerator>(new FakeSerialDeviceEnumerator)), &service); mojo::InterfacePtr<serial::Connection> connection;
diff --git a/extensions/DEPS b/extensions/DEPS index a5faa35..285b7d3 100644 --- a/extensions/DEPS +++ b/extensions/DEPS
@@ -1,5 +1,6 @@ include_rules = [ # Do not add Chrome dependencies. Much work went into removing them. + "+components/browsing_data", "+components/crx_file", "+components/url_matcher", "-content",
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index 9ecb71e..6a643160 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -44,6 +44,7 @@ "//extensions") deps += [ + "//components/browsing_data", "//components/onc", "//components/storage_monitor", "//components/update_client",
diff --git a/extensions/browser/api/device_permissions_prompt.cc b/extensions/browser/api/device_permissions_prompt.cc index 09751b36..6e630456 100644 --- a/extensions/browser/api/device_permissions_prompt.cc +++ b/extensions/browser/api/device_permissions_prompt.cc
@@ -4,10 +4,9 @@ #include "extensions/browser/api/device_permissions_prompt.h" -#include "base/barrier_closure.h" +#include "base/scoped_observer.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "content/public/browser/browser_thread.h" #include "device/core/device_client.h" #include "device/usb/usb_device.h" #include "device/usb/usb_device_filter.h" @@ -18,49 +17,167 @@ #include "extensions/strings/grit/extensions_strings.h" #include "ui/base/l10n/l10n_util.h" -using content::BrowserThread; using device::UsbDevice; using device::UsbDeviceFilter; using device::UsbService; namespace extensions { -DevicePermissionsPrompt::Delegate::~Delegate() { -} +namespace { -DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo( - scoped_refptr<UsbDevice> device) - : device(device) { - base::string16 manufacturer_string = device->manufacturer_string(); - if (manufacturer_string.empty()) { - const char* vendor_name = - device::UsbIds::GetVendorName(device->vendor_id()); - if (vendor_name) { - manufacturer_string = base::UTF8ToUTF16(vendor_name); - } else { - base::string16 vendor_id = - base::ASCIIToUTF16(base::StringPrintf("0x%04x", device->vendor_id())); - manufacturer_string = - l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_VENDOR, vendor_id); +class UsbDeviceInfo : public DevicePermissionsPrompt::Prompt::DeviceInfo { + public: + UsbDeviceInfo(scoped_refptr<UsbDevice> device) : device_(device) { + base::string16 manufacturer_string = device->manufacturer_string(); + if (manufacturer_string.empty()) { + const char* vendor_name = + device::UsbIds::GetVendorName(device->vendor_id()); + if (vendor_name) { + manufacturer_string = base::UTF8ToUTF16(vendor_name); + } else { + base::string16 vendor_id = base::ASCIIToUTF16( + base::StringPrintf("0x%04x", device->vendor_id())); + manufacturer_string = + l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_VENDOR, vendor_id); + } + } + + base::string16 product_string = device->product_string(); + if (product_string.empty()) { + const char* product_name = device::UsbIds::GetProductName( + device->vendor_id(), device->product_id()); + if (product_name) { + product_string = base::UTF8ToUTF16(product_name); + } else { + base::string16 product_id = base::ASCIIToUTF16( + base::StringPrintf("0x%04x", device->product_id())); + product_string = + l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_PRODUCT, product_id); + } + } + + name_ = l10n_util::GetStringFUTF16(IDS_DEVICE_PERMISSIONS_DEVICE_NAME, + product_string, manufacturer_string); + serial_number_ = device->serial_number(); + } + + ~UsbDeviceInfo() override {} + + const scoped_refptr<UsbDevice>& device() const { return device_; } + + private: + // TODO(reillyg): Convert this to a weak reference when UsbDevice has a + // connected flag. + scoped_refptr<UsbDevice> device_; +}; + +class UsbDevicePermissionsPrompt : public DevicePermissionsPrompt::Prompt, + public device::UsbService::Observer { + public: + UsbDevicePermissionsPrompt( + const Extension* extension, + content::BrowserContext* context, + bool multiple, + const std::vector<device::UsbDeviceFilter>& filters, + const DevicePermissionsPrompt::UsbDevicesCallback& callback) + : Prompt(extension, context, multiple), + filters_(filters), + callback_(callback), + service_observer_(this) {} + + private: + ~UsbDevicePermissionsPrompt() override {} + + // DevicePermissionsPrompt::Prompt implementation: + void SetObserver( + DevicePermissionsPrompt::Prompt::Observer* observer) override { + DevicePermissionsPrompt::Prompt::SetObserver(observer); + + if (observer) { + UsbService* service = device::DeviceClient::Get()->GetUsbService(); + if (service && !service_observer_.IsObserving(service)) { + service->GetDevices( + base::Bind(&UsbDevicePermissionsPrompt::OnDevicesEnumerated, this)); + service_observer_.Add(service); + } } } - base::string16 product_string = device->product_string(); - if (product_string.empty()) { - const char* product_name = device::UsbIds::GetProductName( - device->vendor_id(), device->product_id()); - if (product_name) { - product_string = base::UTF8ToUTF16(product_name); - } else { - base::string16 product_id = base::ASCIIToUTF16( - base::StringPrintf("0x%04x", device->product_id())); - product_string = - l10n_util::GetStringFUTF16(IDS_DEVICE_UNKNOWN_PRODUCT, product_id); + base::string16 GetHeading() const override { + return l10n_util::GetStringUTF16( + multiple() ? IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE_MULTIPLE + : IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE_SINGLE); + } + + void Dismissed() override { + DevicePermissionsManager* permissions_manager = + DevicePermissionsManager::Get(browser_context()); + std::vector<scoped_refptr<UsbDevice>> devices; + for (const DeviceInfo* device : devices_) { + if (device->granted()) { + const UsbDeviceInfo* usb_device = + static_cast<const UsbDeviceInfo*>(device); + devices.push_back(usb_device->device()); + if (permissions_manager) { + permissions_manager->AllowUsbDevice(extension()->id(), + usb_device->device()); + } + } + } + DCHECK(multiple() || devices.size() <= 1); + callback_.Run(devices); + callback_.Reset(); + } + + // device::UsbService::Observer implementation: + void OnDeviceAdded(scoped_refptr<UsbDevice> device) override { + if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) { + return; + } + + device->CheckUsbAccess(base::Bind( + &UsbDevicePermissionsPrompt::AddCheckedDevice, this, device)); + } + + void OnDeviceRemoved(scoped_refptr<UsbDevice> device) override { + for (auto it = devices_.begin(); it != devices_.end(); ++it) { + const UsbDeviceInfo* entry = static_cast<const UsbDeviceInfo*>(*it); + if (entry->device() == device) { + devices_.erase(it); + if (observer()) { + observer()->OnDevicesChanged(); + } + return; + } } } - name = l10n_util::GetStringFUTF16(IDS_DEVICE_PERMISSIONS_DEVICE_NAME, - product_string, manufacturer_string); + void OnDevicesEnumerated( + const std::vector<scoped_refptr<UsbDevice>>& devices) { + for (const auto& device : devices) { + OnDeviceAdded(device); + } + } + + void AddCheckedDevice(scoped_refptr<UsbDevice> device, bool allowed) { + if (allowed) { + // TODO(reillyg): This method could be called after OnDeviceRemoved. We + // should check that the device is still connected. + devices_.push_back(new UsbDeviceInfo(device)); + if (observer()) { + observer()->OnDevicesChanged(); + } + } + } + + std::vector<UsbDeviceFilter> filters_; + DevicePermissionsPrompt::UsbDevicesCallback callback_; + ScopedObserver<UsbService, UsbService::Observer> service_observer_; +}; + +} // namespace + +DevicePermissionsPrompt::Prompt::DeviceInfo::DeviceInfo() { } DevicePermissionsPrompt::Prompt::DeviceInfo::~DeviceInfo() { @@ -69,32 +186,14 @@ DevicePermissionsPrompt::Prompt::Observer::~Observer() { } -DevicePermissionsPrompt::Prompt::Prompt(Delegate* delegate, - const Extension* extension, - content::BrowserContext* context) - : extension_(extension), - browser_context_(context), - delegate_(delegate), - usb_service_observer_(this) { +DevicePermissionsPrompt::Prompt::Prompt(const Extension* extension, + content::BrowserContext* context, + bool multiple) + : extension_(extension), browser_context_(context), multiple_(multiple) { } void DevicePermissionsPrompt::Prompt::SetObserver(Observer* observer) { observer_ = observer; - - if (observer_) { - UsbService* service = device::DeviceClient::Get()->GetUsbService(); - if (service && !usb_service_observer_.IsObserving(service)) { - service->GetDevices(base::Bind( - &DevicePermissionsPrompt::Prompt::OnDevicesEnumerated, this)); - usb_service_observer_.Add(service); - } - } -} - -base::string16 DevicePermissionsPrompt::Prompt::GetHeading() const { - return l10n_util::GetStringUTF16( - multiple_ ? IDS_DEVICE_PERMISSIONS_PROMPT_TITLE_MULTIPLE - : IDS_DEVICE_PERMISSIONS_PROMPT_TITLE_SINGLE); } base::string16 DevicePermissionsPrompt::Prompt::GetPromptMessage() const { @@ -107,90 +206,23 @@ base::string16 DevicePermissionsPrompt::Prompt::GetDeviceName( size_t index) const { DCHECK_LT(index, devices_.size()); - return devices_[index].name; + return devices_[index]->name(); } base::string16 DevicePermissionsPrompt::Prompt::GetDeviceSerialNumber( size_t index) const { DCHECK_LT(index, devices_.size()); - return devices_[index].device->serial_number(); + return devices_[index]->serial_number(); } void DevicePermissionsPrompt::Prompt::GrantDevicePermission(size_t index) { DCHECK_LT(index, devices_.size()); - devices_[index].granted = true; -} - -void DevicePermissionsPrompt::Prompt::Dismissed() { - DevicePermissionsManager* permissions_manager = - DevicePermissionsManager::Get(browser_context_); - std::vector<scoped_refptr<UsbDevice>> devices; - for (const DeviceInfo& device : devices_) { - if (device.granted) { - devices.push_back(device.device); - if (permissions_manager) { - permissions_manager->AllowUsbDevice(extension_->id(), device.device); - } - } - } - delegate_->OnUsbDevicesChosen(devices); -} - -void DevicePermissionsPrompt::Prompt::set_filters( - const std::vector<UsbDeviceFilter>& filters) { - filters_ = filters; + devices_[index]->set_granted(); } DevicePermissionsPrompt::Prompt::~Prompt() { } -void DevicePermissionsPrompt::Prompt::OnDeviceAdded( - scoped_refptr<UsbDevice> device) { - if (!(filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_))) { - return; - } - - device->CheckUsbAccess(base::Bind( - &DevicePermissionsPrompt::Prompt::AddCheckedUsbDevice, this, device)); -} - -void DevicePermissionsPrompt::Prompt::OnDeviceRemoved( - scoped_refptr<UsbDevice> device) { - bool removed_entry = false; - for (std::vector<DeviceInfo>::iterator it = devices_.begin(); - it != devices_.end(); ++it) { - if (it->device == device) { - devices_.erase(it); - removed_entry = true; - break; - } - } - if (observer_ && removed_entry) { - observer_->OnDevicesChanged(); - } -} - -void DevicePermissionsPrompt::Prompt::OnDevicesEnumerated( - const std::vector<scoped_refptr<UsbDevice>>& devices) { - for (const auto& device : devices) { - if (filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_)) { - device->CheckUsbAccess(base::Bind( - &DevicePermissionsPrompt::Prompt::AddCheckedUsbDevice, this, device)); - } - } -} - -void DevicePermissionsPrompt::Prompt::AddCheckedUsbDevice( - scoped_refptr<UsbDevice> device, - bool allowed) { - if (allowed) { - devices_.push_back(DeviceInfo(device)); - if (observer_) { - observer_->OnDevicesChanged(); - } - } -} - DevicePermissionsPrompt::DevicePermissionsPrompt( content::WebContents* web_contents) : web_contents_(web_contents) { @@ -200,15 +232,13 @@ } void DevicePermissionsPrompt::AskForUsbDevices( - Delegate* delegate, const Extension* extension, content::BrowserContext* context, bool multiple, - const std::vector<UsbDeviceFilter>& filters) { - prompt_ = new Prompt(delegate, extension, context); - prompt_->set_multiple(multiple); - prompt_->set_filters(filters); - + const std::vector<UsbDeviceFilter>& filters, + const UsbDevicesCallback& callback) { + prompt_ = new UsbDevicePermissionsPrompt(extension, context, multiple, + filters, callback); ShowDialog(); }
diff --git a/extensions/browser/api/device_permissions_prompt.h b/extensions/browser/api/device_permissions_prompt.h index 5e93155..6820855 100644 --- a/extensions/browser/api/device_permissions_prompt.h +++ b/extensions/browser/api/device_permissions_prompt.h
@@ -10,11 +10,8 @@ #include "base/callback.h" #include "base/logging.h" #include "base/memory/ref_counted.h" -#include "base/scoped_observer.h" +#include "base/memory/scoped_vector.h" #include "base/strings/string16.h" -#include "content/public/browser/browser_thread.h" -#include "device/usb/usb_device.h" -#include "device/usb/usb_service.h" namespace content { class BrowserContext; @@ -22,6 +19,7 @@ } namespace device { +class UsbDevice; class UsbDeviceFilter; } @@ -33,28 +31,30 @@ // (similar to choosing files). class DevicePermissionsPrompt { public: - class Delegate { - public: - // Called with the list of selected USB devices. - virtual void OnUsbDevicesChosen( - const std::vector<scoped_refptr<device::UsbDevice>>& devices) = 0; - - protected: - virtual ~Delegate(); - }; + using UsbDevicesCallback = base::Callback<void( + const std::vector<scoped_refptr<device::UsbDevice>>&)>; // Context information available to the UI implementation. - class Prompt : public base::RefCounted<Prompt>, - public device::UsbService::Observer { + class Prompt : public base::RefCounted<Prompt> { public: - // Displayed properties of a device. - struct DeviceInfo { - DeviceInfo(scoped_refptr<device::UsbDevice> device); - ~DeviceInfo(); + // This class stores the device information displayed in the UI. It should + // be extended to support particular device types. + class DeviceInfo { + public: + DeviceInfo(); + virtual ~DeviceInfo(); - scoped_refptr<device::UsbDevice> device; - base::string16 name; - bool granted = false; + const base::string16& name() const { return name_; } + const base::string16& serial_number() const { return serial_number_; } + bool granted() const { return granted_; } + void set_granted() { granted_ = true; } + + protected: + base::string16 name_; + base::string16 serial_number_; + + private: + bool granted_ = false; }; // Since the set of devices can change while the UI is visible an @@ -67,14 +67,14 @@ virtual ~Observer(); }; - Prompt(Delegate* delegate, - const Extension* extension, - content::BrowserContext* context); + Prompt(const Extension* extension, + content::BrowserContext* context, + bool multiple); // Only one observer may be registered at a time. - void SetObserver(Observer* observer); + virtual void SetObserver(Observer* observer); - base::string16 GetHeading() const; + virtual base::string16 GetHeading() const = 0; base::string16 GetPromptMessage() const; size_t GetDeviceCount() const { return devices_.size(); } base::string16 GetDeviceName(size_t index) const; @@ -83,46 +83,44 @@ // Notifies the DevicePermissionsManager for the current extension that // access to the device at the given index is now granted. void GrantDevicePermission(size_t index); - void Dismissed(); + virtual void Dismissed() = 0; + + // Allow the user to select multiple devices. bool multiple() const { return multiple_; } - void set_multiple(bool multiple) { multiple_ = multiple; } - void set_filters(const std::vector<device::UsbDeviceFilter>& filters); + protected: + virtual ~Prompt(); + + const Extension* extension() const { return extension_; } + Observer* observer() const { return observer_; } + content::BrowserContext* browser_context() const { + return browser_context_; + } + + // Subclasses may fill this with a particular subclass of DeviceInfo and may + // assume that only that instances of that type are stored here. + ScopedVector<DeviceInfo> devices_; private: friend class base::RefCounted<Prompt>; - virtual ~Prompt(); - - // device::UsbService::Observer implementation: - void OnDeviceAdded(scoped_refptr<device::UsbDevice> device) override; - void OnDeviceRemoved(scoped_refptr<device::UsbDevice> device) override; - - void OnDevicesEnumerated( - const std::vector<scoped_refptr<device::UsbDevice>>& devices); - void AddCheckedUsbDevice(scoped_refptr<device::UsbDevice> device, - bool allowed); - const extensions::Extension* extension_ = nullptr; - content::BrowserContext* browser_context_ = nullptr; - Delegate* delegate_ = nullptr; - bool multiple_ = false; - std::vector<device::UsbDeviceFilter> filters_; - std::vector<DeviceInfo> devices_; Observer* observer_ = nullptr; - ScopedObserver<device::UsbService, device::UsbService::Observer> - usb_service_observer_; + content::BrowserContext* browser_context_ = nullptr; + bool multiple_ = false; + + DISALLOW_COPY_AND_ASSIGN(Prompt); }; DevicePermissionsPrompt(content::WebContents* web_contents); virtual ~DevicePermissionsPrompt(); - void AskForUsbDevices(Delegate* delegate, - const Extension* extension, + void AskForUsbDevices(const Extension* extension, content::BrowserContext* context, bool multiple, - const std::vector<device::UsbDeviceFilter>& filters); + const std::vector<device::UsbDeviceFilter>& filters, + const UsbDevicesCallback& callback); protected: virtual void ShowDialog() = 0; @@ -136,6 +134,8 @@ // Parameters available to the UI implementation. scoped_refptr<Prompt> prompt_; + + DISALLOW_COPY_AND_ASSIGN(DevicePermissionsPrompt); }; } // namespace extensions
diff --git a/extensions/browser/api/guest_view/guest_view_internal_api.cc b/extensions/browser/api/guest_view/guest_view_internal_api.cc index bfe4fb5..aea9c8e 100644 --- a/extensions/browser/api/guest_view/guest_view_internal_api.cc +++ b/extensions/browser/api/guest_view/guest_view_internal_api.cc
@@ -6,12 +6,15 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_base.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/common/api/guest_view_internal.h" #include "extensions/common/guest_view/guest_view_constants.h" #include "extensions/common/permissions/permissions_data.h" +using guestview::GuestViewManagerDelegate; + namespace guest_view_internal = extensions::core_api::guest_view_internal; namespace extensions { @@ -31,6 +34,12 @@ // if we don't already have one. GuestViewManager* guest_view_manager = GuestViewManager::FromBrowserContext(browser_context()); + if (!guest_view_manager) { + guest_view_manager = GuestViewManager::CreateWithDelegate( + browser_context(), + scoped_ptr<GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate(context_))); + } GuestViewManager::WebContentsCreatedCallback callback = base::Bind(&GuestViewInternalCreateGuestFunction::CreateGuestCallback,
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc index 12e9686..0627e78 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
@@ -20,9 +20,6 @@ #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/user_script.h" -#include "net/base/load_flags.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_fetcher_delegate.h" #include "third_party/WebKit/public/web/WebFindOptions.h" using content::WebContents; @@ -177,6 +174,14 @@ } } + // code: + if (script_value.code) { + extensions::UserScript::File file((base::FilePath()), (base::FilePath()), + GURL()); + file.set_content(*(script_value.code.get())); + script->js_scripts().push_back(file); + } + // all_frames: if (script_value.all_frames) script->set_match_all_frames(*(script_value.all_frames)); @@ -236,51 +241,6 @@ namespace extensions { -// WebUIURLFetcher downloads the content of a file by giving its |url| on WebUI. -// Each WebUIURLFetcher is associated with a given |render_process_id, -// render_view_id| pair. -class WebViewInternalExecuteCodeFunction::WebUIURLFetcher - : public net::URLFetcherDelegate { - public: - WebUIURLFetcher( - content::BrowserContext* context, - const WebViewInternalExecuteCodeFunction::WebUILoadFileCallback& callback) - : context_(context), callback_(callback) {} - ~WebUIURLFetcher() override {} - - void Start(int render_process_id, int render_view_id, const GURL& url) { - fetcher_.reset(net::URLFetcher::Create(url, net::URLFetcher::GET, this)); - fetcher_->SetRequestContext(context_->GetRequestContext()); - fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); - - content::AssociateURLFetcherWithRenderFrame( - fetcher_.get(), url, render_process_id, render_view_id); - fetcher_->Start(); - } - - private: - // net::URLFetcherDelegate: - void OnURLFetchComplete(const net::URLFetcher* source) override { - CHECK_EQ(fetcher_.get(), source); - - std::string data; - bool result = false; - if (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS) { - result = fetcher_->GetResponseAsString(&data); - DCHECK(result); - } - fetcher_.reset(); - callback_.Run(result, data); - callback_.Reset(); - } - - content::BrowserContext* context_; - WebViewInternalExecuteCodeFunction::WebUILoadFileCallback callback_; - scoped_ptr<net::URLFetcher> fetcher_; - - DISALLOW_COPY_AND_ASSIGN(WebUIURLFetcher); -}; - bool WebViewInternalExtensionFunction::RunAsync() { int instance_id = 0; EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &instance_id)); @@ -379,7 +339,7 @@ bool WebViewInternalExecuteCodeFunction::LoadFileForWebUI( const std::string& file_src, - const WebUILoadFileCallback& callback) { + const WebUIURLFetcher::WebUILoadFileCallback& callback) { if (!render_view_host() || !render_view_host()->GetProcess()) return false; WebViewGuest* guest = WebViewGuest::From( @@ -390,9 +350,10 @@ GURL owner_base_url(guest->GetOwnerSiteURL().GetWithEmptyPath()); GURL file_url(owner_base_url.Resolve(file_src)); - url_fetcher_.reset(new WebUIURLFetcher(this->browser_context(), callback)); - url_fetcher_->Start(render_view_host()->GetProcess()->GetID(), - render_view_host()->GetRoutingID(), file_url); + url_fetcher_.reset(new WebUIURLFetcher( + this->browser_context(), render_view_host()->GetProcess()->GetID(), + render_view_host()->GetRoutingID(), file_url, callback)); + url_fetcher_->Start(); return true; } @@ -465,8 +426,9 @@ WebViewContentScriptManager::Get(browser_context()); DCHECK(manager); - manager->AddContentScripts(sender_web_contents, params->instance_id, host_id, - result); + manager->AddContentScripts(sender_web_contents, + render_view_host()->GetRoutingID(), + params->instance_id, host_id, result); return RespondNow(NoArguments()); }
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h index 373abcec..f9b5143d 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h
@@ -8,6 +8,7 @@ #include "extensions/browser/api/capture_web_contents_function.h" #include "extensions/browser/api/execute_code_function.h" #include "extensions/browser/extension_function.h" +#include "extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" // WARNING: WebViewInternal could be loaded in an unblessed context, thus any @@ -54,11 +55,6 @@ : public extensions::ExecuteCodeFunction { public: WebViewInternalExecuteCodeFunction(); - // Called when a file URL request is complete. - // Parameters: - // - whether the request is success. - // - If yes, the content of the file. - using WebUILoadFileCallback = base::Callback<void(bool, const std::string&)>; protected: ~WebViewInternalExecuteCodeFunction() override; @@ -74,11 +70,9 @@ bool LoadFile(const std::string& file) override; private: - class WebUIURLFetcher; - // Loads a file url on WebUI. bool LoadFileForWebUI(const std::string& file_src, - const WebUILoadFileCallback& callback); + const WebUIURLFetcher::WebUILoadFileCallback& callback); // Contains extension resource built from path of file which is // specified in JSON arguments.
diff --git a/extensions/browser/api/socket/socket_api.h b/extensions/browser/api/socket/socket_api.h index a3e4e0e..d6e4736 100644 --- a/extensions/browser/api/socket/socket_api.h +++ b/extensions/browser/api/socket/socket_api.h
@@ -62,7 +62,7 @@ public: SocketResourceManager() : manager_(NULL) {} - virtual bool SetBrowserContext(content::BrowserContext* context) override { + bool SetBrowserContext(content::BrowserContext* context) override { manager_ = ApiResourceManager<T>::Get(context); DCHECK(manager_) << "There is no socket manager. " @@ -72,29 +72,27 @@ return manager_ != NULL; } - virtual int Add(Socket* socket) override { + int Add(Socket* socket) override { // Note: Cast needed here, because "T" may be a subclass of "Socket". return manager_->Add(static_cast<T*>(socket)); } - virtual Socket* Get(const std::string& extension_id, - int api_resource_id) override { + Socket* Get(const std::string& extension_id, int api_resource_id) override { return manager_->Get(extension_id, api_resource_id); } - virtual void Replace(const std::string& extension_id, - int api_resource_id, - Socket* socket) override { + void Replace(const std::string& extension_id, + int api_resource_id, + Socket* socket) override { manager_->Replace(extension_id, api_resource_id, static_cast<T*>(socket)); } - virtual void Remove(const std::string& extension_id, - int api_resource_id) override { + void Remove(const std::string& extension_id, int api_resource_id) override { manager_->Remove(extension_id, api_resource_id); } - virtual base::hash_set<int>* GetResourceIds(const std::string& extension_id) - override { + base::hash_set<int>* GetResourceIds( + const std::string& extension_id) override { return manager_->GetResourceIds(extension_id); }
diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc index d0238130..0e33ca5 100644 --- a/extensions/browser/api/usb/usb_api.cc +++ b/extensions/browser/api/usb/usb_api.cc
@@ -641,13 +641,13 @@ return RespondNow(Error(kErrorNotSupported)); } - AddRef(); prompt_->AskForUsbDevices( - this, extension(), browser_context(), multiple, filters); + extension(), browser_context(), multiple, filters, + base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen, this)); return RespondLater(); } -void UsbGetUserSelectedDevicesFunction::OnUsbDevicesChosen( +void UsbGetUserSelectedDevicesFunction::OnDevicesChosen( const std::vector<scoped_refptr<UsbDevice>>& devices) { scoped_ptr<base::ListValue> result(new base::ListValue()); for (const auto& device : devices) { @@ -655,7 +655,6 @@ } Respond(OneArgument(result.release())); - Release(); } UsbRequestAccessFunction::UsbRequestAccessFunction() {
diff --git a/extensions/browser/api/usb/usb_api.h b/extensions/browser/api/usb/usb_api.h index c7ab6c3..c06c5577 100644 --- a/extensions/browser/api/usb/usb_api.h +++ b/extensions/browser/api/usb/usb_api.h
@@ -14,7 +14,6 @@ #include "device/usb/usb_device_filter.h" #include "device/usb/usb_device_handle.h" #include "extensions/browser/api/api_resource_manager.h" -#include "extensions/browser/api/device_permissions_prompt.h" #include "extensions/browser/extension_function.h" #include "extensions/common/api/usb.h" #include "net/base/io_buffer.h" @@ -23,6 +22,7 @@ class DevicePermissionEntry; class DevicePermissions; +class DevicePermissionsPrompt; class DevicePermissionsManager; class UsbDeviceResource; @@ -108,9 +108,7 @@ DISALLOW_COPY_AND_ASSIGN(UsbGetDevicesFunction); }; -class UsbGetUserSelectedDevicesFunction - : public UIThreadExtensionFunction, - public DevicePermissionsPrompt::Delegate { +class UsbGetUserSelectedDevicesFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("usb.getUserSelectedDevices", USB_GETUSERSELECTEDDEVICES) @@ -123,8 +121,8 @@ // ExtensionFunction: ResponseAction Run() override; - void OnUsbDevicesChosen( - const std::vector<scoped_refptr<device::UsbDevice>>& devices) override; + void OnDevicesChosen( + const std::vector<scoped_refptr<device::UsbDevice>>& devices); scoped_ptr<DevicePermissionsPrompt> prompt_;
diff --git a/extensions/browser/api/usb/usb_apitest.cc b/extensions/browser/api/usb/usb_apitest.cc index affc1076..a1bdc83 100644 --- a/extensions/browser/api/usb/usb_apitest.cc +++ b/extensions/browser/api/usb/usb_apitest.cc
@@ -130,9 +130,7 @@ int alternate_setting, const ResultCallback& callback)); - virtual scoped_refptr<UsbDevice> GetDevice() const override { - return device_; - } + scoped_refptr<UsbDevice> GetDevice() const override { return device_; } void set_device(UsbDevice* device) { device_ = device; }
diff --git a/extensions/browser/app_sorting.h b/extensions/browser/app_sorting.h index 39d50dc..bc6378db3 100644 --- a/extensions/browser/app_sorting.h +++ b/extensions/browser/app_sorting.h
@@ -27,11 +27,17 @@ // caller. virtual void SetExtensionScopedPrefs(ExtensionScopedPrefs* prefs) = 0; + // CHECKs that SetExtensionScopedPrefs has been called with a non-null object. + // TODO(mgiuca): Added this to try and diagnose http://crbug.com/476648. + // Remove it after the investigation is concluded. + virtual void CheckExtensionScopedPrefs() const = 0; + // Sets up the ExtensionSyncService to inform of changes that require syncing. virtual void SetExtensionSyncService( ExtensionSyncService* extension_sync_service) = 0; // Properly initializes internal values that require |extension_ids|. + // SetExtensionScopedPrefs must have been called prior to this. virtual void Initialize(const extensions::ExtensionIdList& extension_ids) = 0; // Resolves any conflicts the might be created as a result of syncing that
diff --git a/extensions/browser/app_window/app_window.cc b/extensions/browser/app_window/app_window.cc index 5ca80d4..64fa3c3 100644 --- a/extensions/browser/app_window/app_window.cc +++ b/extensions/browser/app_window/app_window.cc
@@ -955,6 +955,12 @@ return IsHtmlApiFullscreen(); } +blink::WebDisplayMode AppWindow::GetDisplayMode( + const content::WebContents* source) const { + return IsFullscreen() ? blink::WebDisplayModeFullscreen + : blink::WebDisplayModeStandalone; +} + void AppWindow::OnExtensionUnloaded(BrowserContext* browser_context, const Extension* extension, UnloadedExtensionInfo::Reason reason) {
diff --git a/extensions/browser/app_window/app_window.h b/extensions/browser/app_window/app_window.h index df6b248..10baa0e 100644 --- a/extensions/browser/app_window/app_window.h +++ b/extensions/browser/app_window/app_window.h
@@ -382,6 +382,8 @@ void ExitFullscreenModeForTab(content::WebContents* source) override; bool IsFullscreenForTabOrPending( const content::WebContents* source) const override; + blink::WebDisplayMode GetDisplayMode( + const content::WebContents* source) const override; void RequestMediaAccessPermission( content::WebContents* web_contents, const content::MediaStreamRequest& request,
diff --git a/extensions/browser/browser_context_keyed_api_factory.h b/extensions/browser/browser_context_keyed_api_factory.h index d79c314..dfd2887 100644 --- a/extensions/browser/browser_context_keyed_api_factory.h +++ b/extensions/browser/browser_context_keyed_api_factory.h
@@ -98,7 +98,7 @@ DeclareFactoryDependencies(); } - virtual ~BrowserContextKeyedAPIFactory() {} + ~BrowserContextKeyedAPIFactory() override {} private: // BrowserContextKeyedServiceFactory implementation. @@ -109,7 +109,7 @@ // BrowserContextKeyedBaseFactory implementation. // These can be effectively overridden with template specializations. - virtual content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* GetBrowserContextToUse( content::BrowserContext* context) const override { if (T::kServiceRedirectedInIncognito) return ExtensionsBrowserClient::Get()->GetOriginalContext(context); @@ -120,11 +120,11 @@ return BrowserContextKeyedServiceFactory::GetBrowserContextToUse(context); } - virtual bool ServiceIsCreatedWithBrowserContext() const override { + bool ServiceIsCreatedWithBrowserContext() const override { return T::kServiceIsCreatedWithBrowserContext; } - virtual bool ServiceIsNULLWhileTesting() const override { + bool ServiceIsNULLWhileTesting() const override { return T::kServiceIsNULLWhileTesting; }
diff --git a/extensions/browser/declarative_user_script_master.cc b/extensions/browser/declarative_user_script_master.cc index 130e9ba4..68fc0c6 100644 --- a/extensions/browser/declarative_user_script_master.cc +++ b/extensions/browser/declarative_user_script_master.cc
@@ -4,19 +4,28 @@ #include "extensions/browser/declarative_user_script_master.h" -#include <set> - #include "content/public/browser/browser_context.h" +#include "extensions/browser/extension_user_script_loader.h" +#include "extensions/browser/user_script_loader.h" +#include "extensions/browser/web_ui_user_script_loader.h" +#include "extensions/common/user_script.h" namespace extensions { DeclarativeUserScriptMaster::DeclarativeUserScriptMaster( content::BrowserContext* browser_context, const HostID& host_id) - : host_id_(host_id), - loader_(browser_context, - host_id, - false /* listen_for_extension_system_loaded */) { + : host_id_(host_id) { + switch (host_id_.type()) { + case HostID::EXTENSIONS: + loader_.reset(new ExtensionUserScriptLoader( + browser_context, host_id, + false /* listen_for_extension_system_loaded */)); + break; + case HostID::WEBUI: + loader_.reset(new WebUIUserScriptLoader(browser_context, host_id)); + break; + } } DeclarativeUserScriptMaster::~DeclarativeUserScriptMaster() { @@ -25,27 +34,29 @@ void DeclarativeUserScriptMaster::AddScript(const UserScript& script) { std::set<UserScript> set; set.insert(script); - loader_.AddScripts(set); + loader_->AddScripts(set); } void DeclarativeUserScriptMaster::AddScripts( - const std::set<UserScript>& scripts) { - loader_.AddScripts(scripts); + const std::set<UserScript>& scripts, + int render_process_id, + int render_view_id) { + loader_->AddScripts(scripts, render_process_id, render_view_id); } void DeclarativeUserScriptMaster::RemoveScript(const UserScript& script) { std::set<UserScript> set; set.insert(script); - loader_.RemoveScripts(set); + loader_->RemoveScripts(set); } void DeclarativeUserScriptMaster::RemoveScripts( const std::set<UserScript>& scripts) { - loader_.RemoveScripts(scripts); + loader_->RemoveScripts(scripts); } void DeclarativeUserScriptMaster::ClearScripts() { - loader_.ClearScripts(); + loader_->ClearScripts(); } } // namespace extensions
diff --git a/extensions/browser/declarative_user_script_master.h b/extensions/browser/declarative_user_script_master.h index f573039..55c94f5e 100644 --- a/extensions/browser/declarative_user_script_master.h +++ b/extensions/browser/declarative_user_script_master.h
@@ -5,8 +5,11 @@ #ifndef EXTENSIONS_BROWSER_DECLARATIVE_USER_SCRIPT_MASTER_H_ #define EXTENSIONS_BROWSER_DECLARATIVE_USER_SCRIPT_MASTER_H_ +#include <set> + +#include "base/memory/scoped_ptr.h" #include "base/scoped_observer.h" -#include "extensions/browser/extension_user_script_loader.h" +#include "extensions/common/host_id.h" namespace content { class BrowserContext; @@ -15,6 +18,7 @@ namespace extensions { class UserScript; +class UserScriptLoader; // Manages declarative user scripts for a single extension. Owns a // UserScriptLoader to which file loading and shared memory management @@ -30,9 +34,13 @@ // script load is in progress. void AddScript(const UserScript& script); - // Adds a set of scripts to shared memory region. This may not happen right - // away if a script load is in progress. - void AddScripts(const std::set<UserScript>& scripts); + // Adds a set of scripts to shared meomory region. The fetch of the content + // of the script on WebUI requires to start URL request to the associated + // render specified by |render_process_id, render_view_id|. + // This may not happen right away if a script load is in progress. + void AddScripts(const std::set<UserScript>& scripts, + int render_process_id, + int render_view_id); // Removes script from shared memory region. This may not happen right away if // a script load is in progress. @@ -54,7 +62,7 @@ // Script loader that handles loading contents of scripts into shared memory // and notifying renderers of script updates. - ExtensionUserScriptLoader loader_; + scoped_ptr<UserScriptLoader> loader_; DISALLOW_COPY_AND_ASSIGN(DeclarativeUserScriptMaster); };
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index ed35bc0..e5fe08b 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1069,6 +1069,19 @@ DEVELOPERPRIVATE_SHOWPATH, FILEMANAGERPRIVATE_ADDPROVIDEDFILESYSTEM, FILEMANAGERPRIVATE_CONFIGUREPROVIDEDFILESYSTEM, + SEARCHENGINESPRIVATE_GETDEFAULTSEARCHENGINES, + SEARCHENGINESPRIVATE_SETSELECTEDSEARCHENGINE, + AUTOFILLPRIVATE_SAVEADDRESS, + AUTOFILLPRIVATE_GETADDRESSCOMPONENTS, + AUTOFILLPRIVATE_SAVECREDITCARD, + AUTOFILLPRIVATE_REMOVEENTRY, + AUTOFILLPRIVATE_VALIDATEPHONENUMBERS, + AUTOFILLPRIVATE_MASKCREDITCARD, + INSTANCEID_GETID, + INSTANCEID_GETCREATIONTIME, + INSTANCEID_GETTOKEN, + INSTANCEID_DELETETOKEN, + INSTANCEID_DELETEID, // Last entry: Add new entries above and ensure to update // tools/metrics/histograms/histograms.xml. ENUM_BOUNDARY
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index c4f7da2..88c32ea 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc
@@ -1866,7 +1866,11 @@ app_sorting_(app_sorting.Pass()), time_provider_(time_provider.Pass()), extensions_disabled_(extensions_disabled) { + // TODO(mgiuca): Added these checks to try and diagnose + // http://crbug.com/476648. Remove them after the investigation is concluded. + CHECK(this); app_sorting_->SetExtensionScopedPrefs(this); + app_sorting_->CheckExtensionScopedPrefs(); MakePathsRelative(); // Ensure that any early observers are watching before prefs are initialized. @@ -1891,27 +1895,18 @@ // static void ExtensionPrefs::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterDictionaryPref( - pref_names::kExtensions, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(pref_names::kExtensions); registry->RegisterListPref(pref_names::kToolbar, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); registry->RegisterIntegerPref( pref_names::kToolbarSize, -1, // default value user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - kExtensionsBlacklistUpdate, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(pref_names::kInstallAllowList, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(pref_names::kInstallDenyList, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - pref_names::kInstallForceList, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(pref_names::kAllowedTypes, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kExtensionsBlacklistUpdate); + registry->RegisterListPref(pref_names::kInstallAllowList); + registry->RegisterListPref(pref_names::kInstallDenyList); + registry->RegisterDictionaryPref(pref_names::kInstallForceList); + registry->RegisterListPref(pref_names::kAllowedTypes); registry->RegisterBooleanPref( pref_names::kStorageGarbageCollect, false, // default value @@ -1924,20 +1919,15 @@ pref_names::kNextUpdateCheck, 0, // default value user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(pref_names::kAllowedInstallSites, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(pref_names::kAllowedInstallSites); registry->RegisterStringPref( pref_names::kLastChromeVersion, std::string(), // default value user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterDictionaryPref( - kInstallSignature, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterDictionaryPref(kInstallSignature); - registry->RegisterListPref(pref_names::kNativeMessagingBlacklist, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterListPref(pref_names::kNativeMessagingWhitelist, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterListPref(pref_names::kNativeMessagingBlacklist); + registry->RegisterListPref(pref_names::kNativeMessagingWhitelist); registry->RegisterBooleanPref( pref_names::kNativeMessagingUserLevelHosts, true, // default value @@ -1948,9 +1938,7 @@ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); #if !defined(OS_MACOSX) - registry->RegisterBooleanPref( - pref_names::kAppFullscreenAllowed, true, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); + registry->RegisterBooleanPref(pref_names::kAppFullscreenAllowed, true); #endif }
diff --git a/extensions/browser/extension_user_script_loader.cc b/extensions/browser/extension_user_script_loader.cc index dafcdd5..70b07904 100644 --- a/extensions/browser/extension_user_script_loader.cc +++ b/extensions/browser/extension_user_script_loader.cc
@@ -33,6 +33,8 @@ namespace { +using SubstitutionMap = std::map<std::string, std::string>; + // Verifies file contents as they are read. void VerifyContent(const scoped_refptr<ContentVerifier>& verifier, const std::string& extension_id, @@ -50,11 +52,10 @@ } // Loads user scripts from the extension who owns these scripts. -bool ExtensionLoadScriptContent( - const HostID& host_id, - UserScript::File* script_file, - const UserScriptLoader::SubstitutionMap* localization_messages, - const scoped_refptr<ContentVerifier>& verifier) { +bool LoadScriptContent(const HostID& host_id, + UserScript::File* script_file, + const SubstitutionMap* localization_messages, + const scoped_refptr<ContentVerifier>& verifier) { DCHECK(script_file); std::string content; const base::FilePath& path = ExtensionResource::GetFilePath( @@ -108,15 +109,61 @@ return true; } +SubstitutionMap* GetLocalizationMessages( + const ExtensionUserScriptLoader::HostsInfo& hosts_info, + const HostID& host_id) { + ExtensionUserScriptLoader::HostsInfo::const_iterator iter = + hosts_info.find(host_id); + if (iter == hosts_info.end()) + return nullptr; + return file_util::LoadMessageBundleSubstitutionMap( + iter->second.first, host_id.id(), iter->second.second); +} + +void LoadUserScripts(UserScriptList* user_scripts, + const ExtensionUserScriptLoader::HostsInfo& hosts_info, + const std::set<int>& added_script_ids, + const scoped_refptr<ContentVerifier>& verifier) { + for (UserScript& script : *user_scripts) { + if (added_script_ids.count(script.id()) == 0) + continue; + scoped_ptr<SubstitutionMap> localization_messages( + GetLocalizationMessages(hosts_info, script.host_id())); + for (UserScript::File& script_file : script.js_scripts()) { + if (script_file.GetContent().empty()) + LoadScriptContent(script.host_id(), &script_file, nullptr, verifier); + } + for (UserScript::File& script_file : script.css_scripts()) { + if (script_file.GetContent().empty()) + LoadScriptContent(script.host_id(), &script_file, + localization_messages.get(), verifier); + } + } +} + +void LoadScriptsOnFileThread( + scoped_ptr<UserScriptList> user_scripts, + const ExtensionUserScriptLoader::HostsInfo& hosts_info, + const std::set<int>& added_script_ids, + const scoped_refptr<ContentVerifier>& verifier, + UserScriptLoader::LoadScriptsCallback callback) { + DCHECK(user_scripts.get()); + LoadUserScripts(user_scripts.get(), hosts_info, added_script_ids, verifier); + scoped_ptr<base::SharedMemory> memory = + UserScriptLoader::Serialize(*user_scripts); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(callback, base::Passed(&user_scripts), base::Passed(&memory))); +} + } // namespace ExtensionUserScriptLoader::ExtensionUserScriptLoader( BrowserContext* browser_context, const HostID& host_id, bool listen_for_extension_system_loaded) - : UserScriptLoader( - browser_context, - host_id, + : UserScriptLoader(browser_context, host_id), + content_verifier_( ExtensionSystem::Get(browser_context)->content_verifier()), extension_registry_observer_(this), weak_factory_(this) { @@ -135,6 +182,30 @@ ExtensionUserScriptLoader::~ExtensionUserScriptLoader() { } +void ExtensionUserScriptLoader::LoadScriptsForTest( + UserScriptList* user_scripts) { + HostsInfo info; + std::set<int> added_script_ids; + for (UserScript& script : *user_scripts) + added_script_ids.insert(script.id()); + + LoadUserScripts(user_scripts, info, added_script_ids, + nullptr /* no verifier for testing */); +} + +void ExtensionUserScriptLoader::LoadScripts( + scoped_ptr<UserScriptList> user_scripts, + const std::set<HostID>& changed_hosts, + const std::set<int>& added_script_ids, + LoadScriptsCallback callback) { + UpdateHostsInfo(changed_hosts); + + content::BrowserThread::PostTask( + content::BrowserThread::FILE, FROM_HERE, + base::Bind(&LoadScriptsOnFileThread, base::Passed(&user_scripts), + hosts_info_, added_script_ids, content_verifier_, callback)); +} + void ExtensionUserScriptLoader::UpdateHostsInfo( const std::set<HostID>& changed_hosts) { ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context()); @@ -145,22 +216,18 @@ // which leads to the above lookup failing. In this case, just continue. if (!extension) continue; - AddHostInfo(host_id, ExtensionSet::ExtensionPathAndDefaultLocale( - extension->path(), - LocaleInfo::GetDefaultLocale(extension))); + if (hosts_info_.find(host_id) != hosts_info_.end()) + continue; + hosts_info_[host_id] = ExtensionSet::ExtensionPathAndDefaultLocale( + extension->path(), LocaleInfo::GetDefaultLocale(extension)); } } -UserScriptLoader::LoadUserScriptsContentFunction -ExtensionUserScriptLoader::GetLoadUserScriptsFunction() { - return base::Bind(&ExtensionLoadScriptContent); -} - void ExtensionUserScriptLoader::OnExtensionUnloaded( content::BrowserContext* browser_context, const Extension* extension, UnloadedExtensionInfo::Reason reason) { - RemoveHostInfo(HostID(HostID::EXTENSIONS, extension->id())); + hosts_info_.erase(HostID(HostID::EXTENSIONS, extension->id())); } void ExtensionUserScriptLoader::OnExtensionSystemReady() {
diff --git a/extensions/browser/extension_user_script_loader.h b/extensions/browser/extension_user_script_loader.h index 5ca4060..d18c4e4 100644 --- a/extensions/browser/extension_user_script_loader.h +++ b/extensions/browser/extension_user_script_loader.h
@@ -16,12 +16,16 @@ namespace extensions { +class ContentVerifier; class ExtensionRegistry; // UserScriptLoader for extensions. class ExtensionUserScriptLoader : public UserScriptLoader, public ExtensionRegistryObserver { public: + using PathAndDefaultLocale = std::pair<base::FilePath, std::string>; + using HostsInfo = std::map<HostID, PathAndDefaultLocale>; + // The listen_for_extension_system_loaded is only set true when initilizing // the Extension System, e.g, when constructs SharedUserScriptMaster in // ExtensionSystemImpl. @@ -30,10 +34,20 @@ bool listen_for_extension_system_loaded); ~ExtensionUserScriptLoader() override; + // A wrapper around the method to load user scripts, which is normally run on + // the file thread. Exposed only for tests. + void LoadScriptsForTest(UserScriptList* user_scripts); + private: // UserScriptLoader: - void UpdateHostsInfo(const std::set<HostID>& changed_hosts) override; - LoadUserScriptsContentFunction GetLoadUserScriptsFunction() override; + void LoadScripts(scoped_ptr<UserScriptList> user_scripts, + const std::set<HostID>& changed_hosts, + const std::set<int>& added_script_ids, + LoadScriptsCallback callback) override; + + // Updates |hosts_info_| to contain info for each element of + // |changed_hosts_|. + void UpdateHostsInfo(const std::set<HostID>& changed_hosts); // ExtensionRegistryObserver: void OnExtensionUnloaded(content::BrowserContext* browser_context, @@ -44,6 +58,12 @@ // to be ready. void OnExtensionSystemReady(); + // Maps host info needed for localization to a host ID. + HostsInfo hosts_info_; + + // Manages content verification of the loaded user scripts. + scoped_refptr<ContentVerifier> content_verifier_; + ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> extension_registry_observer_;
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.cc b/extensions/browser/guest_view/app_view/app_view_guest.cc index 328ef0b2..386ab0d7 100644 --- a/extensions/browser/guest_view/app_view/app_view_guest.cc +++ b/extensions/browser/guest_view/app_view/app_view_guest.cc
@@ -279,7 +279,7 @@ scoped_ptr<base::DictionaryValue> embed_request(new base::DictionaryValue()); embed_request->SetInteger(appview::kGuestInstanceID, guest_instance_id()); - embed_request->SetString(appview::kEmbedderID, owner_extension_id()); + embed_request->SetString(appview::kEmbedderID, owner_host()); embed_request->Set(appview::kData, data.release()); AppRuntimeEventRouter::DispatchOnEmbedRequestedEvent( browser_context(), embed_request.Pass(), extension_host->extension());
diff --git a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc new file mode 100644 index 0000000..975d962 --- /dev/null +++ b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.cc
@@ -0,0 +1,93 @@ +// 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 "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" + +#include "content/public/browser/browser_context.h" +#include "content/public/browser/render_process_host.h" +#include "extensions/browser/event_router.h" +#include "extensions/browser/guest_view/app_view/app_view_guest.h" +#include "extensions/browser/guest_view/extension_options/extension_options_guest.h" +#include "extensions/browser/guest_view/extension_view/extension_view_guest.h" +#include "extensions/browser/guest_view/guest_view_base.h" +#include "extensions/browser/guest_view/guest_view_manager.h" +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" +#include "extensions/browser/guest_view/surface_worker/surface_worker_guest.h" +#include "extensions/browser/guest_view/web_view/web_view_guest.h" +#include "extensions/browser/process_manager.h" +#include "extensions/browser/process_map.h" +#include "extensions/common/features/feature.h" +#include "extensions/common/features/feature_provider.h" + +namespace extensions { + +ExtensionsGuestViewManagerDelegate::ExtensionsGuestViewManagerDelegate( + content::BrowserContext* context) + : context_(context) { +} + +ExtensionsGuestViewManagerDelegate::~ExtensionsGuestViewManagerDelegate() { +} + +void ExtensionsGuestViewManagerDelegate::DispatchEvent( + const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + GuestViewBase* guest, + int instance_id) { + EventFilteringInfo info; + info.SetInstanceID(instance_id); + scoped_ptr<base::ListValue> event_args(new base::ListValue()); + event_args->Append(args.release()); + + EventRouter::DispatchEvent( + guest->owner_web_contents(), + guest->browser_context(), + guest->owner_host(), + event_name, + event_args.Pass(), + EventRouter::USER_GESTURE_UNKNOWN, + info); +} + +bool ExtensionsGuestViewManagerDelegate::IsGuestAvailableToContext( + extensions::GuestViewBase* guest) { + const Feature* feature = + FeatureProvider::GetAPIFeature(guest->GetAPINamespace()); + CHECK(feature); + + ProcessMap* process_map = ProcessMap::Get(context_); + CHECK(process_map); + + const Extension* owner_extension = ProcessManager::Get(context_)-> + GetExtensionForWebContents(guest->owner_web_contents()); + + // Ok for |owner_extension| to be nullptr, the embedder might be WebUI. + Feature::Availability availability = feature->IsAvailableToContext( + owner_extension, + process_map->GetMostLikelyContextType( + owner_extension, + guest->owner_web_contents()->GetRenderProcessHost()->GetID()), + guest->GetOwnerSiteURL()); + + return availability.is_available(); +} + +bool ExtensionsGuestViewManagerDelegate::IsOwnedByExtension( + extensions::GuestViewBase* guest) { + return !!ProcessManager::Get(context_)-> + GetExtensionForWebContents(guest->owner_web_contents()); +} + +void ExtensionsGuestViewManagerDelegate::RegisterAdditionalGuestViewTypes() { + extensions::GuestViewManager* manager = + extensions::GuestViewManager::FromBrowserContext(context_); + manager->RegisterGuestViewType<AppViewGuest>(); + manager->RegisterGuestViewType<ExtensionOptionsGuest>(); + manager->RegisterGuestViewType<ExtensionViewGuest>(); + manager->RegisterGuestViewType<MimeHandlerViewGuest>(); + manager->RegisterGuestViewType<SurfaceWorkerGuest>(); + manager->RegisterGuestViewType<WebViewGuest>(); +} + +} // namespace extensions
diff --git a/extensions/browser/guest_view/extensions_guest_view_manager_delegate.h b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.h new file mode 100644 index 0000000..1b47820 --- /dev/null +++ b/extensions/browser/guest_view/extensions_guest_view_manager_delegate.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 EXTENSIONS_BROWSER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_MANAGER_DELEGATE_H_ +#define EXTENSIONS_BROWSER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_MANAGER_DELEGATE_H_ + +#include "extensions/browser/guest_view/guest_view_manager_delegate.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace extensions { +class GuestViewBase; +class GuestViewManager; +} // namespace extensions + +namespace extensions { + +// ExtensionsGuestViewManagerDelegate implements GuestViewManager functionality +// specific to Chromium builds that include the extensions module. +class ExtensionsGuestViewManagerDelegate + : public guestview::GuestViewManagerDelegate { + public: + explicit ExtensionsGuestViewManagerDelegate(content::BrowserContext* context); + ~ExtensionsGuestViewManagerDelegate() override; + + // GuestViewManagerDelegate implementation. + void DispatchEvent(const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + GuestViewBase* guest, + int instance_id) override; + bool IsGuestAvailableToContext(extensions::GuestViewBase* guest) override; + bool IsOwnedByExtension(extensions::GuestViewBase* guest) override; + void RegisterAdditionalGuestViewTypes() override; + + private: + content::BrowserContext* const context_; +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_GUEST_VIEW_EXTENSIONS_GUEST_VIEW_MANAGER_DELEGATE_H_
diff --git a/extensions/browser/guest_view/extensions_guest_view_message_filter.cc b/extensions/browser/guest_view/extensions_guest_view_message_filter.cc index 215bf816..7f52840 100644 --- a/extensions/browser/guest_view/extensions_guest_view_message_filter.cc +++ b/extensions/browser/guest_view/extensions_guest_view_message_filter.cc
@@ -8,6 +8,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_base.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_constants.h" @@ -22,6 +23,7 @@ using content::BrowserThread; using content::RenderFrameHost; using content::WebContents; +using guestview::GuestViewManagerDelegate; namespace extensions { @@ -93,7 +95,12 @@ // Since we are creating a new guest, we will create a GuestViewManager // if we don't already have one. auto manager = GuestViewManager::FromBrowserContext(browser_context_); - DCHECK(manager); + if (!manager) { + manager = GuestViewManager::CreateWithDelegate( + browser_context_, + scoped_ptr<GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate(browser_context_))); + } auto rfh = RenderFrameHost::FromID(render_process_id_, render_frame_id); auto embedder_web_contents = WebContents::FromRenderFrameHost(rfh); @@ -124,8 +131,7 @@ int render_frame_id, int element_instance_id, const gfx::Size& new_size) { - auto manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context_); + auto manager = GuestViewManager::FromBrowserContext(browser_context_); // We should have a GuestViewManager at this point. If we don't then the // embedder is misbehaving. if (!manager) @@ -162,8 +168,7 @@ base::DictionaryValue attach_params; attach_params.SetInteger(guestview::kElementWidth, element_size.width()); attach_params.SetInteger(guestview::kElementHeight, element_size.height()); - auto manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context_); + auto manager = GuestViewManager::FromBrowserContext(browser_context_); CHECK(manager); manager->AttachGuest(embedder_render_process_id, element_instance_id,
diff --git a/extensions/browser/guest_view/guest_view_base.cc b/extensions/browser/guest_view/guest_view_base.cc index 134c326..48b9b25 100644 --- a/extensions/browser/guest_view/guest_view_base.cc +++ b/extensions/browser/guest_view/guest_view_base.cc
@@ -146,7 +146,7 @@ : owner_web_contents_(owner_web_contents), browser_context_(owner_web_contents->GetBrowserContext()), guest_instance_id_( - GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> + GuestViewManager::FromBrowserContext(browser_context_)-> GetNextInstanceID()), view_instance_id_(guestview::kInstanceIDNone), element_instance_id_(guestview::kInstanceIDNone), @@ -157,6 +157,9 @@ is_full_page_plugin_(false), guest_proxy_routing_id_(MSG_ROUTING_NONE), weak_ptr_factory_(this) { + owner_host_ = GuestViewManager::FromBrowserContext(browser_context_)-> + IsOwnedByExtension(this) ? + owner_web_contents->GetLastCommittedURL().host() : std::string(); } void GuestViewBase::Init(const base::DictionaryValue& create_params, @@ -165,8 +168,8 @@ return; initialized_ = true; - if (!GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> - IsGuestAvailableToContext(this, &owner_extension_id_)) { + if (!GuestViewManager::FromBrowserContext(browser_context_)-> + IsGuestAvailableToContext(this)) { // The derived class did not create a WebContents so this class serves no // purpose. Let's self-destruct. delete this; @@ -208,7 +211,7 @@ guest_web_contents->SetDelegate(this); webcontents_guestview_map.Get().insert( std::make_pair(guest_web_contents, this)); - GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> + GuestViewManager::FromBrowserContext(browser_context_)-> AddGuest(guest_instance_id_, guest_web_contents); // Populate the view instance ID if we have it on creation. @@ -331,7 +334,7 @@ return nullptr; content::WebContents* guest_web_contents = - GuestViewManager::FromBrowserContextIfAvailable( + GuestViewManager::FromBrowserContext( host->GetBrowserContext())-> GetGuestByInstanceIDSafely(guest_instance_id, owner_process_id); if (!guest_web_contents) @@ -370,8 +373,7 @@ content::WebContents* GuestViewBase::CreateNewGuestWindow( const content::WebContents::CreateParams& create_params) { - auto guest_manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context()); + auto guest_manager = GuestViewManager::FromBrowserContext(browser_context()); return guest_manager->CreateGuestWithWebContentsParams( GetViewType(), owner_web_contents(), @@ -399,8 +401,7 @@ } void GuestViewBase::DidDetach() { - GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> - DetachGuest(this); + GuestViewManager::FromBrowserContext(browser_context_)->DetachGuest(this); StopTrackingEmbedderZoomLevel(); owner_web_contents()->Send(new GuestViewMsg_GuestDetached( element_instance_id_)); @@ -450,7 +451,7 @@ guest_host_ = nullptr; webcontents_guestview_map.Get().erase(web_contents()); - GuestViewManager::FromBrowserContextIfAvailable(browser_context_)-> + GuestViewManager::FromBrowserContext(browser_context_)-> RemoveGuest(guest_instance_id_); pending_events_.clear(); @@ -488,6 +489,9 @@ owner_web_contents_ = embedder_web_contents; owner_contents_observer_.reset( new OwnerContentsObserver(this, embedder_web_contents)); + owner_host_ = GuestViewManager::FromBrowserContext(browser_context_)-> + IsOwnedByExtension(this) ? + owner_web_contents()->GetLastCommittedURL().host() : std::string(); } // Start tracking the new embedder's zoom level.
diff --git a/extensions/browser/guest_view/guest_view_base.h b/extensions/browser/guest_view/guest_view_base.h index 7969cb9..6252e6c 100644 --- a/extensions/browser/guest_view/guest_view_base.h +++ b/extensions/browser/guest_view/guest_view_base.h
@@ -241,14 +241,6 @@ // Returns the instance ID of the GuestViewBase's element. int element_instance_id() const { return element_instance_id_; } - // Returns the extension ID of the embedder. - const std::string& owner_extension_id() const { - return owner_extension_id_; - } - - // Returns whether this GuestView is embedded in an extension/app. - bool in_extension() const { return !owner_extension_id_.empty(); } - bool can_owner_receive_events() const { return !!view_instance_id_; } // Returns the user browser context of the embedder. @@ -261,6 +253,10 @@ // Returns the URL of the owner WebContents. const GURL& GetOwnerSiteURL() const; + // Returns the host of the owner WebContents. For extensions, this is the + // extension ID. + std::string owner_host() const { return owner_host_; } + // Whether the guest view is inside a plugin document. bool is_full_page_plugin() const { return is_full_page_plugin_; } @@ -381,7 +377,7 @@ // |owner_web_contents_|. If |owner_web_contents_| is destroyed then this // guest will also self-destruct. content::WebContents* owner_web_contents_; - std::string owner_extension_id_; + std::string owner_host_; content::BrowserContext* const browser_context_; // |guest_instance_id_| is a profile-wide unique identifier for a guest
diff --git a/extensions/browser/guest_view/guest_view_event.cc b/extensions/browser/guest_view/guest_view_event.cc index 39641554..00b0af3 100644 --- a/extensions/browser/guest_view/guest_view_event.cc +++ b/extensions/browser/guest_view/guest_view_event.cc
@@ -4,8 +4,8 @@ #include "extensions/browser/guest_view/guest_view_event.h" -#include "extensions/browser/event_router.h" #include "extensions/browser/guest_view/guest_view_base.h" +#include "extensions/browser/guest_view/guest_view_manager.h" namespace extensions { @@ -19,19 +19,8 @@ } void GuestViewEvent::Dispatch(GuestViewBase* guest, int instance_id) { - EventFilteringInfo info; - info.SetInstanceID(instance_id); - scoped_ptr<base::ListValue> args(new base::ListValue()); - args->Append(args_.release()); - - EventRouter::DispatchEvent( - guest->owner_web_contents(), - guest->browser_context(), - guest->owner_extension_id(), - name_, - args.Pass(), - EventRouter::USER_GESTURE_UNKNOWN, - info); + GuestViewManager::FromBrowserContext(guest->browser_context())-> + DispatchEvent(name_, args_.Pass(), guest, instance_id); delete this; }
diff --git a/extensions/browser/guest_view/guest_view_event.h b/extensions/browser/guest_view/guest_view_event.h index 1d557a0..c9c8cb8 100644 --- a/extensions/browser/guest_view/guest_view_event.h +++ b/extensions/browser/guest_view/guest_view_event.h
@@ -14,8 +14,8 @@ class GuestViewBase; -// A GuestViewEvent is a wrapper class for an extension event. -// GuestViewEvents may be queued until the guest is attached to a conatiner. +// A GuestViewEvent is a wrapper class for a GuestView event. +// GuestViewEvents may be queued until the guest is attached to a container. // This wrapper class holds all the necessary information to fire the event // on attachment. GuestViewEvents are owned by GuestViewBase. class GuestViewEvent {
diff --git a/extensions/browser/guest_view/guest_view_manager.cc b/extensions/browser/guest_view/guest_view_manager.cc index dd2ad1c..0d6b28b 100644 --- a/extensions/browser/guest_view/guest_view_manager.cc +++ b/extensions/browser/guest_view/guest_view_manager.cc
@@ -14,18 +14,9 @@ #include "content/public/common/child_process_host.h" #include "content/public/common/result_codes.h" #include "content/public/common/url_constants.h" -#include "extensions/browser/guest_view/app_view/app_view_guest.h" -#include "extensions/browser/guest_view/extension_options/extension_options_guest.h" -#include "extensions/browser/guest_view/extension_view/extension_view_guest.h" #include "extensions/browser/guest_view/guest_view_base.h" +#include "extensions/browser/guest_view/guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" -#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" -#include "extensions/browser/guest_view/surface_worker/surface_worker_guest.h" -#include "extensions/browser/guest_view/web_view/web_view_guest.h" -#include "extensions/browser/process_manager.h" -#include "extensions/browser/process_map.h" -#include "extensions/common/features/feature.h" -#include "extensions/common/features/feature_provider.h" #include "extensions/common/guest_view/guest_view_constants.h" #include "net/base/escape.h" #include "url/gurl.h" @@ -33,29 +24,35 @@ using content::BrowserContext; using content::SiteInstance; using content::WebContents; +using guestview::GuestViewManagerDelegate; namespace extensions { // static GuestViewManagerFactory* GuestViewManager::factory_ = nullptr; -GuestViewManager::GuestViewManager(content::BrowserContext* context) - : current_instance_id_(0), last_instance_id_removed_(0), context_(context) { +GuestViewManager::GuestViewManager( + content::BrowserContext* context, + scoped_ptr<GuestViewManagerDelegate> delegate) + : current_instance_id_(0), + last_instance_id_removed_(0), + context_(context), + delegate_(delegate.Pass()) { } GuestViewManager::~GuestViewManager() {} // static -GuestViewManager* GuestViewManager::FromBrowserContext( - BrowserContext* context) { - GuestViewManager* guest_manager = - static_cast<GuestViewManager*>(context->GetUserData( - guestview::kGuestViewManagerKeyName)); +GuestViewManager* GuestViewManager::CreateWithDelegate( + BrowserContext* context, + scoped_ptr<GuestViewManagerDelegate> delegate) { + GuestViewManager* guest_manager = FromBrowserContext(context); if (!guest_manager) { if (factory_) { - guest_manager = factory_->CreateGuestViewManager(context); + guest_manager = + factory_->CreateGuestViewManager(context, delegate.Pass()); } else { - guest_manager = new GuestViewManager(context); + guest_manager = new GuestViewManager(context, delegate.Pass()); } context->SetUserData(guestview::kGuestViewManagerKeyName, guest_manager); } @@ -63,7 +60,7 @@ } // static -GuestViewManager* GuestViewManager::FromBrowserContextIfAvailable( +GuestViewManager* GuestViewManager::FromBrowserContext( BrowserContext* context) { return static_cast<GuestViewManager*>(context->GetUserData( guestview::kGuestViewManagerKeyName)); @@ -122,6 +119,10 @@ instance_id_map_.erase(it); } +bool GuestViewManager::IsOwnedByExtension(GuestViewBase* guest) { + return delegate_->IsOwnedByExtension(guest); +} + int GuestViewManager::GetNextInstanceID() { return ++current_instance_id_; } @@ -260,39 +261,19 @@ return it->second.Run(owner_web_contents); } -// static void GuestViewManager::RegisterGuestViewTypes() { - RegisterGuestViewType<AppViewGuest>(); - RegisterGuestViewType<ExtensionOptionsGuest>(); - RegisterGuestViewType<ExtensionViewGuest>(); - RegisterGuestViewType<MimeHandlerViewGuest>(); - RegisterGuestViewType<SurfaceWorkerGuest>(); - RegisterGuestViewType<WebViewGuest>(); + delegate_->RegisterAdditionalGuestViewTypes(); } -bool GuestViewManager::IsGuestAvailableToContext( - GuestViewBase* guest, - std::string* owner_extension_id) { - const Feature* feature = - FeatureProvider::GetAPIFeature(guest->GetAPINamespace()); - CHECK(feature); +bool GuestViewManager::IsGuestAvailableToContext(GuestViewBase* guest) { + return delegate_->IsGuestAvailableToContext(guest); +} - ProcessMap* process_map = ProcessMap::Get(context_); - CHECK(process_map); - - const Extension* owner_extension = ProcessManager::Get(context_)-> - GetExtensionForWebContents(guest->owner_web_contents()); - *owner_extension_id = owner_extension ? owner_extension->id() : std::string(); - - // Ok for |owner_extension| to be nullptr, the embedder might be WebUI. - Feature::Availability availability = feature->IsAvailableToContext( - owner_extension, - process_map->GetMostLikelyContextType( - owner_extension, - guest->owner_web_contents()->GetRenderProcessHost()->GetID()), - guest->GetOwnerSiteURL()); - - return availability.is_available(); +void GuestViewManager::DispatchEvent(const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + GuestViewBase* guest, + int instance_id) { + delegate_->DispatchEvent(event_name, args.Pass(), guest, instance_id); } content::WebContents* GuestViewManager::GetGuestByInstanceID(
diff --git a/extensions/browser/guest_view/guest_view_manager.h b/extensions/browser/guest_view/guest_view_manager.h index 626b5838..e1fb334 100644 --- a/extensions/browser/guest_view/guest_view_manager.h +++ b/extensions/browser/guest_view/guest_view_manager.h
@@ -22,6 +22,10 @@ class WebContents; } // namespace content +namespace guestview { +class GuestViewManagerDelegate; +} // namespace guestview + namespace extensions{ class GuestViewBase; class GuestViewManagerFactory; @@ -29,17 +33,19 @@ class GuestViewManager : public content::BrowserPluginGuestManager, public base::SupportsUserData::Data { public: - explicit GuestViewManager(content::BrowserContext* context); + GuestViewManager(content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate); ~GuestViewManager() override; // Returns the GuestViewManager associated with |context|. If one isn't // available, then it is created and returned. - static GuestViewManager* FromBrowserContext(content::BrowserContext* context); + static GuestViewManager* CreateWithDelegate( + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate); // Returns the GuestViewManager associated with |context|. If one isn't // available, then nullptr is returned. - static GuestViewManager* FromBrowserContextIfAvailable( - content::BrowserContext* context); + static GuestViewManager* FromBrowserContext(content::BrowserContext* context); // Overrides factory for testing. Default (NULL) value indicates regular // (non-test) environment. @@ -67,6 +73,9 @@ // ID if one exists. void DetachGuest(GuestViewBase* guest); + // Indicates whether the |guest| is owned by an extension or Chrome App. + bool IsOwnedByExtension(GuestViewBase* guest); + int GetNextInstanceID(); int GetGuestInstanceIDForElementID( int owner_process_id, @@ -105,7 +114,7 @@ protected: friend class GuestViewBase; - FRIEND_TEST_ALL_PREFIXES(GuestViewManagerTest, AddRemove); + friend class GuestViewEvent; // Can be overriden in tests. virtual void AddGuest(int guest_instance_id, @@ -123,8 +132,14 @@ // Indicates whether the provided |guest| can be used in the context it has // been created. - bool IsGuestAvailableToContext(GuestViewBase* guest, - std::string* owner_extension_id); + bool IsGuestAvailableToContext(GuestViewBase* guest); + + // Dispatches the event with |name| with the provided |args| to the embedder + // of the given |guest| with |instance_id| for routing. + void DispatchEvent(const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + GuestViewBase* guest, + int instance_id); content::WebContents* GetGuestByInstanceID(int guest_instance_id); @@ -189,6 +204,8 @@ content::BrowserContext* context_; + scoped_ptr<guestview::GuestViewManagerDelegate> delegate_; + DISALLOW_COPY_AND_ASSIGN(GuestViewManager); };
diff --git a/extensions/browser/guest_view/guest_view_manager_delegate.h b/extensions/browser/guest_view/guest_view_manager_delegate.h new file mode 100644 index 0000000..f6e1795f --- /dev/null +++ b/extensions/browser/guest_view/guest_view_manager_delegate.h
@@ -0,0 +1,53 @@ +// 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 EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_MANAGER_DELEGATE_H_ +#define EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_MANAGER_DELEGATE_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" + +namespace base { +class DictionaryValue; +} // namespace base + +namespace extensions { +class GuestViewBase; +} // namespace extensions + +namespace guestview { + +// A GuestViewManagerDelegate interface allows GuestViewManager to delegate +// responsibilities to other modules in Chromium. Different builds of Chromium +// may use different GuestViewManagerDelegate implementations. For example, +// mobile builds of Chromium do not include an extensions module and so +// permission checks would be different, and IsOwnedByExtension would always +// return false. +class GuestViewManagerDelegate { + public: + virtual ~GuestViewManagerDelegate() {} + + // Dispatches the event with |name| with the provided |args| to the embedder + // of the given |guest| with |instance_id| for routing. + virtual void DispatchEvent(const std::string& event_name, + scoped_ptr<base::DictionaryValue> args, + extensions::GuestViewBase* guest, + int instance_id) = 0; + + // Indicates whether the |guest| can be used within the context of where it + // was created. + virtual bool IsGuestAvailableToContext(extensions::GuestViewBase* guest) = 0; + + // Indicates whether the |guest| is owned by an extension or Chrome App. + virtual bool IsOwnedByExtension(extensions::GuestViewBase* guest) = 0; + + // Registers additional GuestView types the delegator (GuestViewManger) can + // create. + virtual void RegisterAdditionalGuestViewTypes() = 0; +}; + +} // namespace guestview + +#endif // EXTENSIONS_BROWSER_GUEST_VIEW_GUEST_VIEW_MANAGER_DELEGATE_H_
diff --git a/extensions/browser/guest_view/guest_view_manager_factory.h b/extensions/browser/guest_view/guest_view_manager_factory.h index 9133734..695731c 100644 --- a/extensions/browser/guest_view/guest_view_manager_factory.h +++ b/extensions/browser/guest_view/guest_view_manager_factory.h
@@ -9,6 +9,10 @@ class BrowserContext; } +namespace guestview { +class GuestViewManagerDelegate; +} // namespace guestview + namespace extensions { class GuestViewManager; @@ -16,7 +20,8 @@ class GuestViewManagerFactory { public: virtual GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) = 0; + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate) = 0; protected: virtual ~GuestViewManagerFactory() {}
diff --git a/extensions/browser/guest_view/guest_view_manager_unittest.cc b/extensions/browser/guest_view/guest_view_manager_unittest.cc index 1646e49..2a380e4e 100644 --- a/extensions/browser/guest_view/guest_view_manager_unittest.cc +++ b/extensions/browser/guest_view/guest_view_manager_unittest.cc
@@ -9,36 +9,17 @@ #include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/web_contents_tester.h" #include "extensions/browser/extensions_test.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" +#include "extensions/browser/guest_view/guest_view_manager.h" +#include "extensions/browser/guest_view/guest_view_manager_delegate.h" +#include "extensions/browser/guest_view/test_guest_view_manager.h" using content::WebContents; using content::WebContentsTester; +using guestview::GuestViewManagerDelegate; namespace extensions { -namespace guestview { - -// This class allows us to access some private variables in -// GuestViewManager. -class TestGuestViewManager : public GuestViewManager { - public: - explicit TestGuestViewManager(content::BrowserContext* context) - : GuestViewManager(context) {} - - int last_instance_id_removed_for_testing() { - return last_instance_id_removed_; - } - - size_t GetRemovedInstanceIdSize() { return removed_instance_ids_.size(); } - - private: - using GuestViewManager::last_instance_id_removed_; - using GuestViewManager::removed_instance_ids_; - - DISALLOW_COPY_AND_ASSIGN(TestGuestViewManager); -}; - -} // namespace guestview - namespace { class GuestViewManagerTest : public extensions::ExtensionsTest { @@ -64,14 +45,16 @@ TEST_F(GuestViewManagerTest, AddRemove) { content::TestBrowserContext browser_context; - scoped_ptr<guestview::TestGuestViewManager> manager( - new guestview::TestGuestViewManager(&browser_context)); + scoped_ptr<GuestViewManagerDelegate> delegate( + new ExtensionsGuestViewManagerDelegate(&browser_context)); + scoped_ptr<TestGuestViewManager> manager( + new extensions::TestGuestViewManager(&browser_context, delegate.Pass())); scoped_ptr<WebContents> web_contents1(CreateWebContents()); scoped_ptr<WebContents> web_contents2(CreateWebContents()); scoped_ptr<WebContents> web_contents3(CreateWebContents()); - EXPECT_EQ(0, manager->last_instance_id_removed_for_testing()); + EXPECT_EQ(0, manager->last_instance_id_removed()); EXPECT_TRUE(manager->CanUseGuestInstanceID(1)); EXPECT_TRUE(manager->CanUseGuestInstanceID(2)); @@ -86,7 +69,7 @@ EXPECT_FALSE(manager->CanUseGuestInstanceID(2)); EXPECT_TRUE(manager->CanUseGuestInstanceID(3)); - EXPECT_EQ(0, manager->last_instance_id_removed_for_testing()); + EXPECT_EQ(0, manager->last_instance_id_removed()); EXPECT_TRUE(manager->CanUseGuestInstanceID(3)); @@ -95,15 +78,15 @@ EXPECT_FALSE(manager->CanUseGuestInstanceID(1)); EXPECT_FALSE(manager->CanUseGuestInstanceID(2)); - EXPECT_EQ(2, manager->last_instance_id_removed_for_testing()); + EXPECT_EQ(2, manager->last_instance_id_removed()); manager->RemoveGuest(3); - EXPECT_EQ(3, manager->last_instance_id_removed_for_testing()); + EXPECT_EQ(3, manager->last_instance_id_removed()); EXPECT_FALSE(manager->CanUseGuestInstanceID(1)); EXPECT_FALSE(manager->CanUseGuestInstanceID(2)); EXPECT_FALSE(manager->CanUseGuestInstanceID(3)); - EXPECT_EQ(0u, manager->GetRemovedInstanceIdSize()); + EXPECT_EQ(0, manager->GetNumRemovedInstanceIDs()); } } // namespace extensions
diff --git a/extensions/browser/guest_view/guest_view_message_filter.cc b/extensions/browser/guest_view/guest_view_message_filter.cc index 3e833d5..26188fa 100644 --- a/extensions/browser/guest_view/guest_view_message_filter.cc +++ b/extensions/browser/guest_view/guest_view_message_filter.cc
@@ -65,8 +65,7 @@ int guest_instance_id, const base::DictionaryValue& params) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - auto manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context_); + auto manager = GuestViewManager::FromBrowserContext(browser_context_); // We should have a GuestViewManager at this point. If we don't then the // embedder is misbehaving. if (!manager)
diff --git a/extensions/browser/guest_view/surface_worker/surface_worker_guest.cc b/extensions/browser/guest_view/surface_worker/surface_worker_guest.cc index 2dffde38..6c30d9c 100644 --- a/extensions/browser/guest_view/surface_worker/surface_worker_guest.cc +++ b/extensions/browser/guest_view/surface_worker/surface_worker_guest.cc
@@ -65,9 +65,8 @@ content::kGuestScheme, GetOwnerSiteURL().host().c_str())); - GuestViewManager* guest_view_manager = - GuestViewManager::FromBrowserContextIfAvailable( - owner_web_contents()->GetBrowserContext()); + GuestViewManager* guest_view_manager = GuestViewManager::FromBrowserContext( + owner_web_contents()->GetBrowserContext()); content::SiteInstance* guest_site_instance = guest_view_manager->GetGuestSiteInstance(guest_site); WebContents::CreateParams params(
diff --git a/extensions/browser/guest_view/test_guest_view_manager.cc b/extensions/browser/guest_view/test_guest_view_manager.cc index ce7b125..875939e 100644 --- a/extensions/browser/guest_view/test_guest_view_manager.cc +++ b/extensions/browser/guest_view/test_guest_view_manager.cc
@@ -4,32 +4,30 @@ #include "extensions/browser/guest_view/test_guest_view_manager.h" -#include "base/callback.h" -#include "base/strings/stringprintf.h" -#include "content/public/test/browser_test_utils.h" -#include "extensions/browser/app_window/app_window.h" -#include "extensions/browser/app_window/app_window_registry.h" -#include "extensions/browser/extension_host.h" -#include "extensions/browser/process_manager.h" -#include "extensions/common/extension.h" -#include "extensions/common/extension_paths.h" -#include "extensions/shell/browser/shell_extension_system.h" -#include "extensions/shell/test/shell_test.h" -#include "extensions/test/extension_test_message_listener.h" +#include "extensions/browser/guest_view/guest_view_manager_delegate.h" + +using guestview::GuestViewManagerDelegate; namespace extensions { -TestGuestViewManager::TestGuestViewManager(content::BrowserContext* context) - : GuestViewManager(context) { +TestGuestViewManager::TestGuestViewManager( + content::BrowserContext* context, + scoped_ptr<GuestViewManagerDelegate> delegate) + : GuestViewManager(context, delegate.Pass()), + num_guests_created_(0) { } TestGuestViewManager::~TestGuestViewManager() { } -int TestGuestViewManager::GetNumGuests() const { +int TestGuestViewManager::GetNumGuestsActive() const { return guest_web_contents_by_instance_id_.size(); } +int TestGuestViewManager::GetNumRemovedInstanceIDs() const { + return removed_instance_ids_.size(); +} + content::WebContents* TestGuestViewManager::GetLastGuestCreated() { content::WebContents* web_contents = nullptr; for (int i = current_instance_id_; i >= 0; i--) { @@ -53,8 +51,12 @@ } content::WebContents* TestGuestViewManager::WaitForSingleGuestCreated() { - if (GetNumGuests() == 0) + if (!GetNumGuestsActive()) { + // Guests have been created and subsequently destroyed. + if (num_guests_created() > 0) + return nullptr; WaitForGuestCreated(); + } return GetLastGuestCreated(); } @@ -67,6 +69,8 @@ linked_ptr<content::WebContentsDestroyedWatcher>( new content::WebContentsDestroyedWatcher(guest_web_contents))); + ++num_guests_created_; + if (created_message_loop_runner_.get()) created_message_loop_runner_->Quit(); } @@ -84,17 +88,12 @@ } GuestViewManager* TestGuestViewManagerFactory::CreateGuestViewManager( - content::BrowserContext* context) { - return GetManager(context); -} - -// This function gets called from GuestViewManager::FromBrowserContext(), -// where test_guest_view_manager_ is assigned to a linked_ptr that takes care -// of deleting it. -TestGuestViewManager* TestGuestViewManagerFactory::GetManager( - content::BrowserContext* context) { - DCHECK(!test_guest_view_manager_); - test_guest_view_manager_ = new TestGuestViewManager(context); + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate) { + if (!test_guest_view_manager_) { + test_guest_view_manager_ = + new TestGuestViewManager(context, delegate.Pass()); + } return test_guest_view_manager_; }
diff --git a/extensions/browser/guest_view/test_guest_view_manager.h b/extensions/browser/guest_view/test_guest_view_manager.h index b826f30..d819325e 100644 --- a/extensions/browser/guest_view/test_guest_view_manager.h +++ b/extensions/browser/guest_view/test_guest_view_manager.h
@@ -15,7 +15,9 @@ class TestGuestViewManager : public GuestViewManager { public: - explicit TestGuestViewManager(content::BrowserContext* context); + TestGuestViewManager( + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate); ~TestGuestViewManager() override; void WaitForAllGuestsDeleted(); @@ -23,15 +25,35 @@ content::WebContents* GetLastGuestCreated(); + // Returns the number of guests currently still alive at the time of calling + // this method. + int GetNumGuestsActive() const; + + // Returns the size of the set of removed instance IDs. + int GetNumRemovedInstanceIDs() const; + + // Returns the number of guests that have been created since the creation of + // this GuestViewManager. + int num_guests_created() const { return num_guests_created_; } + + // Returns the last guest instance ID removed from the manager. + int last_instance_id_removed() const { return last_instance_id_removed_; } + private: + FRIEND_TEST_ALL_PREFIXES(GuestViewManagerTest, AddRemove); + // GuestViewManager override: void AddGuest(int guest_instance_id, content::WebContents* guest_web_contents) override; void RemoveGuest(int guest_instance_id) override; - int GetNumGuests() const; void WaitForGuestCreated(); + using GuestViewManager::last_instance_id_removed_; + using GuestViewManager::removed_instance_ids_; + + int num_guests_created_; + std::vector<linked_ptr<content::WebContentsDestroyedWatcher>> guest_web_contents_watchers_; scoped_refptr<content::MessageLoopRunner> created_message_loop_runner_; @@ -46,9 +68,8 @@ ~TestGuestViewManagerFactory() override; GuestViewManager* CreateGuestViewManager( - content::BrowserContext* context) override; - - TestGuestViewManager* GetManager(content::BrowserContext* context); + content::BrowserContext* context, + scoped_ptr<guestview::GuestViewManagerDelegate> delegate) override; private: TestGuestViewManager* test_guest_view_manager_;
diff --git a/extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.cc b/extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.cc new file mode 100644 index 0000000..28642909 --- /dev/null +++ b/extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.cc
@@ -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. + +#include "extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h" + +#include "content/public/browser/browser_context.h" +#include "content/public/common/url_fetcher.h" +#include "net/base/load_flags.h" +#include "net/url_request/url_fetcher.h" + +WebUIURLFetcher::WebUIURLFetcher(content::BrowserContext* context, + int render_process_id, + int render_view_id, + const GURL& url, + const WebUILoadFileCallback& callback) + : context_(context), + render_process_id_(render_process_id), + render_view_id_(render_view_id), + url_(url), + callback_(callback) { +} + +WebUIURLFetcher::~WebUIURLFetcher() { +} + +void WebUIURLFetcher::Start() { + fetcher_.reset(net::URLFetcher::Create(url_, net::URLFetcher::GET, this)); + fetcher_->SetRequestContext(context_->GetRequestContext()); + fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); + + content::AssociateURLFetcherWithRenderFrame( + fetcher_.get(), url_, render_process_id_, render_view_id_); + fetcher_->Start(); +} + +void WebUIURLFetcher::OnURLFetchComplete(const net::URLFetcher* source) { + CHECK_EQ(fetcher_.get(), source); + + std::string data; + bool result = false; + if (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS) { + result = fetcher_->GetResponseAsString(&data); + DCHECK(result); + } + fetcher_.reset(); + // We cache the callback and reset it so that any references stored within it + // are destroyed at the end of the method. + auto callback_cache = callback_; + callback_.Reset(); + callback_cache.Run(result, data); +}
diff --git a/extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h b/extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h new file mode 100644 index 0000000..28aa466 --- /dev/null +++ b/extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h
@@ -0,0 +1,55 @@ +// 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 EXTENSIONS_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_UI_URL_FETCHER_H +#define EXTENSIONS_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_UI_URL_FETCHER_H + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "url/gurl.h" + +namespace content { +class BrowserContext; +} + +namespace net { +class URLFetcher; +} + +// WebUIURLFetcher downloads the content of a file by giving its |url| on WebUI. +// Each WebUIURLFetcher is associated with a given |render_process_id, +// render_view_id| pair. +class WebUIURLFetcher : public net::URLFetcherDelegate { + public: + // Called when a file URL request is complete. + // Parameters: + // - whether the request is success. + // - If yes, the content of the file. + using WebUILoadFileCallback = base::Callback<void(bool, const std::string&)>; + + WebUIURLFetcher(content::BrowserContext* context, + int render_process_id, + int render_view_id, + const GURL& url, + const WebUILoadFileCallback& callback); + ~WebUIURLFetcher() override; + + void Start(); + + private: + // net::URLFetcherDelegate: + void OnURLFetchComplete(const net::URLFetcher* source) override; + + content::BrowserContext* context_; + int render_process_id_; + int render_view_id_; + GURL url_; + WebUILoadFileCallback callback_; + scoped_ptr<net::URLFetcher> fetcher_; + + DISALLOW_COPY_AND_ASSIGN(WebUIURLFetcher); +}; + +#endif // EXTENSIONS_BROWSER_GUEST_VIEW_WEB_VIEW_WEB_UI_URL_FETCHER_H
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc index 61b87bde..f432276 100644 --- a/extensions/browser/guest_view/web_view/web_view_apitest.cc +++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -17,6 +17,7 @@ #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/extension_host.h" +#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h" #include "extensions/browser/guest_view/guest_view_manager.h" #include "extensions/browser/guest_view/guest_view_manager_factory.h" #include "extensions/browser/guest_view/test_guest_view_manager.h" @@ -237,9 +238,20 @@ } TestGuestViewManager* WebViewAPITest::GetGuestViewManager() { - return static_cast<TestGuestViewManager*>( - TestGuestViewManager::FromBrowserContext( - ShellContentBrowserClient::Get()->GetBrowserContext())); + content::BrowserContext* context = + ShellContentBrowserClient::Get()->GetBrowserContext(); + TestGuestViewManager* manager = static_cast<TestGuestViewManager*>( + TestGuestViewManager::FromBrowserContext(context)); + // TestGuestViewManager::WaitForSingleGuestCreated may and will get called + // before a guest is created. + if (!manager) { + manager = static_cast<TestGuestViewManager*>( + GuestViewManager::CreateWithDelegate( + context, + scoped_ptr<guestview::GuestViewManagerDelegate>( + new ExtensionsGuestViewManagerDelegate(context)))); + } + return manager; } void WebViewAPITest::SendMessageToGuestAndWait(
diff --git a/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc b/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc index 163934c..15ede19f 100644 --- a/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc +++ b/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc
@@ -109,6 +109,7 @@ void WebViewContentScriptManager::AddContentScripts( content::WebContents* embedder_web_contents, + int embedder_routing_id, int view_instance_id, const HostID& host_id, const std::set<UserScript>& scripts) { @@ -153,7 +154,7 @@ } // Step 3: adds new scripts to the master. - master->AddScripts(scripts); + master->AddScripts(scripts, embedder_process_id, embedder_routing_id); // Step 4: creates owner web contents observer for the given // |embedder_web_contents| if it doesn't exist.
diff --git a/extensions/browser/guest_view/web_view/web_view_content_script_manager.h b/extensions/browser/guest_view/web_view/web_view_content_script_manager.h index a46baed4..77c72a93 100644 --- a/extensions/browser/guest_view/web_view/web_view_content_script_manager.h +++ b/extensions/browser/guest_view/web_view/web_view_content_script_manager.h
@@ -38,6 +38,7 @@ // Adds content scripts for the guest specified by the |embedder_web_contents, // view_instance_id|. void AddContentScripts(content::WebContents* embedder_web_contents, + int embedder_routing_id, int view_instance_id, const HostID& host_id, const std::set<UserScript>& user_scripts);
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index ba6cb76..721cb11 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -7,6 +7,8 @@ #include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "components/browsing_data/storage_partition_http_cache_data_remover.h" +#include "components/web_cache/browser/web_cache_manager.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" @@ -284,7 +286,7 @@ // If we already have a webview tag in the same app using the same storage // partition, we should use the same SiteInstance so the existing tag and // the new tag can script each other. - auto guest_view_manager = GuestViewManager::FromBrowserContextIfAvailable( + auto guest_view_manager = GuestViewManager::FromBrowserContext( owner_render_process_host->GetBrowserContext()); content::SiteInstance* guest_site_instance = guest_view_manager->GetGuestSiteInstance(guest_site); @@ -395,7 +397,7 @@ base::Bind( &RemoveWebViewEventListenersOnIOThread, browser_context(), - owner_extension_id(), + owner_host(), owner_web_contents()->GetRenderProcessHost()->GetID(), view_instance_id())); } @@ -562,7 +564,7 @@ void WebViewGuest::CreateNewGuestWebViewWindow( const content::OpenURLParams& params) { GuestViewManager* guest_manager = - GuestViewManager::FromBrowserContextIfAvailable(browser_context()); + GuestViewManager::FromBrowserContext(browser_context()); // Set the attach params to use the same partition as the opener. // We pull the partition information from the site's URL, which is of the // form guest://site/{persist}?{partition_name}. @@ -705,15 +707,25 @@ return false; if (removal_mask & webview::WEB_VIEW_REMOVE_DATA_MASK_CACHE) { - if (web_view_guest_delegate_) { - // First clear http cache data and then clear the rest in - // |ClearDataInternal|. - web_view_guest_delegate_->ClearCache( - remove_since, base::Bind(&WebViewGuest::ClearDataInternal, - weak_ptr_factory_.GetWeakPtr(), remove_since, - removal_mask, callback)); - return true; - } + // First clear http cache data and then clear the rest in + // |ClearDataInternal|. + int render_process_id = web_contents()->GetRenderProcessHost()->GetID(); + // We need to clear renderer cache separately for our process because + // StoragePartitionHttpCacheDataRemover::ClearData() does not clear that. + web_cache::WebCacheManager::GetInstance()->Remove(render_process_id); + web_cache::WebCacheManager::GetInstance()->ClearCacheForProcess( + render_process_id); + + base::Closure cache_removal_done_callback = base::Bind( + &WebViewGuest::ClearDataInternal, weak_ptr_factory_.GetWeakPtr(), + remove_since, removal_mask, callback); + // StoragePartitionHttpCacheDataRemover removes itself when it is done. + // components/, move |ClearCache| to WebViewGuest: http//crbug.com/471287. + browsing_data::StoragePartitionHttpCacheDataRemover::CreateForRange( + partition, remove_since, base::Time::Now()) + ->Remove(cache_removal_done_callback); + + return true; } ClearDataInternal(remove_since, removal_mask, callback); @@ -871,7 +883,7 @@ owner_web_contents()->GetRenderProcessHost()->GetID(); web_view_info.instance_id = view_instance_id(); web_view_info.partition_id = partition_id; - web_view_info.owner_extension_id = owner_extension_id(); + web_view_info.owner_host = owner_host(); web_view_info.rules_registry_id = rules_registry_id_; // Get content scripts IDs added by the guest. @@ -971,8 +983,10 @@ bool WebViewGuest::HandleKeyboardShortcuts( const content::NativeWebKeyboardEvent& event) { // <webview> outside of Chrome Apps do not handle keyboard shortcuts. - if (!in_extension()) + if (!GuestViewManager::FromBrowserContext(browser_context())-> + IsOwnedByExtension(this)) { return false; + } if (event.type != blink::WebInputEvent::RawKeyDown) return false; @@ -1360,12 +1374,14 @@ } GURL WebViewGuest::ResolveURL(const std::string& src) { - if (!in_extension()) + if (!GuestViewManager::FromBrowserContext(browser_context())-> + IsOwnedByExtension(this)) { return GURL(src); + } GURL default_url(base::StringPrintf("%s://%s/", kExtensionScheme, - owner_extension_id().c_str())); + owner_host().c_str())); return default_url.Resolve(src); }
diff --git a/extensions/browser/guest_view/web_view/web_view_guest_delegate.h b/extensions/browser/guest_view/web_view/web_view_guest_delegate.h index 7b1dd56b..473ffd3d 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest_delegate.h +++ b/extensions/browser/guest_view/web_view/web_view_guest_delegate.h
@@ -32,10 +32,6 @@ typedef std::vector<linked_ptr<api::web_view_internal::ContextMenuItem> > MenuItemVector; - // Clears http cache for this guest's StoragePartition. - virtual void ClearCache(base::Time remove_since, - const base::Closure& callback) = 0; - // Called when context menu operation was handled. virtual bool HandleContextMenu(const content::ContextMenuParams& params) = 0;
diff --git a/extensions/browser/guest_view/web_view/web_view_renderer_state.cc b/extensions/browser/guest_view/web_view/web_view_renderer_state.cc index feed6b3..3068ae3a 100644 --- a/extensions/browser/guest_view/web_view/web_view_renderer_state.cc +++ b/extensions/browser/guest_view/web_view/web_view_renderer_state.cc
@@ -81,7 +81,7 @@ bool WebViewRendererState::GetOwnerInfo(int guest_process_id, int* owner_process_id, - std::string* owner_extension_id) const { + std::string* owner_host) const { DCHECK_CURRENTLY_ON(BrowserThread::IO); // TODO(fsamuel): Store per-process info in WebViewPartitionInfo instead of in // WebViewInfo. @@ -89,8 +89,8 @@ if (info.first.first == guest_process_id) { if (owner_process_id) *owner_process_id = info.second.embedder_process_id; - if (owner_extension_id) - *owner_extension_id = info.second.owner_extension_id; + if (owner_host) + *owner_host = info.second.owner_host; return true; } }
diff --git a/extensions/browser/guest_view/web_view/web_view_renderer_state.h b/extensions/browser/guest_view/web_view/web_view_renderer_state.h index 42b886f0..b6be959 100644 --- a/extensions/browser/guest_view/web_view/web_view_renderer_state.h +++ b/extensions/browser/guest_view/web_view/web_view_renderer_state.h
@@ -25,7 +25,7 @@ int instance_id; int rules_registry_id; std::string partition_id; - std::string owner_extension_id; + std::string owner_host; std::set<int> content_script_ids; WebViewInfo(); @@ -43,7 +43,7 @@ // <webview>. Called on the IO thread. bool GetOwnerInfo(int guest_process_id, int* owner_process_id, - std::string* owner_extension_id) const; + std::string* owner_host) const; // Looks up the partition info for the embedder <webview> for a given guest // process. Called on the IO thread.
diff --git a/extensions/browser/mock_extension_system.h b/extensions/browser/mock_extension_system.h index f28a2923..4766762 100644 --- a/extensions/browser/mock_extension_system.h +++ b/extensions/browser/mock_extension_system.h
@@ -71,16 +71,16 @@ DependsOn(ExtensionRegistryFactory::GetInstance()); } - virtual ~MockExtensionSystemFactory() {} + ~MockExtensionSystemFactory() override {} // BrowserContextKeyedServiceFactory overrides: - virtual KeyedService* BuildServiceInstanceFor( + KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override { return new T(context); } // ExtensionSystemProvider overrides: - virtual ExtensionSystem* GetForBrowserContext( + ExtensionSystem* GetForBrowserContext( content::BrowserContext* context) override { return static_cast<ExtensionSystem*>( GetServiceForBrowserContext(context, true));
diff --git a/extensions/browser/null_app_sorting.cc b/extensions/browser/null_app_sorting.cc index 384f5b1..855de55d 100644 --- a/extensions/browser/null_app_sorting.cc +++ b/extensions/browser/null_app_sorting.cc
@@ -26,6 +26,9 @@ void NullAppSorting::SetExtensionScopedPrefs(ExtensionScopedPrefs* prefs) { } +void NullAppSorting::CheckExtensionScopedPrefs() const { +} + void NullAppSorting::SetExtensionSyncService( ExtensionSyncService* extension_sync_service) { }
diff --git a/extensions/browser/null_app_sorting.h b/extensions/browser/null_app_sorting.h index f3b069b..5f09e28 100644 --- a/extensions/browser/null_app_sorting.h +++ b/extensions/browser/null_app_sorting.h
@@ -19,6 +19,7 @@ // AppSorting overrides: void SetExtensionScopedPrefs(ExtensionScopedPrefs* prefs) override; + void CheckExtensionScopedPrefs() const override; void SetExtensionSyncService( ExtensionSyncService* extension_sync_service) override; void Initialize(const ExtensionIdList& extension_ids) override;
diff --git a/extensions/browser/user_script_loader.cc b/extensions/browser/user_script_loader.cc index 80d4640..94b2c07 100644 --- a/extensions/browser/user_script_loader.cc +++ b/extensions/browser/user_script_loader.cc
@@ -7,21 +7,15 @@ #include <set> #include <string> -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" #include "base/version.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" #include "content/public/browser/render_process_host.h" -#include "extensions/browser/content_verifier.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/notification_types.h" #include "extensions/common/extension_messages.h" -#include "extensions/common/file_util.h" using content::BrowserThread; using content::BrowserContext; @@ -30,111 +24,6 @@ namespace { -using LoadScriptsCallback = - base::Callback<void(scoped_ptr<UserScriptList>, - scoped_ptr<base::SharedMemory>)>; - -UserScriptLoader::SubstitutionMap* GetLocalizationMessages( - const UserScriptLoader::HostsInfo& hosts_info, - const HostID& host_id) { - UserScriptLoader::HostsInfo::const_iterator iter = hosts_info.find(host_id); - if (iter == hosts_info.end()) - return nullptr; - return file_util::LoadMessageBundleSubstitutionMap( - iter->second.first, host_id.id(), iter->second.second); -} - -void LoadUserScripts( - UserScriptList* user_scripts, - const UserScriptLoader::HostsInfo& hosts_info, - const std::set<int>& added_script_ids, - const scoped_refptr<ContentVerifier>& verifier, - UserScriptLoader::LoadUserScriptsContentFunction callback) { - for (UserScriptList::iterator script = user_scripts->begin(); - script != user_scripts->end(); - ++script) { - if (added_script_ids.count(script->id()) == 0) - continue; - scoped_ptr<UserScriptLoader::SubstitutionMap> localization_messages( - GetLocalizationMessages(hosts_info, script->host_id())); - for (size_t k = 0; k < script->js_scripts().size(); ++k) { - UserScript::File& script_file = script->js_scripts()[k]; - if (script_file.GetContent().empty()) - callback.Run(script->host_id(), &script_file, NULL, verifier); - } - for (size_t k = 0; k < script->css_scripts().size(); ++k) { - UserScript::File& script_file = script->css_scripts()[k]; - if (script_file.GetContent().empty()) - callback.Run(script->host_id(), &script_file, - localization_messages.get(), verifier); - } - } -} - -// Pickle user scripts and return pointer to the shared memory. -scoped_ptr<base::SharedMemory> Serialize(const UserScriptList& scripts) { - Pickle pickle; - pickle.WriteSizeT(scripts.size()); - for (UserScriptList::const_iterator script = scripts.begin(); - script != scripts.end(); - ++script) { - // TODO(aa): This can be replaced by sending content script metadata to - // renderers along with other extension data in ExtensionMsg_Loaded. - // See crbug.com/70516. - script->Pickle(&pickle); - // Write scripts as 'data' so that we can read it out in the slave without - // allocating a new string. - for (size_t j = 0; j < script->js_scripts().size(); j++) { - base::StringPiece contents = script->js_scripts()[j].GetContent(); - pickle.WriteData(contents.data(), contents.length()); - } - for (size_t j = 0; j < script->css_scripts().size(); j++) { - base::StringPiece contents = script->css_scripts()[j].GetContent(); - pickle.WriteData(contents.data(), contents.length()); - } - } - - // Create the shared memory object. - base::SharedMemory shared_memory; - - base::SharedMemoryCreateOptions options; - options.size = pickle.size(); - options.share_read_only = true; - if (!shared_memory.Create(options)) - return scoped_ptr<base::SharedMemory>(); - - if (!shared_memory.Map(pickle.size())) - return scoped_ptr<base::SharedMemory>(); - - // Copy the pickle to shared memory. - memcpy(shared_memory.memory(), pickle.data(), pickle.size()); - - base::SharedMemoryHandle readonly_handle; - if (!shared_memory.ShareReadOnlyToProcess(base::GetCurrentProcessHandle(), - &readonly_handle)) - return scoped_ptr<base::SharedMemory>(); - - return make_scoped_ptr(new base::SharedMemory(readonly_handle, - /*read_only=*/true)); -} - -void LoadScriptsOnFileThread( - scoped_ptr<UserScriptList> user_scripts, - const UserScriptLoader::HostsInfo& hosts_info, - const std::set<int>& added_script_ids, - const scoped_refptr<ContentVerifier>& verifier, - UserScriptLoader::LoadUserScriptsContentFunction function, - LoadScriptsCallback callback) { - DCHECK(user_scripts.get()); - LoadUserScripts(user_scripts.get(), hosts_info, added_script_ids, - verifier, function); - scoped_ptr<base::SharedMemory> memory = Serialize(*user_scripts); - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(callback, base::Passed(&user_scripts), base::Passed(&memory))); -} - // Helper function to parse greasesmonkey headers bool GetDeclarationValue(const base::StringPiece& line, const base::StringPiece& prefix, @@ -250,30 +139,14 @@ return true; } -void UserScriptLoader::LoadScriptsForTest(UserScriptList* user_scripts) { - HostsInfo info; - std::set<int> added_script_ids; - for (UserScriptList::iterator it = user_scripts->begin(); - it != user_scripts->end(); - ++it) { - added_script_ids.insert(it->id()); - } - LoadUserScripts(user_scripts, info, added_script_ids, - NULL /* no verifier for testing */, - GetLoadUserScriptsFunction()); -} - -UserScriptLoader::UserScriptLoader( - BrowserContext* browser_context, - const HostID& host_id, - const scoped_refptr<ContentVerifier>& content_verifier) +UserScriptLoader::UserScriptLoader(BrowserContext* browser_context, + const HostID& host_id) : user_scripts_(new UserScriptList()), clear_scripts_(false), ready_(false), pending_load_(false), browser_context_(browser_context), host_id_(host_id), - content_verifier_(content_verifier), weak_factory_(this) { registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED, @@ -293,6 +166,12 @@ AttemptLoad(); } +void UserScriptLoader::AddScripts(const std::set<UserScript>& scripts, + int render_process_id, + int render_view_id) { + AddScripts(scripts); +} + void UserScriptLoader::RemoveScripts(const std::set<UserScript>& scripts) { for (std::set<UserScript>::const_iterator it = scripts.begin(); it != scripts.end(); @@ -382,32 +261,60 @@ for (const UserScript& script : changed_scripts) changed_hosts_.insert(script.host_id()); - // |changed_hosts_| before passing it to LoadScriptsOnFileThread. - UpdateHostsInfo(changed_hosts_); - - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&LoadScriptsOnFileThread, base::Passed(&user_scripts_), - hosts_info_, added_script_ids, content_verifier_, - GetLoadUserScriptsFunction(), - base::Bind(&UserScriptLoader::OnScriptsLoaded, - weak_factory_.GetWeakPtr()))); + LoadScripts(user_scripts_.Pass(), changed_hosts_, added_script_ids, + base::Bind(&UserScriptLoader::OnScriptsLoaded, + weak_factory_.GetWeakPtr())); clear_scripts_ = false; added_scripts_.clear(); removed_scripts_.clear(); - user_scripts_.reset(NULL); + user_scripts_.reset(); } -void UserScriptLoader::AddHostInfo(const HostID& host_id, - const PathAndDefaultLocale& location) { - if (hosts_info_.find(host_id) != hosts_info_.end()) - return; - hosts_info_[host_id] = location; -} +// static +scoped_ptr<base::SharedMemory> UserScriptLoader::Serialize( + const UserScriptList& scripts) { + Pickle pickle; + pickle.WriteSizeT(scripts.size()); + for (const UserScript& script : scripts) { + // TODO(aa): This can be replaced by sending content script metadata to + // renderers along with other extension data in ExtensionMsg_Loaded. + // See crbug.com/70516. + script.Pickle(&pickle); + // Write scripts as 'data' so that we can read it out in the slave without + // allocating a new string. + for (const UserScript::File& script_file : script.js_scripts()) { + base::StringPiece contents = script_file.GetContent(); + pickle.WriteData(contents.data(), contents.length()); + } + for (const UserScript::File& script_file : script.css_scripts()) { + base::StringPiece contents = script_file.GetContent(); + pickle.WriteData(contents.data(), contents.length()); + } + } -void UserScriptLoader::RemoveHostInfo(const HostID& host_id) { - hosts_info_.erase(host_id); + // Create the shared memory object. + base::SharedMemory shared_memory; + + base::SharedMemoryCreateOptions options; + options.size = pickle.size(); + options.share_read_only = true; + if (!shared_memory.Create(options)) + return scoped_ptr<base::SharedMemory>(); + + if (!shared_memory.Map(pickle.size())) + return scoped_ptr<base::SharedMemory>(); + + // Copy the pickle to shared memory. + memcpy(shared_memory.memory(), pickle.data(), pickle.size()); + + base::SharedMemoryHandle readonly_handle; + if (!shared_memory.ShareReadOnlyToProcess(base::GetCurrentProcessHandle(), + &readonly_handle)) + return scoped_ptr<base::SharedMemory>(); + + return make_scoped_ptr(new base::SharedMemory(readonly_handle, + /*read_only=*/true)); } void UserScriptLoader::SetReady(bool ready) {
diff --git a/extensions/browser/user_script_loader.h b/extensions/browser/user_script_loader.h index c800933c..1eeea31 100644 --- a/extensions/browser/user_script_loader.h +++ b/extensions/browser/user_script_loader.h
@@ -29,8 +29,6 @@ namespace extensions { -class ContentVerifier; - // Manages one "logical unit" of user scripts in shared memory by constructing a // new shared memory region when the set of scripts changes. Also notifies // renderers of new shared memory region when new renderers appear, or when @@ -40,32 +38,31 @@ // scripts to load/unload on this logical unit of scripts. class UserScriptLoader : public content::NotificationObserver { public: - using PathAndDefaultLocale = std::pair<base::FilePath, std::string>; - using HostsInfo = std::map<HostID, PathAndDefaultLocale>; - - using SubstitutionMap = std::map<std::string, std::string>; - using LoadUserScriptsContentFunction = - base::Callback<bool(const HostID&, - UserScript::File*, - const SubstitutionMap*, - const scoped_refptr<ContentVerifier>&)>; + using LoadScriptsCallback = + base::Callback<void(scoped_ptr<UserScriptList>, + scoped_ptr<base::SharedMemory>)>; // Parses the includes out of |script| and returns them in |includes|. static bool ParseMetadataHeader(const base::StringPiece& script_text, UserScript* script); UserScriptLoader(content::BrowserContext* browser_context, - const HostID& host_id, - const scoped_refptr<ContentVerifier>& content_verifier); + const HostID& host_id); ~UserScriptLoader() override; - // A wrapper around the method to load user scripts, which is normally run on - // the file thread. Exposed only for tests. - void LoadScriptsForTest(UserScriptList* user_scripts); - // Add |scripts| to the set of scripts managed by this loader. void AddScripts(const std::set<UserScript>& scripts); + // Add |scripts| to the set of scripts managed by this loader. + // The fetch of the content of the script starts URL request + // to the associated render specified by + // |render_process_id, render_view_id|. + // TODO(hanxi): The renderer information doesn't really belong in this base + // class, but it's not an easy fix. + virtual void AddScripts(const std::set<UserScript>& scripts, + int render_process_id, + int render_view_id); + // Remove |scripts| from the set of scripts managed by this loader. void RemoveScripts(const std::set<UserScript>& scripts); @@ -78,24 +75,16 @@ // Returns true if we have any scripts ready. bool scripts_ready() const { return shared_memory_.get() != NULL; } + // Pickle user scripts and return pointer to the shared memory. + static scoped_ptr<base::SharedMemory> Serialize( + const extensions::UserScriptList& scripts); + protected: - // Updates |hosts_info_| to contain info for each element of - // |changed_hosts_|. - virtual void UpdateHostsInfo(const std::set<HostID>& changed_hosts) = 0; - - // Returns a function pointer of a static funcion to load user scripts. - // Derived classes can specify their ways to load scripts in the static - // function they return. - // Note: It has to be safe to call multiple times. - virtual LoadUserScriptsContentFunction GetLoadUserScriptsFunction() = 0; - - // Adds the |host_id, location| to the |hosts_info_| map. - // Only inserts the entry to the map when the given host_id doesn't - // exists. - void AddHostInfo(const HostID& host_id, const PathAndDefaultLocale& location); - - // Removes the entries with the given host_id from the |hosts_info_| map. - void RemoveHostInfo(const HostID& host_id); + // Allows the derived classes have different ways to load user scripts. + virtual void LoadScripts(scoped_ptr<UserScriptList> user_scripts, + const std::set<HostID>& changed_hosts, + const std::set<int>& added_script_ids, + LoadScriptsCallback callback) = 0; // Sets the flag if the initial set of hosts has finished loading; if it's // set to be true, calls AttempLoad() to bootstrap. @@ -144,9 +133,6 @@ // List of scripts from currently-installed extensions we should load. scoped_ptr<UserScriptList> user_scripts_; - // Maps host info needed for localization to a host ID. - HostsInfo hosts_info_; - // The mutually-exclusive sets of scripts that were added or removed since the // last script load. std::set<UserScript> added_scripts_; @@ -178,9 +164,6 @@ // non-empty value for declarative user script shared memory regions. HostID host_id_; - // Manages content verification of the loaded user scripts. - scoped_refptr<ContentVerifier> content_verifier_; - base::WeakPtrFactory<UserScriptLoader> weak_factory_; DISALLOW_COPY_AND_ASSIGN(UserScriptLoader);
diff --git a/extensions/browser/web_ui_user_script_loader.cc b/extensions/browser/web_ui_user_script_loader.cc new file mode 100644 index 0000000..73b0c9a46 --- /dev/null +++ b/extensions/browser/web_ui_user_script_loader.cc
@@ -0,0 +1,151 @@ +// 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 "extensions/browser/web_ui_user_script_loader.h" + +#include "base/bind.h" +#include "base/strings/string_util.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" +#include "extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h" + +namespace { + +void SerializeOnFileThread( + scoped_ptr<extensions::UserScriptList> user_scripts, + extensions::UserScriptLoader::LoadScriptsCallback callback) { + scoped_ptr<base::SharedMemory> memory = + extensions::UserScriptLoader::Serialize(*user_scripts); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(callback, base::Passed(&user_scripts), base::Passed(&memory))); +} + +} // namespace + +struct WebUIUserScriptLoader::UserScriptRenderInfo { + int render_process_id; + int render_view_id; + + UserScriptRenderInfo() : render_process_id(-1), render_view_id(-1) {} + + UserScriptRenderInfo(int render_process_id, int render_view_id) + : render_process_id(render_process_id), render_view_id(render_view_id) {} +}; + +WebUIUserScriptLoader::WebUIUserScriptLoader( + content::BrowserContext* browser_context, + const HostID& host_id) + : UserScriptLoader(browser_context, host_id), complete_fetchers_(0) { + SetReady(true); +} + +WebUIUserScriptLoader::~WebUIUserScriptLoader() { +} + +void WebUIUserScriptLoader::AddScripts( + const std::set<extensions::UserScript>& scripts, + int render_process_id, + int render_view_id) { + UserScriptRenderInfo info(render_process_id, render_view_id); + for (const extensions::UserScript& script : scripts) { + script_render_info_map_.insert( + std::pair<int, UserScriptRenderInfo>(script.id(), info)); + } + + extensions::UserScriptLoader::AddScripts(scripts); +} + +void WebUIUserScriptLoader::LoadScripts( + scoped_ptr<extensions::UserScriptList> user_scripts, + const std::set<HostID>& changed_hosts, + const std::set<int>& added_script_ids, + LoadScriptsCallback callback) { + user_scripts_cache_.swap(user_scripts); + scripts_loaded_callback_ = callback; + + // The total number of the tasks is used to trace whether all the fetches + // are complete. Therefore, we store all the fetcher pointers in |fetchers_| + // before we get theis number. Once we get the total number, start each + // fetch tasks. + DCHECK_EQ(0u, complete_fetchers_); + + for (extensions::UserScript& script : *user_scripts_cache_) { + if (added_script_ids.count(script.id()) == 0) + continue; + + auto iter = script_render_info_map_.find(script.id()); + DCHECK(iter != script_render_info_map_.end()); + int render_process_id = iter->second.render_process_id; + int render_view_id = iter->second.render_view_id; + + content::BrowserContext* browser_context = + content::RenderProcessHost::FromID(render_process_id) + ->GetBrowserContext(); + + CreateWebUIURLFetchers(&script.js_scripts(), browser_context, + render_process_id, render_view_id); + CreateWebUIURLFetchers(&script.css_scripts(), browser_context, + render_process_id, render_view_id); + + script_render_info_map_.erase(script.id()); + } + + // If no fetch is needed, call OnWebUIURLFetchComplete directly. + if (fetchers_.empty()) { + OnWebUIURLFetchComplete(); + return; + } + for (auto fetcher : fetchers_) + fetcher->Start(); +} + +void WebUIUserScriptLoader::CreateWebUIURLFetchers( + extensions::UserScript::FileList* script_files, + content::BrowserContext* browser_context, + int render_process_id, + int render_view_id) { + for (extensions::UserScript::File& file : *script_files) { + if (file.GetContent().empty()) { + // The WebUIUserScriptLoader owns these WebUIURLFetchers. Once the + // loader is destroyed, all the fetchers will be destroyed. Therefore, + // we are sure it is safe to use base::Unretained(this) here. + scoped_ptr<WebUIURLFetcher> fetcher(new WebUIURLFetcher( + browser_context, render_process_id, render_view_id, file.url(), + base::Bind(&WebUIUserScriptLoader::OnSingleWebUIURLFetchComplete, + base::Unretained(this), &file))); + fetchers_.push_back(fetcher.release()); + } + } +} + +void WebUIUserScriptLoader::OnSingleWebUIURLFetchComplete( + extensions::UserScript::File* script_file, + bool success, + const std::string& data) { + if (success) { + // Remove BOM from the content. + std::string::size_type index = data.find(base::kUtf8ByteOrderMark); + if (index == 0) + script_file->set_content(data.substr(strlen(base::kUtf8ByteOrderMark))); + else + script_file->set_content(data); + } + + ++complete_fetchers_; + if (complete_fetchers_ == fetchers_.size()) { + complete_fetchers_ = 0; + OnWebUIURLFetchComplete(); + fetchers_.clear(); + } +} + +void WebUIUserScriptLoader::OnWebUIURLFetchComplete() { + content::BrowserThread::PostTask( + content::BrowserThread::FILE, FROM_HERE, + base::Bind(&SerializeOnFileThread, base::Passed(&user_scripts_cache_), + scripts_loaded_callback_)); + scripts_loaded_callback_.Reset(); +}
diff --git a/extensions/browser/web_ui_user_script_loader.h b/extensions/browser/web_ui_user_script_loader.h new file mode 100644 index 0000000..f74ef00 --- /dev/null +++ b/extensions/browser/web_ui_user_script_loader.h
@@ -0,0 +1,72 @@ +// 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 EXTENSIONS_BROWSER_WEB_UI_USER_SCRIPT_LOADER_H_ +#define EXTENSIONS_BROWSER_WEB_UI_USER_SCRIPT_LOADER_H_ + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "extensions/browser/user_script_loader.h" + +class WebUIURLFetcher; + +namespace content { +class BrowserContext; +} + +// UserScriptLoader for WebUI. +class WebUIUserScriptLoader : public extensions::UserScriptLoader { + public: + WebUIUserScriptLoader(content::BrowserContext* browser_context, + const HostID& host_id); + ~WebUIUserScriptLoader() override; + + private: + struct UserScriptRenderInfo; + using UserScriptRenderInfoMap = std::map<int, UserScriptRenderInfo>; + + // UserScriptLoader: + void AddScripts(const std::set<extensions::UserScript>& scripts, + int render_process_id, + int render_view_id) override; + void LoadScripts(scoped_ptr<extensions::UserScriptList> user_scripts, + const std::set<HostID>& changed_hosts, + const std::set<int>& added_script_ids, + LoadScriptsCallback callback) override; + + // Called at the end of each fetch, tracking whether all fetches are done. + void OnSingleWebUIURLFetchComplete(extensions::UserScript::File* script_file, + bool success, + const std::string& data); + + // Called when the loads of the user scripts are done. + void OnWebUIURLFetchComplete(); + + // Creates WebUiURLFetchers for the given |script_files|. + void CreateWebUIURLFetchers(extensions::UserScript::FileList* script_files, + content::BrowserContext* browser_context, + int render_process_id, + int render_view_id); + + // Caches the render info of script from WebUI when AddScripts is called. + // When starting to load the script, we look up this map to retrieve the + // render info. It is used for the script from WebUI only, since the fetch + // of script content requires the info of associated render. + UserScriptRenderInfoMap script_render_info_map_; + + // The number of complete fetchs. + size_t complete_fetchers_; + + // Caches |user_scripts_| from UserScriptLoader when loading. + scoped_ptr<extensions::UserScriptList> user_scripts_cache_; + + LoadScriptsCallback scripts_loaded_callback_; + + ScopedVector<WebUIURLFetcher> fetchers_; + + DISALLOW_COPY_AND_ASSIGN(WebUIUserScriptLoader); +}; + +#endif // EXTENSIONS_BROWSER_WEB_UI_USER_SCRIPT_LOADER_H_
diff --git a/extensions/common/BUILD.gn b/extensions/common/BUILD.gn index 1718727..03e194c6 100644 --- a/extensions/common/BUILD.gn +++ b/extensions/common/BUILD.gn
@@ -26,7 +26,10 @@ } # GYP version: extensions/extensions.gyp:extensions_common - source_set("common") { + # This must be a static library because extensions common depends on + # GetTrustedICAPublicKey in extensions/browser which isn't always linked + # in. TODO(brettw): This reverse dependency should be fixed. + static_library("common") { sources = rebase_path(extensions_gypi_values.extensions_common_sources, ".", "//extensions") @@ -63,17 +66,16 @@ ] if (use_openssl) { - ssl_sources = + sources += rebase_path(extensions_gypi_values.extensions_common_sources_openssl, ".", "//extensions") - sources += ssl_sources + deps += [ "//third_party/boringssl" ] } else { - nonssl_sources = rebase_path( + sources += rebase_path( extensions_gypi_values.extensions_common_sources_nonopenssl, ".", "//extensions") - sources += nonssl_sources } if (enable_nacl) {
diff --git a/extensions/common/api/_manifest_features.json b/extensions/common/api/_manifest_features.json index 8a1966d8..68a02d8 100644 --- a/extensions/common/api/_manifest_features.json +++ b/extensions/common/api/_manifest_features.json
@@ -90,7 +90,9 @@ "channel": "stable", "extension_types": ["extension"], "whitelist": [ - "950D13BB9B4794F4CA2A68D3597E5DFAA47C88AE" // Drive + "950D13BB9B4794F4CA2A68D3597E5DFAA47C88AE", // Drive + "0EEB39B7A9A52CAAE6A072F83320435749B184A4", // http://crbug.com/481210 + "D4AF239830E1E038C9B60DA365B1EC9CB3BC5658" // http://crbug.com/481210 ] }, { "channel": "canary",
diff --git a/extensions/common/api/web_view_internal.json b/extensions/common/api/web_view_internal.json index a2d679b..b6c425a7 100644 --- a/extensions/common/api/web_view_internal.json +++ b/extensions/common/api/web_view_internal.json
@@ -95,11 +95,6 @@ "enum": ["allow", "deny", "default"] }, { - "id": "RunLocation", - "type": "string", - "enum": ["document_start", "document_end", "document_idle"] - }, - { "id": "ContentScriptDetails", "type": "object", "description": "Details of the content script to inject.", @@ -136,9 +131,13 @@ "optional": true, "description": "The list of JavaScript files to be injected into matching pages. These are injected in the order they appear in this array." }, + "code": { + "type": "string", + "optional": true, + "description": "JavaScript code to be injected into matching pages." + }, "run_at": { - // TODO(hanxi): change the reference to extensionTypes.RunAt after http://crbug.com/477457 is fixed. - "$ref": "RunLocation", + "$ref": "extensionTypes.RunAt", "optional": true, "description": "The soonest that the JavaScript or CSS will be injected into the tab. Defaults to \"document_idle\"." },
diff --git a/extensions/common/extension_messages.cc b/extensions/common/extension_messages.cc index 41b8023..e7fdb51e 100644 --- a/extensions/common/extension_messages.cc +++ b/extensions/common/extension_messages.cc
@@ -60,8 +60,8 @@ id(extension->id()), creation_flags(extension->creation_flags()) { if (include_tab_permissions) { - const extensions::PermissionsData::TabPermissionsMap& tab_permissions = - extension->permissions_data()->tab_specific_permissions(); + extensions::PermissionsData::TabPermissionsMap tab_permissions = + extension->permissions_data()->CopyTabSpecificPermissionsMap(); for (const auto& pair : tab_permissions) { tab_specific_permissions[pair.first] = ExtensionMsg_PermissionSetStruct(*pair.second);
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h index 28b7c97f..64187e8b 100644 --- a/extensions/common/permissions/api_permission.h +++ b/extensions/common/permissions/api_permission.h
@@ -56,6 +56,7 @@ kAudio, kAudioCapture, kAudioModem, + kAutofillPrivate, kAutomation, kAutoTestPrivate, kBackground, @@ -167,6 +168,7 @@ kReadingListPrivate, kRtcPrivate, kSearchProvider, + kSearchEnginesPrivate, kSerial, kSessions, kSettingsPrivate,
diff --git a/extensions/common/permissions/permission_message.h b/extensions/common/permissions/permission_message.h index b783b3d9..b24c50eb 100644 --- a/extensions/common/permissions/permission_message.h +++ b/extensions/common/permissions/permission_message.h
@@ -105,6 +105,8 @@ kInterceptAllKeys, kSettingsPrivate, kPrinterProvider, + kSearchEnginesPrivate, + kAutofillPrivate, // Last entry: Add new entries above and ensure to update the // "ExtensionPermission2" enum in tools/metrics/histograms/histograms.xml. kEnumBoundary,
diff --git a/extensions/common/permissions/permission_message_provider.cc b/extensions/common/permissions/permission_message_provider.cc index f194340..d4c3025 100644 --- a/extensions/common/permissions/permission_message_provider.cc +++ b/extensions/common/permissions/permission_message_provider.cc
@@ -20,7 +20,7 @@ return g_force_permission_system_for_testing == ForceForTesting::FORCE_NEW; const std::string group_name = base::FieldTrialList::FindFullName("PermissionMessageSystem"); - return group_name == "NewSystem"; + return group_name != "OldSystem"; } } // namespace
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc index fb909d0..0488f0a1 100644 --- a/extensions/common/permissions/permissions_data.cc +++ b/extensions/common/permissions/permissions_data.cc
@@ -320,6 +320,12 @@ return false; } +PermissionsData::TabPermissionsMap +PermissionsData::CopyTabSpecificPermissionsMap() const { + base::AutoLock auto_lock(runtime_lock_); + return tab_specific_permissions_; +} + scoped_refptr<const PermissionSet> PermissionsData::GetTabSpecificPermissions( int tab_id) const { base::AutoLock auto_lock(runtime_lock_);
diff --git a/extensions/common/permissions/permissions_data.h b/extensions/common/permissions/permissions_data.h index e0f9b10..6a84566 100644 --- a/extensions/common/permissions/permissions_data.h +++ b/extensions/common/permissions/permissions_data.h
@@ -201,24 +201,21 @@ // page itself. bool CanCaptureVisiblePage(int tab_id, std::string* error) const; - const scoped_refptr<const PermissionSet>& active_permissions() const { + // Returns the tab permissions map. + TabPermissionsMap CopyTabSpecificPermissionsMap() const; + + scoped_refptr<const PermissionSet> active_permissions() const { // We lock so that we can't also be setting the permissions while returning. base::AutoLock auto_lock(runtime_lock_); return active_permissions_unsafe_; } - const scoped_refptr<const PermissionSet>& withheld_permissions() const { + scoped_refptr<const PermissionSet> withheld_permissions() const { // We lock so that we can't also be setting the permissions while returning. base::AutoLock auto_lock(runtime_lock_); return withheld_permissions_unsafe_; } - const TabPermissionsMap& tab_specific_permissions() const { - // We lock so that we can't also be setting the permissions while returning. - base::AutoLock auto_lock(runtime_lock_); - return tab_specific_permissions_; - } - #if defined(UNIT_TEST) scoped_refptr<const PermissionSet> GetTabSpecificPermissionsForTesting( int tab_id) const {
diff --git a/extensions/common/permissions/set_disjunction_permission.h b/extensions/common/permissions/set_disjunction_permission.h index 20bc3ea..87d1858 100644 --- a/extensions/common/permissions/set_disjunction_permission.h +++ b/extensions/common/permissions/set_disjunction_permission.h
@@ -31,12 +31,12 @@ explicit SetDisjunctionPermission(const APIPermissionInfo* info) : APIPermission(info) {} - ~SetDisjunctionPermission() {} + ~SetDisjunctionPermission() override {} // APIPermission overrides - virtual bool HasMessages() const override { return !data_set_.empty(); } + bool HasMessages() const override { return !data_set_.empty(); } - virtual bool Check(const APIPermission::CheckParam* param) const override { + bool Check(const APIPermission::CheckParam* param) const override { for (typename std::set<PermissionDataType>::const_iterator i = data_set_.begin(); i != data_set_.end(); @@ -47,7 +47,7 @@ return false; } - virtual bool Contains(const APIPermission* rhs) const override { + bool Contains(const APIPermission* rhs) const override { CHECK(rhs->info() == info()); const SetDisjunctionPermission* perm = static_cast<const SetDisjunctionPermission*>(rhs); @@ -55,20 +55,20 @@ data_set_, perm->data_set_); } - virtual bool Equal(const APIPermission* rhs) const override { + bool Equal(const APIPermission* rhs) const override { CHECK(rhs->info() == info()); const SetDisjunctionPermission* perm = static_cast<const SetDisjunctionPermission*>(rhs); return data_set_ == perm->data_set_; } - virtual APIPermission* Clone() const override { + APIPermission* Clone() const override { SetDisjunctionPermission* result = new DerivedType(info()); result->data_set_ = data_set_; return result; } - virtual APIPermission* Diff(const APIPermission* rhs) const override { + APIPermission* Diff(const APIPermission* rhs) const override { CHECK(rhs->info() == info()); const SetDisjunctionPermission* perm = static_cast<const SetDisjunctionPermission*>(rhs); @@ -78,7 +78,7 @@ return result->data_set_.empty() ? NULL : result.release(); } - virtual APIPermission* Union(const APIPermission* rhs) const override { + APIPermission* Union(const APIPermission* rhs) const override { CHECK(rhs->info() == info()); const SetDisjunctionPermission* perm = static_cast<const SetDisjunctionPermission*>(rhs); @@ -88,7 +88,7 @@ return result.release(); } - virtual APIPermission* Intersect(const APIPermission* rhs) const override { + APIPermission* Intersect(const APIPermission* rhs) const override { CHECK(rhs->info() == info()); const SetDisjunctionPermission* perm = static_cast<const SetDisjunctionPermission*>(rhs); @@ -98,7 +98,7 @@ return result->data_set_.empty() ? NULL : result.release(); } - virtual bool FromValue( + bool FromValue( const base::Value* value, std::string* error, std::vector<std::string>* unhandled_permissions) override { @@ -137,7 +137,7 @@ return true; } - virtual scoped_ptr<base::Value> ToValue() const override { + scoped_ptr<base::Value> ToValue() const override { base::ListValue* list = new base::ListValue(); typename std::set<PermissionDataType>::const_iterator i; for (i = data_set_.begin(); i != data_set_.end(); ++i) { @@ -147,15 +147,15 @@ return scoped_ptr<base::Value>(list); } - virtual void Write(IPC::Message* m) const override { + void Write(IPC::Message* m) const override { IPC::WriteParam(m, data_set_); } - virtual bool Read(const IPC::Message* m, PickleIterator* iter) override { + bool Read(const IPC::Message* m, PickleIterator* iter) override { return IPC::ReadParam(m, iter, &data_set_); } - virtual void Log(std::string* log) const override { + void Log(std::string* log) const override { IPC::LogParam(data_set_, log); }
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp index 4c12f71c..a0578394 100644 --- a/extensions/extensions.gyp +++ b/extensions/extensions.gyp
@@ -124,6 +124,7 @@ 'dependencies': [ '../base/base.gyp:base', '../base/base.gyp:base_prefs', + '../components/components.gyp:browsing_data', '../components/components.gyp:device_event_log_component', '../components/components.gyp:keyed_service_content', '../components/components.gyp:keyed_service_core',
diff --git a/extensions/extensions.gypi b/extensions/extensions.gypi index 79630432..fc2f567 100644 --- a/extensions/extensions.gypi +++ b/extensions/extensions.gypi
@@ -244,8 +244,6 @@ 'browser/api/app_current_window_internal/app_current_window_internal_api.h', 'browser/api/app_runtime/app_runtime_api.cc', 'browser/api/app_runtime/app_runtime_api.h', - 'browser/api/guest_view/app_view/app_view_guest_internal_api.cc', - 'browser/api/guest_view/app_view/app_view_guest_internal_api.h', 'browser/api/app_window/app_window_api.cc', 'browser/api/app_window/app_window_api.h', 'browser/api/async_api_function.cc', @@ -343,12 +341,16 @@ 'browser/api/document_scan/document_scan_interface_chromeos.cc', 'browser/api/execute_code_function.cc', 'browser/api/execute_code_function.h', - 'browser/api/guest_view/extension_view/extension_view_internal_api.cc', - 'browser/api/guest_view/extension_view/extension_view_internal_api.h', 'browser/api/extensions_api_client.cc', 'browser/api/extensions_api_client.h', + 'browser/api/guest_view/app_view/app_view_guest_internal_api.cc', + 'browser/api/guest_view/app_view/app_view_guest_internal_api.h', + 'browser/api/guest_view/extension_view/extension_view_internal_api.cc', + 'browser/api/guest_view/extension_view/extension_view_internal_api.h', 'browser/api/guest_view/guest_view_internal_api.cc', 'browser/api/guest_view/guest_view_internal_api.h', + 'browser/api/guest_view/web_view/web_view_internal_api.cc', + 'browser/api/guest_view/web_view/web_view_internal_api.h', 'browser/api/hid/hid_api.cc', 'browser/api/hid/hid_api.h', 'browser/api/hid/hid_connection_resource.cc', @@ -499,8 +501,6 @@ 'browser/api/web_request/web_request_permissions.h', 'browser/api/web_request/web_request_time_tracker.cc', 'browser/api/web_request/web_request_time_tracker.h', - 'browser/api/guest_view/web_view/web_view_internal_api.cc', - 'browser/api/guest_view/web_view/web_view_internal_api.h', 'browser/api/webcam_private/webcam_private_api.h', 'browser/api/webcam_private/webcam_private_api_chromeos.cc', 'browser/api_activity_monitor.h', @@ -551,8 +551,6 @@ 'browser/declarative_user_script_manager.h', 'browser/declarative_user_script_master.cc', 'browser/declarative_user_script_master.h', - 'browser/extension_user_script_loader.cc', - 'browser/extension_user_script_loader.h', 'browser/deferred_start_render_host.h', 'browser/deferred_start_render_host_observer.h', 'browser/error_map.cc', @@ -604,6 +602,8 @@ 'browser/extension_system.h', 'browser/extension_system_provider.cc', 'browser/extension_system_provider.h', + 'browser/extension_user_script_loader.cc', + 'browser/extension_user_script_loader.h', 'browser/extension_util.cc', 'browser/extension_util.h', 'browser/extension_web_contents_observer.cc', @@ -637,6 +637,8 @@ 'browser/guest_view/extension_view/extension_view_guest.h', 'browser/guest_view/extension_view/extension_view_guest_delegate.cc', 'browser/guest_view/extension_view/extension_view_guest_delegate.h', + 'browser/guest_view/extensions_guest_view_manager_delegate.cc', + 'browser/guest_view/extensions_guest_view_manager_delegate.h', 'browser/guest_view/extensions_guest_view_message_filter.cc', 'browser/guest_view/extensions_guest_view_message_filter.h', 'browser/guest_view/guest_view.h', @@ -646,6 +648,7 @@ 'browser/guest_view/guest_view_event.h', 'browser/guest_view/guest_view_manager.cc', 'browser/guest_view/guest_view_manager.h', + 'browser/guest_view/guest_view_manager_delegate.h', 'browser/guest_view/guest_view_manager_factory.h', 'browser/guest_view/guest_view_message_filter.cc', 'browser/guest_view/guest_view_message_filter.h', @@ -663,6 +666,8 @@ 'browser/guest_view/surface_worker/surface_worker_guest.h', 'browser/guest_view/web_view/javascript_dialog_helper.cc', 'browser/guest_view/web_view/javascript_dialog_helper.h', + 'browser/guest_view/web_view/web_ui/web_ui_url_fetcher.cc', + 'browser/guest_view/web_view/web_ui/web_ui_url_fetcher.h', 'browser/guest_view/web_view/web_view_constants.cc', 'browser/guest_view/web_view/web_view_constants.h', 'browser/guest_view/web_view/web_view_content_script_manager.cc', @@ -782,6 +787,8 @@ 'browser/warning_service_factory.h', 'browser/warning_set.cc', 'browser/warning_set.h', + 'browser/web_ui_user_script_loader.cc', + 'browser/web_ui_user_script_loader.h', ], 'extensions_browser_sources_chromeos': [ 'browser/api/audio/audio_service_chromeos.cc', @@ -948,10 +955,10 @@ 'renderer/script_context.h', 'renderer/script_context_set.cc', 'renderer/script_context_set.h', - 'renderer/script_injection_callback.cc', - 'renderer/script_injection_callback.h', 'renderer/script_injection.cc', 'renderer/script_injection.h', + 'renderer/script_injection_callback.cc', + 'renderer/script_injection_callback.h', 'renderer/script_injection_manager.cc', 'renderer/script_injection_manager.h', 'renderer/script_injector.h',
diff --git a/extensions/extensions_strings.grd b/extensions/extensions_strings.grd index fec2b34..b91c5f6 100644 --- a/extensions/extensions_strings.grd +++ b/extensions/extensions_strings.grd
@@ -341,10 +341,10 @@ <message name="IDS_DEVICE_PERMISSIONS_DEVICE_NAME" desc="String describing a device in a list of devices."> <ph name="PRODUCT_NAME">$1<ex>SoundKnob</ex></ph> from <ph name="VENDOR_NAME">$2<ex>Griffin Technology</ex></ph> </message> - <message name="IDS_DEVICE_PERMISSIONS_PROMPT_TITLE_SINGLE" desc="Title of the device selection dialog when the app wants only one device selected."> + <message name="IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE_SINGLE" desc="Title of the USB device selection dialog when the app wants only one device selected."> Select a USB device </message> - <message name="IDS_DEVICE_PERMISSIONS_PROMPT_TITLE_MULTIPLE" desc="Title of the device selection dialog when the app will accept one or more selected devices."> + <message name="IDS_USB_DEVICE_PERMISSIONS_PROMPT_TITLE_MULTIPLE" desc="Title of the USB device selection dialog when the app will accept one or more selected devices."> Select USB devices </message> <message name="IDS_DEVICE_PERMISSIONS_PROMPT_SINGLE" desc="Instructions asking the user to select one device for use with an app.">
diff --git a/extensions/renderer/BUILD.gn b/extensions/renderer/BUILD.gn index 1bfceef..19e894f 100644 --- a/extensions/renderer/BUILD.gn +++ b/extensions/renderer/BUILD.gn
@@ -24,5 +24,6 @@ "//skia", "//third_party/WebKit/public:blink", "//third_party/mojo/src/mojo/edk/js", + "//third_party/mojo/src/mojo/public/js", ] }
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 60cf879..e2821a9 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -380,37 +380,6 @@ request_sender_->HandleResponse(request_id, success, response, error); } -bool Dispatcher::CheckContextAccessToExtensionAPI( - const std::string& function_name, - ScriptContext* context) const { - if (!context) { - DLOG(ERROR) << "Not in a v8::Context"; - return false; - } - - // Theoretically we could end up with bindings being injected into sandboxed - // frames, for example content scripts. Don't let them execute API functions. - blink::WebFrame* frame = context->web_frame(); - if (ScriptContext::IsSandboxedPage( - extensions_, ScriptContext::GetDataSourceURLForFrame(frame))) { - static const char kMessage[] = - "%s cannot be used within a sandboxed frame."; - std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); - context->isolate()->ThrowException(v8::Exception::Error( - v8::String::NewFromUtf8(context->isolate(), error_msg.c_str()))); - return false; - } - - Feature::Availability availability = context->GetAvailability(function_name); - if (!availability.is_available()) { - context->isolate()->ThrowException( - v8::Exception::Error(v8::String::NewFromUtf8( - context->isolate(), availability.message().c_str()))); - } - - return availability.is_available(); -} - void Dispatcher::DispatchEvent(const std::string& extension_id, const std::string& event_name) const { base::ListValue args; @@ -657,8 +626,7 @@ scoped_ptr<NativeHandler>( new V8ContextNativeHandler(context, dispatcher))); module_system->RegisterNativeHandler( - "event_natives", - scoped_ptr<NativeHandler>(new EventBindings(dispatcher, context))); + "event_natives", scoped_ptr<NativeHandler>(new EventBindings(context))); module_system->RegisterNativeHandler( "messaging_natives", scoped_ptr<NativeHandler>(MessagingBindings::Get(dispatcher, context)));
diff --git a/extensions/renderer/dispatcher.h b/extensions/renderer/dispatcher.h index c71cb64..6b71722 100644 --- a/extensions/renderer/dispatcher.h +++ b/extensions/renderer/dispatcher.h
@@ -111,12 +111,6 @@ const base::ListValue& response, const std::string& error); - // Checks that the current context contains an extension that has permission - // to execute the specified function. If it does not, a v8 exception is thrown - // and the method returns false. Otherwise returns true. - bool CheckContextAccessToExtensionAPI(const std::string& function_name, - ScriptContext* context) const; - // Dispatches the event named |event_name| to all render views. void DispatchEvent(const std::string& extension_id, const std::string& event_name) const;
diff --git a/extensions/renderer/event_bindings.cc b/extensions/renderer/event_bindings.cc index 472f369..31fbffb7 100644 --- a/extensions/renderer/event_bindings.cc +++ b/extensions/renderer/event_bindings.cc
@@ -19,8 +19,8 @@ #include "extensions/common/extension_messages.h" #include "extensions/common/manifest_handlers/background_info.h" #include "extensions/common/value_counter.h" -#include "extensions/renderer/dispatcher.h" #include "extensions/renderer/extension_helper.h" +#include "extensions/renderer/script_context.h" #include "url/gurl.h" namespace extensions { @@ -136,8 +136,8 @@ } // namespace -EventBindings::EventBindings(Dispatcher* dispatcher, ScriptContext* context) - : ObjectBackedNativeHandler(context), dispatcher_(dispatcher) { +EventBindings::EventBindings(ScriptContext* context) + : ObjectBackedNativeHandler(context) { RouteFunction("AttachEvent", base::Bind(&EventBindings::AttachEventHandler, base::Unretained(this))); RouteFunction("DetachEvent", base::Bind(&EventBindings::DetachEventHandler, @@ -168,8 +168,7 @@ } void EventBindings::AttachEvent(const std::string& event_name) { - // This method throws an exception if it returns false. - if (!dispatcher_->CheckContextAccessToExtensionAPI(event_name, context())) + if (!context()->HasAccessOrThrowError(event_name)) return; // Record the attachment for this context so that events can be detached when @@ -239,9 +238,7 @@ CHECK(args[1]->IsObject()); std::string event_name = *v8::String::Utf8Value(args[0]); - - // This method throws an exception if it returns false. - if (!dispatcher_->CheckContextAccessToExtensionAPI(event_name, context())) + if (!context()->HasAccessOrThrowError(event_name)) return; std::string extension_id = context()->GetExtensionID();
diff --git a/extensions/renderer/event_bindings.h b/extensions/renderer/event_bindings.h index f5cfdcf..cf06692 100644 --- a/extensions/renderer/event_bindings.h +++ b/extensions/renderer/event_bindings.h
@@ -17,13 +17,12 @@ } namespace extensions { -class Dispatcher; class EventMatcher; // This class deals with the javascript bindings related to Event objects. class EventBindings : public ObjectBackedNativeHandler { public: - EventBindings(Dispatcher* dispatcher, ScriptContext* context); + explicit EventBindings(ScriptContext* context); ~EventBindings() override; private: @@ -72,8 +71,6 @@ // unload. std::set<std::string> attached_event_names_; - Dispatcher* dispatcher_; - DISALLOW_COPY_AND_ASSIGN(EventBindings); };
diff --git a/extensions/renderer/request_sender.cc b/extensions/renderer/request_sender.cc index 5797953..fe30fde 100644 --- a/extensions/renderer/request_sender.cc +++ b/extensions/renderer/request_sender.cc
@@ -93,7 +93,7 @@ } // TODO(koz): See if we can make this a CHECK. - if (!dispatcher_->CheckContextAccessToExtensionAPI(name, context)) + if (!context->HasAccessOrThrowError(name)) return; GURL source_url;
diff --git a/extensions/renderer/resources/binding.js b/extensions/renderer/resources/binding.js index 2c6b76a..cf671cb 100644 --- a/extensions/renderer/resources/binding.js +++ b/extensions/renderer/resources/binding.js
@@ -307,6 +307,10 @@ $String.replace(enumValue, /([a-z])([A-Z])/g, '$1_$2'); // Replace my_Enum-Foo with my_Enum_Foo: propertyName = $String.replace(propertyName, /\W/g, '_'); + // If the first character is a digit (we know it must be one of + // a digit, a letter, or an underscore), precede it with an + // underscore. + propertyName = $String.replace(propertyName, /^(\d)/g, '_$1'); // Uppercase (replace my_Enum_Foo with MY_ENUM_FOO): propertyName = $String.toUpperCase(propertyName); mod[id][propertyName] = enumValue;
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc index 9ed4c23f..aff0bb20 100644 --- a/extensions/renderer/script_context.cc +++ b/extensions/renderer/script_context.cc
@@ -8,6 +8,7 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/values.h" #include "content/public/child/v8_value_converter.h" #include "content/public/common/url_constants.h" @@ -120,9 +121,8 @@ // static bool ScriptContext::IsSandboxedPage(const ExtensionSet& extensions, const GURL& url) { - // TODO(kalman): This is checking for the wrong thing, it should be checking - // if the frame's security origin is unique. The extension sandbox directive - // is checked for in extensions/common/manifest_handlers/csp_info.cc. + // TODO(kalman): This is checking the wrong thing. See comment in + // HasAccessOrThrowError. if (url.SchemeIs(kExtensionScheme)) { const Extension* extension = extensions.GetByID(url.host()); if (extension) { @@ -336,8 +336,41 @@ return false; } +bool ScriptContext::HasAccessOrThrowError(const std::string& name) { + // Theoretically[1] we could end up with bindings being injected into + // sandboxed frames, for example content scripts. Don't let them execute API + // functions. + // + // In any case, this check is silly. The frame's document's security origin + // already tells us if it's sandboxed. The only problem is that until + // crbug.com/466373 is fixed, we don't know the security origin up-front and + // may not know it here, either. + // + // [1] citation needed. This ScriptContext should already be in a state that + // doesn't allow this, from ScriptContextSet::ClassifyJavaScriptContext. + if (extension() && + SandboxedPageInfo::IsSandboxedPage(extension(), url_.path())) { + static const char kMessage[] = + "%s cannot be used within a sandboxed frame."; + std::string error_msg = base::StringPrintf(kMessage, name.c_str()); + isolate()->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate(), error_msg.c_str()))); + return false; + } + + Feature::Availability availability = GetAvailability(name); + if (!availability.is_available()) { + isolate()->ThrowException(v8::Exception::Error( + v8::String::NewFromUtf8(isolate(), availability.message().c_str()))); + return false; + } + + return true; +} + ScriptContext::Runner::Runner(ScriptContext* context) : context_(context) { } + void ScriptContext::Runner::Run(const std::string& source, const std::string& resource_name) { context_->module_system()->RunString(source, resource_name);
diff --git a/extensions/renderer/script_context.h b/extensions/renderer/script_context.h index 569deaa..1f6ce40 100644 --- a/extensions/renderer/script_context.h +++ b/extensions/renderer/script_context.h
@@ -45,11 +45,10 @@ Feature::Context effective_context_type); ~ScriptContext() override; - // Returns whether |url| is sandboxed (as declared in any Extension in - // |extension_set| as sandboxed). - // - // Declared in ScriptContext for lack of a better place, but this should - // become unnecessary at some point as crbug.com/466373 is worked on. + // Returns whether |url| from any Extension in |extension_set| is sandboxed, + // as declared in each Extension's manifest. + // TODO(kalman): Delete this when crbug.com/466373 is fixed. + // See comment in HasAccessOrThrowError. static bool IsSandboxedPage(const ExtensionSet& extension_set, const GURL& url); @@ -174,6 +173,11 @@ // extension. bool HasAPIPermission(APIPermission::ID permission) const; + // Throws an Error in this context's JavaScript context, if this context does + // not have access to |name|. Returns true if this context has access (i.e. + // no exception thrown), false if it does not (i.e. an exception was thrown). + bool HasAccessOrThrowError(const std::string& name); + private: class Runner;
diff --git a/extensions/renderer/v8_schema_registry.h b/extensions/renderer/v8_schema_registry.h index 5a3b20c..b8c50ea 100644 --- a/extensions/renderer/v8_schema_registry.h +++ b/extensions/renderer/v8_schema_registry.h
@@ -40,7 +40,7 @@ v8::Handle<v8::Context> GetOrCreateContext(v8::Isolate* isolate); // Cache of schemas. Created lazily by GetOrCreateContext. - typedef v8::StdPersistentValueMap<std::string, v8::Object> SchemaCache; + typedef v8::StdGlobalValueMap<std::string, v8::Object> SchemaCache; scoped_ptr<SchemaCache> schema_cache_; // Single per-instance gin::ContextHolder to create v8::Values.
diff --git a/extensions/shell/browser/shell_browser_context.cc b/extensions/shell/browser/shell_browser_context.cc index 61aec77..827eabe 100644 --- a/extensions/shell/browser/shell_browser_context.cc +++ b/extensions/shell/browser/shell_browser_context.cc
@@ -35,7 +35,7 @@ } content::BrowserPluginGuestManager* ShellBrowserContext::GetGuestManager() { - return GuestViewManager::FromBrowserContextIfAvailable(this); + return GuestViewManager::FromBrowserContext(this); } storage::SpecialStoragePolicy* ShellBrowserContext::GetSpecialStoragePolicy() {
diff --git a/gin/interceptor_unittest.cc b/gin/interceptor_unittest.cc index 4d2d7fb8..af830d4 100644 --- a/gin/interceptor_unittest.cc +++ b/gin/interceptor_unittest.cc
@@ -118,7 +118,7 @@ int value_; - v8::StdPersistentValueMap<std::string, v8::FunctionTemplate> template_cache_; + v8::StdGlobalValueMap<std::string, v8::FunctionTemplate> template_cache_; DISALLOW_COPY_AND_ASSIGN(MyInterceptor); };
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc index 9ef41d3..9a68e0f 100644 --- a/gin/isolate_holder.cc +++ b/gin/isolate_holder.cc
@@ -22,7 +22,11 @@ v8::ArrayBuffer::Allocator* g_array_buffer_allocator = nullptr; } // namespace -IsolateHolder::IsolateHolder() { +IsolateHolder::IsolateHolder() : IsolateHolder(AccessMode::kSingleThread) { +} + +IsolateHolder::IsolateHolder(AccessMode access_mode) + : access_mode_(access_mode) { v8::ArrayBuffer::Allocator* allocator = g_array_buffer_allocator; CHECK(allocator) << "You need to invoke gin::IsolateHolder::Initialize first"; v8::Isolate::CreateParams params;
diff --git a/gin/public/isolate_holder.h b/gin/public/isolate_holder.h index ba75cd8..a103066 100644 --- a/gin/public/isolate_holder.h +++ b/gin/public/isolate_holder.h
@@ -27,7 +27,14 @@ kStrictMode }; + // Stores whether the client uses v8::Locker to access the isolate. + enum AccessMode { + kSingleThread, + kUseLocker + }; + IsolateHolder(); + explicit IsolateHolder(AccessMode access_mode); ~IsolateHolder(); // Should be invoked once before creating IsolateHolder instances to @@ -52,10 +59,14 @@ // thread. void RemoveRunMicrotasksObserver(); + // This method returns if v8::Locker is needed to access isolate. + AccessMode access_mode() const { return access_mode_; } + private: v8::Isolate* isolate_; scoped_ptr<PerIsolateData> isolate_data_; scoped_ptr<RunMicrotasksObserver> task_observer_; + AccessMode access_mode_; DISALLOW_COPY_AND_ASSIGN(IsolateHolder); };
diff --git a/google_apis/drive/drive_api_requests.h b/google_apis/drive/drive_api_requests.h index 0c587ec..3aaee36 100644 --- a/google_apis/drive/drive_api_requests.h +++ b/google_apis/drive/drive_api_requests.h
@@ -113,11 +113,11 @@ weak_ptr_factory_(this) { DCHECK(!callback_.is_null()); } - virtual ~DriveApiDataRequest() {} + ~DriveApiDataRequest() override {} protected: // UrlFetchRequestBase overrides. - virtual void ProcessURLFetchResults(const net::URLFetcher* source) override { + void ProcessURLFetchResults(const net::URLFetcher* source) override { DriveApiErrorCode error = GetErrorCode(); switch (error) { case HTTP_SUCCESS: @@ -136,7 +136,7 @@ } } - virtual void RunCallbackOnPrematureFailure(DriveApiErrorCode error) override { + void RunCallbackOnPrematureFailure(DriveApiErrorCode error) override { callback_.Run(error, scoped_ptr<DataType>()); }
diff --git a/google_apis/gaia/gaia_constants.cc b/google_apis/gaia/gaia_constants.cc index 4c00536..d3d0cd9 100644 --- a/google_apis/gaia/gaia_constants.cc +++ b/google_apis/gaia/gaia_constants.cc
@@ -11,7 +11,6 @@ // Gaia uses this for accounting where login is coming from. const char kChromeOSSource[] = "chromeos"; const char kChromeSource[] = "ChromiumBrowser"; -const char kReconcilorSource[] = "ChromiumReconcilor"; // Service name for Gaia. Used to convert to cookie auth. const char kGaiaService[] = "gaia";
diff --git a/google_apis/gaia/gaia_constants.h b/google_apis/gaia/gaia_constants.h index d7ffb97..4786ac88 100644 --- a/google_apis/gaia/gaia_constants.h +++ b/google_apis/gaia/gaia_constants.h
@@ -12,7 +12,6 @@ // Gaia sources for accounting extern const char kChromeOSSource[]; extern const char kChromeSource[]; -extern const char kReconcilorSource[]; // Gaia services for requesting extern const char kGaiaService[]; // uber token
diff --git a/google_apis/gaia/gaia_oauth_client_unittest.cc b/google_apis/gaia/gaia_oauth_client_unittest.cc index 6197b89..56fdc916 100644 --- a/google_apis/gaia/gaia_oauth_client_unittest.cc +++ b/google_apis/gaia/gaia_oauth_client_unittest.cc
@@ -218,14 +218,14 @@ // https://groups.google.com/a/chromium.org/d/msg/chromium-dev/01sDxsJ1OYw/I_S0xCBRF2oJ MOCK_METHOD1(OnGetUserInfoResponsePtr, void(const base::DictionaryValue* user_info)); - virtual void OnGetUserInfoResponse( + void OnGetUserInfoResponse( scoped_ptr<base::DictionaryValue> user_info) override { user_info_.reset(user_info.release()); OnGetUserInfoResponsePtr(user_info_.get()); } MOCK_METHOD1(OnGetTokenInfoResponsePtr, void(const base::DictionaryValue* token_info)); - virtual void OnGetTokenInfoResponse( + void OnGetTokenInfoResponse( scoped_ptr<base::DictionaryValue> token_info) override { token_info_.reset(token_info.release()); OnGetTokenInfoResponsePtr(token_info_.get());
diff --git a/google_apis/gaia/gaia_switches.cc b/google_apis/gaia/gaia_switches.cc index a1879d1..3e46829 100644 --- a/google_apis/gaia/gaia_switches.cc +++ b/google_apis/gaia/gaia_switches.cc
@@ -6,6 +6,7 @@ namespace switches { +const char kGoogleUrl[] = "google-url"; const char kGaiaUrl[] = "gaia-url"; const char kGoogleApisUrl[] = "google-apis-url"; const char kLsoUrl[] = "lso-url";
diff --git a/google_apis/gaia/gaia_switches.h b/google_apis/gaia/gaia_switches.h index bc69ebe..63921a04 100644 --- a/google_apis/gaia/gaia_switches.h +++ b/google_apis/gaia/gaia_switches.h
@@ -7,6 +7,10 @@ namespace switches { +// Specifies the domain of the APISID cookie. The default value is +// "http://.google.com". +extern const char kGoogleUrl[]; + // Specifies the path for GAIA authentication URL. The default value is // "https://accounts.google.com". extern const char kGaiaUrl[];
diff --git a/google_apis/gaia/gaia_urls.cc b/google_apis/gaia/gaia_urls.cc index 6545d564..95d5245 100644 --- a/google_apis/gaia/gaia_urls.cc +++ b/google_apis/gaia/gaia_urls.cc
@@ -13,6 +13,7 @@ namespace { // Gaia service constants +const char kDefaultGoogleUrl[] = "http://.google.com"; const char kDefaultGaiaUrl[] = "https://accounts.google.com"; const char kDefaultGoogleApisBaseUrl[] = "https://www.googleapis.com"; @@ -76,6 +77,8 @@ } GaiaUrls::GaiaUrls() { + google_url_ = GetURLSwitchValueWithDefault(switches::kGoogleUrl, + kDefaultGoogleUrl); gaia_url_ = GetURLSwitchValueWithDefault(switches::kGaiaUrl, kDefaultGaiaUrl); lso_origin_url_ = GetURLSwitchValueWithDefault(switches::kLsoUrl, kDefaultGaiaUrl); @@ -137,6 +140,10 @@ GaiaUrls::~GaiaUrls() { } +const GURL& GaiaUrls::google_url() const { + return google_url_; +} + const GURL& GaiaUrls::gaia_url() const { return gaia_url_; }
diff --git a/google_apis/gaia/gaia_urls.h b/google_apis/gaia/gaia_urls.h index b5453f2..bbb21177 100644 --- a/google_apis/gaia/gaia_urls.h +++ b/google_apis/gaia/gaia_urls.h
@@ -16,6 +16,7 @@ static GaiaUrls* GetInstance(); // The URLs for different calls in the Google Accounts programmatic login API. + const GURL& google_url() const; const GURL& gaia_url() const; const GURL& captcha_base_url() const; const GURL& client_login_url() const; @@ -57,6 +58,7 @@ friend struct DefaultSingletonTraits<GaiaUrls>; + GURL google_url_; GURL gaia_url_; GURL captcha_base_url_;
diff --git a/google_apis/gcm/BUILD.gn b/google_apis/gcm/BUILD.gn index ff96ea8..83aa067 100644 --- a/google_apis/gcm/BUILD.gn +++ b/google_apis/gcm/BUILD.gn
@@ -59,7 +59,8 @@ } proto_library("proto") { - visibility = [ ":*" ] + # This is part of the gcm component. + visibility = [ ":gcm" ] sources = [ "protocol/android_checkin.proto", "protocol/checkin.proto", @@ -71,7 +72,7 @@ defines = [ "GCM_IMPLEMENTATION" ] } -static_library("test_support") { +source_set("test_support") { testonly = true sources = [ "base/fake_encryptor.cc", @@ -103,11 +104,11 @@ deps = [ ":gcm", - ":proto", ":test_support", "//base", "//net", "//net:test_support", + "//third_party/protobuf:protobuf_lite", ] } @@ -129,12 +130,13 @@ ] deps = [ - ":proto", + ":gcm", ":test_support", "//base", "//base/test:run_all_unittests", "//net", "//net:test_support", "//testing/gtest", + "//third_party/protobuf:protobuf_lite", ] }
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc index 0f464c5..bbff7ff 100644 --- a/google_apis/gcm/tools/mcs_probe.cc +++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -171,6 +171,7 @@ int Verify(net::X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, net::CRLSet* crl_set, net::CertVerifyResult* verify_result,
diff --git a/google_apis/google_api_keys.py b/google_apis/google_api_keys.py index 94170ea2..ef40ff5f 100755 --- a/google_apis/google_api_keys.py +++ b/google_apis/google_api_keys.py
@@ -70,6 +70,11 @@ return _GetToken('GOOGLE_API_KEY') +def GetAPIKeyRemoting(): + """Returns the simple API key.""" + return _GetToken('GOOGLE_API_KEY_REMOTING') + + def GetClientID(client_name): """Returns the OAuth 2.0 client ID for the client of the given name.""" return _GetToken('GOOGLE_CLIENT_ID_%s' % client_name) @@ -82,6 +87,7 @@ if __name__ == "__main__": print 'GOOGLE_API_KEY=%s' % GetAPIKey() + print 'GOOGLE_API_KEY_REMOTING=%s' % GetAPIKeyRemoting() print 'GOOGLE_CLIENT_ID_MAIN=%s' % GetClientID('MAIN') print 'GOOGLE_CLIENT_SECRET_MAIN=%s' % GetClientSecret('MAIN') print 'GOOGLE_CLIENT_ID_CLOUD_PRINT=%s' % GetClientID('CLOUD_PRINT')
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn index 5e1ffb5..8cb4ec4 100644 --- a/gpu/BUILD.gn +++ b/gpu/BUILD.gn
@@ -58,8 +58,6 @@ "command_buffer/service/gles2_cmd_decoder_mock.cc", ] - configs += [ ":gpu_implementation" ] - public_deps = [ ":gpu", "//gpu/command_buffer/client:gles2_interface", @@ -167,6 +165,8 @@ "command_buffer/service/context_group_unittest.cc", "command_buffer/service/feature_info_unittest.cc", "command_buffer/service/framebuffer_manager_unittest.cc", + "command_buffer/service/gl_context_mock.cc", + "command_buffer/service/gl_context_mock.h", "command_buffer/service/gl_surface_mock.cc", "command_buffer/service/gl_surface_mock.h", "command_buffer/service/gles2_cmd_decoder_unittest.cc", @@ -183,6 +183,7 @@ "command_buffer/service/gles2_cmd_decoder_unittest_base.cc", "command_buffer/service/gles2_cmd_decoder_unittest_base.h", "command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc", + "command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc", "command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc", "command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc", "command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc",
diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index a6083d6..a551461 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h
@@ -101,6 +101,8 @@ #define glGetFramebufferAttachmentParameteriv \ GLES2_GET_FUN(GetFramebufferAttachmentParameteriv) #define glGetInteger64v GLES2_GET_FUN(GetInteger64v) +#define glGetIntegeri_v GLES2_GET_FUN(GetIntegeri_v) +#define glGetInteger64i_v GLES2_GET_FUN(GetInteger64i_v) #define glGetIntegerv GLES2_GET_FUN(GetIntegerv) #define glGetInternalformativ GLES2_GET_FUN(GetInternalformativ) #define glGetProgramiv GLES2_GET_FUN(GetProgramiv)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 2a56576..b82c6494 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -821,6 +821,20 @@ 'GL_FOG_HINT', ], }, + 'IndexedGLState': { + 'type': 'GLenum', + 'valid': [ + 'GL_TRANSFORM_FEEDBACK_BUFFER_BINDING', + 'GL_TRANSFORM_FEEDBACK_BUFFER_SIZE', + 'GL_TRANSFORM_FEEDBACK_BUFFER_START', + 'GL_UNIFORM_BUFFER_BINDING', + 'GL_UNIFORM_BUFFER_SIZE', + 'GL_UNIFORM_BUFFER_START', + ], + 'invalid': [ + 'GL_FOG_HINT', + ], + }, 'GetTexParamTarget': { 'type': 'GLenum', 'valid': [ @@ -1628,6 +1642,21 @@ 'GL_DOUBLE', ], }, + 'VertexAttribIType': { + 'type': 'GLenum', + 'valid': [ + 'GL_BYTE', + 'GL_UNSIGNED_BYTE', + 'GL_SHORT', + 'GL_UNSIGNED_SHORT', + 'GL_INT', + 'GL_UNSIGNED_INT', + ], + 'invalid': [ + 'GL_FLOAT', + 'GL_DOUBLE', + ], + }, 'TextureBorder': { 'type': 'GLint', 'is_complete': True, @@ -2462,6 +2491,18 @@ 'decoder_func': 'DoGetIntegerv', 'client_test': False, }, + 'GetInteger64i_v': { + 'type': 'GETn', + 'result': ['SizedResult<GLint64>'], + 'client_test': False, + 'unsafe': True + }, + 'GetIntegeri_v': { + 'type': 'GETn', + 'result': ['SizedResult<GLint>'], + 'client_test': False, + 'unsafe': True + }, 'GetInternalformativ': { 'type': 'GETn', 'result': ['SizedResult<GLint>'], @@ -3230,7 +3271,7 @@ 'VertexAttribIPointer': { 'type': 'Manual', 'cmd_args': 'GLuint indx, GLintVertexAttribSize size, ' - 'GLenumVertexAttribType type, GLsizei stride, ' + 'GLenumVertexAttribIType type, GLsizei stride, ' 'GLuint offset', 'client_test': False, 'unsafe': True, @@ -4499,7 +4540,7 @@ # Make this behavior consistent within Chromium, and avoid leaking GL # errors by generating the error in the command buffer instead of # letting the GL driver generate it. - code.append("base::IsNaN(%s)" % args[ndx].name) + code.append("std::isnan(%s)" % args[ndx].name) if len(code): file.Write(" if (%s) {\n" % " ||\n ".join(code)) file.Write(
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h index 46e343d..c155bf1 100644 --- a/gpu/command_buffer/client/client_test_helper.h +++ b/gpu/command_buffer/client/client_test_helper.h
@@ -63,14 +63,14 @@ class MockClientCommandBuffer : public MockCommandBufferBase { public: MockClientCommandBuffer(); - virtual ~MockClientCommandBuffer(); + ~MockClientCommandBuffer() override; // This is so we can use all the gmock functions when Flush is called. MOCK_METHOD0(OnFlush, void()); MOCK_METHOD1(DestroyTransferBuffer, void(int32 id)); - virtual void Flush(int32 put_offset) override; - virtual void OrderingBarrier(int32 put_offset) override; + void Flush(int32 put_offset) override; + void OrderingBarrier(int32 put_offset) override; void DelegateToFake(); };
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index f03d224..8d94567e 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h
@@ -406,6 +406,12 @@ void GLES2GetInteger64v(GLenum pname, GLint64* params) { gles2::GetGLContext()->GetInteger64v(pname, params); } +void GLES2GetIntegeri_v(GLenum pname, GLuint index, GLint* data) { + gles2::GetGLContext()->GetIntegeri_v(pname, index, data); +} +void GLES2GetInteger64i_v(GLenum pname, GLuint index, GLint64* data) { + gles2::GetGLContext()->GetInteger64i_v(pname, index, data); +} void GLES2GetIntegerv(GLenum pname, GLint* params) { gles2::GetGLContext()->GetIntegerv(pname, params); } @@ -1703,6 +1709,14 @@ reinterpret_cast<GLES2FunctionPointer>(glGetInteger64v), }, { + "glGetIntegeri_v", + reinterpret_cast<GLES2FunctionPointer>(glGetIntegeri_v), + }, + { + "glGetInteger64i_v", + reinterpret_cast<GLES2FunctionPointer>(glGetInteger64i_v), + }, + { "glGetIntegerv", reinterpret_cast<GLES2FunctionPointer>(glGetIntegerv), },
diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index a798425..b4da6002 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h
@@ -842,6 +842,26 @@ } } +void GetIntegeri_v(GLenum pname, + GLuint index, + uint32_t data_shm_id, + uint32_t data_shm_offset) { + gles2::cmds::GetIntegeri_v* c = GetCmdSpace<gles2::cmds::GetIntegeri_v>(); + if (c) { + c->Init(pname, index, data_shm_id, data_shm_offset); + } +} + +void GetInteger64i_v(GLenum pname, + GLuint index, + uint32_t data_shm_id, + uint32_t data_shm_offset) { + gles2::cmds::GetInteger64i_v* c = GetCmdSpace<gles2::cmds::GetInteger64i_v>(); + if (c) { + c->Init(pname, index, data_shm_id, data_shm_offset); + } +} + void GetIntegerv(GLenum pname, uint32_t params_shm_id, uint32_t params_shm_offset) {
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index e5d78f13..9d144b52 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -957,6 +957,18 @@ return GetHelper(pname, params); } +bool GLES2Implementation::GetIntegeri_vHelper( + GLenum pname, GLuint index, GLint* data) { + // TODO(zmo): Implement client side caching. + return false; +} + +bool GLES2Implementation::GetInteger64i_vHelper( + GLenum pname, GLuint index, GLint64* data) { + // TODO(zmo): Implement client side caching. + return false; +} + bool GLES2Implementation::GetInternalformativHelper( GLenum target, GLenum format, GLenum pname, GLsizei bufSize, GLint* params) { @@ -1539,13 +1551,27 @@ void GLES2Implementation::VertexAttribIPointer( GLuint index, GLint size, GLenum type, GLsizei stride, const void* ptr) { GPU_CLIENT_SINGLE_THREAD_CHECK(); - GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribPointer(" + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glVertexAttribIPointer(" << index << ", " << size << ", " - << GLES2Util::GetStringVertexAttribType(type) << ", " + << GLES2Util::GetStringVertexAttribIType(type) << ", " << stride << ", " << ptr << ")"); - helper_->VertexAttribIPointer(index, size, type, stride, ToGLuint(ptr)); + // Record the info on the client side. + if (!vertex_array_object_manager_->SetAttribPointer( + bound_array_buffer_id_, index, size, type, GL_FALSE, stride, ptr)) { + SetGLError(GL_INVALID_OPERATION, "glVertexAttribIPointer", + "client side arrays are not allowed in vertex array objects."); + return; + } + if (!support_client_side_arrays_ || bound_array_buffer_id_ != 0) { + // Only report NON client side buffers to the service. + if (!ValidateOffset("glVertexAttribIPointer", + reinterpret_cast<GLintptr>(ptr))) { + return; + } + helper_->VertexAttribIPointer(index, size, type, stride, ToGLuint(ptr)); + } CheckGLError(); }
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 2c50624f..31dc7e4a 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -568,6 +568,8 @@ GLenum target, GLenum attachment, GLenum pname, GLint* params); bool GetInteger64vHelper(GLenum pname, GLint64* params); bool GetIntegervHelper(GLenum pname, GLint* params); + bool GetIntegeri_vHelper(GLenum pname, GLuint index, GLint* data); + bool GetInteger64i_vHelper(GLenum pname, GLuint index, GLint64* data); bool GetInternalformativHelper( GLenum target, GLenum format, GLenum pname, GLsizei bufSize, GLint* params);
diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index e5672a8..8d9e878 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h
@@ -305,6 +305,10 @@ void GetInteger64v(GLenum pname, GLint64* params) override; +void GetIntegeri_v(GLenum pname, GLuint index, GLint* data) override; + +void GetInteger64i_v(GLenum pname, GLuint index, GLint64* data) override; + void GetIntegerv(GLenum pname, GLint* params) override; void GetInternalformativ(GLenum target,
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h index 918db99..6528554 100644 --- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -1021,6 +1021,62 @@ }); CheckGLError(); } +void GLES2Implementation::GetIntegeri_v(GLenum pname, + GLuint index, + GLint* data) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, data); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetIntegeri_v(" + << GLES2Util::GetStringIndexedGLState(pname) << ", " + << index << ", " << static_cast<const void*>(data) << ")"); + TRACE_EVENT0("gpu", "GLES2Implementation::GetIntegeri_v"); + if (GetIntegeri_vHelper(pname, index, data)) { + return; + } + typedef cmds::GetIntegeri_v::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return; + } + result->SetNumResults(0); + helper_->GetIntegeri_v(pname, index, GetResultShmId(), GetResultShmOffset()); + WaitForCmd(); + result->CopyResult(data); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + CheckGLError(); +} +void GLES2Implementation::GetInteger64i_v(GLenum pname, + GLuint index, + GLint64* data) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glGetInteger64i_v(" + << GLES2Util::GetStringIndexedGLState(pname) << ", " + << index << ", " << static_cast<const void*>(data) << ")"); + TRACE_EVENT0("gpu", "GLES2Implementation::GetInteger64i_v"); + if (GetInteger64i_vHelper(pname, index, data)) { + return; + } + typedef cmds::GetInteger64i_v::Result Result; + Result* result = GetResultAs<Result*>(); + if (!result) { + return; + } + result->SetNumResults(0); + helper_->GetInteger64i_v(pname, index, GetResultShmId(), + GetResultShmOffset()); + WaitForCmd(); + result->CopyResult(data); + GPU_CLIENT_LOG_CODE_BLOCK({ + for (int32_t i = 0; i < result->GetNumResults(); ++i) { + GPU_CLIENT_LOG(" " << i << ": " << result->GetData()[i]); + } + }); + CheckGLError(); +} void GLES2Implementation::GetIntegerv(GLenum pname, GLint* params) { GPU_CLIENT_SINGLE_THREAD_CHECK(); GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params);
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h index 51aea3a..44dca99 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -854,6 +854,42 @@ EXPECT_EQ(static_cast<ResultType>(1), result); } +TEST_F(GLES2ImplementationTest, GetIntegeri_v) { + struct Cmds { + cmds::GetIntegeri_v cmd; + }; + typedef cmds::GetIntegeri_v::Result::Type ResultType; + ResultType result = 0; + Cmds expected; + ExpectedMemoryInfo result1 = + GetExpectedResultMemory(sizeof(uint32_t) + sizeof(ResultType)); + expected.cmd.Init(123, 2, result1.id, result1.offset); + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result1.ptr, SizedResultHelper<ResultType>(1))) + .RetiresOnSaturation(); + gl_->GetIntegeri_v(123, 2, &result); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_EQ(static_cast<ResultType>(1), result); +} + +TEST_F(GLES2ImplementationTest, GetInteger64i_v) { + struct Cmds { + cmds::GetInteger64i_v cmd; + }; + typedef cmds::GetInteger64i_v::Result::Type ResultType; + ResultType result = 0; + Cmds expected; + ExpectedMemoryInfo result1 = + GetExpectedResultMemory(sizeof(uint32_t) + sizeof(ResultType)); + expected.cmd.Init(123, 2, result1.id, result1.offset); + EXPECT_CALL(*command_buffer(), OnFlush()) + .WillOnce(SetMemory(result1.ptr, SizedResultHelper<ResultType>(1))) + .RetiresOnSaturation(); + gl_->GetInteger64i_v(123, 2, &result); + EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected))); + EXPECT_EQ(static_cast<ResultType>(1), result); +} + TEST_F(GLES2ImplementationTest, GetIntegerv) { struct Cmds { cmds::GetIntegerv cmd;
diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index c4be43e..4a97e2cc 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h
@@ -226,6 +226,8 @@ GLenum pname, GLint* params) = 0; virtual void GetInteger64v(GLenum pname, GLint64* params) = 0; +virtual void GetIntegeri_v(GLenum pname, GLuint index, GLint* data) = 0; +virtual void GetInteger64i_v(GLenum pname, GLuint index, GLint64* data) = 0; virtual void GetIntegerv(GLenum pname, GLint* params) = 0; virtual void GetInternalformativ(GLenum target, GLenum format,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 6dad2b328..c976209 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h
@@ -221,6 +221,8 @@ GLenum pname, GLint* params) override; void GetInteger64v(GLenum pname, GLint64* params) override; +void GetIntegeri_v(GLenum pname, GLuint index, GLint* data) override; +void GetInteger64i_v(GLenum pname, GLuint index, GLint64* data) override; void GetIntegerv(GLenum pname, GLint* params) override; void GetInternalformativ(GLenum target, GLenum format,
diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index 5e34714e..911cf024 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h
@@ -349,6 +349,14 @@ void GLES2InterfaceStub::GetInteger64v(GLenum /* pname */, GLint64* /* params */) { } +void GLES2InterfaceStub::GetIntegeri_v(GLenum /* pname */, + GLuint /* index */, + GLint* /* data */) { +} +void GLES2InterfaceStub::GetInteger64i_v(GLenum /* pname */, + GLuint /* index */, + GLint64* /* data */) { +} void GLES2InterfaceStub::GetIntegerv(GLenum /* pname */, GLint* /* params */) { } void GLES2InterfaceStub::GetInternalformativ(GLenum /* target */,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 26a6a22..b7dc435 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h
@@ -221,6 +221,8 @@ GLenum pname, GLint* params) override; void GetInteger64v(GLenum pname, GLint64* params) override; +void GetIntegeri_v(GLenum pname, GLuint index, GLint* data) override; +void GetInteger64i_v(GLenum pname, GLuint index, GLint64* data) override; void GetIntegerv(GLenum pname, GLint* params) override; void GetInternalformativ(GLenum target, GLenum format,
diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index e650034..07bf947a 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h
@@ -600,6 +600,20 @@ gl_->GetInteger64v(pname, params); } +void GLES2TraceImplementation::GetIntegeri_v(GLenum pname, + GLuint index, + GLint* data) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetIntegeri_v"); + gl_->GetIntegeri_v(pname, index, data); +} + +void GLES2TraceImplementation::GetInteger64i_v(GLenum pname, + GLuint index, + GLint64* data) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetInteger64i_v"); + gl_->GetInteger64i_v(pname, index, data); +} + void GLES2TraceImplementation::GetIntegerv(GLenum pname, GLint* params) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetIntegerv"); gl_->GetIntegerv(pname, params);
diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index c0086787..5fd7d6a 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt
@@ -91,6 +91,8 @@ GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLidProgram program, const char* name); GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenumFrameBufferTarget target, GLenumAttachment attachment, GLenumFrameBufferParameter pname, GLint* params); GL_APICALL void GL_APIENTRY glGetInteger64v (GLenumGLState pname, GLint64* params); +GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenumIndexedGLState pname, GLuint index, GLint* data); +GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenumIndexedGLState pname, GLuint index, GLint64* data); GL_APICALL void GL_APIENTRY glGetIntegerv (GLenumGLState pname, GLint* params); GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenumRenderBufferTarget target, GLenumRenderBufferFormat format, GLenumRenderBufferParameter pname, GLsizeiNotNegative bufSize, GLint* params); GL_APICALL void GL_APIENTRY glGetProgramiv (GLidProgram program, GLenumProgramParameter pname, GLint* params); @@ -213,7 +215,7 @@ GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint indx, const GLint* values); GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint indx, GLuint x, GLuint y, GLuint z, GLuint w); GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint indx, const GLuint* values); -GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint indx, GLintVertexAttribSize size, GLenumVertexAttribType type, GLsizei stride, const void* ptr); +GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint indx, GLintVertexAttribSize size, GLenumVertexAttribIType type, GLsizei stride, const void* ptr); GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLintVertexAttribSize size, GLenumVertexAttribType type, GLboolean normalized, GLsizei stride, const void* ptr); GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfieldSyncFlushFlags flags, GLuint64 timeout);
diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h index 054708f..d06836c0 100644 --- a/gpu/command_buffer/common/constants.h +++ b/gpu/command_buffer/common/constants.h
@@ -23,7 +23,8 @@ kInvalidArguments, kLostContext, kGenericError, - kDeferCommandUntilLater + kDeferCommandUntilLater, + kErrorLast = kDeferCommandUntilLater, }; // Return true if the given error code is an actual error. @@ -41,7 +42,17 @@ // It is unknown whether this context provoked the loss of context. kUnknown, - kContextLostReasonLast = kUnknown + + // GL_OUT_OF_MEMORY caused this context to be lost. + kOutOfMemory, + + // A failure to make the context current caused it to be lost. + kMakeCurrentFailed, + + // The GPU channel was lost. This error is set client-side. + kGpuChannelLost, + + kContextLostReasonLast = kGpuChannelLost }; }
diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index ab93ed5f..13f3b54 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h
@@ -4099,6 +4099,116 @@ static_assert(offsetof(GetInteger64v, params_shm_offset) == 12, "offset of GetInteger64v params_shm_offset should be 12"); +struct GetIntegeri_v { + typedef GetIntegeri_v ValueType; + static const CommandId kCmdId = kGetIntegeri_v; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + typedef SizedResult<GLint> Result; + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLenum _pname, + GLuint _index, + uint32_t _data_shm_id, + uint32_t _data_shm_offset) { + SetHeader(); + pname = _pname; + index = _index; + data_shm_id = _data_shm_id; + data_shm_offset = _data_shm_offset; + } + + void* Set(void* cmd, + GLenum _pname, + GLuint _index, + uint32_t _data_shm_id, + uint32_t _data_shm_offset) { + static_cast<ValueType*>(cmd) + ->Init(_pname, _index, _data_shm_id, _data_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t pname; + uint32_t index; + uint32_t data_shm_id; + uint32_t data_shm_offset; +}; + +static_assert(sizeof(GetIntegeri_v) == 20, + "size of GetIntegeri_v should be 20"); +static_assert(offsetof(GetIntegeri_v, header) == 0, + "offset of GetIntegeri_v header should be 0"); +static_assert(offsetof(GetIntegeri_v, pname) == 4, + "offset of GetIntegeri_v pname should be 4"); +static_assert(offsetof(GetIntegeri_v, index) == 8, + "offset of GetIntegeri_v index should be 8"); +static_assert(offsetof(GetIntegeri_v, data_shm_id) == 12, + "offset of GetIntegeri_v data_shm_id should be 12"); +static_assert(offsetof(GetIntegeri_v, data_shm_offset) == 16, + "offset of GetIntegeri_v data_shm_offset should be 16"); + +struct GetInteger64i_v { + typedef GetInteger64i_v ValueType; + static const CommandId kCmdId = kGetInteger64i_v; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + static const uint8 cmd_flags = CMD_FLAG_SET_TRACE_LEVEL(3); + + typedef SizedResult<GLint64> Result; + + static uint32_t ComputeSize() { + return static_cast<uint32_t>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { header.SetCmd<ValueType>(); } + + void Init(GLenum _pname, + GLuint _index, + uint32_t _data_shm_id, + uint32_t _data_shm_offset) { + SetHeader(); + pname = _pname; + index = _index; + data_shm_id = _data_shm_id; + data_shm_offset = _data_shm_offset; + } + + void* Set(void* cmd, + GLenum _pname, + GLuint _index, + uint32_t _data_shm_id, + uint32_t _data_shm_offset) { + static_cast<ValueType*>(cmd) + ->Init(_pname, _index, _data_shm_id, _data_shm_offset); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32_t pname; + uint32_t index; + uint32_t data_shm_id; + uint32_t data_shm_offset; +}; + +static_assert(sizeof(GetInteger64i_v) == 20, + "size of GetInteger64i_v should be 20"); +static_assert(offsetof(GetInteger64i_v, header) == 0, + "offset of GetInteger64i_v header should be 0"); +static_assert(offsetof(GetInteger64i_v, pname) == 4, + "offset of GetInteger64i_v pname should be 4"); +static_assert(offsetof(GetInteger64i_v, index) == 8, + "offset of GetInteger64i_v index should be 8"); +static_assert(offsetof(GetInteger64i_v, data_shm_id) == 12, + "offset of GetInteger64i_v data_shm_id should be 12"); +static_assert(offsetof(GetInteger64i_v, data_shm_offset) == 16, + "offset of GetInteger64i_v data_shm_offset should be 16"); + struct GetIntegerv { typedef GetIntegerv ValueType; static const CommandId kCmdId = kGetIntegerv;
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 2cc8dd9..45f0b8e 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h
@@ -1297,6 +1297,36 @@ CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, GetIntegeri_v) { + cmds::GetIntegeri_v& cmd = *GetBufferAs<cmds::GetIntegeri_v>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLuint>(12), + static_cast<uint32_t>(13), static_cast<uint32_t>(14)); + EXPECT_EQ(static_cast<uint32_t>(cmds::GetIntegeri_v::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.pname); + EXPECT_EQ(static_cast<GLuint>(12), cmd.index); + EXPECT_EQ(static_cast<uint32_t>(13), cmd.data_shm_id); + EXPECT_EQ(static_cast<uint32_t>(14), cmd.data_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + +TEST_F(GLES2FormatTest, GetInteger64i_v) { + cmds::GetInteger64i_v& cmd = *GetBufferAs<cmds::GetInteger64i_v>(); + void* next_cmd = + cmd.Set(&cmd, static_cast<GLenum>(11), static_cast<GLuint>(12), + static_cast<uint32_t>(13), static_cast<uint32_t>(14)); + EXPECT_EQ(static_cast<uint32_t>(cmds::GetInteger64i_v::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.pname); + EXPECT_EQ(static_cast<GLuint>(12), cmd.index); + EXPECT_EQ(static_cast<uint32_t>(13), cmd.data_shm_id); + EXPECT_EQ(static_cast<uint32_t>(14), cmd.data_shm_offset); + CheckBytesWrittenMatchesExpectedSize(next_cmd, sizeof(cmd)); +} + TEST_F(GLES2FormatTest, GetIntegerv) { cmds::GetIntegerv& cmd = *GetBufferAs<cmds::GetIntegerv>(); void* next_cmd =
diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 993a6c3..3fdf899 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h
@@ -100,199 +100,201 @@ OP(GetFragDataLocation) /* 341 */ \ OP(GetFramebufferAttachmentParameteriv) /* 342 */ \ OP(GetInteger64v) /* 343 */ \ - OP(GetIntegerv) /* 344 */ \ - OP(GetInternalformativ) /* 345 */ \ - OP(GetProgramiv) /* 346 */ \ - OP(GetProgramInfoLog) /* 347 */ \ - OP(GetRenderbufferParameteriv) /* 348 */ \ - OP(GetSamplerParameterfv) /* 349 */ \ - OP(GetSamplerParameteriv) /* 350 */ \ - OP(GetShaderiv) /* 351 */ \ - OP(GetShaderInfoLog) /* 352 */ \ - OP(GetShaderPrecisionFormat) /* 353 */ \ - OP(GetShaderSource) /* 354 */ \ - OP(GetString) /* 355 */ \ - OP(GetSynciv) /* 356 */ \ - OP(GetTexParameterfv) /* 357 */ \ - OP(GetTexParameteriv) /* 358 */ \ - OP(GetTransformFeedbackVarying) /* 359 */ \ - OP(GetUniformBlockIndex) /* 360 */ \ - OP(GetUniformfv) /* 361 */ \ - OP(GetUniformiv) /* 362 */ \ - OP(GetUniformIndices) /* 363 */ \ - OP(GetUniformLocation) /* 364 */ \ - OP(GetVertexAttribfv) /* 365 */ \ - OP(GetVertexAttribiv) /* 366 */ \ - OP(GetVertexAttribPointerv) /* 367 */ \ - OP(Hint) /* 368 */ \ - OP(InvalidateFramebufferImmediate) /* 369 */ \ - OP(InvalidateSubFramebufferImmediate) /* 370 */ \ - OP(IsBuffer) /* 371 */ \ - OP(IsEnabled) /* 372 */ \ - OP(IsFramebuffer) /* 373 */ \ - OP(IsProgram) /* 374 */ \ - OP(IsRenderbuffer) /* 375 */ \ - OP(IsSampler) /* 376 */ \ - OP(IsShader) /* 377 */ \ - OP(IsSync) /* 378 */ \ - OP(IsTexture) /* 379 */ \ - OP(IsTransformFeedback) /* 380 */ \ - OP(LineWidth) /* 381 */ \ - OP(LinkProgram) /* 382 */ \ - OP(PauseTransformFeedback) /* 383 */ \ - OP(PixelStorei) /* 384 */ \ - OP(PolygonOffset) /* 385 */ \ - OP(ReadBuffer) /* 386 */ \ - OP(ReadPixels) /* 387 */ \ - OP(ReleaseShaderCompiler) /* 388 */ \ - OP(RenderbufferStorage) /* 389 */ \ - OP(ResumeTransformFeedback) /* 390 */ \ - OP(SampleCoverage) /* 391 */ \ - OP(SamplerParameterf) /* 392 */ \ - OP(SamplerParameterfvImmediate) /* 393 */ \ - OP(SamplerParameteri) /* 394 */ \ - OP(SamplerParameterivImmediate) /* 395 */ \ - OP(Scissor) /* 396 */ \ - OP(ShaderBinary) /* 397 */ \ - OP(ShaderSourceBucket) /* 398 */ \ - OP(StencilFunc) /* 399 */ \ - OP(StencilFuncSeparate) /* 400 */ \ - OP(StencilMask) /* 401 */ \ - OP(StencilMaskSeparate) /* 402 */ \ - OP(StencilOp) /* 403 */ \ - OP(StencilOpSeparate) /* 404 */ \ - OP(TexImage2D) /* 405 */ \ - OP(TexImage3D) /* 406 */ \ - OP(TexParameterf) /* 407 */ \ - OP(TexParameterfvImmediate) /* 408 */ \ - OP(TexParameteri) /* 409 */ \ - OP(TexParameterivImmediate) /* 410 */ \ - OP(TexStorage3D) /* 411 */ \ - OP(TexSubImage2D) /* 412 */ \ - OP(TexSubImage3D) /* 413 */ \ - OP(TransformFeedbackVaryingsBucket) /* 414 */ \ - OP(Uniform1f) /* 415 */ \ - OP(Uniform1fvImmediate) /* 416 */ \ - OP(Uniform1i) /* 417 */ \ - OP(Uniform1ivImmediate) /* 418 */ \ - OP(Uniform1ui) /* 419 */ \ - OP(Uniform1uivImmediate) /* 420 */ \ - OP(Uniform2f) /* 421 */ \ - OP(Uniform2fvImmediate) /* 422 */ \ - OP(Uniform2i) /* 423 */ \ - OP(Uniform2ivImmediate) /* 424 */ \ - OP(Uniform2ui) /* 425 */ \ - OP(Uniform2uivImmediate) /* 426 */ \ - OP(Uniform3f) /* 427 */ \ - OP(Uniform3fvImmediate) /* 428 */ \ - OP(Uniform3i) /* 429 */ \ - OP(Uniform3ivImmediate) /* 430 */ \ - OP(Uniform3ui) /* 431 */ \ - OP(Uniform3uivImmediate) /* 432 */ \ - OP(Uniform4f) /* 433 */ \ - OP(Uniform4fvImmediate) /* 434 */ \ - OP(Uniform4i) /* 435 */ \ - OP(Uniform4ivImmediate) /* 436 */ \ - OP(Uniform4ui) /* 437 */ \ - OP(Uniform4uivImmediate) /* 438 */ \ - OP(UniformBlockBinding) /* 439 */ \ - OP(UniformMatrix2fvImmediate) /* 440 */ \ - OP(UniformMatrix2x3fvImmediate) /* 441 */ \ - OP(UniformMatrix2x4fvImmediate) /* 442 */ \ - OP(UniformMatrix3fvImmediate) /* 443 */ \ - OP(UniformMatrix3x2fvImmediate) /* 444 */ \ - OP(UniformMatrix3x4fvImmediate) /* 445 */ \ - OP(UniformMatrix4fvImmediate) /* 446 */ \ - OP(UniformMatrix4x2fvImmediate) /* 447 */ \ - OP(UniformMatrix4x3fvImmediate) /* 448 */ \ - OP(UseProgram) /* 449 */ \ - OP(ValidateProgram) /* 450 */ \ - OP(VertexAttrib1f) /* 451 */ \ - OP(VertexAttrib1fvImmediate) /* 452 */ \ - OP(VertexAttrib2f) /* 453 */ \ - OP(VertexAttrib2fvImmediate) /* 454 */ \ - OP(VertexAttrib3f) /* 455 */ \ - OP(VertexAttrib3fvImmediate) /* 456 */ \ - OP(VertexAttrib4f) /* 457 */ \ - OP(VertexAttrib4fvImmediate) /* 458 */ \ - OP(VertexAttribI4i) /* 459 */ \ - OP(VertexAttribI4ivImmediate) /* 460 */ \ - OP(VertexAttribI4ui) /* 461 */ \ - OP(VertexAttribI4uivImmediate) /* 462 */ \ - OP(VertexAttribIPointer) /* 463 */ \ - OP(VertexAttribPointer) /* 464 */ \ - OP(Viewport) /* 465 */ \ - OP(WaitSync) /* 466 */ \ - OP(BlitFramebufferCHROMIUM) /* 467 */ \ - OP(RenderbufferStorageMultisampleCHROMIUM) /* 468 */ \ - OP(RenderbufferStorageMultisampleEXT) /* 469 */ \ - OP(FramebufferTexture2DMultisampleEXT) /* 470 */ \ - OP(TexStorage2DEXT) /* 471 */ \ - OP(GenQueriesEXTImmediate) /* 472 */ \ - OP(DeleteQueriesEXTImmediate) /* 473 */ \ - OP(BeginQueryEXT) /* 474 */ \ - OP(BeginTransformFeedback) /* 475 */ \ - OP(EndQueryEXT) /* 476 */ \ - OP(EndTransformFeedback) /* 477 */ \ - OP(InsertEventMarkerEXT) /* 478 */ \ - OP(PushGroupMarkerEXT) /* 479 */ \ - OP(PopGroupMarkerEXT) /* 480 */ \ - OP(GenVertexArraysOESImmediate) /* 481 */ \ - OP(DeleteVertexArraysOESImmediate) /* 482 */ \ - OP(IsVertexArrayOES) /* 483 */ \ - OP(BindVertexArrayOES) /* 484 */ \ - OP(SwapBuffers) /* 485 */ \ - OP(GetMaxValueInBufferCHROMIUM) /* 486 */ \ - OP(EnableFeatureCHROMIUM) /* 487 */ \ - OP(MapBufferRange) /* 488 */ \ - OP(UnmapBuffer) /* 489 */ \ - OP(ResizeCHROMIUM) /* 490 */ \ - OP(GetRequestableExtensionsCHROMIUM) /* 491 */ \ - OP(RequestExtensionCHROMIUM) /* 492 */ \ - OP(GetProgramInfoCHROMIUM) /* 493 */ \ - OP(GetUniformBlocksCHROMIUM) /* 494 */ \ - OP(GetTransformFeedbackVaryingsCHROMIUM) /* 495 */ \ - OP(GetUniformsES3CHROMIUM) /* 496 */ \ - OP(GetTranslatedShaderSourceANGLE) /* 497 */ \ - OP(PostSubBufferCHROMIUM) /* 498 */ \ - OP(TexImageIOSurface2DCHROMIUM) /* 499 */ \ - OP(CopyTextureCHROMIUM) /* 500 */ \ - OP(CopySubTextureCHROMIUM) /* 501 */ \ - OP(DrawArraysInstancedANGLE) /* 502 */ \ - OP(DrawElementsInstancedANGLE) /* 503 */ \ - OP(VertexAttribDivisorANGLE) /* 504 */ \ - OP(GenMailboxCHROMIUM) /* 505 */ \ - OP(ProduceTextureCHROMIUMImmediate) /* 506 */ \ - OP(ProduceTextureDirectCHROMIUMImmediate) /* 507 */ \ - OP(ConsumeTextureCHROMIUMImmediate) /* 508 */ \ - OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 509 */ \ - OP(BindUniformLocationCHROMIUMBucket) /* 510 */ \ - OP(GenValuebuffersCHROMIUMImmediate) /* 511 */ \ - OP(DeleteValuebuffersCHROMIUMImmediate) /* 512 */ \ - OP(IsValuebufferCHROMIUM) /* 513 */ \ - OP(BindValuebufferCHROMIUM) /* 514 */ \ - OP(SubscribeValueCHROMIUM) /* 515 */ \ - OP(PopulateSubscribedValuesCHROMIUM) /* 516 */ \ - OP(UniformValuebufferCHROMIUM) /* 517 */ \ - OP(BindTexImage2DCHROMIUM) /* 518 */ \ - OP(ReleaseTexImage2DCHROMIUM) /* 519 */ \ - OP(TraceBeginCHROMIUM) /* 520 */ \ - OP(TraceEndCHROMIUM) /* 521 */ \ - OP(AsyncTexSubImage2DCHROMIUM) /* 522 */ \ - OP(AsyncTexImage2DCHROMIUM) /* 523 */ \ - OP(WaitAsyncTexImage2DCHROMIUM) /* 524 */ \ - OP(WaitAllAsyncTexImage2DCHROMIUM) /* 525 */ \ - OP(DiscardFramebufferEXTImmediate) /* 526 */ \ - OP(LoseContextCHROMIUM) /* 527 */ \ - OP(InsertSyncPointCHROMIUM) /* 528 */ \ - OP(WaitSyncPointCHROMIUM) /* 529 */ \ - OP(DrawBuffersEXTImmediate) /* 530 */ \ - OP(DiscardBackbufferCHROMIUM) /* 531 */ \ - OP(ScheduleOverlayPlaneCHROMIUM) /* 532 */ \ - OP(SwapInterval) /* 533 */ \ - OP(MatrixLoadfCHROMIUMImmediate) /* 534 */ \ - OP(MatrixLoadIdentityCHROMIUM) /* 535 */ \ - OP(BlendBarrierKHR) /* 536 */ + OP(GetIntegeri_v) /* 344 */ \ + OP(GetInteger64i_v) /* 345 */ \ + OP(GetIntegerv) /* 346 */ \ + OP(GetInternalformativ) /* 347 */ \ + OP(GetProgramiv) /* 348 */ \ + OP(GetProgramInfoLog) /* 349 */ \ + OP(GetRenderbufferParameteriv) /* 350 */ \ + OP(GetSamplerParameterfv) /* 351 */ \ + OP(GetSamplerParameteriv) /* 352 */ \ + OP(GetShaderiv) /* 353 */ \ + OP(GetShaderInfoLog) /* 354 */ \ + OP(GetShaderPrecisionFormat) /* 355 */ \ + OP(GetShaderSource) /* 356 */ \ + OP(GetString) /* 357 */ \ + OP(GetSynciv) /* 358 */ \ + OP(GetTexParameterfv) /* 359 */ \ + OP(GetTexParameteriv) /* 360 */ \ + OP(GetTransformFeedbackVarying) /* 361 */ \ + OP(GetUniformBlockIndex) /* 362 */ \ + OP(GetUniformfv) /* 363 */ \ + OP(GetUniformiv) /* 364 */ \ + OP(GetUniformIndices) /* 365 */ \ + OP(GetUniformLocation) /* 366 */ \ + OP(GetVertexAttribfv) /* 367 */ \ + OP(GetVertexAttribiv) /* 368 */ \ + OP(GetVertexAttribPointerv) /* 369 */ \ + OP(Hint) /* 370 */ \ + OP(InvalidateFramebufferImmediate) /* 371 */ \ + OP(InvalidateSubFramebufferImmediate) /* 372 */ \ + OP(IsBuffer) /* 373 */ \ + OP(IsEnabled) /* 374 */ \ + OP(IsFramebuffer) /* 375 */ \ + OP(IsProgram) /* 376 */ \ + OP(IsRenderbuffer) /* 377 */ \ + OP(IsSampler) /* 378 */ \ + OP(IsShader) /* 379 */ \ + OP(IsSync) /* 380 */ \ + OP(IsTexture) /* 381 */ \ + OP(IsTransformFeedback) /* 382 */ \ + OP(LineWidth) /* 383 */ \ + OP(LinkProgram) /* 384 */ \ + OP(PauseTransformFeedback) /* 385 */ \ + OP(PixelStorei) /* 386 */ \ + OP(PolygonOffset) /* 387 */ \ + OP(ReadBuffer) /* 388 */ \ + OP(ReadPixels) /* 389 */ \ + OP(ReleaseShaderCompiler) /* 390 */ \ + OP(RenderbufferStorage) /* 391 */ \ + OP(ResumeTransformFeedback) /* 392 */ \ + OP(SampleCoverage) /* 393 */ \ + OP(SamplerParameterf) /* 394 */ \ + OP(SamplerParameterfvImmediate) /* 395 */ \ + OP(SamplerParameteri) /* 396 */ \ + OP(SamplerParameterivImmediate) /* 397 */ \ + OP(Scissor) /* 398 */ \ + OP(ShaderBinary) /* 399 */ \ + OP(ShaderSourceBucket) /* 400 */ \ + OP(StencilFunc) /* 401 */ \ + OP(StencilFuncSeparate) /* 402 */ \ + OP(StencilMask) /* 403 */ \ + OP(StencilMaskSeparate) /* 404 */ \ + OP(StencilOp) /* 405 */ \ + OP(StencilOpSeparate) /* 406 */ \ + OP(TexImage2D) /* 407 */ \ + OP(TexImage3D) /* 408 */ \ + OP(TexParameterf) /* 409 */ \ + OP(TexParameterfvImmediate) /* 410 */ \ + OP(TexParameteri) /* 411 */ \ + OP(TexParameterivImmediate) /* 412 */ \ + OP(TexStorage3D) /* 413 */ \ + OP(TexSubImage2D) /* 414 */ \ + OP(TexSubImage3D) /* 415 */ \ + OP(TransformFeedbackVaryingsBucket) /* 416 */ \ + OP(Uniform1f) /* 417 */ \ + OP(Uniform1fvImmediate) /* 418 */ \ + OP(Uniform1i) /* 419 */ \ + OP(Uniform1ivImmediate) /* 420 */ \ + OP(Uniform1ui) /* 421 */ \ + OP(Uniform1uivImmediate) /* 422 */ \ + OP(Uniform2f) /* 423 */ \ + OP(Uniform2fvImmediate) /* 424 */ \ + OP(Uniform2i) /* 425 */ \ + OP(Uniform2ivImmediate) /* 426 */ \ + OP(Uniform2ui) /* 427 */ \ + OP(Uniform2uivImmediate) /* 428 */ \ + OP(Uniform3f) /* 429 */ \ + OP(Uniform3fvImmediate) /* 430 */ \ + OP(Uniform3i) /* 431 */ \ + OP(Uniform3ivImmediate) /* 432 */ \ + OP(Uniform3ui) /* 433 */ \ + OP(Uniform3uivImmediate) /* 434 */ \ + OP(Uniform4f) /* 435 */ \ + OP(Uniform4fvImmediate) /* 436 */ \ + OP(Uniform4i) /* 437 */ \ + OP(Uniform4ivImmediate) /* 438 */ \ + OP(Uniform4ui) /* 439 */ \ + OP(Uniform4uivImmediate) /* 440 */ \ + OP(UniformBlockBinding) /* 441 */ \ + OP(UniformMatrix2fvImmediate) /* 442 */ \ + OP(UniformMatrix2x3fvImmediate) /* 443 */ \ + OP(UniformMatrix2x4fvImmediate) /* 444 */ \ + OP(UniformMatrix3fvImmediate) /* 445 */ \ + OP(UniformMatrix3x2fvImmediate) /* 446 */ \ + OP(UniformMatrix3x4fvImmediate) /* 447 */ \ + OP(UniformMatrix4fvImmediate) /* 448 */ \ + OP(UniformMatrix4x2fvImmediate) /* 449 */ \ + OP(UniformMatrix4x3fvImmediate) /* 450 */ \ + OP(UseProgram) /* 451 */ \ + OP(ValidateProgram) /* 452 */ \ + OP(VertexAttrib1f) /* 453 */ \ + OP(VertexAttrib1fvImmediate) /* 454 */ \ + OP(VertexAttrib2f) /* 455 */ \ + OP(VertexAttrib2fvImmediate) /* 456 */ \ + OP(VertexAttrib3f) /* 457 */ \ + OP(VertexAttrib3fvImmediate) /* 458 */ \ + OP(VertexAttrib4f) /* 459 */ \ + OP(VertexAttrib4fvImmediate) /* 460 */ \ + OP(VertexAttribI4i) /* 461 */ \ + OP(VertexAttribI4ivImmediate) /* 462 */ \ + OP(VertexAttribI4ui) /* 463 */ \ + OP(VertexAttribI4uivImmediate) /* 464 */ \ + OP(VertexAttribIPointer) /* 465 */ \ + OP(VertexAttribPointer) /* 466 */ \ + OP(Viewport) /* 467 */ \ + OP(WaitSync) /* 468 */ \ + OP(BlitFramebufferCHROMIUM) /* 469 */ \ + OP(RenderbufferStorageMultisampleCHROMIUM) /* 470 */ \ + OP(RenderbufferStorageMultisampleEXT) /* 471 */ \ + OP(FramebufferTexture2DMultisampleEXT) /* 472 */ \ + OP(TexStorage2DEXT) /* 473 */ \ + OP(GenQueriesEXTImmediate) /* 474 */ \ + OP(DeleteQueriesEXTImmediate) /* 475 */ \ + OP(BeginQueryEXT) /* 476 */ \ + OP(BeginTransformFeedback) /* 477 */ \ + OP(EndQueryEXT) /* 478 */ \ + OP(EndTransformFeedback) /* 479 */ \ + OP(InsertEventMarkerEXT) /* 480 */ \ + OP(PushGroupMarkerEXT) /* 481 */ \ + OP(PopGroupMarkerEXT) /* 482 */ \ + OP(GenVertexArraysOESImmediate) /* 483 */ \ + OP(DeleteVertexArraysOESImmediate) /* 484 */ \ + OP(IsVertexArrayOES) /* 485 */ \ + OP(BindVertexArrayOES) /* 486 */ \ + OP(SwapBuffers) /* 487 */ \ + OP(GetMaxValueInBufferCHROMIUM) /* 488 */ \ + OP(EnableFeatureCHROMIUM) /* 489 */ \ + OP(MapBufferRange) /* 490 */ \ + OP(UnmapBuffer) /* 491 */ \ + OP(ResizeCHROMIUM) /* 492 */ \ + OP(GetRequestableExtensionsCHROMIUM) /* 493 */ \ + OP(RequestExtensionCHROMIUM) /* 494 */ \ + OP(GetProgramInfoCHROMIUM) /* 495 */ \ + OP(GetUniformBlocksCHROMIUM) /* 496 */ \ + OP(GetTransformFeedbackVaryingsCHROMIUM) /* 497 */ \ + OP(GetUniformsES3CHROMIUM) /* 498 */ \ + OP(GetTranslatedShaderSourceANGLE) /* 499 */ \ + OP(PostSubBufferCHROMIUM) /* 500 */ \ + OP(TexImageIOSurface2DCHROMIUM) /* 501 */ \ + OP(CopyTextureCHROMIUM) /* 502 */ \ + OP(CopySubTextureCHROMIUM) /* 503 */ \ + OP(DrawArraysInstancedANGLE) /* 504 */ \ + OP(DrawElementsInstancedANGLE) /* 505 */ \ + OP(VertexAttribDivisorANGLE) /* 506 */ \ + OP(GenMailboxCHROMIUM) /* 507 */ \ + OP(ProduceTextureCHROMIUMImmediate) /* 508 */ \ + OP(ProduceTextureDirectCHROMIUMImmediate) /* 509 */ \ + OP(ConsumeTextureCHROMIUMImmediate) /* 510 */ \ + OP(CreateAndConsumeTextureCHROMIUMImmediate) /* 511 */ \ + OP(BindUniformLocationCHROMIUMBucket) /* 512 */ \ + OP(GenValuebuffersCHROMIUMImmediate) /* 513 */ \ + OP(DeleteValuebuffersCHROMIUMImmediate) /* 514 */ \ + OP(IsValuebufferCHROMIUM) /* 515 */ \ + OP(BindValuebufferCHROMIUM) /* 516 */ \ + OP(SubscribeValueCHROMIUM) /* 517 */ \ + OP(PopulateSubscribedValuesCHROMIUM) /* 518 */ \ + OP(UniformValuebufferCHROMIUM) /* 519 */ \ + OP(BindTexImage2DCHROMIUM) /* 520 */ \ + OP(ReleaseTexImage2DCHROMIUM) /* 521 */ \ + OP(TraceBeginCHROMIUM) /* 522 */ \ + OP(TraceEndCHROMIUM) /* 523 */ \ + OP(AsyncTexSubImage2DCHROMIUM) /* 524 */ \ + OP(AsyncTexImage2DCHROMIUM) /* 525 */ \ + OP(WaitAsyncTexImage2DCHROMIUM) /* 526 */ \ + OP(WaitAllAsyncTexImage2DCHROMIUM) /* 527 */ \ + OP(DiscardFramebufferEXTImmediate) /* 528 */ \ + OP(LoseContextCHROMIUM) /* 529 */ \ + OP(InsertSyncPointCHROMIUM) /* 530 */ \ + OP(WaitSyncPointCHROMIUM) /* 531 */ \ + OP(DrawBuffersEXTImmediate) /* 532 */ \ + OP(DiscardBackbufferCHROMIUM) /* 533 */ \ + OP(ScheduleOverlayPlaneCHROMIUM) /* 534 */ \ + OP(SwapInterval) /* 535 */ \ + OP(MatrixLoadfCHROMIUMImmediate) /* 536 */ \ + OP(MatrixLoadIdentityCHROMIUM) /* 537 */ \ + OP(BlendBarrierKHR) /* 538 */ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this.
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h index cd5002d4..62da42f 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_autogen.h
@@ -41,6 +41,7 @@ static std::string GetStringImageUsage(uint32_t value); static std::string GetStringIndexType(uint32_t value); static std::string GetStringIndexedBufferTarget(uint32_t value); +static std::string GetStringIndexedGLState(uint32_t value); static std::string GetStringMapBufferAccess(uint32_t value); static std::string GetStringMatrixMode(uint32_t value); static std::string GetStringPixelStore(uint32_t value); @@ -83,6 +84,7 @@ static std::string GetStringUniformBlockParameter(uint32_t value); static std::string GetStringUniformParameter(uint32_t value); static std::string GetStringValueBufferTarget(uint32_t value); +static std::string GetStringVertexAttribIType(uint32_t value); static std::string GetStringVertexAttribType(uint32_t value); static std::string GetStringVertexAttribute(uint32_t value); static std::string GetStringVertexPointer(uint32_t value);
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 89b32c6..dde4a31c 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -4942,6 +4942,21 @@ arraysize(string_table), value); } +std::string GLES2Util::GetStringIndexedGLState(uint32_t value) { + static const EnumToString string_table[] = { + {GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, + "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING"}, + {GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE"}, + {GL_TRANSFORM_FEEDBACK_BUFFER_START, + "GL_TRANSFORM_FEEDBACK_BUFFER_START"}, + {GL_UNIFORM_BUFFER_BINDING, "GL_UNIFORM_BUFFER_BINDING"}, + {GL_UNIFORM_BUFFER_SIZE, "GL_UNIFORM_BUFFER_SIZE"}, + {GL_UNIFORM_BUFFER_START, "GL_UNIFORM_BUFFER_START"}, + }; + return GLES2Util::GetQualifiedEnumString(string_table, + arraysize(string_table), value); +} + std::string GLES2Util::GetStringMapBufferAccess(uint32_t value) { static const EnumToString string_table[] = { {GL_MAP_READ_BIT, "GL_MAP_READ_BIT"}, @@ -5566,6 +5581,19 @@ arraysize(string_table), value); } +std::string GLES2Util::GetStringVertexAttribIType(uint32_t value) { + static const EnumToString string_table[] = { + {GL_BYTE, "GL_BYTE"}, + {GL_UNSIGNED_BYTE, "GL_UNSIGNED_BYTE"}, + {GL_SHORT, "GL_SHORT"}, + {GL_UNSIGNED_SHORT, "GL_UNSIGNED_SHORT"}, + {GL_INT, "GL_INT"}, + {GL_UNSIGNED_INT, "GL_UNSIGNED_INT"}, + }; + return GLES2Util::GetQualifiedEnumString(string_table, + arraysize(string_table), value); +} + std::string GLES2Util::GetStringVertexAttribType(uint32_t value) { static const EnumToString string_table[] = { {GL_BYTE, "GL_BYTE"},
diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index 17871b97..d2667f0 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc
@@ -360,10 +360,10 @@ return total; } -void ContextGroup::LoseContexts(GLenum reset_status) { +void ContextGroup::LoseContexts(error::ContextLostReason reason) { for (size_t ii = 0; ii < decoders_.size(); ++ii) { if (decoders_[ii].get()) { - decoders_[ii]->LoseContext(reset_status); + decoders_[ii]->MarkContextLost(reason); } } }
diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index 248fa19..f2e832f 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h
@@ -166,7 +166,7 @@ uint32 GetMemRepresented() const; // Loses all the context associated with this group. - void LoseContexts(GLenum reset_status); + void LoseContexts(error::ContextLostReason reason); // EXT_draw_buffer related states for backbuffer. GLenum draw_buffer() const {
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc index 05ea8af..5c5da82 100644 --- a/gpu/command_buffer/service/context_state.cc +++ b/gpu/command_buffer/service/context_state.cc
@@ -285,16 +285,8 @@ void ContextState::EnableDisable(GLenum pname, bool enable) const { if (pname == GL_PRIMITIVE_RESTART_FIXED_INDEX) { - // This is only available on Desktop GL 4.3+, but we emulate ES 3.0 on top - // of Desktop GL 4.2+. - const gfx::GLVersionInfo& gl_version = feature_info_->gl_version_info(); - if (!gl_version.is_es && - (gl_version.major_version < 4 || - (gl_version.major_version == 4 && gl_version.minor_version < 3))) { - // TODO(zmo): Ignoring it may not be the best emulation. - NOTIMPLEMENTED(); - return; - } + if (feature_info_->feature_flags().emulate_primitive_restart_fixed_index) + pname = GL_PRIMITIVE_RESTART; } if (enable) { glEnable(pname);
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index c6220bb..098ab64 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc
@@ -161,7 +161,8 @@ blend_equation_advanced(false), blend_equation_advanced_coherent(false), ext_texture_rg(false), - enable_subscribe_uniform(false) { + enable_subscribe_uniform(false), + emulate_primitive_restart_fixed_index(false) { } FeatureInfo::Workarounds::Workarounds() : @@ -1097,6 +1098,13 @@ gfx::GLFenceEGL::SetIgnoreFailures(); } #endif + + if (gl_version_info_->IsLowerThanGL(4, 3)) { + // crbug.com/481184. + // GL_PRIMITIVE_RESTART_FIXED_INDEX is only available on Desktop GL 4.3+, + // but we emulate ES 3.0 on top of Desktop GL 4.2+. + feature_flags_.emulate_primitive_restart_fixed_index = true; + } } bool FeatureInfo::IsES3Capable() const {
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index 7816e79a..398172b 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h
@@ -78,6 +78,7 @@ bool blend_equation_advanced_coherent; bool ext_texture_rg; bool enable_subscribe_uniform; + bool emulate_primitive_restart_fixed_index; }; struct Workarounds {
diff --git a/gpu/command_buffer/service/gl_context_mock.cc b/gpu/command_buffer/service/gl_context_mock.cc new file mode 100644 index 0000000..ce5d10f2 --- /dev/null +++ b/gpu/command_buffer/service/gl_context_mock.cc
@@ -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. + +#include "gpu/command_buffer/service/gl_context_mock.h" + +namespace gpu { + +GLContextMock::GLContextMock() { +} +GLContextMock::~GLContextMock() { +} + +} // namespace gpu
diff --git a/gpu/command_buffer/service/gl_context_mock.h b/gpu/command_buffer/service/gl_context_mock.h new file mode 100644 index 0000000..77d669c --- /dev/null +++ b/gpu/command_buffer/service/gl_context_mock.h
@@ -0,0 +1,25 @@ +// 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 GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_MOCK_H_ +#define GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_MOCK_H_ + +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/gl/gl_context_stub_with_extensions.h" + +namespace gpu { + +class GLContextMock : public gfx::GLContextStubWithExtensions { + public: + GLContextMock(); + + MOCK_METHOD1(MakeCurrent, bool(gfx::GLSurface* surface)); + + protected: + virtual ~GLContextMock(); +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_SERVICE_GL_CONTEXT_MOCK_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 04a9eb2..0e69077 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -7,6 +7,7 @@ #include <stdio.h> #include <algorithm> +#include <cmath> #include <list> #include <map> #include <queue> @@ -18,7 +19,6 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/command_line.h" -#include "base/float_util.h" #include "base/memory/scoped_ptr.h" #include "base/numerics/safe_math.h" #include "base/strings/string_number_conversions.h" @@ -760,6 +760,9 @@ void OnFboChanged() const; void OnUseFramebuffer() const; + error::ContextLostReason GetContextLostReasonFromResetStatus( + GLenum reset_status) const; + // TODO(gman): Cache these pointers? BufferManager* buffer_manager() { return group_->buffer_manager(); @@ -1657,10 +1660,10 @@ GLenum* result_type, GLsizei* result_size); - void MaybeExitOnContextLost(); - bool WasContextLost() override; - bool WasContextLostByRobustnessExtension() override; - void LoseContext(uint32 reset_status) override; + bool WasContextLost() const override; + bool WasContextLostByRobustnessExtension() const override; + void MarkContextLost(error::ContextLostReason reason) override; + bool CheckResetStatus(); #if defined(OS_MACOSX) void ReleaseIOSurfaceForTexture(GLuint texture_id); @@ -1863,7 +1866,8 @@ int commands_to_process_; bool has_robustness_extension_; - GLenum reset_status_; + error::ContextLostReason context_lost_reason_; + bool context_was_lost_; bool reset_by_robustness_extension_; bool supports_post_sub_buffer_; @@ -2405,7 +2409,8 @@ feature_info_(group_->feature_info()), frame_number_(0), has_robustness_extension_(false), - reset_status_(GL_NO_ERROR), + context_lost_reason_(error::kUnknown), + context_was_lost_(false), reset_by_robustness_extension_(false), supports_post_sub_buffer_(false), force_webgl_glsl_validation_(false), @@ -2464,6 +2469,7 @@ TRACE_EVENT0("gpu", "GLES2DecoderImpl::Initialize"); DCHECK(context->IsCurrent(surface.get())); DCHECK(!context_.get()); + DCHECK(!offscreen || !offscreen_size.IsEmpty()); ContextCreationAttribHelper attrib_parser; if (!attrib_parser.Parse(attribs)) @@ -3327,11 +3333,22 @@ if (!context_.get()) return false; - if (!context_->MakeCurrent(surface_.get()) || WasContextLost()) { + if (WasContextLost()) { + LOG(ERROR) << " GLES2DecoderImpl: Trying to make lost context current."; + return false; + } + + if (!context_->MakeCurrent(surface_.get())) { LOG(ERROR) << " GLES2DecoderImpl: Context lost during MakeCurrent."; + MarkContextLost(error::kMakeCurrentFailed); + group_->LoseContexts(error::kUnknown); + return false; + } - MaybeExitOnContextLost(); - + if (CheckResetStatus()) { + LOG(ERROR) + << " GLES2DecoderImpl: Context reset detected after MakeCurrent."; + group_->LoseContexts(error::kUnknown); return false; } @@ -7056,6 +7073,9 @@ error::Error GLES2DecoderImpl::HandleDrawArrays(uint32 immediate_data_size, const void* cmd_data) { + // TODO(zmo): crbug.com/481184 + // On Desktop GL with versions lower than 4.3, we need to emulate + // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex(). const cmds::DrawArrays& c = *static_cast<const cmds::DrawArrays*>(cmd_data); return DoDrawArrays("glDrawArrays", false, @@ -7199,6 +7219,9 @@ error::Error GLES2DecoderImpl::HandleDrawElements(uint32 immediate_data_size, const void* cmd_data) { + // TODO(zmo): crbug.com/481184 + // On Desktop GL with versions lower than 4.3, we need to emulate + // GL_PRIMITIVE_RESTART_FIXED_INDEX using glPrimitiveRestartIndex(). const gles2::cmds::DrawElements& c = *static_cast<const gles2::cmds::DrawElements*>(cmd_data); return DoDrawElements("glDrawElements", @@ -7704,17 +7727,86 @@ error::Error GLES2DecoderImpl::HandleVertexAttribIPointer( uint32 immediate_data_size, const void* cmd_data) { - // TODO(zmo): Unsafe ES3 API, missing states update. if (!unsafe_es3_apis_enabled()) return error::kUnknownCommand; const gles2::cmds::VertexAttribIPointer& c = *static_cast<const gles2::cmds::VertexAttribIPointer*>(cmd_data); + + if (!state_.bound_array_buffer.get() || + state_.bound_array_buffer->IsDeleted()) { + if (state_.vertex_attrib_manager.get() == + state_.default_vertex_attrib_manager.get()) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glVertexAttribIPointer", "no array buffer bound"); + return error::kNoError; + } else if (c.offset != 0) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, + "glVertexAttribIPointer", "client side arrays are not allowed"); + return error::kNoError; + } + } + GLuint indx = c.indx; GLint size = c.size; GLenum type = c.type; GLsizei stride = c.stride; GLsizei offset = c.offset; const void* ptr = reinterpret_cast<const void*>(offset); + if (!validators_->vertex_attrib_i_type.IsValid(type)) { + LOCAL_SET_GL_ERROR_INVALID_ENUM("glVertexAttribIPointer", type, "type"); + return error::kNoError; + } + if (!validators_->vertex_attrib_size.IsValid(size)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glVertexAttribIPointer", "size GL_INVALID_VALUE"); + return error::kNoError; + } + if (indx >= group_->max_vertex_attribs()) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glVertexAttribIPointer", "index out of range"); + return error::kNoError; + } + if (stride < 0) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glVertexAttribIPointer", "stride < 0"); + return error::kNoError; + } + if (stride > 255) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glVertexAttribIPointer", "stride > 255"); + return error::kNoError; + } + if (offset < 0) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glVertexAttribIPointer", "offset < 0"); + return error::kNoError; + } + GLsizei component_size = + GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type); + // component_size must be a power of two to use & as optimized modulo. + DCHECK(GLES2Util::IsPOT(component_size)); + if (offset & (component_size - 1)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glVertexAttribIPointer", "offset not valid for type"); + return error::kNoError; + } + if (stride & (component_size - 1)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_OPERATION, + "glVertexAttribIPointer", "stride not valid for type"); + return error::kNoError; + } + state_.vertex_attrib_manager + ->SetAttribInfo(indx, + state_.bound_array_buffer.get(), + size, + type, + GL_FALSE, + stride, + stride != 0 ? stride : component_size * size, + offset); glVertexAttribIPointer(indx, size, type, stride, ptr); return error::kNoError; } @@ -10305,7 +10397,8 @@ GL_FRAMEBUFFER_COMPLETE) { LOG(ERROR) << "GLES2DecoderImpl::ResizeOffscreenFrameBuffer failed " << "because offscreen saved FBO was incomplete."; - LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB); + MarkContextLost(error::kUnknown); + group_->LoseContexts(error::kUnknown); return; } @@ -10362,7 +10455,10 @@ } else { if (!surface_->SwapBuffers()) { LOG(ERROR) << "Context lost because SwapBuffers failed."; - LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB); + if (!CheckResetStatus()) { + MarkContextLost(error::kUnknown); + group_->LoseContexts(error::kUnknown); + } } } @@ -10622,7 +10718,12 @@ } error::ContextLostReason GLES2DecoderImpl::GetContextLostReason() { - switch (reset_status_) { + return context_lost_reason_; +} + +error::ContextLostReason GLES2DecoderImpl::GetContextLostReasonFromResetStatus( + GLenum reset_status) const { + switch (reset_status) { case GL_NO_ERROR: // TODO(kbr): improve the precision of the error code in this case. // Consider delegating to context for error code if MakeCurrent fails. @@ -10639,7 +10740,24 @@ return error::kUnknown; } -void GLES2DecoderImpl::MaybeExitOnContextLost() { +bool GLES2DecoderImpl::WasContextLost() const { + return context_was_lost_; +} + +bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() const { + return WasContextLost() && reset_by_robustness_extension_; +} + +void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) { + // Only lose the context once. + if (WasContextLost()) + return; + + // Don't make GL calls in here, the context might not be current. + context_lost_reason_ = reason; + current_decoder_error_ = error::kLostContext; + context_was_lost_ = true; + // Some D3D drivers cannot recover from device lost in the GPU process // sandbox. Allow a new GPU process to launch. if (workarounds().exit_on_context_lost) { @@ -10652,57 +10770,43 @@ } } -bool GLES2DecoderImpl::WasContextLost() { - if (reset_status_ != GL_NO_ERROR) { - MaybeExitOnContextLost(); - return true; - } +bool GLES2DecoderImpl::CheckResetStatus() { + DCHECK(!WasContextLost()); + DCHECK(context_->IsCurrent(NULL)); + if (IsRobustnessSupported()) { - GLenum status = glGetGraphicsResetStatusARB(); - if (status != GL_NO_ERROR) { - // The graphics card was reset. Signal a lost context to the application. - reset_status_ = status; - reset_by_robustness_extension_ = true; - LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen") - << " context lost via ARB/EXT_robustness. Reset status = " - << GLES2Util::GetStringEnum(status); - MaybeExitOnContextLost(); - return true; - } - } - return false; -} - -bool GLES2DecoderImpl::WasContextLostByRobustnessExtension() { - return WasContextLost() && reset_by_robustness_extension_; -} - -void GLES2DecoderImpl::LoseContext(uint32 reset_status) { - // Only loses the context once. - if (reset_status_ != GL_NO_ERROR) { - return; - } - - if (workarounds().use_virtualized_gl_contexts) { - // If the context is virtual, the real context being guilty does not ensure - // that the virtual context is guilty. - if (reset_status == GL_GUILTY_CONTEXT_RESET_ARB) { - reset_status = GL_UNKNOWN_CONTEXT_RESET_ARB; - } - } else if (reset_status == GL_UNKNOWN_CONTEXT_RESET_ARB && - IsRobustnessSupported()) { // If the reason for the call was a GL error, we can try to determine the // reset status more accurately. GLenum driver_status = glGetGraphicsResetStatusARB(); - if (driver_status == GL_GUILTY_CONTEXT_RESET_ARB || - driver_status == GL_INNOCENT_CONTEXT_RESET_ARB) { - reset_status = driver_status; - } - } + if (driver_status == GL_NO_ERROR) + return false; - // Marks this context as lost. - reset_status_ = reset_status; - current_decoder_error_ = error::kLostContext; + LOG(ERROR) << (surface_->IsOffscreen() ? "Offscreen" : "Onscreen") + << " context lost via ARB/EXT_robustness. Reset status = " + << GLES2Util::GetStringEnum(driver_status); + + // Don't pretend we know which client was responsible. + if (workarounds().use_virtualized_gl_contexts) + driver_status = GL_UNKNOWN_CONTEXT_RESET_ARB; + + switch (driver_status) { + case GL_GUILTY_CONTEXT_RESET_ARB: + MarkContextLost(error::kGuilty); + break; + case GL_INNOCENT_CONTEXT_RESET_ARB: + MarkContextLost(error::kInnocent); + break; + case GL_UNKNOWN_CONTEXT_RESET_ARB: + MarkContextLost(error::kUnknown); + break; + default: + NOTREACHED(); + return false; + } + reset_by_robustness_extension_ = true; + return true; + } + return false; } error::Error GLES2DecoderImpl::HandleInsertSyncPointCHROMIUM( @@ -12078,9 +12182,9 @@ } void GLES2DecoderImpl::DoLoseContextCHROMIUM(GLenum current, GLenum other) { - group_->LoseContexts(other); - reset_status_ = current; - current_decoder_error_ = error::kLostContext; + MarkContextLost(GetContextLostReasonFromResetStatus(current)); + group_->LoseContexts(GetContextLostReasonFromResetStatus(other)); + reset_by_robustness_extension_ = true; } void GLES2DecoderImpl::DoMatrixLoadfCHROMIUM(GLenum matrix_mode, @@ -12598,8 +12702,9 @@ // the second unmap could still return GL_FALSE. For now, we simply lose // the contexts in the share group. LOG(ERROR) << "glUnmapBuffer unexpectedly returned GL_FALSE"; - group_->LoseContexts(GL_INNOCENT_CONTEXT_RESET_ARB); - reset_status_ = GL_GUILTY_CONTEXT_RESET_ARB; + // Need to lose current context before broadcasting! + MarkContextLost(error::kGuilty); + group_->LoseContexts(error::kInnocent); return error::kLostContext; } return error::kNoError; @@ -12611,13 +12716,27 @@ DoDidUseTexImageIfNeeded(texture, texture->target()); } +// Note that GL_LOST_CONTEXT is specific to GLES. +// For desktop GL we have to query the reset status proactively. void GLES2DecoderImpl::OnContextLostError() { - group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB); + if (!WasContextLost()) { + // Need to lose current context before broadcasting! + CheckResetStatus(); + group_->LoseContexts(error::kUnknown); + reset_by_robustness_extension_ = true; + } } void GLES2DecoderImpl::OnOutOfMemoryError() { - if (lose_context_when_out_of_memory_) { - group_->LoseContexts(GL_UNKNOWN_CONTEXT_RESET_ARB); + if (lose_context_when_out_of_memory_ && !WasContextLost()) { + error::ContextLostReason other = error::kOutOfMemory; + if (CheckResetStatus()) { + other = error::kUnknown; + } else { + // Need to lose current context before broadcasting! + MarkContextLost(error::kOutOfMemory); + } + group_->LoseContexts(other); } }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h index 0cbe0fe5..ac01c958 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -241,13 +241,13 @@ // Returns true if the context was lost either by GL_ARB_robustness, forced // context loss or command buffer parse error. - virtual bool WasContextLost() = 0; + virtual bool WasContextLost() const = 0; // Returns true if the context was lost specifically by GL_ARB_robustness. - virtual bool WasContextLostByRobustnessExtension() = 0; + virtual bool WasContextLostByRobustnessExtension() const = 0; // Lose this context. - virtual void LoseContext(uint32 reset_status) = 0; + virtual void MarkContextLost(error::ContextLostReason reason) = 0; virtual Logger* GetLogger() = 0;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 8d763d4..62d0391c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -1524,6 +1524,73 @@ return error::kNoError; } +error::Error GLES2DecoderImpl::HandleGetIntegeri_v(uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::GetIntegeri_v& c = + *static_cast<const gles2::cmds::GetIntegeri_v*>(cmd_data); + (void)c; + GLenum pname = static_cast<GLenum>(c.pname); + GLuint index = static_cast<GLuint>(c.index); + typedef cmds::GetIntegeri_v::Result Result; + GLsizei num_values = 0; + GetNumValuesReturnedForGLGet(pname, &num_values); + Result* result = GetSharedMemoryAs<Result*>(c.data_shm_id, c.data_shm_offset, + Result::ComputeSize(num_values)); + GLint* data = result ? result->GetData() : NULL; + if (data == NULL) { + return error::kOutOfBounds; + } + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetIntegeri_v"); + // Check that the client initialized the result. + if (result->size != 0) { + return error::kInvalidArguments; + } + glGetIntegeri_v(pname, index, data); + GLenum error = glGetError(); + if (error == GL_NO_ERROR) { + result->SetNumResults(num_values); + } else { + LOCAL_SET_GL_ERROR(error, "GetIntegeri_v", ""); + } + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleGetInteger64i_v( + uint32_t immediate_data_size, + const void* cmd_data) { + if (!unsafe_es3_apis_enabled()) + return error::kUnknownCommand; + const gles2::cmds::GetInteger64i_v& c = + *static_cast<const gles2::cmds::GetInteger64i_v*>(cmd_data); + (void)c; + GLenum pname = static_cast<GLenum>(c.pname); + GLuint index = static_cast<GLuint>(c.index); + typedef cmds::GetInteger64i_v::Result Result; + GLsizei num_values = 0; + GetNumValuesReturnedForGLGet(pname, &num_values); + Result* result = GetSharedMemoryAs<Result*>(c.data_shm_id, c.data_shm_offset, + Result::ComputeSize(num_values)); + GLint64* data = result ? result->GetData() : NULL; + if (data == NULL) { + return error::kOutOfBounds; + } + LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("GetInteger64i_v"); + // Check that the client initialized the result. + if (result->size != 0) { + return error::kInvalidArguments; + } + glGetInteger64i_v(pname, index, data); + GLenum error = glGetError(); + if (error == GL_NO_ERROR) { + result->SetNumResults(num_values); + } else { + LOCAL_SET_GL_ERROR(error, "GetInteger64i_v", ""); + } + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleGetIntegerv(uint32_t immediate_data_size, const void* cmd_data) { const gles2::cmds::GetIntegerv& c = @@ -2247,7 +2314,7 @@ *static_cast<const gles2::cmds::LineWidth*>(cmd_data); (void)c; GLfloat width = static_cast<GLfloat>(c.width); - if (width <= 0.0f || base::IsNaN(width)) { + if (width <= 0.0f || std::isnan(width)) { LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "LineWidth", "width out of range"); return error::kNoError; }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h index c58405b..65df53c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -124,9 +124,9 @@ MOCK_METHOD0(GetTotalTextureUploadTime, base::TimeDelta()); MOCK_METHOD0(GetTotalProcessingCommandsTime, base::TimeDelta()); MOCK_METHOD1(AddProcessingCommandsTime, void(base::TimeDelta)); - MOCK_METHOD0(WasContextLost, bool()); - MOCK_METHOD0(WasContextLostByRobustnessExtension, bool()); - MOCK_METHOD1(LoseContext, void(uint32 reset_status)); + MOCK_CONST_METHOD0(WasContextLost, bool()); + MOCK_CONST_METHOD0(WasContextLostByRobustnessExtension, bool()); + MOCK_METHOD1(MarkContextLost, void(gpu::error::ContextLostReason reason)); DISALLOW_COPY_AND_ASSIGN(MockGLES2Decoder); };
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index cae6c006..d3a20b3c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -1125,17 +1125,30 @@ EXPECT_EQ(GL_INVALID_OPERATION, GetGLError()); } -TEST_P(GLES2DecoderTest, LoseContextCHROMIUMValidArgs) { - EXPECT_CALL(*mock_decoder_, LoseContext(GL_GUILTY_CONTEXT_RESET_ARB)) +TEST_P(GLES2DecoderTest, LoseContextCHROMIUMGuilty) { + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kInnocent)) .Times(1); cmds::LoseContextCHROMIUM cmd; - cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_GUILTY_CONTEXT_RESET_ARB); + cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB); EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension()); +} + +TEST_P(GLES2DecoderTest, LoseContextCHROMIUMUnkown) { + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)) + .Times(1); + cmds::LoseContextCHROMIUM cmd; + cmd.Init(GL_UNKNOWN_CONTEXT_RESET_ARB, GL_UNKNOWN_CONTEXT_RESET_ARB); + EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension()); } TEST_P(GLES2DecoderTest, LoseContextCHROMIUMInvalidArgs0_0) { - EXPECT_CALL(*mock_decoder_, LoseContext(_)) + EXPECT_CALL(*mock_decoder_, MarkContextLost(_)) .Times(0); cmds::LoseContextCHROMIUM cmd; cmd.Init(GL_NONE, GL_GUILTY_CONTEXT_RESET_ARB); @@ -1144,7 +1157,7 @@ } TEST_P(GLES2DecoderTest, LoseContextCHROMIUMInvalidArgs1_0) { - EXPECT_CALL(*mock_decoder_, LoseContext(_)) + EXPECT_CALL(*mock_decoder_, MarkContextLost(_)) .Times(0); cmds::LoseContextCHROMIUM cmd; cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_NONE);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index d06348e..e74693c 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h
@@ -1526,6 +1526,54 @@ EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); } +TEST_P(GLES2DecoderTest1, GetIntegeri_vValidArgs) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + SpecializedSetup<cmds::GetIntegeri_v, 0>(true); + typedef cmds::GetIntegeri_v::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, + result->GetData())); + result->size = 0; + cmds::GetIntegeri_v cmd; + cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, shared_memory_id_, + shared_memory_offset_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( + GL_TRANSFORM_FEEDBACK_BUFFER_BINDING), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + +TEST_P(GLES2DecoderTest1, GetInteger64i_vValidArgs) { + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + SpecializedSetup<cmds::GetInteger64i_v, 0>(true); + typedef cmds::GetInteger64i_v::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetInteger64i_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, + result->GetData())); + result->size = 0; + cmds::GetInteger64i_v cmd; + cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, 2, shared_memory_id_, + shared_memory_offset_); + decoder_->set_unsafe_es3_apis_enabled(true); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( + GL_TRANSFORM_FEEDBACK_BUFFER_BINDING), + result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + decoder_->set_unsafe_es3_apis_enabled(false); + EXPECT_EQ(error::kUnknownCommand, ExecuteCmd(cmd)); +} + TEST_P(GLES2DecoderTest1, GetIntegervValidArgs) { EXPECT_CALL(*gl_, GetError()) .WillOnce(Return(GL_NO_ERROR)) @@ -1828,7 +1876,4 @@ EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd)); EXPECT_EQ(0u, result->size); } -// TODO(gman): GetShaderInfoLog -// TODO(gman): GetShaderPrecisionFormat - #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc index cfd1c1a..234a6e8 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
@@ -367,26 +367,6 @@ }; template <> -void GLES2DecoderTestBase::SpecializedSetup<cmds::ValidateProgram, 0>( - bool /* valid */) { - // Needs the same setup as LinkProgram. - SpecializedSetup<cmds::LinkProgram, 0>(false); - - EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)) - .Times(1) - .RetiresOnSaturation(); - - cmds::LinkProgram link_cmd; - link_cmd.Init(client_program_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd)); - - EXPECT_CALL(*gl_, - GetProgramiv(kServiceProgramId, GL_INFO_LOG_LENGTH, _)) - .WillOnce(SetArgumentPointee<2>(0)) - .RetiresOnSaturation(); -}; - -template <> void GLES2DecoderTestBase::SpecializedSetup<cmds::Uniform1f, 0>( bool /* valid */) { SetupShaderForUniform(GL_FLOAT);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index e7948d1a..a7a5bf0 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -12,6 +12,9 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ +// TODO(gman): GetShaderInfoLog +// TODO(gman): GetShaderPrecisionFormat + // TODO(gman): GetShaderSource // TODO(gman): GetString @@ -1569,22 +1572,4 @@ EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } - -TEST_P(GLES2DecoderTest2, ValidateProgramValidArgs) { - EXPECT_CALL(*gl_, ValidateProgram(kServiceProgramId)); - SpecializedSetup<cmds::ValidateProgram, 0>(true); - cmds::ValidateProgram cmd; - cmd.Init(client_program_id_); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} - -TEST_P(GLES2DecoderTest2, VertexAttrib1fValidArgs) { - EXPECT_CALL(*gl_, VertexAttrib1f(1, 2)); - SpecializedSetup<cmds::VertexAttrib1f, 0>(true); - cmds::VertexAttrib1f cmd; - cmd.Init(1, 2); - EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); - EXPECT_EQ(GL_NO_ERROR, GetGLError()); -} #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc index 86b61ac..d2ef969b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3.cc
@@ -36,6 +36,26 @@ INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderTest3, ::testing::Bool()); +template <> +void GLES2DecoderTestBase::SpecializedSetup<cmds::ValidateProgram, 0>( + bool /* valid */) { + // Needs the same setup as LinkProgram. + SpecializedSetup<cmds::LinkProgram, 0>(false); + + EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId)) + .Times(1) + .RetiresOnSaturation(); + + cmds::LinkProgram link_cmd; + link_cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd)); + + EXPECT_CALL(*gl_, + GetProgramiv(kServiceProgramId, GL_INFO_LOG_LENGTH, _)) + .WillOnce(SetArgumentPointee<2>(0)) + .RetiresOnSaturation(); +}; + TEST_P(GLES2DecoderTest3, TraceBeginCHROMIUM) { const uint32 kCategoryBucketId = 123; const uint32 kNameBucketId = 234;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index 2261f5c..f88a046 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h
@@ -12,6 +12,24 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ +TEST_P(GLES2DecoderTest3, ValidateProgramValidArgs) { + EXPECT_CALL(*gl_, ValidateProgram(kServiceProgramId)); + SpecializedSetup<cmds::ValidateProgram, 0>(true); + cmds::ValidateProgram cmd; + cmd.Init(client_program_id_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + +TEST_P(GLES2DecoderTest3, VertexAttrib1fValidArgs) { + EXPECT_CALL(*gl_, VertexAttrib1f(1, 2)); + SpecializedSetup<cmds::VertexAttrib1f, 0>(true); + cmds::VertexAttrib1f cmd; + cmd.Init(1, 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); +} + TEST_P(GLES2DecoderTest3, VertexAttrib1fvImmediateValidArgs) { cmds::VertexAttrib1fvImmediate& cmd = *GetImmediateAs<cmds::VertexAttrib1fvImmediate>();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 8648134..d757926 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -200,11 +200,11 @@ // Context needs to be created before initializing ContextGroup, which will // in turn initialize FeatureInfo, which needs a context to determine // extension support. - context_ = new gfx::GLContextStubWithExtensions; + context_ = new StrictMock<GLContextMock>(); context_->AddExtensionsString(normalized_init.extensions.c_str()); context_->SetGLVersionString(normalized_init.gl_version.c_str()); - context_->MakeCurrent(surface_.get()); + context_->GLContextStubWithExtensions::MakeCurrent(surface_.get()); gfx::GLSurface::InitializeDynamicMockBindingsForTests(context_.get()); TestHelper::SetupContextGroupInitExpectations( @@ -401,6 +401,11 @@ surface_->GetSize(), DisallowedFeatures(), attribs); + EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(true)); + if (context_->WasAllocatedUsingRobustnessExtension()) { + EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()) + .WillOnce(Return(GL_NO_ERROR)); + } decoder_->MakeCurrent(); decoder_->set_engine(engine_.get()); decoder_->BeginDecoding();
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 0ca537a..7719cdf 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -11,6 +11,7 @@ #include "gpu/command_buffer/service/cmd_buffer_engine.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/framebuffer_manager.h" +#include "gpu/command_buffer/service/gl_context_mock.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h" #include "gpu/command_buffer/service/program_manager.h" @@ -22,7 +23,6 @@ #include "gpu/command_buffer/service/valuebuffer_manager.h" #include "gpu/command_buffer/service/vertex_array_manager.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gl/gl_context_stub_with_extensions.h" #include "ui/gl/gl_surface_stub.h" #include "ui/gl/gl_mock.h" @@ -211,6 +211,10 @@ return *group_.get(); } + void LoseContexts(error::ContextLostReason reason) const { + group_->LoseContexts(reason); + } + ::testing::StrictMock< ::gfx::MockGLInterface>* GetGLMock() const { return gl_.get(); } @@ -540,7 +544,7 @@ // Use StrictMock to make 100% sure we know how GL will be called. scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; scoped_refptr<gfx::GLSurfaceStub> surface_; - scoped_refptr<gfx::GLContextStubWithExtensions> context_; + scoped_refptr<GLContextMock> context_; scoped_ptr<MockGLES2Decoder> mock_decoder_; scoped_ptr<GLES2Decoder> decoder_; MemoryTracker* memory_tracker_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc new file mode 100644 index 0000000..3fe88b9 --- /dev/null +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc
@@ -0,0 +1,273 @@ +// 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 "gpu/command_buffer/service/gles2_cmd_decoder.h" + +#include "base/command_line.h" +#include "base/strings/string_number_conversions.h" +#include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/cmd_buffer_engine.h" +#include "gpu/command_buffer/service/context_group.h" +#include "gpu/command_buffer/service/gl_surface_mock.h" +#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h" +#include "gpu/command_buffer/service/gpu_switches.h" +#include "gpu/command_buffer/service/mocks.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gl/gl_mock.h" + +using ::gfx::MockGLInterface; +using ::testing::_; +using ::testing::DoAll; +using ::testing::InSequence; +using ::testing::Invoke; +using ::testing::MatcherCast; +using ::testing::Mock; +using ::testing::Pointee; +using ::testing::Return; +using ::testing::SaveArg; +using ::testing::SetArrayArgument; +using ::testing::SetArgumentPointee; +using ::testing::SetArgPointee; +using ::testing::StrEq; +using ::testing::StrictMock; + +namespace gpu { +namespace gles2 { + +using namespace cmds; + +class GLES2DecoderDrawOOMTest : public GLES2DecoderManualInitTest { + protected: + void Init(bool has_robustness) { + InitState init; + init.lose_context_when_out_of_memory = true; + if (has_robustness) + init.extensions = "GL_ARB_robustness"; + InitDecoder(init); + SetupDefaultProgram(); + } + + void Draw(GLenum reset_status, + error::ContextLostReason expected_other_reason) { + const GLsizei kFakeLargeCount = 0x1234; + SetupTexture(); + if (context_->WasAllocatedUsingRobustnessExtension()) { + EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()) + .WillOnce(Return(reset_status)); + } + AddExpectationsForSimulatedAttrib0WithError(kFakeLargeCount, 0, + GL_OUT_OF_MEMORY); + EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation(); + // Other contexts in the group should be lost also. + EXPECT_CALL(*mock_decoder_, MarkContextLost(expected_other_reason)) + .Times(1) + .RetiresOnSaturation(); + DrawArrays cmd; + cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount); + EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); + } +}; + +// Test that we lose context. +TEST_P(GLES2DecoderDrawOOMTest, ContextLostReasonOOM) { + Init(false); // without robustness + const error::ContextLostReason expected_reason_for_other_contexts = + error::kOutOfMemory; + Draw(GL_NO_ERROR, expected_reason_for_other_contexts); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_EQ(error::kOutOfMemory, decoder_->GetContextLostReason()); +} + +TEST_P(GLES2DecoderDrawOOMTest, ContextLostReasonWhenStatusIsNoError) { + Init(true); // with robustness + // If the reset status is NO_ERROR, we should be signaling kOutOfMemory. + const error::ContextLostReason expected_reason_for_other_contexts = + error::kOutOfMemory; + Draw(GL_NO_ERROR, expected_reason_for_other_contexts); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_EQ(error::kOutOfMemory, decoder_->GetContextLostReason()); +} + +TEST_P(GLES2DecoderDrawOOMTest, ContextLostReasonWhenStatusIsGuilty) { + Init(true); + // If there was a reset, it should override kOutOfMemory. + const error::ContextLostReason expected_reason_for_other_contexts = + error::kUnknown; + Draw(GL_GUILTY_CONTEXT_RESET_ARB, expected_reason_for_other_contexts); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_EQ(error::kGuilty, decoder_->GetContextLostReason()); +} + +TEST_P(GLES2DecoderDrawOOMTest, ContextLostReasonWhenStatusIsUnknown) { + Init(true); + // If there was a reset, it should override kOutOfMemory. + const error::ContextLostReason expected_reason_for_other_contexts = + error::kUnknown; + Draw(GL_UNKNOWN_CONTEXT_RESET_ARB, expected_reason_for_other_contexts); + EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_EQ(error::kUnknown, decoder_->GetContextLostReason()); +} + +INSTANTIATE_TEST_CASE_P(Service, GLES2DecoderDrawOOMTest, ::testing::Bool()); + +class GLES2DecoderLostContextTest : public GLES2DecoderManualInitTest { + protected: + void Init(bool has_robustness) { + InitState init; + init.gl_version = "opengl es 2.0"; + if (has_robustness) + init.extensions = "GL_KHR_robustness"; + InitDecoder(init); + } + + void InitWithVirtualContextsAndRobustness() { + base::CommandLine command_line(0, NULL); + command_line.AppendSwitchASCII( + switches::kGpuDriverBugWorkarounds, + base::IntToString(USE_VIRTUALIZED_GL_CONTEXTS)); + InitState init; + init.gl_version = "opengl es 2.0"; + init.extensions = "GL_KHR_robustness"; + InitDecoderWithCommandLine(init, &command_line); + } + + void DoGetErrorWithContextLost(GLenum reset_status) { + DCHECK(context_->HasExtension("GL_KHR_robustness")); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_CONTEXT_LOST_KHR)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()) + .WillOnce(Return(reset_status)); + cmds::GetError cmd; + cmd.Init(shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); + EXPECT_EQ(static_cast<GLuint>(GL_NO_ERROR), *GetSharedMemoryAs<GLenum*>()); + } + + void ClearCurrentDecoderError() { + DCHECK(decoder_->WasContextLost()); + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_CONTEXT_LOST_KHR)) + .RetiresOnSaturation(); + cmds::GetError cmd; + cmd.Init(shared_memory_id_, shared_memory_offset_); + EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); + } +}; + +TEST_P(GLES2DecoderLostContextTest, LostFromMakeCurrent) { + Init(false); // without robustness + EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(false)); + // Expect the group to be lost. + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)).Times(1); + decoder_->MakeCurrent(); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_EQ(error::kMakeCurrentFailed, decoder_->GetContextLostReason()); + + // We didn't process commands, so we need to clear the decoder error, + // so that we can shut down cleanly. + ClearCurrentDecoderError(); +} + +TEST_P(GLES2DecoderLostContextTest, LostFromMakeCurrentWithRobustness) { + Init(true); // with robustness + // If we can't make the context current, we cannot query the robustness + // extension. + EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()).Times(0); + EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(false)); + // Expect the group to be lost. + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)).Times(1); + decoder_->MakeCurrent(); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_FALSE(decoder_->WasContextLostByRobustnessExtension()); + EXPECT_EQ(error::kMakeCurrentFailed, decoder_->GetContextLostReason()); + + // We didn't process commands, so we need to clear the decoder error, + // so that we can shut down cleanly. + ClearCurrentDecoderError(); +} + +TEST_P(GLES2DecoderLostContextTest, LostFromResetAfterMakeCurrent) { + Init(true); // with robustness + InSequence seq; + EXPECT_CALL(*context_, MakeCurrent(surface_.get())).WillOnce(Return(true)); + EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()) + .WillOnce(Return(GL_GUILTY_CONTEXT_RESET_KHR)); + // Expect the group to be lost. + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)).Times(1); + decoder_->MakeCurrent(); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension()); + EXPECT_EQ(error::kGuilty, decoder_->GetContextLostReason()); + + // We didn't process commands, so we need to clear the decoder error, + // so that we can shut down cleanly. + ClearCurrentDecoderError(); +} + +TEST_P(GLES2DecoderLostContextTest, LoseGuiltyFromGLError) { + Init(true); + // Always expect other contexts to be signaled as 'kUnknown' since we can't + // query their status without making them current. + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)) + .Times(1); + DoGetErrorWithContextLost(GL_GUILTY_CONTEXT_RESET_KHR); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension()); + EXPECT_EQ(error::kGuilty, decoder_->GetContextLostReason()); +} + +TEST_P(GLES2DecoderLostContextTest, LoseInnocentFromGLError) { + Init(true); + // Always expect other contexts to be signaled as 'kUnknown' since we can't + // query their status without making them current. + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)) + .Times(1); + DoGetErrorWithContextLost(GL_INNOCENT_CONTEXT_RESET_KHR); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension()); + EXPECT_EQ(error::kInnocent, decoder_->GetContextLostReason()); +} + +TEST_P(GLES2DecoderLostContextTest, LoseVirtualContextWithRobustness) { + InitWithVirtualContextsAndRobustness(); + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)) + .Times(1); + // Signal guilty.... + DoGetErrorWithContextLost(GL_GUILTY_CONTEXT_RESET_KHR); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_TRUE(decoder_->WasContextLostByRobustnessExtension()); + // ...but make sure we don't pretend, since for virtual contexts we don't + // know if this was really the guilty client. + EXPECT_EQ(error::kUnknown, decoder_->GetContextLostReason()); +} + +TEST_P(GLES2DecoderLostContextTest, LoseGroupFromRobustness) { + // If one context in a group is lost through robustness, + // the other ones should also get lost and query the reset status. + Init(true); + EXPECT_CALL(*mock_decoder_, MarkContextLost(error::kUnknown)) + .Times(1); + // There should be no GL calls, since we might not have a current context. + EXPECT_CALL(*gl_, GetGraphicsResetStatusARB()).Times(0); + LoseContexts(error::kUnknown); + EXPECT_TRUE(decoder_->WasContextLost()); + EXPECT_EQ(error::kUnknown, decoder_->GetContextLostReason()); + + // We didn't process commands, so we need to clear the decoder error, + // so that we can shut down cleanly. + ClearCurrentDecoderError(); +} + +INSTANTIATE_TEST_CASE_P(Service, + GLES2DecoderLostContextTest, + ::testing::Bool()); + +} // namespace gles2 +} // namespace gpu
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc index fc5e2de..87e95b7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc
@@ -739,35 +739,6 @@ EXPECT_FALSE(GetDecoder()->WasContextLost()); } -// Test that we lose context. -TEST_P(GLES2DecoderManualInitTest, LoseContextWhenOOM) { - InitState init; - init.has_alpha = true; - init.has_depth = true; - init.request_alpha = true; - init.request_depth = true; - init.bind_generates_resource = true; - init.lose_context_when_out_of_memory = true; - InitDecoder(init); - SetupDefaultProgram(); - - const GLsizei kFakeLargeCount = 0x1234; - SetupTexture(); - AddExpectationsForSimulatedAttrib0WithError( - kFakeLargeCount, 0, GL_OUT_OF_MEMORY); - EXPECT_CALL(*gl_, DrawArrays(_, _, _)).Times(0).RetiresOnSaturation(); - // Other contexts in the group should be lost also. - EXPECT_CALL(*mock_decoder_, LoseContext(GL_UNKNOWN_CONTEXT_RESET_ARB)) - .Times(1) - .RetiresOnSaturation(); - DrawArrays cmd; - cmd.Init(GL_TRIANGLES, 0, kFakeLargeCount); - // This context should be lost. - EXPECT_EQ(error::kLostContext, ExecuteCmd(cmd)); - EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError()); - EXPECT_TRUE(decoder_->WasContextLost()); -} - TEST_P(GLES2DecoderWithShaderTest, DrawArraysBadTextureUsesBlack) { DoBindTexture(GL_TEXTURE_2D, client_texture_id_, kServiceTextureId); // This is an NPOT texture. As the default filtering requires mips
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index 2a8684a..3099f29 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h
@@ -41,6 +41,7 @@ ValueValidator<GLenum> image_usage; ValueValidator<GLenum> index_type; ValueValidator<GLenum> indexed_buffer_target; +ValueValidator<GLenum> indexed_g_l_state; ValueValidator<GLenum> map_buffer_access; ValueValidator<GLenum> matrix_mode; ValueValidator<GLenum> pixel_store; @@ -84,6 +85,7 @@ ValueValidator<GLenum> uniform_block_parameter; ValueValidator<GLenum> uniform_parameter; ValueValidator<GLenum> value_buffer_target; +ValueValidator<GLenum> vertex_attrib_i_type; ValueValidator<GLint> vertex_attrib_size; ValueValidator<GLenum> vertex_attrib_type; ValueValidator<GLenum> vertex_attribute;
diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 6b8d4e6..9637a68 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h
@@ -377,6 +377,15 @@ GL_UNIFORM_BUFFER, }; +static const GLenum valid_indexed_g_l_state_table[] = { + GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, + GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, + GL_TRANSFORM_FEEDBACK_BUFFER_START, + GL_UNIFORM_BUFFER_BINDING, + GL_UNIFORM_BUFFER_SIZE, + GL_UNIFORM_BUFFER_START, +}; + static const GLenum valid_map_buffer_access_table[] = { GL_MAP_READ_BIT, GL_MAP_WRITE_BIT, @@ -857,6 +866,15 @@ GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM, }; +static const GLenum valid_vertex_attrib_i_type_table[] = { + GL_BYTE, + GL_UNSIGNED_BYTE, + GL_SHORT, + GL_UNSIGNED_SHORT, + GL_INT, + GL_UNSIGNED_INT, +}; + static const GLint valid_vertex_attrib_size_table[] = { 1, 2, @@ -929,6 +947,8 @@ index_type(valid_index_type_table, arraysize(valid_index_type_table)), indexed_buffer_target(valid_indexed_buffer_target_table, arraysize(valid_indexed_buffer_target_table)), + indexed_g_l_state(valid_indexed_g_l_state_table, + arraysize(valid_indexed_g_l_state_table)), map_buffer_access(valid_map_buffer_access_table, arraysize(valid_map_buffer_access_table)), matrix_mode(valid_matrix_mode_table, arraysize(valid_matrix_mode_table)), @@ -1011,6 +1031,8 @@ arraysize(valid_uniform_parameter_table)), value_buffer_target(valid_value_buffer_target_table, arraysize(valid_value_buffer_target_table)), + vertex_attrib_i_type(valid_vertex_attrib_i_type_table, + arraysize(valid_vertex_attrib_i_type_table)), vertex_attrib_size(valid_vertex_attrib_size_table, arraysize(valid_vertex_attrib_size_table)), vertex_attrib_type(valid_vertex_attrib_type_table,
diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 8988349..23779ea 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc
@@ -404,8 +404,8 @@ gles2_helper_.reset(); command_buffer_.reset(); if (decoder_.get()) { - decoder_->MakeCurrent(); - decoder_->Destroy(true); + bool have_context = decoder_->GetGLContext()->MakeCurrent(surface_.get()); + decoder_->Destroy(have_context); decoder_.reset(); } }
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index b84806a..9b50458 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp
@@ -205,6 +205,8 @@ 'command_buffer/service/context_group_unittest.cc', 'command_buffer/service/feature_info_unittest.cc', 'command_buffer/service/framebuffer_manager_unittest.cc', + 'command_buffer/service/gl_context_mock.cc', + 'command_buffer/service/gl_context_mock.h', 'command_buffer/service/gl_surface_mock.cc', 'command_buffer/service/gl_surface_mock.h', 'command_buffer/service/gles2_cmd_decoder_unittest.cc', @@ -221,6 +223,7 @@ 'command_buffer/service/gles2_cmd_decoder_unittest_base.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_base.h', 'command_buffer/service/gles2_cmd_decoder_unittest_buffers.cc', + 'command_buffer/service/gles2_cmd_decoder_unittest_context_lost.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc', 'command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc', @@ -750,6 +753,15 @@ 'sources': [ 'gpu_unittests.isolate', ], + 'conditions': [ + ['use_x11==1', + { + 'dependencies': [ + '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck', + ], + } + ], + ], }, ], }],
diff --git a/gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc b/gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc index 1e997ba7..36ff45bc 100644 --- a/gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc +++ b/gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc
@@ -29,7 +29,9 @@ functions->fBindBuffer = glBindBuffer; functions->fBindTexture = glBindTexture; functions->fBindVertexArray = glBindVertexArrayOES; + functions->fBlendBarrier = glBlendBarrierKHR; functions->fBlendColor = glBlendColor; + functions->fBlendEquation = glBlendEquation; functions->fBlendFunc = glBlendFunc; functions->fBufferData = glBufferData; functions->fBufferSubData = glBufferSubData;
diff --git a/ios/chrome/PRESUBMIT.py b/ios/chrome/PRESUBMIT.py new file mode 100644 index 0000000..18f3a4f --- /dev/null +++ b/ios/chrome/PRESUBMIT.py
@@ -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. + +"""Presubmit script for ios/chrome. + +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): + results = [] + results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api) + return results
diff --git a/ios/chrome/app/DEPS b/ios/chrome/app/DEPS new file mode 100644 index 0000000..9074a78 --- /dev/null +++ b/ios/chrome/app/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ios/chrome/browser", +]
diff --git a/ios/chrome/app/safe_mode_crashing_modules_config.h b/ios/chrome/app/safe_mode_crashing_modules_config.h new file mode 100644 index 0000000..d918edc --- /dev/null +++ b/ios/chrome/app/safe_mode_crashing_modules_config.h
@@ -0,0 +1,25 @@ +// Copyright 2013 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_CHROME_APP_SAFE_MODE_CRASHING_MODULES_CONFIG_H_ +#define IOS_CHROME_APP_SAFE_MODE_CRASHING_MODULES_CONFIG_H_ + +#import <Foundation/Foundation.h> + +#import "ios/chrome/browser/updatable_config/updatable_dictionary.h" + +// Class for updatable configuration file singleton. This singleton object +// is created when +sharedInstance is called for the first time and the default +// configuration is loaded from a plist bundled into the application. +@interface SafeModeCrashingModulesConfig : UpdatableDictionary + +// Returns singleton object for this class. ++ (SafeModeCrashingModulesConfig*)sharedInstance; + +// Return friendly name of module if module is a known crasher. +- (NSString*)startupCrashModuleFriendlyName:(NSString*)modulePath; + +@end + +#endif // IOS_CHROME_APP_SAFE_MODE_CRASHING_MODULES_CONFIG_H_
diff --git a/ios/chrome/app/safe_mode_crashing_modules_config.mm b/ios/chrome/app/safe_mode_crashing_modules_config.mm new file mode 100644 index 0000000..7dd5e90f --- /dev/null +++ b/ios/chrome/app/safe_mode_crashing_modules_config.mm
@@ -0,0 +1,42 @@ +// Copyright 2013 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/chrome/app/safe_mode_crashing_modules_config.h" + +#include "base/logging.h" + +namespace { + +NSString* const kStartupCrashModulesKey = @"StartupCrashModules"; +NSString* const kModuleFriendlyNameKey = @"ModuleFriendlyName"; + +} // namespace + +@implementation SafeModeCrashingModulesConfig + ++ (SafeModeCrashingModulesConfig*)sharedInstance { + static SafeModeCrashingModulesConfig* instance = + [[SafeModeCrashingModulesConfig alloc] init]; + return instance; +} + +- (instancetype)init { + return [super initWithAppId:nil version:nil plist:@"CrashingModules.plist"]; +} + +- (NSString*)startupCrashModuleFriendlyName:(NSString*)modulePath { + NSDictionary* configData = [self dictionaryFromConfig]; + NSDictionary* modules = [configData objectForKey:kStartupCrashModulesKey]; + if (modules) { + DCHECK([modules isKindOfClass:[NSDictionary class]]); + NSDictionary* module = modules[modulePath]; + if (module) { + DCHECK([module isKindOfClass:[NSDictionary class]]); + return module[kModuleFriendlyNameKey]; + } + } + return nil; +} + +@end
diff --git a/ios/chrome/app/safe_mode_util.cc b/ios/chrome/app/safe_mode_util.cc new file mode 100644 index 0000000..be448a4 --- /dev/null +++ b/ios/chrome/app/safe_mode_util.cc
@@ -0,0 +1,23 @@ +// Copyright 2013 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 "ios/chrome/app/safe_mode_util.h" + +#include <mach-o/dyld.h> + +namespace safe_mode_util { + +std::vector<std::string> GetLoadedImages(const char* path_filter) { + std::vector<std::string> images; + uint32_t image_count = _dyld_image_count(); + for (uint32_t i = 0; i < image_count; ++i) { + const char* path = _dyld_get_image_name(i); + if (path_filter && strncmp(path, path_filter, strlen(path_filter)) != 0) + continue; + images.push_back(path); + } + return images; +} + +} // namespace safe_mode_util
diff --git a/ios/chrome/app/safe_mode_util.h b/ios/chrome/app/safe_mode_util.h new file mode 100644 index 0000000..d4e25fd5 --- /dev/null +++ b/ios/chrome/app/safe_mode_util.h
@@ -0,0 +1,21 @@ +// Copyright 2013 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_CHROME_APP_SAFE_MODE_UTIL_H_ +#define IOS_CHROME_APP_SAFE_MODE_UTIL_H_ + +#include <string> +#include <vector> + +namespace safe_mode_util { + +// Returns a list of the paths of all images (e.g., dynamic libraries) +// currently loaded. +// If |path_filter| is non-NULL, only paths starting with |path_filter| will be +// returned. +std::vector<std::string> GetLoadedImages(const char* path_filter); + +} // namespace safe_mode_util + +#endif // IOS_CHROME_APP_SAFE_MODE_UTIL_H_
diff --git a/ios/chrome/app/safe_mode_util_unittest.cc b/ios/chrome/app/safe_mode_util_unittest.cc new file mode 100644 index 0000000..3164d59 --- /dev/null +++ b/ios/chrome/app/safe_mode_util_unittest.cc
@@ -0,0 +1,46 @@ +// Copyright 2013 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 <string.h> + +#include "base/files/file_path.h" +#include "base/strings/string_util.h" +#include "ios/chrome/app/safe_mode_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +using std::string; +using std::vector; + +namespace { + +typedef PlatformTest SafeModeUtilTest; + +TEST_F(SafeModeUtilTest, GetAllImages) { + vector<string> images = safe_mode_util::GetLoadedImages(nullptr); + // There should be loaded images. + EXPECT_GT(images.size(), 0U); + + // The libSystem dylib should always be present. + bool found_lib_system = false; + string lib_system_prefix("libSystem"); + for (size_t i = 0; i < images.size(); ++i) { + string base_name = base::FilePath(images[i]).BaseName().value(); + if (StartsWithASCII(base_name, lib_system_prefix, true)) { + found_lib_system = true; + break; + } + } + EXPECT_TRUE(found_lib_system); +} + +TEST_F(SafeModeUtilTest, GetSomeImages) { + vector<string> all_images = safe_mode_util::GetLoadedImages(nullptr); + vector<string> usr_lib_images = safe_mode_util::GetLoadedImages("/usr/lib/"); + // There should be images under /usr/lib/, but not all of them are. + EXPECT_GT(usr_lib_images.size(), 0U); + EXPECT_LT(usr_lib_images.size(), all_images.size()); +} + +} // namespace
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index f34a686..d2886e79 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -10,7 +10,9 @@ "+components/keyed_service/core", "+components/keyed_service/ios", "+components/leveldb_proto", + "+components/pref_registry", "+components/suggestions", + "+components/sync_driver", "+components/translate/core", "+components/translate/ios", "+components/web_resource",
diff --git a/ios/chrome/browser/chrome_paths.h b/ios/chrome/browser/chrome_paths.h new file mode 100644 index 0000000..1084da48 --- /dev/null +++ b/ios/chrome/browser/chrome_paths.h
@@ -0,0 +1,28 @@ +// 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_CHROME_BROWSER_CHROME_PATHS_H_ +#define IOS_CHROME_BROWSER_CHROME_PATHS_H_ + +// This file declares path keys for the Chrome on iOS application. These can be +// used with the PathService to access various special directories and files. + +namespace ios { + +enum { + PATH_START = 2000, + + DIR_USER_DATA = PATH_START, // Directory where user data can be written. + DIR_CRASH_DUMPS, // Directory where crash dumps are written. + DIR_TEST_DATA, // Directory where unit test data resides. + + PATH_END +}; + +// Call once to register the provider for the path keys defined above. +void RegisterPathProvider(); + +} // namespace + +#endif // IOS_CHROME_BROWSER_CHROME_PATHS_H_
diff --git a/ios/chrome/browser/chrome_paths.mm b/ios/chrome/browser/chrome_paths.mm new file mode 100644 index 0000000..955df2a --- /dev/null +++ b/ios/chrome/browser/chrome_paths.mm
@@ -0,0 +1,82 @@ +// 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 "ios/chrome/browser/chrome_paths.h" + +#include "base/base_paths.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/threading/thread_restrictions.h" + +namespace ios { +namespace { + +#if defined(GOOGLE_CHROME_BUILD) +const base::FilePath::CharType kProductDirName[] = + FILE_PATH_LITERAL("Google/Chrome"); +#else +const base::FilePath::CharType kProductDirName[] = + FILE_PATH_LITERAL("Chromium"); +#endif + +bool GetDefaultUserDataDirectory(base::FilePath* result) { + if (!PathService::Get(base::DIR_APP_DATA, result)) { + NOTREACHED(); + return false; + } + *result = result->Append(kProductDirName); + return true; +} + +bool PathProvider(int key, base::FilePath* result) { + // Assume that creation of the directory is not required if it does not exist. + // This flag is set to true for the case where it needs to be created. + bool create_dir = false; + + base::FilePath cur; + switch (key) { + case DIR_USER_DATA: + if (!GetDefaultUserDataDirectory(&cur)) + return false; + create_dir = true; + break; + + case DIR_CRASH_DUMPS: + if (!GetDefaultUserDataDirectory(&cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("Crash Reports")); + create_dir = true; + break; + + case DIR_TEST_DATA: + if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("ios")); + cur = cur.Append(FILE_PATH_LITERAL("chrome")); + cur = cur.Append(FILE_PATH_LITERAL("test")); + cur = cur.Append(FILE_PATH_LITERAL("data")); + break; + + default: + return false; + } + + if (!base::PathExists(cur)) { + if (!create_dir || !base::CreateDirectory(cur)) + return false; + } + + *result = cur; + return true; +} + +} // namespace + +void RegisterPathProvider() { + PathService::RegisterProvider(PathProvider, PATH_START, PATH_END); +} + +} // namespace ios
diff --git a/ios/chrome/browser/first_run/first_run.h b/ios/chrome/browser/first_run/first_run.h new file mode 100644 index 0000000..9faf6f2 --- /dev/null +++ b/ios/chrome/browser/first_run/first_run.h
@@ -0,0 +1,61 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file contains the iOS equivalent of FirstRun. + +#ifndef IOS_CHROME_BROWSER_FIRST_RUN_FIRST_RUN_H_ +#define IOS_CHROME_BROWSER_FIRST_RUN_FIRST_RUN_H_ + +#include "base/basictypes.h" + +namespace base { +class FilePath; +} + +namespace user_prefs { +class PrefRegistrySyncable; +} + +// A collection of functions to manage the user experience when running +// this application for the first time. The iOS implementation is significantly +// simpler than other platforms because it is designed to be preemptive and +// stops user from doing anything else until the First Run UX is completed +// or explicitly skipped. +class FirstRun { + public: + // Returns true if this is the first time chrome is run for this user. + static bool IsChromeFirstRun(); + + // Creates the sentinel file that signals that chrome has been configured iff + // the file does not exist yet. Returns true if the file was created and false + // if the file already exists or could not be created. + static bool CreateSentinel(); + + // Removes the sentinel file created in ConfigDone(). Returns false if the + // sentinel file could not be removed. + static bool RemoveSentinel(); + + // Get RLZ ping delay pref name. + static const char* GetPingDelayPrefName(); + + // Register user preferences. + static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); + + private: + // Gives the full path to the sentinel file. The file might not exist. + static bool GetFirstRunSentinelFilePath(base::FilePath* path); + + enum FirstRunState { + FIRST_RUN_UNKNOWN, // The state is not tested or set yet. + FIRST_RUN_TRUE, + FIRST_RUN_FALSE + }; + + // This variable should only be accessed through IsChromeFirstRun(). + static FirstRunState first_run_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(FirstRun); +}; + +#endif // IOS_CHROME_BROWSER_FIRST_RUN_FIRST_RUN_H_
diff --git a/ios/chrome/browser/first_run/first_run.mm b/ios/chrome/browser/first_run/first_run.mm new file mode 100644 index 0000000..39de142 --- /dev/null +++ b/ios/chrome/browser/first_run/first_run.mm
@@ -0,0 +1,77 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/first_run/first_run.h" + +#import <Foundation/Foundation.h> + +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "components/pref_registry/pref_registry_syncable.h" +#include "ios/chrome/browser/chrome_paths.h" + +namespace { + +// The absence of kSentinelFile file will tell us it is a first run. +const char kSentinelFile[] = "First Run"; + +// RLZ ping delay pref name. +const char kPingDelayPrefName[] = "distribution.ping_delay"; + +} // namespace + +FirstRun::FirstRunState FirstRun::first_run_ = FIRST_RUN_UNKNOWN; + +// static +bool FirstRun::GetFirstRunSentinelFilePath(base::FilePath* path) { + base::FilePath first_run_sentinel; + if (!PathService::Get(ios::DIR_USER_DATA, &first_run_sentinel)) + return false; + *path = first_run_sentinel.AppendASCII(kSentinelFile); + return true; +} + +// static +bool FirstRun::IsChromeFirstRun() { + if (first_run_ != FIRST_RUN_UNKNOWN) + return first_run_ == FIRST_RUN_TRUE; + + base::FilePath first_run_sentinel; + if (!GetFirstRunSentinelFilePath(&first_run_sentinel) || + base::PathExists(first_run_sentinel)) { + first_run_ = FIRST_RUN_FALSE; + return false; + } + first_run_ = FIRST_RUN_TRUE; + return true; +} + +// static +bool FirstRun::RemoveSentinel() { + base::FilePath first_run_sentinel; + if (!GetFirstRunSentinelFilePath(&first_run_sentinel)) + return false; + return base::DeleteFile(first_run_sentinel, false); +} + +// static +bool FirstRun::CreateSentinel() { + base::FilePath first_run_sentinel; + if (!GetFirstRunSentinelFilePath(&first_run_sentinel) || + base::PathExists(first_run_sentinel)) + return false; + return base::WriteFile(first_run_sentinel, "", 0) != -1; +} + +// static +const char* FirstRun::GetPingDelayPrefName() { + return kPingDelayPrefName; +} + +// static +void FirstRun::RegisterProfilePrefs( + user_prefs::PrefRegistrySyncable* registry) { + registry->RegisterIntegerPref(GetPingDelayPrefName(), 0); +}
diff --git a/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h b/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h new file mode 100644 index 0000000..a535714 --- /dev/null +++ b/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h
@@ -0,0 +1,27 @@ +// Copyright 2013 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_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOX_GEOLOCATION_H_ +#define IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOX_GEOLOCATION_H_ + +#import <CoreLocation/CoreLocation.h> + +@interface CLLocation (OmniboxGeolocation) + +// The elapsed time in seconds to acquire this location. Defaults to 0 if not +// set. +@property(nonatomic, assign, setter=cr_setAcquisitionInterval:) + NSTimeInterval cr_acquisitionInterval; + +// Returns YES if and only if this location is fresh enough to use for an +// Omnibox query. +- (BOOL)cr_isFreshEnough; + +// Returns YES if and only if this location is old enough to try refreshing the +// device location. +- (BOOL)cr_shouldRefresh; + +@end + +#endif // IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_OMNIBOX_GEOLOCATION_H_
diff --git a/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.mm b/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.mm new file mode 100644 index 0000000..1449373 --- /dev/null +++ b/ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.mm
@@ -0,0 +1,52 @@ +// Copyright 2013 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/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h" + +#import <objc/runtime.h> + +#include "base/mac/scoped_nsobject.h" + +namespace { + +// The key needed for objc_setAssociatedObject. Any value will do, because the +// address is the key. +static char g_acquisitionIntervalKey = 'k'; + +// Number of seconds before a location is no longer considered to be fresh +// enough to use for an Omnibox query. +const NSTimeInterval kLocationIsFreshAge = 24.0 * 60.0 * 60.0; // 24 hours + +// Number of seconds before we will try to refresh the device location. +const NSTimeInterval kLocationShouldRefreshAge = 5.0 * 60.0; // 5 minutes + +} // namespace + +@implementation CLLocation (OmniboxGeolocation) + +- (NSTimeInterval)cr_acquisitionInterval { + NSNumber* interval = + objc_getAssociatedObject(self, &g_acquisitionIntervalKey); + return [interval doubleValue]; +} + +- (void)cr_setAcquisitionInterval:(NSTimeInterval)interval { + base::scoped_nsobject<NSNumber> boxedInterval( + [[NSNumber alloc] initWithDouble:interval]); + objc_setAssociatedObject(self, &g_acquisitionIntervalKey, boxedInterval.get(), + OBJC_ASSOCIATION_RETAIN); +} + +- (BOOL)cr_isFreshEnough { + NSTimeInterval age = -[self.timestamp timeIntervalSinceNow]; + return (age >= 0) && (age <= kLocationIsFreshAge); +} + +- (BOOL)cr_shouldRefresh { + NSTimeInterval age = -[self.timestamp timeIntervalSinceNow]; + // Note: if age < 0 (the location is from the future), don't believe it. + return (age < 0) || (age > kLocationShouldRefreshAge); +} + +@end
diff --git a/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.h b/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.h new file mode 100644 index 0000000..f2de7d6 --- /dev/null +++ b/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.h
@@ -0,0 +1,18 @@ +// Copyright 2013 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_CHROME_BROWSER_GEOLOCATION_CLLOCATION_XGEOHEADER_H_ +#define IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_XGEOHEADER_H_ + +#import <CoreLocation/CoreLocation.h> + +@interface CLLocation (XGeoHeader) + +// Returns a string that encodes the location for use with the "X-Geo" HTTP +// header field. The string is a base-64-encoded ASCII proto. +- (NSString*)cr_xGeoString; + +@end + +#endif // IOS_CHROME_BROWSER_GEOLOCATION_CLLOCATION_XGEOHEADER_H_
diff --git a/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.mm b/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.mm new file mode 100644 index 0000000..1aa9ed7 --- /dev/null +++ b/ios/chrome/browser/geolocation/CLLocation+XGeoHeader.mm
@@ -0,0 +1,74 @@ +// Copyright 2013 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/chrome/browser/geolocation/CLLocation+XGeoHeader.h" + +#include "base/basictypes.h" +#import "third_party/google_toolbox_for_mac/src/Foundation/GTMStringEncoding.h" + +NSString* const kGMOLocationDescriptorFormat = + @"role: CURRENT_LOCATION\n" + @"producer: DEVICE_LOCATION\n" + @"timestamp: %lld\n" + @"radius: %ld\n" + @"latlng <\n" + @" latitude_e7: %.f\n" + @" longitude_e7: %.f\n" + @">"; + +@implementation CLLocation (XGeoHeader) + +- (NSString*)cr_serializeStringToWebSafeBase64String:(NSString*)data { + GTMStringEncoding* encoder = + [GTMStringEncoding rfc4648Base64WebsafeStringEncoding]; + NSString* base64 = + [encoder encode:[data dataUsingEncoding:NSUTF8StringEncoding]]; + if (base64) { + return base64; + } else { + return @""; + } +} + +// Returns the timestamp of this location in microseconds since the UNIX epoch. +// Returns 0 if the timestamp is unavailable or invalid. +- (int64)cr_timestampInMicroseconds { + NSTimeInterval seconds = [self.timestamp timeIntervalSince1970]; + if (seconds > 0) { + const int64 kSecondsToMicroseconds = 1000000; + return (int64)(seconds * kSecondsToMicroseconds); + } + return 0; +} + +// Returns the horizontal accuracy radius of |location|. The smaller the value, +// the more accurate the location. A value -1 is returned if accuracy is +// unavailable. +- (long)cr_accuracyInMillimeters { + const long kMetersToMillimeters = 1000; + if (self.horizontalAccuracy > 0) { + return (long)(self.horizontalAccuracy * kMetersToMillimeters); + } + return -1L; +} + +// Returns the LocationDescriptor as an ASCII proto. +- (NSString*)cr_locationDescriptor { + // Construct the location descriptor using its format string. + return [NSString stringWithFormat:kGMOLocationDescriptorFormat, + [self cr_timestampInMicroseconds], + [self cr_accuracyInMillimeters], + floor(self.coordinate.latitude * 1e7), + floor(self.coordinate.longitude * 1e7)]; +} + +- (NSString*)cr_xGeoString { + NSString* locationDescriptor = [self cr_locationDescriptor]; + // The "a" indicates that it is an ASCII proto. + return [NSString + stringWithFormat:@"a %@", [self cr_serializeStringToWebSafeBase64String: + locationDescriptor]]; +} + +@end
diff --git a/ios/chrome/browser/geolocation/CLLocation+XGeoHeaderTest.mm b/ios/chrome/browser/geolocation/CLLocation+XGeoHeaderTest.mm new file mode 100644 index 0000000..a18a7a5f --- /dev/null +++ b/ios/chrome/browser/geolocation/CLLocation+XGeoHeaderTest.mm
@@ -0,0 +1,34 @@ +// Copyright 2013 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 <CoreLocation/CoreLocation.h> + +#import "ios/chrome/browser/geolocation/CLLocation+XGeoHeader.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +NSString* const kEncoded550BatterySt = + @"a cm9sZTogQ1VSUkVOVF9MT0NBVElPTgpwcm9kdWNlcjogREVWSUNFX0xPQ0FUSU9OCnRpbWV" + "zdGFtcDogMTM4OTAwMDAwMDAwMDAwMApyYWRpdXM6IDEwMDAwCmxhdGxuZyA8CiAgbGF0aXR1" + "ZGVfZTc6IDM3Nzk2MzIyMAogIGxvbmdpdHVkZV9lNzogLTEyMjQwMDI5MTAKPg=="; + +TEST(CLLocationXGeoHeaderTest, TestXGeoString) { + CLLocationCoordinate2D coordinate = + CLLocationCoordinate2DMake(37.796322, -122.400291); + // Picked a fixed timestamp. This one is 2014-01-06 09:20:00 +0000. + NSDate* timestamp = [NSDate dateWithTimeIntervalSince1970:1389000000]; + CLLocation* location = + [[[CLLocation alloc] initWithCoordinate:coordinate + altitude:0 + horizontalAccuracy:10 + verticalAccuracy:100 + course:0 + speed:0 + timestamp:timestamp] autorelease]; + NSString* xGeoString = [location cr_xGeoString]; + EXPECT_TRUE([xGeoString isEqualToString:kEncoded550BatterySt]); +} + +} // namespace
diff --git a/ios/chrome/browser/geolocation/location_manager+Testing.h b/ios/chrome/browser/geolocation/location_manager+Testing.h new file mode 100644 index 0000000..afec45d --- /dev/null +++ b/ios/chrome/browser/geolocation/location_manager+Testing.h
@@ -0,0 +1,20 @@ +// 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 IOS_CHROME_BROWSER_GEOLOCATION_LOCATION_MANAGER_TESTING_H_ +#define IOS_CHROME_BROWSER_GEOLOCATION_LOCATION_MANAGER_TESTING_H_ + +#import "ios/chrome/browser/geolocation/location_manager.h" + +@protocol GeolocationUpdater; + +// Private methods for unit tests. +@interface LocationManager (Testing) + +// Sets the GeolocationUpdater for the receiver to use. +- (void)setGeolocationUpdater:(id<GeolocationUpdater>)geolocationUpdater; + +@end + +#endif // IOS_CHROME_BROWSER_GEOLOCATION_LOCATION_MANAGER_TESTING_H_
diff --git a/ios/chrome/browser/geolocation/location_manager.h b/ios/chrome/browser/geolocation/location_manager.h new file mode 100644 index 0000000..1af7b5c --- /dev/null +++ b/ios/chrome/browser/geolocation/location_manager.h
@@ -0,0 +1,50 @@ +// Copyright 2013 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_CHROME_BROWSER_GEOLOCATION_LOCATION_MANAGER_H_ +#define IOS_CHROME_BROWSER_GEOLOCATION_LOCATION_MANAGER_H_ + +#import <CoreLocation/CoreLocation.h> +#import <Foundation/Foundation.h> + +@class LocationManager; + +// Defines the methods to be implemented by a delegate of a LocationManager +// instance. +@protocol LocationManagerDelegate + +// Notifies the delegate that the application's authorization status changed. +- (void)locationManagerDidChangeAuthorizationStatus: + (LocationManager*)locationManager; + +@end + +// Manages fetching and updating the current device location. +@interface LocationManager : NSObject + +// The application’s authorization status for using location services. This +// proxies |[CLLocationManager authorizationStatus]|, so that we can write unit +// tests for client classes by mocking this class. +@property(nonatomic, readonly) CLAuthorizationStatus authorizationStatus; + +// Returns the most recently fetched location. +@property(nonatomic, readonly) CLLocation* currentLocation; + +// The delegate object for this instance of LocationManager. +@property(nonatomic, assign) id<LocationManagerDelegate> delegate; + +// Boolean value indicating whether location services are enabled on the +// device. This proxies |[CLLocationManager locationServicesEnabled]|, so that +// we can write unit tests for client classes by mocking this class. +@property(nonatomic, readonly) BOOL locationServicesEnabled; + +// Starts updating device location if needed. +- (void)startUpdatingLocation; + +// Stops updating device location. +- (void)stopUpdatingLocation; + +@end + +#endif // IOS_CHROME_BROWSER_GEOLOCATION_LOCATION_MANAGER_H_
diff --git a/ios/chrome/browser/geolocation/location_manager.mm b/ios/chrome/browser/geolocation/location_manager.mm new file mode 100644 index 0000000..cab3ea7 --- /dev/null +++ b/ios/chrome/browser/geolocation/location_manager.mm
@@ -0,0 +1,150 @@ +// Copyright 2013 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/chrome/browser/geolocation/location_manager.h" + +#import "base/ios/weak_nsobject.h" +#include "base/mac/scoped_nsobject.h" +#import "ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h" +#import "ios/chrome/browser/geolocation/location_manager+Testing.h" +#import "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/public/provider/chrome/browser/geolocation_updater_provider.h" + +namespace { + +const CLLocationDistance kLocationDesiredAccuracy = + kCLLocationAccuracyHundredMeters; +// Number of seconds to wait before automatically stopping location updates. +const NSTimeInterval kLocationStopUpdateDelay = 5.0; +// A large value to disable automatic location updates in GeolocationUpdater. +const NSTimeInterval kLocationUpdateInterval = 365.0 * 24.0 * 60.0 * 60.0; + +} // namespace + +@interface LocationManager () { + base::scoped_nsprotocol<id<GeolocationUpdater>> _locationUpdater; + base::scoped_nsobject<CLLocation> _currentLocation; + base::WeakNSProtocol<id<LocationManagerDelegate>> _delegate; + base::scoped_nsobject<NSDate> _startTime; +} + +// Handles GeolocationUpdater notification for an updated device location. +- (void)handleLocationUpdateNotification:(NSNotification*)notification; +// Handles GeolocationUpdater notification for ending device location updates. +- (void)handleLocationStopNotification:(NSNotification*)notification; +// Handles GeolocationUpdater notification for changing authorization. +- (void)handleAuthorizationChangeNotification:(NSNotification*)notification; + +@end + +@implementation LocationManager + +- (id)init { + self = [super init]; + if (self) { + ios::GeolocationUpdaterProvider* provider = + ios::GetChromeBrowserProvider()->GetGeolocationUpdaterProvider(); + + // |provider| may be null in tests. + if (provider) { + _locationUpdater.reset(provider->CreateGeolocationUpdater(false)); + [_locationUpdater setDesiredAccuracy:kLocationDesiredAccuracy + distanceFilter:kLocationDesiredAccuracy / 2]; + [_locationUpdater setStopUpdateDelay:kLocationStopUpdateDelay]; + [_locationUpdater setUpdateInterval:kLocationUpdateInterval]; + + NSNotificationCenter* defaultCenter = + [NSNotificationCenter defaultCenter]; + [defaultCenter addObserver:self + selector:@selector(handleLocationUpdateNotification:) + name:provider->GetUpdateNotificationName() + object:_locationUpdater]; + [defaultCenter addObserver:self + selector:@selector(handleLocationStopNotification:) + name:provider->GetStopNotificationName() + object:_locationUpdater]; + [defaultCenter + addObserver:self + selector:@selector(handleAuthorizationChangeNotification:) + name:provider->GetAuthorizationChangeNotificationName() + object:nil]; + } + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (CLAuthorizationStatus)authorizationStatus { + return [CLLocationManager authorizationStatus]; +} + +- (CLLocation*)currentLocation { + if (!_currentLocation) + _currentLocation.reset([[_locationUpdater currentLocation] retain]); + return _currentLocation; +} + +- (id<LocationManagerDelegate>)delegate { + return _delegate; +} + +- (void)setDelegate:(id<LocationManagerDelegate>)delegate { + _delegate.reset(delegate); +} + +- (BOOL)locationServicesEnabled { + return [CLLocationManager locationServicesEnabled]; +} + +- (void)startUpdatingLocation { + CLLocation* currentLocation = self.currentLocation; + if (!currentLocation || [currentLocation cr_shouldRefresh]) { + if (![_locationUpdater isEnabled]) + _startTime.reset([[NSDate alloc] init]); + + [_locationUpdater requestWhenInUseAuthorization]; + [_locationUpdater setEnabled:YES]; + } +} + +- (void)stopUpdatingLocation { + [_locationUpdater setEnabled:NO]; +} + +#pragma mark - Private + +- (void)handleLocationUpdateNotification:(NSNotification*)notification { + NSString* newLocationKey = ios::GetChromeBrowserProvider() + ->GetGeolocationUpdaterProvider() + ->GetUpdateNewLocationKey(); + CLLocation* location = [[notification userInfo] objectForKey:newLocationKey]; + if (location) { + _currentLocation.reset([location retain]); + + if (_startTime) { + NSTimeInterval interval = -[_startTime timeIntervalSinceNow]; + [_currentLocation cr_setAcquisitionInterval:interval]; + } + } +} + +- (void)handleLocationStopNotification:(NSNotification*)notification { + [_locationUpdater setEnabled:NO]; +} + +- (void)handleAuthorizationChangeNotification:(NSNotification*)notification { + [_delegate locationManagerDidChangeAuthorizationStatus:self]; +} + +#pragma mark - LocationManager+Testing + +- (void)setGeolocationUpdater:(id<GeolocationUpdater>)geolocationUpdater { + _locationUpdater.reset([geolocationUpdater retain]); +} + +@end
diff --git a/ios/chrome/browser/geolocation/location_manager_unittest.mm b/ios/chrome/browser/geolocation/location_manager_unittest.mm new file mode 100644 index 0000000..6b7e7f11 --- /dev/null +++ b/ios/chrome/browser/geolocation/location_manager_unittest.mm
@@ -0,0 +1,107 @@ +// 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. + +#import "ios/chrome/browser/geolocation/location_manager.h" + +#include "base/mac/scoped_nsobject.h" +#import "ios/chrome/browser/geolocation/CLLocation+OmniboxGeolocation.h" +#import "ios/chrome/browser/geolocation/location_manager+Testing.h" +#import "ios/public/provider/chrome/browser/geolocation_updater_provider.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#import "third_party/ocmock/gtest_support.h" + +namespace { + +class LocationManagerTest : public PlatformTest { + public: + LocationManagerTest() {} + + protected: + void SetUp() override { + PlatformTest::SetUp(); + + mock_geolocation_updater_.reset( + [[OCMockObject mockForProtocol:@protocol(GeolocationUpdater)] retain]); + + // Set up LocationManager with a mock GeolocationUpdater. + location_manager_.reset([[LocationManager alloc] init]); + [location_manager_ setGeolocationUpdater:mock_geolocation_updater_.get()]; + } + + void TearDown() override { + [location_manager_ setGeolocationUpdater:nil]; + + PlatformTest::TearDown(); + } + + base::scoped_nsobject<id> mock_geolocation_updater_; + base::scoped_nsobject<LocationManager> location_manager_; +}; + +// Verifies that -[LocationManager startUpdatingLocation] calls +// -[GeolocationUpdater setEnabled:] when GeolocationUpdater does not yet have +// a current location. +TEST_F(LocationManagerTest, StartUpdatingLocationNilCurrentLocation) { + [[[mock_geolocation_updater_ expect] andReturn:nil] currentLocation]; + + // Also expect the call to -[GeolocationUpdater isEnabled]; + BOOL no = NO; + [[[mock_geolocation_updater_ expect] + andReturnValue:OCMOCK_VALUE(no)] isEnabled]; + [[mock_geolocation_updater_ expect] requestWhenInUseAuthorization]; + [[mock_geolocation_updater_ expect] setEnabled:YES]; + + [location_manager_ startUpdatingLocation]; + EXPECT_OCMOCK_VERIFY(mock_geolocation_updater_.get()); +} + +// Verifies that -[LocationManager startUpdatingLocation] calls +// -[GeolocationUpdater setEnabled:] when GeolocationUpdater +// |currentLocation| is stale. +TEST_F(LocationManagerTest, StartUpdatingLocationStaleCurrentLocation) { + // Set up to return a stale mock CLLocation from -[GeolocationUpdater + // currentLocation]. + base::scoped_nsobject<id> mock_location( + [[OCMockObject mockForClass:[CLLocation class]] retain]); + BOOL yes = YES; + [[[mock_location expect] andReturnValue:OCMOCK_VALUE(yes)] cr_shouldRefresh]; + + [[[mock_geolocation_updater_ expect] + andReturn:mock_location.get()] currentLocation]; + + // Also expect the call to -[GeolocationUpdater isEnabled]; + BOOL no = NO; + [[[mock_geolocation_updater_ expect] + andReturnValue:OCMOCK_VALUE(no)] isEnabled]; + [[mock_geolocation_updater_ expect] requestWhenInUseAuthorization]; + [[mock_geolocation_updater_ expect] setEnabled:YES]; + + [location_manager_ startUpdatingLocation]; + EXPECT_OCMOCK_VERIFY(mock_geolocation_updater_.get()); + EXPECT_OCMOCK_VERIFY(mock_location.get()); +} + +// Verifies that -[LocationManager startUpdatingLocation] does not call +// -[GeolocationUpdater setEnabled:] when GeolocationUpdater's +// |currentLocation| is fresh. +TEST_F(LocationManagerTest, StartUpdatingLocationFreshCurrentLocation) { + // Set up to return a fresh mock CLLocation from -[GeolocationUpdater + // currentLocation]. + base::scoped_nsobject<id> mock_location( + [[OCMockObject mockForClass:[CLLocation class]] retain]); + BOOL no = NO; + [[[mock_location expect] andReturnValue:OCMOCK_VALUE(no)] cr_shouldRefresh]; + + [[[mock_geolocation_updater_ expect] + andReturn:mock_location.get()] currentLocation]; + + [location_manager_ startUpdatingLocation]; + EXPECT_OCMOCK_VERIFY(mock_geolocation_updater_.get()); + EXPECT_OCMOCK_VERIFY(mock_location.get()); +} + +} // namespace
diff --git a/ios/chrome/browser/geolocation/omnibox_geolocation_config.h b/ios/chrome/browser/geolocation/omnibox_geolocation_config.h new file mode 100644 index 0000000..1eac6d1 --- /dev/null +++ b/ios/chrome/browser/geolocation/omnibox_geolocation_config.h
@@ -0,0 +1,27 @@ +// Copyright 2013 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_CHROME_BROWSER_GEOLOCATION_OMNIBOX_GEOLOCATION_CONFIG_H_ +#define IOS_CHROME_BROWSER_GEOLOCATION_OMNIBOX_GEOLOCATION_CONFIG_H_ + +#import <Foundation/Foundation.h> + +#import "ios/chrome/browser/updatable_config/updatable_dictionary.h" + +class GURL; + +// Implements updatable configuration for using geolocation for Omnibox +// queries. +@interface OmniboxGeolocationConfig : UpdatableDictionary + +// Returns singleton object for this class. ++ (OmniboxGeolocationConfig*)sharedInstance; + +// Returns YES if and only if |url| has a domain that is whitelisted for +// geolocation for Omnibox queries. +- (BOOL)URLHasEligibleDomain:(const GURL&)url; + +@end + +#endif // IOS_CHROME_BROWSER_GEOLOCATION_OMNIBOX_GEOLOCATION_CONFIG_H_
diff --git a/ios/chrome/browser/geolocation/omnibox_geolocation_config.mm b/ios/chrome/browser/geolocation/omnibox_geolocation_config.mm new file mode 100644 index 0000000..6a56ae4 --- /dev/null +++ b/ios/chrome/browser/geolocation/omnibox_geolocation_config.mm
@@ -0,0 +1,81 @@ +// Copyright 2013 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/chrome/browser/geolocation/omnibox_geolocation_config.h" + +#include <set> +#include <string> + +#include "base/logging.h" +#include "base/strings/sys_string_conversions.h" +#include "url/gurl.h" + +namespace { + +NSString* const kEligibleDomainsKey = @"EligibleDomains"; + +} // namespace + +@interface OmniboxGeolocationConfig () { + // Whitelist of domains eligible for Omnibox geolocation. + std::set<std::string> _eligibleDomains; +} + +// Loads |eligibleDomains_| from config file. +- (void)loadEligibleDomains; + +@end + +@implementation OmniboxGeolocationConfig + ++ (OmniboxGeolocationConfig*)sharedInstance { + static OmniboxGeolocationConfig* instance = + [[OmniboxGeolocationConfig alloc] init]; + return instance; +} + +- (id)init { + self = + [super initWithAppId:nil version:nil plist:@"OmniboxGeolocation.plist"]; + if (self) { + [self loadEligibleDomains]; + } + return self; +} + +- (BOOL)URLHasEligibleDomain:(const GURL&)url { + // Here we iterate through the eligible domains and check url.DomainIs() for + // each domain rather than extracting url.host() and checking the domain for + // membership in |eligibleDomains_|, because GURL::DomainIs() is more robust + // and contains logic that we want to reuse. + for (const auto& eligibleDomain : _eligibleDomains) { + if (url.DomainIs(eligibleDomain.c_str())) + return YES; + } + return NO; +} + +#pragma mark - Private + +- (void)loadEligibleDomains { + _eligibleDomains.clear(); + + NSDictionary* configData = [self dictionaryFromConfig]; + NSArray* eligibleDomains = [configData objectForKey:kEligibleDomainsKey]; + if (eligibleDomains) { + DCHECK([eligibleDomains isKindOfClass:[NSArray class]]); + + for (NSString* domain in eligibleDomains) { + DCHECK([domain isKindOfClass:[NSString class]]); + if ([domain length]) { + _eligibleDomains.insert( + base::SysNSStringToUTF8([domain lowercaseString])); + } + } + } + + DCHECK(!_eligibleDomains.empty()); +} + +@end
diff --git a/ios/chrome/browser/geolocation/test_location_manager.h b/ios/chrome/browser/geolocation/test_location_manager.h new file mode 100644 index 0000000..b6de5fe --- /dev/null +++ b/ios/chrome/browser/geolocation/test_location_manager.h
@@ -0,0 +1,40 @@ +// Copyright 2013 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_CHROME_BROWSER_GEOLOCATION_TEST_LOCATION_MANAGER_H_ +#define IOS_CHROME_BROWSER_GEOLOCATION_TEST_LOCATION_MANAGER_H_ + +#import "ios/chrome/browser/geolocation/location_manager.h" + +// Implements a fake LocationManager for unit tests and KIF tests. +@interface TestLocationManager : LocationManager + +// Writable version of the LocationManager |authorizationStatus| property. If +// the new value is different from the previous value, then invokes the +// LocationManagerDelegate |locationManagerDidChangeAuthorizationStatus:| +// method. +@property(nonatomic, assign) CLAuthorizationStatus authorizationStatus; + +// Writable version of the LocationManager |currentLocation| property. +@property(nonatomic, retain) CLLocation* currentLocation; + +// Writable version of the LocationManager |locationServicesEnabled| property. +@property(nonatomic, assign) BOOL locationServicesEnabled; + +// Returns YES if and only if LocationManager |startUpdatingLocation| has been +// invoked at least once since initialization or the last call to |reset|. +@property(nonatomic, readonly) BOOL started; + +// Returns YES if and only if LocationManager |stopUpdatingLocation| has been +// invoked at least once since initialization or the last call to |reset|. +@property(nonatomic, readonly) BOOL stopped; + +// Resets |authorizationStatus|, |currentLocation|, |locationServicesEnabled|, +// |started|, and |stopped| to the initialized state. Does not reset +// |delegate|. +- (void)reset; + +@end + +#endif // IOS_CHROME_BROWSER_GEOLOCATION_TEST_LOCATION_MANAGER_H_
diff --git a/ios/chrome/browser/geolocation/test_location_manager.mm b/ios/chrome/browser/geolocation/test_location_manager.mm new file mode 100644 index 0000000..eb6633e --- /dev/null +++ b/ios/chrome/browser/geolocation/test_location_manager.mm
@@ -0,0 +1,67 @@ +// Copyright 2013 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/chrome/browser/geolocation/test_location_manager.h" + +#include "base/mac/scoped_nsobject.h" + +@interface TestLocationManager () { + CLAuthorizationStatus _authorizationStatus; + base::scoped_nsobject<CLLocation> _currentLocation; + BOOL _locationServicesEnabled; + BOOL _started; + BOOL _stopped; +} + +@end + +@implementation TestLocationManager + +@synthesize authorizationStatus = _authorizationStatus; +@synthesize locationServicesEnabled = _locationServicesEnabled; +@synthesize started = _started; +@synthesize stopped = _stopped; + +- (id)init { + self = [super init]; + if (self) { + [self reset]; + } + return self; +} + +- (void)setAuthorizationStatus:(CLAuthorizationStatus)authorizationStatus { + if (_authorizationStatus != authorizationStatus) { + _authorizationStatus = authorizationStatus; + [self.delegate locationManagerDidChangeAuthorizationStatus:self]; + } +} + +- (CLLocation*)currentLocation { + return _currentLocation; +} + +- (void)setCurrentLocation:(CLLocation*)currentLocation { + _currentLocation.reset([currentLocation retain]); +} + +- (void)reset { + _authorizationStatus = kCLAuthorizationStatusNotDetermined; + _currentLocation.reset(); + _locationServicesEnabled = YES; + _started = NO; + _stopped = NO; +} + +#pragma mark - LocationManager overrides + +- (void)startUpdatingLocation { + _started = YES; +} + +- (void)stopUpdatingLocation { + _stopped = YES; +} + +@end
diff --git a/ios/chrome/browser/prefs/pref_observer_bridge.h b/ios/chrome/browser/prefs/pref_observer_bridge.h new file mode 100644 index 0000000..4e105467 --- /dev/null +++ b/ios/chrome/browser/prefs/pref_observer_bridge.h
@@ -0,0 +1,32 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_PREFS_PREF_OBSERVER_BRIDGE_H_ +#define IOS_CHROME_BROWSER_PREFS_PREF_OBSERVER_BRIDGE_H_ + +#include <string> + +#include "base/compiler_specific.h" + +class PrefChangeRegistrar; + +@protocol PrefObserverDelegate +- (void)onPreferenceChanged:(const std::string&)preferenceName; +@end + +class PrefObserverBridge { + public: + explicit PrefObserverBridge(id<PrefObserverDelegate> delegate); + virtual ~PrefObserverBridge(); + + virtual void ObserveChangesForPreference(const std::string& pref_name, + PrefChangeRegistrar* registrar); + + private: + virtual void OnPreferenceChanged(const std::string& pref_name); + + id<PrefObserverDelegate> delegate_; +}; + +#endif // IOS_CHROME_BROWSER_PREFS_PREF_OBSERVER_BRIDGE_H_
diff --git a/ios/chrome/browser/prefs/pref_observer_bridge.mm b/ios/chrome/browser/prefs/pref_observer_bridge.mm new file mode 100644 index 0000000..ebd82f78 --- /dev/null +++ b/ios/chrome/browser/prefs/pref_observer_bridge.mm
@@ -0,0 +1,27 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/prefs/pref_observer_bridge.h" + +#include "base/bind.h" +#include "base/prefs/pref_change_registrar.h" + +PrefObserverBridge::PrefObserverBridge(id<PrefObserverDelegate> delegate) + : delegate_(delegate) { +} + +PrefObserverBridge::~PrefObserverBridge() { +} + +void PrefObserverBridge::ObserveChangesForPreference( + const std::string& pref_name, + PrefChangeRegistrar* registrar) { + PrefChangeRegistrar::NamedChangeCallback callback = base::Bind( + &PrefObserverBridge::OnPreferenceChanged, base::Unretained(this)); + registrar->Add(pref_name.c_str(), callback); +} + +void PrefObserverBridge::OnPreferenceChanged(const std::string& pref_name) { + [delegate_ onPreferenceChanged:pref_name]; +}
diff --git a/ios/chrome/browser/procedural_block_types.h b/ios/chrome/browser/procedural_block_types.h new file mode 100644 index 0000000..b5e7386 --- /dev/null +++ b/ios/chrome/browser/procedural_block_types.h
@@ -0,0 +1,13 @@ +// 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 IOS_CHROME_BROWSER_PROCEDURAL_BLOCK_TYPES_H_ +#define IOS_CHROME_BROWSER_PROCEDURAL_BLOCK_TYPES_H_ + +class GURL; + +// A generic procedural block type that takes a |GURL| and returns nothing. +typedef void (^ProceduralBlockWithURL)(const GURL&); + +#endif // IOS_CHROME_BROWSER_PROCEDURAL_BLOCK_TYPES_H_
diff --git a/ios/chrome/browser/suggestions/suggestions_service_factory.h b/ios/chrome/browser/suggestions/suggestions_service_factory.h index 3f86fc3..384982e8 100644 --- a/ios/chrome/browser/suggestions/suggestions_service_factory.h +++ b/ios/chrome/browser/suggestions/suggestions_service_factory.h
@@ -38,7 +38,7 @@ // BrowserStateKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( web::BrowserState* browser_state) const override; - void RegisterProfilePrefs( + void RegisterBrowserStatePrefs( user_prefs::PrefRegistrySyncable* registry) override; DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceFactory);
diff --git a/ios/chrome/browser/suggestions/suggestions_service_factory.mm b/ios/chrome/browser/suggestions/suggestions_service_factory.mm index 400ff13..bc08640 100644 --- a/ios/chrome/browser/suggestions/suggestions_service_factory.mm +++ b/ios/chrome/browser/suggestions/suggestions_service_factory.mm
@@ -75,7 +75,7 @@ thumbnail_manager.Pass(), blacklist_store.Pass()); } -void SuggestionsServiceFactory::RegisterProfilePrefs( +void SuggestionsServiceFactory::RegisterBrowserStatePrefs( user_prefs::PrefRegistrySyncable* registry) { SuggestionsService::RegisterProfilePrefs(registry); }
diff --git a/ios/chrome/browser/sync/sync_observer_bridge.h b/ios/chrome/browser/sync/sync_observer_bridge.h new file mode 100644 index 0000000..0ea0ca1 --- /dev/null +++ b/ios/chrome/browser/sync/sync_observer_bridge.h
@@ -0,0 +1,42 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_SYNC_SYNC_OBSERVER_BRIDGE_H_ +#define IOS_CHROME_BROWSER_SYNC_SYNC_OBSERVER_BRIDGE_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/ios/weak_nsobject.h" +#include "base/scoped_observer.h" +#include "components/sync_driver/sync_service_observer.h" + +namespace sync_driver { +class SyncService; +} + +@protocol SyncObserverModelBridge +- (void)onSyncStateChanged; +@end + +// C++ class to monitor profile sync status in Objective-C type. +class SyncObserverBridge : public sync_driver::SyncServiceObserver { + public: + // |service| must outlive the SyncObserverBridge. + SyncObserverBridge(id<SyncObserverModelBridge> delegate, + sync_driver::SyncService* service); + + ~SyncObserverBridge() override; + + private: + // sync_driver::SyncServiceObserver implementation: + void OnStateChanged() override; + + base::WeakNSProtocol<id<SyncObserverModelBridge>> delegate_; + ScopedObserver<sync_driver::SyncService, sync_driver::SyncServiceObserver> + scoped_observer_; + + DISALLOW_COPY_AND_ASSIGN(SyncObserverBridge); +}; + +#endif // IOS_CHROME_BROWSER_SYNC_SYNC_OBSERVER_BRIDGE_H_
diff --git a/ios/chrome/browser/sync/sync_observer_bridge.mm b/ios/chrome/browser/sync/sync_observer_bridge.mm new file mode 100644 index 0000000..0ccb02ac --- /dev/null +++ b/ios/chrome/browser/sync/sync_observer_bridge.mm
@@ -0,0 +1,23 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/sync/sync_observer_bridge.h" + +#include "base/logging.h" +#include "components/sync_driver/sync_service.h" + +SyncObserverBridge::SyncObserverBridge(id<SyncObserverModelBridge> delegate, + sync_driver::SyncService* sync_service) + : delegate_(delegate), scoped_observer_(this) { + DCHECK(delegate); + if (sync_service) + scoped_observer_.Add(sync_service); +} + +SyncObserverBridge::~SyncObserverBridge() { +} + +void SyncObserverBridge::OnStateChanged() { + [delegate_ onSyncStateChanged]; +}
diff --git a/ios/chrome/browser/ui/uikit_ui_util.h b/ios/chrome/browser/ui/uikit_ui_util.h index 37aa0d39..052fbffb 100644 --- a/ios/chrome/browser/ui/uikit_ui_util.h +++ b/ios/chrome/browser/ui/uikit_ui_util.h
@@ -101,6 +101,9 @@ CGFloat saturationDeltaFactor, UIImage* maskImage); +// Returns a cropped image using |cropRect| on |image|. +UIImage* CropImage(UIImage* image, const CGRect& cropRect); + // Returns the interface orientation of the app. UIInterfaceOrientation GetInterfaceOrientation(); @@ -127,14 +130,26 @@ NSDictionary* subviewsDictionary, UIView* parentView); +// Applies all |constraints| with |metrics| to all views in |subviewsDictionary| +// in the superview |parentView| +void ApplyVisualConstraintsWithMetrics(NSArray* constraints, + NSDictionary* subviewsDictionary, + NSDictionary* metrics, + UIView* parentView); + // Adds a constraint that |subview| is center aligned horizontally in // |parentView|. -// |subview| must be a subiew of |parentView|. +// |subview| must be a subview of |parentView|. void AddSameCenterXConstraint(UIView* parentView, UIView* subview); +// Adds a constraint that |subview| is center aligned vertically in +// |parentView|. +// |subview| must be a subview of |parentView|. +void AddSameCenterYConstraint(UIView* parentView, UIView* subview); + // Adds a constraint that |subview1| and |subview2| are center aligned // vertically on |parentView|. -// |subview1| and |subview2| must be subiews of |parentView|. +// |subview1| and |subview2| must be subview of |parentView|. void AddSameCenterYConstraint(UIView* parentView, UIView* subview1, UIView* subview2);
diff --git a/ios/chrome/browser/ui/uikit_ui_util.mm b/ios/chrome/browser/ui/uikit_ui_util.mm index 5810da0c..8d301aa 100644 --- a/ios/chrome/browser/ui/uikit_ui_util.mm +++ b/ios/chrome/browser/ui/uikit_ui_util.mm
@@ -353,6 +353,13 @@ return outputImage; } +UIImage* CropImage(UIImage* image, const CGRect& cropRect) { + CGImageRef cgImage = CGImageCreateWithImageInRect([image CGImage], cropRect); + UIImage* result = [UIImage imageWithCGImage:cgImage]; + CGImageRelease(cgImage); + return result; +} + UIInterfaceOrientation GetInterfaceOrientation() { return [[UIApplication sharedApplication] statusBarOrientation]; } @@ -419,13 +426,21 @@ void ApplyVisualConstraints(NSArray* constraints, NSDictionary* subviewsDictionary, UIView* parentView) { + ApplyVisualConstraintsWithMetrics(constraints, subviewsDictionary, nil, + parentView); +} + +void ApplyVisualConstraintsWithMetrics(NSArray* constraints, + NSDictionary* subviewsDictionary, + NSDictionary* metrics, + UIView* parentView) { for (NSString* constraint in constraints) { DCHECK([constraint isKindOfClass:[NSString class]]); [parentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:constraint options:0 - metrics:nil + metrics:metrics views:subviewsDictionary]]; } } @@ -442,6 +457,18 @@ constant:0]]; } +void AddSameCenterYConstraint(UIView* parentView, UIView* subview) { + DCHECK_EQ(parentView, [subview superview]); + [parentView addConstraint:[NSLayoutConstraint + constraintWithItem:subview + attribute:NSLayoutAttributeCenterY + relatedBy:NSLayoutRelationEqual + toItem:parentView + attribute:NSLayoutAttributeCenterY + multiplier:1 + constant:0]]; +} + void AddSameCenterYConstraint(UIView* parentView, UIView* subview1, UIView* subview2) {
diff --git a/ios/chrome/browser/updatable_config/updatable_array.h b/ios/chrome/browser/updatable_config/updatable_array.h new file mode 100644 index 0000000..2496327 --- /dev/null +++ b/ios/chrome/browser/updatable_config/updatable_array.h
@@ -0,0 +1,32 @@ +// Copyright 2013 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_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_ARRAY_H_ +#define IOS_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_ARRAY_H_ + +#import "ios/chrome/browser/updatable_config/updatable_config_base.h" +#import "ios/public/provider/chrome/browser/updatable_resource_provider.h" + +// UpdatableResourceBridge supports data files of json or plist format but only +// allows dictionary types in the data. UpdatableArrayDelegate overrides the +// default file loader to accept plist file type with <array> data. +// This class is publicly declared here for unit tests to mock for testing +// and is not intended to be used elsewhere. +@interface UpdatableArrayDelegate : NSObject<UpdatableResourceDelegate> + +// The array object loaded from updatable resource. +@property(nonatomic, readonly) NSArray* resourceArray; + +@end + +@interface UpdatableArray : UpdatableConfigBase + +// Returns an autoreleased copy of the configuration array read from the +// file specified in the initializer. This implementation supports <array> +// data type specified as a plist only. +- (NSArray*)arrayFromConfig; + +@end + +#endif // IOS_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_ARRAY_H_
diff --git a/ios/chrome/browser/updatable_config/updatable_array.mm b/ios/chrome/browser/updatable_config/updatable_array.mm new file mode 100644 index 0000000..ac772c8 --- /dev/null +++ b/ios/chrome/browser/updatable_config/updatable_array.mm
@@ -0,0 +1,78 @@ +// Copyright 2013 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/chrome/browser/updatable_config/updatable_array.h" + +#import "base/logging.h" +#include "base/mac/scoped_nsobject.h" +#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/public/provider/chrome/browser/updatable_resource_provider.h" + +@interface UpdatableArrayDelegate () +// Private helper function to check that |path| is of plist type +// and read the content of |path| into |resourceArray_|. +- (void)setResourceArrayWithContentsOfFile:(NSString*)path; +@end + +@implementation UpdatableArrayDelegate { + base::scoped_nsobject<NSArray> _resourceArray; +} + +- (void)loadDefaults:(id<UpdatableResourceBridge>)resource { + NSString* path = resource.descriptor.bundleResourcePath; + [self setResourceArrayWithContentsOfFile:path]; +} + +- (void)mergeUpdate:(id<UpdatableResourceBridge>)resource { + NSString* path = resource.descriptor.resourcePath; + if ([path isEqualToString:resource.descriptor.bundleResourcePath]) { + // There's no need to merge, because the only resource present is the one + // bundled with the app, and that was loaded by loadDefaults. + return; + } + [self setResourceArrayWithContentsOfFile:path]; +} + +- (NSDictionary*)parseFileAt:(NSString*)path { + // Overrides this method with NOTREACHED() because default implementation in + // UpdatableResourceBridge is for NSDictionary only and results in opaque + // errors when the data file is of <array> type. + NOTREACHED(); + return nil; +} + +- (NSArray*)resourceArray { + return _resourceArray.get(); +} + +- (void)setResourceArrayWithContentsOfFile:(NSString*)path { + NSString* extension = [[path pathExtension] lowercaseString]; + // Only plist file type is supported. + DCHECK([extension isEqualToString:@"plist"]); + _resourceArray.reset([[NSArray arrayWithContentsOfFile:path] retain]); +} + +@end + +@implementation UpdatableArray + +- (id<UpdatableResourceBridge>)newResource:(NSString*)resourceName { + base::scoped_nsobject<UpdatableArrayDelegate> delegate( + [[UpdatableArrayDelegate alloc] init]); + + return ios::GetChromeBrowserProvider() + ->GetUpdatableResourceProvider() + ->CreateUpdatableResource(resourceName, delegate); +} + +- (NSArray*)arrayFromConfig { + id delegate = [[self updatableResource] delegate]; + DCHECK(delegate); + DCHECK([delegate respondsToSelector:@selector(resourceArray)]); + id configData = [[[delegate resourceArray] retain] autorelease]; + DCHECK([configData isKindOfClass:[NSArray class]]); + return configData; +} + +@end
diff --git a/ios/chrome/browser/updatable_config/updatable_config_base.h b/ios/chrome/browser/updatable_config/updatable_config_base.h new file mode 100644 index 0000000..c889495 --- /dev/null +++ b/ios/chrome/browser/updatable_config/updatable_config_base.h
@@ -0,0 +1,63 @@ +// Copyright 2013 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_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_CONFIG_BASE_H_ +#define IOS_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_CONFIG_BASE_H_ + +#import <Foundation/Foundation.h> + +namespace net { +class URLRequestContextGetter; +} // namespace net + +@protocol UpdatableResourceBridge; + +// Abstract base class for configurations bundled in a .plist file in +// application bundle. Configuration is periodically updated by pulling +// in a new configuration file from gstatic.com. +// DO NOT use this class directly, but instantiate either UpdatableArray +// or UpdatableDictionary class instead. +// |startUpdate:| must be called for every subclass. +@interface UpdatableConfigBase : NSObject + +// Initializes a new Updatable Config object using .plist file named |plistName| +// which is in the application bundle. |appId| and |appVersion| are used to +// derive the URL to update this plist from gstatic.com. +// If |appId| is nil, a default value based on the application id from the +// application bundle will be provided. +// If |appVersion| is nil, a default value based on the application version +// number from the application bundle will be provided. +- (instancetype)initWithAppId:(NSString*)appId + version:(NSString*)appVersion + plist:(NSString*)plistName; + +// Starts periodic checks with server for updated version of +// configuration plists +- (void)startUpdate:(net::URLRequestContextGetter*)requestContextGetter; + +// Prevents any future update checks, and releases requestContextGetter. Should +// be called if the app is going to terminate. +- (void)stopUpdateChecks; + +// Performs any post-update operations for the updated data to take effect. +- (void)resourceDidUpdate:(NSNotification*)notification; + +// Subclasses must override this method to return a UpdatableResourceBridge +// object. The returned object determines whether the resource stored in the +// file |resourceName| is of plist, json, or some other data file format. +- (id<UpdatableResourceBridge>)newResource:(NSString*)resourceName; + +// Returns the internal resources object. This accessor is intended for +// use by subclasses of this class and for unit testing only. +// Note that this is really a readonly property for subclasses, but for +// unit testing, the ability to set the resource is also needed. +@property(nonatomic, retain) id<UpdatableResourceBridge> updatableResource; + +// Consistency check defaults to NO and is enabled only by Chrome application, +// not unit or kif tests. ++ (void)enableConsistencyCheck; + +@end + +#endif // IOS_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_CONFIG_BASE_H_
diff --git a/ios/chrome/browser/updatable_config/updatable_config_base.mm b/ios/chrome/browser/updatable_config/updatable_config_base.mm new file mode 100644 index 0000000..b28fe21 --- /dev/null +++ b/ios/chrome/browser/updatable_config/updatable_config_base.mm
@@ -0,0 +1,266 @@ +// Copyright 2013 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/chrome/browser/updatable_config/updatable_config_base.h" + +#include "base/logging.h" +#import "base/mac/bind_objc_block.h" +#include "base/mac/scoped_nsobject.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#import "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/public/provider/chrome/browser/updatable_resource_provider.h" +#include "ios/web/public/web_thread.h" +#import "net/base/mac/url_conversions.h" +#include "net/http/http_status_code.h" +#include "net/url_request/url_fetcher.h" +#include "net/url_request/url_fetcher_delegate.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_getter.h" +#include "url/gurl.h" + +@interface UpdatableConfigBase () +// Returns the application ID to use for fetching updatable configuration. ++ (NSString*)defaultAppId; +// Fetches server-side updatable configuration plist. +- (void)checkUpdate; +#if !defined(NDEBUG) +// A method that will be executed on a delay if -startUpdate: was NOT called. +- (void)startUpdateNotCalled:(id)config; +// Schedules a call to -startUpdateNotCalled: for later to make sure that +// -startUpdate: will be called. +- (void)scheduleConsistencyCheck; +// Cancels the delayed call to -startUpdateNotCalled:. +- (void)cancelConsistencyCheck; +#endif // !defined(NDEBUG) +@end + +namespace { + +#if !defined(NDEBUG) +// Global flag to enable or disable debug check that -startUpdate: +// has been called. +BOOL g_consistency_check_enabled = NO; +#endif + +// Periodically fetch configuration updates from server. +const int64_t kPeriodicCheckInNanoseconds = 60 * 60 * 24 * NSEC_PER_SEC; + +// Class to fetch config update |url| and also act as the delegate to +// handle callbacks from URLFetcher. +class ConfigFetcher : public net::URLFetcherDelegate { + public: + ConfigFetcher(UpdatableConfigBase* owner, + id<UpdatableResourceDescriptorBridge> descriptor) + : owner_(owner), descriptor_(descriptor) {} + + // Starts fetching |url| for updated configuration. + void Fetch(const GURL& url, net::URLRequestContextGetter* context) { + fetcher_.reset(net::URLFetcher::Create(url, net::URLFetcher::GET, this)); + fetcher_->SetRequestContext(context); + fetcher_->Start(); + } + + void OnURLFetchComplete(const net::URLFetcher* fetcher) override { + DCHECK_EQ(fetcher_, fetcher); + NSData* responseData = nil; + if (fetcher_->GetResponseCode() == net::HTTP_OK) { + std::string response; + fetcher_->GetResponseAsString(&response); + responseData = + [NSData dataWithBytes:response.c_str() length:response.length()]; + } + fetcher_.reset(); + // If data was fetched, write the fetched data to local store in a + // separate thread. Then update the resource descriptor that configuration + // update is completed. Finally, schedule the next update check. + web::WebThread::PostBlockingPoolTask(FROM_HERE, base::BindBlock(^{ + BOOL updateSuccess = NO; + if (responseData) { + NSString* path = [descriptor_ updateResourcePath]; + updateSuccess = [responseData writeToFile:path atomically:YES]; + } + dispatch_after(DISPATCH_TIME_NOW, dispatch_get_main_queue(), ^() { + [descriptor_ updateCheckDidFinishWithSuccess:updateSuccess]; + }); + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, kPeriodicCheckInNanoseconds), + dispatch_get_main_queue(), ^{ + [owner_ checkUpdate]; + }); + })); + }; + + private: + UpdatableConfigBase* owner_; + id<UpdatableResourceDescriptorBridge> descriptor_; + scoped_ptr<net::URLFetcher> fetcher_; +}; + +} // namespace + +@implementation UpdatableConfigBase { + base::scoped_nsprotocol<id<UpdatableResourceBridge>> _updatableResource; + scoped_ptr<ConfigFetcher> _configFetcher; + scoped_refptr<net::URLRequestContextGetter> _requestContextGetter; +} + ++ (void)enableConsistencyCheck { +#if !defined(NDEBUG) + g_consistency_check_enabled = YES; +#endif +} + +// Overrides default designated initializer. +- (instancetype)init { + NOTREACHED(); + return nil; +} + +- (instancetype)initWithAppId:(NSString*)appId + version:(NSString*)appVersion + plist:(NSString*)plistName { + self = [super init]; + if (self) { + _updatableResource.reset([self newResource:plistName]); + // UpdatableResourceBridge initializes the appId to what is in the + // application bundle. The following overrides that with either the |appId| + // passed in or a default based on experimental settings if |appId| is nil. + if (!appId) + appId = [UpdatableConfigBase defaultAppId]; + [[_updatableResource descriptor] setApplicationIdentifier:appId]; + // Overrides the default application version if necessary. + if (appVersion) + [[_updatableResource descriptor] setApplicationVersion:appVersion]; + // [UpdatableResourceBridge -loadDefaults] updates the resource in + // two phases and is probably not MT safe. However, + // initWithAppId:version:plist: is called from a singleton's + // initialization loop and thus will not be called more than once. + // TODO(pkl): -loadDefaults accesses the file system to load in the + // plist. This should be done via PostBlockingPoolTask. + [_updatableResource loadDefaults]; + + NSString* notificationName = ios::GetChromeBrowserProvider() + ->GetUpdatableResourceProvider() + ->GetUpdateNotificationName(); + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(resourceDidUpdate:) + name:notificationName + object:[_updatableResource descriptor]]; + +#if !defined(NDEBUG) + [self scheduleConsistencyCheck]; +#endif + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +#if !defined(NDEBUG) + [self cancelConsistencyCheck]; +#endif + [super dealloc]; +} + +- (void)startUpdate:(net::URLRequestContextGetter*)requestContextGetter { +#if !defined(NDEBUG) + [self cancelConsistencyCheck]; +#endif + _requestContextGetter = requestContextGetter; + [self checkUpdate]; +} + +- (void)stopUpdateChecks { + _requestContextGetter = nullptr; +} + +- (void)resourceDidUpdate:(NSNotification*)notification { + id sender = [notification object]; + DCHECK([_updatableResource descriptor] == sender); +} + +#pragma mark - +#pragma mark For Subclasses + +- (id<UpdatableResourceBridge>)newResource:(NSString*)resourceName { + // Subclasses must override this factory method. + NOTREACHED(); + return nil; +} + +- (id<UpdatableResourceBridge>)updatableResource { + return _updatableResource.get(); +} + +#pragma mark - +#pragma mark For Debug Compilations + +#if !defined(NDEBUG) +- (void)scheduleConsistencyCheck { + // Sets a delayed call that will cause a DCHECK if -startUpdate: + // was not called. + [self performSelector:@selector(startUpdateNotCalled:) + withObject:self + afterDelay:60.0]; +} + +- (void)cancelConsistencyCheck { + // Cancels the delayed error check since -startUpdate: has been called. + // Added for completeness since singletons should never be deallocated. + [NSObject + cancelPreviousPerformRequestsWithTarget:self + selector:@selector(startUpdateNotCalled:) + object:self]; +} + +- (void)startUpdateNotCalled:(id)config { + DCHECK(self == config); + if (!g_consistency_check_enabled) + return; + // Make sure that |startUpdate:| was called for this config. + NOTREACHED() << "startUpdate: was not called for " + << [[self description] UTF8String]; +} +#endif // !defined(NDEBUG) + +#pragma mark - +#pragma mark For Unit Testing + +- (void)setUpdatableResource:(id<UpdatableResourceBridge>)resource { + _updatableResource.reset([resource retain]); +} + +#pragma mark - +#pragma mark Private + ++ (NSString*)defaultAppId { + // During development and dogfooding, allow a different configuration + // update file to be used for testing. + NSString* flag = [[NSUserDefaults standardUserDefaults] + stringForKey:@"UpdatableConfigLocation"]; + if ([flag length]) { + if ([flag isEqualToString:@"Stable"]) + return @"com.google.chrome.ios"; + else if ([flag isEqualToString:@"Dogfood"]) + return @"com.google.chrome.ios.beta"; + else if ([flag isEqualToString:@"None"]) + return @"this.does.not.update"; + } + return [[NSBundle mainBundle] bundleIdentifier]; +} + +- (void)checkUpdate { + if (!_requestContextGetter.get()) + return; + if (!_configFetcher) { + _configFetcher.reset( + new ConfigFetcher(self, [_updatableResource descriptor])); + } + GURL url = net::GURLWithNSURL([[_updatableResource descriptor] updateURL]); + _configFetcher->Fetch(url, _requestContextGetter.get()); +} + +@end
diff --git a/ios/chrome/browser/updatable_config/updatable_dictionary.h b/ios/chrome/browser/updatable_config/updatable_dictionary.h new file mode 100644 index 0000000..5331aed --- /dev/null +++ b/ios/chrome/browser/updatable_config/updatable_dictionary.h
@@ -0,0 +1,19 @@ +// Copyright 2013 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_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_DICTIONARY_H_ +#define IOS_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_DICTIONARY_H_ + +#import "ios/chrome/browser/updatable_config/updatable_config_base.h" + +@interface UpdatableDictionary : UpdatableConfigBase + +// Returns an autoreleased copy of the configuration dictionary read from +// the file specified in the initializer. Configuration content must be +// of dictionary type. +- (NSDictionary*)dictionaryFromConfig; + +@end + +#endif // IOS_CHROME_BROWSER_UPDATABLE_CONFIG_UPDATABLE_DICTIONARY_H_
diff --git a/ios/chrome/browser/updatable_config/updatable_dictionary.mm b/ios/chrome/browser/updatable_config/updatable_dictionary.mm new file mode 100644 index 0000000..602ab978 --- /dev/null +++ b/ios/chrome/browser/updatable_config/updatable_dictionary.mm
@@ -0,0 +1,25 @@ +// Copyright 2013 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/chrome/browser/updatable_config/updatable_dictionary.h" + +#import "base/logging.h" +#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/public/provider/chrome/browser/updatable_resource_provider.h" + +@implementation UpdatableDictionary + +- (id<UpdatableResourceBridge>)newResource:(NSString*)resourceName { + return ios::GetChromeBrowserProvider() + ->GetUpdatableResourceProvider() + ->CreateUpdatableResource(resourceName, nil); +} + +- (NSDictionary*)dictionaryFromConfig { + id configData = [[[self.updatableResource resourceData] retain] autorelease]; + DCHECK([configData isKindOfClass:[NSDictionary class]]); + return configData; +} + +@end
diff --git a/ios/chrome/browser/xcallback_parameters.h b/ios/chrome/browser/xcallback_parameters.h new file mode 100644 index 0000000..82b89965 --- /dev/null +++ b/ios/chrome/browser/xcallback_parameters.h
@@ -0,0 +1,38 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_XCALLBACK_PARAMETERS_H_ +#define IOS_CHROME_BROWSER_XCALLBACK_PARAMETERS_H_ + +#import <Foundation/Foundation.h> + +#include "url/gurl.h" + +// This class contains the defining parameters for an XCallback request from +// another app. +@interface XCallbackParameters : NSObject<NSCoding, NSCopying> + +// The id of the calling app. +@property(nonatomic, readonly, copy) NSString* sourceAppId; + +// The user visible name of the calling app. Can be nil. +@property(nonatomic, readonly, copy) NSString* sourceAppName; + +// x-callback-url::x-success URL. If the app is opened using a x-callback-url +// compliant URL, the value of this parameter is used as callback URL when the +// user taps the back button. +@property(nonatomic, readonly) const GURL& successURL; + +// Flag to force the creation of a new tab. Default YES. +@property(nonatomic, readonly) BOOL createNewTab; + +- (instancetype)initWithSourceAppId:(NSString*)sourceAppId + sourceAppName:(NSString*)sourceAppName + successURL:(const GURL&)successURL + createNewTab:(BOOL)createNewTab + NS_DESIGNATED_INITIALIZER; + +@end + +#endif // IOS_CHROME_BROWSER_XCALLBACK_PARAMETERS_H_
diff --git a/ios/chrome/browser/xcallback_parameters.mm b/ios/chrome/browser/xcallback_parameters.mm new file mode 100644 index 0000000..0d55d38 --- /dev/null +++ b/ios/chrome/browser/xcallback_parameters.mm
@@ -0,0 +1,94 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/xcallback_parameters.h" + +#include "base/mac/scoped_nsobject.h" +#include "base/strings/sys_string_conversions.h" + +namespace { +NSString* const kSourceAppIdKey = @"sourceAppId"; +NSString* const kSourceAppNameKey = @"sourceAppName"; +NSString* const kSuccessURLKey = @"successURL"; +NSString* const kCreateNewTabKey = @"createNewTab"; +} + +@interface XCallbackParameters () { + base::scoped_nsobject<NSString> _sourceAppId; + base::scoped_nsobject<NSString> _sourceAppName; + GURL _successURL; + BOOL _createNewTab; +} +@end + +@implementation XCallbackParameters + +@synthesize successURL = _successURL; +@synthesize createNewTab = _createNewTab; + +- (instancetype)initWithSourceAppId:(NSString*)sourceAppId + sourceAppName:(NSString*)sourceAppName + successURL:(const GURL&)successURL + createNewTab:(BOOL)createNewTab { + self = [super init]; + if (self) { + _sourceAppId.reset([sourceAppId copy]); + _sourceAppName.reset([sourceAppName copy]); + _successURL = successURL; + _createNewTab = createNewTab; + } + return self; +} + +- (NSString*)description { + return [NSString stringWithFormat:@"SourceApp: %@ (%@)\nSuccessURL: %s\n", + _sourceAppName.get(), _sourceAppId.get(), + _successURL.spec().c_str()]; +} + +- (NSString*)sourceAppId { + return _sourceAppId.get(); +} + +- (NSString*)sourceAppName { + return _sourceAppName.get(); +} + +#pragma mark - NSCoding Methods + +- (instancetype)initWithCoder:(NSCoder*)aDecoder { + GURL successURL; + NSString* successURLStr = [aDecoder decodeObjectForKey:kSuccessURLKey]; + if (successURLStr) + _successURL = GURL(base::SysNSStringToUTF8(successURLStr)); + + return + [self initWithSourceAppId:[aDecoder decodeObjectForKey:kSourceAppIdKey] + sourceAppName:[aDecoder decodeObjectForKey:kSourceAppNameKey] + successURL:successURL + createNewTab:[aDecoder decodeBoolForKey:kCreateNewTabKey]]; +} + +- (void)encodeWithCoder:(NSCoder*)aCoder { + [aCoder encodeObject:_sourceAppId forKey:kSourceAppIdKey]; + [aCoder encodeObject:_sourceAppName forKey:kSourceAppNameKey]; + if (_successURL.is_valid()) { + NSString* successStr = base::SysUTF8ToNSString(_successURL.spec()); + [aCoder encodeObject:successStr forKey:kSuccessURLKey]; + } + [aCoder encodeBool:_createNewTab forKey:kCreateNewTabKey]; +} + +#pragma mark - NSCopying Methods + +- (instancetype)copyWithZone:(NSZone*)zone { + XCallbackParameters* copy = [[[self class] allocWithZone:zone] init]; + copy->_sourceAppId.reset([_sourceAppId copy]); + copy->_sourceAppName.reset([_sourceAppName copy]); + copy->_successURL = _successURL; + copy->_createNewTab = _createNewTab; + return copy; +} + +@end
diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp index 5163b2b..f524f5d 100644 --- a/ios/chrome/ios_chrome.gyp +++ b/ios/chrome/ios_chrome.gyp
@@ -8,6 +8,27 @@ }, 'targets': [ { + 'target_name': 'ios_chrome_app', + 'type': 'static_library', + 'include_dirs': [ + '../..', + ], + 'dependencies': [ + 'ios_chrome_browser', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + ], + }, + 'sources': [ + 'app/safe_mode_crashing_modules_config.h', + 'app/safe_mode_crashing_modules_config.mm', + 'app/safe_mode_util.h', + 'app/safe_mode_util.cc', + ], + }, + { 'target_name': 'ios_chrome_browser', 'type': 'static_library', 'include_dirs': [ @@ -15,6 +36,7 @@ ], 'dependencies': [ '../../base/base.gyp:base', + '../../base/base.gyp:base_prefs', '../../components/components.gyp:autofill_core_browser', '../../components/components.gyp:autofill_ios_browser', '../../components/components.gyp:data_reduction_proxy_core_common', @@ -24,9 +46,11 @@ '../../components/components.gyp:keyed_service_core', '../../components/components.gyp:keyed_service_ios', '../../components/components.gyp:leveldb_proto', + '../../components/components.gyp:pref_registry', '../../components/components.gyp:suggestions', '../../components/components.gyp:translate_core_browser', '../../components/components.gyp:translate_ios_browser', + '../../components/components.gyp:sync_driver', '../../components/components.gyp:web_resource', '../../components/components.gyp:webp_transcode', '../../components/components_strings.gyp:components_strings', @@ -46,6 +70,7 @@ 'libraries': [ '$(SDKROOT)/System/Library/Frameworks/Accelerate.framework', '$(SDKROOT)/System/Library/Frameworks/CoreGraphics.framework', + '$(SDKROOT)/System/Library/Frameworks/CoreLocation.framework', '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework', '$(SDKROOT)/System/Library/Frameworks/UIKit.framework', @@ -76,6 +101,8 @@ 'browser/browser_state/browser_state_otr_helper.cc', 'browser/browser_state/browser_state_otr_helper.h', 'browser/browsing_data_change_listening.h', + 'browser/chrome_paths.h', + 'browser/chrome_paths.mm', 'browser/chrome_switches.cc', 'browser/chrome_switches.h', 'browser/chrome_url_constants.cc', @@ -92,6 +119,16 @@ 'browser/find_in_page/find_in_page_model.mm', 'browser/find_in_page/js_findinpage_manager.h', 'browser/find_in_page/js_findinpage_manager.mm', + 'browser/first_run/first_run.h', + 'browser/first_run/first_run.mm', + 'browser/geolocation/CLLocation+OmniboxGeolocation.h', + 'browser/geolocation/CLLocation+OmniboxGeolocation.mm', + 'browser/geolocation/CLLocation+XGeoHeader.h', + 'browser/geolocation/CLLocation+XGeoHeader.mm', + 'browser/geolocation/location_manager.h', + 'browser/geolocation/location_manager.mm', + 'browser/geolocation/omnibox_geolocation_config.h', + 'browser/geolocation/omnibox_geolocation_config.mm', 'browser/infobars/confirm_infobar_controller.h', 'browser/infobars/confirm_infobar_controller.mm', 'browser/infobars/infobar.h', @@ -126,6 +163,9 @@ 'browser/passwords/password_generation_utils.mm', 'browser/pref_names.cc', 'browser/pref_names.h', + 'browser/prefs/pref_observer_bridge.h', + 'browser/prefs/pref_observer_bridge.mm', + 'browser/procedural_block_types.h', 'browser/snapshots/snapshot_cache.h', 'browser/snapshots/snapshot_cache.mm', 'browser/snapshots/snapshot_manager.h', @@ -138,6 +178,8 @@ 'browser/suggestions/image_fetcher_impl.mm', 'browser/suggestions/suggestions_service_factory.h', 'browser/suggestions/suggestions_service_factory.mm', + 'browser/sync/sync_observer_bridge.h', + 'browser/sync/sync_observer_bridge.mm', 'browser/translate/after_translate_infobar_controller.h', 'browser/translate/after_translate_infobar_controller.mm', 'browser/translate/before_translate_infobar_controller.h', @@ -193,10 +235,18 @@ 'browser/ui/uikit_ui_util.h', 'browser/ui/uikit_ui_util.mm', 'browser/ui/url_loader.h', + 'browser/updatable_config/updatable_array.h', + 'browser/updatable_config/updatable_array.mm', + 'browser/updatable_config/updatable_config_base.h', + 'browser/updatable_config/updatable_config_base.mm', + 'browser/updatable_config/updatable_dictionary.h', + 'browser/updatable_config/updatable_dictionary.mm', 'browser/web/dom_altering_lock.h', 'browser/web/dom_altering_lock.mm', 'browser/web_resource/ios_web_resource_service.cc', 'browser/web_resource/ios_web_resource_service.h', + 'browser/xcallback_parameters.h', + 'browser/xcallback_parameters.mm', ], }, {
diff --git a/ios/chrome/ios_chrome_tests.gyp b/ios/chrome/ios_chrome_tests.gyp index 3af8d8f..97c0f38 100644 --- a/ios/chrome/ios_chrome_tests.gyp +++ b/ios/chrome/ios_chrome_tests.gyp
@@ -19,11 +19,15 @@ '../ios_tests.gyp:test_support_ios', '../web/ios_web.gyp:ios_web', '../web/ios_web.gyp:test_support_ios_web', + 'ios_chrome.gyp:ios_chrome_app', 'ios_chrome.gyp:ios_chrome_browser', 'ios_chrome.gyp:ios_chrome_common', 'ios_chrome_test_support', ], 'sources': [ + 'app/safe_mode_util_unittest.cc', + 'browser/geolocation/CLLocation+XGeoHeaderTest.mm', + 'browser/geolocation/location_manager_unittest.mm', 'browser/net/image_fetcher_unittest.mm', 'browser/net/metrics_network_client_unittest.mm', 'browser/net/retryable_url_fetcher_unittest.mm', @@ -47,6 +51,9 @@ 'ios_chrome.gyp:ios_chrome_browser', ], 'sources': [ + 'browser/geolocation/location_manager+Testing.h', + 'browser/geolocation/test_location_manager.h', + 'browser/geolocation/test_location_manager.mm', 'browser/net/mock_image_fetcher.h', 'browser/net/mock_image_fetcher.mm', 'test/ios_chrome_unit_test_suite.cc',
diff --git a/ios/ios_tests.gyp b/ios/ios_tests.gyp index c951ed3..e253aa4 100644 --- a/ios/ios_tests.gyp +++ b/ios/ios_tests.gyp
@@ -18,6 +18,8 @@ 'public/test/test_chrome_browser_provider.mm', 'public/test/test_chrome_provider_initializer.cc', 'public/test/test_chrome_provider_initializer.h', + 'public/test/test_updatable_resource_provider.h', + 'public/test/test_updatable_resource_provider.mm', ], 'dependencies': [ '../base/base.gyp:base',
diff --git a/ios/provider/ios_provider_chrome.gyp b/ios/provider/ios_provider_chrome.gyp index d6e7cea..099548d 100644 --- a/ios/provider/ios_provider_chrome.gyp +++ b/ios/provider/ios_provider_chrome.gyp
@@ -14,9 +14,13 @@ '../public/provider/chrome/browser/browser_state/chrome_browser_state.h', '../public/provider/chrome/browser/chrome_browser_provider.cc', '../public/provider/chrome/browser/chrome_browser_provider.h', + '../public/provider/chrome/browser/geolocation_updater_provider.h', + '../public/provider/chrome/browser/geolocation_updater_provider.mm', '../public/provider/chrome/browser/string_provider.h', '../public/provider/chrome/browser/ui/infobar_view_delegate.h', '../public/provider/chrome/browser/ui/infobar_view_protocol.h', + '../public/provider/chrome/browser/updatable_resource_provider.h', + '../public/provider/chrome/browser/updatable_resource_provider.mm', ], 'dependencies': [ '../../base/base.gyp:base',
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.cc b/ios/public/provider/chrome/browser/chrome_browser_provider.cc index 25d98fd..2185f8f 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.cc +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.cc
@@ -35,6 +35,11 @@ return nullptr; } +UpdatableResourceProvider* +ChromeBrowserProvider::GetUpdatableResourceProvider() { + return nullptr; +} + InfoBarViewPlaceholder* ChromeBrowserProvider::CreateInfoBarView() { return nullptr; } @@ -43,6 +48,11 @@ return nullptr; } +GeolocationUpdaterProvider* +ChromeBrowserProvider::GetGeolocationUpdaterProvider() { + return nullptr; +} + void ChromeBrowserProvider::ShowTranslateSettings() { }
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h index bf7a1fe..668c6223 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.h +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -29,7 +29,9 @@ namespace ios { class ChromeBrowserProvider; +class GeolocationUpdaterProvider; class StringProvider; +class UpdatableResourceProvider; // Setter and getter for the provider. The provider should be set early, before // any browser code is called. @@ -47,11 +49,14 @@ virtual net::URLRequestContextGetter* GetSystemURLRequestContext(); // Gets the local state. virtual PrefService* GetLocalState(); + // Returns an UpdatableResourceProvider instance. + virtual UpdatableResourceProvider* GetUpdatableResourceProvider(); // Returns an instance of an infobar view. The caller is responsible for // initializing the returned object and releasing it when appropriate. virtual InfoBarViewPlaceholder* CreateInfoBarView(); // Returns an instance of a string provider. virtual StringProvider* GetStringProvider(); + virtual GeolocationUpdaterProvider* GetGeolocationUpdaterProvider(); // Displays the Translate settings screen. virtual void ShowTranslateSettings(); // Returns the chrome UI scheme.
diff --git a/ios/public/provider/chrome/browser/geolocation_updater_provider.h b/ios/public/provider/chrome/browser/geolocation_updater_provider.h new file mode 100644 index 0000000..6a03f79 --- /dev/null +++ b/ios/public/provider/chrome/browser/geolocation_updater_provider.h
@@ -0,0 +1,89 @@ +// 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_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_H +#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_H + +#import <CoreLocation/CoreLocation.h> +#import <Foundation/Foundation.h> + +#include "base/macros.h" + +// GeolocationUpdater tracks the current location of the user and sends +// NSNotifications when it changes. +// The notification names and keys can be obtained using +// GeolocationUpdaterProvider. +@protocol GeolocationUpdater<NSObject> + +// Returns the most recently fetched location. Returns nil if disabled. +- (CLLocation*)currentLocation; + +// Prompts the user to authorize access to location information while the app is +// in use. Only affects iOS 8+. +- (void)requestWhenInUseAuthorization; + +// Set the |timeout| the before the manager gives up fetching the location +// information. If a timer has already been set to stop fetching location, +// it will be reset to |timeout| seconds from now. +- (void)setStopUpdateDelay:(NSTimeInterval)timeout; + +// Sets how often should the location manager check for a fresh location. +- (void)setUpdateInterval:(NSTimeInterval)interval; + +// Sets the desired accuracy, distance and update interval. +// Desired Accuracy defaults to: kCLLocationAccuracyBest. +// Distance Filter defaults to: 20m. +- (void)setDesiredAccuracy:(CLLocationAccuracy)desiredAccuracy + distanceFilter:(CLLocationDistance)distanceFilter; + +// Does not take into consideration whether location is disabled by the OS. +- (BOOL)isEnabled; + +// Turns the geolocation updater on or off, depending on the value of flag. +// if flag is false, then no more location updates will be requested, and +// currentLocation will return nil. +- (void)setEnabled:(BOOL)flag; + +@end + +namespace ios { + +class GeolocationUpdaterProvider { + public: + GeolocationUpdaterProvider(); + virtual ~GeolocationUpdaterProvider(); + + // Creates a new GeolocationUpdater. + // The returned object is retained and it is the responsability of the caller + // to release it. + virtual id<GeolocationUpdater> CreateGeolocationUpdater(bool enabled); + + // Notification names: + + // Name of NSNotificationCenter notification posted on user location update. + // Passes a |CLLocation| for the new location in the userInfo dictionary with + // the key returned by GetUpdateNewLocationKey(). + virtual NSString* GetUpdateNotificationName(); + // Name of NSNotificationCenter notification posted on when the location + // manager's stops. + virtual NSString* GetStopNotificationName(); + // Name of NSNotificationCenter notification posted when the location + // manager's authorization status changes. For example when the user turns + // off Locations Services in Settings. The new status is passed as a + // |NSNumber| representing the |CLAuthorizationStatus| enum value. + virtual NSString* GetAuthorizationChangeNotificationName(); + + // Notification keys: + + // Key used in the userInfo dictionaries of this class' notifications. + // Contains a |CLLocation *| and is used in the update notification. + virtual NSString* GetUpdateNewLocationKey(); + + private: + DISALLOW_COPY_AND_ASSIGN(GeolocationUpdaterProvider); +}; + +} // namespace ios + +#endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_GEOLOCATION_UPDATER_H
diff --git a/ios/public/provider/chrome/browser/geolocation_updater_provider.mm b/ios/public/provider/chrome/browser/geolocation_updater_provider.mm new file mode 100644 index 0000000..02f7070 --- /dev/null +++ b/ios/public/provider/chrome/browser/geolocation_updater_provider.mm
@@ -0,0 +1,36 @@ +// 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/public/provider/chrome/browser/geolocation_updater_provider.h" + +namespace ios { + +GeolocationUpdaterProvider::GeolocationUpdaterProvider() { +} + +GeolocationUpdaterProvider::~GeolocationUpdaterProvider() { +} + +id<GeolocationUpdater> GeolocationUpdaterProvider::CreateGeolocationUpdater( + bool enabled) { + return nil; +} + +NSString* GeolocationUpdaterProvider::GetUpdateNotificationName() { + return nil; +} + +NSString* GeolocationUpdaterProvider::GetStopNotificationName() { + return nil; +} + +NSString* GeolocationUpdaterProvider::GetAuthorizationChangeNotificationName() { + return nil; +} + +NSString* GeolocationUpdaterProvider::GetUpdateNewLocationKey() { + return nil; +} + +} // namespace ios
diff --git a/ios/public/provider/chrome/browser/updatable_resource_provider.h b/ios/public/provider/chrome/browser/updatable_resource_provider.h new file mode 100644 index 0000000..64993cd --- /dev/null +++ b/ios/public/provider/chrome/browser/updatable_resource_provider.h
@@ -0,0 +1,107 @@ +// 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_PUBLIC_PROVIDER_CHROME_BROWSER_UPDATABLE_RESOURCE_PROVIDER_H_ +#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_UPDATABLE_RESOURCE_PROVIDER_H_ + +#import <Foundation/Foundation.h> + +#include "base/macros.h" + +@protocol UpdatableResourceDelegate; +@protocol UpdatableResourceDescriptorBridge; + +#pragma mark - UpdatableResourceBridge + +// UpdatableResourceBridge represents an updatable resource. +@protocol UpdatableResourceBridge<NSObject> + +// Returns the UpdatableResourceDescriptorBridge associated to this resource. +@property(nonatomic, readonly) id<UpdatableResourceDescriptorBridge> descriptor; + +// Returns the UpdatableResourceDelegate associated to this resource. +- (id<UpdatableResourceDelegate>)delegate; + +// The data provided by this resource. +- (NSDictionary*)resourceData; + +// Initializes this updatable resource with default values. +- (void)loadDefaults; +@end + +#pragma mark - UpdatableResourceDescriptorBridge + +// This class encapsulates identification and versioning information +// for an updatable resource. +@protocol UpdatableResourceDescriptorBridge<NSObject> + +@property(nonatomic, copy) NSString* applicationIdentifier; +@property(nonatomic, copy) NSString* applicationVersion; + +// URL where an update to this resource may be downloaded. +@property(nonatomic, readonly) NSURL* updateURL; + +// Search path for the default file. +@property(nonatomic, copy) NSString* bundleResourcePath; +// Search path for the downloaded file. +@property(nonatomic, copy) NSString* updateResourcePath; + +// This method must be called after an update check has been made. Either +// successfully or not. +- (void)updateCheckDidFinishWithSuccess:(BOOL)wasSuccessful; + +// Returns the full path of the latest and greatest version of the resource +// currently residing on the device. If there is no version of the resource +// currently stored on the device, returns |nil|. +- (NSString*)resourcePath; + +@end + +#pragma mark - UpdatableResourceDelegate + +// Delegate for UpdatableResourceBridge. +@protocol UpdatableResourceDelegate<NSObject> + +// This method can be reimplemented to override the behavior of the +// UpdatableResourceBridge method. +- (void)loadDefaults:(id<UpdatableResourceBridge>)resource; + +// Merges the latest values defined in the file into the values currently stored +// by the updatable resource. +- (void)mergeUpdate:(id<UpdatableResourceBridge>)resource; + +// Parses file at |path| and returns an NSDictionary with the values stored +// therein. +- (NSDictionary*)parseFileAt:(NSString*)path; +@end + +#pragma mark - UpdatableResourceProvider + +namespace ios { + +// Provider for UpdatableResourceBridge. +class UpdatableResourceProvider { + public: + UpdatableResourceProvider(); + virtual ~UpdatableResourceProvider(); + + // Returns the name of the notification that is sent through the notification + // center when a resource is updated. + virtual NSString* GetUpdateNotificationName(); + + // Creates a new UpdatableResourceBrige. + // The user is responsible for releasing it. + // The UpdatableResourceBridge takes ownership of the delegate. + // |delegate| may be nil. + virtual id<UpdatableResourceBridge> CreateUpdatableResource( + NSString* resource_identifier, + id<UpdatableResourceDelegate> delegate); + + private: + DISALLOW_COPY_AND_ASSIGN(UpdatableResourceProvider); +}; + +} // namespace ios + +#endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_UPDATABLE_RESOURCE_PROVIDER_H_
diff --git a/ios/public/provider/chrome/browser/updatable_resource_provider.mm b/ios/public/provider/chrome/browser/updatable_resource_provider.mm new file mode 100644 index 0000000..7172695 --- /dev/null +++ b/ios/public/provider/chrome/browser/updatable_resource_provider.mm
@@ -0,0 +1,25 @@ +// 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/public/provider/chrome/browser/updatable_resource_provider.h" + +namespace ios { + +UpdatableResourceProvider::UpdatableResourceProvider() { +} + +UpdatableResourceProvider::~UpdatableResourceProvider() { +} + +NSString* UpdatableResourceProvider::GetUpdateNotificationName() { + return nil; +} + +id<UpdatableResourceBridge> UpdatableResourceProvider::CreateUpdatableResource( + NSString* resource_identifier, + id<UpdatableResourceDelegate> delegate) { + return nil; +} + +} // namespace ios
diff --git a/ios/public/test/test_updatable_resource_provider.h b/ios/public/test/test_updatable_resource_provider.h new file mode 100644 index 0000000..c067c71 --- /dev/null +++ b/ios/public/test/test_updatable_resource_provider.h
@@ -0,0 +1,25 @@ +// 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_PUBLIC_TEST_TEST_UPDATABLE_RESOURCE_PROVIDER_H_ +#define IOS_PUBLIC_TEST_TEST_UPDATABLE_RESOURCE_PROVIDER_H_ + +#import "ios/public/provider/chrome/browser/updatable_resource_provider.h" + +namespace ios { + +// Dummy UpdatableResourceProvider implementation that simply loads data from +// the specified plist file. +class TestUpdatableResourceProvider : public ios::UpdatableResourceProvider { + private: + // UpdatableResourceProvider implementation. + NSString* GetUpdateNotificationName() override; + id<UpdatableResourceBridge> CreateUpdatableResource( + NSString* resource_identifier, + id<UpdatableResourceDelegate> delegate) override; +}; + +} // namespace ios + +#endif // IOS_PUBLIC_TEST_TEST_UPDATABLE_RESOURCE_PROVIDER_H_
diff --git a/ios/public/test/test_updatable_resource_provider.mm b/ios/public/test/test_updatable_resource_provider.mm new file mode 100644 index 0000000..de8459f2 --- /dev/null +++ b/ios/public/test/test_updatable_resource_provider.mm
@@ -0,0 +1,102 @@ +// 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/public/test/test_updatable_resource_provider.h" + +#include "base/logging.h" +#include "base/mac/scoped_nsobject.h" + +#pragma mark - TestUpdatabeResourceDescriptor + +// Dummy UpdatableResourceDescriptorBridge implementation. +@interface TestUpdatabeResourceDescriptor + : NSObject<UpdatableResourceDescriptorBridge> +@property(nonatomic, readonly) NSURL* updateURL; +@property(nonatomic, copy) NSString* applicationIdentifier; +@property(nonatomic, copy) NSString* applicationVersion; +@property(nonatomic, copy) NSString* bundleResourcePath; +@property(nonatomic, copy) NSString* updateResourcePath; +@end + +@implementation TestUpdatabeResourceDescriptor +@synthesize updateURL; +@synthesize applicationIdentifier; +@synthesize applicationVersion; +@synthesize bundleResourcePath; +@synthesize updateResourcePath; + +- (void)updateCheckDidFinishWithSuccess:(BOOL)wasSuccessful { +} + +- (NSString*)resourcePath { + return nil; +} +@end + +#pragma mark - TestUpdatableResource + +// Dummy UpdatableResourceDescriptorBridge implementation that simply loads data +// from the specified plist file. +@interface TestUpdatableResource : NSObject<UpdatableResourceBridge> +@property(nonatomic, readonly) id<UpdatableResourceDescriptorBridge> descriptor; +- (instancetype)initWithDelegate:(id<UpdatableResourceDelegate>)delegate + plist:(NSString*)resource_identifier + NS_DESIGNATED_INITIALIZER; +@end + +@implementation TestUpdatableResource { + base::scoped_nsprotocol<id<UpdatableResourceDelegate>> _delegate; + base::scoped_nsprotocol<id<UpdatableResourceDescriptorBridge>> _descriptor; +} + +- (instancetype)initWithDelegate:(id<UpdatableResourceDelegate>)delegate + plist:(NSString*)resourceIdentifier { + if (self = [super init]) { + _delegate.reset([delegate retain]); + _descriptor.reset([[TestUpdatabeResourceDescriptor alloc] init]); + DCHECK([resourceIdentifier hasSuffix:@".plist"]) + << "TestUpdatableResource supports only the plist format"; + [_descriptor setBundleResourcePath:resourceIdentifier]; + } + return self; +} + +- (id<UpdatableResourceDescriptorBridge>)descriptor { + return _descriptor.get(); +} + +- (id<UpdatableResourceDelegate>)delegate { + return _delegate; +} + +- (NSDictionary*)resourceData { + return [NSDictionary + dictionaryWithContentsOfFile:[_descriptor bundleResourcePath]]; +} +- (void)loadDefaults { + [_delegate loadDefaults:self]; +} + +@end + +#pragma mark - TestUpdatableResourceProvider + +namespace ios { + +NSString* TestUpdatableResourceProvider::GetUpdateNotificationName() { + return @"ResourceUpdatedTest"; +} + +id<UpdatableResourceBridge> +TestUpdatableResourceProvider::CreateUpdatableResource( + NSString* resource_identifier, + id<UpdatableResourceDelegate> delegate) { + NSString* path = + [NSString stringWithFormat:@"%@/gm-config/ANY/%@", + [[NSBundle mainBundle] resourcePath], + resource_identifier]; + return [[TestUpdatableResource alloc] initWithDelegate:delegate plist:path]; +} + +} // namespace ios
diff --git a/ios/web/DEPS b/ios/web/DEPS index abbd333..dd6fcbb 100644 --- a/ios/web/DEPS +++ b/ios/web/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+crypto", "+ios/public/provider/web", "+ios/net", "+ios/web",
diff --git a/ios/web/PRESUBMIT.py b/ios/web/PRESUBMIT.py new file mode 100644 index 0000000..3d39a554 --- /dev/null +++ b/ios/web/PRESUBMIT.py
@@ -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. + +"""Presubmit script for ios/web. + +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): + results = [] + results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api) + return results
diff --git a/ios/web/ios_web.gyp b/ios/web/ios_web.gyp index dc71de0..2cf5271 100644 --- a/ios/web/ios_web.gyp +++ b/ios/web/ios_web.gyp
@@ -90,6 +90,7 @@ 'public/user_metrics.h', 'public/web_client.h', 'public/web_client.mm', + 'public/web_state/credential.h', 'public/web_state/crw_native_content.h', 'public/web_state/crw_native_content_provider.h', 'public/web_state/crw_web_controller_observer.h', @@ -108,6 +109,7 @@ 'public/web_state/web_state_observer_bridge.h', 'public/web_thread.h', 'public/web_view_type.h', + 'public/web_view_util.h', 'string_util.cc', 'ui_web_view_util.h', 'ui_web_view_util.mm', @@ -118,11 +120,20 @@ 'weak_nsobject_counter.mm', 'web_state/blocked_popup_info.h', 'web_state/blocked_popup_info.mm', + 'web_state/credential.cc', 'web_state/crw_recurring_task_delegate.h', + 'web_state/js/credential_util.h', + 'web_state/js/credential_util.mm', 'web_state/js/crw_js_early_script_manager.h', 'web_state/js/crw_js_early_script_manager.mm', 'web_state/js/crw_js_injection_manager.mm', 'web_state/js/crw_js_injection_receiver.mm', + 'web_state/js/crw_js_invoke_parameter_queue.h', + 'web_state/js/crw_js_invoke_parameter_queue.mm', + 'web_state/js/crw_js_plugin_placeholder_manager.h', + 'web_state/js/crw_js_plugin_placeholder_manager.mm', + 'web_state/js/crw_js_window_id_manager.h', + 'web_state/js/crw_js_window_id_manager.mm', 'web_state/js/page_script_util.h', 'web_state/js/page_script_util.mm', 'web_state/ui/crw_context_menu_provider.h', @@ -150,7 +161,6 @@ 'web_thread.cc', 'web_thread_impl.cc', 'web_thread_impl.h', - 'web_view_util.h', 'web_view_util.mm', ], 'link_settings': { @@ -266,6 +276,7 @@ 'ios_web', '../../content/content_shell_and_tests.gyp:test_support_content', '../../ios/testing/ios_testing.gyp:ocmock_support', + '../../ios/third_party/gcdwebserver/gcdwebserver.gyp:gcdwebserver', '../../testing/gmock.gyp:gmock', '../../testing/gtest.gyp:gtest', '../../third_party/ocmock/ocmock.gyp:ocmock', @@ -276,8 +287,18 @@ 'sources': [ 'public/test/crw_test_js_injection_receiver.h', 'public/test/crw_test_js_injection_receiver.mm', + 'public/test/http_server.h', + 'public/test/http_server.mm', 'public/test/js_test_util.h', 'public/test/js_test_util.mm', + 'public/test/response_providers/data_response_provider.h', + 'public/test/response_providers/data_response_provider.mm', + 'public/test/response_providers/file_based_response_provider.h', + 'public/test/response_providers/file_based_response_provider.mm', + 'public/test/response_providers/file_based_response_provider_impl.cc', + 'public/test/response_providers/file_based_response_provider_impl.h', + 'public/test/response_providers/response_provider.cc', + 'public/test/response_providers/response_provider.h', 'public/test/test_browser_state.cc', 'public/test/test_browser_state.h', 'public/test/test_web_client.h',
diff --git a/ios/web/ios_web_unittests.gyp b/ios/web/ios_web_unittests.gyp index 7000f886..2328056d 100644 --- a/ios/web/ios_web_unittests.gyp +++ b/ios/web/ios_web_unittests.gyp
@@ -34,6 +34,7 @@ 'net/request_tracker_impl_unittest.mm', 'net/web_http_protocol_handler_delegate_unittest.mm', 'public/referrer_util_unittest.cc', + 'public/test/http_server_unittest.mm', 'string_util_unittest.cc', 'ui_web_view_util_unittest.mm', 'url_scheme_util_unittest.mm',
diff --git a/ios/web/navigation/crw_session_controller.mm b/ios/web/navigation/crw_session_controller.mm index 5407ec31..74234ca 100644 --- a/ios/web/navigation/crw_session_controller.mm +++ b/ios/web/navigation/crw_session_controller.mm
@@ -184,7 +184,7 @@ for (size_t i = 0; i < items.size(); ++i) { scoped_ptr<web::NavigationItem> item(items[i]); base::scoped_nsobject<CRWSessionEntry> entry( - [[CRWSessionEntry alloc] initWithNavigationItem:item.Pass() index:i]); + [[CRWSessionEntry alloc] initWithNavigationItem:item.Pass()]); [_entries addObject:entry]; } _currentNavigationIndex = currentIndex; @@ -326,11 +326,9 @@ // (a) new (non-history), browser-initiated navigations, and // (b) pending unsafe navigations (while showing the interstitial) // in order to prevent URL spoof attacks. - web::NavigationItemImpl* pendingItemImpl = - static_cast<web::NavigationItemImpl*>([_pendingEntry navigationItem]); - if (_pendingEntry && - (!pendingItemImpl->is_renderer_initiated() || - pendingItemImpl->IsUnsafe())) { + web::NavigationItemImpl* pendingItem = [_pendingEntry navigationItemImpl]; + if (pendingItem && + (!pendingItem->is_renderer_initiated() || pendingItem->IsUnsafe())) { return _pendingEntry.get(); } return [self lastCommittedEntry]; @@ -397,8 +395,10 @@ } } - BOOL useDesktopUserAgent = _useDesktopUserAgentForNextPendingEntry || - self.currentEntry.useDesktopUserAgent; + BOOL useDesktopUserAgent = + _useDesktopUserAgentForNextPendingEntry || + (self.currentEntry.navigationItem && + self.currentEntry.navigationItem->IsOverridingUserAgent()); _useDesktopUserAgentForNextPendingEntry = NO; _pendingEntry.reset([[self sessionEntryWithURL:url referrer:ref @@ -418,18 +418,17 @@ // session history. Don't modify the entry list. if (!_pendingEntry) return; - web::NavigationItem* item = [_pendingEntry navigationItem]; + + web::NavigationItemImpl* item = [_pendingEntry navigationItemImpl]; if (url != item->GetURL()) { item->SetURL(url); item->SetVirtualURL(url); // Since updates are caused by page redirects, they are renderer-initiated. - web::NavigationItemImpl* pendingItemImpl = - static_cast<web::NavigationItemImpl*>([_pendingEntry navigationItem]); - pendingItemImpl->set_is_renderer_initiated(true); + item->set_is_renderer_initiated(true); // Redirects (3xx response code), or client side navigation must change // POST requests to GETs. - [_pendingEntry setPOSTData:nil]; - [_pendingEntry resetHTTPHeaders]; + item->SetPostData(nil); + item->ResetHttpRequestHeaders(); } // This should probably not be sent if the URLs matched, but that's what was @@ -472,9 +471,7 @@ _currentNavigationIndex = [_entries count] - 1; // Once an entry is committed it's not renderer-initiated any more. (Matches // the implementation in NavigationController.) - web::NavigationItemImpl* pendingItemImpl = - static_cast<web::NavigationItemImpl*>([_pendingEntry navigationItem]); - pendingItemImpl->ResetForCommit(); + [_pendingEntry navigationItemImpl]->ResetForCommit(); _pendingEntry.reset(); } @@ -526,14 +523,17 @@ CHECK( web::history_state_util::IsHistoryStateChangeValid(item->GetURL(), url)); web::Referrer referrer(item->GetURL(), web::ReferrerPolicyDefault); + bool overrideUserAgent = + self.currentEntry.navigationItem->IsOverridingUserAgent(); base::scoped_nsobject<CRWSessionEntry> pushedEntry( [[self sessionEntryWithURL:url referrer:referrer transition:ui::PAGE_TRANSITION_LINK - useDesktopUserAgent:self.currentEntry.useDesktopUserAgent + useDesktopUserAgent:overrideUserAgent rendererInitiated:NO] retain]); - pushedEntry.get().serializedStateObject = stateObject; - pushedEntry.get().createdFromPushState = YES; + web::NavigationItemImpl* pushedItem = [pushedEntry navigationItemImpl]; + pushedItem->SetSerializedStateObject(stateObject); + pushedItem->SetIsCreatedFromPushState(true); web::SSLStatus& sslStatus = [self currentEntry].navigationItem->GetSSL(); pushedEntry.get().navigationItem->GetSSL() = sslStatus; @@ -551,8 +551,10 @@ stateObject:(NSString*)stateObject { DCHECK(!_transientEntry); CRWSessionEntry* currentEntry = self.currentEntry; + web::NavigationItemImpl* currentItem = self.currentEntry.navigationItemImpl; + currentItem->SetURL(url); + currentItem->SetSerializedStateObject(stateObject); currentEntry.navigationItem->SetURL(url); - currentEntry.serializedStateObject = stateObject; // If the change is to a committed entry, notify interested parties. if (currentEntry != self.pendingEntry && _navigationManager) _navigationManager->OnNavigationItemChanged(); @@ -808,15 +810,14 @@ NSUInteger endIndex = firstIndex < secondIndex ? secondIndex : firstIndex; for (NSUInteger i = startIndex + 1; i <= endIndex; i++) { - CRWSessionEntry* entry = [_entries objectAtIndex:i]; + web::NavigationItemImpl* item = [_entries[i] navigationItemImpl]; // Every entry in the sequence has to be created from a pushState() call. - if (!entry.createdFromPushState) + if (!item->IsCreatedFromPushState()) return NO; // Every entry in the sequence has to have a URL that could have been // created from a pushState() call. if (!web::history_state_util::IsHistoryStateChangeValid( - firstEntry.navigationItem->GetURL(), - entry.navigationItem->GetURL())) + firstEntry.navigationItem->GetURL(), item->GetURL())) return NO; } return YES; @@ -839,7 +840,7 @@ - (void)useDesktopUserAgentForNextPendingEntry { if (_pendingEntry) - [_pendingEntry setUseDesktopUserAgent:YES]; + [_pendingEntry navigationItem]->SetIsOverridingUserAgent(true); else _useDesktopUserAgentForNextPendingEntry = YES; } @@ -864,11 +865,13 @@ GURL loaded_url(url); web::BrowserURLRewriter::GetInstance()->RewriteURLIfNecessary(&loaded_url, _browserState); - return [[[CRWSessionEntry alloc] initWithUrl:loaded_url - referrer:referrer - transition:transition - useDesktopUserAgent:useDesktopUserAgent - rendererInitiated:rendererInitiated] autorelease]; + scoped_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl()); + item->SetURL(loaded_url); + item->SetReferrer(referrer); + item->SetTransitionType(transition); + item->SetIsOverridingUserAgent(useDesktopUserAgent); + item->set_is_renderer_initiated(rendererInitiated); + return [[CRWSessionEntry alloc] initWithNavigationItem:item.Pass()]; } @end
diff --git a/ios/web/navigation/crw_session_controller_unittest.mm b/ios/web/navigation/crw_session_controller_unittest.mm index 79a6dff..ea6f4ab 100644 --- a/ios/web/navigation/crw_session_controller_unittest.mm +++ b/ios/web/navigation/crw_session_controller_unittest.mm
@@ -837,11 +837,12 @@ NSString* stateObject1 = @"{'foo': 1}"; [controller pushNewEntryWithURL:pushPageGurl1 stateObject:stateObject1]; CRWSessionEntry* pushedEntry = [controller currentEntry]; + web::NavigationItemImpl* pushedItem = pushedEntry.navigationItemImpl; NSUInteger expectedCount = 2; EXPECT_EQ(expectedCount, controller.get().entries.count); EXPECT_EQ(pushPageGurl1, pushedEntry.navigationItem->GetURL()); - EXPECT_TRUE(pushedEntry.createdFromPushState); - EXPECT_NSEQ(stateObject1, pushedEntry.serializedStateObject); + EXPECT_TRUE(pushedItem->IsCreatedFromPushState()); + EXPECT_NSEQ(stateObject1, pushedItem->GetSerializedStateObject()); EXPECT_EQ(GURL("http://www.firstpage.com/"), pushedEntry.navigationItem->GetReferrer().url); @@ -849,11 +850,12 @@ GURL pushPageGurl2("http://www.firstpage.com/push2"); [controller pushNewEntryWithURL:pushPageGurl2 stateObject:nil]; pushedEntry = [controller currentEntry]; + pushedItem = pushedEntry.navigationItemImpl; expectedCount = 3; EXPECT_EQ(expectedCount, controller.get().entries.count); EXPECT_EQ(pushPageGurl2, pushedEntry.navigationItem->GetURL()); - EXPECT_TRUE(pushedEntry.createdFromPushState); - EXPECT_EQ(nil, pushedEntry.serializedStateObject); + EXPECT_TRUE(pushedItem->IsCreatedFromPushState()); + EXPECT_EQ(nil, pushedItem->GetSerializedStateObject()); EXPECT_EQ(pushPageGurl1, pushedEntry.navigationItem->GetReferrer().url); } @@ -884,9 +886,9 @@ CRWSessionEntry* entry3 = [controller.get().entries objectAtIndex:3]; CRWSessionEntry* entry4 = [controller.get().entries objectAtIndex:4]; CRWSessionEntry* entry5 = [controller.get().entries objectAtIndex:5]; - entry1.createdFromPushState = YES; - entry4.createdFromPushState = YES; - entry5.createdFromPushState = YES; + entry1.navigationItemImpl->SetIsCreatedFromPushState(true); + entry4.navigationItemImpl->SetIsCreatedFromPushState(true); + entry5.navigationItemImpl->SetIsCreatedFromPushState(true); EXPECT_TRUE( [controller isPushStateNavigationBetweenEntry:entry0 andEntry:entry1]); @@ -923,11 +925,12 @@ [controller updateCurrentEntryWithURL:replacePageGurl1 stateObject:stateObject1]; CRWSessionEntry* replacedEntry = [controller currentEntry]; + web::NavigationItemImpl* replacedItem = replacedEntry.navigationItemImpl; NSUInteger expectedCount = 3; EXPECT_EQ(expectedCount, controller.get().entries.count); EXPECT_EQ(replacePageGurl1, replacedEntry.navigationItem->GetURL()); - EXPECT_FALSE(replacedEntry.createdFromPushState); - EXPECT_NSEQ(stateObject1, replacedEntry.serializedStateObject); + EXPECT_FALSE(replacedItem->IsCreatedFromPushState()); + EXPECT_NSEQ(stateObject1, replacedItem->GetSerializedStateObject()); EXPECT_EQ(GURL("http://www.starturl.com/"), replacedEntry.navigationItem->GetReferrer().url); @@ -935,10 +938,11 @@ GURL replacePageGurl2("http://www.firstpage.com/#replace2"); [controller.get() updateCurrentEntryWithURL:replacePageGurl2 stateObject:nil]; replacedEntry = [controller currentEntry]; + replacedItem = replacedEntry.navigationItemImpl; EXPECT_EQ(expectedCount, controller.get().entries.count); EXPECT_EQ(replacePageGurl2, replacedEntry.navigationItem->GetURL()); - EXPECT_FALSE(replacedEntry.createdFromPushState); - EXPECT_NSEQ(nil, replacedEntry.serializedStateObject); + EXPECT_FALSE(replacedItem->IsCreatedFromPushState()); + EXPECT_NSEQ(nil, replacedItem->GetSerializedStateObject()); EXPECT_EQ(GURL("http://www.starturl.com/"), replacedEntry.navigationItem->GetReferrer().url); }
diff --git a/ios/web/navigation/crw_session_entry.h b/ios/web/navigation/crw_session_entry.h index 00d8ec830..6c5f625d 100644 --- a/ios/web/navigation/crw_session_entry.h +++ b/ios/web/navigation/crw_session_entry.h
@@ -15,6 +15,7 @@ namespace web { class NavigationItem; +class NavigationItemImpl; struct Referrer; } @@ -25,40 +26,22 @@ // TODO(rohitrao): Fold CRWSessionEntry's logic into NavigationItem. @interface CRWSessionEntry : NSObject<NSCoding, NSCopying> -@property(nonatomic, assign) NSInteger index; @property(nonatomic, readonly) const GURL& originalUrl; -@property(nonatomic, assign) BOOL useDesktopUserAgent; -@property(nonatomic, assign) BOOL usedDataReductionProxy; -@property(nonatomic, retain) NSString* serializedStateObject; -@property(nonatomic, assign) BOOL createdFromPushState; -@property(nonatomic, retain) NSData* POSTData; -@property(nonatomic, readonly) NSDictionary* httpHeaders; -@property(nonatomic, assign) BOOL skipResubmitDataConfirmation; -// Initialize the session entry with the given url. -- (id)initWithUrl:(const GURL&)url - referrer:(const web::Referrer&)referrer - transition:(ui::PageTransition)transition - useDesktopUserAgent:(BOOL)useDesktopUserAgent - rendererInitiated:(BOOL)rendererInitiated; +// Pointer to the NavigationItem associated with this CRWSessionEntry. +// Eventually, this will replace CRWSessionEntry entirely. +@property(nonatomic, readonly) web::NavigationItem* navigationItem; + +// Pointer to the NavigationItemImpl associated with this CRWSessionEntry. +// TODO(kkhorimoto): This is a convenience property to avoid requiring static +// casts every time the web layer needs access to members only available in +// NavigationItemImpl. Remove once more navigation management moves into +// NavigationManager and CRWSessionEntry=>web::NavigationItemImpl conversions +// become less prominent. +@property(nonatomic, readonly) web::NavigationItemImpl* navigationItemImpl; // Initialize the session entry with the given NavigationItem. -- (id)initWithNavigationItem:(scoped_ptr<web::NavigationItem>)item - index:(int)index; - -// Returns a pointer to the NavigationItem associated with this CRWSessionEntry. -// Eventually, this will replace CRWSessionEntry entirely. -- (web::NavigationItem*)navigationItem; - -// Adds headers from |moreHTTPHeaders| to |httpHeaders|; existing headers with -// the same key will be overridden. -- (void)addHTTPHeaders:(NSDictionary*)moreHTTPHeaders; - -// Removes the header for the given key from |httpHeaders|. -- (void)removeHTTPHeaderForKey:(NSString*)key; - -// Resets |httpHeaders| to nil. -- (void)resetHTTPHeaders; +- (instancetype)initWithNavigationItem:(scoped_ptr<web::NavigationItem>)item; @end
diff --git a/ios/web/navigation/crw_session_entry.mm b/ios/web/navigation/crw_session_entry.mm index c786499..5fd5d4a 100644 --- a/ios/web/navigation/crw_session_entry.mm +++ b/ios/web/navigation/crw_session_entry.mm
@@ -24,46 +24,11 @@ } @interface CRWSessionEntry () { - // The index in the CRWSessionController. - // - // This is used when determining the selected CRWSessionEntry and only useful - // to the SessionServiceIOS. - NSInteger _index; - // The original URL of the page. In cases where a redirect occurred, |url_| // will contain the final post-redirect URL, and |originalUrl_| will contain // the pre-redirect URL. This field is not persisted to disk. GURL _originalUrl; - // Headers passed along with the request. For POST requests, these are - // persisted, to be able to resubmit them. Some specialized non-POST requests - // may also pass custom headers. - base::scoped_nsobject<NSMutableDictionary> _httpHeaders; - - // Data submitted with a POST request, persisted for resubmits. - NSData* _POSTData; - - // Serialized representation of the state object that was used in conjunction - // with a JavaScript window.history.pushState() or - // window.history.replaceState() call that created or modified this - // CRWSessionEntry. Intended to be used for JavaScript history operations and - // will be nil in most cases. - NSString* _serializedStateObject; - - // Whether or not this entry was created by calling history.pushState(). - BOOL _createdFromPushState; - - // If |YES| use a desktop user agent in HTTP requests and UIWebView. - BOOL _useDesktopUserAgent; - - // If |YES| the page was last fetched through the data reduction proxy. - BOOL _usedDataReductionProxy; - - // Whether or not to bypass showing the resubmit data confirmation when - // loading a POST request. Set to YES for browser-generated POST requests such - // as search-by-image requests. - BOOL _skipResubmitDataConfirmation; - // The NavigationItemImpl corresponding to this CRWSessionEntry. // TODO(stuartmorgan): Move ownership to NavigationManagerImpl. scoped_ptr<web::NavigationItemImpl> _navigationItem; @@ -84,48 +49,15 @@ @implementation CRWSessionEntry -@synthesize POSTData = _POSTData; @synthesize originalUrl = _originalUrl; -@synthesize useDesktopUserAgent = _useDesktopUserAgent; -@synthesize usedDataReductionProxy = _usedDataReductionProxy; -@synthesize index = _index; -@synthesize serializedStateObject = _serializedStateObject; -@synthesize createdFromPushState = _createdFromPushState; -@synthesize skipResubmitDataConfirmation = _skipResubmitDataConfirmation; -// Creates a new session entry. These may be nil. -- (instancetype)initWithUrl:(const GURL&)url - referrer:(const web::Referrer&)referrer - transition:(ui::PageTransition)transition - useDesktopUserAgent:(BOOL)useDesktopUserAgent - rendererInitiated:(BOOL)rendererInitiated { - self = [super init]; - if (self) { - _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); - _navigationItem.reset(new web::NavigationItemImpl()); - - _navigationItem->SetURL(url); - _navigationItem->SetReferrer(referrer); - _navigationItem->SetTransitionType(transition); - _navigationItem->set_is_renderer_initiated(rendererInitiated); - - self.originalUrl = url; - self.useDesktopUserAgent = useDesktopUserAgent; - } - return self; -} - -- (instancetype)initWithNavigationItem:(scoped_ptr<web::NavigationItem>)item - index:(int)index { +- (instancetype)initWithNavigationItem:(scoped_ptr<web::NavigationItem>)item { self = [super init]; if (self) { _propertyReleaser_CRWSessionEntry.Init(self, [CRWSessionEntry class]); _navigationItem.reset( static_cast<web::NavigationItemImpl*>(item.release())); - - self.index = index; self.originalUrl = _navigationItem->GetURL(); - self.useDesktopUserAgent = NO; } return self; } @@ -177,15 +109,13 @@ _navigationItem->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); _navigationItem->SetPageScrollState([[self class] scrollStateFromDictionary:[aDecoder decodeObjectForKey:@"state"]]); - self.index = [aDecoder decodeIntForKey:@"index"]; - self.useDesktopUserAgent = - [aDecoder decodeBoolForKey:@"useDesktopUserAgent"]; - self.usedDataReductionProxy = - [aDecoder decodeBoolForKey:@"usedDataReductionProxy"]; - [self addHTTPHeaders:[aDecoder decodeObjectForKey:@"httpHeaders"]]; - self.POSTData = [aDecoder decodeObjectForKey:@"POSTData"]; - self.skipResubmitDataConfirmation = - [aDecoder decodeBoolForKey:@"skipResubmitDataConfirmation"]; + _navigationItem->SetShouldSkipResubmitDataConfirmation( + [aDecoder decodeBoolForKey:@"skipResubmitDataConfirmation"]); + _navigationItem->SetIsOverridingUserAgent( + [aDecoder decodeBoolForKey:@"useDesktopUserAgent"]); + _navigationItem->SetPostData([aDecoder decodeObjectForKey:@"POSTData"]); + _navigationItem->AddHttpRequestHeaders( + [aDecoder decodeObjectForKey:@"httpHeaders"]); } return self; } @@ -193,7 +123,6 @@ - (void)encodeWithCoder:(NSCoder*)aCoder { // Desktop Chrome doesn't persist |url_| or |originalUrl_|, only // |virtualUrl_|. - [aCoder encodeInt:self.index forKey:@"index"]; web::nscoder_util::EncodeString(aCoder, @"virtualUrlString", _navigationItem->GetVirtualURL().spec()); web::nscoder_util::EncodeString(aCoder, @"referrerUrlString", @@ -208,13 +137,13 @@ [aCoder encodeObject:[[self class] dictionaryFromScrollState: _navigationItem->GetPageScrollState()] forKey:@"state"]; - [aCoder encodeBool:self.useDesktopUserAgent forKey:@"useDesktopUserAgent"]; - [aCoder encodeBool:self.usedDataReductionProxy - forKey:@"usedDataReductionProxy"]; - [aCoder encodeObject:self.httpHeaders forKey:@"httpHeaders"]; - [aCoder encodeObject:self.POSTData forKey:@"POSTData"]; - [aCoder encodeBool:self.skipResubmitDataConfirmation + [aCoder encodeBool:_navigationItem->ShouldSkipResubmitDataConfirmation() forKey:@"skipResubmitDataConfirmation"]; + [aCoder encodeBool:_navigationItem->IsOverridingUserAgent() + forKey:@"useDesktopUserAgent"]; + [aCoder encodeObject:_navigationItem->GetPostData() forKey:@"POSTData"]; + [aCoder encodeObject:_navigationItem->GetHttpRequestHeaders() + forKey:@"httpHeaders"]; } // TODO(ios): Shall we overwrite EqualTo:? @@ -224,13 +153,7 @@ copy->_propertyReleaser_CRWSessionEntry.Init(copy, [CRWSessionEntry class]); copy->_navigationItem.reset( new web::NavigationItemImpl(*_navigationItem.get())); - copy->_index = _index; copy->_originalUrl = _originalUrl; - copy->_useDesktopUserAgent = _useDesktopUserAgent; - copy->_usedDataReductionProxy = _usedDataReductionProxy; - copy->_POSTData = [_POSTData copy]; - copy->_httpHeaders.reset([_httpHeaders mutableCopy]); - copy->_skipResubmitDataConfirmation = _skipResubmitDataConfirmation; return copy; } @@ -238,40 +161,22 @@ return [NSString stringWithFormat: @"url:%@ originalurl:%@ title:%@ transition:%d scrollState:%@ " - @"desktopUA:%d " @"proxy:%d", + @"desktopUA:%d", base::SysUTF8ToNSString(_navigationItem->GetURL().spec()), base::SysUTF8ToNSString(self.originalUrl.spec()), base::SysUTF16ToNSString(_navigationItem->GetTitle()), _navigationItem->GetTransitionType(), [[self class] scrollStateDescription:_navigationItem->GetPageScrollState()], - _useDesktopUserAgent, _usedDataReductionProxy]; + _navigationItem->IsOverridingUserAgent()]; } - (web::NavigationItem*)navigationItem { return _navigationItem.get(); } -- (NSDictionary*)httpHeaders { - return _httpHeaders ? [NSDictionary dictionaryWithDictionary:_httpHeaders] - : nil; -} - -- (void)addHTTPHeaders:(NSDictionary*)moreHTTPHeaders { - if (_httpHeaders) - [_httpHeaders addEntriesFromDictionary:moreHTTPHeaders]; - else - _httpHeaders.reset([moreHTTPHeaders mutableCopy]); -} - -- (void)removeHTTPHeaderForKey:(NSString*)key { - [_httpHeaders removeObjectForKey:key]; - if (![_httpHeaders count]) - _httpHeaders.reset(); -} - -- (void)resetHTTPHeaders { - _httpHeaders.reset(); +- (web::NavigationItemImpl*)navigationItemImpl { + return _navigationItem.get(); } #pragma mark - Serialization helpers
diff --git a/ios/web/navigation/crw_session_entry_unittest.mm b/ios/web/navigation/crw_session_entry_unittest.mm index 210afc6..225fd81a 100644 --- a/ios/web/navigation/crw_session_entry_unittest.mm +++ b/ios/web/navigation/crw_session_entry_unittest.mm
@@ -24,11 +24,6 @@ (const web::PageScrollState&)scrollState; @end -static NSString* const kHTTPHeaderKey1 = @"key1"; -static NSString* const kHTTPHeaderKey2 = @"key2"; -static NSString* const kHTTPHeaderValue1 = @"value1"; -static NSString* const kHTTPHeaderValue2 = @"value2"; - class CRWSessionEntryTest : public PlatformTest { public: static void expectEqualSessionEntries(CRWSessionEntry* entry1, @@ -40,15 +35,13 @@ GURL url("http://init.test"); ui::PageTransition transition = ui::PAGE_TRANSITION_AUTO_BOOKMARK; - sessionEntry_.reset([[CRWSessionEntry alloc] initWithUrl:url - referrer:web::Referrer() - transition:transition - useDesktopUserAgent:NO - rendererInitiated:NO]); - [sessionEntry_ navigationItem]->SetTimestamp(base::Time::Now()); - [sessionEntry_ addHTTPHeaders:@{ kHTTPHeaderKey1 : kHTTPHeaderValue1 }]; - [sessionEntry_ - setPOSTData:[@"Test data" dataUsingEncoding:NSUTF8StringEncoding]]; + scoped_ptr<web::NavigationItemImpl> item(new web::NavigationItemImpl()); + item->SetURL(url); + item->SetTransitionType(transition); + item->SetTimestamp(base::Time::Now()); + item->SetPostData([@"Test data" dataUsingEncoding:NSUTF8StringEncoding]); + sessionEntry_.reset( + [[CRWSessionEntry alloc] initWithNavigationItem:item.Pass()]); } void TearDown() override { sessionEntry_.reset(); } @@ -78,38 +71,37 @@ CRWSessionEntry* entry1, CRWSessionEntry* entry2, ui::PageTransition transition) { - EXPECT_EQ(entry1.index, entry2.index); - web::NavigationItem* navItem1 = entry1.navigationItem; - web::NavigationItem* navItem2 = entry2.navigationItem; + web::NavigationItemImpl* navItem1 = entry1.navigationItemImpl; + web::NavigationItemImpl* navItem2 = entry2.navigationItemImpl; // url is not compared because it could differ after copy or archive. EXPECT_EQ(navItem1->GetVirtualURL(), navItem2->GetVirtualURL()); EXPECT_EQ(navItem1->GetReferrer().url, navItem2->GetReferrer().url); EXPECT_EQ(navItem1->GetTimestamp(), navItem2->GetTimestamp()); EXPECT_EQ(navItem1->GetTitle(), navItem2->GetTitle()); EXPECT_EQ(navItem1->GetPageScrollState(), navItem2->GetPageScrollState()); - EXPECT_EQ(entry1.useDesktopUserAgent, entry2.useDesktopUserAgent); - EXPECT_EQ(entry1.usedDataReductionProxy, entry2.usedDataReductionProxy); + EXPECT_EQ(navItem1->ShouldSkipResubmitDataConfirmation(), + navItem2->ShouldSkipResubmitDataConfirmation()); + EXPECT_EQ(navItem1->IsOverridingUserAgent(), + navItem2->IsOverridingUserAgent()); + EXPECT_TRUE((!navItem1->HasPostData() && !navItem2->HasPostData()) || + [navItem1->GetPostData() isEqualToData:navItem2->GetPostData()]); EXPECT_EQ(navItem2->GetTransitionType(), transition); - EXPECT_NSEQ(entry1.httpHeaders, entry2.httpHeaders); - EXPECT_TRUE((!entry1.POSTData && !entry2.POSTData) || - [entry1.POSTData isEqualToData:entry2.POSTData]); - EXPECT_EQ(entry1.skipResubmitDataConfirmation, - entry2.skipResubmitDataConfirmation); + EXPECT_NSEQ(navItem1->GetHttpRequestHeaders(), + navItem2->GetHttpRequestHeaders()); } TEST_F(CRWSessionEntryTest, Description) { [sessionEntry_ navigationItem]->SetTitle(base::SysNSStringToUTF16(@"Title")); - EXPECT_NSEQ([sessionEntry_ description], @"url:http://init.test/ " - @"originalurl:http://init.test/ " @"title:Title " @"transition:2 " - @"scrollState:{ scrollOffset:(nan, nan), zoomScaleRange:(nan, " - @"nan), zoomScale:nan } " @"desktopUA:0 " @"proxy:0"); + EXPECT_NSEQ([sessionEntry_ description], + @"url:http://init.test/ originalurl:http://init.test/ " + @"title:Title transition:2 scrollState:{ scrollOffset:(nan, " + @"nan), zoomScaleRange:(nan, nan), zoomScale:nan } desktopUA:0"); } TEST_F(CRWSessionEntryTest, InitWithCoder) { web::NavigationItem* item = [sessionEntry_ navigationItem]; item->SetVirtualURL(GURL("http://user.friendly")); item->SetTitle(base::SysNSStringToUTF16(@"Title")); - int index = sessionEntry_.get().index; // Old serialized entries have no timestamp. item->SetTimestamp(base::Time::FromInternalValue(0)); @@ -130,8 +122,6 @@ [decoder onSelector:@selector(decodeBytesForKey:returnedLength:) callBlockExpectation:block]; - [[[decoder expect] andReturnValue:OCMOCK_VALUE(index)] - decodeIntForKey:@"index"]; [[[decoder expect] andReturn:virtualUrl] decodeObjectForKey:@"virtualUrl"]; [[[decoder expect] andReturn:referrer] @@ -144,18 +134,19 @@ [CRWSessionEntry dictionaryFromScrollState:scrollState]; [[[decoder expect] andReturn:serializedScrollState] decodeObjectForKey:@"state"]; - BOOL useDesktopUserAgent = sessionEntry_.get().useDesktopUserAgent; + BOOL useDesktopUserAgent = + [sessionEntry_ navigationItem]->IsOverridingUserAgent(); [[[decoder expect] andReturnValue:OCMOCK_VALUE(useDesktopUserAgent)] decodeBoolForKey:@"useDesktopUserAgent"]; - BOOL usedDataReductionProxy = sessionEntry_.get().usedDataReductionProxy; - [[[decoder expect] andReturnValue:OCMOCK_VALUE(usedDataReductionProxy)] - decodeBoolForKey:@"usedDataReductionProxy"]; - [[[decoder expect] andReturn:sessionEntry_.get().httpHeaders] + NSDictionary* requestHeaders = + [sessionEntry_ navigationItem]->GetHttpRequestHeaders(); + [[[decoder expect] andReturn:requestHeaders] decodeObjectForKey:@"httpHeaders"]; - [[[decoder expect] andReturn:sessionEntry_.get().POSTData] + [[[decoder expect] + andReturn:[sessionEntry_ navigationItemImpl]->GetPostData()] decodeObjectForKey:@"POSTData"]; BOOL skipResubmitDataConfirmation = - sessionEntry_.get().skipResubmitDataConfirmation; + [sessionEntry_ navigationItemImpl]->ShouldSkipResubmitDataConfirmation(); [[[decoder expect] andReturnValue:OCMOCK_VALUE(skipResubmitDataConfirmation)] decodeBoolForKey:@"skipResubmitDataConfirmation"]; @@ -174,7 +165,6 @@ web::NavigationItem* item = [sessionEntry_ navigationItem]; item->SetVirtualURL(GURL("http://user.friendly")); item->SetTitle(base::SysNSStringToUTF16(@"Title")); - int index = sessionEntry_.get().index; int64 timestamp = item->GetTimestamp().ToInternalValue(); std::string virtualUrl = item->GetVirtualURL().spec(); @@ -202,8 +192,6 @@ callBlockExpectation:block]; [[[decoder stub] andReturnValue:[NSNumber numberWithBool:YES]] containsValueForKey:[OCMArg any]]; - [[[decoder expect] andReturnValue:OCMOCK_VALUE(index)] - decodeIntForKey:@"index"]; web::ReferrerPolicy expectedPolicy = item->GetReferrer().policy; [[[decoder expect] andReturnValue:OCMOCK_VALUE(expectedPolicy)] @@ -218,18 +206,18 @@ [CRWSessionEntry dictionaryFromScrollState:scrollState]; [[[decoder expect] andReturn:serializedScrollState] decodeObjectForKey:@"state"]; - BOOL useDesktopUserAgent = sessionEntry_.get().useDesktopUserAgent; + BOOL useDesktopUserAgent = + [sessionEntry_ navigationItem]->IsOverridingUserAgent(); [[[decoder expect] andReturnValue:OCMOCK_VALUE(useDesktopUserAgent)] decodeBoolForKey:@"useDesktopUserAgent"]; - BOOL usedDataReductionProxy = sessionEntry_.get().usedDataReductionProxy; - [[[decoder expect] andReturnValue:OCMOCK_VALUE(usedDataReductionProxy)] - decodeBoolForKey:@"usedDataReductionProxy"]; - [[[decoder expect] andReturn:sessionEntry_.get().httpHeaders] + NSDictionary* requestHeaders = + [sessionEntry_ navigationItem]->GetHttpRequestHeaders(); + [[[decoder expect] andReturn:requestHeaders] decodeObjectForKey:@"httpHeaders"]; - [[[decoder expect] andReturn:sessionEntry_.get().POSTData] - decodeObjectForKey:@"POSTData"]; + NSData* POSTData = [sessionEntry_ navigationItemImpl]->GetPostData(); + [[[decoder expect] andReturn:POSTData] decodeObjectForKey:@"POSTData"]; BOOL skipResubmitDataConfirmation = - sessionEntry_.get().skipResubmitDataConfirmation; + [sessionEntry_ navigationItemImpl]->ShouldSkipResubmitDataConfirmation(); [[[decoder expect] andReturnValue:OCMOCK_VALUE(skipResubmitDataConfirmation)] decodeBoolForKey:@"skipResubmitDataConfirmation"]; @@ -276,7 +264,6 @@ }; [coder onSelector:@selector(encodeBytes:length:forKey:) callBlockExpectation:block]; - [[coder expect] encodeInt:[sessionEntry_ index] forKey:@"index"]; [[coder expect] encodeInt:item->GetReferrer().policy forKey:@"referrerPolicy"]; [[coder expect] encodeInt64:item->GetTimestamp().ToInternalValue() @@ -287,14 +274,18 @@ NSDictionary* serializedScrollState = [CRWSessionEntry dictionaryFromScrollState:scrollState]; [[coder expect] encodeObject:serializedScrollState forKey:@"state"]; - [[coder expect] encodeBool:[sessionEntry_ useDesktopUserAgent] - forKey:@"useDesktopUserAgent"]; - [[coder expect] encodeBool:[sessionEntry_ usedDataReductionProxy] - forKey:@"usedDataReductionProxy"]; - [[coder expect] encodeObject:[sessionEntry_ httpHeaders] + BOOL useDesktopUserAgent = + [sessionEntry_ navigationItem]->IsOverridingUserAgent(); + [[coder expect] encodeBool:useDesktopUserAgent forKey:@"useDesktopUserAgent"]; + NSDictionary* requestHeaders = + [sessionEntry_ navigationItem]->GetHttpRequestHeaders(); + [[coder expect] encodeObject:requestHeaders forKey:@"httpHeaders"]; - [[coder expect] encodeObject:[sessionEntry_ POSTData] forKey:@"POSTData"]; - [[coder expect] encodeBool:[sessionEntry_ skipResubmitDataConfirmation] + [[coder expect] encodeObject:[sessionEntry_ navigationItemImpl]->GetPostData() + forKey:@"POSTData"]; + BOOL skipResubmitDataConfirmation = + [sessionEntry_ navigationItemImpl]->ShouldSkipResubmitDataConfirmation(); + [[coder expect] encodeBool:skipResubmitDataConfirmation forKey:@"skipResubmitDataConfirmation"]; [sessionEntry_ encodeWithCoder:coder]; EXPECT_OCMOCK_VERIFY(coder); @@ -338,63 +329,3 @@ TEST_F(CRWSessionEntryTest, EmptyDescription) { EXPECT_GT([[sessionEntry_ description] length], 0U); } - -TEST_F(CRWSessionEntryTest, CreateWithNavigationItem) { - int index = 5; // Just pick something non-zero. - GURL url("http://www.virtualurl.com"); - web::Referrer referrer(GURL("http://www.referrer.com"), - web::ReferrerPolicyDefault); - base::string16 title = base::SysNSStringToUTF16(@"Title"); - std::string state; - ui::PageTransition transition = ui::PAGE_TRANSITION_GENERATED; - - scoped_ptr<web::NavigationItem> navigation_item( - new web::NavigationItemImpl()); - navigation_item->SetURL(url); - navigation_item->SetReferrer(referrer); - navigation_item->SetTitle(title); - navigation_item->SetTransitionType(transition); - - base::scoped_nsobject<CRWSessionEntry> sessionEntry( - [[CRWSessionEntry alloc] initWithNavigationItem:navigation_item.Pass() - index:index]); - web::NavigationItem* item = [sessionEntry navigationItem]; - // Validate everything was set correctly. - EXPECT_EQ(sessionEntry.get().index, index); - // Desktop only persists the virtual url, all three fields are initialized - // by it. - EXPECT_EQ(item->GetURL(), url); - EXPECT_EQ(item->GetVirtualURL(), url); - EXPECT_EQ(sessionEntry.get().originalUrl, url); - EXPECT_EQ(item->GetReferrer().url, referrer.url); - EXPECT_EQ(item->GetTitle(), title); - EXPECT_EQ(item->GetTransitionType(), transition); -} - -TEST_F(CRWSessionEntryTest, AddHTTPHeaders) { - EXPECT_NSEQ(@{ kHTTPHeaderKey1 : kHTTPHeaderValue1 }, - [sessionEntry_ httpHeaders]); - - [sessionEntry_ addHTTPHeaders:@{ kHTTPHeaderKey1 : kHTTPHeaderValue2 }]; - EXPECT_NSEQ(@{ kHTTPHeaderKey1 : kHTTPHeaderValue2 }, - [sessionEntry_ httpHeaders]); - - [sessionEntry_ addHTTPHeaders:@{ kHTTPHeaderKey2 : kHTTPHeaderValue1 }]; - NSDictionary* expected = @{ kHTTPHeaderKey1 : kHTTPHeaderValue2, - kHTTPHeaderKey2 : kHTTPHeaderValue1 }; - EXPECT_NSEQ(expected, [sessionEntry_ httpHeaders]); -} - -TEST_F(CRWSessionEntryTest, RemoveHTTPHeaderForKey) { - NSDictionary* httpHeaders = @{ kHTTPHeaderKey1 : kHTTPHeaderValue1, - kHTTPHeaderKey2 : kHTTPHeaderValue2 }; - [sessionEntry_ addHTTPHeaders:httpHeaders]; - EXPECT_NSEQ(httpHeaders, [sessionEntry_ httpHeaders]); - - [sessionEntry_ removeHTTPHeaderForKey:kHTTPHeaderKey1]; - EXPECT_NSEQ(@{ kHTTPHeaderKey2 : kHTTPHeaderValue2 }, - [sessionEntry_ httpHeaders]); - - [sessionEntry_ removeHTTPHeaderForKey:kHTTPHeaderKey2]; - EXPECT_TRUE([sessionEntry_ httpHeaders] == nil); -}
diff --git a/ios/web/navigation/navigation_item_impl.h b/ios/web/navigation/navigation_item_impl.h index 9abd992..c0ac325 100644 --- a/ios/web/navigation/navigation_item_impl.h +++ b/ios/web/navigation/navigation_item_impl.h
@@ -6,6 +6,7 @@ #define IOS_WEB_NAVIGATION_NAVIGATION_ITEM_IMPL_H_ #include "base/basictypes.h" +#include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "ios/web/navigation/navigation_item_facade_delegate.h" @@ -15,7 +16,6 @@ #include "ios/web/public/ssl_status.h" #include "url/gurl.h" - namespace web { class NavigationItemFacadeDelegate; @@ -64,6 +64,38 @@ base::Time GetTimestamp() const override; void SetUnsafe(bool is_unsafe) override; bool IsUnsafe() const override; + void SetIsOverridingUserAgent(bool is_overriding_user_agent) override; + bool IsOverridingUserAgent() const override; + bool HasPostData() const override; + NSDictionary* GetHttpRequestHeaders() const override; + void AddHttpRequestHeaders(NSDictionary* additional_headers) override; + + // Serialized representation of the state object that was used in conjunction + // with a JavaScript window.history.pushState() or + // window.history.replaceState() call that created or modified this + // CRWSessionEntry. Intended to be used for JavaScript history operations and + // will be nil in most cases. + void SetSerializedStateObject(NSString* serialized_state_object); + NSString* GetSerializedStateObject() const; + + // Whether or not this item was created by calling history.pushState(). + void SetIsCreatedFromPushState(bool push_state); + bool IsCreatedFromPushState() const; + + // Whether or not to bypass showing the resubmit data confirmation when + // loading a POST request. Set to YES for browser-generated POST requests. + void SetShouldSkipResubmitDataConfirmation(bool skip); + bool ShouldSkipResubmitDataConfirmation() const; + + // Data submitted with a POST request, persisted for resubmits. + void SetPostData(NSData* post_data); + NSData* GetPostData() const; + + // Removes the header for |key| from |http_request_headers_|. + void RemoveHttpRequestHeaderForKey(NSString* key); + + // Removes all http headers from |http_request_headers_|. + void ResetHttpRequestHeaders(); // Once a navigation item is committed, we should no longer track // non-persisted state, as documented on the members below. @@ -88,6 +120,13 @@ FaviconStatus favicon_; SSLStatus ssl_; base::Time timestamp_; + bool is_overriding_user_agent_; + base::scoped_nsobject<NSMutableDictionary> http_request_headers_; + + base::scoped_nsobject<NSString> serialized_state_object_; + bool is_created_from_push_state_; + bool should_skip_resubmit_data_confirmation_; + base::scoped_nsobject<NSData> post_data_; // Whether the item, while loading, was created for a renderer-initiated // navigation. This dictates whether the URL should be displayed before the
diff --git a/ios/web/navigation/navigation_item_impl.mm b/ios/web/navigation/navigation_item_impl.mm index 56edd853..5609aab 100644 --- a/ios/web/navigation/navigation_item_impl.mm +++ b/ios/web/navigation/navigation_item_impl.mm
@@ -32,6 +32,9 @@ : unique_id_(GetUniqueIDInConstructor()), page_id_(-1), transition_type_(ui::PAGE_TRANSITION_LINK), + is_overriding_user_agent_(false), + is_created_from_push_state_(false), + should_skip_resubmit_data_confirmation_(false), is_renderer_initiated_(false), is_unsafe_(false), facade_delegate_(nullptr) { @@ -52,6 +55,13 @@ favicon_(item.favicon_), ssl_(item.ssl_), timestamp_(item.timestamp_), + is_overriding_user_agent_(item.is_overriding_user_agent_), + http_request_headers_([item.http_request_headers_ copy]), + serialized_state_object_([item.serialized_state_object_ copy]), + is_created_from_push_state_(item.is_created_from_push_state_), + should_skip_resubmit_data_confirmation_( + item.should_skip_resubmit_data_confirmation_), + post_data_([item.post_data_ copy]), is_renderer_initiated_(item.is_renderer_initiated_), is_unsafe_(item.is_unsafe_), cached_display_title_(item.cached_display_title_), @@ -187,12 +197,6 @@ return timestamp_; } -void NavigationItemImpl::ResetForCommit() { - // Any state that only matters when a navigation item is pending should be - // cleared here. - set_is_renderer_initiated(false); -} - void NavigationItemImpl::SetUnsafe(bool is_unsafe) { is_unsafe_ = is_unsafe; } @@ -201,4 +205,82 @@ return is_unsafe_; } +void NavigationItemImpl::SetIsOverridingUserAgent( + bool is_overriding_user_agent) { + is_overriding_user_agent_ = is_overriding_user_agent; +} + +bool NavigationItemImpl::IsOverridingUserAgent() const { + return is_overriding_user_agent_; +} + +bool NavigationItemImpl::HasPostData() const { + return post_data_.get() != nil; +} + +NSDictionary* NavigationItemImpl::GetHttpRequestHeaders() const { + return [[http_request_headers_ copy] autorelease]; +} + +void NavigationItemImpl::AddHttpRequestHeaders( + NSDictionary* additional_headers) { + if (!additional_headers) + return; + + if (http_request_headers_) + [http_request_headers_ addEntriesFromDictionary:additional_headers]; + else + http_request_headers_.reset([additional_headers mutableCopy]); +} + +void NavigationItemImpl::SetSerializedStateObject( + NSString* serialized_state_object) { + serialized_state_object_.reset([serialized_state_object retain]); +} + +NSString* NavigationItemImpl::GetSerializedStateObject() const { + return serialized_state_object_.get(); +} + +void NavigationItemImpl::SetIsCreatedFromPushState(bool push_state) { + is_created_from_push_state_ = push_state; +} + +bool NavigationItemImpl::IsCreatedFromPushState() const { + return is_created_from_push_state_; +} + +void NavigationItemImpl::SetShouldSkipResubmitDataConfirmation(bool skip) { + should_skip_resubmit_data_confirmation_ = skip; +} + +bool NavigationItemImpl::ShouldSkipResubmitDataConfirmation() const { + return should_skip_resubmit_data_confirmation_; +} + +void NavigationItemImpl::SetPostData(NSData* post_data) { + post_data_.reset([post_data retain]); +} + +NSData* NavigationItemImpl::GetPostData() const { + return post_data_.get(); +} + +void NavigationItemImpl::RemoveHttpRequestHeaderForKey(NSString* key) { + DCHECK(key); + [http_request_headers_ removeObjectForKey:key]; + if (![http_request_headers_ count]) + http_request_headers_.reset(); +} + +void NavigationItemImpl::ResetHttpRequestHeaders() { + http_request_headers_.reset(); +} + +void NavigationItemImpl::ResetForCommit() { + // Any state that only matters when a navigation item is pending should be + // cleared here. + set_is_renderer_initiated(false); +} + } // namespace web
diff --git a/ios/web/navigation/navigation_item_impl_unittest.mm b/ios/web/navigation/navigation_item_impl_unittest.mm index a326b5c..0189ea0 100644 --- a/ios/web/navigation/navigation_item_impl_unittest.mm +++ b/ios/web/navigation/navigation_item_impl_unittest.mm
@@ -5,6 +5,7 @@ #include "base/logging.h" #include "base/mac/scoped_nsobject.h" #include "base/memory/scoped_ptr.h" +#include "base/strings/sys_string_conversions.h" #include "ios/web/navigation/navigation_item_impl.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" @@ -13,10 +14,23 @@ namespace web { namespace { +static NSString* const kHTTPHeaderKey1 = @"key1"; +static NSString* const kHTTPHeaderKey2 = @"key2"; +static NSString* const kHTTPHeaderValue1 = @"value1"; +static NSString* const kHTTPHeaderValue2 = @"value2"; + class NavigationItemTest : public PlatformTest { protected: - void SetUp() override { item_.reset(new NavigationItemImpl()); } + void SetUp() override { + item_.reset(new web::NavigationItemImpl()); + item_->SetURL(GURL("http://init.test")); + item_->SetTransitionType(ui::PAGE_TRANSITION_AUTO_BOOKMARK); + item_->SetTimestamp(base::Time::Now()); + item_->AddHttpRequestHeaders(@{kHTTPHeaderKey1 : kHTTPHeaderValue1}); + item_->SetPostData([@"Test data" dataUsingEncoding:NSUTF8StringEncoding]); + } + // The NavigationItemImpl instance being tested. scoped_ptr<NavigationItemImpl> item_; }; @@ -27,5 +41,71 @@ EXPECT_TRUE(item_->GetURL().is_valid()); } +// Tests that copied NavigationItemImpls create copies of data members that are +// objects. +TEST_F(NavigationItemTest, Copy) { + // Create objects to be copied. + NSString* postData0 = @"postData0"; + NSMutableData* mutablePostData = + [[postData0 dataUsingEncoding:NSUTF8StringEncoding] mutableCopy]; + item_->SetPostData(mutablePostData); + NSString* state0 = @"state0"; + NSMutableString* mutableState = [state0 mutableCopy]; + item_->SetSerializedStateObject(mutableState); + + // Create copy. + web::NavigationItemImpl copy(*item_.get()); + + // Modify the objects. + NSString* postData1 = @"postData1"; + [mutablePostData setData:[postData1 dataUsingEncoding:NSUTF8StringEncoding]]; + NSString* state1 = @"state1"; + [mutableState setString:state1]; + + // Check that changes occurred in |item_|, but not in |copy|. + EXPECT_NSEQ([postData1 dataUsingEncoding:NSUTF8StringEncoding], + item_->GetPostData()); + EXPECT_NSEQ(state1, item_->GetSerializedStateObject()); + EXPECT_NSEQ([postData0 dataUsingEncoding:NSUTF8StringEncoding], + copy.GetPostData()); + EXPECT_NSEQ(state0, copy.GetSerializedStateObject()); +} + +// Tests whether |NavigationItem::AddHttpRequestHeaders()| adds the passed +// headers to the item's request http headers. +TEST_F(NavigationItemTest, AddHttpRequestHeaders) { + EXPECT_NSEQ(@{kHTTPHeaderKey1 : kHTTPHeaderValue1}, + item_->GetHttpRequestHeaders()); + + item_->AddHttpRequestHeaders(@{kHTTPHeaderKey1 : kHTTPHeaderValue2}); + EXPECT_NSEQ(@{kHTTPHeaderKey1 : kHTTPHeaderValue2}, + item_->GetHttpRequestHeaders()); + + item_->AddHttpRequestHeaders(@{kHTTPHeaderKey2 : kHTTPHeaderValue1}); + NSDictionary* expected = @{ + kHTTPHeaderKey1 : kHTTPHeaderValue2, + kHTTPHeaderKey2 : kHTTPHeaderValue1 + }; + EXPECT_NSEQ(expected, item_->GetHttpRequestHeaders()); +} + +// Tests whether |NavigationItem::AddHttpRequestHeaders()| removes the header +// value associated with the passed key from the item's request http headers. +TEST_F(NavigationItemTest, RemoveHttpRequestHeaderForKey) { + NSDictionary* httpHeaders = @{ + kHTTPHeaderKey1 : kHTTPHeaderValue1, + kHTTPHeaderKey2 : kHTTPHeaderValue2 + }; + item_->AddHttpRequestHeaders(httpHeaders); + EXPECT_NSEQ(httpHeaders, item_->GetHttpRequestHeaders()); + + item_->RemoveHttpRequestHeaderForKey(kHTTPHeaderKey1); + EXPECT_NSEQ(@{kHTTPHeaderKey2 : kHTTPHeaderValue2}, + item_->GetHttpRequestHeaders()); + + item_->RemoveHttpRequestHeaderForKey(kHTTPHeaderKey2); + EXPECT_FALSE(item_->GetHttpRequestHeaders()); +} + } // namespace } // namespace web
diff --git a/ios/web/public/navigation_item.h b/ios/web/public/navigation_item.h index e067a82e..37d4e06b 100644 --- a/ios/web/public/navigation_item.h +++ b/ios/web/public/navigation_item.h
@@ -13,6 +13,12 @@ class GURL; +#if defined(__OBJC__) +@class NSDictionary; +#else +class NSDictionary; +#endif // __OBJC__ + namespace web { struct FaviconStatus; struct Referrer; @@ -114,6 +120,21 @@ // property doesn't get serialized. virtual void SetUnsafe(bool is_unsafe) = 0; virtual bool IsUnsafe() const = 0; + + // |true| if this item uses a desktop user agent in HTTP requests and + // UIWebView. + virtual void SetIsOverridingUserAgent(bool is_overriding_user_agent) = 0; + virtual bool IsOverridingUserAgent() const = 0; + + // |true| if this item is the result of a POST request with data. + virtual bool HasPostData() const = 0; + + // Returns the item's current http request headers. + virtual NSDictionary* GetHttpRequestHeaders() const = 0; + + // Adds headers from |additional_headers| to the item's http request headers. + // Existing headers with the same key will be overridden. + virtual void AddHttpRequestHeaders(NSDictionary* additional_headers) = 0; }; } // namespace web
diff --git a/ios/web/public/referrer_util.cc b/ios/web/public/referrer_util.cc index 579ca1b2..7ab2ef1 100644 --- a/ios/web/public/referrer_util.cc +++ b/ios/web/public/referrer_util.cc
@@ -23,8 +23,8 @@ const GURL& destination, const web::Referrer& referrer) { std::string referrer_value; - bool leaving_secure_scheme = - referrer.url.SchemeIsSecure() && !destination.SchemeIsSecure(); + bool leaving_secure_scheme = referrer.url.SchemeIsCryptographic() && + !destination.SchemeIsCryptographic(); if (referrer.policy == ReferrerPolicyAlways || (referrer.policy == ReferrerPolicyDefault && !leaving_secure_scheme)) { if (referrer.url.is_valid())
diff --git a/ios/web/public/test/DEPS b/ios/web/public/test/DEPS new file mode 100644 index 0000000..822e736 --- /dev/null +++ b/ios/web/public/test/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ios/third_party/gcdwebserver", +]
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 ca987a6..692dd96d 100644 --- a/ios/web/public/test/crw_test_js_injection_receiver.mm +++ b/ios/web/public/test/crw_test_js_injection_receiver.mm
@@ -46,6 +46,8 @@ - (void)injectScript:(NSString*)script forClass:(Class)jsInjectionManagerClass { + // Web layer guarantees that __gCrWeb object is always injected first. + [_webView stringByEvaluatingJavaScriptFromString:@"window.__gCrWeb = {};"]; [_webView stringByEvaluatingJavaScriptFromString:script]; }
diff --git a/ios/web/public/test/http_server.h b/ios/web/public/test/http_server.h new file mode 100644 index 0000000..cacc5f1e --- /dev/null +++ b/ios/web/public/test/http_server.h
@@ -0,0 +1,133 @@ +// 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 IOS_WEB_PUBLIC_TEST_HTTP_SERVER_H_ +#define IOS_WEB_PUBLIC_TEST_HTTP_SERVER_H_ + +#include <vector> + +#import "base/mac/scoped_nsobject.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/synchronization/lock.h" +#include "ios/web/public/test/response_providers/response_provider.h" + +@class GCDWebServer; + +namespace web { +namespace test { + +// A convience class for wrapping a ResponseProvider so that it can be used +// inside data structures that operate on ref counted objects. This class is a +// ref counted container for a ResponseProvider. +// This object exists for legacy reasons since a large part of the code base +// still uses ResponseProviders that are not ref counted. +class RefCountedResponseProviderWrapper : + public base::RefCounted<RefCountedResponseProviderWrapper> { + public: + // Main constructor. + explicit RefCountedResponseProviderWrapper( + ResponseProvider* response_provider); + // Returns the ResponseProvider that backs this object. + ResponseProvider* GetResponseProvider() { return response_provider_.get(); } + private: + friend class base::RefCounted<RefCountedResponseProviderWrapper>; + // The ResponseProvider that backs this object. + scoped_ptr<ResponseProvider> response_provider_; + virtual ~RefCountedResponseProviderWrapper(); +}; + +// The HttpServer is an in-process web server that is used to service requests. +// It is a singleton and backed by a GCDWebServer. +// HttpServer can be configured to serve requests by registering +// web::ResponseProviders. +// This class is not thread safe on the whole and only certain methods are +// thread safe. +class HttpServer { + public: + typedef ScopedVector<ResponseProvider> ProviderList; + + // Returns the shared HttpServer instance. Thread safe. + static HttpServer& GetSharedInstance(); + // Returns the shared HttpServer instance and registers the response providers + // as well. Takes ownership of the response providers. Must be called from the + // main thread. + static HttpServer& GetSharedInstanceWithResponseProviders( + const ProviderList& response_providers); + + // A convenience method for the longer form of + // |web::test::HttpServer::GetSharedInstance().MakeUrlForHttpServer| + static GURL MakeUrl(const std::string& url); + + // Starts the server on the default port 8080. CHECKs if the server can not be + // started. + // Must be called from the main thread. + void StartOrDie(); + // Starts the server on |port|. Returns true on success, false otherwise. + // Must be called from the main thread. + bool StartOnPort(NSUInteger port); + // Stops the server and prevents it from accepting new requests. + // Must be called from the main thread. + void Stop(); + // Returns true if the server is running. + // Must be called from the main thread. + bool IsRunning() const; + + // Adds a ResponseProvider. Takes ownership of the ResponseProvider. + // Note for using URLs inside of the |response_provider|: + // The HttpServer cannot run on default HTTP port 80, so URLs used in + // ResponseProviders must be converted at runtime after the HttpServer's port + // is determined. Please use |MakeUrl| to handle converting URLs. + // Must be called from the main thread. + void AddResponseProvider(ResponseProvider* response_provider); + // Removes the |response_provider|. Must be called from the main thread. + void RemoveResponseProvider(ResponseProvider* response_provider); + // Removes all the response providers. Must be called from the main thread. + void RemoveAllResponseProviders(); + + private: + // Initializes the server by registering for a GCDWebServer servlet. Must be + // called from the main thread. + void InitHttpServer(); + HttpServer(); + ~HttpServer(); + + // Sets the port that the server is running on. Thread Safe + void SetPort(NSUInteger port); + // Returns the port that the server is running on. Thread Safe + NSUInteger GetPort() const; + + // Creates a GURL that the server can service based on the |url| + // passed in. + // It does not rewrite URLs if the |url| can already be serviced by the + // server. + // |url| must be a valid URL. Thread safe. + GURL MakeUrlForHttpServer(const std::string& url) const; + + // Returns the response provider that can handle the |request|. + // Note: No more than one reponse provider can handle the request. + // Thread safe. + scoped_refptr<RefCountedResponseProviderWrapper> + GetResponseProviderForRequest( + const web::ResponseProvider::Request& request); + + // Lock for serializing access to |provider_|. + mutable base::Lock provider_list_lock_; + // Lock for serializing access to |port_|. + mutable base::Lock port_lock_; + // The port that the server is running on. 0 if the server is not running. + NSUInteger port_; + // The GCDWebServer backing the HttpServer. + base::scoped_nsobject<GCDWebServer> gcd_web_server_; + // The list of providers to service a request. + std::vector<scoped_refptr<RefCountedResponseProviderWrapper>> providers_; + DISALLOW_COPY_AND_ASSIGN(HttpServer); +}; + +} // namespace test +} // namspace web + +#endif // IOS_WEB_PUBLIC_TEST_HTTP_SERVER_H_ +
diff --git a/ios/web/public/test/http_server.mm b/ios/web/public/test/http_server.mm new file mode 100644 index 0000000..fe16b98 --- /dev/null +++ b/ios/web/public/test/http_server.mm
@@ -0,0 +1,236 @@ +// 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. + +#import "ios/web/public/test/http_server.h" + +#import <Foundation/Foundation.h> + +#include <string> + +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/sys_string_conversions.h" +#import "net/base/mac/url_conversions.h" +#import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServer.h" +#import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServerRequest.h" +#import "ios/third_party/gcdwebserver/src/GCDWebServer/Core/GCDWebServerResponse.h" +#include "url/gurl.h" + +namespace { + +// The default port on which the GCDWebServer is brought up on. +const NSUInteger kDefaultPort = 8080; + +// Converts a GCDWebServerRequest (received from the GCDWebServer servlet) to +// a request object that the ResponseProvider expects. +web::ResponseProvider::Request ResponseProviderRequestFromGCDWebServerRequest( + GCDWebServerRequest* request) { + GURL url(net::GURLWithNSURL(request.URL)); + std::string method(base::SysNSStringToUTF8(request.method)); + // TODO(shreyasv): It is not trivial to extract the body from a + // |GCDWebServerRequest|, add logic to do so. crbug.com/435340. + std::string body; + __block net::HttpRequestHeaders headers; + [[request headers] enumerateKeysAndObjectsUsingBlock:^(NSString* header_key, + NSString* header_value, + BOOL*) { + headers.SetHeader(base::SysNSStringToUTF8(header_key), + base::SysNSStringToUTF8(header_value)); + }]; + return web::ResponseProvider::Request(url, method, body, headers); +} + +} // namespace + +namespace web { +namespace test { + + +RefCountedResponseProviderWrapper::RefCountedResponseProviderWrapper( + ResponseProvider* response_provider) { + response_provider_.reset(response_provider); +} + +RefCountedResponseProviderWrapper::~RefCountedResponseProviderWrapper() {} + +// static +HttpServer& HttpServer::GetSharedInstance() { + static web::test::HttpServer* shared_instance = nullptr; + static dispatch_once_t once; + dispatch_once(&once, ^{ + shared_instance = new HttpServer(); + }); + return *shared_instance; +} + +// static +HttpServer& HttpServer::GetSharedInstanceWithResponseProviders( + const ProviderList& response_providers) { + DCHECK([NSThread isMainThread]); + HttpServer& server = HttpServer::GetSharedInstance(); + for (const auto& response_provider : response_providers) { + server.AddResponseProvider(response_provider); + } + return server; +} + +void HttpServer::InitHttpServer() { + DCHECK(gcd_web_server_); + // Note: This block is called from an arbitrary GCD thread. + id process_request = ^GCDWebServerResponse*(GCDWebServerRequest* request) { + ResponseProvider::Request provider_request = + ResponseProviderRequestFromGCDWebServerRequest(request); + scoped_refptr<RefCountedResponseProviderWrapper> + ref_counted_response_provider = GetResponseProviderForRequest( + provider_request); + + if (!ref_counted_response_provider) { + return [GCDWebServerResponse response]; + } + ResponseProvider* response_provider = + ref_counted_response_provider->GetResponseProvider(); + if (!response_provider) { + return [GCDWebServerResponse response]; + } + + return response_provider->GetGCDWebServerResponse(provider_request); + }; + [gcd_web_server_ removeAllHandlers]; + // Register a servlet for all HTTP GET, POST methods. + [gcd_web_server_ addDefaultHandlerForMethod:@"GET" + requestClass:[GCDWebServerRequest class] + processBlock:process_request]; + [gcd_web_server_ addDefaultHandlerForMethod:@"POST" + requestClass:[GCDWebServerRequest class] + processBlock:process_request]; +} + +HttpServer::HttpServer() : port_(0) { + gcd_web_server_.reset([[GCDWebServer alloc] init]); + InitHttpServer(); +} + +HttpServer::~HttpServer() { +} + +bool HttpServer::StartOnPort(NSUInteger port) { + DCHECK([NSThread isMainThread]); + DCHECK(!IsRunning()) << "The server is already running." + << " Please stop it before starting it again."; + BOOL success = [gcd_web_server_ startWithPort:port bonjourName:@""]; + if (success) { + SetPort(port); + } + return success; +} + +void HttpServer::StartOrDie() { + DCHECK([NSThread isMainThread]); + StartOnPort(kDefaultPort); + CHECK(IsRunning()); +} + +void HttpServer::Stop() { + DCHECK([NSThread isMainThread]); + DCHECK(IsRunning()) << "Cannot stop an already stopped server."; + RemoveAllResponseProviders(); + [gcd_web_server_ stop]; + SetPort(0); +} + +bool HttpServer::IsRunning() const { + DCHECK([NSThread isMainThread]); + return [gcd_web_server_ isRunning]; +} + +// static +GURL HttpServer::MakeUrl(const std::string &url) { + return HttpServer::GetSharedInstance().MakeUrlForHttpServer(url); +} + +GURL HttpServer::MakeUrlForHttpServer(const std::string& url) const { + GURL result(url); + DCHECK(result.is_valid()); + const std::string kLocalhostHost = std::string("localhost"); + if (result.port() == base::IntToString(GetPort()) && + result.host() == kLocalhostHost) { + return result; + } + + GURL::Replacements replacements; + replacements.SetHostStr(kLocalhostHost); + + const std::string port = std::string( + base::IntToString(static_cast<int>(GetPort()))); + replacements.SetPortStr(port); + + // It is necessary to prepend the host of the input URL so that URLs such + // as http://origin/foo, http://destination/foo can be disamgiguated. + const std::string new_path = std::string(result.host() + result.path()); + replacements.SetPathStr(new_path); + + return result.ReplaceComponents(replacements); +} + +scoped_refptr<RefCountedResponseProviderWrapper> + HttpServer::GetResponseProviderForRequest( + const web::ResponseProvider::Request& request) { + base::AutoLock autolock(provider_list_lock_); + scoped_refptr<RefCountedResponseProviderWrapper> result; + for (const auto& ref_counted_response_provider : providers_) { + ResponseProvider* response_provider = + ref_counted_response_provider.get()->GetResponseProvider(); + if (response_provider->CanHandleRequest(request)) { + DCHECK(!result) << + "No more than one response provider can handle the same request."; + result = ref_counted_response_provider; + } + } + return result; +} + +void HttpServer::AddResponseProvider(ResponseProvider* response_provider) { + DCHECK([NSThread isMainThread]); + DCHECK(IsRunning()) << "Can add a response provider only when the server is " + << "running."; + base::AutoLock autolock(provider_list_lock_); + scoped_refptr<RefCountedResponseProviderWrapper> + ref_counted_response_provider( + new RefCountedResponseProviderWrapper(response_provider)); + providers_.push_back(ref_counted_response_provider); +} + +void HttpServer::RemoveResponseProvider(ResponseProvider* response_provider) { + DCHECK([NSThread isMainThread]); + base::AutoLock autolock(provider_list_lock_); + auto found_iter = providers_.end(); + for (auto it = providers_.begin(); it != providers_.end(); ++it) { + if ((*it)->GetResponseProvider() == response_provider) { + found_iter = it; + break; + } + } + if (found_iter != providers_.end()) { + providers_.erase(found_iter); + } +} + +void HttpServer::RemoveAllResponseProviders() { + DCHECK([NSThread isMainThread]); + base::AutoLock autolock(provider_list_lock_); + providers_.clear(); +} + +void HttpServer::SetPort(NSUInteger port) { + base::AutoLock autolock(port_lock_); + port_ = port; +} + +NSUInteger HttpServer::GetPort() const { + base::AutoLock autolock(port_lock_); + return port_; +} + +} // namespace test +} // namespace web
diff --git a/ios/web/public/test/http_server_unittest.mm b/ios/web/public/test/http_server_unittest.mm new file mode 100644 index 0000000..941417b --- /dev/null +++ b/ios/web/public/test/http_server_unittest.mm
@@ -0,0 +1,74 @@ +// 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. + +#import "ios/web/public/test/http_server.h" + +#import <Foundation/Foundation.h> + +#include <string> + +#import "base/mac/scoped_nsobject.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/sys_string_conversions.h" +#import "base/test/ios/wait_util.h" +#include "ios/web/public/test/response_providers/data_response_provider.h" +#include "net/http/http_response_headers.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" + +namespace { + +// A response provider that returns a simple string for all requests. Used for +// testing purposes. +class TestResponseProvider : public web::DataResponseProvider { + public: + bool CanHandleRequest(const Request& request) override { + return true; + } + + void GetResponseHeadersAndBody( + const Request& request, + scoped_refptr<net::HttpResponseHeaders>* headers, + std::string* response_body) override { + *headers = GetDefaultResponseHeaders(); + *response_body = response_body_; + } + // The string that is returned in the response body. + std::string response_body_; +}; + +} // namespace + +// Tests that a web::test::HttpServer can be started and can send and receive +// requests and response from |TestResponseProvider| +TEST(HTTPServer, StartAndInterfaceWithResponseProvider) { + scoped_ptr<TestResponseProvider> provider(new TestResponseProvider()); + const std::string kHelloWorld = "Hello World"; + provider->response_body_ = kHelloWorld; + web::test::HttpServer& server = web::test::HttpServer::GetSharedInstance(); + const NSUInteger kPort = 8080; + server.StartOnPort(kPort); + EXPECT_TRUE(server.IsRunning()); + server.AddResponseProvider(provider.release()); + + NSString* url = + [NSString stringWithFormat:@"http://localhost:%@/samp", @(kPort)]; + __block base::scoped_nsobject<NSString> evaluation_result; + id completion_handler = + ^(NSData* data, NSURLResponse* response, NSError* error) { + evaluation_result.reset([[NSString alloc] + initWithData:data encoding:NSUTF8StringEncoding]); + }; + NSURLSessionDataTask* data_task = + [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:url] + completionHandler:completion_handler]; + [data_task resume]; + base::test::ios::WaitUntilCondition(^bool() { + return evaluation_result; + }); + EXPECT_NSEQ(evaluation_result, base::SysUTF8ToNSString(kHelloWorld)); + server.Stop(); + EXPECT_FALSE(server.IsRunning()); +}
diff --git a/ios/web/public/test/js_test_util.h b/ios/web/public/test/js_test_util.h index 7dd4607e..cd16af1 100644 --- a/ios/web/public/test/js_test_util.h +++ b/ios/web/public/test/js_test_util.h
@@ -5,17 +5,28 @@ #ifndef IOS_WEB_PUBLIC_TEST_JS_TEST_UTIL_H_ #define IOS_WEB_PUBLIC_TEST_JS_TEST_UTIL_H_ +#import <UIKit/UIKit.h> +#import <WebKit/WebKit.h> + @class CRWJSInjectionManager; @class CRWJSInjectionReceiver; -@class NSString; namespace web { + // Evaluates JavaScript on the |manager| and returns the result as a string. NSString* EvaluateJavaScriptAsString(CRWJSInjectionManager* manager, NSString* script); + // Evaluates JavaScript on the |receiver| and returns the result as a string. NSString* EvaluateJavaScriptAsString(CRWJSInjectionReceiver* receiver, NSString* script); + +// Evaluates JavaScript on |web_view| and returns the result as a string. +NSString* EvaluateJavaScriptAsString(UIWebView* web_view, NSString* script); + +// Evaluates JavaScript on |web_view| and returns the result as an id. +id EvaluateJavaScript(WKWebView* web_view, NSString* script); + } // namespace web #endif // IOS_WEB_PUBLIC_TEST_JS_TEST_UTIL_H_
diff --git a/ios/web/public/test/js_test_util.mm b/ios/web/public/test/js_test_util.mm index 74b0298..0e80f29 100644 --- a/ios/web/public/test/js_test_util.mm +++ b/ios/web/public/test/js_test_util.mm
@@ -4,11 +4,13 @@ #import "ios/web/public/test/js_test_util.h" -#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> +#import <WebKit/WebKit.h> #import "base/logging.h" #import "base/mac/scoped_nsobject.h" #import "base/time/time.h" +#import "base/test/ios/wait_util.h" #import "ios/web/public/web_state/js/crw_js_injection_manager.h" #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" @@ -52,4 +54,22 @@ return EvaluateJavaScriptAsString(manager, script); } +NSString* EvaluateJavaScriptAsString(UIWebView* web_view, NSString* script) { + return [web_view stringByEvaluatingJavaScriptFromString:script]; +} + +id EvaluateJavaScript(WKWebView* web_view, NSString* script) { + __block base::scoped_nsobject<id> result; + [web_view evaluateJavaScript:script + completionHandler:^(id evaluationResult, NSError* error) { + DCHECK(!error); + result.reset([evaluationResult copy]); + }]; + base::test::ios::WaitUntilCondition(^bool() { + return result; + }); + return [[result retain] autorelease]; +} + } // namespace web +
diff --git a/ios/web/public/test/response_providers/data_response_provider.h b/ios/web/public/test/response_providers/data_response_provider.h new file mode 100644 index 0000000..3ae5fae --- /dev/null +++ b/ios/web/public/test/response_providers/data_response_provider.h
@@ -0,0 +1,39 @@ +// 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_PUBLIC_TEST_RESPONSE_PROVIDERS_DATA_RESPONSE_PROVIDER_H_ +#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_DATA_RESPONSE_PROVIDER_H_ + +#include <string> + +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" +#include "ios/web/public/test/response_providers/response_provider.h" +#include "net/http/http_response_headers.h" + +namespace web { + +// An abstract ResponseProvider that returns a GCDWebServerDataResponse for a +// request. This class encapsulates the logic to convert the response headers +// and body received from |GetResponseHeadersAndBody| into a +// GCDWebServerDataResponse. +class DataResponseProvider : public ResponseProvider { + public: + // ResponseProvider implementation. + GCDWebServerResponse* GetGCDWebServerResponse(const Request& request) final; + + // Returns the headers and the response body. Will only be called if the + // provider can handle the request. + // Note: This should actually be under protected but since this is used by + // an adapter in order to work with the old MockHttpServer it is under + // public. + virtual void GetResponseHeadersAndBody( + const Request& request, + scoped_refptr<net::HttpResponseHeaders>* headers, + std::string* response_body) = 0; +}; + +} // namespace web + +#endif // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_DATA_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/data_response_provider.mm b/ios/web/public/test/response_providers/data_response_provider.mm new file mode 100644 index 0000000..ae04b8f2 --- /dev/null +++ b/ios/web/public/test/response_providers/data_response_provider.mm
@@ -0,0 +1,36 @@ +// 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 "ios/web/public/test/response_providers/data_response_provider.h" + +#include "base/strings/sys_string_conversions.h" +#import "ios/third_party/gcdwebserver/src/GCDWebServer/Responses/GCDWebServerDataResponse.h" + +namespace web { + +GCDWebServerResponse* DataResponseProvider::GetGCDWebServerResponse( + const Request& request) { + std::string response_body; + scoped_refptr<net::HttpResponseHeaders> response_headers; + GetResponseHeadersAndBody(request, &response_headers, &response_body); + GCDWebServerDataResponse* data_response = [GCDWebServerDataResponse + responseWithHTML:base::SysUTF8ToNSString(response_body)]; + data_response.statusCode = response_headers->response_code(); + void* iter = nullptr; + std::string name; + std::string value; + while (response_headers->EnumerateHeaderLines(&iter, &name, &value)) { + // TODO(shreyasv): Extract out other names that can't be set by using the + // |setValue:forAdditionalHeader:| API such as "ETag" etc. crbug.com/435350 + if (name == "Content-type") { + data_response.contentType = base::SysUTF8ToNSString(value); + continue; + } + [data_response setValue:base::SysUTF8ToNSString(value) + forAdditionalHeader:base::SysUTF8ToNSString(name)]; + } + return data_response; +} + +} // namespace web
diff --git a/ios/web/public/test/response_providers/file_based_response_provider.h b/ios/web/public/test/response_providers/file_based_response_provider.h new file mode 100644 index 0000000..5578e719 --- /dev/null +++ b/ios/web/public/test/response_providers/file_based_response_provider.h
@@ -0,0 +1,36 @@ +// 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_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_H_ +#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_H_ + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "ios/web/public/test/response_providers/file_based_response_provider_impl.h" +#include "ios/web/public/test/response_providers/response_provider.h" + +namespace base { +class FilePath; +} + +namespace web { + +// FileBasedResponseProvider tries to resolve URL as if it were a path relative +// to |path| on the filesystem. +class FileBasedResponseProvider : public ResponseProvider { + public: + explicit FileBasedResponseProvider(const base::FilePath& path); + ~FileBasedResponseProvider() override; + + // web::ReponseProvider implementation. + bool CanHandleRequest(const Request& request) override; + GCDWebServerResponse* GetGCDWebServerResponse( + const Request& request) override; + + private: + scoped_ptr<FileBasedResponseProviderImpl> response_provider_impl_; +}; +} + +#endif // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/response_providers/file_based_response_provider.mm b/ios/web/public/test/response_providers/file_based_response_provider.mm new file mode 100644 index 0000000..4c9fa178 --- /dev/null +++ b/ios/web/public/test/response_providers/file_based_response_provider.mm
@@ -0,0 +1,32 @@ +// 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 "ios/web/public/test/response_providers/file_based_response_provider.h" + +#include "base/files/file_path.h" +#include "base/strings/sys_string_conversions.h" +#import "ios/third_party/gcdwebserver/src/GCDWebServer/Responses/GCDWebServerFileResponse.h" + +namespace web { + +FileBasedResponseProvider::FileBasedResponseProvider(const base::FilePath& path) + : response_provider_impl_(new FileBasedResponseProviderImpl(path)) { +} + +FileBasedResponseProvider::~FileBasedResponseProvider() { +} + +bool FileBasedResponseProvider::CanHandleRequest(const Request& request) { + return response_provider_impl_->CanHandleRequest(request); +} + +GCDWebServerResponse* FileBasedResponseProvider::GetGCDWebServerResponse( + const Request& request) { + const base::FilePath file_path = + response_provider_impl_->BuildTargetPath(request.url); + NSString* path = base::SysUTF8ToNSString(file_path.value()); + return [GCDWebServerFileResponse responseWithFile:path]; +} + +} // namespace web
diff --git a/ios/web/public/test/response_providers/file_based_response_provider_impl.cc b/ios/web/public/test/response_providers/file_based_response_provider_impl.cc new file mode 100644 index 0000000..bb1b4c1 --- /dev/null +++ b/ios/web/public/test/response_providers/file_based_response_provider_impl.cc
@@ -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. + +#include "ios/web/public/test/response_providers/file_based_response_provider_impl.h" + +#include "base/files/file_util.h" +#include "ios/web/public/test/response_providers/response_provider.h" +#include "url/gurl.h" + +namespace web { + +FileBasedResponseProviderImpl::FileBasedResponseProviderImpl( + const base::FilePath& path) + : path_(path) { +} + +FileBasedResponseProviderImpl::~FileBasedResponseProviderImpl() { +} + +bool FileBasedResponseProviderImpl::CanHandleRequest( + const ResponseProvider::Request& request) { + return base::PathExists(BuildTargetPath(request.url)); +} + +base::FilePath FileBasedResponseProviderImpl::BuildTargetPath(const GURL& url) { + base::FilePath result = path_; + const std::string kLocalhostHost = "localhost"; + if (url.host() != kLocalhostHost) { + result = result.Append(url.host()); + } + std::string url_path = url.path(); + // Remove the leading slash in url path. + if (url_path.length() > 0 && url_path[0] == '/') { + url_path.erase(0, 1); + } + if (!url_path.empty()) + result = result.Append(url_path); + return result; +} + +} // namespace web
diff --git a/ios/web/public/test/response_providers/file_based_response_provider_impl.h b/ios/web/public/test/response_providers/file_based_response_provider_impl.h new file mode 100644 index 0000000..95853653 --- /dev/null +++ b/ios/web/public/test/response_providers/file_based_response_provider_impl.h
@@ -0,0 +1,36 @@ +// 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_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_ +#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_ + +#include "base/files/file_path.h" +#include "ios/web/public/test/response_providers/response_provider.h" + +class GURL; + +namespace web { + +// FileBasedMockResponseProvider tries to resolve URL as if it were a path +// relative to |path| on the filesystem. Use |BuildTargetPath| to resolve URLs +// to paths on the filesystem. +class FileBasedResponseProviderImpl { + public: + explicit FileBasedResponseProviderImpl(const base::FilePath& path); + virtual ~FileBasedResponseProviderImpl(); + + // Returns true if the request's URL when converted to a path on the app + // bundle has a file present. + bool CanHandleRequest(const ResponseProvider::Request& request); + // Converts |url| to a path on the app bundle. Used to resolve URLs on to the + // app bundle. + base::FilePath BuildTargetPath(const GURL& url); + + private: + // The path according to which URLs are resolved from. + base::FilePath path_; +}; +} + +#endif // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_FILE_BASED_RESPONSE_PROVIDER_IMPL_H_
diff --git a/ios/web/public/test/response_providers/response_provider.cc b/ios/web/public/test/response_providers/response_provider.cc new file mode 100644 index 0000000..888ad16 --- /dev/null +++ b/ios/web/public/test/response_providers/response_provider.cc
@@ -0,0 +1,68 @@ +// 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 "ios/web/public/test/response_providers/response_provider.h" + +#include "base/strings/stringprintf.h" +#include "net/http/http_response_headers.h" + +namespace web { + +ResponseProvider::Request::Request(const GURL& url, + const std::string& method, + const std::string& body, + const net::HttpRequestHeaders& headers) + : url(url), + method(method), + body(body), + headers(headers) { +} + +ResponseProvider::Request::~Request() { +} + +ResponseProvider::ResponseProvider() { +} + +// static +scoped_refptr<net::HttpResponseHeaders> ResponseProvider::GetResponseHeaders( + const std::string& content_type, + net::HttpStatusCode response_code) { + scoped_refptr<net::HttpResponseHeaders> result( + new net::HttpResponseHeaders("")); + const std::string reason_phrase(net::GetHttpReasonPhrase(response_code)); + const std::string status_line = base::StringPrintf("HTTP/1.1 %i %s", + static_cast<int>(response_code), + reason_phrase.c_str()); + result->ReplaceStatusLine(status_line); + const std::string content_type_header = + base::StringPrintf("Content-type: %s", content_type.c_str()); + result->AddHeader(content_type_header); + return result; +} + +// static +scoped_refptr<net::HttpResponseHeaders> ResponseProvider::GetResponseHeaders( + const std::string& content_type) { + return GetResponseHeaders(content_type, net::HTTP_OK); +} + +// static +scoped_refptr<net::HttpResponseHeaders> + ResponseProvider::GetDefaultResponseHeaders() { + return GetResponseHeaders("text/html", net::HTTP_OK); +} + +// static +scoped_refptr<net::HttpResponseHeaders> + ResponseProvider::GetRedirectResponseHeaders( + const std::string& destination, + const net::HttpStatusCode& http_status) { + scoped_refptr<net::HttpResponseHeaders> headers( + GetResponseHeaders("text/html", http_status)); + headers->AddHeader("Location: " + destination); + return headers; +} + +} // namespace web
diff --git a/ios/web/public/test/response_providers/response_provider.h b/ios/web/public/test/response_providers/response_provider.h new file mode 100644 index 0000000..dbf73ac4 --- /dev/null +++ b/ios/web/public/test/response_providers/response_provider.h
@@ -0,0 +1,81 @@ +// 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 IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_RESPONSE_PROVIDER_H_ +#define IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_RESPONSE_PROVIDER_H_ + +#include <string> + +#include "base/memory/ref_counted.h" +#include "net/http/http_request_headers.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_status_code.h" +#include "url/gurl.h" + +#ifdef __OBJC__ +@class GCDWebServerResponse; +#else +class GCDWebServerResponse; +#endif + +namespace web { + +// An abstract class for a provider that services a request and returns a +// GCDWebServerResponse. +// Note: The ResponseProviders can be called from any arbitrary GCD thread. +class ResponseProvider { + public: + // A data structure that encapsulated all the fields of a request. + struct Request { + Request(const GURL& url, + const std::string& method, + const std::string& body, + const net::HttpRequestHeaders& headers); + virtual ~Request(); + + // The URL for the request. + GURL url; + // The HTTP method for the request such as "GET" or "POST". + std::string method; + // The body of the request. + std::string body; + // The HTTP headers for the request. + net::HttpRequestHeaders headers; + }; + + // Returns true if the request is handled by the provider. + virtual bool CanHandleRequest(const Request& request) = 0; + + // Returns the GCDWebServerResponse as a reply to the request. Will only be + // called if the provider can handle the request. + virtual GCDWebServerResponse* GetGCDWebServerResponse( + const Request& request) = 0; + + // Gets default response headers with a text/html content type and a 200 + // response code. + static scoped_refptr<net::HttpResponseHeaders> GetDefaultResponseHeaders(); + // Gets configurable response headers with a provided content type and a + // 200 response code. + static scoped_refptr<net::HttpResponseHeaders> GetResponseHeaders( + const std::string& content_type); + // Gets configurable response headers with a provided content type and + // response code. + static scoped_refptr<net::HttpResponseHeaders> GetResponseHeaders( + const std::string& content_type, + net::HttpStatusCode response_code); + // Gets configurable response based on |http_status| headers for redirecting + // to |destination|. + static scoped_refptr<net::HttpResponseHeaders> GetRedirectResponseHeaders( + const std::string& destination, + const net::HttpStatusCode& http_status); + + ResponseProvider(); + virtual ~ResponseProvider() {}; + private: + DISALLOW_COPY_AND_ASSIGN(ResponseProvider); +}; + +} // namspace web + +#endif // IOS_WEB_PUBLIC_TEST_RESPONSE_PROVIDERS_RESPONSE_PROVIDER_H_
diff --git a/ios/web/public/test/web_test_util.h b/ios/web/public/test/web_test_util.h new file mode 100644 index 0000000..04a8af2 --- /dev/null +++ b/ios/web/public/test/web_test_util.h
@@ -0,0 +1,76 @@ +// 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 IOS_WEB_PUBLIC_TEST_WEB_TEST_UTIL_H_ +#define IOS_WEB_PUBLIC_TEST_WEB_TEST_UTIL_H_ + +#include "ios/web/public/web_view_util.h" + +// A helper macro that allows skipping a unit test on iOS7 and earlier. Example: +// +// TEST_F(WKWebViewTest, WebViewInitializesCorrectly) { +// CR_TEST_REQUIRES_WK_WEB_VIEW(); +// EXPECT_TRUE(NSClassFromString(@"WKWebView") != nil); +// } +#define CR_TEST_REQUIRES_WK_WEB_VIEW() \ + if (!web::IsWKWebViewSupported()) \ + return + +// Defines a web test that uses two test fixtures and single testing code. +// +// The first two parameters are the corresponding names of UIWebView-based and +// WKWebView-based test fixture classes. Those will also be the test case names. +// The third parameter is the name of the test within the test case. +// +// A test fixture class must be declared earlier. Test code goes between braces +// after using this macro. Example: +// +// typedef web::WebTest UIViewTest; +// typedef web::WKWebViewWebTest WKViewTest; +// +// WEB_TEST_F(UIViewTest, WKViewTest, ControllerInitializesCorrectly) { +// EXPECT_TRUE(this->webController_); +// } + +// Makes the name of a parent test class for WK and UI test fixtures. +// Only intended for use by WEB_TEST_F, not for direct use. +#define WEB_TEST_BASE_CLASS_(ui_fixture, wk_test_case, test_name)\ + ui_fixture##wk_test_case##_##test_name##_WebTest + +// Makes the name of a concrete WK or UI test fixture. +// Only intended for use by WEB_TEST_F, not for direct use. +#define WEB_TEST_TEST_CLASS_(test_case, test_name)\ + test_case##_##test_name##_WebTest + +// Makes the testing template class that runs WebTestBody function as the +// testing code. +// Only intended for use by WEB_TEST_F, not for direct use. +#define GTEST_WEB_TEST_(test_case, test_name, is_wk_web_view) \ + GTEST_TEST_(test_case, test_name, \ + WEB_TEST_TEST_CLASS_(test_case, test_name), \ + ::testing::internal::GetTypeId<test_case>()) { \ + if (!is_wk_web_view || web::IsWKWebViewSupported()) \ + WebTestBody(); \ + }; + +#define WEB_TEST_F(ui_fixture, wk_fixture, test_name) \ + template <typename T> \ + class WEB_TEST_BASE_CLASS_(ui_fixture, wk_fixture, test_name) \ + : public T { \ + protected: \ + void WebTestBody(); \ + }; \ + typedef WEB_TEST_BASE_CLASS_( \ + ui_fixture, wk_fixture, \ + test_name) <ui_fixture> WEB_TEST_TEST_CLASS_(ui_fixture, test_name); \ + typedef WEB_TEST_BASE_CLASS_( \ + ui_fixture, wk_fixture, \ + test_name) <wk_fixture> WEB_TEST_TEST_CLASS_(wk_fixture, test_name); \ + GTEST_WEB_TEST_(ui_fixture, test_name, false) \ + GTEST_WEB_TEST_(wk_fixture, test_name, true) \ + template <typename T> \ + void WEB_TEST_BASE_CLASS_(ui_fixture, wk_fixture, \ + test_name) <T>::WebTestBody() + +#endif // IOS_WEB_PUBLIC_TEST_WEB_TEST_UTIL_H_
diff --git a/ios/web/public/web_state/credential.h b/ios/web/public/web_state/credential.h new file mode 100644 index 0000000..f66d567e0 --- /dev/null +++ b/ios/web/public/web_state/credential.h
@@ -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. + +#ifndef IOS_WEB_PUBLIC_WEB_STATE_CREDENTIAL_H_ +#define IOS_WEB_PUBLIC_WEB_STATE_CREDENTIAL_H_ + +#include "base/strings/string16.h" +#include "url/gurl.h" + +namespace web { + +// Indicates the specific type of a Credential object. +enum CredentialType { + CREDENTIAL_TYPE_EMPTY = 0, + CREDENTIAL_TYPE_LOCAL, + CREDENTIAL_TYPE_FEDERATED, + CREDENTIAL_TYPE_LAST = CREDENTIAL_TYPE_FEDERATED +}; + +// Represents an instance of the JavaScript Credential type. +struct Credential { + Credential(); + ~Credential(); + + // The specific type of this credential. + CredentialType type; + + // An identifier for the credential. + base::string16 id; + + // A human-understandable name corresponding to the credential. + base::string16 name; + + // The URL of the user's avatar. + GURL avatar_url; + + // The password for a local credential. + base::string16 password; + + // The federation URL for a federated credential. + GURL federation_url; +}; + +} // namespace web + +#endif // IOS_WEB_PUBLIC_WEB_STATE_CREDENTIAL_H_
diff --git a/ios/web/public/web_state/crw_web_controller_observer.h b/ios/web/public/web_state/crw_web_controller_observer.h index 4cb14d4..7d6a2541 100644 --- a/ios/web/public/web_state/crw_web_controller_observer.h +++ b/ios/web/public/web_state/crw_web_controller_observer.h
@@ -9,7 +9,7 @@ #include <string> @class CRWWebController; -@class CRWWebViewProxy; +@protocol CRWWebViewProxy; class GURL; @class UIWebView; @@ -33,38 +33,6 @@ // DEPRECATED: Use WebStateObserver instead. - (void)pageLoaded:(CRWWebController*)webController; -// Called when a form is being submitted. -- (void)documentSubmit:(CRWWebController*)webController - formName:(const std::string&)formName - userInteraction:(BOOL)userInteraction; - -// Called when the user is typing on a form field, with |error| indicating if -// there is any error when parsing the form field information. Currently these -// events will not be sent if the Disable Autofill experiment is set. -- (void)formActivity:(CRWWebController*)webController - formName:(const std::string&)formName - fieldName:(const std::string&)fieldName - type:(const std::string&)type - value:(const std::string&)value - error:(bool)error; - -// Identical to |formActivity:formName:fieldName:type:value:error:|, but -// indicates that the activity was triggered by typing the key specified by -// |keyCode|. -- (void)formActivity:(CRWWebController*)webController - formName:(const std::string&)formName - fieldName:(const std::string&)fieldName - type:(const std::string&)type - value:(const std::string&)value - keyCode:(int)keyCode - error:(bool)error; - -// The page requested autocomplete. -- (void)requestAutocomplete:(CRWWebController*)webController - sourceURL:(const GURL&)sourceURL - formName:(const std::string&)formName - userInteraction:(BOOL)userInteraction; - // Called when the web controller is about to close. - (void)webControllerWillClose:(CRWWebController*)webController; @@ -77,7 +45,7 @@ originURL:(const GURL&)originURL; // Gives CRWWebControllerObservers access to the CRWWebViewProxy. -- (void)setWebViewProxy:(CRWWebViewProxy*)webView +- (void)setWebViewProxy:(id<CRWWebViewProxy>)webView controller:(CRWWebController*)webController; @end
diff --git a/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h b/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h index 725577d..eb9a992 100644 --- a/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h +++ b/ios/web/public/web_state/crw_web_view_scroll_view_proxy.h
@@ -44,10 +44,6 @@ // Used by the CRWWebViewProxy to set the UIScrollView to be managed. - (void)setScrollView:(UIScrollView*)scrollView; -// Copies all display properties that can be set on a CRWWebViewScrollViewProxy -// from the underlying UIScrollView into |scrollView|. -- (void)copyPropertiesToScrollView:(UIScrollView*)scrollView; - // Adds |observer| to subscribe to change notifications. - (void)addObserver:(id<CRWWebViewScrollViewProxyObserver>)observer;
diff --git a/ios/web/public/web_state/web_state_observer.h b/ios/web/public/web_state/web_state_observer.h index c24e299..519e5b6 100644 --- a/ios/web/public/web_state/web_state_observer.h +++ b/ios/web/public/web_state/web_state_observer.h
@@ -14,6 +14,7 @@ namespace web { +struct Credential; struct FaviconURL; struct LoadCommittedDetails; class WebState; @@ -42,6 +43,12 @@ virtual void NavigationItemCommitted( const LoadCommittedDetails& load_details) {} + // Called when the current page has started loading. + virtual void DidStartLoading() {} + + // Called when the current page has stopped loading. + virtual void DidStopLoading() {} + // Called when the current page is loaded. virtual void PageLoaded(PageLoadCompletionStatus load_completion_status) {} @@ -80,6 +87,54 @@ // Invoked when new favicon URL candidates are received. virtual void FaviconUrlUpdated(const std::vector<FaviconURL>& candidates) {} + // Notifies the observer that the credential manager API was invoked from + // |source_url| to request a credential from the browser. If |suppress_ui| + // is true, the browser MUST NOT show any UI to the user. If this means that + // no credential will be returned to the page, so be it. Otherwise, the + // browser may show the user any UI that is necessary to get a Credential and + // return it to the page. |federations| specifies a list of acceptable + // federation providers. |user_interaction| indicates whether the API was + // invoked in response to a user interaction. Responses to the page should + // provide the specified |request_id|. + virtual void CredentialsRequested(int request_id, + const GURL& source_url, + bool suppress_ui, + const std::vector<std::string>& federations, + bool is_user_initiated) {} + + // Notifies the observer that the credential manager API was invoked from + // |source_url| to notify the browser that the user signed in. |credential| + // specifies the credential that was used to sign in. Responses to the page + // should provide the specified |request_id|. + virtual void SignedIn(int request_id, + const GURL& source_url, + const web::Credential& credential) {} + + // Notifies the observer that the credential manager API was invoked from + // |source_url| to notify the browser that the user signed in without + // specifying the credential that was used. Responses to the page should + // provide the specified |request_id|. + virtual void SignedIn(int request_id, const GURL& source_url) {} + + // Notifies the observer that the credential manager API was invoked from + // |source_url| to notify the browser that the user signed out. Responses + // to the page should provide the specified |request_id|. + virtual void SignedOut(int request_id, const GURL& source_url) {} + + // Notifies the observer that the credential manager API was invoked from + // |source_url| to notify the browser that the user failed to sign in. + // |credential| specifies the credential that failed to sign in. Responses + // to the page should provide the specified |request_id|. + virtual void SignInFailed(int request_id, + const GURL& source_url, + const web::Credential& credential) {} + + // Notifies the observer that the credential manager API was invoked from + // |source_url| to notify the browser that the user failed to sign in without + // specifying the credential that failed. Responses to the page should provide + // the specified |request_id|. + virtual void SignInFailed(int request_id, const GURL& source_url) {} + // Invoked when the WebState is being destroyed. Gives subclasses a chance // to cleanup. virtual void WebStateDestroyed() {}
diff --git a/ios/web/public/web_state/web_state_observer_bridge.h b/ios/web/public/web_state/web_state_observer_bridge.h index e61bea441..17b4a9f8 100644 --- a/ios/web/public/web_state/web_state_observer_bridge.h +++ b/ios/web/public/web_state/web_state_observer_bridge.h
@@ -70,6 +70,12 @@ // is no longer valid. - (void)webStateDestroyed:(web::WebState*)webState; +// Invoked by WebStateObserverBridge::DidStopLoading. +- (void)webStateDidStopLoading:(web::WebState*)webState; + +// Invoked by WebStateObserverBridge::DidStartLoading. +- (void)webStateDidStartLoading:(web::WebState*)webState; + @end namespace web { @@ -108,6 +114,8 @@ bool user_initiated) override; void FaviconUrlUpdated(const std::vector<FaviconURL>& candidates) override; void WebStateDestroyed() override; + void DidStartLoading() override; + void DidStopLoading() override; private: base::WeakNSProtocol<id<CRWWebStateObserver>> observer_;
diff --git a/ios/web/public/web_view_util.h b/ios/web/public/web_view_util.h new file mode 100644 index 0000000..ed49cf8 --- /dev/null +++ b/ios/web/public/web_view_util.h
@@ -0,0 +1,15 @@ +// 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 IOS_WEB_PUBLIC_WEB_VIEW_UTIL_H_ +#define IOS_WEB_PUBLIC_WEB_VIEW_UTIL_H_ + +namespace web { + +// Returns true if WKWebView is supported on current OS/platform/arch. +bool IsWKWebViewSupported(); + +} // web + +#endif // IOS_WEB_PUBLIC_WEB_VIEW_UTIL_H_
diff --git a/ios/web/web_state/credential.cc b/ios/web/web_state/credential.cc new file mode 100644 index 0000000..f7c08cc --- /dev/null +++ b/ios/web/web_state/credential.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 "ios/web/public/web_state/credential.h" + +namespace web { + +Credential::Credential() = default; + +Credential::~Credential() = default; + +} // namespace web
diff --git a/ios/web/web_state/js/credential_util.h b/ios/web/web_state/js/credential_util.h new file mode 100644 index 0000000..affd0ee --- /dev/null +++ b/ios/web/web_state/js/credential_util.h
@@ -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. + +#ifndef IOS_WEB_WEB_STATE_JS_CREDENTIAL_UTIL_H_ +#define IOS_WEB_WEB_STATE_JS_CREDENTIAL_UTIL_H_ + +namespace base { +class DictionaryValue; +} // namespace base + +namespace web { + +struct Credential; + +// Populates |credential| from |value|, returning true if successful and false +// otherwise. |value| must contain the following string->string key/value +// pairs: +// +// "type": one of "LocalCredential" of "FederatedCredential" +// "id": a string (possibly empty) +// +// The following pairs are optional: +// +// "name": a string (possibly empty) +// "avatarURL": a valid URL as a string +// +// If "type" is "LocalCredential", then |value| must contain +// +// "password" a string (possibly empty) +// +// If "type" is "FederatedCredential", then |value| must contain +// +// "federation": a valid URL as a string +// +// If passed a |value| that doesn't meet these restrictions, |credential| will +// not be modified and false will be returned. |credential| must not be null. +bool DictionaryValueToCredential(const base::DictionaryValue& value, + Credential* credential); + +// Serializes |credential| to |value|. +void CredentialToDictionaryValue(const Credential& credential, + base::DictionaryValue* value); + +} // namespace web + +#endif // IOS_WEB_WEB_STATE_JS_CREDENTIAL_UTIL_H_
diff --git a/ios/web/web_state/js/credential_util.mm b/ios/web/web_state/js/credential_util.mm new file mode 100644 index 0000000..4ee58c8 --- /dev/null +++ b/ios/web/web_state/js/credential_util.mm
@@ -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 "ios/web/web_state/js/credential_util.h" + +#include "base/logging.h" +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "ios/web/public/web_state/credential.h" +#include "url/gurl.h" + +namespace { + +// "type" value for a DictionaryValue representation of LocalCredential. +const char* kLocalCredentialType = "LocalCredential"; + +// "type" value for a DictionaryValue representation of FederatedCredential. +const char* kFederatedCredentialType = "FederatedCredential"; + +} // namespace + +namespace web { + +bool DictionaryValueToCredential(const base::DictionaryValue& value, + Credential* credential) { + DCHECK(credential); + + base::string16 type; + if (!value.GetString("type", &type)) + return false; + CredentialType credential_type; + if (type == base::ASCIIToUTF16(kLocalCredentialType)) + credential_type = CredentialType::CREDENTIAL_TYPE_LOCAL; + else if (type == base::ASCIIToUTF16(kFederatedCredentialType)) + credential_type = CredentialType::CREDENTIAL_TYPE_FEDERATED; + else + return false; + + base::string16 id; + if (!value.GetString("id", &id)) + return false; + + base::string16 name; + value.GetString("name", &name); + + base::string16 avatar; + GURL avatar_url; + if (value.GetString("avatarURL", &avatar)) { + avatar_url = GURL(avatar); + if (!avatar_url.is_valid()) + return false; + } + + base::string16 password; + if (credential_type == CredentialType::CREDENTIAL_TYPE_LOCAL && + !value.GetString("password", &password)) { + return false; + } + + base::string16 federation; + GURL federation_url; + if (credential_type == CredentialType::CREDENTIAL_TYPE_FEDERATED) { + if (!value.GetString("federation", &federation)) + return false; + federation_url = GURL(federation); + if (!federation_url.is_valid()) + return false; + } + + credential->type = credential_type; + credential->id = id; + credential->name = name; + credential->avatar_url = avatar_url; + credential->password = password; + credential->federation_url = federation_url; + return true; +} + +void CredentialToDictionaryValue(const Credential& credential, + base::DictionaryValue* value) { + switch (credential.type) { + case CredentialType::CREDENTIAL_TYPE_LOCAL: + value->SetString("type", kLocalCredentialType); + value->SetString("password", credential.password); + break; + case CredentialType::CREDENTIAL_TYPE_FEDERATED: + value->SetString("type", kFederatedCredentialType); + value->SetString("federation", credential.federation_url.spec()); + break; + default: + NOTREACHED(); + } + value->SetString("id", credential.id); + value->SetString("name", credential.name); + value->SetString("avatarURL", credential.avatar_url.spec()); +} + +} // web
diff --git a/ios/web/web_state/js/crw_js_injection_manager.mm b/ios/web/web_state/js/crw_js_injection_manager.mm index 00c3caa..3b8e5dd 100644 --- a/ios/web/web_state/js/crw_js_injection_manager.mm +++ b/ios/web/web_state/js/crw_js_injection_manager.mm
@@ -11,6 +11,7 @@ #import "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" +#import "ios/web/web_state/js/page_script_util.h" @implementation CRWJSInjectionManager { // JS to inject into the page. This may be nil if it has been purged due to @@ -111,18 +112,7 @@ } - (NSString*)staticInjectionContent { - DCHECK(self.scriptPath); - NSString* path = [base::mac::FrameworkBundle() pathForResource:self.scriptPath - ofType:@"js"]; - DCHECK(path) << "Script file not found: " - << base::SysNSStringToUTF8(self.scriptPath) << ".js"; - NSError* error = nil; - NSString* content = [NSString stringWithContentsOfFile:path - encoding:NSUTF8StringEncoding - error:&error]; - DCHECK(!error) << "Error fetching script: " << [error.description UTF8String]; - DCHECK(content); - return content; + return web::GetPageScript([self scriptPath]); } - (void)injectDependenciesIfMissing {
diff --git a/ios/web/web_state/js/crw_js_invoke_parameter_queue.h b/ios/web/web_state/js/crw_js_invoke_parameter_queue.h new file mode 100644 index 0000000..7a6811a --- /dev/null +++ b/ios/web/web_state/js/crw_js_invoke_parameter_queue.h
@@ -0,0 +1,65 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_WEB_STATE_JS_CRW_JS_INVOKE_PARAMETER_QUEUE_H_ +#define IOS_WEB_WEB_STATE_JS_CRW_JS_INVOKE_PARAMETER_QUEUE_H_ + +#import <UIKit/UIKit.h> + +class GURL; + +// Manages access to individual invoke parameters. +@interface CRWJSInvokeParameters : NSObject + +// The designated initializer. +- (id)initWithCommandString:(NSString*)commandString + userIsInteracting:(BOOL)userIsInteracting + originURL:(const GURL&)originURL + forWindowId:(NSString*)windowId; + +// An escaped string with commands requested by JavaScript. +@property(nonatomic, readonly) NSString* commandString; + +// Whether the user was interacting when the command was issued. +@property(nonatomic, readonly) BOOL userIsInteracting; + +// Returns window id of the originating window. +@property(nonatomic, readonly) NSString* windowId; + +// Returns URL that was current when the crwebinvoke was issued. +@property(nonatomic, readonly) const GURL& originURL; + +@end + + +// Stores parameters passed from JavaScript for deferred processing. +@interface CRWJSInvokeParameterQueue : NSObject + +// YES if there are no more queued messages. +@property(nonatomic, readonly) BOOL isEmpty; + +// Adds a new item to the queue. |commandString| is the escaped command string, +// |userIsInteracting| is true if the user was interacting with the page, +// |originURL| is the URL the command came from, and |windowId| is the id of the +// window that sent the command. +- (void)addCommandString:(NSString*)commandString + userIsInteracting:(BOOL)userIsInteracting + originURL:(const GURL&)originURL + forWindowId:(NSString*)windowId; + +// Removes from |queue_| any CRWJSInvokeParameters whose command string contains +// |commandString|. +- (void)removeCommandString:(NSString*)commandString; + +// Removes the oldest item from the queue and returns it. +- (CRWJSInvokeParameters*)popInvokeParameters; + +@end + +@interface CRWJSInvokeParameterQueue (Testing) +// The number of items in the queue. +@property(nonatomic, readonly) NSUInteger queueLength; +@end + +#endif // IOS_WEB_WEB_STATE_JS_CRW_JS_INVOKE_PARAMETER_QUEUE_H_
diff --git a/ios/web/web_state/js/crw_js_invoke_parameter_queue.mm b/ios/web/web_state/js/crw_js_invoke_parameter_queue.mm new file mode 100644 index 0000000..403bcb7 --- /dev/null +++ b/ios/web/web_state/js/crw_js_invoke_parameter_queue.mm
@@ -0,0 +1,99 @@ +// Copyright 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/web_state/js/crw_js_invoke_parameter_queue.h" + +#import "base/mac/scoped_nsobject.h" +#include "url/gurl.h" + +@implementation CRWJSInvokeParameters { + base::scoped_nsobject<NSString> _commandString; + BOOL _userIsInteracting; + base::scoped_nsobject<NSString> _windowId; + GURL _originURL; +} + +@synthesize userIsInteracting = _userIsInteracting; + +- (id)initWithCommandString:(NSString*)commandString + userIsInteracting:(BOOL)userIsInteracting + originURL:(const GURL&)originURL + forWindowId:(NSString*)windowId { + if ((self = [super init])) { + _commandString.reset([commandString copy]); + _userIsInteracting = userIsInteracting; + _windowId.reset([windowId copy]); + _originURL = originURL; + } + return self; +} + +- (NSString*)commandString { + return _commandString.get(); +} + +- (NSString*)windowId { + return _windowId.get(); +} + +- (const GURL&)originURL { + return _originURL; +} + +@end + +@implementation CRWJSInvokeParameterQueue { + base::scoped_nsobject<NSMutableArray> _queue; +} + +- (id)init { + if ((self = [super init])) { + // Under normal circumstainces there will be maximum one message queued. + _queue.reset([[NSMutableArray arrayWithCapacity:1] retain]); + } + return self; +} + +- (BOOL)isEmpty { + return [_queue count] == 0; +} + +- (NSUInteger)queueLength { + return [_queue count]; +} + +- (void)addCommandString:(NSString*)commandString + userIsInteracting:(BOOL)userIsInteracting + originURL:(const GURL&)originURL + forWindowId:(NSString*)windowId { + base::scoped_nsobject<CRWJSInvokeParameters> invokeParameters( + [[CRWJSInvokeParameters alloc] initWithCommandString:commandString + userIsInteracting:userIsInteracting + originURL:originURL + forWindowId:windowId]); + [_queue addObject:invokeParameters]; +} + +- (void)removeCommandString:(NSString*)commandString { + NSMutableArray* commandsToRemove = [NSMutableArray array]; + for (CRWJSInvokeParameters* params in _queue.get()) { + NSRange range = + [[params commandString] rangeOfString:commandString + options:NSCaseInsensitiveSearch]; + if (range.location != NSNotFound) + [commandsToRemove addObject:params]; + } + [_queue removeObjectsInArray:commandsToRemove]; +} + +- (CRWJSInvokeParameters*)popInvokeParameters { + if (![_queue count]) + return nil; + CRWJSInvokeParameters* invokeParameters = + [[[_queue objectAtIndex:0] retain] autorelease]; + [_queue removeObjectAtIndex:0]; + return invokeParameters; +} + +@end
diff --git a/ios/web/web_state/js/crw_js_plugin_placeholder_manager.h b/ios/web/web_state/js/crw_js_plugin_placeholder_manager.h new file mode 100644 index 0000000..208b1a78 --- /dev/null +++ b/ios/web/web_state/js/crw_js_plugin_placeholder_manager.h
@@ -0,0 +1,17 @@ +// Copyright 2013 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_JS_CRW_JS_PLUGIN_PLACEHOLDER_MANAGER_H_ +#define IOS_WEB_WEB_STATE_JS_CRW_JS_PLUGIN_PLACEHOLDER_MANAGER_H_ + +#import "ios/web/public/web_state/js/crw_js_injection_manager.h" + +// Loads the JavaScript file plugin_placeholder.js, which contains logic for +// adding placeholders to plugins on the page. It will be evaluated on a page +// where plugins that need placeholders have been detected. +@interface CRWJSPluginPlaceholderManager : CRWJSInjectionManager + +@end + +#endif // IOS_WEB_WEB_STATE_JS_CRW_JS_PLUGIN_PLACEHOLDER_MANAGER_H_
diff --git a/ios/web/web_state/js/crw_js_plugin_placeholder_manager.mm b/ios/web/web_state/js/crw_js_plugin_placeholder_manager.mm new file mode 100644 index 0000000..6378d87b --- /dev/null +++ b/ios/web/web_state/js/crw_js_plugin_placeholder_manager.mm
@@ -0,0 +1,51 @@ +// Copyright 2013 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/js/crw_js_plugin_placeholder_manager.h" + +#include "base/logging.h" +#include "base/strings/sys_string_conversions.h" +#include "ios/web/public/web_client.h" + +@implementation CRWJSPluginPlaceholderManager + +namespace { + +// Returns a string with \ and ' escaped, and wrapped in '. +// This is used instead of GetQuotedJSONString because that will convert +// UTF-16 to UTF-8, which can cause problems when injecting scripts depending +// on the page encoding (see crbug.com/302741). +NSString* EscapedQuotedString(NSString* string) { + string = [string stringByReplacingOccurrencesOfString:@"\\" + withString:@"\\\\"]; + string = [string stringByReplacingOccurrencesOfString:@"'" + withString:@"\\'"]; + return [NSString stringWithFormat:@"'%@'", string]; +} + +} + +#pragma mark - +#pragma mark ProtectedMethods + +- (NSString*)scriptPath { + return @"plugin_placeholder"; +} + +- (NSString*)presenceBeacon { + return @"__gCrWeb.plugin"; +} + +- (NSString*)staticInjectionContent { + NSString* baseContent = [super staticInjectionContent]; + DCHECK(web::GetWebClient()); + NSString* pluginNotSupportedText = base::SysUTF16ToNSString( + web::GetWebClient()->GetPluginNotSupportedText()); + NSString* placeholderCall = [NSString stringWithFormat: + @"__gCrWeb.plugin.addPluginPlaceholders(%@);", + EscapedQuotedString(pluginNotSupportedText)]; + return [baseContent stringByAppendingString:placeholderCall]; +} + +@end
diff --git a/ios/web/web_state/js/crw_js_window_id_manager.h b/ios/web/web_state/js/crw_js_window_id_manager.h new file mode 100644 index 0000000..95e0ab2 --- /dev/null +++ b/ios/web/web_state/js/crw_js_window_id_manager.h
@@ -0,0 +1,19 @@ +// 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 IOS_WEB_WEB_STATE_JS_CRW_JS_WINDOW_ID_MANAGER_H_ +#define IOS_WEB_WEB_STATE_JS_CRW_JS_WINDOW_ID_MANAGER_H_ + +#import "ios/web/public/web_state/js/crw_js_injection_manager.h" + +// Loads the JavaScript file window_id.js which sets __gCrWeb.windowId and +// manages the windowId for messages. +@interface CRWJSWindowIdManager : CRWJSInjectionManager + +// A unique window ID is assigned when the script is injected. +@property(nonatomic, copy) NSString* windowId; + +@end + +#endif // IOS_WEB_WEB_STATE_JS_CRW_JS_WINDOW_ID_MANAGER_H_
diff --git a/ios/web/web_state/js/crw_js_window_id_manager.mm b/ios/web/web_state/js/crw_js_window_id_manager.mm new file mode 100644 index 0000000..d689990 --- /dev/null +++ b/ios/web/web_state/js/crw_js_window_id_manager.mm
@@ -0,0 +1,73 @@ +// 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. + +#import "ios/web/web_state/js/crw_js_window_id_manager.h" + +#import "base/mac/scoped_nsobject.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/sys_string_conversions.h" +#include "crypto/random.h" + +namespace { +// Number of random bytes in unique key for window ID. The length of the +// window ID will be twice this number, as it is hexadecimal encoded. +const NSInteger kUniqueKeyLength = 16; +} // namespace + +@interface CRWJSWindowIdManager () { + base::scoped_nsobject<NSString> _windowId; +} + +// Returns a string of randomized ASCII characters. +- (NSString*)generateUniqueKey; + +@end + +@implementation CRWJSWindowIdManager + +- (id)initWithReceiver:(CRWJSInjectionReceiver*)receiver { + self = [super initWithReceiver:receiver]; + if (self) { + _windowId.reset([[self generateUniqueKey] retain]); + } + return self; +} + +- (NSString*)windowId { + return _windowId; +} + +- (void)setWindowId:(NSString*)value { + _windowId.reset([value copy]); +} + +#pragma mark ProtectedMethods + +- (NSString*)scriptPath { + return @"window_id"; +} + +- (NSString*)presenceBeacon { + return @"__gCrWeb.windowIdObject"; +} + +// It is important to recreate the injection content on every injection, because +// it cotains the randomly-generated page ID used for security checks. +- (NSString*)injectionContent { + _windowId.reset([[self generateUniqueKey] retain]); + NSString* script = [super injectionContent]; + return [script stringByReplacingOccurrencesOfString:@"$(WINDOW_ID)" + withString:_windowId]; +} + +#pragma mark - Private + +- (NSString*)generateUniqueKey { + char randomBytes[kUniqueKeyLength]; + crypto::RandBytes(randomBytes, kUniqueKeyLength); + return + base::SysUTF8ToNSString(base::HexEncode(randomBytes, kUniqueKeyLength)); +} + +@end
diff --git a/ios/web/web_state/js/resources/core.js b/ios/web/web_state/js/resources/core.js index 3d72323..717fa1b5 100644 --- a/ios/web/web_state/js/resources/core.js +++ b/ios/web/web_state/js/resources/core.js
@@ -42,8 +42,14 @@ */ var touchMargin_ = 25; - __gCrWeb['innerSizeAsString'] = function() { - return window.innerWidth + '/' + window.innerHeight; + __gCrWeb['getPageWidth'] = function() { + var documentElement = document.documentElement; + var documentBody = document.body; + return Math.max(documentElement.clientWidth, + documentElement.scrollWidth, + documentElement.offsetWidth, + documentBody.scrollWidth, + documentBody.offsetWidth); }; // Implementation of document.elementFromPoint that is working for iOS4 and
diff --git a/ios/web/web_state/web_state_observer_bridge.mm b/ios/web/web_state/web_state_observer_bridge.mm index c2028fe8..fe1f6db 100644 --- a/ios/web/web_state/web_state_observer_bridge.mm +++ b/ios/web/web_state/web_state_observer_bridge.mm
@@ -30,6 +30,20 @@ } } +void WebStateObserverBridge::DidStartLoading() { + SEL selector = @selector(webStateDidStartLoading:); + if ([observer_ respondsToSelector:selector]) { + [observer_ webStateDidStartLoading:web_state()]; + } +} + +void WebStateObserverBridge::DidStopLoading() { + SEL selector = @selector(webStateDidStopLoading:); + if ([observer_ respondsToSelector:selector]) { + [observer_ webStateDidStopLoading:web_state()]; + } +} + void WebStateObserverBridge::PageLoaded( web::PageLoadCompletionStatus load_completion_status) { SEL selector = @selector(webStateDidLoadPage:);
diff --git a/ios/web/web_view_util.h b/ios/web/web_view_util.h deleted file mode 100644 index a625c57..0000000 --- a/ios/web/web_view_util.h +++ /dev/null
@@ -1,15 +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 IOS_WEB_WEB_VIEW_UTIL_H_ -#define IOS_WEB_WEB_VIEW_UTIL_H_ - -namespace web { - -// Returns true if WKWebView is supported on current OS/platform/arch. -bool IsWKWebViewSupported(); - -} // web - -#endif // IOS_WEB_WEB_VIEW_UTIL_H_
diff --git a/ios/web/web_view_util.mm b/ios/web/web_view_util.mm index 6807d507..782a28c 100644 --- a/ios/web/web_view_util.mm +++ b/ios/web/web_view_util.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ios/web/web_view_util.h" +#include "ios/web/public/web_view_util.h" #include <Foundation/Foundation.h> #include <sys/sysctl.h>
diff --git a/ipc/ipc_channel_nacl.cc b/ipc/ipc_channel_nacl.cc index 49ac1393..60a5ddaa 100644 --- a/ipc/ipc_channel_nacl.cc +++ b/ipc/ipc_channel_nacl.cc
@@ -80,7 +80,7 @@ // DelegateSimpleThread implementation. Reads data from the pipe in a loop // until either we are told to quit or a read fails. - virtual void Run() override; + void Run() override; private: int pipe_;
diff --git a/ipc/ipc_channel_nacl.h b/ipc/ipc_channel_nacl.h index 9c1e80f..f0649b26 100644 --- a/ipc/ipc_channel_nacl.h +++ b/ipc/ipc_channel_nacl.h
@@ -38,14 +38,14 @@ ChannelNacl(const IPC::ChannelHandle& channel_handle, Mode mode, Listener* listener); - virtual ~ChannelNacl(); + ~ChannelNacl() override; // Channel implementation. - virtual base::ProcessId GetPeerPID() const override; - virtual base::ProcessId GetSelfPID() const override; - virtual bool Connect() override; - virtual void Close() override; - virtual bool Send(Message* message) override; + base::ProcessId GetPeerPID() const override; + base::ProcessId GetSelfPID() const override; + bool Connect() override; + void Close() override; + bool Send(Message* message) override; // Posted to the main thread by ReaderThreadRunner. void DidRecvMsg(scoped_ptr<MessageContents> contents); @@ -59,12 +59,12 @@ void CallOnChannelConnected(); // ChannelReader implementation. - virtual ReadState ReadData(char* buffer, - int buffer_len, - int* bytes_read) override; - virtual bool WillDispatchInputMessage(Message* msg) override; - virtual bool DidEmptyInputBuffers() override; - virtual void HandleInternalMessage(const Message& msg) override; + ReadState ReadData(char* buffer, + int buffer_len, + int* bytes_read) override; + bool WillDispatchInputMessage(Message* msg) override; + bool DidEmptyInputBuffers() override; + void HandleInternalMessage(const Message& msg) override; Mode mode_; bool waiting_connect_;
diff --git a/ipc/mojo/ipc_channel_mojo_unittest.cc b/ipc/mojo/ipc_channel_mojo_unittest.cc index bf70b7f..4018715 100644 --- a/ipc/mojo/ipc_channel_mojo_unittest.cc +++ b/ipc/mojo/ipc_channel_mojo_unittest.cc
@@ -551,7 +551,7 @@ #if defined(OS_WIN) class IPCChannelMojoDeadHandleTest : public IPCChannelMojoTestBase { protected: - virtual scoped_ptr<IPC::ChannelFactory> CreateChannelFactory( + scoped_ptr<IPC::ChannelFactory> CreateChannelFactory( const IPC::ChannelHandle& handle, base::SequencedTaskRunner* runner) override { host_.reset(new IPC::ChannelMojoHost(task_runner())); @@ -559,7 +559,7 @@ task_runner(), handle); } - virtual bool DidStartClient() override { + bool DidStartClient() override { IPCTestBase::DidStartClient(); const base::ProcessHandle client = client_process().Handle(); // Forces GetFileHandleForProcess() fail. It happens occasionally
diff --git a/jingle/notifier/listener/xmpp_push_client_unittest.cc b/jingle/notifier/listener/xmpp_push_client_unittest.cc index bd0b46d..abe6775 100644 --- a/jingle/notifier/listener/xmpp_push_client_unittest.cc +++ b/jingle/notifier/listener/xmpp_push_client_unittest.cc
@@ -38,14 +38,14 @@ message_loop_.message_loop_proxy()); } - virtual ~XmppPushClientTest() {} + ~XmppPushClientTest() override {} - virtual void SetUp() override { + void SetUp() override { xmpp_push_client_.reset(new XmppPushClient(notifier_options_)); xmpp_push_client_->AddObserver(&mock_observer_); } - virtual void TearDown() override { + void TearDown() override { // Clear out any messages posted by XmppPushClient. message_loop_.RunUntilIdle(); xmpp_push_client_->RemoveObserver(&mock_observer_);
diff --git a/mandoline/app/BUILD.gn b/mandoline/app/BUILD.gn index 0058c1b7..998659c0 100644 --- a/mandoline/app/BUILD.gn +++ b/mandoline/app/BUILD.gn
@@ -17,7 +17,7 @@ "//build/config/sanitizers:deps", "//mojo/common", "//mojo/environment:chromium", - "//mojo/shell:lib", + "//mojo/runner:lib", ] if (!is_android) {
diff --git a/mandoline/app/desktop/launcher_process.cc b/mandoline/app/desktop/launcher_process.cc index 15cbea9..f3e8c1ca 100644 --- a/mandoline/app/desktop/launcher_process.cc +++ b/mandoline/app/desktop/launcher_process.cc
@@ -16,8 +16,8 @@ #include "base/synchronization/waitable_event.h" #include "base/trace_event/trace_event.h" #include "mandoline/app/desktop/launcher_process.h" -#include "mojo/shell/context.h" -#include "mojo/shell/switches.h" +#include "mojo/runner/context.h" +#include "mojo/runner/switches.h" namespace mandoline { namespace {
diff --git a/mandoline/app/desktop/main.cc b/mandoline/app/desktop/main.cc index 6bc45454f..be67ba20 100644 --- a/mandoline/app/desktop/main.cc +++ b/mandoline/app/desktop/main.cc
@@ -5,9 +5,9 @@ #include "base/at_exit.h" #include "base/command_line.h" #include "mandoline/app/desktop/launcher_process.h" -#include "mojo/shell/child_process.h" -#include "mojo/shell/init.h" -#include "mojo/shell/switches.h" +#include "mojo/runner/child_process.h" +#include "mojo/runner/init.h" +#include "mojo/runner/switches.h" int main(int argc, char** argv) { base::AtExitManager at_exit;
diff --git a/mandoline/services/navigation/public/interfaces/BUILD.gn b/mandoline/services/navigation/public/interfaces/BUILD.gn new file mode 100644 index 0000000..5b5dca6 --- /dev/null +++ b/mandoline/services/navigation/public/interfaces/BUILD.gn
@@ -0,0 +1,18 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "navigation.mojom", + ] + + import_dirs = [ mojo_network_service_root ] + + deps = [ + "//mojo/services/network/public/interfaces", + ] +}
diff --git a/third_party/mojo_services/src/navigation/public/interfaces/navigation.mojom b/mandoline/services/navigation/public/interfaces/navigation.mojom similarity index 100% rename from third_party/mojo_services/src/navigation/public/interfaces/navigation.mojom rename to mandoline/services/navigation/public/interfaces/navigation.mojom
diff --git a/media/BUILD.gn b/media/BUILD.gn index 559e29a..53f97bffc 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -13,7 +13,7 @@ # Common configuration for targets in the media directory. # NOT for exporting. config("media_config") { - defines = [ "MEDIA_IMPLEMENTATION" ] + defines = [] if (!media_use_libvpx) { defines += [ "MEDIA_DISABLE_LIBVPX" ] } @@ -37,6 +37,10 @@ } } +config("media_implementation") { + defines = [ "MEDIA_IMPLEMENTATION" ] +} + config("media_dependent_config") { defines = [] if (!media_use_libvpx) { @@ -278,6 +282,7 @@ configs += [ ":media_config", + ":media_implementation", # TODO(wolenetz): Fix size_t to int trunctaion in win64. # See http://crbug.com/171009 @@ -285,6 +290,7 @@ ] all_dependent_configs = [ ":media_dependent_config" ] + allow_circular_includes_from = [] cflags = [] libs = [] defines = [] @@ -334,14 +340,7 @@ deps += [ "//third_party/libvpx" ] } - if (!is_android) { - sources += [ - "filters/opus_audio_decoder.cc", - "filters/opus_audio_decoder.h", - "renderers/default_renderer_factory.cc", - "renderers/default_renderer_factory.h", - ] - } else { + if (is_android) { sources += [ "midi/midi_manager_android.cc", "midi/usb_midi_device_android.cc", @@ -359,6 +358,14 @@ "//media/base/android:media_jni_headers", "//media/base/android:video_capture_jni_headers", ] + allow_circular_includes_from = [ "//media/base/android" ] + } else { + sources += [ + "filters/opus_audio_decoder.cc", + "filters/opus_audio_decoder.h", + "renderers/default_renderer_factory.cc", + "renderers/default_renderer_factory.h", + ] } if (current_cpu != "arm" && is_chromeos) { @@ -368,15 +375,12 @@ ] } - if (use_alsa) { + if (use_alsa && use_udev) { libs += [ "asound" ] sources += [ "midi/midi_manager_alsa.cc", "midi/midi_manager_alsa.h", ] - } - - if (use_udev) { deps += [ "//device/udev_linux" ] } @@ -517,7 +521,10 @@ # Minimal media component for media/cast on iOS. if (is_ios) { component("media_for_cast_ios") { - configs += [ ":media_config" ] + configs += [ + ":media_config", + ":media_implementation", + ] all_dependent_configs = [ ":media_dependent_config" ] include_dirs = [ "." ] libs = [ "CoreVideo.framework" ] @@ -679,7 +686,7 @@ ] } - if (use_alsa) { + if (use_alsa && use_udev) { sources += [ "midi/midi_manager_alsa_unittest.cc" ] } @@ -756,8 +763,10 @@ "base/vector_math.cc", "base/vector_math.h", ] - configs += [ ":media_config" ] - defines = [ "MEDIA_IMPLEMENTATION" ] + configs += [ + ":media_config", + ":media_implementation", + ] deps = [ "//base", ]
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn index 968a2e9..d2bbbd3e 100644 --- a/media/audio/BUILD.gn +++ b/media/audio/BUILD.gn
@@ -115,7 +115,10 @@ ] deps = [] libs = [] - configs += [ "//media:media_config" ] + configs += [ + "//media:media_config", + "//media:media_implementation", + ] if (is_mac) { sources += [ @@ -270,6 +273,7 @@ sources = [ "audio_input_controller_unittest.cc", "audio_input_unittest.cc", + "audio_manager_factory_unittest.cc", "audio_manager_unittest.cc", "audio_output_controller_unittest.cc", "audio_output_device_unittest.cc",
diff --git a/media/audio/agc_audio_stream.h b/media/audio/agc_audio_stream.h index d0ac2bf..a2958ce 100644 --- a/media/audio/agc_audio_stream.h +++ b/media/audio/agc_audio_stream.h
@@ -138,7 +138,7 @@ // be read in each AudioInputCallback::OnData() callback and fed to the // render-side AGC. User must call StartAgc() as well to start measuring // the microphone level. - virtual bool SetAutomaticGainControl(bool enabled) override { + bool SetAutomaticGainControl(bool enabled) override { DVLOG(1) << "SetAutomaticGainControl(enabled=" << enabled << ")"; DCHECK(thread_checker_.CalledOnValidThread()); agc_is_enabled_ = enabled; @@ -146,7 +146,7 @@ } // Gets the current automatic gain control state. - virtual bool GetAutomaticGainControl() override { + bool GetAutomaticGainControl() override { DCHECK(thread_checker_.CalledOnValidThread()); return agc_is_enabled_; }
diff --git a/media/audio/alsa/alsa_output_unittest.cc b/media/audio/alsa/alsa_output_unittest.cc index 2aa19b4..5a7a3af 100644 --- a/media/audio/alsa/alsa_output_unittest.cc +++ b/media/audio/alsa/alsa_output_unittest.cc
@@ -85,14 +85,14 @@ // of active output streams. It is because the number of active streams // is managed inside MakeAudioOutputStream, and we don't use // MakeAudioOutputStream to create the stream in the tests. - virtual void ReleaseOutputStream(AudioOutputStream* stream) override { + void ReleaseOutputStream(AudioOutputStream* stream) override { DCHECK(stream); delete stream; } // We don't mock this method since all tests will do the same thing // and use the current task runner. - virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override { + scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override { return base::MessageLoop::current()->message_loop_proxy(); }
diff --git a/media/audio/audio_input_volume_unittest.cc b/media/audio/audio_input_volume_unittest.cc index 19c712a..d6ee313 100644 --- a/media/audio/audio_input_volume_unittest.cc +++ b/media/audio/audio_input_volume_unittest.cc
@@ -38,7 +38,13 @@ class AudioInputVolumeTest : public ::testing::Test { protected: - AudioInputVolumeTest() : audio_manager_(AudioManager::CreateForTesting()) {} + AudioInputVolumeTest() + : audio_manager_(AudioManager::CreateForTesting()) +#if defined(OS_WIN) + , com_init_(base::win::ScopedCOMInitializer::kMTA) +#endif + { + } bool HasCoreAudioAndInputDevices() { #if defined(OS_WIN) @@ -64,27 +70,27 @@ params, device_id); EXPECT_TRUE(NULL != ais); -#if defined(OS_MACOSX) - EXPECT_TRUE(ais->Open()); -#else - // Some linux devices do not support our settings and some Windows devices - // may be "currently unavailable", we may fail to open those devices. +#if defined(OS_LINUX) || defined(OS_OPENBSD) + // Some linux devices do not support our settings, we may fail to open + // those devices. if (!ais->Open()) { // Default device should always be able to be opened. EXPECT_TRUE(AudioManagerBase::kDefaultDeviceId != device_id); ais->Close(); ais = NULL; } +#elif defined(OS_WIN) || defined(OS_MACOSX) + EXPECT_TRUE(ais->Open()); #endif return ais; } + scoped_ptr<AudioManager> audio_manager_; + #if defined(OS_WIN) base::win::ScopedCOMInitializer com_init_; #endif - - scoped_ptr<AudioManager> audio_manager_; }; #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
diff --git a/media/audio/audio_manager.cc b/media/audio/audio_manager.cc index 2bbffa7..4cb3278 100644 --- a/media/audio/audio_manager.cc +++ b/media/audio/audio_manager.cc
@@ -11,14 +11,23 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/power_monitor/power_monitor.h" -#include "base/synchronization/waitable_event.h" #include "build/build_config.h" +#include "media/audio/audio_manager_factory.h" #include "media/audio/fake_audio_log_factory.h" namespace media { namespace { + +// The singleton instance of AudioManager. This is set when Create() is called. AudioManager* g_last_created = NULL; +// The singleton instance of AudioManagerFactory. This is only set if +// SetFactory() is called. If it is set when Create() is called, its +// CreateInstance() function is used to set |g_last_created|. Otherwise, the +// linked implementation of media::CreateAudioManager is used to set +// |g_last_created|. +AudioManagerFactory* g_audio_manager_factory = NULL; + // Maximum number of failed pings to the audio thread allowed. A crash will be // issued once this count is reached. We require at least two pings before // crashing to ensure unobservable power events aren't mistakenly caught (e.g., @@ -124,7 +133,7 @@ static base::LazyInstance<AudioManagerHelper>::Leaky g_helper = LAZY_INSTANCE_INITIALIZER; -} +} // namespace // Forward declaration of the platform specific AudioManager factory function. AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory); @@ -137,9 +146,29 @@ } // static +void AudioManager::SetFactory(AudioManagerFactory* factory) { + CHECK(factory); + CHECK(!g_last_created); + CHECK(!g_audio_manager_factory); + g_audio_manager_factory = factory; +} + +// static +void AudioManager::ResetFactoryForTesting() { + if (g_audio_manager_factory) { + delete g_audio_manager_factory; + g_audio_manager_factory = nullptr; + } +} + +// static AudioManager* AudioManager::Create(AudioLogFactory* audio_log_factory) { CHECK(!g_last_created); - g_last_created = CreateAudioManager(audio_log_factory); + if (g_audio_manager_factory) + g_last_created = g_audio_manager_factory->CreateInstance(audio_log_factory); + else + g_last_created = CreateAudioManager(audio_log_factory); + return g_last_created; } @@ -158,19 +187,7 @@ // static AudioManager* AudioManager::CreateForTesting() { - AudioManager* manager = Create(g_helper.Pointer()->fake_log_factory()); - - // When created for testing, always ensure all methods are ready to run (even - // if they end up called from other threads. - if (!manager->GetTaskRunner()->BelongsToCurrentThread()) { - base::WaitableEvent event(false, false); - manager->GetTaskRunner()->PostTask( - FROM_HERE, - base::Bind(&base::WaitableEvent::Signal, base::Unretained(&event))); - event.Wait(); - } - - return manager; + return Create(g_helper.Pointer()->fake_log_factory()); } // static
diff --git a/media/audio/audio_manager.h b/media/audio/audio_manager.h index 5e49b8b..5da521d 100644 --- a/media/audio/audio_manager.h +++ b/media/audio/audio_manager.h
@@ -21,13 +21,24 @@ namespace media { class AudioInputStream; +class AudioManagerFactory; class AudioOutputStream; // Manages all audio resources. Provides some convenience functions that avoid // the need to provide iterators over the existing streams. class MEDIA_EXPORT AudioManager { - public: - virtual ~AudioManager(); + public: + virtual ~AudioManager(); + + // This provides an alternative to the statically linked factory method used + // to create AudioManager. This is useful for dynamically-linked third + // party clients seeking to provide a platform-specific implementation of + // AudioManager. After this is called, all static AudioManager::Create* + // methods will return an instance of AudioManager provided by |factory|. This + // call may be made at most once per process, and before any calls to static + // AudioManager::Create* methods. This method takes ownership of |factory|, + // which must not be NULL. + static void SetFactory(AudioManagerFactory* factory); // Construct the audio manager; only one instance is allowed. The manager // will forward CreateAudioLog() calls to the provided AudioLogFactory; as @@ -44,6 +55,10 @@ // Similar to Create() except uses a FakeAudioLogFactory for testing. static AudioManager* CreateForTesting(); + // Should only be used for testing. Resets a previously-set + // AudioManagerFactory. The instance of AudioManager is not affected. + static void ResetFactoryForTesting(); + // Returns the pointer to the last created instance, or NULL if not yet // created. This is a utility method for the code outside of media directory, // like src/chrome. @@ -130,7 +145,8 @@ // Do not free the returned AudioInputStream. It is owned by AudioManager. // When you are done with it, call |Stop()| and |Close()| to release it. virtual AudioInputStream* MakeAudioInputStream( - const AudioParameters& params, const std::string& device_id) = 0; + const AudioParameters& params, + const std::string& device_id) = 0; // Returns the task runner used for audio IO. virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() = 0;
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc index 24e0883..edaabf4c 100644 --- a/media/audio/audio_manager_base.cc +++ b/media/audio/audio_manager_base.cc
@@ -83,10 +83,7 @@ audio_thread_("AudioThread"), audio_log_factory_(audio_log_factory) { #if defined(OS_WIN) - // Do not use MTA mode initalization as it causes hangs for a significant - // population of users and is not supported on Windows 8 for audio capture - // and rendering. See http://crbug.com/422522. - audio_thread_.init_com_with_mta(false); + audio_thread_.init_com_with_mta(true); #elif defined(OS_MACOSX) // CoreAudio calls must occur on the main thread of the process, which in our // case is sadly the browser UI thread. Failure to execute calls on the right
diff --git a/media/audio/audio_manager_factory.h b/media/audio/audio_manager_factory.h new file mode 100644 index 0000000..11f1338 --- /dev/null +++ b/media/audio/audio_manager_factory.h
@@ -0,0 +1,28 @@ +// 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 MEDIA_AUDIO_AUDIO_MANAGER_FACTORY_H_ +#define MEDIA_AUDIO_AUDIO_MANAGER_FACTORY_H_ + +#include "media/base/media_export.h" + +namespace media { + +class AudioManager; +class AudioLogFactory; + +// Allows a platform-specific implementation of AudioManager to be provided in +// place of the default implementation at run-time. +class MEDIA_EXPORT AudioManagerFactory { + public: + virtual ~AudioManagerFactory() {} + + // Creates an instance of AudioManager implementation. Caller owns the + // returned instance. |audio_log_factory| must outlive the returned instance. + virtual AudioManager* CreateInstance(AudioLogFactory* audio_log_factory) = 0; +}; + +} // namespace media + +#endif // MEDIA_AUDIO_AUDIO_MANAGER_FACTORY_H_
diff --git a/media/audio/audio_manager_factory_unittest.cc b/media/audio/audio_manager_factory_unittest.cc new file mode 100644 index 0000000..1d13c2e0 --- /dev/null +++ b/media/audio/audio_manager_factory_unittest.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 "base/memory/scoped_ptr.h" +#include "media/audio/audio_manager.h" +#include "media/audio/audio_manager_factory.h" +#include "media/audio/fake_audio_log_factory.h" +#include "media/audio/fake_audio_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { +namespace { + +class FakeAudioManagerFactory : public AudioManagerFactory { + public: + FakeAudioManagerFactory() {} + ~FakeAudioManagerFactory() override {} + + AudioManager* CreateInstance(AudioLogFactory* audio_log_factory) override { + // |created_instance_| is used for verifying. Ownership is transferred to + // caller. + created_instance_ = new FakeAudioManager(audio_log_factory); + return created_instance_; + } + + AudioManager* created_instance() { return created_instance_; } + + private: + AudioManager* created_instance_; +}; + +} // namespace + +// Verifies that SetFactory has the intended effect. +TEST(AudioManagerFactoryTest, CreateInstance) { + // Create an audio manager and verify that it is not null. + scoped_ptr<AudioManager> manager(AudioManager::CreateForTesting()); + ASSERT_NE(nullptr, manager.get()); + manager.reset(); + + // Set the factory. Note that ownership of |factory| is transferred to + // AudioManager. + FakeAudioManagerFactory* factory = new FakeAudioManagerFactory(); + AudioManager::SetFactory(factory); + + // Create the AudioManager instance. Verify that it matches the instance + // provided by the factory. + manager.reset(AudioManager::CreateForTesting()); + ASSERT_NE(nullptr, manager.get()); + ASSERT_EQ(factory->created_instance(), manager.get()); + + // Reset AudioManagerFactory to prevent factory from persisting to other + // tests on the same process. |manager| will reset when scope exits. + AudioManager::ResetFactoryForTesting(); +} + +} // namespace media
diff --git a/media/audio/audio_manager_unittest.cc b/media/audio/audio_manager_unittest.cc index e876dd1..26c110e 100644 --- a/media/audio/audio_manager_unittest.cc +++ b/media/audio/audio_manager_unittest.cc
@@ -33,7 +33,19 @@ // Windows. class AudioManagerTest : public ::testing::Test { protected: - AudioManagerTest() : audio_manager_(AudioManager::CreateForTesting()) {} + AudioManagerTest() + : audio_manager_(AudioManager::CreateForTesting()) +#if defined(OS_WIN) + , com_init_(base::win::ScopedCOMInitializer::kMTA) +#endif + { + // Wait for audio thread initialization to complete. Otherwise the + // enumeration type may not have been set yet. + base::WaitableEvent event(false, false); + audio_manager_->GetTaskRunner()->PostTask(FROM_HERE, base::Bind( + &base::WaitableEvent::Signal, base::Unretained(&event))); + event.Wait(); + } #if defined(OS_WIN) bool SetMMDeviceEnumeration() { @@ -43,13 +55,13 @@ if (amw->enumeration_type() == AudioManagerWin::kWaveEnumeration) return false; - amw->set_enumeration_type(AudioManagerWin::kMMDeviceEnumeration); + amw->SetEnumerationType(AudioManagerWin::kMMDeviceEnumeration); return true; } void SetWaveEnumeration() { AudioManagerWin* amw = static_cast<AudioManagerWin*>(audio_manager_.get()); - amw->set_enumeration_type(AudioManagerWin::kWaveEnumeration); + amw->SetEnumerationType(AudioManagerWin::kWaveEnumeration); } std::string GetDeviceIdFromPCMWaveInAudioInputStream(
diff --git a/media/audio/audio_power_monitor.cc b/media/audio/audio_power_monitor.cc index b0b1797..efbad6c 100644 --- a/media/audio/audio_power_monitor.cc +++ b/media/audio/audio_power_monitor.cc
@@ -7,7 +7,6 @@ #include <algorithm> #include <cmath> -#include "base/float_util.h" #include "base/logging.h" #include "base/time/time.h" #include "media/base/audio_bus.h" @@ -53,7 +52,7 @@ const std::pair<float, float> ewma_and_max = vector_math::EWMAAndMaxPower( average_power_, buffer.channel(i), num_frames, sample_weight_); // If data in audio buffer is garbage, ignore its effect on the result. - if (!base::IsFinite(ewma_and_max.first)) { + if (!std::isfinite(ewma_and_max.first)) { sum_power += average_power_; } else { sum_power += ewma_and_max.first;
diff --git a/media/audio/cras/cras_input_unittest.cc b/media/audio/cras/cras_input_unittest.cc index 4113f58..c3e3ca81 100644 --- a/media/audio/cras/cras_input_unittest.cc +++ b/media/audio/cras/cras_input_unittest.cc
@@ -41,7 +41,7 @@ // of active output streams. It is because the number of active streams // is managed inside MakeAudioInputStream, and we don't use // MakeAudioInputStream to create the stream in the tests. - virtual void ReleaseInputStream(AudioInputStream* stream) override { + void ReleaseInputStream(AudioInputStream* stream) override { DCHECK(stream); delete stream; }
diff --git a/media/audio/cras/cras_unified_unittest.cc b/media/audio/cras/cras_unified_unittest.cc index d948f223..2f29bfa5 100644 --- a/media/audio/cras/cras_unified_unittest.cc +++ b/media/audio/cras/cras_unified_unittest.cc
@@ -49,7 +49,7 @@ // of active output streams. It is because the number of active streams // is managed inside MakeAudioOutputStream, and we don't use // MakeAudioOutputStream to create the stream in the tests. - virtual void ReleaseOutputStream(AudioOutputStream* stream) override { + void ReleaseOutputStream(AudioOutputStream* stream) override { DCHECK(stream); delete stream; }
diff --git a/media/audio/openbsd/audio_manager_openbsd.h b/media/audio/openbsd/audio_manager_openbsd.h index 5bd7518..3326952 100644 --- a/media/audio/openbsd/audio_manager_openbsd.h +++ b/media/audio/openbsd/audio_manager_openbsd.h
@@ -17,26 +17,26 @@ AudioManagerOpenBSD(AudioLogFactory* audio_log_factory); // Implementation of AudioManager. - virtual bool HasAudioOutputDevices() override; - virtual bool HasAudioInputDevices() override; - virtual AudioParameters GetInputStreamParameters( + bool HasAudioOutputDevices() override; + bool HasAudioInputDevices() override; + AudioParameters GetInputStreamParameters( const std::string& device_id) override; // Implementation of AudioManagerBase. - virtual AudioOutputStream* MakeLinearOutputStream( + AudioOutputStream* MakeLinearOutputStream( const AudioParameters& params) override; - virtual AudioOutputStream* MakeLowLatencyOutputStream( + AudioOutputStream* MakeLowLatencyOutputStream( const AudioParameters& params, const std::string& device_id) override; - virtual AudioInputStream* MakeLinearInputStream( + AudioInputStream* MakeLinearInputStream( const AudioParameters& params, const std::string& device_id) override; - virtual AudioInputStream* MakeLowLatencyInputStream( + AudioInputStream* MakeLowLatencyInputStream( const AudioParameters& params, const std::string& device_id) override; protected: - virtual ~AudioManagerOpenBSD(); + ~AudioManagerOpenBSD() override; - virtual AudioParameters GetPreferredOutputStreamParameters( + AudioParameters GetPreferredOutputStreamParameters( const std::string& output_device_id, const AudioParameters& input_params) override;
diff --git a/media/audio/win/audio_device_listener_win_unittest.cc b/media/audio/win/audio_device_listener_win_unittest.cc index 9f9dc2b..49a1359 100644 --- a/media/audio/win/audio_device_listener_win_unittest.cc +++ b/media/audio/win/audio_device_listener_win_unittest.cc
@@ -25,7 +25,9 @@ class AudioDeviceListenerWinTest : public testing::Test { public: - AudioDeviceListenerWinTest() {} + AudioDeviceListenerWinTest() + : com_init_(ScopedCOMInitializer::kMTA) { + } virtual void SetUp() { if (!CoreAudioUtil::IsSupported())
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc index 674a097..72d1d72 100644 --- a/media/audio/win/audio_low_latency_input_win.cc +++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -158,11 +158,6 @@ // using SetAutomaticGainControl(). StartAgc(); - if (!MarshalComPointers()) { - HandleError(S_FALSE); - return; - } - // Create and start the thread that will drive the capturing by waiting for // capture events. capture_thread_ = @@ -177,8 +172,6 @@ hr = audio_render_client_for_loopback_->Start(); started_ = SUCCEEDED(hr); - if (!started_) - HandleError(hr); } void WASAPIAudioInputStream::Stop() { @@ -357,7 +350,7 @@ } void WASAPIAudioInputStream::Run() { - ScopedCOMInitializer com_init; + ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); // Increase the thread priority. capture_thread_->SetThreadPriority(base::ThreadPriority::REALTIME_AUDIO); @@ -376,10 +369,6 @@ LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ")."; } - // Retrieve COM pointers from the main thread. - ScopedComPtr<IAudioCaptureClient> audio_capture_client; - UnmarshalComPointers(&audio_capture_client); - // Allocate a buffer with a size that enables us to take care of cases like: // 1) The recorded buffer size is smaller, or does not match exactly with, // the selected packet size used in each callback. @@ -394,7 +383,7 @@ LARGE_INTEGER now_count; bool recording = true; bool error = false; - double volume = 0; + double volume = GetVolume(); HANDLE wait_array[2] = { stop_capture_event_.Get(), audio_samples_ready_event_.Get() }; @@ -423,9 +412,11 @@ // Retrieve the amount of data in the capture endpoint buffer, // replace it with silence if required, create callbacks for each // packet and store non-delivered data for the next event. - hr = audio_capture_client->GetBuffer( - &data_ptr, &num_frames_to_read, &flags, &device_position, - &first_audio_frame_timestamp); + hr = audio_capture_client_->GetBuffer(&data_ptr, + &num_frames_to_read, + &flags, + &device_position, + &first_audio_frame_timestamp); if (FAILED(hr)) { DLOG(ERROR) << "Failed to get data from the capture buffer"; continue; @@ -447,7 +438,7 @@ buffer_frame_index += num_frames_to_read; } - hr = audio_capture_client->ReleaseBuffer(num_frames_to_read); + hr = audio_capture_client_->ReleaseBuffer(num_frames_to_read); DLOG_IF(ERROR, FAILED(hr)) << "Failed to release capture buffer"; // Derive a delay estimate for the captured audio packet. @@ -685,11 +676,8 @@ &format_, (effects_ & AudioParameters::DUCKING) ? &kCommunicationsSessionId : NULL); - if (FAILED(hr)) { - PLOG(ERROR) << "Failed to initalize IAudioClient: " << std::hex << hr - << " : "; + if (FAILED(hr)) return hr; - } // Retrieve the length of the endpoint buffer shared between the client // and the audio engine. The buffer length determines the maximum amount @@ -780,26 +768,4 @@ return hr; } -bool WASAPIAudioInputStream::MarshalComPointers() { - DCHECK(CalledOnValidThread()); - DCHECK(!com_stream_); - HRESULT hr = CoMarshalInterThreadInterfaceInStream( - __uuidof(IAudioCaptureClient), audio_capture_client_.get(), - com_stream_.Receive()); - if (FAILED(hr)) - DLOG(ERROR) << "Marshal failed for IAudioCaptureClient: " << std::hex << hr; - DCHECK_EQ(SUCCEEDED(hr), !!com_stream_); - return SUCCEEDED(hr); -} - -void WASAPIAudioInputStream::UnmarshalComPointers( - ScopedComPtr<IAudioCaptureClient>* audio_capture_client) { - DCHECK_EQ(capture_thread_->tid(), base::PlatformThread::CurrentId()); - DCHECK(com_stream_); - HRESULT hr = CoGetInterfaceAndReleaseStream( - com_stream_.Detach(), __uuidof(IAudioCaptureClient), - audio_capture_client->ReceiveVoid()); - CHECK(SUCCEEDED(hr)); -} - } // namespace media
diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h index 00a7de7..7501405 100644 --- a/media/audio/win/audio_low_latency_input_win.h +++ b/media/audio/win/audio_low_latency_input_win.h
@@ -131,13 +131,6 @@ WAVEFORMATEX** device_format, int* effects); - // Handles sharing of COM pointers between the audio and capture threads. The - // marshal method must be called on the audio manager thread, while unmarshal - // must be called on |capture_thread_|. - bool MarshalComPointers(); - void UnmarshalComPointers( - base::win::ScopedComPtr<IAudioCaptureClient>* audio_capture_client); - // Our creator, the audio manager needs to be notified when we close. AudioManagerWin* manager_; @@ -186,17 +179,8 @@ // Pointer to the object that will receive the recorded audio samples. AudioInputCallback* sink_; - // ------------------------------------------------------ - // Warning: COM pointers must be marshaled from the audio thread to be used - // on any other thread. Do not use any of these interfaces on a thread other - // than the audio thread. See MarshalComPointers() and UnmarshalComPointers() - // for marshaling pointers to the capture thread. - - // Stream into which the COM pointers below are marshaled so that they can - // be used on another thread. - base::win::ScopedComPtr<IStream> com_stream_; - // Windows Multimedia Device (MMDevice) API interfaces. + // An IMMDevice interface which represents an audio endpoint device. base::win::ScopedComPtr<IMMDevice> endpoint_device_; @@ -214,17 +198,16 @@ // details. base::win::ScopedComPtr<IAudioClient> audio_render_client_for_loopback_; + // The IAudioCaptureClient interface enables a client to read input data + // from a capture endpoint buffer. + base::win::ScopedComPtr<IAudioCaptureClient> audio_capture_client_; + // The ISimpleAudioVolume interface enables a client to control the // master volume level of an audio session. // The volume-level is a value in the range 0.0 to 1.0. // This interface does only work with shared-mode streams. base::win::ScopedComPtr<ISimpleAudioVolume> simple_audio_volume_; - // The IAudioCaptureClient interface enables a client to read input data - // from a capture endpoint buffer. - base::win::ScopedComPtr<IAudioCaptureClient> audio_capture_client_; - // ------------------------------------------------------ - // The audio engine will signal this event each time a buffer has been // recorded. base::win::ScopedHandle audio_samples_ready_event_;
diff --git a/media/audio/win/audio_low_latency_input_win_unittest.cc b/media/audio/win/audio_low_latency_input_win_unittest.cc index 60d386d..e2e7a03 100644 --- a/media/audio/win/audio_low_latency_input_win_unittest.cc +++ b/media/audio/win/audio_low_latency_input_win_unittest.cc
@@ -62,16 +62,16 @@ data_event_.Wait(); } - virtual void OnData(AudioInputStream* stream, - const AudioBus* src, - uint32 hardware_delay_bytes, - double volume) override { + void OnData(AudioInputStream* stream, + const AudioBus* src, + uint32 hardware_delay_bytes, + double volume) override { EXPECT_NE(hardware_delay_bytes, 0u); num_received_audio_frames_ += src->frames(); data_event_.Signal(); } - virtual void OnError(AudioInputStream* stream) override { + void OnError(AudioInputStream* stream) override { error_ = true; } @@ -163,9 +163,11 @@ class AudioInputStreamWrapper { public: explicit AudioInputStreamWrapper(AudioManager* audio_manager) - : audio_man_(audio_manager), - default_params_(audio_man_->GetInputStreamParameters( - AudioManagerBase::kDefaultDeviceId)) { + : com_init_(ScopedCOMInitializer::kMTA), + audio_man_(audio_manager), + default_params_( + audio_manager->GetInputStreamParameters( + AudioManagerBase::kDefaultDeviceId)) { EXPECT_EQ(format(), AudioParameters::AUDIO_PCM_LOW_LATENCY); frames_per_buffer_ = default_params_.frames_per_buffer(); // We expect the default buffer size to be a 10ms buffer. @@ -205,6 +207,7 @@ return ais; } + ScopedCOMInitializer com_init_; AudioManager* audio_man_; const AudioParameters default_params_; int frames_per_buffer_; @@ -251,24 +254,17 @@ DISALLOW_COPY_AND_ASSIGN(ScopedAudioInputStream); }; -class WinAudioInputTest : public testing::Test { - public: - WinAudioInputTest() : audio_manager_(AudioManager::CreateForTesting()) {} - ~WinAudioInputTest() override {} - - protected: - ScopedCOMInitializer com_init_; - scoped_ptr<AudioManager> audio_manager_; -}; - // Verify that we can retrieve the current hardware/mixing sample rate // for all available input devices. -TEST_F(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); +TEST(WinAudioInputTest, WASAPIAudioInputStreamHardwareSampleRate) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get())); + + ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); // Retrieve a list of all available input devices. media::AudioDeviceNames device_names; - audio_manager_->GetAudioInputDeviceNames(&device_names); + audio_manager->GetAudioInputDeviceNames(&device_names); // Scan all available input devices and repeat the same test for all of them. for (media::AudioDeviceNames::const_iterator it = device_names.begin(); @@ -281,27 +277,30 @@ } // Test Create(), Close() calling sequence. -TEST_F(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); +TEST(WinAudioInputTest, WASAPIAudioInputStreamCreateAndClose) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get())); + CreateDefaultAudioInputStream(audio_manager.get())); ais.Close(); } // Test Open(), Close() calling sequence. -TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); +TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenAndClose) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get())); + CreateDefaultAudioInputStream(audio_manager.get())); EXPECT_TRUE(ais->Open()); ais.Close(); } // Test Open(), Start(), Close() calling sequence. -TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); +TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartAndClose) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get())); + CreateDefaultAudioInputStream(audio_manager.get())); EXPECT_TRUE(ais->Open()); MockAudioInputCallback sink; ais->Start(&sink); @@ -309,10 +308,11 @@ } // Test Open(), Start(), Stop(), Close() calling sequence. -TEST_F(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); +TEST(WinAudioInputTest, WASAPIAudioInputStreamOpenStartStopAndClose) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get())); + CreateDefaultAudioInputStream(audio_manager.get())); EXPECT_TRUE(ais->Open()); MockAudioInputCallback sink; ais->Start(&sink); @@ -321,10 +321,11 @@ } // Test some additional calling sequences. -TEST_F(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); +TEST(WinAudioInputTest, WASAPIAudioInputStreamMiscCallingSequences) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get())); ScopedAudioInputStream ais( - CreateDefaultAudioInputStream(audio_manager_.get())); + CreateDefaultAudioInputStream(audio_manager.get())); WASAPIAudioInputStream* wais = static_cast<WASAPIAudioInputStream*>(ais.get()); @@ -348,8 +349,9 @@ ais.Close(); } -TEST_F(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); +TEST(WinAudioInputTest, WASAPIAudioInputStreamTestPacketSizes) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get())); int count = 0; base::MessageLoopForUI loop; @@ -358,7 +360,7 @@ // Create default WASAPI input stream which records in stereo using // the shared mixing rate. The default buffer size is 10ms. - AudioInputStreamWrapper aisw(audio_manager_.get()); + AudioInputStreamWrapper aisw(audio_manager.get()); ScopedAudioInputStream ais(aisw.Create()); EXPECT_TRUE(ais->Open()); @@ -417,20 +419,21 @@ } // Test that we can capture a stream in loopback. -TEST_F(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { - ABORT_AUDIO_TEST_IF_NOT(audio_manager_->HasAudioOutputDevices() && +TEST(WinAudioInputTest, WASAPIAudioInputStreamLoopback) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(audio_manager->HasAudioOutputDevices() && CoreAudioUtil::IsSupported()); - AudioParameters params = audio_manager_->GetInputStreamParameters( + AudioParameters params = audio_manager->GetInputStreamParameters( AudioManagerBase::kLoopbackInputDeviceId); EXPECT_EQ(params.effects(), 0); AudioParameters output_params = - audio_manager_->GetOutputStreamParameters(std::string()); + audio_manager->GetOutputStreamParameters(std::string()); EXPECT_EQ(params.sample_rate(), output_params.sample_rate()); EXPECT_EQ(params.channel_layout(), output_params.channel_layout()); - ScopedAudioInputStream stream(audio_manager_->MakeAudioInputStream( + ScopedAudioInputStream stream(audio_manager->MakeAudioInputStream( params, AudioManagerBase::kLoopbackInputDeviceId)); ASSERT_TRUE(stream->Open()); FakeAudioInputCallback sink; @@ -450,15 +453,16 @@ // To include disabled tests in test execution, just invoke the test program // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS // environment variable to a value greater than 0. -TEST_F(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager_.get())); +TEST(WinAudioInputTest, DISABLED_WASAPIAudioInputStreamRecordToFile) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndInputDevices(audio_manager.get())); // Name of the output PCM file containing captured data. The output file // will be stored in the directory containing 'media_unittests.exe'. // Example of full name: \src\build\Debug\out_stereo_10sec.pcm. const char* file_name = "out_stereo_10sec.pcm"; - AudioInputStreamWrapper aisw(audio_manager_.get()); + AudioInputStreamWrapper aisw(audio_manager.get()); ScopedAudioInputStream ais(aisw.Create()); EXPECT_TRUE(ais->Open());
diff --git a/media/audio/win/audio_low_latency_output_win.cc b/media/audio/win/audio_low_latency_output_win.cc index a9d637c..f7b31a3 100644 --- a/media/audio/win/audio_low_latency_output_win.cc +++ b/media/audio/win/audio_low_latency_output_win.cc
@@ -249,11 +249,6 @@ } num_written_frames_ = endpoint_buffer_size_frames_; - if (!MarshalComPointers()) { - callback->OnError(this); - return; - } - // Create and start the thread that will drive the rendering by waiting for // render events. render_thread_.reset( @@ -338,7 +333,7 @@ } void WASAPIAudioOutputStream::Run() { - ScopedCOMInitializer com_init; + ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); // Increase the thread priority. render_thread_->SetThreadPriority(base::ThreadPriority::REALTIME_AUDIO); @@ -357,12 +352,6 @@ LOG(WARNING) << "Failed to enable MMCSS (error code=" << err << ")."; } - // Retrieve COM pointers from the main thread. - ScopedComPtr<IAudioClient> audio_client; - ScopedComPtr<IAudioRenderClient> audio_render_client; - ScopedComPtr<IAudioClock> audio_clock; - UnmarshalComPointers(&audio_client, &audio_render_client, &audio_clock); - HRESULT hr = S_FALSE; bool playing = true; @@ -373,7 +362,7 @@ // The device frequency is the frequency generated by the hardware clock in // the audio device. The GetFrequency() method reports a constant frequency. - hr = audio_clock->GetFrequency(&device_frequency); + hr = audio_clock_->GetFrequency(&device_frequency); error = FAILED(hr); PLOG_IF(ERROR, error) << "Failed to acquire IAudioClock interface: " << std::hex << hr; @@ -394,9 +383,7 @@ break; case WAIT_OBJECT_0 + 1: // |audio_samples_render_event_| has been set. - error = !RenderAudioFromSource(device_frequency, audio_client.get(), - audio_render_client.get(), - audio_clock.get()); + error = !RenderAudioFromSource(device_frequency); break; default: error = true; @@ -404,11 +391,11 @@ } } - if (playing && error && audio_client) { + if (playing && error) { // Stop audio rendering since something has gone wrong in our main thread // loop. Note that, we are still in a "started" state, hence a Stop() call // is required to join the thread properly. - audio_client->Stop(); + audio_client_->Stop(); PLOG(ERROR) << "WASAPI rendering failed."; } @@ -418,11 +405,7 @@ } } -bool WASAPIAudioOutputStream::RenderAudioFromSource( - UINT64 device_frequency, - IAudioClient* audio_client, - IAudioRenderClient* audio_render_client, - IAudioClock* audio_clock) { +bool WASAPIAudioOutputStream::RenderAudioFromSource(UINT64 device_frequency) { TRACE_EVENT0("audio", "RenderAudioFromSource"); HRESULT hr = S_FALSE; @@ -437,7 +420,7 @@ if (share_mode_ == AUDCLNT_SHAREMODE_SHARED) { // Get the padding value which represents the amount of rendering // data that is queued up to play in the endpoint buffer. - hr = audio_client->GetCurrentPadding(&num_queued_frames); + hr = audio_client_->GetCurrentPadding(&num_queued_frames); num_available_frames = endpoint_buffer_size_frames_ - num_queued_frames; if (FAILED(hr)) { @@ -479,7 +462,8 @@ for (size_t n = 0; n < num_packets; ++n) { // Grab all available space in the rendering endpoint buffer // into which the client can write a data packet. - hr = audio_render_client->GetBuffer(packet_size_frames_, &audio_data); + hr = audio_render_client_->GetBuffer(packet_size_frames_, + &audio_data); if (FAILED(hr)) { DLOG(ERROR) << "Failed to use rendering audio buffer: " << std::hex << hr; @@ -493,7 +477,7 @@ // unit at the render side. UINT64 position = 0; uint32 audio_delay_bytes = 0; - hr = audio_clock->GetPosition(&position, NULL); + hr = audio_clock_->GetPosition(&position, NULL); if (SUCCEEDED(hr)) { // Stream position of the sample that is currently playing // through the speaker. @@ -533,7 +517,7 @@ // Render silence if we were not able to fill up the buffer totally. DWORD flags = (num_filled_bytes < packet_size_bytes_) ? AUDCLNT_BUFFERFLAGS_SILENT : 0; - audio_render_client->ReleaseBuffer(packet_size_frames_, flags); + audio_render_client_->ReleaseBuffer(packet_size_frames_, flags); num_written_frames_ += packet_size_frames_; } @@ -638,73 +622,4 @@ source_ = NULL; } -bool WASAPIAudioOutputStream::MarshalComPointers() { - DCHECK_EQ(creating_thread_id_, base::PlatformThread::CurrentId()); - DCHECK(!com_stream_); - - ScopedComPtr<IStream> com_stream; - HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, com_stream.Receive()); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to create stream for marshaling COM pointers."; - return false; - } - - hr = CoMarshalInterface(com_stream.get(), __uuidof(IAudioClient), - audio_client_.get(), MSHCTX_INPROC, NULL, - MSHLFLAGS_NORMAL); - if (FAILED(hr)) { - DLOG(ERROR) << "Marshal failed for IAudioClient: " << std::hex << hr; - return false; - } - - hr = CoMarshalInterface(com_stream.get(), __uuidof(IAudioRenderClient), - audio_render_client_.get(), MSHCTX_INPROC, NULL, - MSHLFLAGS_NORMAL); - if (FAILED(hr)) { - DLOG(ERROR) << "Marshal failed for IAudioRenderClient: " << std::hex << hr; - return false; - } - - hr = CoMarshalInterface(com_stream.get(), __uuidof(IAudioClock), - audio_clock_.get(), MSHCTX_INPROC, NULL, - MSHLFLAGS_NORMAL); - if (FAILED(hr)) { - DLOG(ERROR) << "Marshal failed for IAudioClock: " << std::hex << hr; - return false; - } - - LARGE_INTEGER pos = {0}; - hr = com_stream->Seek(pos, STREAM_SEEK_SET, NULL); - if (FAILED(hr)) { - DLOG(ERROR) << "Failed to seek IStream for marshaling: " << std::hex << hr; - return false; - } - - com_stream_ = com_stream.Pass(); - return true; -} - -void WASAPIAudioOutputStream::UnmarshalComPointers( - ScopedComPtr<IAudioClient>* audio_client, - ScopedComPtr<IAudioRenderClient>* audio_render_client, - ScopedComPtr<IAudioClock>* audio_clock) { - DCHECK_EQ(render_thread_->tid(), base::PlatformThread::CurrentId()); - - DCHECK(com_stream_); - ScopedComPtr<IStream> com_stream; - com_stream = com_stream_.Pass(); - - HRESULT hr = CoUnmarshalInterface(com_stream.get(), __uuidof(IAudioClient), - audio_client->ReceiveVoid()); - CHECK(SUCCEEDED(hr)); - - hr = CoUnmarshalInterface(com_stream.get(), __uuidof(IAudioRenderClient), - audio_render_client->ReceiveVoid()); - CHECK(SUCCEEDED(hr)); - - hr = CoUnmarshalInterface(com_stream.get(), __uuidof(IAudioClock), - audio_clock->ReceiveVoid()); - CHECK(SUCCEEDED(hr)); -} - } // namespace media
diff --git a/media/audio/win/audio_low_latency_output_win.h b/media/audio/win/audio_low_latency_output_win.h index 30e791b..9d612b3 100644 --- a/media/audio/win/audio_low_latency_output_win.h +++ b/media/audio/win/audio_low_latency_output_win.h
@@ -157,10 +157,7 @@ // Checks available amount of space in the endpoint buffer and reads // data from the client to fill up the buffer without causing audio // glitches. - bool RenderAudioFromSource(UINT64 device_frequency, - IAudioClient* thread_audio_client, - IAudioRenderClient* thread_audio_render_client, - IAudioClock* thread_audio_clock); + bool RenderAudioFromSource(UINT64 device_frequency); // Called when the device will be opened in exclusive mode and use the // application specified format. @@ -175,15 +172,6 @@ // |source_| is set to NULL. void StopThread(); - // Handles sharing of COM pointers between the audio and render threads. The - // marshal method must be called on the audio manager thread, while unmarshal - // must be called on |render_thread_|. - bool MarshalComPointers(); - void UnmarshalComPointers( - base::win::ScopedComPtr<IAudioClient>* audio_client, - base::win::ScopedComPtr<IAudioRenderClient>* audio_render_client, - base::win::ScopedComPtr<IAudioClock>* audio_clock); - // Contains the thread ID of the creating thread. base::PlatformThreadId creating_thread_id_; @@ -233,18 +221,6 @@ // Pointer to the client that will deliver audio samples to be played out. AudioSourceCallback* source_; - // ------------------------------------------------------ - // Warning: COM pointers must be marshaled from the audio thread to be used - // on any other thread. Do not use any of these interfaces on a thread other - // than the audio thread. See MarshalComPointers() and UnmarshalComPointers() - // for marshaling pointers to the render thread. - - // Stream into which the COM pointers below are marshaled so that they can - // be used on another thread. - base::win::ScopedComPtr<IStream> com_stream_; - - // Windows Audio Session API (WASAPI) interfaces. - // An IAudioClient interface which enables a client to create and initialize // an audio stream between an audio application and the audio engine. base::win::ScopedComPtr<IAudioClient> audio_client_; @@ -253,9 +229,6 @@ // data to a rendering endpoint buffer. base::win::ScopedComPtr<IAudioRenderClient> audio_render_client_; - base::win::ScopedComPtr<IAudioClock> audio_clock_; - // ------------------------------------------------------ - // The audio engine will signal this event each time a buffer becomes // ready to be filled by the client. base::win::ScopedHandle audio_samples_render_event_; @@ -266,6 +239,8 @@ // Container for retrieving data from AudioSourceCallback::OnMoreData(). scoped_ptr<AudioBus> audio_bus_; + base::win::ScopedComPtr<IAudioClock> audio_clock_; + DISALLOW_COPY_AND_ASSIGN(WASAPIAudioOutputStream); };
diff --git a/media/audio/win/audio_low_latency_output_win_unittest.cc b/media/audio/win/audio_low_latency_output_win_unittest.cc index 193c0821..afd565a9 100644 --- a/media/audio/win/audio_low_latency_output_win_unittest.cc +++ b/media/audio/win/audio_low_latency_output_win_unittest.cc
@@ -6,7 +6,6 @@ #include <mmsystem.h> #include "base/basictypes.h" -#include "base/bind.h" #include "base/environment.h" #include "base/files/file_util.h" #include "base/memory/scoped_ptr.h" @@ -227,24 +226,14 @@ return aos; } -class WASAPIAudioOutputStreamTest : public testing::Test { - public: - WASAPIAudioOutputStreamTest() - : audio_manager_(AudioManager::CreateForTesting()) {} - ~WASAPIAudioOutputStreamTest() override {} - - protected: - ScopedCOMInitializer com_init_; - scoped_ptr<AudioManager> audio_manager_; -}; - // Verify that we can retrieve the current hardware/mixing sample rate // for the default audio device. // TODO(henrika): modify this test when we support full device enumeration. -TEST_F(WASAPIAudioOutputStreamTest, HardwareSampleRate) { +TEST(WASAPIAudioOutputStreamTest, HardwareSampleRate) { // Skip this test in exclusive mode since the resulting rate is only utilized // for shared mode streams. - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) && + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) && ExclusiveModeIsEnabled()); // Default device intended for games, system notification sounds, @@ -255,24 +244,27 @@ } // Test Create(), Close() calling sequence. -TEST_F(WASAPIAudioOutputStreamTest, CreateAndClose) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); - AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get()); +TEST(WASAPIAudioOutputStreamTest, CreateAndClose) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get())); + AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); aos->Close(); } // Test Open(), Close() calling sequence. -TEST_F(WASAPIAudioOutputStreamTest, OpenAndClose) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); - AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get()); +TEST(WASAPIAudioOutputStreamTest, OpenAndClose) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get())); + AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); EXPECT_TRUE(aos->Open()); aos->Close(); } // Test Open(), Start(), Close() calling sequence. -TEST_F(WASAPIAudioOutputStreamTest, OpenStartAndClose) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); - AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get()); +TEST(WASAPIAudioOutputStreamTest, OpenStartAndClose) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get())); + AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); EXPECT_TRUE(aos->Open()); MockAudioSourceCallback source; EXPECT_CALL(source, OnError(aos)) @@ -282,9 +274,10 @@ } // Test Open(), Start(), Stop(), Close() calling sequence. -TEST_F(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); - AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get()); +TEST(WASAPIAudioOutputStreamTest, OpenStartStopAndClose) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get())); + AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); EXPECT_TRUE(aos->Open()); MockAudioSourceCallback source; EXPECT_CALL(source, OnError(aos)) @@ -295,9 +288,10 @@ } // Test SetVolume(), GetVolume() -TEST_F(WASAPIAudioOutputStreamTest, Volume) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); - AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get()); +TEST(WASAPIAudioOutputStreamTest, Volume) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get())); + AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); // Initial volume should be full volume (1.0). double volume = 0.0; @@ -330,10 +324,11 @@ } // Test some additional calling sequences. -TEST_F(WASAPIAudioOutputStreamTest, MiscCallingSequences) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); +TEST(WASAPIAudioOutputStreamTest, MiscCallingSequences) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get())); - AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager_.get()); + AudioOutputStream* aos = CreateDefaultAudioOutputStream(audio_manager.get()); WASAPIAudioOutputStream* waos = static_cast<WASAPIAudioOutputStream*>(aos); // Open(), Open() is a valid calling sequence (second call does nothing). @@ -368,15 +363,16 @@ } // Use preferred packet size and verify that rendering starts. -TEST_F(WASAPIAudioOutputStreamTest, ValidPacketSize) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); +TEST(WASAPIAudioOutputStreamTest, ValidPacketSize) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get())); base::MessageLoopForUI loop; MockAudioSourceCallback source; // Create default WASAPI output stream which plays out in stereo using // the shared mixing rate. The default buffer size is 10ms. - AudioOutputStreamWrapper aosw(audio_manager_.get()); + AudioOutputStreamWrapper aosw(audio_manager.get()); AudioOutputStream* aos = aosw.Create(); EXPECT_TRUE(aos->Open()); @@ -405,10 +401,11 @@ // with --gtest_also_run_disabled_tests or set the GTEST_ALSO_RUN_DISABLED_TESTS // environment variable to a value greater than 0. // The test files are approximately 20 seconds long. -TEST_F(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get())); +TEST(WASAPIAudioOutputStreamTest, DISABLED_ReadFromStereoFile) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get())); - AudioOutputStreamWrapper aosw(audio_manager_.get()); + AudioOutputStreamWrapper aosw(audio_manager.get()); AudioOutputStream* aos = aosw.Create(); EXPECT_TRUE(aos->Open()); @@ -453,11 +450,12 @@ // certain set of audio parameters and a sample rate of 48kHz. // The expected outcomes of each setting in this test has been derived // manually using log outputs (--v=1). -TEST_F(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) && +TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt48kHz) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) && ExclusiveModeIsEnabled()); - AudioOutputStreamWrapper aosw(audio_manager_.get()); + AudioOutputStreamWrapper aosw(audio_manager.get()); // 10ms @ 48kHz shall work. // Note that, this is the same size as we can use for shared-mode streaming @@ -500,11 +498,12 @@ // certain set of audio parameters and a sample rate of 44.1kHz. // The expected outcomes of each setting in this test has been derived // manually using log outputs (--v=1). -TEST_F(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) && +TEST(WASAPIAudioOutputStreamTest, ExclusiveModeBufferSizesAt44kHz) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) && ExclusiveModeIsEnabled()); - AudioOutputStreamWrapper aosw(audio_manager_.get()); + AudioOutputStreamWrapper aosw(audio_manager.get()); // 10ms @ 44.1kHz does not work due to misalignment. // This test will propose an aligned buffer size of 10.1587ms. @@ -554,8 +553,9 @@ // Verify that we can open and start the output stream in exclusive mode at // the lowest possible delay at 48kHz. -TEST_F(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) { - ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager_.get()) && +TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt48kHz) { + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); + ABORT_AUDIO_TEST_IF_NOT(HasCoreAudioAndOutputDevices(audio_manager.get()) && ExclusiveModeIsEnabled()); base::MessageLoopForUI loop; @@ -563,7 +563,7 @@ // Create exclusive-mode WASAPI output stream which plays out in stereo // using the minimum buffer size at 48kHz sample rate. - AudioOutputStreamWrapper aosw(audio_manager_.get()); + AudioOutputStreamWrapper aosw(audio_manager.get()); AudioOutputStream* aos = aosw.Create(48000, 160); EXPECT_TRUE(aos->Open()); @@ -588,15 +588,16 @@ // Verify that we can open and start the output stream in exclusive mode at // the lowest possible delay at 44.1kHz. -TEST_F(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) { +TEST(WASAPIAudioOutputStreamTest, ExclusiveModeMinBufferSizeAt44kHz) { ABORT_AUDIO_TEST_IF_NOT(ExclusiveModeIsEnabled()); + scoped_ptr<AudioManager> audio_manager(AudioManager::CreateForTesting()); base::MessageLoopForUI loop; MockAudioSourceCallback source; // Create exclusive-mode WASAPI output stream which plays out in stereo // using the minimum buffer size at 44.1kHz sample rate. - AudioOutputStreamWrapper aosw(audio_manager_.get()); + AudioOutputStreamWrapper aosw(audio_manager.get()); AudioOutputStream* aos = aosw.Create(44100, 160); EXPECT_TRUE(aos->Open());
diff --git a/media/audio/win/audio_manager_win.h b/media/audio/win/audio_manager_win.h index afd1ef9b..9826566 100644 --- a/media/audio/win/audio_manager_win.h +++ b/media/audio/win/audio_manager_win.h
@@ -64,7 +64,9 @@ EnumerationType enumeration_type_; EnumerationType enumeration_type() { return enumeration_type_; } - void set_enumeration_type(EnumerationType type) { enumeration_type_ = type; } + void SetEnumerationType(EnumerationType type) { + enumeration_type_ = type; + } inline bool core_audio_supported() const { return enumeration_type_ == kMMDeviceEnumeration;
diff --git a/media/audio/win/audio_output_win_unittest.cc b/media/audio/win/audio_output_win_unittest.cc index c1dc5b4..93454fc9 100644 --- a/media/audio/win/audio_output_win_unittest.cc +++ b/media/audio/win/audio_output_win_unittest.cc
@@ -427,7 +427,7 @@ ABORT_AUDIO_TEST_IF_NOT(audio_man->HasAudioOutputDevices()); // The WASAPI API requires a correct COM environment. - ScopedCOMInitializer com_init; + ScopedCOMInitializer com_init(ScopedCOMInitializer::kMTA); // Use 10 ms buffer size for WASAPI and 50 ms buffer size for Wave. // Take the existing native sample rate into account.
diff --git a/media/audio/win/core_audio_util_win.cc b/media/audio/win/core_audio_util_win.cc index 4f72564..bf1c56b 100644 --- a/media/audio/win/core_audio_util_win.cc +++ b/media/audio/win/core_audio_util_win.cc
@@ -168,22 +168,21 @@ return hr; } -static ScopedComPtr<IMMDeviceEnumerator> CreateDeviceEnumeratorInternal() { +static ScopedComPtr<IMMDeviceEnumerator> CreateDeviceEnumeratorInternal( + bool allow_reinitialize) { ScopedComPtr<IMMDeviceEnumerator> device_enumerator; HRESULT hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER); - if (hr == CO_E_NOTINITIALIZED) { + if (hr == CO_E_NOTINITIALIZED && allow_reinitialize) { LOG(ERROR) << "CoCreateInstance fails with CO_E_NOTINITIALIZED"; // We have seen crashes which indicates that this method can in fact // fail with CO_E_NOTINITIALIZED in combination with certain 3rd party // modules. Calling CoInitializeEx is an attempt to resolve the reported // issues. See http://crbug.com/378465 for details. - hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); if (SUCCEEDED(hr)) { - hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), NULL, - CLSCTX_INPROC_SERVER); - } else { - LOG(ERROR) << "CoCreateInstance still failed! " << std::hex << hr; + hr = device_enumerator.CreateInstance(__uuidof(MMDeviceEnumerator), + NULL, CLSCTX_INPROC_SERVER); } } return device_enumerator; @@ -217,7 +216,7 @@ // that it is possible to a create the IMMDeviceEnumerator interface. If this // works as well we should be home free. ScopedComPtr<IMMDeviceEnumerator> device_enumerator = - CreateDeviceEnumeratorInternal(); + CreateDeviceEnumeratorInternal(false); if (!device_enumerator) { LOG(ERROR) << "Failed to create Core Audio device enumerator on thread with ID " @@ -276,7 +275,7 @@ ScopedComPtr<IMMDeviceEnumerator> CoreAudioUtil::CreateDeviceEnumerator() { DCHECK(IsSupported()); ScopedComPtr<IMMDeviceEnumerator> device_enumerator = - CreateDeviceEnumeratorInternal(); + CreateDeviceEnumeratorInternal(true); CHECK(device_enumerator); return device_enumerator; }
diff --git a/media/audio/win/core_audio_util_win_unittest.cc b/media/audio/win/core_audio_util_win_unittest.cc index 1a24e5d2..31f91e9 100644 --- a/media/audio/win/core_audio_util_win_unittest.cc +++ b/media/audio/win/core_audio_util_win_unittest.cc
@@ -19,10 +19,13 @@ class CoreAudioUtilWinTest : public ::testing::Test { protected: - // The test runs on a COM thread in the singlethreaded apartment (STA). + // The test runs on a COM thread in the multithreaded apartment (MTA). // If we don't initialize the COM library on a thread before using COM, // all function calls will return CO_E_NOTINITIALIZED. - CoreAudioUtilWinTest() { DCHECK(com_init_.succeeded()); } + CoreAudioUtilWinTest() + : com_init_(ScopedCOMInitializer::kMTA) { + DCHECK(com_init_.succeeded()); + } virtual ~CoreAudioUtilWinTest() {} bool DevicesAvailable() {
diff --git a/media/audio/win/device_enumeration_win.h b/media/audio/win/device_enumeration_win.h index e6485db0..e61a3318 100644 --- a/media/audio/win/device_enumeration_win.h +++ b/media/audio/win/device_enumeration_win.h
@@ -17,7 +17,7 @@ // Example record in the output list: // - device_name: "Microphone (Realtek High Definition Audio)". // - unique_id: "{0.0.1.00000000}.{8db6020f-18e3-4f25-b6f5-7726c9122574}" -// This method must be called from a COM thread using STA. +// This method must be called from a COM thread using MTA. bool GetInputDeviceNamesWin(media::AudioDeviceNames* device_names); bool GetOutputDeviceNamesWin(media::AudioDeviceNames* device_names);
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index 1f05d4467..8a50fbe 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -10,7 +10,8 @@ import("//media/media_options.gni") source_set("base") { - visibility = [ "//media/*" ] + # This is part of the media component. + visibility = [ "//media" ] sources = [ "audio_block_fifo.cc", "audio_block_fifo.h", @@ -187,12 +188,19 @@ "yuv_convert.cc", "yuv_convert.h", ] + + allow_circular_includes_from = [] defines = [] + public_deps = [] deps = [ + "//ui/events:events_base", "//skia", ] libs = [] - configs += [ "//media:media_config" ] + configs += [ + "//media:media_config", + "//media:media_implementation", + ] if (media_use_ffmpeg) { sources += [ @@ -203,6 +211,12 @@ "media_file_checker.cc", "media_file_checker.h", ] + if (is_win) { + sources += [ "media_win.cc" ] + } else if (is_posix) { + sources += [ "media_posix.cc" ] + } + deps += [ "//third_party/ffmpeg" ] } @@ -217,10 +231,13 @@ if (is_android) { sources += [ "media_stub.cc" ] - } else if (is_win) { - sources += [ "media_win.cc" ] - } else if (is_posix) { - sources += [ "media_posix.cc" ] + public_deps = [ + "//media/base/android", + "//media/base/android:media_java", + "//media/base/android:media_jni_headers", + "//media/base/android:video_capture_jni_headers", + ] + allow_circular_includes_from += [ "//media/base/android" ] } if (is_linux && use_x11) { @@ -272,28 +289,30 @@ defines = [ "MEDIA_FOR_CAST_IOS" ] } -source_set("base_for_cast_ios") { - sources = [ - "simd/convert_rgb_to_yuv.h", - "simd/convert_rgb_to_yuv_c.cc", - "simd/convert_yuv_to_rgb.h", - "simd/convert_yuv_to_rgb_c.cc", - "simd/filter_yuv.h", - "simd/filter_yuv_c.cc", - "video_frame.cc", - "video_frame.h", - "video_frame_metadata.cc", - "video_frame_metadata.h", - "video_util.cc", - "video_util.h", - "yuv_convert.cc", - "yuv_convert.h", - ] - configs += [ - "//build/config/compiler:no_size_t_to_int_warning", - "//media:media_config", - ] - all_dependent_configs = [ ":base_for_cast_ios_dependent_config" ] +if (is_ios) { + source_set("base_for_cast_ios") { + sources = [ + "simd/convert_rgb_to_yuv.h", + "simd/convert_rgb_to_yuv_c.cc", + "simd/convert_yuv_to_rgb.h", + "simd/convert_yuv_to_rgb_c.cc", + "simd/filter_yuv.h", + "simd/filter_yuv_c.cc", + "video_frame.cc", + "video_frame.h", + "video_frame_metadata.cc", + "video_frame_metadata.h", + "video_util.cc", + "video_util.h", + "yuv_convert.cc", + "yuv_convert.h", + ] + configs += [ + "//build/config/compiler:no_size_t_to_int_warning", + "//media:media_config", + ] + all_dependent_configs = [ ":base_for_cast_ios_dependent_config" ] + } } source_set("test_support") { @@ -378,9 +397,9 @@ "//media:media_config", ] deps = [ - ":base", ":test_support", "//gpu/command_buffer/common", + "//media", "//skia", "//testing/gmock", "//testing/gtest", @@ -416,8 +435,8 @@ ] configs += [ "//media:media_config" ] deps = [ - ":base", ":test_support", + "//media", "//testing/gmock", "//testing/gtest", ] @@ -438,7 +457,10 @@ "simd/convert_rgb_to_yuv_ssse3.cc", "simd/filter_yuv_sse2.cc", ] - configs += [ "//media:media_config" ] + configs += [ + "//media:media_config", + "//media:media_implementation", + ] if (!is_win) { cflags = [ "-msse2" ] }
diff --git a/media/base/android/BUILD.gn b/media/base/android/BUILD.gn index f6f910e..6108389 100644 --- a/media/base/android/BUILD.gn +++ b/media/base/android/BUILD.gn
@@ -45,11 +45,13 @@ "webaudio_media_codec_bridge.h", "webaudio_media_codec_info.h", ] - configs += [ "//media:media_config" ] + configs += [ + "//media:media_config", + "//media:media_implementation", + ] deps = [ ":media_jni_headers", "//media:shared_memory_support", - "//media/base", "//third_party/widevine/cdm:version_h", "//ui/gl", "//url",
diff --git a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java index 2f80b961..c581131f 100644 --- a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java +++ b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java
@@ -20,6 +20,7 @@ import org.chromium.base.JNINamespace; import java.nio.ByteBuffer; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -75,6 +76,16 @@ static final int MIDI_SUBCLASS = 3; /** + * The request type to request a USB descriptor. + */ + static final int REQUEST_GET_DESCRIPTOR = 0x06; + + /** + * The STRING descriptor type. + */ + static final int STRING_DESCRIPTOR_TYPE = 0x03; + + /** * Constructs a UsbMidiDeviceAndroid. * @param manager * @param device The USB device which this object is assocated with. @@ -258,6 +269,27 @@ } /** + * Returns the string descriptor bytes for the given index + * @param index index of the descriptor + * @return the string descriptor bytes for the given index. + */ + @CalledByNative + byte[] getStringDescriptor(int index) { + if (mConnection == null) { + return new byte[0]; + } + byte[] buffer = new byte[255]; + int type = UsbConstants.USB_DIR_IN | UsbConstants.USB_TYPE_STANDARD; + int request = REQUEST_GET_DESCRIPTOR; + int value = (STRING_DESCRIPTOR_TYPE << 8) | index; + int read = mConnection.controlTransfer(type, request, value, 0, buffer, buffer.length, 0); + if (read < 0) { + return new byte[0]; + } + return Arrays.copyOf(buffer, read); + } + + /** * Closes the device connection. */ @CalledByNative
diff --git a/media/base/android/media_drm_bridge.cc b/media/base/android/media_drm_bridge.cc index 0e31818..0aaeef4 100644 --- a/media/base/android/media_drm_bridge.cc +++ b/media/base/android/media_drm_bridge.cc
@@ -15,6 +15,8 @@ #include "base/location.h" #include "base/logging.h" #include "base/message_loop/message_loop_proxy.h" +#include "base/numerics/safe_conversions.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/sys_byteorder.h" #include "base/sys_info.h" @@ -92,13 +94,12 @@ // 1, If multiple PSSH boxes are found,the "Data" of the first matching PSSH box // will be set in |pssh_data|. // 2, Only PSSH and TENC boxes are allowed in |data|. TENC boxes are skipped. -bool GetPsshData(const uint8* data, - int data_size, +bool GetPsshData(const std::vector<uint8_t>& data, const UUID& uuid, std::vector<uint8>* pssh_data) { - const uint8* cur = data; - const uint8* data_end = data + data_size; - int bytes_left = data_size; + int bytes_left = base::checked_cast<int>(data.size()); + const uint8_t* cur = &data[0]; + const uint8_t* data_end = cur + bytes_left; while (bytes_left > 0) { const uint8* box_head = cur; @@ -427,8 +428,7 @@ } void MediaDrmBridge::SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) { promise->reject(NOT_SUPPORTED_ERROR, 0, "SetServerCertificate() is not supported."); @@ -437,8 +437,7 @@ void MediaDrmBridge::CreateSessionAndGenerateRequest( SessionType session_type, media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) { DVLOG(1) << __FUNCTION__; @@ -456,15 +455,15 @@ if (std::equal(scheme_uuid_.begin(), scheme_uuid_.end(), kWidevineUuid) && init_data_type == media::EmeInitDataType::CENC) { std::vector<uint8> pssh_data; - if (!GetPsshData(init_data, init_data_length, scheme_uuid_, &pssh_data)) { + if (!GetPsshData(init_data, scheme_uuid_, &pssh_data)) { promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid PSSH data."); return; } - j_init_data = - base::android::ToJavaByteArray(env, &pssh_data[0], pssh_data.size()); + j_init_data = base::android::ToJavaByteArray( + env, vector_as_array(&pssh_data), pssh_data.size()); } else { - j_init_data = - base::android::ToJavaByteArray(env, init_data, init_data_length); + j_init_data = base::android::ToJavaByteArray( + env, vector_as_array(&init_data), init_data.size()); } ScopedJavaLocalRef<jstring> j_mime = @@ -483,14 +482,13 @@ void MediaDrmBridge::UpdateSession( const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) { DVLOG(1) << __FUNCTION__; JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jbyteArray> j_response = - base::android::ToJavaByteArray(env, response, response_length); + ScopedJavaLocalRef<jbyteArray> j_response = base::android::ToJavaByteArray( + env, vector_as_array(&response), response.size()); ScopedJavaLocalRef<jbyteArray> j_session_id = base::android::ToJavaByteArray( env, reinterpret_cast<const uint8_t*>(session_id.data()), session_id.size());
diff --git a/media/base/android/media_drm_bridge.h b/media/base/android/media_drm_bridge.h index b767aa6..30842b97 100644 --- a/media/base/android/media_drm_bridge.h +++ b/media/base/android/media_drm_bridge.h
@@ -86,21 +86,18 @@ // MediaKeys (via BrowserCdm) implementation. void SetServerCertificate( - const uint8* certificate_data, - int certificate_data_length, + const std::vector<uint8_t>& certificate, scoped_ptr<media::SimpleCdmPromise> promise) override; void CreateSessionAndGenerateRequest( SessionType session_type, media::EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<media::NewSessionCdmPromise> promise) override; void LoadSession(SessionType session_type, const std::string& session_id, scoped_ptr<media::NewSessionCdmPromise> promise) override; void UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<media::SimpleCdmPromise> promise) override; void CloseSession(const std::string& session_id, scoped_ptr<media::SimpleCdmPromise> promise) override;
diff --git a/media/base/fake_audio_render_callback.h b/media/base/fake_audio_render_callback.h index 7805fc6..65d7df2 100644 --- a/media/base/fake_audio_render_callback.h +++ b/media/base/fake_audio_render_callback.h
@@ -22,17 +22,16 @@ // where x = [|number_of_frames| * m, |number_of_frames| * (m + 1)] and m = // the number of Render() calls fulfilled thus far. explicit FakeAudioRenderCallback(double step); - virtual ~FakeAudioRenderCallback(); + ~FakeAudioRenderCallback() override; // Renders a sine wave into the provided audio data buffer. If |half_fill_| // is set, will only fill half the buffer. - virtual int Render(AudioBus* audio_bus, - int audio_delay_milliseconds) override; + int Render(AudioBus* audio_bus, int audio_delay_milliseconds) override; MOCK_METHOD0(OnRenderError, void()); // AudioTransform::ProvideAudioTransformInput implementation. - virtual double ProvideInput(AudioBus* audio_bus, - base::TimeDelta buffer_delay) override; + double ProvideInput(AudioBus* audio_bus, + base::TimeDelta buffer_delay) override; // Toggles only filling half the requested amount during Render(). void set_half_fill(bool half_fill) { half_fill_ = half_fill; }
diff --git a/media/base/fake_text_track_stream.h b/media/base/fake_text_track_stream.h index 919ae81..bbfbe8bc0 100644 --- a/media/base/fake_text_track_stream.h +++ b/media/base/fake_text_track_stream.h
@@ -15,16 +15,16 @@ class FakeTextTrackStream : public DemuxerStream { public: FakeTextTrackStream(); - virtual ~FakeTextTrackStream(); + ~FakeTextTrackStream() override; // DemuxerStream implementation. - virtual void Read(const ReadCB&) override; + void Read(const ReadCB&) override; MOCK_METHOD0(audio_decoder_config, AudioDecoderConfig()); MOCK_METHOD0(video_decoder_config, VideoDecoderConfig()); - virtual Type type() const override; + Type type() const override; MOCK_METHOD0(EnableBitstreamConverter, void()); - virtual bool SupportsConfigChanges(); - virtual VideoRotation video_rotation() override; + bool SupportsConfigChanges() override; + VideoRotation video_rotation() override; void SatisfyPendingRead(const base::TimeDelta& start, const base::TimeDelta& duration,
diff --git a/media/base/media_keys.h b/media/base/media_keys.h index 796d78d6..ba2a680 100644 --- a/media/base/media_keys.h +++ b/media/base/media_keys.h
@@ -89,8 +89,7 @@ // Provides a server certificate to be used to encrypt messages to the // license server. - virtual void SetServerCertificate(const uint8* certificate_data, - int certificate_data_length, + virtual void SetServerCertificate(const std::vector<uint8_t>& certificate, scoped_ptr<SimpleCdmPromise> promise) = 0; // Creates a session with |session_type|. Then generates a request with the @@ -105,8 +104,7 @@ virtual void CreateSessionAndGenerateRequest( SessionType session_type, EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<NewSessionCdmPromise> promise) = 0; // Loads a session with the |session_id| provided. @@ -118,8 +116,7 @@ // Updates a session specified by |session_id| with |response|. virtual void UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<SimpleCdmPromise> promise) = 0; // Closes the session specified by |session_id|. The CDM should resolve or @@ -151,7 +148,7 @@ typedef base::Callback<void(const std::string& session_id, MediaKeys::MessageType message_type, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& legacy_destination_url)> SessionMessageCB; @@ -163,7 +160,7 @@ typedef base::Callback<void(const std::string& session_id, MediaKeys::Exception exception, - uint32 system_code, + uint32_t system_code, const std::string& error_message)> LegacySessionErrorCB;
diff --git a/media/base/mock_audio_renderer_sink.h b/media/base/mock_audio_renderer_sink.h index 5f1c245..3a85d52 100644 --- a/media/base/mock_audio_renderer_sink.h +++ b/media/base/mock_audio_renderer_sink.h
@@ -21,12 +21,12 @@ MOCK_METHOD0(Play, void()); MOCK_METHOD1(SetVolume, bool(double volume)); - virtual void Initialize(const AudioParameters& params, - RenderCallback* renderer) override; + void Initialize(const AudioParameters& params, + RenderCallback* renderer) override; AudioRendererSink::RenderCallback* callback() { return callback_; } protected: - virtual ~MockAudioRendererSink(); + ~MockAudioRendererSink() override; private: RenderCallback* callback_;
diff --git a/media/blink/cdm_session_adapter.cc b/media/blink/cdm_session_adapter.cc index 8e62bcee..692eecca 100644 --- a/media/blink/cdm_session_adapter.cc +++ b/media/blink/cdm_session_adapter.cc
@@ -50,11 +50,9 @@ } void CdmSessionAdapter::SetServerCertificate( - const uint8* server_certificate, - int server_certificate_length, + const std::vector<uint8_t>& certificate, scoped_ptr<SimpleCdmPromise> promise) { - cdm_->SetServerCertificate(server_certificate, server_certificate_length, - promise.Pass()); + cdm_->SetServerCertificate(certificate, promise.Pass()); } WebContentDecryptionModuleSessionImpl* CdmSessionAdapter::CreateSession() { @@ -79,12 +77,11 @@ void CdmSessionAdapter::InitializeNewSession( EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, MediaKeys::SessionType session_type, scoped_ptr<NewSessionCdmPromise> promise) { cdm_->CreateSessionAndGenerateRequest(session_type, init_data_type, init_data, - init_data_length, promise.Pass()); + promise.Pass()); } void CdmSessionAdapter::LoadSession(MediaKeys::SessionType session_type, @@ -94,10 +91,9 @@ } void CdmSessionAdapter::UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<SimpleCdmPromise> promise) { - cdm_->UpdateSession(session_id, response, response_length, promise.Pass()); + cdm_->UpdateSession(session_id, response, promise.Pass()); } void CdmSessionAdapter::CloseSession(const std::string& session_id, @@ -146,7 +142,7 @@ void CdmSessionAdapter::OnSessionMessage( const std::string& session_id, MediaKeys::MessageType message_type, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& /* legacy_destination_url */) { WebContentDecryptionModuleSessionImpl* session = GetSession(session_id); DLOG_IF(WARNING, !session) << __FUNCTION__ << " for unknown session " @@ -187,7 +183,7 @@ void CdmSessionAdapter::OnLegacySessionError( const std::string& session_id, MediaKeys::Exception exception_code, - uint32 system_code, + uint32_t system_code, const std::string& error_message) { // Error events not used by unprefixed EME. // TODO(jrummell): Remove when prefixed EME removed.
diff --git a/media/blink/cdm_session_adapter.h b/media/blink/cdm_session_adapter.h index 5ed7550e..cc60143 100644 --- a/media/blink/cdm_session_adapter.h +++ b/media/blink/cdm_session_adapter.h
@@ -7,6 +7,7 @@ #include <map> #include <string> +#include <vector> #include "base/basictypes.h" #include "base/containers/hash_tables.h" @@ -42,8 +43,7 @@ // Provides a server certificate to be used to encrypt messages to the // license server. - void SetServerCertificate(const uint8* server_certificate, - int server_certificate_length, + void SetServerCertificate(const std::vector<uint8_t>& certificate, scoped_ptr<SimpleCdmPromise> promise); // Creates a new session and adds it to the internal map. The caller owns the @@ -64,8 +64,7 @@ // Initializes a session with the |init_data_type|, |init_data| and // |session_type| provided. void InitializeNewSession(EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, MediaKeys::SessionType session_type, scoped_ptr<NewSessionCdmPromise> promise); @@ -76,8 +75,7 @@ // Updates the session specified by |session_id| with |response|. void UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<SimpleCdmPromise> promise); // Closes the session specified by |session_id|. @@ -118,7 +116,7 @@ // Callbacks for firing session events. void OnSessionMessage(const std::string& session_id, MediaKeys::MessageType message_type, - const std::vector<uint8>& message, + const std::vector<uint8_t>& message, const GURL& legacy_destination_url); void OnSessionKeysChange(const std::string& session_id, bool has_additional_usable_key, @@ -128,7 +126,7 @@ void OnSessionClosed(const std::string& session_id); void OnLegacySessionError(const std::string& session_id, MediaKeys::Exception exception_code, - uint32 system_code, + uint32_t system_code, const std::string& error_message); // Helper function of the callbacks.
diff --git a/media/blink/webcontentdecryptionmodule_impl.cc b/media/blink/webcontentdecryptionmodule_impl.cc index 7bdd9c9e..6284602 100644 --- a/media/blink/webcontentdecryptionmodule_impl.cc +++ b/media/blink/webcontentdecryptionmodule_impl.cc
@@ -93,8 +93,8 @@ blink::WebContentDecryptionModuleResult result) { DCHECK(server_certificate); adapter_->SetServerCertificate( - server_certificate, - base::saturated_cast<int>(server_certificate_length), + std::vector<uint8>(server_certificate, + server_certificate + server_certificate_length), scoped_ptr<SimpleCdmPromise>( new CdmResultPromise<>(result, std::string()))); }
diff --git a/media/blink/webcontentdecryptionmodulesession_impl.cc b/media/blink/webcontentdecryptionmodulesession_impl.cc index 94afa0e..5ecba27 100644 --- a/media/blink/webcontentdecryptionmodulesession_impl.cc +++ b/media/blink/webcontentdecryptionmodulesession_impl.cc
@@ -8,6 +8,7 @@ #include "base/callback_helpers.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "media/base/cdm_key_information.h" @@ -110,12 +111,11 @@ return true; case EmeInitDataType::CENC: - if (!ValidatePsshInput(init_data, init_data_length)) { + sanitized_init_data->assign(init_data, init_data + init_data_length); + if (!ValidatePsshInput(*sanitized_init_data)) { error_message->assign("Initialization data for CENC is incorrect."); return false; } - - sanitized_init_data->assign(init_data, init_data + init_data_length); return true; case EmeInitDataType::KEYIDS: { @@ -173,6 +173,7 @@ size_t init_data_length, blink::WebEncryptedMediaSessionType session_type, blink::WebContentDecryptionModuleResult result) { + DCHECK(init_data); DCHECK(session_id_.empty()); // From https://w3c.github.io/encrypted-media/#generateRequest. @@ -225,9 +226,7 @@ // instance value. // 9.7 Use the cdm to execute the following steps: adapter_->InitializeNewSession( - eme_init_data_type, vector_as_array(&sanitized_init_data), - base::saturated_cast<int>(sanitized_init_data.size()), - convertSessionType(session_type), + eme_init_data_type, sanitized_init_data, convertSessionType(session_type), scoped_ptr<NewSessionCdmPromise>(new NewSessionCdmResultPromise( result, adapter_->GetKeySystemUMAPrefix() + kGenerateRequestUMAName, base::Bind( @@ -260,7 +259,7 @@ DCHECK(response); DCHECK(!session_id_.empty()); adapter_->UpdateSession( - session_id_, response, base::saturated_cast<int>(response_length), + session_id_, std::vector<uint8>(response, response + response_length), scoped_ptr<SimpleCdmPromise>(new CdmResultPromise<>( result, adapter_->GetKeySystemUMAPrefix() + kUpdateSessionUMAName))); }
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index ac67b21..e8eec4c5 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -5,6 +5,7 @@ #include "media/blink/webmediaplayer_impl.h" #include <algorithm> +#include <cmath> #include <limits> #include <string> #include <vector> @@ -14,7 +15,6 @@ #include "base/callback_helpers.h" #include "base/debug/alias.h" #include "base/debug/crash_logging.h" -#include "base/float_util.h" #include "base/message_loop/message_loop_proxy.h" #include "base/metrics/histogram.h" #include "base/single_thread_task_runner.h" @@ -486,7 +486,7 @@ // Allow a special exception for seeks to zero for streaming sources with a // finite duration; this allows looping to work. const bool allow_seek_to_zero = data_source_ && data_source_->IsStreaming() && - base::IsFinite(seekable_end); + std::isfinite(seekable_end); // TODO(dalecurtis): Technically this allows seeking on media which return an // infinite duration so long as DataSource::IsStreaming() is false. While not
diff --git a/media/blink/websourcebuffer_impl.cc b/media/blink/websourcebuffer_impl.cc index 3491378..0e38778 100644 --- a/media/blink/websourcebuffer_impl.cc +++ b/media/blink/websourcebuffer_impl.cc
@@ -4,19 +4,19 @@ #include "media/blink/websourcebuffer_impl.h" +#include <cmath> #include <limits> #include "base/bind.h" #include "base/callback.h" #include "base/callback_helpers.h" -#include "base/float_util.h" #include "media/filters/chunk_demuxer.h" #include "third_party/WebKit/public/platform/WebSourceBufferClient.h" namespace media { static base::TimeDelta DoubleToTimeDelta(double time) { - DCHECK(!base::IsNaN(time)); + DCHECK(!std::isnan(time)); DCHECK_NE(time, -std::numeric_limits<double>::infinity()); if (time == std::numeric_limits<double>::infinity())
diff --git a/media/cast/sender/h264_vt_encoder.cc b/media/cast/sender/h264_vt_encoder.cc index c8ae82bb..38d671b6 100644 --- a/media/cast/sender/h264_vt_encoder.cc +++ b/media/cast/sender/h264_vt_encoder.cc
@@ -13,6 +13,7 @@ #include "base/location.h" #include "base/logging.h" #include "base/macros.h" +#include "base/power_monitor/power_monitor.h" #include "base/synchronization/lock.h" #include "media/base/mac/corevideo_glue.h" #include "media/base/mac/video_frame_mac.h" @@ -37,16 +38,10 @@ frame_encoded_callback(callback) {} }; -base::ScopedCFTypeRef<CFDictionaryRef> DictionaryWithKeysAndValues( - CFTypeRef* keys, - CFTypeRef* values, - size_t size) { +base::ScopedCFTypeRef<CFDictionaryRef> +DictionaryWithKeysAndValues(CFTypeRef* keys, CFTypeRef* values, size_t size) { return base::ScopedCFTypeRef<CFDictionaryRef>(CFDictionaryCreate( - kCFAllocatorDefault, - keys, - values, - size, - &kCFTypeDictionaryKeyCallBacks, + kCFAllocatorDefault, keys, values, size, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } @@ -209,40 +204,107 @@ } } -// Implementation of the VideoFrameFactory interface using |CVPixelBufferPool|. -class VideoFrameFactoryCVPixelBufferPoolImpl : public VideoFrameFactory { - public: - VideoFrameFactoryCVPixelBufferPoolImpl( - const base::ScopedCFTypeRef<CVPixelBufferPoolRef>& pool, - const gfx::Size& frame_size) - : pool_(pool), - frame_size_(frame_size) {} +} // namespace - ~VideoFrameFactoryCVPixelBufferPoolImpl() override {} +class H264VideoToolboxEncoder::VideoFrameFactoryImpl + : public base::RefCountedThreadSafe<VideoFrameFactoryImpl>, + public VideoFrameFactory { + public: + // Type that proxies the VideoFrameFactory interface to this class. + class Proxy; + + VideoFrameFactoryImpl(const base::WeakPtr<H264VideoToolboxEncoder>& encoder, + const scoped_refptr<CastEnvironment>& cast_environment) + : encoder_(encoder), cast_environment_(cast_environment) {} scoped_refptr<VideoFrame> MaybeCreateFrame( - const gfx::Size& frame_size, base::TimeDelta timestamp) override { - if (frame_size != frame_size_) - return nullptr; // Buffer pool is not a match for requested frame size. + const gfx::Size& frame_size, + base::TimeDelta timestamp) override { + if (frame_size.IsEmpty()) { + DVLOG(1) << "Rejecting empty video frame."; + return nullptr; + } + base::AutoLock auto_lock(lock_); + + // If the pool size does not match, speculatively reset the encoder to use + // the new size and return null. Cache the new frame size right away and + // toss away the pixel buffer pool to avoid spurious tasks until the encoder + // is done resetting. + if (frame_size != pool_frame_size_) { + DVLOG(1) << "MaybeCreateFrame: Detected frame size change."; + cast_environment_->PostTask( + CastEnvironment::MAIN, FROM_HERE, + base::Bind(&H264VideoToolboxEncoder::UpdateFrameSize, encoder_, + frame_size)); + pool_frame_size_ = frame_size; + pool_.reset(); + return nullptr; + } + + if (!pool_) { + DVLOG(1) << "MaybeCreateFrame: No pixel buffer pool."; + return nullptr; + } + + // Allocate a pixel buffer from the pool and return a wrapper VideoFrame. base::ScopedCFTypeRef<CVPixelBufferRef> buffer; - if (CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool_, - buffer.InitializeInto()) != - kCVReturnSuccess) - return nullptr; // Buffer pool has run out of pixel buffers. - DCHECK(buffer); + auto status = CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool_, + buffer.InitializeInto()); + if (status != kCVReturnSuccess) { + DLOG(ERROR) << "CVPixelBufferPoolCreatePixelBuffer failed: " << status; + return nullptr; + } + DCHECK(buffer); return VideoFrame::WrapCVPixelBuffer(buffer, timestamp); } - private: - const base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool_; - const gfx::Size frame_size_; + void Update(const base::ScopedCFTypeRef<CVPixelBufferPoolRef>& pool, + const gfx::Size& frame_size) { + base::AutoLock auto_lock(lock_); + pool_ = pool; + pool_frame_size_ = frame_size; + } - DISALLOW_COPY_AND_ASSIGN(VideoFrameFactoryCVPixelBufferPoolImpl); + private: + friend class base::RefCountedThreadSafe<VideoFrameFactoryImpl>; + ~VideoFrameFactoryImpl() override {} + + base::Lock lock_; + base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool_; + gfx::Size pool_frame_size_; + + // Weak back reference to the encoder and the cast envrionment so we can + // message the encoder when the frame size changes. + const base::WeakPtr<H264VideoToolboxEncoder> encoder_; + const scoped_refptr<CastEnvironment> cast_environment_; + + DISALLOW_COPY_AND_ASSIGN(VideoFrameFactoryImpl); }; -} // namespace +class H264VideoToolboxEncoder::VideoFrameFactoryImpl::Proxy + : public VideoFrameFactory { + public: + explicit Proxy( + const scoped_refptr<VideoFrameFactoryImpl>& video_frame_factory) + : video_frame_factory_(video_frame_factory) { + DCHECK(video_frame_factory_); + } + + scoped_refptr<VideoFrame> MaybeCreateFrame( + const gfx::Size& frame_size, + base::TimeDelta timestamp) override { + return video_frame_factory_->MaybeCreateFrame(frame_size, timestamp); + } + + private: + ~Proxy() override {} + + const scoped_refptr<VideoFrameFactoryImpl> video_frame_factory_; + + DISALLOW_COPY_AND_ASSIGN(Proxy); +}; // static bool H264VideoToolboxEncoder::IsSupported( @@ -253,48 +315,72 @@ H264VideoToolboxEncoder::H264VideoToolboxEncoder( const scoped_refptr<CastEnvironment>& cast_environment, const VideoSenderConfig& video_config, - const gfx::Size& frame_size, - uint32 first_frame_id, const StatusChangeCallback& status_change_cb) : cast_environment_(cast_environment), videotoolbox_glue_(VideoToolboxGlue::Get()), - frame_size_(frame_size), + video_config_(video_config), status_change_cb_(status_change_cb), - next_frame_id_(first_frame_id), - encode_next_frame_as_keyframe_(false) { - DCHECK(!frame_size_.IsEmpty()); + last_frame_id_(kStartFrameId), + encode_next_frame_as_keyframe_(false), + power_suspended_(false), + weak_factory_(this) { + DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN)); DCHECK(!status_change_cb_.is_null()); - OperationalStatus operational_status; - if (video_config.codec == CODEC_VIDEO_H264 && videotoolbox_glue_) { - operational_status = Initialize(video_config) ? - STATUS_INITIALIZED : STATUS_INVALID_CONFIGURATION; - } else { - operational_status = STATUS_UNSUPPORTED_CODEC; - } + OperationalStatus operational_status = + H264VideoToolboxEncoder::IsSupported(video_config) + ? STATUS_INITIALIZED + : STATUS_UNSUPPORTED_CODEC; cast_environment_->PostTask( - CastEnvironment::MAIN, - FROM_HERE, + CastEnvironment::MAIN, FROM_HERE, base::Bind(status_change_cb_, operational_status)); + + if (operational_status == STATUS_INITIALIZED) { + // Create the shared video frame factory. It persists for the combined + // lifetime of the encoder and all video frame factory proxies created by + // |CreateVideoFrameFactory| that reference it. + video_frame_factory_ = + scoped_refptr<VideoFrameFactoryImpl>(new VideoFrameFactoryImpl( + weak_factory_.GetWeakPtr(), cast_environment_)); + + // Register for power state changes. + auto power_monitor = base::PowerMonitor::Get(); + if (power_monitor) { + power_monitor->AddObserver(this); + VLOG(1) << "Registered for power state changes."; + } else { + DLOG(WARNING) << "No power monitor. Process suspension will invalidate " + "the encoder."; + } + } } H264VideoToolboxEncoder::~H264VideoToolboxEncoder() { - Teardown(); + DestroyCompressionSession(); + + // If video_frame_factory_ is not null, the encoder registered for power state + // changes in the ctor and it must now unregister. + if (video_frame_factory_) { + auto power_monitor = base::PowerMonitor::Get(); + if (power_monitor) + power_monitor->RemoveObserver(this); + } } -bool H264VideoToolboxEncoder::Initialize( - const VideoSenderConfig& video_config) { +void H264VideoToolboxEncoder::ResetCompressionSession() { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(!compression_session_); - // Note that the encoder object is given to the compression session as the - // callback context using a raw pointer. The C API does not allow us to use - // a smart pointer, nor is this encoder ref counted. However, this is still - // safe, because we 1) we own the compression session and 2) we tear it down - // safely. When destructing the encoder, the compression session is flushed - // and invalidated. Internally, VideoToolbox will join all of its threads - // before returning to the client. Therefore, when control returns to us, we - // are guaranteed that the output callback will not execute again. + // Ignore reset requests while power suspended. + if (power_suspended_) + return; + + // Notify that we're resetting the encoder. + cast_environment_->PostTask( + CastEnvironment::MAIN, FROM_HERE, + base::Bind(status_change_cb_, STATUS_CODEC_REINIT_PENDING)); + + // Destroy the current session, if any. + DestroyCompressionSession(); // On OS X, allow the hardware encoder. Don't require it, it does not support // all configurations (some of which are used for testing). @@ -309,30 +395,21 @@ // Certain encoders prefer kCVPixelFormatType_422YpCbCr8, which is not // supported through VideoFrame. We can force 420 formats to be used instead. const int formats[] = { - kCVPixelFormatType_420YpCbCr8Planar, - CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange - }; + kCVPixelFormatType_420YpCbCr8Planar, + CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange}; // Keep these attachment settings in-sync with those in ConfigureSession(). - CFTypeRef attachments_keys[] = { - kCVImageBufferColorPrimariesKey, - kCVImageBufferTransferFunctionKey, - kCVImageBufferYCbCrMatrixKey - }; - CFTypeRef attachments_values[] = { - kCVImageBufferColorPrimaries_ITU_R_709_2, - kCVImageBufferTransferFunction_ITU_R_709_2, - kCVImageBufferYCbCrMatrix_ITU_R_709_2 - }; - CFTypeRef buffer_attributes_keys[] = { - kCVPixelBufferPixelFormatTypeKey, - kCVBufferPropagatedAttachmentsKey - }; + CFTypeRef attachments_keys[] = {kCVImageBufferColorPrimariesKey, + kCVImageBufferTransferFunctionKey, + kCVImageBufferYCbCrMatrixKey}; + CFTypeRef attachments_values[] = {kCVImageBufferColorPrimaries_ITU_R_709_2, + kCVImageBufferTransferFunction_ITU_R_709_2, + kCVImageBufferYCbCrMatrix_ITU_R_709_2}; + CFTypeRef buffer_attributes_keys[] = {kCVPixelBufferPixelFormatTypeKey, + kCVBufferPropagatedAttachmentsKey}; CFTypeRef buffer_attributes_values[] = { - ArrayWithIntegers(formats, arraysize(formats)).release(), - DictionaryWithKeysAndValues(attachments_keys, - attachments_values, - arraysize(attachments_keys)).release() - }; + ArrayWithIntegers(formats, arraysize(formats)).release(), + DictionaryWithKeysAndValues(attachments_keys, attachments_values, + arraysize(attachments_keys)).release()}; const base::ScopedCFTypeRef<CFDictionaryRef> buffer_attributes = DictionaryWithKeysAndValues(buffer_attributes_keys, buffer_attributes_values, @@ -340,26 +417,49 @@ for (auto& v : buffer_attributes_values) CFRelease(v); - VTCompressionSessionRef session; + // Create the compression session. + + // Note that the encoder object is given to the compression session as the + // callback context using a raw pointer. The C API does not allow us to use a + // smart pointer, nor is this encoder ref counted. However, this is still + // safe, because we 1) we own the compression session and 2) we tear it down + // safely. When destructing the encoder, the compression session is flushed + // and invalidated. Internally, VideoToolbox will join all of its threads + // before returning to the client. Therefore, when control returns to us, we + // are guaranteed that the output callback will not execute again. OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate( kCFAllocatorDefault, frame_size_.width(), frame_size_.height(), CoreMediaGlue::kCMVideoCodecType_H264, encoder_spec, buffer_attributes, nullptr /* compressedDataAllocator */, &H264VideoToolboxEncoder::CompressionCallback, - reinterpret_cast<void*>(this), &session); + reinterpret_cast<void*>(this), compression_session_.InitializeInto()); if (status != noErr) { DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status; - return false; + // Notify that reinitialization has failed. + cast_environment_->PostTask( + CastEnvironment::MAIN, FROM_HERE, + base::Bind(status_change_cb_, STATUS_CODEC_INIT_FAILED)); + return; } - compression_session_.reset(session); - ConfigureSession(video_config); + // Configure the session (apply session properties based on the current state + // of the encoder, experimental tuning and requirements). + ConfigureCompressionSession(); - return true; + // Update the video frame factory. + base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool( + videotoolbox_glue_->VTCompressionSessionGetPixelBufferPool( + compression_session_), + base::scoped_policy::RETAIN); + video_frame_factory_->Update(pool, frame_size_); + + // Notify that reinitialization is done. + cast_environment_->PostTask( + CastEnvironment::MAIN, FROM_HERE, + base::Bind(status_change_cb_, STATUS_INITIALIZED)); } -void H264VideoToolboxEncoder::ConfigureSession( - const VideoSenderConfig& video_config) { +void H264VideoToolboxEncoder::ConfigureCompressionSession() { SetSessionProperty( videotoolbox_glue_->kVTCompressionPropertyKey_ProfileLevel(), videotoolbox_glue_->kVTProfileLevel_H264_Main_AutoLevel()); @@ -378,10 +478,10 @@ // https://crbug.com/425352 SetSessionProperty( videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(), - (video_config.min_bitrate + video_config.max_bitrate) / 2); + (video_config_.min_bitrate + video_config_.max_bitrate) / 2); SetSessionProperty( videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(), - video_config.max_frame_rate); + video_config_.max_frame_rate); // Keep these attachment settings in-sync with those in Initialize(). SetSessionProperty( videotoolbox_glue_->kVTCompressionPropertyKey_ColorPrimaries(), @@ -392,20 +492,31 @@ SetSessionProperty( videotoolbox_glue_->kVTCompressionPropertyKey_YCbCrMatrix(), kCVImageBufferYCbCrMatrix_ITU_R_709_2); - if (video_config.max_number_of_video_buffers_used > 0) { + if (video_config_.max_number_of_video_buffers_used > 0) { SetSessionProperty( videotoolbox_glue_->kVTCompressionPropertyKey_MaxFrameDelayCount(), - video_config.max_number_of_video_buffers_used); + video_config_.max_number_of_video_buffers_used); } } -void H264VideoToolboxEncoder::Teardown() { +void H264VideoToolboxEncoder::DestroyCompressionSession() { DCHECK(thread_checker_.CalledOnValidThread()); // If the compression session exists, invalidate it. This blocks until all // pending output callbacks have returned and any internal threads have // joined, ensuring no output callback ever sees a dangling encoder pointer. + // + // Before destroying the compression session, the video frame factory's pool + // is updated to null so that no thread will produce new video frames via the + // factory until a new compression session is created. The current frame size + // is passed to prevent the video frame factory from posting |UpdateFrameSize| + // tasks. Indeed, |DestroyCompressionSession| is either called from + // |ResetCompressionSession|, in which case a new pool and frame size will be + // set, or from callsites that require that there be no compression session + // (ex: the dtor). if (compression_session_) { + video_frame_factory_->Update( + base::ScopedCFTypeRef<CVPixelBufferPoolRef>(nullptr), frame_size_); videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_); compression_session_.reset(); } @@ -418,13 +529,24 @@ DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!frame_encoded_callback.is_null()); - if (!compression_session_) { - DLOG(ERROR) << " compression session is null"; + // Reject empty video frames. + const gfx::Size frame_size = video_frame->visible_rect().size(); + if (frame_size.IsEmpty()) { + DVLOG(1) << "Rejecting empty video frame."; return false; } - if (video_frame->visible_rect().size() != frame_size_) + // Handle frame size changes. This will reset the compression session. + if (frame_size != frame_size_) { + DVLOG(1) << "EncodeVideoFrame: Detected frame size change."; + UpdateFrameSize(frame_size); + } + + // Need a compression session to continue. + if (!compression_session_) { + DLOG(ERROR) << "No compression session."; return false; + } // Wrap the VideoFrame in a CVPixelBuffer. In all cases, no data will be // copied. If the VideoFrame was created by this encoder's video frame @@ -434,16 +556,21 @@ // lifetime is extended for the lifetime of the returned CVPixelBuffer. auto pixel_buffer = media::WrapVideoFrameInCVPixelBuffer(*video_frame); if (!pixel_buffer) { + DLOG(ERROR) << "WrapVideoFrameInCVPixelBuffer failed."; return false; } + // Convert the frame timestamp to CMTime. auto timestamp_cm = CoreMediaGlue::CMTimeMake( (reference_time - base::TimeTicks()).InMicroseconds(), USEC_PER_SEC); + // Wrap information we'll need after the frame is encoded in a heap object. + // We'll get the pointer back from the VideoToolbox completion callback. scoped_ptr<InProgressFrameEncode> request(new InProgressFrameEncode( TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency), reference_time, frame_encoded_callback)); + // Build a suitable frame properties dictionary for keyframes. base::ScopedCFTypeRef<CFDictionaryRef> frame_props; if (encode_next_frame_as_keyframe_) { frame_props = DictionaryWithKeyValue( @@ -452,32 +579,53 @@ encode_next_frame_as_keyframe_ = false; } - VTEncodeInfoFlags info; + // Submit the frame to the compression session. The function returns as soon + // as the frame has been enqueued. OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame( compression_session_, pixel_buffer, timestamp_cm, CoreMediaGlue::CMTime{0, 0, 0, 0}, frame_props, - reinterpret_cast<void*>(request.release()), &info); + reinterpret_cast<void*>(request.release()), nullptr); if (status != noErr) { DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status; return false; } - if ((info & VideoToolboxGlue::kVTEncodeInfo_FrameDropped)) { - DLOG(ERROR) << " frame dropped"; - return false; - } return true; } -void H264VideoToolboxEncoder::SetBitRate(int new_bit_rate) { +void H264VideoToolboxEncoder::UpdateFrameSize(const gfx::Size& size_needed) { + DCHECK(thread_checker_.CalledOnValidThread()); + + // Our video frame factory posts a task to update the frame size when its + // cache of the frame size differs from what the client requested. To avoid + // spurious encoder resets, check again here. + if (size_needed == frame_size_) { + DCHECK(compression_session_); + return; + } + + VLOG(1) << "Resetting compression session (for frame size change from " + << frame_size_.ToString() << " to " << size_needed.ToString() << ")."; + + // If there is an existing session, finish every pending frame. + if (compression_session_) { + EmitFrames(); + } + + // Store the new frame size. + frame_size_ = size_needed; + + // Reset the compression session. + ResetCompressionSession(); +} + +void H264VideoToolboxEncoder::SetBitRate(int /*new_bit_rate*/) { DCHECK(thread_checker_.CalledOnValidThread()); // VideoToolbox does not seem to support bitrate reconfiguration. } void H264VideoToolboxEncoder::GenerateKeyFrame() { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(compression_session_); - encode_next_frame_as_keyframe_ = true; } @@ -487,23 +635,15 @@ scoped_ptr<VideoFrameFactory> H264VideoToolboxEncoder::CreateVideoFrameFactory() { - if (!videotoolbox_glue_ || !compression_session_) - return nullptr; - base::ScopedCFTypeRef<CVPixelBufferPoolRef> pool( - videotoolbox_glue_->VTCompressionSessionGetPixelBufferPool( - compression_session_), - base::scoped_policy::RETAIN); + DCHECK(thread_checker_.CalledOnValidThread()); return scoped_ptr<VideoFrameFactory>( - new VideoFrameFactoryCVPixelBufferPoolImpl(pool, frame_size_)); + new VideoFrameFactoryImpl::Proxy(video_frame_factory_)); } void H264VideoToolboxEncoder::EmitFrames() { DCHECK(thread_checker_.CalledOnValidThread()); - - if (!compression_session_) { - DLOG(ERROR) << " compression session is null"; + if (!compression_session_) return; - } OSStatus status = videotoolbox_glue_->VTCompressionSessionCompleteFrames( compression_session_, CoreMediaGlue::CMTime{0, 0, 0, 0}); @@ -512,6 +652,27 @@ } } +void H264VideoToolboxEncoder::OnSuspend() { + VLOG(1) + << "OnSuspend: Emitting all frames and destroying compression session."; + EmitFrames(); + DestroyCompressionSession(); + power_suspended_ = true; +} + +void H264VideoToolboxEncoder::OnResume() { + power_suspended_ = false; + + // Reset the compression session only if the frame size is not zero (which + // will obviously fail). It is possible for the frame size to be zero if no + // frame was submitted for encoding or requested from the video frame factory + // before suspension. + if (!frame_size_.IsEmpty()) { + VLOG(1) << "OnResume: Resetting compression session."; + ResetCompressionSession(); + } +} + bool H264VideoToolboxEncoder::SetSessionProperty(CFStringRef key, int32_t value) { base::ScopedCFTypeRef<CFNumberRef> cfvalue( @@ -546,14 +707,13 @@ if (status != noErr) { DLOG(ERROR) << " encoding failed: " << status; encoder->cast_environment_->PostTask( - CastEnvironment::MAIN, - FROM_HERE, + CastEnvironment::MAIN, FROM_HERE, base::Bind(encoder->status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); } else if ((info & VideoToolboxGlue::kVTEncodeInfo_FrameDropped)) { DVLOG(2) << " frame dropped"; } else { - auto sample_attachments = static_cast<CFDictionaryRef>( - CFArrayGetValueAtIndex( + auto sample_attachments = + static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex( CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray(sbuf, true), 0)); @@ -561,14 +721,14 @@ // keyframe (at least I think, VT documentation is, erm, sparse). Could // alternatively use kCMSampleAttachmentKey_DependsOnOthers == false. keyframe = !CFDictionaryContainsKey( - sample_attachments, - CoreMediaGlue::kCMSampleAttachmentKey_NotSync()); + sample_attachments, + CoreMediaGlue::kCMSampleAttachmentKey_NotSync()); has_frame_data = true; } // Increment the encoder-scoped frame id and assign the new value to this // frame. VideoToolbox calls the output callback serially, so this is safe. - const uint32 frame_id = encoder->next_frame_id_++; + const uint32 frame_id = ++encoder->last_frame_id_; scoped_ptr<EncodedFrame> encoded_frame(new EncodedFrame()); encoded_frame->frame_id = frame_id; @@ -600,89 +760,5 @@ base::Passed(&encoded_frame))); } -// A ref-counted structure that is shared to provide concurrent access to the -// VideoFrameFactory instance for the current encoder. OnEncoderReplaced() can -// change |factory| whenever an encoder instance has been replaced, while users -// of CreateVideoFrameFactory() may attempt to read/use |factory| by any thread -// at any time. -struct SizeAdaptableH264VideoToolboxVideoEncoder::FactoryHolder - : public base::RefCountedThreadSafe<FactoryHolder> { - base::Lock lock; - scoped_ptr<VideoFrameFactory> factory; - - private: - friend class base::RefCountedThreadSafe<FactoryHolder>; - ~FactoryHolder() {} -}; - -SizeAdaptableH264VideoToolboxVideoEncoder:: - SizeAdaptableH264VideoToolboxVideoEncoder( - const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, - const StatusChangeCallback& status_change_cb) - : SizeAdaptableVideoEncoderBase(cast_environment, - video_config, - status_change_cb), - holder_(new FactoryHolder()) {} - -SizeAdaptableH264VideoToolboxVideoEncoder:: - ~SizeAdaptableH264VideoToolboxVideoEncoder() {} - -// A proxy allowing SizeAdaptableH264VideoToolboxVideoEncoder to swap out the -// VideoFrameFactory instance to match one appropriate for the current encoder -// instance. -class SizeAdaptableH264VideoToolboxVideoEncoder::VideoFrameFactoryProxy - : public VideoFrameFactory { - public: - explicit VideoFrameFactoryProxy(const scoped_refptr<FactoryHolder>& holder) - : holder_(holder) {} - - ~VideoFrameFactoryProxy() override {} - - scoped_refptr<VideoFrame> MaybeCreateFrame( - const gfx::Size& frame_size, base::TimeDelta timestamp) override { - base::AutoLock auto_lock(holder_->lock); - return holder_->factory ? - holder_->factory->MaybeCreateFrame(frame_size, timestamp) : nullptr; - } - - private: - const scoped_refptr<FactoryHolder> holder_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameFactoryProxy); -}; - -scoped_ptr<VideoFrameFactory> - SizeAdaptableH264VideoToolboxVideoEncoder::CreateVideoFrameFactory() { - return scoped_ptr<VideoFrameFactory>(new VideoFrameFactoryProxy(holder_)); -} - -scoped_ptr<VideoEncoder> - SizeAdaptableH264VideoToolboxVideoEncoder::CreateEncoder() { - return scoped_ptr<VideoEncoder>(new H264VideoToolboxEncoder( - cast_environment(), - video_config(), - frame_size(), - last_frame_id() + 1, - CreateEncoderStatusChangeCallback())); -} - -void SizeAdaptableH264VideoToolboxVideoEncoder::OnEncoderReplaced( - VideoEncoder* replacement_encoder) { - scoped_ptr<VideoFrameFactory> current_factory( - replacement_encoder->CreateVideoFrameFactory()); - base::AutoLock auto_lock(holder_->lock); - holder_->factory = current_factory.Pass(); - SizeAdaptableVideoEncoderBase::OnEncoderReplaced(replacement_encoder); -} - -void SizeAdaptableH264VideoToolboxVideoEncoder::DestroyEncoder() { - { - base::AutoLock auto_lock(holder_->lock); - holder_->factory.reset(); - } - SizeAdaptableVideoEncoderBase::DestroyEncoder(); -} - } // namespace cast } // namespace media
diff --git a/media/cast/sender/h264_vt_encoder.h b/media/cast/sender/h264_vt_encoder.h index ece6ab3..4df9320 100644 --- a/media/cast/sender/h264_vt_encoder.h +++ b/media/cast/sender/h264_vt_encoder.h
@@ -6,6 +6,7 @@ #define MEDIA_CAST_SENDER_H264_VT_ENCODER_H_ #include "base/mac/scoped_cftyperef.h" +#include "base/power_monitor/power_observer.h" #include "base/threading/thread_checker.h" #include "media/base/mac/videotoolbox_glue.h" #include "media/cast/sender/size_adaptable_video_encoder_base.h" @@ -16,8 +17,11 @@ // VideoToolbox implementation of the media::cast::VideoEncoder interface. // VideoToolbox makes no guarantees that it is thread safe, so this object is -// pinned to the thread on which it is constructed. -class H264VideoToolboxEncoder : public VideoEncoder { +// pinned to the thread on which it is constructed. Supports changing frame +// sizes directly. Implements the base::PowerObserver interface to reset the +// compression session when the host process is suspended. +class H264VideoToolboxEncoder : public VideoEncoder, + public base::PowerObserver { typedef CoreMediaGlue::CMSampleBufferRef CMSampleBufferRef; typedef VideoToolboxGlue::VTCompressionSessionRef VTCompressionSessionRef; typedef VideoToolboxGlue::VTEncodeInfoFlags VTEncodeInfoFlags; @@ -30,8 +34,6 @@ H264VideoToolboxEncoder( const scoped_refptr<CastEnvironment>& cast_environment, const VideoSenderConfig& video_config, - const gfx::Size& frame_size, - uint32 first_frame_id, const StatusChangeCallback& status_change_cb); ~H264VideoToolboxEncoder() override; @@ -46,15 +48,30 @@ scoped_ptr<VideoFrameFactory> CreateVideoFrameFactory() override; void EmitFrames() override; + // base::PowerObserver + void OnSuspend() override; + void OnResume() override; + private: - // Initialize the compression session. - bool Initialize(const VideoSenderConfig& video_config); + // VideoFrameFactory tied to the VideoToolbox encoder. + class VideoFrameFactoryImpl; - // Configure the compression session. - void ConfigureSession(const VideoSenderConfig& video_config); + // Reset the encoder's compression session by destroying the existing one + // using DestroyCompressionSession() and creating a new one. The new session + // is configured using ConfigureCompressionSession(). + void ResetCompressionSession(); - // Teardown the encoder. - void Teardown(); + // Configure the current compression session using current encoder settings. + void ConfigureCompressionSession(); + + // Destroy the current compression session if any. Blocks until all pending + // frames have been flushed out (similar to EmitFrames without doing any + // encoding work). + void DestroyCompressionSession(); + + // Update the encoder's target frame size by resetting the compression + // session. This will also update the video frame factory. + void UpdateFrameSize(const gfx::Size& size_needed); // Set a compression session property. bool SetSessionProperty(CFStringRef key, int32_t value); @@ -74,8 +91,14 @@ // VideoToolboxGlue provides access to VideoToolbox at runtime. const VideoToolboxGlue* const videotoolbox_glue_; - // The size of the visible region of the video frames to be encoded. - const gfx::Size frame_size_; + // VideoSenderConfig copy so we can create compression sessions on demand. + // This is needed to recover from backgrounding and other events that can + // invalidate compression sessions. + const VideoSenderConfig video_config_; + + // Frame size of the current compression session. Can be changed by submitting + // a frame of a different size, which will cause a compression session reset. + gfx::Size frame_size_; // Callback used to report initialization status and runtime errors. const StatusChangeCallback status_change_cb_; @@ -86,43 +109,24 @@ // The compression session. base::ScopedCFTypeRef<VTCompressionSessionRef> compression_session_; - // Frame identifier counter. - uint32 next_frame_id_; + // Video frame factory tied to the encoder. + scoped_refptr<VideoFrameFactoryImpl> video_frame_factory_; + + // The ID of the last frame that was emitted. + uint32 last_frame_id_; // Force next frame to be a keyframe. bool encode_next_frame_as_keyframe_; + // Power suspension state. + bool power_suspended_; + + // NOTE: Weak pointers must be invalidated before all other member variables. + base::WeakPtrFactory<H264VideoToolboxEncoder> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(H264VideoToolboxEncoder); }; -// An implementation of SizeAdaptableVideoEncoderBase to proxy for -// H264VideoToolboxEncoder instances. -class SizeAdaptableH264VideoToolboxVideoEncoder - : public SizeAdaptableVideoEncoderBase { - public: - SizeAdaptableH264VideoToolboxVideoEncoder( - const scoped_refptr<CastEnvironment>& cast_environment, - const VideoSenderConfig& video_config, - const StatusChangeCallback& status_change_cb); - - ~SizeAdaptableH264VideoToolboxVideoEncoder() override; - - scoped_ptr<VideoFrameFactory> CreateVideoFrameFactory() override; - - protected: - scoped_ptr<VideoEncoder> CreateEncoder() override; - void OnEncoderReplaced(VideoEncoder* replacement_encoder) override; - void DestroyEncoder() override; - - private: - struct FactoryHolder; - class VideoFrameFactoryProxy; - - const scoped_refptr<FactoryHolder> holder_; - - DISALLOW_COPY_AND_ASSIGN(SizeAdaptableH264VideoToolboxVideoEncoder); -}; - } // namespace cast } // namespace media
diff --git a/media/cast/sender/h264_vt_encoder_unittest.cc b/media/cast/sender/h264_vt_encoder_unittest.cc index 04f3d629d..26ac062 100644 --- a/media/cast/sender/h264_vt_encoder_unittest.cc +++ b/media/cast/sender/h264_vt_encoder_unittest.cc
@@ -7,7 +7,9 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/message_loop/message_loop.h" +#include "base/power_monitor/power_monitor.h" #include "base/test/launcher/unit_test_launcher.h" +#include "base/test/power_monitor_test_base.h" #include "base/test/simple_test_tick_clock.h" #include "base/test/test_suite.h" #include "media/base/decoder_buffer.h" @@ -190,26 +192,43 @@ CVPixelBufferUnlockBaseAddress(cv_pixel_buffer, 0); } +void NoopFrameEncodedCallback( + scoped_ptr<media::cast::EncodedFrame> /*encoded_frame*/) { +} + +class TestPowerSource : public base::PowerMonitorSource { + public: + void GenerateSuspendEvent() { + ProcessPowerEvent(SUSPEND_EVENT); + base::MessageLoop::current()->RunUntilIdle(); + } + void GenerateResumeEvent() { + ProcessPowerEvent(RESUME_EVENT); + base::MessageLoop::current()->RunUntilIdle(); + } + + private: + bool IsOnBatteryPowerImpl() override { return false; } +}; + class H264VideoToolboxEncoderTest : public ::testing::Test { protected: - H264VideoToolboxEncoderTest() - : operational_status_(STATUS_UNINITIALIZED) { - frame_->set_timestamp(base::TimeDelta()); - } + H264VideoToolboxEncoderTest() = default; void SetUp() override { clock_ = new base::SimpleTestTickClock(); clock_->Advance(base::TimeTicks::Now() - base::TimeTicks()); + power_source_ = new TestPowerSource(); + power_monitor_.reset( + new base::PowerMonitor(scoped_ptr<TestPowerSource>(power_source_))); + cast_environment_ = new CastEnvironment( scoped_ptr<base::TickClock>(clock_).Pass(), message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy(), message_loop_.message_loop_proxy()); encoder_.reset(new H264VideoToolboxEncoder( - cast_environment_, - video_sender_config_, - gfx::Size(kVideoWidth, kVideoHeight), - 0u, + cast_environment_, video_sender_config_, base::Bind(&SaveOperationalStatus, &operational_status_))); message_loop_.RunUntilIdle(); EXPECT_EQ(STATUS_INITIALIZED, operational_status_); @@ -218,6 +237,7 @@ void TearDown() override { encoder_.reset(); message_loop_.RunUntilIdle(); + power_monitor_.reset(); } void AdvanceClockAndVideoFrameTimestamp() { @@ -246,6 +266,8 @@ scoped_refptr<CastEnvironment> cast_environment_; scoped_ptr<VideoEncoder> encoder_; OperationalStatus operational_status_; + TestPowerSource* power_source_; // Owned by the power monitor. + scoped_ptr<base::PowerMonitor> power_monitor_; private: DISALLOW_COPY_AND_ASSIGN(H264VideoToolboxEncoderTest); @@ -306,13 +328,86 @@ TEST_F(H264VideoToolboxEncoderTest, CheckVideoFrameFactory) { auto video_frame_factory = encoder_->CreateVideoFrameFactory(); ASSERT_TRUE(video_frame_factory.get()); - CreateFrameAndMemsetPlane(video_frame_factory.get()); - // TODO(jfroy): Need to test that the encoder can encode VideoFrames provided - // by the VideoFrameFactory. - encoder_.reset(); + // The first call to |MaybeCreateFrame| will return null but post a task to + // the encoder to initialize for the specified frame size. We then drain the + // message loop. After that, the encoder should have initialized and we + // request a frame again. + ASSERT_FALSE(video_frame_factory->MaybeCreateFrame( + gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta())); message_loop_.RunUntilIdle(); CreateFrameAndMemsetPlane(video_frame_factory.get()); } +TEST_F(H264VideoToolboxEncoderTest, CheckPowerMonitoring) { + // Encode a frame, suspend, encode a frame, resume, encode a frame. + + VideoEncoder::FrameEncodedCallback cb = base::Bind(&NoopFrameEncodedCallback); + EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb)); + power_source_->GenerateSuspendEvent(); + EXPECT_FALSE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb)); + power_source_->GenerateResumeEvent(); + EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb)); +} + +TEST_F(H264VideoToolboxEncoderTest, CheckPowerMonitoringNoInitialFrame) { + // Suspend, encode a frame, resume, encode a frame. + + VideoEncoder::FrameEncodedCallback cb = base::Bind(&NoopFrameEncodedCallback); + power_source_->GenerateSuspendEvent(); + EXPECT_FALSE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb)); + power_source_->GenerateResumeEvent(); + EXPECT_TRUE(encoder_->EncodeVideoFrame(frame_, clock_->NowTicks(), cb)); +} + +TEST_F(H264VideoToolboxEncoderTest, CheckPowerMonitoringVideoFrameFactory) { + VideoEncoder::FrameEncodedCallback cb = base::Bind(&NoopFrameEncodedCallback); + auto video_frame_factory = encoder_->CreateVideoFrameFactory(); + ASSERT_TRUE(video_frame_factory.get()); + + // The first call to |MaybeCreateFrame| will return null but post a task to + // the encoder to initialize for the specified frame size. We then drain the + // message loop. After that, the encoder should have initialized and we + // request a frame again. + ASSERT_FALSE(video_frame_factory->MaybeCreateFrame( + gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta())); + message_loop_.RunUntilIdle(); + CreateFrameAndMemsetPlane(video_frame_factory.get()); + + // After a power suspension, the factory should not produce frames. + power_source_->GenerateSuspendEvent(); + + ASSERT_FALSE(video_frame_factory->MaybeCreateFrame( + gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta())); + message_loop_.RunUntilIdle(); + ASSERT_FALSE(video_frame_factory->MaybeCreateFrame( + gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta())); + + // After a power resume event, the factory should produce frames right away + // because the encoder re-initializes on its own. + power_source_->GenerateResumeEvent(); + CreateFrameAndMemsetPlane(video_frame_factory.get()); +} + +TEST_F(H264VideoToolboxEncoderTest, + CheckPowerMonitoringVideoFrameFactoryNoInitialFrame) { + VideoEncoder::FrameEncodedCallback cb = base::Bind(&NoopFrameEncodedCallback); + auto video_frame_factory = encoder_->CreateVideoFrameFactory(); + ASSERT_TRUE(video_frame_factory.get()); + + // After a power suspension, the factory should not produce frames. + power_source_->GenerateSuspendEvent(); + + ASSERT_FALSE(video_frame_factory->MaybeCreateFrame( + gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta())); + message_loop_.RunUntilIdle(); + ASSERT_FALSE(video_frame_factory->MaybeCreateFrame( + gfx::Size(kVideoWidth, kVideoHeight), base::TimeDelta())); + + // After a power resume event, the factory should produce frames right away + // because the encoder re-initializes on its own. + power_source_->GenerateResumeEvent(); + CreateFrameAndMemsetPlane(video_frame_factory.get()); +} + } // namespace cast } // namespace media
diff --git a/media/cast/sender/video_encoder.cc b/media/cast/sender/video_encoder.cc index d23496b..33c15c4 100644 --- a/media/cast/sender/video_encoder.cc +++ b/media/cast/sender/video_encoder.cc
@@ -26,11 +26,8 @@ #if defined(OS_MACOSX) || defined(OS_IOS) if (!video_config.use_external_encoder && H264VideoToolboxEncoder::IsSupported(video_config)) { - return scoped_ptr<VideoEncoder>( - new SizeAdaptableH264VideoToolboxVideoEncoder( - cast_environment, - video_config, - status_change_cb)); + return scoped_ptr<VideoEncoder>(new H264VideoToolboxEncoder( + cast_environment, video_config, status_change_cb)); } #endif // defined(OS_MACOSX)
diff --git a/media/cast/sender/video_encoder_unittest.cc b/media/cast/sender/video_encoder_unittest.cc index a528e28..dc1b948 100644 --- a/media/cast/sender/video_encoder_unittest.cc +++ b/media/cast/sender/video_encoder_unittest.cc
@@ -101,6 +101,10 @@ is_testing_video_toolbox_encoder(); } + bool encoder_has_resize_delay() const { + return is_testing_platform_encoder() && !is_testing_video_toolbox_encoder(); + } + VideoEncoder* video_encoder() const { return video_encoder_.get(); } @@ -282,14 +286,13 @@ uint32 reference_frame_id = 0; const gfx::Size frame_size(1280, 720); - // For the platform encoders, the first one or more frames is dropped while - // the encoder initializes. Then, for all encoders, expect one key frame is - // delivered. + // Some encoders drop one or more frames initially while the encoder + // initializes. Then, for all encoders, expect one key frame is delivered. bool accepted_first_frame = false; do { accepted_first_frame = EncodeAndCheckDelivery( CreateTestVideoFrame(frame_size), frame_id, reference_frame_id); - if (!is_testing_platform_encoder()) + if (!encoder_has_resize_delay()) EXPECT_TRUE(accepted_first_frame); RunTasksAndAdvanceClock(); } while (!accepted_first_frame); @@ -365,28 +368,28 @@ uint32 frame_id = 0; - // Encode one frame at each size. For the platform encoders, expect no frames - // to be delivered since each frame size change will sprun re-initialization - // of the underlying encoder. Otherwise, expect all key frames to come out. + // Encode one frame at each size. For encoders with a resize delay, except no + // frames to be delivered since each frame size change will sprun + // re-initialization of the underlying encoder. Otherwise expect all key + // frames to come out. for (const auto& frame_size : frame_sizes) { - EXPECT_EQ(!is_testing_platform_encoder(), - EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), - frame_id, + EXPECT_EQ(!encoder_has_resize_delay(), + EncodeAndCheckDelivery(CreateTestVideoFrame(frame_size), frame_id, frame_id)); RunTasksAndAdvanceClock(); - if (!is_testing_platform_encoder()) + if (!encoder_has_resize_delay()) ++frame_id; } - // Encode 10+ frames at each size. For the platform decoders, expect the - // first one or more frames are dropped while the encoder re-inits. Then, for - // all encoders, expect one key frame followed by all delta frames. + // Encode 10+ frames at each size. For encoders with a resize delay, expect + // the first one or more frames are dropped while the encoder re-inits. Then, + // for all encoders, expect one key frame followed by all delta frames. for (const auto& frame_size : frame_sizes) { bool accepted_first_frame = false; do { accepted_first_frame = EncodeAndCheckDelivery( CreateTestVideoFrame(frame_size), frame_id, frame_id); - if (!is_testing_platform_encoder()) + if (!encoder_has_resize_delay()) EXPECT_TRUE(accepted_first_frame); RunTasksAndAdvanceClock(); } while (!accepted_first_frame);
diff --git a/media/cast/sender/video_frame_factory.h b/media/cast/sender/video_frame_factory.h index d55deb7..f6b5889d 100644 --- a/media/cast/sender/video_frame_factory.h +++ b/media/cast/sender/video_frame_factory.h
@@ -27,9 +27,7 @@ // Clients are responsible for serialzing access to a |VideoFrameFactory|. // Generally speaking, it is expected that a client will be using these objects // from a rendering thread or callback (which may execute on different threads -// but never concurrently with itself). Forcing every implementation to take a -// lock, even with no contention, is an unnecessary cost, especially on mobile -// platforms. +// but never concurrently with itself). class VideoFrameFactory { public: virtual ~VideoFrameFactory() {} @@ -39,7 +37,10 @@ // with the encoder. The format is guaranteed to be I420 or NV12. // // This can transiently return null if the encoder is not yet initialized or - // is re-initializing. + // is re-initializing. Note however that if an encoder does support optimized + // frames, its |VideoFrameFactory| must eventually return frames. In practice, + // this means that |MaybeCreateFrame| must somehow signal the encoder to + // perform whatever initialization is needed to eventually produce frames. virtual scoped_refptr<VideoFrame> MaybeCreateFrame( const gfx::Size& frame_size, base::TimeDelta timestamp) = 0; };
diff --git a/media/cdm/aes_decryptor.cc b/media/cdm/aes_decryptor.cc index ec0de289..77783e3 100644 --- a/media/cdm/aes_decryptor.cc +++ b/media/cdm/aes_decryptor.cc
@@ -105,7 +105,7 @@ key_list_.erase(position); } -uint32 AesDecryptor::next_session_id_ = 1; +uint32_t AesDecryptor::next_session_id_ = 1; enum ClearBytesBufferSel { kSrcContainsClearBytes, @@ -114,8 +114,8 @@ static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, const ClearBytesBufferSel sel, - const uint8* src, - uint8* dst) { + const uint8_t* src, + uint8_t* dst) { for (size_t i = 0; i < subsamples.size(); i++) { const SubsampleEntry& subsample = subsamples[i]; if (sel == kSrcContainsClearBytes) { @@ -167,7 +167,7 @@ // TODO(xhwang): Find a way to avoid this data copy. return DecoderBuffer::CopyFrom( - reinterpret_cast<const uint8*>(decrypted_text.data()), + reinterpret_cast<const uint8_t*>(decrypted_text.data()), decrypted_text.size()); } @@ -192,7 +192,7 @@ // No need to decrypt if there is no encrypted data. if (total_encrypted_size <= 0) { - return DecoderBuffer::CopyFrom(reinterpret_cast<const uint8*>(sample), + return DecoderBuffer::CopyFrom(reinterpret_cast<const uint8_t*>(sample), sample_size); } @@ -202,9 +202,10 @@ // copy all encrypted subsamples to a contiguous buffer, decrypt them, then // copy the decrypted bytes over the encrypted bytes in the output. // TODO(strobe): attempt to reduce number of memory copies - scoped_ptr<uint8[]> encrypted_bytes(new uint8[total_encrypted_size]); + scoped_ptr<uint8_t[]> encrypted_bytes(new uint8_t[total_encrypted_size]); CopySubsamples(subsamples, kSrcContainsClearBytes, - reinterpret_cast<const uint8*>(sample), encrypted_bytes.get()); + reinterpret_cast<const uint8_t*>(sample), + encrypted_bytes.get()); base::StringPiece encrypted_text( reinterpret_cast<const char*>(encrypted_bytes.get()), @@ -217,9 +218,9 @@ DCHECK_EQ(decrypted_text.size(), encrypted_text.size()); scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom( - reinterpret_cast<const uint8*>(sample), sample_size); + reinterpret_cast<const uint8_t*>(sample), sample_size); CopySubsamples(subsamples, kDstContainsClearBytes, - reinterpret_cast<const uint8*>(decrypted_text.data()), + reinterpret_cast<const uint8_t*>(decrypted_text.data()), output->writable_data()); return output; } @@ -242,8 +243,7 @@ key_map_.clear(); } -void AesDecryptor::SetServerCertificate(const uint8* certificate_data, - int certificate_data_length, +void AesDecryptor::SetServerCertificate(const std::vector<uint8_t>& certificate, scoped_ptr<SimpleCdmPromise> promise) { promise->reject( NOT_SUPPORTED_ERROR, 0, "SetServerCertificate() is not supported."); @@ -252,8 +252,7 @@ void AesDecryptor::CreateSessionAndGenerateRequest( SessionType session_type, EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<NewSessionCdmPromise> promise) { std::string session_id(base::UintToString(next_session_id_++)); valid_sessions_.insert(session_id); @@ -261,27 +260,26 @@ // For now, the AesDecryptor does not care about |session_type|. // TODO(jrummell): Validate |session_type|. - std::vector<uint8> message; + std::vector<uint8_t> message; // TODO(jrummell): Since unprefixed will never send NULL, remove this check // when prefixed EME is removed (http://crbug.com/249976). - if (init_data && init_data_length) { - std::vector<std::vector<uint8>> keys; + if (!init_data.empty()) { + std::vector<std::vector<uint8_t>> keys; switch (init_data_type) { case EmeInitDataType::WEBM: // |init_data| is simply the key needed. - keys.push_back( - std::vector<uint8>(init_data, init_data + init_data_length)); + keys.push_back(init_data); break; case EmeInitDataType::CENC: // |init_data| is a set of 0 or more concatenated 'pssh' boxes. - if (!GetKeyIdsForCommonSystemId(init_data, init_data_length, &keys)) { + if (!GetKeyIdsForCommonSystemId(init_data, &keys)) { promise->reject(NOT_SUPPORTED_ERROR, 0, "No supported PSSH box found."); return; } break; case EmeInitDataType::KEYIDS: { - std::string init_data_string(init_data, init_data + init_data_length); + std::string init_data_string(init_data.begin(), init_data.end()); std::string error_message; if (!ExtractKeyIdsFromKeyIdsInitData(init_data_string, &keys, &error_message)) { @@ -315,11 +313,9 @@ } void AesDecryptor::UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<SimpleCdmPromise> promise) { - CHECK(response); - CHECK_GT(response_length, 0); + CHECK(!response.empty()); // TODO(jrummell): Convert back to a DCHECK once prefixed EME is removed. if (valid_sessions_.find(session_id) == valid_sessions_.end()) { @@ -327,8 +323,7 @@ return; } - std::string key_string(reinterpret_cast<const char*>(response), - response_length); + std::string key_string(response.begin(), response.end()); KeyIdAndKeyPairs keys; SessionType session_type = MediaKeys::TEMPORARY_SESSION;
diff --git a/media/cdm/aes_decryptor.h b/media/cdm/aes_decryptor.h index 5c7a06c..110abfb1 100644 --- a/media/cdm/aes_decryptor.h +++ b/media/cdm/aes_decryptor.h
@@ -7,6 +7,7 @@ #include <set> #include <string> +#include <vector> #include "base/basictypes.h" #include "base/containers/scoped_ptr_hash_map.h" @@ -39,21 +40,18 @@ ~AesDecryptor() override; // MediaKeys implementation. - void SetServerCertificate(const uint8* certificate_data, - int certificate_data_length, + void SetServerCertificate(const std::vector<uint8_t>& certificate, scoped_ptr<SimpleCdmPromise> promise) override; void CreateSessionAndGenerateRequest( SessionType session_type, EmeInitDataType init_data_type, - const uint8* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<NewSessionCdmPromise> promise) override; void LoadSession(SessionType session_type, const std::string& session_id, scoped_ptr<NewSessionCdmPromise> promise) override; void UpdateSession(const std::string& session_id, - const uint8* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<SimpleCdmPromise> promise) override; void CloseSession(const std::string& session_id, scoped_ptr<SimpleCdmPromise> promise) override; @@ -149,7 +147,7 @@ // Make session ID unique per renderer by making it static. Session // IDs seen by the app will be "1", "2", etc. - static uint32 next_session_id_; + static uint32_t next_session_id_; NewKeyCB new_audio_key_cb_; NewKeyCB new_video_key_cb_;
diff --git a/media/cdm/aes_decryptor_unittest.cc b/media/cdm/aes_decryptor_unittest.cc index 3f26239..6fd8cec7 100644 --- a/media/cdm/aes_decryptor_unittest.cc +++ b/media/cdm/aes_decryptor_unittest.cc
@@ -285,9 +285,9 @@ DCHECK(!key_id.empty()); EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsJSONDictionary(), GURL::EmptyGURL())); - decryptor_.CreateSessionAndGenerateRequest( - MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, &key_id[0], - key_id.size(), CreateSessionPromise(RESOLVED)); + decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION, + EmeInitDataType::WEBM, key_id, + CreateSessionPromise(RESOLVED)); // This expects the promise to be called synchronously, which is the case // for AesDecryptor. return session_id_; @@ -335,8 +335,7 @@ } decryptor_.UpdateSession(session_id, - reinterpret_cast<const uint8*>(key.c_str()), - key.length(), + std::vector<uint8>(key.begin(), key.end()), CreatePromise(expected_result)); } @@ -432,29 +431,29 @@ TEST_F(AesDecryptorTest, CreateSessionWithNullInitData) { EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL())); - decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION, - EmeInitDataType::WEBM, NULL, 0, - CreateSessionPromise(RESOLVED)); + decryptor_.CreateSessionAndGenerateRequest( + MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, std::vector<uint8>(), + CreateSessionPromise(RESOLVED)); } TEST_F(AesDecryptorTest, MultipleCreateSession) { EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL())); - decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION, - EmeInitDataType::WEBM, NULL, 0, - CreateSessionPromise(RESOLVED)); + decryptor_.CreateSessionAndGenerateRequest( + MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, std::vector<uint8>(), + CreateSessionPromise(RESOLVED)); EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL())); - decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION, - EmeInitDataType::WEBM, NULL, 0, - CreateSessionPromise(RESOLVED)); + decryptor_.CreateSessionAndGenerateRequest( + MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, std::vector<uint8>(), + CreateSessionPromise(RESOLVED)); EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL())); - decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION, - EmeInitDataType::WEBM, NULL, 0, - CreateSessionPromise(RESOLVED)); + decryptor_.CreateSessionAndGenerateRequest( + MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, std::vector<uint8>(), + CreateSessionPromise(RESOLVED)); } TEST_F(AesDecryptorTest, CreateSessionWithCencInitData) { @@ -475,8 +474,9 @@ EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsJSONDictionary(), GURL::EmptyGURL())); decryptor_.CreateSessionAndGenerateRequest( - MediaKeys::TEMPORARY_SESSION, EmeInitDataType::CENC, init_data, - arraysize(init_data), CreateSessionPromise(RESOLVED)); + MediaKeys::TEMPORARY_SESSION, EmeInitDataType::CENC, + std::vector<uint8>(init_data, init_data + arraysize(init_data)), + CreateSessionPromise(RESOLVED)); } TEST_F(AesDecryptorTest, CreateSessionWithKeyIdsInitData) { @@ -487,7 +487,7 @@ GURL::EmptyGURL())); decryptor_.CreateSessionAndGenerateRequest( MediaKeys::TEMPORARY_SESSION, EmeInitDataType::KEYIDS, - reinterpret_cast<const uint8*>(init_data), arraysize(init_data) - 1, + std::vector<uint8>(init_data, init_data + arraysize(init_data) - 1), CreateSessionPromise(RESOLVED)); }
diff --git a/media/cdm/cenc_utils.cc b/media/cdm/cenc_utils.cc index a59c19c..86779b217 100644 --- a/media/cdm/cenc_utils.cc +++ b/media/cdm/cenc_utils.cc
@@ -40,10 +40,10 @@ // SystemID for the Common System. // https://w3c.github.io/encrypted-media/cenc-format.html#common-system -const uint8 kCommonSystemId[] = { 0x10, 0x77, 0xef, 0xec, - 0xc0, 0xb2, 0x4d, 0x02, - 0xac, 0xe3, 0x3c, 0x1e, - 0x52, 0xe2, 0xfb, 0x4b }; +const uint8_t kCommonSystemId[] = { 0x10, 0x77, 0xef, 0xec, + 0xc0, 0xb2, 0x4d, 0x02, + 0xac, 0xe3, 0x3c, 0x1e, + 0x52, 0xe2, 0xfb, 0x4b }; #define RCHECK(x) \ do { \ @@ -52,10 +52,10 @@ } while (0) // Helper function to read up to 32 bits from a bit stream. -static uint32 ReadBits(BitReader* reader, int num_bits) { +static uint32_t ReadBits(BitReader* reader, int num_bits) { DCHECK_GE(reader->bits_available(), num_bits); DCHECK((num_bits > 0) && (num_bits <= 32)); - uint32 value; + uint32_t value; reader->ReadBits(num_bits, &value); return value; } @@ -63,7 +63,7 @@ // Checks whether the next 16 bytes matches the Common SystemID. // Assumes |reader| has enough data. static bool IsCommonSystemID(BitReader* reader) { - for (uint32 i = 0; i < arraysize(kCommonSystemId); ++i) { + for (uint32_t i = 0; i < arraysize(kCommonSystemId); ++i) { if (ReadBits(reader, 8) != kCommonSystemId[i]) return false; } @@ -100,11 +100,11 @@ return available_bytes >= *size; } -bool ValidatePsshInput(const uint8* input, size_t input_length) { +bool ValidatePsshInput(const std::vector<uint8_t>& input) { size_t offset = 0; - while (offset < input_length) { + while (offset < input.size()) { // Create a BitReader over the remaining part of the buffer. - BitReader reader(input + offset, input_length - offset); + BitReader reader(&input[offset], input.size() - offset); uint32 size; RCHECK(ValidBoxHeader(&reader, &size)); @@ -113,18 +113,16 @@ } // Only valid if this contains 0 or more 'pssh' boxes. - return offset == input_length; + return offset == input.size(); } -bool GetKeyIdsForCommonSystemId(const uint8* input, - int input_length, - std::vector<std::vector<uint8>>* key_ids) { - int offset = 0; - std::vector<std::vector<uint8>> result; +bool GetKeyIdsForCommonSystemId(const std::vector<uint8_t>& input, + KeyIdList* key_ids) { + size_t offset = 0; + KeyIdList result; - while (offset < input_length) { - // Create a BitReader over the remaining part of the buffer. - BitReader reader(input + offset, input_length - offset); + while (offset < input.size()) { + BitReader reader(&input[offset], input.size() - offset); uint32 size; RCHECK(ValidBoxHeader(&reader, &size)); @@ -132,7 +130,7 @@ offset += size; // Check the version, as KIDs only available if version > 0. - uint8 version = ReadBits(&reader, 8); + uint8_t version = ReadBits(&reader, 8); if (version == 0) continue; @@ -142,23 +140,24 @@ continue; // Validate SystemID - RCHECK(static_cast<uint32>(reader.bits_available()) >= + RCHECK(static_cast<uint32_t>(reader.bits_available()) >= arraysize(kCommonSystemId) * 8); if (!IsCommonSystemID(&reader)) continue; // Not Common System, so try the next pssh box. // Since version > 0, next field is the KID_count. - RCHECK(static_cast<uint32>(reader.bits_available()) >= sizeof(uint32) * 8); - uint32 count = ReadBits(&reader, 32); + RCHECK(static_cast<uint32_t>(reader.bits_available()) >= + sizeof(uint32_t) * 8); + uint32_t count = ReadBits(&reader, 32); if (count == 0) continue; // Make sure there is enough data for all the KIDs specified, and then // extract them. - RCHECK(static_cast<uint32>(reader.bits_available()) > count * 16 * 8); + RCHECK(static_cast<uint32_t>(reader.bits_available()) > count * 16 * 8); while (count > 0) { - std::vector<uint8> key; + std::vector<uint8_t> key; key.reserve(16); for (int i = 0; i < 16; ++i) { key.push_back(ReadBits(&reader, 8));
diff --git a/media/cdm/cenc_utils.h b/media/cdm/cenc_utils.h index 6fd9952..ec85fb3 100644 --- a/media/cdm/cenc_utils.h +++ b/media/cdm/cenc_utils.h
@@ -9,12 +9,13 @@ #include "base/basictypes.h" #include "media/base/media_export.h" +#include "media/cdm/json_web_key.h" namespace media { // Validate that |input| is a set of concatenated 'pssh' boxes and the sizes // match. Returns true if |input| looks valid, false otherwise. -MEDIA_EXPORT bool ValidatePsshInput(const uint8* input, size_t input_length); +MEDIA_EXPORT bool ValidatePsshInput(const std::vector<uint8_t>& input); // Gets the Key Ids from a 'pssh' box for the Common SystemID among one or // more concatenated 'pssh' boxes. If |input| looks valid, then true is @@ -24,10 +25,8 @@ // found, or are included but don't contain any key IDs. This should be // fixed once the test files are updated to include correct 'pssh' boxes. // http://crbug.com/460308 -MEDIA_EXPORT bool GetKeyIdsForCommonSystemId( - const uint8* input, - int input_length, - std::vector<std::vector<uint8>>* key_ids); +MEDIA_EXPORT bool GetKeyIdsForCommonSystemId(const std::vector<uint8_t>& input, + KeyIdList* key_ids); } // namespace media
diff --git a/media/cdm/cenc_utils_unittest.cc b/media/cdm/cenc_utils_unittest.cc index fd481da4..99236197 100644 --- a/media/cdm/cenc_utils_unittest.cc +++ b/media/cdm/cenc_utils_unittest.cc
@@ -9,19 +9,19 @@ namespace media { -const uint8 kKey1Data[] = { +const uint8_t kKey1Data[] = { 0x7E, 0x57, 0x1D, 0x03, 0x7E, 0x57, 0x1D, 0x03, 0x7E, 0x57, 0x1D, 0x03, 0x7E, 0x57, 0x1D, 0x03 }; -const uint8 kKey2Data[] = { +const uint8_t kKey2Data[] = { 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x04, }; -const uint8 kKey3Data[] = { +const uint8_t kKey3Data[] = { 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x05, 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x05, }; -const uint8 kKey4Data[] = { +const uint8_t kKey4Data[] = { 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x06, 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x06, }; @@ -36,7 +36,9 @@ protected: // Initialize the start of the 'pssh' box (up to key_count) - void InitializePSSHBox(std::vector<uint8>* box, uint8 size, uint8 version) { + void InitializePSSHBox(std::vector<uint8_t>* box, + uint8_t size, + uint8_t version) { DCHECK(box->size() == 0); box->reserve(size); @@ -75,9 +77,9 @@ box->push_back(0x4B); } - std::vector<uint8> MakePSSHBox(uint8 version) { - std::vector<uint8> box; - uint8 size = (version == 0) ? 32 : 36; + std::vector<uint8_t> MakePSSHBox(uint8_t version) { + std::vector<uint8_t> box; + uint8_t size = (version == 0) ? 32 : 36; InitializePSSHBox(&box, size, version); if (version > 0) { // Add key_count (= 0). @@ -94,13 +96,13 @@ return box; } - std::vector<uint8> MakePSSHBox(uint8 version, - const std::vector<uint8>& key1) { + std::vector<uint8_t> MakePSSHBox(uint8_t version, + const std::vector<uint8_t>& key1) { DCHECK(version > 0); DCHECK(key1.size() == 16); - std::vector<uint8> box; - uint8 size = 52; + std::vector<uint8_t> box; + uint8_t size = 52; InitializePSSHBox(&box, size, version); // Add key_count (= 1). @@ -121,15 +123,15 @@ return box; } - std::vector<uint8> MakePSSHBox(uint8 version, - const std::vector<uint8>& key1, - const std::vector<uint8>& key2) { + std::vector<uint8_t> MakePSSHBox(uint8_t version, + const std::vector<uint8_t>& key1, + const std::vector<uint8_t>& key2) { DCHECK(version > 0); DCHECK(key1.size() == 16); DCHECK(key2.size() == 16); - std::vector<uint8> box; - uint8 size = 68; + std::vector<uint8_t> box; + uint8_t size = 68; InitializePSSHBox(&box, size, version); // Add key_count (= 2). @@ -154,94 +156,94 @@ return box; } - const std::vector<uint8>& Key1() { return key1_; } - const std::vector<uint8>& Key2() { return key2_; } - const std::vector<uint8>& Key3() { return key3_; } - const std::vector<uint8>& Key4() { return key4_; } + const std::vector<uint8_t>& Key1() { return key1_; } + const std::vector<uint8_t>& Key2() { return key2_; } + const std::vector<uint8_t>& Key3() { return key3_; } + const std::vector<uint8_t>& Key4() { return key4_; } private: - std::vector<uint8> key1_; - std::vector<uint8> key2_; - std::vector<uint8> key3_; - std::vector<uint8> key4_; + std::vector<uint8_t> key1_; + std::vector<uint8_t> key2_; + std::vector<uint8_t> key3_; + std::vector<uint8_t> key4_; }; TEST_F(CencUtilsTest, EmptyPSSH) { - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(nullptr, 0)); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(nullptr, 0, &key_ids)); + KeyIdList key_ids; + EXPECT_TRUE(ValidatePsshInput(std::vector<uint8_t>())); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(std::vector<uint8_t>(), &key_ids)); EXPECT_EQ(0u, key_ids.size()); } TEST_F(CencUtilsTest, PSSHVersion0) { - std::vector<uint8> box = MakePSSHBox(0); - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(&box[0], box.size())); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box[0], box.size(), &key_ids)); + std::vector<uint8_t> box = MakePSSHBox(0); + KeyIdList key_ids; + EXPECT_TRUE(ValidatePsshInput(box)); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box, &key_ids)); EXPECT_EQ(0u, key_ids.size()); } TEST_F(CencUtilsTest, PSSHVersion1WithNoKeys) { - std::vector<uint8> box = MakePSSHBox(1); - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(&box[0], box.size())); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box[0], box.size(), &key_ids)); + std::vector<uint8_t> box = MakePSSHBox(1); + KeyIdList key_ids; + EXPECT_TRUE(ValidatePsshInput(box)); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box, &key_ids)); EXPECT_EQ(0u, key_ids.size()); } TEST_F(CencUtilsTest, PSSHVersion1WithOneKey) { - std::vector<uint8> box = MakePSSHBox(1, Key1()); - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(&box[0], box.size())); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box[0], box.size(), &key_ids)); + std::vector<uint8_t> box = MakePSSHBox(1, Key1()); + KeyIdList key_ids; + EXPECT_TRUE(ValidatePsshInput(box)); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box, &key_ids)); EXPECT_EQ(1u, key_ids.size()); EXPECT_EQ(key_ids[0], Key1()); } TEST_F(CencUtilsTest, PSSHVersion1WithTwoKeys) { - std::vector<uint8> box = MakePSSHBox(1, Key1(), Key2()); - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(&box[0], box.size())); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box[0], box.size(), &key_ids)); + std::vector<uint8_t> box = MakePSSHBox(1, Key1(), Key2()); + KeyIdList key_ids; + EXPECT_TRUE(ValidatePsshInput(box)); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box, &key_ids)); EXPECT_EQ(2u, key_ids.size()); EXPECT_EQ(key_ids[0], Key1()); EXPECT_EQ(key_ids[1], Key2()); } TEST_F(CencUtilsTest, PSSHVersion0Plus1) { - std::vector<uint8> box0 = MakePSSHBox(0); - std::vector<uint8> box1 = MakePSSHBox(1, Key1()); + std::vector<uint8_t> box0 = MakePSSHBox(0); + std::vector<uint8_t> box1 = MakePSSHBox(1, Key1()); // Concatentate box1 into box0. for (const auto& value : box1) box0.push_back(value); - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(&box0[0], box0.size())); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box0[0], box0.size(), &key_ids)); + KeyIdList key_ids; + EXPECT_TRUE(ValidatePsshInput(box0)); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box0, &key_ids)); EXPECT_EQ(1u, key_ids.size()); EXPECT_EQ(key_ids[0], Key1()); } TEST_F(CencUtilsTest, PSSHVersion1Plus0) { - std::vector<uint8> box0 = MakePSSHBox(0); - std::vector<uint8> box1 = MakePSSHBox(1, Key1()); + std::vector<uint8_t> box0 = MakePSSHBox(0); + std::vector<uint8_t> box1 = MakePSSHBox(1, Key1()); // Concatentate box0 into box1. for (const auto& value : box0) box1.push_back(value); - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(&box1[0], box1.size())); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box1[0], box1.size(), &key_ids)); + KeyIdList key_ids; + EXPECT_TRUE(ValidatePsshInput(box1)); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box1, &key_ids)); EXPECT_EQ(1u, key_ids.size()); EXPECT_EQ(key_ids[0], Key1()); } TEST_F(CencUtilsTest, MultiplePSSHVersion1) { - std::vector<uint8> box = MakePSSHBox(1, Key1(), Key2()); - std::vector<uint8> box1 = MakePSSHBox(1, Key3()); - std::vector<uint8> box2 = MakePSSHBox(1, Key4()); + std::vector<uint8_t> box = MakePSSHBox(1, Key1(), Key2()); + std::vector<uint8_t> box1 = MakePSSHBox(1, Key3()); + std::vector<uint8_t> box2 = MakePSSHBox(1, Key4()); // Concatentate box1 into box. for (const auto& value : box1) @@ -250,9 +252,9 @@ for (const auto& value : box2) box.push_back(value); - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(&box[0], box.size())); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box[0], box.size(), &key_ids)); + KeyIdList key_ids; + EXPECT_TRUE(ValidatePsshInput(box)); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box, &key_ids)); EXPECT_EQ(4u, key_ids.size()); EXPECT_EQ(key_ids[0], Key1()); EXPECT_EQ(key_ids[1], Key2()); @@ -261,43 +263,45 @@ } TEST_F(CencUtilsTest, InvalidPSSH) { - std::vector<uint8> box = MakePSSHBox(1, Key1(), Key2()); - std::vector<std::vector<uint8>> key_ids; + std::vector<uint8_t> box = MakePSSHBox(1, Key1(), Key2()); + KeyIdList key_ids; for (uint32 i = 1; i < box.size(); ++i) { // Modify size of data passed to be less than real size. - EXPECT_FALSE(ValidatePsshInput(&box[0], i)); - EXPECT_FALSE(GetKeyIdsForCommonSystemId(&box[0], i, &key_ids)); + std::vector<uint8_t> truncated(&box[0], &box[0] + i); + EXPECT_FALSE(ValidatePsshInput(truncated)); + EXPECT_FALSE(GetKeyIdsForCommonSystemId(truncated, &key_ids)); // Modify starting point. - EXPECT_FALSE(ValidatePsshInput(&box[i], box.size() - i)); - EXPECT_FALSE(GetKeyIdsForCommonSystemId(&box[i], box.size() - i, &key_ids)); + std::vector<uint8_t> changed_offset(&box[i], &box[i] + box.size() - i); + EXPECT_FALSE(ValidatePsshInput(changed_offset)); + EXPECT_FALSE(GetKeyIdsForCommonSystemId(changed_offset, &key_ids)); } } TEST_F(CencUtilsTest, InvalidSystemID) { - std::vector<uint8> box = MakePSSHBox(1, Key1(), Key2()); + std::vector<uint8_t> box = MakePSSHBox(1, Key1(), Key2()); // Modify the System ID. ++box[20]; - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box[0], box.size(), &key_ids)); + KeyIdList key_ids; + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box, &key_ids)); EXPECT_EQ(0u, key_ids.size()); } TEST_F(CencUtilsTest, InvalidFlags) { - std::vector<uint8> box = MakePSSHBox(1, Key1(), Key2()); + std::vector<uint8_t> box = MakePSSHBox(1, Key1(), Key2()); // Modify flags. box[10] = 3; - std::vector<std::vector<uint8>> key_ids; + KeyIdList key_ids; // TODO(jrummell): This should fail as the 'pssh' box is skipped. - EXPECT_TRUE(GetKeyIdsForCommonSystemId(&box[0], box.size(), &key_ids)); + EXPECT_TRUE(GetKeyIdsForCommonSystemId(box, &key_ids)); EXPECT_EQ(0u, key_ids.size()); } TEST_F(CencUtilsTest, LongSize) { - const uint8 data[] = { + const uint8_t data[] = { 0x00, 0x00, 0x00, 0x01, // size = 1 0x70, 0x73, 0x73, 0x68, // 'pssh' 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, // longsize @@ -313,14 +317,16 @@ 0x00, 0x00, 0x00, 0x00 // datasize }; - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(data, arraysize(data))); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(data, arraysize(data), &key_ids)); + KeyIdList key_ids; + EXPECT_TRUE( + ValidatePsshInput(std::vector<uint8_t>(data, data + arraysize(data)))); + EXPECT_TRUE(GetKeyIdsForCommonSystemId( + std::vector<uint8_t>(data, data + arraysize(data)), &key_ids)); EXPECT_EQ(2u, key_ids.size()); } TEST_F(CencUtilsTest, NoSize) { - const uint8 data[] = { + const uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, // size = 0 0x70, 0x73, 0x73, 0x68, // 'pssh' 0x01, // version @@ -335,14 +341,16 @@ 0x00, 0x00, 0x00, 0x00 // datasize }; - std::vector<std::vector<uint8>> key_ids; - EXPECT_TRUE(ValidatePsshInput(data, arraysize(data))); - EXPECT_TRUE(GetKeyIdsForCommonSystemId(data, arraysize(data), &key_ids)); + KeyIdList key_ids; + EXPECT_TRUE( + ValidatePsshInput(std::vector<uint8_t>(data, data + arraysize(data)))); + EXPECT_TRUE(GetKeyIdsForCommonSystemId( + std::vector<uint8_t>(data, data + arraysize(data)), &key_ids)); EXPECT_EQ(2u, key_ids.size()); } TEST_F(CencUtilsTest, HugeSize) { - const uint8 data[] = { + const uint8_t data[] = { 0x00, 0x00, 0x00, 0x01, // size = 1 0x70, 0x73, 0x73, 0x68, // 'pssh' 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // longsize = big @@ -358,9 +366,11 @@ 0x00, 0x00, 0x00, 0x00 // datasize }; - std::vector<std::vector<uint8>> key_ids; - EXPECT_FALSE(ValidatePsshInput(data, arraysize(data))); - EXPECT_FALSE(GetKeyIdsForCommonSystemId(data, arraysize(data), &key_ids)); + KeyIdList key_ids; + EXPECT_FALSE( + ValidatePsshInput(std::vector<uint8_t>(data, data + arraysize(data)))); + EXPECT_FALSE(GetKeyIdsForCommonSystemId( + std::vector<uint8_t>(data, data + arraysize(data)), &key_ids)); } } // namespace media
diff --git a/media/cdm/ppapi/cdm_adapter.cc b/media/cdm/ppapi/cdm_adapter.cc index 1d765d0..636ea32 100644 --- a/media/cdm/ppapi/cdm_adapter.cc +++ b/media/cdm/ppapi/cdm_adapter.cc
@@ -105,10 +105,16 @@ return PP_DECRYPTRESULT_DECRYPT_ERROR; case cdm::kDecodeError: return PP_DECRYPTRESULT_DECODE_ERROR; - default: - PP_NOTREACHED(); - return PP_DECRYPTRESULT_DECODE_ERROR; + case cdm::kSessionError: + case cdm::kDeferredInitialization: + // kSessionError and kDeferredInitialization are only used by the + // Initialize* methods internally and never returned. Deliver* + // methods should never use these values. + break; } + + PP_NOTREACHED(); + return PP_DECRYPTRESULT_DECRYPT_ERROR; } PP_DecryptedFrameFormat CdmVideoFormatToPpDecryptedFrameFormat(
diff --git a/media/cdm/ppapi/cdm_file_io_impl.h b/media/cdm/ppapi/cdm_file_io_impl.h index d885f1c..8e7a88b 100644 --- a/media/cdm/ppapi/cdm_file_io_impl.h +++ b/media/cdm/ppapi/cdm_file_io_impl.h
@@ -54,10 +54,10 @@ const pp::CompletionCallback& first_file_read_cb); // cdm::FileIO implementation. - virtual void Open(const char* file_name, uint32_t file_name_size) override; - virtual void Read() override; - virtual void Write(const uint8_t* data, uint32_t data_size) override; - virtual void Close() override; + void Open(const char* file_name, uint32_t file_name_size) override; + void Read() override; + void Write(const uint8_t* data, uint32_t data_size) override; + void Close() override; private: // TODO(xhwang): Introduce more detailed states for UMA logging if needed.
diff --git a/media/cdm/ppapi/cdm_file_io_test.h b/media/cdm/ppapi/cdm_file_io_test.h index 189c1f6..ccacec8 100644 --- a/media/cdm/ppapi/cdm_file_io_test.h +++ b/media/cdm/ppapi/cdm_file_io_test.h
@@ -62,7 +62,7 @@ FileIOTest(const CreateFileIOCB& create_file_io_cb, const std::string& test_name); - ~FileIOTest(); + ~FileIOTest() override; // Adds a test step in this test. |this| object doesn't take the ownership of // |data|, which should be valid throughout the lifetime of |this| object. @@ -96,11 +96,11 @@ static bool MatchesResult(const TestStep& a, const TestStep& b); // cdm::FileIOClient implementation. - virtual void OnOpenComplete(Status status) override; - virtual void OnReadComplete(Status status, - const uint8_t* data, - uint32_t data_size) override; - virtual void OnWriteComplete(Status status) override; + void OnOpenComplete(Status status) override; + void OnReadComplete(Status status, + const uint8_t* data, + uint32_t data_size) override; + void OnWriteComplete(Status status) override; // Runs the next step in this test case. void RunNextStep();
diff --git a/media/cdm/ppapi/cdm_helpers.h b/media/cdm/ppapi/cdm_helpers.h index 18c1d17..77cd8e36 100644 --- a/media/cdm/ppapi/cdm_helpers.h +++ b/media/cdm/ppapi/cdm_helpers.h
@@ -33,11 +33,11 @@ PpbBufferAllocator* allocator); // cdm::Buffer implementation. - virtual void Destroy() override; - virtual uint32_t Capacity() const override; - virtual uint8_t* Data() override; - virtual void SetSize(uint32_t size) override; - virtual uint32_t Size() const override { return size_; } + void Destroy() override; + uint32_t Capacity() const override; + uint8_t* Data() override; + void SetSize(uint32_t size) override; + uint32_t Size() const override { return size_; } // Takes the |buffer_| from this class and returns it. // Note: The caller must ensure |allocator->Release()| is called later so that @@ -54,7 +54,7 @@ PpbBuffer(pp::Buffer_Dev buffer, uint32_t buffer_id, PpbBufferAllocator* allocator); - virtual ~PpbBuffer(); + ~PpbBuffer() override; pp::Buffer_Dev buffer_; uint32_t buffer_id_; @@ -95,17 +95,20 @@ class DecryptedBlockImpl : public cdm::DecryptedBlock { public: DecryptedBlockImpl() : buffer_(NULL), timestamp_(0) {} - virtual ~DecryptedBlockImpl() { if (buffer_) buffer_->Destroy(); } + ~DecryptedBlockImpl() override { + if (buffer_) + buffer_->Destroy(); + } - virtual void SetDecryptedBuffer(cdm::Buffer* buffer) override { + void SetDecryptedBuffer(cdm::Buffer* buffer) override { buffer_ = static_cast<PpbBuffer*>(buffer); } - virtual cdm::Buffer* DecryptedBuffer() override { return buffer_; } + cdm::Buffer* DecryptedBuffer() override { return buffer_; } - virtual void SetTimestamp(int64_t timestamp) override { + void SetTimestamp(int64_t timestamp) override { timestamp_ = timestamp; } - virtual int64_t Timestamp() const override { return timestamp_; } + int64_t Timestamp() const override { return timestamp_; } private: PpbBuffer* buffer_; @@ -117,44 +120,44 @@ class VideoFrameImpl : public cdm::VideoFrame { public: VideoFrameImpl(); - virtual ~VideoFrameImpl(); + ~VideoFrameImpl() override; - virtual void SetFormat(cdm::VideoFormat format) override { + void SetFormat(cdm::VideoFormat format) override { format_ = format; } - virtual cdm::VideoFormat Format() const override { return format_; } + cdm::VideoFormat Format() const override { return format_; } - virtual void SetSize(cdm::Size size) override { size_ = size; } - virtual cdm::Size Size() const override { return size_; } + void SetSize(cdm::Size size) override { size_ = size; } + cdm::Size Size() const override { return size_; } - virtual void SetFrameBuffer(cdm::Buffer* frame_buffer) override { + void SetFrameBuffer(cdm::Buffer* frame_buffer) override { frame_buffer_ = static_cast<PpbBuffer*>(frame_buffer); } - virtual cdm::Buffer* FrameBuffer() override { return frame_buffer_; } + cdm::Buffer* FrameBuffer() override { return frame_buffer_; } - virtual void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane, - uint32_t offset) override { + void SetPlaneOffset(cdm::VideoFrame::VideoPlane plane, + uint32_t offset) override { PP_DCHECK(plane < kMaxPlanes); plane_offsets_[plane] = offset; } - virtual uint32_t PlaneOffset(VideoPlane plane) override { + uint32_t PlaneOffset(VideoPlane plane) override { PP_DCHECK(plane < kMaxPlanes); return plane_offsets_[plane]; } - virtual void SetStride(VideoPlane plane, uint32_t stride) override { + void SetStride(VideoPlane plane, uint32_t stride) override { PP_DCHECK(plane < kMaxPlanes); strides_[plane] = stride; } - virtual uint32_t Stride(VideoPlane plane) override { + uint32_t Stride(VideoPlane plane) override { PP_DCHECK(plane < kMaxPlanes); return strides_[plane]; } - virtual void SetTimestamp(int64_t timestamp) override { + void SetTimestamp(int64_t timestamp) override { timestamp_ = timestamp; } - virtual int64_t Timestamp() const override { return timestamp_; } + int64_t Timestamp() const override { return timestamp_; } private: // The video buffer format. @@ -183,22 +186,22 @@ class AudioFramesImpl : public cdm::AudioFrames { public: AudioFramesImpl() : buffer_(NULL), format_(cdm::kUnknownAudioFormat) {} - virtual ~AudioFramesImpl() { + ~AudioFramesImpl() override { if (buffer_) buffer_->Destroy(); } // AudioFrames implementation. - virtual void SetFrameBuffer(cdm::Buffer* buffer) override { + void SetFrameBuffer(cdm::Buffer* buffer) override { buffer_ = static_cast<PpbBuffer*>(buffer); } - virtual cdm::Buffer* FrameBuffer() override { + cdm::Buffer* FrameBuffer() override { return buffer_; } - virtual void SetFormat(cdm::AudioFormat format) override { + void SetFormat(cdm::AudioFormat format) override { format_ = format; } - virtual cdm::AudioFormat Format() const override { + cdm::AudioFormat Format() const override { return format_; }
diff --git a/media/cdm/ppapi/cdm_wrapper.h b/media/cdm/ppapi/cdm_wrapper.h index 8a85a8a..3e48eb4 100644 --- a/media/cdm/ppapi/cdm_wrapper.h +++ b/media/cdm/ppapi/cdm_wrapper.h
@@ -116,16 +116,16 @@ static_cast<CdmInterface*>(cdm_instance)); } - virtual ~CdmWrapperImpl() { + ~CdmWrapperImpl() override { cdm_->Destroy(); } - virtual void Initialize(bool allow_distinctive_identifier, - bool allow_persistent_state) override { + void Initialize(bool allow_distinctive_identifier, + bool allow_persistent_state) override { cdm_->Initialize(allow_distinctive_identifier, allow_persistent_state); } - virtual void SetServerCertificate( + void SetServerCertificate( uint32_t promise_id, const uint8_t* server_certificate_data, uint32_t server_certificate_data_size) override { @@ -133,7 +133,7 @@ promise_id, server_certificate_data, server_certificate_data_size); } - virtual void CreateSessionAndGenerateRequest( + void CreateSessionAndGenerateRequest( uint32_t promise_id, cdm::SessionType session_type, cdm::InitDataType init_data_type, @@ -143,14 +143,14 @@ promise_id, session_type, init_data_type, init_data, init_data_size); } - virtual void LoadSession(uint32_t promise_id, + void LoadSession(uint32_t promise_id, cdm::SessionType session_type, const char* session_id, uint32_t session_id_size) override { cdm_->LoadSession(promise_id, session_type, session_id, session_id_size); } - virtual void UpdateSession(uint32_t promise_id, + void UpdateSession(uint32_t promise_id, const char* session_id, uint32_t session_id_size, const uint8_t* response, @@ -159,63 +159,63 @@ response_size); } - virtual void CloseSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) override { + void CloseSession(uint32_t promise_id, + const char* session_id, + uint32_t session_id_size) override { cdm_->CloseSession(promise_id, session_id, session_id_size); } - virtual void RemoveSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) override { + void RemoveSession(uint32_t promise_id, + const char* session_id, + uint32_t session_id_size) override { cdm_->RemoveSession(promise_id, session_id, session_id_size); } - virtual void TimerExpired(void* context) override { + void TimerExpired(void* context) override { cdm_->TimerExpired(context); } - virtual cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, - cdm::DecryptedBlock* decrypted_buffer) override { + cdm::Status Decrypt(const cdm::InputBuffer& encrypted_buffer, + cdm::DecryptedBlock* decrypted_buffer) override { return cdm_->Decrypt(encrypted_buffer, decrypted_buffer); } - virtual cdm::Status InitializeAudioDecoder( + cdm::Status InitializeAudioDecoder( const cdm::AudioDecoderConfig& audio_decoder_config) override { return cdm_->InitializeAudioDecoder(audio_decoder_config); } - virtual cdm::Status InitializeVideoDecoder( + cdm::Status InitializeVideoDecoder( const cdm::VideoDecoderConfig& video_decoder_config) override { return cdm_->InitializeVideoDecoder(video_decoder_config); } - virtual void DeinitializeDecoder(cdm::StreamType decoder_type) override { + void DeinitializeDecoder(cdm::StreamType decoder_type) override { cdm_->DeinitializeDecoder(decoder_type); } - virtual void ResetDecoder(cdm::StreamType decoder_type) override { + void ResetDecoder(cdm::StreamType decoder_type) override { cdm_->ResetDecoder(decoder_type); } - virtual cdm::Status DecryptAndDecodeFrame( + cdm::Status DecryptAndDecodeFrame( const cdm::InputBuffer& encrypted_buffer, cdm::VideoFrame* video_frame) override { return cdm_->DecryptAndDecodeFrame(encrypted_buffer, video_frame); } - virtual cdm::Status DecryptAndDecodeSamples( + cdm::Status DecryptAndDecodeSamples( const cdm::InputBuffer& encrypted_buffer, cdm::AudioFrames* audio_frames) override { return cdm_->DecryptAndDecodeSamples(encrypted_buffer, audio_frames); } - virtual void OnPlatformChallengeResponse( + void OnPlatformChallengeResponse( const cdm::PlatformChallengeResponse& response) override { cdm_->OnPlatformChallengeResponse(response); } - virtual void OnQueryOutputProtectionStatus( + void OnQueryOutputProtectionStatus( cdm::QueryResult result, uint32_t link_mask, uint32_t output_protection_mask) override {
diff --git a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc index 725ee88f..39199de7 100644 --- a/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc +++ b/media/cdm/ppapi/external_clear_key/clear_key_cdm.cc
@@ -322,7 +322,8 @@ promise_id))); decryptor_.CreateSessionAndGenerateRequest( ConvertSessionType(session_type), ConvertInitDataType(init_data_type), - init_data, init_data_size, promise.Pass()); + std::vector<uint8_t>(init_data, init_data + init_data_size), + promise.Pass()); if (key_system_ == kExternalClearKeyFileIOTestKeySystem) StartFileIOTest(); @@ -361,9 +362,9 @@ base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), promise_id))); - decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION, - EmeInitDataType::WEBM, NULL, 0, - promise.Pass()); + decryptor_.CreateSessionAndGenerateRequest( + MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, + std::vector<uint8_t>(), promise.Pass()); } void ClearKeyCdm::UpdateSession(uint32 promise_id, @@ -384,7 +385,8 @@ base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), promise_id))); decryptor_.UpdateSession( - web_session_str, response, response_size, promise.Pass()); + web_session_str, std::vector<uint8_t>(response, response + response_size), + promise.Pass()); if (!renewal_timer_set_) { ScheduleNextRenewal(); @@ -721,8 +723,7 @@ base::Bind(&ClearKeyCdm::OnPromiseFailed, base::Unretained(this), promise_id_for_emulated_loadsession_))); decryptor_.UpdateSession(session_id_for_emulated_loadsession_, - reinterpret_cast<const uint8*>(jwk_set.data()), - jwk_set.size(), + std::vector<uint8_t>(jwk_set.begin(), jwk_set.end()), promise.Pass()); }
diff --git a/media/cdm/ppapi/external_clear_key/fake_cdm_video_decoder.h b/media/cdm/ppapi/external_clear_key/fake_cdm_video_decoder.h index 6bc5e323..d10372e 100644 --- a/media/cdm/ppapi/external_clear_key/fake_cdm_video_decoder.h +++ b/media/cdm/ppapi/external_clear_key/fake_cdm_video_decoder.h
@@ -15,17 +15,17 @@ class FakeCdmVideoDecoder : public CdmVideoDecoder { public: explicit FakeCdmVideoDecoder(cdm::Host* host); - virtual ~FakeCdmVideoDecoder(); + ~FakeCdmVideoDecoder() override; // CdmVideoDecoder implementation. - virtual bool Initialize(const cdm::VideoDecoderConfig& config) override; - virtual void Deinitialize() override; - virtual void Reset() override; - virtual cdm::Status DecodeFrame(const uint8_t* compressed_frame, - int32_t compressed_frame_size, - int64_t timestamp, - cdm::VideoFrame* decoded_frame) override; - virtual bool is_initialized() const override { return is_initialized_; } + bool Initialize(const cdm::VideoDecoderConfig& config) override; + void Deinitialize() override; + void Reset() override; + cdm::Status DecodeFrame(const uint8_t* compressed_frame, + int32_t compressed_frame_size, + int64_t timestamp, + cdm::VideoFrame* decoded_frame) override; + bool is_initialized() const override { return is_initialized_; } private: bool is_initialized_;
diff --git a/media/cdm/ppapi/external_clear_key/ffmpeg_cdm_video_decoder.h b/media/cdm/ppapi/external_clear_key/ffmpeg_cdm_video_decoder.h index 00e11fdd..70bd2bf4 100644 --- a/media/cdm/ppapi/external_clear_key/ffmpeg_cdm_video_decoder.h +++ b/media/cdm/ppapi/external_clear_key/ffmpeg_cdm_video_decoder.h
@@ -20,17 +20,17 @@ class FFmpegCdmVideoDecoder : public CdmVideoDecoder { public: explicit FFmpegCdmVideoDecoder(ClearKeyCdmHost* host); - virtual ~FFmpegCdmVideoDecoder(); + ~FFmpegCdmVideoDecoder() override; // CdmVideoDecoder implementation. - virtual bool Initialize(const cdm::VideoDecoderConfig& config) override; - virtual void Deinitialize() override; - virtual void Reset() override; - virtual cdm::Status DecodeFrame(const uint8_t* compressed_frame, - int32_t compressed_frame_size, - int64_t timestamp, - cdm::VideoFrame* decoded_frame) override; - virtual bool is_initialized() const override { return is_initialized_; } + bool Initialize(const cdm::VideoDecoderConfig& config) override; + void Deinitialize() override; + void Reset() override; + cdm::Status DecodeFrame(const uint8_t* compressed_frame, + int32_t compressed_frame_size, + int64_t timestamp, + cdm::VideoFrame* decoded_frame) override; + bool is_initialized() const override { return is_initialized_; } // Returns true when |format| and |data_size| specify a supported video // output configuration.
diff --git a/media/cdm/ppapi/external_clear_key/libvpx_cdm_video_decoder.h b/media/cdm/ppapi/external_clear_key/libvpx_cdm_video_decoder.h index 0ba05b9c..14f8b14 100644 --- a/media/cdm/ppapi/external_clear_key/libvpx_cdm_video_decoder.h +++ b/media/cdm/ppapi/external_clear_key/libvpx_cdm_video_decoder.h
@@ -18,17 +18,17 @@ class LibvpxCdmVideoDecoder : public CdmVideoDecoder { public: explicit LibvpxCdmVideoDecoder(CdmHost* host); - virtual ~LibvpxCdmVideoDecoder(); + ~LibvpxCdmVideoDecoder() override; // CdmVideoDecoder implementation. - virtual bool Initialize(const cdm::VideoDecoderConfig& config) override; - virtual void Deinitialize() override; - virtual void Reset() override; - virtual cdm::Status DecodeFrame(const uint8_t* compressed_frame, - int32_t compressed_frame_size, - int64_t timestamp, - cdm::VideoFrame* decoded_frame) override; - virtual bool is_initialized() const override { return is_initialized_; } + bool Initialize(const cdm::VideoDecoderConfig& config) override; + void Deinitialize() override; + void Reset() override; + cdm::Status DecodeFrame(const uint8_t* compressed_frame, + int32_t compressed_frame_size, + int64_t timestamp, + cdm::VideoFrame* decoded_frame) override; + bool is_initialized() const override { return is_initialized_; } // Returns true when |format| and |data_size| specify a supported video // output configuration.
diff --git a/media/cdm/proxy_decryptor.cc b/media/cdm/proxy_decryptor.cc index 9260e14..c30cb837 100644 --- a/media/cdm/proxy_decryptor.cc +++ b/media/cdm/proxy_decryptor.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/logging.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "media/base/cdm_callback_promise.h" #include "media/base/cdm_factory.h" @@ -216,9 +217,8 @@ // on Android) and the permission status will be evaluated then. DVLOG_IF(1, !granted) << "Permission request rejected."; - media_keys_->CreateSessionAndGenerateRequest( - session_type, init_data_type, vector_as_array(&init_data), - init_data.size(), promise.Pass()); + media_keys_->CreateSessionAndGenerateRequest(session_type, init_data_type, + init_data, promise.Pass()); } void ProxyDecryptor::AddKey(const uint8* key, @@ -271,12 +271,14 @@ GenerateJWKSet(key, key_length, init_data, init_data_length); DCHECK(!jwk.empty()); media_keys_->UpdateSession(new_session_id, - reinterpret_cast<const uint8*>(jwk.data()), - jwk.size(), promise.Pass()); + std::vector<uint8_t>(jwk.begin(), jwk.end()), + promise.Pass()); return; } - media_keys_->UpdateSession(new_session_id, key, key_length, promise.Pass()); + media_keys_->UpdateSession(new_session_id, + std::vector<uint8_t>(key, key + key_length), + promise.Pass()); } void ProxyDecryptor::CancelKeyRequest(const std::string& session_id) {
diff --git a/media/media.gyp b/media/media.gyp index 272ee39f..e4518de 100644 --- a/media/media.gyp +++ b/media/media.gyp
@@ -1100,6 +1100,11 @@ 'dependencies': [ '../device/udev_linux/udev.gyp:udev_linux', ], + }, { # use_udev==0 + 'sources!': [ + 'midi/midi_manager_alsa.cc', + 'midi/midi_manager_alsa.h', + ], }], ], # conditions 'target_conditions': [ @@ -1146,6 +1151,7 @@ 'audio/audio_input_unittest.cc', 'audio/audio_input_volume_unittest.cc', 'audio/audio_low_latency_input_output_unittest.cc', + 'audio/audio_manager_factory_unittest.cc', 'audio/audio_manager_unittest.cc', 'audio/audio_output_controller_unittest.cc', 'audio/audio_output_device_unittest.cc', @@ -1415,7 +1421,7 @@ 'video/capture/mac/video_capture_device_factory_mac_unittest.mm', ] }], - ['use_alsa==1', { + ['use_alsa==1 and use_udev==1', { 'sources': [ 'midi/midi_manager_alsa_unittest.cc', ] @@ -1648,6 +1654,7 @@ ], }, { + # GN version: //media/base:media_sse2 'target_name': 'media_sse2', 'type': 'static_library', 'cflags': [
diff --git a/media/midi/midi_manager.cc b/media/midi/midi_manager.cc index 183988e..6522e56 100644 --- a/media/midi/midi_manager.cc +++ b/media/midi/midi_manager.cc
@@ -19,8 +19,8 @@ MidiManager::~MidiManager() { } -#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(USE_ALSA) && \ - !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#if !defined(OS_MACOSX) && !defined(OS_WIN) && \ + !(defined(USE_ALSA) && defined(USE_UDEV)) && !defined(OS_ANDROID) MidiManager* MidiManager::Create() { return new MidiManager; }
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc index 3db6955..cfa6371 100644 --- a/media/midi/midi_manager_alsa.cc +++ b/media/midi/midi_manager_alsa.cc
@@ -70,6 +70,7 @@ out_client_id_(-1), in_port_id_(-1), decoder_(NULL), + udev_(device::udev_new()), send_thread_("MidiSendThread"), event_thread_("MidiEventThread"), event_thread_shutdown_(false) {
diff --git a/media/midi/midi_manager_alsa.h b/media/midi/midi_manager_alsa.h index a041004d..200c4c0 100644 --- a/media/midi/midi_manager_alsa.h +++ b/media/midi/midi_manager_alsa.h
@@ -17,6 +17,7 @@ #include "base/synchronization/lock.h" #include "base/threading/thread.h" #include "base/values.h" +#include "device/udev_linux/scoped_udev.h" #include "media/midi/midi_manager.h" namespace media { @@ -312,6 +313,9 @@ // ALSA event -> MIDI coder. snd_midi_event_t* decoder_; + // udev, for querying hardware devices. + device::ScopedUdevPtr udev_; + base::Thread send_thread_; base::Thread event_thread_;
diff --git a/media/midi/midi_manager_unittest.cc b/media/midi/midi_manager_unittest.cc index ffbcd0f..cfe58e3 100644 --- a/media/midi/midi_manager_unittest.cc +++ b/media/midi/midi_manager_unittest.cc
@@ -258,8 +258,8 @@ MidiResult result = client->WaitForResult(); // This #ifdef needs to be identical to the one in media/midi/midi_manager.cc. // Do not change the condition for disabling this test. -#if !defined(OS_MACOSX) && !defined(OS_WIN) && !defined(USE_ALSA) && \ - !defined(OS_ANDROID) && !defined(OS_CHROMEOS) +#if !defined(OS_MACOSX) && !defined(OS_WIN) && \ + !(defined(USE_ALSA) && defined(USE_UDEV)) && !defined(OS_ANDROID) EXPECT_EQ(MIDI_NOT_SUPPORTED, result); #elif defined(USE_ALSA) // Temporary until http://crbug.com/371230 is resolved.
diff --git a/media/midi/midi_manager_usb.cc b/media/midi/midi_manager_usb.cc index cefbc1a..346098c 100644 --- a/media/midi/midi_manager_usb.cc +++ b/media/midi/midi_manager_usb.cc
@@ -124,7 +124,7 @@ bool MidiManagerUsb::AddPorts(UsbMidiDevice* device, int device_id) { UsbMidiDescriptorParser parser; - std::vector<uint8> descriptor = device->GetDescriptor(); + std::vector<uint8> descriptor = device->GetDescriptors(); const uint8* data = descriptor.size() > 0 ? &descriptor[0] : NULL; std::vector<UsbMidiJack> jacks; bool parse_result = parser.Parse(device, @@ -134,30 +134,25 @@ if (!parse_result) return false; + std::string manufacturer(device->GetManufacturer()); + std::string product_name(device->GetProductName()); + std::string version(device->GetDeviceVersion()); + for (size_t j = 0; j < jacks.size(); ++j) { + // Port ID must be unique in a MIDI manager. This ID setting is + // sufficiently unique although there is no user-friendly meaning. + // TODO(yhirano): Use a hashed string as ID. + std::string id( + base::StringPrintf("port-%d-%ld", device_id, static_cast<long>(j))); if (jacks[j].direction() == UsbMidiJack::DIRECTION_OUT) { output_streams_.push_back(new UsbMidiOutputStream(jacks[j])); - // TODO(yhirano): Set appropriate properties. - // TODO(yhiran): Port ID should contain product ID / vendor ID. - // Port ID must be unique in a MIDI manager. This (and the below) ID - // setting is sufficiently unique although there is no user-friendly - // meaning. - MidiPortInfo port; - port.state = MIDI_PORT_OPENED; - port.id = base::StringPrintf("port-%d-%ld", - device_id, - static_cast<long>(j)); - AddOutputPort(port); + AddOutputPort(MidiPortInfo(id, manufacturer, product_name, version, + MIDI_PORT_OPENED)); } else { DCHECK_EQ(jacks[j].direction(), UsbMidiJack::DIRECTION_IN); input_stream_->Add(jacks[j]); - // TODO(yhirano): Set appropriate properties. - MidiPortInfo port; - port.state = MIDI_PORT_OPENED; - port.id = base::StringPrintf("port-%d-%ld", - device_id, - static_cast<long>(j)); - AddInputPort(port); + AddInputPort(MidiPortInfo(id, manufacturer, product_name, version, + MIDI_PORT_OPENED)); } } return true;
diff --git a/media/midi/midi_manager_usb_unittest.cc b/media/midi/midi_manager_usb_unittest.cc index 7f5bb27b..01248c12 100644 --- a/media/midi/midi_manager_usb_unittest.cc +++ b/media/midi/midi_manager_usb_unittest.cc
@@ -45,11 +45,15 @@ explicit FakeUsbMidiDevice(Logger* logger) : logger_(logger) {} ~FakeUsbMidiDevice() override {} - std::vector<uint8> GetDescriptor() override { - logger_->AddLog("UsbMidiDevice::GetDescriptor\n"); - return descriptor_; + std::vector<uint8> GetDescriptors() override { + logger_->AddLog("UsbMidiDevice::GetDescriptors\n"); + return descriptors_; } + std::string GetManufacturer() override { return manufacturer_; } + std::string GetProductName() override { return product_name_; } + std::string GetDeviceVersion() override { return device_version_; } + void Send(int endpoint_number, const std::vector<uint8>& data) override { logger_->AddLog("UsbMidiDevice::Send "); logger_->AddLog(base::StringPrintf("endpoint = %d data =", @@ -59,12 +63,24 @@ logger_->AddLog("\n"); } - void SetDescriptor(const std::vector<uint8> descriptor) { - descriptor_ = descriptor; + void SetDescriptors(const std::vector<uint8> descriptors) { + descriptors_ = descriptors; + } + void SetManufacturer(const std::string& manufacturer) { + manufacturer_ = manufacturer; + } + void SetProductName(const std::string& product_name) { + product_name_ = product_name; + } + void SetDeviceVersion(const std::string& device_version) { + device_version_ = device_version; } private: - std::vector<uint8> descriptor_; + std::vector<uint8> descriptors_; + std::string manufacturer_; + std::string product_name_; + std::string device_version_; Logger* logger_; DISALLOW_COPY_AND_ASSIGN(FakeUsbMidiDevice); @@ -215,7 +231,7 @@ TEST_F(MidiManagerUsbTest, Initialize) { scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); - uint8 descriptor[] = { + uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, @@ -231,7 +247,10 @@ 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; - device->SetDescriptor(ToVector(descriptor)); + device->SetDescriptors(ToVector(descriptors)); + device->SetManufacturer("vendor1"); + device->SetProductName("device1"); + device->SetDeviceVersion("1.02"); Initialize(); ScopedVector<UsbMidiDevice> devices; @@ -241,7 +260,21 @@ EXPECT_EQ(MIDI_OK, GetInitializationResult()); ASSERT_EQ(1u, input_ports().size()); + EXPECT_EQ("port-0-2", input_ports()[0].id); + EXPECT_EQ("vendor1", input_ports()[0].manufacturer); + EXPECT_EQ("device1", input_ports()[0].name); + EXPECT_EQ("1.02", input_ports()[0].version); + ASSERT_EQ(2u, output_ports().size()); + EXPECT_EQ("port-0-0", output_ports()[0].id); + EXPECT_EQ("vendor1", output_ports()[0].manufacturer); + EXPECT_EQ("device1", output_ports()[0].name); + EXPECT_EQ("1.02", output_ports()[0].version); + EXPECT_EQ("port-0-1", output_ports()[1].id); + EXPECT_EQ("vendor1", output_ports()[1].manufacturer); + EXPECT_EQ("device1", output_ports()[1].name); + EXPECT_EQ("1.02", output_ports()[1].version); + ASSERT_TRUE(manager_->input_stream()); std::vector<UsbMidiJack> jacks = manager_->input_stream()->jacks(); ASSERT_EQ(2u, manager_->output_streams().size()); @@ -250,13 +283,13 @@ ASSERT_EQ(1u, jacks.size()); EXPECT_EQ(2, jacks[0].endpoint_number()); - EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); + EXPECT_EQ("UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); } TEST_F(MidiManagerUsbTest, InitializeMultipleDevices) { scoped_ptr<FakeUsbMidiDevice> device1(new FakeUsbMidiDevice(&logger_)); scoped_ptr<FakeUsbMidiDevice> device2(new FakeUsbMidiDevice(&logger_)); - uint8 descriptor[] = { + uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, @@ -270,8 +303,14 @@ 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; - device1->SetDescriptor(ToVector(descriptor)); - device2->SetDescriptor(ToVector(descriptor)); + device1->SetDescriptors(ToVector(descriptors)); + device1->SetManufacturer("vendor1"); + device1->SetProductName("device1"); + device1->SetDeviceVersion("1.02"); + device2->SetDescriptors(ToVector(descriptors)); + device2->SetManufacturer("vendor2"); + device2->SetProductName("device2"); + device2->SetDeviceVersion("98.76"); Initialize(); ScopedVector<UsbMidiDevice> devices; @@ -282,7 +321,33 @@ EXPECT_EQ(MIDI_OK, GetInitializationResult()); ASSERT_EQ(2u, input_ports().size()); + EXPECT_EQ("port-0-2", input_ports()[0].id); + EXPECT_EQ("vendor1", input_ports()[0].manufacturer); + EXPECT_EQ("device1", input_ports()[0].name); + EXPECT_EQ("1.02", input_ports()[0].version); + EXPECT_EQ("port-1-2", input_ports()[1].id); + EXPECT_EQ("vendor2", input_ports()[1].manufacturer); + EXPECT_EQ("device2", input_ports()[1].name); + EXPECT_EQ("98.76", input_ports()[1].version); + ASSERT_EQ(4u, output_ports().size()); + EXPECT_EQ("port-0-0", output_ports()[0].id); + EXPECT_EQ("vendor1", output_ports()[0].manufacturer); + EXPECT_EQ("device1", output_ports()[0].name); + EXPECT_EQ("1.02", output_ports()[0].version); + EXPECT_EQ("port-0-1", output_ports()[1].id); + EXPECT_EQ("vendor1", output_ports()[1].manufacturer); + EXPECT_EQ("device1", output_ports()[1].name); + EXPECT_EQ("1.02", output_ports()[1].version); + EXPECT_EQ("port-1-0", output_ports()[2].id); + EXPECT_EQ("vendor2", output_ports()[2].manufacturer); + EXPECT_EQ("device2", output_ports()[2].name); + EXPECT_EQ("98.76", output_ports()[2].version); + EXPECT_EQ("port-1-1", output_ports()[3].id); + EXPECT_EQ("vendor2", output_ports()[3].manufacturer); + EXPECT_EQ("device2", output_ports()[3].name); + EXPECT_EQ("98.76", output_ports()[3].version); + ASSERT_TRUE(manager_->input_stream()); std::vector<UsbMidiJack> jacks = manager_->input_stream()->jacks(); ASSERT_EQ(4u, manager_->output_streams().size()); @@ -292,8 +357,8 @@ EXPECT_EQ(2, jacks[0].endpoint_number()); EXPECT_EQ( - "UsbMidiDevice::GetDescriptor\n" - "UsbMidiDevice::GetDescriptor\n", + "UsbMidiDevice::GetDescriptors\n" + "UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); } @@ -305,10 +370,10 @@ EXPECT_EQ(MIDI_INITIALIZATION_ERROR, GetInitializationResult()); } -TEST_F(MidiManagerUsbTest, InitializeFailBecauseOfInvalidDescriptor) { +TEST_F(MidiManagerUsbTest, InitializeFailBecauseOfInvalidDescriptors) { scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); - uint8 descriptor[] = {0x04}; - device->SetDescriptor(ToVector(descriptor)); + uint8 descriptors[] = {0x04}; + device->SetDescriptors(ToVector(descriptors)); Initialize(); ScopedVector<UsbMidiDevice> devices; @@ -316,13 +381,13 @@ EXPECT_FALSE(IsInitializationCallbackInvoked()); RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(MIDI_INITIALIZATION_ERROR, GetInitializationResult()); - EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); + EXPECT_EQ("UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); } TEST_F(MidiManagerUsbTest, Send) { Initialize(); scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); - uint8 descriptor[] = { + uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, @@ -339,7 +404,7 @@ 0x05, 0x25, 0x01, 0x01, 0x07, }; - device->SetDescriptor(ToVector(descriptor)); + device->SetDescriptors(ToVector(descriptors)); uint8 data[] = { 0x90, 0x45, 0x7f, 0xf0, 0x00, 0x01, 0xf7, @@ -357,7 +422,7 @@ // invoke the task. base::RunLoop run_loop; run_loop.RunUntilIdle(); - EXPECT_EQ("UsbMidiDevice::GetDescriptor\n" + EXPECT_EQ("UsbMidiDevice::GetDescriptors\n" "UsbMidiDevice::Send endpoint = 2 data = " "0x19 0x90 0x45 0x7f " "0x14 0xf0 0x00 0x01 " @@ -368,7 +433,7 @@ TEST_F(MidiManagerUsbTest, SendFromCompromizedRenderer) { scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); - uint8 descriptor[] = { + uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, @@ -385,7 +450,7 @@ 0x05, 0x25, 0x01, 0x01, 0x07, }; - device->SetDescriptor(ToVector(descriptor)); + device->SetDescriptors(ToVector(descriptors)); uint8 data[] = { 0x90, 0x45, 0x7f, 0xf0, 0x00, 0x01, 0xf7, @@ -398,7 +463,7 @@ RunCallbackUntilCallbackInvoked(true, &devices); EXPECT_EQ(MIDI_OK, GetInitializationResult()); ASSERT_EQ(2u, manager_->output_streams().size()); - EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); + EXPECT_EQ("UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); // The specified port index is invalid. The manager must ignore the request. manager_->DispatchSendMidiData(client_.get(), 99, ToVector(data), 0); @@ -411,7 +476,7 @@ TEST_F(MidiManagerUsbTest, Receive) { scoped_ptr<FakeUsbMidiDevice> device(new FakeUsbMidiDevice(&logger_)); - uint8 descriptor[] = { + uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, @@ -428,7 +493,7 @@ 0x05, 0x25, 0x01, 0x01, 0x07, }; - device->SetDescriptor(ToVector(descriptor)); + device->SetDescriptors(ToVector(descriptors)); uint8 data[] = { 0x09, 0x90, 0x45, 0x7f, 0x04, 0xf0, 0x00, 0x01, @@ -448,7 +513,7 @@ base::TimeTicks()); Finalize(); - EXPECT_EQ("UsbMidiDevice::GetDescriptor\n" + EXPECT_EQ("UsbMidiDevice::GetDescriptors\n" "MidiManagerClient::ReceiveMidiData port_index = 0 " "data = 0x90 0x45 0x7f\n" "MidiManagerClient::ReceiveMidiData port_index = 0 " @@ -458,7 +523,7 @@ } TEST_F(MidiManagerUsbTest, AttachDevice) { - uint8 descriptor[] = { + uint8 descriptors[] = { 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x86, 0x1a, 0x2d, 0x75, 0x54, 0x02, 0x00, 0x02, 0x00, 0x01, 0x09, 0x02, 0x75, 0x00, 0x02, 0x01, 0x00, 0x80, 0x30, 0x09, 0x04, 0x00, @@ -490,7 +555,7 @@ EXPECT_EQ("", logger_.TakeLog()); scoped_ptr<FakeUsbMidiDevice> new_device(new FakeUsbMidiDevice(&logger_)); - new_device->SetDescriptor(ToVector(descriptor)); + new_device->SetDescriptors(ToVector(descriptors)); manager_->OnDeviceAttached(new_device.Pass()); ASSERT_EQ(1u, input_ports().size()); @@ -502,7 +567,7 @@ EXPECT_EQ(3u, manager_->output_streams()[1]->jack().jack_id); ASSERT_EQ(1u, jacks.size()); EXPECT_EQ(2, jacks[0].endpoint_number()); - EXPECT_EQ("UsbMidiDevice::GetDescriptor\n", logger_.TakeLog()); + EXPECT_EQ("UsbMidiDevice::GetDescriptors\n", logger_.TakeLog()); } } // namespace
diff --git a/media/midi/usb_midi_descriptor_parser.cc b/media/midi/usb_midi_descriptor_parser.cc index d454ff9..baf503bf 100644 --- a/media/midi/usb_midi_descriptor_parser.cc +++ b/media/midi/usb_midi_descriptor_parser.cc
@@ -7,6 +7,7 @@ #include <algorithm> #include "base/logging.h" +#include "base/strings/stringprintf.h" namespace media { @@ -58,8 +59,20 @@ uint8 id_; }; +int DecodeBcd(uint8 byte) { + DCHECK_LT((byte & 0xf0) >> 4, 0xa); + DCHECK_LT(byte & 0x0f, 0xa); + return ((byte & 0xf0) >> 4) * 10 + (byte & 0x0f); +} + } // namespace +std::string UsbMidiDescriptorParser::DeviceInfo::BcdVersionToString( + uint16 version) { + return base::StringPrintf("%d.%02d", DecodeBcd(version >> 8), + DecodeBcd(version & 0xff)); +} + UsbMidiDescriptorParser::UsbMidiDescriptorParser() : is_parsing_usb_midi_interface_(false), current_endpoint_address_(0), @@ -79,6 +92,31 @@ return result; } +bool UsbMidiDescriptorParser::ParseDeviceInfo( + const uint8* data, size_t size, DeviceInfo* info) { + *info = DeviceInfo(); + for (const uint8* current = data; + current < data + size; + current += current[0]) { + uint8 length = current[0]; + if (length < 2) { + DVLOG(1) << "Descriptor Type is not accessible."; + return false; + } + if (current + length > data + size) { + DVLOG(1) << "The header size is incorrect."; + return false; + } + DescriptorType descriptor_type = static_cast<DescriptorType>(current[1]); + if (descriptor_type != TYPE_DEVICE) + continue; + // We assume that ParseDevice doesn't modify |*info| if it returns false. + return ParseDevice(current, length, info); + } + // No DEVICE descriptor is found. + return false; +} + bool UsbMidiDescriptorParser::ParseInternal(UsbMidiDevice* device, const uint8* data, size_t size, @@ -129,6 +167,21 @@ return true; } +bool UsbMidiDescriptorParser::ParseDevice( + const uint8* data, size_t size, DeviceInfo* info) { + if (size < 0x12) { + DVLOG(1) << "DEVICE header size is incorrect."; + return false; + } + + info->vendor_id = data[8] | (data[9] << 8); + info->product_id = data[0xa] | (data[0xb] << 8); + info->bcd_device_version = data[0xc] | (data[0xd] << 8); + info->manufacturer_index = data[0xe]; + info->product_index = data[0xf]; + return true; +} + bool UsbMidiDescriptorParser::ParseInterface(const uint8* data, size_t size) { if (size != 9) { DVLOG(1) << "INTERFACE header size is incorrect.";
diff --git a/media/midi/usb_midi_descriptor_parser.h b/media/midi/usb_midi_descriptor_parser.h index 826a449..cc07be3b 100644 --- a/media/midi/usb_midi_descriptor_parser.h +++ b/media/midi/usb_midi_descriptor_parser.h
@@ -5,6 +5,7 @@ #ifndef MEDIA_MIDI_USB_MIDI_DESCRIPTOR_PARSER_H_ #define MEDIA_MIDI_USB_MIDI_DESCRIPTOR_PARSER_H_ +#include <string> #include <vector> #include "base/basictypes.h" @@ -21,6 +22,24 @@ // for collecting USB-MIDI jacks information from the descriptor. class MEDIA_EXPORT UsbMidiDescriptorParser { public: + struct DeviceInfo { + DeviceInfo() + : vendor_id(0), + product_id(0), + bcd_device_version(0), + manufacturer_index(0), + product_index(0) {} + uint16 vendor_id; + uint16 product_id; + // The higher one byte represents the "major" number and the lower one byte + // represents the "minor" number. + uint16 bcd_device_version; + uint8 manufacturer_index; + uint8 product_index; + + static std::string BcdVersionToString(uint16); + }; + UsbMidiDescriptorParser(); ~UsbMidiDescriptorParser(); @@ -32,11 +51,14 @@ size_t size, std::vector<UsbMidiJack>* jacks); + bool ParseDeviceInfo(const uint8* data, size_t size, DeviceInfo* info); + private: bool ParseInternal(UsbMidiDevice* device, const uint8* data, size_t size, std::vector<UsbMidiJack>* jacks); + bool ParseDevice(const uint8* data, size_t size, DeviceInfo* info); bool ParseInterface(const uint8* data, size_t size); bool ParseCSInterface(UsbMidiDevice* device, const uint8* data, size_t size); bool ParseEndpoint(const uint8* data, size_t size);
diff --git a/media/midi/usb_midi_descriptor_parser_unittest.cc b/media/midi/usb_midi_descriptor_parser_unittest.cc index 4e243d1..a9a96b9 100644 --- a/media/midi/usb_midi_descriptor_parser_unittest.cc +++ b/media/midi/usb_midi_descriptor_parser_unittest.cc
@@ -13,7 +13,7 @@ TEST(UsbMidiDescriptorParserTest, ParseEmpty) { UsbMidiDescriptorParser parser; std::vector<UsbMidiJack> jacks; - EXPECT_TRUE(parser.Parse(NULL, NULL, 0, &jacks)); + EXPECT_TRUE(parser.Parse(nullptr, nullptr, 0, &jacks)); EXPECT_TRUE(jacks.empty()); } @@ -21,7 +21,7 @@ UsbMidiDescriptorParser parser; std::vector<UsbMidiJack> jacks; uint8 data[] = {0x04}; - EXPECT_FALSE(parser.Parse(NULL, data, arraysize(data), &jacks)); + EXPECT_FALSE(parser.Parse(nullptr, data, arraysize(data), &jacks)); EXPECT_TRUE(jacks.empty()); } @@ -35,7 +35,7 @@ 0x24, 0x01, 0x00, 0x01, 0x07, 0x00, 0x05, 0x25, 0x01, 0x01, 0x01, }; - EXPECT_FALSE(parser.Parse(NULL, data, arraysize(data), &jacks)); + EXPECT_FALSE(parser.Parse(nullptr, data, arraysize(data), &jacks)); EXPECT_TRUE(jacks.empty()); } @@ -50,7 +50,7 @@ 0x24, 0x01, 0x00, 0x01, 0x07, 0x00, 0x05, 0x25, 0x01, 0x01, 0x01, }; - EXPECT_TRUE(parser.Parse(NULL, data, arraysize(data), &jacks)); + EXPECT_TRUE(parser.Parse(nullptr, data, arraysize(data), &jacks)); EXPECT_TRUE(jacks.empty()); } @@ -74,26 +74,48 @@ 0x03, 0x09, 0x05, 0x82, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x05, 0x25, 0x01, 0x01, 0x07, }; - EXPECT_TRUE(parser.Parse(NULL, data, arraysize(data), &jacks)); + EXPECT_TRUE(parser.Parse(nullptr, data, arraysize(data), &jacks)); ASSERT_EQ(3u, jacks.size()); EXPECT_EQ(2u, jacks[0].jack_id); EXPECT_EQ(0u, jacks[0].cable_number); EXPECT_EQ(2u, jacks[0].endpoint_number()); EXPECT_EQ(UsbMidiJack::DIRECTION_OUT, jacks[0].direction()); - EXPECT_EQ(NULL, jacks[0].device); + EXPECT_EQ(nullptr, jacks[0].device); EXPECT_EQ(3u, jacks[1].jack_id); EXPECT_EQ(1u, jacks[1].cable_number); EXPECT_EQ(2u, jacks[1].endpoint_number()); EXPECT_EQ(UsbMidiJack::DIRECTION_OUT, jacks[1].direction()); - EXPECT_EQ(NULL, jacks[1].device); + EXPECT_EQ(nullptr, jacks[1].device); EXPECT_EQ(7u, jacks[2].jack_id); EXPECT_EQ(0u, jacks[2].cable_number); EXPECT_EQ(2u, jacks[2].endpoint_number()); EXPECT_EQ(UsbMidiJack::DIRECTION_IN, jacks[2].direction()); - EXPECT_EQ(NULL, jacks[2].device); + EXPECT_EQ(nullptr, jacks[2].device); +} + +TEST(UsbMidiDescriptorParserTest, ParseDeviceInfoEmpty) { + UsbMidiDescriptorParser parser; + UsbMidiDescriptorParser::DeviceInfo info; + EXPECT_FALSE(parser.ParseDeviceInfo(nullptr, 0, &info)); +} + +TEST(UsbMidiDescriptorParserTest, ParseDeviceInfo) { + UsbMidiDescriptorParser parser; + UsbMidiDescriptorParser::DeviceInfo info; + uint8 data[] = { + 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, 0x01, 0x23, + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x00, 0x0a, + }; + EXPECT_TRUE(parser.ParseDeviceInfo(data, arraysize(data), &info)); + + EXPECT_EQ(0x2301, info.vendor_id); + EXPECT_EQ(0x6745, info.product_id); + EXPECT_EQ(0xab89, info.bcd_device_version); + EXPECT_EQ(0xcd, info.manufacturer_index); + EXPECT_EQ(0xef, info.product_index); } } // namespace
diff --git a/media/midi/usb_midi_device.h b/media/midi/usb_midi_device.h index 3216614..8128c62 100644 --- a/media/midi/usb_midi_device.h +++ b/media/midi/usb_midi_device.h
@@ -66,8 +66,17 @@ virtual ~UsbMidiDevice() {} - // Returns the descriptor of this device. - virtual std::vector<uint8> GetDescriptor() = 0; + // Returns the descriptors of this device. + virtual std::vector<uint8> GetDescriptors() = 0; + + // Return the name of the manufacturer. + virtual std::string GetManufacturer() = 0; + + // Retur the name of the device. + virtual std::string GetProductName() = 0; + + // Return the device version. + virtual std::string GetDeviceVersion() = 0; // Sends |data| to the given USB endpoint of this device. virtual void Send(int endpoint_number, const std::vector<uint8>& data) = 0;
diff --git a/media/midi/usb_midi_device_android.cc b/media/midi/usb_midi_device_android.cc index ff58e62..f62eb86 100644 --- a/media/midi/usb_midi_device_android.cc +++ b/media/midi/usb_midi_device_android.cc
@@ -8,8 +8,11 @@ #include <vector> #include "base/android/jni_array.h" +#include "base/i18n/icu_string_conversions.h" +#include "base/strings/stringprintf.h" #include "base/time/time.h" #include "jni/UsbMidiDeviceAndroid_jni.h" +#include "media/midi/usb_midi_descriptor_parser.h" namespace media { @@ -19,6 +22,9 @@ JNIEnv* env = base::android::AttachCurrentThread(); Java_UsbMidiDeviceAndroid_registerSelf( env, raw_device_.obj(), reinterpret_cast<jlong>(this)); + + GetDescriptorsInternal(); + InitDeviceInfo(); } UsbMidiDeviceAndroid::~UsbMidiDeviceAndroid() { @@ -26,14 +32,20 @@ Java_UsbMidiDeviceAndroid_close(env, raw_device_.obj()); } -std::vector<uint8> UsbMidiDeviceAndroid::GetDescriptor() { - JNIEnv* env = base::android::AttachCurrentThread(); - base::android::ScopedJavaLocalRef<jbyteArray> descriptors = - Java_UsbMidiDeviceAndroid_getDescriptors(env, raw_device_.obj()); +std::vector<uint8> UsbMidiDeviceAndroid::GetDescriptors() { + return descriptors_; +} - std::vector<uint8> ret; - base::android::JavaByteArrayToByteVector(env, descriptors.obj(), &ret); - return ret; +std::string UsbMidiDeviceAndroid::GetManufacturer() { + return manufacturer_; +} + +std::string UsbMidiDeviceAndroid::GetProductName() { + return product_; +} + +std::string UsbMidiDeviceAndroid::GetDeviceVersion() { + return device_version_; } void UsbMidiDeviceAndroid::Send(int endpoint_number, @@ -63,4 +75,71 @@ return RegisterNativesImpl(env); } +void UsbMidiDeviceAndroid::GetDescriptorsInternal() { + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::ScopedJavaLocalRef<jbyteArray> descriptors = + Java_UsbMidiDeviceAndroid_getDescriptors(env, raw_device_.obj()); + + base::android::JavaByteArrayToByteVector(env, descriptors.obj(), + &descriptors_); +} + +void UsbMidiDeviceAndroid::InitDeviceInfo() { + UsbMidiDescriptorParser parser; + UsbMidiDescriptorParser::DeviceInfo info; + + const uint8* data = descriptors_.size() > 0 ? &descriptors_[0] : nullptr; + + if (!parser.ParseDeviceInfo(data, descriptors_.size(), &info)) { + // We don't report the error here. If it is critical, we will realize it + // when we parse the descriptors again for ports. + manufacturer_ = "invalid descriptor"; + product_ = "invalid descriptor"; + device_version_ = "invalid descriptor"; + return; + } + + manufacturer_ = + GetString(info.manufacturer_index, + base::StringPrintf("(vendor id = 0x%04x)", info.vendor_id)); + product_ = + GetString(info.product_index, + base::StringPrintf("(product id = 0x%04x)", info.product_id)); + device_version_ = info.BcdVersionToString(info.bcd_device_version); +} + +std::vector<uint8> UsbMidiDeviceAndroid::GetStringDescriptor(int index) { + JNIEnv* env = base::android::AttachCurrentThread(); + base::android::ScopedJavaLocalRef<jbyteArray> descriptors = + Java_UsbMidiDeviceAndroid_getStringDescriptor(env, raw_device_.obj(), + index); + + std::vector<uint8> ret; + base::android::JavaByteArrayToByteVector(env, descriptors.obj(), &ret); + return ret; +} + +std::string UsbMidiDeviceAndroid::GetString(int index, + const std::string& backup) { + const uint8 DESCRIPTOR_TYPE_STRING = 3; + + if (!index) { + // index 0 means there is no such descriptor. + return backup; + } + std::vector<uint8> descriptor = GetStringDescriptor(index); + if (descriptor.size() < 2 || descriptor.size() < descriptor[0] || + descriptor[1] != DESCRIPTOR_TYPE_STRING) { + // |descriptor| is not a valid string descriptor. + return backup; + } + size_t size = descriptor[0]; + std::string encoded(reinterpret_cast<char*>(&descriptor[0]) + 2, size - 2); + std::string result; + // Unicode ECN specifies that the string is encoded in UTF-16LE. + if (!base::ConvertToUtf8AndNormalize(encoded, "utf-16le", &result)) + return backup; + return result; +} + } // namespace media
diff --git a/media/midi/usb_midi_device_android.h b/media/midi/usb_midi_device_android.h index 19e65b8..7032cf7 100644 --- a/media/midi/usb_midi_device_android.h +++ b/media/midi/usb_midi_device_android.h
@@ -6,6 +6,7 @@ #define MEDIA_MIDI_USB_MIDI_DEVICE_ANDROID_H_ #include <jni.h> +#include <string> #include <vector> #include "base/android/scoped_java_ref.h" @@ -26,7 +27,10 @@ ~UsbMidiDeviceAndroid() override; // UsbMidiDevice implementation. - std::vector<uint8> GetDescriptor() override; + std::vector<uint8> GetDescriptors() override; + std::string GetManufacturer() override; + std::string GetProductName() override; + std::string GetDeviceVersion() override; void Send(int endpoint_number, const std::vector<uint8>& data) override; // Called by the Java world. @@ -38,10 +42,20 @@ static bool RegisterUsbMidiDevice(JNIEnv* env); private: + void GetDescriptorsInternal(); + void InitDeviceInfo(); + std::vector<uint8> GetStringDescriptor(int index); + std::string GetString(int index, const std::string& backup); + // The actual device object. base::android::ScopedJavaGlobalRef<jobject> raw_device_; UsbMidiDeviceDelegate* delegate_; + std::vector<uint8> descriptors_; + std::string manufacturer_; + std::string product_; + std::string device_version_; + DISALLOW_IMPLICIT_CONSTRUCTORS(UsbMidiDeviceAndroid); };
diff --git a/media/midi/usb_midi_input_stream_unittest.cc b/media/midi/usb_midi_input_stream_unittest.cc index 0ec1568..153dc440 100644 --- a/media/midi/usb_midi_input_stream_unittest.cc +++ b/media/midi/usb_midi_input_stream_unittest.cc
@@ -23,7 +23,10 @@ public: TestUsbMidiDevice() {} ~TestUsbMidiDevice() override {} - std::vector<uint8> GetDescriptor() override { return std::vector<uint8>(); } + std::vector<uint8> GetDescriptors() override { return std::vector<uint8>(); } + std::string GetManufacturer() override { return std::string(); } + std::string GetProductName() override { return std::string(); } + std::string GetDeviceVersion() override { return std::string(); } void Send(int endpoint_number, const std::vector<uint8>& data) override {} private:
diff --git a/media/midi/usb_midi_output_stream_unittest.cc b/media/midi/usb_midi_output_stream_unittest.cc index f682f42..264c79d2 100644 --- a/media/midi/usb_midi_output_stream_unittest.cc +++ b/media/midi/usb_midi_output_stream_unittest.cc
@@ -26,7 +26,10 @@ MockUsbMidiDevice() {} ~MockUsbMidiDevice() override {} - std::vector<uint8> GetDescriptor() override { return std::vector<uint8>(); } + std::vector<uint8> GetDescriptors() override { return std::vector<uint8>(); } + std::string GetManufacturer() override { return std::string(); } + std::string GetProductName() override { return std::string(); } + std::string GetDeviceVersion() override { return std::string(); } void Send(int endpoint_number, const std::vector<uint8>& data) override { for (size_t i = 0; i < data.size(); ++i) {
diff --git a/media/mojo/interfaces/BUILD.gn b/media/mojo/interfaces/BUILD.gn index 4a0ca19..fabec424 100644 --- a/media/mojo/interfaces/BUILD.gn +++ b/media/mojo/interfaces/BUILD.gn
@@ -14,6 +14,6 @@ ] deps = [ - "//third_party/mojo_services/src/geometry/public/interfaces", + "//ui/mojo/geometry:interfaces", ] }
diff --git a/media/mojo/interfaces/media_types.mojom b/media/mojo/interfaces/media_types.mojom index fc14286..f23da86 100644 --- a/media/mojo/interfaces/media_types.mojom +++ b/media/mojo/interfaces/media_types.mojom
@@ -4,7 +4,7 @@ module mojo; -import "third_party/mojo_services/src/geometry/public/interfaces/geometry.mojom"; +import "ui/mojo/geometry/geometry.mojom"; // See media/base/buffering_state.h for descriptions. // Kept in sync with media::BufferingState via static_asserts.
diff --git a/media/mojo/scripts/run_mojo_media_renderer.py b/media/mojo/scripts/run_mojo_media_renderer.py index 6ca34dc..66d3217d 100755 --- a/media/mojo/scripts/run_mojo_media_renderer.py +++ b/media/mojo/scripts/run_mojo_media_renderer.py
@@ -3,17 +3,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. # -# The script follows mojo/services/html_viewer/view_url.py and modified it for -# test the mojo media renderer. The page will be rendered in a headless mode. -# -# TODO(xhwang): Explore the possibility of running this with the Kiosk window -# manager. See http://crbug.com/467176 +# The script launches mojo_shell to test the mojo media renderer. import argparse import os import subprocess import sys + root_path = os.path.realpath( os.path.join( os.path.dirname( @@ -22,6 +19,7 @@ os.pardir, os.pardir)) + def _BuildShellCommand(args): sdk_version = subprocess.check_output(["cat", "third_party/mojo/src/mojo/public/VERSION"], cwd=root_path) @@ -29,23 +27,10 @@ shell_command = [os.path.join(build_dir, "mojo_shell")] - options = [] - - options.append( - "--origin=https://storage.googleapis.com/mojo/services/linux-x64/%s" % - sdk_version) - options.append("--url-mappings=mojo:html_viewer=file://%s/html_viewer.mojo," - "mojo:media=file://%s/media.mojo" % (build_dir, build_dir)) - - args_for_html_viewer = "--enable-mojo-media-renderer --is-headless " + options = ["--enable-mojo-media-renderer"] if args.verbose: - args_for_html_viewer += \ - "--vmodule=pipeline*=3,*renderer_impl*=3,*mojo_demuxer*=3" - options.append("--args-for=mojo:html_viewer %s" % args_for_html_viewer) - - if args.verbose: - args_for_media = "--vmodule=mojo*service=3" - options.append("--args-for=mojo:media %s" % args_for_media) + options.append("--vmodule=pipeline*=3,*renderer_impl*=3," + "*mojo_demuxer*=3,mojo*service=3") full_command = shell_command + options + [args.url] @@ -54,13 +39,12 @@ return full_command + def main(): parser = argparse.ArgumentParser( description="View a URL with HTMLViewer with mojo media renderer. " - "You must have built //mojo/services/html_viewer, " - "//mojo/services/network and //media/mojo/services first. " - " Note that this will currently often fail spectacularly due " - " to lack of binary stability in Mojo.") + "You must have built //mojo, //components/html_viewer, " + "//mojo/services/network and //media/mojo/services first.") parser.add_argument( "--build-dir", help="Path to the dir containing the linux-x64 binaries relative to the " @@ -68,8 +52,7 @@ default="out/Release") parser.add_argument("--verbose", help="Increase output verbosity.", action="store_true") - parser.add_argument("url", - help="The URL to be viewed") + parser.add_argument("url", help="The URL to be viewed") args = parser.parse_args() return subprocess.call(_BuildShellCommand(args))
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn index 2a56e2e5..c8ec687b 100644 --- a/media/mojo/services/BUILD.gn +++ b/media/mojo/services/BUILD.gn
@@ -33,7 +33,7 @@ "//mojo/converters/geometry", "//mojo/environment:chromium", "//third_party/mojo/src/mojo/public/c/system:for_component", - "//third_party/mojo_services/src/geometry/public/interfaces", + "//ui/mojo/geometry:interfaces", ] }
diff --git a/media/mojo/services/mojo_cdm.cc b/media/mojo/services/mojo_cdm.cc index df82ec95..17a1a48 100644 --- a/media/mojo/services/mojo_cdm.cc +++ b/media/mojo/services/mojo_cdm.cc
@@ -16,15 +16,6 @@ namespace media { -static mojo::Array<uint8_t> CreateMojoArray(const uint8_t* data, int length) { - DCHECK(data); - DCHECK_GT(length, 0); - std::vector<uint8_t> vector(data, data + length); - mojo::Array<uint8_t> array; - array.Swap(&vector); - return array.Pass(); -} - template <typename PromiseType> static void RejectPromise(scoped_ptr<PromiseType> promise, mojo::CdmPromiseResultPtr result) { @@ -62,11 +53,10 @@ DVLOG(1) << __FUNCTION__; } -void MojoCdm::SetServerCertificate(const uint8_t* certificate_data, - int certificate_data_length, +void MojoCdm::SetServerCertificate(const std::vector<uint8_t>& certificate, scoped_ptr<SimpleCdmPromise> promise) { remote_cdm_->SetServerCertificate( - CreateMojoArray(certificate_data, certificate_data_length), + mojo::Array<uint8_t>::From(certificate), base::Bind(&MojoCdm::OnPromiseResult<>, weak_factory_.GetWeakPtr(), base::Passed(&promise))); } @@ -74,13 +64,12 @@ void MojoCdm::CreateSessionAndGenerateRequest( SessionType session_type, EmeInitDataType init_data_type, - const uint8_t* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<NewSessionCdmPromise> promise) { remote_cdm_->CreateSessionAndGenerateRequest( static_cast<mojo::ContentDecryptionModule::SessionType>(session_type), static_cast<mojo::ContentDecryptionModule::InitDataType>(init_data_type), - CreateMojoArray(init_data, init_data_length), + mojo::Array<uint8_t>::From(init_data), base::Bind(&MojoCdm::OnPromiseResult<std::string>, weak_factory_.GetWeakPtr(), base::Passed(&promise))); } @@ -96,11 +85,10 @@ } void MojoCdm::UpdateSession(const std::string& session_id, - const uint8_t* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<SimpleCdmPromise> promise) { remote_cdm_->UpdateSession( - session_id, CreateMojoArray(response, response_length), + session_id, mojo::Array<uint8_t>::From(response), base::Bind(&MojoCdm::OnPromiseResult<>, weak_factory_.GetWeakPtr(), base::Passed(&promise))); }
diff --git a/media/mojo/services/mojo_cdm.h b/media/mojo/services/mojo_cdm.h index 4c29577..68667dab 100644 --- a/media/mojo/services/mojo_cdm.h +++ b/media/mojo/services/mojo_cdm.h
@@ -5,6 +5,8 @@ #ifndef MEDIA_MOJO_SERVICES_MOJO_CDM_H_ #define MEDIA_MOJO_SERVICES_MOJO_CDM_H_ +#include <vector> + #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "media/base/media_keys.h" @@ -33,21 +35,18 @@ ~MojoCdm() final; // MediaKeys implementation. - void SetServerCertificate(const uint8_t* certificate_data, - int certificate_data_length, + void SetServerCertificate(const std::vector<uint8_t>& certificate, scoped_ptr<SimpleCdmPromise> promise) final; void CreateSessionAndGenerateRequest( SessionType session_type, EmeInitDataType init_data_type, - const uint8_t* init_data, - int init_data_length, + const std::vector<uint8_t>& init_data, scoped_ptr<NewSessionCdmPromise> promise) final; void LoadSession(SessionType session_type, const std::string& session_id, scoped_ptr<NewSessionCdmPromise> promise) final; void UpdateSession(const std::string& session_id, - const uint8_t* response, - int response_length, + const std::vector<uint8_t>& response, scoped_ptr<SimpleCdmPromise> promise) final; void CloseSession(const std::string& session_id, scoped_ptr<SimpleCdmPromise> promise) final;
diff --git a/media/mojo/services/mojo_cdm_service.cc b/media/mojo/services/mojo_cdm_service.cc index 58c335d..b92d9f8 100644 --- a/media/mojo/services/mojo_cdm_service.cc +++ b/media/mojo/services/mojo_cdm_service.cc
@@ -47,11 +47,8 @@ void MojoCdmService::SetServerCertificate( mojo::Array<uint8_t> certificate_data, const mojo::Callback<void(mojo::CdmPromiseResultPtr)>& callback) { - const std::vector<uint8_t>& certificate_data_vector = - certificate_data.storage(); cdm_->SetServerCertificate( - certificate_data_vector.empty() ? nullptr : &certificate_data_vector[0], - certificate_data_vector.size(), + certificate_data.storage(), scoped_ptr<SimpleCdmPromise>(new SimpleMojoCdmPromise(callback))); } @@ -61,12 +58,9 @@ mojo::Array<uint8_t> init_data, const mojo::Callback<void(mojo::CdmPromiseResultPtr, mojo::String)>& callback) { - const std::vector<uint8_t>& init_data_vector = init_data.storage(); cdm_->CreateSessionAndGenerateRequest( static_cast<MediaKeys::SessionType>(session_type), - static_cast<EmeInitDataType>(init_data_type), - init_data_vector.empty() ? nullptr : &init_data_vector[0], - init_data_vector.size(), + static_cast<EmeInitDataType>(init_data_type), init_data.storage(), scoped_ptr<NewSessionCdmPromise>(new NewSessionMojoCdmPromise(callback))); } @@ -85,11 +79,8 @@ const mojo::String& session_id, mojo::Array<uint8_t> response, const mojo::Callback<void(mojo::CdmPromiseResultPtr)>& callback) { - const std::vector<uint8_t>& response_vector = response.storage(); cdm_->UpdateSession( - session_id.To<std::string>(), - response_vector.empty() ? nullptr : &response_vector[0], - response_vector.size(), + session_id.To<std::string>(), response.storage(), scoped_ptr<SimpleCdmPromise>(new SimpleMojoCdmPromise(callback))); }
diff --git a/media/mojo/services/mojo_media_application.cc b/media/mojo/services/mojo_media_application.cc index 48597bd..7a24637 100644 --- a/media/mojo/services/mojo_media_application.cc +++ b/media/mojo/services/mojo_media_application.cc
@@ -2,9 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/command_line.h" #include "base/logging.h" -#include "base/strings/utf_string_conversions.h" #include "media/mojo/services/mojo_renderer_service.h" #include "mojo/application/application_runner_chromium.h" #include "third_party/mojo/src/mojo/public/c/system/main.h" @@ -21,17 +19,6 @@ public: // mojo::ApplicationDelegate implementation. void Initialize(mojo::ApplicationImpl* app) override { - base::CommandLine::StringVector command_line_args; -#if defined(OS_WIN) - for (const auto& arg : app->args()) - command_line_args.push_back(base::UTF8ToUTF16(arg)); -#elif defined(OS_POSIX) - command_line_args = app->args(); -#endif - - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - command_line->InitFromArgv(command_line_args); - logging::LoggingSettings settings; settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; logging::InitLogging(settings);
diff --git a/media/renderers/mock_gpu_video_accelerator_factories.h b/media/renderers/mock_gpu_video_accelerator_factories.h index 12a8095..9bbbb89 100644 --- a/media/renderers/mock_gpu_video_accelerator_factories.h +++ b/media/renderers/mock_gpu_video_accelerator_factories.h
@@ -46,14 +46,12 @@ scoped_ptr<base::SharedMemory> CreateSharedMemory(size_t size) override; - virtual scoped_ptr<VideoDecodeAccelerator> CreateVideoDecodeAccelerator() - override; + scoped_ptr<VideoDecodeAccelerator> CreateVideoDecodeAccelerator() override; - virtual scoped_ptr<VideoEncodeAccelerator> CreateVideoEncodeAccelerator() - override; + scoped_ptr<VideoEncodeAccelerator> CreateVideoEncodeAccelerator() override; private: - virtual ~MockGpuVideoAcceleratorFactories(); + ~MockGpuVideoAcceleratorFactories() override; DISALLOW_COPY_AND_ASSIGN(MockGpuVideoAcceleratorFactories); };
diff --git a/media/test/data/eme_player.html b/media/test/data/eme_player.html index 4a3c2305..18d2932 100644 --- a/media/test/data/eme_player.html +++ b/media/test/data/eme_player.html
@@ -3,7 +3,7 @@ <head> <title>EME playback test application</title> </head> - <body style='font-family:"Lucida Console", Monaco, monospace; font-size:14px'> + <body style='font-family:"Lucida Console", Monaco, monospace; font-size:14px' onload="start()"> <i>Clearkey works only with content encrypted using bear key.</i><br><br> <table> <tr title='URL param mediaFile=...'> @@ -58,12 +58,17 @@ </body> <script src='eme_player_js/app_loader.js' type='text/javascript'></script> <script type='text/javascript'> - var testConfig = new TestConfig(); - testConfig.loadQueryParams(); - // Update document with test configuration values. - var emeApp = new EMEApp(testConfig); + var testConfig; + var emeApp; var player; + function initApp() { + testConfig = new TestConfig(); + testConfig.loadQueryParams(); + // Update document with test configuration values. + emeApp = new EMEApp(testConfig); + } + function onTimeUpdate(e) { var video = e.target; if (video.currentTime < 1) @@ -124,6 +129,7 @@ } function start() { + initApp(); emeApp.createPlayer() .then(function(p) { player = p; @@ -132,7 +138,5 @@ Utils.failTest('Unable to play video.'); }); } - - start(); </script> </html>
diff --git a/media/test/data/eme_player_js/app_loader.js b/media/test/data/eme_player_js/app_loader.js index f4a3e74..a4ef2b5 100644 --- a/media/test/data/eme_player_js/app_loader.js +++ b/media/test/data/eme_player_js/app_loader.js
@@ -5,7 +5,7 @@ // Adds a Javascript source tag to the document. function addScriptTag(src) { document.write( - '<script type="text/javascript" src="eme_player_js/' + src + + '<script type="text/javascript" async="false" src="eme_player_js/' + src + '"></script>'); }
diff --git a/media/test/data/encrypted_frame_size_change.html b/media/test/data/encrypted_frame_size_change.html index 9b0f60f5..c6bf0ae2 100644 --- a/media/test/data/encrypted_frame_size_change.html +++ b/media/test/data/encrypted_frame_size_change.html
@@ -10,10 +10,15 @@ var firstVideoSeek = false; var video_fixed_size = document.getElementsByTagName("video")[0]; var video = document.getElementsByTagName("video")[1]; - var testConfig = new TestConfig(); - testConfig.loadQueryParams(); + var testConfig; + + function initTestConfig() { + testConfig = new TestConfig(); + testConfig.loadQueryParams(); + } function load() { + initTestConfig(); loadVideo(video_fixed_size).then(function() { loadVideo(video); });
diff --git a/media/test/data/mse_config_change.html b/media/test/data/mse_config_change.html index d78cc9e..1ecc444d 100644 --- a/media/test/data/mse_config_change.html +++ b/media/test/data/mse_config_change.html
@@ -6,9 +6,8 @@ <video controls></video> <script src='eme_player_js/app_loader.js' type='text/javascript'></script> <script type="text/javascript"> - var testConfig = new TestConfig(); - testConfig.loadQueryParams(); - var runEncrypted = testConfig.runEncrypted == 1; + var testConfig; + var runEncrypted; var video = document.querySelector('video'); var mediaType = 'video/webm; codecs="vorbis, vp8"'; @@ -35,6 +34,12 @@ // Append MEDIA_2 source at APPEND_TIME, so expected total duration is: var TOTAL_DURATION = APPEND_TIME + MEDIA_2_LENGTH; + function initTestConfig() { + testConfig = new TestConfig(); + testConfig.loadQueryParams(); + runEncrypted = testConfig.runEncrypted == 1; + } + function appendNextSource(mediaSource) { console.log('Appending next media source at ' + APPEND_TIME + 'sec.'); var xhr = new XMLHttpRequest(); @@ -117,6 +122,7 @@ } function runTest() { + initTestConfig(); testConfig.mediaFile = MEDIA_1; testConfig.mediaType = mediaType; video.addEventListener('timeupdate', onTimeUpdate);
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index 54d355c..dd214eba 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -5,6 +5,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" #include "base/strings/string_util.h" #include "build/build_config.h" #include "media/base/cdm_callback_promise.h" @@ -317,12 +318,12 @@ // key ID as the init_data. // http://crbug.com/460308 decryptor->CreateSessionAndGenerateRequest( - MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, kKeyId, - arraysize(kKeyId), CreateSessionPromise(RESOLVED)); + MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, + std::vector<uint8>(kKeyId, kKeyId + arraysize(kKeyId)), + CreateSessionPromise(RESOLVED)); } else { decryptor->CreateSessionAndGenerateRequest( - MediaKeys::TEMPORARY_SESSION, init_data_type, - vector_as_array(&init_data), init_data.size(), + MediaKeys::TEMPORARY_SESSION, init_data_type, init_data, CreateSessionPromise(RESOLVED)); } EXPECT_FALSE(current_session_id_.empty()); @@ -342,8 +343,7 @@ std::string jwk = GenerateJWKSet( kSecretKey, arraysize(kSecretKey), key_id, key_id_length); decryptor->UpdateSession(current_session_id_, - reinterpret_cast<const uint8*>(jwk.data()), - jwk.size(), + std::vector<uint8>(jwk.begin(), jwk.end()), CreatePromise(RESOLVED)); } @@ -379,13 +379,11 @@ // key ID as the init_data. // http://crbug.com/460308 decryptor->CreateSessionAndGenerateRequest( - MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, - vector_as_array(&key_id), key_id.size(), + MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, key_id, CreateSessionPromise(RESOLVED)); } else { decryptor->CreateSessionAndGenerateRequest( - MediaKeys::TEMPORARY_SESSION, init_data_type, - vector_as_array(&init_data), init_data.size(), + MediaKeys::TEMPORARY_SESSION, init_data_type, init_data, CreateSessionPromise(RESOLVED)); } @@ -395,8 +393,7 @@ vector_as_array(&key_id), key_id.size()); decryptor->UpdateSession(current_session_id_, - reinterpret_cast<const uint8*>(jwk.data()), - jwk.size(), + std::vector<uint8>(jwk.begin(), jwk.end()), CreatePromise(RESOLVED)); }
diff --git a/mojo/BUILD.gn b/mojo/BUILD.gn index 66e69af..c89d084 100644 --- a/mojo/BUILD.gn +++ b/mojo/BUILD.gn
@@ -19,7 +19,7 @@ } if (!is_component_build) { - deps += [ "//mojo/shell" ] + deps += [ "//mojo/runner" ] } }
diff --git a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java b/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java index b7916f8..58e2351 100644 --- a/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java +++ b/mojo/android/javatests/src/org/chromium/mojo/bindings/InterfacesTest.java
@@ -192,7 +192,7 @@ private void checkProxy(NamedObject.Proxy proxy, MockNamedObjectImpl impl) { RecordingGetNameResponse callback = new RecordingGetNameResponse(); CapturingErrorHandler errorHandler = new CapturingErrorHandler(); - proxy.setErrorHandler(errorHandler); + proxy.getProxyHandler().setErrorHandler(errorHandler); if (impl != null) { assertNull(impl.getLastMojoException());
diff --git a/mojo/application/BUILD.gn b/mojo/application/BUILD.gn index 5ea3a25e..6c906c2 100644 --- a/mojo/application/BUILD.gn +++ b/mojo/application/BUILD.gn
@@ -35,7 +35,7 @@ ] } -source_set("test_support_source_set") { +source_set("test_support") { testonly = true sources = [ "application_test_base_chromium.cc", @@ -52,21 +52,12 @@ "//third_party/mojo/src/mojo/public/cpp/system", "//testing/gtest", ] -} - -# This group wraps the source_set above, so building any apptest that depends -# on this target also builds this target's data_deps; see crbug.com/477104. -group("test_support") { - testonly = true - public_deps = [ - ":test_support_source_set", - ] data_deps = [] if (is_android) { data_deps += [ "//mojo/android" ] } if (!is_component_build) { - data_deps += [ "//mojo/shell:mojo_shell" ] + data_deps += [ "//mojo/runner:mojo_runner" ] } }
diff --git a/mojo/cc/BUILD.gn b/mojo/cc/BUILD.gn index 1abf712a..8083735 100644 --- a/mojo/cc/BUILD.gn +++ b/mojo/cc/BUILD.gn
@@ -9,6 +9,7 @@ "//cc", "//cc/surfaces", "//cc/surfaces:surface_id", + "//components/surfaces/public/interfaces", "//gpu/command_buffer/client:gles2_implementation", "//gpu/command_buffer/client:gles2_interface", "//mojo/converters/surfaces", @@ -17,7 +18,6 @@ "//third_party/mojo/src/mojo/public/c/gles2", "//third_party/mojo/src/mojo/public/cpp/environment", "//third_party/mojo/src/mojo/public/cpp/system", - "//third_party/mojo_services/src/surfaces/public/interfaces", ] sources = [
diff --git a/mojo/cc/DEPS b/mojo/cc/DEPS index 73912510..d5f554d 100644 --- a/mojo/cc/DEPS +++ b/mojo/cc/DEPS
@@ -1,7 +1,7 @@ include_rules = [ "+cc", "-cc/blink", + "+components/surfaces", "+gpu/command_buffer/client", "+mojo/gpu", - "+third_party/mojo_services/src/surfaces", ]
diff --git a/mojo/cc/output_surface_mojo.h b/mojo/cc/output_surface_mojo.h index 48c4dbe1..fc893ff 100644 --- a/mojo/cc/output_surface_mojo.h +++ b/mojo/cc/output_surface_mojo.h
@@ -8,7 +8,7 @@ #include "base/macros.h" #include "cc/output/output_surface.h" #include "cc/surfaces/surface_id.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom.h" +#include "components/surfaces/public/interfaces/surfaces.mojom.h" namespace mojo {
diff --git a/mojo/converters/geometry/BUILD.gn b/mojo/converters/geometry/BUILD.gn index 694487a..58b46e7e 100644 --- a/mojo/converters/geometry/BUILD.gn +++ b/mojo/converters/geometry/BUILD.gn
@@ -13,7 +13,7 @@ deps = [ "//mojo/environment:chromium", "//third_party/mojo/src/mojo/public/c/system:for_component", - "//third_party/mojo_services/src/geometry/public/interfaces", + "//ui/mojo/geometry:interfaces", ] defines = [ "MOJO_GEOMETRY_IMPLEMENTATION" ]
diff --git a/mojo/converters/geometry/DEPS b/mojo/converters/geometry/DEPS index f5b0b48..3985ac3 100644 --- a/mojo/converters/geometry/DEPS +++ b/mojo/converters/geometry/DEPS
@@ -1,4 +1,4 @@ include_rules = [ - "+third_party/mojo_services/src/geometry", "+ui/gfx/geometry", + "+ui/mojo/geometry", ]
diff --git a/mojo/converters/geometry/geometry_type_converters.h b/mojo/converters/geometry/geometry_type_converters.h index cb2a6b81..f19939b75 100644 --- a/mojo/converters/geometry/geometry_type_converters.h +++ b/mojo/converters/geometry/geometry_type_converters.h
@@ -6,11 +6,11 @@ #define MOJO_CONVERTERS_GEOMETRY_GEOMETRY_TYPE_CONVERTERS_H_ #include "mojo/converters/geometry/mojo_geometry_export.h" -#include "third_party/mojo_services/src/geometry/public/interfaces/geometry.mojom.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" +#include "ui/mojo/geometry/geometry.mojom.h" namespace mojo {
diff --git a/mojo/converters/input_events/BUILD.gn b/mojo/converters/input_events/BUILD.gn index 2c05f8d6..e3790d5 100644 --- a/mojo/converters/input_events/BUILD.gn +++ b/mojo/converters/input_events/BUILD.gn
@@ -15,12 +15,12 @@ deps = [ "//base", - "//ui/events", - "//ui/gfx/geometry", "//mojo/converters/geometry", "//mojo/environment:chromium", "//third_party/mojo/src/mojo/public/c/system:for_component", - "//third_party/mojo_services/src/input_events/public/interfaces", - "//third_party/mojo_services/src/geometry/public/interfaces", + "//ui/events", + "//ui/gfx/geometry", + "//ui/mojo/events:interfaces", + "//ui/mojo/geometry:interfaces", ] }
diff --git a/mojo/converters/input_events/DEPS b/mojo/converters/input_events/DEPS index 6fdb198..81a00b0 100644 --- a/mojo/converters/input_events/DEPS +++ b/mojo/converters/input_events/DEPS
@@ -1,4 +1,4 @@ include_rules = [ - "+third_party/mojo_services/src/input_events", "+ui/events", + "+ui/mojo/events", ]
diff --git a/mojo/converters/input_events/input_events_type_converters.cc b/mojo/converters/input_events/input_events_type_converters.cc index 300ec18..88b35fe 100644 --- a/mojo/converters/input_events/input_events_type_converters.cc +++ b/mojo/converters/input_events/input_events_type_converters.cc
@@ -11,9 +11,9 @@ #include "mojo/converters/geometry/geometry_type_converters.h" #include "mojo/converters/input_events/mojo_extended_key_event_data.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" #include "ui/events/event_utils.h" #include "ui/events/keycodes/keyboard_codes.h" +#include "ui/mojo/events/input_events.mojom.h" namespace mojo { namespace {
diff --git a/mojo/converters/input_events/input_events_type_converters.h b/mojo/converters/input_events/input_events_type_converters.h index b9e152f..0a2e153 100644 --- a/mojo/converters/input_events/input_events_type_converters.h +++ b/mojo/converters/input_events/input_events_type_converters.h
@@ -7,8 +7,8 @@ #include "base/memory/scoped_ptr.h" #include "mojo/converters/input_events/mojo_input_events_export.h" -#include "third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom.h" #include "ui/events/event.h" +#include "ui/mojo/events/input_events.mojom.h" namespace mojo {
diff --git a/mojo/converters/surfaces/BUILD.gn b/mojo/converters/surfaces/BUILD.gn index 3b0a22b8..48f055d 100644 --- a/mojo/converters/surfaces/BUILD.gn +++ b/mojo/converters/surfaces/BUILD.gn
@@ -26,12 +26,12 @@ "//base", "//cc", "//cc/surfaces", + "//components/surfaces/public/interfaces:surface_id", + "//components/surfaces/public/interfaces", "//gpu", "//ui/gfx/geometry", "//mojo/environment:chromium", "//skia", "//third_party/mojo/src/mojo/public/c/system:for_component", - "//third_party/mojo_services/src/surfaces/public/interfaces:surface_id", - "//third_party/mojo_services/src/surfaces/public/interfaces", ] }
diff --git a/mojo/converters/surfaces/DEPS b/mojo/converters/surfaces/DEPS index ceda7b99..c2d22dd 100644 --- a/mojo/converters/surfaces/DEPS +++ b/mojo/converters/surfaces/DEPS
@@ -3,9 +3,9 @@ "+cc/quads", "+cc/resources", "+cc/surfaces", + "+components/surfaces", "+gpu/command_buffer/common/mailbox.h", "+gpu/command_buffer/common/mailbox_holder.h", - "+third_party/mojo_services/src/surfaces", "+third_party/skia/include", "+ui/gfx/geometry", "+ui/gfx/transform.h",
diff --git a/mojo/converters/surfaces/surfaces_type_converters.h b/mojo/converters/surfaces/surfaces_type_converters.h index f41af6d9..a5b0d45 100644 --- a/mojo/converters/surfaces/surfaces_type_converters.h +++ b/mojo/converters/surfaces/surfaces_type_converters.h
@@ -9,12 +9,12 @@ #include "cc/resources/returned_resource.h" #include "cc/resources/transferable_resource.h" #include "cc/surfaces/surface_id.h" +#include "components/surfaces/public/interfaces/quads.mojom.h" +#include "components/surfaces/public/interfaces/surface_id.mojom.h" +#include "components/surfaces/public/interfaces/surfaces.mojom.h" #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/mailbox_holder.h" #include "mojo/converters/surfaces/mojo_surfaces_export.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/quads.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surface_id.mojom.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom.h" #include "third_party/skia/include/core/SkColor.h" namespace cc {
diff --git a/mojo/converters/surfaces/surfaces_utils.h b/mojo/converters/surfaces/surfaces_utils.h index ef5b91e..8b60cf0b7 100644 --- a/mojo/converters/surfaces/surfaces_utils.h +++ b/mojo/converters/surfaces/surfaces_utils.h
@@ -5,8 +5,8 @@ #ifndef MOJO_CONVERTERS_SURFACES_SURFACES_UTILS_H_ #define MOJO_CONVERTERS_SURFACES_SURFACES_UTILS_H_ +#include "components/surfaces/public/interfaces/quads.mojom.h" #include "mojo/converters/surfaces/mojo_surfaces_export.h" -#include "third_party/mojo_services/src/surfaces/public/interfaces/quads.mojom.h" namespace gfx { class Rect;
diff --git a/mojo/converters/surfaces/tests/BUILD.gn b/mojo/converters/surfaces/tests/BUILD.gn index 1f20b7a..0f681cb 100644 --- a/mojo/converters/surfaces/tests/BUILD.gn +++ b/mojo/converters/surfaces/tests/BUILD.gn
@@ -11,6 +11,7 @@ "//base/test:test_support", "//cc", "//cc/surfaces", + "//components/surfaces/public/interfaces", "//gpu", "//mojo/converters/geometry", "//mojo/converters/surfaces", @@ -19,11 +20,10 @@ "//skia", "//testing/gtest", "//third_party/mojo/src/mojo/edk/test:run_all_unittests", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/surfaces/public/interfaces", "//ui/gfx", "//ui/gfx/geometry", "//ui/gfx:test_support", + "//ui/mojo/geometry:interfaces", ] sources = [
diff --git a/mojo/converters/transform/BUILD.gn b/mojo/converters/transform/BUILD.gn index c0115c00..da04119f 100644 --- a/mojo/converters/transform/BUILD.gn +++ b/mojo/converters/transform/BUILD.gn
@@ -12,7 +12,7 @@ "//skia", "//mojo/environment:chromium", "//third_party/mojo/src/mojo/public/c/system:for_component", - "//third_party/mojo_services/src/geometry/public/interfaces", + "//ui/mojo/geometry:interfaces", ] defines = [ "MOJO_TRANSFORM_IMPLEMENTATION" ]
diff --git a/mojo/converters/transform/DEPS b/mojo/converters/transform/DEPS index 4aeafc40..ed693dd 100644 --- a/mojo/converters/transform/DEPS +++ b/mojo/converters/transform/DEPS
@@ -1,4 +1,4 @@ include_rules = [ - "+third_party/mojo_services/src/geometry", "+ui/gfx/transform.h", + "+ui/mojo/geometry", ]
diff --git a/mojo/converters/transform/transform_type_converters.h b/mojo/converters/transform/transform_type_converters.h index 046a152..372c473 100644 --- a/mojo/converters/transform/transform_type_converters.h +++ b/mojo/converters/transform/transform_type_converters.h
@@ -6,8 +6,8 @@ #define MOJO_CONVERTERS_TRANSFORM_TRANSFORM_TYPE_CONVERTERS_H_ #include "mojo/converters/transform/mojo_transform_export.h" -#include "third_party/mojo_services/src/geometry/public/interfaces/geometry.mojom.h" #include "ui/gfx/transform.h" +#include "ui/mojo/geometry/geometry.mojom.h" namespace mojo {
diff --git a/mojo/environment/BUILD.gn b/mojo/environment/BUILD.gn index 49e5c78f..4dbe7c4 100644 --- a/mojo/environment/BUILD.gn +++ b/mojo/environment/BUILD.gn
@@ -13,7 +13,10 @@ "//third_party/mojo/src/mojo/public/cpp/environment/async_waiter.h", "//third_party/mojo/src/mojo/public/cpp/environment/lib/async_waiter.cc", "//third_party/mojo/src/mojo/public/cpp/environment/lib/logging.cc", + "//third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.cc", + "//third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.h", "//third_party/mojo/src/mojo/public/cpp/environment/logging.h", + "//third_party/mojo/src/mojo/public/cpp/environment/task_tracker.h", ] public_deps = [ @@ -40,6 +43,8 @@ "default_logger_impl.h", "default_run_loop_impl.cc", "default_run_loop_impl.h", + "default_task_tracker_impl.cc", + "default_task_tracker_impl.h", ] defines = [ "MOJO_ENVIRONMENT_IMPL_IMPLEMENTATION" ]
diff --git a/mojo/environment/default_task_tracker_impl.cc b/mojo/environment/default_task_tracker_impl.cc new file mode 100644 index 0000000..a53f1b9 --- /dev/null +++ b/mojo/environment/default_task_tracker_impl.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 "mojo/environment/default_task_tracker_impl.h" + +namespace mojo { +namespace internal { +namespace { + +TaskTrackingId StartTracking(const char* function_name, + const char* file_name, + int line_number, + const void* program_counter) { + return TaskTrackingId(0); +} + +void EndTracking(const TaskTrackingId id) { +} + +void SetEnabled(bool enabled) { +} + +const TaskTracker kDefaultTaskTracker = {&StartTracking, + &EndTracking, + &SetEnabled}; + +} // namespace + +const TaskTracker* GetDefaultTaskTracker() { + return &kDefaultTaskTracker; +} + +} // namespace internal +} // namespace mojo
diff --git a/mojo/environment/default_task_tracker_impl.h b/mojo/environment/default_task_tracker_impl.h new file mode 100644 index 0000000..0a417cf --- /dev/null +++ b/mojo/environment/default_task_tracker_impl.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 MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_ +#define MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_ + +#include "mojo/environment/mojo_environment_impl_export.h" +#include "third_party/mojo/src/mojo/public/cpp/environment/task_tracker.h" + +namespace mojo { +namespace internal { + +MOJO_ENVIRONMENT_IMPL_EXPORT const TaskTracker* GetDefaultTaskTracker(); + +} // namespace internal +} // namespace mojo + +#endif // MOJO_ENVIRONMENT_DEFAULT_TASK_TRACKER_IMPL_H_
diff --git a/mojo/environment/environment.cc b/mojo/environment/environment.cc index ec181661..7cc9b1c 100644 --- a/mojo/environment/environment.cc +++ b/mojo/environment/environment.cc
@@ -7,6 +7,7 @@ #include "mojo/environment/default_async_waiter_impl.h" #include "mojo/environment/default_logger_impl.h" #include "mojo/environment/default_run_loop_impl.h" +#include "mojo/environment/default_task_tracker_impl.h" namespace mojo { @@ -35,6 +36,11 @@ } // static +const TaskTracker* Environment::GetDefaultTaskTracker() { + return internal::GetDefaultTaskTracker(); +} + +// static void Environment::InstantiateDefaultRunLoop() { internal::InstantiateDefaultRunLoopImpl(); } @@ -44,4 +50,6 @@ internal::DestroyDefaultRunLoopImpl(); } + + } // namespace mojo
diff --git a/mojo/gles2/BUILD.gn b/mojo/gles2/BUILD.gn index c6e501a..62d4d9e 100644 --- a/mojo/gles2/BUILD.gn +++ b/mojo/gles2/BUILD.gn
@@ -37,6 +37,7 @@ "//base", "//base/third_party/dynamic_annotations", "//components/gles2:lib", + "//components/gpu/public/interfaces", "//gpu/command_buffer/client", "//gpu/command_buffer/client:gles2_cmd_helper", "//gpu/command_buffer/client:gles2_implementation", @@ -47,7 +48,6 @@ "//third_party/mojo/src/mojo/public/c/system", "//third_party/mojo/src/mojo/public/cpp/bindings", "//third_party/mojo/src/mojo/public/cpp/system", - "//third_party/mojo_services/src/gpu/public/interfaces", ] include_dirs = [ ".." ]
diff --git a/mojo/gles2/DEPS b/mojo/gles2/DEPS index 9aea877..42db3a4a 100644 --- a/mojo/gles2/DEPS +++ b/mojo/gles2/DEPS
@@ -1,5 +1,5 @@ include_rules = [ "+components/gles2", + "+components/gpu", "+gpu", - "+third_party/mojo_services/src/gpu", ]
diff --git a/mojo/gles2/command_buffer_client_impl.h b/mojo/gles2/command_buffer_client_impl.h index 811bb076..875f7bb 100644 --- a/mojo/gles2/command_buffer_client_impl.h +++ b/mojo/gles2/command_buffer_client_impl.h
@@ -9,11 +9,11 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" +#include "components/gpu/public/interfaces/command_buffer.mojom.h" #include "gpu/command_buffer/client/gpu_control.h" #include "gpu/command_buffer/common/command_buffer.h" #include "gpu/command_buffer/common/command_buffer_shared.h" #include "mojo/public/cpp/bindings/error_handler.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom.h" namespace base { class RunLoop;
diff --git a/mojo/gpu/mojo_gles2_impl_autogen.cc b/mojo/gpu/mojo_gles2_impl_autogen.cc index edc4caa..685cd16e 100644 --- a/mojo/gpu/mojo_gles2_impl_autogen.cc +++ b/mojo/gpu/mojo_gles2_impl_autogen.cc
@@ -478,6 +478,12 @@ void MojoGLES2Impl::GetInteger64v(GLenum pname, GLint64* params) { NOTREACHED() << "Unimplemented GetInteger64v."; } +void MojoGLES2Impl::GetIntegeri_v(GLenum pname, GLuint index, GLint* data) { + NOTREACHED() << "Unimplemented GetIntegeri_v."; +} +void MojoGLES2Impl::GetInteger64i_v(GLenum pname, GLuint index, GLint64* data) { + NOTREACHED() << "Unimplemented GetInteger64i_v."; +} void MojoGLES2Impl::GetIntegerv(GLenum pname, GLint* params) { MojoGLES2MakeCurrent(context_); glGetIntegerv(pname, params);
diff --git a/mojo/gpu/mojo_gles2_impl_autogen.h b/mojo/gpu/mojo_gles2_impl_autogen.h index 13a933dd..5109897 100644 --- a/mojo/gpu/mojo_gles2_impl_autogen.h +++ b/mojo/gpu/mojo_gles2_impl_autogen.h
@@ -235,6 +235,8 @@ GLenum pname, GLint* params) override; void GetInteger64v(GLenum pname, GLint64* params) override; + void GetIntegeri_v(GLenum pname, GLuint index, GLint* data) override; + void GetInteger64i_v(GLenum pname, GLuint index, GLint64* data) override; void GetIntegerv(GLenum pname, GLint* params) override; void GetInternalformativ(GLenum target, GLenum format,
diff --git a/mojo/mojo_base.gyp b/mojo/mojo_base.gyp index 9f73e5de..c40a9499 100644 --- a/mojo/mojo_base.gyp +++ b/mojo/mojo_base.gyp
@@ -120,8 +120,11 @@ # TODO(vtl): This is kind of ugly. (See TODO in logging.h.) "../third_party/mojo/src/mojo/public/cpp/environment/async_waiter.h", "../third_party/mojo/src/mojo/public/cpp/environment/lib/async_waiter.cc", - "../third_party/mojo/src/mojo/public/cpp/environment/logging.h", "../third_party/mojo/src/mojo/public/cpp/environment/lib/logging.cc", + "../third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.cc", + "../third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.cc", + "../third_party/mojo/src/mojo/public/cpp/environment/logging.h", + "../third_party/mojo/src/mojo/public/cpp/environment/task_tracker.h", ], 'include_dirs': [ '..', @@ -156,6 +159,8 @@ 'environment/default_logger_impl.h', 'environment/default_run_loop_impl.cc', 'environment/default_run_loop_impl.h', + 'environment/default_task_tracker_impl.cc', + 'environment/default_task_tracker_impl.h', ], 'include_dirs': [ '..',
diff --git a/mojo/runner/BUILD.gn b/mojo/runner/BUILD.gn new file mode 100644 index 0000000..d9ddc78 --- /dev/null +++ b/mojo/runner/BUILD.gn
@@ -0,0 +1,414 @@ +# 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. + +import("//build/config/ui.gni") +import("//third_party/mojo/src/mojo/public/mojo.gni") +import("//third_party/mojo/src/mojo/public/mojo_application.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") +import("//testing/test.gni") + +# We don't support building in the component build since mojo apps are +# inherently components. +assert(!is_component_build) + +group("runner") { + testonly = true + + deps = [ + ":mojo_runner", + ":tests", + "//mojo/shell:tests", + ] + + if (is_android) { + deps += [ + ":mojo_runner_apk", + ":tests_apk", + ] + } +} + +if (is_android) { + import("//build/config/android/config.gni") + import("//build/config/android/rules.gni") +} + +executable("mojo_runner") { + sources = [] + + deps = [ + ":lib", + "//base", + "//build/config/sanitizers:deps", + "//mojo/common", + "//mojo/environment:chromium", + ] + + if (!is_android) { + sources += [ + "desktop/launcher_process.cc", + "desktop/launcher_process.h", + "desktop/main.cc", + ] + } else { + sources += [ + "android/library_loader.cc", + "android/main.cc", + "android/main.h", + ] + + # On android, the executable is also the native library used by the apk. + # It means dynamic symbols must be preserved and exported. + ldflags = [ "-Wl,--export-dynamic" ] + + deps += [ + ":jni_headers", + "//components/native_viewport:lib", + "//mojo/shell", + "//ui/gl", + ] + } +} + +source_set("in_process_native_runner") { + sources = [ + "in_process_native_runner.cc", + "in_process_native_runner.h", + ] + + public_deps = [ + ":native_application_support", + "//mojo/shell", + ] + + deps = [ + "//base", + ] +} + +source_set("lib") { + sources = [ + "child_process.cc", + "child_process.h", + "child_process_host.cc", + "child_process_host.h", + "context.cc", + "context.h", + "filename_util.cc", + "filename_util.h", + "init.cc", + "init.h", + "out_of_process_native_runner.cc", + "out_of_process_native_runner.h", + "task_runners.cc", + "task_runners.h", + "url_resolver.cc", + "url_resolver.h", + ] + + deps = [ + ":child_process_bindings", + ":in_process_native_runner", + ":native_application_support", + "//base", + "//base/third_party/dynamic_annotations", + "//base:base_static", + "//mojo/application", + "//mojo/common", + "//mojo/common:tracing_impl", + "//third_party/mojo/src/mojo/edk/system", + "//third_party/mojo/src/mojo/public/cpp/bindings", + "//third_party/mojo/src/mojo/public/interfaces/application", + "//mojo/services/network/public/interfaces", + "//mojo/shell", + "//mojo/services/tracing:bindings", + "//ui/gl", + "//url", + ] + + public_deps = [ + ":switches", + ] + + if (is_android) { + sources += [ + "android/android_handler.cc", + "android/android_handler.h", + "android/android_handler_loader.cc", + "android/android_handler_loader.h", + "android/background_application_loader.cc", + "android/background_application_loader.h", + "android/native_viewport_application_loader.cc", + "android/native_viewport_application_loader.h", + "android/ui_application_loader_android.cc", + "android/ui_application_loader_android.h", + ] + + deps += [ + ":jni_headers", + ":run_android_application_function", + "//components/gles2", + "//components/native_viewport:lib", + "//mojo/application:content_handler", + ] + } + + # This target includes some files behind #ifdef OS... guards. Since gn is not + # smart enough to understand preprocess includes, it does complains about + # these includes when not using the build files for that OS. Suppress checking + # so we can enable checking for the rest of the targets in this file. + # TODO: Might be better to split the files with OS-specific includes out to a + # separate source_set so we can leave checking on for the rest of the target. + check_includes = false +} + +source_set("native_application_support") { + sources = [ + "native_application_support.cc", + "native_application_support.h", + ] + + public_deps = [ + "//third_party/mojo/src/mojo/public/cpp/bindings", + ] + + deps = [ + "//base", + "//mojo/gles2", + ] + + # This target has to include the public thunk headers, which generally + # shouldn't be included without picking an implementation. We are providing + # the implementation but the thunk header target cannot declare that we are + # permitted to include it since it's in the public SDK and we are not. + # Suppress include checking so we can still check the rest of the targets in + # this file. + check_includes = false +} + +source_set("switches") { + sources = [ + "switches.cc", + "switches.h", + ] + + deps = [ + "//base", + ] +} + +if (is_android) { + generate_jni("jni_headers") { + sources = [ + "android/apk/src/org/chromium/mojo/shell/AndroidHandler.java", + "android/apk/src/org/chromium/mojo/shell/Bootstrap.java", + "android/apk/src/org/chromium/mojo/shell/ShellMain.java", + "android/tests/src/org/chromium/mojo/shell/ShellTestBase.java", + ] + jni_package = "mojo/shell" + } + + android_library("bootstrap_java") { + java_files = [ "android/apk/src/org/chromium/mojo/shell/Bootstrap.java" ] + + deps = [ + "//base:base_java", + ] + + dex_path = "$target_out_dir/bootstrap_java.dex.jar" + } + + shared_library("bootstrap") { + sources = [ + "android/bootstrap.cc", + ] + deps = [ + ":jni_headers", + ":lib", + ":run_android_application_function", + "//base", + ] + } + + # Shared header between the bootstrap and the main shell .so. + source_set("run_android_application_function") { + sources = [ + "android/run_android_application_function.h", + ] + + deps = [ + "//base", + ] + } + + android_library("java") { + java_files = [ + "android/apk/src/org/chromium/mojo/shell/AndroidHandler.java", + "android/apk/src/org/chromium/mojo/shell/FileHelper.java", + "android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java", + "android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java", + "android/apk/src/org/chromium/mojo/shell/ShellMain.java", + ] + + deps = [ + "//base:base_java", + ] + } + + android_resources("resources") { + resource_dirs = [ "android/apk/res" ] + custom_package = "org.chromium.mojo.shell" + } + + mojo_runner_assets_dir = "$root_build_dir/mojo_runner_assets" + mojo_runner_test_assets_dir = "$root_build_dir/mojo_runner_test_assets" + + copy_ex("copy_mojo_runner_assets") { + clear_dir = true + dest = mojo_runner_assets_dir + sources = [ + "$root_out_dir/lib.stripped/libbootstrap.so", + "$root_out_dir/network_service.mojo", + "$root_out_dir/obj/mojo/runner/bootstrap_java.dex.jar", + ] + } + + copy("copy_mojo_runner") { + sources = [ + "$root_out_dir/exe.stripped/mojo_runner", + ] + outputs = [ + "$root_out_dir/lib.stripped/libmojo_runner.so", + ] + } + + copy_ex("copy_mojo_runner_test_assets") { + clear_dir = true + dest = mojo_runner_test_assets_dir + sources = [ + "$root_out_dir/test_app.mojo", + "$root_out_dir/test_request_tracker_app.mojo", + ] + } + + android_apk("mojo_runner_apk") { + apk_name = "MojoRunner" + + android_manifest = "android/apk/AndroidManifest.xml" + + native_libs = [ "libmojo_runner.so" ] + + asset_location = mojo_runner_assets_dir + + deps = [ + ":copy_mojo_runner", + ":copy_mojo_runner_assets", + ":java", + ":resources", + "//base:base_java", + "//components/native_viewport:native_viewport_java", + "//third_party/android_tools:google_play_services_default_resources", + ] + } + + android_library("mojo_runner_tests_java") { + java_files = + [ "android/tests/src/org/chromium/mojo/shell/ShellTestBase.java" ] + + deps = [ + ":java", + "//base:base_java", + ] + } +} + +mojom("child_process_bindings") { + sources = [ + "child_process.mojom", + ] + + deps = [ + "//third_party/mojo/src/mojo/public/interfaces/application", + ] +} + +test("tests") { + output_name = "mojo_runner_unittests" + + sources = [ + "child_process_host_unittest.cc", + "data_pipe_peek_unittest.cc", + "in_process_native_runner_unittest.cc", + "native_runner_unittest.cc", + "shell_test_base.cc", + "shell_test_base.h", + "shell_test_base_android.cc", + "shell_test_base_unittest.cc", + "shell_test_main.cc", + "url_resolver_unittest.cc", + ] + + deps = [ + ":in_process_native_runner", + ":lib", + "//base", + "//base:i18n", + "//base/test:test_support", + "//testing/gtest", + "//url", + "//mojo/common", + "//third_party/mojo/src/mojo/edk/system", + "//mojo/environment:chromium", + "//third_party/mojo/src/mojo/public/cpp/bindings", + "//mojo/services/test_service:bindings", + "//mojo/shell", + ] + + datadeps = [ + "//mojo/services/test_service:test_app", + "//mojo/services/test_service:test_request_tracker_app", + ] + + if (is_android) { + sources += [ "android/background_application_loader_unittest.cc" ] + + deps += [ ":jni_headers" ] + + apk_deps = [ + ":copy_mojo_runner_test_assets", + ":mojo_runner_tests_java", + ] + + apk_asset_location = mojo_runner_test_assets_dir + } +} + +mojo_native_application("apptests") { + output_name = "runner_apptests" + + testonly = true + + sources = [ + # TODO(jam): needs http_server service. + #"shell_apptest.cc", + ] + + deps = [ + "//base", + "//mojo/application", + "//mojo/application:test_support", + "//mojo/common:common", + "//mojo/runner/test:bindings", + + #"//mojo/services/http_server/public/cpp", + #"//mojo/services/http_server/public/interfaces", + "//mojo/services/network/public/interfaces", + + "//third_party/mojo/src/mojo/public/cpp/bindings:callback", + "//third_party/mojo/src/mojo/public/cpp/environment", + "//third_party/mojo/src/mojo/public/cpp/system:system", + ] + + #data_deps = [ "//services/http_server:http_server($default_toolchain)" ] +}
diff --git a/mojo/runner/DEPS b/mojo/runner/DEPS new file mode 100644 index 0000000..eae3273 --- /dev/null +++ b/mojo/runner/DEPS
@@ -0,0 +1,9 @@ +include_rules = [ + "+components/gles2", + "+components/gpu", + "+components/native_viewport", + "+crypto", + "+jni", + "+third_party/mojo_services", + "+ui", +]
diff --git a/mojo/shell/PRESUBMIT.py b/mojo/runner/PRESUBMIT.py similarity index 100% rename from mojo/shell/PRESUBMIT.py rename to mojo/runner/PRESUBMIT.py
diff --git a/mojo/runner/android/android_handler.cc b/mojo/runner/android/android_handler.cc new file mode 100644 index 0000000..01e04508 --- /dev/null +++ b/mojo/runner/android/android_handler.cc
@@ -0,0 +1,111 @@ +// 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 "mojo/runner/android/android_handler.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/scoped_native_library.h" +#include "jni/AndroidHandler_jni.h" +#include "mojo/common/data_pipe_utils.h" +#include "mojo/public/c/system/main.h" +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/runner/android/run_android_application_function.h" +#include "mojo/runner/native_application_support.h" + +using base::android::AttachCurrentThread; +using base::android::ScopedJavaLocalRef; +using base::android::ConvertJavaStringToUTF8; +using base::android::ConvertUTF8ToJavaString; +using base::android::GetApplicationContext; + +namespace mojo { +namespace shell { + +namespace { + +// This function loads the application library, sets the application context and +// thunks and calls into the application MojoMain. To ensure that the thunks are +// set correctly we keep it in the Mojo shell .so and pass the function pointer +// to the helper libbootstrap.so. +void RunAndroidApplication(JNIEnv* env, + jobject j_context, + const base::FilePath& app_path, + jint j_handle) { + InterfaceRequest<Application> application_request = + MakeRequest<Application>(MakeScopedHandle(MessagePipeHandle(j_handle))); + + // Load the library, so that we can set the application context there if + // needed. + // TODO(vtl): We'd use a ScopedNativeLibrary, but it doesn't have .get()! + base::NativeLibrary app_library = + LoadNativeApplication(app_path, NativeApplicationCleanup::DELETE); + if (!app_library) + return; + + // Set the application context if needed. Most applications will need to + // access the Android ApplicationContext in which they are run. If the + // application library exports the InitApplicationContext function, we will + // set it there. + const char* init_application_context_name = "InitApplicationContext"; + typedef void (*InitApplicationContextFn)( + const base::android::JavaRef<jobject>&); + InitApplicationContextFn init_application_context = + reinterpret_cast<InitApplicationContextFn>( + base::GetFunctionPointerFromNativeLibrary( + app_library, init_application_context_name)); + if (init_application_context) { + base::android::ScopedJavaLocalRef<jobject> scoped_context(env, j_context); + init_application_context(scoped_context); + } + + // Run the application. + RunNativeApplication(app_library, application_request.Pass()); + // TODO(vtl): See note about unloading and thread-local destructors above + // declaration of |LoadNativeApplication()|. + base::UnloadNativeLibrary(app_library); +} + +} // namespace + +AndroidHandler::AndroidHandler() : content_handler_factory_(this) { +} + +AndroidHandler::~AndroidHandler() { +} + +void AndroidHandler::RunApplication( + InterfaceRequest<Application> application_request, + URLResponsePtr response) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> j_archive_path = + Java_AndroidHandler_getNewTempArchivePath(env, GetApplicationContext()); + base::FilePath archive_path( + ConvertJavaStringToUTF8(env, j_archive_path.obj())); + + common::BlockingCopyToFile(response->body.Pass(), archive_path); + RunAndroidApplicationFn run_android_application_fn = &RunAndroidApplication; + Java_AndroidHandler_bootstrap( + env, GetApplicationContext(), j_archive_path.obj(), + application_request.PassMessagePipe().release().value(), + reinterpret_cast<jlong>(run_android_application_fn)); +} + +void AndroidHandler::Initialize(ApplicationImpl* app) { +} + +bool AndroidHandler::ConfigureIncomingConnection( + ApplicationConnection* connection) { + connection->AddService(&content_handler_factory_); + return true; +} + +bool RegisterAndroidHandlerJni(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/android/android_handler.h b/mojo/runner/android/android_handler.h new file mode 100644 index 0000000..e36ff6d --- /dev/null +++ b/mojo/runner/android/android_handler.h
@@ -0,0 +1,46 @@ +// 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 MOJO_RUNNER_ANDROID_ANDROID_HANDLER_H_ +#define MOJO_RUNNER_ANDROID_ANDROID_HANDLER_H_ + +#include <jni.h> + +#include "mojo/application/content_handler_factory.h" +#include "mojo/public/cpp/application/application_delegate.h" +#include "mojo/public/cpp/application/interface_factory_impl.h" +#include "third_party/mojo_services/src/content_handler/public/interfaces/content_handler.mojom.h" + +namespace base { +class FilePath; +} + +namespace mojo { +namespace shell { + +class AndroidHandler : public ApplicationDelegate, + public ContentHandlerFactory::Delegate { + public: + AndroidHandler(); + ~AndroidHandler(); + + private: + // ApplicationDelegate: + void Initialize(ApplicationImpl* app) override; + bool ConfigureIncomingConnection(ApplicationConnection* connection) override; + + // ContentHandlerFactory::Delegate: + void RunApplication(InterfaceRequest<Application> application_request, + URLResponsePtr response) override; + + ContentHandlerFactory content_handler_factory_; + MOJO_DISALLOW_COPY_AND_ASSIGN(AndroidHandler); +}; + +bool RegisterAndroidHandlerJni(JNIEnv* env); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_ANDROID_ANDROID_HANDLER_H_
diff --git a/mojo/runner/android/android_handler_loader.cc b/mojo/runner/android/android_handler_loader.cc new file mode 100644 index 0000000..5cead0b --- /dev/null +++ b/mojo/runner/android/android_handler_loader.cc
@@ -0,0 +1,25 @@ +// 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 "mojo/runner/android/android_handler_loader.h" + +namespace mojo { +namespace shell { + +AndroidHandlerLoader::AndroidHandlerLoader() { +} + +AndroidHandlerLoader::~AndroidHandlerLoader() { +} + +void AndroidHandlerLoader::Load( + const GURL& url, + InterfaceRequest<Application> application_request) { + DCHECK(application_request.is_pending()); + application_.reset( + new ApplicationImpl(&android_handler_, application_request.Pass())); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/android/android_handler_loader.h b/mojo/runner/android/android_handler_loader.h new file mode 100644 index 0000000..41d6e30 --- /dev/null +++ b/mojo/runner/android/android_handler_loader.h
@@ -0,0 +1,37 @@ +// 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 MOJO_RUNNER_ANDROID_ANDROID_HANDLER_LOADER_H_ +#define MOJO_RUNNER_ANDROID_ANDROID_HANDLER_LOADER_H_ + +#include "base/containers/scoped_ptr_hash_map.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/runner/android/android_handler.h" +#include "mojo/shell/application_loader.h" + +namespace mojo { +namespace shell { + +class AndroidHandlerLoader : public ApplicationLoader { + public: + AndroidHandlerLoader(); + virtual ~AndroidHandlerLoader(); + + private: + // ApplicationLoader overrides: + void Load(const GURL& url, + InterfaceRequest<Application> application_request) override; + + AndroidHandler android_handler_; + scoped_ptr<ApplicationImpl> application_; + + DISALLOW_COPY_AND_ASSIGN(AndroidHandlerLoader); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_ANDROID_ANDROID_HANDLER_LOADER_H_
diff --git a/mojo/shell/android/apk/AndroidManifest.xml b/mojo/runner/android/apk/AndroidManifest.xml similarity index 100% rename from mojo/shell/android/apk/AndroidManifest.xml rename to mojo/runner/android/apk/AndroidManifest.xml
diff --git a/mojo/shell/android/apk/res/values/strings.xml b/mojo/runner/android/apk/res/values/strings.xml similarity index 100% rename from mojo/shell/android/apk/res/values/strings.xml rename to mojo/runner/android/apk/res/values/strings.xml
diff --git a/mojo/shell/android/apk/src/org/chromium/mojo/shell/AndroidHandler.java b/mojo/runner/android/apk/src/org/chromium/mojo/shell/AndroidHandler.java similarity index 100% rename from mojo/shell/android/apk/src/org/chromium/mojo/shell/AndroidHandler.java rename to mojo/runner/android/apk/src/org/chromium/mojo/shell/AndroidHandler.java
diff --git a/mojo/shell/android/apk/src/org/chromium/mojo/shell/Bootstrap.java b/mojo/runner/android/apk/src/org/chromium/mojo/shell/Bootstrap.java similarity index 100% rename from mojo/shell/android/apk/src/org/chromium/mojo/shell/Bootstrap.java rename to mojo/runner/android/apk/src/org/chromium/mojo/shell/Bootstrap.java
diff --git a/mojo/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java b/mojo/runner/android/apk/src/org/chromium/mojo/shell/FileHelper.java similarity index 100% rename from mojo/shell/android/apk/src/org/chromium/mojo/shell/FileHelper.java rename to mojo/runner/android/apk/src/org/chromium/mojo/shell/FileHelper.java
diff --git a/mojo/shell/android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java b/mojo/runner/android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java similarity index 100% rename from mojo/shell/android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java rename to mojo/runner/android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java
diff --git a/mojo/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java b/mojo/runner/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java similarity index 100% rename from mojo/shell/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java rename to mojo/runner/android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java
diff --git a/mojo/shell/android/apk/src/org/chromium/mojo/shell/ShellMain.java b/mojo/runner/android/apk/src/org/chromium/mojo/shell/ShellMain.java similarity index 100% rename from mojo/shell/android/apk/src/org/chromium/mojo/shell/ShellMain.java rename to mojo/runner/android/apk/src/org/chromium/mojo/shell/ShellMain.java
diff --git a/mojo/runner/android/background_application_loader.cc b/mojo/runner/android/background_application_loader.cc new file mode 100644 index 0000000..c6dace8e --- /dev/null +++ b/mojo/runner/android/background_application_loader.cc
@@ -0,0 +1,73 @@ +// 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 "mojo/runner/android/background_application_loader.h" + +#include "base/bind.h" +#include "base/run_loop.h" +#include "mojo/shell/application_manager.h" + +namespace mojo { +namespace shell { + +BackgroundApplicationLoader::BackgroundApplicationLoader( + scoped_ptr<ApplicationLoader> real_loader, + const std::string& thread_name, + base::MessageLoop::Type message_loop_type) + : loader_(real_loader.Pass()), + message_loop_type_(message_loop_type), + thread_name_(thread_name), + message_loop_created_(true, false) { +} + +BackgroundApplicationLoader::~BackgroundApplicationLoader() { + if (thread_) + thread_->Join(); +} + +void BackgroundApplicationLoader::Load( + const GURL& url, + InterfaceRequest<Application> application_request) { + DCHECK(application_request.is_pending()); + if (!thread_) { + // TODO(tim): It'd be nice if we could just have each Load call + // result in a new thread like DynamicService{Loader, Runner}. But some + // loaders are creating multiple ApplicationImpls (NetworkApplicationLoader) + // sharing a delegate (etc). So we have to keep it single threaded, wait + // for the thread to initialize, and post to the TaskRunner for subsequent + // Load calls for now. + thread_.reset(new base::DelegateSimpleThread(this, thread_name_)); + thread_->Start(); + message_loop_created_.Wait(); + DCHECK(task_runner_.get()); + } + + task_runner_->PostTask( + FROM_HERE, + base::Bind(&BackgroundApplicationLoader::LoadOnBackgroundThread, + base::Unretained(this), url, + base::Passed(&application_request))); +} + +void BackgroundApplicationLoader::Run() { + base::MessageLoop message_loop(message_loop_type_); + base::RunLoop loop; + task_runner_ = message_loop.task_runner(); + quit_closure_ = loop.QuitClosure(); + message_loop_created_.Signal(); + loop.Run(); + + // Destroy |loader_| on the thread it's actually used on. + loader_.reset(); +} + +void BackgroundApplicationLoader::LoadOnBackgroundThread( + const GURL& url, + InterfaceRequest<Application> application_request) { + DCHECK(task_runner_->RunsTasksOnCurrentThread()); + loader_->Load(url, application_request.Pass()); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/android/background_application_loader.h b/mojo/runner/android/background_application_loader.h new file mode 100644 index 0000000..e4b0db7 --- /dev/null +++ b/mojo/runner/android/background_application_loader.h
@@ -0,0 +1,64 @@ +// 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 MOJO_RUNNER_ANDROID_BACKGROUND_APPLICATION_LOADER_H_ +#define MOJO_RUNNER_ANDROID_BACKGROUND_APPLICATION_LOADER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/simple_thread.h" +#include "mojo/shell/application_loader.h" + +namespace mojo { +namespace shell { + +class BackgroundApplicationLoader + : public ApplicationLoader, + public base::DelegateSimpleThread::Delegate { + public: + BackgroundApplicationLoader(scoped_ptr<ApplicationLoader> real_loader, + const std::string& thread_name, + base::MessageLoop::Type message_loop_type); + ~BackgroundApplicationLoader() override; + + // ApplicationLoader overrides: + void Load(const GURL& url, + InterfaceRequest<Application> application_request) override; + + private: + // |base::DelegateSimpleThread::Delegate| method: + void Run() override; + + // These functions are exected on the background thread. They call through + // to |background_loader_| to do the actual loading. + void LoadOnBackgroundThread( + const GURL& url, + InterfaceRequest<Application> application_request); + bool quit_on_shutdown_; + scoped_ptr<ApplicationLoader> loader_; + + const base::MessageLoop::Type message_loop_type_; + const std::string thread_name_; + + // Created on |thread_| during construction of |this|. Protected against + // uninitialized use by |message_loop_created_|, and protected against + // use-after-free by holding a reference to the thread-safe object. Note + // that holding a reference won't hold |thread_| from exiting. + scoped_refptr<base::TaskRunner> task_runner_; + base::WaitableEvent message_loop_created_; + + // Lives on |thread_|. + base::Closure quit_closure_; + + scoped_ptr<base::DelegateSimpleThread> thread_; + + DISALLOW_COPY_AND_ASSIGN(BackgroundApplicationLoader); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_ANDROID_BACKGROUND_APPLICATION_LOADER_H_
diff --git a/mojo/runner/android/background_application_loader_unittest.cc b/mojo/runner/android/background_application_loader_unittest.cc new file mode 100644 index 0000000..4c6f5152 --- /dev/null +++ b/mojo/runner/android/background_application_loader_unittest.cc
@@ -0,0 +1,51 @@ +// 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 "mojo/runner/android/background_application_loader.h" + +#include "mojo/public/interfaces/application/application.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { +namespace { + +class DummyLoader : public ApplicationLoader { + public: + DummyLoader() : simulate_app_quit_(true) {} + ~DummyLoader() override {} + + // ApplicationLoader overrides: + void Load(const GURL& url, + InterfaceRequest<Application> application_request) override { + if (simulate_app_quit_) + base::MessageLoop::current()->Quit(); + } + + void DontSimulateAppQuit() { simulate_app_quit_ = false; } + + private: + bool simulate_app_quit_; +}; + +// Tests that the loader can start and stop gracefully. +TEST(BackgroundApplicationLoaderTest, StartStop) { + scoped_ptr<ApplicationLoader> real_loader(new DummyLoader()); + BackgroundApplicationLoader loader(real_loader.Pass(), "test", + base::MessageLoop::TYPE_DEFAULT); +} + +// Tests that the loader can load a service that is well behaved (quits +// itself). +TEST(BackgroundApplicationLoaderTest, Load) { + scoped_ptr<ApplicationLoader> real_loader(new DummyLoader()); + BackgroundApplicationLoader loader(real_loader.Pass(), "test", + base::MessageLoop::TYPE_DEFAULT); + ApplicationPtr application; + loader.Load(GURL(), GetProxy(&application)); +} + +} // namespace +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/android/bootstrap.cc b/mojo/runner/android/bootstrap.cc new file mode 100644 index 0000000..3ffe3482 --- /dev/null +++ b/mojo/runner/android/bootstrap.cc
@@ -0,0 +1,43 @@ +// 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 "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "jni/Bootstrap_jni.h" +#include "mojo/runner/android/run_android_application_function.h" + +namespace mojo { +namespace shell { + +void Bootstrap(JNIEnv* env, + jobject, + jobject j_context, + jstring j_native_library_path, + jint j_handle, + jlong j_run_application_ptr) { + base::FilePath app_path( + base::android::ConvertJavaStringToUTF8(env, j_native_library_path)); + RunAndroidApplicationFn run_android_application_fn = + reinterpret_cast<RunAndroidApplicationFn>(j_run_application_ptr); + run_android_application_fn(env, j_context, app_path, j_handle); +} + +bool RegisterBootstrapJni(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace shell +} // namespace mojo + +JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + base::android::InitVM(vm); + JNIEnv* env = base::android::AttachCurrentThread(); + + if (!mojo::shell::RegisterBootstrapJni(env)) + return -1; + + return JNI_VERSION_1_4; +}
diff --git a/mojo/runner/android/library_loader.cc b/mojo/runner/android/library_loader.cc new file mode 100644 index 0000000..e8f6ff8 --- /dev/null +++ b/mojo/runner/android/library_loader.cc
@@ -0,0 +1,44 @@ +// Copyright 2013 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/android/base_jni_onload.h" +#include "base/android/base_jni_registrar.h" +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "base/bind.h" +#include "components/native_viewport/platform_viewport_android.h" +#include "mojo/runner/android/android_handler.h" +#include "mojo/runner/android/main.h" + +namespace { + +base::android::RegistrationMethod kMojoRegisteredMethods[] = { + {"AndroidHandler", mojo::shell::RegisterAndroidHandlerJni}, + {"PlatformViewportAndroid", + native_viewport::PlatformViewportAndroid::Register}, + {"ShellMain", mojo::shell::RegisterShellMain}, +}; + +bool RegisterJNI(JNIEnv* env) { + if (!base::android::RegisterJni(env)) + return false; + + return RegisterNativeMethods(env, kMojoRegisteredMethods, + arraysize(kMojoRegisteredMethods)); +} + +} // namespace + +// This is called by the VM when the shared library is first loaded. +JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + std::vector<base::android::RegisterCallback> register_callbacks; + register_callbacks.push_back(base::Bind(&RegisterJNI)); + if (!base::android::OnJNIOnLoadRegisterJNI(vm, register_callbacks) || + !base::android::OnJNIOnLoadInit( + std::vector<base::android::InitCallback>())) { + return -1; + } + + return JNI_VERSION_1_4; +}
diff --git a/mojo/runner/android/main.cc b/mojo/runner/android/main.cc new file mode 100644 index 0000000..a610f22 --- /dev/null +++ b/mojo/runner/android/main.cc
@@ -0,0 +1,211 @@ +// Copyright 2013 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/runner/android/main.h" + +#include "base/android/fifo_utils.h" +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/at_exit.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/threading/simple_thread.h" +#include "jni/ShellMain_jni.h" +#include "mojo/common/message_pump_mojo.h" +#include "mojo/runner/android/android_handler_loader.h" +#include "mojo/runner/android/background_application_loader.h" +#include "mojo/runner/android/native_viewport_application_loader.h" +#include "mojo/runner/android/ui_application_loader_android.h" +#include "mojo/runner/context.h" +#include "mojo/runner/init.h" +#include "mojo/shell/application_loader.h" +#include "ui/gl/gl_surface_egl.h" + +using base::LazyInstance; + +namespace mojo { +namespace shell { + +namespace { + +// Tag for logging. +const char kLogTag[] = "chromium"; + +// Command line argument for the communication fifo. +const char kFifoPath[] = "fifo-path"; + +class MojoShellRunner : public base::DelegateSimpleThread::Delegate { + public: + MojoShellRunner(const std::vector<std::string>& parameters) {} + ~MojoShellRunner() override {} + + private: + void Run() override; + + DISALLOW_COPY_AND_ASSIGN(MojoShellRunner); +}; + +LazyInstance<scoped_ptr<base::MessageLoop>> g_java_message_loop = + LAZY_INSTANCE_INITIALIZER; + +LazyInstance<scoped_ptr<Context>> g_context = LAZY_INSTANCE_INITIALIZER; + +LazyInstance<scoped_ptr<MojoShellRunner>> g_shell_runner = + LAZY_INSTANCE_INITIALIZER; + +LazyInstance<scoped_ptr<base::DelegateSimpleThread>> g_shell_thread = + LAZY_INSTANCE_INITIALIZER; + +LazyInstance<base::android::ScopedJavaGlobalRef<jobject>> g_main_activiy = + LAZY_INSTANCE_INITIALIZER; + +void ConfigureAndroidServices(Context* context) { + context->application_manager()->SetLoaderForURL( + make_scoped_ptr(new UIApplicationLoader( + make_scoped_ptr(new NativeViewportApplicationLoader()), + g_java_message_loop.Get().get())), + GURL("mojo:native_viewport_service")); + + // Android handler is bundled with the Mojo shell, because it uses the + // MojoShell application as the JNI bridge to bootstrap execution of other + // Android Mojo apps that need JNI. + context->application_manager()->SetLoaderForURL( + make_scoped_ptr(new BackgroundApplicationLoader( + make_scoped_ptr(new AndroidHandlerLoader()), "android_handler", + base::MessageLoop::TYPE_DEFAULT)), + GURL("mojo:android_handler")); +} + +void QuitShellThread() { + g_shell_thread.Get()->Join(); + g_shell_thread.Pointer()->reset(); + Java_ShellMain_finishActivity(base::android::AttachCurrentThread(), + g_main_activiy.Get().obj()); + exit(0); +} + +void MojoShellRunner::Run() { + base::MessageLoop loop(common::MessagePumpMojo::Create()); + Context* context = g_context.Pointer()->get(); + ConfigureAndroidServices(context); + context->Init(); + + context->Run(GURL("mojo:window_manager")); + loop.Run(); + + g_java_message_loop.Pointer()->get()->PostTask(FROM_HERE, + base::Bind(&QuitShellThread)); +} + +// Initialize stdout redirection if the command line switch is present. +void InitializeRedirection() { + if (!base::CommandLine::ForCurrentProcess()->HasSwitch(kFifoPath)) + return; + + base::FilePath fifo_path = + base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(kFifoPath); + base::FilePath directory = fifo_path.DirName(); + CHECK(base::CreateDirectoryAndGetError(directory, nullptr)) + << "Unable to create directory: " << directory.value(); + unlink(fifo_path.value().c_str()); + CHECK(base::android::CreateFIFO(fifo_path, 0666)) + << "Unable to create fifo: " << fifo_path.value(); + CHECK(base::android::RedirectStream(stdout, fifo_path, "w")) + << "Failed to redirect stdout to file: " << fifo_path.value(); + CHECK(dup2(STDOUT_FILENO, STDERR_FILENO) != -1) + << "Unable to redirect stderr to stdout."; +} + +} // namespace + +static void Init(JNIEnv* env, + jclass clazz, + jobject activity, + jstring mojo_shell_path, + jobjectArray jparameters, + jstring j_local_apps_directory, + jstring j_tmp_dir) { + g_main_activiy.Get().Reset(env, activity); + + // Setting the TMPDIR environment variable so that applications can use it. + // TODO(qsr) We will need our subprocesses to inherit this. + int return_value = + setenv("TMPDIR", + base::android::ConvertJavaStringToUTF8(env, j_tmp_dir).c_str(), 1); + DCHECK_EQ(return_value, 0); + + base::android::ScopedJavaLocalRef<jobject> scoped_activity(env, activity); + base::android::InitApplicationContext(env, scoped_activity); + + std::vector<std::string> parameters; + parameters.push_back( + base::android::ConvertJavaStringToUTF8(env, mojo_shell_path)); + base::android::AppendJavaStringArrayToStringVector(env, jparameters, + ¶meters); + base::CommandLine::Init(0, nullptr); + base::CommandLine::ForCurrentProcess()->InitFromArgv(parameters); + g_shell_runner.Get().reset(new MojoShellRunner(parameters)); + + InitializeLogging(); + + InitializeRedirection(); + + // We want ~MessageLoop to happen prior to ~Context. Initializing + // LazyInstances is akin to stack-allocating objects; their destructors + // will be invoked first-in-last-out. + Context* shell_context = new Context(); + shell_context->SetShellFileRoot(base::FilePath( + base::android::ConvertJavaStringToUTF8(env, j_local_apps_directory))); + g_context.Get().reset(shell_context); + + g_java_message_loop.Get().reset(new base::MessageLoopForUI); + base::MessageLoopForUI::current()->Start(); + + // TODO(abarth): At which point should we switch to cross-platform + // initialization? + + gfx::GLSurface::InitializeOneOff(); +} + +static jboolean Start(JNIEnv* env, jclass clazz) { + if (!base::CommandLine::ForCurrentProcess()->GetArgs().size()) + return false; + +#if defined(MOJO_SHELL_DEBUG_URL) + base::CommandLine::ForCurrentProcess()->AppendArg(MOJO_SHELL_DEBUG_URL); + // Sleep for 5 seconds to give the debugger a chance to attach. + sleep(5); +#endif + + g_shell_thread.Get().reset(new base::DelegateSimpleThread( + g_shell_runner.Get().get(), "ShellThread")); + g_shell_thread.Get()->Start(); + return true; +} + +static void AddApplicationURL(JNIEnv* env, jclass clazz, jstring jurl) { + base::CommandLine::ForCurrentProcess()->AppendArg( + base::android::ConvertJavaStringToUTF8(env, jurl)); +} + +bool RegisterShellMain(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +} // namespace shell +} // namespace mojo + +// TODO(vtl): Even though main() should never be called, mojo_shell fails to +// link without it. Figure out if we can avoid this. +int main(int argc, char** argv) { + NOTREACHED(); +}
diff --git a/mojo/runner/android/main.h b/mojo/runner/android/main.h new file mode 100644 index 0000000..80316829 --- /dev/null +++ b/mojo/runner/android/main.h
@@ -0,0 +1,18 @@ +// Copyright 2013 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_RUNNER_ANDROID_MAIN_H_ +#define MOJO_RUNNER_ANDROID_MAIN_H_ + +#include <jni.h> + +namespace mojo { +namespace shell { + +bool RegisterShellMain(JNIEnv* env); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_ANDROID_MAIN_H_
diff --git a/mojo/runner/android/native_viewport_application_loader.cc b/mojo/runner/android/native_viewport_application_loader.cc new file mode 100644 index 0000000..e2a8afe --- /dev/null +++ b/mojo/runner/android/native_viewport_application_loader.cc
@@ -0,0 +1,50 @@ +// 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 "mojo/runner/android/native_viewport_application_loader.h" + +#include "components/gles2/gpu_state.h" +#include "components/native_viewport/native_viewport_impl.h" +#include "mojo/public/cpp/application/application_impl.h" + +namespace mojo { +namespace shell { + +NativeViewportApplicationLoader::NativeViewportApplicationLoader() { +} + +NativeViewportApplicationLoader::~NativeViewportApplicationLoader() { +} + +void NativeViewportApplicationLoader::Load( + const GURL& url, + InterfaceRequest<Application> application_request) { + DCHECK(application_request.is_pending()); + app_.reset(new ApplicationImpl(this, application_request.Pass())); +} + +bool NativeViewportApplicationLoader::ConfigureIncomingConnection( + ApplicationConnection* connection) { + connection->AddService<NativeViewport>(this); + connection->AddService<Gpu>(this); + return true; +} + +void NativeViewportApplicationLoader::Create( + ApplicationConnection* connection, + InterfaceRequest<NativeViewport> request) { + if (!gpu_state_) + gpu_state_ = new gles2::GpuState; + new native_viewport::NativeViewportImpl(false, gpu_state_, request.Pass()); +} + +void NativeViewportApplicationLoader::Create(ApplicationConnection* connection, + InterfaceRequest<Gpu> request) { + if (!gpu_state_) + gpu_state_ = new gles2::GpuState; + new gles2::GpuImpl(request.Pass(), gpu_state_); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/android/native_viewport_application_loader.h b/mojo/runner/android/native_viewport_application_loader.h new file mode 100644 index 0000000..210369a --- /dev/null +++ b/mojo/runner/android/native_viewport_application_loader.h
@@ -0,0 +1,58 @@ +// 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 MOJO_RUNNER_ANDROID_NATIVE_VIEWPORT_APPLICATION_LOADER_H_ +#define MOJO_RUNNER_ANDROID_NATIVE_VIEWPORT_APPLICATION_LOADER_H_ + +#include "components/gles2/gpu_impl.h" +#include "components/gpu/public/interfaces/gpu.mojom.h" +#include "components/native_viewport/public/interfaces/native_viewport.mojom.h" +#include "mojo/public/cpp/application/application_delegate.h" +#include "mojo/public/cpp/application/interface_factory.h" +#include "mojo/shell/application_loader.h" + +namespace gles2 { +class GpuState; +} + +namespace mojo { + +class ApplicationImpl; + +namespace shell { + +class NativeViewportApplicationLoader : public ApplicationLoader, + public ApplicationDelegate, + public InterfaceFactory<NativeViewport>, + public InterfaceFactory<Gpu> { + public: + NativeViewportApplicationLoader(); + ~NativeViewportApplicationLoader(); + + private: + // ApplicationLoader implementation. + void Load(const GURL& url, + InterfaceRequest<Application> application_request) override; + + // ApplicationDelegate implementation. + bool ConfigureIncomingConnection(ApplicationConnection* connection) override; + + // InterfaceFactory<NativeViewport> implementation. + void Create(ApplicationConnection* connection, + InterfaceRequest<NativeViewport> request) override; + + // InterfaceFactory<Gpu> implementation. + void Create(ApplicationConnection* connection, + InterfaceRequest<Gpu> request) override; + + scoped_refptr<gles2::GpuState> gpu_state_; + scoped_ptr<ApplicationImpl> app_; + + DISALLOW_COPY_AND_ASSIGN(NativeViewportApplicationLoader); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_ANDROID_NATIVE_VIEWPORT_APPLICATION_LOADER_H_
diff --git a/mojo/runner/android/run_android_application_function.h b/mojo/runner/android/run_android_application_function.h new file mode 100644 index 0000000..a9871241e --- /dev/null +++ b/mojo/runner/android/run_android_application_function.h
@@ -0,0 +1,27 @@ +// 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 MOJO_RUNNER_ANDROID_RUN_ANDROID_APPLICATION_FUNCTION_H_ +#define MOJO_RUNNER_ANDROID_RUN_ANDROID_APPLICATION_FUNCTION_H_ + +#include "base/android/jni_android.h" +#include "base/files/file_path.h" + +namespace mojo { +namespace shell { + +// Type of the function that we inject from the main .so of the Mojo shell to +// the helper libbootstrap.so. This function will set the thunks in the +// application .so and call into application MojoMain. Injecting the function +// from the main .so ensures that the thunks are set correctly. + +typedef void (*RunAndroidApplicationFn)(JNIEnv* env, + jobject j_context, + const base::FilePath& app_path, + jint j_handle); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_ANDROID_RUN_ANDROID_APPLICATION_FUNCTION_H_
diff --git a/mojo/shell/android/tests/src/org/chromium/mojo/shell/ShellTestBase.java b/mojo/runner/android/tests/src/org/chromium/mojo/shell/ShellTestBase.java similarity index 100% rename from mojo/shell/android/tests/src/org/chromium/mojo/shell/ShellTestBase.java rename to mojo/runner/android/tests/src/org/chromium/mojo/shell/ShellTestBase.java
diff --git a/mojo/runner/android/ui_application_loader_android.cc b/mojo/runner/android/ui_application_loader_android.cc new file mode 100644 index 0000000..a046d64d6e --- /dev/null +++ b/mojo/runner/android/ui_application_loader_android.cc
@@ -0,0 +1,48 @@ +// 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 "mojo/runner/android/ui_application_loader_android.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "mojo/shell/application_manager.h" + +namespace mojo { +namespace shell { + +UIApplicationLoader::UIApplicationLoader( + scoped_ptr<ApplicationLoader> real_loader, + base::MessageLoop* ui_message_loop) + : loader_(real_loader.Pass()), ui_message_loop_(ui_message_loop) { +} + +UIApplicationLoader::~UIApplicationLoader() { + ui_message_loop_->PostTask( + FROM_HERE, base::Bind(&UIApplicationLoader::ShutdownOnUIThread, + base::Unretained(this))); +} + +void UIApplicationLoader::Load( + const GURL& url, + InterfaceRequest<Application> application_request) { + DCHECK(application_request.is_pending()); + ui_message_loop_->PostTask( + FROM_HERE, + base::Bind(&UIApplicationLoader::LoadOnUIThread, base::Unretained(this), + url, base::Passed(&application_request))); +} + +void UIApplicationLoader::LoadOnUIThread( + const GURL& url, + InterfaceRequest<Application> application_request) { + loader_->Load(url, application_request.Pass()); +} + +void UIApplicationLoader::ShutdownOnUIThread() { + // Destroy |loader_| on the thread it's actually used on. + loader_.reset(); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/android/ui_application_loader_android.h b/mojo/runner/android/ui_application_loader_android.h new file mode 100644 index 0000000..46aefa7 --- /dev/null +++ b/mojo/runner/android/ui_application_loader_android.h
@@ -0,0 +1,54 @@ +// 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 MOJO_RUNNER_ANDROID_UI_APPLICATION_LOADER_ANDROID_H_ +#define MOJO_RUNNER_ANDROID_UI_APPLICATION_LOADER_ANDROID_H_ + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "mojo/shell/application_loader.h" + +namespace base { +class MessageLoop; +} + +namespace mojo { +namespace shell { + +class ApplicationManager; + +// ApplicationLoader implementation that creates a background thread and issues +// load +// requests there. +class UIApplicationLoader : public ApplicationLoader { + public: + UIApplicationLoader(scoped_ptr<ApplicationLoader> real_loader, + base::MessageLoop* ui_message_loop); + ~UIApplicationLoader() override; + + // ApplicationLoader overrides: + void Load(const GURL& url, + InterfaceRequest<Application> application_request) override; + + private: + class UILoader; + + // These functions are exected on the background thread. They call through + // to |background_loader_| to do the actual loading. + // TODO: having this code take a |manager| is fragile (as ApplicationManager + // isn't thread safe). + void LoadOnUIThread(const GURL& url, + InterfaceRequest<Application> application_request); + void ShutdownOnUIThread(); + + scoped_ptr<ApplicationLoader> loader_; + base::MessageLoop* ui_message_loop_; + + DISALLOW_COPY_AND_ASSIGN(UIApplicationLoader); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_ANDROID_UI_APPLICATION_LOADER_ANDROID_H_
diff --git a/mojo/runner/child_process.cc b/mojo/runner/child_process.cc new file mode 100644 index 0000000..cee831f --- /dev/null +++ b/mojo/runner/child_process.cc
@@ -0,0 +1,321 @@ +// 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 "mojo/runner/child_process.h" + +#include "base/base_switches.h" +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/command_line.h" +#include "base/debug/debugger.h" +#include "base/files/file_path.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/single_thread_task_runner.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" +#include "base/threading/thread_checker.h" +#include "mojo/common/message_pump_mojo.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/edk/embedder/process_delegate.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/edk/embedder/simple_platform_support.h" +#include "mojo/public/cpp/system/core.h" +#include "mojo/runner/child_process.mojom.h" +#include "mojo/runner/native_application_support.h" +#include "mojo/runner/switches.h" + +namespace mojo { +namespace shell { + +namespace { + +// Blocker --------------------------------------------------------------------- + +// Blocks a thread until another thread unblocks it, at which point it unblocks +// and runs a closure provided by that thread. +class Blocker { + public: + class Unblocker { + public: + explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {} + ~Unblocker() {} + + void Unblock(base::Closure run_after) { + DCHECK(blocker_); + DCHECK(blocker_->run_after_.is_null()); + blocker_->run_after_ = run_after; + blocker_->event_.Signal(); + blocker_ = nullptr; + } + + private: + Blocker* blocker_; + + // Copy and assign allowed. + }; + + Blocker() : event_(true, false) {} + ~Blocker() {} + + void Block() { + DCHECK(run_after_.is_null()); + event_.Wait(); + run_after_.Run(); + } + + Unblocker GetUnblocker() { return Unblocker(this); } + + private: + base::WaitableEvent event_; + base::Closure run_after_; + + DISALLOW_COPY_AND_ASSIGN(Blocker); +}; + +// AppContext ------------------------------------------------------------------ + +class ChildControllerImpl; + +// Should be created and initialized on the main thread. +class AppContext : public embedder::ProcessDelegate { + public: + AppContext() + : io_thread_("io_thread"), controller_thread_("controller_thread") {} + ~AppContext() override {} + + void Init() { + // Initialize Mojo before starting any threads. + embedder::Init(make_scoped_ptr(new embedder::SimplePlatformSupport())); + + // Create and start our I/O thread. + base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); + CHECK(io_thread_.StartWithOptions(io_thread_options)); + io_runner_ = io_thread_.message_loop_proxy().get(); + CHECK(io_runner_.get()); + + // Create and start our controller thread. + base::Thread::Options controller_thread_options; + controller_thread_options.message_loop_type = + base::MessageLoop::TYPE_CUSTOM; + controller_thread_options.message_pump_factory = + base::Bind(&common::MessagePumpMojo::Create); + CHECK(controller_thread_.StartWithOptions(controller_thread_options)); + controller_runner_ = controller_thread_.message_loop_proxy().get(); + CHECK(controller_runner_.get()); + + // TODO(vtl): This should be SLAVE, not NONE. + embedder::InitIPCSupport(embedder::ProcessType::NONE, controller_runner_, + this, io_runner_, + embedder::ScopedPlatformHandle()); + } + + void Shutdown() { + Blocker blocker; + shutdown_unblocker_ = blocker.GetUnblocker(); + controller_runner_->PostTask( + FROM_HERE, base::Bind(&AppContext::ShutdownOnControllerThread, + base::Unretained(this))); + blocker.Block(); + } + + base::SingleThreadTaskRunner* io_runner() const { return io_runner_.get(); } + + base::SingleThreadTaskRunner* controller_runner() const { + return controller_runner_.get(); + } + + ChildControllerImpl* controller() const { return controller_.get(); } + + void set_controller(scoped_ptr<ChildControllerImpl> controller) { + controller_ = controller.Pass(); + } + + private: + void ShutdownOnControllerThread() { + // First, destroy the controller. + controller_.reset(); + + // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete(). + embedder::ShutdownIPCSupport(); + } + + // ProcessDelegate implementation. + void OnShutdownComplete() override { + shutdown_unblocker_.Unblock(base::Closure()); + } + + base::Thread io_thread_; + scoped_refptr<base::SingleThreadTaskRunner> io_runner_; + + base::Thread controller_thread_; + scoped_refptr<base::SingleThreadTaskRunner> controller_runner_; + + // Accessed only on the controller thread. + scoped_ptr<ChildControllerImpl> controller_; + + // Used to unblock the main thread on shutdown. + Blocker::Unblocker shutdown_unblocker_; + + DISALLOW_COPY_AND_ASSIGN(AppContext); +}; + +// ChildControllerImpl ------------------------------------------------------ + +class ChildControllerImpl : public ChildController, public ErrorHandler { + public: + ~ChildControllerImpl() override { + DCHECK(thread_checker_.CalledOnValidThread()); + + // TODO(vtl): Pass in the result from |MainMain()|. + on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED); + } + + // To be executed on the controller thread. Creates the |ChildController|, + // etc. + static void Init(AppContext* app_context, + embedder::ScopedPlatformHandle platform_channel, + const Blocker::Unblocker& unblocker) { + DCHECK(app_context); + DCHECK(platform_channel.is_valid()); + + DCHECK(!app_context->controller()); + + scoped_ptr<ChildControllerImpl> impl( + new ChildControllerImpl(app_context, unblocker)); + + ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( + platform_channel.Pass(), app_context->io_runner(), + base::Bind(&ChildControllerImpl::DidCreateChannel, + base::Unretained(impl.get())), + base::MessageLoopProxy::current())); + + impl->Bind(host_message_pipe.Pass()); + + app_context->set_controller(impl.Pass()); + } + + void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); } + + // |ErrorHandler| methods: + void OnConnectionError() override { + // A connection error means the connection to the shell is lost. This is not + // recoverable. + LOG(ERROR) << "Connection error to the shell."; + _exit(1); + } + + // |ChildController| methods: + void StartApp(const String& app_path, + bool clean_app_path, + InterfaceRequest<Application> application_request, + const StartAppCallback& on_app_complete) override { + DVLOG(2) << "ChildControllerImpl::StartApp(" << app_path << ", ...)"; + DCHECK(thread_checker_.CalledOnValidThread()); + + on_app_complete_ = on_app_complete; + unblocker_.Unblock(base::Bind(&ChildControllerImpl::StartAppOnMainThread, + base::FilePath::FromUTF8Unsafe(app_path), + clean_app_path + ? NativeApplicationCleanup::DELETE + : NativeApplicationCleanup::DONT_DELETE, + base::Passed(&application_request))); + } + + void ExitNow(int32_t exit_code) override { + DVLOG(2) << "ChildControllerImpl::ExitNow(" << exit_code << ")"; + _exit(exit_code); + } + + private: + ChildControllerImpl(AppContext* app_context, + const Blocker::Unblocker& unblocker) + : app_context_(app_context), + unblocker_(unblocker), + channel_info_(nullptr), + binding_(this) { + binding_.set_error_handler(this); + } + + // Callback for |embedder::CreateChannel()|. + void DidCreateChannel(embedder::ChannelInfo* channel_info) { + DVLOG(2) << "ChildControllerImpl::DidCreateChannel()"; + DCHECK(thread_checker_.CalledOnValidThread()); + channel_info_ = channel_info; + } + + static void StartAppOnMainThread( + const base::FilePath& app_path, + NativeApplicationCleanup cleanup, + InterfaceRequest<Application> application_request) { + // TODO(vtl): This is copied from in_process_native_runner.cc. + DVLOG(2) << "Loading/running Mojo app from " << app_path.value() + << " out of process"; + + // We intentionally don't unload the native library as its lifetime is the + // same as that of the process. + base::NativeLibrary app_library = LoadNativeApplication(app_path, cleanup); + RunNativeApplication(app_library, application_request.Pass()); + } + + base::ThreadChecker thread_checker_; + AppContext* const app_context_; + Blocker::Unblocker unblocker_; + StartAppCallback on_app_complete_; + + embedder::ChannelInfo* channel_info_; + Binding<ChildController> binding_; + + DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl); +}; + +} // namespace + +int ChildProcessMain() { + DVLOG(2) << "ChildProcessMain()"; + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kWaitForDebugger)) { + std::string app = command_line.GetSwitchValueASCII(switches::kApp); +#if defined(OS_WIN) + MessageBox(NULL, command_line.GetSwitchValueNative(switches::kApp).c_str(), + command_line.GetSwitchValueNative(switches::kApp).c_str(), + MB_OK | MB_SETFOREGROUND); +#else + LOG(ERROR) << command_line.GetSwitchValueASCII(switches::kApp) + << " waiting for GDB. pid: " << getpid(); + base::debug::WaitForDebugger(60, true); +#endif + } + + embedder::ScopedPlatformHandle platform_channel = + embedder::PlatformChannelPair::PassClientHandleFromParentProcess( + command_line); + CHECK(platform_channel.is_valid()); + + DCHECK(!base::MessageLoop::current()); + + AppContext app_context; + app_context.Init(); + + Blocker blocker; + app_context.controller_runner()->PostTask( + FROM_HERE, + base::Bind(&ChildControllerImpl::Init, base::Unretained(&app_context), + base::Passed(&platform_channel), blocker.GetUnblocker())); + // This will block, then run whatever the controller wants. + blocker.Block(); + + app_context.Shutdown(); + + return 0; +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/child_process.h b/mojo/runner/child_process.h new file mode 100644 index 0000000..1d4badf --- /dev/null +++ b/mojo/runner/child_process.h
@@ -0,0 +1,17 @@ +// 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 MOJO_RUNNER_CHILD_PROCESS_H_ +#define MOJO_RUNNER_CHILD_PROCESS_H_ + +namespace mojo { +namespace shell { + +// Main method for a child process. +int ChildProcessMain(); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_CHILD_PROCESS_H_
diff --git a/mojo/shell/child_process.mojom b/mojo/runner/child_process.mojom similarity index 100% rename from mojo/shell/child_process.mojom rename to mojo/runner/child_process.mojom
diff --git a/mojo/runner/child_process_host.cc b/mojo/runner/child_process_host.cc new file mode 100644 index 0000000..2198678 --- /dev/null +++ b/mojo/runner/child_process_host.cc
@@ -0,0 +1,163 @@ +// 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 "mojo/runner/child_process_host.h" + +#include "base/base_switches.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/process/kill.h" +#include "base/process/launch.h" +#include "base/stl_util.h" +#include "base/strings/string_split.h" +#include "base/task_runner.h" +#include "base/task_runner_util.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/public/cpp/system/core.h" +#include "mojo/runner/context.h" +#include "mojo/runner/switches.h" +#include "mojo/runner/task_runners.h" +#include "ui/gl/gl_switches.h" + +namespace mojo { +namespace shell { + +ChildProcessHost::ChildProcessHost(Context* context, const std::string& name) + : context_(context), name_(name), channel_info_(nullptr) { + platform_channel_ = platform_channel_pair_.PassServerHandle(); + DCHECK(!name.empty()); + CHECK(platform_channel_.is_valid()); +} + +ChildProcessHost::~ChildProcessHost() { + if (child_process_.IsValid()) { + LOG(WARNING) << "Destroying ChildProcessHost with unjoined child"; + child_process_.Close(); + } +} + +void ChildProcessHost::Start() { + DCHECK(!child_process_.IsValid()); + DCHECK(platform_channel_.is_valid()); + + ScopedMessagePipeHandle handle(embedder::CreateChannel( + platform_channel_.Pass(), context_->task_runners()->io_runner(), + base::Bind(&ChildProcessHost::DidCreateChannel, base::Unretained(this)), + base::MessageLoop::current()->message_loop_proxy())); + + controller_.Bind(handle.Pass()); + + CHECK(base::PostTaskAndReplyWithResult( + context_->task_runners()->blocking_pool(), FROM_HERE, + base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), + base::Bind(&ChildProcessHost::DidStart, base::Unretained(this)))); +} + +int ChildProcessHost::Join() { + DCHECK(child_process_.IsValid()); + int rv = -1; + LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) + << "Failed to wait for child process"; + child_process_.Close(); + return rv; +} + +void ChildProcessHost::StartApp( + const String& app_path, + bool clean_app_path, + InterfaceRequest<Application> application_request, + const ChildController::StartAppCallback& on_app_complete) { + DCHECK(controller_); + + on_app_complete_ = on_app_complete; + controller_->StartApp( + app_path, clean_app_path, application_request.Pass(), + base::Bind(&ChildProcessHost::AppCompleted, base::Unretained(this))); +} + +void ChildProcessHost::ExitNow(int32_t exit_code) { + DCHECK(controller_); + + controller_->ExitNow(exit_code); +} + +void ChildProcessHost::DidStart(bool success) { + DVLOG(2) << "ChildProcessHost::DidStart()"; + + if (!success) { + LOG(ERROR) << "Failed to start child process"; + AppCompleted(MOJO_RESULT_UNKNOWN); + return; + } +} + +bool ChildProcessHost::DoLaunch() { + static const char* kForwardSwitches[] = { + switches::kOverrideUseGLWithOSMesaForTests, + switches::kTraceToConsole, + switches::kV, + switches::kVModule, + }; + + const base::CommandLine* parent_command_line = + base::CommandLine::ForCurrentProcess(); + base::CommandLine child_command_line(parent_command_line->GetProgram()); + child_command_line.CopySwitchesFrom(*parent_command_line, kForwardSwitches, + arraysize(kForwardSwitches)); + child_command_line.AppendSwitchASCII(switches::kApp, name_); + child_command_line.AppendSwitch(switches::kChildProcess); + if (parent_command_line->HasSwitch(switches::kWaitForDebugger)) { + std::vector<std::string> apps_to_debug; + base::SplitString( + parent_command_line->GetSwitchValueASCII(switches::kWaitForDebugger), + ',', &apps_to_debug); + if (apps_to_debug.empty() || ContainsValue(apps_to_debug, name_)) + child_command_line.AppendSwitch(switches::kWaitForDebugger); + } + + auto args = parent_command_line->GetArgs(); + for (const auto& arg : args) + child_command_line.AppendArgNative(arg); + + embedder::HandlePassingInformation handle_passing_info; + platform_channel_pair_.PrepareToPassClientHandleToChildProcess( + &child_command_line, &handle_passing_info); + + base::LaunchOptions options; +#if defined(OS_WIN) + options.handles_to_inherit = &handle_passing_info; +#elif defined(OS_POSIX) + options.fds_to_remap = &handle_passing_info; +#endif + DVLOG(2) << "Launching child with command line: " + << child_command_line.GetCommandLineString(); + child_process_ = base::LaunchProcess(child_command_line, options); + if (!child_process_.IsValid()) + return false; + + platform_channel_pair_.ChildProcessLaunched(); + return true; +} + +void ChildProcessHost::AppCompleted(int32_t result) { + if (!on_app_complete_.is_null()) { + auto on_app_complete = on_app_complete_; + on_app_complete_.reset(); + on_app_complete.Run(result); + } +} + +void ChildProcessHost::DidCreateChannel(embedder::ChannelInfo* channel_info) { + DVLOG(2) << "AppChildProcessHost::DidCreateChannel()"; + + CHECK(channel_info); + channel_info_ = channel_info; +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/child_process_host.h b/mojo/runner/child_process_host.h new file mode 100644 index 0000000..b0516d5e --- /dev/null +++ b/mojo/runner/child_process_host.h
@@ -0,0 +1,86 @@ +// 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 MOJO_RUNNER_CHILD_PROCESS_HOST_H_ +#define MOJO_RUNNER_CHILD_PROCESS_HOST_H_ + +#include "base/macros.h" +#include "base/process/process.h" +#include "mojo/edk/embedder/channel_info_forward.h" +#include "mojo/edk/embedder/platform_channel_pair.h" +#include "mojo/edk/embedder/scoped_platform_handle.h" +#include "mojo/runner/child_process.mojom.h" +#include "mojo/runner/child_process_host.h" + +namespace mojo { +namespace shell { + +class Context; + +// This class represents a "child process host". Handles launching and +// connecting a platform-specific "pipe" to the child, and supports joining the +// child process. Currently runs a single app (loaded from the file system). +// +// This class is not thread-safe. It should be created/used/destroyed on a +// single thread. +// +// Note: Does not currently work on Windows before Vista. +// Note: After |Start()|, |StartApp| must be called and this object must +// remained alive until the |on_app_complete| callback is called. +class ChildProcessHost { + public: + // |name| is just for debugging ease. + ChildProcessHost(Context* context, const std::string& name); + virtual ~ChildProcessHost(); + + // |Start()|s the child process; calls |DidStart()| (on the thread on which + // |Start()| was called) when the child has been started (or failed to start). + // After calling |Start()|, this object must not be destroyed until + // |DidStart()| has been called. + // TODO(vtl): Consider using weak pointers and removing this requirement. + void Start(); + + // Waits for the child process to terminate, and returns its exit code. + // Note: If |Start()| has been called, this must not be called until the + // callback has been called. + int Join(); + + // See |ChildController|: + void StartApp(const String& app_path, + bool clean_app_path, + InterfaceRequest<Application> application_request, + const ChildController::StartAppCallback& on_app_complete); + void ExitNow(int32_t exit_code); + + protected: + // virtual for testing. + virtual void DidStart(bool success); + + private: + bool DoLaunch(); + + void AppCompleted(int32_t result); + + // Callback for |embedder::CreateChannel()|. + void DidCreateChannel(embedder::ChannelInfo* channel_info); + + Context* const context_; + const std::string name_; + base::Process child_process_; + embedder::PlatformChannelPair platform_channel_pair_; + ChildControllerPtr controller_; + embedder::ChannelInfo* channel_info_; + ChildController::StartAppCallback on_app_complete_; + + // Platform-specific "pipe" to the child process. Valid immediately after + // creation. + embedder::ScopedPlatformHandle platform_channel_; + + DISALLOW_COPY_AND_ASSIGN(ChildProcessHost); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_CHILD_PROCESS_HOST_H_
diff --git a/mojo/runner/child_process_host_unittest.cc b/mojo/runner/child_process_host_unittest.cc new file mode 100644 index 0000000..5e69ec93 --- /dev/null +++ b/mojo/runner/child_process_host_unittest.cc
@@ -0,0 +1,63 @@ +// 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. + +// Note: This file also tests child_process.*. + +#include "mojo/runner/child_process_host.h" + +#include "base/logging.h" +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "mojo/common/message_pump_mojo.h" +#include "mojo/runner/context.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { +namespace { + +// Subclass just so we can observe |DidStart()|. +class TestChildProcessHost : public ChildProcessHost { + public: + explicit TestChildProcessHost(Context* context) + : ChildProcessHost(context, "test") {} + ~TestChildProcessHost() override {} + + void DidStart(bool success) override { + EXPECT_TRUE(success); + ChildProcessHost::DidStart(success); + base::MessageLoop::current()->QuitWhenIdle(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(TestChildProcessHost); +}; + +#if defined(OS_ANDROID) +// TODO(qsr): Multiprocess shell tests are not supported on android. +#define MAYBE_StartJoin DISABLED_StartJoin +#else +#define MAYBE_StartJoin StartJoin +#endif // defined(OS_ANDROID) +// Just tests starting the child process and joining it (without starting an +// app). +TEST(ChildProcessHostTest, MAYBE_StartJoin) { + Context context; + base::MessageLoop message_loop( + scoped_ptr<base::MessagePump>(new common::MessagePumpMojo())); + context.Init(); + TestChildProcessHost child_process_host(&context); + child_process_host.Start(); + message_loop.Run(); + child_process_host.ExitNow(123); + int exit_code = child_process_host.Join(); + VLOG(2) << "Joined child: exit_code = " << exit_code; + EXPECT_EQ(123, exit_code); + + context.Shutdown(); +} + +} // namespace +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/context.cc b/mojo/runner/context.cc new file mode 100644 index 0000000..db53876 --- /dev/null +++ b/mojo/runner/context.cc
@@ -0,0 +1,324 @@ +// Copyright 2013 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/runner/context.h" + +#include <vector> + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/trace_event/trace_event.h" +#include "build/build_config.h" +#include "mojo/common/trace_controller_impl.h" +#include "mojo/common/tracing_impl.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/simple_platform_support.h" +#include "mojo/public/cpp/application/application_connection.h" +#include "mojo/public/cpp/application/application_delegate.h" +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/runner/filename_util.h" +#include "mojo/runner/in_process_native_runner.h" +#include "mojo/runner/out_of_process_native_runner.h" +#include "mojo/runner/switches.h" +#include "mojo/services/tracing/tracing.mojom.h" +#include "mojo/shell/application_loader.h" +#include "mojo/shell/application_manager.h" +#include "url/gurl.h" + +namespace mojo { +namespace shell { +namespace { + +// Used to ensure we only init once. +class Setup { + public: + Setup() { + embedder::Init(make_scoped_ptr(new embedder::SimplePlatformSupport())); + } + + ~Setup() {} + + private: + DISALLOW_COPY_AND_ASSIGN(Setup); +}; + +bool ConfigureURLMappings(const base::CommandLine& command_line, + Context* context) { + URLResolver* resolver = context->url_resolver(); + + // Configure the resolution of unknown mojo: URLs. + GURL base_url; + if (command_line.HasSwitch(switches::kOrigin)) + base_url = GURL(command_line.GetSwitchValueASCII(switches::kOrigin)); + else + // Use the shell's file root if the base was not specified. + base_url = context->ResolveShellFileURL(""); + + if (!base_url.is_valid()) + return false; + + resolver->SetMojoBaseURL(base_url); + + // The network service must be loaded from the filesystem. + // This mapping is done before the command line URL mapping are processed, so + // that it can be overridden. + resolver->AddURLMapping( + GURL("mojo:network_service"), + context->ResolveShellFileURL("file:network_service.mojo")); + + // Command line URL mapping. + std::vector<URLResolver::OriginMapping> origin_mappings = + URLResolver::GetOriginMappings(command_line.argv()); + for (const auto& origin_mapping : origin_mappings) + resolver->AddOriginMapping(GURL(origin_mapping.origin), + GURL(origin_mapping.base_url)); + + if (command_line.HasSwitch(switches::kURLMappings)) { + const std::string mappings = + command_line.GetSwitchValueASCII(switches::kURLMappings); + + base::StringPairs pairs; + if (!base::SplitStringIntoKeyValuePairs(mappings, '=', ',', &pairs)) + return false; + using StringPair = std::pair<std::string, std::string>; + for (const StringPair& pair : pairs) { + const GURL from(pair.first); + const GURL to = context->ResolveCommandLineURL(pair.second); + if (!from.is_valid() || !to.is_valid()) + return false; + resolver->AddURLMapping(from, to); + } + } + + return true; +} + +void InitContentHandlers(ApplicationManager* manager, + const base::CommandLine& command_line) { + // Default content handlers. + manager->RegisterContentHandler("application/pdf", GURL("mojo:pdf_viewer")); + manager->RegisterContentHandler("image/png", GURL("mojo:png_viewer")); + manager->RegisterContentHandler("text/html", GURL("mojo:html_viewer")); + + // Command-line-specified content handlers. + std::string handlers_spec = + command_line.GetSwitchValueASCII(switches::kContentHandlers); + if (handlers_spec.empty()) + return; + +#if defined(OS_ANDROID) + // TODO(eseidel): On Android we pass command line arguments is via the + // 'parameters' key on the intent, which we specify during 'am shell start' + // via --esa, however that expects comma-separated values and says: + // am shell --help: + // [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]] + // (to embed a comma into a string escape it using "\,") + // Whatever takes 'parameters' and constructs a CommandLine is failing to + // un-escape the commas, we need to move this fix to that file. + ReplaceSubstringsAfterOffset(&handlers_spec, 0, "\\,", ","); +#endif + + std::vector<std::string> parts; + base::SplitString(handlers_spec, ',', &parts); + if (parts.size() % 2 != 0) { + LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers + << ": must be a comma-separated list of mimetype/url pairs." + << handlers_spec; + return; + } + + for (size_t i = 0; i < parts.size(); i += 2) { + GURL url(parts[i + 1]); + if (!url.is_valid()) { + LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers + << ": '" << parts[i + 1] << "' is not a valid URL."; + return; + } + // TODO(eseidel): We should also validate that the mimetype is valid + // net/base/mime_util.h could do this, but we don't want to depend on net. + manager->RegisterContentHandler(parts[i], url); + } +} + +void InitNativeOptions(ApplicationManager* manager, + const base::CommandLine& command_line) { + std::vector<std::string> force_in_process_url_list; + base::SplitString(command_line.GetSwitchValueASCII(switches::kForceInProcess), + ',', &force_in_process_url_list); + for (const auto& force_in_process_url : force_in_process_url_list) { + GURL gurl(force_in_process_url); + if (!gurl.is_valid()) { + LOG(ERROR) << "Invalid value for switch " << switches::kForceInProcess + << ": '" << force_in_process_url << "'is not a valid URL."; + return; + } + + NativeRunnerFactory::Options options; + options.force_in_process = true; + manager->SetNativeOptionsForURL(options, gurl); + } +} + +class TracingServiceProvider : public ServiceProvider { + public: + explicit TracingServiceProvider(InterfaceRequest<ServiceProvider> request) + : binding_(this, request.Pass()) {} + ~TracingServiceProvider() override {} + + void ConnectToService(const String& service_name, + ScopedMessagePipeHandle client_handle) override { + if (service_name == tracing::TraceController::Name_) { + new TraceControllerImpl( + MakeRequest<tracing::TraceController>(client_handle.Pass())); + } + } + + private: + StrongBinding<ServiceProvider> binding_; + + DISALLOW_COPY_AND_ASSIGN(TracingServiceProvider); +}; + +} // namespace + +Context::Context() : application_manager_(this) { + DCHECK(!base::MessageLoop::current()); + + // By default assume that the local apps reside alongside the shell. + // TODO(ncbray): really, this should be passed in rather than defaulting. + // This default makes sense for desktop but not Android. + base::FilePath shell_dir; + PathService::Get(base::DIR_MODULE, &shell_dir); + SetShellFileRoot(shell_dir); + + base::FilePath cwd; + PathService::Get(base::DIR_CURRENT, &cwd); + SetCommandLineCWD(cwd); +} + +Context::~Context() { + DCHECK(!base::MessageLoop::current()); +} + +// static +void Context::EnsureEmbedderIsInitialized() { + static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER; + setup.Get(); +} + +void Context::SetShellFileRoot(const base::FilePath& path) { + shell_file_root_ = AddTrailingSlashIfNeeded(FilePathToFileURL(path)); +} + +GURL Context::ResolveShellFileURL(const std::string& path) { + return shell_file_root_.Resolve(path); +} + +void Context::SetCommandLineCWD(const base::FilePath& path) { + command_line_cwd_ = AddTrailingSlashIfNeeded(FilePathToFileURL(path)); +} + +GURL Context::ResolveCommandLineURL(const std::string& path) { + return command_line_cwd_.Resolve(path); +} + +bool Context::Init() { + TRACE_EVENT0("mojo_shell", "Context::Init"); + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + + EnsureEmbedderIsInitialized(); + task_runners_.reset( + new TaskRunners(base::MessageLoop::current()->message_loop_proxy())); + + // TODO(vtl): Probably these failures should be checked before |Init()|, and + // this function simply shouldn't fail. + if (!shell_file_root_.is_valid()) + return false; + if (!ConfigureURLMappings(command_line, this)) + return false; + + // TODO(vtl): This should be MASTER, not NONE. + embedder::InitIPCSupport( + embedder::ProcessType::NONE, task_runners_->shell_runner(), this, + task_runners_->io_runner(), embedder::ScopedPlatformHandle()); + + scoped_ptr<NativeRunnerFactory> runner_factory; + if (command_line.HasSwitch(switches::kEnableMultiprocess)) + runner_factory.reset(new OutOfProcessNativeRunnerFactory(this)); + else + runner_factory.reset(new InProcessNativeRunnerFactory(this)); + application_manager_.set_blocking_pool(task_runners_->blocking_pool()); + application_manager_.set_native_runner_factory(runner_factory.Pass()); + application_manager_.set_disable_cache( + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableCache)); + + InitContentHandlers(&application_manager_, command_line); + InitNativeOptions(&application_manager_, command_line); + + ServiceProviderPtr tracing_service_provider_ptr; + new TracingServiceProvider(GetProxy(&tracing_service_provider_ptr)); + application_manager_.ConnectToApplication( + GURL("mojo:tracing"), GURL(""), nullptr, + tracing_service_provider_ptr.Pass(), base::Closure()); + + return true; +} + +void Context::Shutdown() { + TRACE_EVENT0("mojo_shell", "Context::Shutdown"); + DCHECK_EQ(base::MessageLoop::current()->task_runner(), + task_runners_->shell_runner()); + embedder::ShutdownIPCSupport(); + // We'll quit when we get OnShutdownComplete(). + base::MessageLoop::current()->Run(); +} + +GURL Context::ResolveMappings(const GURL& url) { + return url_resolver_.ApplyMappings(url); +} + +GURL Context::ResolveMojoURL(const GURL& url) { + return url_resolver_.ResolveMojoURL(url); +} + +void Context::OnShutdownComplete() { + DCHECK_EQ(base::MessageLoop::current()->task_runner(), + task_runners_->shell_runner()); + base::MessageLoop::current()->Quit(); +} + +void Context::Run(const GURL& url) { + ServiceProviderPtr services; + ServiceProviderPtr exposed_services; + + app_urls_.insert(url); + application_manager_.ConnectToApplication( + url, GURL(), GetProxy(&services), exposed_services.Pass(), + base::Bind(&Context::OnApplicationEnd, base::Unretained(this), url)); +} + +void Context::OnApplicationEnd(const GURL& url) { + if (app_urls_.find(url) != app_urls_.end()) { + app_urls_.erase(url); + if (app_urls_.empty() && base::MessageLoop::current()->is_running()) { + DCHECK_EQ(base::MessageLoop::current()->task_runner(), + task_runners_->shell_runner()); + base::MessageLoop::current()->Quit(); + } + } +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/context.h b/mojo/runner/context.h new file mode 100644 index 0000000..6f4c150 --- /dev/null +++ b/mojo/runner/context.h
@@ -0,0 +1,87 @@ +// Copyright 2013 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_RUNNER_CONTEXT_H_ +#define MOJO_RUNNER_CONTEXT_H_ + +#include <string> + +#include "base/macros.h" +#include "mojo/edk/embedder/process_delegate.h" +#include "mojo/runner/task_runners.h" +#include "mojo/runner/url_resolver.h" +#include "mojo/shell/application_manager.h" + +namespace mojo { +namespace shell { + +class NativeApplicationLoader; + +// The "global" context for the shell's main process. +class Context : public ApplicationManager::Delegate, + public embedder::ProcessDelegate { + public: + Context(); + ~Context() override; + + static void EnsureEmbedderIsInitialized(); + + // Point to the directory containing installed services, such as the network + // service. By default this directory is used as the base URL for resolving + // unknown mojo: URLs. The network service will be loaded from this directory, + // even when the base URL for unknown mojo: URLs is overridden. + void SetShellFileRoot(const base::FilePath& path); + + // Resolve an URL relative to the shell file root. This is a nop for + // everything but relative file URLs or URLs without a scheme. + GURL ResolveShellFileURL(const std::string& path); + + // Override the CWD, which is used for resolving file URLs passed in from the + // command line. + void SetCommandLineCWD(const base::FilePath& path); + + // Resolve an URL relative to the CWD mojo_shell was invoked from. This is a + // nop for everything but relative file URLs or URLs without a scheme. + GURL ResolveCommandLineURL(const std::string& path); + + // This must be called with a message loop set up for the current thread, + // which must remain alive until after Shutdown() is called. Returns true on + // success. + bool Init(); + + // If Init() was called and succeeded, this must be called before destruction. + void Shutdown(); + + void Run(const GURL& url); + + TaskRunners* task_runners() { return task_runners_.get(); } + ApplicationManager* application_manager() { return &application_manager_; } + URLResolver* url_resolver() { return &url_resolver_; } + + private: + class NativeViewportApplicationLoader; + + // ApplicationManager::Delegate overrides. + GURL ResolveMappings(const GURL& url) override; + GURL ResolveMojoURL(const GURL& url) override; + + // ProcessDelegate implementation. + void OnShutdownComplete() override; + + void OnApplicationEnd(const GURL& url); + + std::set<GURL> app_urls_; + scoped_ptr<TaskRunners> task_runners_; + ApplicationManager application_manager_; + URLResolver url_resolver_; + GURL shell_file_root_; + GURL command_line_cwd_; + + DISALLOW_COPY_AND_ASSIGN(Context); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_CONTEXT_H_
diff --git a/mojo/runner/data_pipe_peek_unittest.cc b/mojo/runner/data_pipe_peek_unittest.cc new file mode 100644 index 0000000..6fc2b7d58 --- /dev/null +++ b/mojo/runner/data_pipe_peek_unittest.cc
@@ -0,0 +1,113 @@ +// 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 "mojo/shell/data_pipe_peek.h" + +#include "mojo/runner/context.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { +namespace { + +TEST(DataPipePeek, PeekNBytes) { + Context::EnsureEmbedderIsInitialized(); + + DataPipe data_pipe; + DataPipeConsumerHandle consumer(data_pipe.consumer_handle.get()); + DataPipeProducerHandle producer(data_pipe.producer_handle.get()); + + // Inialize the pipe with 4 bytes. + + const char* s4 = "1234"; + uint32_t num_bytes4 = 4; + EXPECT_EQ(MOJO_RESULT_OK, + WriteDataRaw(producer, s4, &num_bytes4, MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(4u, num_bytes4); + + // We're not consuming data, so peeking for 4 bytes should always succeed. + + std::string bytes; + MojoDeadline timeout = 0; + EXPECT_TRUE(BlockingPeekNBytes(consumer, &bytes, num_bytes4, timeout)); + EXPECT_EQ(bytes, std::string(s4)); + + timeout = 1000; // 1ms + EXPECT_TRUE(BlockingPeekNBytes(consumer, &bytes, num_bytes4, timeout)); + EXPECT_EQ(bytes, std::string(s4)); + + timeout = MOJO_DEADLINE_INDEFINITE; + EXPECT_TRUE(BlockingPeekNBytes(consumer, &bytes, num_bytes4, timeout)); + EXPECT_EQ(bytes, std::string(s4)); + + // Peeking for 5 bytes should fail, until another byte is written. + + uint32_t bytes1 = 1; + uint32_t num_bytes5 = 5; + const char* s1 = "5"; + const char* s5 = "12345"; + + timeout = 0; + EXPECT_FALSE(BlockingPeekNBytes(consumer, &bytes, num_bytes5, timeout)); + + timeout = 500; // Should cause peek to timeout after about 0.5ms. + EXPECT_FALSE(BlockingPeekNBytes(consumer, &bytes, num_bytes5, timeout)); + + EXPECT_EQ(MOJO_RESULT_OK, + WriteDataRaw(producer, s1, &bytes1, MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(1u, bytes1); + + EXPECT_TRUE(BlockingPeekNBytes(consumer, &bytes, num_bytes5, timeout)); + EXPECT_EQ(bytes, std::string(s5)); + + // If the consumer side of the pipe is closed, peek should fail. + + data_pipe.consumer_handle.reset(); + timeout = 0; + EXPECT_FALSE(BlockingPeekNBytes(consumer, &bytes, num_bytes5, timeout)); +} + +TEST(DataPipePeek, PeekLine) { + Context::EnsureEmbedderIsInitialized(); + + DataPipe data_pipe; + DataPipeConsumerHandle consumer(data_pipe.consumer_handle.get()); + DataPipeProducerHandle producer(data_pipe.producer_handle.get()); + + // Inialize the pipe with 4 bytes and no newline. + + const char* s4 = "1234"; + uint32_t num_bytes4 = 4; + EXPECT_EQ(MOJO_RESULT_OK, + WriteDataRaw(producer, s4, &num_bytes4, MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(4u, num_bytes4); + + // Peeking for a line should fail. + + std::string str; + size_t max_str_length = 5; + MojoDeadline timeout = 0; + EXPECT_FALSE(BlockingPeekLine(consumer, &str, max_str_length, timeout)); + + // Writing a newline should cause PeekLine to succeed. + + uint32_t bytes1 = 1; + const char* s1 = "\n"; + EXPECT_EQ(MOJO_RESULT_OK, + WriteDataRaw(producer, s1, &bytes1, MOJO_WRITE_DATA_FLAG_NONE)); + EXPECT_EQ(1u, bytes1); + + EXPECT_TRUE(BlockingPeekLine(consumer, &str, max_str_length, timeout)); + EXPECT_EQ(str, std::string(s4) + "\n"); + + // If the max_line_length parameter is less than the length of the + // newline terminated string, then peek should fail. + + max_str_length = 3; + EXPECT_FALSE(BlockingPeekLine(consumer, &str, max_str_length, timeout)); +} + +} // namespace +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/desktop/launcher_process.cc b/mojo/runner/desktop/launcher_process.cc new file mode 100644 index 0000000..ebbfccb --- /dev/null +++ b/mojo/runner/desktop/launcher_process.cc
@@ -0,0 +1,136 @@ +// Copyright 2013 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 <stdio.h> +#include <string.h> + +#include <algorithm> +#include <iostream> + +#include "base/base_switches.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file_util.h" +#include "base/message_loop/message_loop.h" +#include "base/synchronization/waitable_event.h" +#include "base/trace_event/trace_event.h" +#include "mojo/runner/context.h" +#include "mojo/runner/switches.h" + +namespace mojo { +namespace shell { +namespace { + +// Whether we're currently tracing. +bool g_tracing = false; + +// Number of tracing blocks written. +uint32_t g_blocks = 0; + +// Trace file, if open. +FILE* g_trace_file = nullptr; + +void WriteTraceDataCollected( + base::WaitableEvent* event, + const scoped_refptr<base::RefCountedString>& events_str, + bool has_more_events) { + if (g_blocks) { + fwrite(",", 1, 1, g_trace_file); + } + + ++g_blocks; + fwrite(events_str->data().c_str(), 1, events_str->data().length(), + g_trace_file); + if (!has_more_events) { + static const char kEnd[] = "]}"; + fwrite(kEnd, 1, strlen(kEnd), g_trace_file); + PCHECK(fclose(g_trace_file) == 0); + g_trace_file = nullptr; + event->Signal(); + } +} + +void EndTraceAndFlush(base::WaitableEvent* event) { + g_trace_file = fopen("mojo_shell.trace", "w+"); + PCHECK(g_trace_file); + static const char kStart[] = "{\"traceEvents\":["; + fwrite(kStart, 1, strlen(kStart), g_trace_file); + base::trace_event::TraceLog::GetInstance()->SetDisabled(); + base::trace_event::TraceLog::GetInstance()->Flush( + base::Bind(&WriteTraceDataCollected, base::Unretained(event))); +} + +void StopTracingAndFlushToDisk() { + g_tracing = false; + base::trace_event::TraceLog::GetInstance()->SetDisabled(); + base::WaitableEvent flush_complete_event(false, false); + // TraceLog::Flush requires a message loop but we've already shut ours down. + // Spin up a new thread to flush things out. + base::Thread flush_thread("mojo_shell_trace_event_flush"); + flush_thread.Start(); + flush_thread.message_loop()->PostTask( + FROM_HERE, + base::Bind(EndTraceAndFlush, base::Unretained(&flush_complete_event))); + flush_complete_event.Wait(); +} + +void StartApp(mojo::shell::Context* context) { + // If a mojo app isn't specified (i.e. for an apptest), run the mojo shell's + // window manager. + GURL app_url(GURL("mojo:window_manager")); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + base::CommandLine::StringVector args = command_line->GetArgs(); + for (size_t i = 0; i < args.size(); ++i) { + GURL possible_app(args[i]); + if (possible_app.SchemeIs("mojo")) { + app_url = possible_app; + break; + } + } + + context->Run(app_url); +} + +} // namespace + +int LauncherProcessMain(int argc, char** argv) { + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kTraceStartup)) { + g_tracing = true; + base::trace_event::CategoryFilter category_filter( + command_line.GetSwitchValueASCII(switches::kTraceStartup)); + base::trace_event::TraceLog::GetInstance()->SetEnabled( + category_filter, base::trace_event::TraceLog::RECORDING_MODE, + base::trace_event::TraceOptions(base::trace_event::RECORD_UNTIL_FULL)); + } + + // We want the shell::Context to outlive the MessageLoop so that pipes are + // all gracefully closed / error-out before we try to shut the Context down. + mojo::shell::Context shell_context; + { + base::MessageLoop message_loop; + if (!shell_context.Init()) { + return 0; + } + if (g_tracing) { + message_loop.PostDelayedTask(FROM_HERE, + base::Bind(StopTracingAndFlushToDisk), + base::TimeDelta::FromSeconds(5)); + } + + message_loop.PostTask(FROM_HERE, base::Bind(&StartApp, &shell_context)); + message_loop.Run(); + + // Must be called before |message_loop| is destroyed. + shell_context.Shutdown(); + } + + if (g_tracing) + StopTracingAndFlushToDisk(); + return 0; +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/desktop/launcher_process.h b/mojo/runner/desktop/launcher_process.h similarity index 100% rename from mojo/shell/desktop/launcher_process.h rename to mojo/runner/desktop/launcher_process.h
diff --git a/mojo/runner/desktop/main.cc b/mojo/runner/desktop/main.cc new file mode 100644 index 0000000..b5d8576d --- /dev/null +++ b/mojo/runner/desktop/main.cc
@@ -0,0 +1,24 @@ +// Copyright 2013 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/at_exit.h" +#include "base/command_line.h" +#include "mojo/runner/child_process.h" +#include "mojo/runner/desktop/launcher_process.h" +#include "mojo/runner/init.h" +#include "mojo/runner/switches.h" + +int main(int argc, char** argv) { + base::AtExitManager at_exit; + base::CommandLine::Init(argc, argv); + + mojo::shell::InitializeLogging(); + + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch(switches::kChildProcess)) + return mojo::shell::ChildProcessMain(); + + return mojo::shell::LauncherProcessMain(argc, argv); +}
diff --git a/mojo/runner/filename_util.cc b/mojo/runner/filename_util.cc new file mode 100644 index 0000000..3f8a82b --- /dev/null +++ b/mojo/runner/filename_util.cc
@@ -0,0 +1,72 @@ +// 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 "mojo/runner/filename_util.h" + +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/strings/string_util.h" +#include "url/gurl.h" +#include "url/url_canon_internal.h" +#include "url/url_util.h" + +namespace mojo { +namespace shell { + +// Prefix to prepend to get a file URL. +static const base::FilePath::CharType kFileURLPrefix[] = + FILE_PATH_LITERAL("file://"); + +GURL FilePathToFileURL(const base::FilePath& path) { + // Produce a URL like "file:///C:/foo" for a regular file, or + // "file://///server/path" for UNC. The URL canonicalizer will fix up the + // latter case to be the canonical UNC form: "file://server/path" + base::FilePath::StringType url_string(kFileURLPrefix); + if (!path.IsAbsolute()) { + base::FilePath current_dir; + PathService::Get(base::DIR_CURRENT, ¤t_dir); + url_string.append(current_dir.value()); + url_string.push_back(base::FilePath::kSeparators[0]); + } + url_string.append(path.value()); + + // Now do replacement of some characters. Since we assume the input is a + // literal filename, anything the URL parser might consider special should + // be escaped here. + + // This must be the first substitution since others will introduce percents as + // the escape character + ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL("%"), + FILE_PATH_LITERAL("%25")); + + // A semicolon is supposed to be some kind of separator according to RFC 2396. + ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL(";"), + FILE_PATH_LITERAL("%3B")); + + ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL("#"), + FILE_PATH_LITERAL("%23")); + + ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL("?"), + FILE_PATH_LITERAL("%3F")); + +#if defined(OS_POSIX) + ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL("\\"), + FILE_PATH_LITERAL("%5C")); +#endif + + return GURL(url_string); +} + +GURL AddTrailingSlashIfNeeded(const GURL& url) { + if (!url.has_path() || *url.path().rbegin() == '/') + return url; + + std::string path(url.path() + '/'); + GURL::Replacements replacements; + replacements.SetPathStr(path); + return url.ReplaceComponents(replacements); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/filename_util.h b/mojo/runner/filename_util.h new file mode 100644 index 0000000..22ae001 --- /dev/null +++ b/mojo/runner/filename_util.h
@@ -0,0 +1,28 @@ +// 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 MOJO_RUNNER_FILENAME_UTIL_H_ +#define MOJO_RUNNER_FILENAME_UTIL_H_ + +class GURL; + +namespace base { +class FilePath; +} + +namespace mojo { +namespace shell { + +// Given the full path to a file name, creates a file: URL. The returned URL +// may not be valid if the input is malformed. +GURL FilePathToFileURL(const base::FilePath& path); + +// This URL is going to be treated as a directory. Ensure there is a trailing +// slash so that GURL.Resolve(...) works correctly. +GURL AddTrailingSlashIfNeeded(const GURL& url); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_FILENAME_UTIL_H_
diff --git a/mojo/runner/in_process_native_runner.cc b/mojo/runner/in_process_native_runner.cc new file mode 100644 index 0000000..ce09f5b --- /dev/null +++ b/mojo/runner/in_process_native_runner.cc
@@ -0,0 +1,72 @@ +// 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 "mojo/runner/in_process_native_runner.h" + +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/location.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/threading/platform_thread.h" +#include "mojo/runner/native_application_support.h" + +namespace mojo { +namespace shell { + +InProcessNativeRunner::InProcessNativeRunner(Context* context) + : cleanup_(NativeApplicationCleanup::DONT_DELETE), app_library_(nullptr) { +} + +InProcessNativeRunner::~InProcessNativeRunner() { + // It is important to let the thread exit before unloading the DSO (when + // app_library_ is destructed), because the library may have registered + // thread-local data and destructors to run on thread termination. + if (thread_) { + DCHECK(thread_->HasBeenStarted()); + DCHECK(!thread_->HasBeenJoined()); + thread_->Join(); + } +} + +void InProcessNativeRunner::Start( + const base::FilePath& app_path, + NativeApplicationCleanup cleanup, + InterfaceRequest<Application> application_request, + const base::Closure& app_completed_callback) { + app_path_ = app_path; + cleanup_ = cleanup; + + DCHECK(!application_request_.is_pending()); + application_request_ = application_request.Pass(); + + DCHECK(app_completed_callback_runner_.is_null()); + app_completed_callback_runner_ = + base::Bind(&base::TaskRunner::PostTask, base::MessageLoopProxy::current(), + FROM_HERE, app_completed_callback); + + DCHECK(!thread_); + thread_.reset(new base::DelegateSimpleThread(this, "app_thread")); + thread_->Start(); +} + +void InProcessNativeRunner::Run() { + DVLOG(2) << "Loading/running Mojo app in process from library: " + << app_path_.value() + << " thread id=" << base::PlatformThread::CurrentId(); + + // TODO(vtl): ScopedNativeLibrary doesn't have a .get() method! + base::NativeLibrary app_library = LoadNativeApplication(app_path_, cleanup_); + app_library_.Reset(app_library); + RunNativeApplication(app_library, application_request_.Pass()); + app_completed_callback_runner_.Run(); + app_completed_callback_runner_.Reset(); +} + +scoped_ptr<NativeRunner> InProcessNativeRunnerFactory::Create( + const Options& options) { + return make_scoped_ptr(new InProcessNativeRunner(context_)); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/in_process_native_runner.h b/mojo/runner/in_process_native_runner.h new file mode 100644 index 0000000..e8afcfd9 --- /dev/null +++ b/mojo/runner/in_process_native_runner.h
@@ -0,0 +1,67 @@ +// 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 MOJO_RUNNER_IN_PROCESS_NATIVE_RUNNER_H_ +#define MOJO_RUNNER_IN_PROCESS_NATIVE_RUNNER_H_ + +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/scoped_native_library.h" +#include "base/threading/simple_thread.h" +#include "mojo/runner/native_application_support.h" +#include "mojo/shell/native_runner.h" + +namespace mojo { +namespace shell { + +class Context; + +// An implementation of |NativeRunner| that loads/runs the given app (from the +// file system) on a separate thread (in the current process). +class InProcessNativeRunner : public NativeRunner, + public base::DelegateSimpleThread::Delegate { + public: + explicit InProcessNativeRunner(Context* context); + ~InProcessNativeRunner() override; + + // |NativeRunner| method: + void Start(const base::FilePath& app_path, + NativeApplicationCleanup cleanup, + InterfaceRequest<Application> application_request, + const base::Closure& app_completed_callback) override; + + private: + // |base::DelegateSimpleThread::Delegate| method: + void Run() override; + + base::FilePath app_path_; + NativeApplicationCleanup cleanup_; + InterfaceRequest<Application> application_request_; + base::Callback<bool(void)> app_completed_callback_runner_; + + base::ScopedNativeLibrary app_library_; + scoped_ptr<base::DelegateSimpleThread> thread_; + + DISALLOW_COPY_AND_ASSIGN(InProcessNativeRunner); +}; + +class InProcessNativeRunnerFactory : public NativeRunnerFactory { + public: + explicit InProcessNativeRunnerFactory(Context* context) : context_(context) {} + ~InProcessNativeRunnerFactory() override {} + + scoped_ptr<NativeRunner> Create(const Options& options) override; + + private: + Context* const context_; + + DISALLOW_COPY_AND_ASSIGN(InProcessNativeRunnerFactory); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_IN_PROCESS_NATIVE_RUNNER_H_
diff --git a/mojo/runner/in_process_native_runner_unittest.cc b/mojo/runner/in_process_native_runner_unittest.cc new file mode 100644 index 0000000..12fecfc --- /dev/null +++ b/mojo/runner/in_process_native_runner_unittest.cc
@@ -0,0 +1,23 @@ +// 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 "mojo/runner/in_process_native_runner.h" + +#include "mojo/runner/context.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { + +TEST(InProcessNativeRunnerTest, NotStarted) { + Context context; + base::MessageLoop loop; + context.Init(); + InProcessNativeRunner runner(&context); + context.Shutdown(); + // Shouldn't crash or DCHECK on destruction. +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/init.cc b/mojo/runner/init.cc new file mode 100644 index 0000000..e069f4fb --- /dev/null +++ b/mojo/runner/init.cc
@@ -0,0 +1,24 @@ +// Copyright 2013 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/runner/init.h" + +#include "base/logging.h" + +namespace mojo { +namespace shell { + +void InitializeLogging() { + logging::LoggingSettings settings; + settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; + logging::InitLogging(settings); + // To view log output with IDs and timestamps use "adb logcat -v threadtime". + logging::SetLogItems(false, // Process ID + false, // Thread ID + false, // Timestamp + false); // Tick count +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/init.h b/mojo/runner/init.h new file mode 100644 index 0000000..8ddc2d7 --- /dev/null +++ b/mojo/runner/init.h
@@ -0,0 +1,18 @@ +// Copyright 2013 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_RUNNER_INIT_H_ +#define MOJO_RUNNER_INIT_H_ + +namespace mojo { +namespace shell { + +// Initialization routines shared by desktop and Android main functions. + +void InitializeLogging(); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_INIT_H_
diff --git a/mojo/runner/native_application_support.cc b/mojo/runner/native_application_support.cc new file mode 100644 index 0000000..aa6f68b --- /dev/null +++ b/mojo/runner/native_application_support.cc
@@ -0,0 +1,145 @@ +// 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 "mojo/runner/native_application_support.h" + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "mojo/public/platform/native/gles2_impl_chromium_miscellaneous_thunks.h" +#include "mojo/public/platform/native/gles2_impl_chromium_sub_image_thunks.h" +#include "mojo/public/platform/native/gles2_impl_chromium_sync_point_thunks.h" +#include "mojo/public/platform/native/gles2_impl_chromium_texture_mailbox_thunks.h" +#include "mojo/public/platform/native/gles2_impl_occlusion_query_ext_thunks.h" +#include "mojo/public/platform/native/gles2_impl_thunks.h" +#include "mojo/public/platform/native/gles2_thunks.h" +#include "mojo/public/platform/native/system_thunks.h" + +namespace mojo { +namespace shell { + +namespace { + +template <typename Thunks> +bool SetThunks(Thunks (*make_thunks)(), + const char* function_name, + base::NativeLibrary library) { + typedef size_t (*SetThunksFn)(const Thunks* thunks); + SetThunksFn set_thunks = reinterpret_cast<SetThunksFn>( + base::GetFunctionPointerFromNativeLibrary(library, function_name)); + if (!set_thunks) + return false; + Thunks thunks = make_thunks(); + size_t expected_size = set_thunks(&thunks); + if (expected_size > sizeof(Thunks)) { + LOG(ERROR) << "Invalid app library: expected " << function_name + << " to return thunks of size: " << expected_size; + return false; + } + return true; +} + +} // namespace + +base::NativeLibrary LoadNativeApplication(const base::FilePath& app_path, + NativeApplicationCleanup cleanup) { + DVLOG(2) << "Loading Mojo app in process from library: " << app_path.value(); + + base::NativeLibraryLoadError error; + base::NativeLibrary app_library = base::LoadNativeLibrary(app_path, &error); + if (cleanup == NativeApplicationCleanup::DELETE) + DeleteFile(app_path, false); + LOG_IF(ERROR, !app_library) + << "Failed to load app library (error: " << error.ToString() << ")"; + return app_library; +} + +bool RunNativeApplication(base::NativeLibrary app_library, + InterfaceRequest<Application> application_request) { + // Tolerate |app_library| being null, to make life easier for callers. + if (!app_library) + return false; + + if (!SetThunks(&MojoMakeSystemThunks, "MojoSetSystemThunks", app_library)) { + LOG(ERROR) << "MojoSetSystemThunks not found"; + return false; + } + + if (SetThunks(&MojoMakeGLES2ControlThunks, "MojoSetGLES2ControlThunks", + app_library)) { + // If we have the control thunks, we should also have the GLES2 + // implementation thunks. + if (!SetThunks(&MojoMakeGLES2ImplThunks, "MojoSetGLES2ImplThunks", + app_library)) { + LOG(ERROR) + << "MojoSetGLES2ControlThunks found, but not MojoSetGLES2ImplThunks"; + return false; + } + + // If the application is using GLES2 extension points, register those + // thunks. Applications may use or not use any of these, so don't warn if + // they are missing. + SetThunks(MojoMakeGLES2ImplChromiumMiscellaneousThunks, + "MojoSetGLES2ImplChromiumMiscellaneousThunks", app_library); + SetThunks(MojoMakeGLES2ImplChromiumSubImageThunks, + "MojoSetGLES2ImplChromiumSubImageThunks", app_library); + SetThunks(MojoMakeGLES2ImplChromiumTextureMailboxThunks, + "MojoSetGLES2ImplChromiumTextureMailboxThunks", app_library); + SetThunks(MojoMakeGLES2ImplChromiumSyncPointThunks, + "MojoSetGLES2ImplChromiumSyncPointThunks", app_library); + SetThunks(MojoMakeGLES2ImplOcclusionQueryExtThunks, + "MojoSetGLES2ImplOcclusionQueryExtThunks", app_library); + } + // Unlike system thunks, we don't warn on a lack of GLES2 thunks because + // not everything is a visual app. + + // Go shared library support requires us to initialize the runtime before we + // start running any go code. This is a temporary patch. + typedef void (*InitGoRuntimeFn)(); + InitGoRuntimeFn init_go_runtime = reinterpret_cast<InitGoRuntimeFn>( + base::GetFunctionPointerFromNativeLibrary(app_library, "InitGoRuntime")); + if (init_go_runtime) { + DVLOG(2) << "InitGoRuntime: Initializing Go Runtime found in app"; + init_go_runtime(); + } + +#if !defined(OS_WIN) + // On Windows, initializing base::CommandLine with null parameters gets the + // process's command line from the OS. Other platforms need it to be passed + // in. This needs to be passed in before the app initializes the command line, + // which is done as soon as it loads. + typedef void (*InitCommandLineArgs)(int, const char* const*); + InitCommandLineArgs init_command_line_args = + reinterpret_cast<InitCommandLineArgs>( + base::GetFunctionPointerFromNativeLibrary(app_library, + "InitCommandLineArgs")); + if (init_command_line_args) { + int argc = 0; + base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + const char** argv = new const char* [cmd_line->argv().size()]; + for (auto& arg : cmd_line->argv()) + argv[argc++] = arg.c_str(); + init_command_line_args(argc, argv); + } +#endif + + typedef MojoResult (*MojoMainFunction)(MojoHandle); + MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>( + base::GetFunctionPointerFromNativeLibrary(app_library, "MojoMain")); + if (!main_function) { + LOG(ERROR) << "MojoMain not found"; + return false; + } + // |MojoMain()| takes ownership of the service handle. + MojoHandle handle = application_request.PassMessagePipe().release().value(); + MojoResult result = main_function(handle); + if (result != MOJO_RESULT_OK) { + LOG(ERROR) << "MojoMain returned error (result: " << result << ")"; + } + return true; +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/native_application_support.h b/mojo/runner/native_application_support.h new file mode 100644 index 0000000..b3b8b62 --- /dev/null +++ b/mojo/runner/native_application_support.h
@@ -0,0 +1,51 @@ +// 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 MOJO_RUNNER_NATIVE_APPLICATION_SUPPORT_H_ +#define MOJO_RUNNER_NATIVE_APPLICATION_SUPPORT_H_ + +#include "base/native_library.h" +#include "mojo/public/cpp/bindings/interface_request.h" + +#if defined(OS_WIN) +#undef DELETE +#endif + +namespace base { +class FilePath; +} + +namespace mojo { + +class Application; + +namespace shell { + +enum class NativeApplicationCleanup { DELETE, DONT_DELETE }; + +// Loads the native Mojo application from the DSO specified by |app_path|. +// Returns the |base::NativeLibrary| for the application on success (or null on +// failure). If |cleanup| is |DELETE|, it will delete |app_path| (regardless of +// sucess or failure). +// +// Note: The caller may choose to eventually unload the returned DSO. If so, +// this should be done only after the thread on which |LoadNativeApplication()| +// and |RunNativeApplication()| were called has terminated, so that any +// thread-local destructors have been executed. +base::NativeLibrary LoadNativeApplication(const base::FilePath& app_path, + NativeApplicationCleanup cleanup); + +// Runs the native Mojo application from the DSO that was loaded using +// |LoadNativeApplication()|; this tolerates |app_library| being null. This +// should be called on the same thread as |LoadNativeApplication()|. Returns +// true if |MojoMain()| was called (even if it returns an error), and false +// otherwise. +// TODO(vtl): Maybe this should also have a |MojoResult| as an out parameter? +bool RunNativeApplication(base::NativeLibrary app_library, + InterfaceRequest<Application> application_request); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_NATIVE_APPLICATION_SUPPORT_H_
diff --git a/mojo/runner/native_runner_unittest.cc b/mojo/runner/native_runner_unittest.cc new file mode 100644 index 0000000..499fb75 --- /dev/null +++ b/mojo/runner/native_runner_unittest.cc
@@ -0,0 +1,101 @@ +// 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 "base/files/scoped_temp_dir.h" +#include "mojo/runner/context.h" +#include "mojo/runner/filename_util.h" +#include "mojo/shell/application_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { +namespace { + +struct TestState { + TestState() + : runner_was_created(false), + runner_was_started(false), + runner_was_destroyed(false) {} + + bool runner_was_created; + bool runner_was_started; + bool runner_was_destroyed; +}; + +class TestNativeRunner : public NativeRunner { + public: + explicit TestNativeRunner(TestState* state) : state_(state) { + state_->runner_was_created = true; + } + ~TestNativeRunner() override { + state_->runner_was_destroyed = true; + base::MessageLoop::current()->Quit(); + } + void Start(const base::FilePath& app_path, + NativeApplicationCleanup cleanup, + InterfaceRequest<Application> application_request, + const base::Closure& app_completed_callback) override { + state_->runner_was_started = true; + } + + private: + TestState* state_; +}; + +class TestNativeRunnerFactory : public NativeRunnerFactory { + public: + explicit TestNativeRunnerFactory(TestState* state) : state_(state) {} + ~TestNativeRunnerFactory() override {} + scoped_ptr<NativeRunner> Create(const Options& options) override { + return scoped_ptr<NativeRunner>(new TestNativeRunner(state_)); + } + + private: + TestState* state_; +}; + +class NativeApplicationLoaderTest : public testing::Test, + public ApplicationManager::Delegate { + public: + NativeApplicationLoaderTest() : application_manager_(this) {} + ~NativeApplicationLoaderTest() override {} + void SetUp() override { + context_.Init(); + scoped_ptr<NativeRunnerFactory> factory( + new TestNativeRunnerFactory(&state_)); + application_manager_.set_native_runner_factory(factory.Pass()); + application_manager_.set_blocking_pool( + context_.task_runners()->blocking_pool()); + } + void TearDown() override { context_.Shutdown(); } + + protected: + shell::Context context_; + base::MessageLoop loop_; + ApplicationManager application_manager_; + TestState state_; + + private: + // ApplicationManager::Delegate + GURL ResolveMappings(const GURL& url) override { return url; } + GURL ResolveMojoURL(const GURL& url) override { return url; } +}; + +TEST_F(NativeApplicationLoaderTest, DoesNotExist) { + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath nonexistent_file(FILE_PATH_LITERAL("nonexistent.txt")); + GURL url(FilePathToFileURL(temp_dir.path().Append(nonexistent_file))); + InterfaceRequest<ServiceProvider> services; + ServiceProviderPtr service_provider; + application_manager_.ConnectToApplication( + url, GURL(), services.Pass(), service_provider.Pass(), base::Closure()); + EXPECT_FALSE(state_.runner_was_created); + EXPECT_FALSE(state_.runner_was_started); + EXPECT_FALSE(state_.runner_was_destroyed); +} + +} // namespace +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/out_of_process_native_runner.cc b/mojo/runner/out_of_process_native_runner.cc new file mode 100644 index 0000000..608765e2 --- /dev/null +++ b/mojo/runner/out_of_process_native_runner.cc
@@ -0,0 +1,72 @@ +// 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 "mojo/runner/out_of_process_native_runner.h" + +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "mojo/runner/child_process.mojom.h" +#include "mojo/runner/child_process_host.h" +#include "mojo/runner/in_process_native_runner.h" + +namespace mojo { +namespace shell { + +OutOfProcessNativeRunner::OutOfProcessNativeRunner(Context* context) + : context_(context) { +} + +OutOfProcessNativeRunner::~OutOfProcessNativeRunner() { + if (child_process_host_) { + // TODO(vtl): Race condition: If |ChildProcessHost::DidStart()| hasn't been + // called yet, we shouldn't call |Join()| here. (Until |DidStart()|, we may + // not have a child process to wait on.) Probably we should fix |Join()|. + child_process_host_->Join(); + } +} + +void OutOfProcessNativeRunner::Start( + const base::FilePath& app_path, + NativeApplicationCleanup cleanup, + InterfaceRequest<Application> application_request, + const base::Closure& app_completed_callback) { + app_path_ = app_path; + + DCHECK(app_completed_callback_.is_null()); + app_completed_callback_ = app_completed_callback; + + std::string name = app_path.BaseName().RemoveExtension().MaybeAsASCII(); + child_process_host_.reset(new ChildProcessHost(context_, name)); + child_process_host_->Start(); + + // TODO(vtl): |app_path.AsUTF8Unsafe()| is unsafe. + child_process_host_->StartApp( + app_path.AsUTF8Unsafe(), cleanup == NativeApplicationCleanup::DELETE, + application_request.Pass(), + base::Bind(&OutOfProcessNativeRunner::AppCompleted, + base::Unretained(this))); +} + +void OutOfProcessNativeRunner::AppCompleted(int32_t result) { + DVLOG(2) << "OutOfProcessNativeRunner::AppCompleted(" << result << ")"; + + child_process_host_.reset(); + // This object may be deleted by this callback. + base::Closure app_completed_callback = app_completed_callback_; + app_completed_callback_.Reset(); + app_completed_callback.Run(); +} + +scoped_ptr<NativeRunner> OutOfProcessNativeRunnerFactory::Create( + const Options& options) { + if (options.force_in_process) + return make_scoped_ptr(new InProcessNativeRunner(context_)); + + return make_scoped_ptr(new OutOfProcessNativeRunner(context_)); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/out_of_process_native_runner.h b/mojo/runner/out_of_process_native_runner.h new file mode 100644 index 0000000..323e872 --- /dev/null +++ b/mojo/runner/out_of_process_native_runner.h
@@ -0,0 +1,65 @@ +// 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 MOJO_RUNNER_OUT_OF_PROCESS_NATIVE_RUNNER_H_ +#define MOJO_RUNNER_OUT_OF_PROCESS_NATIVE_RUNNER_H_ + +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "mojo/public/cpp/bindings/error_handler.h" +#include "mojo/shell/native_runner.h" + +namespace mojo { +namespace shell { + +class ChildProcessHost; +class Context; + +// An implementation of |NativeRunner| that loads/runs the given app (from the +// file system) in a separate process (of its own). +class OutOfProcessNativeRunner : public NativeRunner { + public: + explicit OutOfProcessNativeRunner(Context* context); + ~OutOfProcessNativeRunner() override; + + // |NativeRunner| method: + void Start(const base::FilePath& app_path, + NativeApplicationCleanup cleanup, + InterfaceRequest<Application> application_request, + const base::Closure& app_completed_callback) override; + + private: + // |ChildController::StartApp()| callback: + void AppCompleted(int32_t result); + + Context* const context_; + + base::FilePath app_path_; + base::Closure app_completed_callback_; + + scoped_ptr<ChildProcessHost> child_process_host_; + + DISALLOW_COPY_AND_ASSIGN(OutOfProcessNativeRunner); +}; + +class OutOfProcessNativeRunnerFactory : public NativeRunnerFactory { + public: + explicit OutOfProcessNativeRunnerFactory(Context* context) + : context_(context) {} + ~OutOfProcessNativeRunnerFactory() override {} + + scoped_ptr<NativeRunner> Create(const Options& options) override; + + private: + Context* const context_; + + DISALLOW_COPY_AND_ASSIGN(OutOfProcessNativeRunnerFactory); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_OUT_OF_PROCESS_NATIVE_RUNNER_H_
diff --git a/mojo/runner/shell_apptest.cc b/mojo/runner/shell_apptest.cc new file mode 100644 index 0000000..35ad11d --- /dev/null +++ b/mojo/runner/shell_apptest.cc
@@ -0,0 +1,197 @@ +// 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/base_paths.h" +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/path_service.h" +#include "base/run_loop.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "mojo/application/application_test_base_chromium.h" +#include "mojo/common/data_pipe_utils.h" +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/system/macros.h" +#include "mojo/runner/kPingable.h" +#include "mojo/runner/test/pingable.mojom.h" +#include "mojo/services/http_server/public/cpp/http_server_util.h" +#include "mojo/services/http_server/public/interfaces/http_server.mojom.h" +#include "mojo/services/http_server/public/interfaces/http_server_factory.mojom.h" +#include "mojo/services/network/public/interfaces/net_address.mojom.h" + +namespace mojo { +namespace { + +std::string GetURL(uint16_t port, const std::string& path) { + return base::StringPrintf("http://127.0.0.1:%u/%s", + static_cast<unsigned>(port), path.c_str()); +} + +class GetHandler : public http_server::HttpHandler { + public: + GetHandler(InterfaceRequest<http_server::HttpHandler> request, uint16_t port) + : binding_(this, request.Pass()), port_(port) { + } + ~GetHandler() override {} + + private: + // http_server::HttpHandler: + void HandleRequest( + http_server::HttpRequestPtr request, + const Callback<void(http_server::HttpResponsePtr)>& callback) override { + http_server::HttpResponsePtr response; + if (StartsWithASCII(request->relative_url, "/app", true)) { + response = http_server::CreateHttpResponse( + 200, std::string(kPingable.data, kPingable.size)); + response->content_type = "application/octet-stream"; + } else if (request->relative_url == "/redirect") { + response = http_server::HttpResponse::New(); + response->status_code = 302; + response->custom_headers.insert("Location", GetURL(port_, "app")); + } else { + NOTREACHED(); + } + + callback.Run(response.Pass()); + } + + Binding<http_server::HttpHandler> binding_; + uint16_t port_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(GetHandler); +}; + +typedef test::ApplicationTestBase ShellAppTest; + +class ShellHTTPAppTest : public test::ApplicationTestBase { + public: + ShellHTTPAppTest() : ApplicationTestBase() {} + ~ShellHTTPAppTest() override {} + + protected: + // ApplicationTestBase: + void SetUp() override { + ApplicationTestBase::SetUp(); + + application_impl()->ConnectToService("mojo:http_server", + &http_server_factory_); + + NetAddressPtr local_address(NetAddress::New()); + local_address->family = NET_ADDRESS_FAMILY_IPV4; + local_address->ipv4 = NetAddressIPv4::New(); + local_address->ipv4->addr.resize(4); + local_address->ipv4->addr[0] = 127; + local_address->ipv4->addr[1] = 0; + local_address->ipv4->addr[2] = 0; + local_address->ipv4->addr[3] = 1; + local_address->ipv4->port = 0; + http_server_factory_->CreateHttpServer(GetProxy(&http_server_), + local_address.Pass()); + + http_server_->GetPort([this](uint16_t p) { port_ = p; }); + EXPECT_TRUE(http_server_.WaitForIncomingMethodCall()); + + InterfacePtr<http_server::HttpHandler> http_handler; + handler_.reset(new GetHandler(GetProxy(&http_handler).Pass(), port_)); + http_server_->SetHandler(".*", http_handler.Pass(), + [](bool result) { EXPECT_TRUE(result); }); + EXPECT_TRUE(http_server_.WaitForIncomingMethodCall()); + } + + std::string GetURL(const std::string& path) { + return ::mojo::GetURL(port_, path); + } + + http_server::HttpServerFactoryPtr http_server_factory_; + http_server::HttpServerPtr http_server_; + scoped_ptr<GetHandler> handler_; + uint16_t port_; + + private: + MOJO_DISALLOW_COPY_AND_ASSIGN(ShellHTTPAppTest); +}; + +// Test that we can load apps over http. +TEST_F(ShellHTTPAppTest, Http) { + InterfacePtr<Pingable> pingable; + application_impl()->ConnectToService(GetURL("app"), &pingable); + pingable->Ping("hello", + [this](const String& app_url, const String& connection_url, + const String& message) { + EXPECT_EQ(GetURL("app"), app_url); + EXPECT_EQ(GetURL("app"), connection_url); + EXPECT_EQ("hello", message); + base::MessageLoop::current()->Quit(); + }); + base::RunLoop().Run(); +} + +// Test that redirects work. +// TODO(aa): Test that apps receive the correct URL parameters. +TEST_F(ShellHTTPAppTest, Redirect) { + InterfacePtr<Pingable> pingable; + application_impl()->ConnectToService(GetURL("redirect"), &pingable); + pingable->Ping("hello", + [this](const String& app_url, const String& connection_url, + const String& message) { + EXPECT_EQ(GetURL("app"), app_url); + EXPECT_EQ(GetURL("app"), connection_url); + EXPECT_EQ("hello", message); + base::MessageLoop::current()->Quit(); + }); + base::RunLoop().Run(); +} + +// Test that querystring is not considered when resolving http applications. +// TODO(aa|qsr): Fix this test on Linux ASAN http://crbug.com/463662 +#if defined(ADDRESS_SANITIZER) +#define MAYBE_QueryHandling DISABLED_QueryHandling +#else +#define MAYBE_QueryHandling QueryHandling +#endif // ADDRESS_SANITIZER +TEST_F(ShellHTTPAppTest, MAYBE_QueryHandling) { + InterfacePtr<Pingable> pingable1; + InterfacePtr<Pingable> pingable2; + application_impl()->ConnectToService(GetURL("app?foo"), &pingable1); + application_impl()->ConnectToService(GetURL("app?bar"), &pingable2); + + int num_responses = 0; + auto callback = [this, &num_responses](const String& app_url, + const String& connection_url, + const String& message) { + EXPECT_EQ(GetURL("app"), app_url); + EXPECT_EQ("hello", message); + ++num_responses; + if (num_responses == 1) { + EXPECT_EQ(GetURL("app?foo"), connection_url); + } else if (num_responses == 2) { + EXPECT_EQ(GetURL("app?bar"), connection_url); + base::MessageLoop::current()->Quit(); + } else { + CHECK(false); + } + }; + pingable1->Ping("hello", callback); + pingable2->Ping("hello", callback); + base::RunLoop().Run(); +} + +// mojo: URLs can have querystrings too +TEST_F(ShellAppTest, MojoURLQueryHandling) { + InterfacePtr<Pingable> pingable; + application_impl()->ConnectToService("mojo:pingable_app?foo", &pingable); + auto callback = [this](const String& app_url, const String& connection_url, + const String& message) { + EXPECT_TRUE(EndsWith(app_url, "/pingable_app.mojo", true)); + EXPECT_EQ(app_url.To<std::string>() + "?foo", connection_url); + EXPECT_EQ("hello", message); + base::MessageLoop::current()->Quit(); + }; + pingable->Ping("hello", callback); + base::RunLoop().Run(); +} + +} // namespace +} // namespace mojo
diff --git a/mojo/runner/shell_test_base.cc b/mojo/runner/shell_test_base.cc new file mode 100644 index 0000000..5f56ae75 --- /dev/null +++ b/mojo/runner/shell_test_base.cc
@@ -0,0 +1,73 @@ +// 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 "mojo/runner/shell_test_base.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "build/build_config.h" +#include "mojo/runner/filename_util.h" +#include "url/gurl.h" + +namespace mojo { +namespace shell { +namespace test { + +namespace { + +void QuitIfRunning() { + if (base::MessageLoop::current() && + base::MessageLoop::current()->is_running()) { + base::MessageLoop::current()->QuitWhenIdle(); + } +} + +} // namespace + +ShellTestBase::ShellTestBase() { +} + +ShellTestBase::~ShellTestBase() { +} + +void ShellTestBase::SetUp() { + CHECK(shell_context_.Init()); + SetUpTestApplications(); +} + +void ShellTestBase::TearDown() { + shell_context_.Shutdown(); +} + +ScopedMessagePipeHandle ShellTestBase::ConnectToService( + const GURL& application_url, + const std::string& service_name) { + ServiceProviderPtr services; + shell_context_.application_manager()->ConnectToApplication( + application_url, GURL(), GetProxy(&services), nullptr, + base::Bind(&QuitIfRunning)); + MessagePipe pipe; + services->ConnectToService(service_name, pipe.handle1.Pass()); + return pipe.handle0.Pass(); +} + +#if !defined(OS_ANDROID) +void ShellTestBase::SetUpTestApplications() { + // Set the URLResolver origin to be the same as the base file path for + // local files. This is primarily for test convenience, so that references + // to unknown mojo: urls that do not have specific local file or custom + // mappings registered on the URL resolver are treated as shared libraries. + base::FilePath service_dir; + CHECK(PathService::Get(base::DIR_MODULE, &service_dir)); + shell_context_.url_resolver()->SetMojoBaseURL(FilePathToFileURL(service_dir)); +} +#endif + +} // namespace test +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/shell_test_base.h b/mojo/runner/shell_test_base.h new file mode 100644 index 0000000..110a58e --- /dev/null +++ b/mojo/runner/shell_test_base.h
@@ -0,0 +1,59 @@ +// 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 MOJO_RUNNER_SHELL_TEST_BASE_H_ +#define MOJO_RUNNER_SHELL_TEST_BASE_H_ + +#include <string> + +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "mojo/public/cpp/system/core.h" +#include "mojo/runner/context.h" +#include "testing/gtest/include/gtest/gtest.h" + +class GURL; + +namespace mojo { +namespace shell { +namespace test { + +class ShellTestBase : public testing::Test { + public: + ShellTestBase(); + ~ShellTestBase() override; + + void SetUp() override; + void TearDown() override; + + // |application_url| should typically be a mojo: URL (the origin will be set + // to an "appropriate" file: URL). + // TODO(tim): Should the test base be a ServiceProvider? + ScopedMessagePipeHandle ConnectToService(const GURL& application_url, + const std::string& service_name); + + template <typename Interface> + void ConnectToService(const GURL& application_url, + InterfacePtr<Interface>* ptr) { + ptr->Bind(ConnectToService(application_url, Interface::Name_).Pass()); + } + + base::MessageLoop* message_loop() { return &message_loop_; } + Context* shell_context() { return &shell_context_; } + + private: + // Set up the test applications so that mojo: URL resolves to those. + void SetUpTestApplications(); + + Context shell_context_; + base::MessageLoop message_loop_; + + DISALLOW_COPY_AND_ASSIGN(ShellTestBase); +}; + +} // namespace test +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_SHELL_TEST_BASE_H_
diff --git a/mojo/runner/shell_test_base_android.cc b/mojo/runner/shell_test_base_android.cc new file mode 100644 index 0000000..3f6d58d --- /dev/null +++ b/mojo/runner/shell_test_base_android.cc
@@ -0,0 +1,47 @@ +// 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 "mojo/runner/shell_test_base.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_string.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "jni/ShellTestBase_jni.h" +#include "mojo/runner/filename_util.h" +#include "url/gurl.h" + +namespace mojo { +namespace shell { +namespace test { + +namespace { + +JNIEnv* InitEnv() { + JNIEnv* env = base::android::AttachCurrentThread(); + static bool initialized = false; + if (!initialized) { + RegisterNativesImpl(env); + initialized = true; + } + return env; +} + +} // namespace + +void ShellTestBase::SetUpTestApplications() { + // Extract mojo applications, and set the resolve base URL to the directory + // containing those. + JNIEnv* env = InitEnv(); + base::android::ScopedJavaLocalRef<jstring> service_dir( + Java_ShellTestBase_extractMojoApplications( + env, base::android::GetApplicationContext())); + shell_context_.url_resolver()->SetMojoBaseURL( + FilePathToFileURL(base::FilePath( + base::android::ConvertJavaStringToUTF8(env, service_dir.obj())))); +} + +} // namespace test +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/shell_test_base_unittest.cc b/mojo/runner/shell_test_base_unittest.cc new file mode 100644 index 0000000..d7ae8c7 --- /dev/null +++ b/mojo/runner/shell_test_base_unittest.cc
@@ -0,0 +1,309 @@ +// 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 "mojo/runner/shell_test_base.h" + +#include "base/bind.h" +#include "base/i18n/time_formatting.h" +#include "base/macros.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/utf_string_conversions.h" +#include "mojo/public/cpp/bindings/error_handler.h" +#include "mojo/public/cpp/bindings/interface_ptr.h" +#include "mojo/public/cpp/system/core.h" +#include "mojo/services/test_service/test_request_tracker.mojom.h" +#include "mojo/services/test_service/test_service.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +using mojo::test::ServiceReport; +using mojo::test::ServiceReportPtr; +using mojo::test::TestService; +using mojo::test::TestTimeService; +using mojo::test::TestServicePtr; +using mojo::test::TestTimeServicePtr; +using mojo::test::TestTrackedRequestService; +using mojo::test::TestTrackedRequestServicePtr; + +namespace mojo { +namespace shell { +namespace test { +namespace { + +void GetReportCallback(base::MessageLoop* loop, + std::vector<ServiceReport>* reports_out, + Array<ServiceReportPtr> report) { + for (size_t i = 0; i < report.size(); i++) + reports_out->push_back(*report[i]); + loop->QuitWhenIdle(); +} + +class ShellTestBaseTest : public ShellTestBase { + public: + // Convenience helpers for use as callbacks in tests. + template <typename T> + base::Callback<void()> SetAndQuit(T* val, T result) { + return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>, + base::Unretained(this), val, result); + } + template <typename T> + base::Callback<void(T result)> SetAndQuit(T* val) { + return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>, + base::Unretained(this), val); + } + static GURL test_app_url() { return GURL("mojo:test_app"); } + + void GetReport(std::vector<ServiceReport>* report) { + ConnectToService(GURL("mojo:test_request_tracker_app"), &request_tracking_); + request_tracking_->GetReport(base::Bind(&GetReportCallback, + base::Unretained(message_loop()), + base::Unretained(report))); + message_loop()->Run(); + } + + private: + template <typename T> + void SetAndQuitImpl(T* val, T result) { + *val = result; + message_loop()->QuitWhenIdle(); + } + TestTrackedRequestServicePtr request_tracking_; +}; + +class QuitMessageLoopErrorHandler : public ErrorHandler { + public: + QuitMessageLoopErrorHandler() {} + ~QuitMessageLoopErrorHandler() override {} + + // |ErrorHandler| implementation: + void OnConnectionError() override { + base::MessageLoop::current()->QuitWhenIdle(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler); +}; + +// Tests that we can connect to a single service within a single app. +TEST_F(ShellTestBaseTest, ConnectBasic) { + InterfacePtr<TestService> service; + ConnectToService(test_app_url(), &service); + + bool was_run = false; + service->Ping(SetAndQuit<bool>(&was_run, true)); + message_loop()->Run(); + EXPECT_TRUE(was_run); + EXPECT_FALSE(service.encountered_error()); + + service.reset(); + + // This will run until the test app has actually quit (which it will, + // since we killed the only connection to it). + message_loop()->Run(); +} + +// Tests that trying to connect to a service fails properly if the service +// doesn't exist. Implicit in this test is verification that the shell +// terminates if no services are running. +TEST_F(ShellTestBaseTest, ConnectInvalidService) { + InterfacePtr<TestService> test_service; + ConnectToService(GURL("mojo:non_existent_service"), &test_service); + + bool was_run = false; + test_service->Ping(SetAndQuit<bool>(&was_run, true)); + + // This will quit because there's nothing running. + message_loop()->Run(); + EXPECT_FALSE(was_run); + + // It may have quit before an error was processed. + if (!test_service.encountered_error()) { + QuitMessageLoopErrorHandler quitter; + test_service.set_error_handler(&quitter); + message_loop()->Run(); + EXPECT_TRUE(test_service.encountered_error()); + } + + test_service.reset(); +} + +// Tests that we can connect to a single service within a single app using +// a network based loader instead of local files. +// TODO(tim): Disabled because network service leaks NSS at exit, meaning +// subsequent tests can't init properly. +TEST_F(ShellTestBaseTest, DISABLED_ConnectBasicNetwork) { + InterfacePtr<TestService> service; + ConnectToService(test_app_url(), &service); + + bool was_run = false; + service->Ping(SetAndQuit<bool>(&was_run, true)); + message_loop()->Run(); + EXPECT_TRUE(was_run); + EXPECT_FALSE(service.encountered_error()); + + // Note that use of the network service is implicit in this test. + // Since TestService is not the only service in use, the shell won't auto + // magically exit when TestService is destroyed (unlike ConnectBasic). + // Tearing down the shell context will kill connections. The shell loop will + // exit as soon as no more apps are connected. + // TODO(tim): crbug.com/392685. Calling this explicitly shouldn't be + // necessary once the shell terminates if the primordial app exits, which + // we could enforce here by resetting |service|. + shell_context()->application_manager()->TerminateShellConnections(); + message_loop()->Run(); // Waits for all connections to die. +} + +// Tests that trying to connect to a service over network fails preoprly +// if the service doesn't exist. +// TODO(tim): Disabled because network service leaks NSS at exit, meaning +// subsequent tests can't init properly. +TEST_F(ShellTestBaseTest, DISABLED_ConnectInvalidServiceNetwork) { + InterfacePtr<TestService> test_service; + ConnectToService(GURL("http://example.com/non_existent_service"), + &test_service); + QuitMessageLoopErrorHandler quitter; + test_service.set_error_handler(&quitter); + bool was_run = false; + test_service->Ping(SetAndQuit<bool>(&was_run, true)); + message_loop()->Run(); + EXPECT_TRUE(test_service.encountered_error()); + + // TODO(tim): crbug.com/392685. Calling this explicitly shouldn't be + // necessary once the shell terminates if the primordial app exits, which + // we could enforce here by resetting |service|. + shell_context()->application_manager()->TerminateShellConnections(); + message_loop()->Run(); // Waits for all connections to die. +} + +// Similar to ConnectBasic, but causes the app to instantiate multiple +// service implementation objects and verifies the shell can reach both. +TEST_F(ShellTestBaseTest, ConnectMultipleInstancesPerApp) { + { + TestServicePtr service1, service2; + ConnectToService(test_app_url(), &service1); + ConnectToService(test_app_url(), &service2); + + bool was_run1 = false; + bool was_run2 = false; + service1->Ping(SetAndQuit<bool>(&was_run1, true)); + message_loop()->Run(); + service2->Ping(SetAndQuit<bool>(&was_run2, true)); + message_loop()->Run(); + EXPECT_TRUE(was_run1); + EXPECT_TRUE(was_run2); + EXPECT_FALSE(service1.encountered_error()); + EXPECT_FALSE(service2.encountered_error()); + } + message_loop()->Run(); +} + +// Tests that service A and service B, both in App 1, can talk to each other +// and parameters are passed around properly. +TEST_F(ShellTestBaseTest, ConnectDifferentServicesInSingleApp) { + // Have a TestService GetPartyTime on a TestTimeService in the same app. + int64 time_message; + TestServicePtr service; + ConnectToService(test_app_url(), &service); + service->ConnectToAppAndGetTime(test_app_url().spec(), + SetAndQuit<int64>(&time_message)); + message_loop()->Run(); + + // Verify by hitting the TimeService directly. + TestTimeServicePtr time_service; + ConnectToService(test_app_url(), &time_service); + int64 party_time; + time_service->GetPartyTime(SetAndQuit<int64>(&party_time)); + message_loop()->Run(); + + EXPECT_EQ(time_message, party_time); +} + +// Tests that a service A in App 1 can talk to service B in App 2 and +// parameters are passed around properly. +TEST_F(ShellTestBaseTest, ConnectDifferentServicesInDifferentApps) { + int64 time_message; + TestServicePtr service; + ConnectToService(test_app_url(), &service); + service->ConnectToAppAndGetTime("mojo:test_request_tracker_app", + SetAndQuit<int64>(&time_message)); + message_loop()->Run(); + + // Verify by hitting the TimeService in the request tracker app directly. + TestTimeServicePtr time_service; + ConnectToService(GURL("mojo:test_request_tracker_app"), &time_service); + int64 party_time; + time_service->GetPartyTime(SetAndQuit<int64>(&party_time)); + message_loop()->Run(); + + EXPECT_EQ(time_message, party_time); +} + +// Tests that service A in App 1 can be a client of service B in App 2. +TEST_F(ShellTestBaseTest, ConnectServiceAsClientOfSeparateApp) { + TestServicePtr service; + ConnectToService(test_app_url(), &service); + service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure()); + service->Ping(Callback<void()>()); + message_loop()->Run(); + + for (int i = 0; i < 8; i++) + service->Ping(Callback<void()>()); + service->Ping(message_loop()->QuitWhenIdleClosure()); + message_loop()->Run(); + + // If everything worked properly, the tracking service should report + // 10 pings to TestService. + std::vector<ServiceReport> reports; + GetReport(&reports); + ASSERT_EQ(1U, reports.size()); + EXPECT_EQ(TestService::Name_, reports[0].service_name); + EXPECT_EQ(10U, reports[0].total_requests); +} + +// Connect several services together and use the tracking service to verify +// communication. +TEST_F(ShellTestBaseTest, ConnectManyClientsAndServices) { + TestServicePtr service; + TestTimeServicePtr time_service; + + // Make a request to the TestService and have it contact TimeService in the + // tracking app. Do all this with tracking enabled, meaning both services + // are connected as clients of the TrackedRequestService. + ConnectToService(test_app_url(), &service); + service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure()); + message_loop()->Run(); + for (int i = 0; i < 5; i++) + service->Ping(Callback<void()>()); + int64 time_result; + service->ConnectToAppAndGetTime("mojo:test_request_tracker_app", + SetAndQuit<int64>(&time_result)); + message_loop()->Run(); + + // Also make a few requests to the TimeService in the test_app. + ConnectToService(test_app_url(), &time_service); + time_service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure()); + time_service->GetPartyTime(Callback<void(uint64_t)>()); + message_loop()->Run(); + for (int i = 0; i < 18; i++) + time_service->GetPartyTime(Callback<void(uint64_t)>()); + // Flush the tasks with one more to quit. + int64 party_time = 0; + time_service->GetPartyTime(SetAndQuit<int64>(&party_time)); + message_loop()->Run(); + + std::vector<ServiceReport> reports; + GetReport(&reports); + ASSERT_EQ(3U, reports.size()); + EXPECT_EQ(TestService::Name_, reports[0].service_name); + EXPECT_EQ(6U, reports[0].total_requests); + EXPECT_EQ(TestTimeService::Name_, reports[1].service_name); + EXPECT_EQ(1U, reports[1].total_requests); + EXPECT_EQ(TestTimeService::Name_, reports[2].service_name); + EXPECT_EQ(20U, reports[2].total_requests); +} + +} // namespace +} // namespace test +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/shell_test_main.cc b/mojo/runner/shell_test_main.cc new file mode 100644 index 0000000..2718a2d2 --- /dev/null +++ b/mojo/runner/shell_test_main.cc
@@ -0,0 +1,30 @@ +// 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 "base/at_exit.h" +#include "base/bind.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "base/test/launcher/unit_test_launcher.h" +#include "base/test/test_suite.h" +#include "mojo/runner/child_process.h" +#include "mojo/runner/switches.h" +#include "testing/gtest/include/gtest/gtest.h" + +int main(int argc, char** argv) { + base::CommandLine::Init(argc, argv); + const base::CommandLine& command_line = + *base::CommandLine::ForCurrentProcess(); + + if (command_line.HasSwitch(switches::kChildProcess)) { + base::AtExitManager at_exit; + + return mojo::shell::ChildProcessMain(); + } + + base::TestSuite test_suite(argc, argv); + return base::LaunchUnitTests( + argc, argv, + base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); +}
diff --git a/mojo/runner/switches.cc b/mojo/runner/switches.cc new file mode 100644 index 0000000..5042009 --- /dev/null +++ b/mojo/runner/switches.cc
@@ -0,0 +1,58 @@ +// Copyright 2013 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/runner/switches.h" + +#include "base/basictypes.h" + +namespace switches { + +// Used just for debugging to make it easier to attach debuggers. The actual app +// path that is used is sent over IPC. +const char kApp[] = "app"; + +// Used internally by the main process to indicate that a new process should be +// a child process. Not for user use. +const char kChildProcess[] = "child-process"; + +// Comma separated list like: +// text/html,mojo:html_viewer,application/bravo,https://abarth.com/bravo +const char kContentHandlers[] = "content-handlers"; + +// Force dynamically loaded apps / services to be loaded irrespective of cache +// instructions. +const char kDisableCache[] = "disable-cache"; + +// Load apps in separate processes. +// TODO(vtl): Work in progress; doesn't work. Flip this to "disable" (or maybe +// change it to "single-process") when it works. +const char kEnableMultiprocess[] = "enable-multiprocess"; + +// In multiprocess mode, force these apps to be loaded in the main process. +// Comma-separate list of URLs. Example: +// --force-in-process=mojo:native_viewport_service,mojo:network_service +const char kForceInProcess[] = "force-in-process"; + +// Print the usage message and exit. +const char kHelp[] = "help"; + +// Specify origin to map to base url. See url_resolver.cc for details. +// Can be used multiple times. +const char kMapOrigin[] = "map-origin"; + +// Map mojo: URLs to a shared library of similar name at this origin. See +// url_resolver.cc for details. +const char kOrigin[] = "origin"; + +// Starts tracing when the shell starts up, saving a trace file on disk after 5 +// seconds or when the shell exits. +const char kTraceStartup[] = "trace-startup"; + +// Specifies a set of mappings to apply when resolving urls. The value is a set +// of ',' separated mappings, where each mapping consists of a pair of urls +// giving the to/from url to map. For example, 'a=b,c=d' contains two mappings, +// the first maps 'a' to 'b' and the second 'c' to 'd'. +const char kURLMappings[] = "url-mappings"; + +} // namespace switches
diff --git a/mojo/runner/switches.h b/mojo/runner/switches.h new file mode 100644 index 0000000..fd7f065 --- /dev/null +++ b/mojo/runner/switches.h
@@ -0,0 +1,29 @@ +// Copyright 2013 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_RUNNER_SWITCHES_H_ +#define MOJO_RUNNER_SWITCHES_H_ + +#include <set> +#include <string> + +namespace switches { + +// All switches in alphabetical order. The switches should be documented +// alongside the definition of their values in the .cc file. +extern const char kApp[]; +extern const char kChildProcess[]; +extern const char kContentHandlers[]; +extern const char kDisableCache[]; +extern const char kEnableMultiprocess[]; +extern const char kForceInProcess[]; +extern const char kHelp[]; +extern const char kMapOrigin[]; +extern const char kOrigin[]; +extern const char kTraceStartup[]; +extern const char kURLMappings[]; + +} // namespace switches + +#endif // MOJO_RUNNER_SWITCHES_H_
diff --git a/mojo/runner/task_runners.cc b/mojo/runner/task_runners.cc new file mode 100644 index 0000000..e4a49d6 --- /dev/null +++ b/mojo/runner/task_runners.cc
@@ -0,0 +1,39 @@ +// Copyright 2013 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/runner/task_runners.h" + +#include "base/threading/sequenced_worker_pool.h" + +namespace mojo { +namespace shell { + +namespace { + +const size_t kMaxBlockingPoolThreads = 3; + +scoped_ptr<base::Thread> CreateIOThread(const char* name) { + scoped_ptr<base::Thread> thread(new base::Thread(name)); + base::Thread::Options options; + options.message_loop_type = base::MessageLoop::TYPE_IO; + thread->StartWithOptions(options); + return thread.Pass(); +} + +} // namespace + +TaskRunners::TaskRunners( + const scoped_refptr<base::SingleThreadTaskRunner>& shell_runner) + : shell_runner_(shell_runner), + io_thread_(CreateIOThread("io_thread")), + blocking_pool_(new base::SequencedWorkerPool(kMaxBlockingPoolThreads, + "blocking_pool")) { +} + +TaskRunners::~TaskRunners() { + blocking_pool_->Shutdown(); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/task_runners.h b/mojo/runner/task_runners.h new file mode 100644 index 0000000..e09678cd --- /dev/null +++ b/mojo/runner/task_runners.h
@@ -0,0 +1,53 @@ +// Copyright 2013 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_RUNNER_TASK_RUNNERS_H_ +#define MOJO_RUNNER_TASK_RUNNERS_H_ + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/threading/thread.h" + +namespace base { +class SequencedWorkerPool; +} + +namespace mojo { +namespace shell { + +// A context object that contains the common task runners for the shell's main +// process. +class TaskRunners { + public: + explicit TaskRunners( + const scoped_refptr<base::SingleThreadTaskRunner>& shell_runner); + ~TaskRunners(); + + base::SingleThreadTaskRunner* shell_runner() const { + return shell_runner_.get(); + } + + base::SingleThreadTaskRunner* io_runner() const { + return io_thread_->message_loop_proxy().get(); + } + + base::SequencedWorkerPool* blocking_pool() const { + return blocking_pool_.get(); + } + + private: + scoped_refptr<base::SingleThreadTaskRunner> shell_runner_; + scoped_ptr<base::Thread> io_thread_; + + scoped_refptr<base::SequencedWorkerPool> blocking_pool_; + + DISALLOW_COPY_AND_ASSIGN(TaskRunners); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_TASK_RUNNERS_H_
diff --git a/mojo/shell/test/BUILD.gn b/mojo/runner/test/BUILD.gn similarity index 100% rename from mojo/shell/test/BUILD.gn rename to mojo/runner/test/BUILD.gn
diff --git a/mojo/shell/test/pingable.mojom b/mojo/runner/test/pingable.mojom similarity index 100% rename from mojo/shell/test/pingable.mojom rename to mojo/runner/test/pingable.mojom
diff --git a/mojo/runner/test/pingable_app.cc b/mojo/runner/test/pingable_app.cc new file mode 100644 index 0000000..f62dd2e3 --- /dev/null +++ b/mojo/runner/test/pingable_app.cc
@@ -0,0 +1,69 @@ +// 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/c/system/main.h" +#include "mojo/public/cpp/application/application_delegate.h" +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/application_runner.h" +#include "mojo/public/cpp/application/interface_factory.h" +#include "mojo/public/cpp/bindings/callback.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "mojo/runner/test/pingable.mojom.h" + +namespace mojo { + +class PingableImpl : public Pingable { + public: + PingableImpl(InterfaceRequest<Pingable> request, + const std::string& app_url, + const std::string& connection_url) + : binding_(this, request.Pass()), + app_url_(app_url), + connection_url_(connection_url) {} + + ~PingableImpl() override {} + + private: + void Ping(const String& message, + const Callback<void(String, String, String)>& callback) override { + callback.Run(app_url_, connection_url_, message); + } + + StrongBinding<Pingable> binding_; + std::string app_url_; + std::string connection_url_; +}; + +class PingableApp : public mojo::ApplicationDelegate, + public mojo::InterfaceFactory<Pingable> { + public: + PingableApp() {} + ~PingableApp() override {} + + private: + // ApplicationDelegate: + void Initialize(ApplicationImpl* impl) override { app_url_ = impl->url(); } + + bool ConfigureIncomingConnection( + mojo::ApplicationConnection* connection) override { + connection->AddService(this); + return true; + } + + // InterfaceFactory<Pingable>: + void Create(mojo::ApplicationConnection* connection, + mojo::InterfaceRequest<Pingable> request) override { + new PingableImpl(request.Pass(), app_url_, connection->GetConnectionURL()); + } + + std::string app_url_; +}; + +} // namespace mojo + +MojoResult MojoMain(MojoHandle shell_handle) { + mojo::ApplicationRunner runner(new mojo::PingableApp); + return runner.Run(shell_handle); +}
diff --git a/mojo/runner/url_resolver.cc b/mojo/runner/url_resolver.cc new file mode 100644 index 0000000..fc07816e --- /dev/null +++ b/mojo/runner/url_resolver.cc
@@ -0,0 +1,118 @@ +// 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 "mojo/runner/url_resolver.h" + +#include "base/base_paths.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/strings/utf_string_conversions.h" +#include "mojo/runner/filename_util.h" +#include "mojo/runner/switches.h" +#include "mojo/shell/query_util.h" +#include "url/url_util.h" + +namespace mojo { +namespace shell { + +URLResolver::URLResolver() { + // Needed to treat first component of mojo URLs as host, not path. + url::AddStandardScheme("mojo"); +} + +URLResolver::~URLResolver() { +} + +// static +std::vector<URLResolver::OriginMapping> URLResolver::GetOriginMappings( + const base::CommandLine::StringVector& args) { + std::vector<OriginMapping> origin_mappings; + const std::string kArgsForSwitches[] = { + "-" + std::string(switches::kMapOrigin) + "=", + "--" + std::string(switches::kMapOrigin) + "=", + }; + for (auto& arg : args) { + for (size_t i = 0; i < arraysize(kArgsForSwitches); i++) { + const std::string& argsfor_switch = kArgsForSwitches[i]; + std::string arg_string; +#if defined(OS_WIN) + arg_string = base::UTF16ToUTF8(arg); +#else + arg_string = arg; +#endif + if (arg_string.compare(0, argsfor_switch.size(), argsfor_switch) == 0) { + std::string value = + arg_string.substr(argsfor_switch.size(), std::string::npos); + size_t delim = value.find('='); + if (delim <= 0 || delim >= value.size()) + continue; + origin_mappings.push_back( + OriginMapping(value.substr(0, delim), + value.substr(delim + 1, std::string::npos))); + } + } + } + return origin_mappings; +} + +void URLResolver::AddURLMapping(const GURL& url, const GURL& mapped_url) { + url_map_[url] = mapped_url; +} + +void URLResolver::AddOriginMapping(const GURL& origin, const GURL& base_url) { + if (!origin.is_valid() || !base_url.is_valid() || + origin != origin.GetOrigin()) { + // Disallow invalid mappings. + LOG(ERROR) << "Invalid origin for mapping: " << origin; + return; + } + // Force both origin and base_url to have trailing slashes. + origin_map_[origin] = AddTrailingSlashIfNeeded(base_url); +} + +GURL URLResolver::ApplyMappings(const GURL& url) const { + std::string query; + GURL mapped_url = GetBaseURLAndQuery(url, &query); + for (;;) { + const auto& url_it = url_map_.find(mapped_url); + if (url_it != url_map_.end()) { + mapped_url = url_it->second; + continue; + } + + GURL origin = mapped_url.GetOrigin(); + const auto& origin_it = origin_map_.find(origin); + if (origin_it == origin_map_.end()) + break; + mapped_url = GURL(origin_it->second.spec() + + mapped_url.spec().substr(origin.spec().length())); + } + + if (query.length()) + mapped_url = GURL(mapped_url.spec() + query); + return mapped_url; +} + +void URLResolver::SetMojoBaseURL(const GURL& mojo_base_url) { + DCHECK(mojo_base_url.is_valid()); + // Force a trailing slash on the base_url to simplify resolving + // relative files and URLs below. + mojo_base_url_ = AddTrailingSlashIfNeeded(mojo_base_url); +} + +GURL URLResolver::ResolveMojoURL(const GURL& mojo_url) const { + if (mojo_url.scheme() != "mojo") { + // The mapping has produced some sort of non-mojo: URL - file:, http:, etc. + return mojo_url; + } else { + // It's still a mojo: URL, use the default mapping scheme. + std::string query; + GURL base_url = GetBaseURLAndQuery(mojo_url, &query); + std::string lib = base_url.host() + ".mojo" + query; + return mojo_base_url_.Resolve(lib); + } +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/runner/url_resolver.h b/mojo/runner/url_resolver.h new file mode 100644 index 0000000..83398f7 --- /dev/null +++ b/mojo/runner/url_resolver.h
@@ -0,0 +1,79 @@ +// 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 MOJO_RUNNER_URL_RESOLVER_H_ +#define MOJO_RUNNER_URL_RESOLVER_H_ + +#include <map> +#include <set> + +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "url/gurl.h" + +namespace mojo { +namespace shell { + +// This class supports the mapping of URLs to other URLs. +// It's commonly used with mojo: URL, to provide a physical location (i.e. +// file: or https:) but works with any URL. +// By default, "mojo:" URLs resolve to a file location, with ".mojo" appended, +// but that resolution can be customized via the AddCustomMapping method. +class URLResolver { + public: + URLResolver(); + ~URLResolver(); + + // Used for the return value of GetOriginMappings(). + struct OriginMapping { + OriginMapping(const std::string& origin, const std::string& base_url) + : origin(origin), base_url(base_url) {} + + std::string origin; + std::string base_url; + }; + + // Returns a list of origin mappings based on command line args. + // The switch --map-origin can be specified multiple times. Each occurance + // has the format of --map-origin={origin}={base_url} + // For example: + // --map-origin=http://domokit.org=file:///source/out + static std::vector<OriginMapping> GetOriginMappings( + const base::CommandLine::StringVector& argv); + + // Add a custom mapping for a particular URL. If |mapped_url| is + // itself a mojo url normal resolution rules apply. + void AddURLMapping(const GURL& url, const GURL& mapped_url); + + // Add a custom mapping for all urls rooted at |origin|. + void AddOriginMapping(const GURL& origin, const GURL& base_url); + + // Applies all custom mappings for |url|, returning the last non-mapped url. + // For example, if 'a' maps to 'b' and 'b' maps to 'c' calling this with 'a' + // returns 'c'. + GURL ApplyMappings(const GURL& url) const; + + // If specified, then "mojo:" URLs will be resolved relative to this + // URL. That is, the portion after the colon will be appeneded to + // |mojo_base_url| with .mojo appended. + void SetMojoBaseURL(const GURL& mojo_base_url); + + // Resolve the given "mojo:" URL to the URL that should be used to fetch the + // code for the corresponding Mojo App. + GURL ResolveMojoURL(const GURL& mojo_url) const; + + private: + using GURLToGURLMap = std::map<GURL, GURL>; + GURLToGURLMap url_map_; + GURLToGURLMap origin_map_; + GURL mojo_base_url_; + + DISALLOW_COPY_AND_ASSIGN(URLResolver); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_RUNNER_URL_RESOLVER_H_
diff --git a/mojo/runner/url_resolver_unittest.cc b/mojo/runner/url_resolver_unittest.cc new file mode 100644 index 0000000..5862b51 --- /dev/null +++ b/mojo/runner/url_resolver_unittest.cc
@@ -0,0 +1,150 @@ +// 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 "mojo/runner/url_resolver.h" + +#include "base/logging.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { +namespace test { +namespace { + +typedef testing::Test URLResolverTest; + +TEST_F(URLResolverTest, MojoURLsFallThrough) { + URLResolver resolver; + resolver.AddURLMapping(GURL("mojo:test"), GURL("mojo:foo")); + const GURL base_url("file:/base"); + resolver.SetMojoBaseURL(base_url); + GURL mapped_url = resolver.ApplyMappings(GURL("mojo:test")); + std::string resolved(resolver.ResolveMojoURL(mapped_url).spec()); + // Resolved must start with |base_url|. + EXPECT_EQ(base_url.spec(), resolved.substr(0, base_url.spec().size())); + // And must contain foo. + EXPECT_NE(std::string::npos, resolved.find("foo")); +} + +TEST_F(URLResolverTest, MapURL) { + URLResolver resolver; + resolver.AddURLMapping(GURL("https://domokit.org/test.mojo"), + GURL("file:///mojo/src/out/Debug/test.mojo")); + GURL mapped_url = + resolver.ApplyMappings(GURL("https://domokit.org/test.mojo")); + EXPECT_EQ("file:///mojo/src/out/Debug/test.mojo", mapped_url.spec()); +} + +TEST_F(URLResolverTest, MultipleMapURL) { + URLResolver resolver; + resolver.AddURLMapping(GURL("https://a.org/foo"), + GURL("https://b.org/a/foo")); + resolver.AddURLMapping(GURL("https://b.org/a/foo"), + GURL("https://c.org/b/a/foo")); + GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo")); + EXPECT_EQ("https://c.org/b/a/foo", mapped_url.spec()); +} + +TEST_F(URLResolverTest, MapOrigin) { + URLResolver resolver; + resolver.AddOriginMapping(GURL("https://domokit.org"), + GURL("file:///mojo/src/out/Debug")); + GURL mapped_url = + resolver.ApplyMappings(GURL("https://domokit.org/test.mojo")); + EXPECT_EQ("file:///mojo/src/out/Debug/test.mojo", mapped_url.spec()); +} + +TEST_F(URLResolverTest, MultipleMapOrigin) { + URLResolver resolver; + resolver.AddOriginMapping(GURL("https://a.org"), GURL("https://b.org/a")); + resolver.AddOriginMapping(GURL("https://b.org"), GURL("https://c.org/b")); + GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo")); + EXPECT_EQ("https://c.org/b/a/foo", mapped_url.spec()); +} + +TEST_F(URLResolverTest, MapOriginThenURL) { + URLResolver resolver; + resolver.AddOriginMapping(GURL("https://a.org"), GURL("https://b.org/a")); + resolver.AddURLMapping(GURL("https://b.org/a/foo"), + GURL("https://c.org/b/a/foo")); + GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo")); + EXPECT_EQ("https://c.org/b/a/foo", mapped_url.spec()); +} + +TEST_F(URLResolverTest, MapURLThenOrigin) { + URLResolver resolver; + resolver.AddURLMapping(GURL("https://a.org/foo"), + GURL("https://b.org/a/foo")); + resolver.AddOriginMapping(GURL("https://b.org"), GURL("https://c.org/b")); + GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo")); + EXPECT_EQ("https://c.org/b/a/foo", mapped_url.spec()); +} + +#if defined(OS_POSIX) +#define ARG_LITERAL(x) x +#elif defined(OS_WIN) +#define ARG_LITERAL(x) L ## x +#endif + +TEST_F(URLResolverTest, GetOriginMappings) { + base::CommandLine::StringVector args; + args.push_back(ARG_LITERAL("--map-origin=https://a.org=https://b.org/a")); + std::vector<URLResolver::OriginMapping> mappings = + URLResolver::GetOriginMappings(args); + ASSERT_EQ(1U, mappings.size()); + EXPECT_EQ("https://a.org", mappings[0].origin); + EXPECT_EQ("https://b.org/a", mappings[0].base_url); + + args.clear(); + args.push_back(ARG_LITERAL("-map-origin=https://a.org=https://b.org/a")); + mappings = URLResolver::GetOriginMappings(args); + ASSERT_EQ(1U, mappings.size()); + EXPECT_EQ("https://a.org", mappings[0].origin); + EXPECT_EQ("https://b.org/a", mappings[0].base_url); + + args.clear(); + args.push_back(ARG_LITERAL("--map-origin")); + mappings = URLResolver::GetOriginMappings(args); + EXPECT_EQ(0U, mappings.size()); + + args.clear(); + args.push_back(ARG_LITERAL("--map-origin=")); + mappings = URLResolver::GetOriginMappings(args); + EXPECT_EQ(0U, mappings.size()); + + args.clear(); + args.push_back(ARG_LITERAL("mojo_shell")); + args.push_back(ARG_LITERAL("--map-origin=https://a.org=https://b.org/a")); + args.push_back(ARG_LITERAL("--map-origin=https://b.org=https://c.org/b")); + args.push_back(ARG_LITERAL("https://a.org/foo")); + mappings = URLResolver::GetOriginMappings(args); + ASSERT_EQ(2U, mappings.size()); + EXPECT_EQ("https://a.org", mappings[0].origin); + EXPECT_EQ("https://b.org/a", mappings[0].base_url); + EXPECT_EQ("https://b.org", mappings[1].origin); + EXPECT_EQ("https://c.org/b", mappings[1].base_url); +} + +TEST_F(URLResolverTest, TestQueryForURLMapping) { + URLResolver resolver; + resolver.SetMojoBaseURL(GURL("file:/base")); + resolver.AddURLMapping(GURL("https://a.org/foo"), + GURL("https://b.org/a/foo")); + resolver.AddURLMapping(GURL("https://b.org/a/foo"), + GURL("https://c.org/b/a/foo")); + GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo?a=b")); + EXPECT_EQ("https://c.org/b/a/foo?a=b", mapped_url.spec()); +} + +TEST_F(URLResolverTest, TestQueryForBaseURL) { + URLResolver resolver; + resolver.SetMojoBaseURL(GURL("file:///base")); + GURL mapped_url = resolver.ResolveMojoURL(GURL("mojo:foo?a=b")); + EXPECT_EQ("file:///base/foo.mojo?a=b", mapped_url.spec()); +} + +} // namespace +} // namespace test +} // namespace shell +} // namespace mojo
diff --git a/mojo/services/BUILD.gn b/mojo/services/BUILD.gn index 455e190..f52666ba 100644 --- a/mojo/services/BUILD.gn +++ b/mojo/services/BUILD.gn
@@ -7,19 +7,19 @@ group("services") { deps = [ "//mojo/services/network/public/interfaces", - "//third_party/mojo_services/src/clipboard/public/interfaces", + "//components/clipboard/public/interfaces", + "//components/native_viewport/public/interfaces", + "//components/surfaces/public/interfaces", + "//components/view_manager/public/interfaces", + "//mandoline/services/navigation/public/interfaces", "//third_party/mojo_services/src/content_handler/public/interfaces", - "//third_party/mojo_services/src/geometry/public/interfaces", - "//third_party/mojo_services/src/input_events/public/interfaces", - "//third_party/mojo_services/src/native_viewport/public/interfaces", - "//third_party/mojo_services/src/navigation/public/interfaces", - "//third_party/mojo_services/src/surfaces/public/interfaces", - "//third_party/mojo_services/src/view_manager/public/interfaces", + "//ui/mojo/events:interfaces", + "//ui/mojo/geometry:interfaces", ] if (!is_component_build) { deps += [ - "//components/clipboard", + "//components/core_services", "//components/html_viewer", "//components/kiosk_wm:window_manager", "//components/native_viewport", @@ -52,7 +52,6 @@ deps += [ "//components/html_viewer:tests", "//components/view_manager:view_manager_service_unittests", - "//components/window_manager:window_manager_unittests", ] # TODO(GYP): Make this work. @@ -60,7 +59,6 @@ deps -= [ "//components/html_viewer:tests", "//components/view_manager:view_manager_service_unittests", - "//components/window_manager:window_manager_unittests", ] } }
diff --git a/mojo/services/network/public/cpp/BUILD.gn b/mojo/services/network/public/cpp/BUILD.gn index a202fb8..9a557d8 100644 --- a/mojo/services/network/public/cpp/BUILD.gn +++ b/mojo/services/network/public/cpp/BUILD.gn
@@ -3,7 +3,7 @@ # found in the LICENSE file. import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/mojo_sdk.gni") +import("//third_party/mojo/src/mojo/public/mojo_sdk.gni") mojo_sdk_source_set("cpp") { restrict_external_deps = false
diff --git a/mojo/services/network/public/interfaces/BUILD.gn b/mojo/services/network/public/interfaces/BUILD.gn index f20b7313..b4c71910 100644 --- a/mojo/services/network/public/interfaces/BUILD.gn +++ b/mojo/services/network/public/interfaces/BUILD.gn
@@ -3,7 +3,7 @@ # found in the LICENSE file. import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") mojom("interfaces") { sources = [
diff --git a/mojo/shell/BUILD.gn b/mojo/shell/BUILD.gn index 3c06107..5a13e6b3 100644 --- a/mojo/shell/BUILD.gn +++ b/mojo/shell/BUILD.gn
@@ -2,333 +2,49 @@ # 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") -import("//third_party/mojo/src/mojo/public/mojo.gni") -import("//third_party/mojo/src/mojo/public/mojo_application.gni") import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") import("//testing/test.gni") -# We don't support building in the component build since mojo apps are -# inherently components. -assert(!is_component_build) - -group("shell") { - testonly = true - - deps = [ - ":mojo_shell", - ":tests", - "//mojo/shell/application_manager:tests", - ] - - if (is_android) { - deps += [ - ":mojo_shell_apk", - ":tests_apk", - ] - } -} - -if (is_android) { - import("//build/config/android/config.gni") - import("//build/config/android/rules.gni") -} - -executable("mojo_shell") { - sources = [] - - deps = [ - ":lib", - "//base", - "//build/config/sanitizers:deps", - "//mojo/common", - "//mojo/environment:chromium", - ] - - if (!is_android) { - sources += [ - "desktop/launcher_process.cc", - "desktop/launcher_process.h", - "desktop/main.cc", - ] - } else { - sources += [ - "android/library_loader.cc", - "android/main.cc", - "android/main.h", - ] - - # On android, the executable is also the native library used by the apk. - # It means dynamic symbols must be preserved and exported. - ldflags = [ "-Wl,--export-dynamic" ] - - deps += [ - ":jni_headers", - "//components/native_viewport:lib", - "//mojo/shell/application_manager", - "//ui/gl", - ] - } -} - -source_set("in_process_native_runner") { +source_set("shell") { + output_name = "mojo_shell" sources = [ - "in_process_native_runner.cc", - "in_process_native_runner.h", - ] - - public_deps = [ - ":native_application_support", - "//mojo/shell/application_manager", - ] - - deps = [ - "//base", - ] -} - -source_set("lib") { - sources = [ - "child_process.cc", - "child_process.h", - "child_process_host.cc", - "child_process_host.h", - "context.cc", - "context.h", - "filename_util.cc", - "filename_util.h", - "init.cc", - "init.h", - "out_of_process_native_runner.cc", - "out_of_process_native_runner.h", - "task_runners.cc", - "task_runners.h", - "url_resolver.cc", - "url_resolver.h", - ] - - deps = [ - ":child_process_bindings", - ":in_process_native_runner", - ":native_application_support", - "//base", - "//base/third_party/dynamic_annotations", - "//base:base_static", - "//mojo/application", - "//mojo/common", - "//mojo/common:tracing_impl", - "//third_party/mojo/src/mojo/edk/system", - "//third_party/mojo/src/mojo/public/cpp/bindings", - "//third_party/mojo/src/mojo/public/interfaces/application", - "//mojo/services/network/public/interfaces", - "//mojo/shell/application_manager", - "//mojo/services/tracing:bindings", - "//url", - ] - - public_deps = [ - ":switches", - ] - - if (is_android) { - sources += [ - "android/android_handler.cc", - "android/android_handler.h", - "android/android_handler_loader.cc", - "android/android_handler_loader.h", - "android/background_application_loader.cc", - "android/background_application_loader.h", - "android/native_viewport_application_loader.cc", - "android/native_viewport_application_loader.h", - "android/ui_application_loader_android.cc", - "android/ui_application_loader_android.h", - ] - - deps += [ - ":jni_headers", - ":run_android_application_function", - "//components/gles2", - "//components/native_viewport:lib", - "//mojo/application:content_handler", - ] - } - - # This target includes some files behind #ifdef OS... guards. Since gn is not - # smart enough to understand preprocess includes, it does complains about - # these includes when not using the build files for that OS. Suppress checking - # so we can enable checking for the rest of the targets in this file. - # TODO: Might be better to split the files with OS-specific includes out to a - # separate source_set so we can leave checking on for the rest of the target. - check_includes = false -} - -source_set("native_application_support") { - sources = [ - "native_application_support.cc", - "native_application_support.h", - ] - - public_deps = [ - "//third_party/mojo/src/mojo/public/cpp/bindings", - ] - - deps = [ - "//base", - "//mojo/gles2", - ] - - # This target has to include the public thunk headers, which generally - # shouldn't be included without picking an implementation. We are providing - # the implementation but the thunk header target cannot declare that we are - # permitted to include it since it's in the public SDK and we are not. - # Suppress include checking so we can still check the rest of the targets in - # this file. - check_includes = false -} - -source_set("switches") { - sources = [ + "application_loader.h", + "application_manager.cc", + "application_manager.h", + "data_pipe_peek.cc", + "data_pipe_peek.h", + "fetcher.cc", + "fetcher.h", + "identity.cc", + "identity.h", + "local_fetcher.cc", + "local_fetcher.h", + "native_runner.h", + "network_fetcher.cc", + "network_fetcher.h", + "query_util.cc", + "query_util.h", + "shell_impl.cc", + "shell_impl.h", "switches.cc", "switches.h", ] - deps = [ + public_deps = [ "//base", + "//mojo/common", + "//third_party/mojo/src/mojo/public/interfaces/application:application", + "//mojo/services/network/public/interfaces", + "//url", ] -} - -if (is_android) { - generate_jni("jni_headers") { - sources = [ - "android/apk/src/org/chromium/mojo/shell/AndroidHandler.java", - "android/apk/src/org/chromium/mojo/shell/Bootstrap.java", - "android/apk/src/org/chromium/mojo/shell/ShellMain.java", - "android/tests/src/org/chromium/mojo/shell/ShellTestBase.java", - ] - jni_package = "mojo/shell" - } - - android_library("bootstrap_java") { - java_files = [ "android/apk/src/org/chromium/mojo/shell/Bootstrap.java" ] - - deps = [ - "//base:base_java", - ] - - dex_path = "$target_out_dir/bootstrap_java.dex.jar" - } - - shared_library("bootstrap") { - sources = [ - "android/bootstrap.cc", - ] - deps = [ - ":jni_headers", - ":lib", - ":run_android_application_function", - "//base", - ] - } - - # Shared header between the bootstrap and the main shell .so. - source_set("run_android_application_function") { - sources = [ - "android/run_android_application_function.h", - ] - - deps = [ - "//base", - ] - } - - android_library("java") { - java_files = [ - "android/apk/src/org/chromium/mojo/shell/AndroidHandler.java", - "android/apk/src/org/chromium/mojo/shell/FileHelper.java", - "android/apk/src/org/chromium/mojo/shell/MojoShellActivity.java", - "android/apk/src/org/chromium/mojo/shell/MojoShellApplication.java", - "android/apk/src/org/chromium/mojo/shell/ShellMain.java", - ] - - deps = [ - "//base:base_java", - ] - } - - android_resources("resources") { - resource_dirs = [ "android/apk/res" ] - custom_package = "org.chromium.mojo.shell" - } - - mojo_shell_assets_dir = "$root_build_dir/mojo_shell_assets" - mojo_shell_test_assets_dir = "$root_build_dir/mojo_shell_test_assets" - - copy_ex("copy_mojo_shell_assets") { - clear_dir = true - dest = mojo_shell_assets_dir - sources = [ - "$root_out_dir/lib.stripped/libbootstrap.so", - "$root_out_dir/network_service.mojo", - "$root_out_dir/obj/mojo/shell/bootstrap_java.dex.jar", - ] - } - - copy("copy_mojo_shell") { - sources = [ - "$root_out_dir/exe.stripped/mojo_shell", - ] - outputs = [ - "$root_out_dir/lib.stripped/libmojo_shell.so", - ] - } - - copy_ex("copy_mojo_shell_test_assets") { - clear_dir = true - dest = mojo_shell_test_assets_dir - sources = [ - "$root_out_dir/test_app.mojo", - "$root_out_dir/test_request_tracker_app.mojo", - ] - } - - android_apk("mojo_shell_apk") { - apk_name = "MojoShell" - - android_manifest = "android/apk/AndroidManifest.xml" - - native_libs = [ "libmojo_shell.so" ] - - asset_location = mojo_shell_assets_dir - - deps = [ - ":copy_mojo_shell", - ":copy_mojo_shell_assets", - ":java", - ":resources", - "//base:base_java", - "//components/native_viewport:native_viewport_java", - "//third_party/android_tools:google_play_services_default_resources", - ] - } - - android_library("mojo_shell_tests_java") { - java_files = - [ "android/tests/src/org/chromium/mojo/shell/ShellTestBase.java" ] - - deps = [ - ":java", - "//base:base_java", - ] - } -} - -mojom("child_process_bindings") { - sources = [ - "child_process.mojom", - ] - deps = [ - "//third_party/mojo/src/mojo/public/interfaces/application", + "//base/third_party/dynamic_annotations", + "//crypto:crypto", + "//url", + "//third_party/mojo/src/mojo/edk/system", + "//mojo/environment:chromium", + "//third_party/mojo_services/src/content_handler/public/interfaces", + "//mojo/runner:native_application_support", ] } @@ -336,77 +52,27 @@ output_name = "mojo_shell_unittests" sources = [ - "child_process_host_unittest.cc", - "data_pipe_peek_unittest.cc", - "in_process_native_runner_unittest.cc", - "native_runner_unittest.cc", - "shell_test_base.cc", - "shell_test_base.h", - "shell_test_base_android.cc", - "shell_test_base_unittest.cc", - "shell_test_main.cc", - "url_resolver_unittest.cc", + "application_manager_unittest.cc", + "query_util_unittest.cc", ] deps = [ - ":in_process_native_runner", - ":lib", - "//base", - "//base:i18n", - "//base/test:test_support", - "//testing/gtest", - "//url", - "//mojo/common", - "//third_party/mojo/src/mojo/edk/system", - "//mojo/environment:chromium", - "//third_party/mojo/src/mojo/public/cpp/bindings", - "//mojo/services/test_service:bindings", - "//mojo/shell/application_manager", - ] - - datadeps = [ - "//mojo/services/test_service:test_app", - "//mojo/services/test_service:test_request_tracker_app", - ] - - if (is_android) { - sources += [ "android/background_application_loader_unittest.cc" ] - - deps += [ ":jni_headers" ] - - apk_deps = [ - ":copy_mojo_shell_test_assets", - ":mojo_shell_tests_java", - ] - - apk_asset_location = mojo_shell_test_assets_dir - } -} - -mojo_native_application("apptests") { - output_name = "shell_apptests" - - testonly = true - - sources = [ - # TODO(jam): needs http_server service. - #"shell_apptest.cc", - ] - - deps = [ + ":shell", + ":test_bindings", "//base", "//mojo/application", - "//mojo/application:test_support", - "//mojo/common:common", - "//third_party/mojo/src/mojo/public/cpp/bindings:callback", - "//third_party/mojo/src/mojo/public/cpp/environment", - "//third_party/mojo/src/mojo/public/cpp/system:system", - - #"//mojo/services/http_server/public/cpp", - #"//mojo/services/http_server/public/interfaces", - "//mojo/services/network/public/interfaces", - "//mojo/shell/test:bindings", + "//mojo/common", + "//third_party/mojo/src/mojo/edk/test:run_all_unittests", + "//mojo/environment:chromium", + "//third_party/mojo/src/mojo/public/cpp/application", + "//third_party/mojo/src/mojo/public/cpp/bindings", + "//testing/gtest", + "//url", ] +} - #data_deps = [ "//services/http_server:http_server($default_toolchain)" ] +mojom("test_bindings") { + sources = [ + "test.mojom", + ] }
diff --git a/mojo/shell/DEPS b/mojo/shell/DEPS index 0a011fa..7014b6f 100644 --- a/mojo/shell/DEPS +++ b/mojo/shell/DEPS
@@ -1,8 +1,4 @@ include_rules = [ - "+components/gles2", - "+components/native_viewport", "+crypto", - "+jni", - "+third_party/mojo_services", - "+ui", + "+third_party/mojo_services/src/content_handler/public/interfaces", ]
diff --git a/mojo/shell/android/android_handler.cc b/mojo/shell/android/android_handler.cc deleted file mode 100644 index 383dc72..0000000 --- a/mojo/shell/android/android_handler.cc +++ /dev/null
@@ -1,111 +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 "mojo/shell/android/android_handler.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/scoped_native_library.h" -#include "jni/AndroidHandler_jni.h" -#include "mojo/common/data_pipe_utils.h" -#include "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/shell/android/run_android_application_function.h" -#include "mojo/shell/native_application_support.h" - -using base::android::AttachCurrentThread; -using base::android::ScopedJavaLocalRef; -using base::android::ConvertJavaStringToUTF8; -using base::android::ConvertUTF8ToJavaString; -using base::android::GetApplicationContext; - -namespace mojo { -namespace shell { - -namespace { - -// This function loads the application library, sets the application context and -// thunks and calls into the application MojoMain. To ensure that the thunks are -// set correctly we keep it in the Mojo shell .so and pass the function pointer -// to the helper libbootstrap.so. -void RunAndroidApplication(JNIEnv* env, - jobject j_context, - const base::FilePath& app_path, - jint j_handle) { - InterfaceRequest<Application> application_request = - MakeRequest<Application>(MakeScopedHandle(MessagePipeHandle(j_handle))); - - // Load the library, so that we can set the application context there if - // needed. - // TODO(vtl): We'd use a ScopedNativeLibrary, but it doesn't have .get()! - base::NativeLibrary app_library = - LoadNativeApplication(app_path, NativeApplicationCleanup::DELETE); - if (!app_library) - return; - - // Set the application context if needed. Most applications will need to - // access the Android ApplicationContext in which they are run. If the - // application library exports the InitApplicationContext function, we will - // set it there. - const char* init_application_context_name = "InitApplicationContext"; - typedef void (*InitApplicationContextFn)( - const base::android::JavaRef<jobject>&); - InitApplicationContextFn init_application_context = - reinterpret_cast<InitApplicationContextFn>( - base::GetFunctionPointerFromNativeLibrary( - app_library, init_application_context_name)); - if (init_application_context) { - base::android::ScopedJavaLocalRef<jobject> scoped_context(env, j_context); - init_application_context(scoped_context); - } - - // Run the application. - RunNativeApplication(app_library, application_request.Pass()); - // TODO(vtl): See note about unloading and thread-local destructors above - // declaration of |LoadNativeApplication()|. - base::UnloadNativeLibrary(app_library); -} - -} // namespace - -AndroidHandler::AndroidHandler() : content_handler_factory_(this) { -} - -AndroidHandler::~AndroidHandler() { -} - -void AndroidHandler::RunApplication( - InterfaceRequest<Application> application_request, - URLResponsePtr response) { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jstring> j_archive_path = - Java_AndroidHandler_getNewTempArchivePath(env, GetApplicationContext()); - base::FilePath archive_path( - ConvertJavaStringToUTF8(env, j_archive_path.obj())); - - common::BlockingCopyToFile(response->body.Pass(), archive_path); - RunAndroidApplicationFn run_android_application_fn = &RunAndroidApplication; - Java_AndroidHandler_bootstrap( - env, GetApplicationContext(), j_archive_path.obj(), - application_request.PassMessagePipe().release().value(), - reinterpret_cast<jlong>(run_android_application_fn)); -} - -void AndroidHandler::Initialize(ApplicationImpl* app) { -} - -bool AndroidHandler::ConfigureIncomingConnection( - ApplicationConnection* connection) { - connection->AddService(&content_handler_factory_); - return true; -} - -bool RegisterAndroidHandlerJni(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/android/android_handler.h b/mojo/shell/android/android_handler.h deleted file mode 100644 index 868c263..0000000 --- a/mojo/shell/android/android_handler.h +++ /dev/null
@@ -1,46 +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 MOJO_SHELL_ANDROID_CONTENT_HANDLER_H_ -#define MOJO_SHELL_ANDROID_CONTENT_HANDLER_H_ - -#include <jni.h> - -#include "mojo/application/content_handler_factory.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/interface_factory_impl.h" -#include "third_party/mojo_services/src/content_handler/public/interfaces/content_handler.mojom.h" - -namespace base { -class FilePath; -} - -namespace mojo { -namespace shell { - -class AndroidHandler : public ApplicationDelegate, - public ContentHandlerFactory::Delegate { - public: - AndroidHandler(); - ~AndroidHandler(); - - private: - // ApplicationDelegate: - void Initialize(ApplicationImpl* app) override; - bool ConfigureIncomingConnection(ApplicationConnection* connection) override; - - // ContentHandlerFactory::Delegate: - void RunApplication(InterfaceRequest<Application> application_request, - URLResponsePtr response) override; - - ContentHandlerFactory content_handler_factory_; - MOJO_DISALLOW_COPY_AND_ASSIGN(AndroidHandler); -}; - -bool RegisterAndroidHandlerJni(JNIEnv* env); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_ANDROID_CONTENT_HANDLER_H_
diff --git a/mojo/shell/android/android_handler_loader.cc b/mojo/shell/android/android_handler_loader.cc deleted file mode 100644 index 922dbb5..0000000 --- a/mojo/shell/android/android_handler_loader.cc +++ /dev/null
@@ -1,25 +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 "mojo/shell/android/android_handler_loader.h" - -namespace mojo { -namespace shell { - -AndroidHandlerLoader::AndroidHandlerLoader() { -} - -AndroidHandlerLoader::~AndroidHandlerLoader() { -} - -void AndroidHandlerLoader::Load( - const GURL& url, - InterfaceRequest<Application> application_request) { - DCHECK(application_request.is_pending()); - application_.reset( - new ApplicationImpl(&android_handler_, application_request.Pass())); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/android/android_handler_loader.h b/mojo/shell/android/android_handler_loader.h deleted file mode 100644 index 91592737..0000000 --- a/mojo/shell/android/android_handler_loader.h +++ /dev/null
@@ -1,37 +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 SHELL_ANDROID_ANDROID_HANDLER_LOADER_H_ -#define SHELL_ANDROID_ANDROID_HANDLER_LOADER_H_ - -#include "base/containers/scoped_ptr_hash_map.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/shell/android/android_handler.h" -#include "mojo/shell/application_manager/application_loader.h" - -namespace mojo { -namespace shell { - -class AndroidHandlerLoader : public ApplicationLoader { - public: - AndroidHandlerLoader(); - virtual ~AndroidHandlerLoader(); - - private: - // ApplicationLoader overrides: - void Load(const GURL& url, - InterfaceRequest<Application> application_request) override; - - AndroidHandler android_handler_; - scoped_ptr<ApplicationImpl> application_; - - DISALLOW_COPY_AND_ASSIGN(AndroidHandlerLoader); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_ANDROID_ANDROID_HANDLER_LOADER_H_
diff --git a/mojo/shell/android/background_application_loader.cc b/mojo/shell/android/background_application_loader.cc deleted file mode 100644 index cdb175e..0000000 --- a/mojo/shell/android/background_application_loader.cc +++ /dev/null
@@ -1,73 +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 "mojo/shell/android/background_application_loader.h" - -#include "base/bind.h" -#include "base/run_loop.h" -#include "mojo/shell/application_manager/application_manager.h" - -namespace mojo { -namespace shell { - -BackgroundApplicationLoader::BackgroundApplicationLoader( - scoped_ptr<ApplicationLoader> real_loader, - const std::string& thread_name, - base::MessageLoop::Type message_loop_type) - : loader_(real_loader.Pass()), - message_loop_type_(message_loop_type), - thread_name_(thread_name), - message_loop_created_(true, false) { -} - -BackgroundApplicationLoader::~BackgroundApplicationLoader() { - if (thread_) - thread_->Join(); -} - -void BackgroundApplicationLoader::Load( - const GURL& url, - InterfaceRequest<Application> application_request) { - DCHECK(application_request.is_pending()); - if (!thread_) { - // TODO(tim): It'd be nice if we could just have each Load call - // result in a new thread like DynamicService{Loader, Runner}. But some - // loaders are creating multiple ApplicationImpls (NetworkApplicationLoader) - // sharing a delegate (etc). So we have to keep it single threaded, wait - // for the thread to initialize, and post to the TaskRunner for subsequent - // Load calls for now. - thread_.reset(new base::DelegateSimpleThread(this, thread_name_)); - thread_->Start(); - message_loop_created_.Wait(); - DCHECK(task_runner_.get()); - } - - task_runner_->PostTask( - FROM_HERE, - base::Bind(&BackgroundApplicationLoader::LoadOnBackgroundThread, - base::Unretained(this), url, - base::Passed(&application_request))); -} - -void BackgroundApplicationLoader::Run() { - base::MessageLoop message_loop(message_loop_type_); - base::RunLoop loop; - task_runner_ = message_loop.task_runner(); - quit_closure_ = loop.QuitClosure(); - message_loop_created_.Signal(); - loop.Run(); - - // Destroy |loader_| on the thread it's actually used on. - loader_.reset(); -} - -void BackgroundApplicationLoader::LoadOnBackgroundThread( - const GURL& url, - InterfaceRequest<Application> application_request) { - DCHECK(task_runner_->RunsTasksOnCurrentThread()); - loader_->Load(url, application_request.Pass()); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/android/background_application_loader.h b/mojo/shell/android/background_application_loader.h deleted file mode 100644 index 7c549f7..0000000 --- a/mojo/shell/android/background_application_loader.h +++ /dev/null
@@ -1,64 +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 SHELL_ANDROID_BACKGROUND_APPLICATION_LOADER_H_ -#define SHELL_ANDROID_BACKGROUND_APPLICATION_LOADER_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/simple_thread.h" -#include "mojo/shell/application_manager/application_loader.h" - -namespace mojo { -namespace shell { - -class BackgroundApplicationLoader - : public ApplicationLoader, - public base::DelegateSimpleThread::Delegate { - public: - BackgroundApplicationLoader(scoped_ptr<ApplicationLoader> real_loader, - const std::string& thread_name, - base::MessageLoop::Type message_loop_type); - ~BackgroundApplicationLoader() override; - - // ApplicationLoader overrides: - void Load(const GURL& url, - InterfaceRequest<Application> application_request) override; - - private: - // |base::DelegateSimpleThread::Delegate| method: - void Run() override; - - // These functions are exected on the background thread. They call through - // to |background_loader_| to do the actual loading. - void LoadOnBackgroundThread( - const GURL& url, - InterfaceRequest<Application> application_request); - bool quit_on_shutdown_; - scoped_ptr<ApplicationLoader> loader_; - - const base::MessageLoop::Type message_loop_type_; - const std::string thread_name_; - - // Created on |thread_| during construction of |this|. Protected against - // uninitialized use by |message_loop_created_|, and protected against - // use-after-free by holding a reference to the thread-safe object. Note - // that holding a reference won't hold |thread_| from exiting. - scoped_refptr<base::TaskRunner> task_runner_; - base::WaitableEvent message_loop_created_; - - // Lives on |thread_|. - base::Closure quit_closure_; - - scoped_ptr<base::DelegateSimpleThread> thread_; - - DISALLOW_COPY_AND_ASSIGN(BackgroundApplicationLoader); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_ANDROID_BACKGROUND_APPLICATION_LOADER_H_
diff --git a/mojo/shell/android/background_application_loader_unittest.cc b/mojo/shell/android/background_application_loader_unittest.cc deleted file mode 100644 index 4d18073..0000000 --- a/mojo/shell/android/background_application_loader_unittest.cc +++ /dev/null
@@ -1,51 +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 "mojo/shell/android/background_application_loader.h" - -#include "mojo/public/interfaces/application/application.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { -namespace { - -class DummyLoader : public ApplicationLoader { - public: - DummyLoader() : simulate_app_quit_(true) {} - ~DummyLoader() override {} - - // ApplicationLoader overrides: - void Load(const GURL& url, - InterfaceRequest<Application> application_request) override { - if (simulate_app_quit_) - base::MessageLoop::current()->Quit(); - } - - void DontSimulateAppQuit() { simulate_app_quit_ = false; } - - private: - bool simulate_app_quit_; -}; - -// Tests that the loader can start and stop gracefully. -TEST(BackgroundApplicationLoaderTest, StartStop) { - scoped_ptr<ApplicationLoader> real_loader(new DummyLoader()); - BackgroundApplicationLoader loader(real_loader.Pass(), "test", - base::MessageLoop::TYPE_DEFAULT); -} - -// Tests that the loader can load a service that is well behaved (quits -// itself). -TEST(BackgroundApplicationLoaderTest, Load) { - scoped_ptr<ApplicationLoader> real_loader(new DummyLoader()); - BackgroundApplicationLoader loader(real_loader.Pass(), "test", - base::MessageLoop::TYPE_DEFAULT); - ApplicationPtr application; - loader.Load(GURL(), GetProxy(&application)); -} - -} // namespace -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/android/bootstrap.cc b/mojo/shell/android/bootstrap.cc deleted file mode 100644 index 4fcae37..0000000 --- a/mojo/shell/android/bootstrap.cc +++ /dev/null
@@ -1,43 +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 "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "jni/Bootstrap_jni.h" -#include "mojo/shell/android/run_android_application_function.h" - -namespace mojo { -namespace shell { - -void Bootstrap(JNIEnv* env, - jobject, - jobject j_context, - jstring j_native_library_path, - jint j_handle, - jlong j_run_application_ptr) { - base::FilePath app_path( - base::android::ConvertJavaStringToUTF8(env, j_native_library_path)); - RunAndroidApplicationFn run_android_application_fn = - reinterpret_cast<RunAndroidApplicationFn>(j_run_application_ptr); - run_android_application_fn(env, j_context, app_path, j_handle); -} - -bool RegisterBootstrapJni(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace shell -} // namespace mojo - -JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { - base::android::InitVM(vm); - JNIEnv* env = base::android::AttachCurrentThread(); - - if (!mojo::shell::RegisterBootstrapJni(env)) - return -1; - - return JNI_VERSION_1_4; -}
diff --git a/mojo/shell/android/library_loader.cc b/mojo/shell/android/library_loader.cc deleted file mode 100644 index c43a4b5..0000000 --- a/mojo/shell/android/library_loader.cc +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2013 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/android/base_jni_onload.h" -#include "base/android/base_jni_registrar.h" -#include "base/android/jni_android.h" -#include "base/android/jni_registrar.h" -#include "base/bind.h" -#include "components/native_viewport/platform_viewport_android.h" -#include "mojo/shell/android/android_handler.h" -#include "mojo/shell/android/main.h" - -namespace { - -base::android::RegistrationMethod kMojoRegisteredMethods[] = { - {"AndroidHandler", mojo::shell::RegisterAndroidHandlerJni}, - {"PlatformViewportAndroid", - native_viewport::PlatformViewportAndroid::Register}, - {"ShellMain", mojo::shell::RegisterShellMain}, -}; - -bool RegisterJNI(JNIEnv* env) { - if (!base::android::RegisterJni(env)) - return false; - - return RegisterNativeMethods(env, kMojoRegisteredMethods, - arraysize(kMojoRegisteredMethods)); -} - -} // namespace - -// This is called by the VM when the shared library is first loaded. -JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { - std::vector<base::android::RegisterCallback> register_callbacks; - register_callbacks.push_back(base::Bind(&RegisterJNI)); - if (!base::android::OnJNIOnLoadRegisterJNI(vm, register_callbacks) || - !base::android::OnJNIOnLoadInit( - std::vector<base::android::InitCallback>())) { - return -1; - } - - return JNI_VERSION_1_4; -}
diff --git a/mojo/shell/android/main.cc b/mojo/shell/android/main.cc deleted file mode 100644 index 0e6c917..0000000 --- a/mojo/shell/android/main.cc +++ /dev/null
@@ -1,211 +0,0 @@ -// Copyright 2013 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/shell/android/main.h" - -#include "base/android/fifo_utils.h" -#include "base/android/jni_android.h" -#include "base/android/jni_array.h" -#include "base/android/jni_string.h" -#include "base/at_exit.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/lazy_instance.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "base/threading/simple_thread.h" -#include "jni/ShellMain_jni.h" -#include "mojo/common/message_pump_mojo.h" -#include "mojo/shell/android/android_handler_loader.h" -#include "mojo/shell/android/background_application_loader.h" -#include "mojo/shell/android/native_viewport_application_loader.h" -#include "mojo/shell/android/ui_application_loader_android.h" -#include "mojo/shell/application_manager/application_loader.h" -#include "mojo/shell/context.h" -#include "mojo/shell/init.h" -#include "ui/gl/gl_surface_egl.h" - -using base::LazyInstance; - -namespace mojo { -namespace shell { - -namespace { - -// Tag for logging. -const char kLogTag[] = "chromium"; - -// Command line argument for the communication fifo. -const char kFifoPath[] = "fifo-path"; - -class MojoShellRunner : public base::DelegateSimpleThread::Delegate { - public: - MojoShellRunner(const std::vector<std::string>& parameters) {} - ~MojoShellRunner() override {} - - private: - void Run() override; - - DISALLOW_COPY_AND_ASSIGN(MojoShellRunner); -}; - -LazyInstance<scoped_ptr<base::MessageLoop>> g_java_message_loop = - LAZY_INSTANCE_INITIALIZER; - -LazyInstance<scoped_ptr<Context>> g_context = LAZY_INSTANCE_INITIALIZER; - -LazyInstance<scoped_ptr<MojoShellRunner>> g_shell_runner = - LAZY_INSTANCE_INITIALIZER; - -LazyInstance<scoped_ptr<base::DelegateSimpleThread>> g_shell_thread = - LAZY_INSTANCE_INITIALIZER; - -LazyInstance<base::android::ScopedJavaGlobalRef<jobject>> g_main_activiy = - LAZY_INSTANCE_INITIALIZER; - -void ConfigureAndroidServices(Context* context) { - context->application_manager()->SetLoaderForURL( - make_scoped_ptr(new UIApplicationLoader( - make_scoped_ptr(new NativeViewportApplicationLoader()), - g_java_message_loop.Get().get())), - GURL("mojo:native_viewport_service")); - - // Android handler is bundled with the Mojo shell, because it uses the - // MojoShell application as the JNI bridge to bootstrap execution of other - // Android Mojo apps that need JNI. - context->application_manager()->SetLoaderForURL( - make_scoped_ptr(new BackgroundApplicationLoader( - make_scoped_ptr(new AndroidHandlerLoader()), "android_handler", - base::MessageLoop::TYPE_DEFAULT)), - GURL("mojo:android_handler")); -} - -void QuitShellThread() { - g_shell_thread.Get()->Join(); - g_shell_thread.Pointer()->reset(); - Java_ShellMain_finishActivity(base::android::AttachCurrentThread(), - g_main_activiy.Get().obj()); - exit(0); -} - -void MojoShellRunner::Run() { - base::MessageLoop loop(common::MessagePumpMojo::Create()); - Context* context = g_context.Pointer()->get(); - ConfigureAndroidServices(context); - context->Init(); - - context->Run(GURL("mojo:window_manager")); - loop.Run(); - - g_java_message_loop.Pointer()->get()->PostTask(FROM_HERE, - base::Bind(&QuitShellThread)); -} - -// Initialize stdout redirection if the command line switch is present. -void InitializeRedirection() { - if (!base::CommandLine::ForCurrentProcess()->HasSwitch(kFifoPath)) - return; - - base::FilePath fifo_path = - base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(kFifoPath); - base::FilePath directory = fifo_path.DirName(); - CHECK(base::CreateDirectoryAndGetError(directory, nullptr)) - << "Unable to create directory: " << directory.value(); - unlink(fifo_path.value().c_str()); - CHECK(base::android::CreateFIFO(fifo_path, 0666)) - << "Unable to create fifo: " << fifo_path.value(); - CHECK(base::android::RedirectStream(stdout, fifo_path, "w")) - << "Failed to redirect stdout to file: " << fifo_path.value(); - CHECK(dup2(STDOUT_FILENO, STDERR_FILENO) != -1) - << "Unable to redirect stderr to stdout."; -} - -} // namespace - -static void Init(JNIEnv* env, - jclass clazz, - jobject activity, - jstring mojo_shell_path, - jobjectArray jparameters, - jstring j_local_apps_directory, - jstring j_tmp_dir) { - g_main_activiy.Get().Reset(env, activity); - - // Setting the TMPDIR environment variable so that applications can use it. - // TODO(qsr) We will need our subprocesses to inherit this. - int return_value = - setenv("TMPDIR", - base::android::ConvertJavaStringToUTF8(env, j_tmp_dir).c_str(), 1); - DCHECK_EQ(return_value, 0); - - base::android::ScopedJavaLocalRef<jobject> scoped_activity(env, activity); - base::android::InitApplicationContext(env, scoped_activity); - - std::vector<std::string> parameters; - parameters.push_back( - base::android::ConvertJavaStringToUTF8(env, mojo_shell_path)); - base::android::AppendJavaStringArrayToStringVector(env, jparameters, - ¶meters); - base::CommandLine::Init(0, nullptr); - base::CommandLine::ForCurrentProcess()->InitFromArgv(parameters); - g_shell_runner.Get().reset(new MojoShellRunner(parameters)); - - InitializeLogging(); - - InitializeRedirection(); - - // We want ~MessageLoop to happen prior to ~Context. Initializing - // LazyInstances is akin to stack-allocating objects; their destructors - // will be invoked first-in-last-out. - Context* shell_context = new Context(); - shell_context->SetShellFileRoot(base::FilePath( - base::android::ConvertJavaStringToUTF8(env, j_local_apps_directory))); - g_context.Get().reset(shell_context); - - g_java_message_loop.Get().reset(new base::MessageLoopForUI); - base::MessageLoopForUI::current()->Start(); - - // TODO(abarth): At which point should we switch to cross-platform - // initialization? - - gfx::GLSurface::InitializeOneOff(); -} - -static jboolean Start(JNIEnv* env, jclass clazz) { - if (!base::CommandLine::ForCurrentProcess()->GetArgs().size()) - return false; - -#if defined(MOJO_SHELL_DEBUG_URL) - base::CommandLine::ForCurrentProcess()->AppendArg(MOJO_SHELL_DEBUG_URL); - // Sleep for 5 seconds to give the debugger a chance to attach. - sleep(5); -#endif - - g_shell_thread.Get().reset(new base::DelegateSimpleThread( - g_shell_runner.Get().get(), "ShellThread")); - g_shell_thread.Get()->Start(); - return true; -} - -static void AddApplicationURL(JNIEnv* env, jclass clazz, jstring jurl) { - base::CommandLine::ForCurrentProcess()->AppendArg( - base::android::ConvertJavaStringToUTF8(env, jurl)); -} - -bool RegisterShellMain(JNIEnv* env) { - return RegisterNativesImpl(env); -} - -} // namespace shell -} // namespace mojo - -// TODO(vtl): Even though main() should never be called, mojo_shell fails to -// link without it. Figure out if we can avoid this. -int main(int argc, char** argv) { - NOTREACHED(); -}
diff --git a/mojo/shell/android/main.h b/mojo/shell/android/main.h deleted file mode 100644 index 43ea16a..0000000 --- a/mojo/shell/android/main.h +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2013 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 SHELL_ANDROID_MAIN_H_ -#define SHELL_ANDROID_MAIN_H_ - -#include <jni.h> - -namespace mojo { -namespace shell { - -bool RegisterShellMain(JNIEnv* env); - -} // namespace shell -} // namespace mojo - -#endif // SHELL_ANDROID_MAIN_H_
diff --git a/mojo/shell/android/native_viewport_application_loader.cc b/mojo/shell/android/native_viewport_application_loader.cc deleted file mode 100644 index 3822980..0000000 --- a/mojo/shell/android/native_viewport_application_loader.cc +++ /dev/null
@@ -1,50 +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 "mojo/shell/android/native_viewport_application_loader.h" - -#include "components/gles2/gpu_state.h" -#include "components/native_viewport/native_viewport_impl.h" -#include "mojo/public/cpp/application/application_impl.h" - -namespace mojo { -namespace shell { - -NativeViewportApplicationLoader::NativeViewportApplicationLoader() { -} - -NativeViewportApplicationLoader::~NativeViewportApplicationLoader() { -} - -void NativeViewportApplicationLoader::Load( - const GURL& url, - InterfaceRequest<Application> application_request) { - DCHECK(application_request.is_pending()); - app_.reset(new ApplicationImpl(this, application_request.Pass())); -} - -bool NativeViewportApplicationLoader::ConfigureIncomingConnection( - ApplicationConnection* connection) { - connection->AddService<NativeViewport>(this); - connection->AddService<Gpu>(this); - return true; -} - -void NativeViewportApplicationLoader::Create( - ApplicationConnection* connection, - InterfaceRequest<NativeViewport> request) { - if (!gpu_state_) - gpu_state_ = new gles2::GpuState; - new native_viewport::NativeViewportImpl(false, gpu_state_, request.Pass()); -} - -void NativeViewportApplicationLoader::Create(ApplicationConnection* connection, - InterfaceRequest<Gpu> request) { - if (!gpu_state_) - gpu_state_ = new gles2::GpuState; - new gles2::GpuImpl(request.Pass(), gpu_state_); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/android/native_viewport_application_loader.h b/mojo/shell/android/native_viewport_application_loader.h deleted file mode 100644 index 1efa7f4..0000000 --- a/mojo/shell/android/native_viewport_application_loader.h +++ /dev/null
@@ -1,58 +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 MOJO_SHELL_ANDROID_NATIVE_VIEWPORT_APPLICATION_LOADER_H_ -#define MOJO_SHELL_ANDROID_NATIVE_VIEWPORT_APPLICATION_LOADER_H_ - -#include "components/gles2/gpu_impl.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/interface_factory.h" -#include "mojo/shell/application_manager/application_loader.h" -#include "third_party/mojo_services/src/gpu/public/interfaces/gpu.mojom.h" -#include "third_party/mojo_services/src/native_viewport/public/interfaces/native_viewport.mojom.h" - -namespace gles2 { -class GpuState; -} - -namespace mojo { - -class ApplicationImpl; - -namespace shell { - -class NativeViewportApplicationLoader : public ApplicationLoader, - public ApplicationDelegate, - public InterfaceFactory<NativeViewport>, - public InterfaceFactory<Gpu> { - public: - NativeViewportApplicationLoader(); - ~NativeViewportApplicationLoader(); - - private: - // ApplicationLoader implementation. - void Load(const GURL& url, - InterfaceRequest<Application> application_request) override; - - // ApplicationDelegate implementation. - bool ConfigureIncomingConnection(ApplicationConnection* connection) override; - - // InterfaceFactory<NativeViewport> implementation. - void Create(ApplicationConnection* connection, - InterfaceRequest<NativeViewport> request) override; - - // InterfaceFactory<Gpu> implementation. - void Create(ApplicationConnection* connection, - InterfaceRequest<Gpu> request) override; - - scoped_refptr<gles2::GpuState> gpu_state_; - scoped_ptr<ApplicationImpl> app_; - - DISALLOW_COPY_AND_ASSIGN(NativeViewportApplicationLoader); -}; - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_ANDROID_NATIVE_VIEWPORT_APPLICATION_LOADER_H_
diff --git a/mojo/shell/android/run_android_application_function.h b/mojo/shell/android/run_android_application_function.h deleted file mode 100644 index 3ed1744..0000000 --- a/mojo/shell/android/run_android_application_function.h +++ /dev/null
@@ -1,27 +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 SHELL_ANDROID_RUN_ANDROID_APPLICATION_FUNCTION_H_ -#define SHELL_ANDROID_RUN_ANDROID_APPLICATION_FUNCTION_H_ - -#include "base/android/jni_android.h" -#include "base/files/file_path.h" - -namespace mojo { -namespace shell { - -// Type of the function that we inject from the main .so of the Mojo shell to -// the helper libbootstrap.so. This function will set the thunks in the -// application .so and call into application MojoMain. Injecting the function -// from the main .so ensures that the thunks are set correctly. - -typedef void (*RunAndroidApplicationFn)(JNIEnv* env, - jobject j_context, - const base::FilePath& app_path, - jint j_handle); - -} // namespace shell -} // namespace mojo - -#endif // SHELL_ANDROID_RUN_ANDROID_APPLICATION_FUNCTION_H_
diff --git a/mojo/shell/android/ui_application_loader_android.cc b/mojo/shell/android/ui_application_loader_android.cc deleted file mode 100644 index 87f686f..0000000 --- a/mojo/shell/android/ui_application_loader_android.cc +++ /dev/null
@@ -1,48 +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 "mojo/shell/android/ui_application_loader_android.h" - -#include "base/bind.h" -#include "base/message_loop/message_loop.h" -#include "mojo/shell/application_manager/application_manager.h" - -namespace mojo { -namespace shell { - -UIApplicationLoader::UIApplicationLoader( - scoped_ptr<ApplicationLoader> real_loader, - base::MessageLoop* ui_message_loop) - : loader_(real_loader.Pass()), ui_message_loop_(ui_message_loop) { -} - -UIApplicationLoader::~UIApplicationLoader() { - ui_message_loop_->PostTask( - FROM_HERE, base::Bind(&UIApplicationLoader::ShutdownOnUIThread, - base::Unretained(this))); -} - -void UIApplicationLoader::Load( - const GURL& url, - InterfaceRequest<Application> application_request) { - DCHECK(application_request.is_pending()); - ui_message_loop_->PostTask( - FROM_HERE, - base::Bind(&UIApplicationLoader::LoadOnUIThread, base::Unretained(this), - url, base::Passed(&application_request))); -} - -void UIApplicationLoader::LoadOnUIThread( - const GURL& url, - InterfaceRequest<Application> application_request) { - loader_->Load(url, application_request.Pass()); -} - -void UIApplicationLoader::ShutdownOnUIThread() { - // Destroy |loader_| on the thread it's actually used on. - loader_.reset(); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/android/ui_application_loader_android.h b/mojo/shell/android/ui_application_loader_android.h deleted file mode 100644 index 37cc063..0000000 --- a/mojo/shell/android/ui_application_loader_android.h +++ /dev/null
@@ -1,54 +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 SHELL_ANDROID_UI_APPLICATION_LOADER_ANDROID_H_ -#define SHELL_ANDROID_UI_APPLICATION_LOADER_ANDROID_H_ - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/shell/application_manager/application_loader.h" - -namespace base { -class MessageLoop; -} - -namespace mojo { -namespace shell { - -class ApplicationManager; - -// ApplicationLoader implementation that creates a background thread and issues -// load -// requests there. -class UIApplicationLoader : public ApplicationLoader { - public: - UIApplicationLoader(scoped_ptr<ApplicationLoader> real_loader, - base::MessageLoop* ui_message_loop); - ~UIApplicationLoader() override; - - // ApplicationLoader overrides: - void Load(const GURL& url, - InterfaceRequest<Application> application_request) override; - - private: - class UILoader; - - // These functions are exected on the background thread. They call through - // to |background_loader_| to do the actual loading. - // TODO: having this code take a |manager| is fragile (as ApplicationManager - // isn't thread safe). - void LoadOnUIThread(const GURL& url, - InterfaceRequest<Application> application_request); - void ShutdownOnUIThread(); - - scoped_ptr<ApplicationLoader> loader_; - base::MessageLoop* ui_message_loop_; - - DISALLOW_COPY_AND_ASSIGN(UIApplicationLoader); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_ANDROID_UI_APPLICATION_LOADER_ANDROID_H_
diff --git a/mojo/shell/application_manager/application_loader.h b/mojo/shell/application_loader.h similarity index 100% rename from mojo/shell/application_manager/application_loader.h rename to mojo/shell/application_loader.h
diff --git a/mojo/shell/application_manager.cc b/mojo/shell/application_manager.cc new file mode 100644 index 0000000..4648c1fc --- /dev/null +++ b/mojo/shell/application_manager.cc
@@ -0,0 +1,463 @@ +// 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 "mojo/shell/application_manager.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/stl_util.h" +#include "base/strings/string_util.h" +#include "base/trace_event/trace_event.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/error_handler.h" +#include "mojo/shell/fetcher.h" +#include "mojo/shell/local_fetcher.h" +#include "mojo/shell/network_fetcher.h" +#include "mojo/shell/query_util.h" +#include "mojo/shell/shell_impl.h" +#include "mojo/shell/switches.h" +#include "third_party/mojo_services/src/content_handler/public/interfaces/content_handler.mojom.h" + +namespace mojo { +namespace shell { + +namespace { + +// Used by TestAPI. +bool has_created_instance = false; + +} // namespace + +class ApplicationManager::ContentHandlerConnection : public ErrorHandler { + public: + ContentHandlerConnection(ApplicationManager* manager, + const GURL& content_handler_url) + : manager_(manager), content_handler_url_(content_handler_url) { + ServiceProviderPtr services; + manager->ConnectToApplication(content_handler_url, GURL(), + GetProxy(&services), nullptr, + base::Closure()); + MessagePipe pipe; + content_handler_.Bind(pipe.handle0.Pass()); + services->ConnectToService(ContentHandler::Name_, pipe.handle1.Pass()); + content_handler_.set_error_handler(this); + } + + ContentHandler* content_handler() { return content_handler_.get(); } + + GURL content_handler_url() { return content_handler_url_; } + + private: + // ErrorHandler implementation: + void OnConnectionError() override { manager_->OnContentHandlerError(this); } + + ApplicationManager* manager_; + GURL content_handler_url_; + ContentHandlerPtr content_handler_; + + DISALLOW_COPY_AND_ASSIGN(ContentHandlerConnection); +}; + +// static +ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager) + : manager_(manager) { +} + +ApplicationManager::TestAPI::~TestAPI() { +} + +bool ApplicationManager::TestAPI::HasCreatedInstance() { + return has_created_instance; +} + +bool ApplicationManager::TestAPI::HasFactoryForURL(const GURL& url) const { + return manager_->identity_to_shell_impl_.find(Identity(url)) != + manager_->identity_to_shell_impl_.end(); +} + +ApplicationManager::ApplicationManager(Delegate* delegate) + : delegate_(delegate), weak_ptr_factory_(this) { +} + +ApplicationManager::~ApplicationManager() { + STLDeleteValues(&url_to_content_handler_); + TerminateShellConnections(); + STLDeleteValues(&url_to_loader_); + STLDeleteValues(&scheme_to_loader_); +} + +void ApplicationManager::TerminateShellConnections() { + STLDeleteValues(&identity_to_shell_impl_); +} + +void ApplicationManager::ConnectToApplication( + const GURL& requested_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const base::Closure& on_application_end) { + ConnectToApplicationWithParameters( + requested_url, requestor_url, services.Pass(), exposed_services.Pass(), + on_application_end, std::vector<std::string>()); +} + +void ApplicationManager::ConnectToApplicationWithParameters( + const GURL& requested_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const base::Closure& on_application_end, + const std::vector<std::string>& pre_redirect_parameters) { + TRACE_EVENT_INSTANT1( + "mojo_shell", "ApplicationManager::ConnectToApplicationWithParameters", + TRACE_EVENT_SCOPE_THREAD, "requested_url", requested_url.spec()); + DCHECK(requested_url.is_valid()); + + // We check both the mapped and resolved urls for existing shell_impls because + // external applications can be registered for the unresolved mojo:foo urls. + + GURL mapped_url = delegate_->ResolveMappings(requested_url); + if (ConnectToRunningApplication(mapped_url, requestor_url, &services, + &exposed_services)) { + return; + } + + GURL resolved_url = delegate_->ResolveMojoURL(mapped_url); + if (ConnectToRunningApplication(resolved_url, requestor_url, &services, + &exposed_services)) { + return; + } + + // The application is not running, let's compute the parameters. + if (ConnectToApplicationWithLoader(mapped_url, requestor_url, &services, + &exposed_services, on_application_end, + pre_redirect_parameters, + GetLoaderForURL(mapped_url))) { + return; + } + + if (ConnectToApplicationWithLoader(resolved_url, requestor_url, &services, + &exposed_services, on_application_end, + pre_redirect_parameters, + GetLoaderForURL(resolved_url))) { + return; + } + + if (ConnectToApplicationWithLoader( + resolved_url, requestor_url, &services, &exposed_services, + on_application_end, pre_redirect_parameters, default_loader_.get())) { + return; + } + + auto callback = base::Bind(&ApplicationManager::HandleFetchCallback, + weak_ptr_factory_.GetWeakPtr(), requestor_url, + base::Passed(services.Pass()), + base::Passed(exposed_services.Pass()), + on_application_end, pre_redirect_parameters); + + if (resolved_url.SchemeIsFile()) { + new LocalFetcher( + resolved_url, GetBaseURLAndQuery(resolved_url, nullptr), + base::Bind(callback, NativeApplicationCleanup::DONT_DELETE)); + return; + } + + if (!network_service_) + ConnectToService(GURL("mojo:network_service"), &network_service_); + + const NativeApplicationCleanup cleanup = + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDontDeleteOnDownload) + ? NativeApplicationCleanup::DONT_DELETE + : NativeApplicationCleanup::DELETE; + + new NetworkFetcher(disable_cache_, resolved_url, network_service_.get(), + base::Bind(callback, cleanup)); +} + +bool ApplicationManager::ConnectToRunningApplication( + const GURL& resolved_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider>* services, + ServiceProviderPtr* exposed_services) { + GURL application_url = GetBaseURLAndQuery(resolved_url, nullptr); + ShellImpl* shell_impl = GetShellImpl(application_url); + if (!shell_impl) + return false; + + ConnectToClient(shell_impl, resolved_url, requestor_url, services->Pass(), + exposed_services->Pass()); + return true; +} + +bool ApplicationManager::ConnectToApplicationWithLoader( + const GURL& resolved_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider>* services, + ServiceProviderPtr* exposed_services, + const base::Closure& on_application_end, + const std::vector<std::string>& parameters, + ApplicationLoader* loader) { + if (!loader) + return false; + + loader->Load( + resolved_url, + RegisterShell(resolved_url, requestor_url, services->Pass(), + exposed_services->Pass(), on_application_end, parameters)); + return true; +} + +InterfaceRequest<Application> ApplicationManager::RegisterShell( + const GURL& resolved_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const base::Closure& on_application_end, + const std::vector<std::string>& parameters) { + Identity app_identity(resolved_url); + + ApplicationPtr application; + InterfaceRequest<Application> application_request = GetProxy(&application); + ShellImpl* shell = + new ShellImpl(application.Pass(), this, app_identity, on_application_end); + identity_to_shell_impl_[app_identity] = shell; + shell->InitializeApplication(Array<String>::From(parameters)); + ConnectToClient(shell, resolved_url, requestor_url, services.Pass(), + exposed_services.Pass()); + return application_request.Pass(); +} + +ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) { + const auto& shell_it = identity_to_shell_impl_.find(Identity(url)); + if (shell_it != identity_to_shell_impl_.end()) + return shell_it->second; + return nullptr; +} + +void ApplicationManager::ConnectToClient( + ShellImpl* shell_impl, + const GURL& resolved_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { + shell_impl->ConnectToClient(resolved_url, requestor_url, services.Pass(), + exposed_services.Pass()); +} + +void ApplicationManager::HandleFetchCallback( + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const base::Closure& on_application_end, + const std::vector<std::string>& parameters, + NativeApplicationCleanup cleanup, + scoped_ptr<Fetcher> fetcher) { + if (!fetcher) { + // Network error. Drop |application_request| to tell requestor. + return; + } + + GURL redirect_url = fetcher->GetRedirectURL(); + if (!redirect_url.is_empty()) { + // And around we go again... Whee! + ConnectToApplicationWithParameters(redirect_url, requestor_url, + services.Pass(), exposed_services.Pass(), + on_application_end, parameters); + return; + } + + // We already checked if the application was running before we fetched it, but + // it might have started while the fetch was outstanding. We don't want to + // have two copies of the app running, so check again. + // + // Also, it's possible the original URL was redirected to an app that is + // already running. + if (ConnectToRunningApplication(fetcher->GetURL(), requestor_url, &services, + &exposed_services)) { + return; + } + + InterfaceRequest<Application> request( + RegisterShell(fetcher->GetURL(), requestor_url, services.Pass(), + exposed_services.Pass(), on_application_end, parameters)); + + // If the response begins with a #!mojo <content-handler-url>, use it. + GURL content_handler_url; + std::string shebang; + if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) { + LoadWithContentHandler( + content_handler_url, request.Pass(), + fetcher->AsURLResponse(blocking_pool_, + static_cast<int>(shebang.size()))); + return; + } + + MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(fetcher->MimeType()); + if (iter != mime_type_to_url_.end()) { + LoadWithContentHandler(iter->second, request.Pass(), + fetcher->AsURLResponse(blocking_pool_, 0)); + return; + } + + // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo + // application. That could either mean looking for the platform-specific dll + // header, or looking for some specific mojo signature prepended to the + // library. + // TODO(vtl): (Maybe this should be done by the factory/runner?) + + GURL base_resolved_url = GetBaseURLAndQuery(fetcher->GetURL(), nullptr); + NativeRunnerFactory::Options options; + if (url_to_native_options_.find(base_resolved_url) != + url_to_native_options_.end()) { + DVLOG(2) << "Applying stored native options to resolved URL " + << fetcher->GetURL(); + options = url_to_native_options_[base_resolved_url]; + } + + fetcher->AsPath( + blocking_pool_, + base::Bind(&ApplicationManager::RunNativeApplication, + weak_ptr_factory_.GetWeakPtr(), base::Passed(request.Pass()), + options, cleanup, base::Passed(fetcher.Pass()))); +} + +void ApplicationManager::RunNativeApplication( + InterfaceRequest<Application> application_request, + const NativeRunnerFactory::Options& options, + NativeApplicationCleanup cleanup, + scoped_ptr<Fetcher> fetcher, + const base::FilePath& path, + bool path_exists) { + // We only passed fetcher to keep it alive. Done with it now. + fetcher.reset(); + + DCHECK(application_request.is_pending()); + + if (!path_exists) { + LOG(ERROR) << "Library not started because library path '" << path.value() + << "' does not exist."; + return; + } + + TRACE_EVENT1("mojo_shell", "ApplicationManager::RunNativeApplication", "path", + path.AsUTF8Unsafe()); + NativeRunner* runner = native_runner_factory_->Create(options).release(); + native_runners_.push_back(runner); + runner->Start(path, cleanup, application_request.Pass(), + base::Bind(&ApplicationManager::CleanupRunner, + weak_ptr_factory_.GetWeakPtr(), runner)); +} + +void ApplicationManager::RegisterContentHandler( + const std::string& mime_type, + const GURL& content_handler_url) { + DCHECK(content_handler_url.is_valid()) + << "Content handler URL is invalid for mime type " << mime_type; + mime_type_to_url_[mime_type] = content_handler_url; +} + +void ApplicationManager::LoadWithContentHandler( + const GURL& content_handler_url, + InterfaceRequest<Application> application_request, + URLResponsePtr url_response) { + ContentHandlerConnection* connection = nullptr; + URLToContentHandlerMap::iterator iter = + url_to_content_handler_.find(content_handler_url); + if (iter != url_to_content_handler_.end()) { + connection = iter->second; + } else { + connection = new ContentHandlerConnection(this, content_handler_url); + url_to_content_handler_[content_handler_url] = connection; + } + + connection->content_handler()->StartApplication(application_request.Pass(), + url_response.Pass()); +} + +void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, + const GURL& url) { + URLToLoaderMap::iterator it = url_to_loader_.find(url); + if (it != url_to_loader_.end()) + delete it->second; + url_to_loader_[url] = loader.release(); +} + +void ApplicationManager::SetLoaderForScheme( + scoped_ptr<ApplicationLoader> loader, + const std::string& scheme) { + SchemeToLoaderMap::iterator it = scheme_to_loader_.find(scheme); + if (it != scheme_to_loader_.end()) + delete it->second; + scheme_to_loader_[scheme] = loader.release(); +} + +void ApplicationManager::SetNativeOptionsForURL( + const NativeRunnerFactory::Options& options, + const GURL& url) { + DCHECK(!url.has_query()); // Precondition. + // Apply mappings and resolution to get the resolved URL. + GURL resolved_url = + delegate_->ResolveMojoURL(delegate_->ResolveMappings(url)); + DCHECK(!resolved_url.has_query()); // Still shouldn't have query. + // TODO(vtl): We should probably also remove/disregard the query string (and + // maybe canonicalize in other ways). + DVLOG(2) << "Storing native options for resolved URL " << resolved_url + << " (original URL " << url << ")"; + url_to_native_options_[resolved_url] = options; +} + +ApplicationLoader* ApplicationManager::GetLoaderForURL(const GURL& url) { + auto url_it = url_to_loader_.find(GetBaseURLAndQuery(url, nullptr)); + if (url_it != url_to_loader_.end()) + return url_it->second; + auto scheme_it = scheme_to_loader_.find(url.scheme()); + if (scheme_it != scheme_to_loader_.end()) + return scheme_it->second; + return nullptr; +} + +void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) { + // Called from ~ShellImpl, so we do not need to call Destroy here. + const Identity identity = shell_impl->identity(); + base::Closure on_application_end = shell_impl->on_application_end(); + // Remove the shell. + auto it = identity_to_shell_impl_.find(identity); + DCHECK(it != identity_to_shell_impl_.end()); + delete it->second; + identity_to_shell_impl_.erase(it); + if (!on_application_end.is_null()) + on_application_end.Run(); +} + +void ApplicationManager::OnContentHandlerError( + ContentHandlerConnection* content_handler) { + // Remove the mapping to the content handler. + auto it = + url_to_content_handler_.find(content_handler->content_handler_url()); + DCHECK(it != url_to_content_handler_.end()); + delete it->second; + url_to_content_handler_.erase(it); +} + +ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName( + const GURL& application_url, + const std::string& interface_name) { + ServiceProviderPtr services; + ConnectToApplication(application_url, GURL(), GetProxy(&services), nullptr, + base::Closure()); + MessagePipe pipe; + services->ConnectToService(interface_name, pipe.handle1.Pass()); + return pipe.handle0.Pass(); +} + +void ApplicationManager::CleanupRunner(NativeRunner* runner) { + native_runners_.erase( + std::find(native_runners_.begin(), native_runners_.end(), runner)); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/application_manager.h b/mojo/shell/application_manager.h new file mode 100644 index 0000000..8e517f8 --- /dev/null +++ b/mojo/shell/application_manager.h
@@ -0,0 +1,232 @@ +// 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 SHELL_APPLICATION_MANAGER_APPLICATION_MANAGER_H_ +#define SHELL_APPLICATION_MANAGER_APPLICATION_MANAGER_H_ + +#include <map> + +#include "base/macros.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" +#include "base/memory/weak_ptr.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/interfaces/application/application.mojom.h" +#include "mojo/public/interfaces/application/service_provider.mojom.h" +#include "mojo/runner/native_application_support.h" +#include "mojo/services/network/public/interfaces/network_service.mojom.h" +#include "mojo/shell/application_loader.h" +#include "mojo/shell/identity.h" +#include "mojo/shell/native_runner.h" +#include "url/gurl.h" + +namespace base { +class FilePath; +class SequencedWorkerPool; +} + +namespace mojo { +namespace shell { + +class Fetcher; +class ShellImpl; + +class ApplicationManager { + public: + class Delegate { + public: + // Gives the delegate a chance to apply any mappings for the specified url. + // This should not resolve 'mojo' urls, that is done by ResolveMojoURL(). + virtual GURL ResolveMappings(const GURL& url) = 0; + + // Used to map a url with the scheme 'mojo' to the appropriate url. Return + // |url| if the scheme is not 'mojo'. + virtual GURL ResolveMojoURL(const GURL& url) = 0; + + protected: + virtual ~Delegate() {} + }; + + // API for testing. + class TestAPI { + public: + explicit TestAPI(ApplicationManager* manager); + ~TestAPI(); + + // Returns true if the shared instance has been created. + static bool HasCreatedInstance(); + // Returns true if there is a ShellImpl for this URL. + bool HasFactoryForURL(const GURL& url) const; + + private: + ApplicationManager* manager_; + + DISALLOW_COPY_AND_ASSIGN(TestAPI); + }; + + explicit ApplicationManager(Delegate* delegate); + ~ApplicationManager(); + + // Loads a service if necessary and establishes a new client connection. + void ConnectToApplication(const GURL& application_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const base::Closure& on_application_end); + + template <typename Interface> + inline void ConnectToService(const GURL& application_url, + InterfacePtr<Interface>* ptr) { + ScopedMessagePipeHandle service_handle = + ConnectToServiceByName(application_url, Interface::Name_); + ptr->Bind(service_handle.Pass()); + } + + ScopedMessagePipeHandle ConnectToServiceByName( + const GURL& application_url, + const std::string& interface_name); + + void RegisterContentHandler(const std::string& mime_type, + const GURL& content_handler_url); + + // Sets the default Loader to be used if not overridden by SetLoaderForURL() + // or SetLoaderForScheme(). + void set_default_loader(scoped_ptr<ApplicationLoader> loader) { + default_loader_ = loader.Pass(); + } + void set_native_runner_factory( + scoped_ptr<NativeRunnerFactory> runner_factory) { + native_runner_factory_ = runner_factory.Pass(); + } + void set_blocking_pool(base::SequencedWorkerPool* blocking_pool) { + blocking_pool_ = blocking_pool; + } + void set_disable_cache(bool disable_cache) { disable_cache_ = disable_cache; } + // Sets a Loader to be used for a specific url. + void SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, const GURL& url); + // Sets a Loader to be used for a specific url scheme. + void SetLoaderForScheme(scoped_ptr<ApplicationLoader> loader, + const std::string& scheme); + // These options will be used in running any native application at |url| + // (which shouldn't contain a query string). (|url| will be mapped and + // resolved, and any application whose base resolved URL matches it will have + // |options| applied.) + // TODO(vtl): This may not do what's desired if the resolved URL results in an + // HTTP redirect. Really, we want options to be identified with a particular + // implementation, maybe via a signed manifest or something like that. + void SetNativeOptionsForURL(const NativeRunnerFactory::Options& options, + const GURL& url); + + // Destroys all Shell-ends of connections established with Applications. + // Applications connected by this ApplicationManager will observe pipe errors + // and have a chance to shutdown. + void TerminateShellConnections(); + + // Removes a ShellImpl when it encounters an error. + void OnShellImplError(ShellImpl* shell_impl); + + private: + class ContentHandlerConnection; + + typedef std::map<std::string, ApplicationLoader*> SchemeToLoaderMap; + typedef std::map<GURL, ApplicationLoader*> URLToLoaderMap; + typedef std::map<Identity, ShellImpl*> IdentityToShellImplMap; + typedef std::map<GURL, ContentHandlerConnection*> URLToContentHandlerMap; + typedef std::map<std::string, GURL> MimeTypeToURLMap; + typedef std::map<GURL, NativeRunnerFactory::Options> URLToNativeOptionsMap; + + void ConnectToApplicationWithParameters( + const GURL& application_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const base::Closure& on_application_end, + const std::vector<std::string>& pre_redirect_parameters); + + bool ConnectToRunningApplication(const GURL& resolved_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider>* services, + ServiceProviderPtr* exposed_services); + + bool ConnectToApplicationWithLoader( + const GURL& resolved_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider>* services, + ServiceProviderPtr* exposed_services, + const base::Closure& on_application_end, + const std::vector<std::string>& parameters, + ApplicationLoader* loader); + + InterfaceRequest<Application> RegisterShell( + // The URL after resolution and redirects, including the querystring. + const GURL& resolved_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const base::Closure& on_application_end, + const std::vector<std::string>& parameters); + + ShellImpl* GetShellImpl(const GURL& url); + + void ConnectToClient(ShellImpl* shell_impl, + const GURL& resolved_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services); + + void HandleFetchCallback(const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const base::Closure& on_application_end, + const std::vector<std::string>& parameters, + NativeApplicationCleanup cleanup, + scoped_ptr<Fetcher> fetcher); + + void RunNativeApplication(InterfaceRequest<Application> application_request, + const NativeRunnerFactory::Options& options, + NativeApplicationCleanup cleanup, + scoped_ptr<Fetcher> fetcher, + const base::FilePath& file_path, + bool path_exists); + + void LoadWithContentHandler(const GURL& content_handler_url, + InterfaceRequest<Application> application_request, + URLResponsePtr url_response); + + // Returns the appropriate loader for |url|, or null if there is no loader + // configured for the URL. + ApplicationLoader* GetLoaderForURL(const GURL& url); + + // Removes a ContentHandler when it encounters an error. + void OnContentHandlerError(ContentHandlerConnection* content_handler); + + void CleanupRunner(NativeRunner* runner); + + Delegate* const delegate_; + // Loader management. + // Loaders are chosen in the order they are listed here. + URLToLoaderMap url_to_loader_; + SchemeToLoaderMap scheme_to_loader_; + scoped_ptr<ApplicationLoader> default_loader_; + scoped_ptr<NativeRunnerFactory> native_runner_factory_; + + IdentityToShellImplMap identity_to_shell_impl_; + URLToContentHandlerMap url_to_content_handler_; + // Note: The keys are URLs after mapping and resolving. + URLToNativeOptionsMap url_to_native_options_; + + base::SequencedWorkerPool* blocking_pool_; + NetworkServicePtr network_service_; + MimeTypeToURLMap mime_type_to_url_; + ScopedVector<NativeRunner> native_runners_; + bool disable_cache_; + base::WeakPtrFactory<ApplicationManager> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(ApplicationManager); +}; + +} // namespace shell +} // namespace mojo + +#endif // SHELL_APPLICATION_MANAGER_APPLICATION_MANAGER_H_
diff --git a/mojo/shell/application_manager/BUILD.gn b/mojo/shell/application_manager/BUILD.gn deleted file mode 100644 index 9122e7e9..0000000 --- a/mojo/shell/application_manager/BUILD.gn +++ /dev/null
@@ -1,77 +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. - -import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") -import("//testing/test.gni") - -source_set("application_manager") { - output_name = "mojo_application_manager" - sources = [ - "application_loader.h", - "application_manager.cc", - "application_manager.h", - "data_pipe_peek.cc", - "data_pipe_peek.h", - "fetcher.cc", - "fetcher.h", - "identity.cc", - "identity.h", - "local_fetcher.cc", - "local_fetcher.h", - "native_runner.h", - "network_fetcher.cc", - "network_fetcher.h", - "query_util.cc", - "query_util.h", - "shell_impl.cc", - "shell_impl.h", - ] - - public_deps = [ - "//base", - "//mojo/common", - "//third_party/mojo/src/mojo/public/interfaces/application:application", - "//mojo/services/network/public/interfaces", - "//url", - ] - deps = [ - "//base/third_party/dynamic_annotations", - "//crypto:crypto", - "//url", - "//third_party/mojo/src/mojo/edk/system", - "//mojo/environment:chromium", - "//third_party/mojo_services/src/content_handler/public/interfaces", - "//mojo/shell:native_application_support", - "//mojo/shell:switches", - ] -} - -test("tests") { - output_name = "mojo_application_manager_unittests" - - sources = [ - "application_manager_unittest.cc", - "query_util_unittest.cc", - ] - - deps = [ - ":application_manager", - ":test_bindings", - "//base", - "//mojo/application", - "//mojo/common", - "//third_party/mojo/src/mojo/edk/test:run_all_unittests", - "//mojo/environment:chromium", - "//third_party/mojo/src/mojo/public/cpp/application", - "//third_party/mojo/src/mojo/public/cpp/bindings", - "//testing/gtest", - "//url", - ] -} - -mojom("test_bindings") { - sources = [ - "test.mojom", - ] -}
diff --git a/mojo/shell/application_manager/application_manager.cc b/mojo/shell/application_manager/application_manager.cc deleted file mode 100644 index 8c908a7..0000000 --- a/mojo/shell/application_manager/application_manager.cc +++ /dev/null
@@ -1,473 +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 "mojo/shell/application_manager/application_manager.h" - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/stl_util.h" -#include "base/strings/string_util.h" -#include "base/trace_event/trace_event.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/error_handler.h" -#include "mojo/shell/application_manager/fetcher.h" -#include "mojo/shell/application_manager/local_fetcher.h" -#include "mojo/shell/application_manager/network_fetcher.h" -#include "mojo/shell/application_manager/query_util.h" -#include "mojo/shell/application_manager/shell_impl.h" -#include "mojo/shell/switches.h" -#include "third_party/mojo_services/src/content_handler/public/interfaces/content_handler.mojom.h" - -namespace mojo { -namespace shell { - -namespace { - -// Used by TestAPI. -bool has_created_instance = false; - -} // namespace - -ApplicationManager::Delegate::~Delegate() { -} - -GURL ApplicationManager::Delegate::ResolveURL(const GURL& url) { - return url; -} - -GURL ApplicationManager::Delegate::ResolveMappings(const GURL& url) { - return url; -} - -class ApplicationManager::ContentHandlerConnection : public ErrorHandler { - public: - ContentHandlerConnection(ApplicationManager* manager, - const GURL& content_handler_url) - : manager_(manager), content_handler_url_(content_handler_url) { - ServiceProviderPtr services; - manager->ConnectToApplication(content_handler_url, GURL(), - GetProxy(&services), nullptr, - base::Closure()); - MessagePipe pipe; - content_handler_.Bind(pipe.handle0.Pass()); - services->ConnectToService(ContentHandler::Name_, pipe.handle1.Pass()); - content_handler_.set_error_handler(this); - } - - ContentHandler* content_handler() { return content_handler_.get(); } - - GURL content_handler_url() { return content_handler_url_; } - - private: - // ErrorHandler implementation: - void OnConnectionError() override { manager_->OnContentHandlerError(this); } - - ApplicationManager* manager_; - GURL content_handler_url_; - ContentHandlerPtr content_handler_; - - DISALLOW_COPY_AND_ASSIGN(ContentHandlerConnection); -}; - -// static -ApplicationManager::TestAPI::TestAPI(ApplicationManager* manager) - : manager_(manager) { -} - -ApplicationManager::TestAPI::~TestAPI() { -} - -bool ApplicationManager::TestAPI::HasCreatedInstance() { - return has_created_instance; -} - -bool ApplicationManager::TestAPI::HasFactoryForURL(const GURL& url) const { - return manager_->identity_to_shell_impl_.find(Identity(url)) != - manager_->identity_to_shell_impl_.end(); -} - -ApplicationManager::ApplicationManager(Delegate* delegate) - : delegate_(delegate), weak_ptr_factory_(this) { -} - -ApplicationManager::~ApplicationManager() { - STLDeleteValues(&url_to_content_handler_); - TerminateShellConnections(); - STLDeleteValues(&url_to_loader_); - STLDeleteValues(&scheme_to_loader_); -} - -void ApplicationManager::TerminateShellConnections() { - STLDeleteValues(&identity_to_shell_impl_); -} - -void ApplicationManager::ConnectToApplication( - const GURL& requested_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const base::Closure& on_application_end) { - ConnectToApplicationWithParameters( - requested_url, requestor_url, services.Pass(), exposed_services.Pass(), - on_application_end, std::vector<std::string>()); -} - -void ApplicationManager::ConnectToApplicationWithParameters( - const GURL& requested_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const base::Closure& on_application_end, - const std::vector<std::string>& pre_redirect_parameters) { - TRACE_EVENT_INSTANT1( - "mojo_shell", "ApplicationManager::ConnectToApplicationWithParameters", - TRACE_EVENT_SCOPE_THREAD, "requested_url", requested_url.spec()); - DCHECK(requested_url.is_valid()); - - // We check both the mapped and resolved urls for existing shell_impls because - // external applications can be registered for the unresolved mojo:foo urls. - - GURL mapped_url = delegate_->ResolveMappings(requested_url); - if (ConnectToRunningApplication(mapped_url, requestor_url, &services, - &exposed_services)) { - return; - } - - GURL resolved_url = delegate_->ResolveURL(mapped_url); - if (ConnectToRunningApplication(resolved_url, requestor_url, &services, - &exposed_services)) { - return; - } - - // The application is not running, let's compute the parameters. - if (ConnectToApplicationWithLoader(mapped_url, requestor_url, &services, - &exposed_services, on_application_end, - pre_redirect_parameters, - GetLoaderForURL(mapped_url))) { - return; - } - - if (ConnectToApplicationWithLoader(resolved_url, requestor_url, &services, - &exposed_services, on_application_end, - pre_redirect_parameters, - GetLoaderForURL(resolved_url))) { - return; - } - - if (ConnectToApplicationWithLoader( - resolved_url, requestor_url, &services, &exposed_services, - on_application_end, pre_redirect_parameters, default_loader_.get())) { - return; - } - - auto callback = base::Bind(&ApplicationManager::HandleFetchCallback, - weak_ptr_factory_.GetWeakPtr(), requestor_url, - base::Passed(services.Pass()), - base::Passed(exposed_services.Pass()), - on_application_end, pre_redirect_parameters); - - if (resolved_url.SchemeIsFile()) { - new LocalFetcher( - resolved_url, GetBaseURLAndQuery(resolved_url, nullptr), - base::Bind(callback, NativeApplicationCleanup::DONT_DELETE)); - return; - } - - if (!network_service_) - ConnectToService(GURL("mojo:network_service"), &network_service_); - - const NativeApplicationCleanup cleanup = - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDontDeleteOnDownload) - ? NativeApplicationCleanup::DONT_DELETE - : NativeApplicationCleanup::DELETE; - - new NetworkFetcher(disable_cache_, resolved_url, network_service_.get(), - base::Bind(callback, cleanup)); -} - -bool ApplicationManager::ConnectToRunningApplication( - const GURL& resolved_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider>* services, - ServiceProviderPtr* exposed_services) { - GURL application_url = GetBaseURLAndQuery(resolved_url, nullptr); - ShellImpl* shell_impl = GetShellImpl(application_url); - if (!shell_impl) - return false; - - ConnectToClient(shell_impl, resolved_url, requestor_url, services->Pass(), - exposed_services->Pass()); - return true; -} - -bool ApplicationManager::ConnectToApplicationWithLoader( - const GURL& resolved_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider>* services, - ServiceProviderPtr* exposed_services, - const base::Closure& on_application_end, - const std::vector<std::string>& parameters, - ApplicationLoader* loader) { - if (!loader) - return false; - - loader->Load( - resolved_url, - RegisterShell(resolved_url, requestor_url, services->Pass(), - exposed_services->Pass(), on_application_end, parameters)); - return true; -} - -InterfaceRequest<Application> ApplicationManager::RegisterShell( - const GURL& resolved_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const base::Closure& on_application_end, - const std::vector<std::string>& parameters) { - Identity app_identity(resolved_url); - - ApplicationPtr application; - InterfaceRequest<Application> application_request = GetProxy(&application); - ShellImpl* shell = - new ShellImpl(application.Pass(), this, app_identity, on_application_end); - identity_to_shell_impl_[app_identity] = shell; - shell->InitializeApplication(Array<String>::From(parameters)); - ConnectToClient(shell, resolved_url, requestor_url, services.Pass(), - exposed_services.Pass()); - return application_request.Pass(); -} - -ShellImpl* ApplicationManager::GetShellImpl(const GURL& url) { - const auto& shell_it = identity_to_shell_impl_.find(Identity(url)); - if (shell_it != identity_to_shell_impl_.end()) - return shell_it->second; - return nullptr; -} - -void ApplicationManager::ConnectToClient( - ShellImpl* shell_impl, - const GURL& resolved_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) { - shell_impl->ConnectToClient(resolved_url, requestor_url, services.Pass(), - exposed_services.Pass()); -} - -void ApplicationManager::HandleFetchCallback( - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const base::Closure& on_application_end, - const std::vector<std::string>& parameters, - NativeApplicationCleanup cleanup, - scoped_ptr<Fetcher> fetcher) { - if (!fetcher) { - // Network error. Drop |application_request| to tell requestor. - return; - } - - GURL redirect_url = fetcher->GetRedirectURL(); - if (!redirect_url.is_empty()) { - // And around we go again... Whee! - ConnectToApplicationWithParameters(redirect_url, requestor_url, - services.Pass(), exposed_services.Pass(), - on_application_end, parameters); - return; - } - - // We already checked if the application was running before we fetched it, but - // it might have started while the fetch was outstanding. We don't want to - // have two copies of the app running, so check again. - // - // Also, it's possible the original URL was redirected to an app that is - // already running. - if (ConnectToRunningApplication(fetcher->GetURL(), requestor_url, &services, - &exposed_services)) { - return; - } - - InterfaceRequest<Application> request( - RegisterShell(fetcher->GetURL(), requestor_url, services.Pass(), - exposed_services.Pass(), on_application_end, parameters)); - - // If the response begins with a #!mojo <content-handler-url>, use it. - GURL content_handler_url; - std::string shebang; - if (fetcher->PeekContentHandler(&shebang, &content_handler_url)) { - LoadWithContentHandler( - content_handler_url, request.Pass(), - fetcher->AsURLResponse(blocking_pool_, - static_cast<int>(shebang.size()))); - return; - } - - MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(fetcher->MimeType()); - if (iter != mime_type_to_url_.end()) { - LoadWithContentHandler(iter->second, request.Pass(), - fetcher->AsURLResponse(blocking_pool_, 0)); - return; - } - - // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo - // application. That could either mean looking for the platform-specific dll - // header, or looking for some specific mojo signature prepended to the - // library. - // TODO(vtl): (Maybe this should be done by the factory/runner?) - - GURL base_resolved_url = GetBaseURLAndQuery(fetcher->GetURL(), nullptr); - NativeRunnerFactory::Options options; - if (url_to_native_options_.find(base_resolved_url) != - url_to_native_options_.end()) { - DVLOG(2) << "Applying stored native options to resolved URL " - << fetcher->GetURL(); - options = url_to_native_options_[base_resolved_url]; - } - - fetcher->AsPath( - blocking_pool_, - base::Bind(&ApplicationManager::RunNativeApplication, - weak_ptr_factory_.GetWeakPtr(), base::Passed(request.Pass()), - options, cleanup, base::Passed(fetcher.Pass()))); -} - -void ApplicationManager::RunNativeApplication( - InterfaceRequest<Application> application_request, - const NativeRunnerFactory::Options& options, - NativeApplicationCleanup cleanup, - scoped_ptr<Fetcher> fetcher, - const base::FilePath& path, - bool path_exists) { - // We only passed fetcher to keep it alive. Done with it now. - fetcher.reset(); - - DCHECK(application_request.is_pending()); - - if (!path_exists) { - LOG(ERROR) << "Library not started because library path '" << path.value() - << "' does not exist."; - return; - } - - TRACE_EVENT1("mojo_shell", "ApplicationManager::RunNativeApplication", "path", - path.AsUTF8Unsafe()); - NativeRunner* runner = native_runner_factory_->Create(options).release(); - native_runners_.push_back(runner); - runner->Start(path, cleanup, application_request.Pass(), - base::Bind(&ApplicationManager::CleanupRunner, - weak_ptr_factory_.GetWeakPtr(), runner)); -} - -void ApplicationManager::RegisterContentHandler( - const std::string& mime_type, - const GURL& content_handler_url) { - DCHECK(content_handler_url.is_valid()) - << "Content handler URL is invalid for mime type " << mime_type; - mime_type_to_url_[mime_type] = content_handler_url; -} - -void ApplicationManager::LoadWithContentHandler( - const GURL& content_handler_url, - InterfaceRequest<Application> application_request, - URLResponsePtr url_response) { - ContentHandlerConnection* connection = nullptr; - URLToContentHandlerMap::iterator iter = - url_to_content_handler_.find(content_handler_url); - if (iter != url_to_content_handler_.end()) { - connection = iter->second; - } else { - connection = new ContentHandlerConnection(this, content_handler_url); - url_to_content_handler_[content_handler_url] = connection; - } - - connection->content_handler()->StartApplication(application_request.Pass(), - url_response.Pass()); -} - -void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, - const GURL& url) { - URLToLoaderMap::iterator it = url_to_loader_.find(url); - if (it != url_to_loader_.end()) - delete it->second; - url_to_loader_[url] = loader.release(); -} - -void ApplicationManager::SetLoaderForScheme( - scoped_ptr<ApplicationLoader> loader, - const std::string& scheme) { - SchemeToLoaderMap::iterator it = scheme_to_loader_.find(scheme); - if (it != scheme_to_loader_.end()) - delete it->second; - scheme_to_loader_[scheme] = loader.release(); -} - -void ApplicationManager::SetNativeOptionsForURL( - const NativeRunnerFactory::Options& options, - const GURL& url) { - DCHECK(!url.has_query()); // Precondition. - // Apply mappings and resolution to get the resolved URL. - GURL resolved_url = delegate_->ResolveURL(delegate_->ResolveMappings(url)); - DCHECK(!resolved_url.has_query()); // Still shouldn't have query. - // TODO(vtl): We should probably also remove/disregard the query string (and - // maybe canonicalize in other ways). - DVLOG(2) << "Storing native options for resolved URL " << resolved_url - << " (original URL " << url << ")"; - url_to_native_options_[resolved_url] = options; -} - -ApplicationLoader* ApplicationManager::GetLoaderForURL(const GURL& url) { - auto url_it = url_to_loader_.find(GetBaseURLAndQuery(url, nullptr)); - if (url_it != url_to_loader_.end()) - return url_it->second; - auto scheme_it = scheme_to_loader_.find(url.scheme()); - if (scheme_it != scheme_to_loader_.end()) - return scheme_it->second; - return nullptr; -} - -void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) { - // Called from ~ShellImpl, so we do not need to call Destroy here. - const Identity identity = shell_impl->identity(); - base::Closure on_application_end = shell_impl->on_application_end(); - // Remove the shell. - auto it = identity_to_shell_impl_.find(identity); - DCHECK(it != identity_to_shell_impl_.end()); - delete it->second; - identity_to_shell_impl_.erase(it); - if (!on_application_end.is_null()) - on_application_end.Run(); -} - -void ApplicationManager::OnContentHandlerError( - ContentHandlerConnection* content_handler) { - // Remove the mapping to the content handler. - auto it = - url_to_content_handler_.find(content_handler->content_handler_url()); - DCHECK(it != url_to_content_handler_.end()); - delete it->second; - url_to_content_handler_.erase(it); -} - -ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName( - const GURL& application_url, - const std::string& interface_name) { - ServiceProviderPtr services; - ConnectToApplication(application_url, GURL(), GetProxy(&services), nullptr, - base::Closure()); - MessagePipe pipe; - services->ConnectToService(interface_name, pipe.handle1.Pass()); - return pipe.handle0.Pass(); -} - -void ApplicationManager::CleanupRunner(NativeRunner* runner) { - native_runners_.erase( - std::find(native_runners_.begin(), native_runners_.end(), runner)); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/application_manager.h b/mojo/shell/application_manager/application_manager.h deleted file mode 100644 index 44e581d..0000000 --- a/mojo/shell/application_manager/application_manager.h +++ /dev/null
@@ -1,225 +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 SHELL_APPLICATION_MANAGER_APPLICATION_MANAGER_H_ -#define SHELL_APPLICATION_MANAGER_APPLICATION_MANAGER_H_ - -#include <map> - -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/memory/weak_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/interfaces/application/application.mojom.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" -#include "mojo/services/network/public/interfaces/network_service.mojom.h" -#include "mojo/shell/application_manager/application_loader.h" -#include "mojo/shell/application_manager/identity.h" -#include "mojo/shell/application_manager/native_runner.h" -#include "mojo/shell/native_application_support.h" -#include "url/gurl.h" - -namespace base { -class FilePath; -class SequencedWorkerPool; -} - -namespace mojo { -namespace shell { - -class Fetcher; -class ShellImpl; - -class ApplicationManager { - public: - class Delegate { - public: - virtual ~Delegate(); - virtual GURL ResolveURL(const GURL& url); - virtual GURL ResolveMappings(const GURL& url); - }; - - // API for testing. - class TestAPI { - public: - explicit TestAPI(ApplicationManager* manager); - ~TestAPI(); - - // Returns true if the shared instance has been created. - static bool HasCreatedInstance(); - // Returns true if there is a ShellImpl for this URL. - bool HasFactoryForURL(const GURL& url) const; - - private: - ApplicationManager* manager_; - - DISALLOW_COPY_AND_ASSIGN(TestAPI); - }; - - explicit ApplicationManager(Delegate* delegate); - ~ApplicationManager(); - - // Loads a service if necessary and establishes a new client connection. - void ConnectToApplication(const GURL& application_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const base::Closure& on_application_end); - - template <typename Interface> - inline void ConnectToService(const GURL& application_url, - InterfacePtr<Interface>* ptr) { - ScopedMessagePipeHandle service_handle = - ConnectToServiceByName(application_url, Interface::Name_); - ptr->Bind(service_handle.Pass()); - } - - ScopedMessagePipeHandle ConnectToServiceByName( - const GURL& application_url, - const std::string& interface_name); - - void RegisterContentHandler(const std::string& mime_type, - const GURL& content_handler_url); - - // Sets the default Loader to be used if not overridden by SetLoaderForURL() - // or SetLoaderForScheme(). - void set_default_loader(scoped_ptr<ApplicationLoader> loader) { - default_loader_ = loader.Pass(); - } - void set_native_runner_factory( - scoped_ptr<NativeRunnerFactory> runner_factory) { - native_runner_factory_ = runner_factory.Pass(); - } - void set_blocking_pool(base::SequencedWorkerPool* blocking_pool) { - blocking_pool_ = blocking_pool; - } - void set_disable_cache(bool disable_cache) { disable_cache_ = disable_cache; } - // Sets a Loader to be used for a specific url. - void SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, const GURL& url); - // Sets a Loader to be used for a specific url scheme. - void SetLoaderForScheme(scoped_ptr<ApplicationLoader> loader, - const std::string& scheme); - // These options will be used in running any native application at |url| - // (which shouldn't contain a query string). (|url| will be mapped and - // resolved, and any application whose base resolved URL matches it will have - // |options| applied.) - // TODO(vtl): This may not do what's desired if the resolved URL results in an - // HTTP redirect. Really, we want options to be identified with a particular - // implementation, maybe via a signed manifest or something like that. - void SetNativeOptionsForURL(const NativeRunnerFactory::Options& options, - const GURL& url); - - // Destroys all Shell-ends of connections established with Applications. - // Applications connected by this ApplicationManager will observe pipe errors - // and have a chance to shutdown. - void TerminateShellConnections(); - - // Removes a ShellImpl when it encounters an error. - void OnShellImplError(ShellImpl* shell_impl); - - private: - class ContentHandlerConnection; - - typedef std::map<std::string, ApplicationLoader*> SchemeToLoaderMap; - typedef std::map<GURL, ApplicationLoader*> URLToLoaderMap; - typedef std::map<Identity, ShellImpl*> IdentityToShellImplMap; - typedef std::map<GURL, ContentHandlerConnection*> URLToContentHandlerMap; - typedef std::map<std::string, GURL> MimeTypeToURLMap; - typedef std::map<GURL, NativeRunnerFactory::Options> URLToNativeOptionsMap; - - void ConnectToApplicationWithParameters( - const GURL& application_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const base::Closure& on_application_end, - const std::vector<std::string>& pre_redirect_parameters); - - bool ConnectToRunningApplication(const GURL& resolved_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider>* services, - ServiceProviderPtr* exposed_services); - - bool ConnectToApplicationWithLoader( - const GURL& resolved_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider>* services, - ServiceProviderPtr* exposed_services, - const base::Closure& on_application_end, - const std::vector<std::string>& parameters, - ApplicationLoader* loader); - - InterfaceRequest<Application> RegisterShell( - // The URL after resolution and redirects, including the querystring. - const GURL& resolved_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const base::Closure& on_application_end, - const std::vector<std::string>& parameters); - - ShellImpl* GetShellImpl(const GURL& url); - - void ConnectToClient(ShellImpl* shell_impl, - const GURL& resolved_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services); - - void HandleFetchCallback(const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const base::Closure& on_application_end, - const std::vector<std::string>& parameters, - NativeApplicationCleanup cleanup, - scoped_ptr<Fetcher> fetcher); - - void RunNativeApplication(InterfaceRequest<Application> application_request, - const NativeRunnerFactory::Options& options, - NativeApplicationCleanup cleanup, - scoped_ptr<Fetcher> fetcher, - const base::FilePath& file_path, - bool path_exists); - - void LoadWithContentHandler(const GURL& content_handler_url, - InterfaceRequest<Application> application_request, - URLResponsePtr url_response); - - // Returns the appropriate loader for |url|, or null if there is no loader - // configured for the URL. - ApplicationLoader* GetLoaderForURL(const GURL& url); - - // Removes a ContentHandler when it encounters an error. - void OnContentHandlerError(ContentHandlerConnection* content_handler); - - void CleanupRunner(NativeRunner* runner); - - Delegate* const delegate_; - // Loader management. - // Loaders are chosen in the order they are listed here. - URLToLoaderMap url_to_loader_; - SchemeToLoaderMap scheme_to_loader_; - scoped_ptr<ApplicationLoader> default_loader_; - scoped_ptr<NativeRunnerFactory> native_runner_factory_; - - IdentityToShellImplMap identity_to_shell_impl_; - URLToContentHandlerMap url_to_content_handler_; - // Note: The keys are URLs after mapping and resolving. - URLToNativeOptionsMap url_to_native_options_; - - base::SequencedWorkerPool* blocking_pool_; - NetworkServicePtr network_service_; - MimeTypeToURLMap mime_type_to_url_; - ScopedVector<NativeRunner> native_runners_; - bool disable_cache_; - base::WeakPtrFactory<ApplicationManager> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(ApplicationManager); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_APPLICATION_MANAGER_H_
diff --git a/mojo/shell/application_manager/application_manager_unittest.cc b/mojo/shell/application_manager/application_manager_unittest.cc deleted file mode 100644 index f801e36..0000000 --- a/mojo/shell/application_manager/application_manager_unittest.cc +++ /dev/null
@@ -1,743 +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 "base/at_exit.h" -#include "base/bind.h" -#include "base/macros.h" -#include "base/memory/scoped_vector.h" -#include "base/message_loop/message_loop.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/application/interface_factory.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" -#include "mojo/shell/application_manager/application_loader.h" -#include "mojo/shell/application_manager/application_manager.h" -#include "mojo/shell/application_manager/test.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { -namespace { - -const char kTestURLString[] = "test:testService"; -const char kTestAURLString[] = "test:TestA"; -const char kTestBURLString[] = "test:TestB"; - -struct TestContext { - TestContext() : num_impls(0), num_loader_deletes(0) {} - std::string last_test_string; - int num_impls; - int num_loader_deletes; -}; - -void QuitClosure(bool* value) { - *value = true; - base::MessageLoop::current()->QuitWhenIdle(); -} - -class QuitMessageLoopErrorHandler : public ErrorHandler { - public: - QuitMessageLoopErrorHandler() {} - ~QuitMessageLoopErrorHandler() override {} - - // |ErrorHandler| implementation: - void OnConnectionError() override { - base::MessageLoop::current()->QuitWhenIdle(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler); -}; - -class TestServiceImpl : public TestService { - public: - TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request) - : context_(context), binding_(this, request.Pass()) { - ++context_->num_impls; - } - - ~TestServiceImpl() override { - --context_->num_impls; - if (!base::MessageLoop::current()->is_running()) - return; - base::MessageLoop::current()->Quit(); - } - - // TestService implementation: - void Test(const String& test_string, - const Callback<void()>& callback) override { - context_->last_test_string = test_string; - callback.Run(); - } - - private: - TestContext* context_; - StrongBinding<TestService> binding_; -}; - -class TestClient { - public: - explicit TestClient(TestServicePtr service) - : service_(service.Pass()), quit_after_ack_(false) {} - - void AckTest() { - if (quit_after_ack_) - base::MessageLoop::current()->Quit(); - } - - void Test(const std::string& test_string) { - quit_after_ack_ = true; - service_->Test(test_string, - base::Bind(&TestClient::AckTest, base::Unretained(this))); - } - - private: - TestServicePtr service_; - bool quit_after_ack_; - DISALLOW_COPY_AND_ASSIGN(TestClient); -}; - -class TestApplicationLoader : public ApplicationLoader, - public ApplicationDelegate, - public InterfaceFactory<TestService> { - public: - TestApplicationLoader() : context_(nullptr), num_loads_(0) {} - - ~TestApplicationLoader() override { - if (context_) - ++context_->num_loader_deletes; - test_app_.reset(); - } - - void set_context(TestContext* context) { context_ = context; } - int num_loads() const { return num_loads_; } - const std::vector<std::string>& GetArgs() const { return test_app_->args(); } - - private: - // ApplicationLoader implementation. - void Load(const GURL& url, - InterfaceRequest<Application> application_request) override { - ++num_loads_; - test_app_.reset(new ApplicationImpl(this, application_request.Pass())); - } - - // ApplicationDelegate implementation. - bool ConfigureIncomingConnection(ApplicationConnection* connection) override { - connection->AddService(this); - return true; - } - - // InterfaceFactory implementation. - void Create(ApplicationConnection* connection, - InterfaceRequest<TestService> request) override { - new TestServiceImpl(context_, request.Pass()); - } - - scoped_ptr<ApplicationImpl> test_app_; - TestContext* context_; - int num_loads_; - DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader); -}; - -class ClosingApplicationLoader : public ApplicationLoader { - private: - // ApplicationLoader implementation. - void Load(const GURL& url, - InterfaceRequest<Application> application_request) override {} -}; - -class TesterContext { - public: - explicit TesterContext(base::MessageLoop* loop) - : num_b_calls_(0), - num_c_calls_(0), - num_a_deletes_(0), - num_b_deletes_(0), - num_c_deletes_(0), - tester_called_quit_(false), - a_called_quit_(false), - loop_(loop) {} - - void IncrementNumBCalls() { - base::AutoLock lock(lock_); - num_b_calls_++; - } - - void IncrementNumCCalls() { - base::AutoLock lock(lock_); - num_c_calls_++; - } - - void IncrementNumADeletes() { - base::AutoLock lock(lock_); - num_a_deletes_++; - } - - void IncrementNumBDeletes() { - base::AutoLock lock(lock_); - num_b_deletes_++; - } - - void IncrementNumCDeletes() { - base::AutoLock lock(lock_); - num_c_deletes_++; - } - - void set_tester_called_quit() { - base::AutoLock lock(lock_); - tester_called_quit_ = true; - } - - void set_a_called_quit() { - base::AutoLock lock(lock_); - a_called_quit_ = true; - } - - int num_b_calls() { - base::AutoLock lock(lock_); - return num_b_calls_; - } - int num_c_calls() { - base::AutoLock lock(lock_); - return num_c_calls_; - } - int num_a_deletes() { - base::AutoLock lock(lock_); - return num_a_deletes_; - } - int num_b_deletes() { - base::AutoLock lock(lock_); - return num_b_deletes_; - } - int num_c_deletes() { - base::AutoLock lock(lock_); - return num_c_deletes_; - } - bool tester_called_quit() { - base::AutoLock lock(lock_); - return tester_called_quit_; - } - bool a_called_quit() { - base::AutoLock lock(lock_); - return a_called_quit_; - } - - void QuitSoon() { - loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); - } - - private: - // lock_ protects all members except for loop_ which must be unchanged for the - // lifetime of this class. - base::Lock lock_; - int num_b_calls_; - int num_c_calls_; - int num_a_deletes_; - int num_b_deletes_; - int num_c_deletes_; - bool tester_called_quit_; - bool a_called_quit_; - - base::MessageLoop* loop_; -}; - -// Used to test that the requestor url will be correctly passed. -class TestAImpl : public TestA { - public: - TestAImpl(ApplicationImpl* app_impl, - TesterContext* test_context, - InterfaceRequest<TestA> request) - : test_context_(test_context), binding_(this, request.Pass()) { - app_impl->ConnectToApplication(kTestBURLString)->ConnectToService(&b_); - } - - ~TestAImpl() override { - test_context_->IncrementNumADeletes(); - if (base::MessageLoop::current()->is_running()) - Quit(); - } - - private: - void CallB() override { - b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this))); - } - - void CallCFromB() override { - b_->CallC(base::Bind(&TestAImpl::Quit, base::Unretained(this))); - } - - void Quit() { - base::MessageLoop::current()->Quit(); - test_context_->set_a_called_quit(); - test_context_->QuitSoon(); - } - - TesterContext* test_context_; - TestBPtr b_; - StrongBinding<TestA> binding_; -}; - -class TestBImpl : public TestB { - public: - TestBImpl(ApplicationConnection* connection, - TesterContext* test_context, - InterfaceRequest<TestB> request) - : test_context_(test_context), binding_(this, request.Pass()) { - connection->ConnectToService(&c_); - } - - ~TestBImpl() override { - test_context_->IncrementNumBDeletes(); - if (base::MessageLoop::current()->is_running()) - base::MessageLoop::current()->Quit(); - test_context_->QuitSoon(); - } - - private: - void B(const Callback<void()>& callback) override { - test_context_->IncrementNumBCalls(); - callback.Run(); - } - - void CallC(const Callback<void()>& callback) override { - test_context_->IncrementNumBCalls(); - c_->C(callback); - } - - TesterContext* test_context_; - TestCPtr c_; - StrongBinding<TestB> binding_; -}; - -class TestCImpl : public TestC { - public: - TestCImpl(ApplicationConnection* connection, - TesterContext* test_context, - InterfaceRequest<TestC> request) - : test_context_(test_context), binding_(this, request.Pass()) {} - - ~TestCImpl() override { test_context_->IncrementNumCDeletes(); } - - private: - void C(const Callback<void()>& callback) override { - test_context_->IncrementNumCCalls(); - callback.Run(); - } - - TesterContext* test_context_; - StrongBinding<TestC> binding_; -}; - -class Tester : public ApplicationDelegate, - public ApplicationLoader, - public InterfaceFactory<TestA>, - public InterfaceFactory<TestB>, - public InterfaceFactory<TestC> { - public: - Tester(TesterContext* context, const std::string& requestor_url) - : context_(context), requestor_url_(requestor_url) {} - ~Tester() override {} - - private: - void Load(const GURL& url, - InterfaceRequest<Application> application_request) override { - app_.reset(new ApplicationImpl(this, application_request.Pass())); - } - - bool ConfigureIncomingConnection(ApplicationConnection* connection) override { - if (!requestor_url_.empty() && - requestor_url_ != connection->GetRemoteApplicationURL()) { - context_->set_tester_called_quit(); - context_->QuitSoon(); - base::MessageLoop::current()->Quit(); - return false; - } - // If we're coming from A, then add B, otherwise A. - if (connection->GetRemoteApplicationURL() == kTestAURLString) - connection->AddService<TestB>(this); - else - connection->AddService<TestA>(this); - return true; - } - - bool ConfigureOutgoingConnection(ApplicationConnection* connection) override { - // If we're connecting to B, then add C. - if (connection->GetRemoteApplicationURL() == kTestBURLString) - connection->AddService<TestC>(this); - return true; - } - - void Create(ApplicationConnection* connection, - InterfaceRequest<TestA> request) override { - a_bindings_.push_back(new TestAImpl(app_.get(), context_, request.Pass())); - } - - void Create(ApplicationConnection* connection, - InterfaceRequest<TestB> request) override { - new TestBImpl(connection, context_, request.Pass()); - } - - void Create(ApplicationConnection* connection, - InterfaceRequest<TestC> request) override { - new TestCImpl(connection, context_, request.Pass()); - } - - TesterContext* context_; - scoped_ptr<ApplicationImpl> app_; - std::string requestor_url_; - ScopedVector<TestAImpl> a_bindings_; -}; - -class TestDelegate : public ApplicationManager::Delegate { - public: - void AddMapping(const GURL& from, const GURL& to) { mappings_[from] = to; } - - // ApplicationManager::Delegate - GURL ResolveMappings(const GURL& url) override { - auto it = mappings_.find(url); - if (it != mappings_.end()) - return it->second; - return url; - } - - // ApplicationManager::Delegate - GURL ResolveURL(const GURL& url) override { - GURL mapped_url = ResolveMappings(url); - // The shell automatically map mojo URLs. - if (mapped_url.scheme() == "mojo") { - url::Replacements<char> replacements; - replacements.SetScheme("file", url::Component(0, 4)); - mapped_url = mapped_url.ReplaceComponents(replacements); - } - return mapped_url; - } - - private: - std::map<GURL, GURL> mappings_; -}; - -class ApplicationManagerTest : public testing::Test { - public: - ApplicationManagerTest() : tester_context_(&loop_) {} - - ~ApplicationManagerTest() override {} - - void SetUp() override { - application_manager_.reset(new ApplicationManager(&test_delegate_)); - test_loader_ = new TestApplicationLoader; - test_loader_->set_context(&context_); - application_manager_->set_default_loader( - scoped_ptr<ApplicationLoader>(test_loader_)); - - TestServicePtr service_proxy; - application_manager_->ConnectToService(GURL(kTestURLString), - &service_proxy); - test_client_.reset(new TestClient(service_proxy.Pass())); - } - - void TearDown() override { - test_client_.reset(); - application_manager_.reset(); - } - - void AddLoaderForURL(const GURL& url, const std::string& requestor_url) { - application_manager_->SetLoaderForURL( - make_scoped_ptr(new Tester(&tester_context_, requestor_url)), url); - } - - bool HasFactoryForTestURL() { - ApplicationManager::TestAPI manager_test_api(application_manager_.get()); - return manager_test_api.HasFactoryForURL(GURL(kTestURLString)); - } - - protected: - base::ShadowingAtExitManager at_exit_; - TestDelegate test_delegate_; - TestApplicationLoader* test_loader_; - TesterContext tester_context_; - TestContext context_; - base::MessageLoop loop_; - scoped_ptr<TestClient> test_client_; - scoped_ptr<ApplicationManager> application_manager_; - DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest); -}; - -TEST_F(ApplicationManagerTest, Basic) { - test_client_->Test("test"); - loop_.Run(); - EXPECT_EQ(std::string("test"), context_.last_test_string); -} - -// Confirm that no arguments are sent to an application by default. -TEST_F(ApplicationManagerTest, NoArgs) { - ApplicationManager am(&test_delegate_); - GURL test_url("test:test"); - TestApplicationLoader* loader = new TestApplicationLoader; - loader->set_context(&context_); - am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url); - TestServicePtr test_service; - am.ConnectToService(test_url, &test_service); - TestClient test_client(test_service.Pass()); - test_client.Test("test"); - loop_.Run(); - std::vector<std::string> app_args = loader->GetArgs(); - EXPECT_EQ(0U, app_args.size()); -} - -// Confirm that url mappings are respected. -TEST_F(ApplicationManagerTest, URLMapping) { - ApplicationManager am(&test_delegate_); - GURL test_url("test:test"); - GURL test_url2("test:test2"); - test_delegate_.AddMapping(test_url, test_url2); - TestApplicationLoader* loader = new TestApplicationLoader; - loader->set_context(&context_); - am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url2); - { - // Connext to the mapped url - TestServicePtr test_service; - am.ConnectToService(test_url, &test_service); - TestClient test_client(test_service.Pass()); - test_client.Test("test"); - loop_.Run(); - } - { - // Connext to the target url - TestServicePtr test_service; - am.ConnectToService(test_url2, &test_service); - TestClient test_client(test_service.Pass()); - test_client.Test("test"); - loop_.Run(); - } -} - -TEST_F(ApplicationManagerTest, ClientError) { - test_client_->Test("test"); - EXPECT_TRUE(HasFactoryForTestURL()); - loop_.Run(); - EXPECT_EQ(1, context_.num_impls); - test_client_.reset(); - loop_.Run(); - EXPECT_EQ(0, context_.num_impls); - EXPECT_TRUE(HasFactoryForTestURL()); -} - -TEST_F(ApplicationManagerTest, Deletes) { - { - ApplicationManager am(&test_delegate_); - TestApplicationLoader* default_loader = new TestApplicationLoader; - default_loader->set_context(&context_); - TestApplicationLoader* url_loader1 = new TestApplicationLoader; - TestApplicationLoader* url_loader2 = new TestApplicationLoader; - url_loader1->set_context(&context_); - url_loader2->set_context(&context_); - TestApplicationLoader* scheme_loader1 = new TestApplicationLoader; - TestApplicationLoader* scheme_loader2 = new TestApplicationLoader; - scheme_loader1->set_context(&context_); - scheme_loader2->set_context(&context_); - am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader)); - am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1), - GURL("test:test1")); - am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2), - GURL("test:test1")); - am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader1), - "test"); - am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader2), - "test"); - } - EXPECT_EQ(5, context_.num_loader_deletes); -} - -// Confirm that both urls and schemes can have their loaders explicitly set. -TEST_F(ApplicationManagerTest, SetLoaders) { - TestApplicationLoader* default_loader = new TestApplicationLoader; - TestApplicationLoader* url_loader = new TestApplicationLoader; - TestApplicationLoader* scheme_loader = new TestApplicationLoader; - application_manager_->set_default_loader( - scoped_ptr<ApplicationLoader>(default_loader)); - application_manager_->SetLoaderForURL( - scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1")); - application_manager_->SetLoaderForScheme( - scoped_ptr<ApplicationLoader>(scheme_loader), "test"); - - // test::test1 should go to url_loader. - TestServicePtr test_service; - application_manager_->ConnectToService(GURL("test:test1"), &test_service); - EXPECT_EQ(1, url_loader->num_loads()); - EXPECT_EQ(0, scheme_loader->num_loads()); - EXPECT_EQ(0, default_loader->num_loads()); - - // test::test2 should go to scheme loader. - application_manager_->ConnectToService(GURL("test:test2"), &test_service); - EXPECT_EQ(1, url_loader->num_loads()); - EXPECT_EQ(1, scheme_loader->num_loads()); - EXPECT_EQ(0, default_loader->num_loads()); - - // http::test1 should go to default loader. - application_manager_->ConnectToService(GURL("http:test1"), &test_service); - EXPECT_EQ(1, url_loader->num_loads()); - EXPECT_EQ(1, scheme_loader->num_loads()); - EXPECT_EQ(1, default_loader->num_loads()); -} - -// Confirm that the url of a service is correctly passed to another service that -// it loads. -TEST_F(ApplicationManagerTest, ACallB) { - // Any url can load a. - AddLoaderForURL(GURL(kTestAURLString), std::string()); - - // Only a can load b. - AddLoaderForURL(GURL(kTestBURLString), kTestAURLString); - - TestAPtr a; - application_manager_->ConnectToService(GURL(kTestAURLString), &a); - a->CallB(); - loop_.Run(); - EXPECT_EQ(1, tester_context_.num_b_calls()); - EXPECT_TRUE(tester_context_.a_called_quit()); -} - -// A calls B which calls C. -TEST_F(ApplicationManagerTest, BCallC) { - // Any url can load a. - AddLoaderForURL(GURL(kTestAURLString), std::string()); - - // Only a can load b. - AddLoaderForURL(GURL(kTestBURLString), kTestAURLString); - - TestAPtr a; - application_manager_->ConnectToService(GURL(kTestAURLString), &a); - a->CallCFromB(); - loop_.Run(); - - EXPECT_EQ(1, tester_context_.num_b_calls()); - EXPECT_EQ(1, tester_context_.num_c_calls()); - EXPECT_TRUE(tester_context_.a_called_quit()); -} - -// Confirm that a service impl will be deleted if the app that connected to -// it goes away. -TEST_F(ApplicationManagerTest, BDeleted) { - AddLoaderForURL(GURL(kTestAURLString), std::string()); - AddLoaderForURL(GURL(kTestBURLString), std::string()); - - TestAPtr a; - application_manager_->ConnectToService(GURL(kTestAURLString), &a); - - a->CallB(); - loop_.Run(); - - // Kills the a app. - application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(), - GURL(kTestAURLString)); - loop_.Run(); - - EXPECT_EQ(1, tester_context_.num_b_deletes()); -} - -// Confirm that the url of a service is correctly passed to another service that -// it loads, and that it can be rejected. -TEST_F(ApplicationManagerTest, ANoLoadB) { - // Any url can load a. - AddLoaderForURL(GURL(kTestAURLString), std::string()); - - // Only c can load b, so this will fail. - AddLoaderForURL(GURL(kTestBURLString), "test:TestC"); - - TestAPtr a; - application_manager_->ConnectToService(GURL(kTestAURLString), &a); - a->CallB(); - loop_.Run(); - EXPECT_EQ(0, tester_context_.num_b_calls()); - - EXPECT_FALSE(tester_context_.a_called_quit()); - EXPECT_TRUE(tester_context_.tester_called_quit()); -} - -TEST_F(ApplicationManagerTest, NoServiceNoLoad) { - AddLoaderForURL(GURL(kTestAURLString), std::string()); - - // There is no TestC service implementation registered with - // ApplicationManager, so this cannot succeed (but also shouldn't crash). - TestCPtr c; - application_manager_->ConnectToService(GURL(kTestAURLString), &c); - QuitMessageLoopErrorHandler quitter; - c.set_error_handler(&quitter); - - loop_.Run(); - EXPECT_TRUE(c.encountered_error()); -} - -TEST_F(ApplicationManagerTest, MappedURLsShouldNotCauseDuplicateLoad) { - test_delegate_.AddMapping(GURL("foo:foo2"), GURL("foo:foo")); - // 1 because ApplicationManagerTest connects once at startup. - EXPECT_EQ(1, test_loader_->num_loads()); - - TestServicePtr test_service; - application_manager_->ConnectToService(GURL("foo:foo"), &test_service); - EXPECT_EQ(2, test_loader_->num_loads()); - - TestServicePtr test_service2; - application_manager_->ConnectToService(GURL("foo:foo2"), &test_service2); - EXPECT_EQ(2, test_loader_->num_loads()); - - TestServicePtr test_service3; - application_manager_->ConnectToService(GURL("bar:bar"), &test_service2); - EXPECT_EQ(3, test_loader_->num_loads()); -} - -TEST_F(ApplicationManagerTest, MappedURLsShouldWorkWithLoaders) { - TestApplicationLoader* custom_loader = new TestApplicationLoader; - TestContext context; - custom_loader->set_context(&context); - application_manager_->SetLoaderForURL(make_scoped_ptr(custom_loader), - GURL("mojo:foo")); - test_delegate_.AddMapping(GURL("mojo:foo2"), GURL("mojo:foo")); - - TestServicePtr test_service; - application_manager_->ConnectToService(GURL("mojo:foo2"), &test_service); - EXPECT_EQ(1, custom_loader->num_loads()); - custom_loader->set_context(nullptr); -} - -TEST_F(ApplicationManagerTest, TestQueryWithLoaders) { - TestApplicationLoader* url_loader = new TestApplicationLoader; - TestApplicationLoader* scheme_loader = new TestApplicationLoader; - application_manager_->SetLoaderForURL( - scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1")); - application_manager_->SetLoaderForScheme( - scoped_ptr<ApplicationLoader>(scheme_loader), "test"); - - // test::test1 should go to url_loader. - TestServicePtr test_service; - application_manager_->ConnectToService(GURL("test:test1?foo=bar"), - &test_service); - EXPECT_EQ(1, url_loader->num_loads()); - EXPECT_EQ(0, scheme_loader->num_loads()); - - // test::test2 should go to scheme loader. - application_manager_->ConnectToService(GURL("test:test2?foo=bar"), - &test_service); - EXPECT_EQ(1, url_loader->num_loads()); - EXPECT_EQ(1, scheme_loader->num_loads()); -} - -TEST_F(ApplicationManagerTest, TestEndApplicationClosure) { - ClosingApplicationLoader* loader = new ClosingApplicationLoader(); - application_manager_->SetLoaderForScheme( - scoped_ptr<ApplicationLoader>(loader), "test"); - - bool called = false; - application_manager_->ConnectToApplication( - GURL("test:test"), GURL(), nullptr, nullptr, - base::Bind(&QuitClosure, base::Unretained(&called))); - loop_.Run(); - EXPECT_TRUE(called); -} - -} // namespace -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/data_pipe_peek.cc b/mojo/shell/application_manager/data_pipe_peek.cc deleted file mode 100644 index 9109b51..0000000 --- a/mojo/shell/application_manager/data_pipe_peek.cc +++ /dev/null
@@ -1,160 +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 "mojo/shell/application_manager/data_pipe_peek.h" - -#include <stdint.h> - -#include "base/bind.h" -#include "base/macros.h" - -namespace mojo { -namespace shell { - -namespace { - -// Sleep for as long as max_sleep_micros if the deadline hasn't been reached -// and the number of bytes read is still increasing. Returns true if sleep -// was actually called. -// -// This class is a substitute for being able to wait until N bytes are available -// from a data pipe. The MaybeSleep method is called when num_bytes_read are -// available but more are needed by the Peek operation. If a second -// Peek operation finds the same number of bytes after sleeping we assume -// that there's no point in trying again. -// TODO(hansmuller): this heuristic is weak. crbug.com/429377 -class PeekSleeper { - public: - explicit PeekSleeper(MojoTimeTicks deadline) - : deadline_(deadline), - last_number_bytes_read_(0) {} - - bool MaybeSleep(uint32_t num_bytes_read) { - if (num_bytes_read > 0 && last_number_bytes_read_ >= num_bytes_read) - return false; - last_number_bytes_read_ = num_bytes_read; - - MojoTimeTicks now(GetTimeTicksNow()); - if (now > deadline_) - return false; - - MojoTimeTicks sleep_time = - (deadline_ == 0) ? kMaxSleepMicros - : std::min<int64>(deadline_ - now, kMaxSleepMicros); - base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(sleep_time)); - return true; - } - - private: - static const MojoTimeTicks kMaxSleepMicros = 1000 * 10; // 10 ms - - const MojoTimeTicks deadline_; // 0 => MOJO_DEADLINE_INDEFINITE - uint32_t last_number_bytes_read_; - - DISALLOW_COPY_AND_ASSIGN(PeekSleeper); -}; - -const MojoTimeTicks PeekSleeper::kMaxSleepMicros; - -enum PeekStatus { kSuccess, kFail, kKeepReading }; -typedef const base::Callback<PeekStatus(const void*, uint32_t, std::string*)>& - PeekFunc; - -// When data is available on source, call peek_func and then either return true -// and value, continue waiting for enough data to satisfy peek_func, or fail -// and return false. Fail if the timeout is exceeded. -// This function is not guaranteed to work correctly if applied to a data pipe -// that's already been read from. -bool BlockingPeekHelper(DataPipeConsumerHandle source, - std::string* value, - MojoDeadline timeout, - PeekFunc peek_func) { - DCHECK(value); - value->clear(); - - MojoTimeTicks deadline = - (timeout == MOJO_DEADLINE_INDEFINITE) - ? 0 - : 1 + GetTimeTicksNow() + static_cast<MojoTimeTicks>(timeout); - PeekSleeper sleeper(deadline); - - MojoResult result; - do { - const void* buffer; - uint32_t num_bytes; - result = - BeginReadDataRaw(source, &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); - - if (result == MOJO_RESULT_OK) { - PeekStatus status = peek_func.Run(buffer, num_bytes, value); - CHECK_EQ(EndReadDataRaw(source, 0), MOJO_RESULT_OK); - switch (status) { - case PeekStatus::kSuccess: - return true; - case PeekStatus::kFail: - return false; - case PeekStatus::kKeepReading: - break; - } - if (!sleeper.MaybeSleep(num_bytes)) - return false; - } else if (result == MOJO_RESULT_SHOULD_WAIT) { - MojoTimeTicks now(GetTimeTicksNow()); - if (timeout == MOJO_DEADLINE_INDEFINITE || now < deadline) - result = - Wait(source, MOJO_HANDLE_SIGNAL_READABLE, deadline - now, nullptr); - } - } while (result == MOJO_RESULT_OK); - - return false; -} - -PeekStatus PeekLine(size_t max_line_length, - const void* buffer, - uint32_t buffer_num_bytes, - std::string* line) { - const char* p = static_cast<const char*>(buffer); - size_t max_p_index = std::min<size_t>(buffer_num_bytes, max_line_length); - for (size_t i = 0; i < max_p_index; i++) { - if (p[i] == '\n') { - *line = std::string(p, i + 1); // Include the trailing newline. - return PeekStatus::kSuccess; - } - } - return (buffer_num_bytes >= max_line_length) ? PeekStatus::kFail - : PeekStatus::kKeepReading; -} - -PeekStatus PeekNBytes(size_t bytes_length, - const void* buffer, - uint32_t buffer_num_bytes, - std::string* bytes) { - if (buffer_num_bytes >= bytes_length) { - const char* p = static_cast<const char*>(buffer); - *bytes = std::string(p, bytes_length); - return PeekStatus::kSuccess; - } - return PeekStatus::kKeepReading; -} - -} // namespace - -bool BlockingPeekNBytes(DataPipeConsumerHandle source, - std::string* bytes, - size_t bytes_length, - MojoDeadline timeout) { - PeekFunc peek_nbytes = base::Bind(PeekNBytes, bytes_length); - return BlockingPeekHelper(source, bytes, timeout, peek_nbytes); -} - -bool BlockingPeekLine(DataPipeConsumerHandle source, - std::string* line, - size_t max_line_length, - MojoDeadline timeout) { - PeekFunc peek_line = base::Bind(PeekLine, max_line_length); - return BlockingPeekHelper(source, line, timeout, peek_line); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/data_pipe_peek.h b/mojo/shell/application_manager/data_pipe_peek.h deleted file mode 100644 index 5ffbc5b..0000000 --- a/mojo/shell/application_manager/data_pipe_peek.h +++ /dev/null
@@ -1,38 +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 SHELL_APPLICATION_MANAGER_DATA_PIPE_SEEK_H_ -#define SHELL_APPLICATION_MANAGER_DATA_PIPE_SEEK_H_ - -#include <string> - -#include "mojo/public/cpp/system/core.h" - -namespace mojo { -namespace shell { - -// The Peek functions are only intended to be used by the -// DyanmicApplicationLoader class for discovering the type of a -// URL response. They are a stopgap to be replaced by real support -// in the DataPipe classes. - -// Return true and the first newline terminated line from source. Return false -// if more than max_line_length bytes are scanned without seeing a newline, or -// if the timeout is exceeded. -bool BlockingPeekLine(DataPipeConsumerHandle source, - std::string* line, - size_t max_line_length, - MojoDeadline timeout); - -// Return true and the first bytes_length bytes from source. Return false -// if the timeout is exceeded. -bool BlockingPeekNBytes(DataPipeConsumerHandle source, - std::string* bytes, - size_t bytes_length, - MojoDeadline timeout); - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_DATA_PIPE_SEEK_H_
diff --git a/mojo/shell/application_manager/fetcher.cc b/mojo/shell/application_manager/fetcher.cc deleted file mode 100644 index 78fd125..0000000 --- a/mojo/shell/application_manager/fetcher.cc +++ /dev/null
@@ -1,38 +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 "mojo/shell/application_manager/fetcher.h" - -#include "url/gurl.h" - -namespace mojo { -namespace shell { - -const char Fetcher::kMojoMagic[] = "#!mojo "; -const size_t Fetcher::kMaxShebangLength = 2048; - -Fetcher::Fetcher(const FetchCallback& loader_callback) - : loader_callback_(loader_callback) { -} - -Fetcher::~Fetcher() { -} - -bool Fetcher::PeekContentHandler(std::string* mojo_shebang, - GURL* mojo_content_handler_url) { - // TODO(aa): I guess this should just go in ApplicationManager now. - std::string shebang; - if (HasMojoMagic() && PeekFirstLine(&shebang)) { - GURL url(shebang.substr(arraysize(kMojoMagic) - 1, std::string::npos)); - if (url.is_valid()) { - *mojo_shebang = shebang; - *mojo_content_handler_url = url; - return true; - } - } - return false; -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/fetcher.h b/mojo/shell/application_manager/fetcher.h deleted file mode 100644 index 2257f75..0000000 --- a/mojo/shell/application_manager/fetcher.h +++ /dev/null
@@ -1,76 +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. - -#ifndef SHELL_APPLICATION_MANAGER_FETCHER_H_ -#define SHELL_APPLICATION_MANAGER_FETCHER_H_ - -#include "base/callback.h" -#include "base/memory/scoped_ptr.h" - -#include "mojo/services/network/public/interfaces/url_loader.mojom.h" - -class GURL; - -namespace base { -class FilePath; -class TaskRunner; -} - -namespace mojo { -namespace shell { - -// Fetcher abstracts getting an application by either file or http[s] URL. -// -// Although it is possible to use the Network implementation for http[s] URLs -// (because the underlying net library knows how to handle them), it is -// extremely slow because network responses must be copied to disk in order to -// get a file handle we can use with dlopen. -// -// Until this is solved, we use two different implementations so that -// performance isn't completely absymal. -class Fetcher { - public: - // The param will be null in the case where the content could not be fetched. - // Reasons include: - // - network error - // - 4x or 5x HTTP errors - typedef base::Callback<void(scoped_ptr<Fetcher>)> FetchCallback; - - Fetcher(const FetchCallback& fetch_callback); - virtual ~Fetcher(); - - // Returns the original URL that was fetched. - virtual const GURL& GetURL() const = 0; - - // If the fetch resulted in a redirect, this returns the final URL after all - // redirects. Otherwise, it returns an empty URL. - virtual GURL GetRedirectURL() const = 0; - - virtual URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, - uint32_t skip) = 0; - - virtual void AsPath( - base::TaskRunner* task_runner, - base::Callback<void(const base::FilePath&, bool)> callback) = 0; - - virtual std::string MimeType() = 0; - - virtual bool HasMojoMagic() = 0; - - virtual bool PeekFirstLine(std::string* line) = 0; - - bool PeekContentHandler(std::string* mojo_shebang, - GURL* mojo_content_handler_url); - - protected: - static const char kMojoMagic[]; - static const size_t kMaxShebangLength; - - FetchCallback loader_callback_; -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_FETCHER_H_
diff --git a/mojo/shell/application_manager/identity.cc b/mojo/shell/application_manager/identity.cc deleted file mode 100644 index c54f5d8..0000000 --- a/mojo/shell/application_manager/identity.cc +++ /dev/null
@@ -1,28 +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 "mojo/shell/application_manager/identity.h" - -#include "mojo/shell/application_manager/query_util.h" - -namespace mojo { -namespace shell { - -Identity::Identity(const GURL& url, const std::string& qualifier) - : url(GetBaseURLAndQuery(url, nullptr)), qualifier(qualifier) { -} - -// explicit -Identity::Identity(const GURL& base_url) - : url(GetBaseURLAndQuery(base_url, nullptr)), qualifier(url.spec()) { -} - -bool Identity::operator<(const Identity& other) const { - if (url != other.url) - return url < other.url; - return qualifier < other.qualifier; -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/identity.h b/mojo/shell/application_manager/identity.h deleted file mode 100644 index 3d7e1d6..0000000 --- a/mojo/shell/application_manager/identity.h +++ /dev/null
@@ -1,31 +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. - -#ifndef SHELL_APPLICATION_MANAGER_IDENTITY_H_ -#define SHELL_APPLICATION_MANAGER_IDENTITY_H_ - -#include "url/gurl.h" - -namespace mojo { -namespace shell { - -/** - * Represents the identity of an application. |url| is the url of the - * application. |qualifier| is a string that allows to tie a specific instance - * of an application to another. It is used by content handlers that need to be - * run in the context of another application. - */ -struct Identity { - Identity(const GURL& url, const std::string& qualifier); - explicit Identity(const GURL& url); - bool operator<(const Identity& other) const; - - const GURL url; - const std::string qualifier; -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_IDENTITY_H_
diff --git a/mojo/shell/application_manager/local_fetcher.cc b/mojo/shell/application_manager/local_fetcher.cc deleted file mode 100644 index a8b889dc..0000000 --- a/mojo/shell/application_manager/local_fetcher.cc +++ /dev/null
@@ -1,107 +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 "mojo/shell/application_manager/local_fetcher.h" - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/format_macros.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/trace_event/trace_event.h" -#include "mojo/common/common_type_converters.h" -#include "mojo/common/data_pipe_utils.h" -#include "mojo/common/url_type_converters.h" -#include "url/url_util.h" - -namespace mojo { -namespace shell { - -namespace { - -void IgnoreResult(bool result) { -} - -} // namespace - -// A loader for local files. -LocalFetcher::LocalFetcher(const GURL& url, - const GURL& url_without_query, - const FetchCallback& loader_callback) - : Fetcher(loader_callback), url_(url), path_(UrlToFile(url_without_query)) { - TRACE_EVENT1("mojo_shell", "LocalFetcher::LocalFetcher", "url", url.spec()); - loader_callback_.Run(make_scoped_ptr(this)); -} - -base::FilePath LocalFetcher::UrlToFile(const GURL& url) { - DCHECK(url.SchemeIsFile()); - url::RawCanonOutputW<1024> output; - url::DecodeURLEscapeSequences(url.path().data(), - static_cast<int>(url.path().length()), &output); - base::string16 decoded_path = base::string16(output.data(), output.length()); -#if defined(OS_WIN) - base::TrimString(decoded_path, L"/", &decoded_path); - base::FilePath path(decoded_path); -#else - base::FilePath path(base::UTF16ToUTF8(decoded_path)); -#endif - return path; -} - -const GURL& LocalFetcher::GetURL() const { - return url_; -} - -GURL LocalFetcher::GetRedirectURL() const { - return GURL::EmptyGURL(); -} - -URLResponsePtr LocalFetcher::AsURLResponse(base::TaskRunner* task_runner, - uint32_t skip) { - URLResponsePtr response(URLResponse::New()); - response->url = String::From(url_); - DataPipe data_pipe; - response->body = data_pipe.consumer_handle.Pass(); - int64 file_size; - if (base::GetFileSize(path_, &file_size)) { - response->headers = Array<String>(1); - response->headers[0] = - base::StringPrintf("Content-Length: %" PRId64, file_size); - } - common::CopyFromFile(path_, data_pipe.producer_handle.Pass(), skip, - task_runner, base::Bind(&IgnoreResult)); - return response.Pass(); -} - -void LocalFetcher::AsPath( - base::TaskRunner* task_runner, - base::Callback<void(const base::FilePath&, bool)> callback) { - // Async for consistency with network case. - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); -} - -std::string LocalFetcher::MimeType() { - return ""; -} - -bool LocalFetcher::HasMojoMagic() { - std::string magic; - ReadFileToString(path_, &magic, strlen(kMojoMagic)); - return magic == kMojoMagic; -} - -bool LocalFetcher::PeekFirstLine(std::string* line) { - std::string start_of_file; - ReadFileToString(path_, &start_of_file, kMaxShebangLength); - size_t return_position = start_of_file.find('\n'); - if (return_position == std::string::npos) - return false; - *line = start_of_file.substr(0, return_position + 1); - return true; -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/local_fetcher.h b/mojo/shell/application_manager/local_fetcher.h deleted file mode 100644 index 843108f..0000000 --- a/mojo/shell/application_manager/local_fetcher.h +++ /dev/null
@@ -1,51 +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. - -#ifndef SHELL_APPLICATION_MANAGER_LOCAL_FETCHER_H_ -#define SHELL_APPLICATION_MANAGER_LOCAL_FETCHER_H_ - -#include "base/files/file_path.h" -#include "mojo/services/network/public/interfaces/url_loader.mojom.h" -#include "mojo/shell/application_manager/fetcher.h" -#include "url/gurl.h" - -namespace mojo { -namespace shell { - -// Implements Fetcher for file:// URLs. -class LocalFetcher : public Fetcher { - public: - LocalFetcher(const GURL& url, - const GURL& url_without_query, - const FetchCallback& loader_callback); - - private: - static base::FilePath UrlToFile(const GURL& url); - - const GURL& GetURL() const override; - GURL GetRedirectURL() const override; - - URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, - uint32_t skip) override; - - void AsPath( - base::TaskRunner* task_runner, - base::Callback<void(const base::FilePath&, bool)> callback) override; - - std::string MimeType() override; - - bool HasMojoMagic() override; - - bool PeekFirstLine(std::string* line) override; - - GURL url_; - base::FilePath path_; - - DISALLOW_COPY_AND_ASSIGN(LocalFetcher); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_LOCAL_FETCHER_H_
diff --git a/mojo/shell/application_manager/native_runner.h b/mojo/shell/application_manager/native_runner.h deleted file mode 100644 index bc62b77a..0000000 --- a/mojo/shell/application_manager/native_runner.h +++ /dev/null
@@ -1,58 +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. - -#ifndef SHELL_APPLICATION_MANAGER_NATIVE_RUNNER_H_ -#define SHELL_APPLICATION_MANAGER_NATIVE_RUNNER_H_ - -#include "base/callback_forward.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/interfaces/application/application.mojom.h" -#include "mojo/shell/native_application_support.h" - -namespace base { -class FilePath; -} - -namespace mojo { -namespace shell { - -// ApplicationManager requires implementations of NativeRunner and -// NativeRunnerFactory to run native applications. -class NativeRunner { - public: - virtual ~NativeRunner() {} - - // Loads the app in the file at |app_path| and runs it on some other - // thread/process. If |cleanup| is |DELETE|, this takes ownership of the file. - // |app_completed_callback| is posted (to the thread on which |Start()| was - // called) after |MojoMain()| completes. - // TODO(vtl): |app_path| and |cleanup| should probably be moved to the - // factory's Create(). Rationale: The factory may need information from the - // file to decide what kind of NativeRunner to make. - virtual void Start(const base::FilePath& app_path, - NativeApplicationCleanup cleanup, - InterfaceRequest<Application> application_request, - const base::Closure& app_completed_callback) = 0; -}; - -class NativeRunnerFactory { - public: - // Options for running the native app. (This will contain, e.g., information - // about the sandbox profile, etc.) - struct Options { - // Constructs with default options. - Options() : force_in_process(false) {} - - bool force_in_process; - }; - - virtual ~NativeRunnerFactory() {} - virtual scoped_ptr<NativeRunner> Create(const Options& options) = 0; -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_NATIVE_RUNNER_H_
diff --git a/mojo/shell/application_manager/network_fetcher.cc b/mojo/shell/application_manager/network_fetcher.cc deleted file mode 100644 index b93201f9..0000000 --- a/mojo/shell/application_manager/network_fetcher.cc +++ /dev/null
@@ -1,250 +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 "mojo/shell/application_manager/network_fetcher.h" - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/message_loop/message_loop.h" -#include "base/process/process.h" -#include "base/stl_util.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/trace_event/trace_event.h" -#include "crypto/secure_hash.h" -#include "crypto/sha2.h" -#include "mojo/common/common_type_converters.h" -#include "mojo/common/data_pipe_utils.h" -#include "mojo/common/url_type_converters.h" -#include "mojo/services/network/public/interfaces/network_service.mojom.h" -#include "mojo/shell/application_manager/data_pipe_peek.h" -#include "mojo/shell/switches.h" - -namespace mojo { -namespace shell { - -NetworkFetcher::NetworkFetcher(bool disable_cache, - const GURL& url, - NetworkService* network_service, - const FetchCallback& loader_callback) - : Fetcher(loader_callback), - disable_cache_(false), - url_(url), - weak_ptr_factory_(this) { - StartNetworkRequest(url, network_service); -} - -NetworkFetcher::~NetworkFetcher() { -} - -const GURL& NetworkFetcher::GetURL() const { - return url_; -} - -GURL NetworkFetcher::GetRedirectURL() const { - if (!response_) - return GURL::EmptyGURL(); - - if (response_->redirect_url.is_null()) - return GURL::EmptyGURL(); - - return GURL(response_->redirect_url); -} - -URLResponsePtr NetworkFetcher::AsURLResponse(base::TaskRunner* task_runner, - uint32_t skip) { - if (skip != 0) { - MojoResult result = ReadDataRaw( - response_->body.get(), nullptr, &skip, - MOJO_READ_DATA_FLAG_ALL_OR_NONE | MOJO_READ_DATA_FLAG_DISCARD); - DCHECK_EQ(result, MOJO_RESULT_OK); - } - return response_.Pass(); -} - -void NetworkFetcher::RecordCacheToURLMapping(const base::FilePath& path, - const GURL& url) { - // This is used to extract symbols on android. - // TODO(eseidel): All users of this log should move to using the map file. - VLOG(1) << "Caching mojo app " << url << " at " << path.value(); - - base::FilePath temp_dir; - base::GetTempDir(&temp_dir); - base::ProcessId pid = base::Process::Current().Pid(); - std::string map_name = base::StringPrintf("mojo_shell.%d.maps", pid); - base::FilePath map_path = temp_dir.AppendASCII(map_name); - - // TODO(eseidel): Paths or URLs with spaces will need quoting. - std::string map_entry = - base::StringPrintf("%s %s\n", path.value().c_str(), url.spec().c_str()); - // TODO(eseidel): AppendToFile is missing O_CREAT, crbug.com/450696 - if (!PathExists(map_path)) { - base::WriteFile(map_path, map_entry.data(), - static_cast<int>(map_entry.length())); - } else { - base::AppendToFile(map_path, map_entry.data(), - static_cast<int>(map_entry.length())); - } -} - -// For remote debugging, GDB needs to be, a apriori, aware of the filename a -// library will be loaded from. AppIds should be be both predictable and unique, -// but any hash would work. Currently we use sha256 from crypto/secure_hash.h -bool NetworkFetcher::ComputeAppId(const base::FilePath& path, - std::string* digest_string) { - scoped_ptr<crypto::SecureHash> ctx( - crypto::SecureHash::Create(crypto::SecureHash::SHA256)); - base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); - if (!file.IsValid()) { - LOG(ERROR) << "Failed to open " << path.value() << " for computing AppId"; - return false; - } - char buf[1024]; - while (file.IsValid()) { - int bytes_read = file.ReadAtCurrentPos(buf, sizeof(buf)); - if (bytes_read == 0) - break; - ctx->Update(buf, bytes_read); - } - if (!file.IsValid()) { - LOG(ERROR) << "Error reading " << path.value(); - return false; - } - // The output is really a vector of unit8, we're cheating by using a string. - std::string output(crypto::kSHA256Length, 0); - ctx->Finish(string_as_array(&output), output.size()); - output = base::HexEncode(output.c_str(), output.size()); - // Using lowercase for compatiblity with sha256sum output. - *digest_string = base::StringToLowerASCII(output); - return true; -} - -bool NetworkFetcher::RenameToAppId(const GURL& url, - const base::FilePath& old_path, - base::FilePath* new_path) { - std::string app_id; - if (!ComputeAppId(old_path, &app_id)) - return false; - - // Using a hash of the url as a directory to prevent a race when the same - // bytes are downloaded from 2 different urls. In particular, if the same - // application is connected to twice concurrently with different query - // parameters, the directory will be different, which will prevent the - // collision. - std::string dirname = base::HexEncode( - crypto::SHA256HashString(url.spec()).data(), crypto::kSHA256Length); - - base::FilePath temp_dir; - base::GetTempDir(&temp_dir); - base::FilePath app_dir = temp_dir.AppendASCII(dirname); - // The directory is leaked, because it can be reused at any time if the same - // application is downloaded. Deleting it would be racy. This is only - // happening when --predictable-app-filenames is used. - bool result = base::CreateDirectoryAndGetError(app_dir, nullptr); - DCHECK(result); - std::string unique_name = base::StringPrintf("%s.mojo", app_id.c_str()); - *new_path = app_dir.AppendASCII(unique_name); - return base::Move(old_path, *new_path); -} - -void NetworkFetcher::CopyCompleted( - base::Callback<void(const base::FilePath&, bool)> callback, - bool success) { - if (success) { - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kPredictableAppFilenames)) { - // The copy completed, now move to $TMP/$APP_ID.mojo before the dlopen. - success = false; - base::FilePath new_path; - if (RenameToAppId(url_, path_, &new_path)) { - if (base::PathExists(new_path)) { - path_ = new_path; - success = true; - } - } - } - } - - if (success) - RecordCacheToURLMapping(path_, url_); - - base::MessageLoop::current()->PostTask(FROM_HERE, - base::Bind(callback, path_, success)); -} - -void NetworkFetcher::AsPath( - base::TaskRunner* task_runner, - base::Callback<void(const base::FilePath&, bool)> callback) { - if (!path_.empty() || !response_) { - base::MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); - return; - } - - base::CreateTemporaryFile(&path_); - common::CopyToFile(response_->body.Pass(), path_, task_runner, - base::Bind(&NetworkFetcher::CopyCompleted, - weak_ptr_factory_.GetWeakPtr(), callback)); -} - -std::string NetworkFetcher::MimeType() { - return response_->mime_type; -} - -bool NetworkFetcher::HasMojoMagic() { - std::string magic; - return BlockingPeekNBytes(response_->body.get(), &magic, strlen(kMojoMagic), - kPeekTimeout) && - magic == kMojoMagic; -} - -bool NetworkFetcher::PeekFirstLine(std::string* line) { - return BlockingPeekLine(response_->body.get(), line, kMaxShebangLength, - kPeekTimeout); -} - -void NetworkFetcher::StartNetworkRequest(const GURL& url, - NetworkService* network_service) { - TRACE_EVENT_ASYNC_BEGIN1("mojo_shell", "NetworkFetcher::NetworkRequest", this, - "url", url.spec()); - URLRequestPtr request(URLRequest::New()); - request->url = String::From(url); - request->auto_follow_redirects = false; - request->bypass_cache = disable_cache_; - - network_service->CreateURLLoader(GetProxy(&url_loader_)); - url_loader_->Start(request.Pass(), - base::Bind(&NetworkFetcher::OnLoadComplete, - weak_ptr_factory_.GetWeakPtr())); -} - -void NetworkFetcher::OnLoadComplete(URLResponsePtr response) { - TRACE_EVENT_ASYNC_END0("mojo_shell", "NetworkFetcher::NetworkRequest", this); - if (response->error) { - LOG(ERROR) << "Error (" << response->error->code << ": " - << response->error->description << ") while fetching " - << response->url; - loader_callback_.Run(nullptr); - return; - } - - if (response->status_code >= 400 && response->status_code < 600) { - LOG(ERROR) << "Error (" << response->status_code << ": " - << response->status_line << "): " - << "while fetching " << response->url; - loader_callback_.Run(nullptr); - return; - } - - response_ = response.Pass(); - loader_callback_.Run(make_scoped_ptr(this)); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/network_fetcher.h b/mojo/shell/application_manager/network_fetcher.h deleted file mode 100644 index 3ee90a95..0000000 --- a/mojo/shell/application_manager/network_fetcher.h +++ /dev/null
@@ -1,83 +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. - -#ifndef SHELL_APPLICATION_MANAGER_NETWORK_FETCHER_H_ -#define SHELL_APPLICATION_MANAGER_NETWORK_FETCHER_H_ - -#include "mojo/shell/application_manager/fetcher.h" - -#include "base/files/file_path.h" -#include "base/memory/weak_ptr.h" -#include "mojo/services/network/public/interfaces/url_loader.mojom.h" -#include "url/gurl.h" - -namespace mojo { - -class NetworkService; - -namespace shell { - -// Implements Fetcher for http[s] files. -class NetworkFetcher : public Fetcher { - public: - NetworkFetcher(bool disable_cache, - const GURL& url, - NetworkService* network_service, - const FetchCallback& loader_callback); - - ~NetworkFetcher() override; - - private: - // TODO(hansmuller): Revisit this when a real peek operation is available. - static const MojoDeadline kPeekTimeout = MOJO_DEADLINE_INDEFINITE; - - const GURL& GetURL() const override; - GURL GetRedirectURL() const override; - - URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, - uint32_t skip) override; - - static void RecordCacheToURLMapping(const base::FilePath& path, - const GURL& url); - - // AppIds should be be both predictable and unique, but any hash would work. - // Currently we use sha256 from crypto/secure_hash.h - static bool ComputeAppId(const base::FilePath& path, - std::string* digest_string); - - static bool RenameToAppId(const GURL& url, - const base::FilePath& old_path, - base::FilePath* new_path); - - void CopyCompleted(base::Callback<void(const base::FilePath&, bool)> callback, - bool success); - - void AsPath( - base::TaskRunner* task_runner, - base::Callback<void(const base::FilePath&, bool)> callback) override; - - std::string MimeType() override; - - bool HasMojoMagic() override; - - bool PeekFirstLine(std::string* line) override; - - void StartNetworkRequest(const GURL& url, NetworkService* network_service); - - void OnLoadComplete(URLResponsePtr response); - - bool disable_cache_; - const GURL url_; - URLLoaderPtr url_loader_; - URLResponsePtr response_; - base::FilePath path_; - base::WeakPtrFactory<NetworkFetcher> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(NetworkFetcher); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_NETWORK_FETCHER_H_
diff --git a/mojo/shell/application_manager/query_util.cc b/mojo/shell/application_manager/query_util.cc deleted file mode 100644 index 252dcb63..0000000 --- a/mojo/shell/application_manager/query_util.cc +++ /dev/null
@@ -1,31 +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 "mojo/shell/application_manager/query_util.h" - -#include "base/strings/string_util.h" - -namespace mojo { -namespace shell { - -GURL GetBaseURLAndQuery(const GURL& url, std::string* query) { - if (!url.has_query()) { - if (query) - *query = ""; - return url; - } - - if (query) - *query = "?" + url.query(); - GURL::Replacements repl; - repl.SetQueryStr(""); - std::string result = url.ReplaceComponents(repl).spec(); - - // Remove the dangling '?' because it's ugly. - base::ReplaceChars(result, "?", "", &result); - return GURL(result); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/query_util.h b/mojo/shell/application_manager/query_util.h deleted file mode 100644 index a4ca3f7e..0000000 --- a/mojo/shell/application_manager/query_util.h +++ /dev/null
@@ -1,23 +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. - -#ifndef SHELL_APPLICATION_MANAGER_QUERY_UTIL_H_ -#define SHELL_APPLICATION_MANAGER_QUERY_UTIL_H_ - -#include <utility> - -#include "url/gurl.h" - -namespace mojo { -namespace shell { - -// Returns the base URL (without the query string). If |query| is not nullptr, -// set |*query| to the query string. If the url doesn't have a query string, -// |*query| is set to the empty string. -GURL GetBaseURLAndQuery(const GURL& url, std::string* query); - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_QUERY_UTIL_H_
diff --git a/mojo/shell/application_manager/query_util_unittest.cc b/mojo/shell/application_manager/query_util_unittest.cc deleted file mode 100644 index 8a995c4..0000000 --- a/mojo/shell/application_manager/query_util_unittest.cc +++ /dev/null
@@ -1,47 +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 "mojo/shell/application_manager/query_util.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { -namespace { - -TEST(QueryUtil, NoQuery) { - GURL url("http://www.example.com/"); - std::string query; - GURL base_url = GetBaseURLAndQuery(url, &query); - EXPECT_EQ(base_url, url); - EXPECT_EQ(query, ""); -} - -TEST(QueryUtil, WithEmptyQuery) { - GURL url("http://www.example.com/?"); - std::string query; - GURL base_url = GetBaseURLAndQuery(url, &query); - EXPECT_EQ(base_url, GURL("http://www.example.com/")); - EXPECT_EQ(query, "?"); -} - -TEST(QueryUtil, WithFullQuery) { - GURL url("http://www.example.com/?a=b&c=d"); - std::string query; - GURL base_url = GetBaseURLAndQuery(url, &query); - EXPECT_EQ(base_url, GURL("http://www.example.com/")); - EXPECT_EQ(query, "?a=b&c=d"); -} - -TEST(QueryUtil, ForFileURL) { - GURL url("file:///tmp/file?a=b&c=d"); - std::string query; - GURL base_url = GetBaseURLAndQuery(url, &query); - EXPECT_EQ(base_url, GURL("file:///tmp/file")); - EXPECT_EQ(query, "?a=b&c=d"); -} - -} // namespace -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/shell_impl.cc b/mojo/shell/application_manager/shell_impl.cc deleted file mode 100644 index ed8c5ea..0000000 --- a/mojo/shell/application_manager/shell_impl.cc +++ /dev/null
@@ -1,62 +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 "mojo/shell/application_manager/shell_impl.h" - -#include "mojo/common/common_type_converters.h" -#include "mojo/common/url_type_converters.h" -#include "mojo/shell/application_manager/application_manager.h" -#include "third_party/mojo_services/src/content_handler/public/interfaces/content_handler.mojom.h" - -namespace mojo { -namespace shell { - -ShellImpl::ShellImpl(ApplicationPtr application, - ApplicationManager* manager, - const Identity& identity, - const base::Closure& on_application_end) - : manager_(manager), - identity_(identity), - on_application_end_(on_application_end), - application_(application.Pass()), - binding_(this) { - binding_.set_error_handler(this); -} - -ShellImpl::~ShellImpl() { -} - -void ShellImpl::InitializeApplication(Array<String> args) { - ShellPtr shell; - binding_.Bind(GetProxy(&shell)); - application_->Initialize(shell.Pass(), args.Pass(), identity_.url.spec()); -} - -void ShellImpl::ConnectToClient(const GURL& requested_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) { - application_->AcceptConnection(String::From(requestor_url), services.Pass(), - exposed_services.Pass(), requested_url.spec()); -} - -// Shell implementation: -void ShellImpl::ConnectToApplication(const String& app_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) { - GURL app_gurl(app_url); - if (!app_gurl.is_valid()) { - LOG(ERROR) << "Error: invalid URL: " << app_url; - return; - } - manager_->ConnectToApplication(app_gurl, identity_.url, services.Pass(), - exposed_services.Pass(), base::Closure()); -} - -void ShellImpl::OnConnectionError() { - manager_->OnShellImplError(this); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/application_manager/shell_impl.h b/mojo/shell/application_manager/shell_impl.h deleted file mode 100644 index ef557a63..0000000 --- a/mojo/shell/application_manager/shell_impl.h +++ /dev/null
@@ -1,62 +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. - -#ifndef SHELL_APPLICATION_MANAGER_SHELL_IMPL_H_ -#define SHELL_APPLICATION_MANAGER_SHELL_IMPL_H_ - -#include "base/callback.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/error_handler.h" -#include "mojo/public/interfaces/application/application.mojom.h" -#include "mojo/public/interfaces/application/shell.mojom.h" -#include "mojo/shell/application_manager/identity.h" -#include "url/gurl.h" - -namespace mojo { -namespace shell { - -class ApplicationManager; - -class ShellImpl : public Shell, public ErrorHandler { - public: - ShellImpl(ApplicationPtr application, - ApplicationManager* manager, - const Identity& resolved_identity, - const base::Closure& on_application_end); - - ~ShellImpl() override; - - void InitializeApplication(Array<String> args); - - void ConnectToClient(const GURL& requested_url, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services); - - Application* application() { return application_.get(); } - const Identity& identity() const { return identity_; } - base::Closure on_application_end() const { return on_application_end_; } - - private: - // Shell implementation: - void ConnectToApplication(const String& app_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) override; - - // ErrorHandler implementation: - void OnConnectionError() override; - - ApplicationManager* const manager_; - const Identity identity_; - base::Closure on_application_end_; - ApplicationPtr application_; - Binding<Shell> binding_; - - DISALLOW_COPY_AND_ASSIGN(ShellImpl); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_APPLICATION_MANAGER_SHELL_IMPL_H_
diff --git a/mojo/shell/application_manager_unittest.cc b/mojo/shell/application_manager_unittest.cc new file mode 100644 index 0000000..7819e37 --- /dev/null +++ b/mojo/shell/application_manager_unittest.cc
@@ -0,0 +1,741 @@ +// 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 "base/at_exit.h" +#include "base/bind.h" +#include "base/macros.h" +#include "base/memory/scoped_vector.h" +#include "base/message_loop/message_loop.h" +#include "mojo/public/cpp/application/application_connection.h" +#include "mojo/public/cpp/application/application_delegate.h" +#include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/interface_factory.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "mojo/public/interfaces/application/service_provider.mojom.h" +#include "mojo/shell/application_loader.h" +#include "mojo/shell/application_manager.h" +#include "mojo/shell/test.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { +namespace { + +const char kTestURLString[] = "test:testService"; +const char kTestAURLString[] = "test:TestA"; +const char kTestBURLString[] = "test:TestB"; + +struct TestContext { + TestContext() : num_impls(0), num_loader_deletes(0) {} + std::string last_test_string; + int num_impls; + int num_loader_deletes; +}; + +void QuitClosure(bool* value) { + *value = true; + base::MessageLoop::current()->QuitWhenIdle(); +} + +class QuitMessageLoopErrorHandler : public ErrorHandler { + public: + QuitMessageLoopErrorHandler() {} + ~QuitMessageLoopErrorHandler() override {} + + // |ErrorHandler| implementation: + void OnConnectionError() override { + base::MessageLoop::current()->QuitWhenIdle(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler); +}; + +class TestServiceImpl : public TestService { + public: + TestServiceImpl(TestContext* context, InterfaceRequest<TestService> request) + : context_(context), binding_(this, request.Pass()) { + ++context_->num_impls; + } + + ~TestServiceImpl() override { + --context_->num_impls; + if (!base::MessageLoop::current()->is_running()) + return; + base::MessageLoop::current()->Quit(); + } + + // TestService implementation: + void Test(const String& test_string, + const Callback<void()>& callback) override { + context_->last_test_string = test_string; + callback.Run(); + } + + private: + TestContext* context_; + StrongBinding<TestService> binding_; +}; + +class TestClient { + public: + explicit TestClient(TestServicePtr service) + : service_(service.Pass()), quit_after_ack_(false) {} + + void AckTest() { + if (quit_after_ack_) + base::MessageLoop::current()->Quit(); + } + + void Test(const std::string& test_string) { + quit_after_ack_ = true; + service_->Test(test_string, + base::Bind(&TestClient::AckTest, base::Unretained(this))); + } + + private: + TestServicePtr service_; + bool quit_after_ack_; + DISALLOW_COPY_AND_ASSIGN(TestClient); +}; + +class TestApplicationLoader : public ApplicationLoader, + public ApplicationDelegate, + public InterfaceFactory<TestService> { + public: + TestApplicationLoader() : context_(nullptr), num_loads_(0) {} + + ~TestApplicationLoader() override { + if (context_) + ++context_->num_loader_deletes; + test_app_.reset(); + } + + void set_context(TestContext* context) { context_ = context; } + int num_loads() const { return num_loads_; } + const std::vector<std::string>& GetArgs() const { return test_app_->args(); } + + private: + // ApplicationLoader implementation. + void Load(const GURL& url, + InterfaceRequest<Application> application_request) override { + ++num_loads_; + test_app_.reset(new ApplicationImpl(this, application_request.Pass())); + } + + // ApplicationDelegate implementation. + bool ConfigureIncomingConnection(ApplicationConnection* connection) override { + connection->AddService(this); + return true; + } + + // InterfaceFactory implementation. + void Create(ApplicationConnection* connection, + InterfaceRequest<TestService> request) override { + new TestServiceImpl(context_, request.Pass()); + } + + scoped_ptr<ApplicationImpl> test_app_; + TestContext* context_; + int num_loads_; + DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader); +}; + +class ClosingApplicationLoader : public ApplicationLoader { + private: + // ApplicationLoader implementation. + void Load(const GURL& url, + InterfaceRequest<Application> application_request) override {} +}; + +class TesterContext { + public: + explicit TesterContext(base::MessageLoop* loop) + : num_b_calls_(0), + num_c_calls_(0), + num_a_deletes_(0), + num_b_deletes_(0), + num_c_deletes_(0), + tester_called_quit_(false), + a_called_quit_(false), + loop_(loop) {} + + void IncrementNumBCalls() { + base::AutoLock lock(lock_); + num_b_calls_++; + } + + void IncrementNumCCalls() { + base::AutoLock lock(lock_); + num_c_calls_++; + } + + void IncrementNumADeletes() { + base::AutoLock lock(lock_); + num_a_deletes_++; + } + + void IncrementNumBDeletes() { + base::AutoLock lock(lock_); + num_b_deletes_++; + } + + void IncrementNumCDeletes() { + base::AutoLock lock(lock_); + num_c_deletes_++; + } + + void set_tester_called_quit() { + base::AutoLock lock(lock_); + tester_called_quit_ = true; + } + + void set_a_called_quit() { + base::AutoLock lock(lock_); + a_called_quit_ = true; + } + + int num_b_calls() { + base::AutoLock lock(lock_); + return num_b_calls_; + } + int num_c_calls() { + base::AutoLock lock(lock_); + return num_c_calls_; + } + int num_a_deletes() { + base::AutoLock lock(lock_); + return num_a_deletes_; + } + int num_b_deletes() { + base::AutoLock lock(lock_); + return num_b_deletes_; + } + int num_c_deletes() { + base::AutoLock lock(lock_); + return num_c_deletes_; + } + bool tester_called_quit() { + base::AutoLock lock(lock_); + return tester_called_quit_; + } + bool a_called_quit() { + base::AutoLock lock(lock_); + return a_called_quit_; + } + + void QuitSoon() { + loop_->PostTask(FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); + } + + private: + // lock_ protects all members except for loop_ which must be unchanged for the + // lifetime of this class. + base::Lock lock_; + int num_b_calls_; + int num_c_calls_; + int num_a_deletes_; + int num_b_deletes_; + int num_c_deletes_; + bool tester_called_quit_; + bool a_called_quit_; + + base::MessageLoop* loop_; +}; + +// Used to test that the requestor url will be correctly passed. +class TestAImpl : public TestA { + public: + TestAImpl(ApplicationImpl* app_impl, + TesterContext* test_context, + InterfaceRequest<TestA> request) + : test_context_(test_context), binding_(this, request.Pass()) { + app_impl->ConnectToApplication(kTestBURLString)->ConnectToService(&b_); + } + + ~TestAImpl() override { + test_context_->IncrementNumADeletes(); + if (base::MessageLoop::current()->is_running()) + Quit(); + } + + private: + void CallB() override { + b_->B(base::Bind(&TestAImpl::Quit, base::Unretained(this))); + } + + void CallCFromB() override { + b_->CallC(base::Bind(&TestAImpl::Quit, base::Unretained(this))); + } + + void Quit() { + base::MessageLoop::current()->Quit(); + test_context_->set_a_called_quit(); + test_context_->QuitSoon(); + } + + TesterContext* test_context_; + TestBPtr b_; + StrongBinding<TestA> binding_; +}; + +class TestBImpl : public TestB { + public: + TestBImpl(ApplicationConnection* connection, + TesterContext* test_context, + InterfaceRequest<TestB> request) + : test_context_(test_context), binding_(this, request.Pass()) { + connection->ConnectToService(&c_); + } + + ~TestBImpl() override { + test_context_->IncrementNumBDeletes(); + if (base::MessageLoop::current()->is_running()) + base::MessageLoop::current()->Quit(); + test_context_->QuitSoon(); + } + + private: + void B(const Callback<void()>& callback) override { + test_context_->IncrementNumBCalls(); + callback.Run(); + } + + void CallC(const Callback<void()>& callback) override { + test_context_->IncrementNumBCalls(); + c_->C(callback); + } + + TesterContext* test_context_; + TestCPtr c_; + StrongBinding<TestB> binding_; +}; + +class TestCImpl : public TestC { + public: + TestCImpl(ApplicationConnection* connection, + TesterContext* test_context, + InterfaceRequest<TestC> request) + : test_context_(test_context), binding_(this, request.Pass()) {} + + ~TestCImpl() override { test_context_->IncrementNumCDeletes(); } + + private: + void C(const Callback<void()>& callback) override { + test_context_->IncrementNumCCalls(); + callback.Run(); + } + + TesterContext* test_context_; + StrongBinding<TestC> binding_; +}; + +class Tester : public ApplicationDelegate, + public ApplicationLoader, + public InterfaceFactory<TestA>, + public InterfaceFactory<TestB>, + public InterfaceFactory<TestC> { + public: + Tester(TesterContext* context, const std::string& requestor_url) + : context_(context), requestor_url_(requestor_url) {} + ~Tester() override {} + + private: + void Load(const GURL& url, + InterfaceRequest<Application> application_request) override { + app_.reset(new ApplicationImpl(this, application_request.Pass())); + } + + bool ConfigureIncomingConnection(ApplicationConnection* connection) override { + if (!requestor_url_.empty() && + requestor_url_ != connection->GetRemoteApplicationURL()) { + context_->set_tester_called_quit(); + context_->QuitSoon(); + base::MessageLoop::current()->Quit(); + return false; + } + // If we're coming from A, then add B, otherwise A. + if (connection->GetRemoteApplicationURL() == kTestAURLString) + connection->AddService<TestB>(this); + else + connection->AddService<TestA>(this); + return true; + } + + bool ConfigureOutgoingConnection(ApplicationConnection* connection) override { + // If we're connecting to B, then add C. + if (connection->GetRemoteApplicationURL() == kTestBURLString) + connection->AddService<TestC>(this); + return true; + } + + void Create(ApplicationConnection* connection, + InterfaceRequest<TestA> request) override { + a_bindings_.push_back(new TestAImpl(app_.get(), context_, request.Pass())); + } + + void Create(ApplicationConnection* connection, + InterfaceRequest<TestB> request) override { + new TestBImpl(connection, context_, request.Pass()); + } + + void Create(ApplicationConnection* connection, + InterfaceRequest<TestC> request) override { + new TestCImpl(connection, context_, request.Pass()); + } + + TesterContext* context_; + scoped_ptr<ApplicationImpl> app_; + std::string requestor_url_; + ScopedVector<TestAImpl> a_bindings_; +}; + +class TestDelegate : public ApplicationManager::Delegate { + public: + void AddMapping(const GURL& from, const GURL& to) { mappings_[from] = to; } + + // ApplicationManager::Delegate + GURL ResolveMappings(const GURL& url) override { + auto it = mappings_.find(url); + if (it != mappings_.end()) + return it->second; + return url; + } + GURL ResolveMojoURL(const GURL& url) override { + GURL mapped_url = ResolveMappings(url); + // The shell automatically map mojo URLs. + if (mapped_url.scheme() == "mojo") { + url::Replacements<char> replacements; + replacements.SetScheme("file", url::Component(0, 4)); + mapped_url = mapped_url.ReplaceComponents(replacements); + } + return mapped_url; + } + + private: + std::map<GURL, GURL> mappings_; +}; + +class ApplicationManagerTest : public testing::Test { + public: + ApplicationManagerTest() : tester_context_(&loop_) {} + + ~ApplicationManagerTest() override {} + + void SetUp() override { + application_manager_.reset(new ApplicationManager(&test_delegate_)); + test_loader_ = new TestApplicationLoader; + test_loader_->set_context(&context_); + application_manager_->set_default_loader( + scoped_ptr<ApplicationLoader>(test_loader_)); + + TestServicePtr service_proxy; + application_manager_->ConnectToService(GURL(kTestURLString), + &service_proxy); + test_client_.reset(new TestClient(service_proxy.Pass())); + } + + void TearDown() override { + test_client_.reset(); + application_manager_.reset(); + } + + void AddLoaderForURL(const GURL& url, const std::string& requestor_url) { + application_manager_->SetLoaderForURL( + make_scoped_ptr(new Tester(&tester_context_, requestor_url)), url); + } + + bool HasFactoryForTestURL() { + ApplicationManager::TestAPI manager_test_api(application_manager_.get()); + return manager_test_api.HasFactoryForURL(GURL(kTestURLString)); + } + + protected: + base::ShadowingAtExitManager at_exit_; + TestDelegate test_delegate_; + TestApplicationLoader* test_loader_; + TesterContext tester_context_; + TestContext context_; + base::MessageLoop loop_; + scoped_ptr<TestClient> test_client_; + scoped_ptr<ApplicationManager> application_manager_; + DISALLOW_COPY_AND_ASSIGN(ApplicationManagerTest); +}; + +TEST_F(ApplicationManagerTest, Basic) { + test_client_->Test("test"); + loop_.Run(); + EXPECT_EQ(std::string("test"), context_.last_test_string); +} + +// Confirm that no arguments are sent to an application by default. +TEST_F(ApplicationManagerTest, NoArgs) { + ApplicationManager am(&test_delegate_); + GURL test_url("test:test"); + TestApplicationLoader* loader = new TestApplicationLoader; + loader->set_context(&context_); + am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url); + TestServicePtr test_service; + am.ConnectToService(test_url, &test_service); + TestClient test_client(test_service.Pass()); + test_client.Test("test"); + loop_.Run(); + std::vector<std::string> app_args = loader->GetArgs(); + EXPECT_EQ(0U, app_args.size()); +} + +// Confirm that url mappings are respected. +TEST_F(ApplicationManagerTest, URLMapping) { + ApplicationManager am(&test_delegate_); + GURL test_url("test:test"); + GURL test_url2("test:test2"); + test_delegate_.AddMapping(test_url, test_url2); + TestApplicationLoader* loader = new TestApplicationLoader; + loader->set_context(&context_); + am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(loader), test_url2); + { + // Connext to the mapped url + TestServicePtr test_service; + am.ConnectToService(test_url, &test_service); + TestClient test_client(test_service.Pass()); + test_client.Test("test"); + loop_.Run(); + } + { + // Connext to the target url + TestServicePtr test_service; + am.ConnectToService(test_url2, &test_service); + TestClient test_client(test_service.Pass()); + test_client.Test("test"); + loop_.Run(); + } +} + +TEST_F(ApplicationManagerTest, ClientError) { + test_client_->Test("test"); + EXPECT_TRUE(HasFactoryForTestURL()); + loop_.Run(); + EXPECT_EQ(1, context_.num_impls); + test_client_.reset(); + loop_.Run(); + EXPECT_EQ(0, context_.num_impls); + EXPECT_TRUE(HasFactoryForTestURL()); +} + +TEST_F(ApplicationManagerTest, Deletes) { + { + ApplicationManager am(&test_delegate_); + TestApplicationLoader* default_loader = new TestApplicationLoader; + default_loader->set_context(&context_); + TestApplicationLoader* url_loader1 = new TestApplicationLoader; + TestApplicationLoader* url_loader2 = new TestApplicationLoader; + url_loader1->set_context(&context_); + url_loader2->set_context(&context_); + TestApplicationLoader* scheme_loader1 = new TestApplicationLoader; + TestApplicationLoader* scheme_loader2 = new TestApplicationLoader; + scheme_loader1->set_context(&context_); + scheme_loader2->set_context(&context_); + am.set_default_loader(scoped_ptr<ApplicationLoader>(default_loader)); + am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader1), + GURL("test:test1")); + am.SetLoaderForURL(scoped_ptr<ApplicationLoader>(url_loader2), + GURL("test:test1")); + am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader1), + "test"); + am.SetLoaderForScheme(scoped_ptr<ApplicationLoader>(scheme_loader2), + "test"); + } + EXPECT_EQ(5, context_.num_loader_deletes); +} + +// Confirm that both urls and schemes can have their loaders explicitly set. +TEST_F(ApplicationManagerTest, SetLoaders) { + TestApplicationLoader* default_loader = new TestApplicationLoader; + TestApplicationLoader* url_loader = new TestApplicationLoader; + TestApplicationLoader* scheme_loader = new TestApplicationLoader; + application_manager_->set_default_loader( + scoped_ptr<ApplicationLoader>(default_loader)); + application_manager_->SetLoaderForURL( + scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1")); + application_manager_->SetLoaderForScheme( + scoped_ptr<ApplicationLoader>(scheme_loader), "test"); + + // test::test1 should go to url_loader. + TestServicePtr test_service; + application_manager_->ConnectToService(GURL("test:test1"), &test_service); + EXPECT_EQ(1, url_loader->num_loads()); + EXPECT_EQ(0, scheme_loader->num_loads()); + EXPECT_EQ(0, default_loader->num_loads()); + + // test::test2 should go to scheme loader. + application_manager_->ConnectToService(GURL("test:test2"), &test_service); + EXPECT_EQ(1, url_loader->num_loads()); + EXPECT_EQ(1, scheme_loader->num_loads()); + EXPECT_EQ(0, default_loader->num_loads()); + + // http::test1 should go to default loader. + application_manager_->ConnectToService(GURL("http:test1"), &test_service); + EXPECT_EQ(1, url_loader->num_loads()); + EXPECT_EQ(1, scheme_loader->num_loads()); + EXPECT_EQ(1, default_loader->num_loads()); +} + +// Confirm that the url of a service is correctly passed to another service that +// it loads. +TEST_F(ApplicationManagerTest, ACallB) { + // Any url can load a. + AddLoaderForURL(GURL(kTestAURLString), std::string()); + + // Only a can load b. + AddLoaderForURL(GURL(kTestBURLString), kTestAURLString); + + TestAPtr a; + application_manager_->ConnectToService(GURL(kTestAURLString), &a); + a->CallB(); + loop_.Run(); + EXPECT_EQ(1, tester_context_.num_b_calls()); + EXPECT_TRUE(tester_context_.a_called_quit()); +} + +// A calls B which calls C. +TEST_F(ApplicationManagerTest, BCallC) { + // Any url can load a. + AddLoaderForURL(GURL(kTestAURLString), std::string()); + + // Only a can load b. + AddLoaderForURL(GURL(kTestBURLString), kTestAURLString); + + TestAPtr a; + application_manager_->ConnectToService(GURL(kTestAURLString), &a); + a->CallCFromB(); + loop_.Run(); + + EXPECT_EQ(1, tester_context_.num_b_calls()); + EXPECT_EQ(1, tester_context_.num_c_calls()); + EXPECT_TRUE(tester_context_.a_called_quit()); +} + +// Confirm that a service impl will be deleted if the app that connected to +// it goes away. +TEST_F(ApplicationManagerTest, BDeleted) { + AddLoaderForURL(GURL(kTestAURLString), std::string()); + AddLoaderForURL(GURL(kTestBURLString), std::string()); + + TestAPtr a; + application_manager_->ConnectToService(GURL(kTestAURLString), &a); + + a->CallB(); + loop_.Run(); + + // Kills the a app. + application_manager_->SetLoaderForURL(scoped_ptr<ApplicationLoader>(), + GURL(kTestAURLString)); + loop_.Run(); + + EXPECT_EQ(1, tester_context_.num_b_deletes()); +} + +// Confirm that the url of a service is correctly passed to another service that +// it loads, and that it can be rejected. +TEST_F(ApplicationManagerTest, ANoLoadB) { + // Any url can load a. + AddLoaderForURL(GURL(kTestAURLString), std::string()); + + // Only c can load b, so this will fail. + AddLoaderForURL(GURL(kTestBURLString), "test:TestC"); + + TestAPtr a; + application_manager_->ConnectToService(GURL(kTestAURLString), &a); + a->CallB(); + loop_.Run(); + EXPECT_EQ(0, tester_context_.num_b_calls()); + + EXPECT_FALSE(tester_context_.a_called_quit()); + EXPECT_TRUE(tester_context_.tester_called_quit()); +} + +TEST_F(ApplicationManagerTest, NoServiceNoLoad) { + AddLoaderForURL(GURL(kTestAURLString), std::string()); + + // There is no TestC service implementation registered with + // ApplicationManager, so this cannot succeed (but also shouldn't crash). + TestCPtr c; + application_manager_->ConnectToService(GURL(kTestAURLString), &c); + QuitMessageLoopErrorHandler quitter; + c.set_error_handler(&quitter); + + loop_.Run(); + EXPECT_TRUE(c.encountered_error()); +} + +TEST_F(ApplicationManagerTest, MappedURLsShouldNotCauseDuplicateLoad) { + test_delegate_.AddMapping(GURL("foo:foo2"), GURL("foo:foo")); + // 1 because ApplicationManagerTest connects once at startup. + EXPECT_EQ(1, test_loader_->num_loads()); + + TestServicePtr test_service; + application_manager_->ConnectToService(GURL("foo:foo"), &test_service); + EXPECT_EQ(2, test_loader_->num_loads()); + + TestServicePtr test_service2; + application_manager_->ConnectToService(GURL("foo:foo2"), &test_service2); + EXPECT_EQ(2, test_loader_->num_loads()); + + TestServicePtr test_service3; + application_manager_->ConnectToService(GURL("bar:bar"), &test_service2); + EXPECT_EQ(3, test_loader_->num_loads()); +} + +TEST_F(ApplicationManagerTest, MappedURLsShouldWorkWithLoaders) { + TestApplicationLoader* custom_loader = new TestApplicationLoader; + TestContext context; + custom_loader->set_context(&context); + application_manager_->SetLoaderForURL(make_scoped_ptr(custom_loader), + GURL("mojo:foo")); + test_delegate_.AddMapping(GURL("mojo:foo2"), GURL("mojo:foo")); + + TestServicePtr test_service; + application_manager_->ConnectToService(GURL("mojo:foo2"), &test_service); + EXPECT_EQ(1, custom_loader->num_loads()); + custom_loader->set_context(nullptr); +} + +TEST_F(ApplicationManagerTest, TestQueryWithLoaders) { + TestApplicationLoader* url_loader = new TestApplicationLoader; + TestApplicationLoader* scheme_loader = new TestApplicationLoader; + application_manager_->SetLoaderForURL( + scoped_ptr<ApplicationLoader>(url_loader), GURL("test:test1")); + application_manager_->SetLoaderForScheme( + scoped_ptr<ApplicationLoader>(scheme_loader), "test"); + + // test::test1 should go to url_loader. + TestServicePtr test_service; + application_manager_->ConnectToService(GURL("test:test1?foo=bar"), + &test_service); + EXPECT_EQ(1, url_loader->num_loads()); + EXPECT_EQ(0, scheme_loader->num_loads()); + + // test::test2 should go to scheme loader. + application_manager_->ConnectToService(GURL("test:test2?foo=bar"), + &test_service); + EXPECT_EQ(1, url_loader->num_loads()); + EXPECT_EQ(1, scheme_loader->num_loads()); +} + +TEST_F(ApplicationManagerTest, TestEndApplicationClosure) { + ClosingApplicationLoader* loader = new ClosingApplicationLoader(); + application_manager_->SetLoaderForScheme( + scoped_ptr<ApplicationLoader>(loader), "test"); + + bool called = false; + application_manager_->ConnectToApplication( + GURL("test:test"), GURL(), nullptr, nullptr, + base::Bind(&QuitClosure, base::Unretained(&called))); + loop_.Run(); + EXPECT_TRUE(called); +} + +} // namespace +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/child_process.cc b/mojo/shell/child_process.cc deleted file mode 100644 index eecb98c..0000000 --- a/mojo/shell/child_process.cc +++ /dev/null
@@ -1,306 +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 "mojo/shell/child_process.h" - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/single_thread_task_runner.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "base/threading/thread_checker.h" -#include "mojo/common/message_pump_mojo.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/process_delegate.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/edk/embedder/simple_platform_support.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/shell/child_process.mojom.h" -#include "mojo/shell/native_application_support.h" -#include "mojo/shell/switches.h" - -namespace mojo { -namespace shell { - -namespace { - -// Blocker --------------------------------------------------------------------- - -// Blocks a thread until another thread unblocks it, at which point it unblocks -// and runs a closure provided by that thread. -class Blocker { - public: - class Unblocker { - public: - explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {} - ~Unblocker() {} - - void Unblock(base::Closure run_after) { - DCHECK(blocker_); - DCHECK(blocker_->run_after_.is_null()); - blocker_->run_after_ = run_after; - blocker_->event_.Signal(); - blocker_ = nullptr; - } - - private: - Blocker* blocker_; - - // Copy and assign allowed. - }; - - Blocker() : event_(true, false) {} - ~Blocker() {} - - void Block() { - DCHECK(run_after_.is_null()); - event_.Wait(); - run_after_.Run(); - } - - Unblocker GetUnblocker() { return Unblocker(this); } - - private: - base::WaitableEvent event_; - base::Closure run_after_; - - DISALLOW_COPY_AND_ASSIGN(Blocker); -}; - -// AppContext ------------------------------------------------------------------ - -class ChildControllerImpl; - -// Should be created and initialized on the main thread. -class AppContext : public embedder::ProcessDelegate { - public: - AppContext() - : io_thread_("io_thread"), controller_thread_("controller_thread") {} - ~AppContext() override {} - - void Init() { - // Initialize Mojo before starting any threads. - embedder::Init(make_scoped_ptr(new embedder::SimplePlatformSupport())); - - // Create and start our I/O thread. - base::Thread::Options io_thread_options(base::MessageLoop::TYPE_IO, 0); - CHECK(io_thread_.StartWithOptions(io_thread_options)); - io_runner_ = io_thread_.message_loop_proxy().get(); - CHECK(io_runner_.get()); - - // Create and start our controller thread. - base::Thread::Options controller_thread_options; - controller_thread_options.message_loop_type = - base::MessageLoop::TYPE_CUSTOM; - controller_thread_options.message_pump_factory = - base::Bind(&common::MessagePumpMojo::Create); - CHECK(controller_thread_.StartWithOptions(controller_thread_options)); - controller_runner_ = controller_thread_.message_loop_proxy().get(); - CHECK(controller_runner_.get()); - - // TODO(vtl): This should be SLAVE, not NONE. - embedder::InitIPCSupport(embedder::ProcessType::NONE, controller_runner_, - this, io_runner_, - embedder::ScopedPlatformHandle()); - } - - void Shutdown() { - Blocker blocker; - shutdown_unblocker_ = blocker.GetUnblocker(); - controller_runner_->PostTask( - FROM_HERE, base::Bind(&AppContext::ShutdownOnControllerThread, - base::Unretained(this))); - blocker.Block(); - } - - base::SingleThreadTaskRunner* io_runner() const { return io_runner_.get(); } - - base::SingleThreadTaskRunner* controller_runner() const { - return controller_runner_.get(); - } - - ChildControllerImpl* controller() const { return controller_.get(); } - - void set_controller(scoped_ptr<ChildControllerImpl> controller) { - controller_ = controller.Pass(); - } - - private: - void ShutdownOnControllerThread() { - // First, destroy the controller. - controller_.reset(); - - // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete(). - embedder::ShutdownIPCSupport(); - } - - // ProcessDelegate implementation. - void OnShutdownComplete() override { - shutdown_unblocker_.Unblock(base::Closure()); - } - - base::Thread io_thread_; - scoped_refptr<base::SingleThreadTaskRunner> io_runner_; - - base::Thread controller_thread_; - scoped_refptr<base::SingleThreadTaskRunner> controller_runner_; - - // Accessed only on the controller thread. - scoped_ptr<ChildControllerImpl> controller_; - - // Used to unblock the main thread on shutdown. - Blocker::Unblocker shutdown_unblocker_; - - DISALLOW_COPY_AND_ASSIGN(AppContext); -}; - -// ChildControllerImpl ------------------------------------------------------ - -class ChildControllerImpl : public ChildController, public ErrorHandler { - public: - ~ChildControllerImpl() override { - DCHECK(thread_checker_.CalledOnValidThread()); - - // TODO(vtl): Pass in the result from |MainMain()|. - on_app_complete_.Run(MOJO_RESULT_UNIMPLEMENTED); - } - - // To be executed on the controller thread. Creates the |ChildController|, - // etc. - static void Init(AppContext* app_context, - embedder::ScopedPlatformHandle platform_channel, - const Blocker::Unblocker& unblocker) { - DCHECK(app_context); - DCHECK(platform_channel.is_valid()); - - DCHECK(!app_context->controller()); - - scoped_ptr<ChildControllerImpl> impl( - new ChildControllerImpl(app_context, unblocker)); - - ScopedMessagePipeHandle host_message_pipe(embedder::CreateChannel( - platform_channel.Pass(), app_context->io_runner(), - base::Bind(&ChildControllerImpl::DidCreateChannel, - base::Unretained(impl.get())), - base::MessageLoopProxy::current())); - - impl->Bind(host_message_pipe.Pass()); - - app_context->set_controller(impl.Pass()); - } - - void Bind(ScopedMessagePipeHandle handle) { binding_.Bind(handle.Pass()); } - - // |ErrorHandler| methods: - void OnConnectionError() override { - // A connection error means the connection to the shell is lost. This is not - // recoverable. - LOG(ERROR) << "Connection error to the shell."; - _exit(1); - } - - // |ChildController| methods: - void StartApp(const String& app_path, - bool clean_app_path, - InterfaceRequest<Application> application_request, - const StartAppCallback& on_app_complete) override { - DVLOG(2) << "ChildControllerImpl::StartApp(" << app_path << ", ...)"; - DCHECK(thread_checker_.CalledOnValidThread()); - - on_app_complete_ = on_app_complete; - unblocker_.Unblock(base::Bind(&ChildControllerImpl::StartAppOnMainThread, - base::FilePath::FromUTF8Unsafe(app_path), - clean_app_path - ? NativeApplicationCleanup::DELETE - : NativeApplicationCleanup::DONT_DELETE, - base::Passed(&application_request))); - } - - void ExitNow(int32_t exit_code) override { - DVLOG(2) << "ChildControllerImpl::ExitNow(" << exit_code << ")"; - _exit(exit_code); - } - - private: - ChildControllerImpl(AppContext* app_context, - const Blocker::Unblocker& unblocker) - : app_context_(app_context), - unblocker_(unblocker), - channel_info_(nullptr), - binding_(this) { - binding_.set_error_handler(this); - } - - // Callback for |embedder::CreateChannel()|. - void DidCreateChannel(embedder::ChannelInfo* channel_info) { - DVLOG(2) << "ChildControllerImpl::DidCreateChannel()"; - DCHECK(thread_checker_.CalledOnValidThread()); - channel_info_ = channel_info; - } - - static void StartAppOnMainThread( - const base::FilePath& app_path, - NativeApplicationCleanup cleanup, - InterfaceRequest<Application> application_request) { - // TODO(vtl): This is copied from in_process_native_runner.cc. - DVLOG(2) << "Loading/running Mojo app from " << app_path.value() - << " out of process"; - - // We intentionally don't unload the native library as its lifetime is the - // same as that of the process. - base::NativeLibrary app_library = LoadNativeApplication(app_path, cleanup); - RunNativeApplication(app_library, application_request.Pass()); - } - - base::ThreadChecker thread_checker_; - AppContext* const app_context_; - Blocker::Unblocker unblocker_; - StartAppCallback on_app_complete_; - - embedder::ChannelInfo* channel_info_; - Binding<ChildController> binding_; - - DISALLOW_COPY_AND_ASSIGN(ChildControllerImpl); -}; - -} // namespace - -int ChildProcessMain() { - DVLOG(2) << "ChildProcessMain()"; - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - embedder::ScopedPlatformHandle platform_channel = - embedder::PlatformChannelPair::PassClientHandleFromParentProcess( - command_line); - CHECK(platform_channel.is_valid()); - - DCHECK(!base::MessageLoop::current()); - - AppContext app_context; - app_context.Init(); - - Blocker blocker; - app_context.controller_runner()->PostTask( - FROM_HERE, - base::Bind(&ChildControllerImpl::Init, base::Unretained(&app_context), - base::Passed(&platform_channel), blocker.GetUnblocker())); - // This will block, then run whatever the controller wants. - blocker.Block(); - - app_context.Shutdown(); - - return 0; -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/child_process.h b/mojo/shell/child_process.h deleted file mode 100644 index c0cc431..0000000 --- a/mojo/shell/child_process.h +++ /dev/null
@@ -1,17 +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 MOJO_SHELL_CHILD_PROCESS_H_ -#define MOJO_SHELL_CHILD_PROCESS_H_ - -namespace mojo { -namespace shell { - -// Main method for a child process. -int ChildProcessMain(); - -} // namespace shell -} // namespace mojo - -#endif // MOJO_SHELL_CHILD_PROCESS_H_
diff --git a/mojo/shell/child_process_host.cc b/mojo/shell/child_process_host.cc deleted file mode 100644 index 9d955e2..0000000 --- a/mojo/shell/child_process_host.cc +++ /dev/null
@@ -1,144 +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 "mojo/shell/child_process_host.h" - -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/process/kill.h" -#include "base/process/launch.h" -#include "base/task_runner.h" -#include "base/task_runner_util.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/shell/context.h" -#include "mojo/shell/switches.h" -#include "mojo/shell/task_runners.h" - -namespace mojo { -namespace shell { - -ChildProcessHost::ChildProcessHost(Context* context) - : context_(context), channel_info_(nullptr) { - platform_channel_ = platform_channel_pair_.PassServerHandle(); - CHECK(platform_channel_.is_valid()); -} - -ChildProcessHost::~ChildProcessHost() { - if (child_process_.IsValid()) { - LOG(WARNING) << "Destroying ChildProcessHost with unjoined child"; - child_process_.Close(); - } -} - -void ChildProcessHost::Start() { - DCHECK(!child_process_.IsValid()); - DCHECK(platform_channel_.is_valid()); - - ScopedMessagePipeHandle handle(embedder::CreateChannel( - platform_channel_.Pass(), context_->task_runners()->io_runner(), - base::Bind(&ChildProcessHost::DidCreateChannel, base::Unretained(this)), - base::MessageLoop::current()->message_loop_proxy())); - - controller_.Bind(handle.Pass()); - - CHECK(base::PostTaskAndReplyWithResult( - context_->task_runners()->blocking_pool(), FROM_HERE, - base::Bind(&ChildProcessHost::DoLaunch, base::Unretained(this)), - base::Bind(&ChildProcessHost::DidStart, base::Unretained(this)))); -} - -int ChildProcessHost::Join() { - DCHECK(child_process_.IsValid()); - int rv = -1; - LOG_IF(ERROR, !child_process_.WaitForExit(&rv)) - << "Failed to wait for child process"; - child_process_.Close(); - return rv; -} - -void ChildProcessHost::StartApp( - const String& app_path, - bool clean_app_path, - InterfaceRequest<Application> application_request, - const ChildController::StartAppCallback& on_app_complete) { - DCHECK(controller_); - - on_app_complete_ = on_app_complete; - controller_->StartApp( - app_path, clean_app_path, application_request.Pass(), - base::Bind(&ChildProcessHost::AppCompleted, base::Unretained(this))); -} - -void ChildProcessHost::ExitNow(int32_t exit_code) { - DCHECK(controller_); - - controller_->ExitNow(exit_code); -} - -void ChildProcessHost::DidStart(bool success) { - DVLOG(2) << "ChildProcessHost::DidStart()"; - - if (!success) { - LOG(ERROR) << "Failed to start child process"; - AppCompleted(MOJO_RESULT_UNKNOWN); - return; - } -} - -bool ChildProcessHost::DoLaunch() { - static const char* kForwardSwitches[] = { - switches::kTraceToConsole, switches::kV, switches::kVModule, - }; - - const base::CommandLine* parent_command_line = - base::CommandLine::ForCurrentProcess(); - base::CommandLine child_command_line(parent_command_line->GetProgram()); - child_command_line.CopySwitchesFrom(*parent_command_line, kForwardSwitches, - arraysize(kForwardSwitches)); - child_command_line.AppendSwitch(switches::kChildProcess); - - embedder::HandlePassingInformation handle_passing_info; - platform_channel_pair_.PrepareToPassClientHandleToChildProcess( - &child_command_line, &handle_passing_info); - - base::LaunchOptions options; -#if defined(OS_WIN) - options.start_hidden = true; - options.handles_to_inherit = &handle_passing_info; -#elif defined(OS_POSIX) - options.fds_to_remap = &handle_passing_info; -#endif - DVLOG(2) << "Launching child with command line: " - << child_command_line.GetCommandLineString(); - child_process_ = base::LaunchProcess(child_command_line, options); - if (!child_process_.IsValid()) - return false; - - platform_channel_pair_.ChildProcessLaunched(); - return true; -} - -void ChildProcessHost::AppCompleted(int32_t result) { - if (!on_app_complete_.is_null()) { - auto on_app_complete = on_app_complete_; - on_app_complete_.reset(); - on_app_complete.Run(result); - } -} - -void ChildProcessHost::DidCreateChannel(embedder::ChannelInfo* channel_info) { - DVLOG(2) << "AppChildProcessHost::DidCreateChannel()"; - - CHECK(channel_info); - channel_info_ = channel_info; -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/child_process_host.h b/mojo/shell/child_process_host.h deleted file mode 100644 index 61b357b..0000000 --- a/mojo/shell/child_process_host.h +++ /dev/null
@@ -1,84 +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 SHELL_CHILD_PROCESS_HOST_H_ -#define SHELL_CHILD_PROCESS_HOST_H_ - -#include "base/macros.h" -#include "base/process/process.h" -#include "mojo/edk/embedder/channel_info_forward.h" -#include "mojo/edk/embedder/platform_channel_pair.h" -#include "mojo/edk/embedder/scoped_platform_handle.h" -#include "mojo/shell/child_process.mojom.h" -#include "mojo/shell/child_process_host.h" - -namespace mojo { -namespace shell { - -class Context; - -// This class represents a "child process host". Handles launching and -// connecting a platform-specific "pipe" to the child, and supports joining the -// child process. Currently runs a single app (loaded from the file system). -// -// This class is not thread-safe. It should be created/used/destroyed on a -// single thread. -// -// Note: Does not currently work on Windows before Vista. -// Note: After |Start()|, |StartApp| must be called and this object must -// remained alive until the |on_app_complete| callback is called. -class ChildProcessHost { - public: - explicit ChildProcessHost(Context* context); - virtual ~ChildProcessHost(); - - // |Start()|s the child process; calls |DidStart()| (on the thread on which - // |Start()| was called) when the child has been started (or failed to start). - // After calling |Start()|, this object must not be destroyed until - // |DidStart()| has been called. - // TODO(vtl): Consider using weak pointers and removing this requirement. - void Start(); - - // Waits for the child process to terminate, and returns its exit code. - // Note: If |Start()| has been called, this must not be called until the - // callback has been called. - int Join(); - - // See |ChildController|: - void StartApp(const String& app_path, - bool clean_app_path, - InterfaceRequest<Application> application_request, - const ChildController::StartAppCallback& on_app_complete); - void ExitNow(int32_t exit_code); - - protected: - // virtual for testing. - virtual void DidStart(bool success); - - private: - bool DoLaunch(); - - void AppCompleted(int32_t result); - - // Callback for |embedder::CreateChannel()|. - void DidCreateChannel(embedder::ChannelInfo* channel_info); - - Context* const context_; - base::Process child_process_; - embedder::PlatformChannelPair platform_channel_pair_; - ChildControllerPtr controller_; - embedder::ChannelInfo* channel_info_; - ChildController::StartAppCallback on_app_complete_; - - // Platform-specific "pipe" to the child process. Valid immediately after - // creation. - embedder::ScopedPlatformHandle platform_channel_; - - DISALLOW_COPY_AND_ASSIGN(ChildProcessHost); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_CHILD_PROCESS_HOST_H_
diff --git a/mojo/shell/child_process_host_unittest.cc b/mojo/shell/child_process_host_unittest.cc deleted file mode 100644 index 8e8f16d..0000000 --- a/mojo/shell/child_process_host_unittest.cc +++ /dev/null
@@ -1,62 +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. - -// Note: This file also tests child_process.*. - -#include "mojo/shell/child_process_host.h" - -#include "base/logging.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "mojo/common/message_pump_mojo.h" -#include "mojo/shell/context.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { -namespace { - -// Subclass just so we can observe |DidStart()|. -class TestChildProcessHost : public ChildProcessHost { - public: - explicit TestChildProcessHost(Context* context) : ChildProcessHost(context) {} - ~TestChildProcessHost() override {} - - void DidStart(bool success) override { - EXPECT_TRUE(success); - ChildProcessHost::DidStart(success); - base::MessageLoop::current()->QuitWhenIdle(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TestChildProcessHost); -}; - -#if defined(OS_ANDROID) -// TODO(qsr): Multiprocess shell tests are not supported on android. -#define MAYBE_StartJoin DISABLED_StartJoin -#else -#define MAYBE_StartJoin StartJoin -#endif // defined(OS_ANDROID) -// Just tests starting the child process and joining it (without starting an -// app). -TEST(ChildProcessHostTest, MAYBE_StartJoin) { - Context context; - base::MessageLoop message_loop( - scoped_ptr<base::MessagePump>(new common::MessagePumpMojo())); - context.Init(); - TestChildProcessHost child_process_host(&context); - child_process_host.Start(); - message_loop.Run(); - child_process_host.ExitNow(123); - int exit_code = child_process_host.Join(); - VLOG(2) << "Joined child: exit_code = " << exit_code; - EXPECT_EQ(123, exit_code); - - context.Shutdown(); -} - -} // namespace -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/context.cc b/mojo/shell/context.cc deleted file mode 100644 index 0cc27d1..0000000 --- a/mojo/shell/context.cc +++ /dev/null
@@ -1,328 +0,0 @@ -// Copyright 2013 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/shell/context.h" - -#include <vector> - -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/lazy_instance.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/memory/scoped_vector.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/trace_event/trace_event.h" -#include "build/build_config.h" -#include "mojo/common/trace_controller_impl.h" -#include "mojo/common/tracing_impl.h" -#include "mojo/edk/embedder/embedder.h" -#include "mojo/edk/embedder/simple_platform_support.h" -#include "mojo/public/cpp/application/application_connection.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/services/tracing/tracing.mojom.h" -#include "mojo/shell/application_manager/application_loader.h" -#include "mojo/shell/application_manager/application_manager.h" -#include "mojo/shell/filename_util.h" -#include "mojo/shell/in_process_native_runner.h" -#include "mojo/shell/out_of_process_native_runner.h" -#include "mojo/shell/switches.h" -#include "url/gurl.h" - -namespace mojo { -namespace shell { -namespace { - -// Used to ensure we only init once. -class Setup { - public: - Setup() { - embedder::Init(make_scoped_ptr(new embedder::SimplePlatformSupport())); - } - - ~Setup() {} - - private: - DISALLOW_COPY_AND_ASSIGN(Setup); -}; - -bool ConfigureURLMappings(const base::CommandLine& command_line, - Context* context) { - URLResolver* resolver = context->url_resolver(); - - // Configure the resolution of unknown mojo: URLs. - GURL base_url; - if (command_line.HasSwitch(switches::kOrigin)) - base_url = GURL(command_line.GetSwitchValueASCII(switches::kOrigin)); - else - // Use the shell's file root if the base was not specified. - base_url = context->ResolveShellFileURL(""); - - if (!base_url.is_valid()) - return false; - - resolver->SetMojoBaseURL(base_url); - - // The network service must be loaded from the filesystem. - // This mapping is done before the command line URL mapping are processed, so - // that it can be overridden. - resolver->AddURLMapping( - GURL("mojo:network_service"), - context->ResolveShellFileURL("file:network_service.mojo")); - - // Command line URL mapping. - std::vector<URLResolver::OriginMapping> origin_mappings = - URLResolver::GetOriginMappings(command_line.argv()); - for (const auto& origin_mapping : origin_mappings) - resolver->AddOriginMapping(GURL(origin_mapping.origin), - GURL(origin_mapping.base_url)); - - if (command_line.HasSwitch(switches::kURLMappings)) { - const std::string mappings = - command_line.GetSwitchValueASCII(switches::kURLMappings); - - base::StringPairs pairs; - if (!base::SplitStringIntoKeyValuePairs(mappings, '=', ',', &pairs)) - return false; - using StringPair = std::pair<std::string, std::string>; - for (const StringPair& pair : pairs) { - const GURL from(pair.first); - const GURL to = context->ResolveCommandLineURL(pair.second); - if (!from.is_valid() || !to.is_valid()) - return false; - resolver->AddURLMapping(from, to); - } - } - - return true; -} - -void InitContentHandlers(ApplicationManager* manager, - const base::CommandLine& command_line) { - // Default content handlers. - manager->RegisterContentHandler("application/pdf", GURL("mojo:pdf_viewer")); - manager->RegisterContentHandler("image/png", GURL("mojo:png_viewer")); - manager->RegisterContentHandler("text/html", GURL("mojo:html_viewer")); - - // Command-line-specified content handlers. - std::string handlers_spec = - command_line.GetSwitchValueASCII(switches::kContentHandlers); - if (handlers_spec.empty()) - return; - -#if defined(OS_ANDROID) - // TODO(eseidel): On Android we pass command line arguments is via the - // 'parameters' key on the intent, which we specify during 'am shell start' - // via --esa, however that expects comma-separated values and says: - // am shell --help: - // [--esa <EXTRA_KEY> <EXTRA_STRING_VALUE>[,<EXTRA_STRING_VALUE...]] - // (to embed a comma into a string escape it using "\,") - // Whatever takes 'parameters' and constructs a CommandLine is failing to - // un-escape the commas, we need to move this fix to that file. - ReplaceSubstringsAfterOffset(&handlers_spec, 0, "\\,", ","); -#endif - - std::vector<std::string> parts; - base::SplitString(handlers_spec, ',', &parts); - if (parts.size() % 2 != 0) { - LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers - << ": must be a comma-separated list of mimetype/url pairs." - << handlers_spec; - return; - } - - for (size_t i = 0; i < parts.size(); i += 2) { - GURL url(parts[i + 1]); - if (!url.is_valid()) { - LOG(ERROR) << "Invalid value for switch " << switches::kContentHandlers - << ": '" << parts[i + 1] << "' is not a valid URL."; - return; - } - // TODO(eseidel): We should also validate that the mimetype is valid - // net/base/mime_util.h could do this, but we don't want to depend on net. - manager->RegisterContentHandler(parts[i], url); - } -} - -void InitNativeOptions(ApplicationManager* manager, - const base::CommandLine& command_line) { - std::vector<std::string> force_in_process_url_list; - base::SplitString(command_line.GetSwitchValueASCII(switches::kForceInProcess), - ',', &force_in_process_url_list); - for (const auto& force_in_process_url : force_in_process_url_list) { - GURL gurl(force_in_process_url); - if (!gurl.is_valid()) { - LOG(ERROR) << "Invalid value for switch " << switches::kForceInProcess - << ": '" << force_in_process_url << "'is not a valid URL."; - return; - } - - NativeRunnerFactory::Options options; - options.force_in_process = true; - manager->SetNativeOptionsForURL(options, gurl); - } -} - -class TracingServiceProvider : public ServiceProvider { - public: - explicit TracingServiceProvider(InterfaceRequest<ServiceProvider> request) - : binding_(this, request.Pass()) {} - ~TracingServiceProvider() override {} - - void ConnectToService(const String& service_name, - ScopedMessagePipeHandle client_handle) override { - if (service_name == tracing::TraceController::Name_) { - new TraceControllerImpl( - MakeRequest<tracing::TraceController>(client_handle.Pass())); - } - } - - private: - StrongBinding<ServiceProvider> binding_; - - DISALLOW_COPY_AND_ASSIGN(TracingServiceProvider); -}; - -} // namespace - -Context::Context() : application_manager_(this) { - DCHECK(!base::MessageLoop::current()); - - // By default assume that the local apps reside alongside the shell. - // TODO(ncbray): really, this should be passed in rather than defaulting. - // This default makes sense for desktop but not Android. - base::FilePath shell_dir; - PathService::Get(base::DIR_MODULE, &shell_dir); - SetShellFileRoot(shell_dir); - - base::FilePath cwd; - PathService::Get(base::DIR_CURRENT, &cwd); - SetCommandLineCWD(cwd); -} - -Context::~Context() { - DCHECK(!base::MessageLoop::current()); -} - -// static -void Context::EnsureEmbedderIsInitialized() { - static base::LazyInstance<Setup>::Leaky setup = LAZY_INSTANCE_INITIALIZER; - setup.Get(); -} - -void Context::SetShellFileRoot(const base::FilePath& path) { - shell_file_root_ = AddTrailingSlashIfNeeded(FilePathToFileURL(path)); -} - -GURL Context::ResolveShellFileURL(const std::string& path) { - return shell_file_root_.Resolve(path); -} - -void Context::SetCommandLineCWD(const base::FilePath& path) { - command_line_cwd_ = AddTrailingSlashIfNeeded(FilePathToFileURL(path)); -} - -GURL Context::ResolveCommandLineURL(const std::string& path) { - return command_line_cwd_.Resolve(path); -} - -bool Context::Init() { - TRACE_EVENT0("mojo_shell", "Context::Init"); - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - - if (command_line.HasSwitch(switches::kWaitForDebugger)) - base::debug::WaitForDebugger(60, true); - - EnsureEmbedderIsInitialized(); - task_runners_.reset( - new TaskRunners(base::MessageLoop::current()->message_loop_proxy())); - - // TODO(vtl): Probably these failures should be checked before |Init()|, and - // this function simply shouldn't fail. - if (!shell_file_root_.is_valid()) - return false; - if (!ConfigureURLMappings(command_line, this)) - return false; - - // TODO(vtl): This should be MASTER, not NONE. - embedder::InitIPCSupport( - embedder::ProcessType::NONE, task_runners_->shell_runner(), this, - task_runners_->io_runner(), embedder::ScopedPlatformHandle()); - - scoped_ptr<NativeRunnerFactory> runner_factory; - if (command_line.HasSwitch(switches::kEnableMultiprocess)) - runner_factory.reset(new OutOfProcessNativeRunnerFactory(this)); - else - runner_factory.reset(new InProcessNativeRunnerFactory(this)); - application_manager_.set_blocking_pool(task_runners_->blocking_pool()); - application_manager_.set_native_runner_factory(runner_factory.Pass()); - application_manager_.set_disable_cache( - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableCache)); - - InitContentHandlers(&application_manager_, command_line); - InitNativeOptions(&application_manager_, command_line); - - ServiceProviderPtr tracing_service_provider_ptr; - new TracingServiceProvider(GetProxy(&tracing_service_provider_ptr)); - application_manager_.ConnectToApplication( - GURL("mojo:tracing"), GURL(""), nullptr, - tracing_service_provider_ptr.Pass(), base::Closure()); - - return true; -} - -void Context::Shutdown() { - TRACE_EVENT0("mojo_shell", "Context::Shutdown"); - DCHECK_EQ(base::MessageLoop::current()->task_runner(), - task_runners_->shell_runner()); - embedder::ShutdownIPCSupport(); - // We'll quit when we get OnShutdownComplete(). - base::MessageLoop::current()->Run(); -} - -GURL Context::ResolveURL(const GURL& url) { - return url_resolver_.ResolveMojoURL(url); -} - -GURL Context::ResolveMappings(const GURL& url) { - return url_resolver_.ApplyMappings(url); -} - -void Context::OnShutdownComplete() { - DCHECK_EQ(base::MessageLoop::current()->task_runner(), - task_runners_->shell_runner()); - base::MessageLoop::current()->Quit(); -} - -void Context::Run(const GURL& url) { - ServiceProviderPtr services; - ServiceProviderPtr exposed_services; - - app_urls_.insert(url); - application_manager_.ConnectToApplication( - url, GURL(), GetProxy(&services), exposed_services.Pass(), - base::Bind(&Context::OnApplicationEnd, base::Unretained(this), url)); -} - -void Context::OnApplicationEnd(const GURL& url) { - if (app_urls_.find(url) != app_urls_.end()) { - app_urls_.erase(url); - if (app_urls_.empty() && base::MessageLoop::current()->is_running()) { - DCHECK_EQ(base::MessageLoop::current()->task_runner(), - task_runners_->shell_runner()); - base::MessageLoop::current()->Quit(); - } - } -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/context.h b/mojo/shell/context.h deleted file mode 100644 index 4be704e..0000000 --- a/mojo/shell/context.h +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright 2013 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 SHELL_CONTEXT_H_ -#define SHELL_CONTEXT_H_ - -#include <string> - -#include "base/macros.h" -#include "mojo/edk/embedder/process_delegate.h" -#include "mojo/shell/application_manager/application_manager.h" -#include "mojo/shell/task_runners.h" -#include "mojo/shell/url_resolver.h" - -namespace mojo { -namespace shell { - -class NativeApplicationLoader; - -// The "global" context for the shell's main process. -class Context : public ApplicationManager::Delegate, - public embedder::ProcessDelegate { - public: - Context(); - ~Context() override; - - static void EnsureEmbedderIsInitialized(); - - // Point to the directory containing installed services, such as the network - // service. By default this directory is used as the base URL for resolving - // unknown mojo: URLs. The network service will be loaded from this directory, - // even when the base URL for unknown mojo: URLs is overridden. - void SetShellFileRoot(const base::FilePath& path); - - // Resolve an URL relative to the shell file root. This is a nop for - // everything but relative file URLs or URLs without a scheme. - GURL ResolveShellFileURL(const std::string& path); - - // Override the CWD, which is used for resolving file URLs passed in from the - // command line. - void SetCommandLineCWD(const base::FilePath& path); - - // Resolve an URL relative to the CWD mojo_shell was invoked from. This is a - // nop for everything but relative file URLs or URLs without a scheme. - GURL ResolveCommandLineURL(const std::string& path); - - // This must be called with a message loop set up for the current thread, - // which must remain alive until after Shutdown() is called. Returns true on - // success. - bool Init(); - - // If Init() was called and succeeded, this must be called before destruction. - void Shutdown(); - - void Run(const GURL& url); - - TaskRunners* task_runners() { return task_runners_.get(); } - ApplicationManager* application_manager() { return &application_manager_; } - URLResolver* url_resolver() { return &url_resolver_; } - - private: - class NativeViewportApplicationLoader; - - // ApplicationManager::Delegate overrides. - GURL ResolveURL(const GURL& url) override; - GURL ResolveMappings(const GURL& url) override; - - // ProcessDelegate implementation. - void OnShutdownComplete() override; - - void OnApplicationEnd(const GURL& url); - - std::set<GURL> app_urls_; - scoped_ptr<TaskRunners> task_runners_; - ApplicationManager application_manager_; - URLResolver url_resolver_; - GURL shell_file_root_; - GURL command_line_cwd_; - - DISALLOW_COPY_AND_ASSIGN(Context); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_CONTEXT_H_
diff --git a/mojo/shell/data_pipe_peek.cc b/mojo/shell/data_pipe_peek.cc new file mode 100644 index 0000000..4c74c55 --- /dev/null +++ b/mojo/shell/data_pipe_peek.cc
@@ -0,0 +1,160 @@ +// 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 "mojo/shell/data_pipe_peek.h" + +#include <stdint.h> + +#include "base/bind.h" +#include "base/macros.h" + +namespace mojo { +namespace shell { + +namespace { + +// Sleep for as long as max_sleep_micros if the deadline hasn't been reached +// and the number of bytes read is still increasing. Returns true if sleep +// was actually called. +// +// This class is a substitute for being able to wait until N bytes are available +// from a data pipe. The MaybeSleep method is called when num_bytes_read are +// available but more are needed by the Peek operation. If a second +// Peek operation finds the same number of bytes after sleeping we assume +// that there's no point in trying again. +// TODO(hansmuller): this heuristic is weak. crbug.com/429377 +class PeekSleeper { + public: + explicit PeekSleeper(MojoTimeTicks deadline) + : deadline_(deadline), + last_number_bytes_read_(0) {} + + bool MaybeSleep(uint32_t num_bytes_read) { + if (num_bytes_read > 0 && last_number_bytes_read_ >= num_bytes_read) + return false; + last_number_bytes_read_ = num_bytes_read; + + MojoTimeTicks now(GetTimeTicksNow()); + if (now > deadline_) + return false; + + MojoTimeTicks sleep_time = + (deadline_ == 0) ? kMaxSleepMicros + : std::min<int64>(deadline_ - now, kMaxSleepMicros); + base::PlatformThread::Sleep(base::TimeDelta::FromMicroseconds(sleep_time)); + return true; + } + + private: + static const MojoTimeTicks kMaxSleepMicros = 1000 * 10; // 10 ms + + const MojoTimeTicks deadline_; // 0 => MOJO_DEADLINE_INDEFINITE + uint32_t last_number_bytes_read_; + + DISALLOW_COPY_AND_ASSIGN(PeekSleeper); +}; + +const MojoTimeTicks PeekSleeper::kMaxSleepMicros; + +enum PeekStatus { kSuccess, kFail, kKeepReading }; +typedef const base::Callback<PeekStatus(const void*, uint32_t, std::string*)>& + PeekFunc; + +// When data is available on source, call peek_func and then either return true +// and value, continue waiting for enough data to satisfy peek_func, or fail +// and return false. Fail if the timeout is exceeded. +// This function is not guaranteed to work correctly if applied to a data pipe +// that's already been read from. +bool BlockingPeekHelper(DataPipeConsumerHandle source, + std::string* value, + MojoDeadline timeout, + PeekFunc peek_func) { + DCHECK(value); + value->clear(); + + MojoTimeTicks deadline = + (timeout == MOJO_DEADLINE_INDEFINITE) + ? 0 + : 1 + GetTimeTicksNow() + static_cast<MojoTimeTicks>(timeout); + PeekSleeper sleeper(deadline); + + MojoResult result; + do { + const void* buffer; + uint32_t num_bytes; + result = + BeginReadDataRaw(source, &buffer, &num_bytes, MOJO_READ_DATA_FLAG_NONE); + + if (result == MOJO_RESULT_OK) { + PeekStatus status = peek_func.Run(buffer, num_bytes, value); + CHECK_EQ(EndReadDataRaw(source, 0), MOJO_RESULT_OK); + switch (status) { + case PeekStatus::kSuccess: + return true; + case PeekStatus::kFail: + return false; + case PeekStatus::kKeepReading: + break; + } + if (!sleeper.MaybeSleep(num_bytes)) + return false; + } else if (result == MOJO_RESULT_SHOULD_WAIT) { + MojoTimeTicks now(GetTimeTicksNow()); + if (timeout == MOJO_DEADLINE_INDEFINITE || now < deadline) + result = + Wait(source, MOJO_HANDLE_SIGNAL_READABLE, deadline - now, nullptr); + } + } while (result == MOJO_RESULT_OK); + + return false; +} + +PeekStatus PeekLine(size_t max_line_length, + const void* buffer, + uint32_t buffer_num_bytes, + std::string* line) { + const char* p = static_cast<const char*>(buffer); + size_t max_p_index = std::min<size_t>(buffer_num_bytes, max_line_length); + for (size_t i = 0; i < max_p_index; i++) { + if (p[i] == '\n') { + *line = std::string(p, i + 1); // Include the trailing newline. + return PeekStatus::kSuccess; + } + } + return (buffer_num_bytes >= max_line_length) ? PeekStatus::kFail + : PeekStatus::kKeepReading; +} + +PeekStatus PeekNBytes(size_t bytes_length, + const void* buffer, + uint32_t buffer_num_bytes, + std::string* bytes) { + if (buffer_num_bytes >= bytes_length) { + const char* p = static_cast<const char*>(buffer); + *bytes = std::string(p, bytes_length); + return PeekStatus::kSuccess; + } + return PeekStatus::kKeepReading; +} + +} // namespace + +bool BlockingPeekNBytes(DataPipeConsumerHandle source, + std::string* bytes, + size_t bytes_length, + MojoDeadline timeout) { + PeekFunc peek_nbytes = base::Bind(PeekNBytes, bytes_length); + return BlockingPeekHelper(source, bytes, timeout, peek_nbytes); +} + +bool BlockingPeekLine(DataPipeConsumerHandle source, + std::string* line, + size_t max_line_length, + MojoDeadline timeout) { + PeekFunc peek_line = base::Bind(PeekLine, max_line_length); + return BlockingPeekHelper(source, line, timeout, peek_line); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/data_pipe_peek.h b/mojo/shell/data_pipe_peek.h new file mode 100644 index 0000000..0bcf1dd9 --- /dev/null +++ b/mojo/shell/data_pipe_peek.h
@@ -0,0 +1,38 @@ +// 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 MOJO_SHELL_DATA_PIPE_PEEK_H_ +#define MOJO_SHELL_DATA_PIPE_PEEK_H_ + +#include <string> + +#include "mojo/public/cpp/system/core.h" + +namespace mojo { +namespace shell { + +// The Peek functions are only intended to be used by the +// DyanmicApplicationLoader class for discovering the type of a +// URL response. They are a stopgap to be replaced by real support +// in the DataPipe classes. + +// Return true and the first newline terminated line from source. Return false +// if more than max_line_length bytes are scanned without seeing a newline, or +// if the timeout is exceeded. +bool BlockingPeekLine(DataPipeConsumerHandle source, + std::string* line, + size_t max_line_length, + MojoDeadline timeout); + +// Return true and the first bytes_length bytes from source. Return false +// if the timeout is exceeded. +bool BlockingPeekNBytes(DataPipeConsumerHandle source, + std::string* bytes, + size_t bytes_length, + MojoDeadline timeout); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SHELL_DATA_PIPE_PEEK_H_
diff --git a/mojo/shell/data_pipe_peek_unittest.cc b/mojo/shell/data_pipe_peek_unittest.cc deleted file mode 100644 index 126901b..0000000 --- a/mojo/shell/data_pipe_peek_unittest.cc +++ /dev/null
@@ -1,113 +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 "mojo/shell/application_manager/data_pipe_peek.h" - -#include "mojo/shell/context.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { -namespace { - -TEST(DataPipePeek, PeekNBytes) { - Context::EnsureEmbedderIsInitialized(); - - DataPipe data_pipe; - DataPipeConsumerHandle consumer(data_pipe.consumer_handle.get()); - DataPipeProducerHandle producer(data_pipe.producer_handle.get()); - - // Inialize the pipe with 4 bytes. - - const char* s4 = "1234"; - uint32_t num_bytes4 = 4; - EXPECT_EQ(MOJO_RESULT_OK, - WriteDataRaw(producer, s4, &num_bytes4, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(4u, num_bytes4); - - // We're not consuming data, so peeking for 4 bytes should always succeed. - - std::string bytes; - MojoDeadline timeout = 0; - EXPECT_TRUE(BlockingPeekNBytes(consumer, &bytes, num_bytes4, timeout)); - EXPECT_EQ(bytes, std::string(s4)); - - timeout = 1000; // 1ms - EXPECT_TRUE(BlockingPeekNBytes(consumer, &bytes, num_bytes4, timeout)); - EXPECT_EQ(bytes, std::string(s4)); - - timeout = MOJO_DEADLINE_INDEFINITE; - EXPECT_TRUE(BlockingPeekNBytes(consumer, &bytes, num_bytes4, timeout)); - EXPECT_EQ(bytes, std::string(s4)); - - // Peeking for 5 bytes should fail, until another byte is written. - - uint32_t bytes1 = 1; - uint32_t num_bytes5 = 5; - const char* s1 = "5"; - const char* s5 = "12345"; - - timeout = 0; - EXPECT_FALSE(BlockingPeekNBytes(consumer, &bytes, num_bytes5, timeout)); - - timeout = 500; // Should cause peek to timeout after about 0.5ms. - EXPECT_FALSE(BlockingPeekNBytes(consumer, &bytes, num_bytes5, timeout)); - - EXPECT_EQ(MOJO_RESULT_OK, - WriteDataRaw(producer, s1, &bytes1, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(1u, bytes1); - - EXPECT_TRUE(BlockingPeekNBytes(consumer, &bytes, num_bytes5, timeout)); - EXPECT_EQ(bytes, std::string(s5)); - - // If the consumer side of the pipe is closed, peek should fail. - - data_pipe.consumer_handle.reset(); - timeout = 0; - EXPECT_FALSE(BlockingPeekNBytes(consumer, &bytes, num_bytes5, timeout)); -} - -TEST(DataPipePeek, PeekLine) { - Context::EnsureEmbedderIsInitialized(); - - DataPipe data_pipe; - DataPipeConsumerHandle consumer(data_pipe.consumer_handle.get()); - DataPipeProducerHandle producer(data_pipe.producer_handle.get()); - - // Inialize the pipe with 4 bytes and no newline. - - const char* s4 = "1234"; - uint32_t num_bytes4 = 4; - EXPECT_EQ(MOJO_RESULT_OK, - WriteDataRaw(producer, s4, &num_bytes4, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(4u, num_bytes4); - - // Peeking for a line should fail. - - std::string str; - size_t max_str_length = 5; - MojoDeadline timeout = 0; - EXPECT_FALSE(BlockingPeekLine(consumer, &str, max_str_length, timeout)); - - // Writing a newline should cause PeekLine to succeed. - - uint32_t bytes1 = 1; - const char* s1 = "\n"; - EXPECT_EQ(MOJO_RESULT_OK, - WriteDataRaw(producer, s1, &bytes1, MOJO_WRITE_DATA_FLAG_NONE)); - EXPECT_EQ(1u, bytes1); - - EXPECT_TRUE(BlockingPeekLine(consumer, &str, max_str_length, timeout)); - EXPECT_EQ(str, std::string(s4) + "\n"); - - // If the max_line_length parameter is less than the length of the - // newline terminated string, then peek should fail. - - max_str_length = 3; - EXPECT_FALSE(BlockingPeekLine(consumer, &str, max_str_length, timeout)); -} - -} // namespace -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/desktop/launcher_process.cc b/mojo/shell/desktop/launcher_process.cc deleted file mode 100644 index 1b47cc8..0000000 --- a/mojo/shell/desktop/launcher_process.cc +++ /dev/null
@@ -1,136 +0,0 @@ -// Copyright 2013 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 <stdio.h> -#include <string.h> - -#include <algorithm> -#include <iostream> - -#include "base/base_switches.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_util.h" -#include "base/message_loop/message_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/trace_event/trace_event.h" -#include "mojo/shell/context.h" -#include "mojo/shell/switches.h" - -namespace mojo { -namespace shell { -namespace { - -// Whether we're currently tracing. -bool g_tracing = false; - -// Number of tracing blocks written. -uint32_t g_blocks = 0; - -// Trace file, if open. -FILE* g_trace_file = nullptr; - -void WriteTraceDataCollected( - base::WaitableEvent* event, - const scoped_refptr<base::RefCountedString>& events_str, - bool has_more_events) { - if (g_blocks) { - fwrite(",", 1, 1, g_trace_file); - } - - ++g_blocks; - fwrite(events_str->data().c_str(), 1, events_str->data().length(), - g_trace_file); - if (!has_more_events) { - static const char kEnd[] = "]}"; - fwrite(kEnd, 1, strlen(kEnd), g_trace_file); - PCHECK(fclose(g_trace_file) == 0); - g_trace_file = nullptr; - event->Signal(); - } -} - -void EndTraceAndFlush(base::WaitableEvent* event) { - g_trace_file = fopen("mojo_shell.trace", "w+"); - PCHECK(g_trace_file); - static const char kStart[] = "{\"traceEvents\":["; - fwrite(kStart, 1, strlen(kStart), g_trace_file); - base::trace_event::TraceLog::GetInstance()->SetDisabled(); - base::trace_event::TraceLog::GetInstance()->Flush( - base::Bind(&WriteTraceDataCollected, base::Unretained(event))); -} - -void StopTracingAndFlushToDisk() { - g_tracing = false; - base::trace_event::TraceLog::GetInstance()->SetDisabled(); - base::WaitableEvent flush_complete_event(false, false); - // TraceLog::Flush requires a message loop but we've already shut ours down. - // Spin up a new thread to flush things out. - base::Thread flush_thread("mojo_shell_trace_event_flush"); - flush_thread.Start(); - flush_thread.message_loop()->PostTask( - FROM_HERE, - base::Bind(EndTraceAndFlush, base::Unretained(&flush_complete_event))); - flush_complete_event.Wait(); -} - -void StartApp(mojo::shell::Context* context) { - // If a mojo app isn't specified (i.e. for an apptest), run the mojo shell's - // window manager. - GURL app_url(GURL("mojo:window_manager")); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - base::CommandLine::StringVector args = command_line->GetArgs(); - for (size_t i = 0; i < args.size(); ++i) { - GURL possible_app(args[i]); - if (possible_app.SchemeIs("mojo")) { - app_url = possible_app; - break; - } - } - - context->Run(app_url); -} - -} // namespace - -int LauncherProcessMain(int argc, char** argv) { - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kTraceStartup)) { - g_tracing = true; - base::trace_event::CategoryFilter category_filter( - command_line.GetSwitchValueASCII(switches::kTraceStartup)); - base::trace_event::TraceLog::GetInstance()->SetEnabled( - category_filter, base::trace_event::TraceLog::RECORDING_MODE, - base::trace_event::TraceOptions(base::trace_event::RECORD_UNTIL_FULL)); - } - - // We want the shell::Context to outlive the MessageLoop so that pipes are - // all gracefully closed / error-out before we try to shut the Context down. - mojo::shell::Context shell_context; - { - base::MessageLoop message_loop; - if (!shell_context.Init()) { - return 0; - } - if (g_tracing) { - message_loop.PostDelayedTask(FROM_HERE, - base::Bind(StopTracingAndFlushToDisk), - base::TimeDelta::FromSeconds(5)); - } - - message_loop.PostTask(FROM_HERE, base::Bind(&StartApp, &shell_context)); - message_loop.Run(); - - // Must be called before |message_loop| is destroyed. - shell_context.Shutdown(); - } - - if (g_tracing) - StopTracingAndFlushToDisk(); - return 0; -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/desktop/main.cc b/mojo/shell/desktop/main.cc deleted file mode 100644 index ca89c5da9..0000000 --- a/mojo/shell/desktop/main.cc +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2013 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/at_exit.h" -#include "base/command_line.h" -#include "mojo/shell/child_process.h" -#include "mojo/shell/desktop/launcher_process.h" -#include "mojo/shell/init.h" -#include "mojo/shell/switches.h" - -int main(int argc, char** argv) { - base::AtExitManager at_exit; - base::CommandLine::Init(argc, argv); - - mojo::shell::InitializeLogging(); - - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kChildProcess)) - return mojo::shell::ChildProcessMain(); - - return mojo::shell::LauncherProcessMain(argc, argv); -}
diff --git a/mojo/shell/fetcher.cc b/mojo/shell/fetcher.cc new file mode 100644 index 0000000..d9a4e60 --- /dev/null +++ b/mojo/shell/fetcher.cc
@@ -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. + +#include "mojo/shell/fetcher.h" + +#include "url/gurl.h" + +namespace mojo { +namespace shell { + +const char Fetcher::kMojoMagic[] = "#!mojo "; +const size_t Fetcher::kMaxShebangLength = 2048; + +Fetcher::Fetcher(const FetchCallback& loader_callback) + : loader_callback_(loader_callback) { +} + +Fetcher::~Fetcher() { +} + +bool Fetcher::PeekContentHandler(std::string* mojo_shebang, + GURL* mojo_content_handler_url) { + // TODO(aa): I guess this should just go in ApplicationManager now. + std::string shebang; + if (HasMojoMagic() && PeekFirstLine(&shebang)) { + GURL url(shebang.substr(arraysize(kMojoMagic) - 1, std::string::npos)); + if (url.is_valid()) { + *mojo_shebang = shebang; + *mojo_content_handler_url = url; + return true; + } + } + return false; +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/fetcher.h b/mojo/shell/fetcher.h new file mode 100644 index 0000000..21cad3f --- /dev/null +++ b/mojo/shell/fetcher.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 MOJO_SHELL_FETCHER_H_ +#define MOJO_SHELL_FETCHER_H_ + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" + +#include "mojo/services/network/public/interfaces/url_loader.mojom.h" + +class GURL; + +namespace base { +class FilePath; +class TaskRunner; +} + +namespace mojo { +namespace shell { + +// Fetcher abstracts getting an application by either file or http[s] URL. +// +// Although it is possible to use the Network implementation for http[s] URLs +// (because the underlying net library knows how to handle them), it is +// extremely slow because network responses must be copied to disk in order to +// get a file handle we can use with dlopen. +// +// Until this is solved, we use two different implementations so that +// performance isn't completely absymal. +class Fetcher { + public: + // The param will be null in the case where the content could not be fetched. + // Reasons include: + // - network error + // - 4x or 5x HTTP errors + typedef base::Callback<void(scoped_ptr<Fetcher>)> FetchCallback; + + Fetcher(const FetchCallback& fetch_callback); + virtual ~Fetcher(); + + // Returns the original URL that was fetched. + virtual const GURL& GetURL() const = 0; + + // If the fetch resulted in a redirect, this returns the final URL after all + // redirects. Otherwise, it returns an empty URL. + virtual GURL GetRedirectURL() const = 0; + + virtual URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, + uint32_t skip) = 0; + + virtual void AsPath( + base::TaskRunner* task_runner, + base::Callback<void(const base::FilePath&, bool)> callback) = 0; + + virtual std::string MimeType() = 0; + + virtual bool HasMojoMagic() = 0; + + virtual bool PeekFirstLine(std::string* line) = 0; + + bool PeekContentHandler(std::string* mojo_shebang, + GURL* mojo_content_handler_url); + + protected: + static const char kMojoMagic[]; + static const size_t kMaxShebangLength; + + FetchCallback loader_callback_; +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SHELL_FETCHER_H_
diff --git a/mojo/shell/filename_util.cc b/mojo/shell/filename_util.cc deleted file mode 100644 index 073bddaf..0000000 --- a/mojo/shell/filename_util.cc +++ /dev/null
@@ -1,72 +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 "mojo/shell/filename_util.h" - -#include "base/files/file_path.h" -#include "base/path_service.h" -#include "base/strings/string_util.h" -#include "url/gurl.h" -#include "url/url_canon_internal.h" -#include "url/url_util.h" - -namespace mojo { -namespace shell { - -// Prefix to prepend to get a file URL. -static const base::FilePath::CharType kFileURLPrefix[] = - FILE_PATH_LITERAL("file://"); - -GURL FilePathToFileURL(const base::FilePath& path) { - // Produce a URL like "file:///C:/foo" for a regular file, or - // "file://///server/path" for UNC. The URL canonicalizer will fix up the - // latter case to be the canonical UNC form: "file://server/path" - base::FilePath::StringType url_string(kFileURLPrefix); - if (!path.IsAbsolute()) { - base::FilePath current_dir; - PathService::Get(base::DIR_CURRENT, ¤t_dir); - url_string.append(current_dir.value()); - url_string.push_back(base::FilePath::kSeparators[0]); - } - url_string.append(path.value()); - - // Now do replacement of some characters. Since we assume the input is a - // literal filename, anything the URL parser might consider special should - // be escaped here. - - // This must be the first substitution since others will introduce percents as - // the escape character - ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL("%"), - FILE_PATH_LITERAL("%25")); - - // A semicolon is supposed to be some kind of separator according to RFC 2396. - ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL(";"), - FILE_PATH_LITERAL("%3B")); - - ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL("#"), - FILE_PATH_LITERAL("%23")); - - ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL("?"), - FILE_PATH_LITERAL("%3F")); - -#if defined(OS_POSIX) - ReplaceSubstringsAfterOffset(&url_string, 0, FILE_PATH_LITERAL("\\"), - FILE_PATH_LITERAL("%5C")); -#endif - - return GURL(url_string); -} - -GURL AddTrailingSlashIfNeeded(const GURL& url) { - if (!url.has_path() || *url.path().rbegin() == '/') - return url; - - std::string path(url.path() + '/'); - GURL::Replacements replacements; - replacements.SetPathStr(path); - return url.ReplaceComponents(replacements); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/filename_util.h b/mojo/shell/filename_util.h deleted file mode 100644 index 28d0e780..0000000 --- a/mojo/shell/filename_util.h +++ /dev/null
@@ -1,28 +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 SHELL_FILENAME_UTIL_H_ -#define SHELL_FILENAME_UTIL_H_ - -class GURL; - -namespace base { -class FilePath; -} - -namespace mojo { -namespace shell { - -// Given the full path to a file name, creates a file: URL. The returned URL -// may not be valid if the input is malformed. -GURL FilePathToFileURL(const base::FilePath& path); - -// This URL is going to be treated as a directory. Ensure there is a trailing -// slash so that GURL.Resolve(...) works correctly. -GURL AddTrailingSlashIfNeeded(const GURL& url); - -} // namespace shell -} // namespace mojo - -#endif // SHELL_FILENAME_UTIL_H_
diff --git a/mojo/shell/identity.cc b/mojo/shell/identity.cc new file mode 100644 index 0000000..7eb88c7 --- /dev/null +++ b/mojo/shell/identity.cc
@@ -0,0 +1,28 @@ +// 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/shell/identity.h" + +#include "mojo/shell/query_util.h" + +namespace mojo { +namespace shell { + +Identity::Identity(const GURL& url, const std::string& qualifier) + : url(GetBaseURLAndQuery(url, nullptr)), qualifier(qualifier) { +} + +// explicit +Identity::Identity(const GURL& base_url) + : url(GetBaseURLAndQuery(base_url, nullptr)), qualifier(url.spec()) { +} + +bool Identity::operator<(const Identity& other) const { + if (url != other.url) + return url < other.url; + return qualifier < other.qualifier; +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/identity.h b/mojo/shell/identity.h new file mode 100644 index 0000000..ac897a1c --- /dev/null +++ b/mojo/shell/identity.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 MOJO_SHELL_IDENTITY_H_ +#define MOJO_SHELL_IDENTITY_H_ + +#include "url/gurl.h" + +namespace mojo { +namespace shell { + +/** + * Represents the identity of an application. |url| is the url of the + * application. |qualifier| is a string that allows to tie a specific instance + * of an application to another. It is used by content handlers that need to be + * run in the context of another application. + */ +struct Identity { + Identity(const GURL& url, const std::string& qualifier); + explicit Identity(const GURL& url); + bool operator<(const Identity& other) const; + + const GURL url; + const std::string qualifier; +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SHELL_IDENTITY_H_
diff --git a/mojo/shell/in_process_native_runner.cc b/mojo/shell/in_process_native_runner.cc deleted file mode 100644 index 7431fe02..0000000 --- a/mojo/shell/in_process_native_runner.cc +++ /dev/null
@@ -1,72 +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 "mojo/shell/in_process_native_runner.h" - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/location.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/threading/platform_thread.h" -#include "mojo/shell/native_application_support.h" - -namespace mojo { -namespace shell { - -InProcessNativeRunner::InProcessNativeRunner(Context* context) - : cleanup_(NativeApplicationCleanup::DONT_DELETE), app_library_(nullptr) { -} - -InProcessNativeRunner::~InProcessNativeRunner() { - // It is important to let the thread exit before unloading the DSO (when - // app_library_ is destructed), because the library may have registered - // thread-local data and destructors to run on thread termination. - if (thread_) { - DCHECK(thread_->HasBeenStarted()); - DCHECK(!thread_->HasBeenJoined()); - thread_->Join(); - } -} - -void InProcessNativeRunner::Start( - const base::FilePath& app_path, - NativeApplicationCleanup cleanup, - InterfaceRequest<Application> application_request, - const base::Closure& app_completed_callback) { - app_path_ = app_path; - cleanup_ = cleanup; - - DCHECK(!application_request_.is_pending()); - application_request_ = application_request.Pass(); - - DCHECK(app_completed_callback_runner_.is_null()); - app_completed_callback_runner_ = - base::Bind(&base::TaskRunner::PostTask, base::MessageLoopProxy::current(), - FROM_HERE, app_completed_callback); - - DCHECK(!thread_); - thread_.reset(new base::DelegateSimpleThread(this, "app_thread")); - thread_->Start(); -} - -void InProcessNativeRunner::Run() { - DVLOG(2) << "Loading/running Mojo app in process from library: " - << app_path_.value() - << " thread id=" << base::PlatformThread::CurrentId(); - - // TODO(vtl): ScopedNativeLibrary doesn't have a .get() method! - base::NativeLibrary app_library = LoadNativeApplication(app_path_, cleanup_); - app_library_.Reset(app_library); - RunNativeApplication(app_library, application_request_.Pass()); - app_completed_callback_runner_.Run(); - app_completed_callback_runner_.Reset(); -} - -scoped_ptr<NativeRunner> InProcessNativeRunnerFactory::Create( - const Options& options) { - return make_scoped_ptr(new InProcessNativeRunner(context_)); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/in_process_native_runner.h b/mojo/shell/in_process_native_runner.h deleted file mode 100644 index a5639f4..0000000 --- a/mojo/shell/in_process_native_runner.h +++ /dev/null
@@ -1,67 +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 SHELL_IN_PROCESS_NATIVE_RUNNER_H_ -#define SHELL_IN_PROCESS_NATIVE_RUNNER_H_ - -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "base/scoped_native_library.h" -#include "base/threading/simple_thread.h" -#include "mojo/shell/application_manager/native_runner.h" -#include "mojo/shell/native_application_support.h" - -namespace mojo { -namespace shell { - -class Context; - -// An implementation of |NativeRunner| that loads/runs the given app (from the -// file system) on a separate thread (in the current process). -class InProcessNativeRunner : public NativeRunner, - public base::DelegateSimpleThread::Delegate { - public: - explicit InProcessNativeRunner(Context* context); - ~InProcessNativeRunner() override; - - // |NativeRunner| method: - void Start(const base::FilePath& app_path, - NativeApplicationCleanup cleanup, - InterfaceRequest<Application> application_request, - const base::Closure& app_completed_callback) override; - - private: - // |base::DelegateSimpleThread::Delegate| method: - void Run() override; - - base::FilePath app_path_; - NativeApplicationCleanup cleanup_; - InterfaceRequest<Application> application_request_; - base::Callback<bool(void)> app_completed_callback_runner_; - - base::ScopedNativeLibrary app_library_; - scoped_ptr<base::DelegateSimpleThread> thread_; - - DISALLOW_COPY_AND_ASSIGN(InProcessNativeRunner); -}; - -class InProcessNativeRunnerFactory : public NativeRunnerFactory { - public: - explicit InProcessNativeRunnerFactory(Context* context) : context_(context) {} - ~InProcessNativeRunnerFactory() override {} - - scoped_ptr<NativeRunner> Create(const Options& options) override; - - private: - Context* const context_; - - DISALLOW_COPY_AND_ASSIGN(InProcessNativeRunnerFactory); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_IN_PROCESS_NATIVE_RUNNER_H_
diff --git a/mojo/shell/in_process_native_runner_unittest.cc b/mojo/shell/in_process_native_runner_unittest.cc deleted file mode 100644 index 28608c8..0000000 --- a/mojo/shell/in_process_native_runner_unittest.cc +++ /dev/null
@@ -1,23 +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 "mojo/shell/in_process_native_runner.h" - -#include "mojo/shell/context.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { - -TEST(InProcessNativeRunnerTest, NotStarted) { - Context context; - base::MessageLoop loop; - context.Init(); - InProcessNativeRunner runner(&context); - context.Shutdown(); - // Shouldn't crash or DCHECK on destruction. -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/init.cc b/mojo/shell/init.cc deleted file mode 100644 index 71aec63..0000000 --- a/mojo/shell/init.cc +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright 2013 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/shell/init.h" - -#include "base/logging.h" - -namespace mojo { -namespace shell { - -void InitializeLogging() { - logging::LoggingSettings settings; - settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - logging::InitLogging(settings); - // To view log output with IDs and timestamps use "adb logcat -v threadtime". - logging::SetLogItems(false, // Process ID - false, // Thread ID - false, // Timestamp - false); // Tick count -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/init.h b/mojo/shell/init.h deleted file mode 100644 index 23a5140b..0000000 --- a/mojo/shell/init.h +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2013 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 SHELL_INIT_H_ -#define SHELL_INIT_H_ - -namespace mojo { -namespace shell { - -// Initialization routines shared by desktop and Android main functions. - -void InitializeLogging(); - -} // namespace shell -} // namespace mojo - -#endif // SHELL_INIT_H_
diff --git a/mojo/shell/local_fetcher.cc b/mojo/shell/local_fetcher.cc new file mode 100644 index 0000000..a945dc2 --- /dev/null +++ b/mojo/shell/local_fetcher.cc
@@ -0,0 +1,107 @@ +// 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/shell/local_fetcher.h" + +#include "base/bind.h" +#include "base/files/file_util.h" +#include "base/format_macros.h" +#include "base/message_loop/message_loop.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/trace_event/trace_event.h" +#include "mojo/common/common_type_converters.h" +#include "mojo/common/data_pipe_utils.h" +#include "mojo/common/url_type_converters.h" +#include "url/url_util.h" + +namespace mojo { +namespace shell { + +namespace { + +void IgnoreResult(bool result) { +} + +} // namespace + +// A loader for local files. +LocalFetcher::LocalFetcher(const GURL& url, + const GURL& url_without_query, + const FetchCallback& loader_callback) + : Fetcher(loader_callback), url_(url), path_(UrlToFile(url_without_query)) { + TRACE_EVENT1("mojo_shell", "LocalFetcher::LocalFetcher", "url", url.spec()); + loader_callback_.Run(make_scoped_ptr(this)); +} + +base::FilePath LocalFetcher::UrlToFile(const GURL& url) { + DCHECK(url.SchemeIsFile()); + url::RawCanonOutputW<1024> output; + url::DecodeURLEscapeSequences(url.path().data(), + static_cast<int>(url.path().length()), &output); + base::string16 decoded_path = base::string16(output.data(), output.length()); +#if defined(OS_WIN) + base::TrimString(decoded_path, L"/", &decoded_path); + base::FilePath path(decoded_path); +#else + base::FilePath path(base::UTF16ToUTF8(decoded_path)); +#endif + return path; +} + +const GURL& LocalFetcher::GetURL() const { + return url_; +} + +GURL LocalFetcher::GetRedirectURL() const { + return GURL::EmptyGURL(); +} + +URLResponsePtr LocalFetcher::AsURLResponse(base::TaskRunner* task_runner, + uint32_t skip) { + URLResponsePtr response(URLResponse::New()); + response->url = String::From(url_); + DataPipe data_pipe; + response->body = data_pipe.consumer_handle.Pass(); + int64 file_size; + if (base::GetFileSize(path_, &file_size)) { + response->headers = Array<String>(1); + response->headers[0] = + base::StringPrintf("Content-Length: %" PRId64, file_size); + } + common::CopyFromFile(path_, data_pipe.producer_handle.Pass(), skip, + task_runner, base::Bind(&IgnoreResult)); + return response.Pass(); +} + +void LocalFetcher::AsPath( + base::TaskRunner* task_runner, + base::Callback<void(const base::FilePath&, bool)> callback) { + // Async for consistency with network case. + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); +} + +std::string LocalFetcher::MimeType() { + return ""; +} + +bool LocalFetcher::HasMojoMagic() { + std::string magic; + ReadFileToString(path_, &magic, strlen(kMojoMagic)); + return magic == kMojoMagic; +} + +bool LocalFetcher::PeekFirstLine(std::string* line) { + std::string start_of_file; + ReadFileToString(path_, &start_of_file, kMaxShebangLength); + size_t return_position = start_of_file.find('\n'); + if (return_position == std::string::npos) + return false; + *line = start_of_file.substr(0, return_position + 1); + return true; +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/local_fetcher.h b/mojo/shell/local_fetcher.h new file mode 100644 index 0000000..774fdfb --- /dev/null +++ b/mojo/shell/local_fetcher.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 MOJO_SHELL_LOCAL_FETCHER_H_ +#define MOJO_SHELL_LOCAL_FETCHER_H_ + +#include "base/files/file_path.h" +#include "mojo/services/network/public/interfaces/url_loader.mojom.h" +#include "mojo/shell/fetcher.h" +#include "url/gurl.h" + +namespace mojo { +namespace shell { + +// Implements Fetcher for file:// URLs. +class LocalFetcher : public Fetcher { + public: + LocalFetcher(const GURL& url, + const GURL& url_without_query, + const FetchCallback& loader_callback); + + private: + static base::FilePath UrlToFile(const GURL& url); + + const GURL& GetURL() const override; + GURL GetRedirectURL() const override; + + URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, + uint32_t skip) override; + + void AsPath( + base::TaskRunner* task_runner, + base::Callback<void(const base::FilePath&, bool)> callback) override; + + std::string MimeType() override; + + bool HasMojoMagic() override; + + bool PeekFirstLine(std::string* line) override; + + GURL url_; + base::FilePath path_; + + DISALLOW_COPY_AND_ASSIGN(LocalFetcher); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SHELL_LOCAL_FETCHER_H_
diff --git a/mojo/shell/native_application_support.cc b/mojo/shell/native_application_support.cc deleted file mode 100644 index f4ca638..0000000 --- a/mojo/shell/native_application_support.cc +++ /dev/null
@@ -1,145 +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 "mojo/shell/native_application_support.h" - -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "mojo/public/platform/native/gles2_impl_chromium_miscellaneous_thunks.h" -#include "mojo/public/platform/native/gles2_impl_chromium_sub_image_thunks.h" -#include "mojo/public/platform/native/gles2_impl_chromium_sync_point_thunks.h" -#include "mojo/public/platform/native/gles2_impl_chromium_texture_mailbox_thunks.h" -#include "mojo/public/platform/native/gles2_impl_occlusion_query_ext_thunks.h" -#include "mojo/public/platform/native/gles2_impl_thunks.h" -#include "mojo/public/platform/native/gles2_thunks.h" -#include "mojo/public/platform/native/system_thunks.h" - -namespace mojo { -namespace shell { - -namespace { - -template <typename Thunks> -bool SetThunks(Thunks (*make_thunks)(), - const char* function_name, - base::NativeLibrary library) { - typedef size_t (*SetThunksFn)(const Thunks* thunks); - SetThunksFn set_thunks = reinterpret_cast<SetThunksFn>( - base::GetFunctionPointerFromNativeLibrary(library, function_name)); - if (!set_thunks) - return false; - Thunks thunks = make_thunks(); - size_t expected_size = set_thunks(&thunks); - if (expected_size > sizeof(Thunks)) { - LOG(ERROR) << "Invalid app library: expected " << function_name - << " to return thunks of size: " << expected_size; - return false; - } - return true; -} - -} // namespace - -base::NativeLibrary LoadNativeApplication(const base::FilePath& app_path, - NativeApplicationCleanup cleanup) { - DVLOG(2) << "Loading Mojo app in process from library: " << app_path.value(); - - base::NativeLibraryLoadError error; - base::NativeLibrary app_library = base::LoadNativeLibrary(app_path, &error); - if (cleanup == NativeApplicationCleanup::DELETE) - DeleteFile(app_path, false); - LOG_IF(ERROR, !app_library) - << "Failed to load app library (error: " << error.ToString() << ")"; - return app_library; -} - -bool RunNativeApplication(base::NativeLibrary app_library, - InterfaceRequest<Application> application_request) { - // Tolerate |app_library| being null, to make life easier for callers. - if (!app_library) - return false; - - if (!SetThunks(&MojoMakeSystemThunks, "MojoSetSystemThunks", app_library)) { - LOG(ERROR) << "MojoSetSystemThunks not found"; - return false; - } - - if (SetThunks(&MojoMakeGLES2ControlThunks, "MojoSetGLES2ControlThunks", - app_library)) { - // If we have the control thunks, we should also have the GLES2 - // implementation thunks. - if (!SetThunks(&MojoMakeGLES2ImplThunks, "MojoSetGLES2ImplThunks", - app_library)) { - LOG(ERROR) - << "MojoSetGLES2ControlThunks found, but not MojoSetGLES2ImplThunks"; - return false; - } - - // If the application is using GLES2 extension points, register those - // thunks. Applications may use or not use any of these, so don't warn if - // they are missing. - SetThunks(MojoMakeGLES2ImplChromiumMiscellaneousThunks, - "MojoSetGLES2ImplChromiumMiscellaneousThunks", app_library); - SetThunks(MojoMakeGLES2ImplChromiumSubImageThunks, - "MojoSetGLES2ImplChromiumSubImageThunks", app_library); - SetThunks(MojoMakeGLES2ImplChromiumTextureMailboxThunks, - "MojoSetGLES2ImplChromiumTextureMailboxThunks", app_library); - SetThunks(MojoMakeGLES2ImplChromiumSyncPointThunks, - "MojoSetGLES2ImplChromiumSyncPointThunks", app_library); - SetThunks(MojoMakeGLES2ImplOcclusionQueryExtThunks, - "MojoSetGLES2ImplOcclusionQueryExtThunks", app_library); - } - // Unlike system thunks, we don't warn on a lack of GLES2 thunks because - // not everything is a visual app. - - // Go shared library support requires us to initialize the runtime before we - // start running any go code. This is a temporary patch. - typedef void (*InitGoRuntimeFn)(); - InitGoRuntimeFn init_go_runtime = reinterpret_cast<InitGoRuntimeFn>( - base::GetFunctionPointerFromNativeLibrary(app_library, "InitGoRuntime")); - if (init_go_runtime) { - DVLOG(2) << "InitGoRuntime: Initializing Go Runtime found in app"; - init_go_runtime(); - } - -#if !defined(OS_WIN) - // On Windows, initializing base::CommandLine with null parameters gets the - // process's command line from the OS. Other platforms need it to be passed - // in. This needs to be passed in before the app initializes the command line, - // which is done as soon as it loads. - typedef void (*InitCommandLineArgs)(int, const char* const*); - InitCommandLineArgs init_command_line_args = - reinterpret_cast<InitCommandLineArgs>( - base::GetFunctionPointerFromNativeLibrary(app_library, - "InitCommandLineArgs")); - if (init_command_line_args) { - int argc = 0; - base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); - const char** argv = new const char* [cmd_line->argv().size()]; - for (auto& arg : cmd_line->argv()) - argv[argc++] = arg.c_str(); - init_command_line_args(argc, argv); - } -#endif - - typedef MojoResult (*MojoMainFunction)(MojoHandle); - MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>( - base::GetFunctionPointerFromNativeLibrary(app_library, "MojoMain")); - if (!main_function) { - LOG(ERROR) << "MojoMain not found"; - return false; - } - // |MojoMain()| takes ownership of the service handle. - MojoHandle handle = application_request.PassMessagePipe().release().value(); - MojoResult result = main_function(handle); - if (result != MOJO_RESULT_OK) { - LOG(ERROR) << "MojoMain returned error (result: " << result << ")"; - } - return true; -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/native_application_support.h b/mojo/shell/native_application_support.h deleted file mode 100644 index 572c089b..0000000 --- a/mojo/shell/native_application_support.h +++ /dev/null
@@ -1,51 +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 SHELL_NATIVE_APPLICATION_SUPPORT_H_ -#define SHELL_NATIVE_APPLICATION_SUPPORT_H_ - -#include "base/native_library.h" -#include "mojo/public/cpp/bindings/interface_request.h" - -#if defined(OS_WIN) -#undef DELETE -#endif - -namespace base { -class FilePath; -} - -namespace mojo { - -class Application; - -namespace shell { - -enum class NativeApplicationCleanup { DELETE, DONT_DELETE }; - -// Loads the native Mojo application from the DSO specified by |app_path|. -// Returns the |base::NativeLibrary| for the application on success (or null on -// failure). If |cleanup| is |DELETE|, it will delete |app_path| (regardless of -// sucess or failure). -// -// Note: The caller may choose to eventually unload the returned DSO. If so, -// this should be done only after the thread on which |LoadNativeApplication()| -// and |RunNativeApplication()| were called has terminated, so that any -// thread-local destructors have been executed. -base::NativeLibrary LoadNativeApplication(const base::FilePath& app_path, - NativeApplicationCleanup cleanup); - -// Runs the native Mojo application from the DSO that was loaded using -// |LoadNativeApplication()|; this tolerates |app_library| being null. This -// should be called on the same thread as |LoadNativeApplication()|. Returns -// true if |MojoMain()| was called (even if it returns an error), and false -// otherwise. -// TODO(vtl): Maybe this should also have a |MojoResult| as an out parameter? -bool RunNativeApplication(base::NativeLibrary app_library, - InterfaceRequest<Application> application_request); - -} // namespace shell -} // namespace mojo - -#endif // SHELL_NATIVE_APPLICATION_SUPPORT_H_
diff --git a/mojo/shell/native_runner.h b/mojo/shell/native_runner.h new file mode 100644 index 0000000..cc2ffb8 --- /dev/null +++ b/mojo/shell/native_runner.h
@@ -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. + +#ifndef MOJO_SHELL_NATIVE_RUNNER_H_ +#define MOJO_SHELL_NATIVE_RUNNER_H_ + +#include "base/callback_forward.h" +#include "base/memory/scoped_ptr.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/interfaces/application/application.mojom.h" +#include "mojo/runner/native_application_support.h" + +namespace base { +class FilePath; +} + +namespace mojo { +namespace shell { + +// ApplicationManager requires implementations of NativeRunner and +// NativeRunnerFactory to run native applications. +class NativeRunner { + public: + virtual ~NativeRunner() {} + + // Loads the app in the file at |app_path| and runs it on some other + // thread/process. If |cleanup| is |DELETE|, this takes ownership of the file. + // |app_completed_callback| is posted (to the thread on which |Start()| was + // called) after |MojoMain()| completes. + // TODO(vtl): |app_path| and |cleanup| should probably be moved to the + // factory's Create(). Rationale: The factory may need information from the + // file to decide what kind of NativeRunner to make. + virtual void Start(const base::FilePath& app_path, + NativeApplicationCleanup cleanup, + InterfaceRequest<Application> application_request, + const base::Closure& app_completed_callback) = 0; +}; + +class NativeRunnerFactory { + public: + // Options for running the native app. (This will contain, e.g., information + // about the sandbox profile, etc.) + struct Options { + // Constructs with default options. + Options() : force_in_process(false) {} + + bool force_in_process; + }; + + virtual ~NativeRunnerFactory() {} + virtual scoped_ptr<NativeRunner> Create(const Options& options) = 0; +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SHELL_NATIVE_RUNNER_H_
diff --git a/mojo/shell/native_runner_unittest.cc b/mojo/shell/native_runner_unittest.cc deleted file mode 100644 index 4b8b5a0..0000000 --- a/mojo/shell/native_runner_unittest.cc +++ /dev/null
@@ -1,102 +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 "base/files/scoped_temp_dir.h" -#include "mojo/shell/application_manager/application_manager.h" -#include "mojo/shell/context.h" -#include "mojo/shell/filename_util.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { -namespace { - -struct TestState { - TestState() - : runner_was_created(false), - runner_was_started(false), - runner_was_destroyed(false) {} - - bool runner_was_created; - bool runner_was_started; - bool runner_was_destroyed; -}; - -class TestNativeRunner : public NativeRunner { - public: - explicit TestNativeRunner(TestState* state) : state_(state) { - state_->runner_was_created = true; - } - ~TestNativeRunner() override { - state_->runner_was_destroyed = true; - base::MessageLoop::current()->Quit(); - } - void Start(const base::FilePath& app_path, - NativeApplicationCleanup cleanup, - InterfaceRequest<Application> application_request, - const base::Closure& app_completed_callback) override { - state_->runner_was_started = true; - } - - private: - TestState* state_; -}; - -class TestNativeRunnerFactory : public NativeRunnerFactory { - public: - explicit TestNativeRunnerFactory(TestState* state) : state_(state) {} - ~TestNativeRunnerFactory() override {} - scoped_ptr<NativeRunner> Create(const Options& options) override { - return scoped_ptr<NativeRunner>(new TestNativeRunner(state_)); - } - - private: - TestState* state_; -}; - -class NativeApplicationLoaderTest : public testing::Test, - public ApplicationManager::Delegate { - public: - NativeApplicationLoaderTest() : application_manager_(this) {} - ~NativeApplicationLoaderTest() override {} - void SetUp() override { - context_.Init(); - scoped_ptr<NativeRunnerFactory> factory( - new TestNativeRunnerFactory(&state_)); - application_manager_.set_native_runner_factory(factory.Pass()); - application_manager_.set_blocking_pool( - context_.task_runners()->blocking_pool()); - } - void TearDown() override { context_.Shutdown(); } - - protected: - shell::Context context_; - base::MessageLoop loop_; - ApplicationManager application_manager_; - TestState state_; - - private: - // ApplicationManager::Delegate - GURL ResolveURL(const GURL& url) override { return url; } - - GURL ResolveMappings(const GURL& url) override { return url; } -}; - -TEST_F(NativeApplicationLoaderTest, DoesNotExist) { - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - base::FilePath nonexistent_file(FILE_PATH_LITERAL("nonexistent.txt")); - GURL url(FilePathToFileURL(temp_dir.path().Append(nonexistent_file))); - InterfaceRequest<ServiceProvider> services; - ServiceProviderPtr service_provider; - application_manager_.ConnectToApplication( - url, GURL(), services.Pass(), service_provider.Pass(), base::Closure()); - EXPECT_FALSE(state_.runner_was_created); - EXPECT_FALSE(state_.runner_was_started); - EXPECT_FALSE(state_.runner_was_destroyed); -} - -} // namespace -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/network_fetcher.cc b/mojo/shell/network_fetcher.cc new file mode 100644 index 0000000..4de4d5d2 --- /dev/null +++ b/mojo/shell/network_fetcher.cc
@@ -0,0 +1,251 @@ +// 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/shell/network_fetcher.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/message_loop/message_loop.h" +#include "base/process/process.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/trace_event/trace_event.h" +#include "crypto/secure_hash.h" +#include "crypto/sha2.h" +#include "mojo/common/common_type_converters.h" +#include "mojo/common/data_pipe_utils.h" +#include "mojo/common/url_type_converters.h" +#include "mojo/services/network/public/interfaces/network_service.mojom.h" +#include "mojo/shell/data_pipe_peek.h" +#include "mojo/shell/switches.h" + +namespace mojo { +namespace shell { + +NetworkFetcher::NetworkFetcher(bool disable_cache, + const GURL& url, + NetworkService* network_service, + const FetchCallback& loader_callback) + : Fetcher(loader_callback), + disable_cache_(false), + url_(url), + weak_ptr_factory_(this) { + StartNetworkRequest(url, network_service); +} + +NetworkFetcher::~NetworkFetcher() { +} + +const GURL& NetworkFetcher::GetURL() const { + return url_; +} + +GURL NetworkFetcher::GetRedirectURL() const { + if (!response_) + return GURL::EmptyGURL(); + + if (response_->redirect_url.is_null()) + return GURL::EmptyGURL(); + + return GURL(response_->redirect_url); +} + +URLResponsePtr NetworkFetcher::AsURLResponse(base::TaskRunner* task_runner, + uint32_t skip) { + if (skip != 0) { + MojoResult result = ReadDataRaw( + response_->body.get(), nullptr, &skip, + MOJO_READ_DATA_FLAG_ALL_OR_NONE | MOJO_READ_DATA_FLAG_DISCARD); + DCHECK_EQ(result, MOJO_RESULT_OK); + } + return response_.Pass(); +} + +void NetworkFetcher::RecordCacheToURLMapping(const base::FilePath& path, + const GURL& url) { + // This is used to extract symbols on android. + // TODO(eseidel): All users of this log should move to using the map file. + VLOG(1) << "Caching mojo app " << url << " at " << path.value(); + + base::FilePath temp_dir; + base::GetTempDir(&temp_dir); + base::ProcessId pid = base::Process::Current().Pid(); + std::string map_name = base::StringPrintf("mojo_shell.%d.maps", pid); + base::FilePath map_path = temp_dir.AppendASCII(map_name); + + // TODO(eseidel): Paths or URLs with spaces will need quoting. + std::string map_entry = + base::StringPrintf("%s %s\n", path.value().c_str(), url.spec().c_str()); + // TODO(eseidel): AppendToFile is missing O_CREAT, crbug.com/450696 + if (!PathExists(map_path)) { + base::WriteFile(map_path, map_entry.data(), + static_cast<int>(map_entry.length())); + } else { + base::AppendToFile(map_path, map_entry.data(), + static_cast<int>(map_entry.length())); + } +} + +// For remote debugging, GDB needs to be, a apriori, aware of the filename a +// library will be loaded from. AppIds should be be both predictable and unique, +// but any hash would work. Currently we use sha256 from crypto/secure_hash.h +bool NetworkFetcher::ComputeAppId(const base::FilePath& path, + std::string* digest_string) { + scoped_ptr<crypto::SecureHash> ctx( + crypto::SecureHash::Create(crypto::SecureHash::SHA256)); + base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!file.IsValid()) { + LOG(ERROR) << "Failed to open " << path.value() << " for computing AppId"; + return false; + } + char buf[1024]; + while (file.IsValid()) { + int bytes_read = file.ReadAtCurrentPos(buf, sizeof(buf)); + if (bytes_read == 0) + break; + ctx->Update(buf, bytes_read); + } + if (!file.IsValid()) { + LOG(ERROR) << "Error reading " << path.value(); + return false; + } + // The output is really a vector of unit8, we're cheating by using a string. + std::string output(crypto::kSHA256Length, 0); + ctx->Finish(string_as_array(&output), output.size()); + output = base::HexEncode(output.c_str(), output.size()); + // Using lowercase for compatiblity with sha256sum output. + *digest_string = base::StringToLowerASCII(output); + return true; +} + +bool NetworkFetcher::RenameToAppId(const GURL& url, + const base::FilePath& old_path, + base::FilePath* new_path) { + std::string app_id; + if (!ComputeAppId(old_path, &app_id)) + return false; + + // Using a hash of the url as a directory to prevent a race when the same + // bytes are downloaded from 2 different urls. In particular, if the same + // application is connected to twice concurrently with different query + // parameters, the directory will be different, which will prevent the + // collision. + std::string dirname = base::HexEncode( + crypto::SHA256HashString(url.spec()).data(), crypto::kSHA256Length); + + base::FilePath temp_dir; + base::GetTempDir(&temp_dir); + base::FilePath app_dir = temp_dir.AppendASCII(dirname); + // The directory is leaked, because it can be reused at any time if the same + // application is downloaded. Deleting it would be racy. This is only + // happening when --predictable-app-filenames is used. + bool result = base::CreateDirectoryAndGetError(app_dir, nullptr); + DCHECK(result); + std::string unique_name = base::StringPrintf("%s.mojo", app_id.c_str()); + *new_path = app_dir.AppendASCII(unique_name); + return base::Move(old_path, *new_path); +} + +void NetworkFetcher::CopyCompleted( + base::Callback<void(const base::FilePath&, bool)> callback, + bool success) { + if (success) { + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kPredictableAppFilenames)) { + // The copy completed, now move to $TMP/$APP_ID.mojo before the dlopen. + success = false; + base::FilePath new_path; + if (RenameToAppId(url_, path_, &new_path)) { + if (base::PathExists(new_path)) { + path_ = new_path; + success = true; + } + } + } + } + + if (success) + RecordCacheToURLMapping(path_, url_); + + base::MessageLoop::current()->PostTask(FROM_HERE, + base::Bind(callback, path_, success)); +} + +void NetworkFetcher::AsPath( + base::TaskRunner* task_runner, + base::Callback<void(const base::FilePath&, bool)> callback) { + if (!path_.empty() || !response_) { + base::MessageLoop::current()->PostTask( + FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); + return; + } + + base::CreateTemporaryFile(&path_); + common::CopyToFile(response_->body.Pass(), path_, task_runner, + base::Bind(&NetworkFetcher::CopyCompleted, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +std::string NetworkFetcher::MimeType() { + return response_->mime_type; +} + +bool NetworkFetcher::HasMojoMagic() { + std::string magic; + return BlockingPeekNBytes(response_->body.get(), &magic, strlen(kMojoMagic), + kPeekTimeout) && + magic == kMojoMagic; +} + +bool NetworkFetcher::PeekFirstLine(std::string* line) { + return BlockingPeekLine(response_->body.get(), line, kMaxShebangLength, + kPeekTimeout); +} + +void NetworkFetcher::StartNetworkRequest(const GURL& url, + NetworkService* network_service) { + TRACE_EVENT_ASYNC_BEGIN1("mojo_shell", "NetworkFetcher::NetworkRequest", this, + "url", url.spec()); + URLRequestPtr request(URLRequest::New()); + request->url = String::From(url); + request->auto_follow_redirects = false; + request->bypass_cache = disable_cache_; + + network_service->CreateURLLoader(GetProxy(&url_loader_)); + url_loader_->Start(request.Pass(), + base::Bind(&NetworkFetcher::OnLoadComplete, + weak_ptr_factory_.GetWeakPtr())); +} + +void NetworkFetcher::OnLoadComplete(URLResponsePtr response) { + TRACE_EVENT_ASYNC_END0("mojo_shell", "NetworkFetcher::NetworkRequest", this); + scoped_ptr<Fetcher> owner(this); + if (response->error) { + LOG(ERROR) << "Error (" << response->error->code << ": " + << response->error->description << ") while fetching " + << response->url; + loader_callback_.Run(nullptr); + return; + } + + if (response->status_code >= 400 && response->status_code < 600) { + LOG(ERROR) << "Error (" << response->status_code << ": " + << response->status_line << "): " + << "while fetching " << response->url; + loader_callback_.Run(nullptr); + return; + } + + response_ = response.Pass(); + loader_callback_.Run(owner.Pass()); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/network_fetcher.h b/mojo/shell/network_fetcher.h new file mode 100644 index 0000000..028ec5b --- /dev/null +++ b/mojo/shell/network_fetcher.h
@@ -0,0 +1,83 @@ +// 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_SHELL_NETWORK_FETCHER_H_ +#define MOJO_SHELL_NETWORK_FETCHER_H_ + +#include "mojo/shell/fetcher.h" + +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "mojo/services/network/public/interfaces/url_loader.mojom.h" +#include "url/gurl.h" + +namespace mojo { + +class NetworkService; + +namespace shell { + +// Implements Fetcher for http[s] files. +class NetworkFetcher : public Fetcher { + public: + NetworkFetcher(bool disable_cache, + const GURL& url, + NetworkService* network_service, + const FetchCallback& loader_callback); + + ~NetworkFetcher() override; + + private: + // TODO(hansmuller): Revisit this when a real peek operation is available. + static const MojoDeadline kPeekTimeout = MOJO_DEADLINE_INDEFINITE; + + const GURL& GetURL() const override; + GURL GetRedirectURL() const override; + + URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, + uint32_t skip) override; + + static void RecordCacheToURLMapping(const base::FilePath& path, + const GURL& url); + + // AppIds should be be both predictable and unique, but any hash would work. + // Currently we use sha256 from crypto/secure_hash.h + static bool ComputeAppId(const base::FilePath& path, + std::string* digest_string); + + static bool RenameToAppId(const GURL& url, + const base::FilePath& old_path, + base::FilePath* new_path); + + void CopyCompleted(base::Callback<void(const base::FilePath&, bool)> callback, + bool success); + + void AsPath( + base::TaskRunner* task_runner, + base::Callback<void(const base::FilePath&, bool)> callback) override; + + std::string MimeType() override; + + bool HasMojoMagic() override; + + bool PeekFirstLine(std::string* line) override; + + void StartNetworkRequest(const GURL& url, NetworkService* network_service); + + void OnLoadComplete(URLResponsePtr response); + + bool disable_cache_; + const GURL url_; + URLLoaderPtr url_loader_; + URLResponsePtr response_; + base::FilePath path_; + base::WeakPtrFactory<NetworkFetcher> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(NetworkFetcher); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SHELL_NETWORK_FETCHER_H_
diff --git a/mojo/shell/out_of_process_native_runner.cc b/mojo/shell/out_of_process_native_runner.cc deleted file mode 100644 index 181a4d25..0000000 --- a/mojo/shell/out_of_process_native_runner.cc +++ /dev/null
@@ -1,71 +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 "mojo/shell/out_of_process_native_runner.h" - -#include "base/bind.h" -#include "base/callback_helpers.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "mojo/shell/child_process.mojom.h" -#include "mojo/shell/child_process_host.h" -#include "mojo/shell/in_process_native_runner.h" - -namespace mojo { -namespace shell { - -OutOfProcessNativeRunner::OutOfProcessNativeRunner(Context* context) - : context_(context) { -} - -OutOfProcessNativeRunner::~OutOfProcessNativeRunner() { - if (child_process_host_) { - // TODO(vtl): Race condition: If |ChildProcessHost::DidStart()| hasn't been - // called yet, we shouldn't call |Join()| here. (Until |DidStart()|, we may - // not have a child process to wait on.) Probably we should fix |Join()|. - child_process_host_->Join(); - } -} - -void OutOfProcessNativeRunner::Start( - const base::FilePath& app_path, - NativeApplicationCleanup cleanup, - InterfaceRequest<Application> application_request, - const base::Closure& app_completed_callback) { - app_path_ = app_path; - - DCHECK(app_completed_callback_.is_null()); - app_completed_callback_ = app_completed_callback; - - child_process_host_.reset(new ChildProcessHost(context_)); - child_process_host_->Start(); - - // TODO(vtl): |app_path.AsUTF8Unsafe()| is unsafe. - child_process_host_->StartApp( - app_path.AsUTF8Unsafe(), cleanup == NativeApplicationCleanup::DELETE, - application_request.Pass(), - base::Bind(&OutOfProcessNativeRunner::AppCompleted, - base::Unretained(this))); -} - -void OutOfProcessNativeRunner::AppCompleted(int32_t result) { - DVLOG(2) << "OutOfProcessNativeRunner::AppCompleted(" << result << ")"; - - child_process_host_.reset(); - // This object may be deleted by this callback. - base::Closure app_completed_callback = app_completed_callback_; - app_completed_callback_.Reset(); - app_completed_callback.Run(); -} - -scoped_ptr<NativeRunner> OutOfProcessNativeRunnerFactory::Create( - const Options& options) { - if (options.force_in_process) - return make_scoped_ptr(new InProcessNativeRunner(context_)); - - return make_scoped_ptr(new OutOfProcessNativeRunner(context_)); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/out_of_process_native_runner.h b/mojo/shell/out_of_process_native_runner.h deleted file mode 100644 index 23bba66f..0000000 --- a/mojo/shell/out_of_process_native_runner.h +++ /dev/null
@@ -1,65 +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 SHELL_OUT_OF_PROCESS_NATIVE_RUNNER_H_ -#define SHELL_OUT_OF_PROCESS_NATIVE_RUNNER_H_ - -#include "base/callback.h" -#include "base/files/file_path.h" -#include "base/macros.h" -#include "base/memory/scoped_ptr.h" -#include "mojo/public/cpp/bindings/error_handler.h" -#include "mojo/shell/application_manager/native_runner.h" - -namespace mojo { -namespace shell { - -class ChildProcessHost; -class Context; - -// An implementation of |NativeRunner| that loads/runs the given app (from the -// file system) in a separate process (of its own). -class OutOfProcessNativeRunner : public NativeRunner { - public: - explicit OutOfProcessNativeRunner(Context* context); - ~OutOfProcessNativeRunner() override; - - // |NativeRunner| method: - void Start(const base::FilePath& app_path, - NativeApplicationCleanup cleanup, - InterfaceRequest<Application> application_request, - const base::Closure& app_completed_callback) override; - - private: - // |ChildController::StartApp()| callback: - void AppCompleted(int32_t result); - - Context* const context_; - - base::FilePath app_path_; - base::Closure app_completed_callback_; - - scoped_ptr<ChildProcessHost> child_process_host_; - - DISALLOW_COPY_AND_ASSIGN(OutOfProcessNativeRunner); -}; - -class OutOfProcessNativeRunnerFactory : public NativeRunnerFactory { - public: - explicit OutOfProcessNativeRunnerFactory(Context* context) - : context_(context) {} - ~OutOfProcessNativeRunnerFactory() override {} - - scoped_ptr<NativeRunner> Create(const Options& options) override; - - private: - Context* const context_; - - DISALLOW_COPY_AND_ASSIGN(OutOfProcessNativeRunnerFactory); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_OUT_OF_PROCESS_NATIVE_RUNNER_H_
diff --git a/mojo/shell/query_util.cc b/mojo/shell/query_util.cc new file mode 100644 index 0000000..fbe4c56 --- /dev/null +++ b/mojo/shell/query_util.cc
@@ -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. + +#include "mojo/shell/query_util.h" + +#include "base/strings/string_util.h" + +namespace mojo { +namespace shell { + +GURL GetBaseURLAndQuery(const GURL& url, std::string* query) { + if (!url.has_query()) { + if (query) + *query = ""; + return url; + } + + if (query) + *query = "?" + url.query(); + GURL::Replacements repl; + repl.SetQueryStr(""); + std::string result = url.ReplaceComponents(repl).spec(); + + // Remove the dangling '?' because it's ugly. + base::ReplaceChars(result, "?", "", &result); + return GURL(result); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/query_util.h b/mojo/shell/query_util.h new file mode 100644 index 0000000..a1f0ac7 --- /dev/null +++ b/mojo/shell/query_util.h
@@ -0,0 +1,23 @@ +// 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_SHELL_QUERY_UTIL_H_ +#define MOJO_SHELL_QUERY_UTIL_H_ + +#include <utility> + +#include "url/gurl.h" + +namespace mojo { +namespace shell { + +// Returns the base URL (without the query string). If |query| is not nullptr, +// set |*query| to the query string. If the url doesn't have a query string, +// |*query| is set to the empty string. +GURL GetBaseURLAndQuery(const GURL& url, std::string* query); + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SHELL_QUERY_UTIL_H_
diff --git a/mojo/shell/query_util_unittest.cc b/mojo/shell/query_util_unittest.cc new file mode 100644 index 0000000..9b28bc5 --- /dev/null +++ b/mojo/shell/query_util_unittest.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 "mojo/shell/query_util.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace mojo { +namespace shell { +namespace { + +TEST(QueryUtil, NoQuery) { + GURL url("http://www.example.com/"); + std::string query; + GURL base_url = GetBaseURLAndQuery(url, &query); + EXPECT_EQ(base_url, url); + EXPECT_EQ(query, ""); +} + +TEST(QueryUtil, WithEmptyQuery) { + GURL url("http://www.example.com/?"); + std::string query; + GURL base_url = GetBaseURLAndQuery(url, &query); + EXPECT_EQ(base_url, GURL("http://www.example.com/")); + EXPECT_EQ(query, "?"); +} + +TEST(QueryUtil, WithFullQuery) { + GURL url("http://www.example.com/?a=b&c=d"); + std::string query; + GURL base_url = GetBaseURLAndQuery(url, &query); + EXPECT_EQ(base_url, GURL("http://www.example.com/")); + EXPECT_EQ(query, "?a=b&c=d"); +} + +TEST(QueryUtil, ForFileURL) { + GURL url("file:///tmp/file?a=b&c=d"); + std::string query; + GURL base_url = GetBaseURLAndQuery(url, &query); + EXPECT_EQ(base_url, GURL("file:///tmp/file")); + EXPECT_EQ(query, "?a=b&c=d"); +} + +} // namespace +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/shell_apptest.cc b/mojo/shell/shell_apptest.cc deleted file mode 100644 index 66b6889..0000000 --- a/mojo/shell/shell_apptest.cc +++ /dev/null
@@ -1,197 +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 "base/base_paths.h" -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/path_service.h" -#include "base/run_loop.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "mojo/application/application_test_base_chromium.h" -#include "mojo/common/data_pipe_utils.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/system/macros.h" -#include "mojo/services/http_server/public/cpp/http_server_util.h" -#include "mojo/services/http_server/public/interfaces/http_server.mojom.h" -#include "mojo/services/http_server/public/interfaces/http_server_factory.mojom.h" -#include "mojo/services/network/public/interfaces/net_address.mojom.h" -#include "mojo/shell/kPingable.h" -#include "mojo/shell/test/pingable.mojom.h" - -namespace mojo { -namespace { - -std::string GetURL(uint16_t port, const std::string& path) { - return base::StringPrintf("http://127.0.0.1:%u/%s", - static_cast<unsigned>(port), path.c_str()); -} - -class GetHandler : public http_server::HttpHandler { - public: - GetHandler(InterfaceRequest<http_server::HttpHandler> request, uint16_t port) - : binding_(this, request.Pass()), port_(port) { - } - ~GetHandler() override {} - - private: - // http_server::HttpHandler: - void HandleRequest( - http_server::HttpRequestPtr request, - const Callback<void(http_server::HttpResponsePtr)>& callback) override { - http_server::HttpResponsePtr response; - if (StartsWithASCII(request->relative_url, "/app", true)) { - response = http_server::CreateHttpResponse( - 200, std::string(kPingable.data, kPingable.size)); - response->content_type = "application/octet-stream"; - } else if (request->relative_url == "/redirect") { - response = http_server::HttpResponse::New(); - response->status_code = 302; - response->custom_headers.insert("Location", GetURL(port_, "app")); - } else { - NOTREACHED(); - } - - callback.Run(response.Pass()); - } - - Binding<http_server::HttpHandler> binding_; - uint16_t port_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(GetHandler); -}; - -typedef test::ApplicationTestBase ShellAppTest; - -class ShellHTTPAppTest : public test::ApplicationTestBase { - public: - ShellHTTPAppTest() : ApplicationTestBase() {} - ~ShellHTTPAppTest() override {} - - protected: - // ApplicationTestBase: - void SetUp() override { - ApplicationTestBase::SetUp(); - - application_impl()->ConnectToService("mojo:http_server", - &http_server_factory_); - - NetAddressPtr local_address(NetAddress::New()); - local_address->family = NET_ADDRESS_FAMILY_IPV4; - local_address->ipv4 = NetAddressIPv4::New(); - local_address->ipv4->addr.resize(4); - local_address->ipv4->addr[0] = 127; - local_address->ipv4->addr[1] = 0; - local_address->ipv4->addr[2] = 0; - local_address->ipv4->addr[3] = 1; - local_address->ipv4->port = 0; - http_server_factory_->CreateHttpServer(GetProxy(&http_server_), - local_address.Pass()); - - http_server_->GetPort([this](uint16_t p) { port_ = p; }); - EXPECT_TRUE(http_server_.WaitForIncomingMethodCall()); - - InterfacePtr<http_server::HttpHandler> http_handler; - handler_.reset(new GetHandler(GetProxy(&http_handler).Pass(), port_)); - http_server_->SetHandler(".*", http_handler.Pass(), - [](bool result) { EXPECT_TRUE(result); }); - EXPECT_TRUE(http_server_.WaitForIncomingMethodCall()); - } - - std::string GetURL(const std::string& path) { - return ::mojo::GetURL(port_, path); - } - - http_server::HttpServerFactoryPtr http_server_factory_; - http_server::HttpServerPtr http_server_; - scoped_ptr<GetHandler> handler_; - uint16_t port_; - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(ShellHTTPAppTest); -}; - -// Test that we can load apps over http. -TEST_F(ShellHTTPAppTest, Http) { - InterfacePtr<Pingable> pingable; - application_impl()->ConnectToService(GetURL("app"), &pingable); - pingable->Ping("hello", - [this](const String& app_url, const String& connection_url, - const String& message) { - EXPECT_EQ(GetURL("app"), app_url); - EXPECT_EQ(GetURL("app"), connection_url); - EXPECT_EQ("hello", message); - base::MessageLoop::current()->Quit(); - }); - base::RunLoop().Run(); -} - -// Test that redirects work. -// TODO(aa): Test that apps receive the correct URL parameters. -TEST_F(ShellHTTPAppTest, Redirect) { - InterfacePtr<Pingable> pingable; - application_impl()->ConnectToService(GetURL("redirect"), &pingable); - pingable->Ping("hello", - [this](const String& app_url, const String& connection_url, - const String& message) { - EXPECT_EQ(GetURL("app"), app_url); - EXPECT_EQ(GetURL("app"), connection_url); - EXPECT_EQ("hello", message); - base::MessageLoop::current()->Quit(); - }); - base::RunLoop().Run(); -} - -// Test that querystring is not considered when resolving http applications. -// TODO(aa|qsr): Fix this test on Linux ASAN http://crbug.com/463662 -#if defined(ADDRESS_SANITIZER) -#define MAYBE_QueryHandling DISABLED_QueryHandling -#else -#define MAYBE_QueryHandling QueryHandling -#endif // ADDRESS_SANITIZER -TEST_F(ShellHTTPAppTest, MAYBE_QueryHandling) { - InterfacePtr<Pingable> pingable1; - InterfacePtr<Pingable> pingable2; - application_impl()->ConnectToService(GetURL("app?foo"), &pingable1); - application_impl()->ConnectToService(GetURL("app?bar"), &pingable2); - - int num_responses = 0; - auto callback = [this, &num_responses](const String& app_url, - const String& connection_url, - const String& message) { - EXPECT_EQ(GetURL("app"), app_url); - EXPECT_EQ("hello", message); - ++num_responses; - if (num_responses == 1) { - EXPECT_EQ(GetURL("app?foo"), connection_url); - } else if (num_responses == 2) { - EXPECT_EQ(GetURL("app?bar"), connection_url); - base::MessageLoop::current()->Quit(); - } else { - CHECK(false); - } - }; - pingable1->Ping("hello", callback); - pingable2->Ping("hello", callback); - base::RunLoop().Run(); -} - -// mojo: URLs can have querystrings too -TEST_F(ShellAppTest, MojoURLQueryHandling) { - InterfacePtr<Pingable> pingable; - application_impl()->ConnectToService("mojo:pingable_app?foo", &pingable); - auto callback = [this](const String& app_url, const String& connection_url, - const String& message) { - EXPECT_TRUE(EndsWith(app_url, "/pingable_app.mojo", true)); - EXPECT_EQ(app_url.To<std::string>() + "?foo", connection_url); - EXPECT_EQ("hello", message); - base::MessageLoop::current()->Quit(); - }; - pingable->Ping("hello", callback); - base::RunLoop().Run(); -} - -} // namespace -} // namespace mojo
diff --git a/mojo/shell/shell_impl.cc b/mojo/shell/shell_impl.cc new file mode 100644 index 0000000..c516686 --- /dev/null +++ b/mojo/shell/shell_impl.cc
@@ -0,0 +1,62 @@ +// 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/shell/shell_impl.h" + +#include "mojo/common/common_type_converters.h" +#include "mojo/common/url_type_converters.h" +#include "mojo/shell/application_manager.h" +#include "third_party/mojo_services/src/content_handler/public/interfaces/content_handler.mojom.h" + +namespace mojo { +namespace shell { + +ShellImpl::ShellImpl(ApplicationPtr application, + ApplicationManager* manager, + const Identity& identity, + const base::Closure& on_application_end) + : manager_(manager), + identity_(identity), + on_application_end_(on_application_end), + application_(application.Pass()), + binding_(this) { + binding_.set_error_handler(this); +} + +ShellImpl::~ShellImpl() { +} + +void ShellImpl::InitializeApplication(Array<String> args) { + ShellPtr shell; + binding_.Bind(GetProxy(&shell)); + application_->Initialize(shell.Pass(), args.Pass(), identity_.url.spec()); +} + +void ShellImpl::ConnectToClient(const GURL& requested_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { + application_->AcceptConnection(String::From(requestor_url), services.Pass(), + exposed_services.Pass(), requested_url.spec()); +} + +// Shell implementation: +void ShellImpl::ConnectToApplication(const String& app_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) { + GURL app_gurl(app_url); + if (!app_gurl.is_valid()) { + LOG(ERROR) << "Error: invalid URL: " << app_url; + return; + } + manager_->ConnectToApplication(app_gurl, identity_.url, services.Pass(), + exposed_services.Pass(), base::Closure()); +} + +void ShellImpl::OnConnectionError() { + manager_->OnShellImplError(this); +} + +} // namespace shell +} // namespace mojo
diff --git a/mojo/shell/shell_impl.h b/mojo/shell/shell_impl.h new file mode 100644 index 0000000..cf8be59 --- /dev/null +++ b/mojo/shell/shell_impl.h
@@ -0,0 +1,62 @@ +// 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_SHELL_SHELL_IMPL_H_ +#define MOJO_SHELL_SHELL_IMPL_H_ + +#include "base/callback.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/error_handler.h" +#include "mojo/public/interfaces/application/application.mojom.h" +#include "mojo/public/interfaces/application/shell.mojom.h" +#include "mojo/shell/identity.h" +#include "url/gurl.h" + +namespace mojo { +namespace shell { + +class ApplicationManager; + +class ShellImpl : public Shell, public ErrorHandler { + public: + ShellImpl(ApplicationPtr application, + ApplicationManager* manager, + const Identity& resolved_identity, + const base::Closure& on_application_end); + + ~ShellImpl() override; + + void InitializeApplication(Array<String> args); + + void ConnectToClient(const GURL& requested_url, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services); + + Application* application() { return application_.get(); } + const Identity& identity() const { return identity_; } + base::Closure on_application_end() const { return on_application_end_; } + + private: + // Shell implementation: + void ConnectToApplication(const String& app_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services) override; + + // ErrorHandler implementation: + void OnConnectionError() override; + + ApplicationManager* const manager_; + const Identity identity_; + base::Closure on_application_end_; + ApplicationPtr application_; + Binding<Shell> binding_; + + DISALLOW_COPY_AND_ASSIGN(ShellImpl); +}; + +} // namespace shell +} // namespace mojo + +#endif // MOJO_SHELL_SHELL_IMPL_H_
diff --git a/mojo/shell/shell_test_base.cc b/mojo/shell/shell_test_base.cc deleted file mode 100644 index da9a7d9..0000000 --- a/mojo/shell/shell_test_base.cc +++ /dev/null
@@ -1,73 +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 "mojo/shell/shell_test_base.h" - -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/logging.h" -#include "base/path_service.h" -#include "build/build_config.h" -#include "mojo/shell/filename_util.h" -#include "url/gurl.h" - -namespace mojo { -namespace shell { -namespace test { - -namespace { - -void QuitIfRunning() { - if (base::MessageLoop::current() && - base::MessageLoop::current()->is_running()) { - base::MessageLoop::current()->QuitWhenIdle(); - } -} - -} // namespace - -ShellTestBase::ShellTestBase() { -} - -ShellTestBase::~ShellTestBase() { -} - -void ShellTestBase::SetUp() { - CHECK(shell_context_.Init()); - SetUpTestApplications(); -} - -void ShellTestBase::TearDown() { - shell_context_.Shutdown(); -} - -ScopedMessagePipeHandle ShellTestBase::ConnectToService( - const GURL& application_url, - const std::string& service_name) { - ServiceProviderPtr services; - shell_context_.application_manager()->ConnectToApplication( - application_url, GURL(), GetProxy(&services), nullptr, - base::Bind(&QuitIfRunning)); - MessagePipe pipe; - services->ConnectToService(service_name, pipe.handle1.Pass()); - return pipe.handle0.Pass(); -} - -#if !defined(OS_ANDROID) -void ShellTestBase::SetUpTestApplications() { - // Set the URLResolver origin to be the same as the base file path for - // local files. This is primarily for test convenience, so that references - // to unknown mojo: urls that do not have specific local file or custom - // mappings registered on the URL resolver are treated as shared libraries. - base::FilePath service_dir; - CHECK(PathService::Get(base::DIR_MODULE, &service_dir)); - shell_context_.url_resolver()->SetMojoBaseURL(FilePathToFileURL(service_dir)); -} -#endif - -} // namespace test -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/shell_test_base.h b/mojo/shell/shell_test_base.h deleted file mode 100644 index e119a0a..0000000 --- a/mojo/shell/shell_test_base.h +++ /dev/null
@@ -1,59 +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 SHELL_SHELL_TEST_BASE_H_ -#define SHELL_SHELL_TEST_BASE_H_ - -#include <string> - -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/shell/context.h" -#include "testing/gtest/include/gtest/gtest.h" - -class GURL; - -namespace mojo { -namespace shell { -namespace test { - -class ShellTestBase : public testing::Test { - public: - ShellTestBase(); - ~ShellTestBase() override; - - void SetUp() override; - void TearDown() override; - - // |application_url| should typically be a mojo: URL (the origin will be set - // to an "appropriate" file: URL). - // TODO(tim): Should the test base be a ServiceProvider? - ScopedMessagePipeHandle ConnectToService(const GURL& application_url, - const std::string& service_name); - - template <typename Interface> - void ConnectToService(const GURL& application_url, - InterfacePtr<Interface>* ptr) { - ptr->Bind(ConnectToService(application_url, Interface::Name_).Pass()); - } - - base::MessageLoop* message_loop() { return &message_loop_; } - Context* shell_context() { return &shell_context_; } - - private: - // Set up the test applications so that mojo: URL resolves to those. - void SetUpTestApplications(); - - Context shell_context_; - base::MessageLoop message_loop_; - - DISALLOW_COPY_AND_ASSIGN(ShellTestBase); -}; - -} // namespace test -} // namespace shell -} // namespace mojo - -#endif // SHELL_SHELL_TEST_BASE_H_
diff --git a/mojo/shell/shell_test_base_android.cc b/mojo/shell/shell_test_base_android.cc deleted file mode 100644 index 4b3b736..0000000 --- a/mojo/shell/shell_test_base_android.cc +++ /dev/null
@@ -1,47 +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 "mojo/shell/shell_test_base.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_string.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "jni/ShellTestBase_jni.h" -#include "mojo/shell/filename_util.h" -#include "url/gurl.h" - -namespace mojo { -namespace shell { -namespace test { - -namespace { - -JNIEnv* InitEnv() { - JNIEnv* env = base::android::AttachCurrentThread(); - static bool initialized = false; - if (!initialized) { - RegisterNativesImpl(env); - initialized = true; - } - return env; -} - -} // namespace - -void ShellTestBase::SetUpTestApplications() { - // Extract mojo applications, and set the resolve base URL to the directory - // containing those. - JNIEnv* env = InitEnv(); - base::android::ScopedJavaLocalRef<jstring> service_dir( - Java_ShellTestBase_extractMojoApplications( - env, base::android::GetApplicationContext())); - shell_context_.url_resolver()->SetMojoBaseURL( - FilePathToFileURL(base::FilePath( - base::android::ConvertJavaStringToUTF8(env, service_dir.obj())))); -} - -} // namespace test -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/shell_test_base_unittest.cc b/mojo/shell/shell_test_base_unittest.cc deleted file mode 100644 index 4e945115..0000000 --- a/mojo/shell/shell_test_base_unittest.cc +++ /dev/null
@@ -1,309 +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 "mojo/shell/shell_test_base.h" - -#include "base/bind.h" -#include "base/i18n/time_formatting.h" -#include "base/macros.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/utf_string_conversions.h" -#include "mojo/public/cpp/bindings/error_handler.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/system/core.h" -#include "mojo/services/test_service/test_request_tracker.mojom.h" -#include "mojo/services/test_service/test_service.mojom.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -using mojo::test::ServiceReport; -using mojo::test::ServiceReportPtr; -using mojo::test::TestService; -using mojo::test::TestTimeService; -using mojo::test::TestServicePtr; -using mojo::test::TestTimeServicePtr; -using mojo::test::TestTrackedRequestService; -using mojo::test::TestTrackedRequestServicePtr; - -namespace mojo { -namespace shell { -namespace test { -namespace { - -void GetReportCallback(base::MessageLoop* loop, - std::vector<ServiceReport>* reports_out, - Array<ServiceReportPtr> report) { - for (size_t i = 0; i < report.size(); i++) - reports_out->push_back(*report[i]); - loop->QuitWhenIdle(); -} - -class ShellTestBaseTest : public ShellTestBase { - public: - // Convenience helpers for use as callbacks in tests. - template <typename T> - base::Callback<void()> SetAndQuit(T* val, T result) { - return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>, - base::Unretained(this), val, result); - } - template <typename T> - base::Callback<void(T result)> SetAndQuit(T* val) { - return base::Bind(&ShellTestBaseTest::SetAndQuitImpl<T>, - base::Unretained(this), val); - } - static GURL test_app_url() { return GURL("mojo:test_app"); } - - void GetReport(std::vector<ServiceReport>* report) { - ConnectToService(GURL("mojo:test_request_tracker_app"), &request_tracking_); - request_tracking_->GetReport(base::Bind(&GetReportCallback, - base::Unretained(message_loop()), - base::Unretained(report))); - message_loop()->Run(); - } - - private: - template <typename T> - void SetAndQuitImpl(T* val, T result) { - *val = result; - message_loop()->QuitWhenIdle(); - } - TestTrackedRequestServicePtr request_tracking_; -}; - -class QuitMessageLoopErrorHandler : public ErrorHandler { - public: - QuitMessageLoopErrorHandler() {} - ~QuitMessageLoopErrorHandler() override {} - - // |ErrorHandler| implementation: - void OnConnectionError() override { - base::MessageLoop::current()->QuitWhenIdle(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(QuitMessageLoopErrorHandler); -}; - -// Tests that we can connect to a single service within a single app. -TEST_F(ShellTestBaseTest, ConnectBasic) { - InterfacePtr<TestService> service; - ConnectToService(test_app_url(), &service); - - bool was_run = false; - service->Ping(SetAndQuit<bool>(&was_run, true)); - message_loop()->Run(); - EXPECT_TRUE(was_run); - EXPECT_FALSE(service.encountered_error()); - - service.reset(); - - // This will run until the test app has actually quit (which it will, - // since we killed the only connection to it). - message_loop()->Run(); -} - -// Tests that trying to connect to a service fails properly if the service -// doesn't exist. Implicit in this test is verification that the shell -// terminates if no services are running. -TEST_F(ShellTestBaseTest, ConnectInvalidService) { - InterfacePtr<TestService> test_service; - ConnectToService(GURL("mojo:non_existent_service"), &test_service); - - bool was_run = false; - test_service->Ping(SetAndQuit<bool>(&was_run, true)); - - // This will quit because there's nothing running. - message_loop()->Run(); - EXPECT_FALSE(was_run); - - // It may have quit before an error was processed. - if (!test_service.encountered_error()) { - QuitMessageLoopErrorHandler quitter; - test_service.set_error_handler(&quitter); - message_loop()->Run(); - EXPECT_TRUE(test_service.encountered_error()); - } - - test_service.reset(); -} - -// Tests that we can connect to a single service within a single app using -// a network based loader instead of local files. -// TODO(tim): Disabled because network service leaks NSS at exit, meaning -// subsequent tests can't init properly. -TEST_F(ShellTestBaseTest, DISABLED_ConnectBasicNetwork) { - InterfacePtr<TestService> service; - ConnectToService(test_app_url(), &service); - - bool was_run = false; - service->Ping(SetAndQuit<bool>(&was_run, true)); - message_loop()->Run(); - EXPECT_TRUE(was_run); - EXPECT_FALSE(service.encountered_error()); - - // Note that use of the network service is implicit in this test. - // Since TestService is not the only service in use, the shell won't auto - // magically exit when TestService is destroyed (unlike ConnectBasic). - // Tearing down the shell context will kill connections. The shell loop will - // exit as soon as no more apps are connected. - // TODO(tim): crbug.com/392685. Calling this explicitly shouldn't be - // necessary once the shell terminates if the primordial app exits, which - // we could enforce here by resetting |service|. - shell_context()->application_manager()->TerminateShellConnections(); - message_loop()->Run(); // Waits for all connections to die. -} - -// Tests that trying to connect to a service over network fails preoprly -// if the service doesn't exist. -// TODO(tim): Disabled because network service leaks NSS at exit, meaning -// subsequent tests can't init properly. -TEST_F(ShellTestBaseTest, DISABLED_ConnectInvalidServiceNetwork) { - InterfacePtr<TestService> test_service; - ConnectToService(GURL("http://example.com/non_existent_service"), - &test_service); - QuitMessageLoopErrorHandler quitter; - test_service.set_error_handler(&quitter); - bool was_run = false; - test_service->Ping(SetAndQuit<bool>(&was_run, true)); - message_loop()->Run(); - EXPECT_TRUE(test_service.encountered_error()); - - // TODO(tim): crbug.com/392685. Calling this explicitly shouldn't be - // necessary once the shell terminates if the primordial app exits, which - // we could enforce here by resetting |service|. - shell_context()->application_manager()->TerminateShellConnections(); - message_loop()->Run(); // Waits for all connections to die. -} - -// Similar to ConnectBasic, but causes the app to instantiate multiple -// service implementation objects and verifies the shell can reach both. -TEST_F(ShellTestBaseTest, ConnectMultipleInstancesPerApp) { - { - TestServicePtr service1, service2; - ConnectToService(test_app_url(), &service1); - ConnectToService(test_app_url(), &service2); - - bool was_run1 = false; - bool was_run2 = false; - service1->Ping(SetAndQuit<bool>(&was_run1, true)); - message_loop()->Run(); - service2->Ping(SetAndQuit<bool>(&was_run2, true)); - message_loop()->Run(); - EXPECT_TRUE(was_run1); - EXPECT_TRUE(was_run2); - EXPECT_FALSE(service1.encountered_error()); - EXPECT_FALSE(service2.encountered_error()); - } - message_loop()->Run(); -} - -// Tests that service A and service B, both in App 1, can talk to each other -// and parameters are passed around properly. -TEST_F(ShellTestBaseTest, ConnectDifferentServicesInSingleApp) { - // Have a TestService GetPartyTime on a TestTimeService in the same app. - int64 time_message; - TestServicePtr service; - ConnectToService(test_app_url(), &service); - service->ConnectToAppAndGetTime(test_app_url().spec(), - SetAndQuit<int64>(&time_message)); - message_loop()->Run(); - - // Verify by hitting the TimeService directly. - TestTimeServicePtr time_service; - ConnectToService(test_app_url(), &time_service); - int64 party_time; - time_service->GetPartyTime(SetAndQuit<int64>(&party_time)); - message_loop()->Run(); - - EXPECT_EQ(time_message, party_time); -} - -// Tests that a service A in App 1 can talk to service B in App 2 and -// parameters are passed around properly. -TEST_F(ShellTestBaseTest, ConnectDifferentServicesInDifferentApps) { - int64 time_message; - TestServicePtr service; - ConnectToService(test_app_url(), &service); - service->ConnectToAppAndGetTime("mojo:test_request_tracker_app", - SetAndQuit<int64>(&time_message)); - message_loop()->Run(); - - // Verify by hitting the TimeService in the request tracker app directly. - TestTimeServicePtr time_service; - ConnectToService(GURL("mojo:test_request_tracker_app"), &time_service); - int64 party_time; - time_service->GetPartyTime(SetAndQuit<int64>(&party_time)); - message_loop()->Run(); - - EXPECT_EQ(time_message, party_time); -} - -// Tests that service A in App 1 can be a client of service B in App 2. -TEST_F(ShellTestBaseTest, ConnectServiceAsClientOfSeparateApp) { - TestServicePtr service; - ConnectToService(test_app_url(), &service); - service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure()); - service->Ping(Callback<void()>()); - message_loop()->Run(); - - for (int i = 0; i < 8; i++) - service->Ping(Callback<void()>()); - service->Ping(message_loop()->QuitWhenIdleClosure()); - message_loop()->Run(); - - // If everything worked properly, the tracking service should report - // 10 pings to TestService. - std::vector<ServiceReport> reports; - GetReport(&reports); - ASSERT_EQ(1U, reports.size()); - EXPECT_EQ(TestService::Name_, reports[0].service_name); - EXPECT_EQ(10U, reports[0].total_requests); -} - -// Connect several services together and use the tracking service to verify -// communication. -TEST_F(ShellTestBaseTest, ConnectManyClientsAndServices) { - TestServicePtr service; - TestTimeServicePtr time_service; - - // Make a request to the TestService and have it contact TimeService in the - // tracking app. Do all this with tracking enabled, meaning both services - // are connected as clients of the TrackedRequestService. - ConnectToService(test_app_url(), &service); - service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure()); - message_loop()->Run(); - for (int i = 0; i < 5; i++) - service->Ping(Callback<void()>()); - int64 time_result; - service->ConnectToAppAndGetTime("mojo:test_request_tracker_app", - SetAndQuit<int64>(&time_result)); - message_loop()->Run(); - - // Also make a few requests to the TimeService in the test_app. - ConnectToService(test_app_url(), &time_service); - time_service->StartTrackingRequests(message_loop()->QuitWhenIdleClosure()); - time_service->GetPartyTime(Callback<void(uint64_t)>()); - message_loop()->Run(); - for (int i = 0; i < 18; i++) - time_service->GetPartyTime(Callback<void(uint64_t)>()); - // Flush the tasks with one more to quit. - int64 party_time = 0; - time_service->GetPartyTime(SetAndQuit<int64>(&party_time)); - message_loop()->Run(); - - std::vector<ServiceReport> reports; - GetReport(&reports); - ASSERT_EQ(3U, reports.size()); - EXPECT_EQ(TestService::Name_, reports[0].service_name); - EXPECT_EQ(6U, reports[0].total_requests); - EXPECT_EQ(TestTimeService::Name_, reports[1].service_name); - EXPECT_EQ(1U, reports[1].total_requests); - EXPECT_EQ(TestTimeService::Name_, reports[2].service_name); - EXPECT_EQ(20U, reports[2].total_requests); -} - -} // namespace -} // namespace test -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/shell_test_main.cc b/mojo/shell/shell_test_main.cc deleted file mode 100644 index 47b6c09..0000000 --- a/mojo/shell/shell_test_main.cc +++ /dev/null
@@ -1,30 +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 "base/at_exit.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/logging.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "base/test/test_suite.h" -#include "mojo/shell/child_process.h" -#include "mojo/shell/switches.h" -#include "testing/gtest/include/gtest/gtest.h" - -int main(int argc, char** argv) { - base::CommandLine::Init(argc, argv); - const base::CommandLine& command_line = - *base::CommandLine::ForCurrentProcess(); - - if (command_line.HasSwitch(switches::kChildProcess)) { - base::AtExitManager at_exit; - - return mojo::shell::ChildProcessMain(); - } - - base::TestSuite test_suite(argc, argv); - return base::LaunchUnitTests( - argc, argv, - base::Bind(&base::TestSuite::Run, base::Unretained(&test_suite))); -}
diff --git a/mojo/shell/switches.cc b/mojo/shell/switches.cc index 1fff40d5..c6df370 100644 --- a/mojo/shell/switches.cc +++ b/mojo/shell/switches.cc
@@ -8,42 +8,9 @@ namespace switches { -// Used internally by the main process to indicate that a new process should be -// a child process. Not for user use. -const char kChildProcess[] = "child-process"; - -// Comma separated list like: -// text/html,mojo:html_viewer,application/bravo,https://abarth.com/bravo -const char kContentHandlers[] = "content-handlers"; - -// Force dynamically loaded apps / services to be loaded irrespective of cache -// instructions. -const char kDisableCache[] = "disable-cache"; - // If set apps downloaded are not deleted. const char kDontDeleteOnDownload[] = "dont-delete-on-download"; -// Load apps in separate processes. -// TODO(vtl): Work in progress; doesn't work. Flip this to "disable" (or maybe -// change it to "single-process") when it works. -const char kEnableMultiprocess[] = "enable-multiprocess"; - -// In multiprocess mode, force these apps to be loaded in the main process. -// Comma-separate list of URLs. Example: -// --force-in-process=mojo:native_viewport_service,mojo:network_service -const char kForceInProcess[] = "force-in-process"; - -// Print the usage message and exit. -const char kHelp[] = "help"; - -// Specify origin to map to base url. See url_resolver.cc for details. -// Can be used multiple times. -const char kMapOrigin[] = "map-origin"; - -// Map mojo: URLs to a shared library of similar name at this origin. See -// url_resolver.cc for details. -const char kOrigin[] = "origin"; - // If set apps downloaded are saved in with a predictable filename, to help // remote debugging: when gdb is used through gdbserver, it needs to be able to // find locally any loaded library. For this, gdb use the filename of the @@ -51,14 +18,4 @@ // their content. const char kPredictableAppFilenames[] = "predictable-app-filenames"; -// Starts tracing when the shell starts up, saving a trace file on disk after 5 -// seconds or when the shell exits. -const char kTraceStartup[] = "trace-startup"; - -// Specifies a set of mappings to apply when resolving urls. The value is a set -// of ',' separated mappings, where each mapping consists of a pair of urls -// giving the to/from url to map. For example, 'a=b,c=d' contains two mappings, -// the first maps 'a' to 'b' and the second 'c' to 'd'. -const char kURLMappings[] = "url-mappings"; - } // namespace switches
diff --git a/mojo/shell/switches.h b/mojo/shell/switches.h index 31cac8f6..90cece0 100644 --- a/mojo/shell/switches.h +++ b/mojo/shell/switches.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef SHELL_SWITCHES_H_ -#define SHELL_SWITCHES_H_ +#ifndef MOJO_SHELL_SWITCHES_H_ +#define MOJO_SHELL_SWITCHES_H_ #include <set> #include <string> @@ -12,19 +12,9 @@ // All switches in alphabetical order. The switches should be documented // alongside the definition of their values in the .cc file. -extern const char kChildProcess[]; -extern const char kContentHandlers[]; -extern const char kDisableCache[]; extern const char kDontDeleteOnDownload[]; -extern const char kEnableMultiprocess[]; -extern const char kForceInProcess[]; -extern const char kHelp[]; -extern const char kMapOrigin[]; -extern const char kOrigin[]; extern const char kPredictableAppFilenames[]; -extern const char kTraceStartup[]; -extern const char kURLMappings[]; } // namespace switches -#endif // SHELL_SWITCHES_H_ +#endif // MOJO_SHELL_SWITCHES_H_
diff --git a/mojo/shell/task_runners.cc b/mojo/shell/task_runners.cc deleted file mode 100644 index cb157ee0..0000000 --- a/mojo/shell/task_runners.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2013 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/shell/task_runners.h" - -#include "base/threading/sequenced_worker_pool.h" - -namespace mojo { -namespace shell { - -namespace { - -const size_t kMaxBlockingPoolThreads = 3; - -scoped_ptr<base::Thread> CreateIOThread(const char* name) { - scoped_ptr<base::Thread> thread(new base::Thread(name)); - base::Thread::Options options; - options.message_loop_type = base::MessageLoop::TYPE_IO; - thread->StartWithOptions(options); - return thread.Pass(); -} - -} // namespace - -TaskRunners::TaskRunners( - const scoped_refptr<base::SingleThreadTaskRunner>& shell_runner) - : shell_runner_(shell_runner), - io_thread_(CreateIOThread("io_thread")), - blocking_pool_(new base::SequencedWorkerPool(kMaxBlockingPoolThreads, - "blocking_pool")) { -} - -TaskRunners::~TaskRunners() { - blocking_pool_->Shutdown(); -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/task_runners.h b/mojo/shell/task_runners.h deleted file mode 100644 index 891d3e1b..0000000 --- a/mojo/shell/task_runners.h +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2013 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 SHELL_TASK_RUNNERS_H_ -#define SHELL_TASK_RUNNERS_H_ - -#include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/threading/thread.h" - -namespace base { -class SequencedWorkerPool; -} - -namespace mojo { -namespace shell { - -// A context object that contains the common task runners for the shell's main -// process. -class TaskRunners { - public: - explicit TaskRunners( - const scoped_refptr<base::SingleThreadTaskRunner>& shell_runner); - ~TaskRunners(); - - base::SingleThreadTaskRunner* shell_runner() const { - return shell_runner_.get(); - } - - base::SingleThreadTaskRunner* io_runner() const { - return io_thread_->message_loop_proxy().get(); - } - - base::SequencedWorkerPool* blocking_pool() const { - return blocking_pool_.get(); - } - - private: - scoped_refptr<base::SingleThreadTaskRunner> shell_runner_; - scoped_ptr<base::Thread> io_thread_; - - scoped_refptr<base::SequencedWorkerPool> blocking_pool_; - - DISALLOW_COPY_AND_ASSIGN(TaskRunners); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_TASK_RUNNERS_H_
diff --git a/mojo/shell/application_manager/test.mojom b/mojo/shell/test.mojom similarity index 100% rename from mojo/shell/application_manager/test.mojom rename to mojo/shell/test.mojom
diff --git a/mojo/shell/test/pingable_app.cc b/mojo/shell/test/pingable_app.cc deleted file mode 100644 index 1849f71..0000000 --- a/mojo/shell/test/pingable_app.cc +++ /dev/null
@@ -1,69 +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 "mojo/public/c/system/main.h" -#include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/application/application_runner.h" -#include "mojo/public/cpp/application/interface_factory.h" -#include "mojo/public/cpp/bindings/callback.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "mojo/shell/test/pingable.mojom.h" - -namespace mojo { - -class PingableImpl : public Pingable { - public: - PingableImpl(InterfaceRequest<Pingable> request, - const std::string& app_url, - const std::string& connection_url) - : binding_(this, request.Pass()), - app_url_(app_url), - connection_url_(connection_url) {} - - ~PingableImpl() override {} - - private: - void Ping(const String& message, - const Callback<void(String, String, String)>& callback) override { - callback.Run(app_url_, connection_url_, message); - } - - StrongBinding<Pingable> binding_; - std::string app_url_; - std::string connection_url_; -}; - -class PingableApp : public mojo::ApplicationDelegate, - public mojo::InterfaceFactory<Pingable> { - public: - PingableApp() {} - ~PingableApp() override {} - - private: - // ApplicationDelegate: - void Initialize(ApplicationImpl* impl) override { app_url_ = impl->url(); } - - bool ConfigureIncomingConnection( - mojo::ApplicationConnection* connection) override { - connection->AddService(this); - return true; - } - - // InterfaceFactory<Pingable>: - void Create(mojo::ApplicationConnection* connection, - mojo::InterfaceRequest<Pingable> request) override { - new PingableImpl(request.Pass(), app_url_, connection->GetConnectionURL()); - } - - std::string app_url_; -}; - -} // namespace mojo - -MojoResult MojoMain(MojoHandle shell_handle) { - mojo::ApplicationRunner runner(new mojo::PingableApp); - return runner.Run(shell_handle); -}
diff --git a/mojo/shell/url_resolver.cc b/mojo/shell/url_resolver.cc deleted file mode 100644 index 20cb0008..0000000 --- a/mojo/shell/url_resolver.cc +++ /dev/null
@@ -1,118 +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 "mojo/shell/url_resolver.h" - -#include "base/base_paths.h" -#include "base/files/file_path.h" -#include "base/logging.h" -#include "base/strings/utf_string_conversions.h" -#include "mojo/shell/application_manager/query_util.h" -#include "mojo/shell/filename_util.h" -#include "mojo/shell/switches.h" -#include "url/url_util.h" - -namespace mojo { -namespace shell { - -URLResolver::URLResolver() { - // Needed to treat first component of mojo URLs as host, not path. - url::AddStandardScheme("mojo"); -} - -URLResolver::~URLResolver() { -} - -// static -std::vector<URLResolver::OriginMapping> URLResolver::GetOriginMappings( - const base::CommandLine::StringVector& args) { - std::vector<OriginMapping> origin_mappings; - const std::string kArgsForSwitches[] = { - "-" + std::string(switches::kMapOrigin) + "=", - "--" + std::string(switches::kMapOrigin) + "=", - }; - for (auto& arg : args) { - for (size_t i = 0; i < arraysize(kArgsForSwitches); i++) { - const std::string& argsfor_switch = kArgsForSwitches[i]; - std::string arg_string; -#if defined(OS_WIN) - arg_string = base::UTF16ToUTF8(arg); -#else - arg_string = arg; -#endif - if (arg_string.compare(0, argsfor_switch.size(), argsfor_switch) == 0) { - std::string value = - arg_string.substr(argsfor_switch.size(), std::string::npos); - size_t delim = value.find('='); - if (delim <= 0 || delim >= value.size()) - continue; - origin_mappings.push_back( - OriginMapping(value.substr(0, delim), - value.substr(delim + 1, std::string::npos))); - } - } - } - return origin_mappings; -} - -void URLResolver::AddURLMapping(const GURL& url, const GURL& mapped_url) { - url_map_[url] = mapped_url; -} - -void URLResolver::AddOriginMapping(const GURL& origin, const GURL& base_url) { - if (!origin.is_valid() || !base_url.is_valid() || - origin != origin.GetOrigin()) { - // Disallow invalid mappings. - LOG(ERROR) << "Invalid origin for mapping: " << origin; - return; - } - // Force both origin and base_url to have trailing slashes. - origin_map_[origin] = AddTrailingSlashIfNeeded(base_url); -} - -GURL URLResolver::ApplyMappings(const GURL& url) const { - std::string query; - GURL mapped_url = GetBaseURLAndQuery(url, &query); - for (;;) { - const auto& url_it = url_map_.find(mapped_url); - if (url_it != url_map_.end()) { - mapped_url = url_it->second; - continue; - } - - GURL origin = mapped_url.GetOrigin(); - const auto& origin_it = origin_map_.find(origin); - if (origin_it == origin_map_.end()) - break; - mapped_url = GURL(origin_it->second.spec() + - mapped_url.spec().substr(origin.spec().length())); - } - - if (query.length()) - mapped_url = GURL(mapped_url.spec() + query); - return mapped_url; -} - -void URLResolver::SetMojoBaseURL(const GURL& mojo_base_url) { - DCHECK(mojo_base_url.is_valid()); - // Force a trailing slash on the base_url to simplify resolving - // relative files and URLs below. - mojo_base_url_ = AddTrailingSlashIfNeeded(mojo_base_url); -} - -GURL URLResolver::ResolveMojoURL(const GURL& mojo_url) const { - if (mojo_url.scheme() != "mojo") { - // The mapping has produced some sort of non-mojo: URL - file:, http:, etc. - return mojo_url; - } else { - // It's still a mojo: URL, use the default mapping scheme. - std::string query; - GURL base_url = GetBaseURLAndQuery(mojo_url, &query); - std::string lib = base_url.host() + ".mojo" + query; - return mojo_base_url_.Resolve(lib); - } -} - -} // namespace shell -} // namespace mojo
diff --git a/mojo/shell/url_resolver.h b/mojo/shell/url_resolver.h deleted file mode 100644 index 03f9076..0000000 --- a/mojo/shell/url_resolver.h +++ /dev/null
@@ -1,79 +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 SHELL_URL_RESOLVER_H_ -#define SHELL_URL_RESOLVER_H_ - -#include <map> -#include <set> - -#include "base/basictypes.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "url/gurl.h" - -namespace mojo { -namespace shell { - -// This class supports the mapping of URLs to other URLs. -// It's commonly used with mojo: URL, to provide a physical location (i.e. -// file: or https:) but works with any URL. -// By default, "mojo:" URLs resolve to a file location, with ".mojo" appended, -// but that resolution can be customized via the AddCustomMapping method. -class URLResolver { - public: - URLResolver(); - ~URLResolver(); - - // Used for the return value of GetOriginMappings(). - struct OriginMapping { - OriginMapping(const std::string& origin, const std::string& base_url) - : origin(origin), base_url(base_url) {} - - std::string origin; - std::string base_url; - }; - - // Returns a list of origin mappings based on command line args. - // The switch --map-origin can be specified multiple times. Each occurance - // has the format of --map-origin={origin}={base_url} - // For example: - // --map-origin=http://domokit.org=file:///source/out - static std::vector<OriginMapping> GetOriginMappings( - const base::CommandLine::StringVector& argv); - - // Add a custom mapping for a particular URL. If |mapped_url| is - // itself a mojo url normal resolution rules apply. - void AddURLMapping(const GURL& url, const GURL& mapped_url); - - // Add a custom mapping for all urls rooted at |origin|. - void AddOriginMapping(const GURL& origin, const GURL& base_url); - - // Applies all custom mappings for |url|, returning the last non-mapped url. - // For example, if 'a' maps to 'b' and 'b' maps to 'c' calling this with 'a' - // returns 'c'. - GURL ApplyMappings(const GURL& url) const; - - // If specified, then "mojo:" URLs will be resolved relative to this - // URL. That is, the portion after the colon will be appeneded to - // |mojo_base_url| with .mojo appended. - void SetMojoBaseURL(const GURL& mojo_base_url); - - // Resolve the given "mojo:" URL to the URL that should be used to fetch the - // code for the corresponding Mojo App. - GURL ResolveMojoURL(const GURL& mojo_url) const; - - private: - using GURLToGURLMap = std::map<GURL, GURL>; - GURLToGURLMap url_map_; - GURLToGURLMap origin_map_; - GURL mojo_base_url_; - - DISALLOW_COPY_AND_ASSIGN(URLResolver); -}; - -} // namespace shell -} // namespace mojo - -#endif // SHELL_URL_RESOLVER_H_
diff --git a/mojo/shell/url_resolver_unittest.cc b/mojo/shell/url_resolver_unittest.cc deleted file mode 100644 index dd8da75..0000000 --- a/mojo/shell/url_resolver_unittest.cc +++ /dev/null
@@ -1,150 +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 "mojo/shell/url_resolver.h" - -#include "base/logging.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { -namespace shell { -namespace test { -namespace { - -typedef testing::Test URLResolverTest; - -TEST_F(URLResolverTest, MojoURLsFallThrough) { - URLResolver resolver; - resolver.AddURLMapping(GURL("mojo:test"), GURL("mojo:foo")); - const GURL base_url("file:/base"); - resolver.SetMojoBaseURL(base_url); - GURL mapped_url = resolver.ApplyMappings(GURL("mojo:test")); - std::string resolved(resolver.ResolveMojoURL(mapped_url).spec()); - // Resolved must start with |base_url|. - EXPECT_EQ(base_url.spec(), resolved.substr(0, base_url.spec().size())); - // And must contain foo. - EXPECT_NE(std::string::npos, resolved.find("foo")); -} - -TEST_F(URLResolverTest, MapURL) { - URLResolver resolver; - resolver.AddURLMapping(GURL("https://domokit.org/test.mojo"), - GURL("file:///mojo/src/out/Debug/test.mojo")); - GURL mapped_url = - resolver.ApplyMappings(GURL("https://domokit.org/test.mojo")); - EXPECT_EQ("file:///mojo/src/out/Debug/test.mojo", mapped_url.spec()); -} - -TEST_F(URLResolverTest, MultipleMapURL) { - URLResolver resolver; - resolver.AddURLMapping(GURL("https://a.org/foo"), - GURL("https://b.org/a/foo")); - resolver.AddURLMapping(GURL("https://b.org/a/foo"), - GURL("https://c.org/b/a/foo")); - GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo")); - EXPECT_EQ("https://c.org/b/a/foo", mapped_url.spec()); -} - -TEST_F(URLResolverTest, MapOrigin) { - URLResolver resolver; - resolver.AddOriginMapping(GURL("https://domokit.org"), - GURL("file:///mojo/src/out/Debug")); - GURL mapped_url = - resolver.ApplyMappings(GURL("https://domokit.org/test.mojo")); - EXPECT_EQ("file:///mojo/src/out/Debug/test.mojo", mapped_url.spec()); -} - -TEST_F(URLResolverTest, MultipleMapOrigin) { - URLResolver resolver; - resolver.AddOriginMapping(GURL("https://a.org"), GURL("https://b.org/a")); - resolver.AddOriginMapping(GURL("https://b.org"), GURL("https://c.org/b")); - GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo")); - EXPECT_EQ("https://c.org/b/a/foo", mapped_url.spec()); -} - -TEST_F(URLResolverTest, MapOriginThenURL) { - URLResolver resolver; - resolver.AddOriginMapping(GURL("https://a.org"), GURL("https://b.org/a")); - resolver.AddURLMapping(GURL("https://b.org/a/foo"), - GURL("https://c.org/b/a/foo")); - GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo")); - EXPECT_EQ("https://c.org/b/a/foo", mapped_url.spec()); -} - -TEST_F(URLResolverTest, MapURLThenOrigin) { - URLResolver resolver; - resolver.AddURLMapping(GURL("https://a.org/foo"), - GURL("https://b.org/a/foo")); - resolver.AddOriginMapping(GURL("https://b.org"), GURL("https://c.org/b")); - GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo")); - EXPECT_EQ("https://c.org/b/a/foo", mapped_url.spec()); -} - -#if defined(OS_POSIX) -#define ARG_LITERAL(x) x -#elif defined(OS_WIN) -#define ARG_LITERAL(x) L ## x -#endif - -TEST_F(URLResolverTest, GetOriginMappings) { - base::CommandLine::StringVector args; - args.push_back(ARG_LITERAL("--map-origin=https://a.org=https://b.org/a")); - std::vector<URLResolver::OriginMapping> mappings = - URLResolver::GetOriginMappings(args); - ASSERT_EQ(1U, mappings.size()); - EXPECT_EQ("https://a.org", mappings[0].origin); - EXPECT_EQ("https://b.org/a", mappings[0].base_url); - - args.clear(); - args.push_back(ARG_LITERAL("-map-origin=https://a.org=https://b.org/a")); - mappings = URLResolver::GetOriginMappings(args); - ASSERT_EQ(1U, mappings.size()); - EXPECT_EQ("https://a.org", mappings[0].origin); - EXPECT_EQ("https://b.org/a", mappings[0].base_url); - - args.clear(); - args.push_back(ARG_LITERAL("--map-origin")); - mappings = URLResolver::GetOriginMappings(args); - EXPECT_EQ(0U, mappings.size()); - - args.clear(); - args.push_back(ARG_LITERAL("--map-origin=")); - mappings = URLResolver::GetOriginMappings(args); - EXPECT_EQ(0U, mappings.size()); - - args.clear(); - args.push_back(ARG_LITERAL("mojo_shell")); - args.push_back(ARG_LITERAL("--map-origin=https://a.org=https://b.org/a")); - args.push_back(ARG_LITERAL("--map-origin=https://b.org=https://c.org/b")); - args.push_back(ARG_LITERAL("https://a.org/foo")); - mappings = URLResolver::GetOriginMappings(args); - ASSERT_EQ(2U, mappings.size()); - EXPECT_EQ("https://a.org", mappings[0].origin); - EXPECT_EQ("https://b.org/a", mappings[0].base_url); - EXPECT_EQ("https://b.org", mappings[1].origin); - EXPECT_EQ("https://c.org/b", mappings[1].base_url); -} - -TEST_F(URLResolverTest, TestQueryForURLMapping) { - URLResolver resolver; - resolver.SetMojoBaseURL(GURL("file:/base")); - resolver.AddURLMapping(GURL("https://a.org/foo"), - GURL("https://b.org/a/foo")); - resolver.AddURLMapping(GURL("https://b.org/a/foo"), - GURL("https://c.org/b/a/foo")); - GURL mapped_url = resolver.ApplyMappings(GURL("https://a.org/foo?a=b")); - EXPECT_EQ("https://c.org/b/a/foo?a=b", mapped_url.spec()); -} - -TEST_F(URLResolverTest, TestQueryForBaseURL) { - URLResolver resolver; - resolver.SetMojoBaseURL(GURL("file:///base")); - GURL mapped_url = resolver.ResolveMojoURL(GURL("mojo:foo?a=b")); - EXPECT_EQ("file:///base/foo.mojo?a=b", mapped_url.spec()); -} - -} // namespace -} // namespace test -} // namespace shell -} // namespace mojo
diff --git a/mojo/tools/android_mojo_shell.py b/mojo/tools/android_mojo_shell.py index e269228..ca86672 100755 --- a/mojo/tools/android_mojo_shell.py +++ b/mojo/tools/android_mojo_shell.py
@@ -7,13 +7,16 @@ import logging import sys +from mopy.android import AndroidShell from mopy.config import Config -from mopy import android +from mopy.paths import Paths + +USAGE = ("android_mojo_shell.py [<shell-and-app-args>] [<mojo-app>]") def main(): logging.basicConfig() - parser = argparse.ArgumentParser("Helper for running mojo_shell") + parser = argparse.ArgumentParser(usage=USAGE) debug_group = parser.add_mutually_exclusive_group() debug_group.add_argument('--debug', help='Debug build (default)', @@ -23,18 +26,22 @@ parser.add_argument('--target-cpu', help='CPU architecture to run for.', choices=['x64', 'x86', 'arm']) parser.add_argument('--origin', help='Origin for mojo: URLs.') + parser.add_argument('--target-device', help='Device to run on.') launcher_args, args = parser.parse_known_args() config = Config(target_os=Config.OS_ANDROID, target_cpu=launcher_args.target_cpu, is_debug=launcher_args.debug) + paths = Paths(config) + shell = AndroidShell(paths.target_mojo_shell_path, paths.build_dir, + paths.adb_path, launcher_args.target_device) - extra_shell_args = android.PrepareShellRun(config, launcher_args.origin) + extra_shell_args = shell.PrepareShellRun(launcher_args.origin) args.extend(extra_shell_args) - android.CleanLogs() - p = android.ShowLogs() - android.StartShell(args, sys.stdout, p.terminate) + shell.CleanLogs() + p = shell.ShowLogs() + shell.StartShell(args, sys.stdout, p.terminate) return 0
diff --git a/mojo/tools/data/apptests b/mojo/tools/data/apptests index 7f336c6..a35da32 100644 --- a/mojo/tools/data/apptests +++ b/mojo/tools/data/apptests
@@ -44,8 +44,8 @@ "type": "gtest_isolated", "shell-args": ["--url-mappings=mojo:window_manager=mojo:test_window_manager"] }, - # TODO(msw): Fix and enable window_manager_apptests: http://crbug.com/480040 - #{ - # "test": "mojo:window_manager_apptests", - #}, + { + "test": "mojo:window_manager_apptests", + "shell-args": ["--use-headless-config"] + }, ]
diff --git a/mojo/tools/mopy/paths.py b/mojo/tools/mopy/paths.py index 60181e89..19d9ec1 100644 --- a/mojo/tools/mopy/paths.py +++ b/mojo/tools/mopy/paths.py
@@ -27,7 +27,7 @@ self.build_dir = None if self.build_dir is not None: - self.mojo_shell_path = os.path.join(self.build_dir, "mojo_shell") + self.mojo_shell_path = os.path.join(self.build_dir, "mojo_runner") # TODO(vtl): Use the host OS here, since |config| may not be available. # In any case, if the target is Windows, but the host isn't, using # |os.path| isn't correct....
diff --git a/mojo/tools/rev_sdk.py b/mojo/tools/rev_sdk.py index c7508683..c5cefbc 100755 --- a/mojo/tools/rev_sdk.py +++ b/mojo/tools/rev_sdk.py
@@ -10,7 +10,7 @@ import os import sys from utils import commit -from utils import mojo_root_dir +from utils import chromium_root_dir from utils import system sdk_prefix_in_chromium = "third_party/mojo/src" @@ -20,9 +20,15 @@ "nacl_bindings", ] - -services_prefix_in_mojo = "mojo/services" -services_prefix_in_chromium = "third_party/mojo_services/src" +# Individual files to preserve within the target repository during roll. These +# are relative to |sdk_prefix_in_chromium| but are not maintained in the mojo +# repository. +preserved_chromium_files = [ + "mojo/edk/DEPS", + "mojo/public/DEPS", + "mojo/public/platform/nacl/DEPS", + "nacl_bindings/DEPS", +] # A dictionary mapping dirs to clone to their destination locations in Chromium. dirs_to_clone = {} @@ -60,10 +66,17 @@ with open(version_filename, "w") as version_file: version_file.write(src_commit) system(["git", "add", version_filename], cwd=chromium_dir) + + # Reset preserved files that were blown away. + for rel_path in preserved_chromium_files: + preserved_path = os.path.join(sdk_prefix_in_chromium, rel_path) + system(["git", "reset", "--", preserved_path]) + system(["git", "checkout", preserved_path]) + commit("Update mojo sdk to rev " + src_commit, cwd=chromium_dir) if len(sys.argv) != 2: - print "usage: rev_sdk.py <chromium source dir>" + print "usage: rev_sdk.py <mojo source dir>" sys.exit(1) -rev(mojo_root_dir, sys.argv[1]) +rev(sys.argv[1], chromium_root_dir)
diff --git a/mojo/tools/utils.py b/mojo/tools/utils.py new file mode 100755 index 0000000..740b363 --- /dev/null +++ b/mojo/tools/utils.py
@@ -0,0 +1,32 @@ +#!/usr/bin/env python +# 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. + +import fnmatch +import os +import subprocess + +chromium_root_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), + os.pardir, os.pardir) + +def commit(message, cwd=None): + subprocess.call(['git', 'commit', '-a', '-m', message], cwd=cwd) + +def system(command, cwd=None): + return subprocess.check_output(command, cwd=cwd) + +def find(patterns, start='.'): + for path, dirs, files in os.walk(start): + for basename in files + dirs: + if any([fnmatch.fnmatch(basename, pattern) for pattern in patterns]): + filename = os.path.join(path, basename) + yield filename + +def filter_file(path, predicate): + with open(path, 'r+') as f: + lines = f.readlines() + new_lines = [line for line in lines if predicate(line)] + f.seek(0) + f.truncate() + f.write(''.join(new_lines))
diff --git a/native_client_sdk/src/examples/demo/nacl_io_demo/example.js b/native_client_sdk/src/examples/demo/nacl_io_demo/example.js index 128bcd037..7cb83c1 100644 --- a/native_client_sdk/src/examples/demo/nacl_io_demo/example.js +++ b/native_client_sdk/src/examples/demo/nacl_io_demo/example.js
@@ -12,7 +12,7 @@ // Called by the common.js module. function domContentLoaded(name, tc, config, width, height) { - navigator.webkitPersistentStorage.requestQuota(1024 * 1024, + navigator.webkitPersistentStorage.requestQuota(5 * 1024 * 1024, function(bytes) { common.updateStatus( 'Allocated ' + bytes + ' bytes of persistant storage.');
diff --git a/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.cc b/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.cc index bb6b9cc8..b71de27 100644 --- a/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.cc +++ b/native_client_sdk/src/libraries/nacl_io/html5fs/html5_fs.cc
@@ -45,9 +45,8 @@ // Apply a running DJB2a to each part of the path for (size_t segment = 0; segment < path.Size(); segment++) { - const char *ptr = path.Part(segment).c_str(); - size_t len = path.Part(segment).length(); - hash = HashPathSegment(hash, ptr, len); + const std::string& part = path.Part(segment); + hash = HashPathSegment(hash, part.c_str(), part.length()); } return hash; }
diff --git a/net/BUILD.gn b/net/BUILD.gn index 130a597..44347b1 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -84,13 +84,13 @@ include_dirs = [] public_deps = [ + ":net_quic_proto", "//crypto", "//crypto:platform", "//url", ] deps = [ ":net_resources", - ":net_quic_proto", "//base", "//base:prefs", "//base/third_party/dynamic_annotations", @@ -510,6 +510,8 @@ } proto_library("net_quic_proto") { + visibility = [ "//net" ] # Part of the net component. + sources = [ "quic/proto/cached_network_parameters.proto", "quic/proto/source_address_token.proto", @@ -1148,7 +1150,6 @@ ":balsa", ":epoll_server", ":net", - ":net_quic_proto", "//base", "//base/third_party/dynamic_annotations", "//crypto", @@ -1181,7 +1182,6 @@ ":epoll_server", ":epoll_quic_tools", ":net", - ":net_quic_proto", ":simple_quic_tools", "//base", "//third_party/boringssl", @@ -1255,7 +1255,6 @@ ] deps = [ ":net", - ":net_quic_proto", "//base", "//base/third_party/dynamic_annotations", "//url", @@ -1280,10 +1279,10 @@ ] deps = [ ":net", - ":net_quic_proto", ":simple_quic_tools", "//base", "//third_party/boringssl", + "//third_party/protobuf:protobuf_lite", ] } @@ -1302,7 +1301,6 @@ ":extras", ":http_server", ":net", - ":net_quic_proto", ":simple_quic_tools", ":test_support", "//base",
diff --git a/net/android/net_jni_registrar.cc b/net/android/net_jni_registrar.cc index bdebf0e..586f018 100644 --- a/net/android/net_jni_registrar.cc +++ b/net/android/net_jni_registrar.cc
@@ -23,17 +23,16 @@ namespace android { static base::android::RegistrationMethod kNetRegisteredMethods[] = { - { "AndroidCertVerifyResult", net::android::RegisterCertVerifyResult }, - { "AndroidPrivateKey", net::android::RegisterAndroidPrivateKey}, - { "AndroidKeyStore", net::android::RegisterKeyStore }, - { "AndroidNetworkLibrary", net::android::RegisterNetworkLibrary }, - { "GURLUtils", net::RegisterGURLUtils }, - { "NetworkChangeNotifierAndroid", - net::NetworkChangeNotifierAndroid::Register }, - { "ProxyConfigService", net::ProxyConfigServiceAndroid::Register }, - { "X509Util", net::RegisterX509Util }, + {"AndroidCertVerifyResult", RegisterCertVerifyResult}, + {"AndroidPrivateKey", RegisterAndroidPrivateKey}, + {"AndroidKeyStore", RegisterKeyStore}, + {"AndroidNetworkLibrary", RegisterNetworkLibrary}, + {"GURLUtils", RegisterGURLUtils}, + {"NetworkChangeNotifierAndroid", NetworkChangeNotifierAndroid::Register}, + {"ProxyConfigService", ProxyConfigServiceAndroid::Register}, + {"X509Util", RegisterX509Util}, #if defined(USE_ICU_ALTERNATIVES_ON_ANDROID) - { "NetStringUtils", net::RegisterNetStringUtils } + {"NetStringUtils", RegisterNetStringUtils} #endif };
diff --git a/net/android/network_library.h b/net/android/network_library.h index 4a4ddca..f18ee19 100644 --- a/net/android/network_library.h +++ b/net/android/network_library.h
@@ -51,7 +51,7 @@ // Helper used to pass the DER-encoded bytes of an X.509 certificate or // a PKCS#12 archive holding a private key to the CertInstaller activity. -NET_EXPORT void StoreCertificate(net::CertificateMimeType cert_type, +NET_EXPORT void StoreCertificate(CertificateMimeType cert_type, const void* data, size_t data_len);
diff --git a/net/base/backoff_entry_unittest.cc b/net/base/backoff_entry_unittest.cc index cca7c458..29a4281 100644 --- a/net/base/backoff_entry_unittest.cc +++ b/net/base/backoff_entry_unittest.cc
@@ -8,11 +8,12 @@ #include "base/time/tick_clock.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + namespace { using base::TimeDelta; using base::TimeTicks; -using net::BackoffEntry; BackoffEntry::Policy base_policy = { 0, 1000, 2.0, 0.0, 20000, 2000, false }; @@ -311,3 +312,5 @@ } } // namespace + +} // namespace net
diff --git a/net/base/data_url.cc b/net/base/data_url.cc index 58036c6..b03d9976 100644 --- a/net/base/data_url.cc +++ b/net/base/data_url.cc
@@ -60,7 +60,7 @@ charset->assign(iter->substr(kCharsetTagLength)); // The grammar for charset is not specially defined in RFC2045 and // RFC2397. It just needs to be a token. - if (!net::HttpUtil::IsToken(*charset)) + if (!HttpUtil::IsToken(*charset)) return false; } }
diff --git a/net/base/data_url_unittest.cc b/net/base/data_url_unittest.cc index bcb2b49a..fb7dc76 100644 --- a/net/base/data_url_unittest.cc +++ b/net/base/data_url_unittest.cc
@@ -7,6 +7,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +namespace net { + namespace { struct ParseTestData { @@ -17,7 +19,7 @@ const char* data; }; -} +} // namespace TEST(DataURLTest, Parse) { const ParseTestData tests[] = { @@ -229,8 +231,7 @@ std::string mime_type; std::string charset; std::string data; - bool ok = - net::DataURL::Parse(GURL(tests[i].url), &mime_type, &charset, &data); + bool ok = DataURL::Parse(GURL(tests[i].url), &mime_type, &charset, &data); EXPECT_EQ(ok, tests[i].is_valid); if (tests[i].is_valid) { EXPECT_EQ(tests[i].mime_type, mime_type); @@ -239,3 +240,5 @@ } } } + +} // namespace net
diff --git a/net/base/directory_lister.cc b/net/base/directory_lister.cc index f746f9b..43827b2 100644 --- a/net/base/directory_lister.cc +++ b/net/base/directory_lister.cc
@@ -45,42 +45,15 @@ b.info.GetName()); } -bool CompareDate(const DirectoryLister::DirectoryListerData& a, - const DirectoryLister::DirectoryListerData& b) { - // Parent directory before all else. - if (IsDotDot(a.info.GetName())) - return true; - if (IsDotDot(b.info.GetName())) - return false; - - // Directories before regular files. - bool a_is_directory = a.info.IsDirectory(); - bool b_is_directory = b.info.IsDirectory(); - if (a_is_directory != b_is_directory) - return a_is_directory; - return a.info.GetLastModifiedTime() > b.info.GetLastModifiedTime(); -} - -// Comparator for sorting find result by paths. This uses the locale-aware -// comparison function on the filenames for sorting in the user's locale. -// Static. -bool CompareFullPath(const DirectoryLister::DirectoryListerData& a, - const DirectoryLister::DirectoryListerData& b) { - return base::i18n::LocaleAwareCompareFilenames(a.path, b.path); -} - void SortData(std::vector<DirectoryLister::DirectoryListerData>* data, - DirectoryLister::SortType sort_type) { + DirectoryLister::ListingType listing_type) { // Sort the results. See the TODO below (this sort should be removed and we // should do it from JS). - if (sort_type == DirectoryLister::DATE) { - std::sort(data->begin(), data->end(), CompareDate); - } else if (sort_type == DirectoryLister::FULL_PATH) { - std::sort(data->begin(), data->end(), CompareFullPath); - } else if (sort_type == DirectoryLister::ALPHA_DIRS_FIRST) { + if (listing_type == DirectoryLister::ALPHA_DIRS_FIRST) { std::sort(data->begin(), data->end(), CompareAlphaDirsFirst); - } else { - DCHECK_EQ(DirectoryLister::NO_SORT, sort_type); + } else if (listing_type != DirectoryLister::NO_SORT && + listing_type != DirectoryLister::NO_SORT_RECURSIVE) { + NOTREACHED(); } } @@ -89,17 +62,16 @@ DirectoryLister::DirectoryLister(const base::FilePath& dir, DirectoryListerDelegate* delegate) : delegate_(delegate) { - core_ = new Core(dir, false, ALPHA_DIRS_FIRST, this); + core_ = new Core(dir, ALPHA_DIRS_FIRST, this); DCHECK(delegate_); DCHECK(!dir.value().empty()); } DirectoryLister::DirectoryLister(const base::FilePath& dir, - bool recursive, - SortType sort, + ListingType type, DirectoryListerDelegate* delegate) : delegate_(delegate) { - core_ = new Core(dir, recursive, sort, this); + core_ = new Core(dir, type, this); DCHECK(delegate_); DCHECK(!dir.value().empty()); } @@ -120,12 +92,10 @@ } DirectoryLister::Core::Core(const base::FilePath& dir, - bool recursive, - SortType sort, + ListingType type, DirectoryLister* lister) : dir_(dir), - recursive_(recursive), - sort_(sort), + type_(type), origin_loop_(base::MessageLoopProxy::current()), lister_(lister), cancelled_(0) { @@ -156,10 +126,14 @@ } int types = base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES; - if (!recursive_) + bool recursive; + if (NO_SORT_RECURSIVE != type_) { types |= base::FileEnumerator::INCLUDE_DOT_DOT; - - base::FileEnumerator file_enum(dir_, recursive_, types); + recursive = false; + } else { + recursive = true; + } + base::FileEnumerator file_enum(dir_, recursive, types); base::FilePath path; while (!(path = file_enum.Next()).empty()) { @@ -189,7 +163,7 @@ */ } - SortData(directory_list.get(), sort_); + SortData(directory_list.get(), type_); origin_loop_->PostTask( FROM_HERE,
diff --git a/net/base/directory_lister.h b/net/base/directory_lister.h index 51387e8..02f24dfb 100644 --- a/net/base/directory_lister.h +++ b/net/base/directory_lister.h
@@ -44,27 +44,22 @@ virtual ~DirectoryListerDelegate() {} }; - // Sort options - // ALPHA_DIRS_FIRST is the default sort : + // Listing options + // ALPHA_DIRS_FIRST is the default listing type: // directories first in name order, then files by name order - // FULL_PATH sorts by paths as strings, ignoring files v. directories - // DATE sorts by last modified date - // TODO(mmenke): Only NO_SORT and ALPHA_DIRS_FIRST appear to be used in - // production code, and there's very little testing of some of these - // options. Remove unused options, improve testing of the others. - enum SortType { + // Listing is recursive only if listing type is NO_SORT_RECURSIVE. + // TODO(mmenke): Improve testing. + enum ListingType { NO_SORT, - DATE, + NO_SORT_RECURSIVE, ALPHA_DIRS_FIRST, - FULL_PATH }; DirectoryLister(const base::FilePath& dir, DirectoryListerDelegate* delegate); DirectoryLister(const base::FilePath& dir, - bool recursive, - SortType sort, + ListingType type, DirectoryListerDelegate* delegate); // Will invoke Cancel(). @@ -89,10 +84,7 @@ // reference owned by the callback itself. class Core : public base::RefCountedThreadSafe<Core> { public: - Core(const base::FilePath& dir, - bool recursive, - SortType sort, - DirectoryLister* lister); + Core(const base::FilePath& dir, ListingType type, DirectoryLister* lister); // May only be called on a worker pool thread. void Start(); @@ -114,8 +106,7 @@ int error) const; const base::FilePath dir_; - const bool recursive_; - const SortType sort_; + const ListingType type_; const scoped_refptr<base::MessageLoopProxy> origin_loop_; // Only used on the origin thread.
diff --git a/net/base/directory_lister_unittest.cc b/net/base/directory_lister_unittest.cc index adc3d5e..46ca1e9 100644 --- a/net/base/directory_lister_unittest.cc +++ b/net/base/directory_lister_unittest.cc
@@ -29,14 +29,13 @@ class ListerDelegate : public DirectoryLister::DirectoryListerDelegate { public: - explicit ListerDelegate(bool recursive) + explicit ListerDelegate(DirectoryLister::ListingType type) : cancel_lister_on_list_file_(false), cancel_lister_on_list_done_(false), lister_(nullptr), done_(false), error_(-1), - recursive_(recursive) { - } + type_(type) {} // When set to true, this signals that the directory list operation should be // cancelled (And the run loop quit) in the first call to OnListFile. @@ -66,9 +65,7 @@ done_ = true; error_ = error; - if (recursive_) - CheckRecursiveSort(); - else + if (type_ == DirectoryLister::ALPHA_DIRS_FIRST) CheckSort(); if (cancel_lister_on_list_done_) @@ -76,18 +73,6 @@ run_loop.Quit(); } - void CheckRecursiveSort() { - // Check that we got files in the right order. - if (!file_list_.empty()) { - for (size_t previous = 0, current = 1; - current < file_list_.size(); - previous++, current++) { - EXPECT_TRUE(base::i18n::LocaleAwareCompareFilenames( - paths_[previous], paths_[current])); - } - } - } - void CheckSort() { // Check that we got files in the right order. if (!file_list_.empty()) { @@ -133,7 +118,7 @@ bool done_; int error_; - bool recursive_; + DirectoryLister::ListingType type_; std::vector<base::FileEnumerator::FileInfo> file_list_; std::vector<base::FilePath> paths_; @@ -208,7 +193,7 @@ }; TEST_F(DirectoryListerTest, BigDirTest) { - ListerDelegate delegate(false); + ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST); DirectoryLister lister(root_path(), &delegate); delegate.Run(&lister); @@ -218,9 +203,9 @@ } TEST_F(DirectoryListerTest, BigDirRecursiveTest) { - ListerDelegate delegate(true); - DirectoryLister lister( - root_path(), true, DirectoryLister::FULL_PATH, &delegate); + ListerDelegate delegate(DirectoryLister::NO_SORT_RECURSIVE); + DirectoryLister lister(root_path(), DirectoryLister::NO_SORT_RECURSIVE, + &delegate); delegate.Run(&lister); EXPECT_TRUE(delegate.done()); @@ -232,7 +217,7 @@ base::ScopedTempDir tempDir; EXPECT_TRUE(tempDir.CreateUniqueTempDir()); - ListerDelegate delegate(false); + ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST); DirectoryLister lister(tempDir.path(), &delegate); delegate.Run(&lister); @@ -248,7 +233,7 @@ // TODO(mmenke): See if there's a way to make this fail more reliably on // regression. TEST_F(DirectoryListerTest, BasicCancelTest) { - ListerDelegate delegate(false); + ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST); scoped_ptr<DirectoryLister> lister(new DirectoryLister( root_path(), &delegate)); lister->Start(); @@ -260,7 +245,7 @@ } TEST_F(DirectoryListerTest, CancelOnListFileTest) { - ListerDelegate delegate(false); + ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST); DirectoryLister lister(root_path(), &delegate); delegate.set_cancel_lister_on_list_file(true); delegate.Run(&lister); @@ -270,7 +255,7 @@ } TEST_F(DirectoryListerTest, CancelOnListDoneTest) { - ListerDelegate delegate(false); + ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST); DirectoryLister lister(root_path(), &delegate); delegate.set_cancel_lister_on_list_done(true); delegate.Run(&lister); @@ -284,7 +269,7 @@ base::ScopedTempDir tempDir; EXPECT_TRUE(tempDir.CreateUniqueTempDir()); - ListerDelegate delegate(false); + ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST); DirectoryLister lister(tempDir.path(), &delegate); delegate.set_cancel_lister_on_list_file(true); delegate.Run(&lister); @@ -298,7 +283,7 @@ base::ScopedTempDir tempDir; EXPECT_TRUE(tempDir.CreateUniqueTempDir()); - ListerDelegate delegate(false); + ListerDelegate delegate(DirectoryLister::ALPHA_DIRS_FIRST); DirectoryLister lister( tempDir.path().AppendASCII("this_path_does_not_exist"), &delegate); delegate.Run(&lister);
diff --git a/net/base/dns_reloader.cc b/net/base/dns_reloader.cc index e0e0b76..18041d9fc 100644 --- a/net/base/dns_reloader.cc +++ b/net/base/dns_reloader.cc
@@ -17,6 +17,8 @@ #include "base/threading/thread_local_storage.h" #include "net/base/network_change_notifier.h" +namespace net { + namespace { // On Linux/BSD, changes to /etc/resolv.conf can go unnoticed thus resulting @@ -39,7 +41,7 @@ // Android does not have /etc/resolv.conf. The system takes care of nameserver // changes, so none of this is needed. -class DnsReloader : public net::NetworkChangeNotifier::DNSObserver { +class DnsReloader : public NetworkChangeNotifier::DNSObserver { public: struct ReloadState { int resolver_generation; @@ -81,7 +83,7 @@ private: DnsReloader() : resolver_generation_(0) { tls_index_.Initialize(SlotReturnFunction); - net::NetworkChangeNotifier::AddDNSObserver(this); + NetworkChangeNotifier::AddDNSObserver(this); } ~DnsReloader() override { @@ -107,8 +109,6 @@ } // namespace -namespace net { - void EnsureDnsReloaderInit() { g_dns_reloader.Pointer(); }
diff --git a/net/base/escape_unittest.cc b/net/base/escape_unittest.cc index 4d3bcbdd..98afb8cf 100644 --- a/net/base/escape_unittest.cc +++ b/net/base/escape_unittest.cc
@@ -125,8 +125,8 @@ "%A9%20t'a-t-il%20%C3%B4t%C3%A9%20ta%20toux%20"; base::OffsetAdjuster::Adjustments adjustments; - net::UnescapeAndDecodeUTF8URLComponentWithAdjustments( - url, UnescapeRule::SPACES, &adjustments); + UnescapeAndDecodeUTF8URLComponentWithAdjustments(url, UnescapeRule::SPACES, + &adjustments); } TEST(EscapeTest, EscapeUrlEncodedData) {
diff --git a/net/base/file_stream_context.h b/net/base/file_stream_context.h index e8a66f0..74677fe8 100644 --- a/net/base/file_stream_context.h +++ b/net/base/file_stream_context.h
@@ -185,7 +185,7 @@ static void ReadAsync( FileStream::Context* context, HANDLE file, - scoped_refptr<net::IOBuffer> buf, + scoped_refptr<IOBuffer> buf, int buf_len, OVERLAPPED* overlapped, scoped_refptr<base::MessageLoopProxy> origin_thread_loop);
diff --git a/net/base/file_stream_context_win.cc b/net/base/file_stream_context_win.cc index a41a74c..1a39384 100644 --- a/net/base/file_stream_context_win.cc +++ b/net/base/file_stream_context_win.cc
@@ -210,7 +210,7 @@ void FileStream::Context::ReadAsync( FileStream::Context* context, HANDLE file, - scoped_refptr<net::IOBuffer> buf, + scoped_refptr<IOBuffer> buf, int buf_len, OVERLAPPED* overlapped, scoped_refptr<base::MessageLoopProxy> origin_thread_loop) {
diff --git a/net/base/filename_util_internal.cc b/net/base/filename_util_internal.cc index c77375b4..8d7509f3 100644 --- a/net/base/filename_util_internal.cc +++ b/net/base/filename_util_internal.cc
@@ -70,8 +70,8 @@ // encoding detection. base::string16 utf16_output; if (!referrer_charset.empty() && - net::ConvertToUTF16( - unescaped_url_filename, referrer_charset.c_str(), &utf16_output)) { + ConvertToUTF16(unescaped_url_filename, referrer_charset.c_str(), + &utf16_output)) { decoded_filename = base::UTF16ToUTF8(utf16_output); } else { decoded_filename = @@ -172,8 +172,8 @@ if ((ignore_extension || extension.empty()) && !mime_type.empty()) { base::FilePath::StringType preferred_mime_extension; std::vector<base::FilePath::StringType> all_mime_extensions; - net::GetPreferredExtensionForMimeType(mime_type, &preferred_mime_extension); - net::GetExtensionsForMimeType(mime_type, &all_mime_extensions); + GetPreferredExtensionForMimeType(mime_type, &preferred_mime_extension); + GetExtensionsForMimeType(mime_type, &all_mime_extensions); // If the existing extension is in the list of valid extensions for the // given type, use it. This avoids doing things like pointlessly renaming // "foo.jpg" to "foo.jpeg".
diff --git a/net/base/load_flags_list.h b/net/base/load_flags_list.h index 643e310..7876a8c 100644 --- a/net/base/load_flags_list.h +++ b/net/base/load_flags_list.h
@@ -32,69 +32,69 @@ // This is a navigation that will not use the cache at all. It does not // impact the HTTP request headers. -LOAD_FLAG(DISABLE_CACHE, 1 << 5) +LOAD_FLAG(DISABLE_CACHE, 1 << 4) // If present, causes certificate revocation checks to be skipped on secure // connections. -LOAD_FLAG(DISABLE_CERT_REVOCATION_CHECKING, 1 << 6) +LOAD_FLAG(DISABLE_CERT_REVOCATION_CHECKING, 1 << 5) // This load will not make any changes to cookies, including storing new // cookies or updating existing ones. -LOAD_FLAG(DO_NOT_SAVE_COOKIES, 1 << 7) +LOAD_FLAG(DO_NOT_SAVE_COOKIES, 1 << 6) // Do not resolve proxies. This override is used when downloading PAC files // to avoid having a circular dependency. -LOAD_FLAG(BYPASS_PROXY, 1 << 8) +LOAD_FLAG(BYPASS_PROXY, 1 << 7) // Requires EV certificate verification. -LOAD_FLAG(VERIFY_EV_CERT, 1 << 9) +LOAD_FLAG(VERIFY_EV_CERT, 1 << 8) // This load will not send any cookies. -LOAD_FLAG(DO_NOT_SEND_COOKIES, 1 << 10) +LOAD_FLAG(DO_NOT_SEND_COOKIES, 1 << 9) // This load will not send authentication data (user name/password) // to the server (as opposed to the proxy). -LOAD_FLAG(DO_NOT_SEND_AUTH_DATA, 1 << 11) +LOAD_FLAG(DO_NOT_SEND_AUTH_DATA, 1 << 10) // This should only be used for testing (set by HttpNetworkTransaction). -LOAD_FLAG(IGNORE_ALL_CERT_ERRORS, 1 << 12) +LOAD_FLAG(IGNORE_ALL_CERT_ERRORS, 1 << 11) // Indicate that this is a top level frame, so that we don't assume it is a // subresource and speculatively pre-connect or pre-resolve when a referring // page is loaded. -LOAD_FLAG(MAIN_FRAME, 1 << 13) +LOAD_FLAG(MAIN_FRAME, 1 << 12) // Indicate that this is a sub frame, and hence it might have subresources that // should be speculatively resolved, or even speculatively preconnected. -LOAD_FLAG(SUB_FRAME, 1 << 14) +LOAD_FLAG(SUB_FRAME, 1 << 13) // If present, intercept actual request/response headers from network stack // and report them to renderer. This includes cookies, so the flag is only // respected if renderer has CanReadRawCookies capability in the security // policy. -LOAD_FLAG(REPORT_RAW_HEADERS, 1 << 15) +LOAD_FLAG(REPORT_RAW_HEADERS, 1 << 14) // Indicates that this load was motivated by the rel=prefetch feature, // and is (in theory) not intended for the current frame. -LOAD_FLAG(PREFETCH, 1 << 16) +LOAD_FLAG(PREFETCH, 1 << 15) // Indicates that this is a load that ignores limits and should complete // immediately. -LOAD_FLAG(IGNORE_LIMITS, 1 << 17) +LOAD_FLAG(IGNORE_LIMITS, 1 << 16) // Indicates that the operation is somewhat likely to be due to an // explicit user action. This can be used as a hint to treat the // request with higher priority. -LOAD_FLAG(MAYBE_USER_GESTURE, 1 << 18) +LOAD_FLAG(MAYBE_USER_GESTURE, 1 << 17) // Indicates that the username:password portion of the URL should not // be honored, but that other forms of authority may be used. -LOAD_FLAG(DO_NOT_USE_EMBEDDED_IDENTITY, 1 << 19) +LOAD_FLAG(DO_NOT_USE_EMBEDDED_IDENTITY, 1 << 18) // Send request directly to the origin if the effective proxy is the data // reduction proxy. // TODO(rcs): Remove this flag as soon as http://crbug.com/339237 is resolved. -LOAD_FLAG(BYPASS_DATA_REDUCTION_PROXY, 1 << 20) +LOAD_FLAG(BYPASS_DATA_REDUCTION_PROXY, 1 << 19) // Indicates the the request is an asynchronous revalidation. -LOAD_FLAG(ASYNC_REVALIDATION, 1 << 21) +LOAD_FLAG(ASYNC_REVALIDATION, 1 << 20)
diff --git a/net/base/mac/url_conversions_unittest.mm b/net/base/mac/url_conversions_unittest.mm index a52062c..32e6210 100644 --- a/net/base/mac/url_conversions_unittest.mm +++ b/net/base/mac/url_conversions_unittest.mm
@@ -11,6 +11,8 @@ #include "testing/gtest_mac.h" #include "url/gurl.h" +namespace net { + namespace { class URLConversionTest : public ::testing::Test { @@ -211,7 +213,7 @@ for (NSUInteger i = 0; i < [testData_ count]; i += 2) { NSString* inputStr = [testData_ objectAtIndex:i]; NSString* expected = [testData_ objectAtIndex:(i + 1)]; - NSURL* url = net::NSURLWithGURL(GURL(base::SysNSStringToUTF8(inputStr))); + NSURL* url = NSURLWithGURL(GURL(base::SysNSStringToUTF8(inputStr))); EXPECT_NSEQ(expected, [url absoluteString]); } } @@ -219,11 +221,13 @@ TEST_F(URLConversionTest, TestURLWithStringDoesNotModifyAlreadyEscapedURLs) { for (NSUInteger i = 0; i < [testData_ count]; i += 2) { NSString* inputStr = [testData_ objectAtIndex:i + 1]; - NSURL* url = net::NSURLWithGURL(GURL(base::SysNSStringToUTF8(inputStr))); + NSURL* url = NSURLWithGURL(GURL(base::SysNSStringToUTF8(inputStr))); NSString* expected = [testData_ objectAtIndex:i + 1]; // Test the expected URL is created. EXPECT_NSEQ(expected, [url absoluteString]); } } -} // anonymous namespace +} // namespace + +} // namespace net
diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc index f1d4487..ab13005 100644 --- a/net/base/mime_util.cc +++ b/net/base/mime_util.cc
@@ -1378,8 +1378,8 @@ // except on Android. for (size_t i = 0; i < arraysize(supported_certificate_types); ++i) { if (base::strcasecmp(mime_type.c_str(), - net::supported_certificate_types[i].mime_type) == 0) { - return net::supported_certificate_types[i].cert_type; + supported_certificate_types[i].mime_type) == 0) { + return supported_certificate_types[i].cert_type; } } return CERTIFICATE_MIME_TYPE_UNKNOWN;
diff --git a/net/base/mock_file_stream.cc b/net/base/mock_file_stream.cc index a34edb218..792b23b 100644 --- a/net/base/mock_file_stream.cc +++ b/net/base/mock_file_stream.cc
@@ -13,8 +13,8 @@ MockFileStream::MockFileStream( const scoped_refptr<base::TaskRunner>& task_runner) - : net::FileStream(task_runner), - forced_error_(net::OK), + : FileStream(task_runner), + forced_error_(OK), async_error_(false), throttled_(false), weak_factory_(this) { @@ -23,8 +23,8 @@ MockFileStream::MockFileStream( base::File file, const scoped_refptr<base::TaskRunner>& task_runner) - : net::FileStream(file.Pass(), task_runner), - forced_error_(net::OK), + : FileStream(file.Pass(), task_runner), + forced_error_(OK), async_error_(false), throttled_(false), weak_factory_(this) { @@ -38,7 +38,7 @@ Int64CompletionCallback wrapped_callback = base::Bind(&MockFileStream::DoCallback64, weak_factory_.GetWeakPtr(), callback); - if (forced_error_ == net::OK) + if (forced_error_ == OK) return FileStream::Seek(whence, offset, wrapped_callback); return ErrorCallback64(wrapped_callback); } @@ -49,7 +49,7 @@ CompletionCallback wrapped_callback = base::Bind(&MockFileStream::DoCallback, weak_factory_.GetWeakPtr(), callback); - if (forced_error_ == net::OK) + if (forced_error_ == OK) return FileStream::Read(buf, buf_len, wrapped_callback); return ErrorCallback(wrapped_callback); } @@ -60,7 +60,7 @@ CompletionCallback wrapped_callback = base::Bind(&MockFileStream::DoCallback, weak_factory_.GetWeakPtr(), callback); - if (forced_error_ == net::OK) + if (forced_error_ == OK) return FileStream::Write(buf, buf_len, wrapped_callback); return ErrorCallback(wrapped_callback); } @@ -69,7 +69,7 @@ CompletionCallback wrapped_callback = base::Bind(&MockFileStream::DoCallback, weak_factory_.GetWeakPtr(), callback); - if (forced_error_ == net::OK) + if (forced_error_ == OK) return FileStream::Flush(wrapped_callback); return ErrorCallback(wrapped_callback); } @@ -111,12 +111,12 @@ } int MockFileStream::ErrorCallback(const CompletionCallback& callback) { - CHECK_NE(net::OK, forced_error_); + CHECK_NE(OK, forced_error_); if (async_error_) { base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(callback, forced_error_)); clear_forced_error(); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } int ret = forced_error_; clear_forced_error(); @@ -124,12 +124,12 @@ } int64 MockFileStream::ErrorCallback64(const Int64CompletionCallback& callback) { - CHECK_NE(net::OK, forced_error_); + CHECK_NE(OK, forced_error_); if (async_error_) { base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(callback, forced_error_)); clear_forced_error(); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } int64 ret = forced_error_; clear_forced_error();
diff --git a/net/base/mock_file_stream.h b/net/base/mock_file_stream.h index 7b7dea8..39ea1f3 100644 --- a/net/base/mock_file_stream.h +++ b/net/base/mock_file_stream.h
@@ -20,7 +20,7 @@ namespace testing { -class MockFileStream : public net::FileStream { +class MockFileStream : public FileStream { public: explicit MockFileStream(const scoped_refptr<base::TaskRunner>& task_runner); MockFileStream(base::File file, @@ -48,7 +48,7 @@ async_error_ = false; } void clear_forced_error() { - forced_error_ = net::OK; + forced_error_ = OK; async_error_ = false; } int forced_error() const { return forced_error_; } @@ -63,7 +63,7 @@ private: int ReturnError(int function_error) { - if (forced_error_ != net::OK) { + if (forced_error_ != OK) { int ret = forced_error_; clear_forced_error(); return ret; @@ -73,7 +73,7 @@ } int64 ReturnError64(int64 function_error) { - if (forced_error_ != net::OK) { + if (forced_error_ != OK) { int64 ret = forced_error_; clear_forced_error(); return ret;
diff --git a/net/base/net_errors.cc b/net/base/net_errors.cc index 55cdebb1..425cb91 100644 --- a/net/base/net_errors.cc +++ b/net/base/net_errors.cc
@@ -76,15 +76,15 @@ Error FileErrorToNetError(base::File::Error file_error) { switch (file_error) { case base::File::FILE_OK: - return net::OK; + return OK; case base::File::FILE_ERROR_ACCESS_DENIED: - return net::ERR_ACCESS_DENIED; + return ERR_ACCESS_DENIED; case base::File::FILE_ERROR_INVALID_URL: - return net::ERR_INVALID_URL; + return ERR_INVALID_URL; case base::File::FILE_ERROR_NOT_FOUND: - return net::ERR_FILE_NOT_FOUND; + return ERR_FILE_NOT_FOUND; default: - return net::ERR_FAILED; + return ERR_FAILED; } }
diff --git a/net/base/net_util_linux.cc b/net/base/net_util_linux.cc index 83425970..c8b2293 100644 --- a/net/base/net_util_linux.cc +++ b/net/base/net_util_linux.cc
@@ -220,7 +220,7 @@ std::string GetWifiSSID() { NetworkInterfaceList networks; - if (GetNetworkList(&networks, net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) { + if (GetNetworkList(&networks, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) { return internal::GetWifiSSIDFromInterfaceListInternal( networks, internal::GetInterfaceSSID); }
diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index 8e13bb8e..5f999af 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc
@@ -791,42 +791,42 @@ } TEST(NetUtilTest, IsLocalhost) { - EXPECT_TRUE(net::IsLocalhost("localhost")); - EXPECT_TRUE(net::IsLocalhost("localhost.localdomain")); - EXPECT_TRUE(net::IsLocalhost("localhost6")); - EXPECT_TRUE(net::IsLocalhost("localhost6.localdomain6")); - EXPECT_TRUE(net::IsLocalhost("127.0.0.1")); - EXPECT_TRUE(net::IsLocalhost("127.0.1.0")); - EXPECT_TRUE(net::IsLocalhost("127.1.0.0")); - EXPECT_TRUE(net::IsLocalhost("127.0.0.255")); - EXPECT_TRUE(net::IsLocalhost("127.0.255.0")); - EXPECT_TRUE(net::IsLocalhost("127.255.0.0")); - EXPECT_TRUE(net::IsLocalhost("::1")); - EXPECT_TRUE(net::IsLocalhost("0:0:0:0:0:0:0:1")); - EXPECT_TRUE(net::IsLocalhost("foo.localhost")); + EXPECT_TRUE(IsLocalhost("localhost")); + EXPECT_TRUE(IsLocalhost("localhost.localdomain")); + EXPECT_TRUE(IsLocalhost("localhost6")); + EXPECT_TRUE(IsLocalhost("localhost6.localdomain6")); + EXPECT_TRUE(IsLocalhost("127.0.0.1")); + EXPECT_TRUE(IsLocalhost("127.0.1.0")); + EXPECT_TRUE(IsLocalhost("127.1.0.0")); + EXPECT_TRUE(IsLocalhost("127.0.0.255")); + EXPECT_TRUE(IsLocalhost("127.0.255.0")); + EXPECT_TRUE(IsLocalhost("127.255.0.0")); + EXPECT_TRUE(IsLocalhost("::1")); + EXPECT_TRUE(IsLocalhost("0:0:0:0:0:0:0:1")); + EXPECT_TRUE(IsLocalhost("foo.localhost")); - EXPECT_FALSE(net::IsLocalhost("localhostx")); - EXPECT_FALSE(net::IsLocalhost("foo.localdomain")); - EXPECT_FALSE(net::IsLocalhost("localhost6x")); - EXPECT_FALSE(net::IsLocalhost("localhost.localdomain6")); - EXPECT_FALSE(net::IsLocalhost("localhost6.localdomain")); - EXPECT_FALSE(net::IsLocalhost("127.0.0.1.1")); - EXPECT_FALSE(net::IsLocalhost(".127.0.0.255")); - EXPECT_FALSE(net::IsLocalhost("::2")); - EXPECT_FALSE(net::IsLocalhost("::1:1")); - EXPECT_FALSE(net::IsLocalhost("0:0:0:0:1:0:0:1")); - EXPECT_FALSE(net::IsLocalhost("::1:1")); - EXPECT_FALSE(net::IsLocalhost("0:0:0:0:0:0:0:0:1")); - EXPECT_FALSE(net::IsLocalhost("foo.localhost.com")); - EXPECT_FALSE(net::IsLocalhost("foo.localhoste")); + EXPECT_FALSE(IsLocalhost("localhostx")); + EXPECT_FALSE(IsLocalhost("foo.localdomain")); + EXPECT_FALSE(IsLocalhost("localhost6x")); + EXPECT_FALSE(IsLocalhost("localhost.localdomain6")); + EXPECT_FALSE(IsLocalhost("localhost6.localdomain")); + EXPECT_FALSE(IsLocalhost("127.0.0.1.1")); + EXPECT_FALSE(IsLocalhost(".127.0.0.255")); + EXPECT_FALSE(IsLocalhost("::2")); + EXPECT_FALSE(IsLocalhost("::1:1")); + EXPECT_FALSE(IsLocalhost("0:0:0:0:1:0:0:1")); + EXPECT_FALSE(IsLocalhost("::1:1")); + EXPECT_FALSE(IsLocalhost("0:0:0:0:0:0:0:0:1")); + EXPECT_FALSE(IsLocalhost("foo.localhost.com")); + EXPECT_FALSE(IsLocalhost("foo.localhoste")); } TEST(NetUtilTest, IsLocalhostTLD) { - EXPECT_TRUE(net::IsLocalhostTLD("foo.localhost")); - EXPECT_TRUE(net::IsLocalhostTLD("foo.localhost.")); - EXPECT_FALSE(net::IsLocalhostTLD("foo.localhos")); - EXPECT_FALSE(net::IsLocalhostTLD("foo.localhost.com")); - EXPECT_FALSE(net::IsLocalhost("foo.localhoste")); + EXPECT_TRUE(IsLocalhostTLD("foo.localhost")); + EXPECT_TRUE(IsLocalhostTLD("foo.localhost.")); + EXPECT_FALSE(IsLocalhostTLD("foo.localhos")); + EXPECT_FALSE(IsLocalhostTLD("foo.localhost.com")); + EXPECT_FALSE(IsLocalhost("foo.localhoste")); } // Verify GetNetworkList(). @@ -948,7 +948,7 @@ NetworkInterfaceList results; ::base::hash_set<int> online_links; - net::internal::AddressTrackerLinux::AddressMap address_map; + internal::AddressTrackerLinux::AddressMap address_map; // Interface 1 is offline. struct ifaddrmsg msg = { @@ -961,12 +961,9 @@ // Address of offline links should be ignored. ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); - EXPECT_TRUE( - net::internal::GetNetworkListImpl(&results, - INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, - online_links, - address_map, - GetInterfaceName)); + EXPECT_TRUE(internal::GetNetworkListImpl( + &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links, + address_map, GetInterfaceName)); EXPECT_EQ(results.size(), 0ul); // Mark interface 1 online. @@ -976,23 +973,17 @@ address_map.clear(); ASSERT_TRUE( address_map.insert(std::make_pair(ipv6_local_address, msg)).second); - EXPECT_TRUE( - net::internal::GetNetworkListImpl(&results, - INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, - online_links, - address_map, - GetInterfaceName)); + EXPECT_TRUE(internal::GetNetworkListImpl( + &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links, + address_map, GetInterfaceName)); EXPECT_EQ(results.size(), 0ul); // vmware address should return by default. address_map.clear(); ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); - EXPECT_TRUE( - net::internal::GetNetworkListImpl(&results, - INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, - online_links, - address_map, - GetInterfaceNameVM)); + EXPECT_TRUE(internal::GetNetworkListImpl( + &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links, + address_map, GetInterfaceNameVM)); EXPECT_EQ(results.size(), 1ul); EXPECT_EQ(results[0].name, ifname_vm); EXPECT_EQ(results[0].prefix_length, 1ul); @@ -1002,12 +993,9 @@ // vmware address should be trimmed out if policy specified so. address_map.clear(); ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); - EXPECT_TRUE( - net::internal::GetNetworkListImpl(&results, - EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, - online_links, - address_map, - GetInterfaceNameVM)); + EXPECT_TRUE(internal::GetNetworkListImpl( + &results, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links, + address_map, GetInterfaceNameVM)); EXPECT_EQ(results.size(), 0ul); results.clear(); @@ -1015,12 +1003,9 @@ address_map.clear(); msg.ifa_flags = IFA_F_TENTATIVE; ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); - EXPECT_TRUE( - net::internal::GetNetworkListImpl(&results, - INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, - online_links, - address_map, - GetInterfaceName)); + EXPECT_TRUE(internal::GetNetworkListImpl( + &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links, + address_map, GetInterfaceName)); EXPECT_EQ(results.size(), 0ul); results.clear(); @@ -1029,12 +1014,9 @@ address_map.clear(); msg.ifa_flags = IFA_F_TEMPORARY; ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); - EXPECT_TRUE( - net::internal::GetNetworkListImpl(&results, - INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, - online_links, - address_map, - GetInterfaceName)); + EXPECT_TRUE(internal::GetNetworkListImpl( + &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links, + address_map, GetInterfaceName)); EXPECT_EQ(results.size(), 1ul); EXPECT_EQ(results[0].name, ifname_em1); EXPECT_EQ(results[0].prefix_length, 1ul); @@ -1047,12 +1029,9 @@ address_map.clear(); msg.ifa_flags = IFA_F_DEPRECATED; ASSERT_TRUE(address_map.insert(std::make_pair(ipv6_address, msg)).second); - EXPECT_TRUE( - net::internal::GetNetworkListImpl(&results, - INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, - online_links, - address_map, - GetInterfaceName)); + EXPECT_TRUE(internal::GetNetworkListImpl( + &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, online_links, + address_map, GetInterfaceName)); EXPECT_EQ(results.size(), 1ul); EXPECT_EQ(results[0].name, ifname_em1); EXPECT_EQ(results[0].prefix_length, 1ul); @@ -1078,7 +1057,7 @@ // Address of offline links should be ignored. ASSERT_TRUE(FillIfaddrs(&interface, ifname_em1, IFF_UP, ipv6_address, ipv6_netmask, addresses)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter)); EXPECT_EQ(results.size(), 0ul); @@ -1086,7 +1065,7 @@ // Local address should be trimmed out. ASSERT_TRUE(FillIfaddrs(&interface, ifname_em1, IFF_RUNNING, ipv6_local_address, ipv6_netmask, addresses)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter)); EXPECT_EQ(results.size(), 0ul); @@ -1094,7 +1073,7 @@ // vmware address should return by default. ASSERT_TRUE(FillIfaddrs(&interface, ifname_vm, IFF_RUNNING, ipv6_address, ipv6_netmask, addresses)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter)); EXPECT_EQ(results.size(), 1ul); @@ -1106,7 +1085,7 @@ // vmware address should be trimmed out if policy specified so. ASSERT_TRUE(FillIfaddrs(&interface, ifname_vm, IFF_RUNNING, ipv6_address, ipv6_netmask, addresses)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter)); EXPECT_EQ(results.size(), 0ul); @@ -1117,7 +1096,7 @@ ip_attributes_getter.set_native_attributes(IN6_IFF_ANYCAST); ASSERT_TRUE(FillIfaddrs(&interface, ifname_em1, IFF_RUNNING, ipv6_address, ipv6_netmask, addresses)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter)); EXPECT_EQ(results.size(), 0ul); @@ -1128,7 +1107,7 @@ ip_attributes_getter.set_native_attributes(IN6_IFF_TEMPORARY); ASSERT_TRUE(FillIfaddrs(&interface, ifname_em1, IFF_RUNNING, ipv6_address, ipv6_netmask, addresses)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter)); EXPECT_EQ(results.size(), 1ul); @@ -1143,7 +1122,7 @@ ip_attributes_getter.set_native_attributes(IN6_IFF_DEPRECATED); ASSERT_TRUE(FillIfaddrs(&interface, ifname_em1, IFF_RUNNING, ipv6_address, ipv6_netmask, addresses)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, &interface, &ip_attributes_getter)); EXPECT_EQ(results.size(), 1ul); @@ -1232,7 +1211,7 @@ addresses /* sock_addrs */)); adapter_address.OperStatus = IfOperStatusDown; - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address)); EXPECT_EQ(results.size(), 0ul); @@ -1244,7 +1223,7 @@ addresses /* sock_addrs */)); adapter_address.IfType = IF_TYPE_SOFTWARE_LOOPBACK; - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address)); EXPECT_EQ(results.size(), 0ul); @@ -1253,7 +1232,7 @@ &adapter_address /* adapter_address */, ifname_vm /* ifname */, ipv6_address /* ip_address */, ipv6_prefix /* ip_netmask */, addresses /* sock_addrs */)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address)); EXPECT_EQ(results.size(), 1ul); EXPECT_EQ(results[0].name, ifname_vm); @@ -1267,7 +1246,7 @@ &adapter_address /* adapter_address */, ifname_vm /* ifname */, ipv6_address /* ip_address */, ipv6_prefix /* ip_netmask */, addresses /* sock_addrs */)); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address)); EXPECT_EQ(results.size(), 0ul); results.clear(); @@ -1279,7 +1258,7 @@ addresses /* sock_addrs */)); adapter_address.FirstUnicastAddress->DadState = IpDadStateTentative; - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address)); EXPECT_EQ(results.size(), 0ul); results.clear(); @@ -1295,7 +1274,7 @@ IpPrefixOriginRouterAdvertisement; adapter_address.FirstUnicastAddress->SuffixOrigin = IpSuffixOriginRandom; - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address)); EXPECT_EQ(results.size(), 1ul); EXPECT_EQ(results[0].name, ifname_em1); @@ -1313,7 +1292,7 @@ addresses /* sock_addrs */)); adapter_address.FirstUnicastAddress->PreferredLifetime = 0; adapter_address.FriendlyName = const_cast<PWCHAR>(L"FriendlyInterfaceName"); - EXPECT_TRUE(net::internal::GetNetworkListImpl( + EXPECT_TRUE(internal::GetNetworkListImpl( &results, INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES, true, &adapter_address)); EXPECT_EQ(results.size(), 1ul); EXPECT_EQ(results[0].friendly_name, "FriendlyInterfaceName"); @@ -1336,7 +1315,7 @@ #if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS) TEST(NetUtilTest, GetWifiSSIDFromInterfaceList) { NetworkInterfaceList list; - EXPECT_EQ(std::string(), net::internal::GetWifiSSIDFromInterfaceListInternal( + EXPECT_EQ(std::string(), internal::GetWifiSSIDFromInterfaceListInternal( list, TestGetInterfaceSSID)); NetworkInterface interface1; @@ -1345,7 +1324,7 @@ list.push_back(interface1); ASSERT_EQ(1u, list.size()); EXPECT_EQ(std::string(kWiFiSSID), - net::internal::GetWifiSSIDFromInterfaceListInternal( + internal::GetWifiSSIDFromInterfaceListInternal( list, TestGetInterfaceSSID)); NetworkInterface interface2; @@ -1354,7 +1333,7 @@ list.push_back(interface2); ASSERT_EQ(2u, list.size()); EXPECT_EQ(std::string(kWiFiSSID), - net::internal::GetWifiSSIDFromInterfaceListInternal( + internal::GetWifiSSIDFromInterfaceListInternal( list, TestGetInterfaceSSID)); NetworkInterface interface3; @@ -1362,7 +1341,7 @@ interface3.type = NetworkChangeNotifier::CONNECTION_WIFI; list.push_back(interface3); ASSERT_EQ(3u, list.size()); - EXPECT_EQ(std::string(), net::internal::GetWifiSSIDFromInterfaceListInternal( + EXPECT_EQ(std::string(), internal::GetWifiSSIDFromInterfaceListInternal( list, TestGetInterfaceSSID)); list.pop_back(); @@ -1371,7 +1350,7 @@ interface4.type = NetworkChangeNotifier::CONNECTION_ETHERNET; list.push_back(interface4); ASSERT_EQ(3u, list.size()); - EXPECT_EQ(std::string(), net::internal::GetWifiSSIDFromInterfaceListInternal( + EXPECT_EQ(std::string(), internal::GetWifiSSIDFromInterfaceListInternal( list, TestGetInterfaceSSID)); } #endif // OS_LINUX
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc index 86bc253..52f348ef 100644 --- a/net/base/network_change_notifier.cc +++ b/net/base/network_change_notifier.cc
@@ -611,8 +611,7 @@ type == NetworkChangeNotifier::CONNECTION_3G || type == NetworkChangeNotifier::CONNECTION_4G) { // Log zero if not perfectly converted. - if (!base::StringToUint( - net::android::GetTelephonyNetworkOperator(), &mcc_mnc)) { + if (!base::StringToUint(android::GetTelephonyNetworkOperator(), &mcc_mnc)) { mcc_mnc = 0; } }
diff --git a/net/base/network_change_notifier_win_unittest.cc b/net/base/network_change_notifier_win_unittest.cc index ca59750..04b19e6 100644 --- a/net/base/network_change_notifier_win_unittest.cc +++ b/net/base/network_change_notifier_win_unittest.cc
@@ -43,8 +43,7 @@ DISALLOW_COPY_AND_ASSIGN(TestNetworkChangeNotifierWin); }; -class TestIPAddressObserver - : public net::NetworkChangeNotifier::IPAddressObserver { +class TestIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver { public: TestIPAddressObserver() { NetworkChangeNotifier::AddIPAddressObserver(this);
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc index c12d60b..0aaf2bd3 100644 --- a/net/base/network_delegate.cc +++ b/net/base/network_delegate.cc
@@ -135,7 +135,7 @@ bool NetworkDelegate::CanGetCookies(const URLRequest& request, const CookieList& cookie_list) { DCHECK(CalledOnValidThread()); - DCHECK(!(request.load_flags() & net::LOAD_DO_NOT_SEND_COOKIES)); + DCHECK(!(request.load_flags() & LOAD_DO_NOT_SEND_COOKIES)); return OnCanGetCookies(request, cookie_list); } @@ -143,7 +143,7 @@ const std::string& cookie_line, CookieOptions* options) { DCHECK(CalledOnValidThread()); - DCHECK(!(request.load_flags() & net::LOAD_DO_NOT_SAVE_COOKIES)); + DCHECK(!(request.load_flags() & LOAD_DO_NOT_SAVE_COOKIES)); return OnCanSetCookie(request, cookie_line, options); }
diff --git a/net/base/openssl_private_key_store_android.cc b/net/base/openssl_private_key_store_android.cc index a917d589..ba0d75b 100644 --- a/net/base/openssl_private_key_store_android.cc +++ b/net/base/openssl_private_key_store_android.cc
@@ -36,7 +36,7 @@ } bool ret = false; if (public_len > 0 && private_len > 0) { - ret = net::android::StoreKeyPair( + ret = android::StoreKeyPair( static_cast<const uint8*>(public_key), public_len, static_cast<const uint8*>(private_key), private_len); }
diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc index 4bf1782..c43c8b08 100644 --- a/net/base/sdch_manager.cc +++ b/net/base/sdch_manager.cc
@@ -249,7 +249,7 @@ referring_url.scheme() != dictionary_url.scheme()) return SDCH_DICTIONARY_LOAD_ATTEMPT_FROM_DIFFERENT_HOST; - if (!secure_scheme_supported() && referring_url.SchemeIsSecure()) + if (!secure_scheme_supported() && referring_url.SchemeIsCryptographic()) return SDCH_DICTIONARY_SELECTED_FOR_SSL; // TODO(jar): Remove this failsafe conservative hack which is more restrictive @@ -298,7 +298,8 @@ if (it == dictionaries_.end()) return result.Pass(); - if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure()) { + if (!SdchManager::secure_scheme_supported() && + target_url.SchemeIsSecure()) { *problem_code = SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; return result.Pass(); }
diff --git a/net/base/test_completion_callback.cc b/net/base/test_completion_callback.cc index 7094592..ba44211 100644 --- a/net/base/test_completion_callback.cc +++ b/net/base/test_completion_callback.cc
@@ -72,7 +72,7 @@ void ReleaseBufferCompletionCallback::SetResult(int result) { if (!buffer_->HasOneRef()) - result = net::ERR_FAILED; + result = ERR_FAILED; TestCompletionCallback::SetResult(result); }
diff --git a/net/base/test_completion_callback.h b/net/base/test_completion_callback.h index b7f8985..3762783 100644 --- a/net/base/test_completion_callback.h +++ b/net/base/test_completion_callback.h
@@ -58,7 +58,7 @@ } R GetResult(R result) { - if (net::ERR_IO_PENDING != result) + if (ERR_IO_PENDING != result) return result; return WaitForResult(); }
diff --git a/net/base/test_completion_callback_unittest.cc b/net/base/test_completion_callback_unittest.cc index b0c8565b..35e52d7 100644 --- a/net/base/test_completion_callback_unittest.cc +++ b/net/base/test_completion_callback_unittest.cc
@@ -13,6 +13,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +namespace net { + namespace { const int kMagicResult = 8888; @@ -36,7 +38,7 @@ // Do some imaginary work on a worker thread; // when done, worker posts callback on the original thread. // Returns true on success - bool DoSomething(const net::CompletionCallback& callback); + bool DoSomething(const CompletionCallback& callback); private: class ExampleWorker; @@ -49,8 +51,7 @@ class ExampleEmployer::ExampleWorker : public base::RefCountedThreadSafe<ExampleWorker> { public: - ExampleWorker(ExampleEmployer* employer, - const net::CompletionCallback& callback) + ExampleWorker(ExampleEmployer* employer, const CompletionCallback& callback) : employer_(employer), callback_(callback), origin_loop_(base::MessageLoop::current()) {} @@ -63,7 +64,7 @@ // Only used on the origin thread (where DoSomething was called). ExampleEmployer* employer_; - net::CompletionCallback callback_; + CompletionCallback callback_; // Used to post ourselves onto the origin thread. base::Lock origin_loop_lock_; base::MessageLoop* origin_loop_; @@ -101,7 +102,7 @@ ExampleEmployer::~ExampleEmployer() { } -bool ExampleEmployer::DoSomething(const net::CompletionCallback& callback) { +bool ExampleEmployer::DoSomething(const CompletionCallback& callback) { DCHECK(!request_.get()) << "already in use"; request_ = new ExampleWorker(this, callback); @@ -125,7 +126,7 @@ TEST_F(TestCompletionCallbackTest, Simple) { ExampleEmployer boss; - net::TestCompletionCallback callback; + TestCompletionCallback callback; bool queued = boss.DoSomething(callback.callback()); EXPECT_TRUE(queued); int result = callback.WaitForResult(); @@ -134,11 +135,11 @@ TEST_F(TestCompletionCallbackTest, Closure) { ExampleEmployer boss; - net::TestClosure closure; + TestClosure closure; bool did_check_result = false; - net::CompletionCallback completion_callback = - base::Bind(&CallClosureAfterCheckingResult, - closure.closure(), base::Unretained(&did_check_result)); + CompletionCallback completion_callback = + base::Bind(&CallClosureAfterCheckingResult, closure.closure(), + base::Unretained(&did_check_result)); bool queued = boss.DoSomething(completion_callback); EXPECT_TRUE(queued); @@ -148,3 +149,5 @@ } // TODO: test deleting ExampleEmployer while work outstanding + +} // namespace net
diff --git a/net/cert/cert_verifier.cc b/net/cert/cert_verifier.cc index e4acec4..4152d55 100644 --- a/net/cert/cert_verifier.cc +++ b/net/cert/cert_verifier.cc
@@ -4,13 +4,28 @@ #include "net/cert/cert_verifier.h" +#include "build/build_config.h" #include "net/cert/cert_verify_proc.h" + +#if defined(OS_NACL) +#include "base/logging.h" +#else #include "net/cert/multi_threaded_cert_verifier.h" +#endif namespace net { +bool CertVerifier::SupportsOCSPStapling() { + return false; +} + CertVerifier* CertVerifier::CreateDefault() { +#if defined(OS_NACL) + NOTIMPLEMENTED(); + return nullptr; +#else return new MultiThreadedCertVerifier(CertVerifyProc::CreateDefault()); +#endif } } // namespace net
diff --git a/net/cert/cert_verifier.h b/net/cert/cert_verifier.h index 743c8350..71a3478 100644 --- a/net/cert/cert_verifier.h +++ b/net/cert/cert_verifier.h
@@ -81,6 +81,8 @@ // |verify_result->cert_status|, and the error code for the most serious // error is returned. // + // |ocsp_response|, if non-empty, is a stapled OCSP response to use. + // // |flags| is bitwise OR'd of VerifyFlags. // If VERIFY_REV_CHECKING_ENABLED is set in |flags|, certificate revocation // checking is performed. @@ -103,6 +105,7 @@ // TODO(rsleevi): Move CRLSet* out of the CertVerifier signature. virtual int Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, CertVerifyResult* verify_result, @@ -114,6 +117,9 @@ // After a request is canceled, its completion callback will not be called. virtual void CancelRequest(RequestHandle req) = 0; + // Returns true if this CertVerifier supports stapled OCSP responses. + virtual bool SupportsOCSPStapling(); + // Creates a CertVerifier implementation that verifies certificates using // the preferred underlying cryptographic libraries. static CertVerifier* CreateDefault();
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc index 1e3fc89..9ea19b4 100644 --- a/net/cert/cert_verify_proc.cc +++ b/net/cert/cert_verify_proc.cc
@@ -190,6 +190,7 @@ int CertVerifyProc::Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -209,7 +210,7 @@ if (flags & CertVerifier::VERIFY_EV_CERT) flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY; - int rv = VerifyInternal(cert, hostname, flags, crl_set, + int rv = VerifyInternal(cert, hostname, ocsp_response, flags, crl_set, additional_trust_anchors, verify_result); UMA_HISTOGRAM_BOOLEAN("Net.CertCommonNameFallback",
diff --git a/net/cert/cert_verify_proc.h b/net/cert/cert_verify_proc.h index f60ed6d..fdc1205 100644 --- a/net/cert/cert_verify_proc.h +++ b/net/cert/cert_verify_proc.h
@@ -38,6 +38,8 @@ // |verify_result->cert_status|, and the error code for the most serious // error is returned. // + // |ocsp_response|, if non-empty, is a stapled OCSP response to use. + // // |flags| is bitwise OR'd of VerifyFlags: // // If VERIFY_REV_CHECKING_ENABLED is set in |flags|, online certificate @@ -56,6 +58,7 @@ // implementation. int Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -66,6 +69,11 @@ // passed to Verify() is ignored when this returns false. virtual bool SupportsAdditionalTrustAnchors() const = 0; + // Returns true if the implementation supports passing a stapled OCSP response + // to the Verify() call. The |ocsp_response| parameter passed to Verify() is + // ignored when this returns false. + virtual bool SupportsOCSPStapling() const = 0; + protected: CertVerifyProc(); virtual ~CertVerifyProc(); @@ -76,9 +84,12 @@ FRIEND_TEST_ALL_PREFIXES(CertVerifyProcTest, TestHasTooLongValidity); // Performs the actual verification using the desired underlying - // cryptographic library. + // cryptographic library. On entry, |verify_result->verified_cert| + // is set to |cert|, the unverified chain. If no chain is built, the + // value must be left untouched. virtual int VerifyInternal(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_android.cc b/net/cert/cert_verify_proc_android.cc index 91d0b559..6689ad8 100644 --- a/net/cert/cert_verify_proc_android.cc +++ b/net/cert/cert_verify_proc_android.cc
@@ -155,9 +155,14 @@ return false; } +bool CertVerifyProcAndroid::SupportsOCSPStapling() const { + return false; +} + int CertVerifyProcAndroid::VerifyInternal( X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_android.h b/net/cert/cert_verify_proc_android.h index 6830df6..755ce80 100644 --- a/net/cert/cert_verify_proc_android.h +++ b/net/cert/cert_verify_proc_android.h
@@ -16,6 +16,7 @@ CertVerifyProcAndroid(); bool SupportsAdditionalTrustAnchors() const override; + bool SupportsOCSPStapling() const override; protected: ~CertVerifyProcAndroid() override; @@ -23,6 +24,7 @@ private: int VerifyInternal(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc index 388d0fc4..d298fee 100644 --- a/net/cert/cert_verify_proc_mac.cc +++ b/net/cert/cert_verify_proc_mac.cc
@@ -178,13 +178,14 @@ // Stores the constructed certificate chain |cert_chain| and information about // the signature algorithms used into |*verify_result|. If the leaf cert in // |cert_chain| contains a weak (MD2, MD4, MD5, SHA-1) signature, stores that -// in |*leaf_is_weak|. +// in |*leaf_is_weak|. |cert_chain| must not be empty. void GetCertChainInfo(CFArrayRef cert_chain, CSSM_TP_APPLE_EVIDENCE_INFO* chain_info, CertVerifyResult* verify_result, bool* leaf_is_weak) { + DCHECK_LT(0, CFArrayGetCount(cert_chain)); + *leaf_is_weak = false; - verify_result->verified_cert = nullptr; verify_result->has_md2 = false; verify_result->has_md4 = false; verify_result->has_md5 = false; @@ -253,8 +254,10 @@ *leaf_is_weak = true; } } - if (!verified_cert) + if (!verified_cert) { + NOTREACHED(); return; + } verify_result->verified_cert = X509Certificate::CreateFromHandle(verified_cert, verified_chain); @@ -473,9 +476,16 @@ return false; } +bool CertVerifyProcMac::SupportsOCSPStapling() const { + // TODO(rsleevi): Plumb an OCSP response into the Mac system library. + // https://crbug.com/430714 + return false; +} + int CertVerifyProcMac::VerifyInternal( X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -561,17 +571,23 @@ if (rv != OK) return rv; - CertVerifyResult temp_verify_result; - bool leaf_is_weak = false; - GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result, - &leaf_is_weak); - bool untrusted = (temp_trust_result != kSecTrustResultUnspecified && temp_trust_result != kSecTrustResultProceed); - bool weak_chain = - !leaf_is_weak && - (temp_verify_result.has_md2 || temp_verify_result.has_md4 || - temp_verify_result.has_md5 || temp_verify_result.has_sha1); + bool weak_chain = false; + if (CFArrayGetCount(temp_chain) == 0) { + // If the chain is empty, it cannot be trusted or have recoverable + // errors. + DCHECK(untrusted); + DCHECK_NE(kSecTrustResultRecoverableTrustFailure, temp_trust_result); + } else { + CertVerifyResult temp_verify_result; + bool leaf_is_weak = false; + GetCertChainInfo(temp_chain, temp_chain_info, &temp_verify_result, + &leaf_is_weak); + weak_chain = !leaf_is_weak && + (temp_verify_result.has_md2 || temp_verify_result.has_md4 || + temp_verify_result.has_md5 || temp_verify_result.has_sha1); + } // Set the result to the current chain if: // - This is the first verification attempt. This ensures that if // everything is awful (e.g. it may just be an untrusted cert), that @@ -609,9 +625,11 @@ if (crl_set && !CheckRevocationWithCRLSet(completed_chain, crl_set)) verify_result->cert_status |= CERT_STATUS_REVOKED; - bool leaf_is_weak_unused = false; - GetCertChainInfo(completed_chain, chain_info, verify_result, - &leaf_is_weak_unused); + if (CFArrayGetCount(completed_chain) > 0) { + bool leaf_is_weak_unused = false; + GetCertChainInfo(completed_chain, chain_info, verify_result, + &leaf_is_weak_unused); + } // As of Security Update 2012-002/OS X 10.7.4, when an RSA key < 1024 bits // is encountered, CSSM returns CSSMERR_TP_VERIFY_ACTION_FAILED and adds
diff --git a/net/cert/cert_verify_proc_mac.h b/net/cert/cert_verify_proc_mac.h index 5cd7f4c..3c87edd 100644 --- a/net/cert/cert_verify_proc_mac.h +++ b/net/cert/cert_verify_proc_mac.h
@@ -16,6 +16,7 @@ CertVerifyProcMac(); bool SupportsAdditionalTrustAnchors() const override; + bool SupportsOCSPStapling() const override; protected: ~CertVerifyProcMac() override; @@ -23,6 +24,7 @@ private: int VerifyInternal(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc index 1236f41..02a584f 100644 --- a/net/cert/cert_verify_proc_nss.cc +++ b/net/cert/cert_verify_proc_nss.cc
@@ -33,6 +33,10 @@ #include "net/cert/x509_util_ios.h" #endif // defined(OS_IOS) +#if defined(USE_NSS_CERTS) +#include <dlfcn.h> +#endif + namespace net { namespace { @@ -756,7 +760,14 @@ } // namespace -CertVerifyProcNSS::CertVerifyProcNSS() {} +CertVerifyProcNSS::CertVerifyProcNSS() +#if defined(USE_NSS_CERTS) + : cache_ocsp_response_from_side_channel_( + reinterpret_cast<CacheOCSPResponseFromSideChannelFunction>( + dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"))) +#endif +{ +} CertVerifyProcNSS::~CertVerifyProcNSS() {} @@ -764,9 +775,19 @@ return true; } +bool CertVerifyProcNSS::SupportsOCSPStapling() const { +#if defined(USE_NSS_CERTS) + return cache_ocsp_response_from_side_channel_; +#else + // TODO(davidben): Support OCSP stapling on iOS. + return false; +#endif +} + int CertVerifyProcNSS::VerifyInternalImpl( X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -781,6 +802,21 @@ CERTCertificate* cert_handle = cert->os_cert_handle(); #endif // defined(OS_IOS) +#if defined(USE_NSS_CERTS) + if (!ocsp_response.empty() && cache_ocsp_response_from_side_channel_) { + // Note: NSS uses a thread-safe global hash table, so this call will + // affect any concurrent verification operations on |cert| or copies of + // the same certificate. This is an unavoidable limitation of NSS's OCSP + // API. + SECItem ocsp_response_item; + ocsp_response_item.data = reinterpret_cast<unsigned char*>( + const_cast<char*>(ocsp_response.data())); + ocsp_response_item.len = ocsp_response.size(); + cache_ocsp_response_from_side_channel_(CERT_GetDefaultCertDB(), cert_handle, + PR_Now(), &ocsp_response_item, NULL); + } +#endif // defined(USE_NSS_CERTS) + if (!cert->VerifyNameMatch(hostname, &verify_result->common_name_fallback_used)) { verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; @@ -928,14 +964,12 @@ int CertVerifyProcNSS::VerifyInternal( X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, CertVerifyResult* verify_result) { - return VerifyInternalImpl(cert, - hostname, - flags, - crl_set, + return VerifyInternalImpl(cert, hostname, ocsp_response, flags, crl_set, additional_trust_anchors, NULL, // chain_verify_callback verify_result);
diff --git a/net/cert/cert_verify_proc_nss.h b/net/cert/cert_verify_proc_nss.h index 395facf5..5a4b3611 100644 --- a/net/cert/cert_verify_proc_nss.h +++ b/net/cert/cert_verify_proc_nss.h
@@ -18,6 +18,7 @@ CertVerifyProcNSS(); bool SupportsAdditionalTrustAnchors() const override; + bool SupportsOCSPStapling() const override; protected: ~CertVerifyProcNSS() override; @@ -27,6 +28,7 @@ // CERTChainVerifyCallbackFunc in NSS's lib/certdb/certt.h. int VerifyInternalImpl(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -36,10 +38,22 @@ private: int VerifyInternal(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, CertVerifyResult* verify_result) override; + +#if defined(USE_NSS_CERTS) + using CacheOCSPResponseFromSideChannelFunction = + SECStatus (*)(CERTCertDBHandle* handle, + CERTCertificate* cert, + PRTime time, + SECItem* encodedResponse, + void* pwArg); + const CacheOCSPResponseFromSideChannelFunction + cache_ocsp_response_from_side_channel_; +#endif }; } // namespace net
diff --git a/net/cert/cert_verify_proc_openssl.cc b/net/cert/cert_verify_proc_openssl.cc index 890462e6..56492452 100644 --- a/net/cert/cert_verify_proc_openssl.cc +++ b/net/cert/cert_verify_proc_openssl.cc
@@ -190,9 +190,14 @@ return false; } +bool CertVerifyProcOpenSSL::SupportsOCSPStapling() const { + return false; +} + int CertVerifyProcOpenSSL::VerifyInternal( X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_openssl.h b/net/cert/cert_verify_proc_openssl.h index 979d65ad..5836386c 100644 --- a/net/cert/cert_verify_proc_openssl.h +++ b/net/cert/cert_verify_proc_openssl.h
@@ -15,6 +15,7 @@ CertVerifyProcOpenSSL(); bool SupportsAdditionalTrustAnchors() const override; + bool SupportsOCSPStapling() const override; protected: ~CertVerifyProcOpenSSL() override; @@ -22,6 +23,7 @@ private: int VerifyInternal(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc index 1d4ac9b..9208e86 100644 --- a/net/cert/cert_verify_proc_unittest.cc +++ b/net/cert/cert_verify_proc_unittest.cc
@@ -57,6 +57,7 @@ // CertVerifyProc implementation: bool SupportsAdditionalTrustAnchors() const override { return false; } + bool SupportsOCSPStapling() const override { return false; } protected: ~WellKnownCaCertVerifyProc() override {} @@ -64,6 +65,7 @@ private: int VerifyInternal(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -77,6 +79,7 @@ int WellKnownCaCertVerifyProc::VerifyInternal( X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -125,7 +128,7 @@ CRLSet* crl_set, const CertificateList& additional_trust_anchors, CertVerifyResult* verify_result) { - return verify_proc_->Verify(cert, hostname, flags, crl_set, + return verify_proc_->Verify(cert, hostname, std::string(), flags, crl_set, additional_trust_anchors, verify_result); } @@ -1019,15 +1022,11 @@ // detecting known roots. TEST_F(CertVerifyProcTest, IsIssuedByKnownRootIgnoresTestRoots) { // Load root_ca_cert.pem into the test root store. - TestRootCerts* root_certs = TestRootCerts::GetInstance(); - root_certs->AddFromFile( - GetTestCertsDirectory().AppendASCII("root_ca_cert.pem")); + ScopedTestRoot test_root( + ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem").get()); - CertificateList cert_list = CreateCertificateListFromFile( - GetTestCertsDirectory(), "ok_cert.pem", - X509Certificate::FORMAT_AUTO); - ASSERT_EQ(1U, cert_list.size()); - scoped_refptr<X509Certificate> cert(cert_list[0]); + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); // Verification should pass. int flags = 0; @@ -1038,9 +1037,6 @@ EXPECT_EQ(0U, verify_result.cert_status); // But should not be marked as a known root. EXPECT_FALSE(verify_result.is_issued_by_known_root); - - root_certs->Clear(); - EXPECT_TRUE(root_certs->IsEmpty()); } #if defined(OS_MACOSX) && !defined(OS_IOS) @@ -1594,4 +1590,28 @@ CertVerifyProcNameTest, testing::ValuesIn(kVerifyNameData)); +#if defined(OS_MACOSX) && !defined(OS_IOS) +// Test that CertVerifyProcMac reacts appropriately when Apple's certificate +// verifier rejects a certificate with a fatal error. This is a regression +// test for https://crbug.com/472291. +TEST_F(CertVerifyProcTest, LargeKey) { + // Load root_ca_cert.pem into the test root store. + ScopedTestRoot test_root( + ImportCertFromFile(GetTestCertsDirectory(), "root_ca_cert.pem").get()); + + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "large_key.pem")); + + // Apple's verifier rejects this certificate as invalid because the + // RSA key is too large. If a future version of OS X changes this, + // large_key.pem may need to be regenerated with a larger key. + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, + &verify_result); + EXPECT_EQ(ERR_CERT_INVALID, error); + EXPECT_EQ(CERT_STATUS_INVALID, verify_result.cert_status); +} +#endif // defined(OS_MACOSX) && !defined(OS_IOS) + } // namespace net
diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc index 13a337bf..21572b4 100644 --- a/net/cert/cert_verify_proc_win.cc +++ b/net/cert/cert_verify_proc_win.cc
@@ -559,9 +559,19 @@ return false; } +bool CertVerifyProcWin::SupportsOCSPStapling() const { + // CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be + // set on Windows XP without error. There is some overhead from the server + // sending the OCSP response if it supports the extension, for the subset of + // XP clients who will request it but be unable to use it, but this is an + // acceptable trade-off for simplicity of implementation. + return true; +} + int CertVerifyProcWin::VerifyInternal( X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -633,6 +643,18 @@ chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine()); ScopedPCCERT_CONTEXT cert_list(cert->CreateOSCertChainForCert()); + + if (!ocsp_response.empty()) { + // Attach the OCSP response to the chain. + CRYPT_DATA_BLOB ocsp_response_blob; + ocsp_response_blob.cbData = ocsp_response.size(); + ocsp_response_blob.pbData = + reinterpret_cast<BYTE*>(const_cast<char*>(ocsp_response.data())); + CertSetCertificateContextProperty( + cert_list.get(), CERT_OCSP_RESPONSE_PROP_ID, + CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, &ocsp_response_blob); + } + PCCERT_CHAIN_CONTEXT chain_context; // IE passes a non-NULL pTime argument that specifies the current system // time. IE passes CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT as the
diff --git a/net/cert/cert_verify_proc_win.h b/net/cert/cert_verify_proc_win.h index 9c2d26a..c56c821 100644 --- a/net/cert/cert_verify_proc_win.h +++ b/net/cert/cert_verify_proc_win.h
@@ -16,6 +16,7 @@ CertVerifyProcWin(); bool SupportsAdditionalTrustAnchors() const override; + bool SupportsOCSPStapling() const override; protected: ~CertVerifyProcWin() override; @@ -23,6 +24,7 @@ private: int VerifyInternal(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors,
diff --git a/net/cert/crl_set_unittest.cc b/net/cert/crl_set_unittest.cc index 16b3dfc..4f74c29e 100644 --- a/net/cert/crl_set_unittest.cc +++ b/net/cert/crl_set_unittest.cc
@@ -6,6 +6,8 @@ #include "net/cert/crl_set_storage.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + // These data blocks were generated using a lot of code that is still in // development. For now, if you need to update them, you have to contact agl. static const uint8 kGIACRLSet[] = { @@ -186,11 +188,11 @@ TEST(CRLSetTest, Parse) { base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), sizeof(kGIACRLSet)); - scoped_refptr<net::CRLSet> set; - EXPECT_TRUE(net::CRLSetStorage::Parse(s, &set)); + scoped_refptr<CRLSet> set; + EXPECT_TRUE(CRLSetStorage::Parse(s, &set)); ASSERT_TRUE(set.get() != NULL); - const net::CRLSet::CRLList& crls = set->crls(); + const CRLSet::CRLList& crls = set->crls(); ASSERT_EQ(1u, crls.size()); const std::vector<std::string>& serials = crls[0].second; static const unsigned kExpectedNumSerials = 13; @@ -203,12 +205,14 @@ const std::string gia_spki_hash( reinterpret_cast<const char*>(kGIASPKISHA256), sizeof(kGIASPKISHA256)); - EXPECT_EQ(net::CRLSet::REVOKED, set->CheckSerial( - std::string("\x16\x7D\x75\x9D\x00\x03\x00\x00\x14\x55", 10), - gia_spki_hash)); - EXPECT_EQ(net::CRLSet::GOOD, set->CheckSerial( - std::string("\x47\x54\x3E\x79\x00\x03\x00\x00\x14\xF5", 10), - gia_spki_hash)); + EXPECT_EQ(CRLSet::REVOKED, + set->CheckSerial( + std::string("\x16\x7D\x75\x9D\x00\x03\x00\x00\x14\x55", 10), + gia_spki_hash)); + EXPECT_EQ(CRLSet::GOOD, + set->CheckSerial( + std::string("\x47\x54\x3E\x79\x00\x03\x00\x00\x14\xF5", 10), + gia_spki_hash)); EXPECT_FALSE(set->IsExpired()); } @@ -216,34 +220,34 @@ TEST(CRLSetTest, NoOpDeltaUpdate) { base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), sizeof(kGIACRLSet)); - scoped_refptr<net::CRLSet> set; - EXPECT_TRUE(net::CRLSetStorage::Parse(s, &set)); + scoped_refptr<CRLSet> set; + EXPECT_TRUE(CRLSetStorage::Parse(s, &set)); ASSERT_TRUE(set.get() != NULL); - scoped_refptr<net::CRLSet> delta_set; + scoped_refptr<CRLSet> delta_set; base::StringPiece delta(reinterpret_cast<const char*>(kNoopDeltaCRL), sizeof(kNoopDeltaCRL)); - EXPECT_TRUE(net::CRLSetStorage::ApplyDelta(set.get(), delta, &delta_set)); + EXPECT_TRUE(CRLSetStorage::ApplyDelta(set.get(), delta, &delta_set)); ASSERT_TRUE(delta_set.get() != NULL); - std::string out = net::CRLSetStorage::Serialize(delta_set.get()); + std::string out = CRLSetStorage::Serialize(delta_set.get()); EXPECT_EQ(s.as_string(), out); } TEST(CRLSetTest, AddCRLDelta) { base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), sizeof(kGIACRLSet)); - scoped_refptr<net::CRLSet> set; - EXPECT_TRUE(net::CRLSetStorage::Parse(s, &set)); + scoped_refptr<CRLSet> set; + EXPECT_TRUE(CRLSetStorage::Parse(s, &set)); ASSERT_TRUE(set.get() != NULL); - scoped_refptr<net::CRLSet> delta_set; + scoped_refptr<CRLSet> delta_set; base::StringPiece delta(reinterpret_cast<const char*>(kAddCRLDelta), sizeof(kAddCRLDelta)); - EXPECT_TRUE(net::CRLSetStorage::ApplyDelta(set.get(), delta, &delta_set)); + EXPECT_TRUE(CRLSetStorage::ApplyDelta(set.get(), delta, &delta_set)); ASSERT_TRUE(delta_set.get() != NULL); - const net::CRLSet::CRLList& crls = delta_set->crls(); + const CRLSet::CRLList& crls = delta_set->crls(); ASSERT_EQ(2u, crls.size()); const std::vector<std::string>& serials = crls[1].second; ASSERT_EQ(12u, serials.size()); @@ -255,24 +259,23 @@ TEST(CRLSetTest, AddRemoveCRLDelta) { base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), sizeof(kGIACRLSet)); - scoped_refptr<net::CRLSet> set; - EXPECT_TRUE(net::CRLSetStorage::Parse(s, &set)); + scoped_refptr<CRLSet> set; + EXPECT_TRUE(CRLSetStorage::Parse(s, &set)); ASSERT_TRUE(set.get() != NULL); - scoped_refptr<net::CRLSet> delta_set; + scoped_refptr<CRLSet> delta_set; base::StringPiece delta(reinterpret_cast<const char*>(kAddCRLDelta), sizeof(kAddCRLDelta)); - EXPECT_TRUE(net::CRLSetStorage::ApplyDelta(set.get(), delta, &delta_set)); + EXPECT_TRUE(CRLSetStorage::ApplyDelta(set.get(), delta, &delta_set)); ASSERT_TRUE(delta_set.get() != NULL); - scoped_refptr<net::CRLSet> delta2_set; + scoped_refptr<CRLSet> delta2_set; base::StringPiece delta2(reinterpret_cast<const char*>(kRemoveCRLDelta), sizeof(kRemoveCRLDelta)); - EXPECT_TRUE( - net::CRLSetStorage::ApplyDelta(delta_set.get(), delta2, &delta2_set)); + EXPECT_TRUE(CRLSetStorage::ApplyDelta(delta_set.get(), delta2, &delta2_set)); ASSERT_TRUE(delta2_set.get() != NULL); - const net::CRLSet::CRLList& crls = delta2_set->crls(); + const CRLSet::CRLList& crls = delta2_set->crls(); ASSERT_EQ(1u, crls.size()); const std::vector<std::string>& serials = crls[0].second; ASSERT_EQ(13u, serials.size()); @@ -281,17 +284,17 @@ TEST(CRLSetTest, UpdateSerialsDelta) { base::StringPiece s(reinterpret_cast<const char*>(kGIACRLSet), sizeof(kGIACRLSet)); - scoped_refptr<net::CRLSet> set; - EXPECT_TRUE(net::CRLSetStorage::Parse(s, &set)); + scoped_refptr<CRLSet> set; + EXPECT_TRUE(CRLSetStorage::Parse(s, &set)); ASSERT_TRUE(set.get() != NULL); - scoped_refptr<net::CRLSet> delta_set; + scoped_refptr<CRLSet> delta_set; base::StringPiece delta(reinterpret_cast<const char*>(kUpdateSerialsDelta), sizeof(kUpdateSerialsDelta)); - EXPECT_TRUE(net::CRLSetStorage::ApplyDelta(set.get(), delta, &delta_set)); + EXPECT_TRUE(CRLSetStorage::ApplyDelta(set.get(), delta, &delta_set)); ASSERT_TRUE(delta_set.get() != NULL); - const net::CRLSet::CRLList& crls = delta_set->crls(); + const CRLSet::CRLList& crls = delta_set->crls(); ASSERT_EQ(1u, crls.size()); const std::vector<std::string>& serials = crls[0].second; EXPECT_EQ(45u, serials.size()); @@ -300,8 +303,8 @@ TEST(CRLSetTest, BlockedSPKIs) { base::StringPiece s(reinterpret_cast<const char*>(kBlockedSPKICRLSet), sizeof(kBlockedSPKICRLSet)); - scoped_refptr<net::CRLSet> set; - EXPECT_TRUE(net::CRLSetStorage::Parse(s, &set)); + scoped_refptr<CRLSet> set; + EXPECT_TRUE(CRLSetStorage::Parse(s, &set)); ASSERT_TRUE(set.get() != NULL); const uint8 spki_hash[] = { @@ -310,9 +313,9 @@ 0, }; - EXPECT_EQ(net::CRLSet::GOOD, set->CheckSPKI("")); - EXPECT_EQ(net::CRLSet::REVOKED, set->CheckSPKI( - reinterpret_cast<const char*>(spki_hash))); + EXPECT_EQ(CRLSet::GOOD, set->CheckSPKI("")); + EXPECT_EQ(CRLSet::REVOKED, + set->CheckSPKI(reinterpret_cast<const char*>(spki_hash))); } TEST(CRLSetTest, Expired) { @@ -320,9 +323,11 @@ // 1970. base::StringPiece s(reinterpret_cast<const char*>(kExpiredCRLSet), sizeof(kExpiredCRLSet)); - scoped_refptr<net::CRLSet> set; - EXPECT_TRUE(net::CRLSetStorage::Parse(s, &set)); + scoped_refptr<CRLSet> set; + EXPECT_TRUE(CRLSetStorage::Parse(s, &set)); ASSERT_TRUE(set.get() != NULL); EXPECT_TRUE(set->IsExpired()); } + +} // namespace net
diff --git a/net/cert/mock_cert_verifier.cc b/net/cert/mock_cert_verifier.cc index ea5538e..faffacf 100644 --- a/net/cert/mock_cert_verifier.cc +++ b/net/cert/mock_cert_verifier.cc
@@ -38,6 +38,7 @@ int MockCertVerifier::Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, CertVerifyResult* verify_result,
diff --git a/net/cert/mock_cert_verifier.h b/net/cert/mock_cert_verifier.h index 000da11f..1ccfe62 100644 --- a/net/cert/mock_cert_verifier.h +++ b/net/cert/mock_cert_verifier.h
@@ -27,6 +27,7 @@ // CertVerifier implementation int Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, CertVerifyResult* verify_result,
diff --git a/net/cert/multi_log_ct_verifier_unittest.cc b/net/cert/multi_log_ct_verifier_unittest.cc index 9e1ea4d..6fa4477 100644 --- a/net/cert/multi_log_ct_verifier_unittest.cc +++ b/net/cert/multi_log_ct_verifier_unittest.cc
@@ -21,6 +21,7 @@ #include "net/cert/sct_status_flags.h" #include "net/cert/signed_certificate_timestamp.h" #include "net/cert/x509_certificate.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/test_net_log.h" #include "net/test/cert_test_util.h" @@ -72,19 +73,19 @@ } bool CheckForEmbeddedSCTInNetLog(TestNetLog& net_log) { - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log.GetEntries(&entries); if (entries.size() != 2) return false; - const TestNetLog::CapturedEntry& received = entries[0]; + const CapturedNetLogEntry& received = entries[0]; std::string embedded_scts; if (!received.GetStringValue("embedded_scts", &embedded_scts)) return false; if (embedded_scts.empty()) return false; - const TestNetLog::CapturedEntry& parsed = entries[1]; + const CapturedNetLogEntry& parsed = entries[1]; base::ListValue* verified_scts; if (!parsed.GetListValue("verified_scts", &verified_scts) || verified_scts->GetSize() != 1) {
diff --git a/net/cert/multi_threaded_cert_verifier.cc b/net/cert/multi_threaded_cert_verifier.cc index 128987f1..44eff8e7 100644 --- a/net/cert/multi_threaded_cert_verifier.cc +++ b/net/cert/multi_threaded_cert_verifier.cc
@@ -12,6 +12,7 @@ #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" #include "base/profiler/scoped_tracker.h" +#include "base/sha1.h" #include "base/stl_util.h" #include "base/synchronization/lock.h" #include "base/threading/worker_pool.h" @@ -218,6 +219,7 @@ CertVerifierWorker(CertVerifyProc* verify_proc, X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -225,14 +227,14 @@ : verify_proc_(verify_proc), cert_(cert), hostname_(hostname), + ocsp_response_(ocsp_response), flags_(flags), crl_set_(crl_set), additional_trust_anchors_(additional_trust_anchors), origin_loop_(base::MessageLoop::current()), cert_verifier_(cert_verifier), canceled_(false), - error_(ERR_FAILED) { - } + error_(ERR_FAILED) {} // Returns the certificate being verified. May only be called /before/ // Start() is called. @@ -257,12 +259,9 @@ private: void Run() { // Runs on a worker thread. - error_ = verify_proc_->Verify(cert_.get(), - hostname_, - flags_, - crl_set_.get(), - additional_trust_anchors_, - &verify_result_); + error_ = verify_proc_->Verify(cert_.get(), hostname_, ocsp_response_, + flags_, crl_set_.get(), + additional_trust_anchors_, &verify_result_); #if defined(USE_NSS_CERTS) || defined(OS_IOS) // Detach the thread from NSPR. // Calling NSS functions attaches the thread to NSPR, which stores @@ -290,11 +289,8 @@ // memory leaks or worse errors. base::AutoLock locked(lock_); if (!canceled_) { - cert_verifier_->HandleResult(cert_.get(), - hostname_, - flags_, - additional_trust_anchors_, - error_, + cert_verifier_->HandleResult(cert_.get(), hostname_, ocsp_response_, + flags_, additional_trust_anchors_, error_, verify_result_); } } @@ -331,6 +327,7 @@ scoped_refptr<CertVerifyProc> verify_proc_; scoped_refptr<X509Certificate> cert_; const std::string hostname_; + const std::string ocsp_response_; const int flags_; scoped_refptr<CRLSet> crl_set_; const CertificateList additional_trust_anchors_; @@ -460,6 +457,7 @@ int MultiThreadedCertVerifier::Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, CertVerifyResult* verify_result, @@ -480,8 +478,8 @@ trust_anchor_provider_ ? trust_anchor_provider_->GetAdditionalTrustAnchors() : empty_cert_list; - const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), - hostname, flags, additional_trust_anchors); + const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), hostname, + ocsp_response, flags, additional_trust_anchors); const CertVerifierCache::value_type* cached_entry = cache_.Get(key, CacheValidityPeriod(base::Time::Now())); if (cached_entry) { @@ -502,14 +500,9 @@ job = j->second; } else { // Need to make a new request. - CertVerifierWorker* worker = - new CertVerifierWorker(verify_proc_.get(), - cert, - hostname, - flags, - crl_set, - additional_trust_anchors, - this); + CertVerifierWorker* worker = new CertVerifierWorker( + verify_proc_.get(), cert, hostname, ocsp_response, flags, crl_set, + additional_trust_anchors, this); job = new CertVerifierJob( worker, BoundNetLog::Make(net_log.net_log(), NetLog::SOURCE_CERT_VERIFIER_JOB)); @@ -541,15 +534,24 @@ request->Cancel(); } +bool MultiThreadedCertVerifier::SupportsOCSPStapling() { + return verify_proc_->SupportsOCSPStapling(); +} + MultiThreadedCertVerifier::RequestParams::RequestParams( const SHA1HashValue& cert_fingerprint_arg, const SHA1HashValue& ca_fingerprint_arg, const std::string& hostname_arg, + const std::string& ocsp_response_arg, int flags_arg, const CertificateList& additional_trust_anchors) - : hostname(hostname_arg), - flags(flags_arg) { - hash_values.reserve(2 + additional_trust_anchors.size()); + : hostname(hostname_arg), flags(flags_arg) { + hash_values.reserve(3 + additional_trust_anchors.size()); + SHA1HashValue ocsp_hash; + base::SHA1HashBytes( + reinterpret_cast<const unsigned char*>(ocsp_response_arg.data()), + ocsp_response_arg.size(), ocsp_hash.data); + hash_values.push_back(ocsp_hash); hash_values.push_back(cert_fingerprint_arg); hash_values.push_back(ca_fingerprint_arg); for (size_t i = 0; i < additional_trust_anchors.size(); ++i) @@ -560,17 +562,16 @@ bool MultiThreadedCertVerifier::RequestParams::operator<( const RequestParams& other) const { - // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, and - // |hostname| under assumption that integer comparisons are faster than - // memory and string comparisons. + // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, + // |hostname|, and |ocsp_response|, under assumption that integer comparisons + // are faster than memory and string comparisons. if (flags != other.flags) return flags < other.flags; if (hostname != other.hostname) return hostname < other.hostname; return std::lexicographical_compare( - hash_values.begin(), hash_values.end(), - other.hash_values.begin(), other.hash_values.end(), - net::SHA1HashValueLessThan()); + hash_values.begin(), hash_values.end(), other.hash_values.begin(), + other.hash_values.end(), SHA1HashValueLessThan()); } // HandleResult is called by CertVerifierWorker on the origin message loop. @@ -578,14 +579,15 @@ void MultiThreadedCertVerifier::HandleResult( X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, const CertificateList& additional_trust_anchors, int error, const CertVerifyResult& verify_result) { DCHECK(CalledOnValidThread()); - const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), - hostname, flags, additional_trust_anchors); + const RequestParams key(cert->fingerprint(), cert->ca_fingerprint(), hostname, + ocsp_response, flags, additional_trust_anchors); CachedResult cached_result; cached_result.error = error;
diff --git a/net/cert/multi_threaded_cert_verifier.h b/net/cert/multi_threaded_cert_verifier.h index 6880960..bfcab38 100644 --- a/net/cert/multi_threaded_cert_verifier.h +++ b/net/cert/multi_threaded_cert_verifier.h
@@ -56,6 +56,7 @@ // CertVerifier implementation int Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, CertVerifyResult* verify_result, @@ -65,6 +66,8 @@ void CancelRequest(CertVerifier::RequestHandle req) override; + bool SupportsOCSPStapling() override; + private: friend class CertVerifierWorker; // Calls HandleResult. friend class CertVerifierRequest; @@ -84,6 +87,7 @@ RequestParams(const SHA1HashValue& cert_fingerprint_arg, const SHA1HashValue& ca_fingerprint_arg, const std::string& hostname_arg, + const std::string& ocsp_response_arg, int flags_arg, const CertificateList& additional_trust_anchors); ~RequestParams(); @@ -131,6 +135,7 @@ void HandleResult(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, const CertificateList& additional_trust_anchors, int error,
diff --git a/net/cert/multi_threaded_cert_verifier_unittest.cc b/net/cert/multi_threaded_cert_verifier_unittest.cc index c7c143f..142e65a8 100644 --- a/net/cert/multi_threaded_cert_verifier_unittest.cc +++ b/net/cert/multi_threaded_cert_verifier_unittest.cc
@@ -41,9 +41,11 @@ // CertVerifyProc implementation bool SupportsAdditionalTrustAnchors() const override { return false; } + bool SupportsOCSPStapling() const override { return false; } int VerifyInternal(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, const CertificateList& additional_trust_anchors, @@ -85,14 +87,9 @@ TestCompletionCallback callback; CertVerifier::RequestHandle request_handle; - error = verifier_.Verify(test_cert.get(), - "www.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), 0, + NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle); error = callback.WaitForResult(); @@ -102,14 +99,9 @@ ASSERT_EQ(0u, verifier_.inflight_joins()); ASSERT_EQ(1u, verifier_.GetCacheSize()); - error = verifier_.Verify(test_cert.get(), - "www.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), 0, + NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); // Synchronous completion. ASSERT_NE(ERR_IO_PENDING, error); ASSERT_TRUE(IsCertificateError(error)); @@ -155,14 +147,9 @@ TestCompletionCallback callback; CertVerifier::RequestHandle request_handle; - error = verifier_.Verify(cert_chain1.get(), - "www.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(cert_chain1.get(), "www.example.com", std::string(), + 0, NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle); error = callback.WaitForResult(); @@ -172,14 +159,9 @@ ASSERT_EQ(0u, verifier_.inflight_joins()); ASSERT_EQ(1u, verifier_.GetCacheSize()); - error = verifier_.Verify(cert_chain2.get(), - "www.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(cert_chain2.get(), "www.example.com", std::string(), + 0, NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle); error = callback.WaitForResult(); @@ -205,24 +187,14 @@ TestCompletionCallback callback2; CertVerifier::RequestHandle request_handle2; - error = verifier_.Verify(test_cert.get(), - "www.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), 0, + NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle); - error = verifier_.Verify(test_cert.get(), - "www.example.com", - 0, - NULL, - &verify_result2, - callback2.callback(), - &request_handle2, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), 0, + NULL, &verify_result2, callback2.callback(), + &request_handle2, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle2 != NULL); error = callback.WaitForResult(); @@ -245,14 +217,9 @@ CertVerifyResult verify_result; CertVerifier::RequestHandle request_handle; - error = verifier_.Verify(test_cert.get(), - "www.example.com", - 0, - NULL, - &verify_result, - base::Bind(&FailTest), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), 0, + NULL, &verify_result, base::Bind(&FailTest), + &request_handle, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, error); ASSERT_TRUE(request_handle != NULL); verifier_.CancelRequest(request_handle); @@ -262,14 +229,9 @@ // worker thread) is likely to complete by the end of this test. TestCompletionCallback callback; for (int i = 0; i < 5; ++i) { - error = verifier_.Verify(test_cert.get(), - "www2.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www2.example.com", std::string(), + 0, NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle); error = callback.WaitForResult(); @@ -294,8 +256,8 @@ // CertVerifyWorker may be leaked if the main thread shuts down before the // worker thread. ANNOTATE_SCOPED_MEMORY_LEAK; - error = verifier_.Verify(test_cert.get(), "www.example.com", 0, NULL, - &verify_result, callback.callback(), + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), + 0, NULL, &verify_result, callback.callback(), &request_handle, BoundNetLog()); } ASSERT_EQ(ERR_IO_PENDING, error); @@ -327,55 +289,67 @@ // 1 means key1 is greater than key2 int expected_result; } tests[] = { - { // Test for basic equivalence. - MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", - 0, test_list), - MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", - 0, test_list), - 0, - }, - { // Test that different certificates but with the same CA and for + { + // Test for basic equivalence. + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), 0, test_list), + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), 0, test_list), + 0, + }, + { + // Test that different certificates but with the same CA and for // the same host are different validation keys. - MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", - 0, test_list), - MultiThreadedCertVerifier::RequestParams(z_key, a_key, "www.example.test", - 0, test_list), - -1, - }, - { // Test that the same EE certificate for the same host, but with + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), 0, test_list), + MultiThreadedCertVerifier::RequestParams( + z_key, a_key, "www.example.test", std::string(), 0, test_list), + -1, + }, + { + // Test that the same EE certificate for the same host, but with // different chains are different validation keys. - MultiThreadedCertVerifier::RequestParams(a_key, z_key, "www.example.test", - 0, test_list), - MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", - 0, test_list), - 1, - }, - { // The same certificate, with the same chain, but for different + MultiThreadedCertVerifier::RequestParams( + a_key, z_key, "www.example.test", std::string(), 0, test_list), + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), 0, test_list), + 1, + }, + { + // The same certificate, with the same chain, but for different // hosts are different validation keys. - MultiThreadedCertVerifier::RequestParams(a_key, a_key, - "www1.example.test", 0, - test_list), - MultiThreadedCertVerifier::RequestParams(a_key, a_key, - "www2.example.test", 0, - test_list), - -1, - }, - { // The same certificate, chain, and host, but with different flags + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www1.example.test", std::string(), 0, test_list), + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www2.example.test", std::string(), 0, test_list), + -1, + }, + { + // The same certificate, chain, and host, but with different flags // are different validation keys. - MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", - CertVerifier::VERIFY_EV_CERT, - test_list), - MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", - 0, test_list), - 1, - }, - { // Different additional_trust_anchors. - MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", - 0, empty_list), - MultiThreadedCertVerifier::RequestParams(a_key, a_key, "www.example.test", - 0, test_list), - -1, - }, + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), + CertVerifier::VERIFY_EV_CERT, test_list), + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), 0, test_list), + 1, + }, + { + // Different additional_trust_anchors. + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), 0, empty_list), + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), 0, test_list), + -1, + }, + { + // Different OCSP responses. + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", "ocsp response", 0, test_list), + MultiThreadedCertVerifier::RequestParams( + a_key, a_key, "www.example.test", std::string(), 0, test_list), + -1, + }, }; for (size_t i = 0; i < arraysize(tests); ++i) { SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i)); @@ -422,14 +396,9 @@ CertVerifier::RequestHandle request_handle; EXPECT_CALL(trust_provider, GetAdditionalTrustAnchors()) .WillOnce(ReturnRef(empty_cert_list)); - error = verifier_.Verify(test_cert.get(), - "www.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), 0, + NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); Mock::VerifyAndClearExpectations(&trust_provider); ASSERT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle); @@ -441,14 +410,9 @@ // The next Verify() uses the cached result. EXPECT_CALL(trust_provider, GetAdditionalTrustAnchors()) .WillOnce(ReturnRef(empty_cert_list)); - error = verifier_.Verify(test_cert.get(), - "www.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), 0, + NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); Mock::VerifyAndClearExpectations(&trust_provider); EXPECT_EQ(ERR_CERT_COMMON_NAME_INVALID, error); EXPECT_FALSE(request_handle); @@ -459,14 +423,9 @@ // trust anchors will not reuse the cache. EXPECT_CALL(trust_provider, GetAdditionalTrustAnchors()) .WillOnce(ReturnRef(cert_list)); - error = verifier_.Verify(test_cert.get(), - "www.example.com", - 0, - NULL, - &verify_result, - callback.callback(), - &request_handle, - BoundNetLog()); + error = verifier_.Verify(test_cert.get(), "www.example.com", std::string(), 0, + NULL, &verify_result, callback.callback(), + &request_handle, BoundNetLog()); Mock::VerifyAndClearExpectations(&trust_provider); ASSERT_EQ(ERR_IO_PENDING, error); EXPECT_TRUE(request_handle);
diff --git a/net/cert/nss_cert_database.cc b/net/cert/nss_cert_database.cc index e1b3198d..8aaf759 100644 --- a/net/cert/nss_cert_database.cc +++ b/net/cert/nss_cert_database.cc
@@ -178,12 +178,11 @@ } } -int NSSCertDatabase::ImportFromPKCS12( - CryptoModule* module, - const std::string& data, - const base::string16& password, - bool is_extractable, - net::CertificateList* imported_certs) { +int NSSCertDatabase::ImportFromPKCS12(CryptoModule* module, + const std::string& data, + const base::string16& password, + bool is_extractable, + CertificateList* imported_certs) { DVLOG(1) << __func__ << " " << PK11_GetModuleID(module->os_module_handle()) << ":" << PK11_GetSlotID(module->os_module_handle()); @@ -192,7 +191,7 @@ password, is_extractable, imported_certs); - if (result == net::OK) + if (result == OK) NotifyObserversOfCertAdded(NULL); return result;
diff --git a/net/cert/nss_cert_database_unittest.cc b/net/cert/nss_cert_database_unittest.cc index 3c83d05..7c97f11b 100644 --- a/net/cert/nss_cert_database_unittest.cc +++ b/net/cert/nss_cert_database_unittest.cc
@@ -75,9 +75,7 @@ } protected: - net::CryptoModule* GetPublicModule() { - return public_module_.get(); - } + CryptoModule* GetPublicModule() { return public_module_.get(); } static std::string ReadTestFile(const std::string& name) { std::string result; @@ -116,7 +114,7 @@ scoped_ptr<NSSCertDatabase> cert_db_; const CertificateList empty_cert_list_; crypto::ScopedTestNSSDB test_nssdb_; - scoped_refptr<net::CryptoModule> public_module_; + scoped_refptr<CryptoModule> public_module_; }; TEST_F(CertDatabaseNSSTest, ListCertsSync) { @@ -556,12 +554,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(goog_cert.get(), - "www.google.com", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(goog_cert.get(), "www.google.com", std::string(), + flags, NULL, empty_cert_list_, &verify_result); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result.cert_status); } @@ -587,12 +582,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(puny_cert.get(), - "xn--wgv71a119e.com", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(puny_cert.get(), "xn--wgv71a119e.com", std::string(), + flags, NULL, empty_cert_list_, &verify_result); EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result.cert_status); } @@ -619,12 +611,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(puny_cert.get(), - "xn--wgv71a119e.com", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(puny_cert.get(), "xn--wgv71a119e.com", std::string(), + flags, NULL, empty_cert_list_, &verify_result); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result.cert_status); } @@ -655,12 +644,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result.cert_status); } @@ -697,12 +683,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result); EXPECT_EQ(ERR_CERT_REVOKED, error); EXPECT_EQ(CERT_STATUS_REVOKED, verify_result.cert_status); } @@ -745,12 +728,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result.cert_status); @@ -776,12 +756,8 @@ // Server cert should fail to verify. CertVerifyResult verify_result2; - error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result2); + error = verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result2); EXPECT_EQ(ERR_CERT_REVOKED, error); EXPECT_EQ(CERT_STATUS_REVOKED, verify_result2.cert_status); } @@ -821,12 +797,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result.cert_status); @@ -836,12 +809,8 @@ // Server cert should fail to verify. CertVerifyResult verify_result2; - error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result2); + error = verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result2); EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result2.cert_status); } @@ -891,12 +860,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result.cert_status); @@ -906,12 +872,8 @@ // Server cert should fail to verify. CertVerifyResult verify_result2; - error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result2); + error = verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result2); EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, error); EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, verify_result2.cert_status); } @@ -955,12 +917,9 @@ scoped_refptr<CertVerifyProc> verify_proc(new CertVerifyProcNSS()); int flags = 0; CertVerifyResult verify_result; - int error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result); + int error = + verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result); EXPECT_EQ(ERR_CERT_REVOKED, error); EXPECT_EQ(CERT_STATUS_REVOKED, verify_result.cert_status); @@ -970,12 +929,8 @@ // Server cert should verify. CertVerifyResult verify_result2; - error = verify_proc->Verify(certs[0].get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result2); + error = verify_proc->Verify(certs[0].get(), "127.0.0.1", std::string(), flags, + NULL, empty_cert_list_, &verify_result2); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result2.cert_status); }
diff --git a/net/cert/single_request_cert_verifier.cc b/net/cert/single_request_cert_verifier.cc index 909af07d..afd1ac2 100644 --- a/net/cert/single_request_cert_verifier.cc +++ b/net/cert/single_request_cert_verifier.cc
@@ -27,6 +27,7 @@ int SingleRequestCertVerifier::Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, CertVerifyResult* verify_result, @@ -40,7 +41,7 @@ // We need to be notified of completion before |callback| is called, so that // we can clear out |cur_request_*|. int rv = cert_verifier_->Verify( - cert, hostname, flags, crl_set, verify_result, + cert, hostname, ocsp_response, flags, crl_set, verify_result, base::Bind(&SingleRequestCertVerifier::OnVerifyCompletion, base::Unretained(this)), &request, net_log);
diff --git a/net/cert/single_request_cert_verifier.h b/net/cert/single_request_cert_verifier.h index 6b19281..67bb0888 100644 --- a/net/cert/single_request_cert_verifier.h +++ b/net/cert/single_request_cert_verifier.h
@@ -26,6 +26,7 @@ // upon success. See CertVerifier::Verify() for details. int Verify(X509Certificate* cert, const std::string& hostname, + const std::string& ocsp_response, int flags, CRLSet* crl_set, CertVerifyResult* verify_result,
diff --git a/net/cert/test_root_certs_unittest.cc b/net/cert/test_root_certs_unittest.cc index 1bbb8fc..e55c147c 100644 --- a/net/cert/test_root_certs_unittest.cc +++ b/net/cert/test_root_certs_unittest.cc
@@ -89,12 +89,9 @@ int flags = 0; CertVerifyResult bad_verify_result; scoped_refptr<CertVerifyProc> verify_proc(CertVerifyProc::CreateDefault()); - int bad_status = verify_proc->Verify(test_cert.get(), - "127.0.0.1", - flags, - NULL, - CertificateList(), - &bad_verify_result); + int bad_status = + verify_proc->Verify(test_cert.get(), "127.0.0.1", std::string(), flags, + NULL, CertificateList(), &bad_verify_result); EXPECT_NE(OK, bad_status); EXPECT_NE(0u, bad_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID); @@ -106,12 +103,9 @@ // Test that the certificate verification now succeeds, because the // TestRootCerts is successfully imbuing trust. CertVerifyResult good_verify_result; - int good_status = verify_proc->Verify(test_cert.get(), - "127.0.0.1", - flags, - NULL, - CertificateList(), - &good_verify_result); + int good_status = + verify_proc->Verify(test_cert.get(), "127.0.0.1", std::string(), flags, + NULL, CertificateList(), &good_verify_result); EXPECT_EQ(OK, good_status); EXPECT_EQ(0u, good_verify_result.cert_status); @@ -122,12 +116,9 @@ // revert to their original state, and don't linger. If trust status // lingers, it will likely break other tests in net_unittests. CertVerifyResult restored_verify_result; - int restored_status = verify_proc->Verify(test_cert.get(), - "127.0.0.1", - flags, - NULL, - CertificateList(), - &restored_verify_result); + int restored_status = + verify_proc->Verify(test_cert.get(), "127.0.0.1", std::string(), flags, + NULL, CertificateList(), &restored_verify_result); EXPECT_NE(OK, restored_status); EXPECT_NE(0u, restored_verify_result.cert_status & CERT_STATUS_AUTHORITY_INVALID);
diff --git a/net/cert/x509_certificate_mac.cc b/net/cert/x509_certificate_mac.cc index 10cfb56..c02f33b1 100644 --- a/net/cert/x509_certificate_mac.cc +++ b/net/cert/x509_certificate_mac.cc
@@ -497,7 +497,9 @@ SecKeyRef key; OSStatus status = SecCertificateCopyPublicKey(cert_handle, &key); if (status) { - NOTREACHED() << "SecCertificateCopyPublicKey failed: " << status; + // SecCertificateCopyPublicKey may fail if the certificate has an invalid + // key. See https://crbug.com/472291. + LOG(WARNING) << "SecCertificateCopyPublicKey failed: " << status; return; } ScopedCFTypeRef<SecKeyRef> scoped_key(key);
diff --git a/net/cert/x509_certificate_unittest.cc b/net/cert/x509_certificate_unittest.cc index 2ff572d4..4fdb9a7 100644 --- a/net/cert/x509_certificate_unittest.cc +++ b/net/cert/x509_certificate_unittest.cc
@@ -1158,12 +1158,23 @@ size_t expected_bits; X509Certificate::PublicKeyType expected_type; } kPublicKeyInfoTestData[] = { - { "768-rsa-ee-by-768-rsa-intermediate.pem", 768, - X509Certificate::kPublicKeyTypeRSA }, - { "1024-rsa-ee-by-768-rsa-intermediate.pem", 1024, - X509Certificate::kPublicKeyTypeRSA }, - { "prime256v1-ecdsa-ee-by-1024-rsa-intermediate.pem", 256, - X509Certificate::kPublicKeyTypeECDSA }, + {"768-rsa-ee-by-768-rsa-intermediate.pem", + 768, + X509Certificate::kPublicKeyTypeRSA}, + {"1024-rsa-ee-by-768-rsa-intermediate.pem", + 1024, + X509Certificate::kPublicKeyTypeRSA}, + {"prime256v1-ecdsa-ee-by-1024-rsa-intermediate.pem", + 256, + X509Certificate::kPublicKeyTypeECDSA}, +#if defined(OS_MACOSX) && !defined(OS_IOS) + // OS X has an key length limit of 4096 bits. This should manifest as an + // unknown key. If a future version of OS X changes this, large_key.pem may + // need to be renegerated with a larger key. See https://crbug.com/472291. + {"large_key.pem", 0, X509Certificate::kPublicKeyTypeUnknown}, +#else + {"large_key.pem", 4104, X509Certificate::kPublicKeyTypeRSA}, +#endif }; class X509CertificatePublicKeyInfoTest
diff --git a/net/cert_net/cert_net_fetcher_impl_unittest.cc b/net/cert_net/cert_net_fetcher_impl_unittest.cc index c803b4c..e602418 100644 --- a/net/cert_net/cert_net_fetcher_impl_unittest.cc +++ b/net/cert_net/cert_net_fetcher_impl_unittest.cc
@@ -136,7 +136,7 @@ public: CertNetFetcherImplTest() : test_server_(SpawnedTestServer::TYPE_HTTP, - net::SpawnedTestServer::kLocalhost, + SpawnedTestServer::kLocalhost, base::FilePath(kDocRoot)) { context_.set_network_delegate(&network_delegate_); }
diff --git a/net/cert_net/nss_ocsp_unittest.cc b/net/cert_net/nss_ocsp_unittest.cc index 155bcb2..be72e82 100644 --- a/net/cert_net/nss_ocsp_unittest.cc +++ b/net/cert_net/nss_ocsp_unittest.cc
@@ -40,20 +40,20 @@ "Content-type: application/pkix-cert\0" "\0"; -class AiaResponseHandler : public net::URLRequestInterceptor { +class AiaResponseHandler : public URLRequestInterceptor { public: AiaResponseHandler(const std::string& headers, const std::string& cert_data) : headers_(headers), cert_data_(cert_data), request_count_(0) {} ~AiaResponseHandler() override {} - // net::URLRequestInterceptor implementation: - net::URLRequestJob* MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { + // URLRequestInterceptor implementation: + URLRequestJob* MaybeInterceptRequest( + URLRequest* request, + NetworkDelegate* network_delegate) const override { ++const_cast<AiaResponseHandler*>(this)->request_count_; - return new net::URLRequestTestJob( - request, network_delegate, headers_, cert_data_, true); + return new URLRequestTestJob(request, network_delegate, headers_, + cert_data_, true); } int request_count() const { return request_count_; } @@ -141,14 +141,9 @@ CertVerifier::RequestHandle request_handle; int flags = CertVerifier::VERIFY_CERT_IO_ENABLED; - int error = verifier()->Verify(test_cert.get(), - "aia-host.invalid", - flags, - NULL, - &verify_result, - test_callback.callback(), - &request_handle, - BoundNetLog()); + int error = verifier()->Verify( + test_cert.get(), "aia-host.invalid", std::string(), flags, NULL, + &verify_result, test_callback.callback(), &request_handle, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, error); error = test_callback.WaitForResult();
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc index 5932c23..d957976 100644 --- a/net/cookies/canonical_cookie.cc +++ b/net/cookies/canonical_cookie.cc
@@ -104,8 +104,7 @@ // Compares cookies using name, domain and path, so that "equivalent" cookies // (per RFC 2965) are equal to each other. -int PartialCookieOrdering(const net::CanonicalCookie& a, - const net::CanonicalCookie& b) { +int PartialCookieOrdering(const CanonicalCookie& a, const CanonicalCookie& b) { int diff = a.Name().compare(b.Name()); if (diff != 0) return diff;
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc index d335ae4..4f9b8d7 100644 --- a/net/cookies/cookie_monster.cc +++ b/net/cookies/cookie_monster.cc
@@ -165,15 +165,14 @@ // Compare cookies using name, domain and path, so that "equivalent" cookies // (per RFC 2965) are equal to each other. -bool PartialDiffCookieSorter(const net::CanonicalCookie& a, - const net::CanonicalCookie& b) { +bool PartialDiffCookieSorter(const CanonicalCookie& a, + const CanonicalCookie& b) { return a.PartialCompare(b); } // This is a stricter ordering than PartialDiffCookieOrdering, where all fields // are used. -bool FullDiffCookieSorter(const net::CanonicalCookie& a, - const net::CanonicalCookie& b) { +bool FullDiffCookieSorter(const CanonicalCookie& a, const CanonicalCookie& b) { return a.FullCompare(b); } @@ -1164,10 +1163,10 @@ bool CookieMonster::ImportCookies(const CookieList& list) { base::AutoLock autolock(lock_); InitIfNecessary(); - for (net::CookieList::const_iterator iter = list.begin(); iter != list.end(); + for (CookieList::const_iterator iter = list.begin(); iter != list.end(); ++iter) { scoped_ptr<CanonicalCookie> cookie(new CanonicalCookie(*iter)); - net::CookieOptions options; + CookieOptions options; options.set_include_httponly(); options.set_include_first_party_only(); if (!SetCanonicalCookie(&cookie, cookie->CreationDate(), options)) @@ -1930,7 +1929,7 @@ bool CookieMonster::SetCanonicalCookies(const CookieList& list) { base::AutoLock autolock(lock_); - net::CookieOptions options; + CookieOptions options; options.set_include_httponly(); for (CookieList::const_iterator it = list.begin(); it != list.end(); ++it) {
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc index 95ccbad..0214f68f 100644 --- a/net/cookies/cookie_monster_perftest.cc +++ b/net/cookies/cookie_monster_perftest.cc
@@ -73,7 +73,7 @@ EXPECT_TRUE(success); BaseCallback::Run(); } - net::CookieOptions options_; + CookieOptions options_; }; class GetCookiesCallback : public BaseCallback { @@ -92,7 +92,7 @@ BaseCallback::Run(); } std::string cookies_; - net::CookieOptions options_; + CookieOptions options_; }; } // namespace
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc index c76c03f..61dbd09 100644 --- a/net/cookies/cookie_monster_unittest.cc +++ b/net/cookies/cookie_monster_unittest.cc
@@ -2064,8 +2064,8 @@ std::vector<CanonicalCookie*> out_cookies; base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(&net::LoadedCallbackTask::Run, - new net::LoadedCallbackTask(loaded_callback, out_cookies))); + base::Bind(&LoadedCallbackTask::Run, + new LoadedCallbackTask(loaded_callback, out_cookies))); } void LoadCookiesForKey(const std::string& key, @@ -2466,7 +2466,7 @@ ASSERT_TRUE(++it == cookies.end()); GetCookieListCallback callback(&other_thread_); base::Closure task = - base::Bind(&net::MultiThreadedCookieMonsterTest::GetAllCookiesTask, + base::Bind(&MultiThreadedCookieMonsterTest::GetAllCookiesTask, base::Unretained(this), cm, &callback); RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); @@ -2488,7 +2488,7 @@ ASSERT_TRUE(++it == cookies.end()); GetCookieListCallback callback(&other_thread_); base::Closure task = - base::Bind(&net::MultiThreadedCookieMonsterTest::GetAllCookiesForURLTask, + base::Bind(&MultiThreadedCookieMonsterTest::GetAllCookiesForURLTask, base::Unretained(this), cm, url_google_, &callback); RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); @@ -2512,7 +2512,7 @@ ASSERT_TRUE(++it == cookies.end()); GetCookieListCallback callback(&other_thread_); base::Closure task = base::Bind( - &net::MultiThreadedCookieMonsterTest::GetAllCookiesForURLWithOptionsTask, + &MultiThreadedCookieMonsterTest::GetAllCookiesForURLWithOptionsTask, base::Unretained(this), cm, url_google_, options, &callback); RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); @@ -2530,7 +2530,7 @@ false, false, COOKIE_PRIORITY_DEFAULT)); ResultSavingCookieCallback<bool> callback(&other_thread_); base::Closure task = - base::Bind(&net::MultiThreadedCookieMonsterTest::SetCookieWithDetailsTask, + base::Bind(&MultiThreadedCookieMonsterTest::SetCookieWithDetailsTask, base::Unretained(this), cm, url_google_foo_, &callback); RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); @@ -2546,10 +2546,10 @@ Time())); EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options)); ResultSavingCookieCallback<int> callback(&other_thread_); - base::Closure task = base::Bind( - &net::MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenTask, - base::Unretained(this), cm, now - TimeDelta::FromDays(99), Time(), - &callback); + base::Closure task = + base::Bind(&MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenTask, + base::Unretained(this), cm, now - TimeDelta::FromDays(99), + Time(), &callback); RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); EXPECT_EQ(1, callback.result()); @@ -2563,7 +2563,7 @@ EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options)); ResultSavingCookieCallback<int> callback(&other_thread_); base::Closure task = - base::Bind(&net::MultiThreadedCookieMonsterTest::DeleteAllForHostTask, + base::Bind(&MultiThreadedCookieMonsterTest::DeleteAllForHostTask, base::Unretained(this), cm, url_google_, &callback); RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); @@ -2604,7 +2604,7 @@ // 2. Second set of deletions. base::Closure task = base::Bind( - &net::MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenForHostTask, + &MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenForHostTask, base::Unretained(this), cm, ago1, Time(), url_google_, &callback); RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); @@ -2623,9 +2623,9 @@ ResultSavingCookieCallback<bool> callback(&other_thread_); cookies = GetAllCookies(cm.get()); it = cookies.begin(); - base::Closure task = base::Bind( - &net::MultiThreadedCookieMonsterTest::DeleteCanonicalCookieTask, - base::Unretained(this), cm, *it, &callback); + base::Closure task = + base::Bind(&MultiThreadedCookieMonsterTest::DeleteCanonicalCookieTask, + base::Unretained(this), cm, *it, &callback); RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); EXPECT_TRUE(callback.result()); @@ -2831,9 +2831,9 @@ scoped_refptr<CookieMonster> monster_; }; -void RecordCookieChanges(std::vector<net::CanonicalCookie>* out_cookies, +void RecordCookieChanges(std::vector<CanonicalCookie>* out_cookies, std::vector<bool>* out_removes, - const net::CanonicalCookie& cookie, + const CanonicalCookie& cookie, bool removed) { DCHECK(out_cookies); out_cookies->push_back(cookie); @@ -2842,7 +2842,7 @@ } TEST_F(CookieMonsterNotificationTest, NoNotifyWithNoCookie) { - std::vector<net::CanonicalCookie> cookies; + std::vector<CanonicalCookie> cookies; scoped_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( test_url_, "abc", @@ -2852,7 +2852,7 @@ } TEST_F(CookieMonsterNotificationTest, NoNotifyWithInitialCookie) { - std::vector<net::CanonicalCookie> cookies; + std::vector<CanonicalCookie> cookies; SetCookie(monster(), test_url_, "abc=def"); base::MessageLoop::current()->RunUntilIdle(); scoped_ptr<CookieStore::CookieChangedSubscription> sub( @@ -2864,7 +2864,7 @@ } TEST_F(CookieMonsterNotificationTest, NotifyOnSet) { - std::vector<net::CanonicalCookie> cookies; + std::vector<CanonicalCookie> cookies; std::vector<bool> removes; scoped_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( @@ -2881,7 +2881,7 @@ } TEST_F(CookieMonsterNotificationTest, NotifyOnDelete) { - std::vector<net::CanonicalCookie> cookies; + std::vector<CanonicalCookie> cookies; std::vector<bool> removes; scoped_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( @@ -2903,7 +2903,7 @@ } TEST_F(CookieMonsterNotificationTest, NotifyOnUpdate) { - std::vector<net::CanonicalCookie> cookies; + std::vector<CanonicalCookie> cookies; std::vector<bool> removes; scoped_ptr<CookieStore::CookieChangedSubscription> sub( monster()->AddCallbackForCookie( @@ -2931,8 +2931,8 @@ } TEST_F(CookieMonsterNotificationTest, MultipleNotifies) { - std::vector<net::CanonicalCookie> cookies0; - std::vector<net::CanonicalCookie> cookies1; + std::vector<CanonicalCookie> cookies0; + std::vector<CanonicalCookie> cookies1; scoped_ptr<CookieStore::CookieChangedSubscription> sub0( monster()->AddCallbackForCookie( test_url_, "abc", @@ -2952,8 +2952,8 @@ } TEST_F(CookieMonsterNotificationTest, MultipleSameNotifies) { - std::vector<net::CanonicalCookie> cookies0; - std::vector<net::CanonicalCookie> cookies1; + std::vector<CanonicalCookie> cookies0; + std::vector<CanonicalCookie> cookies1; scoped_ptr<CookieStore::CookieChangedSubscription> sub0( monster()->AddCallbackForCookie( test_url_, "abc",
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h index 8a666c93..fa429fd 100644 --- a/net/cookies/cookie_store_unittest.h +++ b/net/cookies/cookie_store_unittest.h
@@ -1107,10 +1107,9 @@ EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B")); this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_)); StringResultCookieCallback callback(&this->other_thread_); - base::Closure task = base::Bind( - &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesTask, - base::Unretained(this), - cs, this->url_google_, &callback); + base::Closure task = + base::Bind(&MultiThreadedCookieStoreTest<TypeParam>::GetCookiesTask, + base::Unretained(this), cs, this->url_google_, &callback); this->RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); EXPECT_EQ("A=B", callback.result()); @@ -1126,9 +1125,8 @@ "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options)); StringResultCookieCallback callback(&this->other_thread_); base::Closure task = base::Bind( - &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithOptionsTask, - base::Unretained(this), - cs, this->url_google_, options, &callback); + &MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithOptionsTask, + base::Unretained(this), cs, this->url_google_, options, &callback); this->RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); EXPECT_EQ("A=B", callback.result()); @@ -1143,9 +1141,8 @@ this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options)); ResultSavingCookieCallback<bool> callback(&this->other_thread_); base::Closure task = base::Bind( - &net::MultiThreadedCookieStoreTest<TypeParam>::SetCookieWithOptionsTask, - base::Unretained(this), - cs, this->url_google_, "A=B", options, &callback); + &MultiThreadedCookieStoreTest<TypeParam>::SetCookieWithOptionsTask, + base::Unretained(this), cs, this->url_google_, "A=B", options, &callback); this->RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); EXPECT_TRUE(callback.result()); @@ -1162,10 +1159,9 @@ EXPECT_TRUE( this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options)); NoResultCookieCallback callback(&this->other_thread_); - base::Closure task = base::Bind( - &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteCookieTask, - base::Unretained(this), - cs, this->url_google_, "A", &callback); + base::Closure task = + base::Bind(&MultiThreadedCookieStoreTest<TypeParam>::DeleteCookieTask, + base::Unretained(this), cs, this->url_google_, "A", &callback); this->RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); } @@ -1188,9 +1184,8 @@ this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options)); ResultSavingCookieCallback<int> callback(&this->other_thread_); base::Closure task = base::Bind( - &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteSessionCookiesTask, - base::Unretained(this), - cs, &callback); + &MultiThreadedCookieStoreTest<TypeParam>::DeleteSessionCookiesTask, + base::Unretained(this), cs, &callback); this->RunOnOtherThread(task); EXPECT_TRUE(callback.did_run()); EXPECT_EQ(1, callback.result());
diff --git a/net/cookies/cookie_util_unittest.cc b/net/cookies/cookie_util_unittest.cc index 392faf1..ae666ba59 100644 --- a/net/cookies/cookie_util_unittest.cc +++ b/net/cookies/cookie_util_unittest.cc
@@ -4,22 +4,24 @@ #include <string> #include <utility> -#include <vector> #include "base/basictypes.h" +#include "base/strings/string_split.h" #include "net/cookies/cookie_util.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + namespace { struct RequestCookieParsingTest { std::string str; - std::vector<std::pair<std::string, std::string> > parsed; + base::StringPairs parsed; }; -net::cookie_util::ParsedRequestCookies MakeParsedRequestCookies( - const std::vector<std::pair<std::string, std::string> >& data) { - net::cookie_util::ParsedRequestCookies parsed; +cookie_util::ParsedRequestCookies MakeParsedRequestCookies( + const base::StringPairs& data) { + cookie_util::ParsedRequestCookies parsed; for (size_t i = 0; i < data.size(); i++) { parsed.push_back(std::make_pair(base::StringPiece(data[i].first), base::StringPiece(data[i].second))); @@ -27,20 +29,17 @@ return parsed; } -void CheckParse( - const std::string& str, - const std::vector<std::pair<std::string, std::string> >& parsed_expected) { - net::cookie_util::ParsedRequestCookies parsed; - net::cookie_util::ParseRequestCookieLine(str, &parsed); +void CheckParse(const std::string& str, + const base::StringPairs& parsed_expected) { + cookie_util::ParsedRequestCookies parsed; + cookie_util::ParseRequestCookieLine(str, &parsed); EXPECT_EQ(MakeParsedRequestCookies(parsed_expected), parsed); } -void CheckSerialize( - const std::vector<std::pair<std::string, std::string> >& parsed, - const std::string& str_expected) { - net::cookie_util::ParsedRequestCookies prc = - MakeParsedRequestCookies(parsed); - EXPECT_EQ(str_expected, net::cookie_util::SerializeRequestCookieLine(prc)); +void CheckSerialize(const base::StringPairs& parsed, + const std::string& str_expected) { + cookie_util::ParsedRequestCookies prc = MakeParsedRequestCookies(parsed); + EXPECT_EQ(str_expected, cookie_util::SerializeRequestCookieLine(prc)); } TEST(CookieUtilTest, TestDomainIsHostOnly) { @@ -55,7 +54,7 @@ for (size_t i = 0; i < arraysize(tests); ++i) { EXPECT_EQ(tests[i].is_host_only, - net::cookie_util::DomainIsHostOnly(tests[i].str)); + cookie_util::DomainIsHostOnly(tests[i].str)); } } @@ -137,7 +136,7 @@ base::Time parsed_time; for (size_t i = 0; i < arraysize(tests); ++i) { - parsed_time = net::cookie_util::ParseCookieTime(tests[i].str); + parsed_time = cookie_util::ParseCookieTime(tests[i].str); if (!tests[i].valid) { EXPECT_FALSE(!parsed_time.is_null()) << tests[i].str; continue; @@ -197,15 +196,17 @@ // Note: registry_controlled_domains::GetDomainAndRegistry is tested in its // own unittests. EXPECT_EQ("example.com", - net::cookie_util::GetEffectiveDomain("http", "www.example.com")); + cookie_util::GetEffectiveDomain("http", "www.example.com")); EXPECT_EQ("example.com", - net::cookie_util::GetEffectiveDomain("https", "www.example.com")); + cookie_util::GetEffectiveDomain("https", "www.example.com")); EXPECT_EQ("example.com", - net::cookie_util::GetEffectiveDomain("ws", "www.example.com")); + cookie_util::GetEffectiveDomain("ws", "www.example.com")); EXPECT_EQ("example.com", - net::cookie_util::GetEffectiveDomain("wss", "www.example.com")); + cookie_util::GetEffectiveDomain("wss", "www.example.com")); EXPECT_EQ("www.example.com", - net::cookie_util::GetEffectiveDomain("ftp", "www.example.com")); + cookie_util::GetEffectiveDomain("ftp", "www.example.com")); } } // namespace + +} // namespace net
diff --git a/net/data/ssl/certificates/large_key.pem b/net/data/ssl/certificates/large_key.pem new file mode 100644 index 0000000..8ccb287b --- /dev/null +++ b/net/data/ssl/certificates/large_key.pem
@@ -0,0 +1,112 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + fa:ba:a5:10:ef:85:bb:70 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1 + Validity + Not Before: Apr 23 21:32:21 2015 GMT + Not After : Apr 20 21:32:21 2025 GMT + Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (4104 bit) + Modulus (4104 bit): + 00:c9:98:35:7d:a5:d4:41:1b:83:60:84:76:14:c2: + 0d:a6:7f:e7:52:15:a5:7c:96:96:56:b8:98:f9:bc: + 94:56:23:14:f2:74:05:e6:ba:d9:3a:58:dd:b5:03: + 9c:d1:f5:47:76:c2:45:78:f9:b8:e1:44:40:45:08: + 2d:d1:ff:c3:bf:d7:b2:4a:94:6a:61:37:dd:cb:66: + 22:28:8d:cc:5f:35:dd:9a:1a:d5:0e:cc:36:76:ae: + 65:a2:96:d3:cd:de:8d:b4:c9:28:a8:a8:2d:45:89: + 98:aa:7d:9e:12:7b:e1:a5:ba:d9:56:8a:4a:1f:1c: + 7d:e2:cf:f5:f0:54:38:6d:47:4c:1d:1c:22:3c:74: + 72:4b:fd:c2:97:66:b1:9c:8e:c3:d6:88:5e:6a:ed: + c9:fe:b7:d9:ef:03:25:5d:da:4a:ab:5e:fa:f4:a8: + 87:30:90:00:85:a6:5b:40:77:b6:34:64:63:58:05: + cd:1e:58:d6:fd:b2:13:51:ba:a4:9f:7f:e3:db:88: + 88:58:1f:df:5f:67:cc:49:0a:bb:e0:ce:d9:3f:ce: + 26:20:1e:35:f3:f0:8a:bd:8b:8b:4f:16:80:53:4e: + 44:3b:1a:9e:60:6b:ff:cf:f7:9f:40:bf:d2:86:e4: + 79:39:3a:d7:5a:bd:d0:63:cf:f6:54:e1:9e:09:e7: + 63:8a:17:33:bf:f2:5f:ec:ee:45:18:52:ee:e7:23: + a2:a8:af:d2:85:4b:bb:f9:12:ba:35:22:d2:5e:9c: + 42:2d:66:e1:01:02:d4:0f:ff:86:1c:91:8f:55:9c: + 9f:24:4e:17:c8:23:c1:a7:4e:39:ed:4b:dc:b8:c4: + 3f:7d:c9:0f:ff:01:40:4d:dd:9a:55:29:84:f8:52: + 72:da:38:32:9a:ef:2b:2e:67:5b:d2:2d:70:46:91: + 42:79:22:a2:08:c0:fd:24:95:9e:04:a6:5c:9e:c0: + ed:25:2a:57:62:17:b7:c0:12:d4:8b:59:f3:db:8b: + cd:95:4f:d9:32:f2:f0:e1:14:9b:db:73:e7:b4:97: + a6:90:f7:0d:cb:59:93:94:12:2a:c1:28:7d:3c:bd: + b5:7e:bb:13:c0:4c:ef:ce:20:3d:3b:4f:84:25:77: + dc:1f:0f:08:dd:76:9c:ad:7d:00:2f:23:42:6a:37: + e9:d0:6b:8e:9a:6f:3b:46:09:74:23:43:a9:58:46: + 62:33:69:2a:0c:df:cd:6c:75:88:f1:01:3d:67:e0: + a8:e3:bd:23:03:66:f3:11:f2:07:a8:bf:4b:c9:81: + ce:a9:ed:8d:48:a6:10:15:fb:79:27:ae:2e:8f:35: + c5:39:12:eb:f2:b7:28:d3:b3:e7:4c:71:d8:e1:d1: + f7:39:94:87 + Exponent: 65537 (0x10001) + Signature Algorithm: sha256WithRSAEncryption + 2d:3b:5f:58:30:58:97:65:d0:36:a6:03:0c:6b:bc:a6:5b:e7: + 8f:a3:a7:05:5d:db:9b:3f:0e:22:89:3e:e1:00:91:3c:17:ab: + 10:10:80:f5:d1:f9:cb:d7:38:9e:bc:36:a0:31:d2:e3:2f:98: + 62:d8:a2:cd:73:7c:56:29:b0:c0:41:01:71:50:70:7a:b2:9d: + b6:ad:13:71:d8:19:7d:4f:7a:be:4b:36:2e:d7:f7:81:53:a7: + e0:7f:04:77:09:84:a3:56:22:48:7e:6d:ca:20:12:ed:a7:da: + 29:cf:46:46:81:8f:97:4b:17:63:25:f2:18:48:c1:82:21:c7: + be:4f:54:29:88:29:78:d0:be:98:9c:d9:4f:76:e7:6b:a2:10: + 4a:ce:45:02:c7:5e:5a:ac:5f:0e:4b:a3:51:a9:ec:7a:3f:a0: + 51:49:75:bc:af:f4:89:88:35:69:65:15:a5:33:c5:2f:1e:c5: + 30:98:6b:04:14:b9:29:b5:31:76:23:88:32:72:29:e4:16:de: + bb:95:d6:bb:48:e5:38:37:57:6e:8a:2f:c0:64:2c:01:4d:e6: + 69:9e:ae:4a:39:87:96:5d:50:e6:25:08:46:77:ea:da:4d:b2: + bd:5e:44:ca:e2:46:b1:7a:4a:3d:83:16:a9:a6:e5:c4:ef:fc: + af:77:58:6e:3b:cd:b3:b3:0e:d2:59:d2:be:16:ac:64:fa:f7: + b1:06:02:7d:c9:8a:06:65:73:da:d8:a8:02:41:d5:68:41:7a: + 0f:a7:5c:90:b3:6f:01:66:65:96:4c:50:bd:c7:38:67:61:21: + 52:dc:a9:f0:f7:0b:16:95:2d:5d:b8:0b:da:9a:fe:f8:4c:e9: + fa:6a:32:a7:d4:67:7b:21:45:7a:4e:7c:a6:fa:cb:65:3d:8f: + 38:90:5a:29:7d:7f:21:32:6d:c6:61:70:f9:a8:4e:3f:9b:3c: + f0:4b:40:d6:7d:e5:d6:31:08:ff:29:21:f9:e7:81:36:1a:86: + d5:96:06:1d:1e:b1:fc:4c:e3:6d:ce:3a:2c:16:b8:03:76:f3: + 70:77:15:ea:b5:32:c3:f5:9f:a6:61:e1:29:bb:88:2c:a0:cf: + 05:f5:3d:97:ae:b5:b9:01:e8:2f:5e:54:17:2e:09:5b:ea:d0: + 4a:95:65:d9:cf:83:3a:bc:1d:7d:28:4b:7b:8d:5c:ef:8a:06: + f9:64:b5:ec:3f:73:fc:6c:58:cc:57:da:d3:5d:5e:b5:58:43: + 53:27:f0:49:01:e4:45:8d:eb:68:f3:40:fc:ec:63:62:ce:c3: + d9:97:d3:a3:51:8c:c5:09:a9:81:6e:23:e0:6a:1f:02:b0:f8: + b0:40:0c:2f:ea:ee:c2:1f:1b +-----BEGIN CERTIFICATE----- +MIIFPjCCAyUCCQD6uqUQ74W7cDANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJV +UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQ +MA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMB4XDTE1MDQyMzIx +MzIyMVoXDTI1MDQyMDIxMzIyMVowYDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh +bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg +Q0ExEjAQBgNVBAMMCTEyNy4wLjAuMTCCAiMwDQYJKoZIhvcNAQEBBQADggIQADCC +AgsCggICAMmYNX2l1EEbg2CEdhTCDaZ/51IVpXyWlla4mPm8lFYjFPJ0Bea62TpY +3bUDnNH1R3bCRXj5uOFEQEUILdH/w7/XskqUamE33ctmIiiNzF813Zoa1Q7MNnau +ZaKW083ejbTJKKioLUWJmKp9nhJ74aW62VaKSh8cfeLP9fBUOG1HTB0cIjx0ckv9 +wpdmsZyOw9aIXmrtyf632e8DJV3aSqte+vSohzCQAIWmW0B3tjRkY1gFzR5Y1v2y +E1G6pJ9/49uIiFgf319nzEkKu+DO2T/OJiAeNfPwir2Li08WgFNORDsanmBr/8/3 +n0C/0obkeTk611q90GPP9lThngnnY4oXM7/yX+zuRRhS7ucjoqiv0oVLu/kSujUi +0l6cQi1m4QEC1A//hhyRj1WcnyROF8gjwadOOe1L3LjEP33JD/8BQE3dmlUphPhS +cto4MprvKy5nW9ItcEaRQnkiogjA/SSVngSmXJ7A7SUqV2IXt8AS1ItZ89uLzZVP +2TLy8OEUm9tz57SXppD3DctZk5QSKsEofTy9tX67E8BM784gPTtPhCV33B8PCN12 +nK19AC8jQmo36dBrjppvO0YJdCNDqVhGYjNpKgzfzWx1iPEBPWfgqOO9IwNm8xHy +B6i/S8mBzqntjUimEBX7eSeuLo81xTkS6/K3KNOz50xx2OHR9zmUhwIDAQABMA0G +CSqGSIb3DQEBCwUAA4ICAgAtO19YMFiXZdA2pgMMa7ymW+ePo6cFXdubPw4iiT7h +AJE8F6sQEID10fnL1zievDagMdLjL5hi2KLNc3xWKbDAQQFxUHB6sp22rRNx2Bl9 +T3q+SzYu1/eBU6fgfwR3CYSjViJIfm3KIBLtp9opz0ZGgY+XSxdjJfIYSMGCIce+ +T1QpiCl40L6YnNlPdudrohBKzkUCx15arF8OS6NRqex6P6BRSXW8r/SJiDVpZRWl +M8UvHsUwmGsEFLkptTF2I4gycinkFt67lda7SOU4N1duii/AZCwBTeZpnq5KOYeW +XVDmJQhGd+raTbK9XkTK4kaxeko9gxappuXE7/yvd1huO82zsw7SWdK+Fqxk+vex +BgJ9yYoGZXPa2KgCQdVoQXoPp1yQs28BZmWWTFC9xzhnYSFS3Knw9wsWlS1duAva +mv74TOn6ajKn1Gd7IUV6Tnym+stlPY84kFopfX8hMm3GYXD5qE4/mzzwS0DWfeXW +MQj/KSH554E2GobVlgYdHrH8TONtzjosFrgDdvNwdxXqtTLD9Z+mYeEpu4gsoM8F +9T2XrrW5AegvXlQXLglb6tBKlWXZz4M6vB19KEt7jVzvigb5ZLXsP3P8bFjMV9rT +XV61WENTJ/BJAeRFjeto80D87GNizsPZl9OjUYzFCamBbiPgah8CsPiwQAwv6u7C +Hxs= +-----END CERTIFICATE-----
diff --git a/net/data/ssl/scripts/generate-test-certs.sh b/net/data/ssl/scripts/generate-test-certs.sh index b0fd908..92d8f22 100755 --- a/net/data/ssl/scripts/generate-test-certs.sh +++ b/net/data/ssl/scripts/generate-test-certs.sh
@@ -150,6 +150,13 @@ -config ../scripts/ee.cnf -newkey rsa:2048 -text \ -out ../certificates/reject_intranet_hosts.pem +## Leaf certificate with a large key; Apple's certificate verifier rejects with +## a fatal error if the key is bigger than 4096 bits. +try openssl req -x509 -days 3650 \ + -config ../scripts/ee.cnf -newkey rsa:4104 -text \ + -sha256 \ + -out ../certificates/large_key.pem + ## Validity too long unit test support. try openssl req -config ../scripts/ee.cnf \ -newkey rsa:2048 -text -out ../certificates/10_year_validity.req
diff --git a/net/disk_cache/blockfile/stats.h b/net/disk_cache/blockfile/stats.h index 769c171c..32dcc2f 100644 --- a/net/disk_cache/blockfile/stats.h +++ b/net/disk_cache/blockfile/stats.h
@@ -6,9 +6,9 @@ #define NET_DISK_CACHE_BLOCKFILE_STATS_H_ #include <string> -#include <vector> #include "base/basictypes.h" +#include "base/strings/string_split.h" #include "net/base/net_export.h" #include "net/disk_cache/blockfile/addr.h" @@ -18,7 +18,7 @@ namespace disk_cache { -typedef std::vector<std::pair<std::string, std::string> > StatsItems; +using StatsItems = base::StringPairs; // This class stores cache-specific usage information, for tunning purposes. class NET_EXPORT_PRIVATE Stats {
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc index 3808644..b5a6c9e 100644 --- a/net/disk_cache/simple/simple_backend_impl.cc +++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -735,7 +735,9 @@ // static void SimpleBackendImpl::FlushWorkerPoolForTesting() { - g_sequenced_worker_pool.Get().FlushForTesting(); + // We only need to do this if we there is an active task runner. + if (base::ThreadTaskRunnerHandle::IsSet()) + g_sequenced_worker_pool.Get().FlushForTesting(); } } // namespace disk_cache
diff --git a/net/dns/dns_config_service.h b/net/dns/dns_config_service.h index bfb5785..d7f3b07 100644 --- a/net/dns/dns_config_service.h +++ b/net/dns/dns_config_service.h
@@ -50,7 +50,7 @@ ~NameServerClassifier(); NameServersType GetNameServersType( - const std::vector<net::IPEndPoint>& nameservers) const; + const std::vector<IPEndPoint>& nameservers) const; private: struct NameServerTypeRule;
diff --git a/net/dns/dns_session_unittest.cc b/net/dns/dns_session_unittest.cc index ea04016..46815e00 100644 --- a/net/dns/dns_session_unittest.cc +++ b/net/dns/dns_session_unittest.cc
@@ -29,8 +29,8 @@ scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket( DatagramSocket::BindType bind_type, const RandIntCallback& rand_int_cb, - net::NetLog* net_log, - const net::NetLog::Source& source) override; + NetLog* net_log, + const NetLog::Source& source) override; scoped_ptr<StreamSocket> CreateTransportClientSocket( const AddressList& addresses, @@ -182,8 +182,8 @@ TestClientSocketFactory::CreateDatagramClientSocket( DatagramSocket::BindType bind_type, const RandIntCallback& rand_int_cb, - net::NetLog* net_log, - const net::NetLog::Source& source) { + NetLog* net_log, + const NetLog::Source& source) { // We're not actually expecting to send or receive any data, so use the // simplest SocketDataProvider with no data supplied. SocketDataProvider* data_provider = new StaticSocketDataProvider();
diff --git a/net/dns/dns_test_util.cc b/net/dns/dns_test_util.cc index 30e3d2e7..2ba3763 100644 --- a/net/dns/dns_test_util.cc +++ b/net/dns/dns_test_util.cc
@@ -106,8 +106,8 @@ const uint32 kTTL = 86400; // One day. // Size of RDATA which is a IPv4 or IPv6 address. - size_t rdata_size = qtype_ == net::dns_protocol::kTypeA ? - net::kIPv4AddressSize : net::kIPv6AddressSize; + size_t rdata_size = qtype_ == dns_protocol::kTypeA ? kIPv4AddressSize + : kIPv6AddressSize; // 12 is the sum of sizes of the compressed name reference, TYPE, // CLASS, TTL and RDLENGTH. @@ -118,10 +118,10 @@ base::BigEndianWriter writer(buffer + nbytes, answer_size); writer.WriteU16(kPointerToQueryName); writer.WriteU16(qtype_); - writer.WriteU16(net::dns_protocol::kClassIN); + writer.WriteU16(dns_protocol::kClassIN); writer.WriteU32(kTTL); writer.WriteU16(rdata_size); - if (qtype_ == net::dns_protocol::kTypeA) { + if (qtype_ == dns_protocol::kTypeA) { char kIPv4Loopback[] = { 0x7f, 0, 0, 1 }; writer.WriteBytes(kIPv4Loopback, sizeof(kIPv4Loopback)); } else {
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc index 933c7558..2693a5ca 100644 --- a/net/dns/dns_transaction_unittest.cc +++ b/net/dns/dns_transaction_unittest.cc
@@ -187,8 +187,8 @@ scoped_ptr<DatagramClientSocket> CreateDatagramClientSocket( DatagramSocket::BindType bind_type, const RandIntCallback& rand_int_cb, - net::NetLog* net_log, - const net::NetLog::Source& source) override { + NetLog* net_log, + const NetLog::Source& source) override { if (fail_next_socket_) { fail_next_socket_ = false; return scoped_ptr<DatagramClientSocket>(
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index 5e050c6..feb9a1bb 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -24,6 +24,7 @@ #include "base/message_loop/message_loop_proxy.h" #include "base/metrics/field_trial.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/strings/utf_string_conversions.h" @@ -1871,6 +1872,10 @@ const CompletionCallback& callback, RequestHandle* out_req, const BoundNetLog& source_net_log) { + // TODO(eroman): Remove ScopedTracker below once crbug.com/455942 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION("455942 HostResolverImpl::Resolve")); + DCHECK(addresses); DCHECK(CalledOnValidThread()); DCHECK_EQ(false, callback.is_null()); @@ -2184,15 +2189,10 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 }; IPAddressNumber address(kIPv6Address, kIPv6Address + arraysize(kIPv6Address)); - BoundNetLog probe_net_log = BoundNetLog::Make( - net_log.net_log(), NetLog::SOURCE_IPV6_REACHABILITY_CHECK); - probe_net_log.BeginEvent(NetLog::TYPE_IPV6_REACHABILITY_CHECK, - net_log.source().ToEventParametersCallback()); - bool rv6 = IsGloballyReachable(address, probe_net_log); - probe_net_log.EndEvent(NetLog::TYPE_IPV6_REACHABILITY_CHECK); - if (rv6) { - net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_IPV6_SUPPORTED); - } else { + bool rv6 = IsGloballyReachable(address, net_log); + net_log.AddEvent(NetLog::TYPE_HOST_RESOLVER_IMPL_IPV6_REACHABILITY_CHECK, + NetLog::BoolCallback("ipv6_available", rv6)); + if (!rv6) { effective_address_family = ADDRESS_FAMILY_IPV4; effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6; }
diff --git a/net/dns/mdns_client_impl.cc b/net/dns/mdns_client_impl.cc index 1c313d8..ac13bf5 100644 --- a/net/dns/mdns_client_impl.cc +++ b/net/dns/mdns_client_impl.cc
@@ -45,8 +45,8 @@ ScopedVector<DatagramServerSocket>* sockets) { InterfaceIndexFamilyList interfaces(GetMDnsInterfacesToBind()); for (size_t i = 0; i < interfaces.size(); ++i) { - DCHECK(interfaces[i].second == net::ADDRESS_FAMILY_IPV4 || - interfaces[i].second == net::ADDRESS_FAMILY_IPV6); + DCHECK(interfaces[i].second == ADDRESS_FAMILY_IPV4 || + interfaces[i].second == ADDRESS_FAMILY_IPV6); scoped_ptr<DatagramServerSocket> socket( CreateAndBindMDnsSocket(interfaces[i].second, interfaces[i].first)); if (socket) @@ -454,7 +454,7 @@ uint16 rrtype, const std::string& name, MDnsListener::Delegate* delegate) { - return scoped_ptr<net::MDnsListener>( + return scoped_ptr<MDnsListener>( new MDnsListenerImpl(rrtype, name, clock_.get(), delegate, this)); }
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc index 6d8cba38..810765c 100644 --- a/net/dns/mock_host_resolver.cc +++ b/net/dns/mock_host_resolver.cc
@@ -379,7 +379,7 @@ return ERR_NAME_NOT_RESOLVED; case Rule::kResolverTypeSystem: #if defined(OS_WIN) - net::EnsureWinsockInit(); + EnsureWinsockInit(); #endif return SystemHostResolverCall(effective_host, address_family,
diff --git a/net/docs/bug-triage-suggested-workflow.md b/net/docs/bug-triage-suggested-workflow.md index 4c448bc1..4b6ee7b 100644 --- a/net/docs/bug-triage-suggested-workflow.md +++ b/net/docs/bug-triage-suggested-workflow.md
@@ -188,10 +188,19 @@ section. If a search on go/crash indicates a crasher is no longer occurring, mark it as WontFix. -* Particularly for Windows, look for weird dlls associated with the crashes. - If there are some, it may be caused by malware. You can often figure out if - a dll is malware by a search, though it's harder to figure out if a dll is - definitively not malware. +* On Windows, you may want to look for weird dlls associated with the crashes. + This generally needs crashes from a fair number of different users to reach + any conclusions. + * To get a list of loaded modules in related crash dumps, select + modules->3rd party in the left pane. It can be difficult to distinguish + between safe dlls and those likely to cause problems, but even if you're + not that familiar with windows, some may stick out. Anti-virus programs, + download managers, and more gray hat badware often have meaningful dll + names or dll paths (Generally product names or company names). If you + see one of these in a significant number of the crash dumps, it may well + be the cause. + * You can also try selecting the "has malware" option, though that's much + less reliable than looking manually. * See if the same users are repeatedly running into the same issue. This can be accomplished by search for (Or clicking on) the client ID associated with
diff --git a/net/extras/sqlite/sqlite_channel_id_store.cc b/net/extras/sqlite/sqlite_channel_id_store.cc index d7edf9c1..daf0eea 100644 --- a/net/extras/sqlite/sqlite_channel_id_store.cc +++ b/net/extras/sqlite/sqlite_channel_id_store.cc
@@ -127,6 +127,10 @@ // Batch a channel id operation (add or delete). void BatchOperation(PendingOperation::OperationType op, const DefaultChannelIDStore::ChannelID& channel_id); + // Prunes the list of pending operations to remove any operations for an + // identifier in |server_identifiers|. + void PrunePendingOperationsForDeletes( + const std::list<std::string>& server_identifiers); // Commit our pending operations to the database. void Commit(); // Close() executed on the background task runner. @@ -477,6 +481,28 @@ } } +void SQLiteChannelIDStore::Backend::PrunePendingOperationsForDeletes( + const std::list<std::string>& server_identifiers) { + DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); + base::AutoLock locked(lock_); + + for (PendingOperationsList::iterator it = pending_.begin(); + it != pending_.end();) { + bool remove = + std::find(server_identifiers.begin(), server_identifiers.end(), + (*it)->channel_id().server_identifier()) != + server_identifiers.end(); + + if (remove) { + scoped_ptr<PendingOperation> po(*it); + it = pending_.erase(it); + --num_pending_; + } else { + ++it; + } + } +} + void SQLiteChannelIDStore::Backend::Commit() { DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); @@ -567,6 +593,8 @@ if (!db_.get()) return; + PrunePendingOperationsForDeletes(server_identifiers); + sql::Statement del_smt(db_->GetCachedStatement( SQL_FROM_HERE, "DELETE FROM origin_bound_certs WHERE origin=?")); if (!del_smt.is_valid()) {
diff --git a/net/ftp/ftp_auth_cache_unittest.cc b/net/ftp/ftp_auth_cache_unittest.cc index bd47b64..892153c3 100644 --- a/net/ftp/ftp_auth_cache_unittest.cc +++ b/net/ftp/ftp_auth_cache_unittest.cc
@@ -12,7 +12,8 @@ #include "url/gurl.h" using base::ASCIIToUTF16; -using net::FtpAuthCache; + +namespace net { namespace { @@ -40,7 +41,7 @@ EXPECT_TRUE(cache.Lookup(origin1) == NULL); // Add entry for origin1. - cache.Add(origin1, net::AuthCredentials(kUsername1, kPassword1)); + cache.Add(origin1, AuthCredentials(kUsername1, kPassword1)); FtpAuthCache::Entry* entry1 = cache.Lookup(origin1); ASSERT_TRUE(entry1); EXPECT_EQ(origin1, entry1->origin); @@ -48,7 +49,7 @@ EXPECT_EQ(kPassword1, entry1->credentials.password()); // Add an entry for origin2. - cache.Add(origin2, net::AuthCredentials(kUsername2, kPassword2)); + cache.Add(origin2, AuthCredentials(kUsername2, kPassword2)); FtpAuthCache::Entry* entry2 = cache.Lookup(origin2); ASSERT_TRUE(entry2); EXPECT_EQ(origin2, entry2->origin); @@ -59,7 +60,7 @@ EXPECT_EQ(entry1, cache.Lookup(origin1)); // Overwrite the entry for origin1. - cache.Add(origin1, net::AuthCredentials(kUsername3, kPassword3)); + cache.Add(origin1, AuthCredentials(kUsername3, kPassword3)); FtpAuthCache::Entry* entry3 = cache.Lookup(origin1); ASSERT_TRUE(entry3); EXPECT_EQ(origin1, entry3->origin); @@ -67,11 +68,11 @@ EXPECT_EQ(kPassword3, entry3->credentials.password()); // Remove entry of origin1. - cache.Remove(origin1, net::AuthCredentials(kUsername3, kPassword3)); + cache.Remove(origin1, AuthCredentials(kUsername3, kPassword3)); EXPECT_TRUE(cache.Lookup(origin1) == NULL); // Remove non-existent entry. - cache.Remove(origin1, net::AuthCredentials(kUsername3, kPassword3)); + cache.Remove(origin1, AuthCredentials(kUsername3, kPassword3)); EXPECT_TRUE(cache.Lookup(origin1) == NULL); } @@ -83,8 +84,8 @@ GURL origin1("ftp://foo:80"); GURL origin2("ftp://foo:21"); - cache.Add(origin1, net::AuthCredentials(kUsername, kPassword)); - cache.Add(origin2, net::AuthCredentials(kUsername, kPassword)); + cache.Add(origin1, AuthCredentials(kUsername, kPassword)); + cache.Add(origin2, AuthCredentials(kUsername, kPassword)); EXPECT_NE(cache.Lookup(origin1), cache.Lookup(origin2)); } @@ -97,7 +98,7 @@ FtpAuthCache cache; // Add. - cache.Add(GURL("ftp://HoSt:21"), net::AuthCredentials(kUsername, kPassword)); + cache.Add(GURL("ftp://HoSt:21"), AuthCredentials(kUsername, kPassword)); // Lookup. FtpAuthCache::Entry* entry1 = cache.Lookup(GURL("ftp://HoSt:21")); @@ -106,7 +107,7 @@ EXPECT_EQ(entry1, cache.Lookup(GURL("ftp://host"))); // Overwrite. - cache.Add(GURL("ftp://host"), net::AuthCredentials(kOthername, kOtherword)); + cache.Add(GURL("ftp://host"), AuthCredentials(kOthername, kOtherword)); FtpAuthCache::Entry* entry2 = cache.Lookup(GURL("ftp://HoSt:21")); ASSERT_TRUE(entry2); EXPECT_EQ(GURL("ftp://host"), entry2->origin); @@ -114,23 +115,22 @@ EXPECT_EQ(kOtherword, entry2->credentials.password()); // Remove - cache.Remove(GURL("ftp://HOsT"), - net::AuthCredentials(kOthername, kOtherword)); + cache.Remove(GURL("ftp://HOsT"), AuthCredentials(kOthername, kOtherword)); EXPECT_TRUE(cache.Lookup(GURL("ftp://host")) == NULL); } TEST(FtpAuthCacheTest, OnlyRemoveMatching) { FtpAuthCache cache; - cache.Add(GURL("ftp://host"), net::AuthCredentials(kUsername, kPassword)); + cache.Add(GURL("ftp://host"), AuthCredentials(kUsername, kPassword)); EXPECT_TRUE(cache.Lookup(GURL("ftp://host"))); // Auth data doesn't match, shouldn't remove. - cache.Remove(GURL("ftp://host"), net::AuthCredentials(kBogus, kBogus)); + cache.Remove(GURL("ftp://host"), AuthCredentials(kBogus, kBogus)); EXPECT_TRUE(cache.Lookup(GURL("ftp://host"))); // Auth data matches, should remove. - cache.Remove(GURL("ftp://host"), net::AuthCredentials(kUsername, kPassword)); + cache.Remove(GURL("ftp://host"), AuthCredentials(kUsername, kPassword)); EXPECT_TRUE(cache.Lookup(GURL("ftp://host")) == NULL); } @@ -139,7 +139,7 @@ for (size_t i = 0; i < FtpAuthCache::kMaxEntries; i++) { cache.Add(GURL("ftp://host" + base::IntToString(i)), - net::AuthCredentials(kUsername, kPassword)); + AuthCredentials(kUsername, kPassword)); } // No entries should be evicted before reaching the limit. @@ -148,8 +148,7 @@ } // Adding one entry should cause eviction of the first entry. - cache.Add(GURL("ftp://last_host"), - net::AuthCredentials(kUsername, kPassword)); + cache.Add(GURL("ftp://last_host"), AuthCredentials(kUsername, kPassword)); EXPECT_TRUE(cache.Lookup(GURL("ftp://host0")) == NULL); // Remaining entries should not get evicted. @@ -158,3 +157,5 @@ } EXPECT_TRUE(cache.Lookup(GURL("ftp://last_host"))); } + +} // namespace net
diff --git a/net/ftp/ftp_ctrl_response_buffer_unittest.cc b/net/ftp/ftp_ctrl_response_buffer_unittest.cc index f74b287..759ed87 100644 --- a/net/ftp/ftp_ctrl_response_buffer_unittest.cc +++ b/net/ftp/ftp_ctrl_response_buffer_unittest.cc
@@ -9,28 +9,29 @@ #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + namespace { class FtpCtrlResponseBufferTest : public testing::Test { public: - FtpCtrlResponseBufferTest() : buffer_(net::BoundNetLog()) { - } + FtpCtrlResponseBufferTest() : buffer_(BoundNetLog()) {} protected: int PushDataToBuffer(const char* data) { return buffer_.ConsumeData(data, strlen(data)); } - net::FtpCtrlResponseBuffer buffer_; + FtpCtrlResponseBuffer buffer_; }; TEST_F(FtpCtrlResponseBufferTest, Basic) { EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("200 Status Text\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("200 Status Text\r\n")); EXPECT_TRUE(buffer_.ResponseAvailable()); - net::FtpCtrlResponse response = buffer_.PopResponse(); + FtpCtrlResponse response = buffer_.PopResponse(); EXPECT_FALSE(buffer_.ResponseAvailable()); EXPECT_EQ(200, response.status_code); ASSERT_EQ(1U, response.lines.size()); @@ -38,18 +39,18 @@ } TEST_F(FtpCtrlResponseBufferTest, Chunks) { - EXPECT_EQ(net::OK, PushDataToBuffer("20")); + EXPECT_EQ(OK, PushDataToBuffer("20")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("0 Status")); + EXPECT_EQ(OK, PushDataToBuffer("0 Status")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer(" Text")); + EXPECT_EQ(OK, PushDataToBuffer(" Text")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("\r")); + EXPECT_EQ(OK, PushDataToBuffer("\r")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("\n")); + EXPECT_EQ(OK, PushDataToBuffer("\n")); EXPECT_TRUE(buffer_.ResponseAvailable()); - net::FtpCtrlResponse response = buffer_.PopResponse(); + FtpCtrlResponse response = buffer_.PopResponse(); EXPECT_FALSE(buffer_.ResponseAvailable()); EXPECT_EQ(200, response.status_code); ASSERT_EQ(1U, response.lines.size()); @@ -57,16 +58,16 @@ } TEST_F(FtpCtrlResponseBufferTest, Continuation) { - EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230-FirstLine\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("230-SecondLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230-SecondLine\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("230 LastLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230 LastLine\r\n")); EXPECT_TRUE(buffer_.ResponseAvailable()); - net::FtpCtrlResponse response = buffer_.PopResponse(); + FtpCtrlResponse response = buffer_.PopResponse(); EXPECT_FALSE(buffer_.ResponseAvailable()); EXPECT_EQ(230, response.status_code); ASSERT_EQ(3U, response.lines.size()); @@ -76,22 +77,22 @@ } TEST_F(FtpCtrlResponseBufferTest, MultilineContinuation) { - EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230-FirstLine\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("Continued\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("Continued\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("230-SecondLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230-SecondLine\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("215 Continued\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("215 Continued\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("230 LastLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230 LastLine\r\n")); EXPECT_TRUE(buffer_.ResponseAvailable()); - net::FtpCtrlResponse response = buffer_.PopResponse(); + FtpCtrlResponse response = buffer_.PopResponse(); EXPECT_FALSE(buffer_.ResponseAvailable()); EXPECT_EQ(230, response.status_code); ASSERT_EQ(3U, response.lines.size()); @@ -102,16 +103,16 @@ TEST_F(FtpCtrlResponseBufferTest, MultilineContinuationZeroLength) { // For the corner case from bug 29322. - EXPECT_EQ(net::OK, PushDataToBuffer("230-\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230-\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("example.com\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("example.com\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("230 LastLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230 LastLine\r\n")); EXPECT_TRUE(buffer_.ResponseAvailable()); - net::FtpCtrlResponse response = buffer_.PopResponse(); + FtpCtrlResponse response = buffer_.PopResponse(); EXPECT_FALSE(buffer_.ResponseAvailable()); EXPECT_EQ(230, response.status_code); ASSERT_EQ(2U, response.lines.size()); @@ -120,18 +121,18 @@ } TEST_F(FtpCtrlResponseBufferTest, SimilarContinuation) { - EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230-FirstLine\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); // Notice the space at the start of the line. It should be recognized // as a continuation, and not the last line. - EXPECT_EQ(net::OK, PushDataToBuffer(" 230 Continued\r\n")); + EXPECT_EQ(OK, PushDataToBuffer(" 230 Continued\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("230 TrueLastLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230 TrueLastLine\r\n")); EXPECT_TRUE(buffer_.ResponseAvailable()); - net::FtpCtrlResponse response = buffer_.PopResponse(); + FtpCtrlResponse response = buffer_.PopResponse(); EXPECT_FALSE(buffer_.ResponseAvailable()); EXPECT_EQ(230, response.status_code); ASSERT_EQ(2U, response.lines.size()); @@ -141,19 +142,19 @@ // The nesting of multi-line responses is not allowed. TEST_F(FtpCtrlResponseBufferTest, NoNesting) { - EXPECT_EQ(net::OK, PushDataToBuffer("230-FirstLine\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230-FirstLine\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("300-Continuation\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("300-Continuation\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("300 Still continuation\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("300 Still continuation\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); - EXPECT_EQ(net::OK, PushDataToBuffer("230 Real End\r\n")); + EXPECT_EQ(OK, PushDataToBuffer("230 Real End\r\n")); ASSERT_TRUE(buffer_.ResponseAvailable()); - net::FtpCtrlResponse response = buffer_.PopResponse(); + FtpCtrlResponse response = buffer_.PopResponse(); EXPECT_FALSE(buffer_.ResponseAvailable()); EXPECT_EQ(230, response.status_code); ASSERT_EQ(2U, response.lines.size()); @@ -163,13 +164,15 @@ } TEST_F(FtpCtrlResponseBufferTest, NonNumericResponse) { - EXPECT_EQ(net::ERR_INVALID_RESPONSE, PushDataToBuffer("Non-numeric\r\n")); + EXPECT_EQ(ERR_INVALID_RESPONSE, PushDataToBuffer("Non-numeric\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); } TEST_F(FtpCtrlResponseBufferTest, OutOfRangeResponse) { - EXPECT_EQ(net::ERR_INVALID_RESPONSE, PushDataToBuffer("777 OK?\r\n")); + EXPECT_EQ(ERR_INVALID_RESPONSE, PushDataToBuffer("777 OK?\r\n")); EXPECT_FALSE(buffer_.ResponseAvailable()); } } // namespace + +} // namespace net
diff --git a/net/ftp/ftp_directory_listing_parser_ls.cc b/net/ftp/ftp_directory_listing_parser_ls.cc index 2d23b6aec..7fb92073 100644 --- a/net/ftp/ftp_directory_listing_parser_ls.cc +++ b/net/ftp/ftp_directory_listing_parser_ls.cc
@@ -14,6 +14,8 @@ #include "net/ftp/ftp_directory_listing_parser.h" #include "net/ftp/ftp_util.h" +namespace net { + namespace { bool TwoColumnDateListingToTime(const base::string16& date, @@ -78,11 +80,8 @@ // * 8. year or time <-- column_offset will be the index of this column // 9. file name (optional, may contain spaces) for (size_t i = 5U; i < columns.size(); i++) { - if (net::FtpUtil::LsDateListingToTime(columns[i - 2], - columns[i - 1], - columns[i], - current_time, - modification_time)) { + if (FtpUtil::LsDateListingToTime(columns[i - 2], columns[i - 1], columns[i], + current_time, modification_time)) { *size = columns[i - 3]; *offset = i; return true; @@ -93,11 +92,8 @@ // (for example Russian listings). We try to recognize them only after making // sure no column offset works above (this is a more strict way). for (size_t i = 5U; i < columns.size(); i++) { - if (net::FtpUtil::LsDateListingToTime(columns[i - 1], - columns[i - 2], - columns[i], - current_time, - modification_time)) { + if (FtpUtil::LsDateListingToTime(columns[i - 1], columns[i - 2], columns[i], + current_time, modification_time)) { *size = columns[i - 3]; *offset = i; return true; @@ -120,8 +116,6 @@ } // namespace -namespace net { - bool ParseFtpDirectoryListingLs( const std::vector<base::string16>& lines, const base::Time& current_time,
diff --git a/net/ftp/ftp_network_transaction.cc b/net/ftp/ftp_network_transaction.cc index 5732c64..3c67114 100644 --- a/net/ftp/ftp_network_transaction.cc +++ b/net/ftp/ftp_network_transaction.cc
@@ -25,12 +25,14 @@ #include "net/socket/client_socket_factory.h" #include "net/socket/stream_socket.h" +namespace net { + +namespace { + const char kCRLF[] = "\r\n"; const int kCtrlBufLen = 1024; -namespace { - // Returns true if |input| can be safely used as a part of FTP command. bool IsValidFTPCommandString(const std::string& input) { // RFC 959 only allows ASCII strings, but at least Firefox can send non-ASCII @@ -94,21 +96,21 @@ int GetNetErrorCodeForFtpResponseCode(int response_code) { switch (response_code) { case 421: - return net::ERR_FTP_SERVICE_UNAVAILABLE; + return ERR_FTP_SERVICE_UNAVAILABLE; case 426: - return net::ERR_FTP_TRANSFER_ABORTED; + return ERR_FTP_TRANSFER_ABORTED; case 450: - return net::ERR_FTP_FILE_BUSY; + return ERR_FTP_FILE_BUSY; case 500: case 501: - return net::ERR_FTP_SYNTAX_ERROR; + return ERR_FTP_SYNTAX_ERROR; case 502: case 504: - return net::ERR_FTP_COMMAND_NOT_SUPPORTED; + return ERR_FTP_COMMAND_NOT_SUPPORTED; case 503: - return net::ERR_FTP_BAD_COMMAND_SEQUENCE; + return ERR_FTP_BAD_COMMAND_SEQUENCE; default: - return net::ERR_FTP_FAILED; + return ERR_FTP_FAILED; } } @@ -116,8 +118,7 @@ // The text returned in response to the EPSV command MUST be: // <some text> (<d><d><d><tcp-port><d>) // <d> is a delimiter character, ideally to be | -bool ExtractPortFromEPSVResponse(const net::FtpCtrlResponse& response, - int* port) { +bool ExtractPortFromEPSVResponse(const FtpCtrlResponse& response, int* port) { if (response.lines.size() != 1) return false; const char* ptr = response.lines[0].c_str(); @@ -146,8 +147,7 @@ // 127,0,0,1,23,21 IP address and port without (). // // See RFC 959, Section 4.1.2 -bool ExtractPortFromPASVResponse(const net::FtpCtrlResponse& response, - int* port) { +bool ExtractPortFromPASVResponse(const FtpCtrlResponse& response, int* port) { if (response.lines.size() != 1) return false; @@ -200,8 +200,6 @@ } // namespace -namespace net { - FtpNetworkTransaction::FtpNetworkTransaction( FtpNetworkSession* session, ClientSocketFactory* socket_factory) @@ -492,7 +490,7 @@ UnescapeRule::URL_SPECIAL_CHARS; // This may unescape to non-ASCII characters, but we allow that. See the // comment for IsValidFTPCommandString. - path = net::UnescapeURLComponent(path, unescape_rules); + path = UnescapeURLComponent(path, unescape_rules); if (system_type_ == SYSTEM_TYPE_VMS) { if (is_directory)
diff --git a/net/ftp/ftp_util_unittest.cc b/net/ftp/ftp_util_unittest.cc index a2b2849..121780bb 100644 --- a/net/ftp/ftp_util_unittest.cc +++ b/net/ftp/ftp_util_unittest.cc
@@ -15,6 +15,8 @@ using base::ASCIIToUTF16; using base::UTF8ToUTF16; +namespace net { + namespace { TEST(FtpUtilTest, UnixFilePathToVMS) { @@ -36,7 +38,7 @@ }; for (size_t i = 0; i < arraysize(kTestCases); i++) { EXPECT_EQ(kTestCases[i].expected_output, - net::FtpUtil::UnixFilePathToVMS(kTestCases[i].input)) + FtpUtil::UnixFilePathToVMS(kTestCases[i].input)) << kTestCases[i].input; } } @@ -69,7 +71,7 @@ }; for (size_t i = 0; i < arraysize(kTestCases); i++) { EXPECT_EQ(kTestCases[i].expected_output, - net::FtpUtil::UnixDirectoryPathToVMS(kTestCases[i].input)) + FtpUtil::UnixDirectoryPathToVMS(kTestCases[i].input)) << kTestCases[i].input; } } @@ -109,7 +111,7 @@ }; for (size_t i = 0; i < arraysize(kTestCases); i++) { EXPECT_EQ(kTestCases[i].expected_output, - net::FtpUtil::VMSPathToUnix(kTestCases[i].input)) + FtpUtil::VMSPathToUnix(kTestCases[i].input)) << kTestCases[i].input; } } @@ -169,7 +171,7 @@ kTestCases[i].rest)); base::Time time; - ASSERT_TRUE(net::FtpUtil::LsDateListingToTime( + ASSERT_TRUE(FtpUtil::LsDateListingToTime( UTF8ToUTF16(kTestCases[i].month), UTF8ToUTF16(kTestCases[i].day), UTF8ToUTF16(kTestCases[i].rest), mock_current_time, &time)); @@ -209,10 +211,9 @@ kTestCases[i].date, kTestCases[i].time)); base::Time time; - ASSERT_TRUE(net::FtpUtil::WindowsDateListingToTime( - UTF8ToUTF16(kTestCases[i].date), - UTF8ToUTF16(kTestCases[i].time), - &time)); + ASSERT_TRUE(FtpUtil::WindowsDateListingToTime( + UTF8ToUTF16(kTestCases[i].date), UTF8ToUTF16(kTestCases[i].time), + &time)); base::Time::Exploded time_exploded; time.LocalExplode(&time_exploded); @@ -248,9 +249,11 @@ kTestCases[i].text, kTestCases[i].column)); EXPECT_EQ(ASCIIToUTF16(kTestCases[i].expected_result), - net::FtpUtil::GetStringPartAfterColumns( + FtpUtil::GetStringPartAfterColumns( ASCIIToUTF16(kTestCases[i].text), kTestCases[i].column)); } } } // namespace + +} // namespace net
diff --git a/net/http/disk_cache_based_quic_server_info.cc b/net/http/disk_cache_based_quic_server_info.cc index 6ac0bcd..19d88a9 100644 --- a/net/http/disk_cache_based_quic_server_info.cc +++ b/net/http/disk_cache_based_quic_server_info.cc
@@ -400,7 +400,7 @@ if (!backend_) { UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.NoBackend", call, QUIC_SERVER_INFO_NUM_OF_API_CALLS); - } else if (backend_->GetCacheType() == net::MEMORY_CACHE) { + } else if (backend_->GetCacheType() == MEMORY_CACHE) { UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.MemoryCache", call, QUIC_SERVER_INFO_NUM_OF_API_CALLS); } else { @@ -425,7 +425,7 @@ if (!backend_) { UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.NoBackend", failure, NUM_OF_FAILURES); - } else if (backend_->GetCacheType() == net::MEMORY_CACHE) { + } else if (backend_->GetCacheType() == MEMORY_CACHE) { UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.MemoryCache", failure, NUM_OF_FAILURES); } else {
diff --git a/net/http/disk_cache_based_quic_server_info_unittest.cc b/net/http/disk_cache_based_quic_server_info_unittest.cc index 991881a7..d4ddfc25 100644 --- a/net/http/disk_cache_based_quic_server_info_unittest.cc +++ b/net/http/disk_cache_based_quic_server_info_unittest.cc
@@ -50,14 +50,14 @@ 0 }; -class DeleteCacheCompletionCallback : public net::TestCompletionCallbackBase { +class DeleteCacheCompletionCallback : public TestCompletionCallbackBase { public: explicit DeleteCacheCompletionCallback(QuicServerInfo* server_info) : server_info_(server_info), callback_(base::Bind(&DeleteCacheCompletionCallback::OnComplete, base::Unretained(this))) {} - const net::CompletionCallback& callback() const { return callback_; } + const CompletionCallback& callback() const { return callback_; } private: void OnComplete(int result) { @@ -66,7 +66,7 @@ } QuicServerInfo* server_info_; - net::CompletionCallback callback_; + CompletionCallback callback_; DISALLOW_COPY_AND_ASSIGN(DeleteCacheCompletionCallback); };
diff --git a/net/http/failing_http_transaction_factory.cc b/net/http/failing_http_transaction_factory.cc index dfe78f24..a190597 100644 --- a/net/http/failing_http_transaction_factory.cc +++ b/net/http/failing_http_transaction_factory.cc
@@ -51,7 +51,7 @@ const HttpResponseInfo* GetResponseInfo() const override; LoadState GetLoadState() const override; UploadProgress GetUploadProgress() const override; - void SetQuicServerInfo(net::QuicServerInfo* quic_server_info) override; + void SetQuicServerInfo(QuicServerInfo* quic_server_info) override; bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; void SetPriority(RequestPriority priority) override; void SetWebSocketHandshakeStreamCreateHelper( @@ -135,7 +135,8 @@ } void FailingHttpTransaction::SetQuicServerInfo( - net::QuicServerInfo* quic_server_info) {} + QuicServerInfo* quic_server_info) { +} bool FailingHttpTransaction::GetLoadTimingInfo( LoadTimingInfo* load_timing_info) const {
diff --git a/net/http/http_auth_cache.h b/net/http/http_auth_cache.h index 1867295..f05f8184 100644 --- a/net/http/http_auth_cache.h +++ b/net/http/http_auth_cache.h
@@ -36,9 +36,7 @@ } // The case-sensitive realm string of the challenge. - const std::string realm() const { - return realm_; - } + const std::string& realm() const { return realm_; } // The authentication scheme of the challenge. HttpAuth::Scheme scheme() const { @@ -46,9 +44,7 @@ } // The authentication challenge. - const std::string auth_challenge() const { - return auth_challenge_; - } + const std::string& auth_challenge() const { return auth_challenge_; } // The login credentials. const AuthCredentials& credentials() const {
diff --git a/net/http/http_auth_handler.h b/net/http/http_auth_handler.h index 439fe076..1aee795 100644 --- a/net/http/http_auth_handler.h +++ b/net/http/http_auth_handler.h
@@ -87,9 +87,7 @@ } // The challenge which was issued when creating the handler. - const std::string challenge() const { - return auth_challenge_; - } + const std::string& challenge() const { return auth_challenge_; } // Numeric rank based on the challenge's security level. Higher // numbers are better. Used by HttpAuth::ChooseBestChallenge().
diff --git a/net/http/http_auth_handler_basic.cc b/net/http/http_auth_handler_basic.cc index 4837138..b1624b8 100644 --- a/net/http/http_auth_handler_basic.cc +++ b/net/http/http_auth_handler_basic.cc
@@ -43,8 +43,7 @@ if (!LowerCaseEqualsASCII(parameters.name(), "realm")) continue; - if (!net::ConvertToUtf8AndNormalize(parameters.value(), kCharsetLatin1, - realm)) { + if (!ConvertToUtf8AndNormalize(parameters.value(), kCharsetLatin1, realm)) { return false; } }
diff --git a/net/http/http_auth_handler_digest.cc b/net/http/http_auth_handler_digest.cc index 7dee081..5c2e417 100644 --- a/net/http/http_auth_handler_digest.cc +++ b/net/http/http_auth_handler_digest.cc
@@ -227,7 +227,7 @@ const std::string& value) { if (LowerCaseEqualsASCII(name, "realm")) { std::string realm; - if (!net::ConvertToUtf8AndNormalize(value, kCharsetLatin1, &realm)) + if (!ConvertToUtf8AndNormalize(value, kCharsetLatin1, &realm)) return false; realm_ = realm; original_realm_ = value;
diff --git a/net/http/http_auth_handler_negotiate_unittest.cc b/net/http/http_auth_handler_negotiate_unittest.cc index 233597d..eaee8e5 100644 --- a/net/http/http_auth_handler_negotiate_unittest.cc +++ b/net/http/http_auth_handler_negotiate_unittest.cc
@@ -19,14 +19,14 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" -#if defined(OS_WIN) -typedef net::MockSSPILibrary MockAuthLibrary; -#elif defined(OS_POSIX) -typedef net::test::MockGSSAPILibrary MockAuthLibrary; -#endif - namespace net { +#if defined(OS_WIN) +typedef MockSSPILibrary MockAuthLibrary; +#elif defined(OS_POSIX) +typedef test::MockGSSAPILibrary MockAuthLibrary; +#endif + class HttpAuthHandlerNegotiateTest : public PlatformTest { public: void SetUp() override {
diff --git a/net/http/http_auth_handler_unittest.cc b/net/http/http_auth_handler_unittest.cc index 335bec3a..6ffd81b 100644 --- a/net/http/http_auth_handler_unittest.cc +++ b/net/http/http_auth_handler_unittest.cc
@@ -11,6 +11,7 @@ #include "net/http/http_auth_challenge_tokenizer.h" #include "net/http/http_auth_handler_mock.h" #include "net/http/http_request_info.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log_unittest.h" #include "net/log/test_net_log.h" #include "testing/gtest/include/gtest/gtest.h" @@ -39,8 +40,8 @@ challenge.begin(), challenge.end()); HttpAuthHandlerMock mock_handler; TestNetLog capturing_net_log; - BoundNetLog bound_net_log(BoundNetLog::Make(&capturing_net_log, - net::NetLog::SOURCE_NONE)); + BoundNetLog bound_net_log( + BoundNetLog::Make(&capturing_net_log, NetLog::SOURCE_NONE)); mock_handler.InitFromChallenge(&tokenizer, target, origin, bound_net_log); @@ -50,7 +51,7 @@ if (async) test_callback.WaitForResult(); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; capturing_net_log.GetEntries(&entries); EXPECT_EQ(2u, entries.size());
diff --git a/net/http/http_byte_range_unittest.cc b/net/http/http_byte_range_unittest.cc index d075294..0a77da3e 100644 --- a/net/http/http_byte_range_unittest.cc +++ b/net/http/http_byte_range_unittest.cc
@@ -5,6 +5,10 @@ #include "net/http/http_byte_range.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + +namespace { + TEST(HttpByteRangeTest, ValidRanges) { const struct { int64 first_byte_position; @@ -24,7 +28,7 @@ }; for (size_t i = 0; i < arraysize(tests); ++i) { - net::HttpByteRange range; + HttpByteRange range; range.set_first_byte_position(tests[i].first_byte_position); range.set_last_byte_position(tests[i].last_byte_position); range.set_suffix_length(tests[i].suffix_length); @@ -56,7 +60,7 @@ }; for (size_t i = 0; i < arraysize(tests); ++i) { - net::HttpByteRange range; + HttpByteRange range; range.set_first_byte_position(tests[i].first_byte_position); range.set_last_byte_position(tests[i].last_byte_position); range.set_suffix_length(tests[i].suffix_length); @@ -79,14 +83,20 @@ TEST(HttpByteRangeTest, GetHeaderValue) { static const struct { - net::HttpByteRange range; + HttpByteRange range; const char* expected; - } tests[] = {{net::HttpByteRange::Bounded(0, 0), "bytes=0-0"}, - {net::HttpByteRange::Bounded(0, 100), "bytes=0-100"}, - {net::HttpByteRange::Bounded(0, -1), "bytes=0-"}, - {net::HttpByteRange::RightUnbounded(100), "bytes=100-"}, - {net::HttpByteRange::Suffix(100), "bytes=-100"}, }; + } tests[] = { + {HttpByteRange::Bounded(0, 0), "bytes=0-0"}, + {HttpByteRange::Bounded(0, 100), "bytes=0-100"}, + {HttpByteRange::Bounded(0, -1), "bytes=0-"}, + {HttpByteRange::RightUnbounded(100), "bytes=100-"}, + {HttpByteRange::Suffix(100), "bytes=-100"}, + }; for (size_t i = 0; i < arraysize(tests); ++i) { EXPECT_EQ(tests[i].expected, tests[i].range.GetHeaderValue()); } } + +} // namespace + +} // namespace net
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc index 51929ff..b5a79a3a 100644 --- a/net/http/http_cache.cc +++ b/net/http/http_cache.cc
@@ -76,7 +76,7 @@ // static HttpCache::BackendFactory* HttpCache::DefaultBackend::InMemory(int max_bytes) { - return new DefaultBackend(MEMORY_CACHE, net::CACHE_BACKEND_DEFAULT, + return new DefaultBackend(MEMORY_CACHE, CACHE_BACKEND_DEFAULT, base::FilePath(), max_bytes, NULL); } @@ -145,8 +145,10 @@ trans_(trans), entry_(entry), backend_(NULL) {} - WorkItem(WorkItemOperation operation, Transaction* trans, - const net::CompletionCallback& cb, disk_cache::Backend** backend) + WorkItem(WorkItemOperation operation, + Transaction* trans, + const CompletionCallback& cb, + disk_cache::Backend** backend) : operation_(operation), trans_(trans), entry_(NULL), @@ -186,7 +188,7 @@ WorkItemOperation operation_; Transaction* trans_; ActiveEntry** entry_; - net::CompletionCallback callback_; // User callback. + CompletionCallback callback_; // User callback. disk_cache::Backend** backend_; }; @@ -446,7 +448,7 @@ } //----------------------------------------------------------------------------- -HttpCache::HttpCache(const net::HttpNetworkSession::Params& params, +HttpCache::HttpCache(const HttpNetworkSession::Params& params, BackendFactory* backend_factory) : net_log_(params.net_log), backend_factory_(backend_factory), @@ -582,7 +584,7 @@ // Do lazy initialization of disk cache if needed. if (!disk_cache_.get()) { // We don't care about the result. - CreateBackend(NULL, net::CompletionCallback()); + CreateBackend(NULL, CompletionCallback()); } HttpCache::Transaction* trans = @@ -622,7 +624,7 @@ // Do lazy initialization of disk cache if needed. if (!disk_cache_.get()) { // We don't care about the result. - CreateBackend(NULL, net::CompletionCallback()); + CreateBackend(NULL, CompletionCallback()); } HttpCache::Transaction* transaction = @@ -655,7 +657,7 @@ //----------------------------------------------------------------------------- int HttpCache::CreateBackend(disk_cache::Backend** backend, - const net::CompletionCallback& callback) { + const CompletionCallback& callback) { if (!backend_factory_.get()) return ERR_FAILED; @@ -696,8 +698,8 @@ if (!building_backend_) return ERR_FAILED; - WorkItem* item = new WorkItem( - WI_CREATE_BACKEND, trans, net::CompletionCallback(), NULL); + WorkItem* item = + new WorkItem(WI_CREATE_BACKEND, trans, CompletionCallback(), NULL); PendingOp* pending_op = GetPendingOp(std::string()); DCHECK(pending_op->writer); pending_op->pending_queue.push_back(item);
diff --git a/net/http/http_cache.h b/net/http/http_cache.h index 8f48c2a..8e99a98 100644 --- a/net/http/http_cache.h +++ b/net/http/http_cache.h
@@ -128,7 +128,7 @@ // The disk cache is initialized lazily (by CreateTransaction) in this case. // The HttpCache takes ownership of the |backend_factory|. - HttpCache(const net::HttpNetworkSession::Params& params, + HttpCache(const HttpNetworkSession::Params& params, BackendFactory* backend_factory); // The disk cache is initialized lazily (by CreateTransaction) in this case. @@ -157,7 +157,7 @@ // |callback| will be notified when the operation completes. The pointer that // receives the |backend| must remain valid until the operation completes. int GetBackend(disk_cache::Backend** backend, - const net::CompletionCallback& callback); + const CompletionCallback& callback); // Returns the current backend (can be NULL). disk_cache::Backend* GetCurrentBackend() const; @@ -285,7 +285,7 @@ // Creates the |backend| object and notifies the |callback| when the operation // completes. Returns an error code. int CreateBackend(disk_cache::Backend** backend, - const net::CompletionCallback& callback); + const CompletionCallback& callback); // Makes sure that the backend creation is complete before allowing the // provided transaction to use the object. Returns an error code. |trans|
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index cebecda..83fea07 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc
@@ -53,6 +53,8 @@ using base::TimeDelta; using base::TimeTicks; +namespace net { + namespace { // TODO(ricea): Move this to HttpResponseHeaders once it is standardised. @@ -83,9 +85,9 @@ // TODO(brandonsalmon): Remove this when cache keys are stored // and no longer have to be recomputed to retrieve the OSCertHandle // from the disk. -std::string GetCacheKeyForCert(net::X509Certificate::OSCertHandle cert_handle) { - net::SHA1HashValue fingerprint = - net::X509Certificate::CalculateFingerprint(cert_handle); +std::string GetCacheKeyForCert(X509Certificate::OSCertHandle cert_handle) { + SHA1HashValue fingerprint = + X509Certificate::CalculateFingerprint(cert_handle); return "cert:" + base::HexEncode(fingerprint.data, arraysize(fingerprint.data)); @@ -100,7 +102,7 @@ int dist_from_root, bool is_leaf, const scoped_refptr<SharedChainData>& shared_chain_data, - net::X509Certificate::OSCertHandle cert_handle) { + X509Certificate::OSCertHandle cert_handle) { // If |num_pending_ops| is one, this was the last pending read operation // for this chain of certificates. The total time used to read the chain // can be calculated by subtracting the starting time from Now(). @@ -171,54 +173,9 @@ return status_code_range == 2 || status_code_range == 3; } -// Error codes that will be considered indicative of a page being offline/ -// unreachable for LOAD_FROM_CACHE_IF_OFFLINE. -bool IsOfflineError(int error) { - return (error == net::ERR_NAME_NOT_RESOLVED || - error == net::ERR_INTERNET_DISCONNECTED || - error == net::ERR_ADDRESS_UNREACHABLE || - error == net::ERR_CONNECTION_TIMED_OUT); -} - -// Enum for UMA, indicating the status (with regard to offline mode) of -// a particular request. -enum RequestOfflineStatus { - // A cache transaction hit in cache (data was present and not stale) - // and returned it. - OFFLINE_STATUS_FRESH_CACHE, - - // A network request was required for a cache entry, and it succeeded. - OFFLINE_STATUS_NETWORK_SUCCEEDED, - - // A network request was required for a cache entry, and it failed with - // a non-offline error. - OFFLINE_STATUS_NETWORK_FAILED, - - // A network request was required for a cache entry, it failed with an - // offline error, and we could serve stale data if - // LOAD_FROM_CACHE_IF_OFFLINE was set. - OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE, - - // A network request was required for a cache entry, it failed with - // an offline error, and there was no servable data in cache (even - // stale data). - OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE, - - OFFLINE_STATUS_MAX_ENTRIES -}; - -void RecordOfflineStatus(int load_flags, RequestOfflineStatus status) { - // Restrict to main frame to keep statistics close to - // "would have shown them something useful if offline mode was enabled". - if (load_flags & net::LOAD_MAIN_FRAME) { - UMA_HISTOGRAM_ENUMERATION("HttpCache.OfflineStatus", status, - OFFLINE_STATUS_MAX_ENTRIES); - } -} - void RecordNoStoreHeaderHistogram(int load_flags, - const net::HttpResponseInfo* response) { - if (load_flags & net::LOAD_MAIN_FRAME) { + const HttpResponseInfo* response) { + if (load_flags & LOAD_MAIN_FRAME) { UMA_HISTOGRAM_BOOLEAN( "Net.MainFrameNoStore", response->headers->HasHeaderValue("cache-control", "no-store")); @@ -226,9 +183,9 @@ } base::Value* NetLogAsyncRevalidationInfoCallback( - const net::NetLog::Source& source, - const net::HttpRequestInfo* request, - net::NetLogCaptureMode capture_mode) { + const NetLog::Source& source, + const HttpRequestInfo* request, + NetLogCaptureMode capture_mode) { base::DictionaryValue* dict = new base::DictionaryValue(); source.AddToEventParameters(dict); @@ -246,8 +203,6 @@ } // namespace -namespace net { - struct HeaderNameAndValue { const char* name; const char* value; @@ -1116,28 +1071,6 @@ if (!cache_.get()) return ERR_UNEXPECTED; - // If requested, and we have a readable cache entry, and we have - // an error indicating that we're offline as opposed to in contact - // with a bad server, read from cache anyway. - if (IsOfflineError(result)) { - if (mode_ == READ_WRITE && entry_ && !partial_) { - RecordOfflineStatus(effective_load_flags_, - OFFLINE_STATUS_DATA_AVAILABLE_OFFLINE); - if (effective_load_flags_ & LOAD_FROM_CACHE_IF_OFFLINE) { - UpdateTransactionPattern(PATTERN_NOT_COVERED); - response_.server_data_unavailable = true; - return SetupEntryForRead(); - } - } else { - RecordOfflineStatus(effective_load_flags_, - OFFLINE_STATUS_DATA_UNAVAILABLE_OFFLINE); - } - } else { - RecordOfflineStatus(effective_load_flags_, - (result == OK ? OFFLINE_STATUS_NETWORK_SUCCEEDED : - OFFLINE_STATUS_NETWORK_FAILED)); - } - // If we tried to conditionalize the request and failed, we know // we won't be reading from the cache after this point. if (couldnt_conditionalize_request_) @@ -2226,7 +2159,6 @@ if (skip_validation) { // TODO(ricea): Is this pattern okay for asynchronous revalidations? UpdateTransactionPattern(PATTERN_ENTRY_USED); - RecordOfflineStatus(effective_load_flags_, OFFLINE_STATUS_FRESH_CACHE); return SetupEntryForRead(); } else { // Make the network request conditional, to see if we may reuse our cached @@ -2756,7 +2688,7 @@ // blocking page is shown. An alternative would be to reverse-map the cert // status to a net error and replay the net error. if ((response_.headers->HasHeaderValue("cache-control", "no-store")) || - net::IsCertStatusError(response_.ssl_info.cert_status)) { + IsCertStatusError(response_.ssl_info.cert_status)) { DoneWritingToEntry(false); if (net_log_.GetCaptureMode().enabled()) net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
diff --git a/net/http/http_cache_transaction.h b/net/http/http_cache_transaction.h index d8642c8..d9d99e3 100644 --- a/net/http/http_cache_transaction.h +++ b/net/http/http_cache_transaction.h
@@ -138,7 +138,7 @@ bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; void SetPriority(RequestPriority priority) override; void SetWebSocketHandshakeStreamCreateHelper( - net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) override; + WebSocketHandshakeStreamBase::CreateHelper* create_helper) override; void SetBeforeNetworkStartCallback( const BeforeNetworkStartCallback& callback) override; void SetBeforeProxyHeadersSentCallback(
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index b64ebbf..5f855a7 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -34,7 +34,9 @@ #include "net/http/http_transaction_test_util.h" #include "net/http/http_util.h" #include "net/http/mock_http_cache.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/client_socket_handle.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/websockets/websocket_handshake_stream_base.h" @@ -42,19 +44,21 @@ using base::Time; +namespace net { + namespace { // Tests the load timing values of a request that goes through a // MockNetworkTransaction. -void TestLoadTimingNetworkRequest(const net::LoadTimingInfo& load_timing_info) { +void TestLoadTimingNetworkRequest(const LoadTimingInfo& load_timing_info) { EXPECT_FALSE(load_timing_info.socket_reused); - EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); + EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); - net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, - net::CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); + ExpectConnectTimingHasTimes(load_timing_info.connect_timing, + CONNECT_TIMING_HAS_CONNECT_TIMES_ONLY); EXPECT_LE(load_timing_info.connect_timing.connect_end, load_timing_info.send_start); @@ -67,14 +71,14 @@ } // Tests the load timing values of a request that receives a cached response. -void TestLoadTimingCachedResponse(const net::LoadTimingInfo& load_timing_info) { +void TestLoadTimingCachedResponse(const LoadTimingInfo& load_timing_info) { EXPECT_FALSE(load_timing_info.socket_reused); - EXPECT_EQ(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); + EXPECT_EQ(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); - net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); + ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); // Only the send start / end times should be sent, and they should have the // same value. @@ -87,7 +91,7 @@ EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); } -class DeleteCacheCompletionCallback : public net::TestCompletionCallbackBase { +class DeleteCacheCompletionCallback : public TestCompletionCallbackBase { public: explicit DeleteCacheCompletionCallback(MockHttpCache* cache) : cache_(cache), @@ -95,7 +99,7 @@ base::Unretained(this))) { } - const net::CompletionCallback& callback() const { return callback_; } + const CompletionCallback& callback() const { return callback_; } private: void OnComplete(int result) { @@ -104,7 +108,7 @@ } MockHttpCache* cache_; - net::CompletionCallback callback_; + CompletionCallback callback_; DISALLOW_COPY_AND_ASSIGN(DeleteCacheCompletionCallback); }; @@ -112,41 +116,41 @@ //----------------------------------------------------------------------------- // helpers -void ReadAndVerifyTransaction(net::HttpTransaction* trans, +void ReadAndVerifyTransaction(HttpTransaction* trans, const MockTransaction& trans_info) { std::string content; int rv = ReadTransaction(trans, &content); - EXPECT_EQ(net::OK, rv); + EXPECT_EQ(OK, rv); std::string expected(trans_info.data); EXPECT_EQ(expected, content); } -void RunTransactionTestBase(net::HttpCache* cache, +void RunTransactionTestBase(HttpCache* cache, const MockTransaction& trans_info, const MockHttpRequest& request, - net::HttpResponseInfo* response_info, - const net::BoundNetLog& net_log, - net::LoadTimingInfo* load_timing_info, + HttpResponseInfo* response_info, + const BoundNetLog& net_log, + LoadTimingInfo* load_timing_info, int64* received_bytes) { - net::TestCompletionCallback callback; + TestCompletionCallback callback; // write to the cache - scoped_ptr<net::HttpTransaction> trans; - int rv = cache->CreateTransaction(net::DEFAULT_PRIORITY, &trans); - EXPECT_EQ(net::OK, rv); + scoped_ptr<HttpTransaction> trans; + int rv = cache->CreateTransaction(DEFAULT_PRIORITY, &trans); + EXPECT_EQ(OK, rv); ASSERT_TRUE(trans.get()); rv = trans->Start(&request, callback.callback(), net_log); - if (rv == net::ERR_IO_PENDING) + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); ASSERT_EQ(trans_info.return_code, rv); - if (net::OK != rv) + if (OK != rv) return; - const net::HttpResponseInfo* response = trans->GetResponseInfo(); + const HttpResponseInfo* response = trans->GetResponseInfo(); ASSERT_TRUE(response); if (response_info) @@ -156,7 +160,7 @@ // If a fake network connection is used, need a NetLog to get a fake socket // ID. EXPECT_TRUE(net_log.net_log()); - *load_timing_info = net::LoadTimingInfo(); + *load_timing_info = LoadTimingInfo(); trans->GetLoadTimingInfo(load_timing_info); } @@ -166,65 +170,64 @@ *received_bytes = trans->GetTotalReceivedBytes(); } -void RunTransactionTestWithRequest(net::HttpCache* cache, +void RunTransactionTestWithRequest(HttpCache* cache, const MockTransaction& trans_info, const MockHttpRequest& request, - net::HttpResponseInfo* response_info) { + HttpResponseInfo* response_info) { RunTransactionTestBase(cache, trans_info, request, response_info, - net::BoundNetLog(), NULL, NULL); + BoundNetLog(), NULL, NULL); } -void RunTransactionTestAndGetTiming(net::HttpCache* cache, +void RunTransactionTestAndGetTiming(HttpCache* cache, const MockTransaction& trans_info, - const net::BoundNetLog& log, - net::LoadTimingInfo* load_timing_info) { + const BoundNetLog& log, + LoadTimingInfo* load_timing_info) { RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info), NULL, log, load_timing_info, NULL); } -void RunTransactionTest(net::HttpCache* cache, - const MockTransaction& trans_info) { - RunTransactionTestAndGetTiming(cache, trans_info, net::BoundNetLog(), NULL); +void RunTransactionTest(HttpCache* cache, const MockTransaction& trans_info) { + RunTransactionTestAndGetTiming(cache, trans_info, BoundNetLog(), NULL); } -void RunTransactionTestWithLog(net::HttpCache* cache, +void RunTransactionTestWithLog(HttpCache* cache, const MockTransaction& trans_info, - const net::BoundNetLog& log) { + const BoundNetLog& log) { RunTransactionTestAndGetTiming(cache, trans_info, log, NULL); } -void RunTransactionTestWithResponseInfo(net::HttpCache* cache, +void RunTransactionTestWithResponseInfo(HttpCache* cache, const MockTransaction& trans_info, - net::HttpResponseInfo* response) { + HttpResponseInfo* response) { RunTransactionTestWithRequest(cache, trans_info, MockHttpRequest(trans_info), response); } void RunTransactionTestWithResponseInfoAndGetTiming( - net::HttpCache* cache, + HttpCache* cache, const MockTransaction& trans_info, - net::HttpResponseInfo* response, - const net::BoundNetLog& log, - net::LoadTimingInfo* load_timing_info) { + HttpResponseInfo* response, + const BoundNetLog& log, + LoadTimingInfo* load_timing_info) { RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info), response, log, load_timing_info, NULL); } -void RunTransactionTestWithResponse(net::HttpCache* cache, +void RunTransactionTestWithResponse(HttpCache* cache, const MockTransaction& trans_info, std::string* response_headers) { - net::HttpResponseInfo response; + HttpResponseInfo response; RunTransactionTestWithResponseInfo(cache, trans_info, &response); response.headers->GetNormalizedHeaders(response_headers); } void RunTransactionTestWithResponseAndGetTiming( - net::HttpCache* cache, + HttpCache* cache, const MockTransaction& trans_info, std::string* response_headers, - const net::BoundNetLog& log, - net::LoadTimingInfo* load_timing_info) { - net::HttpResponseInfo response; + const BoundNetLog& log, + LoadTimingInfo* load_timing_info) { + HttpResponseInfo response; RunTransactionTestBase(cache, trans_info, MockHttpRequest(trans_info), &response, log, load_timing_info, NULL); response.headers->GetNormalizedHeaders(response_headers); @@ -241,7 +244,7 @@ void set_no_store(bool value) { no_store = value; } - static void FastNoStoreHandler(const net::HttpRequestInfo* request, + static void FastNoStoreHandler(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { @@ -256,20 +259,19 @@ bool FastTransactionServer::no_store; const MockTransaction kFastNoStoreGET_Transaction = { - "http://www.google.com/nostore", - "GET", - base::Time(), - "", - net::LOAD_VALIDATE_CACHE, - "HTTP/1.1 200 OK", - "Cache-Control: max-age=10000\n", - base::Time(), - "<html><body>Google Blah Blah</body></html>", - TEST_MODE_SYNC_NET_START, - &FastTransactionServer::FastNoStoreHandler, - 0, - net::OK -}; + "http://www.google.com/nostore", + "GET", + base::Time(), + "", + LOAD_VALIDATE_CACHE, + "HTTP/1.1 200 OK", + "Cache-Control: max-age=10000\n", + base::Time(), + "<html><body>Google Blah Blah</body></html>", + TEST_MODE_SYNC_NET_START, + &FastTransactionServer::FastNoStoreHandler, + 0, + OK}; // This class provides a handler for kRangeGET_TransactionOK so that the range // request can be served on demand. @@ -299,7 +301,7 @@ // the server reacts to requests headers like so: // X-Require-Mock-Auth -> return 401. // X-Return-Default-Range -> assume 40-49 was requested. - static void RangeHandler(const net::HttpRequestInfo* request, + static void RangeHandler(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data); @@ -327,7 +329,7 @@ static const char kExtraHeaderKey[] = "Extra"; // Static. -void RangeTransactionServer::RangeHandler(const net::HttpRequestInfo* request, +void RangeTransactionServer::RangeHandler(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { @@ -353,11 +355,11 @@ return; } - std::vector<net::HttpByteRange> ranges; + std::vector<HttpByteRange> ranges; std::string range_header; - if (!request->extra_headers.GetHeader( - net::HttpRequestHeaders::kRange, &range_header) || - !net::HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ || + if (!request->extra_headers.GetHeader(HttpRequestHeaders::kRange, + &range_header) || + !HttpUtil::ParseRangeHeader(range_header, &ranges) || bad_200_ || ranges.size() != 1) { // This is not a byte range request. We return 200. response_status->assign("HTTP/1.1 200 OK"); @@ -367,7 +369,7 @@ } // We can handle this range request. - net::HttpByteRange byte_range = ranges[0]; + HttpByteRange byte_range = ranges[0]; if (request->extra_headers.HasHeader("X-Return-Default-Range")) { byte_range.set_first_byte_position(40); @@ -419,24 +421,22 @@ } const MockTransaction kRangeGET_TransactionOK = { - "http://www.google.com/range", - "GET", - base::Time(), - "Range: bytes = 40-49\r\n" - EXTRA_HEADER, - net::LOAD_NORMAL, - "HTTP/1.1 206 Partial Content", - "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" - "ETag: \"foo\"\n" - "Accept-Ranges: bytes\n" - "Content-Length: 10\n", - base::Time(), - "rg: 40-49 ", - TEST_MODE_NORMAL, - &RangeTransactionServer::RangeHandler, - 0, - net::OK -}; + "http://www.google.com/range", + "GET", + base::Time(), + "Range: bytes = 40-49\r\n" EXTRA_HEADER, + LOAD_NORMAL, + "HTTP/1.1 206 Partial Content", + "Last-Modified: Sat, 18 Apr 2007 01:10:43 GMT\n" + "ETag: \"foo\"\n" + "Accept-Ranges: bytes\n" + "Content-Length: 10\n", + base::Time(), + "rg: 40-49 ", + TEST_MODE_NORMAL, + &RangeTransactionServer::RangeHandler, + 0, + OK}; const char kFullRangeData[] = "rg: 00-09 rg: 10-19 rg: 20-29 rg: 30-39 " @@ -445,10 +445,10 @@ // Verifies the response headers (|response|) match a partial content // response for the range starting at |start| and ending at |end|. void Verify206Response(std::string response, int start, int end) { - std::string raw_headers(net::HttpUtil::AssembleRawHeaders(response.data(), - response.size())); - scoped_refptr<net::HttpResponseHeaders> headers( - new net::HttpResponseHeaders(raw_headers)); + std::string raw_headers( + HttpUtil::AssembleRawHeaders(response.data(), response.size())); + scoped_refptr<HttpResponseHeaders> headers( + new HttpResponseHeaders(raw_headers)); ASSERT_EQ(206, headers->response_code()); @@ -470,20 +470,20 @@ ASSERT_TRUE(cache->CreateBackendEntry(kRangeGET_TransactionOK.url, &entry, NULL)); - raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(), - raw_headers.size()); + raw_headers = + HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size()); - net::HttpResponseInfo response; + HttpResponseInfo response; response.response_time = base::Time::Now(); response.request_time = base::Time::Now(); - response.headers = new net::HttpResponseHeaders(raw_headers); + response.headers = new HttpResponseHeaders(raw_headers); // Set the last argument for this to be an incomplete request. EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100)); + scoped_refptr<IOBuffer> buf(new IOBuffer(100)); int len = static_cast<int>(base::strlcpy(buf->data(), "rg: 00-09 rg: 10-19 ", 100)); - net::TestCompletionCallback cb; + TestCompletionCallback cb; int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true); EXPECT_EQ(len, cb.GetResult(rv)); entry->Close(); @@ -508,24 +508,24 @@ }; struct Context { - Context() : result(net::ERR_IO_PENDING) {} + Context() : result(ERR_IO_PENDING) {} int result; - net::TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; + TestCompletionCallback callback; + scoped_ptr<HttpTransaction> trans; }; class FakeWebSocketHandshakeStreamCreateHelper - : public net::WebSocketHandshakeStreamBase::CreateHelper { + : public WebSocketHandshakeStreamBase::CreateHelper { public: ~FakeWebSocketHandshakeStreamCreateHelper() override {} - net::WebSocketHandshakeStreamBase* CreateBasicStream( - scoped_ptr<net::ClientSocketHandle> connect, + WebSocketHandshakeStreamBase* CreateBasicStream( + scoped_ptr<ClientSocketHandle> connect, bool using_proxy) override { return NULL; } - net::WebSocketHandshakeStreamBase* CreateSpdyStream( - const base::WeakPtr<net::SpdySession>& session, + WebSocketHandshakeStreamBase* CreateSpdyStream( + const base::WeakPtr<SpdySession>& session, bool use_relative_url) override { return NULL; } @@ -534,14 +534,14 @@ // Returns true if |entry| is not one of the log types paid attention to in this // test. Note that TYPE_HTTP_CACHE_WRITE_INFO and TYPE_HTTP_CACHE_*_DATA are // ignored. -bool ShouldIgnoreLogEntry(const net::TestNetLog::CapturedEntry& entry) { +bool ShouldIgnoreLogEntry(const CapturedNetLogEntry& entry) { switch (entry.type) { - case net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND: - case net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY: - case net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY: - case net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY: - case net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY: - case net::NetLog::TYPE_HTTP_CACHE_READ_INFO: + case NetLog::TYPE_HTTP_CACHE_GET_BACKEND: + case NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY: + case NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY: + case NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY: + case NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY: + case NetLog::TYPE_HTTP_CACHE_READ_INFO: return false; default: return true; @@ -550,15 +550,15 @@ // Modifies |entries| to only include log entries created by the cache layer and // asserted on in these tests. -void FilterLogEntries(net::TestNetLog::CapturedEntryList* entries) { +void FilterLogEntries(CapturedNetLogEntry::List* entries) { entries->erase(std::remove_if(entries->begin(), entries->end(), &ShouldIgnoreLogEntry), entries->end()); } -bool LogContainsEventType(const net::BoundTestNetLog& log, - net::NetLog::EventType expected) { - net::TestNetLog::CapturedEntryList entries; +bool LogContainsEventType(const BoundTestNetLog& log, + NetLog::EventType expected) { + CapturedNetLogEntry::List entries; log.GetEntries(&entries); for (size_t i = 0; i < entries.size(); i++) { if (entries[i].type == expected) @@ -576,25 +576,25 @@ TEST(HttpCache, CreateThenDestroy) { MockHttpCache cache; - scoped_ptr<net::HttpTransaction> trans; - EXPECT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + EXPECT_EQ(OK, cache.CreateTransaction(&trans)); ASSERT_TRUE(trans.get()); } TEST(HttpCache, GetBackend) { - MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(0)); + MockHttpCache cache(HttpCache::DefaultBackend::InMemory(0)); disk_cache::Backend* backend; - net::TestCompletionCallback cb; + TestCompletionCallback cb; // This will lazily initialize the backend. int rv = cache.http_cache()->GetBackend(&backend, cb.callback()); - EXPECT_EQ(net::OK, cb.GetResult(rv)); + EXPECT_EQ(OK, cb.GetResult(rv)); } TEST(HttpCache, SimpleGET) { MockHttpCache cache; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; // Write to the cache. RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction, @@ -611,8 +611,8 @@ cache.disk_cache()->set_fail_requests(); - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; // Read from the network, and don't use the cache. RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction, @@ -620,23 +620,23 @@ // Check that the NetLog was filled as expected. // (We attempted to both Open and Create entries, but both failed). - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); FilterLogEntries(&entries); EXPECT_EQ(6u, entries.size()); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); EXPECT_EQ(1, cache.network_layer()->transaction_count()); EXPECT_EQ(0, cache.disk_cache()->open_count()); @@ -666,15 +666,15 @@ RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); MockHttpRequest request(kSimpleGET_Transaction); - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); const int kBufferSize = 10; - scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kBufferSize)); - net::ReleaseBufferCompletionCallback cb(buffer.get()); + scoped_refptr<IOBuffer> buffer(new IOBuffer(kBufferSize)); + ReleaseBufferCompletionCallback cb(buffer.get()); - int rv = trans->Start(&request, cb.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, cb.GetResult(rv)); + int rv = trans->Start(&request, cb.callback(), BoundNetLog()); + EXPECT_EQ(OK, cb.GetResult(rv)); rv = trans->Read(buffer.get(), kBufferSize, cb.callback()); EXPECT_EQ(kBufferSize, cb.GetResult(rv)); @@ -709,10 +709,10 @@ scoped_ptr<Context> c(new Context()); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); rv = c->callback.WaitForResult(); // Start failing request now. @@ -754,11 +754,11 @@ // Now fail to read from the cache. scoped_ptr<Context> c(new Context()); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); MockHttpRequest request(kSimpleGET_Transaction); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, c->callback.GetResult(rv)); + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, c->callback.GetResult(rv)); // Now verify that the entry was removed from the cache. cache.disk_cache()->set_soft_failures(false); @@ -777,41 +777,41 @@ TEST(HttpCache, SimpleGET_LoadOnlyFromCache_Hit) { MockHttpCache cache; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; // Write to the cache. RunTransactionTestAndGetTiming(cache.http_cache(), kSimpleGET_Transaction, log.bound(), &load_timing_info); // Check that the NetLog was filled as expected. - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); FilterLogEntries(&entries); EXPECT_EQ(8u, entries.size()); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 6, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 7, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); TestLoadTimingNetworkRequest(load_timing_info); // Force this transaction to read from the cache. MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; log.Clear(); @@ -823,22 +823,22 @@ FilterLogEntries(&entries); EXPECT_EQ(8u, entries.size()); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 2, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 3, net::NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 4, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 5, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 6, net::NetLog::TYPE_HTTP_CACHE_READ_INFO)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 7, net::NetLog::TYPE_HTTP_CACHE_READ_INFO)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_READ_INFO)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_READ_INFO)); EXPECT_EQ(1, cache.network_layer()->transaction_count()); EXPECT_EQ(1, cache.disk_cache()->open_count()); @@ -851,18 +851,18 @@ // force this transaction to read from the cache MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; MockHttpRequest request(transaction); - net::TestCompletionCallback callback; + TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_CACHE_MISS, rv); + ASSERT_EQ(ERR_CACHE_MISS, rv); trans.reset(); @@ -879,7 +879,7 @@ // force this transaction to read from the cache if valid MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_PREFERRING_CACHE; + transaction.load_flags |= LOAD_PREFERRING_CACHE; RunTransactionTest(cache.http_cache(), transaction); @@ -893,7 +893,7 @@ // force this transaction to read from the cache if valid MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_PREFERRING_CACHE; + transaction.load_flags |= LOAD_PREFERRING_CACHE; RunTransactionTest(cache.http_cache(), transaction); @@ -915,7 +915,7 @@ RunTransactionTest(cache.http_cache(), transaction); // Read from the cache. - transaction.load_flags |= net::LOAD_PREFERRING_CACHE; + transaction.load_flags |= LOAD_PREFERRING_CACHE; RunTransactionTest(cache.http_cache(), transaction); EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -938,10 +938,10 @@ // Attempt to read from the cache... this is a vary mismatch that must reach // the network again. - transaction.load_flags |= net::LOAD_PREFERRING_CACHE; + transaction.load_flags |= LOAD_PREFERRING_CACHE; transaction.request_headers = "Foo: none\r\n"; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(), &load_timing_info); @@ -952,106 +952,6 @@ RemoveMockTransaction(&transaction); } -// Tests that LOAD_FROM_CACHE_IF_OFFLINE returns proper response on -// network success -TEST(HttpCache, SimpleGET_CacheOverride_Network) { - MockHttpCache cache; - - // Prime cache. - MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_FROM_CACHE_IF_OFFLINE; - transaction.response_headers = "Cache-Control: no-cache\n"; - - AddMockTransaction(&transaction); - RunTransactionTest(cache.http_cache(), transaction); - EXPECT_EQ(1, cache.network_layer()->transaction_count()); - EXPECT_EQ(1, cache.disk_cache()->create_count()); - RemoveMockTransaction(&transaction); - - // Re-run transaction; make sure the result came from the network, - // not the cache. - transaction.data = "Changed data."; - AddMockTransaction(&transaction); - net::HttpResponseInfo response_info; - RunTransactionTestWithResponseInfo(cache.http_cache(), transaction, - &response_info); - - EXPECT_EQ(2, cache.network_layer()->transaction_count()); - EXPECT_FALSE(response_info.server_data_unavailable); - EXPECT_TRUE(response_info.network_accessed); - - RemoveMockTransaction(&transaction); -} - -// Tests that LOAD_FROM_CACHE_IF_OFFLINE returns proper response on -// offline failure -TEST(HttpCache, SimpleGET_CacheOverride_Offline) { - MockHttpCache cache; - - // Prime cache. - MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_FROM_CACHE_IF_OFFLINE; - transaction.response_headers = "Cache-Control: no-cache\n"; - - AddMockTransaction(&transaction); - RunTransactionTest(cache.http_cache(), transaction); - EXPECT_EQ(1, cache.network_layer()->transaction_count()); - EXPECT_EQ(1, cache.disk_cache()->create_count()); - RemoveMockTransaction(&transaction); - - // Network failure with offline error; should return cache entry above + - // flag signalling stale data. - transaction.return_code = net::ERR_NAME_NOT_RESOLVED; - AddMockTransaction(&transaction); - - MockHttpRequest request(transaction); - net::TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); - - const net::HttpResponseInfo* response_info = trans->GetResponseInfo(); - ASSERT_TRUE(response_info); - EXPECT_TRUE(response_info->server_data_unavailable); - EXPECT_TRUE(response_info->was_cached); - EXPECT_FALSE(response_info->network_accessed); - ReadAndVerifyTransaction(trans.get(), transaction); - EXPECT_EQ(2, cache.network_layer()->transaction_count()); - - RemoveMockTransaction(&transaction); -} - -// Tests that LOAD_FROM_CACHE_IF_OFFLINE returns proper response on -// non-offline failure. -TEST(HttpCache, SimpleGET_CacheOverride_NonOffline) { - MockHttpCache cache; - - // Prime cache. - MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_FROM_CACHE_IF_OFFLINE; - transaction.response_headers = "Cache-Control: no-cache\n"; - - AddMockTransaction(&transaction); - RunTransactionTest(cache.http_cache(), transaction); - EXPECT_EQ(1, cache.network_layer()->transaction_count()); - EXPECT_EQ(1, cache.disk_cache()->create_count()); - RemoveMockTransaction(&transaction); - - // Network failure with non-offline error; should fail with that error. - transaction.return_code = net::ERR_PROXY_CONNECTION_FAILED; - AddMockTransaction(&transaction); - - net::HttpResponseInfo response_info2; - RunTransactionTestWithResponseInfo(cache.http_cache(), transaction, - &response_info2); - - EXPECT_EQ(2, cache.network_layer()->transaction_count()); - EXPECT_FALSE(response_info2.server_data_unavailable); - - RemoveMockTransaction(&transaction); -} - // Tests that was_cached was set properly on a failure, even if the cached // response wasn't returned. TEST(HttpCache, SimpleGET_CacheSignal_Failure) { @@ -1068,19 +968,19 @@ RemoveMockTransaction(&transaction); // Network failure with error; should fail but have was_cached set. - transaction.return_code = net::ERR_FAILED; + transaction.return_code = ERR_FAILED; AddMockTransaction(&transaction); MockHttpRequest request(transaction); - net::TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY, &trans); - EXPECT_EQ(net::OK, rv); + TestCompletionCallback callback; + scoped_ptr<HttpTransaction> trans; + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans); + EXPECT_EQ(OK, rv); ASSERT_TRUE(trans.get()); - rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::ERR_FAILED, callback.GetResult(rv)); + rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_FAILED, callback.GetResult(rv)); - const net::HttpResponseInfo* response_info = trans->GetResponseInfo(); + const HttpResponseInfo* response_info = trans->GetResponseInfo(); ASSERT_TRUE(response_info); EXPECT_TRUE(response_info->was_cached); EXPECT_EQ(2, cache.network_layer()->transaction_count()); @@ -1093,7 +993,7 @@ MockHttpCache cache; // write to the cache - net::HttpResponseInfo response_info; + HttpResponseInfo response_info; RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction, &response_info); @@ -1116,7 +1016,7 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Re-run transaction; make sure we don't mark the network as accessed. - net::HttpResponseInfo response_info; + HttpResponseInfo response_info; RunTransactionTestWithResponseInfo(cache.http_cache(), transaction, &response_info); @@ -1133,37 +1033,37 @@ // Force this transaction to write to the cache again. MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_BYPASS_CACHE; + transaction.load_flags |= LOAD_BYPASS_CACHE; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; // Write to the cache. RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(), &load_timing_info); // Check that the NetLog was filled as expected. - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); FilterLogEntries(&entries); EXPECT_EQ(8u, entries.size()); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 0, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 1, net::NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 2, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 3, net::NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 4, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 5, net::NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); - EXPECT_TRUE(net::LogContainsBeginEvent( - entries, 6, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); - EXPECT_TRUE(net::LogContainsEndEvent( - entries, 7, net::NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 0, NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 1, NetLog::TYPE_HTTP_CACHE_GET_BACKEND)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 2, NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 3, NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 4, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 5, NetLog::TYPE_HTTP_CACHE_CREATE_ENTRY)); + EXPECT_TRUE( + LogContainsBeginEvent(entries, 6, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); + EXPECT_TRUE( + LogContainsEndEvent(entries, 7, NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY)); EXPECT_EQ(2, cache.network_layer()->transaction_count()); EXPECT_EQ(0, cache.disk_cache()->open_count()); @@ -1216,11 +1116,11 @@ // Force this transaction to validate the cache. MockTransaction transaction(kSimpleGET_Transaction); - transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.load_flags |= LOAD_VALIDATE_CACHE; - net::HttpResponseInfo response_info; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + HttpResponseInfo response_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestWithResponseInfoAndGetTiming( cache.http_cache(), transaction, &response_info, log.bound(), &load_timing_info); @@ -1252,11 +1152,10 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); } -static void PreserveRequestHeaders_Handler( - const net::HttpRequestInfo* request, - std::string* response_status, - std::string* response_headers, - std::string* response_data) { +static void PreserveRequestHeaders_Handler(const HttpRequestInfo* request, + std::string* response_status, + std::string* response_headers, + std::string* response_data) { EXPECT_TRUE(request->extra_headers.HasHeader(kExtraHeaderKey)); } @@ -1314,17 +1213,17 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); - EXPECT_EQ(net::LOAD_STATE_IDLE, c->trans->GetLoadState()); + ASSERT_EQ(OK, c->result); + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState()); - c->result = c->trans->Start( - &request, c->callback.callback(), net::BoundNetLog()); + c->result = + c->trans->Start(&request, c->callback.callback(), BoundNetLog()); } // All requests are waiting for the active entry. for (int i = 0; i < kNumTransactions; ++i) { Context* c = context_list[i]; - EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState()); + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, c->trans->GetLoadState()); } // Allow all requests to move from the Create queue to the active entry. @@ -1341,12 +1240,12 @@ // Read, i.e. idle. for (int i = 0; i < kNumTransactions; ++i) { Context* c = context_list[i]; - EXPECT_EQ(net::LOAD_STATE_IDLE, c->trans->GetLoadState()); + EXPECT_EQ(LOAD_STATE_IDLE, c->trans->GetLoadState()); } for (int i = 0; i < kNumTransactions; ++i) { Context* c = context_list[i]; - if (c->result == net::ERR_IO_PENDING) + if (c->result == ERR_IO_PENDING) c->result = c->callback.WaitForResult(); ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); } @@ -1372,7 +1271,7 @@ MockHttpRequest request(kSimpleGET_Transaction); MockHttpRequest reader_request(kSimpleGET_Transaction); - reader_request.load_flags = net::LOAD_ONLY_FROM_CACHE; + reader_request.load_flags = LOAD_ONLY_FROM_CACHE; std::vector<Context*> context_list; const int kNumTransactions = 5; @@ -1382,14 +1281,14 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); MockHttpRequest* this_request = &request; if (i == 1 || i == 2) this_request = &reader_request; - c->result = c->trans->Start( - this_request, c->callback.callback(), net::BoundNetLog()); + c->result = + c->trans->Start(this_request, c->callback.callback(), BoundNetLog()); } // Allow all requests to move from the Create queue to the active entry. @@ -1403,21 +1302,20 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); Context* c = context_list[0]; - ASSERT_EQ(net::ERR_IO_PENDING, c->result); + ASSERT_EQ(ERR_IO_PENDING, c->result); c->result = c->callback.WaitForResult(); ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); // Now we have 2 active readers and two queued transactions. - EXPECT_EQ(net::LOAD_STATE_IDLE, - context_list[2]->trans->GetLoadState()); - EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_CACHE, + EXPECT_EQ(LOAD_STATE_IDLE, context_list[2]->trans->GetLoadState()); + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, context_list[3]->trans->GetLoadState()); c = context_list[1]; - ASSERT_EQ(net::ERR_IO_PENDING, c->result); + ASSERT_EQ(ERR_IO_PENDING, c->result); c->result = c->callback.WaitForResult(); - if (c->result == net::OK) + if (c->result == OK) ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); // At this point we have one reader, two pending transactions and a task on @@ -1430,9 +1328,9 @@ for (int i = 3; i < kNumTransactions; ++i) { Context* c = context_list[i]; - if (c->result == net::ERR_IO_PENDING) + if (c->result == ERR_IO_PENDING) c->result = c->callback.WaitForResult(); - if (c->result == net::OK) + if (c->result == OK) ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); } @@ -1453,11 +1351,11 @@ // See http://code.google.com/p/chromium/issues/detail?id=25588 TEST(HttpCache, SimpleGET_DoomWithPending) { // We need simultaneous doomed / not_doomed entries so let's use a real cache. - MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024)); + MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024)); MockHttpRequest request(kSimpleGET_Transaction); MockHttpRequest writer_request(kSimpleGET_Transaction); - writer_request.load_flags = net::LOAD_BYPASS_CACHE; + writer_request.load_flags = LOAD_BYPASS_CACHE; ScopedVector<Context> context_list; const int kNumTransactions = 4; @@ -1467,14 +1365,14 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); MockHttpRequest* this_request = &request; if (i == 3) this_request = &writer_request; - c->result = c->trans->Start( - this_request, c->callback.callback(), net::BoundNetLog()); + c->result = + c->trans->Start(this_request, c->callback.callback(), BoundNetLog()); } // The first request should be a writer at this point, and the two subsequent @@ -1490,7 +1388,7 @@ if (i == 1) continue; Context* c = context_list[i]; - ASSERT_EQ(net::ERR_IO_PENDING, c->result); + ASSERT_EQ(ERR_IO_PENDING, c->result); c->result = c->callback.WaitForResult(); ReadAndVerifyTransaction(c->trans.get(), kSimpleGET_Transaction); } @@ -1515,10 +1413,10 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); - c->result = c->trans->Start( - &request, c->callback.callback(), net::BoundNetLog()); + c->result = + c->trans->Start(&request, c->callback.callback(), BoundNetLog()); } // Allow all requests to move from the Create queue to the active entry. @@ -1536,7 +1434,7 @@ for (int i = 0; i < kNumTransactions; ++i) { Context* c = context_list[i]; - if (c->result == net::ERR_IO_PENDING) + if (c->result == ERR_IO_PENDING) c->result = c->callback.WaitForResult(); ReadAndVerifyTransaction(c->trans.get(), kFastNoStoreGET_Transaction); delete c; @@ -1562,10 +1460,10 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); - c->result = c->trans->Start( - &request, c->callback.callback(), net::BoundNetLog()); + c->result = + c->trans->Start(&request, c->callback.callback(), BoundNetLog()); } // Allow all requests to move from the Create queue to the active entry. @@ -1580,7 +1478,7 @@ for (int i = 0; i < kNumTransactions; ++i) { Context* c = context_list[i]; - if (c->result == net::ERR_IO_PENDING) + if (c->result == ERR_IO_PENDING) c->result = c->callback.WaitForResult(); // Destroy only the first transaction. if (i == 0) { @@ -1622,10 +1520,10 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); - c->result = c->trans->Start( - &request, c->callback.callback(), net::BoundNetLog()); + c->result = + c->trans->Start(&request, c->callback.callback(), BoundNetLog()); } // The first request should be creating the disk cache entry and the others @@ -1673,11 +1571,10 @@ Context* c = new Context(); c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); - c->result = c->trans->Start( - &request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::ERR_IO_PENDING, c->result); + c->result = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, c->result); // Release the reference that the mock disk cache keeps for this entry, so // that we test that the http cache handles the cancellation correctly. @@ -1693,7 +1590,7 @@ MockHttpCache cache; MockHttpRequest request(kSimpleGET_Transaction); - request.load_flags = net::LOAD_BYPASS_CACHE; + request.load_flags = LOAD_BYPASS_CACHE; std::vector<Context*> context_list; const int kNumTransactions = 5; @@ -1703,10 +1600,10 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); - c->result = c->trans->Start( - &request, c->callback.callback(), net::BoundNetLog()); + c->result = + c->trans->Start(&request, c->callback.callback(), BoundNetLog()); } // The first request should be deleting the disk cache entry and the others @@ -1742,14 +1639,12 @@ MockHttpRequest request(kSimpleGET_Transaction); Context c1, c2; - ASSERT_EQ(net::OK, cache.CreateTransaction(&c1.trans)); - ASSERT_EQ(net::ERR_IO_PENDING, - c1.trans->Start(&request, c1.callback.callback(), - net::BoundNetLog())); - ASSERT_EQ(net::OK, cache.CreateTransaction(&c2.trans)); - ASSERT_EQ(net::ERR_IO_PENDING, - c2.trans->Start(&request, c2.callback.callback(), - net::BoundNetLog())); + ASSERT_EQ(OK, cache.CreateTransaction(&c1.trans)); + ASSERT_EQ(ERR_IO_PENDING, + c1.trans->Start(&request, c1.callback.callback(), BoundNetLog())); + ASSERT_EQ(OK, cache.CreateTransaction(&c2.trans)); + ASSERT_EQ(ERR_IO_PENDING, + c2.trans->Start(&request, c2.callback.callback(), BoundNetLog())); // The second request is queued after the first one. @@ -1768,18 +1663,18 @@ RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); MockHttpRequest request(kSimpleGET_Transaction); - net::TestCompletionCallback callback; + TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); rv = trans->Read(buf.get(), 256, callback.callback()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + EXPECT_EQ(ERR_IO_PENDING, rv); // Test that destroying the transaction while it is reading from the cache // works properly. @@ -1806,10 +1701,10 @@ Context* c = context_list[i]; c->result = cache->CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); - c->result = c->trans->Start( - &request, c->callback.callback(), net::BoundNetLog()); + c->result = + c->trans->Start(&request, c->callback.callback(), BoundNetLog()); } // The first request should be creating the disk cache entry and the others @@ -1845,15 +1740,15 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); } context_list[0]->result = context_list[0]->trans->Start( - &request0, context_list[0]->callback.callback(), net::BoundNetLog()); + &request0, context_list[0]->callback.callback(), BoundNetLog()); context_list[1]->result = context_list[1]->trans->Start( - &request1, context_list[1]->callback.callback(), net::BoundNetLog()); + &request1, context_list[1]->callback.callback(), BoundNetLog()); context_list[2]->result = context_list[2]->trans->Start( - &request2, context_list[2]->callback.callback(), net::BoundNetLog()); + &request2, context_list[2]->callback.callback(), BoundNetLog()); // Just to make sure that everything is still pending. base::MessageLoop::current()->RunUntilIdle(); @@ -1891,15 +1786,15 @@ Context* c = context_list[i]; c->result = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); } context_list[0]->result = context_list[0]->trans->Start( - &request0, context_list[0]->callback.callback(), net::BoundNetLog()); + &request0, context_list[0]->callback.callback(), BoundNetLog()); context_list[1]->result = context_list[1]->trans->Start( - &request1, context_list[1]->callback.callback(), net::BoundNetLog()); + &request1, context_list[1]->callback.callback(), BoundNetLog()); context_list[2]->result = context_list[2]->trans->Start( - &request2, context_list[2]->callback.callback(), net::BoundNetLog()); + &request2, context_list[2]->callback.callback(), BoundNetLog()); // Just to make sure that everything is still pending. base::MessageLoop::current()->RunUntilIdle(); @@ -1937,9 +1832,9 @@ scoped_ptr<Context> c(new Context()); c->result = cache->CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); - c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); + c->trans->Start(&request, c->callback.callback(), BoundNetLog()); // Just to make sure that everything is still pending. base::MessageLoop::current()->RunUntilIdle(); @@ -1949,14 +1844,14 @@ // We cannot call FinishCreation because the factory itself will go away with // the cache, so grab the callback and attempt to use it. - net::CompletionCallback callback = factory->callback(); + CompletionCallback callback = factory->callback(); scoped_ptr<disk_cache::Backend>* backend = factory->backend(); cache.reset(); base::MessageLoop::current()->RunUntilIdle(); backend->reset(); - callback.Run(net::ERR_ABORTED); + callback.Run(ERR_ABORTED); } // Tests that we can delete the cache while creating the backend, from within @@ -1968,21 +1863,21 @@ DeleteCacheCompletionCallback cb(cache); disk_cache::Backend* backend; int rv = cache->http_cache()->GetBackend(&backend, cb.callback()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + EXPECT_EQ(ERR_IO_PENDING, rv); // Now let's queue a regular transaction MockHttpRequest request(kSimpleGET_Transaction); scoped_ptr<Context> c(new Context()); c->result = cache->CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, c->result); + ASSERT_EQ(OK, c->result); - c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); + c->trans->Start(&request, c->callback.callback(), BoundNetLog()); // And another direct backend request. - net::TestCompletionCallback cb2; + TestCompletionCallback cb2; rv = cache->http_cache()->GetBackend(&backend, cb2.callback()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + EXPECT_EQ(ERR_IO_PENDING, rv); // Just to make sure that everything is still pending. base::MessageLoop::current()->RunUntilIdle(); @@ -1996,7 +1891,7 @@ // The cache should be gone by now. base::MessageLoop::current()->RunUntilIdle(); - EXPECT_EQ(net::OK, c->callback.GetResult(c->result)); + EXPECT_EQ(OK, c->callback.GetResult(c->result)); EXPECT_FALSE(cb2.have_result()); } @@ -2012,8 +1907,8 @@ // Get the same URL again, but this time we expect it to result // in a conditional request. - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestAndGetTiming(cache.http_cache(), kTypicalGET_Transaction, log.bound(), &load_timing_info); @@ -2023,13 +1918,12 @@ TestLoadTimingNetworkRequest(load_timing_info); } -static void ETagGet_ConditionalRequest_Handler( - const net::HttpRequestInfo* request, - std::string* response_status, - std::string* response_headers, - std::string* response_data) { +static void ETagGet_ConditionalRequest_Handler(const HttpRequestInfo* request, + std::string* response_status, + std::string* response_headers, + std::string* response_data) { EXPECT_TRUE( - request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch)); + request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch)); response_status->assign("HTTP/1.1 304 Not Modified"); response_headers->assign(kETagGET_Transaction.response_headers); response_data->clear(); @@ -2049,10 +1943,10 @@ // Get the same URL again, but this time we expect it to result // in a conditional request. - transaction.load_flags = net::LOAD_VALIDATE_CACHE; + transaction.load_flags = LOAD_VALIDATE_CACHE; transaction.handler = ETagGet_ConditionalRequest_Handler; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(), &load_timing_info); @@ -2072,7 +1966,7 @@ bool EtagUsed() { return s_etag_used_; } bool LastModifiedUsed() { return s_last_modified_used_; } - static void Handler(const net::HttpRequestInfo* request, + static void Handler(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data); @@ -2084,15 +1978,14 @@ bool RevalidationServer::s_etag_used_ = false; bool RevalidationServer::s_last_modified_used_ = false; -void RevalidationServer::Handler(const net::HttpRequestInfo* request, +void RevalidationServer::Handler(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { - if (request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch)) + if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch)) s_etag_used_ = true; - if (request->extra_headers.HasHeader( - net::HttpRequestHeaders::kIfModifiedSince)) { + if (request->extra_headers.HasHeader(HttpRequestHeaders::kIfModifiedSince)) { s_last_modified_used_ = true; } @@ -2126,8 +2019,8 @@ // Read from the cache. RevalidationServer server; transaction.handler = server.Handler; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(), &load_timing_info); @@ -2160,8 +2053,8 @@ RevalidationServer server; transaction.handler = server.Handler; transaction.request_headers = "Foo: none\r\n"; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(), &load_timing_info); @@ -2193,8 +2086,8 @@ RevalidationServer server; transaction.handler = server.Handler; transaction.request_headers = "Foo: none\r\n"; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestAndGetTiming(cache.http_cache(), transaction, log.bound(), &load_timing_info); @@ -2355,13 +2248,12 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); } -static void ETagGet_UnconditionalRequest_Handler( - const net::HttpRequestInfo* request, - std::string* response_status, - std::string* response_headers, - std::string* response_data) { +static void ETagGet_UnconditionalRequest_Handler(const HttpRequestInfo* request, + std::string* response_status, + std::string* response_headers, + std::string* response_data) { EXPECT_FALSE( - request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch)); + request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch)); } TEST(HttpCache, ETagGET_Http10) { @@ -2378,7 +2270,7 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Get the same URL again, without generating a conditional request. - transaction.load_flags = net::LOAD_VALIDATE_CACHE; + transaction.load_flags = LOAD_VALIDATE_CACHE; transaction.handler = ETagGet_UnconditionalRequest_Handler; RunTransactionTest(cache.http_cache(), transaction); @@ -2401,7 +2293,7 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Get the same URL again, but use a byte range request. - transaction.load_flags = net::LOAD_VALIDATE_CACHE; + transaction.load_flags = LOAD_VALIDATE_CACHE; transaction.handler = ETagGet_UnconditionalRequest_Handler; transaction.request_headers = "Range: bytes = 5-\r\n"; RunTransactionTest(cache.http_cache(), transaction); @@ -2412,12 +2304,12 @@ } static void ETagGet_ConditionalRequest_NoStore_Handler( - const net::HttpRequestInfo* request, + const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { EXPECT_TRUE( - request->extra_headers.HasHeader(net::HttpRequestHeaders::kIfNoneMatch)); + request->extra_headers.HasHeader(HttpRequestHeaders::kIfNoneMatch)); response_status->assign("HTTP/1.1 304 Not Modified"); response_headers->assign("Cache-Control: no-store\n"); response_data->clear(); @@ -2437,7 +2329,7 @@ // Get the same URL again, but this time we expect it to result // in a conditional request. - transaction.load_flags = net::LOAD_VALIDATE_CACHE; + transaction.load_flags = LOAD_VALIDATE_CACHE; transaction.handler = ETagGet_ConditionalRequest_NoStore_Handler; RunTransactionTest(cache.http_cache(), transaction); @@ -2509,7 +2401,7 @@ // Request |kUrl| a second time. Now |kNetResponse1| it is in the HTTP // cache, so we don't hit the network. - request.load_flags = net::LOAD_ONLY_FROM_CACHE; + request.load_flags = LOAD_ONLY_FROM_CACHE; kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock. net_response_1.AssignTo(&request); // Expected result. @@ -2528,7 +2420,7 @@ // different -- this simulates a change made to the CSS file. request.request_headers = extra_request_headers; - request.load_flags = net::LOAD_NORMAL; + request.load_flags = LOAD_NORMAL; net_response_2.AssignTo(&mock_network_response); // Network mock. net_response_2.AssignTo(&request); // Expected result. @@ -2547,7 +2439,7 @@ // value in the cache with the modified response. request.request_headers = ""; - request.load_flags = net::LOAD_ONLY_FROM_CACHE; + request.load_flags = LOAD_ONLY_FROM_CACHE; kUnexpectedResponse.AssignTo(&mock_network_response); // Network mock. cached_response_2.AssignTo(&request); // Expected result. @@ -2901,7 +2793,7 @@ // Since the cache key strips the hash sections, this should be a cache hit. std::string url_with_hash = std::string(trans.url) + "#multiple#hashes"; trans.url = url_with_hash.c_str(); - trans.load_flags = net::LOAD_ONLY_FROM_CACHE; + trans.load_flags = LOAD_ONLY_FROM_CACHE; RunTransactionTest(cache.http_cache(), trans); @@ -2925,7 +2817,7 @@ // Tests POST handling with a disabled cache (no DCHECK). TEST(HttpCache, SimplePOST_DisabledCache) { MockHttpCache cache; - cache.http_cache()->set_mode(net::HttpCache::Mode::DISABLE); + cache.http_cache()->set_mode(HttpCache::Mode::DISABLE); RunTransactionTest(cache.http_cache(), kSimplePOST_Transaction); @@ -2938,17 +2830,17 @@ MockHttpCache cache; MockTransaction transaction(kSimplePOST_Transaction); - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; MockHttpRequest request(transaction); - net::TestCompletionCallback callback; + TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); ASSERT_TRUE(trans.get()); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - ASSERT_EQ(net::ERR_CACHE_MISS, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + ASSERT_EQ(ERR_CACHE_MISS, callback.GetResult(rv)); trans.reset(); @@ -2966,10 +2858,10 @@ const int64 kUploadId = 1; // Just a dummy value. - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), - kUploadId); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), + kUploadId); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -2981,7 +2873,7 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Load from cache. - request.load_flags |= net::LOAD_ONLY_FROM_CACHE; + request.load_flags |= LOAD_ONLY_FROM_CACHE; RunTransactionTestWithRequest(cache.http_cache(), transaction, request, NULL); EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -2998,10 +2890,10 @@ const int64 kUploadId = 1; // Just a dummy value. - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), - kUploadId); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), + kUploadId); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3018,9 +2910,9 @@ TEST(HttpCache, SimplePOST_SeparateCache) { MockHttpCache cache; - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); MockTransaction transaction(kSimplePOST_Transaction); MockHttpRequest req1(transaction); @@ -3057,9 +2949,9 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); transaction.method = "POST"; transaction.status = "HTTP/1.1 205 No Content"; @@ -3096,9 +2988,9 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "POST"; transaction.status = "HTTP/1.1 205 No Content"; @@ -3127,9 +3019,9 @@ factory->FinishCreation(); MockHttpCache cache(factory); - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); MockTransaction transaction(kSimplePOST_Transaction); AddMockTransaction(&transaction); @@ -3156,9 +3048,9 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 1); transaction.method = "POST"; transaction.status = "HTTP/1.1 100 Continue"; @@ -3184,18 +3076,18 @@ MockHttpCache cache; MockTransaction transaction(kSimplePOST_Transaction); AddMockTransaction(&transaction); - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; transaction.method = "HEAD"; MockHttpRequest request(transaction); - net::TestCompletionCallback callback; + TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); ASSERT_TRUE(trans.get()); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - ASSERT_EQ(net::ERR_CACHE_MISS, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + ASSERT_EQ(ERR_CACHE_MISS, callback.GetResult(rv)); trans.reset(); @@ -3220,7 +3112,7 @@ // Load from cache. transaction.method = "HEAD"; - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; transaction.data = ""; RunTransactionTest(cache.http_cache(), transaction); @@ -3242,7 +3134,7 @@ // Load from cache. transaction.method = "HEAD"; - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; transaction.data = ""; std::string headers; @@ -3287,8 +3179,8 @@ // Load from cache. transaction.method = "HEAD"; transaction.request_headers = "Range: bytes = 0-4\r\n"; - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; - transaction.return_code = net::ERR_CACHE_MISS; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; + transaction.return_code = ERR_CACHE_MISS; RunTransactionTest(cache.http_cache(), transaction); EXPECT_EQ(0, cache.disk_cache()->open_count()); @@ -3386,7 +3278,7 @@ base::MessageLoop::current()->RunUntilIdle(); // Load from the cache. - transaction2.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction2.load_flags |= LOAD_ONLY_FROM_CACHE; RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers); EXPECT_NE(std::string::npos, headers.find("Foo: bar\n")); @@ -3426,7 +3318,7 @@ base::MessageLoop::current()->RunUntilIdle(); // Load from the cache. - transaction2.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction2.load_flags |= LOAD_ONLY_FROM_CACHE; RunTransactionTestWithResponse(cache.http_cache(), transaction2, &headers); EXPECT_NE(std::string::npos, headers.find("Foo: bar\n")); @@ -3453,8 +3345,8 @@ // Load from the cache. transaction.method = "GET"; - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; - transaction.return_code = net::ERR_CACHE_MISS; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; + transaction.return_code = ERR_CACHE_MISS; RunTransactionTest(cache.http_cache(), transaction); RemoveMockTransaction(&transaction); @@ -3467,9 +3359,9 @@ MockTransaction transaction(kSimplePOST_Transaction); transaction.method = "PUT"; - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3496,9 +3388,9 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; MockHttpRequest req2(transaction); @@ -3532,9 +3424,9 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; transaction.status = "HTTP/1.1 305 Use Proxy"; @@ -3570,9 +3462,9 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "PUT"; transaction.status = "HTTP/1.1 404 Not Found"; @@ -3600,9 +3492,9 @@ MockTransaction transaction(kSimplePOST_Transaction); transaction.method = "DELETE"; - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); MockHttpRequest request(transaction); request.upload_data_stream = &upload_data_stream; @@ -3629,9 +3521,9 @@ EXPECT_EQ(0, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); - ScopedVector<net::UploadElementReader> element_readers; - element_readers.push_back(new net::UploadBytesElementReader("hello", 5)); - net::ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); + ScopedVector<UploadElementReader> element_readers; + element_readers.push_back(new UploadBytesElementReader("hello", 5)); + ElementsUploadDataStream upload_data_stream(element_readers.Pass(), 0); transaction.method = "DELETE"; MockHttpRequest req2(transaction); @@ -3725,16 +3617,16 @@ // Fail the network request. MockTransaction transaction(kSimpleGET_Transaction); - transaction.return_code = net::ERR_FAILED; - transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.return_code = ERR_FAILED; + transaction.load_flags |= LOAD_VALIDATE_CACHE; AddMockTransaction(&transaction); RunTransactionTest(cache.http_cache(), transaction); EXPECT_EQ(2, cache.network_layer()->transaction_count()); RemoveMockTransaction(&transaction); - transaction.load_flags = net::LOAD_ONLY_FROM_CACHE; - transaction.return_code = net::OK; + transaction.load_flags = LOAD_ONLY_FROM_CACHE; + transaction.return_code = OK; AddMockTransaction(&transaction); RunTransactionTest(cache.http_cache(), transaction); @@ -3811,47 +3703,47 @@ TEST(HttpCache, SimpleGET_DoesntLogHeaders) { MockHttpCache cache; - net::BoundTestNetLog log; + BoundTestNetLog log; RunTransactionTestWithLog(cache.http_cache(), kSimpleGET_Transaction, log.bound()); EXPECT_FALSE(LogContainsEventType( - log, net::NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS)); + log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS)); } TEST(HttpCache, RangeGET_LogsHeaders) { MockHttpCache cache; - net::BoundTestNetLog log; + BoundTestNetLog log; RunTransactionTestWithLog(cache.http_cache(), kRangeGET_Transaction, log.bound()); EXPECT_TRUE(LogContainsEventType( - log, net::NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS)); + log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS)); } TEST(HttpCache, ExternalValidation_LogsHeaders) { MockHttpCache cache; - net::BoundTestNetLog log; + BoundTestNetLog log; MockTransaction transaction(kSimpleGET_Transaction); transaction.request_headers = "If-None-Match: foo\r\n" EXTRA_HEADER; RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound()); EXPECT_TRUE(LogContainsEventType( - log, net::NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS)); + log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS)); } TEST(HttpCache, SpecialHeaders_LogsHeaders) { MockHttpCache cache; - net::BoundTestNetLog log; + BoundTestNetLog log; MockTransaction transaction(kSimpleGET_Transaction); transaction.request_headers = "cache-control: no-cache\r\n" EXTRA_HEADER; RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound()); EXPECT_TRUE(LogContainsEventType( - log, net::NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS)); + log, NetLog::TYPE_HTTP_CACHE_CALLER_REQUEST_HEADERS)); } // Tests that receiving 206 for a regular request is handled correctly. @@ -3962,12 +3854,12 @@ RunTransactionTest(cache.http_cache(), transaction); // Now verify that the cached data is not used. - net::BoundTestNetLog log; + BoundTestNetLog log; RunTransactionTestWithLog(cache.http_cache(), kRangeGET_TransactionOK, log.bound()); EXPECT_TRUE(LogContainsEventType( - log, net::NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST)); + log, NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST)); } // Tests that a failure to conditionalize a regular request (no range) with a @@ -4124,8 +4016,8 @@ // Write and read from the cache (20-59). transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER; transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 "; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestWithResponseAndGetTiming( cache.http_cache(), transaction, &headers, log.bound(), &load_timing_info); @@ -4184,8 +4076,8 @@ // Write and read from the cache (20-59). transaction.request_headers = "Range: bytes = 20-59\r\n" EXTRA_HEADER; transaction.data = "rg: 20-29 rg: 30-39 rg: 40-49 rg: 50-59 "; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestWithResponseAndGetTiming( cache.http_cache(), transaction, &headers, log.bound(), &load_timing_info); @@ -4221,8 +4113,8 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Read from the cache (40-49). - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestWithResponseAndGetTiming( cache.http_cache(), transaction, &headers, log.bound(), &load_timing_info); @@ -4234,7 +4126,7 @@ TestLoadTimingCachedResponse(load_timing_info); // Read again forcing the revalidation. - transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.load_flags |= LOAD_VALIDATE_CACHE; RunTransactionTestWithResponseAndGetTiming( cache.http_cache(), transaction, &headers, log.bound(), &load_timing_info); @@ -4299,7 +4191,7 @@ RangeTransactionServer handler; handler.set_not_modified(true); MockTransaction transaction(kRangeGET_TransactionOK); - transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.load_flags |= LOAD_VALIDATE_CACHE; RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); Verify206Response(headers, 40, 49); @@ -4329,7 +4221,7 @@ RangeTransactionServer handler; handler.set_modified(true); MockTransaction transaction(kRangeGET_TransactionOK); - transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.load_flags |= LOAD_VALIDATE_CACHE; RunTransactionTestWithResponse(cache.http_cache(), transaction, &headers); Verify206Response(headers, 40, 49); @@ -4720,8 +4612,8 @@ MockHttpCache cache; AddMockTransaction(&kRangeGET_TransactionOK); std::string headers; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; // Write to the cache (40-49). RunTransactionTestWithResponseAndGetTiming( @@ -4759,8 +4651,8 @@ MockTransaction transaction(kRangeGET_TransactionOK); AddMockTransaction(&transaction); std::string headers; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; // Write to the cache (0-9). transaction.request_headers = "Range: bytes = 0-9\r\n" EXTRA_HEADER; @@ -4785,7 +4677,7 @@ TestLoadTimingNetworkRequest(load_timing_info); // Read from the cache (0-9), write and read from cache (10 - 79). - transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.load_flags |= LOAD_VALIDATE_CACHE; transaction.request_headers = "Foo: bar\r\n" EXTRA_HEADER; transaction.data = kFullRangeData; RunTransactionTestWithResponseAndGetTiming( @@ -4825,12 +4717,12 @@ // real server will answer with 200. MockTransaction transaction2(kRangeGET_TransactionOK); transaction2.request_headers = EXTRA_HEADER; - transaction2.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction2.load_flags |= LOAD_VALIDATE_CACHE; transaction2.data = "Not a range"; RangeTransactionServer handler; handler.set_modified(true); - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestWithResponseAndGetTiming( cache.http_cache(), transaction2, &headers, log.bound(), &load_timing_info); @@ -4860,25 +4752,25 @@ std::string raw_headers(kRangeGET_TransactionOK.status); raw_headers.append("\n"); raw_headers.append(kRangeGET_TransactionOK.response_headers); - raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(), - raw_headers.size()); + raw_headers = + HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size()); - net::HttpResponseInfo response; - response.headers = new net::HttpResponseHeaders(raw_headers); + HttpResponseInfo response; + response.headers = new HttpResponseHeaders(raw_headers); EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500)); + scoped_refptr<IOBuffer> buf(new IOBuffer(500)); int len = static_cast<int>(base::strlcpy(buf->data(), kRangeGET_TransactionOK.data, 500)); - net::TestCompletionCallback cb; + TestCompletionCallback cb; int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true); EXPECT_EQ(len, cb.GetResult(rv)); entry->Close(); // Now see that we don't use the stored entry. std::string headers; - net::BoundTestNetLog log; - net::LoadTimingInfo load_timing_info; + BoundTestNetLog log; + LoadTimingInfo load_timing_info; RunTransactionTestWithResponseAndGetTiming( cache.http_cache(), kSimpleGET_Transaction, &headers, log.bound(), &load_timing_info); @@ -4908,17 +4800,17 @@ std::string raw_headers(kRangeGET_TransactionOK.status); raw_headers.append("\n"); raw_headers.append(kRangeGET_TransactionOK.response_headers); - raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(), - raw_headers.size()); + raw_headers = + HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size()); - net::HttpResponseInfo response; - response.headers = new net::HttpResponseHeaders(raw_headers); + HttpResponseInfo response; + response.headers = new HttpResponseHeaders(raw_headers); EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500)); + scoped_refptr<IOBuffer> buf(new IOBuffer(500)); int len = static_cast<int>(base::strlcpy(buf->data(), kRangeGET_TransactionOK.data, 500)); - net::TestCompletionCallback cb; + TestCompletionCallback cb; int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true); EXPECT_EQ(len, cb.GetResult(rv)); entry->Close(); @@ -4950,17 +4842,17 @@ std::string raw_headers(kRangeGET_TransactionOK.status); raw_headers.append("\n"); raw_headers.append("Content-Length: 80\n"); - raw_headers = net::HttpUtil::AssembleRawHeaders(raw_headers.data(), - raw_headers.size()); + raw_headers = + HttpUtil::AssembleRawHeaders(raw_headers.data(), raw_headers.size()); - net::HttpResponseInfo response; - response.headers = new net::HttpResponseHeaders(raw_headers); + HttpResponseInfo response; + response.headers = new HttpResponseHeaders(raw_headers); EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, false)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(500)); + scoped_refptr<IOBuffer> buf(new IOBuffer(500)); int len = static_cast<int>(base::strlcpy(buf->data(), kRangeGET_TransactionOK.data, 500)); - net::TestCompletionCallback cb; + TestCompletionCallback cb; int rv = entry->WriteData(1, 0, buf.get(), len, cb.callback(), true); EXPECT_EQ(len, cb.GetResult(rv)); entry->Close(); @@ -5017,7 +4909,7 @@ MockTransaction transaction3(kRangeGET_TransactionOK); transaction3.request_headers = "Range: bytes = 80-90\r\n" EXTRA_HEADER; transaction3.data = transaction.data; - transaction3.load_flags = net::LOAD_PREFERRING_CACHE; + transaction3.load_flags = LOAD_PREFERRING_CACHE; RunTransactionTestWithResponse(cache.http_cache(), transaction3, &headers); EXPECT_EQ(2, cache.disk_cache()->open_count()); EXPECT_EQ(0U, headers.find("HTTP/1.1 200 ")); @@ -5131,10 +5023,10 @@ Context* c = new Context(); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -5142,9 +5034,9 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Make sure that the entry has some data stored. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); - if (rv == net::ERR_IO_PENDING) + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(buf->size(), rv); @@ -5166,14 +5058,14 @@ RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); MockHttpRequest request(kRangeGET_TransactionOK); - request.load_flags |= net::LOAD_VALIDATE_CACHE; + request.load_flags |= LOAD_VALIDATE_CACHE; Context* c = new Context(); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(2, cache.network_layer()->transaction_count()); @@ -5182,11 +5074,11 @@ // Make sure that we revalidate the entry and read from the cache (a single // read will return while waiting for the network). - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); EXPECT_EQ(5, c->callback.GetResult(rv)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + EXPECT_EQ(ERR_IO_PENDING, rv); // Destroy the transaction before completing the read. delete c; @@ -5211,14 +5103,14 @@ RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); MockHttpRequest request(kRangeGET_TransactionOK); - request.load_flags |= net::LOAD_VALIDATE_CACHE; + request.load_flags |= LOAD_VALIDATE_CACHE; Context* c = new Context(); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); rv = c->callback.WaitForResult(); EXPECT_EQ(2, cache.network_layer()->transaction_count()); @@ -5227,11 +5119,11 @@ // Make sure that we revalidate the entry and read from the cache (a single // read will return while waiting for the network). - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); EXPECT_EQ(5, c->callback.GetResult(rv)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + EXPECT_EQ(ERR_IO_PENDING, rv); // Destroy the transaction before completing the read. delete c; @@ -5242,10 +5134,10 @@ c = new Context(); rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); MockDiskEntry::IgnoreCallbacks(true); base::MessageLoop::current()->RunUntilIdle(); @@ -5362,7 +5254,7 @@ // Tests that we handle large range values properly. TEST(HttpCache, RangeGET_LargeValues) { // We need a real sparse cache for this test. - MockHttpCache cache(net::HttpCache::DefaultBackend::InMemory(1024 * 1024)); + MockHttpCache cache(HttpCache::DefaultBackend::InMemory(1024 * 1024)); std::string headers; MockTransaction transaction(kRangeGET_TransactionOK); @@ -5436,7 +5328,7 @@ ScopedMockTransaction transaction(kRangeGET_TransactionOK); transaction.request_headers = "Range: bytes = 40-\r\n" EXTRA_HEADER; transaction.test_mode = TEST_MODE_SYNC_NET_START; - transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.load_flags |= LOAD_VALIDATE_CACHE; // Write to the cache. RunTransactionTest(cache.http_cache(), kRangeGET_TransactionOK); @@ -5445,14 +5337,14 @@ RangeTransactionServer handler; handler.set_bad_200(true); transaction.data = "Not a range"; - net::BoundTestNetLog log; + BoundTestNetLog log; RunTransactionTestWithLog(cache.http_cache(), transaction, log.bound()); EXPECT_EQ(3, cache.network_layer()->transaction_count()); EXPECT_EQ(1, cache.disk_cache()->open_count()); EXPECT_EQ(1, cache.disk_cache()->create_count()); EXPECT_TRUE(LogContainsEventType( - log, net::NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST)); + log, NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST)); } // Tests that when the server gives us less data than expected, we don't keep @@ -5509,20 +5401,20 @@ // Force this transaction to read from the cache. MockTransaction transaction(kRangeGET_TransactionOK); - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; MockHttpRequest request(transaction); - net::TestCompletionCallback callback; + TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY, &trans); - EXPECT_EQ(net::OK, rv); + scoped_ptr<HttpTransaction> trans; + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans); + EXPECT_EQ(OK, rv); ASSERT_TRUE(trans.get()); - rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + rv = trans->Start(&request, callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_CACHE_MISS, rv); + ASSERT_EQ(ERR_CACHE_MISS, rv); trans.reset(); @@ -5542,9 +5434,9 @@ NULL)); std::string headers("HTTP/1.1 200 OK"); - headers = net::HttpUtil::AssembleRawHeaders(headers.data(), headers.size()); - net::HttpResponseInfo response; - response.headers = new net::HttpResponseHeaders(headers); + headers = HttpUtil::AssembleRawHeaders(headers.data(), headers.size()); + HttpResponseInfo response; + response.headers = new HttpResponseHeaders(headers); // Set the last argument for this to be an incomplete request. EXPECT_TRUE(MockHttpCache::WriteResponseInfo(entry, &response, true, true)); @@ -5563,17 +5455,17 @@ // Tests basic pickling/unpickling of HttpResponseInfo. TEST(HttpCache, PersistHttpResponseInfo) { // Set some fields (add more if needed.) - net::HttpResponseInfo response1; + HttpResponseInfo response1; response1.was_cached = false; - response1.socket_address = net::HostPortPair("1.2.3.4", 80); - response1.headers = new net::HttpResponseHeaders("HTTP/1.1 200 OK"); + response1.socket_address = HostPortPair("1.2.3.4", 80); + response1.headers = new HttpResponseHeaders("HTTP/1.1 200 OK"); // Pickle. Pickle pickle; response1.Persist(&pickle, false, false); // Unpickle. - net::HttpResponseInfo response2; + HttpResponseInfo response2; bool response_truncated; EXPECT_TRUE(response2.InitFromPickle(pickle, &response_truncated)); EXPECT_FALSE(response_truncated); @@ -5594,10 +5486,10 @@ Context* c = new Context(); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) c->result = c->callback.WaitForResult(); EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -5624,10 +5516,10 @@ Context* c = new Context(); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -5635,9 +5527,9 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Make sure that the entry has some data stored. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); - if (rv == net::ERR_IO_PENDING) + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(buf->size(), rv); @@ -5667,10 +5559,10 @@ Context* c = new Context(); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -5678,9 +5570,9 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Make sure that the entry has some data stored. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); - if (rv == net::ERR_IO_PENDING) + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(buf->size(), rv); @@ -5711,10 +5603,10 @@ scoped_ptr<Context> c(new Context()); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -5722,15 +5614,15 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Make sure that the entry has some data stored. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(10)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(10)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); - if (rv == net::ERR_IO_PENDING) + if (rv == ERR_IO_PENDING) rv = c->callback.WaitForResult(); EXPECT_EQ(buf->size(), rv); // We want to cancel the request when the transaction is busy. rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); - EXPECT_EQ(net::ERR_IO_PENDING, rv); + EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_FALSE(c->callback.have_result()); MockHttpCache::SetTestMode(TEST_MODE_SYNC_ALL); @@ -5749,7 +5641,7 @@ // Verify that the entry is marked as incomplete. disk_cache::Entry* entry; ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); - net::HttpResponseInfo response; + HttpResponseInfo response; bool truncated = false; EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); EXPECT_TRUE(truncated); @@ -5772,13 +5664,13 @@ scoped_ptr<Context> c(new Context()); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, c->callback.GetResult(rv)); + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, c->callback.GetResult(rv)); // Read everything. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(22)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(22)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); EXPECT_EQ(buf->size(), c->callback.GetResult(rv)); @@ -5788,7 +5680,7 @@ // Verify that the entry is not marked as truncated. disk_cache::Entry* entry; ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); - net::HttpResponseInfo response; + HttpResponseInfo response; bool truncated = true; EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); EXPECT_FALSE(truncated); @@ -5834,7 +5726,7 @@ ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); EXPECT_EQ(80, entry->GetDataSize(1)); bool truncated = true; - net::HttpResponseInfo response; + HttpResponseInfo response; EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); EXPECT_FALSE(truncated); entry->Close(); @@ -5913,23 +5805,23 @@ Context* c = new Context(); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); // Queue another request to this transaction. We have to start this request // before the first one gets the response from the server and dooms the entry, // otherwise it will just create a new entry without being queued to the first // request. Context* pending = new Context(); - ASSERT_EQ(net::OK, cache.CreateTransaction(&pending->trans)); + ASSERT_EQ(OK, cache.CreateTransaction(&pending->trans)); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::ERR_IO_PENDING, + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, pending->trans->Start(&request, pending->callback.callback(), - net::BoundNetLog())); - EXPECT_EQ(net::OK, c->callback.GetResult(rv)); + BoundNetLog())); + EXPECT_EQ(OK, c->callback.GetResult(rv)); // Make sure that the entry has some data stored. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(5)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(5)); rv = c->trans->Read(buf.get(), buf->size(), c->callback.callback()); EXPECT_EQ(5, c->callback.GetResult(rv)); @@ -6004,11 +5896,11 @@ scoped_ptr<Context> c(new Context); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); MockHttpRequest request(transaction); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, c->callback.GetResult(rv)); + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, c->callback.GetResult(rv)); // We should have checked with the server before finishing Start(). EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -6039,18 +5931,17 @@ scoped_ptr<Context> c(new Context); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); MockHttpRequest request(transaction); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, c->callback.GetResult(rv)); + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, c->callback.GetResult(rv)); - const net::HttpResponseInfo* response = c->trans->GetResponseInfo(); + const HttpResponseInfo* response = c->trans->GetResponseInfo(); ASSERT_TRUE(response); ASSERT_EQ(401, response->headers->response_code()); - rv = c->trans->RestartWithAuth(net::AuthCredentials(), - c->callback.callback()); - EXPECT_EQ(net::OK, c->callback.GetResult(rv)); + rv = c->trans->RestartWithAuth(AuthCredentials(), c->callback.callback()); + EXPECT_EQ(OK, c->callback.GetResult(rv)); response = c->trans->GetResponseInfo(); ASSERT_TRUE(response); ASSERT_EQ(200, response->headers->response_code()); @@ -6097,7 +5988,7 @@ ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); EXPECT_EQ(11, entry->GetDataSize(1)); bool truncated = true; - net::HttpResponseInfo response; + HttpResponseInfo response; EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); EXPECT_FALSE(truncated); entry->Close(); @@ -6125,13 +6016,13 @@ MockHttpRequest request(transaction); Context* c = new Context(); int rv = cache.CreateTransaction(&c->trans); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - rv = c->trans->Start(&request, c->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, c->callback.GetResult(rv)); + rv = c->trans->Start(&request, c->callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, c->callback.GetResult(rv)); // Read 20 bytes from the cache, and 10 from the net. - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(100)); + scoped_refptr<IOBuffer> buf(new IOBuffer(100)); rv = c->trans->Read(buf.get(), 20, c->callback.callback()); EXPECT_EQ(20, c->callback.GetResult(rv)); rv = c->trans->Read(buf.get(), 10, c->callback.callback()); @@ -6150,7 +6041,7 @@ ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); EXPECT_EQ(30, entry->GetDataSize(1)); bool truncated = false; - net::HttpResponseInfo response; + HttpResponseInfo response; EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); EXPECT_TRUE(truncated); entry->Close(); @@ -6198,17 +6089,17 @@ r2(transaction), r3(transaction); - TestTransactionConsumer c1(net::DEFAULT_PRIORITY, cache.http_cache()), - c2(net::DEFAULT_PRIORITY, cache.http_cache()), - c3(net::DEFAULT_PRIORITY, cache.http_cache()); + TestTransactionConsumer c1(DEFAULT_PRIORITY, cache.http_cache()), + c2(DEFAULT_PRIORITY, cache.http_cache()), + c3(DEFAULT_PRIORITY, cache.http_cache()); - c1.Start(&r1, net::BoundNetLog()); + c1.Start(&r1, BoundNetLog()); - r2.load_flags |= net::LOAD_ONLY_FROM_CACHE; - c2.Start(&r2, net::BoundNetLog()); + r2.load_flags |= LOAD_ONLY_FROM_CACHE; + c2.Start(&r2, BoundNetLog()); - r3.load_flags |= net::LOAD_ONLY_FROM_CACHE; - c3.Start(&r3, net::BoundNetLog()); + r3.load_flags |= LOAD_ONLY_FROM_CACHE; + c3.Start(&r3, BoundNetLog()); base::MessageLoop::current()->Run(); @@ -6216,9 +6107,9 @@ EXPECT_TRUE(c2.is_done()); EXPECT_TRUE(c3.is_done()); - EXPECT_EQ(net::OK, c1.error()); - EXPECT_EQ(net::OK, c2.error()); - EXPECT_EQ(net::OK, c3.error()); + EXPECT_EQ(OK, c1.error()); + EXPECT_EQ(OK, c2.error()); + EXPECT_EQ(OK, c3.error()); } TEST(HttpCache, ValidationResultsIn200) { @@ -6232,7 +6123,7 @@ // force this transaction to validate the cache MockTransaction transaction(kETagGET_Transaction); - transaction.load_flags |= net::LOAD_VALIDATE_CACHE; + transaction.load_flags |= LOAD_VALIDATE_CACHE; RunTransactionTest(cache.http_cache(), transaction); // read from the cache @@ -6247,19 +6138,19 @@ kTestTransaction.response_headers = "Location: http://www.bar.com/\n"; MockHttpRequest request(kTestTransaction); - net::TestCompletionCallback callback; + TestCompletionCallback callback; // Write to the cache. { - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - const net::HttpResponseInfo* info = trans->GetResponseInfo(); + const HttpResponseInfo* info = trans->GetResponseInfo(); ASSERT_TRUE(info); EXPECT_EQ(info->headers->response_code(), 301); @@ -6285,15 +6176,15 @@ // Read from the cache. { - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); - const net::HttpResponseInfo* info = trans->GetResponseInfo(); + const HttpResponseInfo* info = trans->GetResponseInfo(); ASSERT_TRUE(info); EXPECT_EQ(info->headers->response_code(), 301); @@ -6356,7 +6247,7 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // Try loading again with LOAD_PREFERRING_CACHE. - transaction.load_flags = net::LOAD_PREFERRING_CACHE; + transaction.load_flags = LOAD_PREFERRING_CACHE; RunTransactionTest(cache.http_cache(), transaction); EXPECT_EQ(1, cache.network_layer()->transaction_count()); @@ -6408,7 +6299,7 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // try loading again; it should result in a network fetch - transaction.load_flags = net::LOAD_VALIDATE_CACHE; + transaction.load_flags = LOAD_VALIDATE_CACHE; transaction.response_headers = "cache-control: no-store\n"; RunTransactionTest(cache.http_cache(), transaction); @@ -6436,7 +6327,7 @@ EXPECT_EQ(1, cache.disk_cache()->create_count()); // try loading again; it should result in a network fetch - transaction.load_flags = net::LOAD_VALIDATE_CACHE; + transaction.load_flags = LOAD_VALIDATE_CACHE; transaction.response_headers = "cache-control: no-store\n"; transaction.status = "HTTP/1.1 304 Not Modified"; RunTransactionTest(cache.http_cache(), transaction); @@ -6454,33 +6345,33 @@ MockHttpCache cache; MockTransaction transaction = kSimpleGET_Transaction; - transaction.cert_status = net::CERT_STATUS_REVOKED; + transaction.cert_status = CERT_STATUS_REVOKED; ScopedMockTransaction scoped_transaction(transaction); // write to the cache RunTransactionTest(cache.http_cache(), transaction); // Test that it was not cached. - transaction.load_flags |= net::LOAD_ONLY_FROM_CACHE; + transaction.load_flags |= LOAD_ONLY_FROM_CACHE; MockHttpRequest request(transaction); - net::TestCompletionCallback callback; + TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_CACHE_MISS, rv); + ASSERT_EQ(ERR_CACHE_MISS, rv); } // Ensure that we don't crash by if left-behind transactions. TEST(HttpCache, OutlivedTransactions) { MockHttpCache* cache = new MockHttpCache; - scoped_ptr<net::HttpTransaction> trans; - EXPECT_EQ(net::OK, cache->CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + EXPECT_EQ(OK, cache->CreateTransaction(&trans)); delete cache; trans.reset(); @@ -6494,7 +6385,7 @@ RunTransactionTest(cache.http_cache(), kSimpleGET_Transaction); // go into disabled mode - cache.http_cache()->set_mode(net::HttpCache::DISABLE); + cache.http_cache()->set_mode(HttpCache::DISABLE); // force this transaction to write to the cache again MockTransaction transaction(kSimpleGET_Transaction); @@ -6544,7 +6435,7 @@ // Request |kUrl| again, this time validating the cache and getting // a 304 back. - request.load_flags = net::LOAD_VALIDATE_CACHE; + request.load_flags = LOAD_VALIDATE_CACHE; static const Response kNetResponse2 = { "HTTP/1.1 304 Not Modified", @@ -6560,7 +6451,7 @@ mock_network_response.request_time = request_time; mock_network_response.response_time = response_time; - net::HttpResponseInfo response; + HttpResponseInfo response; RunTransactionTestWithResponseInfo(cache.http_cache(), request, &response); // The request and response times should have been updated. @@ -6585,22 +6476,22 @@ MockHttpCache cache; // Write to the cache - net::HttpResponseInfo response; + HttpResponseInfo response; RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction, &response); EXPECT_TRUE(response.metadata.get() == NULL); // Trivial call. - cache.http_cache()->WriteMetadata(GURL("foo"), net::DEFAULT_PRIORITY, - Time::Now(), NULL, 0); + cache.http_cache()->WriteMetadata(GURL("foo"), DEFAULT_PRIORITY, Time::Now(), + NULL, 0); // Write meta data to the same entry. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50)); memset(buf->data(), 0, buf->size()); base::strlcpy(buf->data(), "Hi there", buf->size()); - cache.http_cache()->WriteMetadata( - GURL(kSimpleGET_Transaction.url), net::DEFAULT_PRIORITY, - response.response_time, buf.get(), buf->size()); + cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url), + DEFAULT_PRIORITY, response.response_time, + buf.get(), buf->size()); // Release the buffer before the operation takes place. buf = NULL; @@ -6624,20 +6515,20 @@ MockHttpCache cache; // Write to the cache - net::HttpResponseInfo response; + HttpResponseInfo response; RunTransactionTestWithResponseInfo(cache.http_cache(), kSimpleGET_Transaction, &response); EXPECT_TRUE(response.metadata.get() == NULL); // Attempt to write meta data to the same entry. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50)); memset(buf->data(), 0, buf->size()); base::strlcpy(buf->data(), "Hi there", buf->size()); base::Time expected_time = response.response_time - base::TimeDelta::FromMilliseconds(20); cache.http_cache()->WriteMetadata(GURL(kSimpleGET_Transaction.url), - net::DEFAULT_PRIORITY, expected_time, - buf.get(), buf->size()); + DEFAULT_PRIORITY, expected_time, buf.get(), + buf->size()); // Makes sure we finish pending operations. base::MessageLoop::current()->RunUntilIdle(); @@ -6657,25 +6548,25 @@ MockHttpCache cache; // Write to the cache - net::HttpResponseInfo response; + HttpResponseInfo response; RunTransactionTestWithResponseInfo(cache.http_cache(), kTypicalGET_Transaction, &response); EXPECT_TRUE(response.metadata.get() == NULL); // Write meta data to the same entry. - scoped_refptr<net::IOBufferWithSize> buf(new net::IOBufferWithSize(50)); + scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(50)); memset(buf->data(), 0, buf->size()); base::strlcpy(buf->data(), "Hi there", buf->size()); - cache.http_cache()->WriteMetadata( - GURL(kTypicalGET_Transaction.url), net::DEFAULT_PRIORITY, - response.response_time, buf.get(), buf->size()); + cache.http_cache()->WriteMetadata(GURL(kTypicalGET_Transaction.url), + DEFAULT_PRIORITY, response.response_time, + buf.get(), buf->size()); // Makes sure we finish pending operations. base::MessageLoop::current()->RunUntilIdle(); // Start with a READ mode transaction. MockTransaction trans1(kTypicalGET_Transaction); - trans1.load_flags = net::LOAD_ONLY_FROM_CACHE; + trans1.load_flags = LOAD_ONLY_FROM_CACHE; RunTransactionTestWithResponseInfo(cache.http_cache(), trans1, &response); ASSERT_TRUE(response.metadata.get() != NULL); @@ -6688,7 +6579,7 @@ base::MessageLoop::current()->RunUntilIdle(); // Now make sure that the entry is re-validated with the server. - trans1.load_flags = net::LOAD_VALIDATE_CACHE; + trans1.load_flags = LOAD_VALIDATE_CACHE; trans1.status = "HTTP/1.1 304 Not Modified"; AddMockTransaction(&trans1); @@ -6704,7 +6595,7 @@ // Now return 200 when validating the entry so the metadata will be lost. MockTransaction trans2(kTypicalGET_Transaction); - trans2.load_flags = net::LOAD_VALIDATE_CACHE; + trans2.load_flags = LOAD_VALIDATE_CACHE; RunTransactionTestWithResponseInfo(cache.http_cache(), trans2, &response); EXPECT_TRUE(response.metadata.get() == NULL); @@ -6717,17 +6608,17 @@ // of the stream. TEST(HttpCache, FilterCompletion) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; { - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); MockHttpRequest request(kSimpleGET_Transaction); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, callback.GetResult(rv)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); rv = trans->Read(buf.get(), 256, callback.callback()); EXPECT_GT(callback.GetResult(rv), 0); @@ -6751,17 +6642,17 @@ // for a redirect. TEST(HttpCache, DoneReading) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; ScopedMockTransaction transaction(kSimpleGET_Transaction); transaction.data = ""; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); MockHttpRequest request(transaction); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, callback.GetResult(rv)); trans->DoneReading(); // Leave the transaction around. @@ -6780,17 +6671,17 @@ // Tests that we stop caching when told. TEST(HttpCache, StopCachingDeletesEntry) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; MockHttpRequest request(kSimpleGET_Transaction); { - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, callback.GetResult(rv)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); rv = trans->Read(buf.get(), 10, callback.callback()); EXPECT_EQ(10, callback.GetResult(rv)); @@ -6818,17 +6709,17 @@ // after StopCaching. TEST(HttpCache, StopCachingThenDoneReadingDeletesEntry) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; MockHttpRequest request(kSimpleGET_Transaction); { - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, callback.GetResult(rv)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); rv = trans->Read(buf.get(), 10, callback.callback()); EXPECT_EQ(10, callback.GetResult(rv)); @@ -6858,22 +6749,22 @@ // Tests that we stop caching when told, when using auth. TEST(HttpCache, StopCachingWithAuthDeletesEntry) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; MockTransaction mock_transaction(kSimpleGET_Transaction); mock_transaction.status = "HTTP/1.1 401 Unauthorized"; AddMockTransaction(&mock_transaction); MockHttpRequest request(mock_transaction); { - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, callback.GetResult(rv)); trans->StopCaching(); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); rv = trans->Read(buf.get(), 10, callback.callback()); EXPECT_EQ(callback.GetResult(rv), 10); } @@ -6893,12 +6784,12 @@ // Tests that when we are told to stop caching we don't throw away valid data. TEST(HttpCache, StopCachingSavesEntry) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; MockHttpRequest request(kSimpleGET_Transaction); { - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); // Force a response that can be resumed. MockTransaction mock_transaction(kSimpleGET_Transaction); @@ -6907,10 +6798,10 @@ "Content-Length: 42\n" "Etag: \"foo\"\n"; - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, callback.GetResult(rv)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); rv = trans->Read(buf.get(), 10, callback.callback()); EXPECT_EQ(callback.GetResult(rv), 10); @@ -6928,7 +6819,7 @@ // Verify that the entry is marked as incomplete. disk_cache::Entry* entry; ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); - net::HttpResponseInfo response; + HttpResponseInfo response; bool truncated = false; EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); EXPECT_TRUE(truncated); @@ -6938,7 +6829,7 @@ // Tests that we handle truncated enries when StopCaching is called. TEST(HttpCache, StopCachingTruncatedEntry) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; MockHttpRequest request(kRangeGET_TransactionOK); request.extra_headers.Clear(); request.extra_headers.AddHeaderFromString(EXTRA_HEADER_LINE); @@ -6953,13 +6844,13 @@ { // Now make a regular request. - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.CreateTransaction(&trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.CreateTransaction(&trans)); - int rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::OK, callback.GetResult(rv)); + int rv = trans->Start(&request, callback.callback(), BoundNetLog()); + EXPECT_EQ(OK, callback.GetResult(rv)); - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); rv = trans->Read(buf.get(), 10, callback.callback()); EXPECT_EQ(callback.GetResult(rv), 10); @@ -6980,7 +6871,7 @@ ASSERT_TRUE(cache.OpenBackendEntry(kRangeGET_TransactionOK.url, &entry)); EXPECT_EQ(80, entry->GetDataSize(1)); bool truncated = true; - net::HttpResponseInfo response; + HttpResponseInfo response; EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); EXPECT_FALSE(truncated); entry->Close(); @@ -6992,7 +6883,7 @@ // a Content-Length header. TEST(HttpCache, TruncatedByContentLength) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; MockTransaction transaction(kSimpleGET_Transaction); AddMockTransaction(&transaction); @@ -7013,7 +6904,7 @@ // from the net. TEST(HttpCache, TruncatedByContentLength2) { MockHttpCache cache; - net::TestCompletionCallback callback; + TestCompletionCallback callback; MockTransaction transaction(kSimpleGET_Transaction); AddMockTransaction(&transaction); @@ -7026,7 +6917,7 @@ // Verify that the entry is marked as incomplete. disk_cache::Entry* entry; ASSERT_TRUE(cache.OpenBackendEntry(kSimpleGET_Transaction.url, &entry)); - net::HttpResponseInfo response; + HttpResponseInfo response; bool truncated = false; EXPECT_TRUE(MockHttpCache::ReadResponseInfo(entry, &response, &truncated)); EXPECT_TRUE(truncated); @@ -7038,40 +6929,36 @@ TEST(HttpCache, SetPriority) { MockHttpCache cache; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.http_cache()->CreateTransaction(net::IDLE, &trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(IDLE, &trans)); // Shouldn't crash, but doesn't do anything either. - trans->SetPriority(net::LOW); + trans->SetPriority(LOW); EXPECT_FALSE(cache.network_layer()->last_transaction()); - EXPECT_EQ(net::DEFAULT_PRIORITY, + EXPECT_EQ(DEFAULT_PRIORITY, cache.network_layer()->last_create_transaction_priority()); - net::HttpRequestInfo info; + HttpRequestInfo info; info.url = GURL(kSimpleGET_Transaction.url); - net::TestCompletionCallback callback; - EXPECT_EQ(net::ERR_IO_PENDING, - trans->Start(&info, callback.callback(), net::BoundNetLog())); + TestCompletionCallback callback; + EXPECT_EQ(ERR_IO_PENDING, + trans->Start(&info, callback.callback(), BoundNetLog())); EXPECT_TRUE(cache.network_layer()->last_transaction()); if (cache.network_layer()->last_transaction()) { - EXPECT_EQ(net::LOW, - cache.network_layer()->last_create_transaction_priority()); - EXPECT_EQ(net::LOW, - cache.network_layer()->last_transaction()->priority()); + EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority()); + EXPECT_EQ(LOW, cache.network_layer()->last_transaction()->priority()); } - trans->SetPriority(net::HIGHEST); + trans->SetPriority(HIGHEST); if (cache.network_layer()->last_transaction()) { - EXPECT_EQ(net::LOW, - cache.network_layer()->last_create_transaction_priority()); - EXPECT_EQ(net::HIGHEST, - cache.network_layer()->last_transaction()->priority()); + EXPECT_EQ(LOW, cache.network_layer()->last_create_transaction_priority()); + EXPECT_EQ(HIGHEST, cache.network_layer()->last_transaction()->priority()); } - EXPECT_EQ(net::OK, callback.WaitForResult()); + EXPECT_EQ(OK, callback.WaitForResult()); } // Make sure that calling SetWebSocketHandshakeStreamCreateHelper on a cache @@ -7080,16 +6967,16 @@ MockHttpCache cache; FakeWebSocketHandshakeStreamCreateHelper create_helper; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, cache.http_cache()->CreateTransaction(net::IDLE, &trans)); + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(IDLE, &trans)); EXPECT_FALSE(cache.network_layer()->last_transaction()); - net::HttpRequestInfo info; + HttpRequestInfo info; info.url = GURL(kSimpleGET_Transaction.url); - net::TestCompletionCallback callback; - EXPECT_EQ(net::ERR_IO_PENDING, - trans->Start(&info, callback.callback(), net::BoundNetLog())); + TestCompletionCallback callback; + EXPECT_EQ(ERR_IO_PENDING, + trans->Start(&info, callback.callback(), BoundNetLog())); ASSERT_TRUE(cache.network_layer()->last_transaction()); EXPECT_FALSE(cache.network_layer()->last_transaction()-> @@ -7098,7 +6985,7 @@ EXPECT_EQ(&create_helper, cache.network_layer()->last_transaction()-> websocket_handshake_stream_create_helper()); - EXPECT_EQ(net::OK, callback.WaitForResult()); + EXPECT_EQ(OK, callback.WaitForResult()); } // Make sure that a cache transaction passes on its priority to @@ -7120,28 +7007,25 @@ transaction.request_headers = EXTRA_HEADER; transaction.data = kFullRangeData; - scoped_ptr<net::HttpTransaction> trans; - ASSERT_EQ(net::OK, - cache.http_cache()->CreateTransaction(net::MEDIUM, &trans)); - EXPECT_EQ(net::DEFAULT_PRIORITY, + scoped_ptr<HttpTransaction> trans; + ASSERT_EQ(OK, cache.http_cache()->CreateTransaction(MEDIUM, &trans)); + EXPECT_EQ(DEFAULT_PRIORITY, cache.network_layer()->last_create_transaction_priority()); MockHttpRequest info(transaction); - net::TestCompletionCallback callback; - EXPECT_EQ(net::ERR_IO_PENDING, - trans->Start(&info, callback.callback(), net::BoundNetLog())); - EXPECT_EQ(net::OK, callback.WaitForResult()); + TestCompletionCallback callback; + EXPECT_EQ(ERR_IO_PENDING, + trans->Start(&info, callback.callback(), BoundNetLog())); + EXPECT_EQ(OK, callback.WaitForResult()); - EXPECT_EQ(net::MEDIUM, - cache.network_layer()->last_create_transaction_priority()); + EXPECT_EQ(MEDIUM, cache.network_layer()->last_create_transaction_priority()); - trans->SetPriority(net::HIGHEST); + trans->SetPriority(HIGHEST); // Should trigger a new network transaction and pick up the new // priority. ReadAndVerifyTransaction(trans.get(), transaction); - EXPECT_EQ(net::HIGHEST, - cache.network_layer()->last_create_transaction_priority()); + EXPECT_EQ(HIGHEST, cache.network_layer()->last_create_transaction_priority()); RemoveMockTransaction(&kRangeGET_TransactionOK); } @@ -7151,8 +7035,8 @@ const MockTransaction& trans_info) { int64 received_bytes = -1; RunTransactionTestBase(cache.http_cache(), trans_info, - MockHttpRequest(trans_info), NULL, net::BoundNetLog(), - NULL, &received_bytes); + MockHttpRequest(trans_info), NULL, BoundNetLog(), NULL, + &received_bytes); return received_bytes; } @@ -7179,7 +7063,7 @@ int64 received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); EXPECT_EQ(TransactionSize(transaction), received_bytes); - transaction.load_flags = net::LOAD_VALIDATE_CACHE; + transaction.load_flags = LOAD_VALIDATE_CACHE; transaction.handler = ETagGet_ConditionalRequest_Handler; received_bytes = RunTransactionAndGetReceivedBytes(cache, transaction); EXPECT_EQ(TransactionSize(transaction), received_bytes); @@ -7246,7 +7130,7 @@ static const int kRequireValidationSecs = kMaxAgeSecs + 1; HttpCachePrefetchValidationTest() : transaction_(kSimpleGET_Transaction) { - DCHECK_LT(kMaxAgeSecs, prefetch_reuse_mins() * net::kNumSecondsPerMinute); + DCHECK_LT(kMaxAgeSecs, prefetch_reuse_mins() * kNumSecondsPerMinute); clock_ = new base::SimpleTestClock(); cache_.http_cache()->SetClockForTesting(make_scoped_ptr(clock_)); @@ -7266,7 +7150,7 @@ clock_->Advance(base::TimeDelta::FromSeconds(seconds)); } - int prefetch_reuse_mins() { return net::HttpCache::kPrefetchReuseMins; } + int prefetch_reuse_mins() { return HttpCache::kPrefetchReuseMins; } // How many times this test has sent requests to the (fake) origin // server. Every test case needs to make at least one request to initialise @@ -7282,71 +7166,71 @@ }; TEST_F(HttpCachePrefetchValidationTest, SkipValidationShortlyAfterPrefetch) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL)); } TEST_F(HttpCachePrefetchValidationTest, ValidateLongAfterPrefetch) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); - AdvanceTime(prefetch_reuse_mins() * net::kNumSecondsPerMinute); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); + AdvanceTime(prefetch_reuse_mins() * kNumSecondsPerMinute); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL)); } TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceOnly) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_NORMAL)); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL)); } TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnceReadOnly) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_ONLY_FROM_CACHE)); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_ONLY_FROM_CACHE)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL)); } TEST_F(HttpCachePrefetchValidationTest, BypassCacheOverwritesPrefetch) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_BYPASS_CACHE)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_BYPASS_CACHE)); AdvanceTime(kRequireValidationSecs); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL)); } TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnExistingEntryThatNeedsValidation) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL)); AdvanceTime(kRequireValidationSecs); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_NORMAL)); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL)); } TEST_F(HttpCachePrefetchValidationTest, SkipValidationOnExistingEntryThatDoesNotNeedValidation) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_NORMAL)); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_NORMAL)); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_NORMAL)); } TEST_F(HttpCachePrefetchValidationTest, PrefetchMultipleTimes) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL)); } TEST_F(HttpCachePrefetchValidationTest, ValidateOnDelayedSecondPrefetch) { - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_TRUE(TransactionRequiredNetwork(net::LOAD_PREFETCH)); + EXPECT_TRUE(TransactionRequiredNetwork(LOAD_PREFETCH)); AdvanceTime(kRequireValidationSecs); - EXPECT_FALSE(TransactionRequiredNetwork(net::LOAD_NORMAL)); + EXPECT_FALSE(TransactionRequiredNetwork(LOAD_NORMAL)); } // Framework for tests of stale-while-revalidate related functionality. With @@ -7395,7 +7279,7 @@ std::string validator_; }; -static void CheckResourceFreshnessHeader(const net::HttpRequestInfo* request, +static void CheckResourceFreshnessHeader(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { @@ -7422,7 +7306,7 @@ EXPECT_EQ(2, transaction_count()); } -static void CheckResourceFreshnessAbsent(const net::HttpRequestInfo* request, +static void CheckResourceFreshnessAbsent(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { @@ -7493,7 +7377,7 @@ RunFixtureTransactionTest(); } -static void CheckIfModifiedSinceHeader(const net::HttpRequestInfo* request, +static void CheckIfModifiedSinceHeader(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { @@ -7513,7 +7397,7 @@ RunFixtureTransactionTest(); } -static void CheckIfNoneMatchHeader(const net::HttpRequestInfo* request, +static void CheckIfNoneMatchHeader(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { @@ -7536,11 +7420,10 @@ RunFixtureTransactionTest(); } -static void CheckResourceFreshnessHeaderPresent( - const net::HttpRequestInfo* request, - std::string* response_status, - std::string* response_headers, - std::string* response_data) { +static void CheckResourceFreshnessHeaderPresent(const HttpRequestInfo* request, + std::string* response_status, + std::string* response_headers, + std::string* response_data) { EXPECT_TRUE(request->extra_headers.HasHeader("Resource-Freshness")); } @@ -7613,7 +7496,7 @@ EXPECT_EQ(2, transaction_count()); } -static void CheckUrlMatches(const net::HttpRequestInfo* request, +static void CheckUrlMatches(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { @@ -7657,13 +7540,13 @@ INSTANTIATE_TEST_CASE_P(HttpCacheStaleWhileRevalidate, SyncLoadFlagTest, - ::testing::Values(net::LOAD_VALIDATE_CACHE, - net::LOAD_BYPASS_CACHE, - net::LOAD_DISABLE_CACHE)); + ::testing::Values(LOAD_VALIDATE_CACHE, + LOAD_BYPASS_CACHE, + LOAD_DISABLE_CACHE)); TEST_F(HttpCacheStaleWhileRevalidateTest, PreferringCacheDoesNotTriggerAsyncRequest) { - transaction_.load_flags |= net::LOAD_PREFERRING_CACHE; + transaction_.load_flags |= LOAD_PREFERRING_CACHE; // Write to the cache. RunFixtureTransactionTest(); @@ -7696,8 +7579,8 @@ TEST_F(HttpCacheStaleWhileRevalidateTest, OnlyFromCacheDoesNotTriggerAsyncRequest) { - transaction_.load_flags |= net::LOAD_ONLY_FROM_CACHE; - transaction_.return_code = net::ERR_CACHE_MISS; + transaction_.load_flags |= LOAD_ONLY_FROM_CACHE; + transaction_.return_code = ERR_CACHE_MISS; // Writing to the cache should fail, because we are avoiding the network. RunFixtureTransactionTest(); @@ -7725,18 +7608,17 @@ // Now read back. RunTransactionTestBase() expects to receive the network // error back from the HttpCache::Transaction, but since the cache request // will return OK we need to duplicate some of its implementation here. - transaction_.return_code = net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED; - net::TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - int rv = - cache_.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY, &trans); - EXPECT_EQ(net::OK, rv); + transaction_.return_code = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; + TestCompletionCallback callback; + scoped_ptr<HttpTransaction> trans; + int rv = cache_.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans); + EXPECT_EQ(OK, rv); ASSERT_TRUE(trans.get()); MockHttpRequest request(transaction_); - rv = trans->Start(&request, callback.callback(), net::BoundNetLog()); - ASSERT_EQ(net::ERR_IO_PENDING, rv); - ASSERT_EQ(net::OK, callback.WaitForResult()); + rv = trans->Start(&request, callback.callback(), BoundNetLog()); + ASSERT_EQ(ERR_IO_PENDING, rv); + ASSERT_EQ(OK, callback.WaitForResult()); ReadAndVerifyTransaction(trans.get(), transaction_); EXPECT_EQ(1, transaction_count()); @@ -7747,7 +7629,7 @@ EXPECT_EQ(2, transaction_count()); // Now run the transaction again. It should run synchronously. - transaction_.return_code = net::OK; + transaction_.return_code = OK; RunFixtureTransactionTest(); EXPECT_EQ(3, transaction_count()); @@ -7767,7 +7649,7 @@ base::RunLoop().RunUntilIdle(); // The cache entry should still be complete. - transaction_.load_flags = net::LOAD_ONLY_FROM_CACHE; + transaction_.load_flags = LOAD_ONLY_FROM_CACHE; RunFixtureTransactionTest(); } @@ -7789,17 +7671,17 @@ EXPECT_EQ(2, transaction_count()); } -static void CheckLoadFlagsAsyncRevalidation(const net::HttpRequestInfo* request, +static void CheckLoadFlagsAsyncRevalidation(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { - EXPECT_EQ(net::LOAD_ASYNC_REVALIDATION, request->load_flags); + EXPECT_EQ(LOAD_ASYNC_REVALIDATION, request->load_flags); } // Check that the load flags on the async request are the same as the load flags // on the original request, plus LOAD_ASYNC_REVALIDATION. TEST_F(HttpCacheStaleWhileRevalidateTest, LoadFlagsAsyncRevalidation) { - transaction_.load_flags = net::LOAD_NORMAL; + transaction_.load_flags = LOAD_NORMAL; // Write to the cache. RunFixtureTransactionTest(); @@ -7816,7 +7698,7 @@ EXPECT_EQ(2, transaction_count()); } -static void SimpleMockAuthHandler(const net::HttpRequestInfo* request, +static void SimpleMockAuthHandler(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data) { @@ -7862,14 +7744,14 @@ transaction.data = "rg: 00-09 "; AddMockTransaction(&transaction); - net::TestCompletionCallback callback; - scoped_ptr<net::HttpTransaction> trans; - int rv = cache.http_cache()->CreateTransaction(net::DEFAULT_PRIORITY, &trans); - EXPECT_EQ(net::OK, rv); + TestCompletionCallback callback; + scoped_ptr<HttpTransaction> trans; + int rv = cache.http_cache()->CreateTransaction(DEFAULT_PRIORITY, &trans); + EXPECT_EQ(OK, rv); ASSERT_TRUE(trans.get()); // Start our transaction. - trans->Start(&request, callback.callback(), net::BoundNetLog()); + trans->Start(&request, callback.callback(), BoundNetLog()); // A second transaction on a different part of the file (the default // kRangeGET_TransactionOK requests 40-49) should not be blocked by @@ -7894,14 +7776,14 @@ scoped_ptr<Context> first(new Context); first->result = cache.CreateTransaction(&first->trans); - ASSERT_EQ(net::OK, first->result); - EXPECT_EQ(net::LOAD_STATE_IDLE, first->trans->GetLoadState()); - first->result = first->trans->Start( - &request, first->callback.callback(), net::BoundNetLog()); - EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_CACHE, first->trans->GetLoadState()); + ASSERT_EQ(OK, first->result); + EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState()); + first->result = + first->trans->Start(&request, first->callback.callback(), BoundNetLog()); + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, first->trans->GetLoadState()); base::MessageLoop::current()->RunUntilIdle(); - EXPECT_EQ(net::LOAD_STATE_IDLE, first->trans->GetLoadState()); + EXPECT_EQ(LOAD_STATE_IDLE, first->trans->GetLoadState()); ASSERT_TRUE(first->trans->GetResponseInfo()); EXPECT_TRUE(first->trans->GetResponseInfo()->headers->HasHeaderValue( "Cache-Control", "no-store")); @@ -7910,17 +7792,19 @@ // Let us create the second (read) transaction. scoped_ptr<Context> second(new Context); second->result = cache.CreateTransaction(&second->trans); - ASSERT_EQ(net::OK, second->result); - EXPECT_EQ(net::LOAD_STATE_IDLE, second->trans->GetLoadState()); - second->result = second->trans->Start( - &request, second->callback.callback(), net::BoundNetLog()); + ASSERT_EQ(OK, second->result); + EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState()); + second->result = second->trans->Start(&request, second->callback.callback(), + BoundNetLog()); // Here the second transaction proceeds without reading the first body. - EXPECT_EQ(net::LOAD_STATE_WAITING_FOR_CACHE, second->trans->GetLoadState()); + EXPECT_EQ(LOAD_STATE_WAITING_FOR_CACHE, second->trans->GetLoadState()); base::MessageLoop::current()->RunUntilIdle(); - EXPECT_EQ(net::LOAD_STATE_IDLE, second->trans->GetLoadState()); + EXPECT_EQ(LOAD_STATE_IDLE, second->trans->GetLoadState()); ASSERT_TRUE(second->trans->GetResponseInfo()); EXPECT_TRUE(second->trans->GetResponseInfo()->headers->HasHeaderValue( "Cache-Control", "no-store")); ReadAndVerifyTransaction(second->trans.get(), kSimpleGET_Transaction); } + +} // namespace net
diff --git a/net/http/http_content_disposition.cc b/net/http/http_content_disposition.cc index 3a1dede..29593cda 100644 --- a/net/http/http_content_disposition.cc +++ b/net/http/http_content_disposition.cc
@@ -14,6 +14,8 @@ #include "net/base/net_util.h" #include "net/http/http_util.h" +namespace net { + namespace { enum RFC2047EncodingType { @@ -73,7 +75,7 @@ return true; } - return net::ConvertToUtf8(decoded, charset.c_str(), output); + return ConvertToUtf8(decoded, charset.c_str(), output); } bool DecodeWord(const std::string& encoded_word, @@ -93,15 +95,15 @@ } else { base::string16 utf16_output; if (!referrer_charset.empty() && - net::ConvertToUTF16(encoded_word, referrer_charset.c_str(), - &utf16_output)) { + ConvertToUTF16(encoded_word, referrer_charset.c_str(), + &utf16_output)) { *output = base::UTF16ToUTF8(utf16_output); } else { *output = base::WideToUTF8(base::SysNativeMBToWide(encoded_word)); } } - *parse_result_flags |= net::HttpContentDisposition::HAS_NON_ASCII_STRINGS; + *parse_result_flags |= HttpContentDisposition::HAS_NON_ASCII_STRINGS; return true; } @@ -173,7 +175,7 @@ if (*(encoded_word.end() - 1) == '=') { output->swap(decoded_word); *parse_result_flags |= - net::HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS; + HttpContentDisposition::HAS_RFC2047_ENCODED_STRINGS; return true; } // encoded_word ending prematurelly with '?' or extra '?' @@ -186,11 +188,9 @@ // web browser. // What IE6/7 does: %-escaped UTF-8. - decoded_word = net::UnescapeURLComponent(encoded_word, - net::UnescapeRule::SPACES); + decoded_word = UnescapeURLComponent(encoded_word, UnescapeRule::SPACES); if (decoded_word != encoded_word) - *parse_result_flags |= - net::HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS; + *parse_result_flags |= HttpContentDisposition::HAS_PERCENT_ENCODED_STRINGS; if (base::IsStringUTF8(decoded_word)) { output->swap(decoded_word); return true; @@ -322,16 +322,14 @@ return true; } - std::string unescaped = net::UnescapeURLComponent( - value, net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS); + std::string unescaped = UnescapeURLComponent( + value, UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS); - return net::ConvertToUtf8AndNormalize(unescaped, charset.c_str(), decoded); + return ConvertToUtf8AndNormalize(unescaped, charset.c_str(), decoded); } } // namespace -namespace net { - HttpContentDisposition::HttpContentDisposition( const std::string& header, const std::string& referrer_charset) : type_(INLINE),
diff --git a/net/http/http_content_disposition_unittest.cc b/net/http/http_content_disposition_unittest.cc index e617c6ca..ade0d293 100644 --- a/net/http/http_content_disposition_unittest.cc +++ b/net/http/http_content_disposition_unittest.cc
@@ -207,301 +207,245 @@ TEST(HttpContentDispositionTest, tc2231) { const struct FileNameCDCase { const char* header; - net::HttpContentDisposition::Type expected_type; + HttpContentDisposition::Type expected_type; const wchar_t* expected_filename; } tests[] = { - // http://greenbytes.de/tech/tc2231/#inlonly - { "inline", - net::HttpContentDisposition::INLINE, - L"" - }, - // http://greenbytes.de/tech/tc2231/#inlonlyquoted - { "\"inline\"", - net::HttpContentDisposition::INLINE, - L"" - }, - // http://greenbytes.de/tech/tc2231/#inlwithasciifilename - { "inline; filename=\"foo.html\"", - net::HttpContentDisposition::INLINE, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#inlwithfnattach - { "inline; filename=\"Not an attachment!\"", - net::HttpContentDisposition::INLINE, - L"Not an attachment!" - }, - // http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf - { "inline; filename=\"foo.pdf\"", - net::HttpContentDisposition::INLINE, - L"foo.pdf" - }, - // http://greenbytes.de/tech/tc2231/#attonly - { "attachment", - net::HttpContentDisposition::ATTACHMENT, - L"" - }, - // http://greenbytes.de/tech/tc2231/#attonlyquoted - { "\"attachment\"", - net::HttpContentDisposition::INLINE, - L"" - }, - // http://greenbytes.de/tech/tc2231/#attonly403 - // TODO(abarth): This isn't testable in this unit test. - // http://greenbytes.de/tech/tc2231/#attonlyucase - { "ATTACHMENT", - net::HttpContentDisposition::ATTACHMENT, - L"" - }, - // http://greenbytes.de/tech/tc2231/#attwithasciifilename - { "attachment; filename=\"foo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithasciifnescapedchar - { "attachment; filename=\"f\\oo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithasciifnescapedquote - { "attachment; filename=\"\\\"quoting\\\" tested.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"\"quoting\" tested.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithquotedsemicolon - { "attachment; filename=\"Here's a semicolon;.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"Here's a semicolon;.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithfilenameandextparam - { "attachment; foo=\"bar\"; filename=\"foo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithfilenameandextparamescaped - { "attachment; foo=\"\\\"\\\\\";filename=\"foo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithasciifilenameucase - { "attachment; FILENAME=\"foo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenq - { "attachment; filename=foo.html", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenqs - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=foo.html ;", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attemptyparam - // Note: tc2231 says we should fail to parse this header. - { "attachment; ;filename=foo", - net::HttpContentDisposition::ATTACHMENT, - L"foo" - }, - // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenqws - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=foo bar.html", - net::HttpContentDisposition::ATTACHMENT, - L"foo bar.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithfntokensq - { "attachment; filename='foo.bar'", - net::HttpContentDisposition::ATTACHMENT, - L"foo.bar" // Should be L"'foo.bar'" - }, + // http://greenbytes.de/tech/tc2231/#inlonly + {"inline", HttpContentDisposition::INLINE, L""}, + // http://greenbytes.de/tech/tc2231/#inlonlyquoted + {"\"inline\"", HttpContentDisposition::INLINE, L""}, + // http://greenbytes.de/tech/tc2231/#inlwithasciifilename + {"inline; filename=\"foo.html\"", + HttpContentDisposition::INLINE, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#inlwithfnattach + {"inline; filename=\"Not an attachment!\"", + HttpContentDisposition::INLINE, + L"Not an attachment!"}, + // http://greenbytes.de/tech/tc2231/#inlwithasciifilenamepdf + {"inline; filename=\"foo.pdf\"", + HttpContentDisposition::INLINE, + L"foo.pdf"}, + // http://greenbytes.de/tech/tc2231/#attonly + {"attachment", HttpContentDisposition::ATTACHMENT, L""}, + // http://greenbytes.de/tech/tc2231/#attonlyquoted + {"\"attachment\"", HttpContentDisposition::INLINE, L""}, + // http://greenbytes.de/tech/tc2231/#attonly403 + // TODO(abarth): This isn't testable in this unit test. + // http://greenbytes.de/tech/tc2231/#attonlyucase + {"ATTACHMENT", HttpContentDisposition::ATTACHMENT, L""}, + // http://greenbytes.de/tech/tc2231/#attwithasciifilename + {"attachment; filename=\"foo.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attwithasciifnescapedchar + {"attachment; filename=\"f\\oo.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attwithasciifnescapedquote + {"attachment; filename=\"\\\"quoting\\\" tested.html\"", + HttpContentDisposition::ATTACHMENT, + L"\"quoting\" tested.html"}, + // http://greenbytes.de/tech/tc2231/#attwithquotedsemicolon + {"attachment; filename=\"Here's a semicolon;.html\"", + HttpContentDisposition::ATTACHMENT, + L"Here's a semicolon;.html"}, + // http://greenbytes.de/tech/tc2231/#attwithfilenameandextparam + {"attachment; foo=\"bar\"; filename=\"foo.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attwithfilenameandextparamescaped + {"attachment; foo=\"\\\"\\\\\";filename=\"foo.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attwithasciifilenameucase + {"attachment; FILENAME=\"foo.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenq + {"attachment; filename=foo.html", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenqs + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=foo.html ;", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attemptyparam + // Note: tc2231 says we should fail to parse this header. + {"attachment; ;filename=foo", HttpContentDisposition::ATTACHMENT, L"foo"}, + // http://greenbytes.de/tech/tc2231/#attwithasciifilenamenqws + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=foo bar.html", + HttpContentDisposition::ATTACHMENT, + L"foo bar.html"}, + // http://greenbytes.de/tech/tc2231/#attwithfntokensq + { + "attachment; filename='foo.bar'", + HttpContentDisposition::ATTACHMENT, + L"foo.bar" // Should be L"'foo.bar'" + }, #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER - // http://greenbytes.de/tech/tc2231/#attwithisofnplain - { "attachment; filename=\"foo-\xE4html\"", - net::HttpContentDisposition::ATTACHMENT, - L"" // Should be L"foo-\xE4.html" - }, + // http://greenbytes.de/tech/tc2231/#attwithisofnplain + { + "attachment; filename=\"foo-\xE4html\"", + HttpContentDisposition::ATTACHMENT, + L"" // Should be L"foo-\xE4.html" + }, #endif - // http://greenbytes.de/tech/tc2231/#attwithutf8fnplain - // Note: We'll UTF-8 decode the file name, even though tc2231 says not to. - { "attachment; filename=\"foo-\xC3\xA4.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo-\xE4.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithfnrawpctenca - { "attachment; filename=\"foo-%41.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo-A.html" // Should be L"foo-%41.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithfnusingpct - { "attachment; filename=\"50%.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"50%.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithfnrawpctencaq - { "attachment; filename=\"foo-%\\41.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo-A.html" // Should be L"foo-%41.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithnamepct - { "attachment; name=\"foo-%41.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo-A.html" // Should be L"foo-%41.html" - }, + // http://greenbytes.de/tech/tc2231/#attwithutf8fnplain + // Note: We'll UTF-8 decode the file name, even though tc2231 says not to. + {"attachment; filename=\"foo-\xC3\xA4.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo-\xE4.html"}, + // http://greenbytes.de/tech/tc2231/#attwithfnrawpctenca + { + "attachment; filename=\"foo-%41.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo-A.html" // Should be L"foo-%41.html" + }, + // http://greenbytes.de/tech/tc2231/#attwithfnusingpct + {"attachment; filename=\"50%.html\"", + HttpContentDisposition::ATTACHMENT, + L"50%.html"}, + // http://greenbytes.de/tech/tc2231/#attwithfnrawpctencaq + { + "attachment; filename=\"foo-%\\41.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo-A.html" // Should be L"foo-%41.html" + }, + // http://greenbytes.de/tech/tc2231/#attwithnamepct + { + "attachment; name=\"foo-%41.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo-A.html" // Should be L"foo-%41.html" + }, #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER - // http://greenbytes.de/tech/tc2231/#attwithfilenamepctandiso - { "attachment; filename=\"\xE4-%41.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"" // Should be L"\xE4-%41.htm" - }, + // http://greenbytes.de/tech/tc2231/#attwithfilenamepctandiso + { + "attachment; filename=\"\xE4-%41.html\"", + HttpContentDisposition::ATTACHMENT, + L"" // Should be L"\xE4-%41.htm" + }, #endif - // http://greenbytes.de/tech/tc2231/#attwithfnrawpctenclong - { "attachment; filename=\"foo-%c3%a4-%e2%82%ac.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo-\xE4-\u20AC.html" // Should be L"foo-%c3%a4-%e2%82%ac.html" - }, - // http://greenbytes.de/tech/tc2231/#attwithasciifilenamews1 - { "attachment; filename =\"foo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attwith2filenames - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=\"foo.html\"; filename=\"bar.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attfnbrokentoken - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=foo[1](2).html", - net::HttpContentDisposition::ATTACHMENT, - L"foo[1](2).html" - }, + // http://greenbytes.de/tech/tc2231/#attwithfnrawpctenclong + { + "attachment; filename=\"foo-%c3%a4-%e2%82%ac.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo-\xE4-\u20AC.html" // Should be L"foo-%c3%a4-%e2%82%ac.html" + }, + // http://greenbytes.de/tech/tc2231/#attwithasciifilenamews1 + {"attachment; filename =\"foo.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attwith2filenames + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=\"foo.html\"; filename=\"bar.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attfnbrokentoken + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=foo[1](2).html", + HttpContentDisposition::ATTACHMENT, + L"foo[1](2).html"}, #ifdef ICU_SHOULD_FAIL_CONVERSION_ON_INVALID_CHARACTER - // http://greenbytes.de/tech/tc2231/#attfnbrokentokeniso - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=foo-\xE4.html", - net::HttpContentDisposition::ATTACHMENT, - L"" - }, + // http://greenbytes.de/tech/tc2231/#attfnbrokentokeniso + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=foo-\xE4.html", + HttpContentDisposition::ATTACHMENT, + L""}, #endif - // http://greenbytes.de/tech/tc2231/#attfnbrokentokenutf - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=foo-\xC3\xA4.html", - net::HttpContentDisposition::ATTACHMENT, - L"foo-\xE4.html" - }, - // http://greenbytes.de/tech/tc2231/#attmissingdisposition - // Note: tc2231 says we should fail to parse this header. - { "filename=foo.html", - net::HttpContentDisposition::INLINE, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attmissingdisposition2 - // Note: tc2231 says we should fail to parse this header. - { "x=y; filename=foo.html", - net::HttpContentDisposition::INLINE, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attmissingdisposition3 - // Note: tc2231 says we should fail to parse this header. - { "\"foo; filename=bar;baz\"; filename=qux", - net::HttpContentDisposition::INLINE, - L"" // Firefox gets qux - }, - // http://greenbytes.de/tech/tc2231/#attmissingdisposition4 - // Note: tc2231 says we should fail to parse this header. - { "filename=foo.html, filename=bar.html", - net::HttpContentDisposition::INLINE, - L"foo.html, filename=bar.html" - }, - // http://greenbytes.de/tech/tc2231/#emptydisposition - // Note: tc2231 says we should fail to parse this header. - { "; filename=foo.html", - net::HttpContentDisposition::INLINE, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attandinline - // Note: tc2231 says we should fail to parse this header. - { "inline; attachment; filename=foo.html", - net::HttpContentDisposition::INLINE, - L"" - }, - // http://greenbytes.de/tech/tc2231/#attandinline2 - // Note: tc2231 says we should fail to parse this header. - { "attachment; inline; filename=foo.html", - net::HttpContentDisposition::ATTACHMENT, - L"" - }, - // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=\"foo.html\".txt", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html\".txt" - }, - // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn2 - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=\"bar", - net::HttpContentDisposition::ATTACHMENT, - L"bar" - }, - // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn3 - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=foo\"bar;baz\"qux", - net::HttpContentDisposition::ATTACHMENT, - L"foo\"bar;baz\"qux" - }, - // http://greenbytes.de/tech/tc2231/#attmultinstances - // Note: tc2231 says we should fail to parse this header. - { "attachment; filename=foo.html, attachment; filename=bar.html", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html, attachment" - }, - // http://greenbytes.de/tech/tc2231/#attmissingdelim - { "attachment; foo=foo filename=bar", - net::HttpContentDisposition::ATTACHMENT, - L"" - }, - // http://greenbytes.de/tech/tc2231/#attreversed - // Note: tc2231 says we should fail to parse this header. - { "filename=foo.html; attachment", - net::HttpContentDisposition::INLINE, - L"foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attconfusedparam - { "attachment; xfilename=foo.html", - net::HttpContentDisposition::ATTACHMENT, - L"" - }, - // http://greenbytes.de/tech/tc2231/#attabspath - { "attachment; filename=\"/foo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"/foo.html" - }, - // http://greenbytes.de/tech/tc2231/#attabspathwin - { "attachment; filename=\"\\\\foo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"\\foo.html" - }, - // http://greenbytes.de/tech/tc2231/#dispext - { "foobar", - net::HttpContentDisposition::ATTACHMENT, - L"" - }, - // http://greenbytes.de/tech/tc2231/#dispextbadfn - { "attachment; example=\"filename=example.txt\"", - net::HttpContentDisposition::ATTACHMENT, - L"" - }, - // http://greenbytes.de/tech/tc2231/#attnewandfn - { "attachment; foobar=x; filename=\"foo.html\"", - net::HttpContentDisposition::ATTACHMENT, - L"foo.html" - }, - // TODO(abarth): Add the filename* tests, but check - // HttpContentDispositionTest.Filename for overlap. - // TODO(abarth): http://greenbytes.de/tech/tc2231/#attrfc2047token - // TODO(abarth): http://greenbytes.de/tech/tc2231/#attrfc2047quoted + // http://greenbytes.de/tech/tc2231/#attfnbrokentokenutf + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=foo-\xC3\xA4.html", + HttpContentDisposition::ATTACHMENT, + L"foo-\xE4.html"}, + // http://greenbytes.de/tech/tc2231/#attmissingdisposition + // Note: tc2231 says we should fail to parse this header. + {"filename=foo.html", HttpContentDisposition::INLINE, L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attmissingdisposition2 + // Note: tc2231 says we should fail to parse this header. + {"x=y; filename=foo.html", HttpContentDisposition::INLINE, L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attmissingdisposition3 + // Note: tc2231 says we should fail to parse this header. + { + "\"foo; filename=bar;baz\"; filename=qux", + HttpContentDisposition::INLINE, + L"" // Firefox gets qux + }, + // http://greenbytes.de/tech/tc2231/#attmissingdisposition4 + // Note: tc2231 says we should fail to parse this header. + {"filename=foo.html, filename=bar.html", + HttpContentDisposition::INLINE, + L"foo.html, filename=bar.html"}, + // http://greenbytes.de/tech/tc2231/#emptydisposition + // Note: tc2231 says we should fail to parse this header. + {"; filename=foo.html", HttpContentDisposition::INLINE, L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attandinline + // Note: tc2231 says we should fail to parse this header. + {"inline; attachment; filename=foo.html", + HttpContentDisposition::INLINE, + L""}, + // http://greenbytes.de/tech/tc2231/#attandinline2 + // Note: tc2231 says we should fail to parse this header. + {"attachment; inline; filename=foo.html", + HttpContentDisposition::ATTACHMENT, + L""}, + // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=\"foo.html\".txt", + HttpContentDisposition::ATTACHMENT, + L"foo.html\".txt"}, + // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn2 + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=\"bar", + HttpContentDisposition::ATTACHMENT, + L"bar"}, + // http://greenbytes.de/tech/tc2231/#attbrokenquotedfn3 + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=foo\"bar;baz\"qux", + HttpContentDisposition::ATTACHMENT, + L"foo\"bar;baz\"qux"}, + // http://greenbytes.de/tech/tc2231/#attmultinstances + // Note: tc2231 says we should fail to parse this header. + {"attachment; filename=foo.html, attachment; filename=bar.html", + HttpContentDisposition::ATTACHMENT, + L"foo.html, attachment"}, + // http://greenbytes.de/tech/tc2231/#attmissingdelim + {"attachment; foo=foo filename=bar", + HttpContentDisposition::ATTACHMENT, + L""}, + // http://greenbytes.de/tech/tc2231/#attreversed + // Note: tc2231 says we should fail to parse this header. + {"filename=foo.html; attachment", + HttpContentDisposition::INLINE, + L"foo.html"}, + // http://greenbytes.de/tech/tc2231/#attconfusedparam + {"attachment; xfilename=foo.html", + HttpContentDisposition::ATTACHMENT, + L""}, + // http://greenbytes.de/tech/tc2231/#attabspath + {"attachment; filename=\"/foo.html\"", + HttpContentDisposition::ATTACHMENT, + L"/foo.html"}, + // http://greenbytes.de/tech/tc2231/#attabspathwin + {"attachment; filename=\"\\\\foo.html\"", + HttpContentDisposition::ATTACHMENT, + L"\\foo.html"}, + // http://greenbytes.de/tech/tc2231/#dispext + {"foobar", HttpContentDisposition::ATTACHMENT, L""}, + // http://greenbytes.de/tech/tc2231/#dispextbadfn + {"attachment; example=\"filename=example.txt\"", + HttpContentDisposition::ATTACHMENT, + L""}, + // http://greenbytes.de/tech/tc2231/#attnewandfn + {"attachment; foobar=x; filename=\"foo.html\"", + HttpContentDisposition::ATTACHMENT, + L"foo.html"}, + // TODO(abarth): Add the filename* tests, but check + // HttpContentDispositionTest.Filename for overlap. + // TODO(abarth): http://greenbytes.de/tech/tc2231/#attrfc2047token + // TODO(abarth): http://greenbytes.de/tech/tc2231/#attrfc2047quoted }; for (size_t i = 0; i < arraysize(tests); ++i) { HttpContentDisposition header(tests[i].header, std::string());
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 4ff037b..45e8736 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -30,17 +30,19 @@ #include "net/socket/ssl_client_socket.h" #include "net/spdy/spdy_session_pool.h" +namespace net { + namespace { -net::ClientSocketPoolManager* CreateSocketPoolManager( - net::HttpNetworkSession::SocketPoolType pool_type, - const net::HttpNetworkSession::Params& params) { +ClientSocketPoolManager* CreateSocketPoolManager( + HttpNetworkSession::SocketPoolType pool_type, + const HttpNetworkSession::Params& params) { // TODO(yutak): Differentiate WebSocket pool manager and allow more // simultaneous connections for WebSockets. - return new net::ClientSocketPoolManagerImpl( - params.net_log, params.client_socket_factory - ? params.client_socket_factory - : net::ClientSocketFactory::GetDefaultFactory(), + return new ClientSocketPoolManagerImpl( + params.net_log, + params.client_socket_factory ? params.client_socket_factory + : ClientSocketFactory::GetDefaultFactory(), params.host_resolver, params.cert_verifier, params.channel_id_service, params.transport_security_state, params.cert_transparency_verifier, params.cert_policy_enforcer, params.ssl_session_cache_shard, @@ -49,8 +51,6 @@ } // unnamed namespace -namespace net { - // The maximum receive window sizes for HTTP/2 sessions and streams. const int32 kSpdySessionMaxRecvWindowSize = 10 * 1024 * 1024; // 10 MB const int32 kSpdyStreamMaxRecvWindowSize = 10 * 1024 * 1024; // 10 MB @@ -83,7 +83,7 @@ spdy_max_concurrent_streams_limit(0), time_func(&base::TimeTicks::Now), use_alternate_protocols(false), - alternate_protocol_probability_threshold(1), + alternative_service_probability_threshold(1), enable_quic(false), enable_quic_for_proxies(false), enable_quic_port_selection(true), @@ -124,7 +124,7 @@ params.host_resolver, params.client_socket_factory ? params.client_socket_factory - : net::ClientSocketFactory::GetDefaultFactory(), + : ClientSocketFactory::GetDefaultFactory(), params.http_server_properties, params.cert_verifier, params.channel_id_service, @@ -196,8 +196,8 @@ } } - http_server_properties_->SetAlternateProtocolProbabilityThreshold( - params.alternate_protocol_probability_threshold); + http_server_properties_->SetAlternativeServiceProbabilityThreshold( + params.alternative_service_probability_threshold); } HttpNetworkSession::~HttpNetworkSession() { @@ -271,8 +271,8 @@ dict->Set("connection_options", connection_options); dict->SetString("origin_to_force_quic_on", params_.origin_to_force_quic_on.ToString()); - dict->SetDouble("alternate_protocol_probability_threshold", - params_.alternate_protocol_probability_threshold); + dict->SetDouble("alternative_service_probability_threshold", + params_.alternative_service_probability_threshold); return dict; } @@ -323,4 +323,4 @@ return NULL; } -} // namespace net +} // namespace net
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h index cd18f79..95fea4c 100644 --- a/net/http/http_network_session.h +++ b/net/http/http_network_session.h
@@ -104,7 +104,7 @@ // Noe: Using this in the case of NPN for HTTP only results in the browser // trying SSL and then falling back to http. bool use_alternate_protocols; - double alternate_protocol_probability_threshold; + double alternative_service_probability_threshold; bool enable_quic; bool enable_quic_for_proxies;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index a1bba94e..bc8a81f 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -50,6 +50,7 @@ #include "net/http/http_stream_factory.h" #include "net/http/http_stream_parser.h" #include "net/http/http_transaction_test_util.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" #include "net/log/test_net_log.h" @@ -82,6 +83,8 @@ //----------------------------------------------------------------------------- +namespace net { + namespace { const base::string16 kBar(ASCIIToUTF16("bar")); @@ -97,19 +100,19 @@ const base::string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm")); const base::string16 kWrongPassword(ASCIIToUTF16("wrongpassword")); -int GetIdleSocketCountInTransportSocketPool(net::HttpNetworkSession* session) { - return session->GetTransportSocketPool( - net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount(); +int GetIdleSocketCountInTransportSocketPool(HttpNetworkSession* session) { + return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL) + ->IdleSocketCount(); } -int GetIdleSocketCountInSSLSocketPool(net::HttpNetworkSession* session) { - return session->GetSSLSocketPool( - net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IdleSocketCount(); +int GetIdleSocketCountInSSLSocketPool(HttpNetworkSession* session) { + return session->GetSSLSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL) + ->IdleSocketCount(); } -bool IsTransportSocketPoolStalled(net::HttpNetworkSession* session) { - return session->GetTransportSocketPool( - net::HttpNetworkSession::NORMAL_SOCKET_POOL)->IsStalled(); +bool IsTransportSocketPoolStalled(HttpNetworkSession* session) { + return session->GetTransportSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL) + ->IsStalled(); } // Takes in a Value created from a NetLogHttpResponseParameter, and returns @@ -129,14 +132,14 @@ // Tests LoadTimingInfo in the case a socket is reused and no PAC script is // used. -void TestLoadTimingReused(const net::LoadTimingInfo& load_timing_info) { +void TestLoadTimingReused(const LoadTimingInfo& load_timing_info) { EXPECT_TRUE(load_timing_info.socket_reused); - EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); + EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); - net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); + ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); EXPECT_FALSE(load_timing_info.send_start.is_null()); EXPECT_LE(load_timing_info.send_start, load_timing_info.send_end); @@ -149,16 +152,16 @@ // Tests LoadTimingInfo in the case a new socket is used and no PAC script is // used. -void TestLoadTimingNotReused(const net::LoadTimingInfo& load_timing_info, +void TestLoadTimingNotReused(const LoadTimingInfo& load_timing_info, int connect_timing_flags) { EXPECT_FALSE(load_timing_info.socket_reused); - EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); + EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); EXPECT_TRUE(load_timing_info.proxy_resolve_start.is_null()); EXPECT_TRUE(load_timing_info.proxy_resolve_end.is_null()); - net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, - connect_timing_flags); + ExpectConnectTimingHasTimes(load_timing_info.connect_timing, + connect_timing_flags); EXPECT_LE(load_timing_info.connect_timing.connect_end, load_timing_info.send_start); @@ -172,11 +175,11 @@ // Tests LoadTimingInfo in the case a socket is reused and a PAC script is // used. -void TestLoadTimingReusedWithPac(const net::LoadTimingInfo& load_timing_info) { +void TestLoadTimingReusedWithPac(const LoadTimingInfo& load_timing_info) { EXPECT_TRUE(load_timing_info.socket_reused); - EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); + EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); - net::ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); + ExpectConnectTimingHasNoTimes(load_timing_info.connect_timing); EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); EXPECT_LE(load_timing_info.proxy_resolve_start, @@ -193,18 +196,18 @@ // Tests LoadTimingInfo in the case a new socket is used and a PAC script is // used. -void TestLoadTimingNotReusedWithPac(const net::LoadTimingInfo& load_timing_info, +void TestLoadTimingNotReusedWithPac(const LoadTimingInfo& load_timing_info, int connect_timing_flags) { EXPECT_FALSE(load_timing_info.socket_reused); - EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); + EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); EXPECT_LE(load_timing_info.proxy_resolve_start, load_timing_info.proxy_resolve_end); EXPECT_LE(load_timing_info.proxy_resolve_end, load_timing_info.connect_timing.connect_start); - net::ExpectConnectTimingHasTimes(load_timing_info.connect_timing, - connect_timing_flags); + ExpectConnectTimingHasTimes(load_timing_info.connect_timing, + connect_timing_flags); EXPECT_LE(load_timing_info.connect_timing.connect_end, load_timing_info.send_start); @@ -216,7 +219,7 @@ EXPECT_TRUE(load_timing_info.receive_headers_end.is_null()); } -void AddWebSocketHeaders(net::HttpRequestHeaders* headers) { +void AddWebSocketHeaders(HttpRequestHeaders* headers) { headers->SetHeader("Connection", "Upgrade"); headers->SetHeader("Upgrade", "websocket"); headers->SetHeader("Origin", "http://www.example.org"); @@ -224,12 +227,6 @@ headers->SetHeader("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ=="); } -} // namespace - -namespace net { - -namespace { - HttpNetworkSession* CreateSession(SpdySessionDependencies* session_deps) { return SpdySessionDependencies::SpdyCreateSession(session_deps); } @@ -358,7 +355,7 @@ rv = ReadTransaction(trans.get(), &out.response_data); EXPECT_EQ(OK, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS, @@ -1435,7 +1432,7 @@ session_deps_.socket_factory->AddSocketDataProvider(&data2); // Preconnect a socket. - net::SSLConfig ssl_config; + SSLConfig ssl_config; session->ssl_config_service()->GetSSLConfig(&ssl_config); session->GetNextProtos(&ssl_config.next_protos); session->http_stream_factory()->PreconnectStreams( @@ -1988,7 +1985,7 @@ HttpRequestInfo request; request.method = "GET"; request.url = GURL("http://www.example.org/"); - request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); scoped_ptr<HttpTransaction> trans( @@ -2391,7 +2388,7 @@ request.method = "GET"; request.url = GURL("https://www.example.org/"); // when the no authentication data flag is set. - request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against proxy server "myproxy:70". session_deps_.proxy_service.reset( @@ -2452,7 +2449,7 @@ rv = callback1.WaitForResult(); EXPECT_EQ(OK, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, @@ -2509,7 +2506,7 @@ request.method = "GET"; request.url = GURL("https://www.example.org/"); // when the no authentication data flag is set. - request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against proxy server "myproxy:70". session_deps_.proxy_service.reset( @@ -2571,7 +2568,7 @@ rv = callback1.WaitForResult(); EXPECT_EQ(OK, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, @@ -2630,7 +2627,7 @@ request.url = GURL("https://www.example.org/"); // Ensure that proxy authentication is attempted even // when the no authentication data flag is set. - request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against proxy server "myproxy:70". session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); @@ -2687,7 +2684,7 @@ rv = callback1.WaitForResult(); EXPECT_EQ(OK, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, @@ -2737,7 +2734,7 @@ request.url = GURL("https://www.example.org/"); // Ensure that proxy authentication is attempted even // when the no authentication data flag is set. - request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against proxy server "myproxy:70". session_deps_.proxy_service.reset(ProxyService::CreateFixed("myproxy:70")); @@ -2792,7 +2789,7 @@ rv = callback1.WaitForResult(); EXPECT_EQ(OK, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, @@ -3055,7 +3052,7 @@ rv = callback1.WaitForResult(); EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, @@ -3635,8 +3632,6 @@ ssl.SetNextProto(GetParam()); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); SSLSocketDataProvider ssl2(ASYNC, OK); - ssl2.was_npn_negotiated = false; - ssl2.protocol_negotiated = kProtoUnknown; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); TestCompletionCallback callback1; @@ -3725,7 +3720,6 @@ session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); SSLSocketDataProvider ssl2(ASYNC, OK); ssl2.SetNextProto(GetParam()); - ssl2.protocol_negotiated = GetParam(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); TestCompletionCallback callback1; @@ -3904,12 +3898,8 @@ ssl.SetNextProto(GetParam()); session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); SSLSocketDataProvider ssl2(ASYNC, OK); - ssl2.was_npn_negotiated = false; - ssl2.protocol_negotiated = kProtoUnknown; session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); SSLSocketDataProvider ssl3(ASYNC, OK); - ssl3.was_npn_negotiated = false; - ssl3.protocol_negotiated = kProtoUnknown; session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl3); TestCompletionCallback callback; @@ -3934,7 +3924,7 @@ EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); std::string response_data; - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback())); scoped_ptr<HttpTransaction> trans2( @@ -4042,8 +4032,6 @@ ssl.SetNextProto(GetParam()); session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl); SSLSocketDataProvider ssl2(ASYNC, OK); - ssl2.was_npn_negotiated = false; - ssl2.protocol_negotiated = kProtoUnknown; session_deps_.deterministic_socket_factory->AddSSLSocketDataProvider(&ssl2); TestCompletionCallback callback; @@ -4068,7 +4056,7 @@ EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); std::string response_data; - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); EXPECT_EQ(1, trans->Read(buf.get(), 256, callback.callback())); trans.reset(); @@ -4179,7 +4167,7 @@ EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine()); std::string response_data; - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); EXPECT_EQ(ERR_IO_PENDING, trans->Read(buf.get(), 256, callback.callback())); spdy_data.RunFor(1); EXPECT_EQ(1, callback.WaitForResult()); @@ -4213,7 +4201,7 @@ request.method = "GET"; request.url = GURL("http://www.example.org/"); // when the no authentication data flag is set. - request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against https proxy server "myproxy:70". session_deps_.proxy_service.reset( @@ -6566,7 +6554,7 @@ EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info)); EXPECT_FALSE(load_timing_info.socket_reused); - EXPECT_NE(net::NetLog::Source::kInvalidId, load_timing_info.socket_log_id); + EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); EXPECT_FALSE(load_timing_info.proxy_resolve_start.is_null()); EXPECT_LE(load_timing_info.proxy_resolve_start, @@ -6759,7 +6747,7 @@ request.method = "GET"; request.url = GURL("https://www.example.org/"); // when the no authentication data flag is set. - request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA; + request.load_flags = LOAD_DO_NOT_SEND_AUTH_DATA; // Configure against https proxy server "myproxy:70". session_deps_.proxy_service.reset( @@ -6845,7 +6833,7 @@ rv = callback1.WaitForResult(); EXPECT_EQ(OK, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, @@ -10442,9 +10430,7 @@ }; SSLSocketDataProvider ssl(ASYNC, OK); - ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated; - ssl.next_proto = "http/1.1"; - ssl.protocol_negotiated = kProtoHTTP11; + ssl.SetNextProto(kProtoHTTP11); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); @@ -10909,7 +10895,7 @@ rv = callback1.WaitForResult(); EXPECT_EQ(OK, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, @@ -10983,7 +10969,7 @@ rv = callback1.WaitForResult(); EXPECT_EQ(ERR_EMPTY_RESPONSE, rv); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t pos = ExpectLogContainsSomewhere( entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS, @@ -11048,17 +11034,16 @@ // call and verify that the HttpTransaction fails with that error. void HttpNetworkTransactionTest::CheckErrorIsPassedBack( int error, IoMode mode) { - net::HttpRequestInfo request_info; + HttpRequestInfo request_info; request_info.url = GURL("https://www.example.com/"); request_info.method = "GET"; - request_info.load_flags = net::LOAD_NORMAL; + request_info.load_flags = LOAD_NORMAL; SSLSocketDataProvider ssl_data(mode, OK); - net::MockWrite data_writes[] = { - net::MockWrite(mode, error), + MockWrite data_writes[] = { + MockWrite(mode, error), }; - net::StaticSocketDataProvider data(NULL, 0, - data_writes, arraysize(data_writes)); + StaticSocketDataProvider data(NULL, 0, data_writes, arraysize(data_writes)); session_deps_.socket_factory->AddSocketDataProvider(&data); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data); @@ -11067,8 +11052,8 @@ new HttpNetworkTransaction(DEFAULT_PRIORITY, session.get())); TestCompletionCallback callback; - int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); - if (rv == net::ERR_IO_PENDING) + int rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); ASSERT_EQ(error, rv); } @@ -11094,10 +11079,10 @@ // 4) The client supplies an invalid/unacceptable certificate. TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) { - net::HttpRequestInfo request_info; + HttpRequestInfo request_info; request_info.url = GURL("https://www.example.com/"); request_info.method = "GET"; - request_info.load_flags = net::LOAD_NORMAL; + request_info.load_flags = LOAD_NORMAL; scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); cert_request->host_and_port = HostPortPair("www.example.com", 443); @@ -11105,10 +11090,10 @@ // [ssl_]data1 contains the data for the first SSL handshake. When a // CertificateRequest is received for the first time, the handshake will // be aborted to allow the caller to provide a certificate. - SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); + SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); ssl_data1.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); - net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); + StaticSocketDataProvider data1(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data1); // [ssl_]data2 contains the data for the second SSL handshake. When TLS @@ -11117,10 +11102,10 @@ // matches the result of a server sending a handshake_failure alert, // rather than a Finished message, because it requires a client // certificate and none was supplied. - SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); + SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); ssl_data2.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); - net::StaticSocketDataProvider data2(NULL, 0, NULL, 0); + StaticSocketDataProvider data2(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data2); // [ssl_]data3 contains the data for the third SSL handshake. When a @@ -11130,10 +11115,10 @@ // of the HttpNetworkTransaction. Because this test failure is due to // requiring a client certificate, this fallback handshake should also // fail. - SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); + SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR); ssl_data3.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); - net::StaticSocketDataProvider data3(NULL, 0, NULL, 0); + StaticSocketDataProvider data3(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data3); // [ssl_]data4 contains the data for the fourth SSL handshake. When a @@ -11143,17 +11128,17 @@ // of the HttpNetworkTransaction. Because this test failure is due to // requiring a client certificate, this fallback handshake should also // fail. - SSLSocketDataProvider ssl_data4(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); + SSLSocketDataProvider ssl_data4(ASYNC, ERR_SSL_PROTOCOL_ERROR); ssl_data4.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4); - net::StaticSocketDataProvider data4(NULL, 0, NULL, 0); + StaticSocketDataProvider data4(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data4); // Need one more if TLSv1.2 is enabled. - SSLSocketDataProvider ssl_data5(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); + SSLSocketDataProvider ssl_data5(ASYNC, ERR_SSL_PROTOCOL_ERROR); ssl_data5.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5); - net::StaticSocketDataProvider data5(NULL, 0, NULL, 0); + StaticSocketDataProvider data5(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data5); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -11162,20 +11147,20 @@ // Begin the SSL handshake with the peer. This consumes ssl_data1. TestCompletionCallback callback; - int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); - ASSERT_EQ(net::ERR_IO_PENDING, rv); + int rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); + ASSERT_EQ(ERR_IO_PENDING, rv); // Complete the SSL handshake, which should abort due to requiring a // client certificate. rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); + ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); // Indicate that no certificate should be supplied. From the perspective // of SSLClientCertCache, NULL is just as meaningful as a real // certificate, so this is the same as supply a // legitimate-but-unacceptable certificate. rv = trans->RestartWithCertificate(NULL, callback.callback()); - ASSERT_EQ(net::ERR_IO_PENDING, rv); + ASSERT_EQ(ERR_IO_PENDING, rv); // Ensure the certificate was added to the client auth cache before // allowing the connection to continue restarting. @@ -11188,7 +11173,7 @@ // then consume ssl_data3 and ssl_data4, both of which should also fail. // The result code is checked against what ssl_data4 should return. rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); + ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); // Ensure that the client certificate is removed from the cache on a // handshake failure. @@ -11204,10 +11189,10 @@ // 4) The client supplies an invalid/unacceptable certificate. TEST_P(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) { - net::HttpRequestInfo request_info; + HttpRequestInfo request_info; request_info.url = GURL("https://www.example.com/"); request_info.method = "GET"; - request_info.load_flags = net::LOAD_NORMAL; + request_info.load_flags = LOAD_NORMAL; scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo()); cert_request->host_and_port = HostPortPair("www.example.com", 443); @@ -11227,10 +11212,10 @@ // Like the non-False Start case, when a client certificate is requested by // the peer, the handshake is aborted during the Connect() call. // [ssl_]data1 represents the initial SSL handshake with the peer. - SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); + SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); ssl_data1.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); - net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); + StaticSocketDataProvider data1(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data1); // When a client certificate is supplied, Connect() will not be aborted @@ -11240,41 +11225,37 @@ // called, which then detects that the handshake was aborted, due to the // peer sending a handshake_failure because it requires a client // certificate. - SSLSocketDataProvider ssl_data2(ASYNC, net::OK); + SSLSocketDataProvider ssl_data2(ASYNC, OK); ssl_data2.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); - net::MockRead data2_reads[] = { - net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR), + MockRead data2_reads[] = { + MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR), }; - net::StaticSocketDataProvider data2( - data2_reads, arraysize(data2_reads), NULL, 0); + StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data2); // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is // the data for the SSL handshake once the TLSv1.1 connection falls back to // TLSv1. It has the same behaviour as [ssl_]data2. - SSLSocketDataProvider ssl_data3(ASYNC, net::OK); + SSLSocketDataProvider ssl_data3(ASYNC, OK); ssl_data3.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); - net::StaticSocketDataProvider data3( - data2_reads, arraysize(data2_reads), NULL, 0); + StaticSocketDataProvider data3(data2_reads, arraysize(data2_reads), NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data3); // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection // falls back to SSLv3. It has the same behaviour as [ssl_]data2. - SSLSocketDataProvider ssl_data4(ASYNC, net::OK); + SSLSocketDataProvider ssl_data4(ASYNC, OK); ssl_data4.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4); - net::StaticSocketDataProvider data4( - data2_reads, arraysize(data2_reads), NULL, 0); + StaticSocketDataProvider data4(data2_reads, arraysize(data2_reads), NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data4); // Need one more if TLSv1.2 is enabled. - SSLSocketDataProvider ssl_data5(ASYNC, net::OK); + SSLSocketDataProvider ssl_data5(ASYNC, OK); ssl_data5.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5); - net::StaticSocketDataProvider data5( - data2_reads, arraysize(data2_reads), NULL, 0); + StaticSocketDataProvider data5(data2_reads, arraysize(data2_reads), NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data5); scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_)); @@ -11283,20 +11264,20 @@ // Begin the initial SSL handshake. TestCompletionCallback callback; - int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog()); - ASSERT_EQ(net::ERR_IO_PENDING, rv); + int rv = trans->Start(&request_info, callback.callback(), BoundNetLog()); + ASSERT_EQ(ERR_IO_PENDING, rv); // Complete the SSL handshake, which should abort due to requiring a // client certificate. rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); + ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); // Indicate that no certificate should be supplied. From the perspective // of SSLClientCertCache, NULL is just as meaningful as a real // certificate, so this is the same as supply a // legitimate-but-unacceptable certificate. rv = trans->RestartWithCertificate(NULL, callback.callback()); - ASSERT_EQ(net::ERR_IO_PENDING, rv); + ASSERT_EQ(ERR_IO_PENDING, rv); // Ensure the certificate was added to the client auth cache before // allowing the connection to continue restarting. @@ -11309,7 +11290,7 @@ // then consume ssl_data3 and ssl_data4, both of which should also fail. // The result code is checked against what ssl_data4 should return. rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv); + ASSERT_EQ(ERR_SSL_PROTOCOL_ERROR, rv); // Ensure that the client certificate is removed from the cache on a // handshake failure. @@ -11338,35 +11319,35 @@ // [ssl_]data[1-3]. Rather than represending the endpoint // (www.example.com:443), they represent failures with the HTTPS proxy // (proxy:70). - SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED); + SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); ssl_data1.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); - net::StaticSocketDataProvider data1(NULL, 0, NULL, 0); + StaticSocketDataProvider data1(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data1); - SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); + SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); ssl_data2.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); - net::StaticSocketDataProvider data2(NULL, 0, NULL, 0); + StaticSocketDataProvider data2(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data2); // TODO(wtc): find out why this unit test doesn't need [ssl_]data3. #if 0 - SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR); + SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR); ssl_data3.cert_request_info = cert_request.get(); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); - net::StaticSocketDataProvider data3(NULL, 0, NULL, 0); + StaticSocketDataProvider data3(NULL, 0, NULL, 0); session_deps_.socket_factory->AddSocketDataProvider(&data3); #endif - net::HttpRequestInfo requests[2]; + HttpRequestInfo requests[2]; requests[0].url = GURL("https://www.example.com/"); requests[0].method = "GET"; - requests[0].load_flags = net::LOAD_NORMAL; + requests[0].load_flags = LOAD_NORMAL; requests[1].url = GURL("http://www.example.com/"); requests[1].method = "GET"; - requests[1].load_flags = net::LOAD_NORMAL; + requests[1].load_flags = LOAD_NORMAL; for (size_t i = 0; i < arraysize(requests); ++i) { session_deps_.socket_factory->ResetNextMockIndexes(); @@ -11376,21 +11357,20 @@ // Begin the SSL handshake with the proxy. TestCompletionCallback callback; - int rv = trans->Start( - &requests[i], callback.callback(), net::BoundNetLog()); - ASSERT_EQ(net::ERR_IO_PENDING, rv); + int rv = trans->Start(&requests[i], callback.callback(), BoundNetLog()); + ASSERT_EQ(ERR_IO_PENDING, rv); // Complete the SSL handshake, which should abort due to requiring a // client certificate. rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); + ASSERT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv); // Indicate that no certificate should be supplied. From the perspective // of SSLClientCertCache, NULL is just as meaningful as a real // certificate, so this is the same as supply a // legitimate-but-unacceptable certificate. rv = trans->RestartWithCertificate(NULL, callback.callback()); - ASSERT_EQ(net::ERR_IO_PENDING, rv); + ASSERT_EQ(ERR_IO_PENDING, rv); // Ensure the certificate was added to the client auth cache before // allowing the connection to continue restarting. @@ -11407,7 +11387,7 @@ // then consume ssl_data3, which should also fail. The result code is // checked against what ssl_data3 should return. rv = callback.WaitForResult(); - ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv); + ASSERT_EQ(ERR_PROXY_CONNECTION_FAILED, rv); // Now that the new handshake has failed, ensure that the client // certificate was removed from the client auth cache. @@ -11625,7 +11605,7 @@ EXPECT_EQ("hello!", response_data); } -class OneTimeCachingHostResolver : public net::HostResolver { +class OneTimeCachingHostResolver : public HostResolver { public: explicit OneTimeCachingHostResolver(const HostPortPair& host_port) : host_port_(host_port) {} @@ -13202,8 +13182,8 @@ // Preconnect an SSL socket. A preconnect is needed because connect jobs are // cancelled when a normal transaction is cancelled. - net::HttpStreamFactory* http_stream_factory = session->http_stream_factory(); - net::SSLConfig ssl_config; + HttpStreamFactory* http_stream_factory = session->http_stream_factory(); + SSLConfig ssl_config; session->ssl_config_service()->GetSSLConfig(&ssl_config); http_stream_factory->PreconnectStreams(1, ssl_request, DEFAULT_PRIORITY, ssl_config, ssl_config);
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc index ff5fdf9f..9b9c382 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc
@@ -259,8 +259,8 @@ SSLClientSocket* ssl = static_cast<SSLClientSocket*>(transport_socket_handle_->socket()); - using_spdy_ = ssl->was_spdy_negotiated(); protocol_negotiated_ = ssl->GetNegotiatedProtocol(); + using_spdy_ = NextProtoIsSPDY(protocol_negotiated_); // Reset the timer to just the length of time allowed for HttpProxy handshake // so that a fast SSL connection plus a slow HttpProxy failure doesn't take
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index 2dd9bae..fffb897f 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -120,8 +120,8 @@ const ProxyInfo& proxy_info, HttpRequestHeaders* headers) override {} - void OnBeforeTunnelRequest(const net::HostPortPair& proxy_server, - net::HttpRequestHeaders* extra_headers) override { + void OnBeforeTunnelRequest(const HostPortPair& proxy_server, + HttpRequestHeaders* extra_headers) override { on_before_tunnel_request_called_ = true; if (extra_headers) { extra_headers->SetHeader("Foo", proxy_server.ToString()); @@ -129,9 +129,9 @@ } void OnTunnelHeadersReceived( - const net::HostPortPair& origin, - const net::HostPortPair& proxy_server, - const net::HttpResponseHeaders& response_headers) override { + const HostPortPair& origin, + const HostPortPair& proxy_server, + const HttpResponseHeaders& response_headers) override { on_tunnel_headers_received_called_ = true; on_tunnel_headers_received_origin_ = origin; on_tunnel_headers_received_proxy_server_ = proxy_server;
diff --git a/net/http/http_response_headers_unittest.cc b/net/http/http_response_headers_unittest.cc index 81bd5a3..c3aff96e 100644 --- a/net/http/http_response_headers_unittest.cc +++ b/net/http/http_response_headers_unittest.cc
@@ -15,14 +15,16 @@ #include "net/http/http_response_headers.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + namespace { struct TestData { const char* raw_headers; const char* expected_headers; int expected_response_code; - net::HttpVersion expected_parsed_version; - net::HttpVersion expected_version; + HttpVersion expected_parsed_version; + HttpVersion expected_version; }; class HttpResponseHeadersTest : public testing::Test { @@ -50,10 +52,10 @@ raw_headers += cache_control; raw_headers += "\n"; HeadersToRaw(&raw_headers); - headers_ = new net::HttpResponseHeaders(raw_headers); + headers_ = new HttpResponseHeaders(raw_headers); } - const scoped_refptr<net::HttpResponseHeaders>& headers() { return headers_; } + const scoped_refptr<HttpResponseHeaders>& headers() { return headers_; } // Return a pointer to a TimeDelta object. For use when the value doesn't // matter. @@ -79,7 +81,7 @@ } private: - scoped_refptr<net::HttpResponseHeaders> headers_; + scoped_refptr<HttpResponseHeaders> headers_; TimeDelta delta_; }; @@ -96,8 +98,8 @@ std::string expected_headers(test.expected_headers); std::string headers; - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(raw_headers)); + scoped_refptr<HttpResponseHeaders> parsed( + new HttpResponseHeaders(raw_headers)); parsed->GetNormalizedHeaders(&headers); // Transform to readable output format (so it's easier to see diffs). @@ -115,193 +117,167 @@ } TestData response_headers_tests[] = { - { - // Normalise whitespace. + {// Normalise whitespace. - "HTTP/1.1 202 Accepted \n" - "Content-TYPE : text/html; charset=utf-8 \n" - "Set-Cookie: a \n" - "Set-Cookie: b \n", + "HTTP/1.1 202 Accepted \n" + "Content-TYPE : text/html; charset=utf-8 \n" + "Set-Cookie: a \n" + "Set-Cookie: b \n", - "HTTP/1.1 202 Accepted\n" - "Content-TYPE: text/html; charset=utf-8\n" - "Set-Cookie: a, b\n", + "HTTP/1.1 202 Accepted\n" + "Content-TYPE: text/html; charset=utf-8\n" + "Set-Cookie: a, b\n", - 202, - net::HttpVersion(1,1), - net::HttpVersion(1,1) - }, - { - // Normalize leading whitespace. + 202, + HttpVersion(1, 1), + HttpVersion(1, 1)}, + {// Normalize leading whitespace. - "HTTP/1.1 202 Accepted \n" - // Starts with space -- will be skipped as invalid. - " Content-TYPE : text/html; charset=utf-8 \n" - "Set-Cookie: a \n" - "Set-Cookie: b \n", + "HTTP/1.1 202 Accepted \n" + // Starts with space -- will be skipped as invalid. + " Content-TYPE : text/html; charset=utf-8 \n" + "Set-Cookie: a \n" + "Set-Cookie: b \n", - "HTTP/1.1 202 Accepted\n" - "Set-Cookie: a, b\n", + "HTTP/1.1 202 Accepted\n" + "Set-Cookie: a, b\n", - 202, - net::HttpVersion(1,1), - net::HttpVersion(1,1) - }, - { - // Normalize blank headers. + 202, + HttpVersion(1, 1), + HttpVersion(1, 1)}, + {// Normalize blank headers. - "HTTP/1.1 200 OK\n" - "Header1 : \n" - "Header2: \n" - "Header3:\n" - "Header4\n" - "Header5 :\n", + "HTTP/1.1 200 OK\n" + "Header1 : \n" + "Header2: \n" + "Header3:\n" + "Header4\n" + "Header5 :\n", - "HTTP/1.1 200 OK\n" - "Header1: \n" - "Header2: \n" - "Header3: \n" - "Header5: \n", + "HTTP/1.1 200 OK\n" + "Header1: \n" + "Header2: \n" + "Header3: \n" + "Header5: \n", - 200, - net::HttpVersion(1,1), - net::HttpVersion(1,1) - }, - { - // Don't believe the http/0.9 version if there are headers! + 200, + HttpVersion(1, 1), + HttpVersion(1, 1)}, + {// Don't believe the http/0.9 version if there are headers! - "hTtP/0.9 201\n" - "Content-TYPE: text/html; charset=utf-8\n", + "hTtP/0.9 201\n" + "Content-TYPE: text/html; charset=utf-8\n", - "HTTP/1.0 201 OK\n" - "Content-TYPE: text/html; charset=utf-8\n", + "HTTP/1.0 201 OK\n" + "Content-TYPE: text/html; charset=utf-8\n", - 201, - net::HttpVersion(0,9), - net::HttpVersion(1,0) - }, - { - // Accept the HTTP/0.9 version number if there are no headers. - // This is how HTTP/0.9 responses get constructed from - // HttpNetworkTransaction. + 201, + HttpVersion(0, 9), + HttpVersion(1, 0)}, + {// Accept the HTTP/0.9 version number if there are no headers. + // This is how HTTP/0.9 responses get constructed from + // HttpNetworkTransaction. - "hTtP/0.9 200 OK\n", + "hTtP/0.9 200 OK\n", - "HTTP/0.9 200 OK\n", + "HTTP/0.9 200 OK\n", - 200, - net::HttpVersion(0,9), - net::HttpVersion(0,9) - }, - { - // Add missing OK. + 200, + HttpVersion(0, 9), + HttpVersion(0, 9)}, + {// Add missing OK. - "HTTP/1.1 201\n" - "Content-TYPE: text/html; charset=utf-8\n", + "HTTP/1.1 201\n" + "Content-TYPE: text/html; charset=utf-8\n", - "HTTP/1.1 201 OK\n" - "Content-TYPE: text/html; charset=utf-8\n", + "HTTP/1.1 201 OK\n" + "Content-TYPE: text/html; charset=utf-8\n", - 201, - net::HttpVersion(1,1), - net::HttpVersion(1,1) - }, - { - // Normalize bad status line. + 201, + HttpVersion(1, 1), + HttpVersion(1, 1)}, + {// Normalize bad status line. - "SCREWED_UP_STATUS_LINE\n" - "Content-TYPE: text/html; charset=utf-8\n", + "SCREWED_UP_STATUS_LINE\n" + "Content-TYPE: text/html; charset=utf-8\n", - "HTTP/1.0 200 OK\n" - "Content-TYPE: text/html; charset=utf-8\n", + "HTTP/1.0 200 OK\n" + "Content-TYPE: text/html; charset=utf-8\n", - 200, - net::HttpVersion(0,0), // Parse error. - net::HttpVersion(1,0) - }, - { - // Normalize invalid status code. + 200, + HttpVersion(0, 0), // Parse error. + HttpVersion(1, 0)}, + {// Normalize invalid status code. - "HTTP/1.1 -1 Unknown\n", + "HTTP/1.1 -1 Unknown\n", - "HTTP/1.1 200 OK\n", + "HTTP/1.1 200 OK\n", - 200, - net::HttpVersion(1,1), - net::HttpVersion(1,1) - }, - { - // Normalize empty header. + 200, + HttpVersion(1, 1), + HttpVersion(1, 1)}, + {// Normalize empty header. - "", + "", - "HTTP/1.0 200 OK\n", + "HTTP/1.0 200 OK\n", - 200, - net::HttpVersion(0,0), // Parse Error. - net::HttpVersion(1,0) - }, - { - // Normalize headers that start with a colon. + 200, + HttpVersion(0, 0), // Parse Error. + HttpVersion(1, 0)}, + {// Normalize headers that start with a colon. - "HTTP/1.1 202 Accepted \n" - "foo: bar\n" - ": a \n" - " : b\n" - "baz: blat \n", + "HTTP/1.1 202 Accepted \n" + "foo: bar\n" + ": a \n" + " : b\n" + "baz: blat \n", - "HTTP/1.1 202 Accepted\n" - "foo: bar\n" - "baz: blat\n", + "HTTP/1.1 202 Accepted\n" + "foo: bar\n" + "baz: blat\n", - 202, - net::HttpVersion(1,1), - net::HttpVersion(1,1) - }, - { - // Normalize headers that end with a colon. + 202, + HttpVersion(1, 1), + HttpVersion(1, 1)}, + {// Normalize headers that end with a colon. - "HTTP/1.1 202 Accepted \n" - "foo: \n" - "bar:\n" - "baz: blat \n" - "zip:\n", + "HTTP/1.1 202 Accepted \n" + "foo: \n" + "bar:\n" + "baz: blat \n" + "zip:\n", - "HTTP/1.1 202 Accepted\n" - "foo: \n" - "bar: \n" - "baz: blat\n" - "zip: \n", + "HTTP/1.1 202 Accepted\n" + "foo: \n" + "bar: \n" + "baz: blat\n" + "zip: \n", - 202, - net::HttpVersion(1,1), - net::HttpVersion(1,1) - }, - { - // Normalize whitespace headers. + 202, + HttpVersion(1, 1), + HttpVersion(1, 1)}, + {// Normalize whitespace headers. - "\n \n", + "\n \n", - "HTTP/1.0 200 OK\n", + "HTTP/1.0 200 OK\n", - 200, - net::HttpVersion(0,0), // Parse error. - net::HttpVersion(1,0) - }, - { - // Consolidate Set-Cookie headers. + 200, + HttpVersion(0, 0), // Parse error. + HttpVersion(1, 0)}, + {// Consolidate Set-Cookie headers. - "HTTP/1.1 200 OK\n" - "Set-Cookie: x=1\n" - "Set-Cookie: y=2\n", + "HTTP/1.1 200 OK\n" + "Set-Cookie: x=1\n" + "Set-Cookie: y=2\n", - "HTTP/1.1 200 OK\n" - "Set-Cookie: x=1, y=2\n", + "HTTP/1.1 200 OK\n" + "Set-Cookie: x=1, y=2\n", - 200, - net::HttpVersion(1,1), - net::HttpVersion(1,1) - }, + 200, + HttpVersion(1, 1), + HttpVersion(1, 1)}, }; INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, @@ -314,8 +290,7 @@ "Cache-control: private\n" "cache-Control: no-store\n"; HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); std::string value; EXPECT_TRUE(parsed->GetNormalizedHeader("cache-control", &value)); @@ -323,7 +298,7 @@ } struct PersistData { - net::HttpResponseHeaders::PersistOptions options; + HttpResponseHeaders::PersistOptions options; const char* raw_headers; const char* expected_headers; }; @@ -338,15 +313,13 @@ std::string headers = test.raw_headers; HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed1( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed1(new HttpResponseHeaders(headers)); Pickle pickle; parsed1->Persist(&pickle, test.options); PickleIterator iter(pickle); - scoped_refptr<net::HttpResponseHeaders> parsed2( - new net::HttpResponseHeaders(&iter)); + scoped_refptr<HttpResponseHeaders> parsed2(new HttpResponseHeaders(&iter)); std::string h2; parsed2->GetNormalizedHeaders(&h2); @@ -354,167 +327,151 @@ } const struct PersistData persistence_tests[] = { - { net::HttpResponseHeaders::PERSIST_ALL, - "HTTP/1.1 200 OK\n" - "Cache-control:private\n" - "cache-Control:no-store\n", + {HttpResponseHeaders::PERSIST_ALL, + "HTTP/1.1 200 OK\n" + "Cache-control:private\n" + "cache-Control:no-store\n", - "HTTP/1.1 200 OK\n" - "Cache-control: private, no-store\n" - }, - { net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP, - "HTTP/1.1 200 OK\n" - "connection: keep-alive\n" - "server: blah\n", + "HTTP/1.1 200 OK\n" + "Cache-control: private, no-store\n"}, + {HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP, + "HTTP/1.1 200 OK\n" + "connection: keep-alive\n" + "server: blah\n", - "HTTP/1.1 200 OK\n" - "server: blah\n" - }, - { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE | - net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP, - "HTTP/1.1 200 OK\n" - "fOo: 1\n" - "Foo: 2\n" - "Transfer-Encoding: chunked\n" - "CoNnection: keep-alive\n" - "cache-control: private, no-cache=\"foo\"\n", + "HTTP/1.1 200 OK\n" + "server: blah\n"}, + {HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE | + HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP, + "HTTP/1.1 200 OK\n" + "fOo: 1\n" + "Foo: 2\n" + "Transfer-Encoding: chunked\n" + "CoNnection: keep-alive\n" + "cache-control: private, no-cache=\"foo\"\n", - "HTTP/1.1 200 OK\n" - "cache-control: private, no-cache=\"foo\"\n" - }, - { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private,no-cache=\"foo, bar\"\n" - "bar", + "HTTP/1.1 200 OK\n" + "cache-control: private, no-cache=\"foo\"\n"}, + {HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private,no-cache=\"foo, bar\"\n" + "bar", - "HTTP/1.1 200 OK\n" - "Cache-Control: private,no-cache=\"foo, bar\"\n" - }, - // Ignore bogus no-cache value. - { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private,no-cache=foo\n", + "HTTP/1.1 200 OK\n" + "Cache-Control: private,no-cache=\"foo, bar\"\n"}, + // Ignore bogus no-cache value. + {HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private,no-cache=foo\n", - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private,no-cache=foo\n" - }, - // Ignore bogus no-cache value. - { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\n", + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private,no-cache=foo\n"}, + // Ignore bogus no-cache value. + {HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\n", - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\n" - }, - // Ignore empty no-cache value. - { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\"\"\n", + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\n"}, + // Ignore empty no-cache value. + {HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\"\"\n", - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\"\"\n" - }, - // Ignore wrong quotes no-cache value. - { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\'foo\'\n", + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\"\"\n"}, + // Ignore wrong quotes no-cache value. + {HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\'foo\'\n", - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\'foo\'\n" - }, - // Ignore unterminated quotes no-cache value. - { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\"foo\n", + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\'foo\'\n"}, + // Ignore unterminated quotes no-cache value. + {HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\"foo\n", - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\"foo\n" - }, - // Accept sloppy LWS. - { net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, - "HTTP/1.1 200 OK\n" - "Foo: 2\n" - "Cache-Control: private, no-cache=\" foo\t, bar\"\n", + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\"foo\n"}, + // Accept sloppy LWS. + {HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE, + "HTTP/1.1 200 OK\n" + "Foo: 2\n" + "Cache-Control: private, no-cache=\" foo\t, bar\"\n", - "HTTP/1.1 200 OK\n" - "Cache-Control: private, no-cache=\" foo\t, bar\"\n" - }, - // Header name appears twice, separated by another header. - { net::HttpResponseHeaders::PERSIST_ALL, - "HTTP/1.1 200 OK\n" - "Foo: 1\n" - "Bar: 2\n" - "Foo: 3\n", + "HTTP/1.1 200 OK\n" + "Cache-Control: private, no-cache=\" foo\t, bar\"\n"}, + // Header name appears twice, separated by another header. + {HttpResponseHeaders::PERSIST_ALL, + "HTTP/1.1 200 OK\n" + "Foo: 1\n" + "Bar: 2\n" + "Foo: 3\n", - "HTTP/1.1 200 OK\n" - "Foo: 1, 3\n" - "Bar: 2\n" - }, - // Header name appears twice, separated by another header (type 2). - { net::HttpResponseHeaders::PERSIST_ALL, - "HTTP/1.1 200 OK\n" - "Foo: 1, 3\n" - "Bar: 2\n" - "Foo: 4\n", + "HTTP/1.1 200 OK\n" + "Foo: 1, 3\n" + "Bar: 2\n"}, + // Header name appears twice, separated by another header (type 2). + {HttpResponseHeaders::PERSIST_ALL, + "HTTP/1.1 200 OK\n" + "Foo: 1, 3\n" + "Bar: 2\n" + "Foo: 4\n", - "HTTP/1.1 200 OK\n" - "Foo: 1, 3, 4\n" - "Bar: 2\n" - }, - // Test filtering of cookie headers. - { net::HttpResponseHeaders::PERSIST_SANS_COOKIES, - "HTTP/1.1 200 OK\n" - "Set-Cookie: foo=bar; httponly\n" - "Set-Cookie: bar=foo\n" - "Bar: 1\n" - "Set-Cookie2: bar2=foo2\n", + "HTTP/1.1 200 OK\n" + "Foo: 1, 3, 4\n" + "Bar: 2\n"}, + // Test filtering of cookie headers. + {HttpResponseHeaders::PERSIST_SANS_COOKIES, + "HTTP/1.1 200 OK\n" + "Set-Cookie: foo=bar; httponly\n" + "Set-Cookie: bar=foo\n" + "Bar: 1\n" + "Set-Cookie2: bar2=foo2\n", - "HTTP/1.1 200 OK\n" - "Bar: 1\n" - }, - // Test LWS at the end of a header. - { net::HttpResponseHeaders::PERSIST_ALL, - "HTTP/1.1 200 OK\n" - "Content-Length: 450 \n" - "Content-Encoding: gzip\n", + "HTTP/1.1 200 OK\n" + "Bar: 1\n"}, + // Test LWS at the end of a header. + {HttpResponseHeaders::PERSIST_ALL, + "HTTP/1.1 200 OK\n" + "Content-Length: 450 \n" + "Content-Encoding: gzip\n", - "HTTP/1.1 200 OK\n" - "Content-Length: 450\n" - "Content-Encoding: gzip\n" - }, - // Test LWS at the end of a header. - { net::HttpResponseHeaders::PERSIST_RAW, - "HTTP/1.1 200 OK\n" - "Content-Length: 450 \n" - "Content-Encoding: gzip\n", + "HTTP/1.1 200 OK\n" + "Content-Length: 450\n" + "Content-Encoding: gzip\n"}, + // Test LWS at the end of a header. + {HttpResponseHeaders::PERSIST_RAW, + "HTTP/1.1 200 OK\n" + "Content-Length: 450 \n" + "Content-Encoding: gzip\n", - "HTTP/1.1 200 OK\n" - "Content-Length: 450\n" - "Content-Encoding: gzip\n" - }, - // Test filtering of transport security state headers. - { net::HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE, - "HTTP/1.1 200 OK\n" - "Strict-Transport-Security: max-age=1576800\n" - "Bar: 1\n" - "Public-Key-Pins: max-age=100000; " - "pin-sha1=\"ObT42aoSpAqWdY9WfRfL7i0HsVk=\";" - "pin-sha1=\"7kW49EVwZG0hSNx41ZO/fUPN0ek=\"", + "HTTP/1.1 200 OK\n" + "Content-Length: 450\n" + "Content-Encoding: gzip\n"}, + // Test filtering of transport security state headers. + {HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE, + "HTTP/1.1 200 OK\n" + "Strict-Transport-Security: max-age=1576800\n" + "Bar: 1\n" + "Public-Key-Pins: max-age=100000; " + "pin-sha1=\"ObT42aoSpAqWdY9WfRfL7i0HsVk=\";" + "pin-sha1=\"7kW49EVwZG0hSNx41ZO/fUPN0ek=\"", - "HTTP/1.1 200 OK\n" - "Bar: 1\n" - }, + "HTTP/1.1 200 OK\n" + "Bar: 1\n"}, }; INSTANTIATE_TEST_CASE_P(HttpResponseHeaders, @@ -529,8 +486,7 @@ "Cache-control:private , no-cache=\"set-cookie,server\" \n" "cache-Control: no-store\n"; HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); void* iter = NULL; std::string value; @@ -551,8 +507,7 @@ "WWW-Authenticate:Digest realm=foobar, nonce=x, domain=y\n" "WWW-Authenticate:Basic realm=quatar\n"; HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); void* iter = NULL; std::string value; @@ -571,8 +526,7 @@ "Date: Tue, 07 Aug 2007 23:10:55 GMT\n" "Last-Modified: Wed, 01 Aug 2007 23:23:45 GMT\n"; HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); std::string value; EXPECT_TRUE(parsed->EnumerateHeader(NULL, "date", &value)); @@ -590,8 +544,7 @@ "Last-Modified: Tue, 07 Aug 2007 19:10:55 EDT\n" "Expires: Tue, 07 Aug 2007 23:10:55 UTC\n"; HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); base::Time expected_value; ASSERT_TRUE(base::Time::FromString("Tue, 07 Aug 2007 23:10:55 GMT", &expected_value)); @@ -630,8 +583,7 @@ std::string headers(test.raw_headers); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); std::string value; EXPECT_EQ(test.has_mimetype, parsed->GetMimeType(&value)); @@ -778,11 +730,6 @@ ContentTypeTest, testing::ValuesIn(mimetype_tests)); -using net::ValidationType; -using net::VALIDATION_NONE; -using net::VALIDATION_SYNCHRONOUS; -using net::VALIDATION_ASYNCHRONOUS; - struct RequiresValidationTestData { const char* headers; ValidationType validation_type; @@ -803,8 +750,7 @@ std::string headers(test.headers); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); ValidationType validation_type = parsed->RequiresValidation(request_time, response_time, current_time); @@ -1021,13 +967,13 @@ std::string orig_headers(test.orig_headers); HeadersToRaw(&orig_headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(orig_headers)); + scoped_refptr<HttpResponseHeaders> parsed( + new HttpResponseHeaders(orig_headers)); std::string new_headers(test.new_headers); HeadersToRaw(&new_headers); - scoped_refptr<net::HttpResponseHeaders> new_parsed( - new net::HttpResponseHeaders(new_headers)); + scoped_refptr<HttpResponseHeaders> new_parsed( + new HttpResponseHeaders(new_headers)); parsed->Update(*new_parsed.get()); @@ -1136,8 +1082,7 @@ std::string headers(test.headers); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); std::string name, value, lines; @@ -1196,8 +1141,7 @@ std::string headers(test.headers); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); std::string location; EXPECT_EQ(parsed->IsRedirect(&location), test.is_redirect); @@ -1283,8 +1227,7 @@ std::string headers(test.headers); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); EXPECT_EQ(test.expected_len, parsed->GetContentLength()); } @@ -1382,8 +1325,7 @@ std::string headers(test.headers); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); int64 first_byte_position; int64 last_byte_position; @@ -1659,8 +1601,7 @@ std::string headers(test.headers); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); EXPECT_EQ(test.expected_keep_alive, parsed->IsKeepAlive()); } @@ -1820,8 +1761,7 @@ std::string headers(test.headers); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); EXPECT_EQ(test.expected_result, parsed->HasStrongValidators()); } @@ -1879,16 +1819,14 @@ TEST(HttpResponseHeadersTest, GetStatusText) { std::string headers("HTTP/1.1 404 Not Found"); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); EXPECT_EQ(std::string("Not Found"), parsed->GetStatusText()); } TEST(HttpResponseHeadersTest, GetStatusTextMissing) { std::string headers("HTTP/1.1 404"); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); // Since the status line gets normalized, we have OK. EXPECT_EQ(std::string("OK"), parsed->GetStatusText()); } @@ -1896,16 +1834,14 @@ TEST(HttpResponseHeadersTest, GetStatusTextMultiSpace) { std::string headers("HTTP/1.0 404 Not Found"); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); EXPECT_EQ(std::string("Not Found"), parsed->GetStatusText()); } TEST(HttpResponseHeadersTest, GetStatusBadStatusLine) { std::string headers("Foo bar."); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); // The bad status line would have gotten rewritten as // HTTP/1.0 200 OK. EXPECT_EQ(std::string("OK"), parsed->GetStatusText()); @@ -1927,8 +1863,8 @@ std::string orig_headers(test.orig_headers); HeadersToRaw(&orig_headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(orig_headers)); + scoped_refptr<HttpResponseHeaders> parsed( + new HttpResponseHeaders(orig_headers)); std::string new_header(test.new_header); parsed->AddHeader(new_header); @@ -1983,8 +1919,8 @@ std::string orig_headers(test.orig_headers); HeadersToRaw(&orig_headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(orig_headers)); + scoped_refptr<HttpResponseHeaders> parsed( + new HttpResponseHeaders(orig_headers)); std::string name(test.to_remove); parsed->RemoveHeader(name); @@ -2040,8 +1976,8 @@ std::string orig_headers(test.orig_headers); HeadersToRaw(&orig_headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(orig_headers)); + scoped_refptr<HttpResponseHeaders> parsed( + new HttpResponseHeaders(orig_headers)); std::string name(test.to_remove_name); std::string value(test.to_remove_value); @@ -2144,8 +2080,8 @@ std::string orig_headers(test.orig_headers); HeadersToRaw(&orig_headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(orig_headers)); + scoped_refptr<HttpResponseHeaders> parsed( + new HttpResponseHeaders(orig_headers)); std::string name(test.new_status); parsed->ReplaceStatusLine(name); @@ -2208,12 +2144,12 @@ TEST_P(UpdateWithNewRangeTest, UpdateWithNewRange) { const UpdateWithNewRangeTestData test = GetParam(); - const net::HttpByteRange range = net::HttpByteRange::Bounded(3, 5); + const HttpByteRange range = HttpByteRange::Bounded(3, 5); std::string orig_headers(test.orig_headers); std::replace(orig_headers.begin(), orig_headers.end(), '\n', '\0'); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(orig_headers + '\0')); + scoped_refptr<HttpResponseHeaders> parsed( + new HttpResponseHeaders(orig_headers + '\0')); int64 content_size = parsed->GetContentLength(); std::string resulting_headers; @@ -2263,15 +2199,14 @@ "Content-Length: 450\n" "Connection: keep-alive\n"); HeadersToRaw(&headers); - scoped_refptr<net::HttpResponseHeaders> parsed( - new net::HttpResponseHeaders(headers)); + scoped_refptr<HttpResponseHeaders> parsed(new HttpResponseHeaders(headers)); scoped_ptr<base::Value> event_param(parsed->NetLogCallback( - net::NetLogCaptureMode::IncludeCookiesAndCredentials())); - scoped_refptr<net::HttpResponseHeaders> recreated; + NetLogCaptureMode::IncludeCookiesAndCredentials())); + scoped_refptr<HttpResponseHeaders> recreated; - ASSERT_TRUE(net::HttpResponseHeaders::FromNetLogParam(event_param.get(), - &recreated)); + ASSERT_TRUE( + HttpResponseHeaders::FromNetLogParam(event_param.get(), &recreated)); ASSERT_TRUE(recreated.get()); EXPECT_EQ(parsed->GetHttpVersion(), recreated->GetHttpVersion()); EXPECT_EQ(parsed->response_code(), recreated->response_code()); @@ -2396,4 +2331,6 @@ EXPECT_EQ(TimeDelta::FromSeconds(1), GetStaleWhileRevalidateValue()); } -} // end namespace +} // namespace + +} // namespace net
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc index eb4b3c5..ba118ac6 100644 --- a/net/http/http_response_info.cc +++ b/net/http/http_response_info.cc
@@ -324,17 +324,16 @@ pickle->WriteInt64(request_time.ToInternalValue()); pickle->WriteInt64(response_time.ToInternalValue()); - net::HttpResponseHeaders::PersistOptions persist_options = - net::HttpResponseHeaders::PERSIST_RAW; + HttpResponseHeaders::PersistOptions persist_options = + HttpResponseHeaders::PERSIST_RAW; if (skip_transient_headers) { - persist_options = - net::HttpResponseHeaders::PERSIST_SANS_COOKIES | - net::HttpResponseHeaders::PERSIST_SANS_CHALLENGES | - net::HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP | - net::HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE | - net::HttpResponseHeaders::PERSIST_SANS_RANGES | - net::HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE; + persist_options = HttpResponseHeaders::PERSIST_SANS_COOKIES | + HttpResponseHeaders::PERSIST_SANS_CHALLENGES | + HttpResponseHeaders::PERSIST_SANS_HOP_BY_HOP | + HttpResponseHeaders::PERSIST_SANS_NON_CACHEABLE | + HttpResponseHeaders::PERSIST_SANS_RANGES | + HttpResponseHeaders::PERSIST_SANS_SECURITY_STATE; } headers->Persist(pickle, persist_options);
diff --git a/net/http/http_response_info_unittest.cc b/net/http/http_response_info_unittest.cc index 07e4b6de..b0f91557 100644 --- a/net/http/http_response_info_unittest.cc +++ b/net/http/http_response_info_unittest.cc
@@ -8,21 +8,25 @@ #include "net/http/http_response_headers.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + +namespace { + class HttpResponseInfoTest : public testing::Test { protected: void SetUp() override { - response_info_.headers = new net::HttpResponseHeaders(""); + response_info_.headers = new HttpResponseHeaders(""); } - void PickleAndRestore(const net::HttpResponseInfo& response_info, - net::HttpResponseInfo* restored_response_info) const { + void PickleAndRestore(const HttpResponseInfo& response_info, + HttpResponseInfo* restored_response_info) const { Pickle pickle; response_info.Persist(&pickle, false, false); bool truncated = false; restored_response_info->InitFromPickle(pickle, &truncated); } - net::HttpResponseInfo response_info_; + HttpResponseInfo response_info_; }; TEST_F(HttpResponseInfoTest, UnusedSincePrefetchDefault) { @@ -31,19 +35,23 @@ TEST_F(HttpResponseInfoTest, UnusedSincePrefetchCopy) { response_info_.unused_since_prefetch = true; - net::HttpResponseInfo response_info_clone(response_info_); + HttpResponseInfo response_info_clone(response_info_); EXPECT_TRUE(response_info_clone.unused_since_prefetch); } TEST_F(HttpResponseInfoTest, UnusedSincePrefetchPersistFalse) { - net::HttpResponseInfo restored_response_info; + HttpResponseInfo restored_response_info; PickleAndRestore(response_info_, &restored_response_info); EXPECT_FALSE(restored_response_info.unused_since_prefetch); } TEST_F(HttpResponseInfoTest, UnusedSincePrefetchPersistTrue) { response_info_.unused_since_prefetch = true; - net::HttpResponseInfo restored_response_info; + HttpResponseInfo restored_response_info; PickleAndRestore(response_info_, &restored_response_info); EXPECT_TRUE(restored_response_info.unused_since_prefetch); } + +} // namespace + +} // namespace net
diff --git a/net/http/http_server_properties.h b/net/http/http_server_properties.h index 367d059..d3825ae 100644 --- a/net/http/http_server_properties.h +++ b/net/http/http_server_properties.h
@@ -279,8 +279,7 @@ // to |threshold| will be honored. |threshold| must be between 0.0 and 1.0 // inclusive. Hence, a threshold of 0.0 implies that all advertisements will // be honored. - virtual void SetAlternateProtocolProbabilityThreshold( - double threshold) = 0; + virtual void SetAlternativeServiceProbabilityThreshold(double threshold) = 0; // Gets a reference to the SettingsMap stored for a host. // If no settings are stored, returns an empty SettingsMap.
diff --git a/net/http/http_server_properties_impl.cc b/net/http/http_server_properties_impl.cc index 11d20f61..c42293ae 100644 --- a/net/http/http_server_properties_impl.cc +++ b/net/http/http_server_properties_impl.cc
@@ -27,7 +27,7 @@ alternative_service_map_(AlternativeServiceMap::NO_AUTO_EVICT), spdy_settings_map_(SpdySettingsMap::NO_AUTO_EVICT), server_network_stats_map_(ServerNetworkStatsMap::NO_AUTO_EVICT), - alternate_protocol_probability_threshold_(1), + alternative_service_probability_threshold_(1.0), weak_ptr_factory_(this) { canonical_suffixes_.push_back(".c.youtube.com"); canonical_suffixes_.push_back(".googlevideo.com"); @@ -185,7 +185,7 @@ } bool HttpServerPropertiesImpl::RequiresHTTP11( - const net::HostPortPair& host_port_pair) { + const HostPortPair& host_port_pair) { DCHECK(CalledOnValidThread()); if (host_port_pair.host().empty()) return false; @@ -194,7 +194,7 @@ } void HttpServerPropertiesImpl::SetHTTP11Required( - const net::HostPortPair& host_port_pair) { + const HostPortPair& host_port_pair) { DCHECK(CalledOnValidThread()); if (host_port_pair.host().empty()) return; @@ -227,7 +227,7 @@ AlternativeServiceMap::const_iterator it = alternative_service_map_.Get(origin); if (it != alternative_service_map_.end()) { - if (it->second.probability < alternate_protocol_probability_threshold_) { + if (it->second.probability < alternative_service_probability_threshold_) { return AlternativeService(); } AlternativeService alternative_service(it->second.alternative_service); @@ -245,7 +245,7 @@ if (it == alternative_service_map_.end()) { return AlternativeService(); } - if (it->second.probability < alternate_protocol_probability_threshold_) { + if (it->second.probability < alternative_service_probability_threshold_) { return AlternativeService(); } AlternativeService alternative_service(it->second.alternative_service); @@ -290,7 +290,7 @@ << alternative_service_info.ToString() << "."; } } else { - if (alternative_probability >= alternate_protocol_probability_threshold_) { + if (alternative_probability >= alternative_service_probability_threshold_) { // TODO(rch): Consider the case where multiple requests are started // before the first completes. In this case, only one of the jobs // would reach this code, whereas all of them should should have. @@ -506,9 +506,9 @@ return server_network_stats_map_; } -void HttpServerPropertiesImpl::SetAlternateProtocolProbabilityThreshold( +void HttpServerPropertiesImpl::SetAlternativeServiceProbabilityThreshold( double threshold) { - alternate_protocol_probability_threshold_ = threshold; + alternative_service_probability_threshold_ = threshold; } AlternativeServiceMap::const_iterator
diff --git a/net/http/http_server_properties_impl.h b/net/http/http_server_properties_impl.h index 67b91271..e9f576fd 100644 --- a/net/http/http_server_properties_impl.h +++ b/net/http/http_server_properties_impl.h
@@ -103,7 +103,7 @@ void ClearAlternativeService(const HostPortPair& origin) override; const AlternativeServiceMap& alternative_service_map() const override; base::Value* GetAlternativeServiceInfoAsValue() const override; - void SetAlternateProtocolProbabilityThreshold(double threshold) override; + void SetAlternativeServiceProbabilityThreshold(double threshold) override; const SettingsMap& GetSpdySettings( const HostPortPair& host_port_pair) override; bool SetSpdySetting(const HostPortPair& host_port_pair, @@ -170,7 +170,7 @@ // ".googlevideo.com", ".googleusercontent.com") of canonical hostnames. CanonicalSufficList canonical_suffixes_; - double alternate_protocol_probability_threshold_; + double alternative_service_probability_threshold_; base::WeakPtrFactory<HttpServerPropertiesImpl> weak_ptr_factory_;
diff --git a/net/http/http_server_properties_impl_unittest.cc b/net/http/http_server_properties_impl_unittest.cc index cce7d6c9..00a4da96 100644 --- a/net/http/http_server_properties_impl_unittest.cc +++ b/net/http/http_server_properties_impl_unittest.cc
@@ -265,7 +265,7 @@ } TEST_F(AlternateProtocolServerPropertiesTest, Probability) { - impl_.SetAlternateProtocolProbabilityThreshold(0.25); + impl_.SetAlternativeServiceProbabilityThreshold(0.25); HostPortPair test_host_port_pair("foo", 80); const AlternativeService alternative_service(NPN_SPDY_4, "foo", 443); @@ -281,7 +281,7 @@ } TEST_F(AlternateProtocolServerPropertiesTest, ProbabilityExcluded) { - impl_.SetAlternateProtocolProbabilityThreshold(0.75); + impl_.SetAlternativeServiceProbabilityThreshold(0.75); HostPortPair test_host_port_pair("foo", 80); const AlternativeService alternative_service(NPN_SPDY_4, "foo", 443); @@ -433,7 +433,7 @@ } TEST_F(AlternateProtocolServerPropertiesTest, CanonicalBelowThreshold) { - impl_.SetAlternateProtocolProbabilityThreshold(0.02); + impl_.SetAlternativeServiceProbabilityThreshold(0.02); HostPortPair test_host_port_pair("foo.c.youtube.com", 80); HostPortPair canonical_port_pair("bar.c.youtube.com", 80); @@ -445,7 +445,7 @@ } TEST_F(AlternateProtocolServerPropertiesTest, CanonicalAboveThreshold) { - impl_.SetAlternateProtocolProbabilityThreshold(0.02); + impl_.SetAlternativeServiceProbabilityThreshold(0.02); HostPortPair test_host_port_pair("foo.c.youtube.com", 80); HostPortPair canonical_port_pair("bar.c.youtube.com", 80);
diff --git a/net/http/http_server_properties_manager.cc b/net/http/http_server_properties_manager.cc index eb80a53e..88a8466 100644 --- a/net/http/http_server_properties_manager.cc +++ b/net/http/http_server_properties_manager.cc
@@ -254,10 +254,10 @@ return http_server_properties_impl_->GetAlternativeServiceInfoAsValue(); } -void HttpServerPropertiesManager::SetAlternateProtocolProbabilityThreshold( +void HttpServerPropertiesManager::SetAlternativeServiceProbabilityThreshold( double threshold) { DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); - http_server_properties_impl_->SetAlternateProtocolProbabilityThreshold( + http_server_properties_impl_->SetAlternativeServiceProbabilityThreshold( threshold); }
diff --git a/net/http/http_server_properties_manager.h b/net/http/http_server_properties_manager.h index db4c6335..406905d 100644 --- a/net/http/http_server_properties_manager.h +++ b/net/http/http_server_properties_manager.h
@@ -103,7 +103,7 @@ void ClearAlternativeService(const HostPortPair& origin) override; const AlternativeServiceMap& alternative_service_map() const override; base::Value* GetAlternativeServiceInfoAsValue() const override; - void SetAlternateProtocolProbabilityThreshold(double threshold) override; + void SetAlternativeServiceProbabilityThreshold(double threshold) override; const SettingsMap& GetSpdySettings( const HostPortPair& host_port_pair) override; bool SetSpdySetting(const HostPortPair& host_port_pair,
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index 5843d4c..847c5540 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc
@@ -948,9 +948,8 @@ if (ssl_started && (result == OK || IsCertificateError(result))) { if (using_quic_ && result == OK) { was_npn_negotiated_ = true; - NextProto protocol_negotiated = + protocol_negotiated_ = SSLClientSocket::NextProtoFromString("quic/1+spdy/3"); - protocol_negotiated_ = protocol_negotiated; } else { SSLClientSocket* ssl_socket = static_cast<SSLClientSocket*>(connection_->socket()); @@ -959,14 +958,12 @@ std::string proto; SSLClientSocket::NextProtoStatus status = ssl_socket->GetNextProto(&proto); - NextProto protocol_negotiated = - SSLClientSocket::NextProtoFromString(proto); - protocol_negotiated_ = protocol_negotiated; + protocol_negotiated_ = SSLClientSocket::NextProtoFromString(proto); net_log_.AddEvent( NetLog::TYPE_HTTP_STREAM_REQUEST_PROTO, base::Bind(&NetLogHttpStreamProtoCallback, status, &proto)); - if (ssl_socket->was_spdy_negotiated()) + if (NextProtoIsSPDY(protocol_negotiated_)) SwitchToSpdyMode(); } }
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc index f3bbf98..5951a5c 100644 --- a/net/http/http_transaction_test_util.cc +++ b/net/http/http_transaction_test_util.cc
@@ -21,6 +21,8 @@ #include "net/http/http_transaction.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + namespace { typedef base::hash_map<std::string, const MockTransaction*> MockTransactionMap; static MockTransactionMap mock_transactions; @@ -30,86 +32,81 @@ // mock transaction data const MockTransaction kSimpleGET_Transaction = { - "http://www.google.com/", - "GET", - base::Time(), - "", - net::LOAD_NORMAL, - "HTTP/1.1 200 OK", - "Cache-Control: max-age=10000\n", - base::Time(), - "<html><body>Google Blah Blah</body></html>", - TEST_MODE_NORMAL, - NULL, - 0, - net::OK -}; + "http://www.google.com/", + "GET", + base::Time(), + "", + LOAD_NORMAL, + "HTTP/1.1 200 OK", + "Cache-Control: max-age=10000\n", + base::Time(), + "<html><body>Google Blah Blah</body></html>", + TEST_MODE_NORMAL, + NULL, + 0, + OK}; const MockTransaction kSimplePOST_Transaction = { - "http://bugdatabase.com/edit", - "POST", - base::Time(), - "", - net::LOAD_NORMAL, - "HTTP/1.1 200 OK", - "", - base::Time(), - "<html><body>Google Blah Blah</body></html>", - TEST_MODE_NORMAL, - NULL, - 0, - net::OK -}; + "http://bugdatabase.com/edit", + "POST", + base::Time(), + "", + LOAD_NORMAL, + "HTTP/1.1 200 OK", + "", + base::Time(), + "<html><body>Google Blah Blah</body></html>", + TEST_MODE_NORMAL, + NULL, + 0, + OK}; const MockTransaction kTypicalGET_Transaction = { - "http://www.example.com/~foo/bar.html", - "GET", - base::Time(), - "", - net::LOAD_NORMAL, - "HTTP/1.1 200 OK", - "Date: Wed, 28 Nov 2007 09:40:09 GMT\n" - "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n", - base::Time(), - "<html><body>Google Blah Blah</body></html>", - TEST_MODE_NORMAL, - NULL, - 0, - net::OK -}; + "http://www.example.com/~foo/bar.html", + "GET", + base::Time(), + "", + LOAD_NORMAL, + "HTTP/1.1 200 OK", + "Date: Wed, 28 Nov 2007 09:40:09 GMT\n" + "Last-Modified: Wed, 28 Nov 2007 00:40:09 GMT\n", + base::Time(), + "<html><body>Google Blah Blah</body></html>", + TEST_MODE_NORMAL, + NULL, + 0, + OK}; const MockTransaction kETagGET_Transaction = { - "http://www.google.com/foopy", - "GET", - base::Time(), - "", - net::LOAD_NORMAL, - "HTTP/1.1 200 OK", - "Cache-Control: max-age=10000\n" - "Etag: \"foopy\"\n", - base::Time(), - "<html><body>Google Blah Blah</body></html>", - TEST_MODE_NORMAL, - NULL, - 0, - net::OK -}; + "http://www.google.com/foopy", + "GET", + base::Time(), + "", + LOAD_NORMAL, + "HTTP/1.1 200 OK", + "Cache-Control: max-age=10000\n" + "Etag: \"foopy\"\n", + base::Time(), + "<html><body>Google Blah Blah</body></html>", + TEST_MODE_NORMAL, + NULL, + 0, + OK}; const MockTransaction kRangeGET_Transaction = { - "http://www.google.com/", - "GET", - base::Time(), - "Range: 0-100\r\n", - net::LOAD_NORMAL, - "HTTP/1.1 200 OK", - "Cache-Control: max-age=10000\n", - base::Time(), - "<html><body>Google Blah Blah</body></html>", - TEST_MODE_NORMAL, - NULL, - 0, - net::OK -}; + "http://www.google.com/", + "GET", + base::Time(), + "Range: 0-100\r\n", + LOAD_NORMAL, + "HTTP/1.1 200 OK", + "Cache-Control: max-age=10000\n", + base::Time(), + "<html><body>Google Blah Blah</body></html>", + TEST_MODE_NORMAL, + NULL, + 0, + OK}; static const MockTransaction* const kBuiltinMockTransactions[] = { &kSimpleGET_Transaction, @@ -154,9 +151,9 @@ int TestTransactionConsumer::quit_counter_ = 0; TestTransactionConsumer::TestTransactionConsumer( - net::RequestPriority priority, - net::HttpTransactionFactory* factory) - : state_(IDLE), error_(net::OK) { + RequestPriority priority, + HttpTransactionFactory* factory) + : state_(IDLE), error_(OK) { // Disregard the error code. factory->CreateTransaction(priority, &trans_); ++quit_counter_; @@ -165,18 +162,18 @@ TestTransactionConsumer::~TestTransactionConsumer() { } -void TestTransactionConsumer::Start(const net::HttpRequestInfo* request, - const net::BoundNetLog& net_log) { +void TestTransactionConsumer::Start(const HttpRequestInfo* request, + const BoundNetLog& net_log) { state_ = STARTING; int result = trans_->Start( request, base::Bind(&TestTransactionConsumer::OnIOComplete, base::Unretained(this)), net_log); - if (result != net::ERR_IO_PENDING) + if (result != ERR_IO_PENDING) DidStart(result); } void TestTransactionConsumer::DidStart(int result) { - if (result != net::OK) { + if (result != OK) { DidFinish(result); } else { Read(); @@ -201,12 +198,12 @@ void TestTransactionConsumer::Read() { state_ = READING; - read_buf_ = new net::IOBuffer(1024); + read_buf_ = new IOBuffer(1024); int result = trans_->Read(read_buf_.get(), 1024, base::Bind(&TestTransactionConsumer::OnIOComplete, base::Unretained(this))); - if (result != net::ERR_IO_PENDING) + if (result != ERR_IO_PENDING) DidRead(result); } @@ -223,55 +220,54 @@ } } -MockNetworkTransaction::MockNetworkTransaction( - net::RequestPriority priority, - MockNetworkLayer* factory) +MockNetworkTransaction::MockNetworkTransaction(RequestPriority priority, + MockNetworkLayer* factory) : request_(NULL), data_cursor_(0), priority_(priority), websocket_handshake_stream_create_helper_(NULL), transaction_factory_(factory->AsWeakPtr()), received_bytes_(0), - socket_log_id_(net::NetLog::Source::kInvalidId), + socket_log_id_(NetLog::Source::kInvalidId), weak_factory_(this) { } MockNetworkTransaction::~MockNetworkTransaction() {} -int MockNetworkTransaction::Start(const net::HttpRequestInfo* request, - const net::CompletionCallback& callback, - const net::BoundNetLog& net_log) { +int MockNetworkTransaction::Start(const HttpRequestInfo* request, + const CompletionCallback& callback, + const BoundNetLog& net_log) { if (request_) - return net::ERR_FAILED; + return ERR_FAILED; request_ = request; return StartInternal(request, callback, net_log); } int MockNetworkTransaction::RestartIgnoringLastError( - const net::CompletionCallback& callback) { - return net::ERR_FAILED; + const CompletionCallback& callback) { + return ERR_FAILED; } int MockNetworkTransaction::RestartWithCertificate( - net::X509Certificate* client_cert, - const net::CompletionCallback& callback) { - return net::ERR_FAILED; + X509Certificate* client_cert, + const CompletionCallback& callback) { + return ERR_FAILED; } int MockNetworkTransaction::RestartWithAuth( - const net::AuthCredentials& credentials, - const net::CompletionCallback& callback) { + const AuthCredentials& credentials, + const CompletionCallback& callback) { if (!IsReadyToRestartForAuth()) - return net::ERR_FAILED; + return ERR_FAILED; - net::HttpRequestInfo auth_request_info = *request_; + HttpRequestInfo auth_request_info = *request_; auth_request_info.extra_headers.AddHeaderFromString("Authorization: Bar"); // Let the MockTransactionHandler worry about this: the only way for this // test to succeed is by using an explicit handler for the transaction so // that server behavior can be simulated. - return StartInternal(&auth_request_info, callback, net::BoundNetLog()); + return StartInternal(&auth_request_info, callback, BoundNetLog()); } bool MockNetworkTransaction::IsReadyToRestartForAuth() { @@ -287,8 +283,9 @@ status_line.find(" 407 ") != std::string::npos; } -int MockNetworkTransaction::Read(net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { +int MockNetworkTransaction::Read(IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) { int data_len = static_cast<int>(data_.size()); int num = std::min(buf_len, data_len - data_cursor_); if (test_mode_ & TEST_MODE_SLOW_READ) @@ -301,7 +298,7 @@ return num; CallbackLater(callback, num); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } void MockNetworkTransaction::StopCaching() { @@ -310,7 +307,7 @@ } bool MockNetworkTransaction::GetFullRequestHeaders( - net::HttpRequestHeaders* headers) const { + HttpRequestHeaders* headers) const { return false; } @@ -323,26 +320,27 @@ transaction_factory_->TransactionDoneReading(); } -const net::HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const { +const HttpResponseInfo* MockNetworkTransaction::GetResponseInfo() const { return &response_; } -net::LoadState MockNetworkTransaction::GetLoadState() const { +LoadState MockNetworkTransaction::GetLoadState() const { if (data_cursor_) - return net::LOAD_STATE_READING_RESPONSE; - return net::LOAD_STATE_IDLE; + return LOAD_STATE_READING_RESPONSE; + return LOAD_STATE_IDLE; } -net::UploadProgress MockNetworkTransaction::GetUploadProgress() const { - return net::UploadProgress(); +UploadProgress MockNetworkTransaction::GetUploadProgress() const { + return UploadProgress(); } void MockNetworkTransaction::SetQuicServerInfo( - net::QuicServerInfo* quic_server_info) {} + QuicServerInfo* quic_server_info) { +} bool MockNetworkTransaction::GetLoadTimingInfo( - net::LoadTimingInfo* load_timing_info) const { - if (socket_log_id_ != net::NetLog::Source::kInvalidId) { + LoadTimingInfo* load_timing_info) const { + if (socket_log_id_ != NetLog::Source::kInvalidId) { // The minimal set of times for a request that gets a response, assuming it // gets a new socket. load_timing_info->socket_reused = false; @@ -362,31 +360,30 @@ return true; } -void MockNetworkTransaction::SetPriority(net::RequestPriority priority) { +void MockNetworkTransaction::SetPriority(RequestPriority priority) { priority_ = priority; } void MockNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper( - net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) { + WebSocketHandshakeStreamBase::CreateHelper* create_helper) { websocket_handshake_stream_create_helper_ = create_helper; } -int MockNetworkTransaction::StartInternal( - const net::HttpRequestInfo* request, - const net::CompletionCallback& callback, - const net::BoundNetLog& net_log) { +int MockNetworkTransaction::StartInternal(const HttpRequestInfo* request, + const CompletionCallback& callback, + const BoundNetLog& net_log) { const MockTransaction* t = FindMockTransaction(request->url); if (!t) - return net::ERR_FAILED; + return ERR_FAILED; test_mode_ = t->test_mode; // Return immediately if we're returning an error. - if (net::OK != t->return_code) { + if (OK != t->return_code) { if (test_mode_ & TEST_MODE_SYNC_NET_START) return t->return_code; CallbackLater(callback, t->return_code); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } std::string resp_status = t->status; @@ -411,7 +408,7 @@ if (!t->response_time.is_null()) response_.response_time = t->response_time; - response_.headers = new net::HttpResponseHeaders(header_data); + response_.headers = new HttpResponseHeaders(header_data); response_.vary_data.Init(*request, *response_.headers.get()); response_.ssl_info.cert_status = t->cert_status; data_ = resp_data; @@ -419,14 +416,14 @@ if (net_log.net_log()) socket_log_id_ = net_log.net_log()->NextID(); - if (request_->load_flags & net::LOAD_PREFETCH) + if (request_->load_flags & LOAD_PREFETCH) response_.unused_since_prefetch = true; if (test_mode_ & TEST_MODE_SYNC_NET_START) - return net::OK; + return OK; - CallbackLater(callback, net::OK); - return net::ERR_IO_PENDING; + CallbackLater(callback, OK); + return ERR_IO_PENDING; } void MockNetworkTransaction::SetBeforeNetworkStartCallback( @@ -439,18 +436,18 @@ int MockNetworkTransaction::ResumeNetworkStart() { // Should not get here. - return net::ERR_FAILED; + return ERR_FAILED; } -void MockNetworkTransaction::CallbackLater( - const net::CompletionCallback& callback, int result) { +void MockNetworkTransaction::CallbackLater(const CompletionCallback& callback, + int result) { base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&MockNetworkTransaction::RunCallback, weak_factory_.GetWeakPtr(), callback, result)); } -void MockNetworkTransaction::RunCallback( - const net::CompletionCallback& callback, int result) { +void MockNetworkTransaction::RunCallback(const CompletionCallback& callback, + int result) { callback.Run(result); } @@ -458,7 +455,7 @@ : transaction_count_(0), done_reading_called_(false), stop_caching_called_(false), - last_create_transaction_priority_(net::DEFAULT_PRIORITY), + last_create_transaction_priority_(DEFAULT_PRIORITY), clock_(nullptr) { } @@ -472,23 +469,22 @@ stop_caching_called_ = true; } -int MockNetworkLayer::CreateTransaction( - net::RequestPriority priority, - scoped_ptr<net::HttpTransaction>* trans) { +int MockNetworkLayer::CreateTransaction(RequestPriority priority, + scoped_ptr<HttpTransaction>* trans) { transaction_count_++; last_create_transaction_priority_ = priority; scoped_ptr<MockNetworkTransaction> mock_transaction( new MockNetworkTransaction(priority, this)); last_transaction_ = mock_transaction->AsWeakPtr(); *trans = mock_transaction.Pass(); - return net::OK; + return OK; } -net::HttpCache* MockNetworkLayer::GetCache() { +HttpCache* MockNetworkLayer::GetCache() { return NULL; } -net::HttpNetworkSession* MockNetworkLayer::GetSession() { +HttpNetworkSession* MockNetworkLayer::GetSession() { return NULL; } @@ -506,16 +502,16 @@ //----------------------------------------------------------------------------- // helpers -int ReadTransaction(net::HttpTransaction* trans, std::string* result) { +int ReadTransaction(HttpTransaction* trans, std::string* result) { int rv; - net::TestCompletionCallback callback; + TestCompletionCallback callback; std::string content; do { - scoped_refptr<net::IOBuffer> buf(new net::IOBuffer(256)); + scoped_refptr<IOBuffer> buf(new IOBuffer(256)); rv = trans->Read(buf.get(), 256, callback.callback()); - if (rv == net::ERR_IO_PENDING) + if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); if (rv > 0) @@ -525,5 +521,7 @@ } while (rv > 0); result->swap(content); - return net::OK; + return OK; } + +} // namespace net
diff --git a/net/http/http_transaction_test_util.h b/net/http/http_transaction_test_util.h index 6d968b4..e63e433 100644 --- a/net/http/http_transaction_test_util.h +++ b/net/http/http_transaction_test_util.h
@@ -26,10 +26,10 @@ #include "net/log/net_log.h" namespace net { + class HttpRequestHeaders; class IOBuffer; struct HttpRequestInfo; -} //----------------------------------------------------------------------------- // mock transaction data @@ -48,7 +48,7 @@ TEST_MODE_SLOW_READ = 1 << 5 }; -typedef void (*MockTransactionHandler)(const net::HttpRequestInfo* request, +typedef void (*MockTransactionHandler)(const HttpRequestInfo* request, std::string* response_status, std::string* response_headers, std::string* response_data); @@ -67,10 +67,10 @@ const char* data; int test_mode; MockTransactionHandler handler; - net::CertStatus cert_status; + CertStatus cert_status; // Value returned by MockNetworkTransaction::Start (potentially // asynchronously if |!(test_mode & TEST_MODE_SYNC_NET_START)|.) - net::Error return_code; + Error return_code; }; extern const MockTransaction kSimpleGET_Transaction; @@ -103,7 +103,7 @@ //----------------------------------------------------------------------------- // mock http request -class MockHttpRequest : public net::HttpRequestInfo { +class MockHttpRequest : public HttpRequestInfo { public: explicit MockHttpRequest(const MockTransaction& t); }; @@ -113,17 +113,16 @@ class TestTransactionConsumer { public: - TestTransactionConsumer(net::RequestPriority priority, - net::HttpTransactionFactory* factory); + TestTransactionConsumer(RequestPriority priority, + HttpTransactionFactory* factory); virtual ~TestTransactionConsumer(); - void Start(const net::HttpRequestInfo* request, - const net::BoundNetLog& net_log); + void Start(const HttpRequestInfo* request, const BoundNetLog& net_log); bool is_done() const { return state_ == DONE; } int error() const { return error_; } - const net::HttpResponseInfo* response_info() const { + const HttpResponseInfo* response_info() const { return trans_->GetResponseInfo(); } const std::string& content() const { return content_; } @@ -144,9 +143,9 @@ void OnIOComplete(int result); State state_; - scoped_ptr<net::HttpTransaction> trans_; + scoped_ptr<HttpTransaction> trans_; std::string content_; - scoped_refptr<net::IOBuffer> read_buf_; + scoped_refptr<IOBuffer> read_buf_; int error_; static int quit_counter_; @@ -162,52 +161,51 @@ // synchronously or asynchronously to help exercise different code paths in the // HttpCache implementation. class MockNetworkTransaction - : public net::HttpTransaction, + : public HttpTransaction, public base::SupportsWeakPtr<MockNetworkTransaction> { - typedef net::WebSocketHandshakeStreamBase::CreateHelper CreateHelper; + typedef WebSocketHandshakeStreamBase::CreateHelper CreateHelper; + public: - MockNetworkTransaction(net::RequestPriority priority, - MockNetworkLayer* factory); + MockNetworkTransaction(RequestPriority priority, MockNetworkLayer* factory); ~MockNetworkTransaction() override; - int Start(const net::HttpRequestInfo* request, - const net::CompletionCallback& callback, - const net::BoundNetLog& net_log) override; + int Start(const HttpRequestInfo* request, + const CompletionCallback& callback, + const BoundNetLog& net_log) override; - int RestartIgnoringLastError( - const net::CompletionCallback& callback) override; + int RestartIgnoringLastError(const CompletionCallback& callback) override; - int RestartWithCertificate(net::X509Certificate* client_cert, - const net::CompletionCallback& callback) override; + int RestartWithCertificate(X509Certificate* client_cert, + const CompletionCallback& callback) override; - int RestartWithAuth(const net::AuthCredentials& credentials, - const net::CompletionCallback& callback) override; + int RestartWithAuth(const AuthCredentials& credentials, + const CompletionCallback& callback) override; bool IsReadyToRestartForAuth() override; - int Read(net::IOBuffer* buf, + int Read(IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; void StopCaching() override; - bool GetFullRequestHeaders(net::HttpRequestHeaders* headers) const override; + bool GetFullRequestHeaders(HttpRequestHeaders* headers) const override; int64 GetTotalReceivedBytes() const override; void DoneReading() override; - const net::HttpResponseInfo* GetResponseInfo() const override; + const HttpResponseInfo* GetResponseInfo() const override; - net::LoadState GetLoadState() const override; + LoadState GetLoadState() const override; - net::UploadProgress GetUploadProgress() const override; + UploadProgress GetUploadProgress() const override; - void SetQuicServerInfo(net::QuicServerInfo* quic_server_info) override; + void SetQuicServerInfo(QuicServerInfo* quic_server_info) override; - bool GetLoadTimingInfo(net::LoadTimingInfo* load_timing_info) const override; + bool GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const override; - void SetPriority(net::RequestPriority priority) override; + void SetPriority(RequestPriority priority) override; void SetWebSocketHandshakeStreamCreateHelper( CreateHelper* create_helper) override; @@ -223,22 +221,22 @@ CreateHelper* websocket_handshake_stream_create_helper() { return websocket_handshake_stream_create_helper_; } - net::RequestPriority priority() const { return priority_; } - const net::HttpRequestInfo* request() const { return request_; } + RequestPriority priority() const { return priority_; } + const HttpRequestInfo* request() const { return request_; } private: - int StartInternal(const net::HttpRequestInfo* request, - const net::CompletionCallback& callback, - const net::BoundNetLog& net_log); - void CallbackLater(const net::CompletionCallback& callback, int result); - void RunCallback(const net::CompletionCallback& callback, int result); + int StartInternal(const HttpRequestInfo* request, + const CompletionCallback& callback, + const BoundNetLog& net_log); + void CallbackLater(const CompletionCallback& callback, int result); + void RunCallback(const CompletionCallback& callback, int result); - const net::HttpRequestInfo* request_; - net::HttpResponseInfo response_; + const HttpRequestInfo* request_; + HttpResponseInfo response_; std::string data_; int data_cursor_; int test_mode_; - net::RequestPriority priority_; + RequestPriority priority_; CreateHelper* websocket_handshake_stream_create_helper_; base::WeakPtr<MockNetworkLayer> transaction_factory_; int64 received_bytes_; @@ -252,7 +250,7 @@ }; -class MockNetworkLayer : public net::HttpTransactionFactory, +class MockNetworkLayer : public HttpTransactionFactory, public base::SupportsWeakPtr<MockNetworkLayer> { public: MockNetworkLayer(); @@ -266,7 +264,7 @@ // Returns the last priority passed to CreateTransaction, or // DEFAULT_PRIORITY if it hasn't been called yet. - net::RequestPriority last_create_transaction_priority() const { + RequestPriority last_create_transaction_priority() const { return last_create_transaction_priority_; } @@ -285,11 +283,11 @@ last_transaction_.reset(); } - // net::HttpTransactionFactory: - int CreateTransaction(net::RequestPriority priority, - scoped_ptr<net::HttpTransaction>* trans) override; - net::HttpCache* GetCache() override; - net::HttpNetworkSession* GetSession() override; + // HttpTransactionFactory: + int CreateTransaction(RequestPriority priority, + scoped_ptr<HttpTransaction>* trans) override; + HttpCache* GetCache() override; + HttpNetworkSession* GetSession() override; // The caller must guarantee that |clock| will outlive this object. void SetClock(base::Clock* clock); @@ -302,7 +300,7 @@ int transaction_count_; bool done_reading_called_; bool stop_caching_called_; - net::RequestPriority last_create_transaction_priority_; + RequestPriority last_create_transaction_priority_; // By default clock_ is NULL but it can be set to a custom clock by test // frameworks using SetClock. @@ -315,6 +313,8 @@ // helpers // read the transaction completely -int ReadTransaction(net::HttpTransaction* trans, std::string* result); +int ReadTransaction(HttpTransaction* trans, std::string* result); + +} // namespace net #endif // NET_HTTP_HTTP_TRANSACTION_UNITTEST_H_
diff --git a/net/http/http_util.cc b/net/http/http_util.cc index 5e342270..baa2eff1 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc
@@ -380,7 +380,7 @@ const char* const headers_to_remove[], size_t headers_to_remove_len) { std::string stripped_headers; - net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); + HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); while (it.GetNext()) { bool should_remove = false; @@ -711,7 +711,7 @@ std::string* headers) { if (header_value.empty()) return; - if (net::HttpUtil::HasHeader(*headers, header_name)) + if (HttpUtil::HasHeader(*headers, header_name)) return; *headers += std::string(header_name) + ": " + header_value + "\r\n"; }
diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc index ee501c7..3f4f625 100644 --- a/net/http/http_util_unittest.cc +++ b/net/http/http_util_unittest.cc
@@ -9,7 +9,7 @@ #include "net/http/http_util.h" #include "testing/gtest/include/gtest/gtest.h" -using net::HttpUtil; +namespace net { namespace { class HttpUtilTest : public testing::Test {}; @@ -730,8 +730,8 @@ std::string charset; bool had_charset = false; std::string boundary; - net::HttpUtil::ParseContentType(tests[i].content_type, &mime_type, - &charset, &had_charset, &boundary); + HttpUtil::ParseContentType(tests[i].content_type, &mime_type, &charset, + &had_charset, &boundary); EXPECT_EQ(tests[i].expected_mime_type, mime_type) << "i=" << i; EXPECT_EQ(tests[i].expected_charset, charset) << "i=" << i; EXPECT_EQ(tests[i].expected_had_charset, had_charset) << "i=" << i; @@ -854,7 +854,7 @@ }; for (size_t i = 0; i < arraysize(tests); ++i) { - std::vector<net::HttpByteRange> ranges; + std::vector<HttpByteRange> ranges; bool return_value = HttpUtil::ParseRanges(std::string(tests[i].headers), &ranges); EXPECT_EQ(tests[i].expected_return_value, return_value); @@ -993,7 +993,7 @@ ASSERT_FALSE(invalid_parser.valid()); } -} // anonymous namespace +} // namespace TEST(HttpUtilTest, NameValuePairsIteratorCopyAndAssign) { std::string data = "alpha='\\'a\\''; beta=\" b \"; cappa='c;'; delta=\"d\""; @@ -1114,3 +1114,5 @@ ASSERT_NO_FATAL_FAILURE(CheckNextNameValuePair( &parser, false, true, std::string(), std::string())); } + +} // namespace net
diff --git a/net/http/http_vary_data_unittest.cc b/net/http/http_vary_data_unittest.cc index 19dbbd77..c9bff65 100644 --- a/net/http/http_vary_data_unittest.cc +++ b/net/http/http_vary_data_unittest.cc
@@ -9,19 +9,21 @@ #include "net/http/http_vary_data.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + namespace { typedef testing::Test HttpVaryDataTest; struct TestTransaction { - net::HttpRequestInfo request; - scoped_refptr<net::HttpResponseHeaders> response; + HttpRequestInfo request; + scoped_refptr<HttpResponseHeaders> response; void Init(const std::string& request_headers, const std::string& response_headers) { std::string temp(response_headers); std::replace(temp.begin(), temp.end(), '\n', '\0'); - response = new net::HttpResponseHeaders(temp); + response = new HttpResponseHeaders(temp); request.extra_headers.Clear(); request.extra_headers.AddHeadersFromString(request_headers); @@ -43,7 +45,7 @@ TestTransaction t; t.Init(std::string(), kTestResponses[i]); - net::HttpVaryData v; + HttpVaryData v; EXPECT_FALSE(v.is_valid()); EXPECT_FALSE(v.Init(t.request, *t.response.get())); EXPECT_FALSE(v.is_valid()); @@ -51,7 +53,7 @@ } TEST(HttpVaryDataTest, MultipleInit) { - net::HttpVaryData v; + HttpVaryData v; // Init to something valid. TestTransaction t1; @@ -73,7 +75,7 @@ TestTransaction b; b.Init("Foo: 2", "HTTP/1.1 200 OK\nVary: foo\n\n"); - net::HttpVaryData v; + HttpVaryData v; EXPECT_TRUE(v.Init(a.request, *a.response.get())); EXPECT_FALSE(v.MatchesRequest(b.request, *b.response.get())); @@ -86,7 +88,7 @@ TestTransaction b; b.Init("Foo: 12\r\nbar: 3", "HTTP/1.1 200 OK\nVary: foo, bar\n\n"); - net::HttpVaryData v; + HttpVaryData v; EXPECT_TRUE(v.Init(a.request, *a.response.get())); EXPECT_FALSE(v.MatchesRequest(b.request, *b.response.get())); @@ -99,7 +101,7 @@ TestTransaction b; b.Init("Foo: 1", "HTTP/1.1 200 OK\nVary: foo\n\n"); - net::HttpVaryData v; + HttpVaryData v; EXPECT_TRUE(v.Init(a.request, *a.response.get())); EXPECT_TRUE(v.MatchesRequest(b.request, *b.response.get())); @@ -112,7 +114,7 @@ TestTransaction b; b.Init("Foo: 1\r\nbaR: 2", "HTTP/1.1 200 OK\nVary: foo\nVary: bar\n\n"); - net::HttpVaryData v; + HttpVaryData v; EXPECT_TRUE(v.Init(a.request, *a.response.get())); EXPECT_TRUE(v.MatchesRequest(b.request, *b.response.get())); @@ -125,7 +127,7 @@ TestTransaction b; b.Init("Cookie: 2", "HTTP/1.1 301 Moved\nLocation: x\n\n"); - net::HttpVaryData v; + HttpVaryData v; EXPECT_TRUE(v.Init(a.request, *a.response.get())); EXPECT_FALSE(v.MatchesRequest(b.request, *b.response.get())); @@ -140,8 +142,10 @@ TestTransaction b; b.Init("Cookie: 2", "HTTP/1.1 301 Moved\nLocation: x\nVary: cooKie\n\n"); - net::HttpVaryData v; + HttpVaryData v; EXPECT_TRUE(v.Init(a.request, *a.response.get())); EXPECT_FALSE(v.MatchesRequest(b.request, *b.response.get())); } + +} // namespace net
diff --git a/net/http/mock_http_cache.cc b/net/http/mock_http_cache.cc index a423a04a..02b74bc 100644 --- a/net/http/mock_http_cache.cc +++ b/net/http/mock_http_cache.cc
@@ -10,6 +10,8 @@ #include "net/base/net_errors.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + namespace { // We can override the test mode for a given operation by setting this global @@ -36,7 +38,7 @@ return t->test_mode; } -void CallbackForwader(const net::CompletionCallback& callback, int result) { +void CallbackForwader(const CompletionCallback& callback, int result) { callback.Run(result); } @@ -46,7 +48,7 @@ struct MockDiskEntry::CallbackInfo { scoped_refptr<MockDiskEntry> entry; - net::CompletionCallback callback; + CompletionCallback callback; int result; }; @@ -82,17 +84,19 @@ return static_cast<int32>(data_[index].size()); } -int MockDiskEntry::ReadData( - int index, int offset, net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { +int MockDiskEntry::ReadData(int index, + int offset, + IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) { DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); DCHECK(!callback.is_null()); if (fail_requests_) - return net::ERR_CACHE_READ_FAILURE; + return ERR_CACHE_READ_FAILURE; if (offset < 0 || offset > static_cast<int>(data_[index].size())) - return net::ERR_FAILED; + return ERR_FAILED; if (static_cast<size_t>(offset) == data_[index].size()) return 0; @@ -103,23 +107,26 @@ return num; CallbackLater(callback, num); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } -int MockDiskEntry::WriteData( - int index, int offset, net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback, bool truncate) { +int MockDiskEntry::WriteData(int index, + int offset, + IOBuffer* buf, + int buf_len, + const CompletionCallback& callback, + bool truncate) { DCHECK(index >= 0 && index < kNumCacheEntryDataIndices); DCHECK(!callback.is_null()); DCHECK(truncate); if (fail_requests_) { - CallbackLater(callback, net::ERR_CACHE_READ_FAILURE); - return net::ERR_IO_PENDING; + CallbackLater(callback, ERR_CACHE_READ_FAILURE); + return ERR_IO_PENDING; } if (offset < 0 || offset > static_cast<int>(data_[index].size())) - return net::ERR_FAILED; + return ERR_FAILED; data_[index].resize(offset + buf_len); if (buf_len) @@ -129,21 +136,23 @@ return buf_len; CallbackLater(callback, buf_len); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } -int MockDiskEntry::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { +int MockDiskEntry::ReadSparseData(int64 offset, + IOBuffer* buf, + int buf_len, + const CompletionCallback& callback) { DCHECK(!callback.is_null()); if (fail_sparse_requests_) - return net::ERR_NOT_IMPLEMENTED; + return ERR_NOT_IMPLEMENTED; if (!sparse_ || busy_) - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + return ERR_CACHE_OPERATION_NOT_SUPPORTED; if (offset < 0) - return net::ERR_FAILED; + return ERR_FAILED; if (fail_requests_) - return net::ERR_CACHE_READ_FAILURE; + return ERR_CACHE_READ_FAILURE; DCHECK(offset < kint32max); int real_offset = static_cast<int>(offset); @@ -160,29 +169,30 @@ CallbackLater(callback, num); busy_ = true; delayed_ = false; - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } -int MockDiskEntry::WriteSparseData(int64 offset, net::IOBuffer* buf, +int MockDiskEntry::WriteSparseData(int64 offset, + IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) { + const CompletionCallback& callback) { DCHECK(!callback.is_null()); if (fail_sparse_requests_) - return net::ERR_NOT_IMPLEMENTED; + return ERR_NOT_IMPLEMENTED; if (busy_) - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + return ERR_CACHE_OPERATION_NOT_SUPPORTED; if (!sparse_) { if (data_[1].size()) - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + return ERR_CACHE_OPERATION_NOT_SUPPORTED; sparse_ = true; } if (offset < 0) - return net::ERR_FAILED; + return ERR_FAILED; if (!buf_len) return 0; if (fail_requests_) - return net::ERR_CACHE_READ_FAILURE; + return ERR_CACHE_READ_FAILURE; DCHECK(offset < kint32max); int real_offset = static_cast<int>(offset); @@ -195,19 +205,21 @@ return buf_len; CallbackLater(callback, buf_len); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } -int MockDiskEntry::GetAvailableRange(int64 offset, int len, int64* start, - const net::CompletionCallback& callback) { +int MockDiskEntry::GetAvailableRange(int64 offset, + int len, + int64* start, + const CompletionCallback& callback) { DCHECK(!callback.is_null()); if (!sparse_ || busy_) - return net::ERR_CACHE_OPERATION_NOT_SUPPORTED; + return ERR_CACHE_OPERATION_NOT_SUPPORTED; if (offset < 0) - return net::ERR_FAILED; + return ERR_FAILED; if (fail_requests_) - return net::ERR_CACHE_READ_FAILURE; + return ERR_CACHE_READ_FAILURE; *start = offset; DCHECK(offset < kint32max); @@ -233,7 +245,7 @@ return count; CallbackLater(callback, count); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } bool MockDiskEntry::CouldBeSparse() const { @@ -246,21 +258,21 @@ cancel_ = true; } -int MockDiskEntry::ReadyForSparseIO(const net::CompletionCallback& callback) { +int MockDiskEntry::ReadyForSparseIO(const CompletionCallback& callback) { if (fail_sparse_requests_) - return net::ERR_NOT_IMPLEMENTED; + return ERR_NOT_IMPLEMENTED; if (!cancel_) - return net::OK; + return OK; cancel_ = false; DCHECK(!callback.is_null()); if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_READ) - return net::OK; + return OK; // The pending operation is already in the message loop (and hopefully // already in the second pass). Just notify the caller that it finished. CallbackLater(callback, 0); - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } // If |value| is true, don't deliver any completion callbacks until called @@ -272,7 +284,7 @@ return; ignore_callbacks_ = value; if (!value) - StoreAndDeliverCallbacks(false, NULL, net::CompletionCallback(), 0); + StoreAndDeliverCallbacks(false, NULL, CompletionCallback(), 0); } MockDiskEntry::~MockDiskEntry() { @@ -281,7 +293,7 @@ // Unlike the callbacks for MockHttpTransaction, we want this one to run even // if the consumer called Close on the MockDiskEntry. We achieve that by // leveraging the fact that this class is reference counted. -void MockDiskEntry::CallbackLater(const net::CompletionCallback& callback, +void MockDiskEntry::CallbackLater(const CompletionCallback& callback, int result) { if (ignore_callbacks_) return StoreAndDeliverCallbacks(true, this, callback, result); @@ -290,8 +302,8 @@ base::Bind(&MockDiskEntry::RunCallback, this, callback, result)); } -void MockDiskEntry::RunCallback( - const net::CompletionCallback& callback, int result) { +void MockDiskEntry::RunCallback(const CompletionCallback& callback, + int result) { if (busy_) { // This is kind of hacky, but controlling the behavior of just this entry // from a test is sort of complicated. What we really want to do is @@ -313,9 +325,10 @@ // When |store| is true, stores the callback to be delivered later; otherwise // delivers any callback previously stored. // Static. -void MockDiskEntry::StoreAndDeliverCallbacks( - bool store, MockDiskEntry* entry, const net::CompletionCallback& callback, - int result) { +void MockDiskEntry::StoreAndDeliverCallbacks(bool store, + MockDiskEntry* entry, + const CompletionCallback& callback, + int result) { static std::vector<CallbackInfo> callback_list; if (store) { CallbackInfo c = {entry, callback, result}; @@ -345,28 +358,29 @@ ReleaseAll(); } -net::CacheType MockDiskCache::GetCacheType() const { - return net::DISK_CACHE; +CacheType MockDiskCache::GetCacheType() const { + return DISK_CACHE; } int32 MockDiskCache::GetEntryCount() const { return static_cast<int32>(entries_.size()); } -int MockDiskCache::OpenEntry(const std::string& key, disk_cache::Entry** entry, - const net::CompletionCallback& callback) { +int MockDiskCache::OpenEntry(const std::string& key, + disk_cache::Entry** entry, + const CompletionCallback& callback) { DCHECK(!callback.is_null()); if (fail_requests_) - return net::ERR_CACHE_OPEN_FAILURE; + return ERR_CACHE_OPEN_FAILURE; EntryMap::iterator it = entries_.find(key); if (it == entries_.end()) - return net::ERR_CACHE_OPEN_FAILURE; + return ERR_CACHE_OPEN_FAILURE; if (it->second->is_doomed()) { it->second->Release(); entries_.erase(it); - return net::ERR_CACHE_OPEN_FAILURE; + return ERR_CACHE_OPEN_FAILURE; } open_count_++; @@ -378,18 +392,18 @@ it->second->set_fail_requests(); if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) - return net::OK; + return OK; - CallbackLater(callback, net::OK); - return net::ERR_IO_PENDING; + CallbackLater(callback, OK); + return ERR_IO_PENDING; } int MockDiskCache::CreateEntry(const std::string& key, disk_cache::Entry** entry, - const net::CompletionCallback& callback) { + const CompletionCallback& callback) { DCHECK(!callback.is_null()); if (fail_requests_) - return net::ERR_CACHE_CREATE_FAILURE; + return ERR_CACHE_CREATE_FAILURE; EntryMap::iterator it = entries_.find(key); if (it != entries_.end()) { @@ -397,7 +411,7 @@ if (double_create_check_) NOTREACHED(); else - return net::ERR_CACHE_CREATE_FAILURE; + return ERR_CACHE_CREATE_FAILURE; } it->second->Release(); entries_.erase(it); @@ -420,14 +434,14 @@ new_entry->set_fail_sparse_requests(); if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) - return net::OK; + return OK; - CallbackLater(callback, net::OK); - return net::ERR_IO_PENDING; + CallbackLater(callback, OK); + return ERR_IO_PENDING; } int MockDiskCache::DoomEntry(const std::string& key, - const net::CompletionCallback& callback) { + const CompletionCallback& callback) { DCHECK(!callback.is_null()); EntryMap::iterator it = entries_.find(key); if (it != entries_.end()) { @@ -436,32 +450,32 @@ } if (GetTestModeForEntry(key) & TEST_MODE_SYNC_CACHE_START) - return net::OK; + return OK; - CallbackLater(callback, net::OK); - return net::ERR_IO_PENDING; + CallbackLater(callback, OK); + return ERR_IO_PENDING; } -int MockDiskCache::DoomAllEntries(const net::CompletionCallback& callback) { - return net::ERR_NOT_IMPLEMENTED; +int MockDiskCache::DoomAllEntries(const CompletionCallback& callback) { + return ERR_NOT_IMPLEMENTED; } int MockDiskCache::DoomEntriesBetween(const base::Time initial_time, const base::Time end_time, - const net::CompletionCallback& callback) { - return net::ERR_NOT_IMPLEMENTED; + const CompletionCallback& callback) { + return ERR_NOT_IMPLEMENTED; } int MockDiskCache::DoomEntriesSince(const base::Time initial_time, - const net::CompletionCallback& callback) { - return net::ERR_NOT_IMPLEMENTED; + const CompletionCallback& callback) { + return ERR_NOT_IMPLEMENTED; } class MockDiskCache::NotImplementedIterator : public Iterator { public: int OpenNextEntry(disk_cache::Entry** next_entry, - const net::CompletionCallback& callback) override { - return net::ERR_NOT_IMPLEMENTED; + const CompletionCallback& callback) override { + return ERR_NOT_IMPLEMENTED; } }; @@ -483,7 +497,7 @@ entries_.clear(); } -void MockDiskCache::CallbackLater(const net::CompletionCallback& callback, +void MockDiskCache::CallbackLater(const CompletionCallback& callback, int result) { base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&CallbackForwader, callback, result)); @@ -491,11 +505,11 @@ //----------------------------------------------------------------------------- -int MockBackendFactory::CreateBackend(net::NetLog* net_log, +int MockBackendFactory::CreateBackend(NetLog* net_log, scoped_ptr<disk_cache::Backend>* backend, - const net::CompletionCallback& callback) { + const CompletionCallback& callback) { backend->reset(new MockDiskCache()); - return net::OK; + return OK; } //----------------------------------------------------------------------------- @@ -504,24 +518,24 @@ : http_cache_(new MockNetworkLayer(), NULL, new MockBackendFactory()) { } -MockHttpCache::MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory) +MockHttpCache::MockHttpCache(HttpCache::BackendFactory* disk_cache_factory) : http_cache_(new MockNetworkLayer(), NULL, disk_cache_factory) { } disk_cache::Backend* MockHttpCache::backend() { - net::TestCompletionCallback cb; + TestCompletionCallback cb; disk_cache::Backend* backend; int rv = http_cache_.GetBackend(&backend, cb.callback()); rv = cb.GetResult(rv); - return (rv == net::OK) ? backend : NULL; + return (rv == OK) ? backend : NULL; } MockDiskCache* MockHttpCache::disk_cache() { return static_cast<MockDiskCache*>(backend()); } -int MockHttpCache::CreateTransaction(scoped_ptr<net::HttpTransaction>* trans) { - return http_cache_.CreateTransaction(net::DEFAULT_PRIORITY, trans); +int MockHttpCache::CreateTransaction(scoped_ptr<HttpTransaction>* trans) { + return http_cache_.CreateTransaction(DEFAULT_PRIORITY, trans); } void MockHttpCache::BypassCacheLock() { @@ -533,31 +547,31 @@ } bool MockHttpCache::ReadResponseInfo(disk_cache::Entry* disk_entry, - net::HttpResponseInfo* response_info, + HttpResponseInfo* response_info, bool* response_truncated) { int size = disk_entry->GetDataSize(0); - net::TestCompletionCallback cb; - scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(size)); + TestCompletionCallback cb; + scoped_refptr<IOBuffer> buffer(new IOBuffer(size)); int rv = disk_entry->ReadData(0, 0, buffer.get(), size, cb.callback()); rv = cb.GetResult(rv); EXPECT_EQ(size, rv); - return net::HttpCache::ParseResponseInfo(buffer->data(), size, - response_info, - response_truncated); + return HttpCache::ParseResponseInfo(buffer->data(), size, response_info, + response_truncated); } -bool MockHttpCache::WriteResponseInfo( - disk_cache::Entry* disk_entry, const net::HttpResponseInfo* response_info, - bool skip_transient_headers, bool response_truncated) { +bool MockHttpCache::WriteResponseInfo(disk_cache::Entry* disk_entry, + const HttpResponseInfo* response_info, + bool skip_transient_headers, + bool response_truncated) { Pickle pickle; response_info->Persist( &pickle, skip_transient_headers, response_truncated); - net::TestCompletionCallback cb; - scoped_refptr<net::WrappedIOBuffer> data(new net::WrappedIOBuffer( - reinterpret_cast<const char*>(pickle.data()))); + TestCompletionCallback cb; + scoped_refptr<WrappedIOBuffer> data( + new WrappedIOBuffer(reinterpret_cast<const char*>(pickle.data()))); int len = static_cast<int>(pickle.size()); int rv = disk_entry->WriteData(0, 0, data.get(), len, cb.callback(), true); @@ -567,17 +581,17 @@ bool MockHttpCache::OpenBackendEntry(const std::string& key, disk_cache::Entry** entry) { - net::TestCompletionCallback cb; + TestCompletionCallback cb; int rv = backend()->OpenEntry(key, entry, cb.callback()); - return (cb.GetResult(rv) == net::OK); + return (cb.GetResult(rv) == OK); } bool MockHttpCache::CreateBackendEntry(const std::string& key, disk_cache::Entry** entry, - net::NetLog* net_log) { - net::TestCompletionCallback cb; + NetLog* net_log) { + TestCompletionCallback cb; int rv = backend()->CreateEntry(key, entry, cb.callback()); - return (cb.GetResult(rv) == net::OK); + return (cb.GetResult(rv) == OK); } // Static. @@ -597,17 +611,18 @@ int MockDiskCacheNoCB::CreateEntry(const std::string& key, disk_cache::Entry** entry, - const net::CompletionCallback& callback) { - return net::ERR_IO_PENDING; + const CompletionCallback& callback) { + return ERR_IO_PENDING; } //----------------------------------------------------------------------------- int MockBackendNoCbFactory::CreateBackend( - net::NetLog* net_log, scoped_ptr<disk_cache::Backend>* backend, - const net::CompletionCallback& callback) { + NetLog* net_log, + scoped_ptr<disk_cache::Backend>* backend, + const CompletionCallback& callback) { backend->reset(new MockDiskCacheNoCB()); - return net::OK; + return OK; } //----------------------------------------------------------------------------- @@ -622,8 +637,9 @@ } int MockBlockingBackendFactory::CreateBackend( - net::NetLog* net_log, scoped_ptr<disk_cache::Backend>* backend, - const net::CompletionCallback& callback) { + NetLog* net_log, + scoped_ptr<disk_cache::Backend>* backend, + const CompletionCallback& callback) { if (!block_) { if (!fail_) backend->reset(new MockDiskCache()); @@ -632,7 +648,7 @@ backend_ = backend; callback_ = callback; - return net::ERR_IO_PENDING; + return ERR_IO_PENDING; } void MockBlockingBackendFactory::FinishCreation() { @@ -640,8 +656,10 @@ if (!callback_.is_null()) { if (!fail_) backend_->reset(new MockDiskCache()); - net::CompletionCallback cb = callback_; + CompletionCallback cb = callback_; callback_.Reset(); cb.Run(Result()); // This object can be deleted here. } } + +} // namespace net
diff --git a/net/http/mock_http_cache.h b/net/http/mock_http_cache.h index 36b5656..f77ace4 100644 --- a/net/http/mock_http_cache.h +++ b/net/http/mock_http_cache.h
@@ -15,6 +15,8 @@ #include "net/http/http_cache.h" #include "net/http/http_transaction_test_util.h" +namespace net { + //----------------------------------------------------------------------------- // Mock disk cache (a very basic memory cache implementation). @@ -33,31 +35,30 @@ int32 GetDataSize(int index) const override; int ReadData(int index, int offset, - net::IOBuffer* buf, + IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; int WriteData(int index, int offset, - net::IOBuffer* buf, + IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback, + const CompletionCallback& callback, bool truncate) override; int ReadSparseData(int64 offset, - net::IOBuffer* buf, + IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; int WriteSparseData(int64 offset, - net::IOBuffer* buf, + IOBuffer* buf, int buf_len, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; int GetAvailableRange(int64 offset, int len, int64* start, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; bool CouldBeSparse() const override; void CancelSparseIO() override; - int ReadyForSparseIO( - const net::CompletionCallback& completion_callback) override; + int ReadyForSparseIO(const CompletionCallback& completion_callback) override; // Fail most subsequent requests. void set_fail_requests() { fail_requests_ = true; } @@ -78,14 +79,15 @@ // Unlike the callbacks for MockHttpTransaction, we want this one to run even // if the consumer called Close on the MockDiskEntry. We achieve that by // leveraging the fact that this class is reference counted. - void CallbackLater(const net::CompletionCallback& callback, int result); + void CallbackLater(const CompletionCallback& callback, int result); - void RunCallback(const net::CompletionCallback& callback, int result); + void RunCallback(const CompletionCallback& callback, int result); // When |store| is true, stores the callback to be delivered later; otherwise // delivers any callback previously stored. - static void StoreAndDeliverCallbacks(bool store, MockDiskEntry* entry, - const net::CompletionCallback& callback, + static void StoreAndDeliverCallbacks(bool store, + MockDiskEntry* entry, + const CompletionCallback& callback, int result); static const int kNumCacheEntryDataIndices = 3; @@ -108,22 +110,22 @@ MockDiskCache(); ~MockDiskCache() override; - net::CacheType GetCacheType() const override; + CacheType GetCacheType() const override; int32 GetEntryCount() const override; int OpenEntry(const std::string& key, disk_cache::Entry** entry, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; int CreateEntry(const std::string& key, disk_cache::Entry** entry, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; int DoomEntry(const std::string& key, - const net::CompletionCallback& callback) override; - int DoomAllEntries(const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; + int DoomAllEntries(const CompletionCallback& callback) override; int DoomEntriesBetween(base::Time initial_time, base::Time end_time, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; int DoomEntriesSince(base::Time initial_time, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; scoped_ptr<Iterator> CreateIterator() override; void GetStats( std::vector<std::pair<std::string, std::string>>* stats) override; @@ -153,7 +155,7 @@ typedef base::hash_map<std::string, MockDiskEntry*> EntryMap; class NotImplementedIterator; - void CallbackLater(const net::CompletionCallback& callback, int result); + void CallbackLater(const CompletionCallback& callback, int result); EntryMap entries_; int open_count_; @@ -164,19 +166,19 @@ bool fail_sparse_requests_; }; -class MockBackendFactory : public net::HttpCache::BackendFactory { +class MockBackendFactory : public HttpCache::BackendFactory { public: - int CreateBackend(net::NetLog* net_log, + int CreateBackend(NetLog* net_log, scoped_ptr<disk_cache::Backend>* backend, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; }; class MockHttpCache { public: MockHttpCache(); - explicit MockHttpCache(net::HttpCache::BackendFactory* disk_cache_factory); + explicit MockHttpCache(HttpCache::BackendFactory* disk_cache_factory); - net::HttpCache* http_cache() { return &http_cache_; } + HttpCache* http_cache() { return &http_cache_; } MockNetworkLayer* network_layer() { return static_cast<MockNetworkLayer*>(http_cache_.network_layer()); @@ -184,8 +186,8 @@ disk_cache::Backend* backend(); MockDiskCache* disk_cache(); - // Wrapper around http_cache()->CreateTransaction(net::DEFAULT_PRIORITY...) - int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans); + // Wrapper around http_cache()->CreateTransaction(DEFAULT_PRIORITY...) + int CreateTransaction(scoped_ptr<HttpTransaction>* trans); // Wrapper to bypass the cache lock for new transactions. void BypassCacheLock(); @@ -195,12 +197,12 @@ // Helper function for reading response info from the disk cache. static bool ReadResponseInfo(disk_cache::Entry* disk_entry, - net::HttpResponseInfo* response_info, + HttpResponseInfo* response_info, bool* response_truncated); // Helper function for writing response info into the disk cache. static bool WriteResponseInfo(disk_cache::Entry* disk_entry, - const net::HttpResponseInfo* response_info, + const HttpResponseInfo* response_info, bool skip_transient_headers, bool response_truncated); @@ -208,8 +210,9 @@ bool OpenBackendEntry(const std::string& key, disk_cache::Entry** entry); // Helper function to synchronously create a backend entry. - bool CreateBackendEntry(const std::string& key, disk_cache::Entry** entry, - net::NetLog* net_log); + bool CreateBackendEntry(const std::string& key, + disk_cache::Entry** entry, + NetLog* net_log); // Returns the test mode after considering the global override. static int GetTestMode(int test_mode); @@ -219,32 +222,32 @@ static void SetTestMode(int test_mode); private: - net::HttpCache http_cache_; + HttpCache http_cache_; }; // This version of the disk cache doesn't invoke CreateEntry callbacks. class MockDiskCacheNoCB : public MockDiskCache { int CreateEntry(const std::string& key, disk_cache::Entry** entry, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; }; -class MockBackendNoCbFactory : public net::HttpCache::BackendFactory { +class MockBackendNoCbFactory : public HttpCache::BackendFactory { public: - int CreateBackend(net::NetLog* net_log, + int CreateBackend(NetLog* net_log, scoped_ptr<disk_cache::Backend>* backend, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; }; // This backend factory allows us to control the backend instantiation. -class MockBlockingBackendFactory : public net::HttpCache::BackendFactory { +class MockBlockingBackendFactory : public HttpCache::BackendFactory { public: MockBlockingBackendFactory(); ~MockBlockingBackendFactory() override; - int CreateBackend(net::NetLog* net_log, + int CreateBackend(NetLog* net_log, scoped_ptr<disk_cache::Backend>* backend, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; // Completes the backend creation. Any blocked call will be notified via the // provided callback. @@ -253,15 +256,17 @@ scoped_ptr<disk_cache::Backend>* backend() { return backend_; } void set_fail(bool fail) { fail_ = fail; } - const net::CompletionCallback& callback() { return callback_; } + const CompletionCallback& callback() { return callback_; } private: - int Result() { return fail_ ? net::ERR_FAILED : net::OK; } + int Result() { return fail_ ? ERR_FAILED : OK; } scoped_ptr<disk_cache::Backend>* backend_; - net::CompletionCallback callback_; + CompletionCallback callback_; bool block_; bool fail_; }; +} // namespace net + #endif // NET_HTTP_MOCK_HTTP_CACHE_H_
diff --git a/net/http/partial_data.cc b/net/http/partial_data.cc index 2dcb015..100eed8 100644 --- a/net/http/partial_data.cc +++ b/net/http/partial_data.cc
@@ -80,7 +80,7 @@ int rv = entry->GetAvailableRange( offset, len, &start_, base::Bind(&PartialData::Core::OnIOComplete, base::Unretained(this))); - if (rv != net::ERR_IO_PENDING) { + if (rv != ERR_IO_PENDING) { // The callback will not be invoked. Lets cleanup. *start = start_; delete this; @@ -429,9 +429,10 @@ resource_size_)); } -int PartialData::CacheRead( - disk_cache::Entry* entry, IOBuffer* data, int data_len, - const net::CompletionCallback& callback) { +int PartialData::CacheRead(disk_cache::Entry* entry, + IOBuffer* data, + int data_len, + const CompletionCallback& callback) { int read_len = std::min(data_len, cached_min_len_); if (!read_len) return 0; @@ -450,9 +451,10 @@ return rv; } -int PartialData::CacheWrite( - disk_cache::Entry* entry, IOBuffer* data, int data_len, - const net::CompletionCallback& callback) { +int PartialData::CacheWrite(disk_cache::Entry* entry, + IOBuffer* data, + int data_len, + const CompletionCallback& callback) { DVLOG(3) << "To write: " << data_len; if (sparse_entry_) { return entry->WriteSparseData(
diff --git a/net/http/partial_data.h b/net/http/partial_data.h index ea98ff0..8d87da5 100644 --- a/net/http/partial_data.h +++ b/net/http/partial_data.h
@@ -96,13 +96,17 @@ // cache that provides the right arguments for the current range. When the IO // operation completes, OnCacheReadCompleted() must be called with the result // of the operation. - int CacheRead(disk_cache::Entry* entry, IOBuffer* data, int data_len, - const net::CompletionCallback& callback); + int CacheRead(disk_cache::Entry* entry, + IOBuffer* data, + int data_len, + const CompletionCallback& callback); // Writes |data_len| bytes to cache. This is basically a wrapper around the // API of the cache that provides the right arguments for the current range. - int CacheWrite(disk_cache::Entry* entry, IOBuffer* data, int data_len, - const net::CompletionCallback& callback); + int CacheWrite(disk_cache::Entry* entry, + IOBuffer* data, + int data_len, + const CompletionCallback& callback); // This method should be called when CacheRead() finishes the read, to update // the internal state about the current range.
diff --git a/net/http/transport_security_persister.cc b/net/http/transport_security_persister.cc index 82a4b5140..08aa07e 100644 --- a/net/http/transport_security_persister.cc +++ b/net/http/transport_security_persister.cc
@@ -19,10 +19,7 @@ #include "net/cert/x509_certificate.h" #include "net/http/transport_security_state.h" -using net::HashValue; -using net::HashValueTag; -using net::HashValueVector; -using net::TransportSecurityState; +namespace net { namespace { @@ -91,9 +88,6 @@ } // namespace - -namespace net { - TransportSecurityPersister::TransportSecurityPersister( TransportSecurityState* state, const base::FilePath& profile_path, @@ -108,9 +102,8 @@ transport_security_state_->SetDelegate(this); base::PostTaskAndReplyWithResult( - background_runner_.get(), - FROM_HERE, - base::Bind(&::LoadState, writer_.path()), + background_runner_.get(), FROM_HERE, + base::Bind(&LoadState, writer_.path()), base::Bind(&TransportSecurityPersister::CompleteLoad, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/net/http/transport_security_persister_unittest.cc b/net/http/transport_security_persister_unittest.cc index 7bb2e99..1d547ea 100644 --- a/net/http/transport_security_persister_unittest.cc +++ b/net/http/transport_security_persister_unittest.cc
@@ -15,8 +15,9 @@ #include "net/http/transport_security_state.h" #include "testing/gtest/include/gtest/gtest.h" -using net::TransportSecurityPersister; -using net::TransportSecurityState; +namespace net { + +namespace { class TransportSecurityPersisterTest : public testing::Test { public: @@ -86,13 +87,13 @@ TEST_F(TransportSecurityPersisterTest, SerializeData3) { // Add an entry. - net::HashValue fp1(net::HASH_VALUE_SHA1); + HashValue fp1(HASH_VALUE_SHA1); memset(fp1.data(), 0, fp1.size()); - net::HashValue fp2(net::HASH_VALUE_SHA1); + HashValue fp2(HASH_VALUE_SHA1); memset(fp2.data(), 1, fp2.size()); base::Time expiry = base::Time::Now() + base::TimeDelta::FromSeconds(1000); - net::HashValueVector dynamic_spki_hashes; + HashValueVector dynamic_spki_hashes; dynamic_spki_hashes.push_back(fp1); dynamic_spki_hashes.push_back(fp2); bool include_subdomains = false; @@ -168,11 +169,11 @@ TransportSecurityState::DomainState domain_state; static const char kTestDomain[] = "example.com"; EXPECT_FALSE(state_.GetDynamicDomainState(kTestDomain, &domain_state)); - net::HashValueVector hashes; + HashValueVector hashes; std::string failure_log; EXPECT_FALSE(domain_state.CheckPublicKeyPins(hashes, &failure_log)); - net::HashValue sha1(net::HASH_VALUE_SHA1); + HashValue sha1(HASH_VALUE_SHA1); memset(sha1.data(), '1', sha1.size()); domain_state.pkp.spki_hashes.push_back(sha1); @@ -204,3 +205,7 @@ sha1.data(), sha1.size())); } + +} // namespace + +} // namespace net
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h index 6d0958f..8373a35 100644 --- a/net/http/transport_security_state_static.h +++ b/net/http/transport_security_state_static.h
@@ -682,7 +682,7 @@ 0xf0, 0xe4, 0x00, 0xf2, 0xb6, 0xb7, 0xb9, 0x02, 0xb1, 0x03, 0xb0, 0xb2, 0x04, 0x05, 0x06, 0xea, 0xfa, 0x07, 0x08, 0xe6, 0x09, 0xed, 0xe9, 0x0a, 0x01, 0x0b, 0xeb, 0xf7, 0x0d, 0xe3, 0xe1, 0x0e, 0x80, 0x0f, 0x0c, 0x10, - 0xb8, 0xb5, 0xb3, 0x12, 0xf1, 0xb4, 0x13, 0x14, 0xf8, 0x15, 0xf6, 0x16, + 0xb8, 0xb5, 0x12, 0xb3, 0xf1, 0xb4, 0x13, 0x14, 0x15, 0xf8, 0xf6, 0x16, 0x17, 0xe2, 0xe7, 0x18, 0xef, 0x19, 0xff, 0x1a, 0xe8, 0xae, 0xf3, 0x1c, 0xe5, 0x1d, 0xee, 0xf4, 0xad, 0xf9, 0x20, 0xf5, 0x21, 0xec, 0x1f, 0x22, 0x1e, 0x23, 0x1b, 0x24, 0x11, 0x25, @@ -694,15 +694,15 @@ 0x35, 0x69, 0x68, 0x79, 0xfd, 0x04, 0x5c, 0x93, 0xa7, 0xad, 0x55, 0x65, 0x44, 0x5b, 0x37, 0xf4, 0xb4, 0x7c, 0xf0, 0xf4, 0x5b, 0x3f, 0xce, 0x89, 0x68, 0x87, 0x67, 0xad, 0x38, 0x25, 0x7a, 0xd0, 0x47, 0xa9, 0x47, 0x13, - 0xff, 0x9a, 0xdf, 0x63, 0x58, 0x7b, 0x76, 0xae, 0xd1, 0x90, 0xb4, 0xff, + 0xff, 0x9a, 0xdf, 0x63, 0x58, 0x7b, 0x74, 0x2e, 0x81, 0x90, 0xb4, 0xff, 0xe2, 0x11, 0x6d, 0xbc, 0xe7, 0xf5, 0x8e, 0xad, 0x36, 0x6c, 0x94, 0x99, 0x29, 0x03, 0xe6, 0x94, 0x02, 0xd3, 0xfb, 0xb9, 0xf0, 0x1c, 0xb4, 0x96, 0xe6, 0x9e, 0x7e, 0x7f, 0x0a, 0xe6, 0x38, 0xb4, 0x31, 0xf9, 0x52, 0x1c, 0xff, 0x0b, 0x70, 0xac, 0xc7, 0x25, 0xa5, 0xb9, 0x92, 0x56, 0xac, 0xd0, - 0x98, 0xc7, 0x1e, 0x3b, 0x09, 0x06, 0x96, 0xae, 0xa3, 0x08, 0xf2, 0x41, + 0x98, 0xc7, 0x1e, 0x3b, 0x09, 0x06, 0x96, 0xae, 0xe3, 0x08, 0xf2, 0x41, 0x3f, 0xff, 0xf5, 0x1f, 0x72, 0xff, 0xfd, 0xff, 0xd8, 0x70, 0xd2, 0xe7, 0x33, 0xca, 0xd3, 0xfb, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xa8, 0xa7, 0xfc, - 0x1c, 0x3e, 0xf7, 0x58, 0x25, 0xd5, 0xa7, 0xff, 0xb8, 0x5c, 0xdc, 0xdc, + 0x1c, 0x3e, 0xf7, 0x78, 0x25, 0xd5, 0xa7, 0xff, 0xb8, 0x5c, 0xdc, 0xdc, 0xcb, 0xc2, 0xd8, 0x15, 0xa7, 0xdf, 0xb5, 0x55, 0x95, 0x15, 0xec, 0xf8, 0x8c, 0x5b, 0xdb, 0xd6, 0x96, 0xf8, 0x7b, 0xdf, 0x33, 0x9f, 0xfb, 0x7a, 0x7e, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x23, 0x4f, 0xfe, 0xdc, 0xf4, 0xfd, @@ -713,9 +713,9 @@ 0x24, 0xca, 0x13, 0xef, 0xda, 0xaa, 0xca, 0x8a, 0x46, 0x7f, 0x99, 0xed, 0xfb, 0xdb, 0xf7, 0xad, 0x3a, 0x9f, 0xbe, 0x1f, 0x60, 0x99, 0xcf, 0xff, 0xd8, 0x1e, 0x37, 0x9d, 0xfa, 0x34, 0x0d, 0x69, 0x80, 0x94, 0xb7, 0x3a, - 0x23, 0xae, 0x8c, 0xa7, 0xfe, 0xde, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, + 0x23, 0xae, 0xcc, 0xa7, 0xfe, 0xde, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x4a, 0x11, 0x7b, 0x25, 0xb9, 0xf2, 0xe5, 0x43, 0x08, 0xdb, 0x3a, 0x11, - 0xf9, 0x9a, 0x07, 0xe1, 0x5c, 0x72, 0x8e, 0x28, 0x81, 0x5e, 0xee, 0x57, + 0xf9, 0x9a, 0x07, 0xe1, 0x5c, 0x72, 0x8e, 0x28, 0x81, 0x5e, 0xea, 0x57, 0xd4, 0x3a, 0x7d, 0x8c, 0x74, 0xc1, 0x6c, 0xff, 0xed, 0xcf, 0x4f, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x27, 0x39, 0xff, 0xdb, 0x9e, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x51, 0x33, 0xff, 0x7d, 0xfb, 0xf0, 0xb4, 0xe3, 0xc8, @@ -726,9 +726,9 @@ 0x8b, 0x1f, 0xc8, 0x78, 0xcb, 0x43, 0x1e, 0x79, 0x0b, 0x4d, 0xad, 0x96, 0x9e, 0xeb, 0xd8, 0xd4, 0xa0, 0xe6, 0xe6, 0x85, 0xe7, 0xd5, 0x7f, 0x73, 0x8b, 0x4b, 0x7b, 0xd3, 0xd0, 0xc8, 0x46, 0x38, 0x49, 0xc8, 0x40, 0x0a, - 0xcd, 0xd1, 0x04, 0xff, 0xed, 0xcf, 0x4f, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, + 0xcd, 0xd9, 0x04, 0xff, 0xed, 0xcf, 0x4f, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x26, 0x49, 0xfd, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x5b, 0xd3, 0xff, 0xb7, - 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xa4, 0xe6, 0x32, 0xae, 0xc5, + 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xa4, 0xe6, 0x32, 0xae, 0x95, 0xa7, 0xed, 0x81, 0xe7, 0xf4, 0x05, 0xa6, 0xe6, 0xe6, 0x59, 0xe8, 0x51, 0x04, 0x32, 0xbe, 0xb7, 0xca, 0x0f, 0xc6, 0xcd, 0x2b, 0xdc, 0x3f, 0xf3, 0x0a, 0x79, 0xfd, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x43, 0xb3, 0xff, 0xb7, @@ -748,7 +748,7 @@ 0x5d, 0x5a, 0x7f, 0xff, 0xee, 0x7a, 0x12, 0xcf, 0xb8, 0x39, 0x73, 0x98, 0x16, 0xd6, 0x98, 0xd5, 0xa7, 0xff, 0x13, 0x8f, 0xcd, 0x9f, 0xe0, 0xf5, 0x42, 0xb4, 0xd4, 0x61, 0x69, 0x19, 0x78, 0x8f, 0x7b, 0x10, 0xf1, 0xd2, - 0x92, 0xe6, 0xba, 0x35, 0x69, 0xf7, 0x2b, 0xb4, 0xf5, 0xa7, 0xf3, 0xf4, + 0x92, 0xe6, 0xbb, 0x35, 0x69, 0xf7, 0x2b, 0xb4, 0xf5, 0xa7, 0xf3, 0xf4, 0xda, 0x32, 0x73, 0x28, 0xca, 0x5a, 0x78, 0xb4, 0x40, 0x5a, 0x73, 0xae, 0xba, 0x94, 0xfa, 0x87, 0xbc, 0xc4, 0xb7, 0x2f, 0xe7, 0xd5, 0xd7, 0x33, 0xab, 0x40, 0x51, 0x36, 0x03, 0xf1, 0x35, 0x9e, 0xe5, 0x55, 0x2d, 0x3f, @@ -765,11 +765,11 @@ 0xe7, 0x81, 0xd2, 0xbd, 0x69, 0xfd, 0xde, 0x10, 0x83, 0xc9, 0xd6, 0x9f, 0xd7, 0xb1, 0xc5, 0xb6, 0x02, 0xd2, 0x67, 0x9f, 0x3d, 0x1a, 0x43, 0x2a, 0xc0, 0xc7, 0xb2, 0x28, 0xfc, 0x68, 0x34, 0x5a, 0x30, 0x89, 0x9f, 0xfe, - 0xf9, 0x7b, 0x77, 0x37, 0x8d, 0x7a, 0x03, 0xe7, 0x56, 0x9b, 0xd7, 0xad, + 0xf9, 0x7b, 0x75, 0x37, 0x8d, 0x7a, 0x03, 0xe7, 0x56, 0x9b, 0xd7, 0xad, 0x3e, 0x60, 0x6a, 0xfe, 0xad, 0x3a, 0xbb, 0xa5, 0xa6, 0xf6, 0xf5, 0xa7, 0x0f, 0x5c, 0x79, 0xb3, 0xf8, 0xdc, 0xfd, 0xed, 0xbc, 0x07, 0x67, 0x56, 0x86, 0x3e, 0x62, 0x33, 0x9f, 0xff, 0x7a, 0xdd, 0xf0, 0x3e, 0x98, 0xf1, - 0x9d, 0xba, 0xce, 0xad, 0x3f, 0xf7, 0x18, 0xdf, 0x1d, 0x1a, 0xeb, 0x75, + 0x9d, 0xbb, 0xce, 0xad, 0x3f, 0xf7, 0x18, 0xdf, 0x1d, 0x1a, 0xeb, 0x75, 0x69, 0xfd, 0xe3, 0x67, 0x97, 0x3d, 0x3a, 0xd0, 0x03, 0xfc, 0x14, 0x59, 0xff, 0x7d, 0xcf, 0x1a, 0x62, 0xbe, 0xba, 0xb4, 0x31, 0xf1, 0x7a, 0x43, 0x3f, 0xff, 0xfd, 0xe8, 0xeb, 0xe2, 0xce, 0x78, 0xf3, 0xd2, 0x7e, 0x6d, @@ -794,7 +794,7 @@ 0x36, 0x7e, 0x7a, 0x20, 0xd2, 0xd2, 0xe9, 0x22, 0xc7, 0x44, 0x93, 0xfe, 0x6b, 0x78, 0x1a, 0xd1, 0xd8, 0x56, 0x9f, 0xff, 0x66, 0x70, 0xad, 0xcc, 0xf1, 0xaf, 0x78, 0xc6, 0x6b, 0x4f, 0xff, 0x77, 0x98, 0x0f, 0x07, 0x6c, - 0xe8, 0x70, 0x56, 0x9f, 0xed, 0xbc, 0x1d, 0xb0, 0x7b, 0x74, 0xb4, 0xb5, + 0xe8, 0x70, 0x56, 0x9f, 0xed, 0xbc, 0x1d, 0xb0, 0x7b, 0x76, 0xb4, 0xb5, 0x88, 0x8c, 0xa4, 0xf9, 0x11, 0xd3, 0x49, 0x13, 0xde, 0xc3, 0x96, 0x7c, 0xf6, 0xd9, 0xfa, 0x5a, 0x7f, 0xff, 0xff, 0xd8, 0x26, 0xf8, 0x2e, 0x7b, 0xbb, 0x85, 0xd6, 0x38, 0xd1, 0xbc, 0x2d, 0xf3, 0x9b, 0x01, 0x82, 0x94, @@ -806,13 +806,13 @@ 0xb8, 0x39, 0xab, 0x8b, 0x4f, 0xff, 0x88, 0x7b, 0xcc, 0x31, 0xd7, 0x30, 0xce, 0x84, 0x0b, 0x4f, 0x99, 0xdf, 0x1a, 0x71, 0x69, 0xff, 0x98, 0x6f, 0x1c, 0xb9, 0xaf, 0x5b, 0x65, 0xa0, 0x93, 0x4b, 0xd4, 0x20, 0xba, 0xb1, - 0xe9, 0x5c, 0xf6, 0x77, 0x2e, 0xe5, 0xa7, 0x5d, 0x67, 0x16, 0x9b, 0x02, + 0xe9, 0x5c, 0xf6, 0x77, 0x2e, 0xa5, 0xa7, 0x5d, 0xe7, 0x16, 0x9b, 0x02, 0xb4, 0x5e, 0xa8, 0x6d, 0xf1, 0xc0, 0x69, 0x0f, 0xa4, 0xb7, 0x07, 0xa7, 0xc5, 0xdd, 0x60, 0x16, 0x9f, 0x82, 0xc3, 0xca, 0x7a, 0xd3, 0x98, 0x2c, 0xb4, 0xfc, 0xfc, 0xee, 0xa9, 0xcf, 0x07, 0x8a, 0x72, 0xb9, 0xff, 0xf7, 0xfd, 0xff, 0xd8, 0x70, 0xd2, 0xe7, 0x33, 0xca, 0xd3, 0xde, 0xd6, 0xdd, 0x5a, 0x1e, 0x99, 0x63, 0x8d, 0x7f, 0x47, 0xe2, 0xbc, 0x2d, 0x3f, 0x6a, - 0xd6, 0xa1, 0x35, 0x68, 0xbb, 0x46, 0xdf, 0xa1, 0x53, 0x5f, 0xb2, 0xd3, + 0xd6, 0xa1, 0x35, 0x68, 0xba, 0x06, 0xdf, 0xa1, 0x53, 0x5f, 0xb2, 0xd3, 0xee, 0x51, 0x9b, 0x01, 0x68, 0xa3, 0xc1, 0x30, 0x31, 0x3f, 0xbe, 0xe0, 0xe7, 0x2b, 0xab, 0x43, 0x22, 0xf7, 0x1a, 0x08, 0x8e, 0x7c, 0x0c, 0xef, 0x9b, 0xd6, 0x9f, 0xce, 0xf7, 0x39, 0xe3, 0x6d, 0x2d, 0x0c, 0x7c, 0x34, @@ -843,7 +843,7 @@ 0xaf, 0xa3, 0x8b, 0x7d, 0xc5, 0xa7, 0xfb, 0x6c, 0x34, 0x07, 0xcf, 0x1f, 0xc4, 0x48, 0x12, 0xec, 0xff, 0x60, 0xdf, 0xe0, 0x15, 0x4e, 0x2d, 0x3f, 0xdf, 0xbd, 0xaf, 0xbf, 0xdf, 0xde, 0xb4, 0xff, 0x7a, 0x3e, 0x35, 0xed, - 0xd7, 0xbf, 0x5a, 0x18, 0xff, 0xf4, 0x7d, 0x3f, 0xfa, 0xff, 0x1a, 0xe7, + 0xdf, 0xbf, 0x5a, 0x18, 0xff, 0xf4, 0x7d, 0x3f, 0xfa, 0xff, 0x1a, 0xe7, 0xbe, 0x3b, 0xad, 0x37, 0xd6, 0x9f, 0xff, 0xf6, 0x6d, 0xa2, 0xc7, 0x7c, 0x73, 0x3b, 0xac, 0xbf, 0xc6, 0x10, 0x56, 0x8c, 0x46, 0x09, 0x28, 0xc5, 0xeb, 0xb1, 0x81, 0x66, 0x36, 0x16, 0x76, 0x8c, 0x0f, 0x62, 0x72, 0x4f, @@ -858,7 +858,7 @@ 0x32, 0x77, 0xa0, 0xa3, 0xe5, 0xa8, 0xd1, 0x27, 0xcc, 0x3d, 0x2b, 0x8b, 0x4f, 0x77, 0x54, 0x05, 0xa7, 0xfe, 0xe1, 0x78, 0x2f, 0xfb, 0x7d, 0x7e, 0xcb, 0x4f, 0x17, 0x2a, 0xf5, 0xa7, 0xae, 0x37, 0x59, 0x69, 0xf7, 0xb7, - 0x70, 0xd7, 0x56, 0x9f, 0xb9, 0x57, 0xf8, 0x7f, 0x56, 0x9f, 0x79, 0x17, + 0x50, 0xd7, 0x56, 0x9f, 0xb9, 0x57, 0xf8, 0x7f, 0x56, 0x9f, 0x79, 0x17, 0xbc, 0xeb, 0x4f, 0xab, 0xe3, 0xb1, 0x2d, 0x0c, 0x8a, 0xb2, 0x2c, 0x01, 0x87, 0x4a, 0x60, 0x29, 0xdc, 0x61, 0x39, 0xa4, 0x36, 0x47, 0x22, 0x1e, 0xc3, 0x36, 0x7f, 0x71, 0x88, 0x6b, 0xe6, 0xad, 0x3f, 0x31, 0x0d, 0x7c, @@ -909,25 +909,25 @@ 0x96, 0xe1, 0x7d, 0xc5, 0xa6, 0xce, 0x84, 0xfc, 0xf1, 0x02, 0x7a, 0xf2, 0x1e, 0xad, 0x0c, 0xb9, 0xf7, 0x86, 0x25, 0x19, 0x67, 0xca, 0x0f, 0x08, 0xde, 0x43, 0xbe, 0x9e, 0x46, 0x13, 0xfa, 0x84, 0xaf, 0xa5, 0x93, 0xaa, - 0xd8, 0xb4, 0xff, 0x9c, 0xf1, 0xd1, 0xc7, 0x70, 0xb4, 0xb4, 0x5d, 0xe7, + 0xd8, 0xb4, 0xff, 0x9c, 0xf1, 0xd1, 0xc7, 0x70, 0xb4, 0xb4, 0x5d, 0x67, 0xb4, 0xc3, 0x53, 0x83, 0xe1, 0xc5, 0xa7, 0xff, 0xb6, 0x78, 0xb7, 0x83, 0x8b, 0x1b, 0xd2, 0xbd, 0x68, 0xc3, 0xf1, 0x21, 0xf9, 0xf9, 0xbf, 0xe0, - 0x6e, 0x3a, 0xb4, 0xfd, 0x7b, 0x8f, 0xbb, 0xff, 0x7a, 0xd3, 0xe3, 0x90, + 0x6e, 0x3a, 0xb4, 0xfd, 0x7b, 0x8f, 0xba, 0xff, 0x7a, 0xd3, 0xe3, 0x90, 0x70, 0x2b, 0x49, 0xc5, 0xa6, 0x63, 0xad, 0x2e, 0xad, 0x1f, 0x34, 0xb4, 0x2b, 0x01, 0x3d, 0x6e, 0x1b, 0x4f, 0x77, 0x55, 0xb2, 0xd3, 0x39, 0x4b, 0x4f, 0xee, 0x17, 0xf6, 0x78, 0xb2, 0xd0, 0x65, 0x26, 0x7c, 0xc6, 0xd8, 0xf8, 0x44, 0x47, 0x22, 0xf4, 0x5a, 0x7f, 0x68, 0xb6, 0x76, 0x84, 0x0b, 0x4f, 0xff, 0xcc, 0x71, 0xcb, 0x6d, 0xd1, 0xae, 0x1d, 0xb3, 0xab, 0x4f, 0xff, 0x9b, 0xed, 0x6c, 0x3b, 0x59, 0xe5, 0xaf, 0x4e, 0xb4, 0x38, 0x8d, - 0xfe, 0x19, 0xdd, 0x2c, 0x4f, 0xdf, 0xc6, 0x35, 0x85, 0x69, 0xc3, 0x47, - 0x5a, 0x60, 0x32, 0xd0, 0xf3, 0xda, 0x22, 0xb1, 0x1a, 0x8b, 0xb1, 0xf0, - 0x84, 0xae, 0xf8, 0xc3, 0xae, 0xda, 0x33, 0x4a, 0x57, 0xbe, 0x11, 0x2f, + 0xfe, 0x19, 0xdd, 0xac, 0x4f, 0xdf, 0xc6, 0x35, 0x85, 0x69, 0xc3, 0x47, + 0x5a, 0x60, 0x32, 0xd0, 0xf3, 0xda, 0x22, 0xb1, 0x1a, 0x8b, 0xa5, 0xf0, + 0x84, 0xae, 0xb8, 0xc3, 0xae, 0x8a, 0x33, 0x4a, 0x57, 0xbe, 0x11, 0x2f, 0x2b, 0x0c, 0xad, 0xcc, 0xa4, 0x15, 0x1b, 0x1a, 0xdd, 0xa7, 0x01, 0xf6, 0x95, 0x50, 0x51, 0xc0, 0xb9, 0x1f, 0x0f, 0xe5, 0x8d, 0x9e, 0x3d, 0xfe, 0x52, 0x62, 0x2a, 0x50, 0x48, 0x21, 0x70, 0x33, 0xf3, 0xda, 0x96, 0x91, - 0xd9, 0xdf, 0xff, 0x61, 0xfd, 0x72, 0x12, 0xee, 0x90, 0x5d, 0x46, 0xdf, + 0xd9, 0xdf, 0xff, 0x61, 0xfd, 0x72, 0x12, 0xee, 0x90, 0x5d, 0xc6, 0xdf, 0xe6, 0x33, 0xa3, 0x10, 0x8e, 0x9f, 0xff, 0xbd, 0xb6, 0xfb, 0x77, 0xed, - 0x9b, 0x5d, 0xe1, 0xaa, 0x35, 0x68, 0xdd, 0x54, 0x21, 0x4a, 0x20, 0x9f, + 0x9b, 0x5d, 0x61, 0xaa, 0x35, 0x68, 0xdd, 0x54, 0x21, 0x4a, 0x20, 0x9f, 0xdb, 0xe7, 0xed, 0x55, 0x65, 0x45, 0x3b, 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0xa8, 0xe7, 0xfd, 0x4f, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x26, 0x88, 0xc3, 0xfd, 0x39, 0x9c, 0xfe, 0xf3, 0x57, 0x37, 0xe9, 0x5e, 0xb4, 0x6e, 0x7b, @@ -935,14 +935,14 @@ 0xcf, 0x56, 0x96, 0xf8, 0x7c, 0x3f, 0x33, 0x9f, 0x7e, 0xd5, 0x56, 0x54, 0x56, 0xd3, 0xfc, 0xfd, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0x41, 0x96, 0xf8, 0x7f, 0x14, 0x67, 0x3f, 0xf6, 0xf4, 0xfd, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, - 0x43, 0x9f, 0xf3, 0xf8, 0xdd, 0xd1, 0x91, 0xab, 0xb0, 0x56, 0x9f, 0xfc, + 0x43, 0x9f, 0xf3, 0xf8, 0xdd, 0xd1, 0x91, 0xab, 0xa4, 0x56, 0x9f, 0xfc, 0x64, 0x8c, 0x91, 0x91, 0xc6, 0x38, 0xd7, 0x0b, 0xeb, 0x4b, 0x65, 0xa6, 0x21, 0x5a, 0x02, 0x69, 0x5c, 0x11, 0x9f, 0x66, 0x08, 0x34, 0xb4, 0xff, 0xbf, 0xdf, 0x23, 0x56, 0xc1, 0xb2, 0xd3, 0xd6, 0xaa, 0xb2, 0xa2, 0xc4, - 0x8c, 0x3e, 0xbf, 0x9f, 0x4f, 0xb3, 0xec, 0x26, 0xad, 0x3e, 0xf3, 0x75, + 0x8c, 0x3e, 0xbf, 0x9f, 0x4f, 0xb3, 0xec, 0x26, 0xad, 0x3e, 0xf3, 0x77, 0x9f, 0x65, 0xa7, 0x69, 0x85, 0x69, 0x71, 0x8f, 0x14, 0x8a, 0xe7, 0xfe, 0x6c, 0xd6, 0x08, 0x48, 0x0c, 0x2b, 0x4e, 0x16, 0xbd, 0x69, 0x3c, 0x4f, - 0x6b, 0xd3, 0xf9, 0xd7, 0x44, 0x05, 0xa7, 0xc5, 0x73, 0xda, 0xd2, 0xd3, + 0x6b, 0xd3, 0xf9, 0xd7, 0x64, 0x05, 0xa7, 0xc5, 0x73, 0xda, 0xd2, 0xd3, 0xfc, 0x1e, 0x61, 0xf2, 0xbf, 0x7a, 0xd3, 0xee, 0xf6, 0x9f, 0xa5, 0xa7, 0xfd, 0xee, 0x6c, 0x1b, 0x9c, 0xca, 0x71, 0x68, 0xd8, 0xfa, 0x6e, 0x13, 0xcc, 0xcf, 0x5a, 0x19, 0x1b, 0x79, 0x0a, 0x1f, 0x92, 0xcf, 0xf3, 0x6b, @@ -955,7 +955,7 @@ 0xdf, 0xe5, 0x16, 0x8a, 0xe2, 0xd0, 0xc7, 0xa7, 0x84, 0x10, 0x48, 0xdf, 0x14, 0x2d, 0x3e, 0xcf, 0xce, 0xb7, 0xff, 0x4e, 0x2d, 0x3e, 0xbf, 0xad, 0xb3, 0xd6, 0x86, 0x3d, 0x7a, 0x2e, 0x9f, 0xf0, 0xb1, 0x07, 0xa3, 0x5b, - 0x69, 0x68, 0xbb, 0x17, 0xe1, 0x0c, 0x9d, 0x21, 0x9f, 0x82, 0x45, 0x90, + 0x69, 0x68, 0xba, 0x57, 0xe1, 0x0c, 0x9d, 0x21, 0x9f, 0x82, 0x45, 0x90, 0x90, 0x34, 0x86, 0xcd, 0x7b, 0x42, 0x00, 0x8a, 0x1c, 0x1e, 0xfc, 0x60, 0x87, 0x33, 0xe4, 0x31, 0x2a, 0x15, 0x60, 0x23, 0xd4, 0x62, 0x1d, 0x84, 0x2f, 0x92, 0x09, 0xff, 0xb8, 0x4d, 0xde, 0x51, 0xb8, 0x20, 0x5a, 0x7f, @@ -978,10 +978,10 @@ 0x41, 0xe1, 0x1d, 0x69, 0xfb, 0xa5, 0x81, 0x63, 0xad, 0x1d, 0x3d, 0x87, 0x4b, 0x66, 0xd0, 0xad, 0x3f, 0x6d, 0xa6, 0xb6, 0x1d, 0x68, 0xfa, 0x36, 0x29, 0xcf, 0x44, 0x7e, 0x8a, 0xcf, 0x70, 0xd0, 0x9d, 0x69, 0xb1, 0xeb, - 0x46, 0x1b, 0x81, 0x23, 0x8b, 0xb1, 0x71, 0x99, 0xa1, 0x38, 0xf2, 0x20, + 0x46, 0x1b, 0x81, 0x23, 0x8b, 0xa5, 0x71, 0x99, 0xa1, 0x38, 0xf2, 0x20, 0x8c, 0x64, 0x24, 0x88, 0x8b, 0xe4, 0x1c, 0x8c, 0x10, 0x05, 0xa3, 0x0f, 0x7e, 0xba, 0xcf, 0xd5, 0xb6, 0xe7, 0xae, 0xad, 0x1b, 0xa3, 0x7c, 0x61, - 0x63, 0x3f, 0xe2, 0xd5, 0xf8, 0xee, 0xe6, 0x41, 0x95, 0x76, 0x2d, 0x3f, + 0x63, 0x3f, 0xe2, 0xd5, 0xf8, 0xee, 0xe6, 0x41, 0x95, 0x74, 0xad, 0x3f, 0xea, 0x7e, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x4a, 0x4f, 0xf3, 0xf7, 0xcf, 0xda, 0xaa, 0xca, 0x89, 0x3a, 0x5b, 0x9d, 0x11, 0xf4, 0x95, 0x0c, 0xfb, 0x80, 0xf7, 0xc7, 0xe0, 0x1b, 0xc4, 0xf4, 0xc2, 0xcb, 0x46, 0x2a, 0x50, @@ -999,11 +999,11 @@ 0xb9, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x44, 0xcb, 0x3f, 0xb7, 0xcf, 0xda, 0xaa, 0xca, 0x8a, 0x92, 0x7f, 0x6f, 0x9f, 0xb5, 0x55, 0x95, 0x15, 0xd4, 0xfe, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x2c, 0x59, 0xff, 0x8f, 0x4f, - 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x27, 0xa9, 0xfe, 0x77, 0x7a, 0x62, 0xba, - 0x23, 0x0b, 0x4f, 0xfb, 0xdd, 0x72, 0x9f, 0xbd, 0xd9, 0xae, 0xad, 0x3f, + 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x27, 0xa9, 0xfe, 0x77, 0x7a, 0x62, 0xbb, + 0x23, 0x0b, 0x4f, 0xfb, 0xdd, 0x72, 0x9f, 0xbd, 0xd3, 0xae, 0xad, 0x3f, 0xea, 0xdb, 0x71, 0xce, 0xe8, 0x8e, 0xb4, 0xbb, 0xf4, 0x42, 0x69, 0x1a, 0x37, 0x4c, 0xe9, 0x94, 0x0a, 0x18, 0x33, 0xec, 0xe9, 0x7b, 0xa5, 0xa6, - 0x32, 0x0c, 0x9d, 0x68, 0x32, 0x73, 0xc9, 0xbb, 0x44, 0xf3, 0xfd, 0x77, + 0x32, 0x0c, 0x9d, 0x68, 0x32, 0x73, 0xc9, 0xba, 0x04, 0xf3, 0xfd, 0x75, 0xf9, 0x1c, 0xff, 0xda, 0xcb, 0x4f, 0x7c, 0xfd, 0xd9, 0x69, 0xd6, 0xce, 0x25, 0x38, 0xed, 0xa5, 0xa7, 0xff, 0xee, 0x0d, 0x1a, 0x5f, 0x67, 0xbf, 0x34, 0x00, 0x32, 0xd3, 0xff, 0xf7, 0xc8, 0xc5, 0x1f, 0x76, 0xff, 0xc8, @@ -1011,7 +1011,7 @@ 0x83, 0x5b, 0x68, 0xd3, 0x69, 0x68, 0xb1, 0xf8, 0x09, 0x1c, 0xff, 0xea, 0xd0, 0xe0, 0x37, 0xe1, 0x5a, 0xbe, 0xb4, 0xfc, 0x1c, 0x37, 0xb9, 0x65, 0xa7, 0xb8, 0xc7, 0xb2, 0xd1, 0x47, 0x9d, 0xd2, 0xd9, 0xff, 0xc3, 0xe1, - 0x98, 0x58, 0xfe, 0x3c, 0x72, 0xe9, 0x69, 0xab, 0x65, 0xa7, 0xf5, 0x6a, + 0x98, 0x58, 0xfe, 0x3c, 0x72, 0xed, 0x69, 0xab, 0x65, 0xa7, 0xf5, 0x6a, 0xb9, 0xe8, 0xde, 0xb4, 0x09, 0xe4, 0xfa, 0x2d, 0x17, 0xaa, 0xd8, 0x21, 0xbf, 0xac, 0x9e, 0x1a, 0x3c, 0x21, 0x18, 0x4b, 0x74, 0x84, 0xc4, 0x26, 0x67, 0x0d, 0x75, 0x69, 0xc2, 0x5a, 0x5a, 0x4e, 0x99, 0x66, 0xd1, 0x86, @@ -1025,12 +1025,12 @@ 0xf5, 0xa3, 0x0f, 0xb2, 0x86, 0xc4, 0x92, 0x7d, 0xe9, 0xba, 0x0b, 0x2d, 0x18, 0x8f, 0xc2, 0x85, 0x3f, 0x0b, 0x27, 0xff, 0xff, 0x71, 0x8b, 0xff, 0x6f, 0x3d, 0x21, 0xf5, 0xf9, 0xa0, 0xfb, 0x5f, 0x7a, 0xd3, 0xeb, 0xc3, - 0xf2, 0x75, 0x69, 0xf8, 0x35, 0xf0, 0x5d, 0x62, 0xd3, 0xcf, 0xe7, 0x9b, + 0xf2, 0x75, 0x69, 0xf8, 0x35, 0xf0, 0x5d, 0xe2, 0xd3, 0xcf, 0xe7, 0x9b, 0x8b, 0x4f, 0xf8, 0x49, 0xfd, 0xe6, 0x7c, 0xb4, 0xb4, 0xff, 0xab, 0x00, 0xc3, 0x41, 0xc3, 0x56, 0x87, 0x9f, 0xb8, 0x0f, 0x27, 0xf5, 0x6d, 0xae, 0xf7, 0x0c, 0xd6, 0x9f, 0xfc, 0xd9, 0xb7, 0x78, 0xdd, 0x16, 0x06, 0x96, 0x9d, 0xae, 0x1d, 0x68, 0xe9, 0xf2, 0x7a, 0x91, 0x3f, 0x7b, 0xae, 0xeb, - 0x3a, 0xb4, 0xe7, 0x5d, 0x75, 0x29, 0xff, 0xdd, 0x2e, 0xeb, 0x85, 0x75, + 0x3a, 0xb4, 0xe7, 0x5d, 0x75, 0x29, 0xff, 0xdd, 0x2e, 0xeb, 0x85, 0x77, 0xe7, 0xec, 0xf4, 0xb7, 0x2f, 0xe0, 0x91, 0x57, 0xea, 0x6c, 0xff, 0xff, 0x17, 0x5e, 0xc3, 0x9d, 0xe1, 0x67, 0x58, 0xe5, 0xf7, 0xad, 0x0f, 0x56, 0xfb, 0x8f, 0x24, 0x52, 0xe1, 0x7f, 0xe1, 0x3a, 0x72, 0x21, 0x84, 0xd7, @@ -1045,7 +1045,7 @@ 0x20, 0x5a, 0x6f, 0x4e, 0xb4, 0x11, 0xe2, 0x70, 0xb6, 0x7f, 0x35, 0x7f, 0x8e, 0xd0, 0x52, 0x99, 0xd7, 0x52, 0x80, 0x9e, 0x53, 0xa6, 0x53, 0xba, 0x46, 0x69, 0x6e, 0x68, 0xe7, 0xed, 0xac, 0x5a, 0xe1, 0x2d, 0x3d, 0xeb, - 0xfd, 0xea, 0xd0, 0x49, 0xba, 0x38, 0xcd, 0xa8, 0x47, 0x74, 0xbe, 0xe8, + 0xfd, 0xea, 0xd0, 0x49, 0xba, 0x38, 0xcd, 0xa8, 0x47, 0x74, 0xbe, 0xec, 0xb6, 0x67, 0x74, 0xb4, 0xb1, 0x69, 0x6d, 0x86, 0x9b, 0xa2, 0xf3, 0xff, 0x6b, 0x41, 0x16, 0x0f, 0x1b, 0xba, 0x5a, 0x18, 0xfa, 0xbd, 0x27, 0x9f, 0xf7, 0x4b, 0xf4, 0x03, 0x1d, 0xce, 0x2d, 0x3f, 0xc4, 0xe8, 0xe7, 0x4b, @@ -1059,7 +1059,7 @@ 0xcc, 0x0a, 0x10, 0x2d, 0x3f, 0xff, 0xc7, 0xa1, 0xd9, 0xfb, 0xbb, 0x85, 0x73, 0x07, 0x03, 0x4f, 0x5c, 0x5e, 0xb3, 0xdd, 0x1f, 0x6f, 0x5a, 0x09, 0x12, 0xe2, 0xe9, 0x0c, 0x9a, 0xbd, 0x15, 0xe8, 0xcf, 0xd8, 0x6c, 0x4f, - 0xb6, 0x7d, 0xde, 0x64, 0x5d, 0x8b, 0x4f, 0xff, 0x67, 0x75, 0x8e, 0x71, + 0xb6, 0x7d, 0xd6, 0x64, 0x5d, 0x2b, 0x4f, 0xff, 0x67, 0x75, 0x8e, 0x71, 0xae, 0x67, 0x38, 0xcb, 0x4f, 0xff, 0xff, 0x8b, 0x36, 0xd1, 0x63, 0xbe, 0x33, 0x67, 0xe8, 0xbb, 0xa2, 0xd8, 0x21, 0xf6, 0xf5, 0xa7, 0xff, 0xc4, 0x21, 0xf1, 0xe7, 0xa5, 0xaa, 0x21, 0xf5, 0xeb, 0x40, 0xa6, 0x61, 0xd5, @@ -1071,7 +1071,7 @@ 0x73, 0xd6, 0x9f, 0xff, 0xfd, 0xd6, 0x0f, 0x3d, 0xa3, 0x4f, 0x41, 0xcc, 0x13, 0x75, 0xac, 0x10, 0x2d, 0x0f, 0x54, 0x34, 0x11, 0xcd, 0xa3, 0x57, 0x23, 0x09, 0xfe, 0xce, 0xf1, 0xbf, 0xdc, 0xb2, 0xd3, 0x9b, 0xee, 0x2d, - 0x0c, 0xb9, 0x0d, 0x91, 0xb4, 0x11, 0xbd, 0x4a, 0x4f, 0x14, 0x5b, 0xa3, + 0x0c, 0xb9, 0x0d, 0x91, 0xb4, 0x11, 0xbd, 0x4a, 0x4f, 0x14, 0x5b, 0xb3, 0x79, 0xda, 0xa7, 0x16, 0x9e, 0xce, 0xd1, 0x85, 0xa3, 0x63, 0x7c, 0x23, 0x93, 0xfe, 0xa1, 0x0e, 0x0f, 0xaf, 0xcd, 0x2d, 0x3c, 0xd9, 0xe4, 0x2b, 0x4f, 0xe3, 0x4b, 0xb5, 0xc7, 0x4c, 0xd6, 0x9f, 0xef, 0xe3, 0x9c, 0xcd, @@ -1088,12 +1088,12 @@ 0x69, 0xfd, 0x80, 0xc7, 0x1b, 0x6d, 0x2d, 0x0c, 0x79, 0xd8, 0x37, 0x3f, 0x72, 0x9e, 0xda, 0x7a, 0xd3, 0xfd, 0x9c, 0x2d, 0xb5, 0xcf, 0x74, 0xb4, 0xd8, 0x36, 0x3e, 0x60, 0x16, 0x4f, 0xc3, 0x40, 0x0e, 0x0a, 0xd3, 0xf1, - 0xca, 0xeb, 0x3e, 0x6a, 0xd3, 0x9d, 0x75, 0xd4, 0xa7, 0xfe, 0x6f, 0x8f, + 0xca, 0xef, 0x3e, 0x6a, 0xd3, 0x9d, 0x75, 0xd4, 0xa7, 0xfe, 0x6f, 0x8f, 0xb5, 0xe7, 0x1c, 0x63, 0xad, 0xb9, 0x7f, 0x0c, 0xb9, 0x89, 0x91, 0x94, 0x99, 0x97, 0xb9, 0x0c, 0xef, 0xa5, 0x9c, 0xce, 0x8c, 0x85, 0xbb, 0x50, 0x86, 0xe9, 0x67, 0xa5, 0x4e, 0xa7, 0xcf, 0xeb, 0x70, 0x8c, 0x18, 0xf4, - 0xd5, 0xa5, 0x77, 0x2d, 0x22, 0x5a, 0x7f, 0xba, 0xdf, 0xd7, 0x18, 0x7a, - 0xb4, 0xae, 0xe5, 0xa7, 0xfb, 0xad, 0xfd, 0x71, 0x87, 0xab, 0x4d, 0xa6, + 0xd5, 0xa5, 0x75, 0x2d, 0x22, 0x5a, 0x7f, 0xba, 0xdf, 0xd7, 0x18, 0x7a, + 0xb4, 0xae, 0xa5, 0xa7, 0xfb, 0xad, 0xfd, 0x71, 0x87, 0xab, 0x4d, 0xa6, 0x5a, 0x71, 0xc2, 0xcb, 0x4f, 0xe1, 0xed, 0x39, 0xa6, 0xea, 0xd0, 0x47, 0x9b, 0x43, 0x73, 0xc5, 0x59, 0x65, 0xa7, 0xfd, 0x97, 0x07, 0x34, 0xe0, 0xb0, 0x56, 0x9e, 0xb0, 0x5a, 0xf5, 0xa6, 0x03, 0x2d, 0x3b, 0x45, 0xf5, @@ -1111,7 +1111,7 @@ 0x9d, 0xa2, 0x0a, 0xe4, 0x12, 0x99, 0xd7, 0x57, 0x20, 0x94, 0x59, 0x14, 0xae, 0x14, 0xf4, 0xbd, 0xd2, 0x89, 0xab, 0xa9, 0x90, 0x49, 0xb9, 0xbf, 0x9f, 0xb3, 0x99, 0x82, 0x6a, 0xd3, 0xa8, 0x41, 0xe1, 0x7c, 0x69, 0xa7, - 0x30, 0xcf, 0x0c, 0x01, 0x8c, 0xe3, 0xa6, 0x93, 0xd7, 0x59, 0x5c, 0x5a, + 0x30, 0xcf, 0x0c, 0x01, 0x8c, 0xe3, 0xa6, 0x93, 0xd7, 0x79, 0x5c, 0x5a, 0x58, 0x66, 0x89, 0x30, 0x38, 0x49, 0xeb, 0x4f, 0xe7, 0x1f, 0xed, 0xfd, 0x2b, 0xd2, 0x9f, 0xc4, 0xff, 0x6b, 0x5c, 0x25, 0xa7, 0xec, 0xb9, 0x47, 0xce, 0x2d, 0x27, 0xa5, 0x3a, 0xbf, 0x7a, 0x50, 0x94, 0x31, 0xb6, 0xb0, @@ -1128,21 +1128,21 @@ 0x2c, 0xe2, 0xd3, 0xff, 0xff, 0xbd, 0xff, 0xae, 0x0d, 0x03, 0x5a, 0xc3, 0x73, 0xdf, 0xd0, 0x5b, 0x8c, 0xb4, 0xe7, 0x5d, 0x75, 0x29, 0x9e, 0xc9, 0x6e, 0x5f, 0xc3, 0x26, 0x27, 0x7a, 0xaf, 0xe1, 0x33, 0x3f, 0x5e, 0xe3, - 0xee, 0xff, 0xde, 0xb4, 0xf7, 0x2b, 0x67, 0x56, 0x9f, 0x5f, 0xf2, 0x63, + 0xee, 0xbf, 0xde, 0xb4, 0xf7, 0x2b, 0x67, 0x56, 0x9f, 0x5f, 0xf2, 0x63, 0xad, 0x3f, 0xfc, 0xde, 0x7a, 0x2c, 0x0a, 0xe8, 0x3c, 0x8b, 0xd6, 0x83, 0x29, 0x1a, 0x24, 0x6d, 0x44, 0x7d, 0x27, 0x9d, 0xe4, 0x2e, 0x2d, 0x39, 0xe4, 0x2b, 0x4f, 0x5f, 0xe4, 0xc3, 0xab, 0x4f, 0xdd, 0x67, 0x07, 0xdd, 0x2d, 0x17, 0xa2, 0x3d, 0xe3, 0xf4, 0x35, 0xd2, 0x89, 0xab, 0x4b, 0x4d, - 0xed, 0xdc, 0xb4, 0x09, 0xb1, 0xf4, 0x56, 0x6a, 0xde, 0xec, 0x76, 0x1b, - 0x57, 0x79, 0x7d, 0xdb, 0x3e, 0x32, 0x44, 0x6d, 0x2b, 0xce, 0xf8, 0xcc, + 0xed, 0xd4, 0xb4, 0x09, 0xb1, 0xf4, 0x56, 0x6a, 0xde, 0xe9, 0x76, 0x1b, + 0x57, 0x59, 0x7d, 0xd1, 0x3e, 0x32, 0x44, 0x6d, 0x2b, 0xce, 0xf8, 0xcc, 0xdf, 0x0b, 0x40, 0xc7, 0xf3, 0x92, 0xec, 0x0d, 0x86, 0xbd, 0xa1, 0xb3, 0xb4, 0x67, 0xa5, 0x1d, 0xbb, 0x91, 0xfb, 0xfe, 0x36, 0x83, 0xc7, 0x0b, 0xc9, 0xcc, 0x8a, 0x85, 0x18, 0x08, 0x46, 0x32, 0xdd, 0x4e, 0x83, 0xf6, - 0x99, 0x2d, 0xec, 0x70, 0x97, 0x51, 0x83, 0xf9, 0x86, 0x79, 0x86, 0xe9, + 0x99, 0x2d, 0xec, 0x70, 0x97, 0x71, 0x83, 0xf9, 0x86, 0x79, 0x86, 0xe9, 0xff, 0xdb, 0x9e, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x51, 0x53, 0xfb, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xba, 0x27, 0xfe, 0xde, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x49, 0x73, 0xef, 0xda, 0xaa, 0xca, 0x8b, 0xca, 0x6a, - 0xb8, 0xb4, 0xb7, 0xc3, 0xca, 0xba, 0x33, 0x86, 0x76, 0xf5, 0xd7, 0x94, + 0xb8, 0xb4, 0xb7, 0xc3, 0xca, 0xbb, 0x33, 0x86, 0x76, 0xf5, 0xd7, 0x94, 0x3c, 0xff, 0x0f, 0xec, 0xae, 0xe1, 0xf9, 0xcf, 0xf9, 0x1b, 0xc8, 0xdb, 0x15, 0x8d, 0x4a, 0x06, 0xea, 0xbf, 0xa7, 0xf7, 0x21, 0x37, 0x3f, 0xfb, 0x73, 0xd3, 0xf7, 0xcf, 0xda, 0xaa, 0xca, 0x89, 0x66, 0x6f, 0x78, 0xb4, @@ -1158,12 +1158,12 @@ 0x41, 0x1e, 0x05, 0x14, 0x4f, 0xff, 0x7b, 0xdd, 0x6c, 0xf6, 0x10, 0x6b, 0xc7, 0xa2, 0xb4, 0xe6, 0xeb, 0x2d, 0x22, 0x09, 0xf7, 0x5c, 0x54, 0x9b, 0x8e, 0x2d, 0x3f, 0xb6, 0xd0, 0xe7, 0xc2, 0xcb, 0x41, 0x1e, 0x4d, 0x0b, - 0xcf, 0x77, 0x9e, 0xdd, 0x2d, 0x3f, 0xdd, 0x27, 0x74, 0xdc, 0xa3, 0x35, + 0xcf, 0x77, 0x9e, 0xdd, 0xad, 0x3f, 0xdd, 0x27, 0x74, 0xdc, 0xa3, 0x35, 0xa5, 0x84, 0x7c, 0x27, 0x26, 0x9f, 0xf7, 0x18, 0xb8, 0x4c, 0x2e, 0x7a, 0xb4, 0xed, 0x13, 0xab, 0x4f, 0xec, 0xd3, 0x77, 0x5c, 0x25, 0xa7, 0xf8, - 0x58, 0x7a, 0x57, 0x8b, 0x2d, 0x2d, 0xee, 0xc5, 0xde, 0x1b, 0xc5, 0xf2, + 0x58, 0x7a, 0x57, 0x8b, 0x2d, 0x2d, 0xee, 0x95, 0xde, 0x1b, 0xc5, 0xf2, 0x3f, 0x8d, 0x99, 0x5c, 0x85, 0x27, 0x18, 0xea, 0x11, 0xc0, 0x72, 0x18, - 0x40, 0xe8, 0x9a, 0xe1, 0xed, 0xd0, 0xe7, 0x93, 0x19, 0xff, 0xdb, 0x9e, + 0x40, 0xe8, 0x9a, 0xe1, 0xed, 0xd8, 0xe7, 0x93, 0x19, 0xff, 0xdb, 0x9e, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x4d, 0x33, 0xff, 0xb7, 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0x9c, 0x67, 0xff, 0x6e, 0x7a, 0x7e, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x40, 0xcf, 0xbf, 0x6a, 0xab, 0x2a, 0x2e, 0x09, @@ -1183,7 +1183,7 @@ 0x4b, 0x67, 0xfd, 0xd7, 0x1b, 0xbc, 0xa7, 0x3c, 0x62, 0xd3, 0xff, 0x88, 0xe3, 0xef, 0x0b, 0xf9, 0xa7, 0x19, 0x69, 0xff, 0xbd, 0xef, 0xfd, 0x73, 0x56, 0xa7, 0x34, 0xb4, 0xff, 0xd8, 0xe7, 0xa3, 0x7e, 0xad, 0x4e, 0x69, - 0x69, 0x6f, 0x76, 0x2a, 0x0e, 0x61, 0x7c, 0x85, 0xd9, 0x11, 0x52, 0x08, + 0x69, 0x6f, 0x74, 0xaa, 0x0e, 0x61, 0x7c, 0x85, 0xd9, 0x11, 0x52, 0x08, 0xa4, 0xf5, 0x26, 0x7f, 0xf6, 0xe7, 0xa7, 0xef, 0x9f, 0xb5, 0x55, 0x95, 0x13, 0x54, 0xfe, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x2b, 0xb9, 0xeb, 0x55, 0x59, 0x51, 0x5f, 0x4e, 0x75, 0xd7, 0x52, 0x90, 0xa5, 0xb9, 0x7f, 0x1f, @@ -1191,14 +1191,14 @@ 0x38, 0xed, 0x77, 0x4d, 0x97, 0xad, 0x2e, 0xad, 0x3f, 0xc5, 0xfc, 0xbc, 0x9f, 0x81, 0x5a, 0x3e, 0x78, 0xf4, 0x21, 0x2f, 0xad, 0x0b, 0x4b, 0x84, 0x5d, 0x7c, 0x42, 0x5b, 0xe2, 0x67, 0xee, 0x11, 0x50, 0xe0, 0x8e, 0x6a, - 0x10, 0xb7, 0x47, 0x73, 0xff, 0xb7, 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, + 0x10, 0xb7, 0x67, 0x73, 0xff, 0xb7, 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0x9e, 0xe7, 0xdc, 0x63, 0x15, 0xb2, 0xd3, 0xef, 0xda, 0xaa, 0xca, 0x8b, 0x86, 0x5b, 0xb1, 0xee, 0x61, 0x4c, 0xff, 0xdb, 0xd3, 0xf7, 0xcf, 0xda, 0xaa, 0xca, 0x89, 0x3e, 0x19, 0x7c, 0x22, 0xf3, 0xa7, 0x9f, 0x9b, 0x29, 0x36, 0xce, 0x4e, 0x2b, 0xfe, 0x3e, 0x9e, 0x32, 0xea, 0x16, 0x77, 0x09, 0xe7, 0xf6, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x15, 0x4f, 0xbf, 0x6a, 0xab, 0x2a, 0x29, 0x99, 0xf8, 0xb9, 0x95, 0xb0, 0x16, 0x96, 0xf8, 0x7b, - 0xf7, 0x46, 0x73, 0xff, 0xb7, 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, + 0xf7, 0x66, 0x73, 0xff, 0xb7, 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0x99, 0xe7, 0xff, 0x6e, 0x7a, 0x7e, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x46, 0xc5, 0xe9, 0xbb, 0x86, 0x13, 0xc6, 0x95, 0xf5, 0x5e, 0x7f, 0xd4, 0xfd, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0x3a, 0x9f, 0xfb, 0xf7, 0xef, 0xa1, 0xce, @@ -1211,7 +1211,7 @@ 0xfc, 0x4c, 0x7b, 0xf1, 0xd5, 0xa7, 0xff, 0xb3, 0xbc, 0xc7, 0xfe, 0x87, 0xbc, 0xa7, 0xad, 0x33, 0x01, 0x69, 0xfd, 0x5b, 0x35, 0x8a, 0xdb, 0xfd, 0x11, 0xe2, 0x5b, 0xe5, 0x36, 0x38, 0x8f, 0xfd, 0x42, 0x96, 0x5b, 0xdd, - 0x8a, 0xc5, 0x98, 0x5c, 0x24, 0x79, 0x0b, 0xeb, 0x17, 0x6c, 0x95, 0xf4, + 0x2a, 0xc5, 0x98, 0x5c, 0x24, 0x79, 0x0b, 0xeb, 0x17, 0x6c, 0x95, 0xf4, 0x6e, 0xc6, 0x71, 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0xaa, 0xa7, 0xfd, 0x4f, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x26, 0xd9, 0x6f, 0x87, 0xfa, 0x73, 0x39, 0xfd, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x57, 0xf3, 0xef, 0xda, 0xaa, 0xca, @@ -1223,10 +1223,10 @@ 0x73, 0xeb, 0x47, 0xcf, 0x6f, 0x45, 0xb3, 0xbe, 0xc7, 0x5a, 0x7a, 0x8c, 0x15, 0xeb, 0x4f, 0x18, 0x30, 0x56, 0x5a, 0x7f, 0x31, 0xea, 0xe3, 0x7c, 0xc2, 0xd3, 0xf6, 0x7e, 0xbb, 0xeb, 0x2d, 0x3f, 0xfd, 0x42, 0xc4, 0x63, - 0x45, 0xac, 0xe6, 0x5d, 0x2d, 0x27, 0x02, 0x7f, 0x97, 0x0b, 0x25, 0xbb, + 0x45, 0xac, 0xe6, 0x5d, 0xad, 0x27, 0x02, 0x7f, 0x97, 0x0b, 0x25, 0xbb, 0x27, 0xb3, 0x8f, 0x1f, 0x22, 0xe0, 0xdd, 0x11, 0xf4, 0x97, 0xcc, 0x2c, - 0x67, 0xd7, 0x7d, 0xdb, 0x01, 0xac, 0xb4, 0xfb, 0xf6, 0xaa, 0xb2, 0xa2, - 0xe9, 0x9f, 0x30, 0xd0, 0x59, 0x69, 0x6f, 0x76, 0x91, 0x15, 0x86, 0x64, + 0x67, 0xd7, 0x5d, 0xd1, 0x01, 0xac, 0xb4, 0xfb, 0xf6, 0xaa, 0xb2, 0xa2, + 0xe9, 0x9f, 0x30, 0xd0, 0x59, 0x69, 0x6f, 0x74, 0x11, 0x15, 0x86, 0x64, 0x67, 0x3f, 0xfd, 0x83, 0xd2, 0x3f, 0x18, 0x86, 0xbe, 0x6a, 0xd3, 0xff, 0x9e, 0xdf, 0x07, 0x8d, 0x71, 0x8f, 0x42, 0xb4, 0xfc, 0xfa, 0x7d, 0x0d, 0x96, 0x98, 0xfb, 0xe1, 0xfa, 0xb8, 0x95, 0x3d, 0x8e, 0x99, 0x47, 0x5a, @@ -1244,9 +1244,9 @@ 0xec, 0xcc, 0x34, 0xda, 0x7a, 0xd0, 0x6a, 0x25, 0xfa, 0xcb, 0x3e, 0xb8, 0x5f, 0xc0, 0xad, 0x3f, 0xfd, 0xae, 0x16, 0xbb, 0xcc, 0x09, 0x6b, 0x05, 0x69, 0xdc, 0x61, 0xc3, 0xf5, 0xf4, 0xa2, 0x7a, 0xd5, 0x56, 0x54, 0x49, - 0x93, 0xeb, 0x5d, 0xab, 0xbc, 0xca, 0x32, 0xd6, 0x9f, 0xd9, 0xb7, 0x7b, + 0x93, 0xeb, 0x5d, 0x0b, 0xac, 0xca, 0x32, 0xd6, 0x9f, 0xd9, 0xb7, 0x7b, 0x4f, 0xd2, 0xd0, 0xc7, 0xe1, 0xf3, 0xd8, 0x7a, 0x3c, 0x3e, 0x64, 0x78, - 0x4e, 0xcf, 0xc1, 0x01, 0x97, 0xa0, 0x5d, 0x2d, 0x3b, 0x44, 0x15, 0xa7, + 0x4e, 0xcf, 0xc1, 0x01, 0x97, 0xa0, 0x5d, 0xad, 0x3b, 0x44, 0x15, 0xa7, 0xe1, 0x6d, 0x8f, 0x5d, 0x5a, 0x7f, 0x9a, 0xdd, 0xf7, 0x9f, 0x67, 0x56, 0x9f, 0xed, 0xac, 0x5f, 0xd3, 0x8d, 0x4b, 0x4d, 0xc2, 0x71, 0x17, 0x5f, 0x1b, 0x39, 0x67, 0x4e, 0xa7, 0xba, 0x47, 0xa5, 0xa7, 0xf1, 0x73, 0x4d, @@ -1266,16 +1266,16 @@ 0x98, 0x71, 0xc2, 0xf9, 0x2d, 0x18, 0x99, 0x7e, 0x8b, 0xfa, 0x8b, 0xe9, 0xc3, 0xa7, 0x93, 0xe1, 0xce, 0x57, 0x56, 0x9f, 0xf3, 0xd8, 0x6f, 0xf3, 0xf1, 0xf5, 0xeb, 0x41, 0x99, 0xf3, 0x38, 0x4b, 0x3d, 0xdb, 0xf0, 0x2b, - 0x4f, 0xf1, 0x1b, 0xe7, 0xe0, 0x39, 0x69, 0x68, 0x70, 0xf7, 0x6e, 0x88, + 0x4f, 0xf1, 0x1b, 0xe7, 0xe0, 0x39, 0x69, 0x68, 0x70, 0xf7, 0x6e, 0xc8, 0xa7, 0x3a, 0xeb, 0xab, 0x4f, 0xff, 0xb0, 0xfd, 0x16, 0x06, 0x07, 0x58, 0x76, 0xb2, 0x5b, 0x97, 0xf3, 0xfc, 0x64, 0x7d, 0xba, 0x56, 0x20, 0xad, 0x18, 0x9b, 0x31, 0x42, 0x0f, 0x88, 0xba, 0x62, 0x9d, 0xd7, 0xf1, 0x69, 0x12, 0xd3, 0xf7, 0x1b, 0xc5, 0x8a, 0xf5, 0xa7, 0xef, 0xd7, 0xc5, 0x9e, 0xb4, 0xff, 0xf5, 0x77, 0x99, 0x73, 0x85, 0xe3, 0x5a, 0x23, 0xad, 0x17, - 0x6d, 0x17, 0x61, 0x0f, 0xf9, 0x78, 0x95, 0xcc, 0xfd, 0xee, 0xc6, 0x6a, - 0x35, 0xde, 0xd2, 0xce, 0xcf, 0x85, 0xce, 0x47, 0x12, 0x69, 0xad, 0xa1, + 0x45, 0x17, 0x61, 0x0f, 0xf9, 0x78, 0x95, 0xcc, 0xfd, 0xee, 0x96, 0x6a, + 0x35, 0xd6, 0xd2, 0xce, 0xcf, 0x85, 0xce, 0x47, 0x12, 0x69, 0xad, 0xa1, 0xe1, 0xb4, 0x69, 0x44, 0x60, 0xe4, 0x24, 0x0e, 0x51, 0x50, 0x8f, 0x18, - 0x62, 0xea, 0x50, 0x47, 0x65, 0x0c, 0x5d, 0x20, 0xf9, 0x86, 0xbc, 0xff, + 0x62, 0xea, 0x50, 0x47, 0x65, 0x0c, 0x5d, 0xa0, 0xf9, 0x86, 0xbc, 0xff, 0xef, 0xe3, 0xa1, 0xe6, 0x38, 0x39, 0xf7, 0xad, 0x3b, 0xf8, 0x66, 0xb4, 0xb3, 0xe7, 0xd0, 0x74, 0xa9, 0xfd, 0xfb, 0x7b, 0x41, 0x3b, 0x2d, 0x3f, 0xf3, 0x7f, 0xcf, 0x4b, 0xbc, 0xc0, 0x92, 0xd3, 0xfe, 0xe0, 0xb5, 0xfe, @@ -1292,10 +1292,10 @@ 0x1f, 0x93, 0x39, 0xf7, 0xed, 0x55, 0x65, 0x45, 0x8f, 0x3f, 0xc3, 0x46, 0xf0, 0x98, 0x6f, 0x5a, 0x7e, 0xc2, 0xef, 0x4b, 0xab, 0x4f, 0xb3, 0xf9, 0x8e, 0x2d, 0x2d, 0xf1, 0x17, 0x6e, 0x19, 0xe8, 0xdf, 0xc9, 0x5c, 0xeb, - 0xb4, 0x73, 0x56, 0x9f, 0x8c, 0xb1, 0xce, 0x57, 0x56, 0x9f, 0xe1, 0xa0, + 0xa0, 0x73, 0x56, 0x9f, 0x8c, 0xb1, 0xce, 0x57, 0x56, 0x9f, 0xe1, 0xa0, 0x6a, 0xbb, 0xda, 0x5a, 0x78, 0x07, 0x2f, 0xad, 0x3f, 0xff, 0xcd, 0xf1, 0xc0, 0xe7, 0x38, 0x56, 0xe1, 0x77, 0x55, 0xb2, 0xd0, 0x48, 0x85, 0xe1, - 0x0c, 0xfc, 0xdf, 0x05, 0xd7, 0xbd, 0x5a, 0x7f, 0x98, 0x7b, 0x77, 0xd7, + 0x0c, 0xfc, 0xdf, 0x05, 0xdf, 0xbd, 0x5a, 0x7f, 0x98, 0x7b, 0x75, 0xd7, 0x7d, 0x65, 0xa7, 0x55, 0x59, 0x51, 0x68, 0x4f, 0xfa, 0x9d, 0x31, 0x6a, 0xfd, 0xf8, 0xea, 0xd3, 0xf0, 0x18, 0x5b, 0xba, 0x5a, 0x2c, 0x89, 0x4f, 0x93, 0x81, 0x0a, 0x7f, 0xff, 0xf8, 0xbf, 0xca, 0x12, 0x6e, 0x97, 0x1b, @@ -1325,15 +1325,15 @@ 0x46, 0x31, 0x3a, 0x0d, 0x8c, 0xa9, 0xdb, 0x50, 0xd2, 0x9e, 0xce, 0x57, 0x56, 0x9f, 0x88, 0x7d, 0x7e, 0x69, 0x69, 0xff, 0x67, 0x5b, 0x60, 0x57, 0x38, 0x4b, 0x48, 0xeb, 0x4f, 0xc4, 0x3e, 0xbf, 0x35, 0xe0, 0xf3, 0x6e, - 0x1e, 0xc1, 0xa8, 0xc1, 0xeb, 0xcc, 0xb7, 0xbb, 0x19, 0x93, 0x17, 0x79, + 0x1e, 0xc1, 0xa8, 0xc1, 0xeb, 0xcc, 0xb7, 0xba, 0x59, 0x93, 0x17, 0x59, 0x1b, 0x18, 0x06, 0x17, 0x79, 0x1e, 0x59, 0x21, 0x9e, 0x33, 0x6e, 0x4a, - 0x53, 0x04, 0x3b, 0x06, 0x32, 0x1d, 0x43, 0x67, 0xb1, 0xe3, 0x5d, 0x21, + 0x53, 0x04, 0x3b, 0x06, 0x32, 0x1d, 0x43, 0x67, 0xb1, 0xe3, 0x5d, 0xa1, 0x79, 0x87, 0x0c, 0xfc, 0x60, 0x82, 0x2c, 0xe2, 0xd3, 0x9a, 0x85, 0x69, 0xec, 0xe5, 0x75, 0x69, 0x19, 0x78, 0x7c, 0xfc, 0x2e, 0x11, 0x99, 0xec, 0xd0, 0x09, 0x69, 0xf7, 0xed, 0x55, 0x65, 0x45, 0xad, 0x3f, 0x61, 0x8d, 0x50, 0xd9, 0x69, 0xdf, 0x63, 0xad, 0x3f, 0xea, 0x7e, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x41, 0xcf, 0x63, 0x8d, 0xd5, 0xa7, 0xf9, 0x9e, 0xdf, 0xbd, - 0xbf, 0x7a, 0xd2, 0xde, 0xef, 0x4d, 0xdd, 0xe7, 0x18, 0x40, 0xe1, 0x9f, + 0xbf, 0x7a, 0xd2, 0xde, 0xeb, 0x4d, 0xdd, 0xe7, 0x18, 0x40, 0xe1, 0x9f, 0xcb, 0x4e, 0x37, 0xc4, 0xa1, 0x21, 0x9f, 0xfd, 0xb9, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x45, 0x17, 0x3f, 0xb7, 0xcf, 0xda, 0xaa, 0xca, 0x8b, 0xaa, 0x1e, 0xd9, 0x86, 0xda, 0x12, 0x85, 0x0a, 0xa3, 0xc3, 0xe3, 0x94, @@ -1345,22 +1345,22 @@ 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0xac, 0x27, 0xc4, 0xe8, 0x7d, 0xfa, 0xd3, 0xfc, 0xfd, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0x3f, 0x9d, 0x8d, 0x7a, 0xd3, 0xfb, 0x36, 0x7d, 0x3c, 0x85, 0x69, 0xab, 0xab, 0x4b, 0x7c, 0x4c, 0x0a, - 0xc6, 0x74, 0x52, 0x28, 0xbd, 0x1b, 0xba, 0x31, 0x9f, 0xfd, 0xb9, 0xe9, + 0xc6, 0x74, 0x52, 0x28, 0xbd, 0x1b, 0xbb, 0x31, 0x9f, 0xfd, 0xb9, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x44, 0xdf, 0x3f, 0xf1, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x44, 0xfd, 0x39, 0x86, 0xcb, 0x4f, 0xe3, 0x24, 0x64, - 0x0e, 0x5e, 0xdb, 0x2d, 0x3e, 0x32, 0x8c, 0xbb, 0xac, 0xd9, 0x69, 0x71, + 0x0e, 0x5e, 0xdb, 0x2d, 0x3e, 0x32, 0x8c, 0xbb, 0xbc, 0xd9, 0x69, 0x71, 0x68, 0x32, 0x91, 0x06, 0x64, 0x1f, 0x7a, 0x6b, 0x3f, 0xc6, 0x4b, 0x95, - 0xde, 0xd5, 0x3a, 0xb4, 0xfd, 0xde, 0x15, 0x00, 0xc9, 0x2d, 0x3e, 0xbb, - 0xee, 0xd8, 0x0d, 0x65, 0xa7, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0xb6, + 0xde, 0xd5, 0x3a, 0xb4, 0xfd, 0xde, 0x15, 0x00, 0xc9, 0x2d, 0x3e, 0xba, + 0xee, 0x88, 0x0d, 0x65, 0xa7, 0xff, 0x99, 0x99, 0x99, 0x99, 0x99, 0xb6, 0xd2, 0xd3, 0xef, 0x95, 0xf4, 0x74, 0xa6, 0x75, 0xd4, 0xa3, 0x0d, 0xfb, 0xa4, 0xf2, 0xf5, 0x2d, 0xcd, 0x0c, 0x32, 0x32, 0xf5, 0x0a, 0x99, 0xf5, 0x50, 0xb1, 0x85, 0xa7, 0xfe, 0xe3, 0x17, 0xfd, 0x1f, 0x7b, 0xef, 0x56, 0x9e, 0xf8, 0x93, 0x2d, 0x39, 0xda, 0x75, 0x69, 0xff, 0xdd, 0xfd, 0x5e, 0x1e, 0x36, 0xbb, 0xef, 0x16, 0x9b, 0x0f, 0xc3, 0xe9, 0xd0, 0xec, 0xfa, 0xad, 0xc2, 0xfa, 0xd3, 0xff, 0xff, 0x86, 0x8d, 0x2f, 0xb3, 0xfc, 0x70, - 0x8e, 0x16, 0xf1, 0x75, 0xef, 0x0b, 0xeb, 0x4f, 0x53, 0xcb, 0x65, 0xa0, + 0x8e, 0x16, 0xf1, 0x77, 0xef, 0x0b, 0xeb, 0x4f, 0x53, 0xcb, 0x65, 0xa0, 0x28, 0xf2, 0xf9, 0x6f, 0x09, 0x85, 0xfa, 0x4c, 0xb4, 0xff, 0xf3, 0x6c, - 0xfa, 0x10, 0x78, 0x01, 0x7c, 0x8d, 0x5a, 0x2e, 0x8f, 0x80, 0xc0, 0x7c, + 0xfa, 0x10, 0x78, 0x01, 0x7c, 0x8d, 0x5a, 0x2e, 0xcf, 0x80, 0xc0, 0x7c, 0xf5, 0xe7, 0x27, 0xad, 0x3e, 0xd0, 0xfb, 0x4f, 0x5a, 0x7f, 0x71, 0x8f, 0xb8, 0x00, 0xcb, 0x4b, 0xec, 0x7f, 0x98, 0x44, 0x44, 0xf3, 0xfd, 0xb0, 0x7c, 0xb1, 0x9f, 0x3d, 0xd2, 0xd3, 0xff, 0xe0, 0xf1, 0xbe, 0x40, 0x6f, @@ -1416,7 +1416,7 @@ 0xfa, 0x5b, 0x9f, 0x9c, 0x3d, 0x3c, 0x3e, 0x47, 0x39, 0x0c, 0xaa, 0x8f, 0x86, 0x55, 0x29, 0x1e, 0x7f, 0xcc, 0xfa, 0x1c, 0xd7, 0xdb, 0x4b, 0x4f, 0xbf, 0xb3, 0xf3, 0xab, 0x4f, 0xee, 0x35, 0xc0, 0xb0, 0x19, 0x68, 0xf9, - 0xed, 0xf4, 0xa2, 0x7f, 0x9b, 0x67, 0xdd, 0x35, 0xb0, 0xeb, 0x4f, 0xfe, + 0xed, 0xf4, 0xa2, 0x7f, 0x9b, 0x67, 0xdd, 0xb5, 0xb0, 0xeb, 0x4f, 0xfe, 0xa3, 0x6c, 0xdd, 0xd6, 0x74, 0xb6, 0x75, 0x68, 0x64, 0x54, 0x70, 0x88, 0x4e, 0xe7, 0xff, 0xd5, 0x4f, 0xae, 0x78, 0xcb, 0xfd, 0xef, 0xb5, 0xe5, 0x51, 0x7d, 0xcf, 0xfb, 0x44, 0x3b, 0x3f, 0xfe, 0xb6, 0x96, 0x87, 0x11, @@ -1447,8 +1447,8 @@ 0x26, 0xf8, 0x17, 0x10, 0x0c, 0xfa, 0xbb, 0xa2, 0xd9, 0x71, 0x00, 0xcf, 0xc4, 0x3e, 0xbf, 0x34, 0xb8, 0x80, 0x61, 0x91, 0x20, 0x24, 0x7d, 0x34, 0x80, 0xaf, 0xff, 0xe4, 0x35, 0xdc, 0x3f, 0xfb, 0x0f, 0x08, 0x28, 0xb4, - 0x05, 0x1a, 0x95, 0xa7, 0xd8, 0xf0, 0x2e, 0xa1, 0x29, 0xe6, 0x17, 0xd3, - 0xaa, 0xac, 0xa8, 0x80, 0x77, 0x45, 0xdc, 0xf1, 0xb7, 0x6c, 0x27, 0x5a, + 0x05, 0x1a, 0x95, 0xa7, 0xd8, 0xf0, 0x2e, 0xe1, 0x29, 0xe6, 0x17, 0xd3, + 0xaa, 0xac, 0xa8, 0x80, 0x77, 0x45, 0xdc, 0xf1, 0xb7, 0x44, 0x27, 0x5a, 0x7f, 0xe7, 0x8e, 0x5b, 0x84, 0x00, 0x7a, 0xe2, 0xd3, 0x01, 0x92, 0x91, 0xa9, 0x4e, 0xe3, 0x5e, 0xb4, 0xce, 0xba, 0x94, 0x11, 0xed, 0x19, 0x8a, 0xb8, 0x22, 0xe8, 0xe4, 0xe3, 0x96, 0x92, 0xdc, 0xf0, 0x27, 0x17, 0xbd, @@ -1464,24 +1464,24 @@ 0x9f, 0x63, 0x8f, 0x6d, 0x96, 0x9d, 0xc2, 0x71, 0x69, 0xec, 0x16, 0x7a, 0x51, 0xf4, 0x43, 0x09, 0x1f, 0x4a, 0x0c, 0x0e, 0x43, 0x2a, 0xa1, 0xc2, 0xf2, 0x8d, 0x6f, 0x84, 0x95, 0x0b, 0x59, 0xfb, 0x6d, 0x7f, 0xed, 0xd5, - 0xa7, 0x88, 0x7b, 0xa5, 0xa7, 0x7b, 0x77, 0x69, 0x69, 0xff, 0x80, 0x7c, + 0xa7, 0x88, 0x7b, 0xa5, 0xa7, 0x7b, 0x75, 0x69, 0x69, 0xff, 0x80, 0x7c, 0xb7, 0x08, 0x3c, 0xf4, 0xd5, 0xa7, 0xfe, 0xd1, 0xa6, 0xd7, 0x86, 0x38, 0x91, 0xab, 0x4f, 0xf6, 0x77, 0xa4, 0x6f, 0x72, 0xcb, 0x4f, 0xe0, 0xb6, 0xda, 0xcd, 0xba, 0xb4, 0xff, 0x37, 0x4a, 0xc4, 0x16, 0xea, 0xd2, 0xd0, 0x51, 0x45, 0x87, 0x1f, 0x34, 0x8d, 0x93, 0x1e, 0xec, 0x3a, 0x67, 0xec, - 0xd7, 0x9d, 0x77, 0x16, 0x9f, 0xae, 0xb3, 0xa0, 0xae, 0xad, 0x0f, 0x3d, + 0xd7, 0x9d, 0x77, 0x16, 0x9f, 0xae, 0xf3, 0xa0, 0xae, 0xad, 0x0f, 0x3d, 0xde, 0x97, 0x43, 0x2a, 0x2f, 0x22, 0x2a, 0x8d, 0x93, 0xd8, 0x43, 0xcf, 0x70, 0xa9, 0xeb, 0x4f, 0xf3, 0xc7, 0xd0, 0x78, 0xb1, 0xc0, 0xb4, 0x9a, 0xf3, 0xdc, 0xd8, 0x82, 0x7d, 0x57, 0x02, 0x16, 0x5a, 0x6d, 0x69, 0x69, 0xce, 0xba, 0xea, 0xd3, 0x02, 0x92, 0xdc, 0xbf, 0x8f, 0x9e, 0xd6, 0x8d, 0x67, 0xfd, 0x9a, 0x1a, 0x35, 0xc1, 0x27, 0x16, 0x9d, 0x40, 0xc4, 0xa1, - 0xe8, 0xfc, 0x3c, 0x20, 0xb8, 0x45, 0x74, 0x7d, 0x3f, 0xba, 0x39, 0xb0, + 0xe8, 0xfc, 0x3c, 0x20, 0xb8, 0x45, 0x76, 0x7d, 0x3f, 0xba, 0x39, 0xb0, 0x3c, 0xbd, 0x69, 0xa8, 0xeb, 0x4f, 0xf0, 0xe5, 0xcc, 0xdd, 0xd7, 0x5d, 0x4a, 0x71, 0xeb, 0xab, 0x43, 0x87, 0xdb, 0xc1, 0x5b, 0x87, 0xb3, 0xf0, 0xdc, 0xa3, 0x91, 0xd6, 0x9f, 0x63, 0x8f, 0x67, 0xad, 0x3f, 0x5e, 0x16, 0xc1, 0x0a, 0xd0, 0xc9, 0xcc, 0x92, 0x2d, 0x42, 0x8b, 0x46, 0x5d, 0x2d, 0xf2, 0x4f, 0x3a, 0x80, 0x4b, 0x4e, 0x6f, 0x8a, 0xd3, 0xef, 0x6a, 0xfd, - 0x71, 0x69, 0x17, 0xcf, 0x0f, 0xa3, 0x50, 0x74, 0x42, 0x5d, 0xcb, 0xb3, + 0x71, 0x69, 0x17, 0xcf, 0x0f, 0xa3, 0x50, 0x74, 0x42, 0x5d, 0x4b, 0xb3, 0xff, 0xb0, 0x34, 0x7c, 0xd9, 0xf8, 0x0c, 0x0a, 0xd3, 0x72, 0x96, 0x99, 0xcd, 0x2d, 0x3e, 0xcb, 0x84, 0x21, 0xc3, 0x59, 0xe4, 0x56, 0x7d, 0xcc, 0xdb, 0xac, 0xb4, 0xf8, 0xc5, 0x5f, 0xe5, 0xeb, 0x47, 0x84, 0xc1, 0xb7, @@ -1494,20 +1494,20 @@ 0x6e, 0xbf, 0x38, 0xb4, 0xfc, 0x20, 0xc0, 0xd3, 0xd6, 0x9f, 0x53, 0xfc, 0x04, 0x96, 0x9f, 0x79, 0x71, 0xec, 0x66, 0x94, 0x32, 0x2d, 0xb0, 0xdb, 0x85, 0x7e, 0x4a, 0x27, 0xfe, 0x34, 0x7d, 0xaf, 0x39, 0xa2, 0x61, 0x5a, - 0x75, 0xd1, 0x05, 0x68, 0xf9, 0xf1, 0x1d, 0x12, 0x5e, 0x55, 0x10, 0x2c, - 0xba, 0xaa, 0x05, 0x24, 0x5d, 0x37, 0x8e, 0x8f, 0xcf, 0xf8, 0xae, 0xb8, + 0x75, 0xd9, 0x05, 0x68, 0xf9, 0xf1, 0x1d, 0x12, 0x5e, 0x55, 0x10, 0x2c, + 0xba, 0xaa, 0x05, 0x24, 0x5d, 0x37, 0x8e, 0x8f, 0xcf, 0xf8, 0xae, 0xf8, 0x5e, 0x77, 0x00, 0x19, 0x29, 0xfe, 0x1e, 0xeb, 0xdd, 0xba, 0x4e, 0xad, 0x3f, 0xbd, 0xad, 0x66, 0x09, 0xab, 0x43, 0x1f, 0x6f, 0x0e, 0xe7, 0xff, 0x11, 0xbe, 0x06, 0x8d, 0xf1, 0xa0, 0x01, 0x96, 0x9f, 0xd5, 0xcd, 0xb4, 0xc3, 0xd5, 0xa3, 0x48, 0x80, 0xea, 0x74, 0xff, 0x85, 0xb6, 0x3d, 0x77, 0x36, 0xea, 0xd3, 0xfc, 0xd6, 0xef, 0xbc, 0xfb, 0x3a, 0xb4, 0xff, 0xfe, 0xe3, 0x7c, 0x19, 0x70, 0xb5, 0xac, 0x1b, 0x50, 0x81, 0x69, 0xf3, 0x60, - 0xf6, 0xe9, 0x69, 0x1d, 0x68, 0x39, 0xb8, 0x12, 0x89, 0xcf, 0xf4, 0x2b, + 0xf6, 0xed, 0x69, 0x1d, 0x68, 0x39, 0xb8, 0x12, 0x89, 0xcf, 0xf4, 0x2b, 0x4e, 0xd5, 0x6d, 0xe0, 0xde, 0xd1, 0x04, 0x05, 0x52, 0x26, 0xd0, 0xa1, 0xf9, 0x19, 0xcf, 0xb8, 0x75, 0xd8, 0x6a, 0x43, 0x2b, 0x58, 0x29, 0x5e, 0x93, 0xff, 0xfd, 0xfb, 0xf0, 0x9c, 0xaa, 0x7e, 0x98, 0xe1, 0xe3, 0x0d, 0x96, 0x9e, 0x0f, 0x3d, 0xbd, 0x69, 0xfc, 0x1a, 0x7e, 0x5f, 0xe8, 0xad, - 0x36, 0x5e, 0xc7, 0xaf, 0x84, 0x93, 0xf7, 0x6e, 0xbd, 0xe6, 0x59, 0x69, + 0x36, 0x5e, 0xc7, 0xaf, 0x84, 0x93, 0xf7, 0x6e, 0xfd, 0xe6, 0x59, 0x69, 0xfd, 0xf6, 0xe9, 0x01, 0x9e, 0xb4, 0xeb, 0xc5, 0xeb, 0x43, 0x2e, 0xb6, 0x9d, 0x7b, 0x92, 0xdf, 0xe8, 0xa8, 0x61, 0x79, 0xa2, 0xce, 0x98, 0xfa, 0x63, 0x3f, 0x9e, 0xe6, 0x0d, 0x73, 0x16, 0x9f, 0xd7, 0x29, 0xc0, 0xb0, @@ -1539,7 +1539,7 @@ 0xcb, 0x43, 0x26, 0x41, 0x50, 0x83, 0x9e, 0x05, 0x6d, 0xa5, 0xa6, 0x75, 0xd5, 0xa3, 0x46, 0xe9, 0xd2, 0x29, 0xf1, 0x72, 0xb3, 0x89, 0x6e, 0x68, 0xa1, 0xeb, 0xa2, 0x41, 0x4a, 0xda, 0x13, 0xc6, 0x64, 0x4e, 0x42, 0xeb, - 0xe5, 0x07, 0x57, 0xe3, 0x58, 0x08, 0x2e, 0xe3, 0xa1, 0x8d, 0x47, 0x50, + 0xe5, 0x07, 0x57, 0xe3, 0x58, 0x08, 0x2e, 0xa3, 0xa1, 0x8d, 0x47, 0x50, 0x83, 0x9f, 0x38, 0xce, 0x71, 0x96, 0x9c, 0xeb, 0xae, 0xa5, 0x3c, 0xfe, 0xe5, 0x92, 0xdc, 0xbf, 0x9f, 0x60, 0x48, 0x1a, 0x5d, 0xdf, 0xd1, 0xf3, 0xe4, 0x13, 0x18, 0x64, 0x66, 0x54, 0x2a, 0xe6, 0xfe, 0x96, 0x9d, 0x71, @@ -1550,7 +1550,7 @@ 0xd9, 0xa9, 0xeb, 0xb3, 0xf6, 0x7b, 0xd7, 0xe6, 0x97, 0x67, 0xec, 0x04, 0xf4, 0x44, 0x8a, 0x7c, 0xd9, 0xac, 0x15, 0xd9, 0xfb, 0x0b, 0xb3, 0xf6, 0x6a, 0xea, 0xec, 0xfd, 0x39, 0x6f, 0x27, 0x89, 0xfc, 0xfa, 0x91, 0x3d, - 0x97, 0x44, 0x05, 0xd9, 0xfb, 0x0b, 0xb3, 0xf6, 0x60, 0x32, 0xec, 0xfd, + 0x97, 0x64, 0x05, 0xd9, 0xfb, 0x0b, 0xb3, 0xf6, 0x60, 0x32, 0xec, 0xfd, 0x9f, 0xec, 0x05, 0x7f, 0x2e, 0x60, 0x57, 0x67, 0xec, 0xfd, 0x9c, 0x2d, 0x7b, 0x7a, 0xec, 0xfd, 0x80, 0x22, 0x88, 0x48, 0xb4, 0x8b, 0x3d, 0xfb, 0xdb, 0xab, 0xb3, 0xf6, 0x17, 0x67, 0xee, 0x1a, 0xf9, 0x9d, 0x75, 0x76, @@ -1569,7 +1569,7 @@ 0xad, 0x02, 0x89, 0x3e, 0x9d, 0xcf, 0x3d, 0x81, 0xb2, 0xd3, 0xf0, 0x18, 0x73, 0x6e, 0xad, 0x38, 0x68, 0x1e, 0x0f, 0x3b, 0xc9, 0x14, 0xeb, 0x8d, 0xf5, 0xa1, 0xea, 0x9c, 0xc2, 0xca, 0x74, 0x00, 0x25, 0x8c, 0x30, 0x3a, - 0xe1, 0x70, 0xda, 0x40, 0x5a, 0x7f, 0x84, 0xbd, 0xbb, 0xb5, 0x74, 0xdd, + 0xe1, 0x70, 0xda, 0x40, 0x5a, 0x7f, 0x84, 0xbd, 0xba, 0xb5, 0x76, 0xdd, 0x5a, 0x1e, 0x7a, 0x02, 0x21, 0x39, 0xd7, 0x5d, 0x4c, 0x42, 0x09, 0xf7, 0xed, 0x55, 0x64, 0xc4, 0x20, 0xdc, 0xd6, 0xce, 0x75, 0xd7, 0x53, 0x10, 0x7a, 0x13, 0x10, 0x7b, 0x73, 0x5b, 0x23, 0xe2, 0x26, 0xec, 0xe5, 0x3f, @@ -1587,7 +1587,7 @@ 0x16, 0xaf, 0xe0, 0x81, 0x69, 0xf1, 0xf4, 0xed, 0x6c, 0xb4, 0xb4, 0x14, 0x4c, 0x79, 0x6f, 0x86, 0x5e, 0x6e, 0xc8, 0x5e, 0x14, 0x6a, 0x7f, 0x94, 0x67, 0x51, 0xa0, 0xea, 0x18, 0x13, 0x9d, 0x75, 0xd4, 0xa7, 0x81, 0x42, - 0x14, 0xb7, 0x2f, 0xe7, 0xbf, 0xe0, 0xdb, 0xa5, 0xa7, 0xef, 0x39, 0xfc, + 0x14, 0xb7, 0x2f, 0xe7, 0xbf, 0xe0, 0xdb, 0xb5, 0xa7, 0xef, 0x39, 0xfc, 0xc7, 0x16, 0x87, 0xa2, 0x18, 0x8c, 0x34, 0x51, 0x3f, 0xfc, 0x3b, 0x78, 0xd8, 0x0c, 0x36, 0xab, 0xc6, 0x96, 0x9f, 0xff, 0xff, 0xee, 0xeb, 0xce, 0xbc, 0x72, 0x8b, 0xa5, 0xcb, 0x17, 0x87, 0x97, 0x28, 0x7a, 0xfc, 0xfe, @@ -1596,7 +1596,7 @@ 0xb5, 0xe7, 0x4d, 0x8b, 0x4e, 0xa3, 0x3d, 0x2d, 0x0f, 0x3e, 0x2a, 0x44, 0x9c, 0x1c, 0x3a, 0xd3, 0xc0, 0xee, 0x01, 0x68, 0x23, 0x79, 0xf1, 0xb8, 0x65, 0x51, 0x8f, 0x2f, 0xc5, 0x1a, 0x8c, 0x30, 0x61, 0x07, 0xea, 0xec, - 0xfc, 0x67, 0xa2, 0x1d, 0x9e, 0xb4, 0xff, 0xab, 0xf7, 0x45, 0xcc, 0xad, + 0xfc, 0x67, 0xa2, 0x1d, 0x9e, 0xb4, 0xff, 0xab, 0xf7, 0x65, 0xcc, 0xad, 0x80, 0xb4, 0xff, 0xf8, 0xba, 0xc7, 0xcd, 0xba, 0xc7, 0xf3, 0xfa, 0x02, 0xd3, 0xfd, 0xa6, 0xff, 0x5b, 0x70, 0x92, 0xd0, 0xf4, 0x47, 0x69, 0x5a, 0x7f, 0x11, 0xbd, 0x6e, 0x36, 0x96, 0x9f, 0xf0, 0xd3, 0x9c, 0xaf, 0xfc, @@ -1606,13 +1606,13 @@ 0xa3, 0xed, 0xd1, 0x2c, 0xff, 0x60, 0xff, 0x35, 0x85, 0xc5, 0xa7, 0xff, 0x77, 0x58, 0xe7, 0x1a, 0xe6, 0x73, 0x8c, 0xb4, 0xfd, 0xc0, 0x95, 0xc6, 0x0a, 0xd1, 0x87, 0xf3, 0x49, 0x73, 0xd9, 0xd2, 0xd2, 0xd3, 0xf1, 0x90, - 0xe0, 0xdd, 0x97, 0xfa, 0xb4, 0x68, 0xf6, 0xba, 0x41, 0x01, 0x4d, 0xae, + 0xe0, 0xdd, 0x37, 0xfa, 0xb4, 0x68, 0xf6, 0xba, 0x41, 0x01, 0x4d, 0xae, 0xc4, 0x23, 0x0a, 0xee, 0xbd, 0x4f, 0xff, 0x16, 0xb0, 0x3d, 0xd1, 0x1b, 0xca, 0x12, 0x5a, 0x7f, 0xff, 0x0f, 0x73, 0x84, 0xdd, 0x20, 0x33, 0xf7, 0x75, 0xd7, 0x52, 0x9e, 0x0e, 0x61, 0xa9, 0x4f, 0x50, 0x2b, 0xab, 0x4e, 0x78, 0xfa, 0xa8, 0x86, 0x67, 0x3a, 0xeb, 0xa9, 0x4e, 0xc1, 0xb2, 0x5b, 0x97, 0xf3, 0xfe, 0xcb, 0xf0, 0x34, 0xf1, 0x6b, 0xd6, 0x80, 0x1f, 0x38, - 0x95, 0x4f, 0x50, 0x99, 0x3d, 0xde, 0xb4, 0xfe, 0x78, 0xe7, 0x7b, 0xed, + 0x95, 0x4f, 0x50, 0x99, 0x3d, 0xd6, 0xb4, 0xfe, 0x78, 0xe7, 0x7b, 0xed, 0xeb, 0x4e, 0xa3, 0x36, 0x5a, 0x19, 0x3f, 0x0b, 0xd8, 0x82, 0x43, 0xb1, 0x07, 0xe1, 0x5f, 0xc2, 0x1a, 0x2c, 0xf4, 0xd2, 0x78, 0xba, 0x4c, 0xb4, 0xff, 0xfb, 0x95, 0xfd, 0x61, 0x0d, 0x77, 0x4e, 0xb0, 0xad, 0x3f, 0xbd, @@ -1620,14 +1620,14 @@ 0xaa, 0xca, 0x88, 0x32, 0x7f, 0xf7, 0xea, 0xe6, 0x0d, 0xb8, 0x40, 0xf3, 0xd5, 0xa1, 0x91, 0x53, 0xea, 0xec, 0x71, 0x1f, 0xdd, 0x86, 0xdc, 0xdc, 0xf5, 0x69, 0xc4, 0xe9, 0x9a, 0xd3, 0xfb, 0x2e, 0x6b, 0xbd, 0x63, 0xad, - 0x1f, 0x3d, 0x3e, 0x0f, 0xc1, 0x22, 0x33, 0x4d, 0x53, 0xfa, 0xeb, 0x35, - 0x75, 0x9f, 0x65, 0xa7, 0xff, 0x85, 0xad, 0xe3, 0xf8, 0x5e, 0xdd, 0xd8, + 0x1f, 0x3d, 0x3e, 0x0f, 0xc1, 0x22, 0x33, 0x4d, 0x53, 0xfa, 0xef, 0x35, + 0x77, 0x9f, 0x65, 0xa7, 0xff, 0x85, 0xad, 0xe3, 0xf8, 0x5e, 0xdd, 0x58, 0x63, 0x16, 0x87, 0xaa, 0xd2, 0x08, 0xf9, 0x46, 0xa1, 0xa8, 0x5a, 0x74, 0x88, 0xc1, 0xbc, 0xff, 0x7b, 0xd0, 0x7a, 0x76, 0xce, 0xad, 0x3f, 0xf8, 0x6f, 0xf0, 0xe1, 0x0e, 0x07, 0x04, 0xd5, 0xa7, 0x79, 0xc6, 0x5a, 0x18, 0xf9, 0xe9, 0x2e, 0x73, 0x7d, 0xc5, 0xa1, 0x99, 0x2c, 0x61, 0x5c, 0xc8, 0xff, 0x2c, 0x84, 0x52, 0x8f, 0x6a, 0x5a, 0x50, 0xb2, 0xfb, 0x0a, 0x1b, - 0xa2, 0x09, 0xf5, 0x1e, 0xb3, 0x4b, 0x4f, 0xff, 0x59, 0xb5, 0xa6, 0x3e, + 0xb2, 0x09, 0xf5, 0x1e, 0xb3, 0x4b, 0x4f, 0xff, 0x59, 0xb5, 0xa6, 0x3e, 0x74, 0xb5, 0xca, 0x5a, 0x7f, 0x08, 0xb3, 0xce, 0xc4, 0xb4, 0xfe, 0xe9, 0x5c, 0x2e, 0xbd, 0x92, 0x91, 0xd6, 0x9f, 0xb0, 0x4d, 0xfb, 0x6e, 0x47, 0x87, 0xe4, 0xce, 0x31, 0x30, 0x52, 0x4d, 0xd3, 0x94, 0xf7, 0xfd, 0xd9, @@ -1642,8 +1642,8 @@ 0xec, 0x0f, 0x8a, 0x2c, 0xd3, 0x5f, 0x82, 0x46, 0xad, 0x3f, 0x33, 0x84, 0x76, 0x71, 0x69, 0xb1, 0xd5, 0xa1, 0x29, 0xfb, 0x5e, 0x5b, 0xec, 0x74, 0xa1, 0x28, 0x4a, 0x12, 0x84, 0xa1, 0xe7, 0xc0, 0x41, 0x40, 0x2e, 0xf4, - 0x2a, 0xe8, 0x28, 0xc0, 0x54, 0xdc, 0xc4, 0xa7, 0xea, 0xae, 0xb8, 0xc7, - 0x4b, 0xc1, 0x6b, 0x2b, 0xb9, 0x28, 0x4a, 0x12, 0x87, 0x96, 0x84, 0x15, + 0x2a, 0xec, 0x28, 0xc0, 0x54, 0xdc, 0xc4, 0xa7, 0xea, 0xae, 0xb8, 0xc7, + 0x4b, 0xc1, 0x6b, 0x2b, 0xa9, 0x28, 0x4a, 0x12, 0x87, 0x96, 0x84, 0x15, 0x09, 0x42, 0x50, 0x94, 0x25, 0x09, 0x42, 0x51, 0x79, 0xbc, 0x08, 0x51, 0x05, 0x00, 0x2b, 0x41, 0x57, 0x02, 0xa1, 0x28, 0x4a, 0x1e, 0x5a, 0x68, 0x2a, 0x12, 0x84, 0xa1, 0x28, 0x4a, 0x1e, 0x6a, 0x00, 0x15, 0xd0, 0xa3, @@ -1664,16 +1664,16 @@ 0x12, 0x84, 0xa1, 0x8d, 0x43, 0x81, 0x5c, 0x0a, 0xf4, 0x2a, 0x19, 0x7e, 0x92, 0xf7, 0x07, 0x9e, 0x84, 0xa7, 0x16, 0xec, 0xd7, 0xb2, 0x41, 0x32, 0x99, 0x9e, 0xb8, 0x73, 0xf8, 0x45, 0x9d, 0x23, 0x87, 0x14, 0xca, 0x03, - 0xa1, 0x76, 0xd3, 0x37, 0x58, 0x7d, 0x79, 0xb8, 0xca, 0xea, 0x5d, 0xd1, + 0xa1, 0x76, 0xd3, 0x37, 0x58, 0x7d, 0x79, 0xb8, 0xca, 0xea, 0x5d, 0xd9, 0x67, 0x92, 0x43, 0x09, 0x33, 0xe7, 0x8b, 0x66, 0x92, 0xdd, 0x35, 0x59, 0xc4, 0xc7, 0x4a, 0x78, 0xad, 0x5f, 0x5a, 0x71, 0x07, 0x16, 0x96, 0xfb, 0x22, 0x37, 0xe7, 0x3c, 0x1a, 0xe9, 0x04, 0x9a, 0xe3, 0x29, 0x07, 0xcd, 0x27, 0xf2, 0x7f, 0x70, 0x9d, 0x0f, 0xda, 0xf5, 0xa3, 0x63, 0xed, 0x70, 0xe6, 0x7d, 0x98, 0xe5, 0x79, 0x5a, 0x60, 0x32, 0xd3, 0xf7, 0xe8, 0x7c, 0xb0, 0x16, 0x9a, 0xbe, 0xb4, 0x89, 0x6b, 0x16, 0xb2, 0xb2, 0xd2, 0x3a, - 0xd3, 0x5d, 0x6e, 0x48, 0x95, 0xf8, 0xaf, 0x10, 0xa8, 0x7b, 0xc8, 0x84, + 0xd3, 0x5d, 0xee, 0x48, 0x95, 0xf8, 0xaf, 0x10, 0xa8, 0x7b, 0xc8, 0x84, 0xff, 0x71, 0x8f, 0x8e, 0x30, 0xde, 0xb4, 0x62, 0x24, 0x80, 0xb5, 0x3f, - 0x1c, 0xae, 0xa8, 0x40, 0xb4, 0xff, 0x79, 0xa0, 0xeb, 0x0e, 0xc6, 0x6b, + 0x1c, 0xae, 0xe8, 0x40, 0xb4, 0xff, 0x79, 0xa0, 0xeb, 0x0e, 0xc6, 0x6b, 0x4e, 0xcd, 0x9d, 0x5a, 0x76, 0xc0, 0xcf, 0x9e, 0xc8, 0x9e, 0x4f, 0x50, 0x68, 0x56, 0x9f, 0xfe, 0x6f, 0x15, 0xff, 0xd0, 0x1b, 0x77, 0x5d, 0x75, 0x68, 0x64, 0xcb, 0x6a, 0x10, 0xfa, 0x33, 0xf4, 0x7e, 0x2f, 0x6c, 0xa6, @@ -1686,8 +1686,8 @@ 0x37, 0xc0, 0x38, 0xed, 0x01, 0x69, 0xd9, 0x8e, 0x2d, 0x2c, 0xe1, 0xec, 0x00, 0xf6, 0x7e, 0xf7, 0xfe, 0x9e, 0x85, 0x69, 0xe3, 0xb6, 0x5e, 0xb4, 0xfb, 0x2e, 0x0b, 0x6c, 0xb4, 0x11, 0xe4, 0xe8, 0x86, 0x79, 0x87, 0xb6, - 0x5a, 0x4d, 0x89, 0xac, 0x0b, 0xce, 0x89, 0xfa, 0xef, 0x74, 0x43, 0x3d, - 0xed, 0x7d, 0xeb, 0x4f, 0x37, 0xb7, 0x76, 0x92, 0x9f, 0x3f, 0x77, 0x5d, + 0x5a, 0x4d, 0x89, 0xac, 0x0b, 0xce, 0x89, 0xfa, 0xef, 0x76, 0x43, 0x3d, + 0xed, 0x7d, 0xeb, 0x4f, 0x37, 0xb7, 0x56, 0x92, 0x9f, 0x3f, 0x77, 0x5d, 0x75, 0x68, 0x13, 0xd3, 0xf4, 0x9e, 0x7a, 0xba, 0x7e, 0xad, 0x01, 0x45, 0xc6, 0x3a, 0x80, 0x8a, 0x19, 0x5e, 0x31, 0x12, 0x9d, 0xb2, 0x89, 0x01, 0x1e, 0xcf, 0xb1, 0x84, 0xce, 0x32, 0x8c, 0x98, 0xcb, 0x5a, 0x73, 0xc6, @@ -1718,7 +1718,7 @@ 0xf8, 0xef, 0x21, 0xe7, 0xd9, 0xc2, 0xcb, 0x90, 0xba, 0x9f, 0x07, 0x3e, 0x46, 0xad, 0x3f, 0x71, 0xbc, 0x8e, 0xc0, 0x5a, 0x7e, 0x6e, 0xe3, 0x84, 0x75, 0xa7, 0xc3, 0x9e, 0x71, 0xc5, 0xa7, 0xfb, 0x94, 0x7e, 0x13, 0x6c, - 0xf5, 0xa7, 0xef, 0x22, 0xfb, 0xaa, 0xbd, 0x68, 0x23, 0xea, 0x01, 0xc4, + 0xf5, 0xa7, 0xef, 0x22, 0xfb, 0xba, 0xbd, 0x68, 0x23, 0xea, 0x01, 0xc4, 0x5e, 0x8d, 0xf1, 0x2c, 0xec, 0x24, 0xa7, 0xfd, 0x95, 0xc7, 0x08, 0x79, 0x9b, 0x2d, 0x0c, 0xca, 0x15, 0x09, 0xfe, 0x4f, 0xcb, 0x14, 0x26, 0x4c, 0xc9, 0xea, 0x30, 0xe1, 0x35, 0x9f, 0xee, 0x13, 0xf9, 0x4f, 0x23, 0xad, @@ -1729,15 +1729,15 @@ 0x4f, 0xfa, 0xfa, 0x1d, 0x77, 0x84, 0xda, 0x5a, 0x77, 0xf5, 0xa5, 0xc4, 0x07, 0x3f, 0xfb, 0xed, 0xc6, 0xf1, 0x9f, 0xb5, 0x55, 0x95, 0x10, 0x1e, 0xe6, 0xa6, 0x29, 0x19, 0xbe, 0x59, 0xa0, 0x09, 0xa1, 0xf6, 0x31, 0xf8, - 0xc4, 0xe6, 0x4a, 0x36, 0xf9, 0xdc, 0xa3, 0x35, 0xa7, 0x98, 0x17, 0x58, + 0xc4, 0xe6, 0x4a, 0x36, 0xf9, 0xdc, 0xa3, 0x35, 0xa7, 0x98, 0x17, 0x78, 0xb4, 0x00, 0xf0, 0x7a, 0x3d, 0x3c, 0x3d, 0x07, 0xab, 0x4f, 0xff, 0xcf, 0xcd, 0x17, 0xfe, 0x47, 0xf3, 0xde, 0x63, 0xbd, 0x5a, 0x30, 0xff, 0xe8, 0x8a, 0x7f, 0xff, 0xa9, 0xf8, 0x2e, 0x3f, 0x36, 0x7f, 0x96, 0x06, 0xee, 0xba, 0xea, 0x50, 0xc9, 0x97, 0x72, 0x14, 0x22, 0x41, 0x3e, 0x03, 0x77, 0x0c, 0xd6, 0x9f, 0xcd, 0x9f, 0xb5, 0x55, 0x95, 0x10, 0x4c, 0xff, 0x37, 0x73, 0xf6, 0xaa, 0xb2, 0xa2, 0xf9, 0x9c, 0x39, 0xa0, 0xa2, 0x02, 0xc7, - 0xb2, 0x21, 0x46, 0xe5, 0xc8, 0x54, 0xcf, 0xef, 0x79, 0x75, 0xc2, 0xb7, - 0x16, 0x9f, 0xf5, 0xf5, 0xb5, 0xd6, 0x74, 0x6a, 0xe2, 0xd3, 0xfe, 0xc0, + 0xb2, 0x21, 0x46, 0xe5, 0xc8, 0x54, 0xcf, 0xef, 0x79, 0x77, 0xc2, 0xb7, + 0x16, 0x9f, 0xf5, 0xf5, 0xb5, 0xde, 0x74, 0x6a, 0xe2, 0xd3, 0xfe, 0xc0, 0xb3, 0xdb, 0x98, 0x0a, 0x5a, 0x73, 0xae, 0xba, 0x94, 0xfb, 0x99, 0x6a, 0xfa, 0x5b, 0x97, 0xf3, 0xff, 0xf9, 0xcf, 0xb5, 0xcf, 0x06, 0xd7, 0x8f, 0x2e, 0x6b, 0xc6, 0x6d, 0xd5, 0xa3, 0xa8, 0xa5, 0xf2, 0x6d, 0x17, 0xa6, @@ -1747,11 +1747,11 @@ 0x01, 0xbe, 0xf5, 0xa1, 0x8f, 0xef, 0xc9, 0x7c, 0xff, 0xbd, 0xd3, 0x60, 0xf4, 0xcb, 0x76, 0xcb, 0x4f, 0xff, 0xf6, 0xaf, 0xc7, 0x47, 0x03, 0xf2, 0xf6, 0xf0, 0xf1, 0x86, 0xf5, 0xa7, 0x3a, 0xeb, 0xa9, 0x4f, 0xef, 0x20, - 0x61, 0xcd, 0xba, 0x96, 0xe5, 0xfc, 0xff, 0xfd, 0x77, 0x78, 0xb7, 0x08, + 0x61, 0xcd, 0xba, 0x96, 0xe5, 0xfc, 0xff, 0xfd, 0x75, 0x78, 0xb7, 0x08, 0x21, 0xc7, 0x7c, 0x77, 0x59, 0x7a, 0xd1, 0xc4, 0x55, 0x7a, 0x89, 0x04, 0x9a, 0xb5, 0x46, 0x65, 0x0f, 0x5c, 0xfc, 0x09, 0x71, 0x47, 0x3d, 0xf8, 0x57, 0x1e, 0x13, 0xa2, 0x47, 0xd8, 0xe6, 0xa7, 0xfd, 0x84, 0x37, 0xd0, - 0xf7, 0x0e, 0xb4, 0xff, 0xb8, 0x4e, 0x87, 0x99, 0xdb, 0xac, 0x5a, 0x7d, + 0xf7, 0x0e, 0xb4, 0xff, 0xb8, 0x4e, 0x87, 0x99, 0xdb, 0xbc, 0x5a, 0x7d, 0xcc, 0xeb, 0x8f, 0x5a, 0x7f, 0xd9, 0xd6, 0xfe, 0xb8, 0xc3, 0xd5, 0xc4, 0x11, 0x3f, 0x9b, 0x3f, 0x6a, 0xab, 0x2a, 0x20, 0x8d, 0xcf, 0x26, 0x7e, 0xae, 0x7f, 0xe4, 0xea, 0xd3, 0xf1, 0x98, 0x5d, 0xa1, 0x7a, 0xd0, 0x27, @@ -1764,12 +1764,12 @@ 0x6f, 0x3f, 0x79, 0x3e, 0x9d, 0xad, 0x96, 0x86, 0x3e, 0xae, 0x9c, 0xcf, 0x13, 0x84, 0xea, 0xd3, 0xff, 0xef, 0x6f, 0x16, 0xce, 0x6e, 0xdd, 0xce, 0x7b, 0xf5, 0xa7, 0xd9, 0xdd, 0x79, 0xd0, 0x4f, 0xe7, 0xc9, 0x14, 0xfd, - 0x6e, 0x15, 0xd1, 0x1a, 0xb4, 0xf1, 0x9f, 0x32, 0xf5, 0xa7, 0xf3, 0x07, + 0x6e, 0x15, 0xd9, 0x1a, 0xb4, 0xf1, 0x9f, 0x32, 0xf5, 0xa7, 0xf3, 0x07, 0x3a, 0x5c, 0xf5, 0x69, 0x1d, 0x8f, 0x5c, 0x24, 0xb3, 0xff, 0xff, 0xc5, 0xda, 0x3d, 0x08, 0x1e, 0x5a, 0xf4, 0xfc, 0x26, 0xef, 0x3d, 0xa3, 0xad, 0x01, 0x4c, 0xa8, 0xa1, 0x0f, 0x44, 0xf3, 0xff, 0x07, 0xde, 0xe9, 0x85, 0x83, 0x8e, 0x2d, 0x3e, 0x06, 0x1d, 0xb8, 0xb4, 0x11, 0xf5, 0x0a, 0x24, - 0xef, 0xf9, 0xd2, 0xd3, 0x35, 0xdb, 0x5a, 0x7f, 0xd4, 0x36, 0xcf, 0xda, + 0xef, 0xf9, 0xd2, 0xd3, 0x35, 0xd1, 0x5a, 0x7f, 0xd4, 0x36, 0xcf, 0xda, 0xaa, 0xca, 0x88, 0x46, 0x19, 0x10, 0x20, 0x1e, 0xf4, 0x6e, 0x7f, 0xf3, 0x66, 0xde, 0x7a, 0x43, 0xeb, 0xf3, 0x4b, 0x4f, 0xfb, 0xce, 0x72, 0x8f, 0xbb, 0xae, 0xba, 0xb4, 0xff, 0xfb, 0x2d, 0xc6, 0x10, 0x89, 0x5f, 0x82, @@ -1777,7 +1777,7 @@ 0xc3, 0x3f, 0xc1, 0x6d, 0x69, 0xaf, 0xc7, 0x56, 0x8c, 0x3e, 0x3a, 0x2a, 0x9c, 0xeb, 0xae, 0xa5, 0x3f, 0xd8, 0x0a, 0xfe, 0x5c, 0xc0, 0xa5, 0xb9, 0x7f, 0x33, 0xae, 0xa5, 0x39, 0xd7, 0x5d, 0x4a, 0x7e, 0xab, 0xc3, 0xc6, - 0xd2, 0x5b, 0x97, 0xf0, 0x28, 0xbc, 0x75, 0x22, 0xe8, 0xde, 0x7d, 0x62, + 0xd2, 0x5b, 0x97, 0xf0, 0x28, 0xbc, 0x75, 0x22, 0xec, 0xde, 0x7d, 0x62, 0x0f, 0x93, 0xa5, 0xb9, 0xb3, 0x9c, 0xeb, 0xae, 0xa5, 0x3b, 0x4d, 0xf4, 0xb7, 0x2f, 0xe4, 0x02, 0x44, 0x27, 0x56, 0x67, 0xe0, 0x8b, 0x3e, 0xac, 0xb4, 0xf8, 0x25, 0x71, 0x82, 0xb4, 0xf6, 0x0e, 0x19, 0xad, 0x2f, 0x3f, @@ -1794,7 +1794,7 @@ 0x89, 0x6c, 0xf8, 0x18, 0x5c, 0x35, 0x69, 0xff, 0xec, 0xb3, 0x0d, 0x77, 0x41, 0xf6, 0xbe, 0xf5, 0xa3, 0x63, 0xf5, 0x39, 0x3c, 0xf6, 0x59, 0xb4, 0xb4, 0xf9, 0xbb, 0xab, 0x98, 0xb4, 0xfb, 0xdf, 0x9b, 0xc2, 0x5a, 0x19, - 0x12, 0x82, 0x47, 0xd2, 0x0b, 0xa2, 0x89, 0xff, 0xe2, 0xb9, 0x82, 0x11, + 0x12, 0x82, 0x47, 0xd2, 0x0b, 0xb2, 0x89, 0xff, 0xe2, 0xb9, 0x82, 0x11, 0xa7, 0x70, 0x68, 0xd5, 0xa7, 0xff, 0xf8, 0x3c, 0x27, 0x70, 0xc1, 0x1e, 0xbb, 0xaf, 0x5f, 0x9b, 0x75, 0x68, 0xc4, 0x5c, 0x52, 0x74, 0x33, 0x77, 0x15, 0x79, 0x13, 0xe3, 0xf7, 0x0c, 0x72, 0xf9, 0x3c, 0x18, 0x6b, 0xdd, @@ -1803,7 +1803,7 @@ 0x4f, 0xb1, 0xb5, 0xbb, 0x0f, 0x69, 0xd7, 0x18, 0x56, 0x9f, 0xfe, 0xc1, 0xdf, 0xa6, 0x96, 0xda, 0xe6, 0x02, 0x96, 0x87, 0x9f, 0x60, 0x47, 0x27, 0xf5, 0x0d, 0xb3, 0xbc, 0x25, 0xa3, 0x63, 0xd2, 0x39, 0x14, 0xc6, 0x4d, - 0x76, 0xd6, 0x9f, 0xb8, 0xe1, 0x70, 0x8e, 0xb4, 0xff, 0x85, 0xbb, 0xca, + 0x74, 0x56, 0x9f, 0xb8, 0xe1, 0x70, 0x8e, 0xb4, 0xff, 0x85, 0xbb, 0xca, 0x05, 0x6d, 0xa5, 0xa7, 0x39, 0xef, 0xd6, 0x9f, 0xf5, 0x17, 0xf3, 0x6d, 0xdd, 0x75, 0xd5, 0xa2, 0x8f, 0x83, 0x43, 0xd3, 0xff, 0xc2, 0xcf, 0xf1, 0xe7, 0xa4, 0x3e, 0xbf, 0x34, 0xb4, 0x62, 0x67, 0xb6, 0x2d, 0xe4, 0x27, @@ -1833,7 +1833,7 @@ 0xf8, 0x44, 0x8f, 0xe3, 0xdc, 0xf1, 0xab, 0x70, 0xbe, 0x46, 0xdf, 0x8e, 0xae, 0x20, 0xb8, 0xc4, 0xc9, 0x76, 0x44, 0xa5, 0xd9, 0xfe, 0xe1, 0x7c, 0x8d, 0xbf, 0x1d, 0x5c, 0x41, 0x73, 0xff, 0xd5, 0x5b, 0x3f, 0x5c, 0x20, - 0x85, 0xbe, 0xc9, 0x4f, 0xfb, 0x1e, 0xff, 0x75, 0xf1, 0xbe, 0xe9, 0x71, + 0x85, 0xbe, 0xc9, 0x4f, 0xfb, 0x1e, 0xff, 0x75, 0xf1, 0xbe, 0xed, 0x71, 0x05, 0xc5, 0x91, 0xcb, 0xf4, 0x7d, 0x27, 0x4f, 0xfa, 0xc5, 0xfe, 0xd0, 0x35, 0xe1, 0xd5, 0xc4, 0x17, 0x3f, 0x70, 0xb9, 0xc2, 0x02, 0xa0, 0x0b, 0x9f, 0x60, 0x3c, 0x1a, 0xea, 0xe2, 0x0b, 0x9b, 0x3b, 0x63, 0xf1, 0xe1, @@ -1846,7 +1846,7 @@ 0x93, 0x55, 0x96, 0x98, 0x1a, 0x01, 0xe5, 0x74, 0xd6, 0x7f, 0xd8, 0xfe, 0x53, 0xcc, 0x18, 0xf6, 0xf5, 0xa7, 0xea, 0x7b, 0x5c, 0xae, 0x2d, 0x38, 0xec, 0xf5, 0xa7, 0xd8, 0x1e, 0x7a, 0xea, 0xd1, 0x47, 0x88, 0x23, 0x73, - 0x83, 0x5d, 0x5a, 0x3e, 0x6e, 0xe8, 0x82, 0x71, 0x5d, 0x62, 0xd3, 0xab, + 0x83, 0x5d, 0x5a, 0x3e, 0x6e, 0xe8, 0x82, 0x71, 0x5d, 0xe2, 0xd3, 0xab, 0xe0, 0x5a, 0x5b, 0x31, 0xb8, 0xe8, 0xec, 0xfd, 0x97, 0xd7, 0x18, 0xcd, 0x68, 0x64, 0xd6, 0x8a, 0x15, 0x94, 0xb0, 0x24, 0xf3, 0xff, 0xd8, 0x22, 0xd7, 0x9f, 0x85, 0xff, 0xd3, 0xd6, 0x9d, 0x5f, 0xbd, 0x69, 0x80, 0xcb, @@ -1855,7 +1855,7 @@ 0x5b, 0xc9, 0xd6, 0x98, 0x0c, 0xb4, 0xcc, 0x6a, 0xd3, 0xfd, 0x9d, 0xd3, 0x1f, 0xce, 0x38, 0xb4, 0xfe, 0xd6, 0x70, 0xb5, 0xed, 0xeb, 0x4c, 0xeb, 0xa9, 0x4f, 0xf0, 0xe5, 0xca, 0x7e, 0x88, 0x2b, 0x45, 0x93, 0xf1, 0x21, - 0xcf, 0x8a, 0x9d, 0x5b, 0x84, 0x00, 0x61, 0xbb, 0x85, 0x44, 0x5b, 0x47, + 0xcf, 0x8a, 0x9d, 0x5b, 0x84, 0x00, 0x61, 0xba, 0x85, 0x44, 0x5b, 0x47, 0x4e, 0x9a, 0x79, 0x18, 0x9c, 0xeb, 0xae, 0xa5, 0x23, 0xa5, 0xb9, 0x7f, 0x3e, 0xa7, 0x2a, 0xbe, 0x96, 0xe8, 0xde, 0xf3, 0x0b, 0xe9, 0xfd, 0xb7, 0x5b, 0x39, 0x97, 0xad, 0x0c, 0xda, 0x7a, 0xbc, 0x8f, 0x23, 0x60, 0x35, @@ -1867,7 +1867,7 @@ 0xde, 0xb6, 0xcd, 0x7b, 0x69, 0x69, 0xff, 0xfe, 0x33, 0x1a, 0xab, 0x8c, 0xfe, 0x37, 0xef, 0x6e, 0xea, 0x9e, 0xb4, 0xfb, 0x32, 0xff, 0x74, 0xb4, 0xff, 0xdc, 0xf6, 0xff, 0x77, 0xe1, 0x5a, 0xbe, 0xb4, 0xff, 0x72, 0xb5, - 0xc2, 0xbe, 0x85, 0x69, 0xea, 0xbf, 0xcb, 0xd6, 0x8b, 0xbd, 0x54, 0x83, + 0xc2, 0xbe, 0x85, 0x69, 0xea, 0xbf, 0xcb, 0xd6, 0x8b, 0xad, 0x54, 0x83, 0x3b, 0xde, 0x41, 0xb1, 0x6f, 0xc8, 0x29, 0xe3, 0x4d, 0x3d, 0x28, 0xf2, 0x90, 0x60, 0xde, 0x7e, 0x1f, 0x42, 0x7a, 0x7a, 0xd3, 0xff, 0x9e, 0x2d, 0xe0, 0xe2, 0xc6, 0xf4, 0xaf, 0x5a, 0x7d, 0x47, 0xce, 0x1d, 0x68, 0xd8, @@ -1875,7 +1875,7 @@ 0xb4, 0x32, 0x61, 0xe5, 0x09, 0xe3, 0x91, 0xd0, 0xdc, 0xea, 0xf1, 0xe5, 0x69, 0xff, 0xe1, 0x7f, 0x8c, 0x09, 0x6b, 0x6e, 0xfb, 0x5a, 0x5a, 0x7e, 0xf9, 0xba, 0xd1, 0x38, 0xb4, 0xfb, 0xc7, 0x1b, 0xef, 0x5a, 0x3c, 0x23, - 0x27, 0x07, 0xe9, 0x49, 0xd2, 0xf9, 0xfa, 0xf7, 0x1f, 0x77, 0xfe, 0xf5, + 0x27, 0x07, 0xe9, 0x49, 0xd2, 0xf9, 0xfa, 0xf7, 0x1f, 0x75, 0xfe, 0xf5, 0xa7, 0x8f, 0x95, 0xc5, 0xa6, 0x7d, 0xeb, 0x4f, 0xb9, 0x84, 0xfd, 0x2d, 0x3f, 0xfd, 0xc6, 0xf3, 0xbf, 0x46, 0x81, 0xad, 0x30, 0x12, 0x9f, 0xc0, 0xcf, 0xda, 0xaa, 0xcb, 0x88, 0x12, 0x77, 0x4a, 0xf5, 0xa1, 0xe8, 0xd1, @@ -1887,7 +1887,7 @@ 0x91, 0xbb, 0xeb, 0xbc, 0xf6, 0x9e, 0xf6, 0x5a, 0x2f, 0x44, 0x31, 0xa6, 0x13, 0xd8, 0x1a, 0x7a, 0xd3, 0xea, 0x11, 0x23, 0xad, 0x3e, 0x23, 0xd0, 0xe2, 0xd0, 0x65, 0x2b, 0xff, 0x63, 0x67, 0x90, 0x64, 0x3a, 0x0a, 0x16, - 0x75, 0x1c, 0x08, 0x09, 0x44, 0x82, 0xe8, 0x92, 0x7c, 0x5d, 0x6e, 0xe9, + 0x75, 0x1c, 0x08, 0x09, 0x44, 0x82, 0xec, 0x92, 0x7c, 0x5d, 0x6e, 0xe9, 0x29, 0xeb, 0x37, 0x74, 0x94, 0xce, 0xba, 0x94, 0x3c, 0xf7, 0xf0, 0x99, 0xd2, 0x19, 0xb1, 0xd4, 0xb7, 0x35, 0xf3, 0xff, 0xec, 0xeb, 0x5b, 0x30, 0x7b, 0xc2, 0x61, 0xbd, 0x68, 0x01, 0xfc, 0x3a, 0x4f, 0x3f, 0xff, 0x9a, @@ -1896,12 +1896,12 @@ 0x8f, 0xbf, 0x85, 0x13, 0xec, 0xf4, 0xed, 0xa5, 0xa1, 0x69, 0xd9, 0x8e, 0x7c, 0xd8, 0xe8, 0x9e, 0x1c, 0x44, 0x37, 0xd5, 0x27, 0x3e, 0xbe, 0xb4, 0xf9, 0xf9, 0xdc, 0x0a, 0x52, 0x27, 0x0f, 0x07, 0xa3, 0x73, 0xfc, 0x39, - 0xcc, 0xf1, 0xcc, 0xbd, 0x69, 0xfb, 0xdb, 0xb8, 0xbf, 0xfc, 0x5a, 0x7b, + 0xcc, 0xf1, 0xcc, 0xbd, 0x69, 0xfb, 0xdb, 0xa8, 0xbf, 0xfc, 0x5a, 0x7b, 0xa6, 0xe7, 0x16, 0x98, 0x0c, 0xb4, 0xc0, 0x65, 0xa7, 0xde, 0xbf, 0x07, 0x72, 0x35, 0x40, 0x15, 0x86, 0x44, 0x50, 0xa6, 0x4f, 0xff, 0x60, 0xd6, 0xda, 0x34, 0xda, 0xf1, 0x63, 0x81, 0x69, 0xff, 0xbb, 0xcc, 0x3f, 0x96, 0x06, 0x6d, 0xd5, 0xa7, 0xf6, 0xd6, 0x2f, 0xf9, 0x60, 0xad, 0x3c, 0x03, - 0xd3, 0xfc, 0x23, 0x3b, 0x4a, 0x7d, 0x46, 0x9d, 0x75, 0x9b, 0x2d, 0x3c, + 0xd3, 0xfc, 0x23, 0x3b, 0x4a, 0x7d, 0x46, 0x9d, 0x77, 0x9b, 0x2d, 0x3c, 0x0f, 0x97, 0xd6, 0x86, 0x44, 0x4d, 0x24, 0xba, 0x3f, 0x3d, 0xaf, 0x76, 0xea, 0xd3, 0xbf, 0x8e, 0xad, 0x3f, 0xe7, 0x1a, 0xfd, 0x7f, 0x2c, 0xd7, 0xad, 0x3f, 0x8f, 0x87, 0xc0, 0x93, 0xab, 0x4f, 0xc3, 0x8e, 0x70, 0xba, @@ -1917,15 +1917,15 @@ 0x95, 0xc8, 0xb8, 0x9e, 0x30, 0xc7, 0x21, 0x3d, 0x5f, 0x2e, 0x2d, 0x0c, 0xc9, 0x33, 0x79, 0x1e, 0x46, 0xae, 0x6b, 0x2d, 0x8a, 0x08, 0xe7, 0xf0, 0xbc, 0xe4, 0x6f, 0x14, 0x5e, 0x02, 0x41, 0x86, 0xd6, 0xa1, 0x7f, 0xd9, - 0x50, 0xb7, 0x45, 0xd3, 0x19, 0x04, 0xb4, 0xfc, 0xc7, 0xff, 0xeb, 0xab, + 0x50, 0xb7, 0x65, 0xd3, 0x19, 0x04, 0xb4, 0xfc, 0xc7, 0xff, 0xeb, 0xab, 0x4f, 0xff, 0x11, 0xf6, 0x7e, 0xbc, 0x60, 0x8e, 0x10, 0x16, 0x83, 0x29, - 0x12, 0xbc, 0x1a, 0xe9, 0x64, 0xb7, 0x32, 0xe1, 0xac, 0xfd, 0x76, 0x42, - 0x76, 0xed, 0x9d, 0x99, 0x31, 0xf5, 0xda, 0x32, 0x69, 0xeb, 0xeb, 0xe5, + 0x12, 0xbc, 0x1a, 0xe9, 0x64, 0xb7, 0x32, 0xe1, 0xac, 0xfd, 0x74, 0xc2, + 0x76, 0xe8, 0x9d, 0x99, 0x31, 0xf5, 0xd0, 0x32, 0x69, 0xeb, 0xeb, 0xe5, 0x44, 0xbe, 0x70, 0x24, 0x33, 0x8b, 0x39, 0x68, 0x64, 0xcd, 0x8f, 0xca, 0xd3, 0xc1, 0x9b, 0x4e, 0xc4, 0x94, 0xeb, 0x83, 0x94, 0x86, 0xcf, 0xd2, 0x52, 0x8f, 0x2e, 0x93, 0x94, 0xb7, 0x6a, 0xac, 0xcd, 0x01, 0x39, 0x71, - 0x77, 0x42, 0xa8, 0x69, 0x5c, 0xfa, 0xaf, 0x2f, 0xbb, 0x5b, 0x89, 0x7b, - 0x2e, 0x06, 0xe4, 0x74, 0xae, 0xc6, 0x13, 0x75, 0x38, 0x7b, 0xe6, 0x95, + 0x75, 0x42, 0xa8, 0x69, 0x5c, 0xfa, 0xaf, 0x2f, 0xbb, 0x5b, 0x89, 0x7b, + 0x2e, 0x06, 0xe4, 0x74, 0xae, 0xc6, 0x13, 0x77, 0x38, 0x7b, 0xe6, 0x95, 0x98, 0x62, 0x37, 0x98, 0xde, 0x1b, 0x2c, 0xaf, 0xc6, 0xb6, 0x74, 0xfe, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x2e, 0x39, 0xfd, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x5d, 0x73, 0xff, 0x6f, 0x4f, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x25, @@ -1941,7 +1941,7 @@ 0xec, 0x4b, 0x3f, 0x9e, 0xdf, 0xbd, 0xbf, 0x7a, 0xd3, 0xfb, 0xf7, 0x9d, 0x85, 0xfa, 0x5a, 0x18, 0xf9, 0xf0, 0xd2, 0x7f, 0xf6, 0x39, 0xca, 0x3f, 0x78, 0xdd, 0xf4, 0xeb, 0x40, 0x55, 0x26, 0x63, 0x21, 0xa4, 0x75, 0x0d, - 0x01, 0x84, 0x57, 0x92, 0x09, 0xff, 0x87, 0x2f, 0xde, 0xe9, 0x84, 0x73, + 0x01, 0x84, 0x57, 0x92, 0x09, 0xff, 0x87, 0x2f, 0xde, 0xed, 0x84, 0x73, 0xab, 0x46, 0xe8, 0xa8, 0xfb, 0x1c, 0xfe, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x2c, 0x89, 0xfd, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x5a, 0xf3, 0xfb, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xb9, 0x27, 0xdf, 0xb5, 0x55, 0x95, 0x17, 0x64, @@ -1969,17 +1969,17 @@ 0x88, 0x93, 0x8e, 0xf1, 0x2a, 0x7e, 0x6d, 0x78, 0xee, 0x71, 0x69, 0xcc, 0x37, 0xad, 0x3f, 0xff, 0xfc, 0xfd, 0x73, 0x3d, 0x77, 0x5c, 0xcb, 0x66, 0xbc, 0x66, 0xcf, 0xd1, 0x09, 0x2d, 0x3d, 0x6a, 0xab, 0x2a, 0x2b, 0x19, - 0xff, 0x5d, 0x67, 0x47, 0x3d, 0x61, 0xea, 0xd0, 0x6a, 0x66, 0xb6, 0x2e, + 0xff, 0x5d, 0xe7, 0x47, 0x3d, 0x61, 0xea, 0xd0, 0x6a, 0x66, 0xb6, 0x2e, 0xd8, 0x6f, 0xf0, 0x80, 0xe9, 0x6c, 0xff, 0xe6, 0x1e, 0x9b, 0xeb, 0x0e, 0x59, 0xbe, 0xb4, 0xff, 0x07, 0x99, 0xad, 0x9e, 0xdc, 0x5a, 0x7f, 0x9b, 0x67, 0xb8, 0xfa, 0xfd, 0xeb, 0x46, 0x1f, 0xa1, 0x1c, 0xcf, 0xfb, 0x03, 0xf2, 0xf6, 0xf0, 0x69, 0xeb, 0x4f, 0xfe, 0xfd, 0xed, 0xdf, 0x1e, 0x6d, 0xe4, 0xc7, 0x9d, 0x2d, 0x30, 0x7a, 0xb4, 0x61, 0xf6, 0x0a, 0xb4, 0xff, 0xff, 0xc3, 0xed, 0xf9, 0x6f, 0x03, 0xe9, 0x8f, 0x19, 0xb3, 0xf3, 0xd1, - 0x06, 0x96, 0x9f, 0xc6, 0x55, 0xee, 0x3e, 0xef, 0xfd, 0xeb, 0x4f, 0xd7, - 0xf9, 0xba, 0xa1, 0x02, 0xd3, 0xff, 0x39, 0xca, 0x3f, 0x78, 0xdd, 0xf4, + 0x06, 0x96, 0x9f, 0xc6, 0x55, 0xee, 0x3e, 0xeb, 0xfd, 0xeb, 0x4f, 0xd7, + 0xf9, 0xbb, 0xa1, 0x02, 0xd3, 0xff, 0x39, 0xca, 0x3f, 0x78, 0xdd, 0xf4, 0xeb, 0x43, 0x1f, 0xc6, 0x19, 0x4e, 0xe1, 0x6f, 0x8a, 0xd3, 0xac, 0xa5, - 0xc8, 0x5e, 0x09, 0x06, 0xa1, 0x59, 0xd2, 0x0b, 0xa7, 0xbf, 0x30, 0xb9, + 0xc8, 0x5e, 0x09, 0x06, 0xa1, 0x59, 0xd2, 0x0b, 0xb7, 0xbf, 0x30, 0xb9, 0x9f, 0xbf, 0xf6, 0x0e, 0x1d, 0x69, 0xbc, 0x81, 0x69, 0xdc, 0x23, 0xad, 0x27, 0x16, 0x8a, 0x35, 0x9e, 0x8d, 0xcf, 0xa8, 0x6f, 0xf7, 0x4b, 0x41, 0x22, 0xe4, 0x05, 0x82, 0x89, 0xa2, 0x19, 0xda, 0xf3, 0xa5, 0xa7, 0xb6, @@ -1995,7 +1995,7 @@ 0x1b, 0xa1, 0x49, 0xff, 0x8d, 0x21, 0xb6, 0x98, 0xf5, 0xb7, 0x56, 0x9c, 0x0c, 0x30, 0xb4, 0x1a, 0x7c, 0x3f, 0x44, 0x91, 0xab, 0x4d, 0xf3, 0x56, 0x82, 0x35, 0x1e, 0x44, 0x67, 0xff, 0x75, 0x9e, 0x5d, 0xe6, 0x6d, 0xdf, - 0x59, 0x69, 0x62, 0xd0, 0x47, 0xb3, 0x74, 0x95, 0x0c, 0x9e, 0xe6, 0x31, + 0x59, 0x69, 0x62, 0xd0, 0x47, 0xb3, 0x76, 0x95, 0x0c, 0x9e, 0xe6, 0x31, 0x14, 0x24, 0x38, 0x97, 0x4f, 0x70, 0xb4, 0x8e, 0xb4, 0xb9, 0xd2, 0xea, 0xe0, 0x54, 0xfc, 0x06, 0xe6, 0x5c, 0xa5, 0xa7, 0xe2, 0xee, 0x72, 0x8d, 0x5a, 0x73, 0xae, 0xba, 0x94, 0xff, 0xd9, 0x60, 0xb5, 0xfe, 0x73, 0x95, @@ -2006,12 +2006,12 @@ 0x87, 0x45, 0xfd, 0x19, 0x9f, 0xd6, 0x2d, 0x0e, 0x5c, 0xa5, 0xa6, 0xce, 0xad, 0x3e, 0xcb, 0xc7, 0x36, 0x5a, 0x36, 0x3e, 0xee, 0x19, 0x08, 0xac, 0xee, 0x30, 0x56, 0x85, 0xa7, 0xfe, 0x03, 0x0d, 0xab, 0xa0, 0xf2, 0x2f, - 0x5a, 0x7b, 0xa3, 0x8f, 0x5a, 0x7d, 0x9e, 0xdd, 0xda, 0xa5, 0xa7, 0xff, + 0x5a, 0x7b, 0xa3, 0x8f, 0x5a, 0x7d, 0x9e, 0xdd, 0x5a, 0xa5, 0xa7, 0xff, 0x16, 0xb9, 0x81, 0x1c, 0xb8, 0x39, 0xa5, 0xa3, 0x64, 0x6c, 0x7d, 0x10, 0x48, 0x3a, 0x59, 0x2d, 0xd9, 0x93, 0xbd, 0x7b, 0xeb, 0xc8, 0xc3, 0x09, 0xcc, 0x86, 0x51, 0x1e, 0xfd, 0x64, 0xed, 0xbc, 0x94, 0x3b, 0x4c, 0xc0, - 0x28, 0xbb, 0x8b, 0x45, 0x2f, 0x51, 0xbd, 0xf6, 0x19, 0xce, 0x97, 0xdd, - 0x0d, 0xf9, 0x87, 0x14, 0xfb, 0xf6, 0xaa, 0xb2, 0xa2, 0xb7, 0x9f, 0xf5, + 0x28, 0xba, 0x8b, 0x45, 0x2f, 0x51, 0xbd, 0xf6, 0x19, 0xce, 0x97, 0xdd, + 0x8d, 0xf9, 0x87, 0x14, 0xfb, 0xf6, 0xaa, 0xb2, 0xa2, 0xb7, 0x9f, 0xf5, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0x9c, 0x25, 0xbe, 0x1f, 0xe9, 0xcc, 0xe6, 0xf7, 0x8b, 0x4f, 0xbf, 0x6a, 0xab, 0x2a, 0x2d, 0x19, 0xfe, 0x73, 0x0c, 0xf5, 0xff, 0xd7, 0x56, 0x9f, 0x9a, 0x87, 0xd0, 0xe2, 0xd3, 0x11, @@ -2019,13 +2019,13 @@ 0xff, 0x36, 0xd4, 0x67, 0xc1, 0xa3, 0x3b, 0xd6, 0x9f, 0xf3, 0x7c, 0x18, 0x59, 0xfe, 0xfa, 0xb4, 0x32, 0x35, 0x38, 0xa7, 0xa4, 0x49, 0x63, 0x89, 0x8c, 0xea, 0x1d, 0x53, 0xfd, 0x9c, 0xe7, 0xa6, 0x9d, 0xb4, 0xb4, 0xf6, - 0x02, 0xb8, 0xb4, 0xb7, 0xbb, 0x15, 0x29, 0xe0, 0xbb, 0x86, 0x67, 0x3c, - 0xe4, 0x68, 0x9d, 0x2f, 0xba, 0x3a, 0x9e, 0xb5, 0x55, 0x95, 0x16, 0xd4, + 0x02, 0xb8, 0xb4, 0xb7, 0xba, 0x55, 0x29, 0xe0, 0xbb, 0x86, 0x67, 0x3c, + 0xe4, 0x68, 0x9d, 0x2f, 0xbb, 0x3a, 0x9e, 0xb5, 0x55, 0x95, 0x16, 0xd4, 0xfd, 0xc6, 0x3b, 0x10, 0x56, 0x8f, 0x9e, 0xc7, 0x4b, 0x67, 0xfd, 0xc2, 0x0d, 0x3c, 0x3c, 0x23, 0xad, 0x3c, 0xd7, 0x30, 0x96, 0x9f, 0xe6, 0x7b, 0x7e, 0xf6, 0xfd, 0xeb, 0x4f, 0xf3, 0x7f, 0xc6, 0x9b, 0x94, 0x4b, 0x4f, 0xee, 0x15, 0x3f, 0xa5, 0x7a, 0xd1, 0x89, 0x91, 0xd8, 0x8b, 0xe7, 0xa2, - 0x42, 0xe9, 0xcd, 0xd1, 0xc4, 0xfc, 0x6d, 0x7c, 0x3e, 0x8a, 0xd3, 0xe2, + 0x42, 0xe9, 0xcd, 0xd9, 0xc4, 0xfc, 0x6d, 0x7c, 0x3e, 0x8a, 0xd3, 0xe2, 0xbc, 0xed, 0x65, 0xa7, 0xd5, 0xb3, 0xfc, 0xe9, 0x69, 0x6e, 0x69, 0xff, 0xf4, 0xba, 0xe1, 0x3c, 0x6e, 0x98, 0x90, 0x21, 0xb3, 0x3f, 0xb7, 0xcf, 0xda, 0xaa, 0xca, 0x8b, 0x96, 0x7f, 0x6f, 0x9f, 0xb5, 0x55, 0x95, 0x17, @@ -2034,411 +2034,408 @@ 0x15, 0x74, 0xfe, 0x7f, 0x6f, 0x9f, 0xb5, 0x55, 0x95, 0x15, 0x3c, 0xc5, 0xd5, 0xa7, 0xad, 0x55, 0x65, 0x45, 0x73, 0x3f, 0xb7, 0xcf, 0xda, 0xaa, 0xca, 0x8b, 0x3a, 0x3e, 0x7d, 0x9c, 0x2d, 0x9f, 0xfe, 0xce, 0xb6, 0xbc, - 0x7b, 0xae, 0xb3, 0x8e, 0x12, 0xd3, 0xfe, 0xe1, 0x7c, 0x3c, 0xc2, 0x13, - 0x56, 0x9f, 0x7f, 0x3a, 0x47, 0x5a, 0x7a, 0x85, 0x82, 0xb4, 0xfd, 0x8e, - 0x31, 0xdb, 0xca, 0xd3, 0xef, 0xda, 0xaa, 0xca, 0x89, 0x0a, 0x7f, 0xd8, - 0x7c, 0xaf, 0xdf, 0xe3, 0x63, 0xad, 0x3f, 0xc5, 0xb6, 0xba, 0x2c, 0x7d, - 0x2d, 0x33, 0xf7, 0xc4, 0x56, 0x70, 0xcc, 0x08, 0x33, 0xd7, 0x67, 0x18, - 0xeb, 0x4f, 0xec, 0xe6, 0xb5, 0x9f, 0xbd, 0x69, 0x6e, 0x15, 0x5c, 0xf9, - 0x08, 0x12, 0x22, 0x71, 0x4f, 0xe7, 0xa7, 0x26, 0xe0, 0xfd, 0x43, 0x6b, - 0x47, 0x9d, 0x26, 0x9f, 0xfd, 0xb9, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, - 0x44, 0xf9, 0x16, 0x5c, 0x19, 0x33, 0x96, 0x4d, 0xc8, 0x4e, 0x4f, 0xed, - 0xfc, 0xe7, 0xf3, 0x1c, 0x5a, 0x7d, 0xfb, 0x55, 0x59, 0x51, 0x59, 0x4f, - 0xfa, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x4d, 0xd2, 0xdf, 0x0f, 0xf4, - 0xe6, 0x71, 0x64, 0x6d, 0x14, 0x2c, 0xa7, 0xdf, 0xb5, 0x55, 0x95, 0x12, - 0xb4, 0xf8, 0x58, 0x35, 0xc5, 0xa7, 0xdb, 0x9e, 0x9f, 0xbe, 0x1e, 0xc1, - 0x19, 0xcf, 0xfc, 0xf2, 0xd7, 0xa7, 0x12, 0xb9, 0xed, 0x2d, 0x3e, 0xfd, - 0xaa, 0xac, 0xa8, 0x97, 0x27, 0xf8, 0xa9, 0xfd, 0x16, 0x3e, 0x96, 0x9e, - 0xb8, 0x42, 0xcb, 0x4f, 0xff, 0xab, 0xa5, 0xeb, 0xc4, 0x9e, 0xdd, 0x1f, - 0x5e, 0xb4, 0xfb, 0x73, 0xd3, 0xf7, 0x64, 0xc9, 0x31, 0x1b, 0x86, 0x74, - 0x6d, 0xa2, 0x19, 0xff, 0xb7, 0xa7, 0xef, 0x9f, 0xb5, 0x55, 0x95, 0x11, - 0xdc, 0xff, 0x77, 0x98, 0xfd, 0xe8, 0x74, 0xb4, 0xfd, 0x77, 0x8b, 0x5b, - 0x05, 0x69, 0xbd, 0xe2, 0xd3, 0xf1, 0x96, 0x39, 0xca, 0xea, 0xd3, 0xfb, - 0x1d, 0xd3, 0x0f, 0x74, 0xb4, 0xff, 0x98, 0x7d, 0xe9, 0x55, 0xca, 0x7a, - 0xd3, 0xd6, 0xaa, 0xb2, 0xa2, 0xa1, 0x8b, 0x1f, 0x5f, 0xcf, 0xa6, 0x7e, - 0x2d, 0x3f, 0xfc, 0xd4, 0x7c, 0xf8, 0xe1, 0x5c, 0x2f, 0xd2, 0xd3, 0xfc, - 0xcf, 0x6f, 0xde, 0xdf, 0xbd, 0x69, 0xee, 0x77, 0x2f, 0x5a, 0x7d, 0x97, - 0xd0, 0xdc, 0x5a, 0x7f, 0xff, 0xff, 0x33, 0xfc, 0x77, 0x84, 0xda, 0xf1, - 0x9e, 0xd9, 0xae, 0x78, 0xcf, 0xff, 0x2e, 0x7b, 0x5c, 0x5a, 0x31, 0x1c, - 0x42, 0x45, 0xa2, 0x89, 0xff, 0xfe, 0xf6, 0x8c, 0xca, 0xfe, 0x51, 0x75, - 0xb8, 0x5d, 0xd6, 0x05, 0x69, 0x6e, 0x65, 0xab, 0x47, 0xbb, 0x0b, 0xee, - 0xf1, 0x7b, 0xcc, 0x32, 0x13, 0xb6, 0x22, 0xf8, 0xa8, 0xa6, 0x76, 0x31, - 0xbb, 0xa2, 0xe9, 0xf7, 0xed, 0x55, 0x65, 0x45, 0x51, 0x3f, 0xea, 0x7e, - 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x35, 0xcb, 0x7c, 0x3f, 0xd3, 0x99, 0xcf, - 0xbf, 0x6a, 0xab, 0x2a, 0x2a, 0xc9, 0xfe, 0x67, 0xb7, 0xef, 0x6f, 0xde, - 0xb4, 0xb7, 0xc3, 0xec, 0x13, 0x39, 0xff, 0x6f, 0xc6, 0xdb, 0xad, 0xca, - 0x33, 0x5a, 0x7f, 0xed, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x44, 0x89, - 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0xb4, 0xa7, 0xfd, 0x4f, 0xdf, 0x3f, 0x6a, - 0xab, 0x2a, 0x27, 0xd9, 0x6f, 0x87, 0xfa, 0x73, 0x39, 0xff, 0xdb, 0x9e, - 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x50, 0x93, 0xee, 0x15, 0xed, 0xf5, - 0xa7, 0xdf, 0xb5, 0x55, 0x95, 0x14, 0x7c, 0xff, 0x33, 0xdb, 0xf7, 0xb7, - 0xef, 0x5a, 0x7f, 0xc2, 0xce, 0x30, 0xb3, 0x9c, 0x65, 0xa7, 0xff, 0xec, - 0x0f, 0x1b, 0xce, 0xfd, 0x1a, 0x06, 0xb4, 0xc0, 0x4a, 0x7d, 0xb9, 0xe9, - 0xfb, 0xb2, 0x65, 0x78, 0x4e, 0x26, 0x7d, 0x39, 0xba, 0x3c, 0x86, 0x65, - 0x53, 0x5f, 0x1b, 0x1b, 0xd9, 0xf1, 0x44, 0xd9, 0x6f, 0xf6, 0x8c, 0xb7, - 0x68, 0x4a, 0x11, 0x3b, 0x88, 0x5c, 0x86, 0x70, 0x0a, 0x3b, 0x1c, 0x14, - 0xfe, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x22, 0x29, 0xfb, 0x3f, 0x6a, 0xab, - 0x2a, 0x22, 0xb9, 0xfe, 0x33, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x2b, 0x88, - 0xdd, 0x10, 0x14, 0x71, 0x3f, 0xf8, 0x0c, 0x36, 0xde, 0xba, 0x0f, 0x22, - 0xf5, 0xa7, 0xb7, 0xbd, 0xc3, 0x35, 0xa4, 0x5b, 0x1f, 0x98, 0x12, 0xe7, - 0xb3, 0x95, 0xd5, 0xa7, 0xf6, 0x17, 0xc0, 0x0f, 0x74, 0xb4, 0x8c, 0xb1, - 0x3d, 0x3d, 0x10, 0x4f, 0xff, 0xdd, 0xd1, 0x72, 0x89, 0xe4, 0x3d, 0xf7, - 0x9f, 0xc5, 0xa7, 0xdf, 0xb5, 0x55, 0x95, 0x14, 0xf4, 0xeb, 0x1c, 0x96, - 0x9f, 0xff, 0xbf, 0xff, 0x7f, 0xf6, 0x1c, 0x34, 0xb9, 0xcc, 0xf2, 0xb4, - 0xff, 0xc4, 0xfc, 0x10, 0x31, 0xcb, 0xef, 0x5a, 0x7f, 0x3d, 0xbf, 0x7b, - 0x7e, 0xf5, 0xa7, 0xbc, 0x0d, 0x3d, 0x69, 0xf5, 0x67, 0x08, 0xeb, 0x46, - 0x8f, 0x1e, 0xe1, 0x14, 0x32, 0x27, 0xf1, 0xee, 0x7f, 0x98, 0x6d, 0x97, - 0x33, 0xba, 0x5a, 0x2e, 0xf5, 0x4d, 0x2c, 0x59, 0x8b, 0x36, 0x33, 0x21, - 0xba, 0x5d, 0x18, 0x70, 0x5c, 0x21, 0x9f, 0xfd, 0x4f, 0xdc, 0x23, 0x4e, - 0xeb, 0x4c, 0x05, 0xa3, 0x74, 0x62, 0x05, 0xea, 0x76, 0xe1, 0xc5, 0xa7, - 0xff, 0xdc, 0x6f, 0xe3, 0xca, 0xbb, 0x81, 0x2f, 0x6c, 0xb4, 0xf9, 0x9e, - 0x0f, 0x5e, 0xb4, 0xf5, 0xaa, 0xac, 0xa8, 0xac, 0xe1, 0xc3, 0xd5, 0xf9, - 0x44, 0xf7, 0x48, 0xfa, 0x5a, 0x7e, 0xbc, 0xec, 0x2f, 0xd2, 0xd3, 0x9a, - 0xf2, 0x5a, 0x7d, 0xd0, 0x79, 0x17, 0xad, 0x3b, 0xda, 0xd2, 0xd3, 0xec, - 0x72, 0xff, 0x40, 0xb4, 0xb7, 0x0a, 0x74, 0x79, 0x0a, 0x8d, 0x88, 0xfe, - 0x43, 0xc2, 0xda, 0x1b, 0x12, 0x9f, 0x23, 0x93, 0xff, 0x6f, 0x4f, 0xdf, - 0x3f, 0x6a, 0xab, 0x2a, 0x24, 0x59, 0xfb, 0x3f, 0x6a, 0xab, 0x2a, 0x2c, - 0x99, 0xff, 0xdd, 0xd7, 0x9d, 0x6f, 0x97, 0x90, 0xbf, 0x4b, 0x46, 0xe8, - 0x85, 0xc3, 0x89, 0xfd, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x5b, 0x13, 0xb3, - 0x58, 0xb4, 0xf5, 0xaa, 0xac, 0xa8, 0xb6, 0xe7, 0xb5, 0x7d, 0x7d, 0x68, - 0xf9, 0xe7, 0xf4, 0xb6, 0x7f, 0x99, 0xed, 0xfb, 0xdb, 0xf7, 0xad, 0x2d, - 0xde, 0x8c, 0x4c, 0x69, 0x12, 0x29, 0xd7, 0x7f, 0x02, 0xb4, 0xeb, 0xf8, - 0x4b, 0x4f, 0xfa, 0xef, 0xbb, 0xee, 0xdf, 0x79, 0x82, 0xc0, 0x5a, 0x7e, - 0x61, 0x78, 0x7d, 0x3a, 0xd3, 0xef, 0xda, 0xaa, 0xca, 0x8b, 0xc2, 0x7b, - 0xb7, 0x59, 0xc5, 0xa7, 0xfe, 0x6f, 0x27, 0xd9, 0xfd, 0xc1, 0xee, 0x96, - 0x9f, 0x60, 0x80, 0xc3, 0x2d, 0x3e, 0x6f, 0x3e, 0xd6, 0x96, 0x9d, 0xd6, - 0x02, 0xd2, 0xdc, 0xcb, 0x4e, 0xfe, 0xef, 0x21, 0x32, 0x61, 0xcb, 0xd3, - 0x70, 0xb7, 0x63, 0x3e, 0x12, 0x01, 0x18, 0x49, 0xfa, 0x53, 0x38, 0xb3, - 0x65, 0xa7, 0xad, 0x55, 0x65, 0x45, 0xe9, 0x3f, 0xe2, 0xef, 0x06, 0x9e, - 0x0a, 0x02, 0xd1, 0xf3, 0xe9, 0x39, 0x6c, 0xff, 0x86, 0xba, 0xf6, 0x37, - 0xa5, 0x7a, 0xd3, 0xec, 0x3f, 0x28, 0x2b, 0x4b, 0x70, 0xa6, 0x15, 0x90, - 0x84, 0xf2, 0x44, 0x60, 0xfa, 0x19, 0x9a, 0x93, 0x7c, 0x2f, 0xdf, 0x09, - 0x6c, 0x97, 0x51, 0x62, 0x42, 0x8e, 0xff, 0xef, 0xc7, 0x86, 0xb0, 0x08, - 0xc6, 0x30, 0x3f, 0x63, 0xf4, 0x76, 0x3a, 0xe9, 0xbd, 0xe2, 0xd3, 0xd9, - 0xca, 0xea, 0xd3, 0xfb, 0x0b, 0xe0, 0x07, 0xba, 0x5a, 0x46, 0x58, 0x9e, - 0x9e, 0x88, 0x27, 0xc5, 0xd6, 0xda, 0xf5, 0xa7, 0xdf, 0xb5, 0x55, 0x95, - 0x11, 0x1c, 0xff, 0xf7, 0x3d, 0xd6, 0xb0, 0xe3, 0x97, 0x3c, 0x31, 0x90, - 0xb4, 0xff, 0x9e, 0xd7, 0xff, 0x3b, 0xd2, 0xea, 0xd3, 0xfd, 0x9f, 0xcd, - 0x65, 0x0d, 0xeb, 0x4f, 0xff, 0xf3, 0x72, 0x8b, 0xad, 0xc1, 0xce, 0xf0, - 0xb9, 0x84, 0xea, 0xd3, 0x5e, 0x74, 0xa6, 0x75, 0xd4, 0xa7, 0xfd, 0xbd, - 0xb8, 0x4e, 0x71, 0xaf, 0xdc, 0x06, 0xbd, 0xd1, 0x79, 0xeb, 0x8d, 0xd6, - 0x5a, 0x1e, 0x7f, 0x84, 0xb5, 0x3f, 0x65, 0x1f, 0x36, 0xea, 0xd3, 0x19, - 0x46, 0x6b, 0x4f, 0xc6, 0x63, 0x9c, 0xae, 0xad, 0x3f, 0x31, 0xb8, 0x24, - 0x6a, 0xd3, 0xf6, 0x74, 0xc7, 0x73, 0x8b, 0x46, 0x22, 0x20, 0x4b, 0xb4, - 0x59, 0x3f, 0xff, 0x5b, 0x7f, 0xd0, 0x97, 0x77, 0xfb, 0x74, 0x68, 0x0b, - 0x45, 0xd8, 0xb8, 0x8b, 0x77, 0xb5, 0x31, 0x66, 0x14, 0x58, 0xcf, 0x65, - 0x82, 0x3e, 0xf9, 0xb5, 0x46, 0x1a, 0x02, 0x1d, 0x16, 0x76, 0x14, 0xd7, - 0x0b, 0xa6, 0x31, 0xc5, 0xa7, 0xdf, 0xb5, 0x55, 0x95, 0x11, 0x74, 0xfb, - 0xa0, 0xf2, 0x2f, 0x4a, 0x5b, 0xde, 0x7e, 0x98, 0x31, 0x46, 0x71, 0xba, - 0x6e, 0x4f, 0x8c, 0xf6, 0x7f, 0xe3, 0xd3, 0xf7, 0xcf, 0xda, 0xaa, 0xca, - 0x89, 0x9a, 0x6d, 0x3d, 0x69, 0xf5, 0xdb, 0x32, 0xf4, 0xdd, 0x5a, 0x2e, - 0xd9, 0xe4, 0x5d, 0xa1, 0x69, 0xdb, 0x36, 0x96, 0x9d, 0x62, 0x3a, 0xd3, - 0x5d, 0x19, 0x4b, 0x4f, 0xfe, 0xe3, 0x1e, 0xbb, 0x9b, 0x00, 0xfe, 0x78, - 0xb4, 0xfd, 0xdc, 0xbf, 0x00, 0xe2, 0xd3, 0xfb, 0xc6, 0x0d, 0x7c, 0x17, - 0x4b, 0x4f, 0xff, 0x8f, 0x5c, 0xcd, 0x81, 0xc7, 0x6b, 0x8e, 0x73, 0xd5, - 0xa0, 0x28, 0x8f, 0xc3, 0x69, 0xb5, 0x8b, 0x41, 0x94, 0x9a, 0xf1, 0x0f, - 0x38, 0x99, 0xc8, 0x5e, 0xd1, 0x14, 0xfc, 0xeb, 0x08, 0xe7, 0x56, 0x9e, - 0xae, 0x13, 0x8b, 0x46, 0x1e, 0x65, 0x8a, 0xe5, 0x65, 0xa7, 0xff, 0xc0, - 0xd9, 0xfc, 0xf5, 0xbf, 0xbf, 0x0a, 0xd5, 0xf5, 0xa7, 0xfe, 0x30, 0x5d, - 0x2b, 0x10, 0x7b, 0x96, 0x5a, 0x7f, 0xff, 0xbd, 0xa1, 0xb0, 0xe0, 0x79, - 0xef, 0x8e, 0x33, 0xfe, 0xd7, 0xad, 0x3d, 0xd2, 0xe1, 0x2d, 0x0c, 0x99, - 0x2e, 0x2c, 0x71, 0x10, 0x5a, 0x67, 0xfb, 0x85, 0xdc, 0x3e, 0xd8, 0x75, - 0xa7, 0xff, 0xc1, 0x21, 0xbf, 0x34, 0x55, 0xcd, 0xdd, 0x75, 0xd4, 0xa7, - 0xed, 0x9f, 0xa0, 0x7a, 0xe2, 0xd3, 0xaa, 0xac, 0xa8, 0xb3, 0xe7, 0xe0, - 0x50, 0xbc, 0x8e, 0xb4, 0x58, 0xf4, 0x80, 0x4f, 0x3f, 0xe2, 0xe3, 0x3c, - 0xba, 0xdd, 0xd2, 0xd3, 0xff, 0xc5, 0xfe, 0x57, 0x8c, 0xb8, 0x39, 0xac, - 0x15, 0xa7, 0x3a, 0xeb, 0xa9, 0x4f, 0xfa, 0x9f, 0xa1, 0xcb, 0x07, 0x3e, - 0x96, 0xe5, 0xfc, 0xff, 0xcd, 0xb3, 0xc7, 0xd0, 0x78, 0xb1, 0xc0, 0xb4, - 0xff, 0x37, 0x08, 0x23, 0x54, 0xe2, 0xd3, 0xfc, 0x42, 0x1f, 0x21, 0xf7, - 0xba, 0x5a, 0x1e, 0xab, 0x92, 0xc7, 0x0e, 0x2c, 0x7e, 0x10, 0x67, 0x22, - 0xe1, 0xe0, 0x1b, 0xb4, 0x99, 0xd4, 0x8b, 0x86, 0xd3, 0xfd, 0xfa, 0x77, - 0x84, 0xdf, 0x65, 0xa7, 0xbe, 0x4c, 0x75, 0xa7, 0xff, 0xdd, 0x37, 0xd6, - 0xc0, 0xf3, 0x35, 0xb3, 0xdb, 0x8b, 0x41, 0xcf, 0xdc, 0x48, 0x26, 0xa7, - 0xad, 0x3f, 0xff, 0xff, 0x0d, 0x3b, 0xdc, 0xe0, 0xe7, 0x7d, 0x01, 0xe9, - 0xf4, 0x16, 0x1a, 0xfd, 0x3d, 0x69, 0x10, 0x51, 0x34, 0xe0, 0xac, 0x32, - 0x39, 0x39, 0x0b, 0xb9, 0xff, 0xff, 0xf6, 0x03, 0x59, 0x82, 0x6f, 0x9f, - 0x8b, 0x67, 0x37, 0xd0, 0xe5, 0xe7, 0xc3, 0xad, 0x3e, 0xb9, 0x5c, 0x6f, - 0x2b, 0x46, 0x22, 0xb4, 0xa1, 0x07, 0x3b, 0x4d, 0x7a, 0xd3, 0xae, 0xb3, - 0x8b, 0x43, 0xcf, 0x83, 0x44, 0xdd, 0x1c, 0x9d, 0xcf, 0x5d, 0x5a, 0x70, - 0x3d, 0xb2, 0xd3, 0xbb, 0x9e, 0x56, 0x9f, 0x9b, 0x6d, 0x78, 0xfb, 0x2d, - 0x3c, 0x41, 0xf6, 0xcb, 0x4f, 0x37, 0x74, 0xcb, 0x40, 0x51, 0x93, 0xb0, - 0xf1, 0x0e, 0x9c, 0x77, 0x85, 0xf7, 0x44, 0x53, 0x65, 0x96, 0x9f, 0xbe, - 0x57, 0x30, 0x74, 0xb4, 0xfb, 0x82, 0xd9, 0xf5, 0x27, 0xfc, 0x5f, 0x7e, - 0x7e, 0xff, 0x68, 0x2a, 0x88, 0x37, 0x73, 0x4b, 0x3e, 0xab, 0x11, 0xd9, - 0x69, 0xf9, 0xfc, 0x1a, 0xdb, 0xab, 0x4b, 0x2c, 0x7a, 0x42, 0x4b, 0x3f, - 0xff, 0xea, 0x77, 0xb9, 0xce, 0xb6, 0x0e, 0xdd, 0xcf, 0x95, 0xf4, 0x75, - 0xa2, 0xec, 0x4e, 0x9d, 0x85, 0x5e, 0xa5, 0x90, 0xaf, 0x12, 0x69, 0xfe, - 0x63, 0xe1, 0x6c, 0xf2, 0x15, 0xa7, 0xd8, 0x1d, 0x71, 0x96, 0x82, 0x3d, - 0xcf, 0x9b, 0x4e, 0xe6, 0x0a, 0xd3, 0xff, 0xf0, 0xd1, 0xbe, 0x3c, 0x8d, - 0x77, 0x45, 0xb7, 0x09, 0xd5, 0xa3, 0x0f, 0xe7, 0xd1, 0xa9, 0xff, 0x1f, - 0x3b, 0xaf, 0x3a, 0xa7, 0xe2, 0xd3, 0xf6, 0xb4, 0xdf, 0xeb, 0x2d, 0xb9, - 0xbf, 0x9f, 0x79, 0x72, 0xab, 0xeb, 0x4f, 0x73, 0x0a, 0xe2, 0xd3, 0xf6, - 0x8b, 0xf9, 0xef, 0xd6, 0x82, 0x45, 0xa9, 0xcf, 0x78, 0x53, 0xd2, 0x29, - 0x8e, 0x65, 0xaa, 0x2f, 0xc9, 0xff, 0x9f, 0xdf, 0x5e, 0xf3, 0xf7, 0xac, - 0x75, 0xa7, 0xff, 0xb8, 0xc1, 0xcb, 0x78, 0xc1, 0xc0, 0xf1, 0x96, 0x9f, - 0xf8, 0xb0, 0x73, 0x35, 0xe1, 0xfa, 0x3a, 0xd1, 0xb2, 0x35, 0xdc, 0x46, - 0xd2, 0x74, 0xe3, 0x5b, 0xeb, 0x4f, 0xc1, 0x60, 0x7f, 0x36, 0x5a, 0x37, - 0x3c, 0x93, 0x8e, 0x4c, 0x4e, 0x2d, 0x3b, 0xa5, 0x7a, 0xd3, 0x85, 0xac, - 0xb4, 0xff, 0xf0, 0xb5, 0xbc, 0x7f, 0x0b, 0xdb, 0xbb, 0x0c, 0x62, 0xd1, - 0xe1, 0x14, 0x47, 0x16, 0x11, 0xc3, 0x03, 0x50, 0xca, 0xae, 0xc2, 0x79, - 0x90, 0xff, 0x27, 0xba, 0x86, 0x2c, 0xfb, 0x85, 0x73, 0x02, 0xb4, 0xf5, - 0x75, 0xb6, 0x5a, 0x7f, 0xff, 0xcd, 0xc2, 0x3e, 0xee, 0x3e, 0xbf, 0xe7, - 0x85, 0xb6, 0xac, 0x57, 0xad, 0x06, 0xa2, 0xe9, 0xc2, 0x83, 0x04, 0x33, - 0xf5, 0x7d, 0xb9, 0xe4, 0x2b, 0x4f, 0x3b, 0x59, 0xa5, 0xa7, 0xf9, 0xe7, - 0xa7, 0xf7, 0x4c, 0x6a, 0xd0, 0xc7, 0xb5, 0x44, 0x33, 0x13, 0xab, 0x4c, - 0x42, 0xb4, 0xb0, 0x26, 0xab, 0x42, 0xd1, 0x48, 0xf8, 0x18, 0x44, 0x7a, - 0x95, 0x3b, 0x6b, 0xde, 0xb4, 0xf7, 0x9f, 0x6b, 0x4b, 0x4f, 0x00, 0x19, - 0xb2, 0xd3, 0xf1, 0x8e, 0xe5, 0x0d, 0x96, 0x9f, 0xef, 0x69, 0xe1, 0xcc, - 0x06, 0x96, 0x9f, 0xc0, 0x2d, 0xb6, 0x7e, 0x75, 0x68, 0xe1, 0xf6, 0x68, - 0xe2, 0x7e, 0x6d, 0xb4, 0x72, 0x33, 0x5a, 0x3e, 0x98, 0x6f, 0x08, 0xbb, - 0x09, 0x9b, 0x84, 0x50, 0xc9, 0xbb, 0x64, 0x66, 0x33, 0x39, 0xea, 0xd2, - 0x3a, 0xd1, 0xb1, 0xa8, 0xbb, 0x86, 0x27, 0xea, 0xd9, 0xe2, 0xc1, 0x5a, - 0x7f, 0x9b, 0x67, 0x90, 0x9e, 0xba, 0xb4, 0x51, 0xf1, 0x89, 0x64, 0xff, - 0xc4, 0xda, 0x1a, 0x7f, 0x8d, 0x67, 0xd6, 0x9f, 0xff, 0xc5, 0xab, 0xf1, - 0xdc, 0x1f, 0x4c, 0x36, 0xf8, 0x35, 0xf5, 0xa0, 0x51, 0x4b, 0xd4, 0x39, - 0xff, 0xff, 0x70, 0xb6, 0xee, 0x6d, 0xdf, 0xfd, 0xba, 0x0f, 0x22, 0xfe, - 0x62, 0xd3, 0xc1, 0x0d, 0x0a, 0xd3, 0xfe, 0xae, 0x58, 0xab, 0xc6, 0xab, - 0x8b, 0x4f, 0xfb, 0x2d, 0xc2, 0x36, 0xeb, 0xdf, 0x9a, 0xb4, 0xff, 0x70, - 0xa8, 0x18, 0x1a, 0x7a, 0xd0, 0xca, 0xae, 0x03, 0x08, 0xac, 0x86, 0x2d, - 0x88, 0x89, 0xbf, 0x84, 0x02, 0x7d, 0xd4, 0x49, 0xff, 0xb0, 0x41, 0x99, - 0xfd, 0x75, 0xb1, 0x69, 0xfe, 0xdb, 0xb9, 0xf2, 0xbe, 0x8e, 0xb4, 0xb0, - 0x07, 0xf2, 0x28, 0x13, 0xff, 0xe6, 0x17, 0xe7, 0x08, 0xe1, 0xc7, 0x1b, - 0x3e, 0xb4, 0xfc, 0x0d, 0x59, 0xbe, 0x6a, 0xd3, 0xfb, 0x1f, 0x84, 0x1e, - 0x12, 0xd3, 0xdd, 0x79, 0xf8, 0xb4, 0xf1, 0x1a, 0x4e, 0xad, 0x18, 0x78, - 0x82, 0x45, 0x37, 0x8c, 0x5a, 0x7b, 0x42, 0xc7, 0x5a, 0x18, 0xdb, 0xec, - 0x2f, 0x3d, 0x9c, 0x79, 0xd6, 0x86, 0x4e, 0xcc, 0xd2, 0x6a, 0x52, 0x12, - 0xed, 0x3a, 0x7a, 0xaf, 0x74, 0x43, 0x2e, 0x2d, 0x36, 0x9e, 0xb4, 0x00, - 0xd3, 0x7a, 0x21, 0x3f, 0x5e, 0xe3, 0xee, 0xff, 0xde, 0xb4, 0xf7, 0x2b, - 0x3e, 0xb4, 0xf0, 0x5b, 0x6d, 0x2d, 0x3f, 0x8d, 0xe6, 0x77, 0x85, 0xd5, - 0xa6, 0x2f, 0xad, 0x06, 0x52, 0x30, 0x18, 0xdb, 0x08, 0x08, 0x8b, 0x86, - 0x73, 0xff, 0x5f, 0xcc, 0x08, 0x4b, 0x6c, 0xdb, 0xab, 0x4f, 0xfc, 0x16, - 0x0f, 0xdb, 0xa5, 0x62, 0x0a, 0xd3, 0xce, 0x31, 0x87, 0xad, 0x3f, 0xce, - 0x6a, 0xe5, 0x0d, 0xfe, 0x85, 0x69, 0xfb, 0x9e, 0xde, 0xe7, 0x09, 0x69, - 0xe1, 0x1c, 0xea, 0xd0, 0xc9, 0x9c, 0x05, 0x1b, 0x10, 0x88, 0x93, 0x87, - 0xbd, 0x30, 0x9f, 0xfe, 0xc1, 0x6b, 0x9f, 0x6f, 0xe1, 0x71, 0x82, 0xb4, - 0xb7, 0x32, 0x9b, 0xf8, 0x7b, 0xb0, 0xba, 0xed, 0x8e, 0x34, 0x6f, 0x37, - 0xc2, 0x81, 0xe4, 0x21, 0x8c, 0xd7, 0x25, 0x8f, 0x9b, 0x09, 0x5b, 0x47, - 0x25, 0xb4, 0x66, 0x85, 0x0f, 0x87, 0x25, 0x00, 0xfe, 0x15, 0xc7, 0x84, - 0xd7, 0x25, 0xe8, 0xd4, 0x61, 0x80, 0x8c, 0xb2, 0xee, 0x34, 0x18, 0xe5, - 0x35, 0x2c, 0x23, 0xb2, 0xa9, 0x5d, 0x84, 0x6d, 0xd4, 0x38, 0xbc, 0xc7, - 0x08, 0x61, 0x56, 0x37, 0x74, 0x43, 0x1c, 0xb4, 0x03, 0xf3, 0xff, 0xb7, - 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0x9b, 0x27, 0xf6, 0xf9, 0xfb, - 0x55, 0x59, 0x51, 0x56, 0xcf, 0xe7, 0xbf, 0xde, 0x8b, 0x3d, 0x69, 0xec, - 0xe5, 0x75, 0x69, 0x19, 0x78, 0x7a, 0x62, 0x67, 0x3a, 0xaa, 0xca, 0x8a, - 0xd2, 0x7c, 0x6e, 0xda, 0xf7, 0x65, 0xa5, 0xfb, 0x1e, 0x99, 0x13, 0xcf, - 0xff, 0x59, 0xbf, 0x80, 0xa3, 0xd3, 0xd8, 0xac, 0xb4, 0xff, 0xf3, 0xf5, - 0x82, 0xc7, 0xac, 0xef, 0x58, 0xeb, 0x4d, 0xde, 0xb2, 0x26, 0x29, 0x32, - 0x79, 0xfd, 0x2b, 0xd6, 0x9f, 0x79, 0xe8, 0xb0, 0x16, 0x93, 0x6c, 0x79, - 0x57, 0x08, 0xa7, 0xeb, 0xf3, 0x85, 0x87, 0x5a, 0x7f, 0x3d, 0xbf, 0x7b, - 0x7e, 0xf5, 0xa7, 0xce, 0x60, 0x4e, 0x66, 0xb4, 0xfc, 0x2c, 0xee, 0xcf, - 0xd2, 0xd0, 0xe1, 0xec, 0x98, 0x2b, 0x86, 0x45, 0x96, 0x42, 0x36, 0x7f, - 0x3f, 0x3b, 0x42, 0x0f, 0x56, 0x96, 0xf7, 0x7a, 0xb1, 0x4c, 0x7e, 0x28, - 0x5f, 0xf1, 0xde, 0x8a, 0x86, 0x1b, 0xdd, 0x26, 0x9f, 0xdb, 0xe7, 0xed, - 0x55, 0x65, 0x45, 0x81, 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0x9d, 0x67, 0xff, - 0xf7, 0x1a, 0xf0, 0xe1, 0xf7, 0xd6, 0xb3, 0x85, 0xaf, 0x6f, 0x5a, 0x7d, - 0xb9, 0xe9, 0xfb, 0xe2, 0x25, 0xdc, 0x33, 0x9f, 0xcf, 0xd6, 0xe6, 0x9a, - 0xc7, 0x5a, 0x7d, 0xfb, 0x55, 0x59, 0x51, 0x6c, 0xcf, 0xff, 0xea, 0x7e, - 0xfa, 0x62, 0xc0, 0x96, 0x6b, 0x3a, 0x2c, 0xb4, 0xff, 0x80, 0xda, 0xdf, - 0x85, 0x6a, 0xfa, 0xd3, 0xfc, 0xcf, 0x6f, 0xde, 0xdf, 0xbd, 0x69, 0x6f, - 0x89, 0x83, 0x1c, 0xce, 0x97, 0x04, 0xfa, 0x7a, 0xd5, 0x56, 0x54, 0x5c, - 0xd2, 0x3a, 0xd1, 0xf3, 0x7a, 0xe9, 0x6c, 0xce, 0x1d, 0x69, 0x6f, 0x86, - 0xe5, 0xd2, 0x29, 0xf7, 0xed, 0x55, 0x65, 0x45, 0xdf, 0x3f, 0x9f, 0xbe, - 0xbf, 0xf2, 0x75, 0x69, 0x6f, 0x87, 0xd1, 0x46, 0x73, 0xdb, 0x9a, 0x10, - 0x2d, 0x0c, 0xea, 0xb5, 0x32, 0xd1, 0x21, 0xd8, 0xd7, 0x65, 0x72, 0x97, - 0x4d, 0xf7, 0x83, 0xc3, 0x5a, 0x90, 0x81, 0x19, 0xe6, 0xa1, 0x71, 0xd8, - 0x48, 0x79, 0x27, 0x9f, 0x6b, 0x47, 0xa7, 0xad, 0x3f, 0xf6, 0xd6, 0xf6, - 0xb6, 0xee, 0x60, 0x9a, 0xb4, 0xe1, 0xad, 0xd8, 0xfb, 0x7a, 0x4f, 0x3f, - 0x86, 0xfc, 0x31, 0xd6, 0x35, 0x69, 0xff, 0x6a, 0x8d, 0xe1, 0x30, 0xfa, - 0xcb, 0x4f, 0xfb, 0x95, 0xda, 0xe6, 0xcf, 0xce, 0xad, 0x18, 0x7f, 0x64, - 0x7b, 0x3f, 0xff, 0xfd, 0xf1, 0xa7, 0x47, 0x3b, 0xdc, 0xbd, 0x86, 0x8d, - 0xd1, 0xdb, 0x04, 0x2b, 0x4f, 0x5a, 0xaa, 0xca, 0x89, 0x5e, 0x7f, 0xf7, - 0x79, 0x8f, 0xb7, 0x08, 0x2c, 0x3d, 0x5a, 0x3e, 0x7e, 0xa2, 0x5b, 0x33, - 0xef, 0x5a, 0x7f, 0xc3, 0x4e, 0x87, 0x8d, 0x7e, 0x3a, 0xb4, 0xff, 0xfc, - 0xfc, 0x20, 0x61, 0xcb, 0xba, 0x63, 0xd6, 0xdd, 0x5a, 0x7b, 0xda, 0xfb, - 0xd6, 0x9f, 0xff, 0xc5, 0xda, 0x3d, 0x08, 0x38, 0xed, 0x0d, 0xf6, 0x2b, - 0xd6, 0x80, 0xa2, 0x0a, 0x88, 0xa0, 0x29, 0x9e, 0x61, 0xff, 0x21, 0xb7, - 0x3f, 0xee, 0xd3, 0xf5, 0xc6, 0xff, 0x90, 0xad, 0x3f, 0xf7, 0x4a, 0xe1, - 0x75, 0xc7, 0xb0, 0xf5, 0x69, 0xd4, 0xfd, 0xd9, 0x5f, 0x6b, 0xe1, 0x60, - 0x12, 0x0c, 0x87, 0x79, 0xc8, 0x75, 0x1a, 0x9f, 0x4d, 0x7c, 0xa0, 0x4f, - 0xfe, 0xce, 0x6e, 0x38, 0x12, 0x1e, 0xe7, 0x16, 0x9d, 0xd6, 0x0a, 0x53, - 0xff, 0xb9, 0x45, 0xd6, 0x79, 0x7e, 0xff, 0x40, 0x94, 0xfe, 0xab, 0x6e, - 0x1f, 0xdd, 0xdb, 0xb1, 0xf2, 0xe8, 0x6e, 0x5b, 0xd9, 0x76, 0xc4, 0xf3, - 0x83, 0xfd, 0x84, 0xad, 0xc8, 0x56, 0x4f, 0xfe, 0xdc, 0xf4, 0xfd, 0xf3, - 0xf6, 0xaa, 0xb2, 0xa2, 0x61, 0x9f, 0xfc, 0x2d, 0x70, 0x5b, 0x6d, 0xcc, - 0xab, 0xb7, 0xa7, 0xad, 0x3f, 0xfb, 0xf4, 0x0d, 0xcd, 0xeb, 0xdd, 0x6d, - 0x3d, 0x69, 0xb3, 0x70, 0xa2, 0x93, 0xca, 0xbc, 0xff, 0xc6, 0x5e, 0x6c, - 0xff, 0x6b, 0xa2, 0xcf, 0x5a, 0x7f, 0x35, 0x5f, 0xd3, 0x6b, 0xeb, 0x4f, - 0xab, 0xef, 0xa3, 0xad, 0x02, 0x7b, 0x3e, 0x99, 0xcf, 0xff, 0x8b, 0xfc, - 0xaf, 0x01, 0xc7, 0xf1, 0xae, 0x05, 0x96, 0x9f, 0xfb, 0x36, 0x77, 0xcf, - 0x1a, 0xdc, 0x27, 0x16, 0x8e, 0x22, 0x7c, 0x55, 0xe7, 0xe3, 0xb6, 0x0f, - 0x6e, 0x96, 0x96, 0x96, 0x9f, 0x36, 0x0f, 0x6e, 0x96, 0x9f, 0xb8, 0x5d, - 0xd5, 0x6d, 0xe0, 0xf9, 0x9c, 0x2e, 0x38, 0x84, 0xff, 0xfe, 0x74, 0xc7, - 0x73, 0x9e, 0x07, 0x2f, 0x2c, 0x1d, 0x9f, 0xa5, 0xa7, 0xce, 0xf7, 0x39, - 0x65, 0xa4, 0x38, 0x88, 0xda, 0x65, 0x9f, 0xfe, 0x6e, 0x8d, 0x03, 0x98, - 0x41, 0xf7, 0xba, 0x5a, 0x7e, 0xb9, 0xe7, 0xa2, 0xc0, 0x5a, 0x7f, 0xf3, - 0x74, 0x0c, 0xfc, 0xdb, 0xb7, 0xfa, 0xea, 0xd0, 0xc7, 0xfa, 0x46, 0x13, - 0xf8, 0x14, 0x0f, 0xfc, 0xbe, 0xb4, 0xfd, 0xa2, 0x34, 0xf5, 0xd5, 0xa7, - 0xff, 0xfd, 0xfc, 0xb8, 0xc3, 0xdf, 0x1e, 0x45, 0xb9, 0x45, 0xd6, 0xee, - 0x96, 0x8d, 0x91, 0x37, 0xf2, 0xd9, 0xef, 0x17, 0x0c, 0x5e, 0xb4, 0x61, - 0xe6, 0x9a, 0x49, 0x3f, 0xdc, 0x61, 0xed, 0x1c, 0xba, 0xb4, 0xff, 0xfb, - 0x83, 0x9d, 0xe1, 0x66, 0xdd, 0xcb, 0x8d, 0xa5, 0xa7, 0x30, 0x3c, 0xad, - 0x18, 0x7e, 0x42, 0xab, 0x3d, 0x5e, 0x43, 0x8b, 0x4b, 0x7b, 0xbd, 0x78, - 0x10, 0x30, 0xa2, 0xc8, 0x60, 0xda, 0x11, 0x0e, 0x43, 0x8b, 0xe4, 0xdc, - 0x86, 0x58, 0x08, 0x06, 0x31, 0xad, 0x11, 0x76, 0x15, 0x1e, 0x90, 0x4f, - 0xff, 0x7c, 0xb6, 0x7e, 0x8b, 0xbc, 0x6f, 0xf5, 0x96, 0x9f, 0x7e, 0xd5, - 0x56, 0x54, 0x55, 0xd3, 0xbe, 0xc7, 0x5a, 0x7f, 0x9f, 0xbe, 0x7e, 0xd5, - 0x56, 0x54, 0x47, 0x93, 0xfc, 0xcf, 0x6f, 0xde, 0xdf, 0xbd, 0x69, 0x6e, - 0x14, 0xc6, 0xf1, 0x3f, 0xe6, 0x74, 0x36, 0x28, 0xb3, 0xfb, 0x7c, 0xfd, - 0xaa, 0xac, 0xa8, 0xb0, 0x67, 0xf6, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x65, - 0x4f, 0xed, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0xd3, 0x9f, 0xeb, 0xbf, 0x84, - 0xe8, 0x6a, 0xac, 0xb4, 0xff, 0x5d, 0xfe, 0x4f, 0x9d, 0xd1, 0x69, 0x69, - 0xff, 0xf8, 0xb9, 0x43, 0xd7, 0xe7, 0xf1, 0x84, 0x73, 0xab, 0x4f, 0xae, - 0x50, 0x70, 0xeb, 0x43, 0xcf, 0xf7, 0x15, 0x67, 0xf6, 0x6b, 0xc7, 0xff, - 0xef, 0x16, 0x9f, 0xff, 0x30, 0xdb, 0x85, 0xc2, 0xfb, 0x38, 0xee, 0x71, - 0x69, 0xe6, 0xf2, 0xdc, 0x5a, 0x7a, 0xd5, 0x56, 0x54, 0x5b, 0x93, 0xff, - 0x36, 0x7f, 0x07, 0xc7, 0x33, 0x67, 0x56, 0x8d, 0x91, 0x29, 0xf2, 0x2d, - 0x16, 0xce, 0x38, 0x92, 0xd2, 0x15, 0xa7, 0xfb, 0x9e, 0xd6, 0xb3, 0x04, - 0xd5, 0xa7, 0xda, 0xad, 0xa8, 0x2b, 0x48, 0x82, 0x7b, 0xfd, 0x38, 0x86, - 0x45, 0x7e, 0x0d, 0x71, 0xba, 0x7f, 0x98, 0x7d, 0x3b, 0x6b, 0xa4, 0xb4, - 0xf0, 0x5b, 0x3e, 0xb4, 0xfb, 0xc6, 0xda, 0x23, 0x56, 0x9a, 0xaa, 0xf3, - 0xcb, 0xd8, 0x82, 0x16, 0x9d, 0xed, 0x75, 0x69, 0xbd, 0x65, 0xa1, 0xe6, - 0xcb, 0xa3, 0x90, 0xb4, 0xf6, 0xd6, 0x2f, 0xad, 0x3c, 0x4c, 0x7d, 0xf1, - 0x11, 0x3b, 0x1e, 0x1c, 0x87, 0xa1, 0x53, 0x87, 0xb7, 0x4b, 0x4f, 0xf3, - 0xf7, 0xcf, 0xda, 0xaa, 0xca, 0x8a, 0x1e, 0x08, 0xf8, 0xe8, 0x7a, 0x7f, - 0x37, 0xc0, 0xd6, 0xc3, 0xad, 0x3f, 0xea, 0x0b, 0x07, 0x84, 0x24, 0x75, - 0xa7, 0xfe, 0xd3, 0x0b, 0x98, 0x20, 0xae, 0xe2, 0xd0, 0x73, 0xfc, 0xe1, - 0xdc, 0xff, 0xde, 0xbf, 0x95, 0xfd, 0xba, 0xc5, 0x7a, 0xd3, 0xfc, 0xcf, - 0x6f, 0xde, 0xdf, 0xbd, 0x69, 0xf1, 0x77, 0x54, 0x4b, 0x4f, 0xf7, 0xc1, - 0xfa, 0x1e, 0xe0, 0x16, 0x80, 0x1e, 0xe7, 0xa4, 0xb3, 0xfd, 0x82, 0x35, - 0xdf, 0x2d, 0x65, 0xa7, 0xfc, 0x5b, 0x6b, 0xc7, 0x7c, 0x07, 0x05, 0x69, - 0xf5, 0x6d, 0xae, 0x92, 0xd1, 0xc4, 0x50, 0x09, 0xbe, 0x90, 0xa7, 0xd5, - 0xe9, 0xad, 0xe5, 0x69, 0xf5, 0xdf, 0x9f, 0x6d, 0x2d, 0x0e, 0x1e, 0xa8, - 0x95, 0x4f, 0xf5, 0x69, 0x9c, 0xd9, 0xf9, 0x71, 0x69, 0xff, 0xf0, 0x78, - 0xde, 0x77, 0xe8, 0xd0, 0x35, 0xa6, 0x02, 0x53, 0x07, 0x16, 0x8c, 0x3e, - 0xc2, 0x57, 0x9f, 0xdc, 0xa0, 0x38, 0x2c, 0x15, 0xa5, 0xbd, 0xd8, 0xc9, - 0x62, 0xbb, 0x47, 0xad, 0x0b, 0xc7, 0x90, 0x84, 0xdb, 0x21, 0xd1, 0x68, - 0x70, 0x11, 0x73, 0x90, 0x82, 0xfc, 0x2d, 0xcf, 0x0b, 0x7e, 0x10, 0x54, - 0x2b, 0x40, 0x44, 0x28, 0xda, 0x84, 0xaf, 0x61, 0x87, 0xec, 0x21, 0x2e, - 0x11, 0x5d, 0x42, 0x9f, 0xc9, 0x04, 0xfe, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, - 0x2f, 0x38, 0x66, 0xd6, 0x59, 0xeb, 0x61, 0x87, 0xde, 0x4f, 0x1a, 0xed, - 0x1f, 0x9f, 0xd3, 0xce, 0x7f, 0xc3, 0xf1, 0xa4, 0xd0, 0xdc, 0x8d, 0xae, - 0x7f, 0x6f, 0x9f, 0xb5, 0x55, 0x95, 0x14, 0xb4, 0xfb, 0xf6, 0xaa, 0xb2, - 0xa2, 0xc2, 0x9f, 0xff, 0x36, 0x08, 0x5b, 0x8d, 0xb7, 0x70, 0x68, 0xeb, - 0x4b, 0x7c, 0x44, 0x21, 0xcc, 0xe7, 0xf6, 0xf9, 0xfb, 0x55, 0x59, 0x51, - 0x65, 0xcf, 0x6e, 0x6d, 0xda, 0x32, 0x16, 0x9d, 0xbf, 0x93, 0xad, 0x2d, - 0x58, 0xf3, 0xbd, 0x2f, 0x90, 0x16, 0x98, 0xdb, 0xd6, 0x9a, 0xbe, 0xf3, - 0x51, 0x82, 0x13, 0xfa, 0xfd, 0xb4, 0xc1, 0xe9, 0x2d, 0x3e, 0x6c, 0xb8, - 0xda, 0x5a, 0x61, 0x6a, 0x3d, 0xb7, 0x4d, 0x27, 0xa9, 0xef, 0x0a, 0xd3, - 0xf5, 0x7d, 0xbb, 0x5c, 0x5a, 0x73, 0xae, 0xba, 0x94, 0xff, 0x33, 0xf6, - 0xef, 0xdb, 0x36, 0x4b, 0x72, 0xfe, 0x66, 0xd2, 0xd0, 0x14, 0x64, 0xf0, - 0x84, 0x52, 0xae, 0x24, 0xcf, 0xc5, 0x5a, 0x06, 0xbd, 0x5a, 0x7f, 0xfe, - 0xe1, 0x77, 0x99, 0xa1, 0xc3, 0xfb, 0xae, 0x53, 0xd6, 0x9f, 0xcc, 0xfe, - 0xd7, 0x28, 0x2b, 0x46, 0x22, 0x2f, 0xeb, 0x52, 0x7a, 0xd2, 0x7a, 0xd2, - 0x7a, 0xd0, 0xc6, 0xc0, 0xd1, 0x02, 0x10, 0x9f, 0xff, 0x77, 0x45, 0x6c, - 0x1f, 0xb0, 0xe0, 0x70, 0xd5, 0xa5, 0xb2, 0xd3, 0x6b, 0xd5, 0xa3, 0x0f, - 0xeb, 0x4a, 0x5d, 0x11, 0x98, 0x99, 0x69, 0xf8, 0x58, 0xe2, 0xd8, 0xb4, - 0xcf, 0x65, 0xa0, 0x27, 0xa4, 0xe0, 0xa7, 0xa5, 0x33, 0xff, 0xff, 0xdc, - 0x6e, 0xe8, 0xb5, 0xa6, 0xef, 0x09, 0xbe, 0x03, 0xd3, 0xdf, 0xd3, 0x56, - 0x99, 0x8e, 0xb4, 0xff, 0xfc, 0xf6, 0x1f, 0x5e, 0xf6, 0xef, 0x30, 0xfe, - 0x58, 0x0b, 0x4d, 0x6d, 0xd9, 0x75, 0x6a, 0xf5, 0x10, 0xc2, 0x1b, 0x21, - 0xeb, 0x63, 0xef, 0xc2, 0xe2, 0x94, 0x86, 0x14, 0xfa, 0x84, 0x07, 0x4c, - 0x6e, 0x9f, 0x7c, 0x8a, 0xcf, 0xfe, 0xdc, 0xf4, 0xfd, 0xf3, 0xf6, 0xaa, - 0xb2, 0xa2, 0x8c, 0x9f, 0x5c, 0x6f, 0xb0, 0x16, 0x9f, 0x0d, 0x01, 0xbc, - 0xad, 0x2d, 0xd8, 0xf3, 0xf8, 0x51, 0x0f, 0x64, 0x38, 0xfe, 0x18, 0x67, - 0x29, 0xa9, 0xde, 0x7d, 0x43, 0x43, 0xb0, 0xa6, 0x9f, 0xfb, 0x7a, 0x7e, - 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x1c, 0xcf, 0xfe, 0xdc, 0xf4, 0xfd, 0xf3, - 0xf6, 0xaa, 0xb2, 0xa2, 0x72, 0x9f, 0xdb, 0xe7, 0xed, 0x55, 0x65, 0x45, - 0x99, 0x3f, 0xcf, 0xd5, 0x1f, 0x7e, 0x74, 0x0b, 0x4f, 0xf1, 0x92, 0x0e, - 0x1d, 0xb6, 0x63, 0xad, 0x3f, 0xc0, 0xfb, 0x77, 0x95, 0xb3, 0xd6, 0x9f, - 0xd9, 0xaf, 0xff, 0x36, 0xd2, 0xd2, 0xdc, 0xc8, 0x45, 0x53, 0x1f, 0x3c, - 0xe6, 0x7f, 0x6f, 0x9f, 0xb5, 0x55, 0x95, 0x16, 0xec, 0xfc, 0x35, 0xbf, - 0xef, 0xe2, 0xd3, 0xfe, 0xa7, 0xef, 0x9f, 0xb5, 0x55, 0x95, 0x14, 0x84, - 0xb7, 0xb1, 0xfc, 0x1c, 0xba, 0x7f, 0xed, 0xe9, 0xfb, 0xe7, 0xed, 0x55, - 0x65, 0x44, 0xa5, 0x17, 0xab, 0x37, 0x71, 0x44, 0xea, 0xf4, 0x7e, 0x08, - 0x72, 0x09, 0xdf, 0x61, 0x6e, 0x60, 0xa6, 0x7d, 0xb9, 0x6b, 0xd3, 0xad, - 0x3f, 0xea, 0x7e, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x3b, 0x4d, 0x79, 0x9a, - 0xd3, 0xff, 0xe2, 0x0f, 0xa7, 0x63, 0x14, 0x11, 0x61, 0xcb, 0x2d, 0x3f, - 0xcc, 0xf6, 0xfd, 0xed, 0xfb, 0xd6, 0x96, 0xe7, 0x47, 0x8f, 0x12, 0xa8, - 0x68, 0x55, 0x27, 0xff, 0xb7, 0xf3, 0x75, 0x42, 0x0c, 0xeb, 0x09, 0x01, - 0x69, 0xff, 0xa8, 0xfc, 0xcb, 0x57, 0x1b, 0xcb, 0xd6, 0x9f, 0xf8, 0x73, - 0x95, 0x7e, 0x68, 0x6b, 0x65, 0xa6, 0xba, 0xdc, 0x28, 0x86, 0xd2, 0x24, - 0x3d, 0x53, 0x39, 0xe3, 0x1a, 0xd2, 0x15, 0xd4, 0x36, 0x27, 0xff, 0xe0, - 0xd7, 0x77, 0xcd, 0x30, 0xec, 0x0d, 0x69, 0x80, 0xb4, 0xfb, 0xf6, 0xaa, - 0xb2, 0xa2, 0x2c, 0x9f, 0xf5, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0x97, - 0x67, 0xff, 0xec, 0x0f, 0x1b, 0xce, 0xfd, 0x1a, 0x06, 0xb4, 0xc0, 0x4a, - 0x5b, 0xe2, 0x36, 0x4e, 0x67, 0x74, 0x95, 0x3f, 0xfb, 0x73, 0xd3, 0xf7, - 0xcf, 0xda, 0xaa, 0xca, 0x89, 0x8a, 0x7d, 0xfb, 0x55, 0x59, 0x51, 0x54, - 0xcb, 0x16, 0x8c, 0x3c, 0x23, 0x4c, 0xe7, 0xff, 0xff, 0x7e, 0xb9, 0xb3, - 0xf3, 0xbb, 0xf2, 0xb5, 0xf2, 0x77, 0xbc, 0x2f, 0xbd, 0x68, 0xdd, 0x13, - 0x94, 0x45, 0x3f, 0xfb, 0x73, 0xd3, 0xf7, 0xcf, 0xda, 0xaa, 0xca, 0x89, - 0xd2, 0x7f, 0x15, 0x7d, 0x9f, 0x57, 0x16, 0x9f, 0x38, 0xce, 0x36, 0x96, - 0x9f, 0x9d, 0xc2, 0xb9, 0x82, 0xb4, 0x11, 0xea, 0xe8, 0xa2, 0x71, 0x71, - 0x96, 0xdc, 0xd0, 0xcf, 0xfd, 0xee, 0xba, 0xdb, 0x6f, 0xeb, 0x84, 0x75, - 0xa0, 0xe7, 0xe9, 0xc2, 0xb9, 0xff, 0x53, 0xf7, 0xcf, 0xda, 0xaa, 0xca, - 0x89, 0xde, 0x7d, 0xdf, 0x68, 0xe4, 0x94, 0xff, 0x85, 0xbb, 0x9a, 0xcc, - 0xd9, 0xeb, 0x4b, 0x70, 0xa7, 0xd7, 0x91, 0x8e, 0x1c, 0x8a, 0x92, 0xba, - 0x4f, 0x3f, 0xfb, 0x73, 0xd3, 0xf7, 0xcf, 0xda, 0xaa, 0xca, 0x8a, 0x16, - 0x7f, 0xff, 0xf8, 0xb9, 0xe9, 0xcf, 0x4f, 0xde, 0xdc, 0xf7, 0xac, 0x39, - 0x79, 0xbe, 0xb3, 0x8b, 0x4f, 0xfe, 0xdc, 0xf4, 0xfd, 0xf3, 0xf6, 0xaa, - 0xb2, 0xa2, 0x92, 0x9f, 0xff, 0xd9, 0xad, 0xfc, 0xe3, 0x9c, 0xa3, 0xf7, - 0x8d, 0xdf, 0x4e, 0xb4, 0x32, 0xf7, 0x9d, 0xf1, 0x9a, 0x3c, 0xe6, 0xd1, - 0x9a, 0xfc, 0x8c, 0xf2, 0x90, 0x80, 0xad, 0xd5, 0x7f, 0x61, 0x07, 0x74, - 0xaf, 0x3f, 0xb7, 0xcf, 0xda, 0xaa, 0xca, 0x88, 0x92, 0x7f, 0xf6, 0xe7, - 0xa7, 0xef, 0x9f, 0xb5, 0x55, 0x95, 0x12, 0xf4, 0xf7, 0xfd, 0xee, 0x96, - 0x9f, 0x7c, 0x07, 0x2d, 0x2d, 0x3f, 0x88, 0x7b, 0xe4, 0xe2, 0xcb, 0x4f, - 0xfe, 0xe5, 0xc6, 0x10, 0x19, 0xe0, 0x73, 0xfb, 0x2d, 0x33, 0x75, 0x69, - 0xff, 0xde, 0x84, 0xbf, 0xe5, 0xc3, 0x1e, 0xd0, 0xb8, 0xb4, 0x3d, 0x1c, - 0xc4, 0x64, 0x04, 0xed, 0x0a, 0xcf, 0xfd, 0x4e, 0x69, 0xae, 0x57, 0x1b, - 0x67, 0x16, 0x96, 0x2d, 0x37, 0xd9, 0x68, 0x0a, 0x7a, 0xe4, 0x46, 0xe4, - 0x61, 0xbf, 0x3c, 0xb8, 0x8e, 0x60, 0x3e, 0x7f, 0x8a, 0x87, 0xde, 0xb8, - 0xc6, 0xad, 0x3c, 0x57, 0x80, 0xcd, 0x69, 0xeb, 0x55, 0x59, 0x51, 0x4b, - 0xc3, 0x87, 0xa5, 0xf2, 0x59, 0xf0, 0xf6, 0xfc, 0x75, 0x69, 0xff, 0x30, - 0xb7, 0x3c, 0x7a, 0x3e, 0xd9, 0x69, 0xde, 0xd6, 0x96, 0x9e, 0xd6, 0x77, - 0x4b, 0x40, 0x4f, 0xf5, 0xc4, 0x0e, 0x8e, 0x4f, 0xf0, 0x35, 0xf6, 0xd9, - 0xe4, 0x75, 0xa7, 0xfa, 0xaf, 0xf1, 0x7f, 0xae, 0x31, 0x9a, 0xd0, 0xc7, - 0xf5, 0xe9, 0xcc, 0xff, 0x16, 0x9c, 0x21, 0xeb, 0x01, 0x68, 0x79, 0xec, - 0x9c, 0x8a, 0x7f, 0xef, 0xdc, 0x60, 0x78, 0xe3, 0x1e, 0x85, 0x68, 0xc3, - 0xe8, 0x22, 0x29, 0xdf, 0x63, 0xad, 0x3f, 0x30, 0xb9, 0xd2, 0x35, 0x69, - 0xfb, 0xe0, 0x6b, 0x61, 0xd6, 0x99, 0xf8, 0xb4, 0xe6, 0x06, 0x96, 0x86, - 0x3d, 0xc0, 0x96, 0x3a, 0x2b, 0x3f, 0xf1, 0x1e, 0x83, 0xe5, 0xc7, 0xb0, - 0xec, 0xb4, 0xf6, 0x89, 0xde, 0xad, 0x1c, 0x3e, 0x8e, 0xa3, 0x4f, 0xff, - 0xc7, 0x67, 0x8b, 0x5f, 0xe5, 0xcd, 0x73, 0x0c, 0x7c, 0x0b, 0x4f, 0x59, - 0xae, 0x69, 0x69, 0xfe, 0x03, 0x03, 0xcd, 0xc6, 0x13, 0x0b, 0x46, 0x1f, - 0x01, 0x11, 0xcf, 0xff, 0xfd, 0xc6, 0xfe, 0xd6, 0x2d, 0xbc, 0x1b, 0x5e, - 0x35, 0xca, 0xb3, 0x08, 0x56, 0x9f, 0xdc, 0xa7, 0x0b, 0xed, 0x7a, 0xd3, - 0x61, 0xd6, 0x80, 0xa2, 0xfe, 0x9d, 0xee, 0x19, 0xcf, 0x8c, 0x11, 0xdb, - 0x4b, 0x4f, 0xaa, 0xe6, 0x7f, 0x4b, 0x40, 0x4f, 0x40, 0xe5, 0x13, 0xee, - 0x50, 0x91, 0xd6, 0x86, 0x3c, 0x7c, 0x22, 0x98, 0x16, 0x5a, 0x5a, 0x5a, - 0x62, 0x37, 0x46, 0x9b, 0xd1, 0x69, 0x6e, 0xcb, 0xef, 0x01, 0x62, 0xc8, - 0x45, 0xec, 0x46, 0x50, 0xa5, 0x72, 0x36, 0xbf, 0x90, 0x1c, 0x6f, 0x90, - 0x89, 0xa8, 0x4b, 0x80, 0x88, 0x61, 0x81, 0xa8, 0x6f, 0xf6, 0x19, 0x17, - 0x48, 0xd3, 0xfb, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xa7, 0x27, 0xfc, 0x5f, - 0xad, 0x73, 0x30, 0x6c, 0xb4, 0xfe, 0x23, 0x85, 0xb5, 0xe8, 0xad, 0x3f, - 0xf1, 0xa5, 0xb6, 0x87, 0x03, 0xca, 0x75, 0x69, 0xff, 0x67, 0x1b, 0xf9, - 0xbb, 0xae, 0xba, 0x94, 0xc4, 0xea, 0xd3, 0x5f, 0xb8, 0x53, 0x09, 0xe1, - 0xdf, 0x4c, 0xae, 0x91, 0x4c, 0x20, 0xcf, 0xbf, 0x6a, 0xab, 0x2a, 0x2b, - 0xc9, 0xff, 0xfb, 0x03, 0xc6, 0xf3, 0xbf, 0x46, 0x81, 0xad, 0x30, 0x12, - 0x96, 0xf8, 0x88, 0xfb, 0xa3, 0x39, 0xff, 0xb7, 0xa7, 0xef, 0x9f, 0xb5, - 0x55, 0x95, 0x12, 0x3c, 0xe2, 0x03, 0x2d, 0x3a, 0xd8, 0x74, 0xb7, 0x2e, - 0xa7, 0xdf, 0xb5, 0x55, 0x95, 0x12, 0x44, 0xff, 0xfc, 0xc5, 0xf2, 0x30, - 0xc3, 0x7b, 0x74, 0xb9, 0x57, 0xad, 0x3d, 0xbd, 0x3f, 0x76, 0x45, 0xc6, - 0x15, 0xf0, 0xce, 0x7f, 0xed, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x44, - 0x95, 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0xbc, 0x67, 0xda, 0xd7, 0x72, 0xcb, - 0x4f, 0xf3, 0xf7, 0xcf, 0xda, 0xaa, 0xca, 0x89, 0x36, 0x5b, 0xe2, 0x27, - 0xfe, 0x67, 0x44, 0xf3, 0xeb, 0xad, 0xd9, 0xde, 0x2d, 0x0c, 0xd8, 0x00, - 0x5e, 0x7e, 0xfa, 0x4d, 0x30, 0x61, 0xfe, 0x51, 0xa4, 0x39, 0x0e, 0xd3, - 0x96, 0x72, 0x32, 0x3e, 0xa3, 0xfb, 0x0f, 0x0f, 0x26, 0xb0, 0xd2, 0xa0, - 0xa8, 0x2f, 0x8f, 0x79, 0xf3, 0x83, 0x81, 0x95, 0x73, 0x97, 0xb8, 0xe2, - 0x6c, 0xb0, 0xeb, 0x5b, 0x87, 0xbd, 0xa9, 0x66, 0xc5, 0x48, 0x38, 0x33, - 0x94, 0x36, 0xe5, 0x7e, 0x73, 0xfa, 0xcf, 0x30, 0xf8, 0xde, 0x5e, 0xe4, - 0xff, 0x65, 0x57, 0xb2, 0xa0, 0x9c, 0xea, 0xbb, 0xa3, 0x1c, 0x1a, 0x59, - 0x2e, 0xa9, 0xc2, 0xdd, 0xb6, 0x2c, 0x3e, 0xd7, 0x90, 0xb7, 0x29, 0x24, - 0x6e, 0xcb, 0xa8, 0xba, 0x95, 0xcd, 0xe6, 0x7d, 0x00, 0xc5, 0x61, 0x55, - 0x00, + 0x7b, 0xae, 0xb3, 0x8e, 0x12, 0xd3, 0xef, 0xe7, 0x48, 0xeb, 0x4f, 0x50, + 0xb0, 0x56, 0x9f, 0xb1, 0xc6, 0x3b, 0x79, 0x5a, 0x7d, 0xfb, 0x55, 0x59, + 0x51, 0x21, 0x4f, 0xfb, 0x0f, 0x95, 0xfb, 0xfc, 0x6c, 0x75, 0xa7, 0xf8, + 0xb6, 0xd7, 0x45, 0x8f, 0xa5, 0xa6, 0x7e, 0xf8, 0x8a, 0xce, 0x19, 0x81, + 0x06, 0x7a, 0xe9, 0xe3, 0x1d, 0x69, 0xfd, 0x9c, 0xd6, 0xb3, 0xf7, 0xad, + 0x2d, 0xc2, 0xaa, 0xab, 0x21, 0x02, 0x44, 0x5f, 0x53, 0x39, 0x37, 0x07, + 0xea, 0x1b, 0x5a, 0x3c, 0xe9, 0x34, 0xff, 0xed, 0xcf, 0x4f, 0xdf, 0x3f, + 0x6a, 0xab, 0x2a, 0x27, 0xc8, 0xb2, 0xbc, 0xe3, 0x39, 0x5d, 0x3c, 0x84, + 0x74, 0xfe, 0xdf, 0xce, 0x7f, 0x31, 0xc5, 0xa7, 0xdf, 0xb5, 0x55, 0x95, + 0x15, 0x94, 0xff, 0xa9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x44, 0xdd, 0x2d, + 0xf0, 0xff, 0x4e, 0x67, 0x16, 0x46, 0xd1, 0x42, 0xca, 0x7d, 0xfb, 0x55, + 0x59, 0x51, 0x2b, 0x4f, 0x85, 0x83, 0x5c, 0x5a, 0x7d, 0xb9, 0xe9, 0xfb, + 0xe1, 0xec, 0x11, 0x9c, 0xff, 0xcf, 0x2d, 0x7a, 0x71, 0x2b, 0x9e, 0xd2, + 0xd3, 0xef, 0xda, 0xaa, 0xca, 0x89, 0x72, 0x7f, 0x8a, 0x9f, 0xd1, 0x63, + 0xe9, 0x69, 0xeb, 0x84, 0x2c, 0xb4, 0xff, 0xfa, 0xba, 0x5e, 0xbc, 0x49, + 0xed, 0xd1, 0xf5, 0xeb, 0x4f, 0xb7, 0x3d, 0x3f, 0x76, 0x4c, 0x93, 0x11, + 0xb8, 0x67, 0x46, 0xda, 0x21, 0x9f, 0xfb, 0x7a, 0x7e, 0xf9, 0xfb, 0x55, + 0x59, 0x51, 0x1d, 0xcf, 0xf7, 0x79, 0x8f, 0xde, 0x87, 0x4b, 0x4f, 0xd7, + 0x58, 0xb5, 0xb0, 0x56, 0x9b, 0xde, 0x2d, 0x3f, 0x19, 0x63, 0x9c, 0xae, + 0xad, 0x3f, 0xb1, 0xdd, 0x30, 0xf7, 0x4b, 0x4f, 0xf9, 0x87, 0xde, 0x95, + 0x5c, 0xa7, 0xad, 0x3d, 0x6a, 0xab, 0x2a, 0x2a, 0x18, 0xb1, 0xf5, 0xfc, + 0xfa, 0x67, 0xe2, 0xd3, 0xff, 0xcd, 0x47, 0xcf, 0x8e, 0x15, 0xc2, 0xfd, + 0x2d, 0x3f, 0xcc, 0xf6, 0xfd, 0xed, 0xfb, 0xd6, 0x9e, 0xe7, 0x72, 0xf5, + 0xa7, 0xd9, 0x7d, 0x0d, 0xc5, 0xa7, 0xff, 0xff, 0xf3, 0x3f, 0xc7, 0x78, + 0x4d, 0xaf, 0x19, 0xed, 0x9a, 0xe7, 0x8c, 0xff, 0xf2, 0xe7, 0xb5, 0xc5, + 0xa3, 0x11, 0xc4, 0x24, 0x5a, 0x28, 0x9f, 0xff, 0xef, 0x68, 0xcc, 0xaf, + 0xe5, 0x17, 0x5b, 0x85, 0xdd, 0x60, 0x56, 0x96, 0xe6, 0x5a, 0xb4, 0x7b, + 0xa4, 0xbe, 0xeb, 0x17, 0xbc, 0xc3, 0x21, 0x3b, 0x62, 0x2f, 0x8a, 0x8a, + 0x67, 0x63, 0x1b, 0xbb, 0x2e, 0x9f, 0x7e, 0xd5, 0x56, 0x54, 0x55, 0x13, + 0xfe, 0xa7, 0xef, 0x9f, 0xb5, 0x55, 0x95, 0x13, 0x5c, 0xb7, 0xc3, 0xfd, + 0x39, 0x9c, 0xfb, 0xf6, 0xaa, 0xb2, 0xa2, 0xac, 0x9f, 0xe6, 0x7b, 0x7e, + 0xf6, 0xfd, 0xeb, 0x4b, 0x7c, 0x3e, 0xc1, 0x33, 0x9f, 0xf6, 0xfc, 0x6d, + 0xba, 0xdc, 0xa3, 0x35, 0xa7, 0xfe, 0xde, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, + 0x54, 0x48, 0x93, 0xef, 0xda, 0xaa, 0xca, 0x8b, 0x4a, 0x7f, 0xd4, 0xfd, + 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0x7d, 0x96, 0xf8, 0x7f, 0xa7, 0x33, 0x9f, + 0xfd, 0xb9, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x45, 0x09, 0x3e, 0xe1, + 0x5e, 0xdf, 0x5a, 0x7d, 0xfb, 0x55, 0x59, 0x51, 0x47, 0xcf, 0xf3, 0x3d, + 0xbf, 0x7b, 0x7e, 0xf5, 0xa7, 0xfc, 0x2c, 0xe3, 0x0b, 0x39, 0xc6, 0x5a, + 0x7f, 0xfe, 0xc0, 0xf1, 0xbc, 0xef, 0xd1, 0xa0, 0x6b, 0x4c, 0x04, 0xa7, + 0xdb, 0x9e, 0x9f, 0xbb, 0x26, 0x57, 0x84, 0xe2, 0x67, 0xd3, 0x9b, 0xb3, + 0xc8, 0x66, 0x55, 0x35, 0xf1, 0xb1, 0xbd, 0x9f, 0x14, 0x4d, 0x96, 0xff, + 0x68, 0xcb, 0x76, 0x84, 0xa1, 0x13, 0xb8, 0x85, 0xc8, 0x67, 0x00, 0xa3, + 0xb1, 0xc1, 0x4f, 0xed, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0x22, 0x9f, 0xb3, + 0xf6, 0xaa, 0xb2, 0xa2, 0x2b, 0x9f, 0xe3, 0x3d, 0xf3, 0xf6, 0xaa, 0xb2, + 0xa2, 0xb8, 0x8d, 0xd1, 0x01, 0x47, 0x13, 0xff, 0x80, 0xc3, 0x6d, 0xeb, + 0xa0, 0xf2, 0x2f, 0x5a, 0x7b, 0x7b, 0xdc, 0x33, 0x5a, 0x45, 0xb1, 0xf9, + 0x81, 0x2e, 0x7b, 0x39, 0x5d, 0x5a, 0x7f, 0x61, 0x7c, 0x00, 0xf7, 0x4b, + 0x48, 0xcb, 0x13, 0xd3, 0xd1, 0x04, 0xff, 0xfd, 0xdd, 0x17, 0x28, 0x9e, + 0x43, 0xdf, 0x79, 0xfc, 0x5a, 0x7d, 0xfb, 0x55, 0x59, 0x51, 0x4f, 0x4e, + 0xb1, 0xc9, 0x69, 0xff, 0xfb, 0xff, 0xf7, 0xff, 0x61, 0xc3, 0x4b, 0x9c, + 0xcf, 0x2b, 0x4f, 0xfc, 0x4f, 0xc1, 0x03, 0x1c, 0xbe, 0xf5, 0xa7, 0xf3, + 0xdb, 0xf7, 0xb7, 0xef, 0x5a, 0x7b, 0xc0, 0xd3, 0xd6, 0x9f, 0x56, 0x70, + 0x8e, 0xb4, 0x68, 0xf1, 0xee, 0x11, 0x43, 0x22, 0x7f, 0x1e, 0xe7, 0xf9, + 0x86, 0xd9, 0x73, 0x3b, 0xa5, 0xa2, 0xeb, 0x54, 0xd2, 0xc5, 0x98, 0xb3, + 0x63, 0x32, 0x1b, 0xa5, 0xd1, 0x87, 0x05, 0xc2, 0x19, 0xff, 0xd4, 0xfd, + 0xc2, 0x34, 0xee, 0xb4, 0xc0, 0x5a, 0x37, 0x46, 0x20, 0x5e, 0xa7, 0x6e, + 0x1c, 0x5a, 0x7f, 0xfd, 0xc6, 0xfe, 0x3c, 0xab, 0xb8, 0x12, 0xf6, 0xcb, + 0x4f, 0x99, 0xe0, 0xf5, 0xeb, 0x4f, 0x5a, 0xaa, 0xca, 0x8a, 0xce, 0x1c, + 0x3d, 0x5f, 0x94, 0x4f, 0x74, 0x8f, 0xa5, 0xa7, 0xeb, 0xce, 0xc2, 0xfd, + 0x2d, 0x39, 0xaf, 0x25, 0xa7, 0xdd, 0x07, 0x91, 0x7a, 0xd3, 0xbd, 0xad, + 0x2d, 0x3e, 0xc7, 0x2f, 0xf4, 0x0b, 0x4b, 0x70, 0xa7, 0x47, 0x90, 0xa8, + 0xd8, 0x8f, 0xe4, 0x3c, 0x2d, 0xa1, 0xb1, 0x29, 0xf2, 0x39, 0x3f, 0xf6, + 0xf4, 0xfd, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0x45, 0x9f, 0xb3, 0xf6, 0xaa, + 0xb2, 0xa2, 0xc9, 0x9f, 0xfd, 0xdd, 0x79, 0xd6, 0xf9, 0x79, 0x0b, 0xf4, + 0xb4, 0x6e, 0x88, 0x5c, 0x38, 0x9f, 0xdb, 0xe7, 0xed, 0x55, 0x65, 0x45, + 0xb1, 0x3b, 0x35, 0x8b, 0x4f, 0x5a, 0xaa, 0xca, 0x8b, 0x6e, 0x7b, 0x57, + 0xd7, 0xd6, 0x8f, 0x9e, 0x7f, 0x4b, 0x67, 0xf9, 0x9e, 0xdf, 0xbd, 0xbf, + 0x7a, 0xd2, 0xdd, 0xe8, 0xc4, 0xc6, 0x91, 0x22, 0x9d, 0x75, 0xf0, 0x2b, + 0x4e, 0xbf, 0x84, 0xb4, 0xff, 0xae, 0xbb, 0xae, 0xe8, 0xf7, 0x98, 0x2c, + 0x05, 0xa7, 0xe6, 0x17, 0x87, 0xd3, 0xad, 0x3e, 0xfd, 0xaa, 0xac, 0xa8, + 0xbc, 0x27, 0xbb, 0x77, 0x9c, 0x5a, 0x7f, 0xe6, 0xf2, 0x7d, 0x9f, 0xdc, + 0x1e, 0xe9, 0x69, 0xf6, 0x08, 0x0c, 0x32, 0xd3, 0xe6, 0xf3, 0xed, 0x69, + 0x69, 0xdd, 0x60, 0x2d, 0x2d, 0xcc, 0xb4, 0xef, 0xee, 0xb2, 0x13, 0x26, + 0x1c, 0xbd, 0x37, 0x0b, 0x76, 0x33, 0xe1, 0x20, 0x11, 0x84, 0x9f, 0xa5, + 0x33, 0x8b, 0x36, 0x5a, 0x7a, 0xd5, 0x56, 0x54, 0x5e, 0x93, 0xfe, 0x2e, + 0xf0, 0x69, 0xe0, 0xa0, 0x2d, 0x1f, 0x3e, 0x93, 0x96, 0xcf, 0xf8, 0x6b, + 0xaf, 0x63, 0x7a, 0x57, 0xad, 0x3e, 0xc3, 0xf2, 0x82, 0xb4, 0xb7, 0x0a, + 0x61, 0x59, 0x08, 0x4f, 0x24, 0x46, 0x0f, 0xa1, 0x99, 0xa9, 0x37, 0xc2, + 0xfd, 0xf0, 0x96, 0xc9, 0x75, 0x16, 0x24, 0x28, 0xef, 0xfe, 0xfc, 0x78, + 0x6b, 0x00, 0x8c, 0x63, 0x03, 0xf6, 0x3f, 0x47, 0x63, 0xae, 0x9b, 0xde, + 0x2d, 0x3d, 0x9c, 0xae, 0xad, 0x3f, 0xb0, 0xbe, 0x00, 0x7b, 0xa5, 0xa4, + 0x65, 0x89, 0xe9, 0xe8, 0x82, 0x7c, 0x5d, 0x6d, 0xaf, 0x5a, 0x7d, 0xfb, + 0x55, 0x59, 0x51, 0x11, 0xcf, 0xff, 0x73, 0xdd, 0x6b, 0x0e, 0x39, 0x73, + 0xc3, 0x19, 0x0b, 0x4f, 0xf9, 0xed, 0x7f, 0xf3, 0xbd, 0x2e, 0xad, 0x3f, + 0xd9, 0xfc, 0xd6, 0x50, 0xde, 0xb4, 0xff, 0xff, 0x37, 0x28, 0xba, 0xdc, + 0x1c, 0xef, 0x0b, 0x98, 0x4e, 0xad, 0x35, 0xe7, 0x4a, 0x67, 0x5d, 0x4a, + 0x7f, 0xdb, 0xdb, 0x84, 0xe7, 0x1a, 0xfd, 0xc0, 0x6b, 0xdd, 0x17, 0x9e, + 0xb8, 0xdd, 0x65, 0xa1, 0xe7, 0xf8, 0x4b, 0x53, 0xf6, 0x51, 0xf3, 0x6e, + 0xad, 0x31, 0x94, 0x66, 0xb4, 0xfc, 0x66, 0x39, 0xca, 0xea, 0xd3, 0xf3, + 0x1b, 0x82, 0x46, 0xad, 0x3f, 0x67, 0x4c, 0x77, 0x38, 0xb4, 0x62, 0x22, + 0x04, 0xbb, 0x45, 0x93, 0xff, 0xf5, 0xb7, 0xfd, 0x09, 0x77, 0x7f, 0xb7, + 0x46, 0x80, 0xb4, 0x5d, 0x2b, 0x88, 0xb7, 0x5b, 0x53, 0x16, 0x61, 0x45, + 0x8c, 0xf6, 0x58, 0x23, 0xef, 0x9b, 0x54, 0x61, 0xa0, 0x21, 0xd1, 0x67, + 0x61, 0x4d, 0x70, 0xba, 0x63, 0x1c, 0x5a, 0x7d, 0xfb, 0x55, 0x59, 0x51, + 0x17, 0x4f, 0xba, 0x0f, 0x22, 0xf4, 0xa5, 0xbd, 0xe7, 0xe9, 0x83, 0x14, + 0x67, 0x1b, 0xa6, 0xe4, 0xf8, 0xcf, 0x67, 0xfe, 0x3d, 0x3f, 0x7c, 0xfd, + 0xaa, 0xac, 0xa8, 0x99, 0xa7, 0xeb, 0xa1, 0x74, 0x4c, 0xbd, 0x37, 0x56, + 0x9d, 0xb3, 0x69, 0x69, 0xd6, 0x23, 0xad, 0x35, 0xd9, 0x94, 0xb4, 0xff, + 0xee, 0x31, 0xeb, 0xb9, 0xb0, 0x0f, 0xe7, 0x8b, 0x4f, 0xdd, 0xcb, 0xf0, + 0x0e, 0x2d, 0x3f, 0xbc, 0x60, 0xd7, 0xc1, 0x76, 0xb4, 0xff, 0xf8, 0xf5, + 0xcc, 0xd8, 0x1c, 0x76, 0xb8, 0xe7, 0x3d, 0x5a, 0x02, 0x88, 0xfc, 0x36, + 0x9b, 0x58, 0xb4, 0x19, 0x49, 0xaf, 0x10, 0xf3, 0x89, 0x9c, 0x85, 0xed, + 0x11, 0x4f, 0xce, 0xb0, 0x8e, 0x75, 0x69, 0xea, 0xe1, 0x38, 0xb4, 0x61, + 0xe6, 0x58, 0xae, 0x56, 0x5a, 0x7f, 0xfc, 0x0d, 0x9f, 0xcf, 0x5b, 0xfb, + 0xf0, 0xad, 0x5f, 0x5a, 0x7f, 0xe3, 0x05, 0xd2, 0xb1, 0x07, 0xb9, 0x65, + 0xa7, 0xff, 0xfb, 0xda, 0x1b, 0x0e, 0x07, 0x9e, 0xf8, 0xe3, 0x3f, 0xed, + 0x7a, 0xd3, 0xdd, 0x2e, 0x12, 0xd0, 0xc9, 0x92, 0xe2, 0xc7, 0x11, 0x05, + 0xa6, 0x7f, 0xb8, 0x5d, 0xc3, 0xed, 0x87, 0x5a, 0x7f, 0xfc, 0x12, 0x1b, + 0xf3, 0x45, 0x5c, 0xdd, 0xd7, 0x5d, 0x4a, 0x7e, 0xd9, 0xfa, 0x07, 0xae, + 0x2d, 0x3a, 0xaa, 0xca, 0x8b, 0x3e, 0x7e, 0x05, 0x0b, 0xc8, 0xeb, 0x45, + 0x8f, 0x48, 0x04, 0xf3, 0xfe, 0x2e, 0x33, 0xcb, 0xad, 0xdd, 0x2d, 0x3f, + 0xfc, 0x5f, 0xe5, 0x78, 0xcb, 0x83, 0x9a, 0xc1, 0x5a, 0x73, 0xae, 0xba, + 0x94, 0xff, 0xa9, 0xfa, 0x1c, 0xb0, 0x73, 0xe9, 0x6e, 0x5f, 0xcf, 0xfc, + 0xdb, 0x3c, 0x7d, 0x07, 0x8b, 0x1c, 0x0b, 0x4f, 0xf3, 0x70, 0x82, 0x35, + 0x4e, 0x2d, 0x3f, 0xc4, 0x21, 0xf2, 0x1f, 0x7b, 0xa5, 0xa1, 0xea, 0xb9, + 0x2c, 0x70, 0xe2, 0xc7, 0xe1, 0x06, 0x72, 0x2e, 0x1e, 0x01, 0xbb, 0x49, + 0x9d, 0x48, 0xb8, 0x6d, 0x3f, 0xdf, 0xa7, 0x78, 0x4d, 0xf6, 0x5a, 0x7b, + 0xe4, 0xc7, 0x5a, 0x7f, 0xfd, 0xd3, 0x7d, 0x6c, 0x0f, 0x33, 0x5b, 0x3d, + 0xb8, 0xb4, 0x1c, 0xfd, 0xc4, 0x82, 0x6a, 0x7a, 0xd3, 0xff, 0xff, 0xf0, + 0xd3, 0xbd, 0xce, 0x0e, 0x77, 0xd0, 0x1e, 0x9f, 0x41, 0x61, 0xaf, 0xd3, + 0xd6, 0x91, 0x05, 0x13, 0x4e, 0x0a, 0xc3, 0x23, 0x93, 0x90, 0xbb, 0x9f, + 0xff, 0xff, 0x60, 0x35, 0x98, 0x26, 0xf9, 0xf8, 0xb6, 0x73, 0x7d, 0x0e, + 0x5e, 0x7c, 0x3a, 0xd3, 0xeb, 0x95, 0xc6, 0xf2, 0xb4, 0x62, 0x2b, 0x4a, + 0x10, 0x73, 0xb4, 0xd7, 0xad, 0x3a, 0xef, 0x38, 0xb4, 0x3c, 0xf8, 0x34, + 0x4d, 0xd1, 0xc9, 0xdc, 0xf5, 0xd5, 0xa7, 0x03, 0xdb, 0x2d, 0x3b, 0xb9, + 0xe5, 0x69, 0xf9, 0xb6, 0xd7, 0x8f, 0xb2, 0xd3, 0xc4, 0x1f, 0x6c, 0xb4, + 0xf3, 0x77, 0x4c, 0xb4, 0x05, 0x19, 0x3b, 0x0f, 0x10, 0xe9, 0xc7, 0x78, + 0x5f, 0x76, 0x45, 0x36, 0x59, 0x69, 0xfb, 0xe5, 0x73, 0x07, 0x4b, 0x4f, + 0xb8, 0x2d, 0x9f, 0x52, 0x7f, 0xc5, 0xf7, 0xe7, 0xef, 0xf6, 0x82, 0xa8, + 0x83, 0x77, 0x34, 0xb3, 0xea, 0xb1, 0x1d, 0x96, 0x9f, 0x9f, 0xc1, 0xad, + 0xba, 0xb4, 0xb2, 0xc7, 0xa4, 0x24, 0xb3, 0xff, 0xfe, 0xa7, 0x7b, 0x9c, + 0xeb, 0x60, 0xed, 0xdc, 0xf9, 0x5f, 0x47, 0x5a, 0x2e, 0x94, 0xe9, 0xd8, + 0x55, 0xea, 0x59, 0x0a, 0xf1, 0x26, 0x9f, 0xe6, 0x3e, 0x16, 0xcf, 0x21, + 0x5a, 0x7d, 0x81, 0xd7, 0x19, 0x68, 0x23, 0xdc, 0xf9, 0xb4, 0xee, 0x60, + 0xad, 0x3f, 0xff, 0x0d, 0x1b, 0xe3, 0xc8, 0xd7, 0x74, 0x5b, 0x70, 0x9d, + 0x5a, 0x30, 0xfe, 0x7d, 0x1a, 0x9f, 0xf1, 0xf3, 0xba, 0xf3, 0xaa, 0x7e, + 0x2d, 0x3f, 0x6b, 0x4d, 0xfe, 0xb2, 0xdb, 0x9b, 0xf9, 0xf7, 0x97, 0x2a, + 0xbe, 0xb4, 0xf7, 0x30, 0xae, 0x2d, 0x3f, 0x68, 0xbf, 0x9e, 0xfd, 0x68, + 0x24, 0x5a, 0x9c, 0xf7, 0x85, 0x3d, 0x22, 0x98, 0xe6, 0x5a, 0xa2, 0xfc, + 0x9f, 0xf9, 0xfd, 0xf5, 0xef, 0x3f, 0x7a, 0xc7, 0x5a, 0x7f, 0xfb, 0x8c, + 0x1c, 0xb7, 0x8c, 0x1c, 0x0f, 0x19, 0x69, 0xff, 0x8b, 0x07, 0x33, 0x5e, + 0x1f, 0xa3, 0xad, 0x1b, 0x23, 0x5d, 0xc4, 0x6d, 0x27, 0x4e, 0x35, 0xbe, + 0xb4, 0xfc, 0x16, 0x07, 0xf3, 0x65, 0xa3, 0x73, 0xc9, 0x38, 0xe4, 0xc4, + 0xe2, 0xd3, 0xba, 0x57, 0xad, 0x38, 0x5a, 0xcb, 0x4f, 0xff, 0x0b, 0x5b, + 0xc7, 0xf0, 0xbd, 0xba, 0xb0, 0xc6, 0x2d, 0x1e, 0x11, 0x44, 0x71, 0x61, + 0x1c, 0x30, 0x35, 0x0c, 0xaa, 0xec, 0x27, 0x99, 0x0f, 0xf2, 0x7b, 0xa8, + 0x62, 0xcf, 0xb8, 0x57, 0x30, 0x2b, 0x4f, 0x57, 0x5b, 0x65, 0xa7, 0xff, + 0xfc, 0xdc, 0x23, 0xee, 0xe3, 0xeb, 0xfe, 0x78, 0x5b, 0x6a, 0xc5, 0x7a, + 0xd0, 0x6a, 0x2e, 0x9c, 0x28, 0x30, 0x43, 0x3f, 0x57, 0xdb, 0x9e, 0x42, + 0xb4, 0xf3, 0xb5, 0x9a, 0x5a, 0x7f, 0x9e, 0x7a, 0x7f, 0x74, 0xc6, 0xad, + 0x0c, 0x7b, 0x54, 0x43, 0x31, 0x3a, 0xb4, 0xc4, 0x2b, 0x4b, 0x02, 0x6a, + 0xb4, 0x2d, 0x14, 0x8f, 0x81, 0x84, 0x47, 0xa9, 0x53, 0xb6, 0xbd, 0xeb, + 0x4f, 0x79, 0xf6, 0xb4, 0xb4, 0xf0, 0x01, 0x9b, 0x2d, 0x3f, 0x18, 0xee, + 0x50, 0xd9, 0x69, 0xfe, 0xf6, 0x9e, 0x1c, 0xc0, 0x69, 0x69, 0xfc, 0x02, + 0xdb, 0x67, 0xe7, 0x56, 0x8e, 0x1f, 0x66, 0x8e, 0x27, 0xe6, 0xdb, 0x47, + 0x23, 0x35, 0xa3, 0xe9, 0x86, 0xf0, 0x8b, 0xb0, 0x99, 0xb8, 0x45, 0x0c, + 0x9b, 0xb6, 0x46, 0x63, 0x33, 0x9e, 0xad, 0x23, 0xad, 0x1b, 0x1a, 0x8b, + 0xa8, 0x62, 0x7e, 0xad, 0x9e, 0x2c, 0x15, 0xa7, 0xf9, 0xb6, 0x79, 0x09, + 0xeb, 0xab, 0x45, 0x1f, 0x18, 0x96, 0x4f, 0xfc, 0x4d, 0xa1, 0xa7, 0xf8, + 0xd6, 0x7d, 0x69, 0xff, 0xfc, 0x5a, 0xbf, 0x1d, 0xc1, 0xf4, 0xc3, 0x6f, + 0x83, 0x5f, 0x5a, 0x05, 0x14, 0xbd, 0x43, 0x9f, 0xff, 0xf7, 0x0b, 0x6e, + 0xe6, 0xdd, 0xff, 0xdb, 0xa0, 0xf2, 0x2f, 0xe6, 0x2d, 0x3c, 0x10, 0xd0, + 0xad, 0x3f, 0xea, 0xe5, 0x8a, 0xbc, 0x6a, 0xb8, 0xb4, 0xff, 0xb2, 0xdc, + 0x23, 0x6e, 0xfd, 0xf9, 0xab, 0x4f, 0xf7, 0x0a, 0x81, 0x81, 0xa7, 0xad, + 0x0c, 0xaa, 0xe0, 0x30, 0x8a, 0xc8, 0x62, 0xd8, 0x88, 0x9b, 0xf8, 0x40, + 0x27, 0xdd, 0x44, 0x9f, 0xfb, 0x04, 0x19, 0x9f, 0xd7, 0x5b, 0x16, 0x9f, + 0xed, 0xbb, 0x9f, 0x2b, 0xe8, 0xeb, 0x4b, 0x00, 0x7f, 0x22, 0x81, 0x3f, + 0xfe, 0x61, 0x7e, 0x70, 0x8e, 0x1c, 0x71, 0xb3, 0xeb, 0x4f, 0xc0, 0xd5, + 0x9b, 0xe6, 0xad, 0x3f, 0xb1, 0xf8, 0x41, 0xe1, 0x2d, 0x3d, 0xd7, 0x9f, + 0x8b, 0x4f, 0x11, 0xa4, 0xea, 0xd1, 0x87, 0x88, 0x24, 0x53, 0x78, 0xc5, + 0xa7, 0xb4, 0x2c, 0x75, 0xa1, 0x8d, 0xbe, 0xc2, 0xf3, 0xd9, 0xc7, 0x9d, + 0x68, 0x64, 0xec, 0xcd, 0x26, 0xa5, 0x21, 0x2e, 0xd3, 0xa7, 0xaa, 0xf7, + 0x64, 0x32, 0xe2, 0xd3, 0x69, 0xeb, 0x40, 0x0d, 0x37, 0xa2, 0x13, 0xf5, + 0xee, 0x3e, 0xeb, 0xfd, 0xeb, 0x4f, 0x72, 0xb3, 0xeb, 0x4f, 0x05, 0xb6, + 0xd2, 0xd3, 0xf8, 0xde, 0x67, 0x78, 0x5d, 0x5a, 0x62, 0xfa, 0xd0, 0x65, + 0x23, 0x01, 0x8d, 0xb0, 0x80, 0x88, 0xb8, 0x67, 0x3f, 0xf5, 0xfc, 0xc0, + 0x84, 0xb6, 0xcd, 0xba, 0xb4, 0xff, 0xc1, 0x60, 0xfd, 0xba, 0x56, 0x20, + 0xad, 0x3c, 0xe3, 0x18, 0x7a, 0xd3, 0xfc, 0xe6, 0xae, 0x50, 0xdf, 0xe8, + 0x56, 0x9f, 0xb9, 0xed, 0xee, 0x70, 0x96, 0x9e, 0x11, 0xce, 0xad, 0x0c, + 0x99, 0xc0, 0x51, 0xb1, 0x08, 0x89, 0x38, 0x7b, 0xd3, 0x09, 0xff, 0xec, + 0x16, 0xb9, 0xf6, 0xfe, 0x17, 0x18, 0x2b, 0x4b, 0x73, 0x29, 0xbf, 0x97, + 0xba, 0x4f, 0xae, 0x88, 0xe3, 0x46, 0xf3, 0x7c, 0x28, 0x1e, 0x42, 0x18, + 0xcd, 0x72, 0x58, 0xf9, 0xb0, 0x95, 0xb4, 0x72, 0x5b, 0x46, 0x68, 0x50, + 0xf8, 0x72, 0x50, 0x0f, 0xe1, 0x5c, 0x78, 0x4d, 0x72, 0x5e, 0x8d, 0x46, + 0x18, 0x08, 0xcb, 0x2e, 0xa3, 0x41, 0x8e, 0x53, 0x52, 0xc2, 0x3b, 0x2a, + 0x95, 0xd8, 0x46, 0xdd, 0xc3, 0x8b, 0xcc, 0x70, 0x86, 0x15, 0x63, 0x77, + 0x43, 0xc1, 0xca, 0xff, 0x9e, 0x7f, 0xf6, 0xe7, 0xa7, 0xef, 0x9f, 0xb5, + 0x55, 0x95, 0x13, 0x64, 0xfe, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, 0x2a, 0xd9, + 0xfc, 0xf7, 0xfb, 0xd1, 0x67, 0xad, 0x3d, 0x9c, 0xae, 0xad, 0x23, 0x2f, + 0x0f, 0x4c, 0x4c, 0xe7, 0x55, 0x59, 0x51, 0x5a, 0x4f, 0x8d, 0xdb, 0x5e, + 0xec, 0xb4, 0xbf, 0x63, 0xd3, 0x22, 0x79, 0xff, 0xeb, 0x37, 0xf0, 0x14, + 0x7a, 0x7b, 0x15, 0x96, 0x9f, 0xfe, 0x7e, 0xb0, 0x58, 0xf5, 0x9d, 0xeb, + 0x1d, 0x69, 0xbb, 0xd6, 0x44, 0xc5, 0x26, 0x4f, 0x3f, 0xa5, 0x7a, 0xd3, + 0xef, 0x3d, 0x16, 0x02, 0xd2, 0x6d, 0x8f, 0x2a, 0xe1, 0x14, 0xfd, 0x7e, + 0x70, 0xb0, 0xeb, 0x4f, 0xe7, 0xb7, 0xef, 0x6f, 0xde, 0xb4, 0xf9, 0xcc, + 0x09, 0xcc, 0xd6, 0x9f, 0x85, 0x9d, 0xd9, 0xfa, 0x5a, 0x1c, 0x3d, 0x93, + 0x05, 0x70, 0xc8, 0xb2, 0xc8, 0x46, 0xcf, 0xe7, 0xe7, 0x68, 0x41, 0xea, + 0xd2, 0xde, 0xeb, 0x56, 0x29, 0x8f, 0xc5, 0x0b, 0xfe, 0x3b, 0xd1, 0x50, + 0xc3, 0x7b, 0xa4, 0xd3, 0xfb, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xb0, 0x27, + 0xdf, 0xb5, 0x55, 0x95, 0x13, 0xac, 0xff, 0xfe, 0xe3, 0x5e, 0x1c, 0x3e, + 0xfa, 0xd6, 0x70, 0xb5, 0xed, 0xeb, 0x4f, 0xb7, 0x3d, 0x3f, 0x7c, 0x44, + 0xbb, 0x86, 0x73, 0xf9, 0xfa, 0xdc, 0xd3, 0x58, 0xeb, 0x4f, 0xbf, 0x6a, + 0xab, 0x2a, 0x2d, 0x99, 0xff, 0xfd, 0x4f, 0xdf, 0x4c, 0x58, 0x12, 0xcd, + 0x67, 0x45, 0x96, 0x9f, 0xf0, 0x1b, 0x5b, 0xf0, 0xad, 0x5f, 0x5a, 0x7f, + 0x99, 0xed, 0xfb, 0xdb, 0xf7, 0xad, 0x2d, 0xf1, 0x30, 0x63, 0x99, 0xd2, + 0xe0, 0x9f, 0x4f, 0x5a, 0xaa, 0xca, 0x8b, 0x9a, 0x47, 0x5a, 0x3e, 0x6f, + 0x5d, 0x2d, 0x99, 0xc3, 0xad, 0x2d, 0xf0, 0xdc, 0xba, 0x45, 0x3e, 0xfd, + 0xaa, 0xac, 0xa8, 0xbb, 0xe7, 0xf3, 0xf7, 0xd7, 0xfe, 0x4e, 0xad, 0x2d, + 0xf0, 0xfa, 0x28, 0xce, 0x7b, 0x73, 0x42, 0x05, 0xa1, 0x9d, 0x54, 0xde, + 0x5a, 0x20, 0xbb, 0x1a, 0x6c, 0xae, 0x52, 0xe9, 0xbe, 0xf0, 0x78, 0x6b, + 0x52, 0x10, 0x23, 0x3c, 0xd4, 0x2e, 0x3b, 0x09, 0x0f, 0x24, 0xf3, 0xed, + 0x68, 0xf4, 0xf5, 0xa7, 0xfe, 0xda, 0xde, 0xd6, 0xdd, 0xcc, 0x13, 0x56, + 0x9c, 0x35, 0xbb, 0x1f, 0x6f, 0x49, 0xe7, 0xf0, 0xdf, 0x86, 0x3a, 0xc6, + 0xad, 0x3f, 0xed, 0x51, 0xbc, 0x26, 0x1f, 0x59, 0x69, 0xff, 0x72, 0xbb, + 0x5c, 0xd9, 0xf9, 0xd5, 0xa3, 0x0f, 0xec, 0x8f, 0x67, 0xff, 0xff, 0xbe, + 0x34, 0xe8, 0xe7, 0x7b, 0x97, 0xb0, 0xd1, 0xba, 0x3b, 0x60, 0x85, 0x69, + 0xeb, 0x55, 0x59, 0x51, 0x2b, 0xcf, 0xfe, 0xef, 0x31, 0xf6, 0xe1, 0x05, + 0x87, 0xab, 0x47, 0xcf, 0xd4, 0x4b, 0x66, 0x7d, 0xeb, 0x4f, 0xf8, 0x69, + 0xd0, 0xf1, 0xaf, 0xc7, 0x56, 0x9f, 0xff, 0x9f, 0x84, 0x0c, 0x39, 0x77, + 0x4c, 0x7a, 0xdb, 0xab, 0x4f, 0x7b, 0x5f, 0x7a, 0xd3, 0xff, 0xf8, 0xbb, + 0x47, 0xa1, 0x07, 0x1d, 0xa1, 0xbe, 0xc5, 0x7a, 0xd0, 0x14, 0x41, 0x51, + 0x14, 0x05, 0x33, 0xcc, 0x3f, 0xe4, 0x36, 0xe7, 0xfd, 0xda, 0x7e, 0xb8, + 0xdf, 0xf2, 0x15, 0xa7, 0xfe, 0xe9, 0x5c, 0x2e, 0xb8, 0xf6, 0x1e, 0xad, + 0x3a, 0x9f, 0xbb, 0x2b, 0xed, 0x7c, 0x2c, 0x02, 0x41, 0x90, 0xef, 0x39, + 0x0e, 0xa3, 0x53, 0xe9, 0xaf, 0x94, 0x09, 0xff, 0xd9, 0xcd, 0xc7, 0x02, + 0x43, 0xdc, 0xe2, 0xd3, 0xba, 0xc1, 0x4a, 0x7f, 0xf7, 0x28, 0xba, 0xcf, + 0x2f, 0xdf, 0xe8, 0x12, 0x9f, 0xd5, 0x6d, 0xc3, 0xfb, 0xab, 0x76, 0x3e, + 0x5d, 0x0d, 0xcb, 0x7b, 0x2e, 0xd8, 0x9e, 0x70, 0x7f, 0xb0, 0x95, 0xb9, + 0x0a, 0xc9, 0xff, 0xdb, 0x9e, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x4c, + 0x33, 0xff, 0xf6, 0x6f, 0xe7, 0xf4, 0x0d, 0xcd, 0xeb, 0xdd, 0x6d, 0x3d, + 0x69, 0xff, 0x8c, 0xbc, 0xd9, 0xfe, 0xd7, 0x45, 0x9e, 0xb4, 0xfe, 0x6a, + 0xbf, 0xa6, 0xd7, 0xd6, 0x9f, 0x57, 0xdf, 0x47, 0x5a, 0x04, 0xf6, 0x7d, + 0x33, 0x9f, 0xff, 0x17, 0xf9, 0x5e, 0x03, 0x8f, 0xe3, 0x5c, 0x0b, 0x2d, + 0x3f, 0xf6, 0x6c, 0xef, 0x9e, 0x35, 0xb8, 0x4e, 0x2d, 0x1c, 0x44, 0xf8, + 0xab, 0xcf, 0xc7, 0x6c, 0x1e, 0xdd, 0xad, 0x2d, 0x2d, 0x3e, 0x6c, 0x1e, + 0xdd, 0xad, 0x3f, 0x70, 0xbb, 0xaa, 0xdb, 0xc1, 0xf3, 0x38, 0x5c, 0x71, + 0x09, 0xff, 0xfc, 0xe9, 0x8e, 0xe7, 0x3c, 0x0e, 0x5e, 0x58, 0x3b, 0x3f, + 0x4b, 0x4f, 0x9d, 0xee, 0x72, 0xcb, 0x48, 0x71, 0x11, 0xb4, 0xcb, 0x3f, + 0xfc, 0xdd, 0x1a, 0x07, 0x30, 0x83, 0xef, 0x74, 0xb4, 0xfd, 0x73, 0xcf, + 0x45, 0x80, 0xb4, 0xff, 0xe6, 0xe8, 0x19, 0xf9, 0xb7, 0x6f, 0xf5, 0xd5, + 0xa1, 0x8f, 0xf4, 0x8c, 0x27, 0xf0, 0x28, 0x1f, 0xf9, 0x7d, 0x69, 0xfb, + 0x44, 0x69, 0xeb, 0xab, 0x4f, 0xff, 0xfb, 0xf9, 0x71, 0x87, 0xbe, 0x3c, + 0x8b, 0x72, 0x8b, 0xad, 0xdd, 0x2d, 0x1b, 0x22, 0x6f, 0xe5, 0xb3, 0xde, + 0x2e, 0x18, 0xbd, 0x68, 0xc3, 0xcd, 0x34, 0x92, 0x7f, 0xb8, 0xc3, 0xda, + 0x39, 0x75, 0x69, 0xff, 0xf7, 0x07, 0x3b, 0xc2, 0xcd, 0xbb, 0x97, 0x1b, + 0x4b, 0x4e, 0x60, 0x79, 0x5a, 0x30, 0xfc, 0x85, 0x56, 0x7a, 0xbc, 0x87, + 0x16, 0x96, 0xf7, 0x5a, 0xf0, 0x20, 0x61, 0x45, 0x90, 0xc1, 0xb4, 0x22, + 0x1c, 0x87, 0x17, 0xc9, 0xb9, 0x0c, 0xb0, 0x10, 0x0c, 0x63, 0x5a, 0x22, + 0xec, 0x2a, 0x3d, 0x20, 0x9f, 0xfe, 0xf9, 0x6c, 0xfd, 0x17, 0x78, 0xdf, + 0xeb, 0x2d, 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0xab, 0xa7, 0x7d, 0x8e, 0xb4, + 0xff, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0x8f, 0x27, 0xf9, 0x9e, 0xdf, + 0xbd, 0xbf, 0x7a, 0xd2, 0xdc, 0x29, 0x8d, 0xe2, 0x7f, 0xcc, 0xe8, 0x6c, + 0x51, 0x67, 0xf6, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x60, 0xcf, 0xed, 0xf3, + 0xf6, 0xaa, 0xb2, 0xa2, 0xca, 0x9f, 0xdb, 0xe7, 0xed, 0x55, 0x65, 0x45, + 0xa7, 0x3f, 0xd7, 0x5f, 0x09, 0xd0, 0xd5, 0x59, 0x69, 0xfe, 0xba, 0xfc, + 0x9f, 0x3b, 0xa2, 0xd2, 0xd3, 0xff, 0xf1, 0x72, 0x87, 0xaf, 0xcf, 0xe3, + 0x08, 0xe7, 0x56, 0x9f, 0x5c, 0xa0, 0xe1, 0xd6, 0x87, 0x9f, 0xee, 0x2a, + 0xcf, 0xec, 0xd7, 0x8f, 0xff, 0xde, 0x2d, 0x3f, 0xfe, 0x61, 0xb7, 0x0b, + 0x85, 0xf6, 0x71, 0xdc, 0xe2, 0xd3, 0xcd, 0xe5, 0xb8, 0xb4, 0xf5, 0xaa, + 0xac, 0xa8, 0xb7, 0x27, 0xfe, 0x6c, 0xfe, 0x0f, 0x8e, 0x66, 0xce, 0xad, + 0x1b, 0x22, 0x53, 0xe4, 0x5a, 0x2d, 0x9c, 0x71, 0x25, 0xa4, 0x2b, 0x4f, + 0xf7, 0x3d, 0xad, 0x66, 0x09, 0xab, 0x4f, 0xb5, 0x5b, 0x50, 0x56, 0x91, + 0x04, 0xf7, 0xfa, 0x71, 0x0c, 0x8a, 0xfc, 0x1a, 0xe3, 0x74, 0xff, 0x30, + 0xfa, 0x76, 0xd7, 0x49, 0x69, 0xe0, 0xb6, 0x7d, 0x69, 0xf7, 0x8d, 0xb4, + 0x46, 0xad, 0x35, 0x55, 0xe7, 0x97, 0xb1, 0x04, 0x2d, 0x3b, 0xda, 0xea, + 0xd3, 0x7a, 0xcb, 0x43, 0xcd, 0x97, 0x47, 0x21, 0x69, 0xed, 0xac, 0x5f, + 0x5a, 0x78, 0x98, 0xfb, 0xe2, 0x22, 0x76, 0x3c, 0x39, 0x0f, 0x42, 0xa7, + 0x0f, 0x6e, 0xd6, 0x9f, 0xe7, 0xef, 0x9f, 0xb5, 0x55, 0x95, 0x14, 0x3c, + 0x11, 0xf1, 0xd0, 0xf4, 0xfe, 0x6f, 0x81, 0xad, 0x87, 0x5a, 0x7f, 0xd4, + 0x16, 0x0f, 0x08, 0x48, 0xeb, 0x4f, 0xfd, 0xa6, 0x17, 0x30, 0x41, 0x5d, + 0xc5, 0xa0, 0xe7, 0xf9, 0xc3, 0xb9, 0xff, 0xbd, 0x7f, 0x2b, 0xfb, 0x75, + 0x8a, 0xf5, 0xa7, 0xf9, 0x9e, 0xdf, 0xbd, 0xbf, 0x7a, 0xd3, 0xe2, 0xee, + 0xa8, 0x96, 0x9f, 0xef, 0x83, 0xf4, 0x3d, 0xc0, 0x2d, 0x00, 0x3d, 0xcf, + 0x49, 0x67, 0xfb, 0x04, 0x6b, 0xbe, 0x5a, 0xcb, 0x4f, 0xf8, 0xb6, 0xd7, + 0x8e, 0xf8, 0x0e, 0x0a, 0xd3, 0xea, 0xdb, 0x5d, 0x25, 0xa3, 0x88, 0xa0, + 0x13, 0x7d, 0x21, 0x4f, 0xab, 0xd3, 0x5b, 0xca, 0xd3, 0xeb, 0xaf, 0x3e, + 0xda, 0x5a, 0x1c, 0x3d, 0x51, 0x2a, 0x9f, 0xea, 0xd3, 0x39, 0xb3, 0xf2, + 0xe2, 0xd3, 0xff, 0xe0, 0xf1, 0xbc, 0xef, 0xd1, 0xa0, 0x6b, 0x4c, 0x04, + 0xa6, 0x0e, 0x2d, 0x18, 0x7d, 0x84, 0xaf, 0x3f, 0xb9, 0x40, 0x70, 0x58, + 0x2b, 0x4b, 0x7b, 0xa5, 0x92, 0xc5, 0x74, 0x0f, 0x5a, 0x17, 0x8f, 0x21, + 0x09, 0xb6, 0x43, 0xa2, 0xd0, 0xe0, 0x22, 0xe7, 0x21, 0x05, 0xf8, 0x5b, + 0x9e, 0x16, 0xfc, 0x20, 0xa8, 0x56, 0x80, 0x88, 0x51, 0xb5, 0x09, 0x5e, + 0xc3, 0x0f, 0xd8, 0x42, 0x5c, 0x22, 0xbb, 0x85, 0x3f, 0x92, 0x09, 0xfd, + 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x5e, 0x70, 0xcd, 0xa9, 0x13, 0xd6, 0xc2, + 0xaf, 0x93, 0xcc, 0xbb, 0x47, 0xe7, 0xf4, 0xf3, 0x9f, 0xf0, 0xfc, 0x69, + 0x34, 0x37, 0x23, 0x6b, 0x9f, 0xdb, 0xe7, 0xed, 0x55, 0x65, 0x45, 0x2d, + 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0xb0, 0xa7, 0xff, 0xcd, 0x82, 0x16, 0xe3, + 0x6d, 0xdc, 0x1a, 0x3a, 0xd2, 0xdf, 0x11, 0x08, 0x73, 0x39, 0xfd, 0xbe, + 0x7e, 0xd5, 0x56, 0x54, 0x59, 0x73, 0xdb, 0x9b, 0x74, 0x0c, 0x85, 0xa7, + 0x6f, 0xe4, 0xeb, 0x4b, 0x56, 0x3c, 0xef, 0x4b, 0xe4, 0x05, 0xa6, 0x36, + 0xf5, 0xa6, 0xaf, 0xbc, 0xd4, 0x60, 0x84, 0xfe, 0xbf, 0x6d, 0x30, 0x7a, + 0x4b, 0x4f, 0x9b, 0x2e, 0x36, 0x96, 0x98, 0x5a, 0x8f, 0x6d, 0xd3, 0x49, + 0xea, 0x7b, 0xc2, 0xb4, 0xfd, 0x5f, 0x6e, 0xd7, 0x16, 0x9c, 0xeb, 0xae, + 0xa5, 0x3f, 0xcc, 0xfd, 0xbb, 0xf6, 0xcd, 0x92, 0xdc, 0xbf, 0x99, 0xb4, + 0xb4, 0x05, 0x19, 0x3c, 0x21, 0x14, 0xab, 0x89, 0x33, 0xf1, 0x56, 0x81, + 0xaf, 0x56, 0x9f, 0xff, 0xb8, 0x5d, 0xe6, 0x68, 0x70, 0xfe, 0xeb, 0x94, + 0xf5, 0xa7, 0xf3, 0x3f, 0xb5, 0xca, 0x0a, 0xd1, 0x88, 0x8b, 0xfa, 0xd4, + 0x9e, 0xb4, 0x9e, 0xb4, 0x9e, 0xb4, 0x31, 0xb0, 0x34, 0x40, 0x84, 0x27, + 0xff, 0xdd, 0xd1, 0x5b, 0x07, 0xec, 0x38, 0x1c, 0x35, 0x69, 0x6c, 0xb4, + 0xda, 0xf5, 0x68, 0xc3, 0xfa, 0xd2, 0x97, 0x44, 0x66, 0x26, 0x5a, 0x7e, + 0x16, 0x38, 0xb6, 0x2d, 0x33, 0xd9, 0x68, 0x09, 0xe9, 0x38, 0x29, 0xe9, + 0x4c, 0xff, 0xff, 0xf7, 0x1b, 0xba, 0x2d, 0x69, 0xbb, 0xc2, 0x6f, 0x80, + 0xf4, 0xf7, 0xf4, 0xd5, 0xa6, 0x63, 0xad, 0x3f, 0xff, 0x3d, 0x87, 0xd7, + 0xbd, 0xbb, 0xcc, 0x3f, 0x96, 0x02, 0xd3, 0x5b, 0x76, 0x5d, 0x5a, 0xbd, + 0x44, 0x30, 0x86, 0xc8, 0x7a, 0xd8, 0xfb, 0xf0, 0xb8, 0xa5, 0x21, 0x85, + 0x3e, 0xa1, 0x01, 0xd3, 0x1b, 0xb7, 0xdf, 0x22, 0xb3, 0xff, 0xb7, 0x3d, + 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xa3, 0x27, 0xd7, 0x1b, 0xec, 0x05, + 0xa7, 0xc3, 0x40, 0x6f, 0x2b, 0x4b, 0x76, 0x3c, 0xfe, 0x14, 0x43, 0xd9, + 0x0e, 0x3f, 0x86, 0x19, 0xca, 0x6a, 0x77, 0x9f, 0x50, 0xd0, 0xec, 0x29, + 0xa7, 0xfe, 0xde, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, 0x47, 0x33, 0xff, + 0xb7, 0x3d, 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0x9c, 0xa7, 0xf6, 0xf9, + 0xfb, 0x55, 0x59, 0x51, 0x66, 0x4f, 0xf3, 0xf5, 0x47, 0xdf, 0x9d, 0x02, + 0xd3, 0xfc, 0x64, 0x83, 0x87, 0x6d, 0x98, 0xeb, 0x4f, 0xf0, 0x3e, 0xdd, + 0xe5, 0x6c, 0xf5, 0xa7, 0xf6, 0x6b, 0xff, 0xcd, 0xb4, 0xb4, 0xb7, 0x32, + 0x11, 0x54, 0xc7, 0xcf, 0x39, 0x9f, 0xdb, 0xe7, 0xed, 0x55, 0x65, 0x45, + 0xbb, 0x3f, 0x0d, 0x6f, 0xfb, 0xf8, 0xb4, 0xff, 0xa9, 0xfb, 0xe7, 0xed, + 0x55, 0x65, 0x45, 0x21, 0x2d, 0xec, 0x7f, 0x07, 0x2e, 0x9f, 0xfb, 0x7a, + 0x7e, 0xf9, 0xfb, 0x55, 0x59, 0x51, 0x29, 0x45, 0xea, 0xcd, 0xdc, 0x51, + 0x3a, 0xbd, 0x1f, 0x82, 0x1c, 0x82, 0x77, 0xd8, 0x5b, 0x98, 0x29, 0x9f, + 0x6e, 0x5a, 0xf4, 0xeb, 0x4f, 0xfa, 0x9f, 0xbe, 0x7e, 0xd5, 0x56, 0x54, + 0x4e, 0xd3, 0x5e, 0x66, 0xb4, 0xff, 0xf8, 0x83, 0xe9, 0xd8, 0xc5, 0x04, + 0x58, 0x72, 0xcb, 0x4f, 0xf3, 0x3d, 0xbf, 0x7b, 0x7e, 0xf5, 0xa5, 0xb9, + 0xd1, 0xe3, 0xc4, 0xaa, 0x1a, 0x15, 0x49, 0xff, 0xed, 0xfc, 0xdd, 0xd0, + 0x83, 0x3a, 0xc2, 0x40, 0x5a, 0x7f, 0xea, 0x3f, 0x32, 0xd5, 0xc6, 0xf2, + 0xf5, 0xa7, 0xfe, 0x1c, 0xe5, 0x5f, 0x9a, 0x1a, 0xd9, 0x69, 0xae, 0xf7, + 0x0a, 0x21, 0xb4, 0x89, 0x0f, 0x54, 0xce, 0x78, 0xc6, 0xb4, 0x85, 0x77, + 0x0d, 0x89, 0xff, 0xf8, 0x35, 0xdd, 0xf3, 0x4c, 0x3b, 0x03, 0x5a, 0x60, + 0x2d, 0x3e, 0xfd, 0xaa, 0xac, 0xa8, 0x8b, 0x27, 0xfd, 0x4f, 0xdf, 0x3f, + 0x6a, 0xab, 0x2a, 0x25, 0xd9, 0xff, 0xfb, 0x03, 0xc6, 0xf3, 0xbf, 0x46, + 0x81, 0xad, 0x30, 0x12, 0x96, 0xf8, 0x8d, 0x93, 0x99, 0xdd, 0xa5, 0x4f, + 0xfe, 0xdc, 0xf4, 0xfd, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0x62, 0x9f, 0x7e, + 0xd5, 0x56, 0x54, 0x55, 0x32, 0xc5, 0xa3, 0x0f, 0x08, 0xd3, 0x39, 0xff, + 0xff, 0xdf, 0xae, 0x6c, 0xfc, 0xee, 0xfc, 0xad, 0x7c, 0x9d, 0xef, 0x0b, + 0xef, 0x5a, 0x37, 0x44, 0xe5, 0x11, 0x4f, 0xfe, 0xdc, 0xf4, 0xfd, 0xf3, + 0xf6, 0xaa, 0xb2, 0xa2, 0x74, 0x9f, 0xc5, 0x5f, 0x67, 0xd5, 0xc5, 0xa7, + 0xce, 0x33, 0x8d, 0xa5, 0xa7, 0xe7, 0x70, 0xae, 0x60, 0xad, 0x04, 0x7a, + 0xba, 0x28, 0x9c, 0x5c, 0x65, 0xb7, 0x34, 0x33, 0xff, 0x7b, 0xae, 0xb6, + 0xdb, 0xfa, 0xe1, 0x1d, 0x68, 0x39, 0xfa, 0x70, 0xae, 0x7f, 0xd4, 0xfd, + 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, 0x77, 0x9f, 0x77, 0xda, 0x39, 0x25, 0x3f, + 0xe1, 0x6e, 0xe6, 0xb3, 0x36, 0x7a, 0xd2, 0xdc, 0x29, 0xf5, 0xe4, 0x63, + 0x87, 0x22, 0xa4, 0xae, 0x93, 0xcf, 0xfe, 0xdc, 0xf4, 0xfd, 0xf3, 0xf6, + 0xaa, 0xb2, 0xa2, 0x85, 0x9f, 0xff, 0xfe, 0x2e, 0x7a, 0x73, 0xd3, 0xf7, + 0xb7, 0x3d, 0xeb, 0x0e, 0x5e, 0x6f, 0xac, 0xe2, 0xd3, 0xff, 0xb7, 0x3d, + 0x3f, 0x7c, 0xfd, 0xaa, 0xac, 0xa8, 0xa4, 0xa7, 0xff, 0xf6, 0x6b, 0x7f, + 0x38, 0xe7, 0x28, 0xfd, 0xe3, 0x77, 0xd3, 0xad, 0x0c, 0xbd, 0xe7, 0x7c, + 0x66, 0x8f, 0x39, 0xb4, 0x66, 0xbf, 0x23, 0x3c, 0xa4, 0x20, 0x2b, 0x75, + 0x5f, 0xd8, 0x41, 0xdd, 0xab, 0xcf, 0xed, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, + 0x24, 0x9f, 0xfd, 0xb9, 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x44, 0xbd, + 0x3d, 0xff, 0x7b, 0xa5, 0xa7, 0xdf, 0x01, 0xcb, 0x4b, 0x4f, 0xe2, 0x1e, + 0xf9, 0x38, 0xb2, 0xd3, 0xff, 0xb9, 0x71, 0x84, 0x06, 0x78, 0x1c, 0xfe, + 0xcb, 0x4c, 0xdd, 0x5a, 0x7f, 0xf7, 0xa1, 0x2f, 0xf9, 0x70, 0xc7, 0xb4, + 0x2e, 0x2d, 0x0f, 0x47, 0x31, 0x19, 0x01, 0x3b, 0x42, 0xb3, 0xff, 0x53, + 0x9a, 0x6b, 0x95, 0xc6, 0xd9, 0xc5, 0xa5, 0x8b, 0x4d, 0xf6, 0x5a, 0x02, + 0x9e, 0xb9, 0x11, 0xb9, 0x18, 0x6f, 0xcf, 0x2e, 0x23, 0x98, 0x0f, 0x9f, + 0xe2, 0xa1, 0xf7, 0xae, 0x31, 0xab, 0x4f, 0x15, 0xe0, 0x33, 0x5a, 0x7a, + 0xd5, 0x56, 0x54, 0x52, 0xf0, 0xe1, 0xe9, 0x7c, 0x96, 0x7c, 0x3d, 0xbf, + 0x1d, 0x5a, 0x7f, 0xcc, 0x2d, 0xcf, 0x1e, 0x8f, 0xb6, 0x5a, 0x77, 0xb5, + 0xa5, 0xa7, 0xb5, 0x9d, 0xd2, 0xd0, 0x13, 0xfd, 0x71, 0x03, 0xa3, 0x93, + 0xfc, 0x0d, 0x7d, 0xb6, 0x79, 0x1d, 0x69, 0xfe, 0xab, 0xfc, 0x5f, 0xeb, + 0x8c, 0x66, 0xb4, 0x31, 0xfd, 0x7a, 0x73, 0x3f, 0xc5, 0xa7, 0x08, 0x7a, + 0xc0, 0x5a, 0x1e, 0x7b, 0x27, 0x22, 0x9f, 0xfb, 0xf7, 0x18, 0x1e, 0x38, + 0xc7, 0xa1, 0x5a, 0x30, 0xfa, 0x08, 0x8a, 0x77, 0xd8, 0xeb, 0x4f, 0xcc, + 0x2e, 0x74, 0x8d, 0x5a, 0x7e, 0xf8, 0x1a, 0xd8, 0x75, 0xa6, 0x7e, 0x2d, + 0x39, 0x81, 0xa5, 0xa1, 0x8f, 0x70, 0x25, 0x8e, 0x8a, 0xcf, 0xfc, 0x47, + 0xa0, 0xf9, 0x71, 0xec, 0x3b, 0x2d, 0x3d, 0xa2, 0x77, 0xab, 0x47, 0x0f, + 0xa3, 0xa8, 0xd3, 0xff, 0xf1, 0xd9, 0xe2, 0xd7, 0xf9, 0x73, 0x5c, 0xc3, + 0x1f, 0x02, 0xd3, 0xd6, 0x6b, 0x9a, 0x5a, 0x7f, 0x80, 0xc0, 0xf3, 0x71, + 0x84, 0xc2, 0xd1, 0x87, 0xc0, 0x44, 0x73, 0xff, 0xff, 0x71, 0xbf, 0xb5, + 0x8b, 0x6f, 0x06, 0xd7, 0x8d, 0x72, 0xac, 0xc2, 0x15, 0xa7, 0xf7, 0x29, + 0xc2, 0xfb, 0x5e, 0xb4, 0xd8, 0x75, 0xa0, 0x28, 0xbf, 0xa7, 0x7b, 0x86, + 0x73, 0xe3, 0x04, 0x76, 0xd2, 0xd3, 0xea, 0xb9, 0x9f, 0xd2, 0xd0, 0x13, + 0xd0, 0x39, 0x44, 0xfb, 0x94, 0x24, 0x75, 0xa1, 0x8f, 0x1f, 0x08, 0xa6, + 0x05, 0x96, 0x96, 0x96, 0x98, 0x8d, 0xd1, 0xa6, 0xf4, 0x5a, 0x5b, 0xb2, + 0xfb, 0xc0, 0x58, 0xb2, 0x11, 0x7b, 0x11, 0x94, 0x29, 0x5c, 0x8d, 0xaf, + 0xe4, 0x07, 0x1b, 0xe4, 0x22, 0x6a, 0x12, 0xe0, 0x22, 0x18, 0x60, 0x6a, + 0x1b, 0xfd, 0x86, 0x45, 0xda, 0x34, 0xfe, 0xdf, 0x3f, 0x6a, 0xab, 0x2a, + 0x29, 0xc9, 0xff, 0x17, 0xeb, 0x5c, 0xcc, 0x1b, 0x2d, 0x3f, 0x88, 0xe1, + 0x6d, 0x7a, 0x2b, 0x4f, 0xfc, 0x69, 0x6d, 0xa1, 0xc0, 0xf2, 0x9d, 0x5a, + 0x7f, 0xd9, 0xc6, 0xfe, 0x6e, 0xeb, 0xae, 0xa5, 0x31, 0x3a, 0xb4, 0xd7, + 0xee, 0x14, 0xc2, 0x78, 0x77, 0xd3, 0x2b, 0xb4, 0x53, 0x08, 0x33, 0xef, + 0xda, 0xaa, 0xca, 0x8a, 0xf2, 0x7f, 0xfe, 0xc0, 0xf1, 0xbc, 0xef, 0xd1, + 0xa0, 0x6b, 0x4c, 0x04, 0xa5, 0xbe, 0x22, 0x3e, 0xec, 0xce, 0x7f, 0xed, + 0xe9, 0xfb, 0xe7, 0xed, 0x55, 0x65, 0x44, 0x8f, 0x38, 0x80, 0xcb, 0x4e, + 0xb6, 0x1d, 0x2d, 0xcb, 0xa9, 0xf7, 0xed, 0x55, 0x65, 0x44, 0x91, 0x3f, + 0xff, 0x31, 0x7c, 0x8c, 0x30, 0xde, 0xdd, 0x2e, 0x55, 0xeb, 0x4f, 0x6f, + 0x4f, 0xdd, 0x91, 0x71, 0x85, 0x7c, 0x33, 0x9f, 0xfb, 0x7a, 0x7e, 0xf9, + 0xfb, 0x55, 0x59, 0x51, 0x25, 0x4f, 0xbf, 0x6a, 0xab, 0x2a, 0x2f, 0x19, + 0xf6, 0xb5, 0xdc, 0xb2, 0xd3, 0xfc, 0xfd, 0xf3, 0xf6, 0xaa, 0xb2, 0xa2, + 0x4d, 0x96, 0xf8, 0x89, 0xff, 0x99, 0xd1, 0x3c, 0xfa, 0xef, 0x76, 0x77, + 0x8b, 0x43, 0x36, 0x00, 0x17, 0x9f, 0xbe, 0x93, 0x4c, 0x18, 0x7f, 0x94, + 0x69, 0x0e, 0x43, 0xb4, 0xe5, 0x9c, 0x8c, 0x8f, 0xa8, 0xfe, 0xc3, 0xc3, + 0xc9, 0xac, 0x34, 0xa8, 0x1a, 0x2b, 0xe3, 0xde, 0x7c, 0xe0, 0xe0, 0x65, + 0x5c, 0xe5, 0xee, 0x38, 0x9b, 0x2c, 0x3a, 0xd6, 0xe1, 0xef, 0x6a, 0x59, + 0xb1, 0x52, 0x0e, 0x0c, 0xe5, 0x0d, 0xb9, 0x5f, 0x9c, 0xfe, 0xb3, 0xcc, + 0x3e, 0x37, 0x97, 0xb9, 0x3f, 0xd9, 0x55, 0xec, 0xa8, 0x27, 0x27, 0xee, + 0xa8, 0xc6, 0xc6, 0x96, 0x4b, 0xaa, 0x70, 0xb7, 0x6d, 0x89, 0x47, 0xb5, + 0xe0, 0x8d, 0xca, 0x48, 0xf3, 0xb2, 0xea, 0x2e, 0xe5, 0x73, 0x79, 0x9f, + 0x40, 0x31, 0x58, 0x55, 0x40, }; -static const unsigned kPreloadedHSTSBits = 167522; +static const unsigned kPreloadedHSTSBits = 167268; -static const unsigned kHSTSRootPosition = 166926; +static const unsigned kHSTSRootPosition = 166672; #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 3aefaa3..ff403ec 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -1655,7 +1655,6 @@ { "name": "twisto.cz", "include_subdomains": true, "mode": "force-https" }, { "name": "webassadors.com", "include_subdomains": true, "mode": "force-https" }, { "name": "wundi.net", "include_subdomains": true, "mode": "force-https" }, - { "name": "cs50.harvard.edu", "include_subdomains": true, "mode": "force-https" }, { "name": "007sascha.de", "include_subdomains": true, "mode": "force-https" }, { "name": "2048game.co.uk", "include_subdomains": true, "mode": "force-https" }, { "name": "adorai.tk", "include_subdomains": true, "mode": "force-https" }, @@ -1738,7 +1737,6 @@ { "name": "dynaloop.net", "include_subdomains": true, "mode": "force-https" }, { "name": "eduroam.no", "include_subdomains": true, "mode": "force-https" }, { "name": "egit.co", "include_subdomains": true, "mode": "force-https" }, - { "name": "friendlink.jp", "include_subdomains": true, "mode": "force-https" }, { "name": "gambitnash.co.uk", "include_subdomains": true, "mode": "force-https" }, { "name": "gavick.com", "include_subdomains": true, "mode": "force-https" }, { "name": "hachre.de", "include_subdomains": true, "mode": "force-https" }, @@ -1850,7 +1848,6 @@ { "name": "bzv-fr.eu", "include_subdomains": true, "mode": "force-https" }, { "name": "codepoints.net", "include_subdomains": true, "mode": "force-https" }, { "name": "codepx.com", "include_subdomains": true, "mode": "force-https" }, - { "name": "cs50.net", "include_subdomains": true, "mode": "force-https" }, { "name": "cyprus-company-service.com", "include_subdomains": true, "mode": "force-https" }, { "name": "darkpony.ru", "include_subdomains": true, "mode": "force-https" }, { "name": "darom.jp", "include_subdomains": true, "mode": "force-https" },
diff --git a/net/log/capturing_net_log_observer.cc b/net/log/capturing_net_log_observer.cc index b226b98..3e7b960b 100644 --- a/net/log/capturing_net_log_observer.cc +++ b/net/log/capturing_net_log_observer.cc
@@ -43,7 +43,7 @@ captured_entries_.clear(); } -void CapturingNetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) { +void CapturingNetLogObserver::OnAddEntry(const NetLog::Entry& entry) { // Using Dictionaries instead of Values makes checking values a little // simpler. base::DictionaryValue* param_dict = nullptr;
diff --git a/net/log/net_log.cc b/net/log/net_log.cc index e112c2c..33243d3c 100644 --- a/net/log/net_log.cc +++ b/net/log/net_log.cc
@@ -41,6 +41,14 @@ return event_params; } +base::Value* NetLogBoolCallback(const char* name, + bool value, + NetLogCaptureMode /* capture_mode */) { + base::DictionaryValue* event_params = new base::DictionaryValue(); + event_params->SetBoolean(name, value); + return event_params; +} + base::Value* NetLogIntegerCallback(const char* name, int value, NetLogCaptureMode /* capture_mode */) { @@ -207,15 +215,15 @@ } void NetLog::AddGlobalEntry(EventType type) { - AddEntry(type, Source(net::NetLog::SOURCE_NONE, NextID()), - net::NetLog::PHASE_NONE, NULL); + AddEntry(type, Source(NetLog::SOURCE_NONE, NextID()), NetLog::PHASE_NONE, + NULL); } void NetLog::AddGlobalEntry( EventType type, const NetLog::ParametersCallback& parameters_callback) { - AddEntry(type, Source(net::NetLog::SOURCE_NONE, NextID()), - net::NetLog::PHASE_NONE, ¶meters_callback); + AddEntry(type, Source(NetLog::SOURCE_NONE, NextID()), NetLog::PHASE_NONE, + ¶meters_callback); } uint32 NetLog::NextID() { @@ -228,7 +236,7 @@ return NetLogCaptureMode::FromInternalValue(capture_mode); } -void NetLog::DeprecatedAddObserver(net::NetLog::ThreadSafeObserver* observer, +void NetLog::DeprecatedAddObserver(NetLog::ThreadSafeObserver* observer, NetLogCaptureMode capture_mode) { DCHECK(capture_mode.enabled()); @@ -242,7 +250,7 @@ UpdateCaptureMode(); } -void NetLog::SetObserverCaptureMode(net::NetLog::ThreadSafeObserver* observer, +void NetLog::SetObserverCaptureMode(NetLog::ThreadSafeObserver* observer, NetLogCaptureMode capture_mode) { DCHECK(capture_mode.enabled()); base::AutoLock lock(lock_); @@ -254,8 +262,7 @@ UpdateCaptureMode(); } -void NetLog::DeprecatedRemoveObserver( - net::NetLog::ThreadSafeObserver* observer) { +void NetLog::DeprecatedRemoveObserver(NetLog::ThreadSafeObserver* observer) { base::AutoLock lock(lock_); DCHECK(observers_.HasObserver(observer)); @@ -349,6 +356,11 @@ } // static +NetLog::ParametersCallback NetLog::BoolCallback(const char* name, bool value) { + return base::Bind(&NetLogBoolCallback, name, value); +} + +// static NetLog::ParametersCallback NetLog::IntegerCallback(const char* name, int value) { return base::Bind(&NetLogIntegerCallback, name, value);
diff --git a/net/log/net_log.h b/net/log/net_log.h index 7d32e1c9..42d40a2e 100644 --- a/net/log/net_log.h +++ b/net/log/net_log.h
@@ -261,7 +261,10 @@ // Returns a C-String symbolic name for |event_phase|. static const char* EventPhaseToString(EventPhase event_phase); - // Creates a ParametersCallback that encapsulates a single integer. + // Creates a ParametersCallback that encapsulates a single bool. + // Warning: |name| must remain valid for the life of the callback. + static ParametersCallback BoolCallback(const char* name, bool value); + // Warning: |name| must remain valid for the life of the callback. // TODO(mmenke): Rename this to be consistent with Int64Callback. static ParametersCallback IntegerCallback(const char* name, int value);
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h index 9337181..c2cc7f2 100644 --- a/net/log/net_log_event_type_list.h +++ b/net/log/net_log_event_type_list.h
@@ -54,8 +54,14 @@ // } EVENT_TYPE(HOST_RESOLVER_IMPL_REQUEST) -// This event is logged when IPv6 support is determined via IPv6 connect probe. -EVENT_TYPE(HOST_RESOLVER_IMPL_IPV6_SUPPORTED) +// This event is created (in a source of the same name) when the host resolver +// creates a UDP socket to check for global IPv6 connectivity. +// It contains the following parameter: +// +// { +// "ipv6_available": <True if the probe indicates ipv6 connectivity>, +// } +EVENT_TYPE(HOST_RESOLVER_IMPL_IPV6_REACHABILITY_CHECK) // This event is logged when a request is handled by a cache entry. EVENT_TYPE(HOST_RESOLVER_IMPL_CACHE_HIT) @@ -2421,10 +2427,6 @@ // contains no parameters. EVENT_TYPE(SIMPLE_CACHE_ENTRY_CLOSE_END) -// This event is created (in a source of the same name) when the internal DNS -// resolver creates a UDP socket to check for global IPv6 connectivity. -EVENT_TYPE(IPV6_REACHABILITY_CHECK) - // ------------------------------------------------------------------------ // SDCH // ------------------------------------------------------------------------
diff --git a/net/log/net_log_source_type_list.h b/net/log/net_log_source_type_list.h index e7939aa7..f72c8de3 100644 --- a/net/log/net_log_source_type_list.h +++ b/net/log/net_log_source_type_list.h
@@ -25,6 +25,5 @@ SOURCE_TYPE(FILESTREAM) SOURCE_TYPE(DNS_PROBER) SOURCE_TYPE(PROXY_CLIENT_SOCKET) -SOURCE_TYPE(IPV6_REACHABILITY_CHECK) SOURCE_TYPE(ASYNC_REVALIDATION) SOURCE_TYPE(DATA_REDUCTION_PROXY)
diff --git a/net/log/net_log_unittest.cc b/net/log/net_log_unittest.cc index 9fad152..9f1696b 100644 --- a/net/log/net_log_unittest.cc +++ b/net/log/net_log_unittest.cc
@@ -30,7 +30,7 @@ TEST(NetLogTest, Basic) { TestNetLog net_log; - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log.GetEntries(&entries); EXPECT_EQ(0u, entries.size()); @@ -63,7 +63,7 @@ net_log.AddGlobalEntry(NetLog::TYPE_SOCKET_ALIVE, base::Bind(NetCaptureModeCallback)); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log.GetEntries(&entries); ASSERT_EQ(1u, entries.size());
diff --git a/net/log/net_log_unittest.h b/net/log/net_log_unittest.h index 1634e60..119d8cf 100644 --- a/net/log/net_log_unittest.h +++ b/net/log/net_log_unittest.h
@@ -7,6 +7,7 @@ #include <cstddef> +#include "net/log/captured_net_log_entry.h" #include "net/log/test_net_log.h" #include "testing/gtest/include/gtest/gtest.h" @@ -20,7 +21,7 @@ } inline ::testing::AssertionResult LogContainsEventHelper( - const TestNetLog::CapturedEntryList& entries, + const CapturedNetLogEntry::List& entries, int i, // Negative indices are reverse indices. const base::TimeTicks& expected_time, bool check_time, @@ -31,7 +32,7 @@ : static_cast<size_t>(i); if (j >= entries.size()) return ::testing::AssertionFailure() << j << " is out of bounds."; - const TestNetLog::CapturedEntry& entry = entries[j]; + const CapturedNetLogEntry& entry = entries[j]; if (expected_event != entry.type) { return ::testing::AssertionFailure() << "Actual event: " << NetLog::EventTypeToString(entry.type) @@ -54,7 +55,7 @@ } inline ::testing::AssertionResult LogContainsEventAtTime( - const TestNetLog::CapturedEntryList& log, + const CapturedNetLogEntry::List& log, int i, // Negative indices are reverse indices. const base::TimeTicks& expected_time, NetLog::EventType expected_event, @@ -65,7 +66,7 @@ // Version without timestamp. inline ::testing::AssertionResult LogContainsEvent( - const TestNetLog::CapturedEntryList& log, + const CapturedNetLogEntry::List& log, int i, // Negative indices are reverse indices. NetLog::EventType expected_event, NetLog::EventPhase expected_phase) { @@ -75,7 +76,7 @@ // Version for PHASE_BEGIN (and no timestamp). inline ::testing::AssertionResult LogContainsBeginEvent( - const TestNetLog::CapturedEntryList& log, + const CapturedNetLogEntry::List& log, int i, // Negative indices are reverse indices. NetLog::EventType expected_event) { return LogContainsEvent(log, i, expected_event, NetLog::PHASE_BEGIN); @@ -83,14 +84,14 @@ // Version for PHASE_END (and no timestamp). inline ::testing::AssertionResult LogContainsEndEvent( - const TestNetLog::CapturedEntryList& log, + const CapturedNetLogEntry::List& log, int i, // Negative indices are reverse indices. NetLog::EventType expected_event) { return LogContainsEvent(log, i, expected_event, NetLog::PHASE_END); } inline ::testing::AssertionResult LogContainsEntryWithType( - const TestNetLog::CapturedEntryList& entries, + const CapturedNetLogEntry::List& entries, int i, // Negative indices are reverse indices. NetLog::EventType type) { // Negative indices are reverse indices. @@ -98,7 +99,7 @@ : static_cast<size_t>(i); if (j >= entries.size()) return ::testing::AssertionFailure() << j << " is out of bounds."; - const TestNetLog::CapturedEntry& entry = entries[j]; + const CapturedNetLogEntry& entry = entries[j]; if (entry.type != type) return ::testing::AssertionFailure() << "Type does not match."; return ::testing::AssertionSuccess(); @@ -107,7 +108,7 @@ // Check if the log contains any entry of the given type at |min_index| or // after. inline ::testing::AssertionResult LogContainsEntryWithTypeAfter( - const TestNetLog::CapturedEntryList& entries, + const CapturedNetLogEntry::List& entries, int min_index, // Negative indices are reverse indices. NetLog::EventType type) { // Negative indices are reverse indices. @@ -116,7 +117,7 @@ ? static_cast<size_t>(static_cast<int>(entries.size()) + min_index) : static_cast<size_t>(min_index); for (size_t i = real_index; i < entries.size(); ++i) { - const TestNetLog::CapturedEntry& entry = entries[i]; + const CapturedNetLogEntry& entry = entries[i]; if (entry.type == type) return ::testing::AssertionSuccess(); } @@ -127,13 +128,13 @@ // as long as the first index where it is found is at least |min_index|. // Returns the position where the event was found. inline size_t ExpectLogContainsSomewhere( - const TestNetLog::CapturedEntryList& entries, + const CapturedNetLogEntry::List& entries, size_t min_index, NetLog::EventType expected_event, NetLog::EventPhase expected_phase) { size_t i = 0; for (; i < entries.size(); ++i) { - const TestNetLog::CapturedEntry& entry = entries[i]; + const CapturedNetLogEntry& entry = entries[i]; if (entry.type == expected_event && entry.phase == expected_phase) break; } @@ -146,13 +147,13 @@ // as long as one index where it is found is at least |min_index|. // Returns the first such position where the event was found. inline size_t ExpectLogContainsSomewhereAfter( - const TestNetLog::CapturedEntryList& entries, + const CapturedNetLogEntry::List& entries, size_t min_index, NetLog::EventType expected_event, NetLog::EventPhase expected_phase) { size_t i = min_index; for (; i < entries.size(); ++i) { - const TestNetLog::CapturedEntry& entry = entries[i]; + const CapturedNetLogEntry& entry = entries[i]; if (entry.type == expected_event && entry.phase == expected_phase) break; }
diff --git a/net/log/net_log_util.cc b/net/log/net_log_util.cc index d178a32..7172967 100644 --- a/net/log/net_log_util.cc +++ b/net/log/net_log_util.cc
@@ -67,8 +67,8 @@ }; const StringToConstant kLoadStateTable[] = { -#define LOAD_STATE(label) \ - { #label, net::LOAD_STATE_##label } \ +#define LOAD_STATE(label) \ + { #label, LOAD_STATE_##label } \ , #include "net/base/load_states_list.h" #undef LOAD_STATE @@ -103,11 +103,11 @@ // Returns the disk cache backend for |context| if there is one, or NULL. // Despite the name, can return an in memory "disk cache". -disk_cache::Backend* GetDiskCacheBackend(net::URLRequestContext* context) { +disk_cache::Backend* GetDiskCacheBackend(URLRequestContext* context) { if (!context->http_transaction_factory()) return NULL; - net::HttpCache* http_cache = context->http_transaction_factory()->GetCache(); + HttpCache* http_cache = context->http_transaction_factory()->GetCache(); if (!http_cache) return NULL; @@ -115,8 +115,8 @@ } // Returns true if |request1| was created before |request2|. -bool RequestCreatedBefore(const net::URLRequest* request1, - const net::URLRequest* request2) { +bool RequestCreatedBefore(const URLRequest* request1, + const URLRequest* request2) { if (request1->creation_time() < request2->creation_time()) return true; if (request1->creation_time() > request2->creation_time()) @@ -129,7 +129,7 @@ // Returns a Value representing the state of a pre-existing URLRequest when // net-internals was opened. base::Value* GetRequestStateAsValue(const net::URLRequest* request, - net::NetLogCaptureMode capture_mode) { + NetLogCaptureMode capture_mode) { return request->GetStateAsValue(); } @@ -143,7 +143,7 @@ // Add a dictionary with information on the relationship between event type // enums and their symbolic names. - constants_dict->Set("logEventTypes", net::NetLog::GetEventTypesAsValue()); + constants_dict->Set("logEventTypes", NetLog::GetEventTypesAsValue()); // Add a dictionary with information about the relationship between CertStatus // flags and their symbolic names. @@ -203,10 +203,9 @@ { base::DictionaryValue* dict = new base::DictionaryValue(); - for (net::QuicErrorCode error = net::QUIC_NO_ERROR; - error < net::QUIC_LAST_ERROR; - error = static_cast<net::QuicErrorCode>(error + 1)) { - dict->SetInteger(net::QuicUtils::ErrorToString(error), + for (QuicErrorCode error = QUIC_NO_ERROR; error < QUIC_LAST_ERROR; + error = static_cast<QuicErrorCode>(error + 1)) { + dict->SetInteger(QuicUtils::ErrorToString(error), static_cast<int>(error)); } @@ -218,10 +217,10 @@ { base::DictionaryValue* dict = new base::DictionaryValue(); - for (net::QuicRstStreamErrorCode error = net::QUIC_STREAM_NO_ERROR; - error < net::QUIC_STREAM_LAST_ERROR; - error = static_cast<net::QuicRstStreamErrorCode>(error + 1)) { - dict->SetInteger(net::QuicUtils::StreamErrorToString(error), + for (QuicRstStreamErrorCode error = QUIC_STREAM_NO_ERROR; + error < QUIC_STREAM_LAST_ERROR; + error = static_cast<QuicRstStreamErrorCode>(error + 1)) { + dict->SetInteger(QuicUtils::StreamErrorToString(error), static_cast<int>(error)); } @@ -244,16 +243,16 @@ { base::DictionaryValue* dict = new base::DictionaryValue(); - dict->SetInteger("PHASE_BEGIN", net::NetLog::PHASE_BEGIN); - dict->SetInteger("PHASE_END", net::NetLog::PHASE_END); - dict->SetInteger("PHASE_NONE", net::NetLog::PHASE_NONE); + dict->SetInteger("PHASE_BEGIN", NetLog::PHASE_BEGIN); + dict->SetInteger("PHASE_END", NetLog::PHASE_END); + dict->SetInteger("PHASE_NONE", NetLog::PHASE_NONE); constants_dict->Set("logEventPhase", dict); } // Information about the relationship between source type enums and // their symbolic names. - constants_dict->Set("logSourceType", net::NetLog::GetSourceTypesAsValue()); + constants_dict->Set("logSourceType", NetLog::GetSourceTypesAsValue()); // TODO(eroman): This is here for compatibility in loading new log files with // older builds of Chrome. Safe to remove this once M45 is on the stable @@ -265,10 +264,9 @@ { base::DictionaryValue* dict = new base::DictionaryValue(); - dict->SetInteger("ADDRESS_FAMILY_UNSPECIFIED", - net::ADDRESS_FAMILY_UNSPECIFIED); - dict->SetInteger("ADDRESS_FAMILY_IPV4", net::ADDRESS_FAMILY_IPV4); - dict->SetInteger("ADDRESS_FAMILY_IPV6", net::ADDRESS_FAMILY_IPV6); + dict->SetInteger("ADDRESS_FAMILY_UNSPECIFIED", ADDRESS_FAMILY_UNSPECIFIED); + dict->SetInteger("ADDRESS_FAMILY_IPV4", ADDRESS_FAMILY_IPV4); + dict->SetInteger("ADDRESS_FAMILY_IPV6", ADDRESS_FAMILY_IPV6); constants_dict->Set("addressFamily", dict); } @@ -328,7 +326,7 @@ // TODO(mmenke): The code for most of these sources should probably be moved // into the sources themselves. if (info_sources & NET_INFO_PROXY_SETTINGS) { - net::ProxyService* proxy_service = context->proxy_service(); + ProxyService* proxy_service = context->proxy_service(); base::DictionaryValue* dict = new base::DictionaryValue(); if (proxy_service->fetched_config().is_valid()) @@ -340,20 +338,20 @@ } if (info_sources & NET_INFO_BAD_PROXIES) { - const net::ProxyRetryInfoMap& bad_proxies_map = + const ProxyRetryInfoMap& bad_proxies_map = context->proxy_service()->proxy_retry_info(); base::ListValue* list = new base::ListValue(); - for (net::ProxyRetryInfoMap::const_iterator it = bad_proxies_map.begin(); + for (ProxyRetryInfoMap::const_iterator it = bad_proxies_map.begin(); it != bad_proxies_map.end(); ++it) { const std::string& proxy_uri = it->first; - const net::ProxyRetryInfo& retry_info = it->second; + const ProxyRetryInfo& retry_info = it->second; base::DictionaryValue* dict = new base::DictionaryValue(); dict->SetString("proxy_uri", proxy_uri); dict->SetString("bad_until", - net::NetLog::TickCountToString(retry_info.bad_until)); + NetLog::TickCountToString(retry_info.bad_until)); list->Append(dict); } @@ -362,9 +360,9 @@ } if (info_sources & NET_INFO_HOST_RESOLVER) { - net::HostResolver* host_resolver = context->host_resolver(); + HostResolver* host_resolver = context->host_resolver(); DCHECK(host_resolver); - net::HostCache* cache = host_resolver->GetHostCache(); + HostCache* cache = host_resolver->GetHostCache(); if (cache) { base::DictionaryValue* dict = new base::DictionaryValue(); base::Value* dns_config = host_resolver->GetDnsConfigAsValue(); @@ -382,10 +380,10 @@ base::ListValue* entry_list = new base::ListValue(); - net::HostCache::EntryMap::Iterator it(cache->entries()); + HostCache::EntryMap::Iterator it(cache->entries()); for (; it.HasNext(); it.Advance()) { - const net::HostCache::Key& key = it.key(); - const net::HostCache::Entry& entry = it.value(); + const HostCache::Key& key = it.key(); + const HostCache::Entry& entry = it.value(); base::DictionaryValue* entry_dict = new base::DictionaryValue(); @@ -393,9 +391,9 @@ entry_dict->SetInteger("address_family", static_cast<int>(key.address_family)); entry_dict->SetString("expiration", - net::NetLog::TickCountToString(it.expiration())); + NetLog::TickCountToString(it.expiration())); - if (entry.error != net::OK) { + if (entry.error != OK) { entry_dict->SetInteger("error", entry.error); } else { // Append all of the resolved addresses. @@ -415,7 +413,7 @@ } } - net::HttpNetworkSession* http_network_session = + HttpNetworkSession* http_network_session = context->http_transaction_factory()->GetSession(); if (info_sources & NET_INFO_SOCKET_POOL) { @@ -431,8 +429,7 @@ if (info_sources & NET_INFO_SPDY_STATUS) { base::DictionaryValue* status_dict = new base::DictionaryValue(); - status_dict->SetBoolean("spdy_enabled", - net::HttpStreamFactory::spdy_enabled()); + status_dict->SetBoolean("spdy_enabled", HttpStreamFactory::spdy_enabled()); status_dict->SetBoolean( "use_alternate_protocols", http_network_session->params().use_alternate_protocols); @@ -454,7 +451,7 @@ } if (info_sources & NET_INFO_SPDY_ALT_SVC_MAPPINGS) { - const net::HttpServerProperties& http_server_properties = + const HttpServerProperties& http_server_properties = *context->http_server_properties(); net_info_dict->Set( NetInfoSourceToString(NET_INFO_SPDY_ALT_SVC_MAPPINGS), @@ -524,12 +521,12 @@ // Create fake events. ScopedVector<NetLog::Entry> entries; for (const auto& request : requests) { - net::NetLog::ParametersCallback callback = + NetLog::ParametersCallback callback = base::Bind(&GetRequestStateAsValue, base::Unretained(request)); - net::NetLog::EntryData entry_data( - net::NetLog::TYPE_REQUEST_ALIVE, request->net_log().source(), - net::NetLog::PHASE_BEGIN, request->creation_time(), &callback); + NetLog::EntryData entry_data( + NetLog::TYPE_REQUEST_ALIVE, request->net_log().source(), + NetLog::PHASE_BEGIN, request->creation_time(), &callback); NetLog::Entry entry(&entry_data, request->net_log().GetCaptureMode()); observer->OnAddEntry(entry); }
diff --git a/net/log/net_log_util_unittest.cc b/net/log/net_log_util_unittest.cc index 2befc17a..27b2967 100644 --- a/net/log/net_log_util_unittest.cc +++ b/net/log/net_log_util_unittest.cc
@@ -31,7 +31,7 @@ // caches, and they have the same number of elements. TEST(NetLogUtil, GetNetInfo) { TestURLRequestContext context; - net::HttpCache* http_cache = context.http_transaction_factory()->GetCache(); + HttpCache* http_cache = context.http_transaction_factory()->GetCache(); // Get NetInfo when there's no cache backend (It's only created on first use). EXPECT_FALSE(http_cache->GetCurrentBackend());
diff --git a/net/log/test_net_log.cc b/net/log/test_net_log.cc index d98ffc3a..2c38b2f 100644 --- a/net/log/test_net_log.cc +++ b/net/log/test_net_log.cc
@@ -19,12 +19,13 @@ SetObserverCaptureMode(&capturing_net_log_observer_, capture_mode); } -void TestNetLog::GetEntries(TestNetLog::CapturedEntryList* entry_list) const { +void TestNetLog::GetEntries(CapturedNetLogEntry::List* entry_list) const { capturing_net_log_observer_.GetEntries(entry_list); } -void TestNetLog::GetEntriesForSource(NetLog::Source source, - CapturedEntryList* entry_list) const { +void TestNetLog::GetEntriesForSource( + NetLog::Source source, + CapturedNetLogEntry::List* entry_list) const { capturing_net_log_observer_.GetEntriesForSource(source, entry_list); } @@ -37,21 +38,19 @@ } BoundTestNetLog::BoundTestNetLog() - : net_log_( - BoundNetLog::Make(&capturing_net_log_, net::NetLog::SOURCE_NONE)) { + : net_log_(BoundNetLog::Make(&capturing_net_log_, NetLog::SOURCE_NONE)) { } BoundTestNetLog::~BoundTestNetLog() { } -void BoundTestNetLog::GetEntries( - TestNetLog::CapturedEntryList* entry_list) const { +void BoundTestNetLog::GetEntries(CapturedNetLogEntry::List* entry_list) const { capturing_net_log_.GetEntries(entry_list); } void BoundTestNetLog::GetEntriesForSource( NetLog::Source source, - TestNetLog::CapturedEntryList* entry_list) const { + CapturedNetLogEntry::List* entry_list) const { capturing_net_log_.GetEntriesForSource(source, entry_list); }
diff --git a/net/log/test_net_log.h b/net/log/test_net_log.h index 1526d827..3099dedf 100644 --- a/net/log/test_net_log.h +++ b/net/log/test_net_log.h
@@ -21,18 +21,15 @@ // net_test_support project. class TestNetLog : public NetLog { public: - // TODO(mmenke): Get rid of these. - typedef CapturedNetLogEntry CapturedEntry; - typedef CapturedNetLogEntry::List CapturedEntryList; - TestNetLog(); ~TestNetLog() override; void SetCaptureMode(NetLogCaptureMode capture_mode); // Below methods are forwarded to capturing_net_log_observer_. - void GetEntries(CapturedEntryList* entry_list) const; - void GetEntriesForSource(Source source, CapturedEntryList* entry_list) const; + void GetEntries(CapturedNetLogEntry::List* entry_list) const; + void GetEntriesForSource(Source source, + CapturedNetLogEntry::List* entry_list) const; size_t GetSize() const; void Clear(); @@ -56,11 +53,11 @@ BoundNetLog bound() const { return net_log_; } // Fills |entry_list| with all entries in the log. - void GetEntries(TestNetLog::CapturedEntryList* entry_list) const; + void GetEntries(CapturedNetLogEntry::List* entry_list) const; // Fills |entry_list| with all entries in the log from the specified Source. void GetEntriesForSource(NetLog::Source source, - TestNetLog::CapturedEntryList* entry_list) const; + CapturedNetLogEntry::List* entry_list) const; // Returns number of entries in the log. size_t GetSize() const;
diff --git a/net/log/trace_net_log_observer_unittest.cc b/net/log/trace_net_log_observer_unittest.cc index 2c2bb48..10d249f 100644 --- a/net/log/trace_net_log_observer_unittest.cc +++ b/net/log/trace_net_log_observer_unittest.cc
@@ -17,6 +17,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event_impl.h" #include "base/values.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/test_net_log.h" #include "testing/gtest/include/gtest/gtest.h" @@ -156,7 +157,7 @@ } TEST_F(TraceNetLogObserverTest, TraceEventCaptured) { - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log()->GetEntries(&entries); EXPECT_TRUE(entries.empty()); @@ -223,7 +224,7 @@ EndTraceAndFlush(); trace_net_log_observer()->StopWatchForTraceStart(); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log()->GetEntries(&entries); EXPECT_EQ(3u, entries.size()); EXPECT_EQ(2u, trace_events()->GetSize()); @@ -263,7 +264,7 @@ EndTraceAndFlush(); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log()->GetEntries(&entries); EXPECT_EQ(2u, entries.size()); EXPECT_EQ(1u, trace_events()->GetSize()); @@ -292,7 +293,7 @@ EndTraceAndFlush(); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log()->GetEntries(&entries); EXPECT_EQ(3u, entries.size()); EXPECT_EQ(0u, trace_events()->GetSize()); @@ -310,7 +311,7 @@ EndTraceAndFlush(); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log()->GetEntries(&entries); EXPECT_EQ(3u, entries.size()); EXPECT_EQ(0u, trace_events()->GetSize()); @@ -329,7 +330,7 @@ EndTraceAndFlush(); trace_net_log_observer()->StopWatchForTraceStart(); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log()->GetEntries(&entries); EXPECT_EQ(2u, entries.size()); EXPECT_EQ(2u, trace_events()->GetSize());
diff --git a/net/log/write_to_file_net_log_observer.cc b/net/log/write_to_file_net_log_observer.cc index 9df765eb..8ef5a71 100644 --- a/net/log/write_to_file_net_log_observer.cc +++ b/net/log/write_to_file_net_log_observer.cc
@@ -25,16 +25,16 @@ } void WriteToFileNetLogObserver::set_capture_mode( - net::NetLogCaptureMode capture_mode) { + NetLogCaptureMode capture_mode) { DCHECK(!net_log()); capture_mode_ = capture_mode; } void WriteToFileNetLogObserver::StartObserving( - net::NetLog* net_log, + NetLog* net_log, base::ScopedFILE file, base::Value* constants, - net::URLRequestContext* url_request_context) { + URLRequestContext* url_request_context) { DCHECK(file.get()); file_ = file.Pass(); added_events_ = false; @@ -67,7 +67,7 @@ } void WriteToFileNetLogObserver::StopObserving( - net::URLRequestContext* url_request_context) { + URLRequestContext* url_request_context) { net_log()->DeprecatedRemoveObserver(this); // End events array. @@ -88,7 +88,7 @@ file_.reset(); } -void WriteToFileNetLogObserver::OnAddEntry(const net::NetLog::Entry& entry) { +void WriteToFileNetLogObserver::OnAddEntry(const NetLog::Entry& entry) { // Add a comma and newline for every event but the first. Newlines are needed // so can load partial log files by just ignoring the last line. For this to // work, lines cannot be pretty printed.
diff --git a/net/log/write_to_file_net_log_observer.h b/net/log/write_to_file_net_log_observer.h index 8ef0115..9789272 100644 --- a/net/log/write_to_file_net_log_observer.h +++ b/net/log/write_to_file_net_log_observer.h
@@ -49,7 +49,7 @@ void StartObserving(NetLog* net_log, base::ScopedFILE file, base::Value* constants, - net::URLRequestContext* url_request_context); + URLRequestContext* url_request_context); // Stops observing net_log(). Must already be watching. Must be called // before destruction of the WriteToFileNetLogObserver and the NetLog. @@ -57,7 +57,7 @@ // |url_request_context| is an optional argument used to added additional // network stack state to the log. If the context is non-NULL, this must be // called on the context's thread. - void StopObserving(net::URLRequestContext* url_request_context); + void StopObserving(URLRequestContext* url_request_context); // net::NetLog::ThreadSafeObserver implementation: void OnAddEntry(const NetLog::Entry& entry) override;
diff --git a/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h b/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h index c89192c..70bc8e2d 100644 --- a/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h +++ b/net/proxy/dhcp_proxy_script_adapter_fetcher_win.h
@@ -47,7 +47,7 @@ // You may only call Fetch() once on a given instance of // DhcpProxyScriptAdapterFetcher. virtual void Fetch(const std::string& adapter_name, - const net::CompletionCallback& callback); + const CompletionCallback& callback); // Cancels the fetch on this adapter. virtual void Cancel(); @@ -170,7 +170,7 @@ // Callback to let our client know we're done. Invalid in states // START, FINISH and CANCEL. - net::CompletionCallback callback_; + CompletionCallback callback_; // Fetcher to retrieve PAC files once URL is known. scoped_ptr<ProxyScriptFetcher> script_fetcher_;
diff --git a/net/proxy/dhcp_proxy_script_fetcher_win.h b/net/proxy/dhcp_proxy_script_fetcher_win.h index aa60a13a..d490805 100644 --- a/net/proxy/dhcp_proxy_script_fetcher_win.h +++ b/net/proxy/dhcp_proxy_script_fetcher_win.h
@@ -39,7 +39,7 @@ // DhcpProxyScriptFetcher implementation. int Fetch(base::string16* utf16_text, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; void Cancel() override; const GURL& GetPacURL() const override; std::string GetFetcherName() const override; @@ -148,7 +148,7 @@ int num_pending_fetchers_; // Lets our client know we're done. Not valid in states START or DONE. - net::CompletionCallback callback_; + CompletionCallback callback_; // Pointer to string we will write results to. Not valid in states // START and DONE.
diff --git a/net/proxy/mock_proxy_resolver.h b/net/proxy/mock_proxy_resolver.h index 024a083..ee24da4 100644 --- a/net/proxy/mock_proxy_resolver.h +++ b/net/proxy/mock_proxy_resolver.h
@@ -28,11 +28,11 @@ Request(MockAsyncProxyResolverBase* resolver, const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback); + const CompletionCallback& callback); const GURL& url() const { return url_; } ProxyInfo* results() const { return results_; } - const net::CompletionCallback& callback() const { return callback_; } + const CompletionCallback& callback() const { return callback_; } void CompleteNow(int rv); @@ -44,7 +44,7 @@ MockAsyncProxyResolverBase* resolver_; const GURL url_; ProxyInfo* results_; - net::CompletionCallback callback_; + CompletionCallback callback_; base::MessageLoop* origin_loop_; }; @@ -53,7 +53,7 @@ SetPacScriptRequest( MockAsyncProxyResolverBase* resolver, const scoped_refptr<ProxyResolverScriptData>& script_data, - const net::CompletionCallback& callback); + const CompletionCallback& callback); ~SetPacScriptRequest(); const ProxyResolverScriptData* script_data() const { @@ -65,7 +65,7 @@ private: MockAsyncProxyResolverBase* resolver_; const scoped_refptr<ProxyResolverScriptData> script_data_; - net::CompletionCallback callback_; + CompletionCallback callback_; base::MessageLoop* origin_loop_; }; @@ -76,13 +76,13 @@ // ProxyResolver implementation. int GetProxyForURL(const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback, + const CompletionCallback& callback, RequestHandle* request_handle, const BoundNetLog& /*net_log*/) override; void CancelRequest(RequestHandle request_handle) override; LoadState GetLoadState(RequestHandle request_handle) const override; int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; void CancelSetPacScript() override; const RequestsList& pending_requests() const {
diff --git a/net/proxy/mojo_proxy_resolver_impl_unittest.cc b/net/proxy/mojo_proxy_resolver_impl_unittest.cc index 8f2f4ab2..53ad02c5 100644 --- a/net/proxy/mojo_proxy_resolver_impl_unittest.cc +++ b/net/proxy/mojo_proxy_resolver_impl_unittest.cc
@@ -120,12 +120,12 @@ // MockAsyncProxyResolverExpectsBytes overrides. int GetProxyForURL(const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback, + const CompletionCallback& callback, RequestHandle* request_handle, const BoundNetLog& net_log) override; void CancelRequest(RequestHandle request_handle) override; int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; // Wait until the mock resolver has received a CancelRequest call. void WaitForCancel(); @@ -149,7 +149,7 @@ int CallbackMockProxyResolver::GetProxyForURL( const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback, + const CompletionCallback& callback, RequestHandle* request_handle, const BoundNetLog& net_log) { if (sync_result_) { @@ -171,7 +171,7 @@ int CallbackMockProxyResolver::SetPacScript( const scoped_refptr<ProxyResolverScriptData>& script_data, - const net::CompletionCallback& callback) { + const CompletionCallback& callback) { if (set_pac_script_sync_) { set_pac_script_sync_ = false; return OK; @@ -244,9 +244,9 @@ request->CompleteNow(OK); client.WaitForResult(); - EXPECT_EQ(net::OK, client.error()); - std::vector<net::ProxyServer> servers = - client.results().To<std::vector<net::ProxyServer>>(); + EXPECT_EQ(OK, client.error()); + std::vector<ProxyServer> servers = + client.results().To<std::vector<ProxyServer>>(); ASSERT_EQ(6u, servers.size()); EXPECT_EQ(ProxyServer::SCHEME_HTTP, servers[0].scheme()); EXPECT_EQ("proxy.example.com", servers[0].host_port_pair().host()); @@ -282,11 +282,11 @@ ASSERT_EQ(0u, mock_proxy_resolver_->pending_requests().size()); client.WaitForResult(); - EXPECT_EQ(net::OK, client.error()); - std::vector<net::ProxyServer> proxy_servers = - client.results().To<std::vector<net::ProxyServer>>(); + EXPECT_EQ(OK, client.error()); + std::vector<ProxyServer> proxy_servers = + client.results().To<std::vector<ProxyServer>>(); ASSERT_EQ(1u, proxy_servers.size()); - net::ProxyServer& server = proxy_servers[0]; + ProxyServer& server = proxy_servers[0]; EXPECT_TRUE(server.is_direct()); } @@ -303,8 +303,8 @@ client.WaitForResult(); EXPECT_EQ(ERR_FAILED, client.error()); - std::vector<net::ProxyServer> proxy_servers = - client.results().To<std::vector<net::ProxyServer>>(); + std::vector<ProxyServer> proxy_servers = + client.results().To<std::vector<ProxyServer>>(); EXPECT_TRUE(proxy_servers.empty()); } @@ -330,20 +330,20 @@ client1.WaitForResult(); client2.WaitForResult(); - EXPECT_EQ(net::OK, client1.error()); - std::vector<net::ProxyServer> proxy_servers1 = - client1.results().To<std::vector<net::ProxyServer>>(); + EXPECT_EQ(OK, client1.error()); + std::vector<ProxyServer> proxy_servers1 = + client1.results().To<std::vector<ProxyServer>>(); ASSERT_EQ(1u, proxy_servers1.size()); - net::ProxyServer& server1 = proxy_servers1[0]; + ProxyServer& server1 = proxy_servers1[0]; EXPECT_EQ(ProxyServer::SCHEME_HTTPS, server1.scheme()); EXPECT_EQ("proxy.example.com", server1.host_port_pair().host()); EXPECT_EQ(12345, server1.host_port_pair().port()); - EXPECT_EQ(net::OK, client2.error()); - std::vector<net::ProxyServer> proxy_servers2 = - client2.results().To<std::vector<net::ProxyServer>>(); + EXPECT_EQ(OK, client2.error()); + std::vector<ProxyServer> proxy_servers2 = + client2.results().To<std::vector<ProxyServer>>(); ASSERT_EQ(1u, proxy_servers1.size()); - net::ProxyServer& server2 = proxy_servers2[0]; + ProxyServer& server2 = proxy_servers2[0]; EXPECT_EQ(ProxyServer::SCHEME_SOCKS5, server2.scheme()); EXPECT_EQ("another-proxy.example.com", server2.host_port_pair().host()); EXPECT_EQ(6789, server2.host_port_pair().port());
diff --git a/net/proxy/multi_threaded_proxy_resolver_unittest.cc b/net/proxy/multi_threaded_proxy_resolver_unittest.cc index 618aa14..83e11ae4 100644 --- a/net/proxy/multi_threaded_proxy_resolver_unittest.cc +++ b/net/proxy/multi_threaded_proxy_resolver_unittest.cc
@@ -13,8 +13,10 @@ #include "base/threading/platform_thread.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/proxy/mock_proxy_resolver.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_factory.h" @@ -209,7 +211,7 @@ // on completion, this should have been copied into |log0|. // We also have 1 log entry that was emitted by the // MultiThreadedProxyResolver. - TestNetLog::CapturedEntryList entries0; + CapturedNetLogEntry::List entries0; log0.GetEntries(&entries0); ASSERT_EQ(2u, entries0.size()); @@ -307,7 +309,7 @@ EXPECT_EQ(0, callback0.WaitForResult()); EXPECT_EQ("PROXY request0:80", results0.ToPacString()); - TestNetLog::CapturedEntryList entries0; + CapturedNetLogEntry::List entries0; log0.GetEntries(&entries0); ASSERT_EQ(2u, entries0.size()); @@ -318,7 +320,7 @@ EXPECT_EQ(1, callback1.WaitForResult()); EXPECT_EQ("PROXY request1:80", results1.ToPacString()); - TestNetLog::CapturedEntryList entries1; + CapturedNetLogEntry::List entries1; log1.GetEntries(&entries1); ASSERT_EQ(4u, entries1.size()); @@ -333,7 +335,7 @@ EXPECT_EQ(2, callback2.WaitForResult()); EXPECT_EQ("PROXY request2:80", results2.ToPacString()); - TestNetLog::CapturedEntryList entries2; + CapturedNetLogEntry::List entries2; log2.GetEntries(&entries2); ASSERT_EQ(4u, entries2.size());
diff --git a/net/proxy/network_delegate_error_observer_unittest.cc b/net/proxy/network_delegate_error_observer_unittest.cc index 0a2e01a..7d9bc6c06 100644 --- a/net/proxy/network_delegate_error_observer_unittest.cc +++ b/net/proxy/network_delegate_error_observer_unittest.cc
@@ -16,7 +16,7 @@ namespace { -class TestNetworkDelegate : public net::NetworkDelegateImpl { +class TestNetworkDelegate : public NetworkDelegateImpl { public: TestNetworkDelegate() : got_pac_error_(false) {} ~TestNetworkDelegate() override {} @@ -24,7 +24,7 @@ bool got_pac_error() const { return got_pac_error_; } private: - // net::NetworkDelegate implementation. + // NetworkDelegate implementation. int OnBeforeURLRequest(URLRequest* request, const CompletionCallback& callback, GURL* new_url) override { @@ -43,7 +43,7 @@ const HttpResponseHeaders* original_response_headers, scoped_refptr<HttpResponseHeaders>* override_response_headers, GURL* allowed_unsafe_redirect_url) override { - return net::OK; + return OK; } void OnBeforeRedirect(URLRequest* request, const GURL& new_location) override {} @@ -70,7 +70,7 @@ CookieOptions* options) override { return true; } - bool OnCanAccessFile(const net::URLRequest& request, + bool OnCanAccessFile(const URLRequest& request, const base::FilePath& path) const override { return true; } @@ -81,8 +81,6 @@ bool got_pac_error_; }; -} // namespace - // Check that the OnPACScriptError method can be called from an arbitrary // thread. TEST(NetworkDelegateErrorObserverTest, CallOnThread) { @@ -119,4 +117,6 @@ // Shouldn't have crashed until here... } +} // namespace + } // namespace net
diff --git a/net/proxy/proxy_config_service_linux_unittest.cc b/net/proxy/proxy_config_service_linux_unittest.cc index 2c1995c..d48a762d 100644 --- a/net/proxy/proxy_config_service_linux_unittest.cc +++ b/net/proxy/proxy_config_service_linux_unittest.cc
@@ -250,16 +250,13 @@ std::vector<std::string> > string_lists_table; }; -} // namespace -} // namespace net - // This helper class runs ProxyConfigServiceLinux::GetLatestProxyConfig() on // the IO thread and synchronously waits for the result. // Some code duplicated from proxy_script_fetcher_unittest.cc. class SynchConfigGetter { public: // Takes ownership of |config_service|. - explicit SynchConfigGetter(net::ProxyConfigServiceLinux* config_service) + explicit SynchConfigGetter(ProxyConfigServiceLinux* config_service) : event_(false, false), io_thread_("IO_Thread"), config_service_(config_service) { @@ -295,8 +292,8 @@ io_thread_.message_loop_proxy()); } // Synchronously gets the proxy config. - net::ProxyConfigService::ConfigAvailability SyncGetLatestProxyConfig( - net::ProxyConfig* config) { + ProxyConfigService::ConfigAvailability SyncGetLatestProxyConfig( + ProxyConfig* config) { io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(&SynchConfigGetter::GetLatestConfigOnIOThread, base::Unretained(this))); @@ -333,18 +330,16 @@ base::WaitableEvent event_; base::Thread io_thread_; - net::ProxyConfigServiceLinux* config_service_; + ProxyConfigServiceLinux* config_service_; // The config obtained by |io_thread_| and read back by the main // thread. - net::ProxyConfig proxy_config_; + ProxyConfig proxy_config_; // Return value from GetLatestProxyConfig(). - net::ProxyConfigService::ConfigAvailability get_latest_config_result_; + ProxyConfigService::ConfigAvailability get_latest_config_result_; }; -namespace net { - // This test fixture is only really needed for the KDEConfigParser test case, // but all the test cases with the same prefix ("ProxyConfigServiceLinuxTest") // must use the same test fixture class (also "ProxyConfigServiceLinuxTest"). @@ -1612,4 +1607,6 @@ } } +} // namespace + } // namespace net
diff --git a/net/proxy/proxy_config_service_mac.cc b/net/proxy/proxy_config_service_mac.cc index 6d192538..1483dbc6 100644 --- a/net/proxy/proxy_config_service_mac.cc +++ b/net/proxy/proxy_config_service_mac.cc
@@ -225,8 +225,8 @@ observers_.RemoveObserver(observer); } -net::ProxyConfigService::ConfigAvailability - ProxyConfigServiceMac::GetLatestProxyConfig(ProxyConfig* config) { +ProxyConfigService::ConfigAvailability +ProxyConfigServiceMac::GetLatestProxyConfig(ProxyConfig* config) { DCHECK(io_thread_task_runner_->BelongsToCurrentThread()); // Lazy-initialize by fetching the proxy setting from this thread.
diff --git a/net/proxy/proxy_resolver.h b/net/proxy/proxy_resolver.h index 355c368..ced97b86 100644 --- a/net/proxy/proxy_resolver.h +++ b/net/proxy/proxy_resolver.h
@@ -46,7 +46,7 @@ // |*request| is written to, and can be passed to CancelRequest(). virtual int GetProxyForURL(const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback, + const CompletionCallback& callback, RequestHandle* request, const BoundNetLog& net_log) = 0; @@ -69,7 +69,7 @@ // the result through |callback|. virtual int SetPacScript( const scoped_refptr<ProxyResolverScriptData>& pac_script, - const net::CompletionCallback& callback) = 0; + const CompletionCallback& callback) = 0; private: const bool expects_pac_bytes_;
diff --git a/net/proxy/proxy_resolver_mac.cc b/net/proxy/proxy_resolver_mac.cc index 6d592bb..6d69080 100644 --- a/net/proxy/proxy_resolver_mac.cc +++ b/net/proxy/proxy_resolver_mac.cc
@@ -21,26 +21,28 @@ #include <CoreServices/CoreServices.h> #endif +namespace net { + namespace { // Utility function to map a CFProxyType to a ProxyServer::Scheme. // If the type is unknown, returns ProxyServer::SCHEME_INVALID. -net::ProxyServer::Scheme GetProxyServerScheme(CFStringRef proxy_type) { +ProxyServer::Scheme GetProxyServerScheme(CFStringRef proxy_type) { if (CFEqual(proxy_type, kCFProxyTypeNone)) - return net::ProxyServer::SCHEME_DIRECT; + return ProxyServer::SCHEME_DIRECT; if (CFEqual(proxy_type, kCFProxyTypeHTTP)) - return net::ProxyServer::SCHEME_HTTP; + return ProxyServer::SCHEME_HTTP; if (CFEqual(proxy_type, kCFProxyTypeHTTPS)) { // The "HTTPS" on the Mac side here means "proxy applies to https://" URLs; // the proxy itself is still expected to be an HTTP proxy. - return net::ProxyServer::SCHEME_HTTP; + return ProxyServer::SCHEME_HTTP; } if (CFEqual(proxy_type, kCFProxyTypeSOCKS)) { // We can't tell whether this was v4 or v5. We will assume it is // v5 since that is the only version OS X supports. - return net::ProxyServer::SCHEME_SOCKS5; + return ProxyServer::SCHEME_SOCKS5; } - return net::ProxyServer::SCHEME_INVALID; + return ProxyServer::SCHEME_INVALID; } // Callback for CFNetworkExecuteProxyAutoConfigurationURL. |client| is a pointer @@ -62,8 +64,6 @@ } // namespace -namespace net { - ProxyResolverMac::ProxyResolverMac() : ProxyResolver(false /*expects_pac_bytes*/) { }
diff --git a/net/proxy/proxy_resolver_mac.h b/net/proxy/proxy_resolver_mac.h index ef10b5cb..3db83f6 100644 --- a/net/proxy/proxy_resolver_mac.h +++ b/net/proxy/proxy_resolver_mac.h
@@ -23,7 +23,7 @@ // ProxyResolver methods: int GetProxyForURL(const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback, + const CompletionCallback& callback, RequestHandle* request, const BoundNetLog& net_log) override; @@ -34,7 +34,7 @@ void CancelSetPacScript() override; int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data, - const net::CompletionCallback& /*callback*/) override; + const CompletionCallback& /*callback*/) override; private: scoped_refptr<ProxyResolverScriptData> script_data_;
diff --git a/net/proxy/proxy_resolver_mojo.cc b/net/proxy/proxy_resolver_mojo.cc index 3801d41a..bc15704d 100644 --- a/net/proxy/proxy_resolver_mojo.cc +++ b/net/proxy/proxy_resolver_mojo.cc
@@ -25,7 +25,7 @@ Job(ProxyResolverMojo* resolver, const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback); + const CompletionCallback& callback); ~Job() override; // Cancels the job and prevents the callback from being run. @@ -47,7 +47,7 @@ ProxyResolverMojo* resolver_; const GURL url_; ProxyInfo* results_; - net::CompletionCallback callback_; + CompletionCallback callback_; LoadState load_state_ = LOAD_STATE_RESOLVING_PROXY_FOR_URL; base::ThreadChecker thread_checker_; @@ -57,7 +57,7 @@ ProxyResolverMojo::Job::Job(ProxyResolverMojo* resolver, const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback) + const CompletionCallback& callback) : resolver_(resolver), url_(url), results_(results), @@ -100,9 +100,10 @@ DVLOG(1) << "Servers: " << results_->ToPacString(); } - callback_.Run(error); + CompletionCallback callback = callback_; callback_.Reset(); resolver_->RemoveJob(this); + callback.Run(error); } void ProxyResolverMojo::Job::LoadStateChanged(int32_t load_state) { @@ -131,7 +132,7 @@ int ProxyResolverMojo::SetPacScript( const scoped_refptr<ProxyResolverScriptData>& pac_script, - const net::CompletionCallback& callback) { + const CompletionCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(set_pac_script_callback_.IsCancelled()); DCHECK(!callback.is_null()); @@ -157,14 +158,17 @@ void ProxyResolverMojo::OnSetPacScriptDone( const scoped_refptr<ProxyResolverScriptData>& pac_script, - const net::CompletionCallback& callback, + const CompletionCallback& callback, int32_t result) { DCHECK(thread_checker_.CalledOnValidThread()); DCHECK(!set_pac_script_callback_.IsCancelled()); DVLOG(1) << "ProxyResolverMojo::OnSetPacScriptDone: " << result; - callback.Run(result); + // |callback| is owned by |set_pac_script_callback_|, so make a copy before + // cancelling. + auto callback_copy = callback; set_pac_script_callback_.Cancel(); + callback_copy.Run(result); } void ProxyResolverMojo::SetUpServices() { @@ -182,26 +186,6 @@ mojo_proxy_resolver_ptr_.set_error_handler(this); } -void ProxyResolverMojo::AbortPendingRequests() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (!set_pac_script_callback_.IsCancelled()) { - set_pac_script_callback_.callback().Run(ERR_PAC_SCRIPT_TERMINATED); - set_pac_script_callback_.Cancel(); - } - - // Need to use this loop because deleting a Job will cause its callback to be - // run with a failure error code, which may cause other Jobs to be deleted. - while (!pending_jobs_.empty()) { - auto it = pending_jobs_.begin(); - Job* job = *it; - pending_jobs_.erase(it); - - // Deleting the job will cause its completion callback to be run with an - // ERR_PAC_SCRIPT_TERMINATED error. - delete job; - } -} - void ProxyResolverMojo::OnConnectionError() { DCHECK(thread_checker_.CalledOnValidThread()); DVLOG(1) << "ProxyResolverMojo::OnConnectionError"; @@ -210,10 +194,11 @@ // will happen on the next |SetPacScript()| request. mojo_proxy_resolver_ptr_.reset(); - // Aborting requests will invoke their callbacks, which may call - // |SetPacScript()| and re-create the connection. So disconnect from the Mojo - // service (above) before aborting the pending requests. - AbortPendingRequests(); + // This callback may call |SetPacScript()| and re-create the connection. So + // disconnect from the Mojo service (above) before aborting the pending + // request. + if (!set_pac_script_callback_.IsCancelled()) + set_pac_script_callback_.callback().Run(ERR_PAC_SCRIPT_TERMINATED); } void ProxyResolverMojo::RemoveJob(Job* job) { @@ -225,7 +210,7 @@ int ProxyResolverMojo::GetProxyForURL(const GURL& url, ProxyInfo* results, - const net::CompletionCallback& callback, + const CompletionCallback& callback, RequestHandle* request, const BoundNetLog& net_log) { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/net/proxy/proxy_resolver_mojo.h b/net/proxy/proxy_resolver_mojo.h index 9d97095..10a512e 100644 --- a/net/proxy/proxy_resolver_mojo.h +++ b/net/proxy/proxy_resolver_mojo.h
@@ -71,8 +71,6 @@ void SetUpServices(); - void AbortPendingRequests(); - void RemoveJob(Job* job); // Connection to the Mojo proxy resolver.
diff --git a/net/proxy/proxy_resolver_mojo_unittest.cc b/net/proxy/proxy_resolver_mojo_unittest.cc index 8702236..27ae43c7 100644 --- a/net/proxy/proxy_resolver_mojo_unittest.cc +++ b/net/proxy/proxy_resolver_mojo_unittest.cc
@@ -401,6 +401,12 @@ proxy_resolver_mojo_->SetPacScript(pac_script, pac_callback)); } + void DeleteProxyResolverCallback(const CompletionCallback& callback, + int result) { + proxy_resolver_mojo_.reset(); + callback.Run(result); + } + MockHostResolver mock_host_resolver_; TestMojoProxyResolverFactory mojo_proxy_resolver_factory_; scoped_ptr<ProxyResolverMojo> proxy_resolver_mojo_; @@ -527,6 +533,34 @@ EXPECT_EQ(ERR_UNEXPECTED, callback2.GetResult(ERR_IO_PENDING)); } +TEST_F(ProxyResolverMojoTest, SetPacScript_DeleteInCallback) { + mojo_proxy_resolver_factory_.AddFuturePacScriptAction( + 0, SetPacScriptAction::ReturnResult(OK)); + scoped_refptr<ProxyResolverScriptData> pac_script( + ProxyResolverScriptData::FromUTF8(kScriptData)); + TestCompletionCallback callback; + EXPECT_EQ(OK, + callback.GetResult(proxy_resolver_mojo_->SetPacScript( + pac_script, + base::Bind(&ProxyResolverMojoTest::DeleteProxyResolverCallback, + base::Unretained(this), callback.callback())))); + EXPECT_EQ(1, mojo_proxy_resolver_factory_.num_create_calls()); +} + +TEST_F(ProxyResolverMojoTest, SetPacScript_DeleteInCallbackFromDisconnect) { + mojo_proxy_resolver_factory_.AddFuturePacScriptAction( + 0, SetPacScriptAction::Disconnect()); + scoped_refptr<ProxyResolverScriptData> pac_script( + ProxyResolverScriptData::FromUTF8(kScriptData)); + TestCompletionCallback callback; + EXPECT_EQ(ERR_PAC_SCRIPT_TERMINATED, + callback.GetResult(proxy_resolver_mojo_->SetPacScript( + pac_script, + base::Bind(&ProxyResolverMojoTest::DeleteProxyResolverCallback, + base::Unretained(this), callback.callback())))); + EXPECT_EQ(1, mojo_proxy_resolver_factory_.num_create_calls()); +} + TEST_F(ProxyResolverMojoTest, GetProxyForURL) { mojo_proxy_resolver_factory_.AddFutureGetProxyAction( 0, GetProxyForUrlAction::ReturnServers( @@ -732,4 +766,37 @@ EXPECT_EQ(2, mojo_proxy_resolver_factory_.num_create_calls()); } +TEST_F(ProxyResolverMojoTest, GetProxyForURL_DeleteInCallback) { + mojo_proxy_resolver_factory_.AddFutureGetProxyAction( + 0, GetProxyForUrlAction::ReturnServers( + GURL(kExampleUrl), ProxyServersFromPacString("DIRECT"))); + SetPacScript(0); + ProxyInfo results; + TestCompletionCallback callback; + ProxyResolver::RequestHandle handle; + BoundNetLog net_log; + EXPECT_EQ(OK, + callback.GetResult(proxy_resolver_mojo_->GetProxyForURL( + GURL(kExampleUrl), &results, + base::Bind(&ProxyResolverMojoTest::DeleteProxyResolverCallback, + base::Unretained(this), callback.callback()), + &handle, net_log))); +} + +TEST_F(ProxyResolverMojoTest, GetProxyForURL_DeleteInCallbackFromDisconnect) { + mojo_proxy_resolver_factory_.AddFutureGetProxyAction( + 0, GetProxyForUrlAction::Disconnect(GURL(kExampleUrl))); + SetPacScript(0); + ProxyInfo results; + TestCompletionCallback callback; + ProxyResolver::RequestHandle handle; + BoundNetLog net_log; + EXPECT_EQ(ERR_PAC_SCRIPT_TERMINATED, + callback.GetResult(proxy_resolver_mojo_->GetProxyForURL( + GURL(kExampleUrl), &results, + base::Bind(&ProxyResolverMojoTest::DeleteProxyResolverCallback, + base::Unretained(this), callback.callback()), + &handle, net_log))); +} + } // namespace net
diff --git a/net/proxy/proxy_resolver_perftest.cc b/net/proxy/proxy_resolver_perftest.cc index c4fbd73bd..480908e3 100644 --- a/net/proxy/proxy_resolver_perftest.cc +++ b/net/proxy/proxy_resolver_perftest.cc
@@ -21,6 +21,10 @@ #include "net/proxy/proxy_resolver_mac.h" #endif +namespace net { + +namespace { + // This class holds the URL to use for resolving, and the expected result. // We track the expected result in order to make sure the performance // test is actually resolving URLs properly, otherwise the perf numbers @@ -81,16 +85,13 @@ class PacPerfSuiteRunner { public: // |resolver_name| is the label used when logging the results. - PacPerfSuiteRunner(net::ProxyResolver* resolver, - const std::string& resolver_name) + PacPerfSuiteRunner(ProxyResolver* resolver, const std::string& resolver_name) : resolver_(resolver), resolver_name_(resolver_name), - test_server_( - net::SpawnedTestServer::TYPE_HTTP, - net::SpawnedTestServer::kLocalhost, - base::FilePath( - FILE_PATH_LITERAL("net/data/proxy_resolver_perftest"))) { - } + test_server_(SpawnedTestServer::TYPE_HTTP, + SpawnedTestServer::kLocalhost, + base::FilePath(FILE_PATH_LITERAL( + "net/data/proxy_resolver_perftest"))) {} void RunAllTests() { ASSERT_TRUE(test_server_.Start()); @@ -110,9 +111,8 @@ GURL pac_url = test_server_.GetURL(std::string("files/") + script_name); int rv = resolver_->SetPacScript( - net::ProxyResolverScriptData::FromURL(pac_url), - net::CompletionCallback()); - EXPECT_EQ(net::OK, rv); + ProxyResolverScriptData::FromURL(pac_url), CompletionCallback()); + EXPECT_EQ(OK, rv); } else { LoadPacScriptIntoResolver(script_name); } @@ -121,11 +121,11 @@ // resolvers, the first resolve will be slow since it has to download // the PAC script. { - net::ProxyInfo proxy_info; - int result = resolver_->GetProxyForURL( - GURL("http://www.warmup.com"), &proxy_info, net::CompletionCallback(), - NULL, net::BoundNetLog()); - ASSERT_EQ(net::OK, result); + ProxyInfo proxy_info; + int result = + resolver_->GetProxyForURL(GURL("http://www.warmup.com"), &proxy_info, + CompletionCallback(), NULL, BoundNetLog()); + ASSERT_EQ(OK, result); } // Start the perf timer. @@ -137,14 +137,14 @@ const PacQuery& query = queries[i % queries_len]; // Resolve. - net::ProxyInfo proxy_info; - int result = resolver_->GetProxyForURL( - GURL(query.query_url), &proxy_info, net::CompletionCallback(), NULL, - net::BoundNetLog()); + ProxyInfo proxy_info; + int result = + resolver_->GetProxyForURL(GURL(query.query_url), &proxy_info, + CompletionCallback(), NULL, BoundNetLog()); // Check that the result was correct. Note that ToPacString() and // ASSERT_EQ() are fast, so they won't skew the results. - ASSERT_EQ(net::OK, result); + ASSERT_EQ(OK, result); ASSERT_EQ(query.expected_result, proxy_info.ToPacString()); } @@ -171,31 +171,30 @@ // Load the PAC script into the ProxyResolver. int rv = resolver_->SetPacScript( - net::ProxyResolverScriptData::FromUTF8(file_contents), - net::CompletionCallback()); - EXPECT_EQ(net::OK, rv); + ProxyResolverScriptData::FromUTF8(file_contents), CompletionCallback()); + EXPECT_EQ(OK, rv); } - net::ProxyResolver* resolver_; + ProxyResolver* resolver_; std::string resolver_name_; - net::SpawnedTestServer test_server_; + SpawnedTestServer test_server_; }; #if defined(OS_WIN) TEST(ProxyResolverPerfTest, ProxyResolverWinHttp) { - net::ProxyResolverWinHttp resolver; + ProxyResolverWinHttp resolver; PacPerfSuiteRunner runner(&resolver, "ProxyResolverWinHttp"); runner.RunAllTests(); } #elif defined(OS_MACOSX) TEST(ProxyResolverPerfTest, ProxyResolverMac) { - net::ProxyResolverMac resolver; + ProxyResolverMac resolver; PacPerfSuiteRunner runner(&resolver, "ProxyResolverMac"); runner.RunAllTests(); } #endif -class MockJSBindings : public net::ProxyResolverV8::JSBindings { +class MockJSBindings : public ProxyResolverV8::JSBindings { public: MockJSBindings() {} @@ -216,8 +215,12 @@ TEST(ProxyResolverPerfTest, ProxyResolverV8) { MockJSBindings js_bindings; - net::ProxyResolverV8 resolver; + ProxyResolverV8 resolver; resolver.set_js_bindings(&js_bindings); PacPerfSuiteRunner runner(&resolver, "ProxyResolverV8"); runner.RunAllTests(); } + +} // namespace + +} // namespace net
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc index c41b190..e004f69 100644 --- a/net/proxy/proxy_resolver_v8.cc +++ b/net/proxy/proxy_resolver_v8.cc
@@ -376,7 +376,7 @@ has_initialized_v8_ = true; } - holder_.reset(new gin::IsolateHolder); + holder_.reset(new gin::IsolateHolder(gin::IsolateHolder::kUseLocker)); } return holder_->isolate();
diff --git a/net/proxy/proxy_resolver_v8.h b/net/proxy/proxy_resolver_v8.h index 446800c..229d4466 100644 --- a/net/proxy/proxy_resolver_v8.h +++ b/net/proxy/proxy_resolver_v8.h
@@ -58,14 +58,14 @@ // ProxyResolver implementation: int GetProxyForURL(const GURL& url, ProxyInfo* results, - const net::CompletionCallback& /*callback*/, + const CompletionCallback& /*callback*/, RequestHandle* /*request*/, const BoundNetLog& net_log) override; void CancelRequest(RequestHandle request) override; LoadState GetLoadState(RequestHandle request) const override; void CancelSetPacScript() override; int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data, - const net::CompletionCallback& /*callback*/) override; + const CompletionCallback& /*callback*/) override; // Get total/ued heap memory usage of all v8 instances used by the proxy // resolver.
diff --git a/net/proxy/proxy_resolver_v8_tracing.cc b/net/proxy/proxy_resolver_v8_tracing.cc index 3970589..ce5cb5f 100644 --- a/net/proxy/proxy_resolver_v8_tracing.cc +++ b/net/proxy/proxy_resolver_v8_tracing.cc
@@ -174,8 +174,10 @@ bool GetDnsFromLocalCache(const std::string& host, ResolveDnsOperation op, std::string* output, bool* return_value); - void SaveDnsToLocalCache(const std::string& host, ResolveDnsOperation op, - int net_error, const net::AddressList& addresses); + void SaveDnsToLocalCache(const std::string& host, + ResolveDnsOperation op, + int net_error, + const AddressList& addresses); // Builds a RequestInfo to service the specified PAC DNS operation. static HostResolver::RequestInfo MakeDnsRequestInfo(const std::string& host, @@ -782,7 +784,7 @@ const std::string& host, ResolveDnsOperation op, int net_error, - const net::AddressList& addresses) { + const AddressList& addresses) { CheckIsOnOriginThread(); // Serialize the result into a string to save to the cache.
diff --git a/net/proxy/proxy_resolver_v8_tracing_unittest.cc b/net/proxy/proxy_resolver_v8_tracing_unittest.cc index 13dfe62..7294937 100644 --- a/net/proxy/proxy_resolver_v8_tracing_unittest.cc +++ b/net/proxy/proxy_resolver_v8_tracing_unittest.cc
@@ -18,8 +18,10 @@ #include "net/base/test_completion_callback.h" #include "net/dns/host_cache.h" #include "net/dns/mock_host_resolver.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_error_observer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -152,12 +154,12 @@ // Check the NetLogs -- there was 1 alert and 1 javascript error, and they // were output to both the global log, and per-request log. - TestNetLog::CapturedEntryList entries_list[2]; + CapturedNetLogEntry::List entries_list[2]; log.GetEntries(&entries_list[0]); request_log.GetEntries(&entries_list[1]); for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { - const TestNetLog::CapturedEntryList& entries = entries_list[list_i]; + const CapturedNetLogEntry::List& entries = entries_list[list_i]; EXPECT_EQ(2u, entries.size()); EXPECT_TRUE( LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, @@ -206,12 +208,12 @@ // Check the NetLogs -- the script generated 50 alerts, which were mirrored // to both the global and per-request logs. - TestNetLog::CapturedEntryList entries_list[2]; + CapturedNetLogEntry::List entries_list[2]; log.GetEntries(&entries_list[0]); request_log.GetEntries(&entries_list[1]); for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { - const TestNetLog::CapturedEntryList& entries = entries_list[list_i]; + const CapturedNetLogEntry::List& entries = entries_list[list_i]; EXPECT_EQ(50u, entries.size()); for (size_t i = 0; i < entries.size(); ++i) { ASSERT_TRUE( @@ -254,12 +256,12 @@ // Check the NetLogs -- the script generated 50 alerts, which were mirrored // to both the global and per-request logs. - TestNetLog::CapturedEntryList entries_list[2]; + CapturedNetLogEntry::List entries_list[2]; log.GetEntries(&entries_list[0]); request_log.GetEntries(&entries_list[1]); for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { - const TestNetLog::CapturedEntryList& entries = entries_list[list_i]; + const CapturedNetLogEntry::List& entries = entries_list[list_i]; EXPECT_EQ(1000u, entries.size()); for (size_t i = 0; i < entries.size(); ++i) { ASSERT_TRUE( @@ -332,12 +334,12 @@ // Check the NetLogs -- the script generated 1 alert, mirrored to both // the per-request and global logs. - TestNetLog::CapturedEntryList entries_list[2]; + CapturedNetLogEntry::List entries_list[2]; log.GetEntries(&entries_list[0]); request_log.GetEntries(&entries_list[1]); for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { - const TestNetLog::CapturedEntryList& entries = entries_list[list_i]; + const CapturedNetLogEntry::List& entries = entries_list[list_i]; EXPECT_EQ(1u, entries.size()); EXPECT_TRUE( LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, @@ -441,12 +443,12 @@ // Check the NetLogs -- the script generated 1 alert, mirrored to both // the per-request and global logs. - TestNetLog::CapturedEntryList entries_list[2]; + CapturedNetLogEntry::List entries_list[2]; log.GetEntries(&entries_list[0]); request_log.GetEntries(&entries_list[1]); for (size_t list_i = 0; list_i < arraysize(entries_list); list_i++) { - const TestNetLog::CapturedEntryList& entries = entries_list[list_i]; + const CapturedNetLogEntry::List& entries = entries_list[list_i]; EXPECT_EQ(1u, entries.size()); EXPECT_TRUE( LogContainsEvent(entries, 0, NetLog::TYPE_PAC_JAVASCRIPT_ALERT, @@ -614,7 +616,7 @@ // Check the NetLogs -- the script generated 2 alerts during initialization. EXPECT_EQ(0u, request_log.GetSize()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); ASSERT_EQ(2u, entries.size());
diff --git a/net/proxy/proxy_resolver_v8_unittest.cc b/net/proxy/proxy_resolver_v8_unittest.cc index 1f33e18..14272255 100644 --- a/net/proxy/proxy_resolver_v8_unittest.cc +++ b/net/proxy/proxy_resolver_v8_unittest.cc
@@ -9,7 +9,9 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "net/base/net_errors.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_v8.h" #include "testing/gtest/include/gtest/gtest.h" @@ -155,7 +157,7 @@ EXPECT_EQ(0U, resolver.mock_js_bindings()->alerts.size()); EXPECT_EQ(0U, resolver.mock_js_bindings()->errors.size()); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); // No bindings were called, so no log entries. EXPECT_EQ(0u, entries.size());
diff --git a/net/proxy/proxy_resolver_winhttp.h b/net/proxy/proxy_resolver_winhttp.h index c3f7ede..3c2004a 100644 --- a/net/proxy/proxy_resolver_winhttp.h +++ b/net/proxy/proxy_resolver_winhttp.h
@@ -23,7 +23,7 @@ // ProxyResolver implementation: int GetProxyForURL(const GURL& url, ProxyInfo* results, - const net::CompletionCallback& /*callback*/, + const CompletionCallback& /*callback*/, RequestHandle* /*request*/, const BoundNetLog& /*net_log*/) override; void CancelRequest(RequestHandle request) override; @@ -33,7 +33,7 @@ void CancelSetPacScript() override; int SetPacScript(const scoped_refptr<ProxyResolverScriptData>& script_data, - const net::CompletionCallback& /*callback*/) override; + const CompletionCallback& /*callback*/) override; private: bool OpenWinHttpSession();
diff --git a/net/proxy/proxy_script_decider.h b/net/proxy/proxy_script_decider.h index aa37c88..9b1d4a8 100644 --- a/net/proxy/proxy_script_decider.h +++ b/net/proxy/proxy_script_decider.h
@@ -72,7 +72,7 @@ int Start(const ProxyConfig& config, const base::TimeDelta wait_delay, bool fetch_pac_bytes, - const net::CompletionCallback& callback); + const CompletionCallback& callback); const ProxyConfig& effective_config() const; @@ -163,7 +163,7 @@ ProxyScriptFetcher* proxy_script_fetcher_; DhcpProxyScriptFetcher* dhcp_proxy_script_fetcher_; - net::CompletionCallback callback_; + CompletionCallback callback_; size_t current_pac_source_index_;
diff --git a/net/proxy/proxy_script_decider_unittest.cc b/net/proxy/proxy_script_decider_unittest.cc index 383c159..d92dfc2 100644 --- a/net/proxy/proxy_script_decider_unittest.cc +++ b/net/proxy/proxy_script_decider_unittest.cc
@@ -14,8 +14,10 @@ #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" #include "net/dns/mock_host_resolver.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/proxy/dhcp_proxy_script_fetcher.h" #include "net/proxy/mock_proxy_script_fetcher.h" #include "net/proxy/proxy_config.h" @@ -195,7 +197,7 @@ EXPECT_EQ(rule.text(), decider.script_data()->utf16()); // Check the NetLog was filled correctly. - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(4u, entries.size()); @@ -232,7 +234,7 @@ EXPECT_EQ(NULL, decider.script_data()); // Check the NetLog was filled correctly. - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(4u, entries.size()); @@ -492,7 +494,7 @@ // Check the NetLog was filled correctly. // (Note that various states are repeated since both WPAD and custom // PAC scripts are tried). - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(10u, entries.size()); @@ -592,7 +594,7 @@ EXPECT_EQ(NULL, decider.script_data()); // Check the NetLog was filled correctly. - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(6u, entries.size()); @@ -632,7 +634,7 @@ EXPECT_EQ(NULL, decider.script_data()); // Check the NetLog was filled correctly. - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(4u, entries.size());
diff --git a/net/proxy/proxy_script_fetcher.h b/net/proxy/proxy_script_fetcher.h index 02f3195..ed89268 100644 --- a/net/proxy/proxy_script_fetcher.h +++ b/net/proxy/proxy_script_fetcher.h
@@ -44,8 +44,9 @@ // deleting |this|), then no callback is invoked. // // Only one fetch is allowed to be outstanding at a time. - virtual int Fetch(const GURL& url, base::string16* utf16_text, - const net::CompletionCallback& callback) = 0; + virtual int Fetch(const GURL& url, + base::string16* utf16_text, + const CompletionCallback& callback) = 0; // Aborts the in-progress fetch (if any). virtual void Cancel() = 0;
diff --git a/net/proxy/proxy_script_fetcher_impl.cc b/net/proxy/proxy_script_fetcher_impl.cc index 7d5d1ff..8ef777a 100644 --- a/net/proxy/proxy_script_fetcher_impl.cc +++ b/net/proxy/proxy_script_fetcher_impl.cc
@@ -7,6 +7,7 @@ #include "base/compiler_specific.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" +#include "base/profiler/scoped_tracker.h" #include "base/strings/string_util.h" #include "net/base/data_url.h" #include "net/base/io_buffer.h" @@ -114,6 +115,11 @@ int ProxyScriptFetcherImpl::Fetch( const GURL& url, base::string16* text, const CompletionCallback& callback) { + // TODO(eroman): Remove ScopedTracker below once crbug.com/455942 is fixed. + tracked_objects::ScopedTracker tracking_profile1( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "455942 ProxyScriptFetcherImpl::Fetch (Other)")); + // It is invalid to call Fetch() while a request is already in progress. DCHECK(!cur_request_.get()); DCHECK(!callback.is_null()); @@ -121,6 +127,10 @@ // Handle base-64 encoded data-urls that contain custom PAC scripts. if (url.SchemeIs("data")) { + // TODO(eroman): Remove ScopedTracker below once crbug.com/455942 is fixed. + tracked_objects::ScopedTracker tracking_profile2( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "455942 ProxyScriptFetcherImpl::Fetch (data url)")); std::string mime_type; std::string charset; std::string data; @@ -155,6 +165,12 @@ // Post a task to timeout this request if it takes too long. cur_request_id_ = ++next_id_; + + // TODO(eroman): Remove ScopedTracker below once crbug.com/455942 is fixed. + tracked_objects::ScopedTracker tracking_profile3( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "455942 ProxyScriptFetcherImpl::Fetch (PostDelayedTask)")); + base::MessageLoop::current()->PostDelayedTask( FROM_HERE, base::Bind(&ProxyScriptFetcherImpl::OnTimeout,
diff --git a/net/proxy/proxy_script_fetcher_impl.h b/net/proxy/proxy_script_fetcher_impl.h index 54afa4c..2afb116 100644 --- a/net/proxy/proxy_script_fetcher_impl.h +++ b/net/proxy/proxy_script_fetcher_impl.h
@@ -47,7 +47,7 @@ // ProxyScriptFetcher methods: int Fetch(const GURL& url, base::string16* text, - const net::CompletionCallback& callback) override; + const CompletionCallback& callback) override; void Cancel() override; URLRequestContext* GetRequestContext() const override; @@ -98,7 +98,7 @@ int cur_request_id_; // Callback to invoke on completion of the fetch. - net::CompletionCallback callback_; + CompletionCallback callback_; // Holds the error condition that was hit on the current request, or OK. int result_code_;
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc index 52c248f7..5046db3 100644 --- a/net/proxy/proxy_script_fetcher_impl_unittest.cc +++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -36,12 +36,12 @@ using base::ASCIIToUTF16; -namespace net { - // TODO(eroman): // - Test canceling an outstanding request. // - Test deleting ProxyScriptFetcher while a request is in progress. +namespace net { + namespace { const base::FilePath::CharType kDocRoot[] = @@ -172,7 +172,7 @@ return true; } - bool OnCanAccessFile(const net::URLRequest& request, + bool OnCanAccessFile(const URLRequest& request, const base::FilePath& path) const override { return true; } @@ -183,13 +183,11 @@ DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate); }; -} // namespace - class ProxyScriptFetcherImplTest : public PlatformTest { public: ProxyScriptFetcherImplTest() : test_server_(SpawnedTestServer::TYPE_HTTP, - net::SpawnedTestServer::kLocalhost, + SpawnedTestServer::kLocalhost, base::FilePath(kDocRoot)) { context_.set_network_delegate(&network_delegate_); } @@ -482,4 +480,6 @@ } } +} // namespace + } // namespace net
diff --git a/net/proxy/proxy_server.cc b/net/proxy/proxy_server.cc index 78d5c3e3..1e8bba9 100644 --- a/net/proxy/proxy_server.cc +++ b/net/proxy/proxy_server.cc
@@ -231,7 +231,7 @@ std::string host; int port = -1; // If the scheme has a host/port, parse it. - bool ok = net::ParseHostAndPort(begin, end, &host, &port); + bool ok = ParseHostAndPort(begin, end, &host, &port); if (!ok) return ProxyServer(); // Invalid -- failed parsing <host>[":"<port>]
diff --git a/net/proxy/proxy_server_unittest.cc b/net/proxy/proxy_server_unittest.cc index 0a596e47..25ad434 100644 --- a/net/proxy/proxy_server_unittest.cc +++ b/net/proxy/proxy_server_unittest.cc
@@ -6,6 +6,10 @@ #include "net/proxy/proxy_server.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + +namespace { + // Test the creation of ProxyServer using ProxyServer::FromURI, which parses // inputs of the form [<scheme>"://"]<host>[":"<port>]. Verify that each part // was labelled correctly, and the accessors all give the right data. @@ -13,156 +17,123 @@ const struct { const char* const input_uri; const char* const expected_uri; - net::ProxyServer::Scheme expected_scheme; + ProxyServer::Scheme expected_scheme; const char* const expected_host; int expected_port; const char* const expected_pac_string; } tests[] = { - // HTTP proxy URIs: - { - "foopy:10", // No scheme. + // HTTP proxy URIs: + {"foopy:10", // No scheme. "foopy:10", - net::ProxyServer::SCHEME_HTTP, + ProxyServer::SCHEME_HTTP, "foopy", 10, - "PROXY foopy:10" - }, - { - "http://foopy", // No port. + "PROXY foopy:10"}, + {"http://foopy", // No port. "foopy:80", - net::ProxyServer::SCHEME_HTTP, + ProxyServer::SCHEME_HTTP, "foopy", 80, - "PROXY foopy:80" - }, - { - "http://foopy:10", + "PROXY foopy:80"}, + {"http://foopy:10", "foopy:10", - net::ProxyServer::SCHEME_HTTP, + ProxyServer::SCHEME_HTTP, "foopy", 10, - "PROXY foopy:10" - }, + "PROXY foopy:10"}, - // IPv6 HTTP proxy URIs: - { - "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10", // No scheme. + // IPv6 HTTP proxy URIs: + {"[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10", // No scheme. "[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10", - net::ProxyServer::SCHEME_HTTP, + ProxyServer::SCHEME_HTTP, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", 10, - "PROXY [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10" - }, - { - "http://[3ffe:2a00:100:7031::1]", // No port. + "PROXY [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:10"}, + {"http://[3ffe:2a00:100:7031::1]", // No port. "[3ffe:2a00:100:7031::1]:80", - net::ProxyServer::SCHEME_HTTP, + ProxyServer::SCHEME_HTTP, "3ffe:2a00:100:7031::1", 80, - "PROXY [3ffe:2a00:100:7031::1]:80" - }, - { - "http://[::192.9.5.5]", + "PROXY [3ffe:2a00:100:7031::1]:80"}, + {"http://[::192.9.5.5]", "[::192.9.5.5]:80", - net::ProxyServer::SCHEME_HTTP, + ProxyServer::SCHEME_HTTP, "::192.9.5.5", 80, - "PROXY [::192.9.5.5]:80" - }, - { - "http://[::FFFF:129.144.52.38]:80", + "PROXY [::192.9.5.5]:80"}, + {"http://[::FFFF:129.144.52.38]:80", "[::FFFF:129.144.52.38]:80", - net::ProxyServer::SCHEME_HTTP, + ProxyServer::SCHEME_HTTP, "::FFFF:129.144.52.38", 80, - "PROXY [::FFFF:129.144.52.38]:80" - }, + "PROXY [::FFFF:129.144.52.38]:80"}, - // SOCKS4 proxy URIs: - { - "socks4://foopy", // No port. + // SOCKS4 proxy URIs: + {"socks4://foopy", // No port. "socks4://foopy:1080", - net::ProxyServer::SCHEME_SOCKS4, + ProxyServer::SCHEME_SOCKS4, "foopy", 1080, - "SOCKS foopy:1080" - }, - { + "SOCKS foopy:1080"}, + {"socks4://foopy:10", "socks4://foopy:10", - "socks4://foopy:10", - net::ProxyServer::SCHEME_SOCKS4, + ProxyServer::SCHEME_SOCKS4, "foopy", 10, - "SOCKS foopy:10" - }, + "SOCKS foopy:10"}, - // SOCKS5 proxy URIs - { - "socks5://foopy", // No port. + // SOCKS5 proxy URIs + {"socks5://foopy", // No port. "socks5://foopy:1080", - net::ProxyServer::SCHEME_SOCKS5, + ProxyServer::SCHEME_SOCKS5, "foopy", 1080, - "SOCKS5 foopy:1080" - }, - { + "SOCKS5 foopy:1080"}, + {"socks5://foopy:10", "socks5://foopy:10", - "socks5://foopy:10", - net::ProxyServer::SCHEME_SOCKS5, + ProxyServer::SCHEME_SOCKS5, "foopy", 10, - "SOCKS5 foopy:10" - }, + "SOCKS5 foopy:10"}, - // SOCKS proxy URIs (should default to SOCKS5) - { - "socks://foopy", // No port. + // SOCKS proxy URIs (should default to SOCKS5) + {"socks://foopy", // No port. "socks5://foopy:1080", - net::ProxyServer::SCHEME_SOCKS5, + ProxyServer::SCHEME_SOCKS5, "foopy", 1080, - "SOCKS5 foopy:1080" - }, - { - "socks://foopy:10", + "SOCKS5 foopy:1080"}, + {"socks://foopy:10", "socks5://foopy:10", - net::ProxyServer::SCHEME_SOCKS5, + ProxyServer::SCHEME_SOCKS5, "foopy", 10, - "SOCKS5 foopy:10" - }, + "SOCKS5 foopy:10"}, - // HTTPS proxy URIs: - { - "https://foopy", // No port + // HTTPS proxy URIs: + {"https://foopy", // No port "https://foopy:443", - net::ProxyServer::SCHEME_HTTPS, + ProxyServer::SCHEME_HTTPS, "foopy", 443, - "HTTPS foopy:443" - }, - { - "https://foopy:10", // Non-standard port + "HTTPS foopy:443"}, + {"https://foopy:10", // Non-standard port "https://foopy:10", - net::ProxyServer::SCHEME_HTTPS, + ProxyServer::SCHEME_HTTPS, "foopy", 10, - "HTTPS foopy:10" - }, - { - "https://1.2.3.4:10", // IP Address + "HTTPS foopy:10"}, + {"https://1.2.3.4:10", // IP Address "https://1.2.3.4:10", - net::ProxyServer::SCHEME_HTTPS, + ProxyServer::SCHEME_HTTPS, "1.2.3.4", 10, - "HTTPS 1.2.3.4:10" - }, + "HTTPS 1.2.3.4:10"}, }; for (size_t i = 0; i < arraysize(tests); ++i) { - net::ProxyServer uri = - net::ProxyServer::FromURI(tests[i].input_uri, - net::ProxyServer::SCHEME_HTTP); + ProxyServer uri = + ProxyServer::FromURI(tests[i].input_uri, ProxyServer::SCHEME_HTTP); EXPECT_TRUE(uri.is_valid()); EXPECT_FALSE(uri.is_direct()); EXPECT_EQ(tests[i].expected_uri, uri.ToURI()); @@ -174,15 +145,14 @@ } TEST(ProxyServerTest, DefaultConstructor) { - net::ProxyServer proxy_server; + ProxyServer proxy_server; EXPECT_FALSE(proxy_server.is_valid()); } // Test parsing of the special URI form "direct://". Analagous to the "DIRECT" // entry in a PAC result. TEST(ProxyServerTest, Direct) { - net::ProxyServer uri = - net::ProxyServer::FromURI("direct://", net::ProxyServer::SCHEME_HTTP); + ProxyServer uri = ProxyServer::FromURI("direct://", ProxyServer::SCHEME_HTTP); EXPECT_TRUE(uri.is_valid()); EXPECT_TRUE(uri.is_direct()); EXPECT_EQ("direct://", uri.ToURI()); @@ -203,8 +173,7 @@ }; for (size_t i = 0; i < arraysize(tests); ++i) { - net::ProxyServer uri = - net::ProxyServer::FromURI(tests[i], net::ProxyServer::SCHEME_HTTP); + ProxyServer uri = ProxyServer::FromURI(tests[i], ProxyServer::SCHEME_HTTP); EXPECT_FALSE(uri.is_valid()); EXPECT_FALSE(uri.is_direct()); EXPECT_FALSE(uri.is_http()); @@ -221,8 +190,7 @@ }; for (size_t i = 0; i < arraysize(tests); ++i) { - net::ProxyServer uri = - net::ProxyServer::FromURI(tests[i], net::ProxyServer::SCHEME_HTTP); + ProxyServer uri = ProxyServer::FromURI(tests[i], ProxyServer::SCHEME_HTTP); EXPECT_EQ("foopy:80", uri.ToURI()); } } @@ -280,7 +248,7 @@ }; for (size_t i = 0; i < arraysize(tests); ++i) { - net::ProxyServer uri = net::ProxyServer::FromPacString(tests[i].input_pac); + ProxyServer uri = ProxyServer::FromPacString(tests[i].input_pac); EXPECT_TRUE(uri.is_valid()); EXPECT_EQ(tests[i].expected_uri, uri.ToURI()); } @@ -296,7 +264,7 @@ }; for (size_t i = 0; i < arraysize(tests); ++i) { - net::ProxyServer uri = net::ProxyServer::FromPacString(tests[i]); + ProxyServer uri = ProxyServer::FromPacString(tests[i]); EXPECT_FALSE(uri.is_valid()); } } @@ -337,13 +305,11 @@ for (size_t i = 0; i < arraysize(tests); ++i) { // Parse the expected inputs to ProxyServer instances. - const net::ProxyServer server1 = - net::ProxyServer::FromURI( - tests[i].server1, net::ProxyServer::SCHEME_HTTP); + const ProxyServer server1 = + ProxyServer::FromURI(tests[i].server1, ProxyServer::SCHEME_HTTP); - const net::ProxyServer server2 = - net::ProxyServer::FromURI( - tests[i].server2, net::ProxyServer::SCHEME_HTTP); + const ProxyServer server2 = + ProxyServer::FromURI(tests[i].server2, ProxyServer::SCHEME_HTTP); switch (tests[i].expected_comparison) { case -1: @@ -366,3 +332,7 @@ } } } + +} // namespace + +} // namespace net
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc index 7de5449..f55561d 100644 --- a/net/proxy/proxy_service.cc +++ b/net/proxy/proxy_service.cc
@@ -785,13 +785,13 @@ class ProxyService::PacRequest : public base::RefCounted<ProxyService::PacRequest> { public: - PacRequest(ProxyService* service, - const GURL& url, - int load_flags, - NetworkDelegate* network_delegate, - ProxyInfo* results, - const net::CompletionCallback& user_callback, - const BoundNetLog& net_log) + PacRequest(ProxyService* service, + const GURL& url, + int load_flags, + NetworkDelegate* network_delegate, + ProxyInfo* results, + const CompletionCallback& user_callback, + const BoundNetLog& net_log) : service_(service), user_callback_(user_callback), results_(results), @@ -868,6 +868,10 @@ int QueryDidComplete(int result_code) { DCHECK(!was_cancelled()); + // Clear |resolve_job_| so is_started() returns false while + // DidFinishResolvingProxy() runs. + resolve_job_ = nullptr; + // Note that DidFinishResolvingProxy might modify |results_|. int rv = service_->DidFinishResolvingProxy(url_, load_flags_, network_delegate_, results_, @@ -882,7 +886,6 @@ results_->proxy_resolve_end_time_ = TimeTicks::Now(); // Reset the state associated with in-progress-resolve. - resolve_job_ = NULL; config_id_ = ProxyConfig::kInvalidConfigID; config_source_ = PROXY_CONFIG_SOURCE_UNKNOWN; @@ -909,7 +912,7 @@ // Remove this completed PacRequest from the service's pending list. /// (which will probably cause deletion of |this|). if (!user_callback_.is_null()) { - net::CompletionCallback callback = user_callback_; + CompletionCallback callback = user_callback_; service_->RemovePendingRequest(this); callback.Run(result_code); } @@ -921,7 +924,7 @@ // requests are cancelled during ~ProxyService, so this is guaranteed // to be valid throughout our lifetime. ProxyService* service_; - net::CompletionCallback user_callback_; + CompletionCallback user_callback_; ProxyInfo* results_; GURL url_; int load_flags_; @@ -992,7 +995,7 @@ // static ProxyService* ProxyService::CreateFixed(const std::string& proxy) { - net::ProxyConfig proxy_config; + ProxyConfig proxy_config; proxy_config.proxy_rules().ParseFromString(proxy); return ProxyService::CreateFixed(proxy_config); } @@ -1026,7 +1029,7 @@ int ProxyService::ResolveProxy(const GURL& raw_url, int load_flags, ProxyInfo* result, - const net::CompletionCallback& callback, + const CompletionCallback& callback, PacRequest** pac_request, NetworkDelegate* network_delegate, const BoundNetLog& net_log) { @@ -1043,7 +1046,7 @@ int ProxyService::ResolveProxyHelper(const GURL& raw_url, int load_flags, ProxyInfo* result, - const net::CompletionCallback& callback, + const CompletionCallback& callback, PacRequest** pac_request, NetworkDelegate* network_delegate, const BoundNetLog& net_log) { @@ -1105,7 +1108,7 @@ ProxyInfo* result, NetworkDelegate* network_delegate, const BoundNetLog& net_log) { - net::CompletionCallback null_callback; + CompletionCallback null_callback; return ResolveProxyHelper(raw_url, load_flags, result, @@ -1399,6 +1402,7 @@ net_log.AddEventWithNetErrorCode( NetLog::TYPE_PROXY_SERVICE_RESOLVED_PROXY_LIST, result_code); + bool reset_config = result_code == ERR_PAC_SCRIPT_TERMINATED; if (!config_.pac_mandatory()) { // Fall-back to direct when the proxy resolver fails. This corresponds // with a javascript runtime error in the PAC script. @@ -1417,6 +1421,14 @@ } else { result_code = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED; } + if (reset_config) { + ResetProxyConfig(false); + // If the ProxyResolver crashed, force it to be re-initialized for the + // next request by resetting the proxy config. If there are other pending + // requests, trigger the recreation immediately so those requests retry. + if (pending_requests_.size() > 1) + ApplyProxyConfigIfAvailable(); + } } net_log.EndEvent(NetLog::TYPE_PROXY_SERVICE); @@ -1557,10 +1569,9 @@ // Emit the proxy settings change to the NetLog stream. if (net_log_) { - net_log_->AddGlobalEntry( - net::NetLog::TYPE_PROXY_CONFIG_CHANGED, - base::Bind(&NetLogProxyConfigChangedCallback, - &fetched_config_, &effective_config)); + net_log_->AddGlobalEntry(NetLog::TYPE_PROXY_CONFIG_CHANGED, + base::Bind(&NetLogProxyConfigChangedCallback, + &fetched_config_, &effective_config)); } // Set the new configuration as the most recently fetched one.
diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h index f5437d5..232a944 100644 --- a/net/proxy/proxy_service.h +++ b/net/proxy/proxy_service.h
@@ -126,7 +126,7 @@ int ResolveProxy(const GURL& url, int load_flags, ProxyInfo* results, - const net::CompletionCallback& callback, + const CompletionCallback& callback, PacRequest** pac_request, NetworkDelegate* network_delegate, const BoundNetLog& net_log); @@ -336,7 +336,7 @@ int ResolveProxyHelper(const GURL& url, int load_flags, ProxyInfo* results, - const net::CompletionCallback& callback, + const CompletionCallback& callback, PacRequest** pac_request, NetworkDelegate* network_delegate, const BoundNetLog& net_log);
diff --git a/net/proxy/proxy_service_unittest.cc b/net/proxy/proxy_service_unittest.cc index db4151db..5a4ca69 100644 --- a/net/proxy/proxy_service_unittest.cc +++ b/net/proxy/proxy_service_unittest.cc
@@ -14,8 +14,10 @@ #include "net/base/net_errors.h" #include "net/base/network_delegate_impl.h" #include "net/base/test_completion_callback.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/proxy/dhcp_proxy_script_fetcher.h" #include "net/proxy/mock_proxy_resolver.h" #include "net/proxy/mock_proxy_script_fetcher.h" @@ -250,9 +252,8 @@ ProxyInfo info; TestCompletionCallback callback; BoundTestNetLog log; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, - log.bound()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, log.bound()); EXPECT_EQ(OK, rv); EXPECT_TRUE(resolver.pending_requests().empty()); @@ -261,7 +262,7 @@ EXPECT_TRUE(info.proxy_resolve_end_time().is_null()); // Check the NetLog was filled correctly. - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(3u, entries.size()); @@ -290,16 +291,14 @@ BoundTestNetLog log; // First, warm up the ProxyService. - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, - log.bound()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, log.bound()); EXPECT_EQ(OK, rv); // Verify that network delegate is invoked. TestResolveProxyNetworkDelegate delegate; - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, - log.bound()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL, + &delegate, log.bound()); EXPECT_TRUE(delegate.on_resolve_proxy_called()); EXPECT_EQ(&service, delegate.proxy_service()); @@ -309,24 +308,21 @@ delegate.set_add_proxy(true); // Callback should interpose: - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, - log.bound()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL, + &delegate, log.bound()); EXPECT_FALSE(info.is_direct()); EXPECT_EQ(info.proxy_server().host_port_pair().host(), "delegate_proxy.com"); delegate.set_add_proxy(false); // Check non-bypassed URL: - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, - log.bound()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL, + &delegate, log.bound()); EXPECT_FALSE(info.is_direct()); EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1"); // Check bypassed URL: - rv = service.ResolveProxy( - bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL, - &delegate, log.bound()); + rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(), + NULL, &delegate, log.bound()); EXPECT_TRUE(info.is_direct()); } @@ -349,32 +345,28 @@ BoundTestNetLog log; // First, warm up the ProxyService. - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, - log.bound()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, log.bound()); EXPECT_EQ(OK, rv); TestResolveProxyNetworkDelegate delegate; delegate.set_remove_proxy(true); // Callback should interpose: - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, - log.bound()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL, + &delegate, log.bound()); EXPECT_TRUE(info.is_direct()); delegate.set_remove_proxy(false); // Check non-bypassed URL: - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, &delegate, - log.bound()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), NULL, + &delegate, log.bound()); EXPECT_FALSE(info.is_direct()); EXPECT_EQ(info.proxy_server().host_port_pair().host(), "foopy1"); // Check bypassed URL: - rv = service.ResolveProxy( - bypass_url, net::LOAD_NORMAL, &info, callback.callback(), NULL, - &delegate, log.bound()); + rv = service.ResolveProxy(bypass_url, LOAD_NORMAL, &info, callback.callback(), + NULL, &delegate, log.bound()); EXPECT_TRUE(info.is_direct()); } @@ -395,9 +387,8 @@ ProxyService::PacRequest* request; BoundTestNetLog log; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), &request, NULL, - log.bound()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), + &request, NULL, log.bound()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(LOAD_STATE_RESOLVING_PROXY_FOR_URL, service.GetLoadState(request)); @@ -423,7 +414,7 @@ EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); // Check the NetLog was filled correctly. - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(5u, entries.size()); @@ -453,9 +444,8 @@ ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -484,9 +474,8 @@ ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -516,8 +505,8 @@ TestCompletionCallback callback2; ProxyServer expected_proxy_server = info.proxy_server(); rv = service.ReconsiderProxyAfterError( - url, net::LOAD_NORMAL, net::ERR_PROXY_CONNECTION_FAILED, - &info, callback2.callback(), NULL, &network_delegate, BoundNetLog()); + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback2.callback(), NULL, &network_delegate, BoundNetLog()); // ReconsiderProxyAfterError returns error indicating nothing left. EXPECT_EQ(ERR_FAILED, rv); EXPECT_TRUE(info.is_empty()); @@ -538,9 +527,8 @@ ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -596,9 +584,8 @@ ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -618,10 +605,9 @@ // Fallback 1. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback2.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foobar:10", info.proxy_server().ToURI()); @@ -630,20 +616,18 @@ NetworkDelegateImpl network_delegate; ProxyServer expected_proxy_server3 = info.proxy_server(); TestCompletionCallback callback3; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback3.callback(), NULL, - &network_delegate, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback3.callback(), NULL, &network_delegate, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(info.is_direct()); // Fallback 3. ProxyServer expected_proxy_server4 = info.proxy_server(); TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback4.callback(), NULL, - &network_delegate, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback4.callback(), NULL, &network_delegate, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foobar:20", info.proxy_server().ToURI()); @@ -651,10 +635,9 @@ // Fallback 4 -- Nothing to fall back to! ProxyServer expected_proxy_server5 = info.proxy_server(); TestCompletionCallback callback5; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback5.callback(), NULL, - &network_delegate, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback5.callback(), NULL, &network_delegate, BoundNetLog()); EXPECT_EQ(ERR_FAILED, rv); EXPECT_TRUE(info.is_empty()); } @@ -676,9 +659,8 @@ GURL url("http://www.google.com/"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); ASSERT_EQ(ERR_IO_PENDING, rv); resolver.pending_set_pac_script_request()->CompleteNow(OK); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -714,9 +696,8 @@ GURL url("http://www.google.com/"); ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -742,9 +723,8 @@ // The second resolve request will try to run through the proxy resolver, // regardless of whether the first request failed in it. TestCompletionCallback callback2; - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL, + NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -760,6 +740,148 @@ EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); } +TEST_F(ProxyServiceTest, ProxyResolverTerminatedDuringRequest) { + // Test what happens when the ProxyResolver fails with a fatal error while + // a GetProxyForURL() call is in progress. + + MockProxyConfigService* config_service = + new MockProxyConfigService("http://foopy/proxy.pac"); + + MockAsyncProxyResolver resolver; + + ProxyService service( + config_service, + make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), nullptr); + + // Start first resolve request. + GURL url("http://www.google.com/"); + ProxyInfo info; + TestCompletionCallback callback1; + int rv = + service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback1.callback(), + nullptr, nullptr, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + ASSERT_TRUE(resolver.pending_set_pac_script_request()); + EXPECT_EQ(GURL("http://foopy/proxy.pac"), + resolver.pending_set_pac_script_request()->script_data()->url()); + resolver.pending_set_pac_script_request()->CompleteNow(OK); + + ASSERT_EQ(1u, resolver.pending_requests().size()); + EXPECT_EQ(url, resolver.pending_requests()[0]->url()); + + // Fail the first resolve request in MockAsyncProxyResolver. + resolver.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED); + + // Although the proxy resolver failed the request, ProxyService implicitly + // falls-back to DIRECT. + EXPECT_EQ(OK, callback1.WaitForResult()); + EXPECT_TRUE(info.is_direct()); + + // Failed PAC executions still have proxy resolution times. + EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); + EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); + EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); + + // With no other requests, the ProxyService waits for a new request before + // initializing a new ProxyResolver. + EXPECT_FALSE(resolver.pending_set_pac_script_request()); + + TestCompletionCallback callback2; + rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback2.callback(), + nullptr, nullptr, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + ASSERT_TRUE(resolver.pending_set_pac_script_request()); + EXPECT_EQ(GURL("http://foopy/proxy.pac"), + resolver.pending_set_pac_script_request()->script_data()->url()); + resolver.pending_set_pac_script_request()->CompleteNow(OK); + + ASSERT_EQ(1u, resolver.pending_requests().size()); + EXPECT_EQ(url, resolver.pending_requests()[0]->url()); + + // This time we will have the resolver succeed. + resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); + resolver.pending_requests()[0]->CompleteNow(OK); + + EXPECT_EQ(OK, callback2.WaitForResult()); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); +} + +TEST_F(ProxyServiceTest, + ProxyResolverTerminatedDuringRequestWithConcurrentRequest) { + // Test what happens when the ProxyResolver fails with a fatal error while + // a GetProxyForURL() call is in progress. + + MockProxyConfigService* config_service = + new MockProxyConfigService("http://foopy/proxy.pac"); + + MockAsyncProxyResolver resolver; + + ProxyService service( + config_service, + make_scoped_ptr(new ForwardingProxyResolverFactory(&resolver)), nullptr); + + // Start two resolve requests. + GURL url1("http://www.google.com/"); + GURL url2("https://www.google.com/"); + ProxyInfo info; + TestCompletionCallback callback1; + int rv = + service.ResolveProxy(url1, net::LOAD_NORMAL, &info, callback1.callback(), + nullptr, nullptr, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + TestCompletionCallback callback2; + rv = service.ResolveProxy(url2, net::LOAD_NORMAL, &info, callback2.callback(), + nullptr, nullptr, BoundNetLog()); + EXPECT_EQ(ERR_IO_PENDING, rv); + + ASSERT_TRUE(resolver.pending_set_pac_script_request()); + EXPECT_EQ(GURL("http://foopy/proxy.pac"), + resolver.pending_set_pac_script_request()->script_data()->url()); + resolver.pending_set_pac_script_request()->CompleteNow(OK); + + ASSERT_EQ(2u, resolver.pending_requests().size()); + EXPECT_EQ(url1, resolver.pending_requests()[0]->url()); + EXPECT_EQ(url2, resolver.pending_requests()[1]->url()); + + // Fail the first resolve request in MockAsyncProxyResolver. + resolver.pending_requests()[0]->CompleteNow(ERR_PAC_SCRIPT_TERMINATED); + + // Although the proxy resolver failed the request, ProxyService implicitly + // falls-back to DIRECT. + EXPECT_EQ(OK, callback1.WaitForResult()); + EXPECT_TRUE(info.is_direct()); + + // Failed PAC executions still have proxy resolution times. + EXPECT_FALSE(info.proxy_resolve_start_time().is_null()); + EXPECT_FALSE(info.proxy_resolve_end_time().is_null()); + EXPECT_LE(info.proxy_resolve_start_time(), info.proxy_resolve_end_time()); + + // The second request is cancelled when the proxy resolver terminates. + ASSERT_EQ(1u, resolver.cancelled_requests().size()); + EXPECT_EQ(url2, resolver.cancelled_requests()[0]->url()); + + // Since a second request was in progress, the ProxyService starts + // initializating a new ProxyResolver. + ASSERT_TRUE(resolver.pending_set_pac_script_request()); + EXPECT_EQ(GURL("http://foopy/proxy.pac"), + resolver.pending_set_pac_script_request()->script_data()->url()); + resolver.pending_set_pac_script_request()->CompleteNow(OK); + + ASSERT_EQ(1u, resolver.pending_requests().size()); + EXPECT_EQ(url2, resolver.pending_requests()[0]->url()); + + // This request succeeds. + resolver.pending_requests()[0]->results()->UseNamedProxy("foopy_valid:8080"); + resolver.pending_requests()[0]->CompleteNow(OK); + + EXPECT_EQ(OK, callback2.WaitForResult()); + EXPECT_FALSE(info.is_direct()); + EXPECT_EQ("foopy_valid:8080", info.proxy_server().ToURI()); +} + TEST_F(ProxyServiceTest, ProxyScriptFetcherFailsDownloadingMandatoryPac) { // Test what happens when the ProxyScriptResolver fails to download a // mandatory PAC script. @@ -780,9 +902,8 @@ GURL url("http://www.google.com/"); ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -799,9 +920,8 @@ // As the proxy resolver failed the request and is configured for a mandatory // PAC script, ProxyService must not implicitly fall-back to DIRECT. TestCompletionCallback callback2; - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL, + NULL, BoundNetLog()); EXPECT_EQ(ERR_MANDATORY_PROXY_CONFIGURATION_FAILED, rv); EXPECT_FALSE(info.is_direct()); } @@ -831,9 +951,8 @@ GURL url("http://www.google.com/"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // Check that nothing has been sent to the proxy resolver yet. @@ -877,9 +996,8 @@ GURL url("http://www.google.com/"); ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -901,9 +1019,8 @@ // The second resolve request will try to run through the proxy resolver, // regardless of whether the first request failed in it. TestCompletionCallback callback2; - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback2.callback(), NULL, + NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -937,9 +1054,8 @@ // Get the proxy information. ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -967,10 +1083,9 @@ // Fake an error on the proxy. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback2.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); // Proxy times should not have been modified by fallback. @@ -984,13 +1099,12 @@ TestProxyFallbackNetworkDelegate test_delegate; service.ReportSuccess(info, &test_delegate); EXPECT_EQ("foopy1:8080", test_delegate.proxy_server().ToURI()); - EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, + EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, test_delegate.proxy_fallback_net_error()); TestCompletionCallback callback3; - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback3.callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback3.callback(), NULL, + NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -1016,10 +1130,9 @@ // We fake another error. It should now try the third one. TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback4.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback4.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); @@ -1027,20 +1140,18 @@ // proxy servers we thought were valid; next we try the proxy server // that was in our bad proxies map (foopy1:8080). TestCompletionCallback callback5; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback5.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback5.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); // Fake another error, the last proxy is gone, the list should now be empty, // so there is nothing left to try. TestCompletionCallback callback6; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback6.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback6.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_FAILED, rv); EXPECT_FALSE(info.is_direct()); EXPECT_TRUE(info.is_empty()); @@ -1051,8 +1162,8 @@ // Look up proxies again TestCompletionCallback callback7; - rv = service.ResolveProxy(url, net::LOAD_NORMAL, &info, callback7.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback7.callback(), NULL, + NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -1092,9 +1203,8 @@ // Get the proxy information. ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -1116,10 +1226,9 @@ // Fake an error on the proxy. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback2.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); // Now we get back the second proxy. @@ -1127,10 +1236,9 @@ // Fake an error on this proxy as well. TestCompletionCallback callback3; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback3.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback3.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); // Finally, we get back DIRECT. @@ -1142,10 +1250,9 @@ // Now we tell the proxy service that even DIRECT failed. TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback4.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback4.callback(), NULL, NULL, BoundNetLog()); // There was nothing left to try after DIRECT, so we are out of // choices. EXPECT_EQ(ERR_FAILED, rv); @@ -1168,9 +1275,8 @@ // Get the proxy information. ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -1195,10 +1301,9 @@ ProxyConfig::CreateFromCustomPacURL(GURL("http://foopy-new/proxy.pac"))); TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback2.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy-new/proxy.pac"), @@ -1218,10 +1323,9 @@ // We fake another error. It should now ignore the first one. TestCompletionCallback callback3; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback3.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback3.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy2:9090", info.proxy_server().ToURI()); @@ -1232,10 +1336,9 @@ // We fake another error. It should go back to the first proxy. TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback4.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback4.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy-new2/proxy.pac"), @@ -1274,9 +1377,8 @@ // Get the proxy information. ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -1296,10 +1398,9 @@ // Fake a proxy error. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback2.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); // The first proxy is ignored, and the second one is selected. @@ -1309,9 +1410,8 @@ // Fake a PAC failure. ProxyInfo info2; TestCompletionCallback callback3; - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -1331,10 +1431,9 @@ // "just work" the next time we call it. ProxyInfo info3; TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info3, callback4.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3, + callback4.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -1375,9 +1474,8 @@ // Get the proxy information. ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback1.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -1397,10 +1495,9 @@ // Fake a proxy error. TestCompletionCallback callback2; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info, callback2.callback(), NULL, - NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); // The first proxy is ignored, and the second one is selected. @@ -1410,9 +1507,8 @@ // Fake a PAC failure. ProxyInfo info2; TestCompletionCallback callback3; - rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info2, callback3.callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(url, LOAD_NORMAL, &info2, callback3.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -1433,10 +1529,9 @@ // "just work" the next time we call it. ProxyInfo info3; TestCompletionCallback callback4; - rv = service.ReconsiderProxyAfterError(url, net::LOAD_NORMAL, - net::ERR_PROXY_CONNECTION_FAILED, - &info3, callback4.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ReconsiderProxyAfterError( + url, LOAD_NORMAL, ERR_PROXY_CONNECTION_FAILED, &info3, + callback4.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -1470,16 +1565,14 @@ GURL url2("http://www.webkit.com"); // Request for a .org domain should bypass proxy. - rv = service.ResolveProxy( - url1, net::LOAD_NORMAL, &info[0], callback[0].callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(url1, LOAD_NORMAL, &info[0], callback[0].callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(info[0].is_direct()); // Request for a .com domain hits the proxy. - rv = service.ResolveProxy( - url2, net::LOAD_NORMAL, &info[1], callback[1].callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(url2, LOAD_NORMAL, &info[1], callback[1].callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy1:8080", info[1].proxy_server().ToURI()); } @@ -1494,9 +1587,9 @@ GURL test_url("http://www.msn.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); @@ -1506,9 +1599,9 @@ GURL test_url("ftp://ftp.google.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(info.is_direct()); EXPECT_EQ("direct://", info.proxy_server().ToURI()); @@ -1518,9 +1611,9 @@ GURL test_url("https://webbranch.techcu.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); @@ -1531,9 +1624,9 @@ GURL test_url("http://www.microsoft.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); @@ -1552,9 +1645,9 @@ GURL test_url("http://www.google.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); ASSERT_EQ(OK, rv); // Should be SOURCE_TEST, even if there are no HTTP proxies configured. EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); @@ -1567,9 +1660,9 @@ GURL test_url("https://www.google.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); ASSERT_EQ(OK, rv); // Used the HTTPS proxy. So source should be TEST. EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); @@ -1581,9 +1674,9 @@ GURL test_url("http://www.google.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); ASSERT_EQ(OK, rv); // ProxyConfig is empty. Source should still be TEST. EXPECT_EQ(PROXY_CONFIG_SOURCE_TEST, info.config_source()); @@ -1604,9 +1697,9 @@ GURL test_url("http://www.msn.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); @@ -1616,9 +1709,9 @@ GURL test_url("ftp://ftp.google.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); @@ -1628,9 +1721,9 @@ GURL test_url("https://webbranch.techcu.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); @@ -1640,9 +1733,9 @@ GURL test_url("unknown://www.microsoft.com"); ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy(test_url, net::LOAD_NORMAL, &info, - callback.callback(), NULL, - NULL, BoundNetLog()); + int rv = + service.ResolveProxy(test_url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("socks4://foopy2:1080", info.proxy_server().ToURI()); @@ -1664,9 +1757,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info1, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // Nothing has been sent to the proxy resolver yet, since the proxy @@ -1684,7 +1777,7 @@ ProxyInfo info2; TestCompletionCallback callback2; ProxyService::PacRequest* request2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, callback2.callback(), &request2, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -1693,7 +1786,7 @@ ProxyInfo info3; TestCompletionCallback callback3; - rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, + rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3, callback3.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(3u, resolver.pending_requests().size()); @@ -1746,8 +1839,8 @@ ProxyInfo info1; TestCompletionCallback callback1; ProxyService::PacRequest* request1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info1, callback1.callback(), &request1, NULL, + int rv = service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), &request1, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -1758,7 +1851,7 @@ ProxyInfo info2; TestCompletionCallback callback2; ProxyService::PacRequest* request2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, callback2.callback(), &request2, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -1766,7 +1859,7 @@ ProxyInfo info3; TestCompletionCallback callback3; ProxyService::PacRequest* request3; - rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, + rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3, callback3.callback(), &request3, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -1852,9 +1945,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info1, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // The first request should have triggered download of PAC script. @@ -1863,7 +1956,7 @@ ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -1914,9 +2007,9 @@ TestCompletionCallback callback1; ProxyService::PacRequest* request1; BoundTestNetLog log1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info1, callback1.callback(), &request1, NULL, - log1.bound()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), &request1, NULL, log1.bound()); EXPECT_EQ(ERR_IO_PENDING, rv); // The first request should have triggered download of PAC script. @@ -1926,14 +2019,14 @@ ProxyInfo info2; TestCompletionCallback callback2; ProxyService::PacRequest* request2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, callback2.callback(), &request2, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ProxyInfo info3; TestCompletionCallback callback3; - rv = service.ResolveProxy(GURL("http://request3"), net::LOAD_NORMAL, &info3, + rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3, callback3.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -1970,7 +2063,7 @@ EXPECT_FALSE(callback1.have_result()); // Cancelled. EXPECT_FALSE(callback2.have_result()); // Cancelled. - TestNetLog::CapturedEntryList entries1; + CapturedNetLogEntry::List entries1; log1.GetEntries(&entries1); // Check the NetLog for request 1 (which was cancelled) got filled properly. @@ -2008,15 +2101,15 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info1, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ProxyInfo info2; TestCompletionCallback callback2; ProxyService::PacRequest* request2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, callback2.callback(), &request2, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -2088,15 +2181,15 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info1, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ProxyInfo info2; TestCompletionCallback callback2; ProxyService::PacRequest* request2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, callback2.callback(), &request2, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -2164,15 +2257,15 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info1, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ProxyInfo info2; TestCompletionCallback callback2; ProxyService::PacRequest* request2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, callback2.callback(), &request2, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -2225,9 +2318,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://www.google.com"), net::LOAD_NORMAL, &info1, - callback1.callback(), NULL, NULL, BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // Check that nothing has been sent to the proxy resolver yet. @@ -2257,9 +2350,8 @@ // Start another request, it should pickup the bypass item. ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, - &info2, callback2.callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); ASSERT_EQ(1u, resolver.pending_requests().size()); @@ -2296,9 +2388,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, - &info1, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // Check that nothing has been sent to the proxy resolver yet. @@ -2328,9 +2420,8 @@ ProxyInfo info; TestCompletionCallback callback; - int rv = service.ResolveProxy( - url, net::LOAD_NORMAL, &info, callback.callback(), NULL, NULL, - BoundNetLog()); + int rv = service.ResolveProxy(url, LOAD_NORMAL, &info, callback.callback(), + NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_EQ(GURL("http://foopy/proxy.pac"), @@ -2345,9 +2436,9 @@ ProxyInfo info; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy1:8080", info.proxy_server().ToURI()); @@ -2356,7 +2447,7 @@ config2.set_auto_detect(false); service.ResetConfigService(new MockProxyConfigService(config2)); TestCompletionCallback callback2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info, callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_EQ("foopy2:8080", info.proxy_server().ToURI()); @@ -2377,9 +2468,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, - &info1, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // Check that nothing has been sent to the proxy resolver yet. @@ -2409,9 +2500,8 @@ // Start another request -- the effective configuration has changed. ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy(GURL("http://www.google.com"), net::LOAD_NORMAL, - &info2, callback2.callback(), NULL, NULL, - BoundNetLog()); + rv = service.ResolveProxy(GURL("http://www.google.com"), LOAD_NORMAL, &info2, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(info2.is_direct()); @@ -2441,9 +2531,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy(GURL("http://request1"), net::LOAD_NORMAL, - &info1, callback1.callback(), NULL, NULL, - BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // The first request should have triggered initial download of PAC script. @@ -2484,7 +2574,7 @@ // Start a second request. ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy(GURL("http://request2"), net::LOAD_NORMAL, &info2, + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); @@ -2520,7 +2610,7 @@ // Check that the expected events were output to the log stream. In particular // PROXY_CONFIG_CHANGED should have only been emitted once (for the initial // setup), and NOT a second time when the IP address changed. - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsEntryWithType(entries, 0, @@ -2557,9 +2647,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), - NULL, NULL, BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // The first request should have triggered initial download of PAC script. @@ -2618,9 +2708,8 @@ // Start a second request. ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy( - GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // Check that it was sent to the resolver. @@ -2663,9 +2752,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), - NULL, NULL, BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // The first request should have triggered initial download of PAC script. @@ -2729,9 +2818,8 @@ // Start a second request. ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy( - GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // Check that it was sent to the resolver. @@ -2774,9 +2862,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), - NULL, NULL, BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // The first request should have triggered initial download of PAC script. @@ -2836,9 +2924,8 @@ // Start a second request. ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy( - GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // Check that it was sent to the resolver. @@ -2881,9 +2968,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), - NULL, NULL, BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // The first request should have triggered initial download of PAC script. @@ -2941,9 +3028,8 @@ // Start a second request. ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy( - GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(info2.is_direct()); } @@ -3034,9 +3120,9 @@ ProxyInfo info1; TestCompletionCallback callback1; - int rv = service.ResolveProxy( - GURL("http://request1"), net::LOAD_NORMAL, &info1, callback1.callback(), - NULL, NULL, BoundNetLog()); + int rv = + service.ResolveProxy(GURL("http://request1"), LOAD_NORMAL, &info1, + callback1.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // The first request should have triggered initial download of PAC script. @@ -3078,9 +3164,8 @@ // Start a second request. ProxyInfo info2; TestCompletionCallback callback2; - rv = service.ResolveProxy( - GURL("http://request2"), net::LOAD_NORMAL, &info2, callback2.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ResolveProxy(GURL("http://request2"), LOAD_NORMAL, &info2, + callback2.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(ERR_IO_PENDING, rv); // This request should have sent work to the resolver; complete it. @@ -3109,9 +3194,8 @@ // since the PAC script poller experienced a failure. ProxyInfo info3; TestCompletionCallback callback3; - rv = service.ResolveProxy( - GURL("http://request3"), net::LOAD_NORMAL, &info3, callback3.callback(), - NULL, NULL, BoundNetLog()); + rv = service.ResolveProxy(GURL("http://request3"), LOAD_NORMAL, &info3, + callback3.callback(), NULL, NULL, BoundNetLog()); EXPECT_EQ(OK, rv); EXPECT_TRUE(info3.is_direct()); } @@ -3134,7 +3218,7 @@ BoundTestNetLog log; bool synchronous_success = service.TryResolveProxySynchronously( - url, net::LOAD_NORMAL, &info, NULL, log.bound()); + url, LOAD_NORMAL, &info, NULL, log.bound()); EXPECT_FALSE(synchronous_success); // No request should have been queued. @@ -3163,7 +3247,7 @@ BoundTestNetLog log; bool synchronous_success = service.TryResolveProxySynchronously( - url, net::LOAD_NORMAL, &info, NULL, log.bound()); + url, LOAD_NORMAL, &info, NULL, log.bound()); EXPECT_TRUE(synchronous_success); EXPECT_FALSE(info.is_direct()); EXPECT_EQ("foopy1", info.proxy_server().host_port_pair().host());
diff --git a/net/quic/crypto/crypto_framer_test.cc b/net/quic/crypto/crypto_framer_test.cc index ce815a8..23846a6 100644 --- a/net/quic/crypto/crypto_framer_test.cc +++ b/net/quic/crypto/crypto_framer_test.cc
@@ -29,7 +29,7 @@ namespace test { -class TestCryptoVisitor : public ::net::CryptoFramerVisitorInterface { +class TestCryptoVisitor : public CryptoFramerVisitorInterface { public: TestCryptoVisitor() : error_count_(0) {}
diff --git a/net/quic/crypto/local_strike_register_client_test.cc b/net/quic/crypto/local_strike_register_client_test.cc index b713c10..5665cb6 100644 --- a/net/quic/crypto/local_strike_register_client_test.cc +++ b/net/quic/crypto/local_strike_register_client_test.cc
@@ -63,7 +63,7 @@ void SetUp() override { strike_register_.reset(new LocalStrikeRegisterClient( kMaxEntries, kCurrentTimeExternalSecs, kWindowSecs, kOrbit, - net::StrikeRegister::NO_STARTUP_PERIOD_NEEDED)); + StrikeRegister::NO_STARTUP_PERIOD_NEEDED)); } scoped_ptr<LocalStrikeRegisterClient> strike_register_;
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc index c20463d..386a52c 100644 --- a/net/quic/crypto/proof_verifier_chromium.cc +++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -223,15 +223,12 @@ next_state_ = STATE_VERIFY_CERT_COMPLETE; int flags = 0; - return verifier_->Verify( - cert_.get(), - hostname_, - flags, - SSLConfigService::GetCRLSet().get(), - &verify_details_->cert_verify_result, - base::Bind(&ProofVerifierChromium::Job::OnIOComplete, - base::Unretained(this)), - net_log_); + return verifier_->Verify(cert_.get(), hostname_, std::string(), flags, + SSLConfigService::GetCRLSet().get(), + &verify_details_->cert_verify_result, + base::Bind(&ProofVerifierChromium::Job::OnIOComplete, + base::Unretained(this)), + net_log_); } int ProofVerifierChromium::Job::DoVerifyCertComplete(int result) {
diff --git a/net/quic/crypto/strike_register_test.cc b/net/quic/crypto/strike_register_test.cc index 73a6b2f..b2a73c8 100644 --- a/net/quic/crypto/strike_register_test.cc +++ b/net/quic/crypto/strike_register_test.cc
@@ -11,10 +11,10 @@ #include "base/rand_util.h" #include "testing/gtest/include/gtest/gtest.h" +namespace net { + namespace { -using net::InsertStatus; -using net::StrikeRegister; using std::min; using std::pair; using std::set; @@ -40,9 +40,9 @@ StrikeRegister::DENY_REQUESTS_AT_STARTUP); uint8 nonce[32]; SetNonce(nonce, 999, kOrbit); - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); SetNonce(nonce, 1000, kOrbit); - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); EXPECT_EQ(0u, set.GetCurrentValidWindowSecs(1000 /* current time */)); EXPECT_EQ(0u, set.GetCurrentValidWindowSecs(1100 /* current time */)); @@ -60,8 +60,8 @@ StrikeRegister::NO_STARTUP_PERIOD_NEEDED); uint8 nonce[32]; SetNonce(nonce, 1000, kOrbit); - EXPECT_EQ(net::NONCE_OK, set.Insert(nonce, 1000)); - EXPECT_EQ(net::NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1000)); + EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1000)); + EXPECT_EQ(NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1000)); EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1000 /* current time */)); EXPECT_EQ(101u, set.GetCurrentValidWindowSecs(1050 /* current time */)); @@ -77,9 +77,9 @@ StrikeRegister::DENY_REQUESTS_AT_STARTUP); uint8 nonce[32]; SetNonce(nonce, 1101, kOrbit); - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1000)); SetNonce(nonce, 999, kOrbit); - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); } TEST(StrikeRegisterTest, BadOrbit) { @@ -90,7 +90,7 @@ uint8 nonce[32]; static const uint8 kBadOrbit[8] = { 0, 0, 0, 0, 1, 1, 1, 1 }; SetNonce(nonce, 1101, kBadOrbit); - EXPECT_EQ(net::NONCE_INVALID_ORBIT_FAILURE, set.Insert(nonce, 1100)); + EXPECT_EQ(NONCE_INVALID_ORBIT_FAILURE, set.Insert(nonce, 1100)); } TEST(StrikeRegisterTest, OneValue) { @@ -99,7 +99,7 @@ StrikeRegister::DENY_REQUESTS_AT_STARTUP); uint8 nonce[32]; SetNonce(nonce, 1101, kOrbit); - EXPECT_EQ(net::NONCE_OK, set.Insert(nonce, 1101)); + EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1101)); } TEST(StrikeRegisterTest, RejectDuplicate) { @@ -109,8 +109,8 @@ StrikeRegister::DENY_REQUESTS_AT_STARTUP); uint8 nonce[32]; SetNonce(nonce, 1101, kOrbit); - EXPECT_EQ(net::NONCE_OK, set.Insert(nonce, 1101)); - EXPECT_EQ(net::NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1101)); + EXPECT_EQ(NONCE_OK, set.Insert(nonce, 1101)); + EXPECT_EQ(NONCE_NOT_UNIQUE_FAILURE, set.Insert(nonce, 1101)); } TEST(StrikeRegisterTest, HorizonUpdating) { @@ -127,7 +127,7 @@ for (unsigned i = 0; i < 5; i++) { SetNonce(nonce[i], 1101 + i, kOrbit); nonce[i][31] = i; - EXPECT_EQ(net::NONCE_OK, set.Insert(nonce[i], 1100)); + EXPECT_EQ(NONCE_OK, set.Insert(nonce[i], 1100)); } // Valid window is still equal to |window_secs + 1|. @@ -136,34 +136,34 @@ // This should push the oldest value out and force the horizon to // be updated. SetNonce(nonce[5], 1110, kOrbit); - EXPECT_EQ(net::NONCE_OK, set.Insert(nonce[5], 1110)); + EXPECT_EQ(NONCE_OK, set.Insert(nonce[5], 1110)); // Effective horizon is computed based on the timestamp of the // value that was pushed out. EXPECT_EQ(9u, set.GetCurrentValidWindowSecs(1110)); SetNonce(nonce[5], 1111, kOrbit); - EXPECT_EQ(net::NONCE_OK, set.Insert(nonce[5], 1110)); + EXPECT_EQ(NONCE_OK, set.Insert(nonce[5], 1110)); EXPECT_EQ(8u, set.GetCurrentValidWindowSecs(1110)); // This should be behind the horizon now: SetNonce(nonce[5], 1101, kOrbit); nonce[5][31] = 10; - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110)); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110)); // Insert beyond the valid range. SetNonce(nonce[5], 1117, kOrbit); nonce[5][31] = 2; - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110)); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110)); // Insert at the upper valid range. SetNonce(nonce[5], 1116, kOrbit); nonce[5][31] = 1; - EXPECT_EQ(net::NONCE_OK, set.Insert(nonce[5], 1110)); + EXPECT_EQ(NONCE_OK, set.Insert(nonce[5], 1110)); // This should be beyond the upper valid range now: SetNonce(nonce[5], 1116, kOrbit); nonce[5][31] = 2; - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110)); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce[5], 1110)); } } @@ -177,7 +177,7 @@ for (unsigned i = 0; i < 100000; i++) { SetNonce(nonce, 1101 + i/500, kOrbit); memcpy(nonce + 12, &i, sizeof(i)); - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, set.Insert(nonce, 1100)); } } @@ -212,7 +212,7 @@ // Check to see if the orbit is correct. if (memcmp(nonce_bytes + 4, orbit_, sizeof(orbit_))) { - return net::NONCE_INVALID_ORBIT_FAILURE; + return NONCE_INVALID_ORBIT_FAILURE; } const uint32 nonce_time = ExternalTimeToInternal(TimeFromBytes(nonce_bytes)); @@ -221,14 +221,14 @@ // so we have to reject anything with a timestamp less than or // equal to that. if (nonce_time < horizon_) { - return net::NONCE_INVALID_TIME_FAILURE; + return NONCE_INVALID_TIME_FAILURE; } // Check that the timestamp is in the current window. if ((current_time > window_secs_ && nonce_time < (current_time - window_secs_)) || nonce_time > (current_time + window_secs_)) { - return net::NONCE_INVALID_TIME_FAILURE; + return NONCE_INVALID_TIME_FAILURE; } pair<uint32, string> nonce = std::make_pair( @@ -236,11 +236,11 @@ set<pair<uint32, string> >::const_iterator it = nonces_.find(nonce); if (it != nonces_.end()) { - return net::NONCE_NOT_UNIQUE_FAILURE; + return NONCE_NOT_UNIQUE_FAILURE; } nonces_.insert(nonce); - return net::NONCE_OK; + return NONCE_OK; } uint32 GetCurrentValidWindowSecs(const uint32 current_time_external) const { @@ -319,9 +319,9 @@ // Inserts succeed after the startup period. if (time > current_time + window) { - EXPECT_EQ(net::NONCE_OK, nonce_error1); + EXPECT_EQ(NONCE_OK, nonce_error1); } else { - EXPECT_EQ(net::NONCE_INVALID_TIME_FAILURE, nonce_error1); + EXPECT_EQ(NONCE_INVALID_TIME_FAILURE, nonce_error1); } EXPECT_EQ(s1->GetCurrentValidWindowSecs(time), s2->GetCurrentValidWindowSecs(time)); @@ -403,4 +403,6 @@ } } -} // anonymous namespace +} // namespace + +} // namespace net
diff --git a/net/quic/quic_default_packet_writer.cc b/net/quic/quic_default_packet_writer.cc index 177d292..aea9e9b 100644 --- a/net/quic/quic_default_packet_writer.cc +++ b/net/quic/quic_default_packet_writer.cc
@@ -27,8 +27,8 @@ WriteResult QuicDefaultPacketWriter::WritePacket( const char* buffer, size_t buf_len, - const net::IPAddressNumber& self_address, - const net::IPEndPoint& peer_address) { + const IPAddressNumber& self_address, + const IPEndPoint& peer_address) { scoped_refptr<StringIOBuffer> buf( new StringIOBuffer(std::string(buffer, buf_len))); DCHECK(!IsWriteBlocked());
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc index 1e948b8a..a07d32d 100644 --- a/net/quic/quic_end_to_end_unittest.cc +++ b/net/quic/quic_end_to_end_unittest.cc
@@ -31,12 +31,14 @@ #include "testing/platform_test.h" using base::StringPiece; -using net::tools::QuicInMemoryCache; -using net::tools::QuicServer; -using net::tools::test::QuicInMemoryCachePeer; -using net::tools::test::ServerThread; namespace net { + +using tools::QuicInMemoryCache; +using tools::QuicServer; +using tools::test::QuicInMemoryCachePeer; +using tools::test::ServerThread; + namespace test { namespace { @@ -127,8 +129,8 @@ // Starts the QUIC server listening on a random port. void StartServer() { - net::IPAddressNumber ip; - CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip)); + IPAddressNumber ip; + CHECK(ParseIPLiteralToNumber("127.0.0.1", &ip)); server_address_ = IPEndPoint(ip, 0); server_config_.SetInitialStreamFlowControlWindowToSend( kInitialStreamFlowControlWindowForTest);
diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc index 4c46574..ee588cb 100644 --- a/net/quic/quic_framer_test.cc +++ b/net/quic/quic_framer_test.cc
@@ -166,7 +166,7 @@ string ciphertext_; }; -class TestQuicVisitor : public ::net::QuicFramerVisitorInterface { +class TestQuicVisitor : public QuicFramerVisitorInterface { public: TestQuicVisitor() : error_count_(0),
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 67428f72d..f02d8118 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -19,6 +19,7 @@ #include "net/http/http_stream_factory.h" #include "net/http/http_transaction_test_util.h" #include "net/http/transport_security_state.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log_unittest.h" #include "net/log/test_net_log.h" #include "net/proxy/proxy_config_service_fixed.h" @@ -412,22 +413,20 @@ SendRequestAndExpectQuicResponse("hello!"); // Check that the NetLog was filled reasonably. - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log_.GetEntries(&entries); EXPECT_LT(0u, entries.size()); // Check that we logged a QUIC_SESSION_PACKET_RECEIVED. - int pos = net::ExpectLogContainsSomewhere( - entries, 0, - net::NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED, - net::NetLog::PHASE_NONE); + int pos = ExpectLogContainsSomewhere( + entries, 0, NetLog::TYPE_QUIC_SESSION_PACKET_RECEIVED, + NetLog::PHASE_NONE); EXPECT_LT(0, pos); // ... and also a TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED. - pos = net::ExpectLogContainsSomewhere( - entries, 0, - net::NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED, - net::NetLog::PHASE_NONE); + pos = ExpectLogContainsSomewhere( + entries, 0, NetLog::TYPE_QUIC_SESSION_PACKET_HEADER_RECEIVED, + NetLog::PHASE_NONE); EXPECT_LT(0, pos); std::string packet_sequence_number; @@ -436,10 +435,9 @@ EXPECT_EQ("1", packet_sequence_number); // ... and also a QUIC_SESSION_STREAM_FRAME_RECEIVED. - pos = net::ExpectLogContainsSomewhere( - entries, 0, - net::NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED, - net::NetLog::PHASE_NONE); + pos = ExpectLogContainsSomewhere( + entries, 0, NetLog::TYPE_QUIC_SESSION_STREAM_FRAME_RECEIVED, + NetLog::PHASE_NONE); EXPECT_LT(0, pos); int log_stream_id; @@ -665,7 +663,7 @@ // the alternate-protocol job will "win". AddHangingNonAlternateProtocolSocketData(); - params_.alternate_protocol_probability_threshold = .25; + params_.alternative_service_probability_threshold = .25; CreateSessionWithNextProtos(); SendRequestAndExpectHttpResponse("hello world"); @@ -686,7 +684,7 @@ socket_factory_.AddSocketDataProvider(&http_data); socket_factory_.AddSocketDataProvider(&http_data); - params_.alternate_protocol_probability_threshold = .75; + params_.alternative_service_probability_threshold = .75; CreateSessionWithNextProtos(); SendRequestAndExpectHttpResponse("hello world"); @@ -708,7 +706,7 @@ socket_factory_.AddSocketDataProvider(&http_data); socket_factory_.AddSocketDataProvider(&http_data); - params_.alternate_protocol_probability_threshold = .75; + params_.alternative_service_probability_threshold = .75; CreateSessionWithNextProtos(); SendRequestAndExpectHttpResponse("hello world");
diff --git a/net/quic/quic_utils_test.cc b/net/quic/quic_utils_test.cc index d2f2631..d741abb 100644 --- a/net/quic/quic_utils_test.cc +++ b/net/quic/quic_utils_test.cc
@@ -91,10 +91,10 @@ QuicTagVector parsed_options = QuicUtils::ParseQuicConnectionOptions( "PACE,TIMER,TBBR,REJ"); QuicTagVector expected_options; - expected_options.push_back(net::kPACE); - expected_options.push_back(net::kTIME); - expected_options.push_back(net::kTBBR); - expected_options.push_back(net::kREJ); + expected_options.push_back(kPACE); + expected_options.push_back(kTIME); + expected_options.push_back(kTBBR); + expected_options.push_back(kREJ); EXPECT_EQ(expected_options, parsed_options); }
diff --git a/net/sdch/sdch_owner.cc b/net/sdch/sdch_owner.cc index 948ee1f0..ac69f3d 100644 --- a/net/sdch/sdch_owner.cc +++ b/net/sdch/sdch_owner.cc
@@ -345,7 +345,7 @@ int use_count, const std::string& dictionary_text, const GURL& dictionary_url, - const net::BoundNetLog& net_log, + const BoundNetLog& net_log, bool was_from_cache) { struct DictionaryItem { base::Time last_used; @@ -411,9 +411,9 @@ if (total_dictionary_bytes_ + dictionary_text.size() - recoverable_bytes > max_total_dictionary_size_) { RecordDictionaryFate(DICTIONARY_FATE_FETCH_IGNORED_NO_SPACE); - net::SdchManager::SdchErrorRecovery(SDCH_DICTIONARY_NO_ROOM); - net_log.AddEvent(net::NetLog::TYPE_SDCH_DICTIONARY_ERROR, - base::Bind(&net::NetLogSdchDictionaryFetchProblemCallback, + SdchManager::SdchErrorRecovery(SDCH_DICTIONARY_NO_ROOM); + net_log.AddEvent(NetLog::TYPE_SDCH_DICTIONARY_ERROR, + base::Bind(&NetLogSdchDictionaryFetchProblemCallback, SDCH_DICTIONARY_NO_ROOM, dictionary_url, true)); return; } @@ -422,14 +422,14 @@ // dictionaries so that no state change will occur if dictionary addition // fails. std::string server_hash; - net::SdchProblemCode rv = manager_->AddSdchDictionary( + SdchProblemCode rv = manager_->AddSdchDictionary( dictionary_text, dictionary_url, &server_hash); - if (rv != net::SDCH_OK) { + if (rv != SDCH_OK) { RecordDictionaryFate(DICTIONARY_FATE_FETCH_MANAGER_REFUSED); - net::SdchManager::SdchErrorRecovery(rv); - net_log.AddEvent(net::NetLog::TYPE_SDCH_DICTIONARY_ERROR, - base::Bind(&net::NetLogSdchDictionaryFetchProblemCallback, - rv, dictionary_url, true)); + SdchManager::SdchErrorRecovery(rv); + net_log.AddEvent(NetLog::TYPE_SDCH_DICTIONARY_ERROR, + base::Bind(&NetLogSdchDictionaryFetchProblemCallback, rv, + dictionary_url, true)); return; } @@ -547,7 +547,7 @@ specific_dictionary_map->SetInteger(kDictionaryUseCountKey, use_count + 1); } -void SdchOwner::OnGetDictionary(net::SdchManager* manager, +void SdchOwner::OnGetDictionary(SdchManager* manager, const GURL& request_url, const GURL& dictionary_url) { #if defined(OS_CHROMEOS) @@ -590,7 +590,7 @@ base::Unretained(this), base::Time(), 0)); } -void SdchOwner::OnClearDictionaries(net::SdchManager* manager) { +void SdchOwner::OnClearDictionaries(SdchManager* manager) { total_dictionary_bytes_ = 0; fetcher_->Cancel();
diff --git a/net/sdch/sdch_owner.h b/net/sdch/sdch_owner.h index 053eecd..a600ac8e 100644 --- a/net/sdch/sdch_owner.h +++ b/net/sdch/sdch_owner.h
@@ -32,15 +32,14 @@ // exposes interface for setting SDCH policy. It should be instantiated by // the net/ embedder. // TODO(rdsmith): Implement dictionary prioritization. -class NET_EXPORT SdchOwner : public net::SdchObserver, - public PrefStore::Observer { +class NET_EXPORT SdchOwner : public SdchObserver, public PrefStore::Observer { public: static const size_t kMaxTotalDictionarySize; static const size_t kMinSpaceForDictionaryFetch; // Consumer must guarantee that |sdch_manager| and |context| outlive // this object. - SdchOwner(net::SdchManager* sdch_manager, net::URLRequestContext* context); + SdchOwner(SdchManager* sdch_manager, URLRequestContext* context); ~SdchOwner() override; // Enables use of pref persistence. Note that |pref_store| is owned @@ -59,10 +58,10 @@ // SdchObserver implementation. void OnDictionaryUsed(SdchManager* manager, const std::string& server_hash) override; - void OnGetDictionary(net::SdchManager* manager, + void OnGetDictionary(SdchManager* manager, const GURL& request_url, const GURL& dictionary_url) override; - void OnClearDictionaries(net::SdchManager* manager) override; + void OnClearDictionaries(SdchManager* manager) override; // PrefStore::Observer implementation. void OnPrefValueChanged(const std::string& key) override; @@ -76,7 +75,7 @@ int use_count, const std::string& dictionary_text, const GURL& dictionary_url, - const net::BoundNetLog& net_log, + const BoundNetLog& net_log, bool was_from_cache); void SetClockForTesting(scoped_ptr<base::Clock> clock); @@ -117,8 +116,8 @@ bool IsPersistingDictionaries() const; // For investigation of http://crbug.com/454198; remove when resolved. - base::WeakPtr<net::SdchManager> manager_; - scoped_ptr<net::SdchDictionaryFetcher> fetcher_; + base::WeakPtr<SdchManager> manager_; + scoped_ptr<SdchDictionaryFetcher> fetcher_; size_t total_dictionary_bytes_;
diff --git a/net/server/http_server_response_info.h b/net/server/http_server_response_info.h index bbb76d883..e583e0dd 100644 --- a/net/server/http_server_response_info.h +++ b/net/server/http_server_response_info.h
@@ -7,8 +7,8 @@ #include <string> #include <utility> -#include <vector> +#include "base/strings/string_split.h" #include "net/http/http_status_code.h" namespace net { @@ -37,7 +37,7 @@ const std::string& body() const; private: - typedef std::vector<std::pair<std::string, std::string> > Headers; + using Headers = base::StringPairs; HttpStatusCode status_code_; Headers headers_;
diff --git a/net/server/http_server_unittest.cc b/net/server/http_server_unittest.cc index 54af2a8..de0af80a 100644 --- a/net/server/http_server_unittest.cc +++ b/net/server/http_server_unittest.cc
@@ -99,7 +99,7 @@ int total_bytes_received = 0; message->clear(); while (total_bytes_received < expected_bytes) { - net::TestCompletionCallback callback; + TestCompletionCallback callback; ReadInternal(callback.callback()); int bytes_received = callback.WaitForResult(); if (bytes_received <= 0) @@ -145,7 +145,7 @@ Write(); } - void ReadInternal(const net::CompletionCallback& callback) { + void ReadInternal(const CompletionCallback& callback) { read_buffer_ = new IOBufferWithSize(kMaxExpectedResponseLength); int result = socket_->Read(read_buffer_.get(), kMaxExpectedResponseLength, callback); @@ -183,7 +183,7 @@ void SetUp() override { scoped_ptr<ServerSocket> server_socket( - new TCPServerSocket(NULL, net::NetLog::Source())); + new TCPServerSocket(NULL, NetLog::Source())); server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1); server_.reset(new HttpServer(server_socket.Pass(), this)); ASSERT_EQ(OK, server_->GetLocalAddress(&server_address_));
diff --git a/net/server/web_socket.cc b/net/server/web_socket.cc index e5d1cb7..2ddb03c 100644 --- a/net/server/web_socket.cc +++ b/net/server/web_socket.cc
@@ -40,12 +40,12 @@ return base::HostToNet32(static_cast<uint32>(number / spaces)); } -class WebSocketHixie76 : public net::WebSocket { +class WebSocketHixie76 : public WebSocket { public: - static net::WebSocket* Create(HttpServer* server, - HttpConnection* connection, - const HttpServerRequestInfo& request, - size_t* pos) { + static WebSocket* Create(HttpServer* server, + HttpConnection* connection, + const HttpServerRequestInfo& request, + size_t* pos) { if (connection->read_buf()->GetSize() < static_cast<int>(*pos + kWebSocketHandshakeBodyLen)) return NULL;
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index 2de67bd..f989a462 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -24,8 +24,10 @@ #include "net/base/request_priority.h" #include "net/base/test_completion_callback.h" #include "net/http/http_response_headers.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/socket_test_util.h" @@ -116,9 +118,8 @@ explicit MockClientSocket(net::NetLog* net_log) : connected_(false), has_unread_data_(false), - net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)), - was_used_to_convey_data_(false) { - } + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), + was_used_to_convey_data_(false) {} // Sets whether the socket has unread data. If true, the next call to Read() // will return 1 byte and IsConnectedAndIdle() will return false. @@ -295,8 +296,8 @@ int ConnectInternal() override { AddressList ignored; - client_socket_factory_->CreateTransportClientSocket( - ignored, NULL, net::NetLog::Source()); + client_socket_factory_->CreateTransportClientSocket(ignored, NULL, + NetLog::Source()); SetSocket( scoped_ptr<StreamSocket>(new MockClientSocket(net_log().net_log()))); switch (job_type_) { @@ -495,7 +496,7 @@ int RequestSocket(const std::string& group_name, const void* params, - net::RequestPriority priority, + RequestPriority priority, ClientSocketHandle* handle, const CompletionCallback& callback, const BoundNetLog& net_log) override { @@ -773,7 +774,7 @@ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); EXPECT_EQ(ERR_TIMED_OUT, delegate.WaitForResult()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(6u, entries.size()); @@ -815,7 +816,7 @@ handle.Reset(); TestLoadTimingInfoNotConnected(handle); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(4u, entries.size()); @@ -856,7 +857,7 @@ EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL); TestLoadTimingInfoNotConnected(handle); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(3u, entries.size()); @@ -1691,7 +1692,7 @@ handle.Reset(); TestLoadTimingInfoNotConnected(handle); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(4u, entries.size()); @@ -1731,7 +1732,7 @@ EXPECT_FALSE(handle.is_ssl_error()); EXPECT_TRUE(handle.ssl_error_response_info().headers.get() == NULL); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_EQ(3u, entries.size()); @@ -2245,7 +2246,7 @@ EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsEntryWithType( entries, 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET)); @@ -2327,7 +2328,7 @@ EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a")); EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a")); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_FALSE(LogContainsEntryWithType( entries, 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET)); @@ -2399,7 +2400,7 @@ EXPECT_EQ(OK, rv); EXPECT_TRUE(handle.is_reused()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsEntryWithType( entries, 1, NetLog::TYPE_SOCKET_POOL_REUSED_AN_EXISTING_SOCKET));
diff --git a/net/socket/next_proto.cc b/net/socket/next_proto.cc index 4632e97..cfc65782 100644 --- a/net/socket/next_proto.cc +++ b/net/socket/next_proto.cc
@@ -37,4 +37,9 @@ return next_protos; } +bool NextProtoIsSPDY(NextProto next_proto) { + return next_proto >= kProtoSPDYMinimumVersion && + next_proto <= kProtoSPDYMaximumVersion; +} + } // namespace net
diff --git a/net/socket/next_proto.h b/net/socket/next_proto.h index b4b1d72..72ee0bb 100644 --- a/net/socket/next_proto.h +++ b/net/socket/next_proto.h
@@ -57,6 +57,9 @@ NET_EXPORT NextProtoVector NextProtosWithSpdyAndQuic(bool spdy_enabled, bool quic_enabled); +// Returns true if |next_proto| is a version of SPDY or HTTP/2. +bool NextProtoIsSPDY(NextProto next_proto); + } // namespace net #endif // NET_SOCKET_NEXT_PROTO_H_
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc index b3f5040e..a4557a9 100644 --- a/net/socket/socket_test_util.cc +++ b/net/socket/socket_test_util.cc
@@ -284,8 +284,6 @@ SSLSocketDataProvider::SSLSocketDataProvider(IoMode mode, int result) : connect(mode, result), next_proto_status(SSLClientSocket::kNextProtoUnsupported), - was_npn_negotiated(false), - protocol_negotiated(kProtoUnknown), client_cert_sent(false), cert_request_info(NULL), channel_id_sent(false), @@ -300,9 +298,7 @@ } void SSLSocketDataProvider::SetNextProto(NextProto proto) { - was_npn_negotiated = true; next_proto_status = SSLClientSocket::kNextProtoNegotiated; - protocol_negotiated = proto; next_proto = SSLClientSocket::NextProtoToString(proto); } @@ -908,8 +904,8 @@ MockClientSocketFactory::CreateDatagramClientSocket( DatagramSocket::BindType bind_type, const RandIntCallback& rand_int_cb, - net::NetLog* net_log, - const net::NetLog::Source& source) { + NetLog* net_log, + const NetLog::Source& source) { SocketDataProvider* data_provider = mock_data_.GetNext(); scoped_ptr<MockUDPClientSocket> socket( new MockUDPClientSocket(data_provider, net_log)); @@ -921,8 +917,8 @@ scoped_ptr<StreamSocket> MockClientSocketFactory::CreateTransportClientSocket( const AddressList& addresses, - net::NetLog* net_log, - const net::NetLog::Source& source) { + NetLog* net_log, + const NetLog::Source& source) { SocketDataProvider* data_provider = mock_data_.GetNext(); scoped_ptr<MockTCPClientSocket> socket( new MockTCPClientSocket(addresses, net_log, data_provider)); @@ -1024,8 +1020,8 @@ return NULL; } -SSLClientSocket::NextProtoStatus -MockClientSocket::GetNextProto(std::string* proto) { +SSLClientSocket::NextProtoStatus MockClientSocket::GetNextProto( + std::string* proto) const { proto->clear(); return SSLClientSocket::kNextProtoUnsupported; } @@ -1048,7 +1044,7 @@ result)); } -void MockClientSocket::RunCallback(const net::CompletionCallback& callback, +void MockClientSocket::RunCallback(const CompletionCallback& callback, int result) { if (!callback.is_null()) callback.Run(result); @@ -1057,7 +1053,7 @@ MockTCPClientSocket::MockTCPClientSocket(const AddressList& addresses, net::NetLog* net_log, SocketDataProvider* data) - : MockClientSocket(BoundNetLog::Make(net_log, net::NetLog::SOURCE_NONE)), + : MockClientSocket(BoundNetLog::Make(net_log, NetLog::SOURCE_NONE)), addresses_(addresses), data_(data), read_offset_(0), @@ -1267,7 +1263,7 @@ } DeterministicSocketHelper::DeterministicSocketHelper( - net::NetLog* net_log, + NetLog* net_log, DeterministicSocketData* data) : write_pending_(false), write_result_(0), @@ -1278,7 +1274,7 @@ data_(data), was_used_to_convey_data_(false), peer_closed_connection_(false), - net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_NONE)) { + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_NONE)) { } DeterministicSocketHelper::~DeterministicSocketHelper() {} @@ -1469,7 +1465,7 @@ DeterministicMockTCPClientSocket::DeterministicMockTCPClientSocket( net::NetLog* net_log, DeterministicSocketData* data) - : MockClientSocket(BoundNetLog::Make(net_log, net::NetLog::SOURCE_NONE)), + : MockClientSocket(BoundNetLog::Make(net_log, NetLog::SOURCE_NONE)), helper_(net_log, data) { peer_addr_ = data->connect_data().peer_addr; } @@ -1581,11 +1577,7 @@ // tests. transport_socket->socket()->NetLog()), transport_(transport_socket.Pass()), - data_(data), - is_npn_state_set_(false), - new_npn_value_(false), - is_protocol_negotiated_set_(false), - protocol_negotiated_(kProtoUnknown) { + data_(data) { DCHECK(data_); peer_addr_ = data->connect.peer_addr; } @@ -1663,42 +1655,11 @@ } SSLClientSocket::NextProtoStatus MockSSLClientSocket::GetNextProto( - std::string* proto) { + std::string* proto) const { *proto = data_->next_proto; return data_->next_proto_status; } -bool MockSSLClientSocket::set_was_npn_negotiated(bool negotiated) { - is_npn_state_set_ = true; - return new_npn_value_ = negotiated; -} - -bool MockSSLClientSocket::WasNpnNegotiated() const { - if (is_npn_state_set_) - return new_npn_value_; - return data_->was_npn_negotiated; -} - -NextProto MockSSLClientSocket::GetNegotiatedProtocol() const { - if (is_protocol_negotiated_set_) - return protocol_negotiated_; - return data_->protocol_negotiated; -} - -void MockSSLClientSocket::set_protocol_negotiated( - NextProto protocol_negotiated) { - is_protocol_negotiated_set_ = true; - protocol_negotiated_ = protocol_negotiated; -} - -bool MockSSLClientSocket::WasChannelIDSent() const { - return data_->channel_id_sent; -} - -void MockSSLClientSocket::set_channel_id_sent(bool channel_id_sent) { - data_->channel_id_sent = channel_id_sent; -} - ChannelIDService* MockSSLClientSocket::GetChannelIDService() const { return data_->channel_id_service; } @@ -1725,7 +1686,7 @@ source_port_(123), pending_read_buf_(NULL), pending_read_buf_len_(0), - net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_NONE)), + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_NONE)), weak_factory_(this) { DCHECK(data_); data_->Reset(); @@ -1837,7 +1798,7 @@ // let CompleteRead() schedule a callback. read_data_.mode = SYNCHRONOUS; - net::CompletionCallback callback = pending_read_callback_; + CompletionCallback callback = pending_read_callback_; int rv = CompleteRead(); RunCallback(callback, rv); } @@ -2050,7 +2011,7 @@ last_request_priority_ = priority; scoped_ptr<StreamSocket> socket = client_socket_factory_->CreateTransportClientSocket( - AddressList(), net_log.net_log(), net::NetLog::Source()); + AddressList(), net_log.net_log(), NetLog::Source()); MockConnectJob* job = new MockConnectJob(socket.Pass(), handle, callback); job_list_.push_back(job); handle->set_pool_id(1); @@ -2105,7 +2066,7 @@ DeterministicMockClientSocketFactory::CreateDatagramClientSocket( DatagramSocket::BindType bind_type, const RandIntCallback& rand_int_cb, - net::NetLog* net_log, + NetLog* net_log, const NetLog::Source& source) { DeterministicSocketData* data_provider = mock_data().GetNext(); scoped_ptr<DeterministicMockUDPClientSocket> socket( @@ -2120,8 +2081,8 @@ scoped_ptr<StreamSocket> DeterministicMockClientSocketFactory::CreateTransportClientSocket( const AddressList& addresses, - net::NetLog* net_log, - const net::NetLog::Source& source) { + NetLog* net_log, + const NetLog::Source& source) { DeterministicSocketData* data_provider = mock_data().GetNext(); scoped_ptr<DeterministicMockTCPClientSocket> socket( new DeterministicMockTCPClientSocket(net_log, data_provider));
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index 4dad762..702ddb56 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -361,8 +361,6 @@ MockConnect connect; SSLClientSocket::NextProtoStatus next_proto_status; std::string next_proto; - bool was_npn_negotiated; - NextProto protocol_negotiated; NextProtoVector next_protos_expected_in_ssl_config; bool client_cert_sent; SSLCertRequestInfo* cert_request_info; @@ -790,7 +788,7 @@ unsigned char* out, unsigned int outlen) override; int GetTLSUniqueChannelBinding(std::string* out) override; - NextProtoStatus GetNextProto(std::string* proto) override; + NextProtoStatus GetNextProto(std::string* proto) const override; ChannelIDService* GetChannelIDService() const override; protected: @@ -875,15 +873,14 @@ }; // DeterministicSocketHelper is a helper class that can be used -// to simulate net::Socket::Read() and net::Socket::Write() +// to simulate Socket::Read() and Socket::Write() // using deterministic |data|. // Note: This is provided as a common helper class because // of the inheritance hierarchy of DeterministicMock[UDP,TCP]ClientSocket and a // desire not to introduce an additional common base class. class DeterministicSocketHelper { public: - DeterministicSocketHelper(net::NetLog* net_log, - DeterministicSocketData* data); + DeterministicSocketHelper(NetLog* net_log, DeterministicSocketData* data); virtual ~DeterministicSocketHelper(); bool write_pending() const { return write_pending_; } @@ -1041,23 +1038,17 @@ bool WasEverUsed() const override; bool UsingTCPFastOpen() const override; int GetPeerAddress(IPEndPoint* address) const override; - bool WasNpnNegotiated() const override; bool GetSSLInfo(SSLInfo* ssl_info) override; // SSLClientSocket implementation. void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; - NextProtoStatus GetNextProto(std::string* proto) override; - bool set_was_npn_negotiated(bool negotiated) override; - void set_protocol_negotiated(NextProto protocol_negotiated) override; - NextProto GetNegotiatedProtocol() const override; + NextProtoStatus GetNextProto(std::string* proto) const override; // This MockSocket does not implement the manual async IO feature. void OnReadComplete(const MockRead& data) override; void OnWriteComplete(int rv) override; void OnConnectComplete(const MockConnect& data) override; - bool WasChannelIDSent() const override; - void set_channel_id_sent(bool channel_id_sent) override; ChannelIDService* GetChannelIDService() const override; private: @@ -1067,10 +1058,6 @@ scoped_ptr<ClientSocketHandle> transport_; SSLSocketDataProvider* data_; - bool is_npn_state_set_; - bool new_npn_value_; - bool is_protocol_negotiated_set_; - NextProto protocol_negotiated_; DISALLOW_COPY_AND_ASSIGN(MockSSLClientSocket); }; @@ -1143,7 +1130,7 @@ ClientSocketHandle* handle() { return &handle_; } - const net::CompletionCallback& callback() const { return callback_; } + const CompletionCallback& callback() const { return callback_; } private: void OnComplete(int result);
diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc index 4ee9681a18..775ba8c 100644 --- a/net/socket/socks5_client_socket_unittest.cc +++ b/net/socket/socks5_client_socket_unittest.cc
@@ -13,8 +13,10 @@ #include "net/base/test_completion_callback.h" #include "net/base/winsock_init.h" #include "net/dns/mock_host_resolver.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/client_socket_factory.h" #include "net/socket/socket_test_util.h" #include "net/socket/tcp_client_socket.h" @@ -146,7 +148,7 @@ EXPECT_EQ(ERR_IO_PENDING, rv); EXPECT_FALSE(user_sock_->IsConnected()); - TestNetLog::CapturedEntryList net_log_entries; + CapturedNetLogEntry::List net_log_entries; net_log_.GetEntries(&net_log_entries); EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0, NetLog::TYPE_SOCKS5_CONNECT)); @@ -270,7 +272,7 @@ int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList net_log_entries; + CapturedNetLogEntry::List net_log_entries; net_log_.GetEntries(&net_log_entries); EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0, NetLog::TYPE_SOCKS5_CONNECT)); @@ -301,7 +303,7 @@ int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList net_log_entries; + CapturedNetLogEntry::List net_log_entries; net_log_.GetEntries(&net_log_entries); EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0, NetLog::TYPE_SOCKS5_CONNECT)); @@ -330,7 +332,7 @@ hostname, 80, &net_log_); int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList net_log_entries; + CapturedNetLogEntry::List net_log_entries; net_log_.GetEntries(&net_log_entries); EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0, NetLog::TYPE_SOCKS5_CONNECT)); @@ -361,7 +363,7 @@ hostname, 80, &net_log_); int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList net_log_entries; + CapturedNetLogEntry::List net_log_entries; net_log_.GetEntries(&net_log_entries); EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0, NetLog::TYPE_SOCKS5_CONNECT));
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc index ea7f82eb..7f8e7d4 100644 --- a/net/socket/socks_client_socket_unittest.cc +++ b/net/socket/socks_client_socket_unittest.cc
@@ -10,8 +10,10 @@ #include "net/base/winsock_init.h" #include "net/dns/host_resolver.h" #include "net/dns/mock_host_resolver.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/client_socket_factory.h" #include "net/socket/socket_test_util.h" #include "net/socket/tcp_client_socket.h" @@ -159,7 +161,7 @@ int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE( LogContainsBeginEvent(entries, 0, NetLog::TYPE_SOCKS_CONNECT)); @@ -231,7 +233,7 @@ int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent( entries, 0, NetLog::TYPE_SOCKS_CONNECT)); @@ -267,7 +269,7 @@ int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent( entries, 0, NetLog::TYPE_SOCKS_CONNECT)); @@ -305,7 +307,7 @@ int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent( entries, 0, NetLog::TYPE_SOCKS_CONNECT)); @@ -337,7 +339,7 @@ int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent( entries, 0, NetLog::TYPE_SOCKS_CONNECT)); @@ -367,7 +369,7 @@ int rv = user_sock_->Connect(callback_.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent( entries, 0, NetLog::TYPE_SOCKS_CONNECT));
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc index f333cb8e..4dd6a4e 100644 --- a/net/socket/ssl_client_socket.cc +++ b/net/socket/ssl_client_socket.cc
@@ -18,11 +18,7 @@ namespace net { SSLClientSocket::SSLClientSocket() - : was_npn_negotiated_(false), - was_spdy_negotiated_(false), - protocol_negotiated_(kProtoUnknown), - channel_id_sent_(false), - signed_cert_timestamps_received_(false), + : signed_cert_timestamps_received_(false), stapled_ocsp_response_received_(false), negotiation_extension_(kExtensionUnknown) { } @@ -91,11 +87,15 @@ } bool SSLClientSocket::WasNpnNegotiated() const { - return was_npn_negotiated_; + std::string unused_proto; + return GetNextProto(&unused_proto) == kNextProtoNegotiated; } NextProto SSLClientSocket::GetNegotiatedProtocol() const { - return protocol_negotiated_; + std::string proto; + if (GetNextProto(&proto) != kNextProtoNegotiated) + return kProtoUnknown; + return NextProtoFromString(proto); } bool SSLClientSocket::IgnoreCertError(int error, int load_flags) { @@ -105,43 +105,30 @@ IsCertificateError(error); } -bool SSLClientSocket::set_was_npn_negotiated(bool negotiated) { - return was_npn_negotiated_ = negotiated; -} - -bool SSLClientSocket::was_spdy_negotiated() const { - return was_spdy_negotiated_; -} - -bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated) { - return was_spdy_negotiated_ = negotiated; -} - -void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated) { - protocol_negotiated_ = protocol_negotiated; -} - -void SSLClientSocket::set_negotiation_extension( - SSLNegotiationExtension negotiation_extension) { - negotiation_extension_ = negotiation_extension; -} - -bool SSLClientSocket::WasChannelIDSent() const { - return channel_id_sent_; -} - -void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) { - channel_id_sent_ = channel_id_sent; -} - -void SSLClientSocket::set_signed_cert_timestamps_received( - bool signed_cert_timestamps_received) { - signed_cert_timestamps_received_ = signed_cert_timestamps_received; -} - -void SSLClientSocket::set_stapled_ocsp_response_received( - bool stapled_ocsp_response_received) { - stapled_ocsp_response_received_ = stapled_ocsp_response_received; +void SSLClientSocket::RecordNegotiationExtension() { + if (negotiation_extension_ == kExtensionUnknown) + return; + std::string proto; + SSLClientSocket::NextProtoStatus status = GetNextProto(&proto); + if (status == kNextProtoUnsupported) + return; + // Convert protocol into numerical value for histogram. + NextProto protocol_negotiated = SSLClientSocket::NextProtoFromString(proto); + base::HistogramBase::Sample sample = + static_cast<base::HistogramBase::Sample>(protocol_negotiated); + // In addition to the protocol negotiated, we want to record which TLS + // extension was used, and in case of NPN, whether there was overlap between + // server and client list of supported protocols. + if (negotiation_extension_ == kExtensionNPN) { + if (status == kNextProtoNoOverlap) { + sample += 1000; + } else { + sample += 500; + } + } else { + DCHECK_EQ(kExtensionALPN, negotiation_extension_); + } + UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLProtocolNegotiation", sample); } // static @@ -242,30 +229,4 @@ return wire_protos; } -void SSLClientSocket::RecordNegotiationExtension() { - if (negotiation_extension_ == kExtensionUnknown) - return; - std::string proto; - SSLClientSocket::NextProtoStatus status = GetNextProto(&proto); - if (status == kNextProtoUnsupported) - return; - // Convert protocol into numerical value for histogram. - NextProto protocol_negotiated = SSLClientSocket::NextProtoFromString(proto); - base::HistogramBase::Sample sample = - static_cast<base::HistogramBase::Sample>(protocol_negotiated); - // In addition to the protocol negotiated, we want to record which TLS - // extension was used, and in case of NPN, whether there was overlap between - // server and client list of supported protocols. - if (negotiation_extension_ == kExtensionNPN) { - if (status == kNextProtoNoOverlap) { - sample += 1000; - } else { - sample += 500; - } - } else { - DCHECK_EQ(kExtensionALPN, negotiation_extension_); - } - UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLProtocolNegotiation", sample); -} - } // namespace net
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h index 357f0d3..cb5e5fbe 100644 --- a/net/socket/ssl_client_socket.h +++ b/net/socket/ssl_client_socket.h
@@ -105,7 +105,7 @@ // kNextProtoNegotiated: *proto is set to the negotiated protocol. // kNextProtoNoOverlap: *proto is set to the first protocol in the // supported list. - virtual NextProtoStatus GetNextProto(std::string* proto) = 0; + virtual NextProtoStatus GetNextProto(std::string* proto) const = 0; static NextProto NextProtoFromString(const std::string& proto_string); @@ -125,41 +125,29 @@ // cryptographic implementation. static uint16 GetMaxSupportedSSLVersion(); - virtual bool set_was_npn_negotiated(bool negotiated); - - virtual bool was_spdy_negotiated() const; - - virtual bool set_was_spdy_negotiated(bool negotiated); - - virtual void set_protocol_negotiated(NextProto protocol_negotiated); - - void set_negotiation_extension(SSLNegotiationExtension negotiation_extension); - // Returns the ChannelIDService used by this socket, or NULL if // channel ids are not supported. virtual ChannelIDService* GetChannelIDService() const = 0; - // Returns true if a channel ID was sent on this connection. - // This may be useful for protocols, like SPDY, which allow the same - // connection to be shared between multiple domains, each of which need - // a channel ID. - // - // Public for ssl_client_socket_openssl_unittest.cc. - virtual bool WasChannelIDSent() const; + protected: + void set_negotiation_extension( + SSLNegotiationExtension negotiation_extension) { + negotiation_extension_ = negotiation_extension; + } + + void set_signed_cert_timestamps_received( + bool signed_cert_timestamps_received) { + signed_cert_timestamps_received_ = signed_cert_timestamps_received; + } + + void set_stapled_ocsp_response_received(bool stapled_ocsp_response_received) { + stapled_ocsp_response_received_ = stapled_ocsp_response_received; + } // Record which TLS extension was used to negotiate protocol and protocol // chosen in a UMA histogram. void RecordNegotiationExtension(); - protected: - virtual void set_channel_id_sent(bool channel_id_sent); - - virtual void set_signed_cert_timestamps_received( - bool signed_cert_timestamps_received); - - virtual void set_stapled_ocsp_response_received( - bool stapled_ocsp_response_received); - // Records histograms for channel id support during full handshakes - resumed // handshakes are ignored. static void RecordChannelIDSupport( @@ -210,14 +198,6 @@ FRIEND_TEST_ALL_PREFIXES(SSLClientSocketTest, VerifyServerChainProperlyOrdered); - // True if NPN was responded to, independent of selecting SPDY or HTTP. - bool was_npn_negotiated_; - // True if NPN successfully negotiated SPDY. - bool was_spdy_negotiated_; - // Protocol that we negotiated with the server. - NextProto protocol_negotiated_; - // True if a channel ID was sent. - bool channel_id_sent_; // True if SCTs were received via a TLS extension. bool signed_cert_timestamps_received_; // True if a stapled OCSP response was received.
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 16641f9..bb92343 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc
@@ -69,7 +69,6 @@ #include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/logging.h" -#include "base/memory/singleton.h" #include "base/metrics/histogram.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" @@ -159,57 +158,6 @@ // overlap with any value of the net::Error range, including net::OK). const int kNoPendingReadResult = 1; -#if defined(USE_NSS_CERTS) -typedef SECStatus -(*CacheOCSPResponseFromSideChannelFunction)( - CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time, - SECItem *encodedResponse, void *pwArg); - -// On Linux, we dynamically link against the system version of libnss3.so. In -// order to continue working on systems without up-to-date versions of NSS we -// lookup CERT_CacheOCSPResponseFromSideChannel with dlsym. - -// RuntimeLibNSSFunctionPointers is a singleton which caches the results of any -// runtime symbol resolution that we need. -class RuntimeLibNSSFunctionPointers { - public: - CacheOCSPResponseFromSideChannelFunction - GetCacheOCSPResponseFromSideChannelFunction() { - return cache_ocsp_response_from_side_channel_; - } - - static RuntimeLibNSSFunctionPointers* GetInstance() { - return Singleton<RuntimeLibNSSFunctionPointers>::get(); - } - - private: - friend struct DefaultSingletonTraits<RuntimeLibNSSFunctionPointers>; - - RuntimeLibNSSFunctionPointers() { - cache_ocsp_response_from_side_channel_ = - (CacheOCSPResponseFromSideChannelFunction) - dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel"); - } - - CacheOCSPResponseFromSideChannelFunction - cache_ocsp_response_from_side_channel_; -}; - -CacheOCSPResponseFromSideChannelFunction -GetCacheOCSPResponseFromSideChannelFunction() { - return RuntimeLibNSSFunctionPointers::GetInstance() - ->GetCacheOCSPResponseFromSideChannelFunction(); -} - -bool IsOCSPStaplingSupported() { - return GetCacheOCSPResponseFromSideChannelFunction() != NULL; -} -#else -bool IsOCSPStaplingSupported() { - return false; -} -#endif - // Helper functions to make it possible to log events from within the // SSLClientSocketNSS::Core. void AddLogEvent(const base::WeakPtr<BoundNetLog>& net_log, @@ -2069,18 +2017,6 @@ nss_handshake_state_.stapled_ocsp_response = std::string( reinterpret_cast<char*>(ocsp_responses->items[0].data), ocsp_responses->items[0].len); - - if (IsOCSPStaplingSupported()) { -#if defined(USE_NSS_CERTS) - CacheOCSPResponseFromSideChannelFunction cache_ocsp_response = - GetCacheOCSPResponseFromSideChannelFunction(); - - cache_ocsp_response( - CERT_GetDefaultCertDB(), - nss_handshake_state_.server_cert_chain[0], PR_Now(), - &ocsp_responses->items[0], NULL); -#endif - } } void SSLClientSocketNSS::Core::UpdateConnectionStatus() { @@ -2444,6 +2380,8 @@ transport_security_state_(context.transport_security_state), policy_enforcer_(context.cert_policy_enforcer), valid_thread_id_(base::kInvalidThreadId) { + DCHECK(cert_verifier_); + EnterFunction(""); InitCore(); LeaveFunction(""); @@ -2499,7 +2437,7 @@ server_cert_verify_result_.is_issued_by_known_root; ssl_info->client_cert_sent = ssl_config_.send_client_cert && ssl_config_.client_cert.get(); - ssl_info->channel_id_sent = WasChannelIDSent(); + ssl_info->channel_id_sent = core_->state().channel_id_sent; ssl_info->pinning_failure_log = pinning_failure_log_; PRUint16 cipher_suite = SSLConnectionStatusToCipherSuite( @@ -2567,8 +2505,8 @@ return OK; } -SSLClientSocket::NextProtoStatus -SSLClientSocketNSS::GetNextProto(std::string* proto) { +SSLClientSocket::NextProtoStatus SSLClientSocketNSS::GetNextProto( + std::string* proto) const { *proto = core_->state().next_proto; return core_->state().next_proto_status; } @@ -2875,8 +2813,8 @@ // Request OCSP stapling even on platforms that don't support it, in // order to extract Certificate Transparency information. rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, - (IsOCSPStaplingSupported() || - ssl_config_.signed_cert_timestamps_enabled)); + cert_verifier_->SupportsOCSPStapling() || + ssl_config_.signed_cert_timestamps_enabled); if (rv != SECSuccess) { LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_OCSP_STAPLING"); @@ -3046,11 +2984,12 @@ return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION; } + RecordNegotiationExtension(); + // SSL handshake is completed. Let's verify the certificate. GotoState(STATE_VERIFY_CERT); // Done! } - set_channel_id_sent(core_->state().channel_id_sent); set_signed_cert_timestamps_received( !core_->state().sct_list_from_tls_extension.empty()); set_stapled_ocsp_response_received( @@ -3104,11 +3043,9 @@ flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS; verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); return verifier_->Verify( - core_->state().server_cert.get(), - host_and_port_.host(), - flags, - SSLConfigService::GetCRLSet().get(), - &server_cert_verify_result_, + core_->state().server_cert.get(), host_and_port_.host(), + core_->state().stapled_ocsp_response, flags, + SSLConfigService::GetCRLSet().get(), &server_cert_verify_result_, base::Bind(&SSLClientSocketNSS::OnHandshakeIOComplete, base::Unretained(this)), net_log_);
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h index a4964d3..e348ebc9 100644 --- a/net/socket/ssl_client_socket_nss.h +++ b/net/socket/ssl_client_socket_nss.h
@@ -69,7 +69,7 @@ // SSLClientSocket implementation. void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; - NextProtoStatus GetNextProto(std::string* proto) override; + NextProtoStatus GetNextProto(std::string* proto) const override; // SSLSocket implementation. int ExportKeyingMaterial(const base::StringPiece& label,
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index 7b11ddc..d5391eb3 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc
@@ -145,19 +145,6 @@ return 1; } -bool IsOCSPStaplingSupported() { -#if defined(OS_WIN) - // CERT_OCSP_RESPONSE_PROP_ID is only implemented on Vista+, but it can be - // set on Windows XP without error. There is some overhead from the server - // sending the OCSP response if it supports the extension, for the subset of - // XP clients who will request it but be unable to use it, but this is an - // acceptable trade-off for simplicity of implementation. - return true; -#else - return false; -#endif -} - } // namespace class SSLClientSocketOpenSSL::SSLContext { @@ -382,13 +369,14 @@ ssl_session_cache_shard_(context.ssl_session_cache_shard), next_handshake_state_(STATE_NONE), npn_status_(kNextProtoUnsupported), - channel_id_xtn_negotiated_(false), + channel_id_sent_(false), handshake_completed_(false), certificate_verified_(false), transport_security_state_(context.transport_security_state), policy_enforcer_(context.cert_policy_enforcer), net_log_(transport_->socket()->NetLog()), weak_factory_(this) { + DCHECK(cert_verifier_); } SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { @@ -403,7 +391,7 @@ } SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( - std::string* proto) { + std::string* proto) const { *proto = npn_proto_; return npn_status_; } @@ -517,7 +505,7 @@ npn_status_ = kNextProtoUnsupported; npn_proto_.clear(); - channel_id_xtn_negotiated_ = false; + channel_id_sent_ = false; channel_id_request_handle_.Cancel(); } @@ -606,7 +594,7 @@ server_cert_verify_result_.public_key_hashes; ssl_info->client_cert_sent = ssl_config_.send_client_cert && ssl_config_.client_cert.get(); - ssl_info->channel_id_sent = WasChannelIDSent(); + ssl_info->channel_id_sent = channel_id_sent_; ssl_info->pinning_failure_log = pinning_failure_log_; AddSCTInfoToSSLInfo(ssl_info); @@ -846,7 +834,7 @@ SSL_enable_ocsp_stapling(ssl_); } - if (IsOCSPStaplingSupported()) + if (cert_verifier_->SupportsOCSPStapling()) SSL_enable_ocsp_stapling(ssl_); // Enable fastradio padding. @@ -939,14 +927,14 @@ } } - RecordChannelIDSupport(channel_id_service_, - channel_id_xtn_negotiated_, + RecordNegotiationExtension(); + RecordChannelIDSupport(channel_id_service_, channel_id_sent_, ssl_config_.channel_id_enabled, crypto::ECPrivateKey::IsSupported()); // Only record OCSP histograms if OCSP was requested. if (ssl_config_.signed_cert_timestamps_enabled || - IsOCSPStaplingSupported()) { + cert_verifier_->SupportsOCSPStapling()) { const uint8_t* ocsp_response; size_t ocsp_response_len; SSL_get0_ocsp_response(ssl_, &ocsp_response, &ocsp_response_len); @@ -972,7 +960,6 @@ if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) { // The server supports channel ID. Stop to look one up before returning to // the handshake. - channel_id_xtn_negotiated_ = true; GotoState(STATE_CHANNEL_ID_LOOKUP); return OK; } @@ -1042,7 +1029,7 @@ } // Return to the handshake. - set_channel_id_sent(true); + channel_id_sent_ = true; net_log_.AddEvent(NetLog::TYPE_SSL_CHANNEL_ID_PROVIDED); GotoState(STATE_HANDSHAKE); return OK; @@ -1079,6 +1066,15 @@ return ERR_CERT_INVALID; } + std::string ocsp_response; + if (cert_verifier_->SupportsOCSPStapling()) { + const uint8_t* ocsp_response_raw; + size_t ocsp_response_len; + SSL_get0_ocsp_response(ssl_, &ocsp_response_raw, &ocsp_response_len); + ocsp_response.assign(reinterpret_cast<const char*>(ocsp_response_raw), + ocsp_response_len); + } + start_cert_verification_time_ = base::TimeTicks::Now(); int flags = 0; @@ -1092,13 +1088,10 @@ flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS; verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); return verifier_->Verify( - server_cert_.get(), - host_and_port_.host(), - flags, + server_cert_.get(), host_and_port_.host(), ocsp_response, flags, // TODO(davidben): Route the CRLSet through SSLConfig so // SSLClientSocket doesn't depend on SSLConfigService. - SSLConfigService::GetCRLSet().get(), - &server_cert_verify_result_, + SSLConfigService::GetCRLSet().get(), &server_cert_verify_result_, base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete, base::Unretained(this)), net_log_); @@ -1174,33 +1167,6 @@ NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, base::Bind(&NetLogX509CertificateCallback, base::Unretained(server_cert_.get()))); - - // TODO(rsleevi): Plumb an OCSP response into the Mac system library and - // update IsOCSPStaplingSupported for Mac. https://crbug.com/430714 - if (IsOCSPStaplingSupported()) { -#if defined(OS_WIN) - const uint8_t* ocsp_response_raw; - size_t ocsp_response_len; - SSL_get0_ocsp_response(ssl_, &ocsp_response_raw, &ocsp_response_len); - - CRYPT_DATA_BLOB ocsp_response_blob; - ocsp_response_blob.cbData = ocsp_response_len; - ocsp_response_blob.pbData = const_cast<BYTE*>(ocsp_response_raw); - BOOL ok = CertSetCertificateContextProperty( - server_cert_->os_cert_handle(), - CERT_OCSP_RESPONSE_PROP_ID, - CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, - &ocsp_response_blob); - if (!ok) { - VLOG(1) << "Failed to set OCSP response property: " - << GetLastError(); - } -#else - // TODO(davidben): Support OCSP stapling when NSS is the system - // certificate verifier. https://crbug.com/479034. - NOTREACHED(); -#endif - } } }
diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h index dc9c7e90..29833b9 100644 --- a/net/socket/ssl_client_socket_openssl.h +++ b/net/socket/ssl_client_socket_openssl.h
@@ -61,7 +61,7 @@ // SSLClientSocket implementation. void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info) override; - NextProtoStatus GetNextProto(std::string* proto) override; + NextProtoStatus GetNextProto(std::string* proto) const override; ChannelIDService* GetChannelIDService() const override; // SSLSocket implementation. @@ -290,8 +290,8 @@ // Written by the |channel_id_service_|. std::string channel_id_private_key_; std::string channel_id_cert_; - // True if channel ID extension was negotiated. - bool channel_id_xtn_negotiated_; + // True if a channel ID was sent. + bool channel_id_sent_; // True if the initial handshake has completed. bool handshake_completed_; // True if the initial handshake's certificate has been verified.
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc index e6c770c..3426622 100644 --- a/net/socket/ssl_client_socket_pool.cc +++ b/net/socket/ssl_client_socket_pool.cc
@@ -329,33 +329,11 @@ connect_timing_.ssl_end = base::TimeTicks::Now(); - SSLClientSocket::NextProtoStatus status = - SSLClientSocket::kNextProtoUnsupported; - std::string proto; - // GetNextProto will fail and and trigger a NOTREACHED if we pass in a socket - // that hasn't had SSL_ImportFD called on it. If we get a certificate error - // here, then we know that we called SSL_ImportFD. - if (result == OK || IsCertificateError(result)) { - status = ssl_socket_->GetNextProto(&proto); - ssl_socket_->RecordNegotiationExtension(); - } - - // If we want spdy over npn, make sure it succeeded. - if (status == SSLClientSocket::kNextProtoNegotiated) { - ssl_socket_->set_was_npn_negotiated(true); - NextProto protocol_negotiated = - SSLClientSocket::NextProtoFromString(proto); - ssl_socket_->set_protocol_negotiated(protocol_negotiated); - // If we negotiated a SPDY version, it must have been present in - // SSLConfig::next_protos. - // TODO(mbelshe): Verify this. - if (protocol_negotiated >= kProtoSPDYMinimumVersion && - protocol_negotiated <= kProtoSPDYMaximumVersion) { - ssl_socket_->set_was_spdy_negotiated(true); - } - } - if (params_->want_spdy_over_npn() && !ssl_socket_->was_spdy_negotiated()) + // If we want SPDY over ALPN/NPN, make sure it succeeded. + if (params_->want_spdy_over_npn() && + !NextProtoIsSPDY(ssl_socket_->GetNegotiatedProtocol())) { return ERR_NPN_NEGOTIATION_FAILED; + } if (result == OK || ssl_socket_->IgnoreCertError(result, params_->load_flags())) {
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index 9267abd5..9b90ae8 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -19,8 +19,10 @@ #include "net/cert/test_root_certs.h" #include "net/dns/host_resolver.h" #include "net/http/transport_security_state.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/socket_test_util.h" @@ -969,9 +971,8 @@ // they'll give up waiting for application data and send the Finished after a // timeout. This means that an SSL connect end event may appear as a socket // write. -static bool LogContainsSSLConnectEndEvent( - const TestNetLog::CapturedEntryList& log, - int i) { +static bool LogContainsSSLConnectEndEvent(const CapturedNetLogEntry::List& log, + int i) { return LogContainsEndEvent(log, i, NetLog::TYPE_SSL_CONNECT) || LogContainsEvent( log, i, NetLog::TYPE_SOCKET_BYTES_SENT, NetLog::PHASE_NONE); @@ -1014,7 +1015,7 @@ rv = sock->Connect(callback.callback()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); if (rv == ERR_IO_PENDING) @@ -1056,7 +1057,7 @@ rv = sock->Connect(callback.callback()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); if (rv == ERR_IO_PENDING) @@ -1100,7 +1101,7 @@ rv = sock->Connect(callback.callback()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); if (rv == ERR_IO_PENDING) @@ -1144,7 +1145,7 @@ rv = sock->Connect(callback.callback()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); if (rv == ERR_IO_PENDING) @@ -1209,7 +1210,7 @@ // TODO(davidben): Add a test which requires them and verify the error. rv = sock->Connect(callback.callback()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); if (rv == ERR_IO_PENDING) @@ -2136,7 +2137,7 @@ rv = callback.WaitForResult(); EXPECT_EQ(static_cast<int>(arraysize(request_text) - 1), rv); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); size_t last_index = ExpectLogContainsSomewhereAfter( entries, 5, NetLog::TYPE_SSL_SOCKET_BYTES_SENT, NetLog::PHASE_NONE); @@ -2248,7 +2249,7 @@ EXPECT_FALSE(sock->IsConnected()); rv = sock->Connect(callback.callback()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); @@ -2542,7 +2543,7 @@ EXPECT_FALSE(sock->IsConnected()); rv = sock->Connect(callback.callback()); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_TRUE(LogContainsBeginEvent(entries, 5, NetLog::TYPE_SSL_CONNECT)); if (rv == ERR_IO_PENDING) @@ -3391,7 +3392,9 @@ EXPECT_EQ(OK, rv); EXPECT_TRUE(sock_->IsConnected()); - EXPECT_TRUE(sock_->WasChannelIDSent()); + SSLInfo ssl_info; + ASSERT_TRUE(sock_->GetSSLInfo(&ssl_info)); + EXPECT_TRUE(ssl_info.channel_id_sent); sock_->Disconnect(); EXPECT_FALSE(sock_->IsConnected());
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc index a7cc7d8..2620eba 100644 --- a/net/socket/tcp_socket_win.cc +++ b/net/socket/tcp_socket_win.cc
@@ -801,25 +801,30 @@ result = connect(socket_, storage.addr, storage.addr_len); } - // The MSDN page for connect says: - // With a nonblocking socket, the connection attempt cannot be completed - // immediately. In this case, connect will return SOCKET_ERROR, and - // WSAGetLastError will return WSAEWOULDBLOCK. - // which implies that for a nonblocking socket, connect never returns 0. - // It's not clear what the correct thing to do is if connect() - // returns 0. It's not clear whether this ever happens in practice. - // This CHECK() is here to verify that it doesn't. - // TODO(ricea): If the CHECK() fires in canary or dev, revert this - // CL. If it doesn't, reconsider what we want to do here long-term. - CHECK(result); + if (!result) { + // Connected without waiting! + // + // The MSDN page for connect says: + // With a nonblocking socket, the connection attempt cannot be completed + // immediately. In this case, connect will return SOCKET_ERROR, and + // WSAGetLastError will return WSAEWOULDBLOCK. + // which implies that for a nonblocking socket, connect never returns 0. + // It's not documented whether the event object will be signaled or not + // if connect does return 0. So the code below is essentially dead code + // and we don't know if it's correct. + NOTREACHED(); - int os_error = WSAGetLastError(); - if (os_error != WSAEWOULDBLOCK) { - LOG(ERROR) << "connect failed: " << os_error; - connect_os_error_ = os_error; - int rv = MapConnectError(os_error); - CHECK_NE(ERR_IO_PENDING, rv); - return rv; + if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) + return OK; + } else { + int os_error = WSAGetLastError(); + if (os_error != WSAEWOULDBLOCK) { + LOG(ERROR) << "connect failed: " << os_error; + connect_os_error_ = os_error; + int rv = MapConnectError(os_error); + CHECK_NE(ERR_IO_PENDING, rv); + return rv; + } } // TODO(ricea): Remove ScopedTracker below once crbug.com/436634 is fixed.
diff --git a/net/socket/transport_client_socket_unittest.cc b/net/socket/transport_client_socket_unittest.cc index e481b4fa..a4c142140 100644 --- a/net/socket/transport_client_socket_unittest.cc +++ b/net/socket/transport_client_socket_unittest.cc
@@ -2,21 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/socket/tcp_client_socket.h" +#include <string> #include "base/basictypes.h" +#include "base/bind.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/run_loop.h" #include "net/base/address_list.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" -#include "net/base/winsock_init.h" #include "net/dns/mock_host_resolver.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/client_socket_factory.h" -#include "net/socket/tcp_listen_socket.h" +#include "net/socket/tcp_client_socket.h" +#include "net/socket/tcp_server_socket.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -26,40 +30,19 @@ const char kServerReply[] = "HTTP/1.1 404 Not Found"; -enum ClientSocketTestTypes { - TCP, - SCTP -}; +enum ClientSocketTestTypes { TCP, SCTP }; } // namespace class TransportClientSocketTest - : public StreamListenSocket::Delegate, - public ::testing::TestWithParam<ClientSocketTestTypes> { + : public ::testing::TestWithParam<ClientSocketTestTypes> { public: TransportClientSocketTest() : listen_port_(0), socket_factory_(ClientSocketFactory::GetDefaultFactory()), - close_server_socket_on_next_send_(false) { - } + close_server_socket_on_next_send_(false) {} - virtual ~TransportClientSocketTest() { - } - - // Implement StreamListenSocket::Delegate methods - void DidAccept(StreamListenSocket* server, - scoped_ptr<StreamListenSocket> connection) override { - connected_sock_.reset( - static_cast<TCPListenSocket*>(connection.release())); - } - void DidRead(StreamListenSocket*, const char* str, int len) override { - // TODO(dkegel): this might not be long enough to tickle some bugs. - connected_sock_->Send(kServerReply, arraysize(kServerReply) - 1, - false /* Don't append line feed */); - if (close_server_socket_on_next_send_) - CloseServerSocket(); - } - void DidClose(StreamListenSocket* sock) override {} + virtual ~TransportClientSocketTest() {} // Testcase hooks void SetUp() override; @@ -69,12 +52,9 @@ connected_sock_.reset(); } - void PauseServerReads() { - connected_sock_->PauseReads(); - } - - void ResumeServerReads() { - connected_sock_->ResumeReads(); + void AcceptCallback(int res) { + ASSERT_EQ(OK, res); + connect_loop_.Quit(); } int DrainClientSocket(IOBuffer* buf, @@ -82,96 +62,164 @@ uint32 bytes_to_read, TestCompletionCallback* callback); - void SendClientRequest(); + // Establishes a connection to the server. + void EstablishConnection(TestCompletionCallback* callback); + + // Sends a request from the client to the server socket. Makes the server read + // the request and send a response. + void SendRequestAndResponse(); + + // Makes |connected_sock_| to read |expected_bytes_read| bytes. Returns the + // the data read as a string. + std::string ReadServerData(int expected_bytes_read); + + // Sends server response. + void SendServerResponse(); void set_close_server_socket_on_next_send(bool close) { close_server_socket_on_next_send_ = close; } protected: + base::RunLoop connect_loop_; uint16 listen_port_; TestNetLog net_log_; ClientSocketFactory* const socket_factory_; scoped_ptr<StreamSocket> sock_; + scoped_ptr<StreamSocket> connected_sock_; private: - scoped_ptr<TCPListenSocket> listen_sock_; - scoped_ptr<TCPListenSocket> connected_sock_; + scoped_ptr<TCPServerSocket> listen_sock_; bool close_server_socket_on_next_send_; }; void TransportClientSocketTest::SetUp() { ::testing::TestWithParam<ClientSocketTestTypes>::SetUp(); - // Find a free port to listen on - scoped_ptr<TCPListenSocket> sock; - uint16 port; - // Range of ports to listen on. Shouldn't need to try many. - const uint16 kMinPort = 10100; - const uint16 kMaxPort = 10200; -#if defined(OS_WIN) - EnsureWinsockInit(); -#endif - for (port = kMinPort; port < kMaxPort; port++) { - sock = TCPListenSocket::CreateAndListen("127.0.0.1", port, this); - if (sock.get()) - break; - } - ASSERT_TRUE(sock.get() != NULL); - listen_sock_ = sock.Pass(); - listen_port_ = port; + // Open a server socket on an ephemeral port. + listen_sock_.reset(new TCPServerSocket(NULL, NetLog::Source())); + IPAddressNumber address; + ParseIPLiteralToNumber("127.0.0.1", &address); + IPEndPoint local_address(address, 0); + ASSERT_EQ(OK, listen_sock_->Listen(local_address, 1)); + // Get the server's address (including the actual port number). + ASSERT_EQ(OK, listen_sock_->GetLocalAddress(&local_address)); + listen_port_ = local_address.port(); + listen_sock_->Accept(&connected_sock_, + base::Bind(&TransportClientSocketTest::AcceptCallback, + base::Unretained(this))); AddressList addr; // MockHostResolver resolves everything to 127.0.0.1. scoped_ptr<HostResolver> resolver(new MockHostResolver()); HostResolver::RequestInfo info(HostPortPair("localhost", listen_port_)); TestCompletionCallback callback; - int rv = resolver->Resolve( - info, DEFAULT_PRIORITY, &addr, callback.callback(), NULL, BoundNetLog()); + int rv = resolver->Resolve(info, DEFAULT_PRIORITY, &addr, callback.callback(), + NULL, BoundNetLog()); CHECK_EQ(ERR_IO_PENDING, rv); rv = callback.WaitForResult(); CHECK_EQ(rv, OK); - sock_ = - socket_factory_->CreateTransportClientSocket(addr, - &net_log_, - NetLog::Source()); + sock_ = socket_factory_->CreateTransportClientSocket(addr, &net_log_, + NetLog::Source()); } int TransportClientSocketTest::DrainClientSocket( - IOBuffer* buf, uint32 buf_len, - uint32 bytes_to_read, TestCompletionCallback* callback) { + IOBuffer* buf, + uint32 buf_len, + uint32 bytes_to_read, + TestCompletionCallback* callback) { int rv = OK; uint32 bytes_read = 0; while (bytes_read < bytes_to_read) { rv = sock_->Read(buf, buf_len, callback->callback()); EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); - - if (rv == ERR_IO_PENDING) - rv = callback->WaitForResult(); - - EXPECT_GE(rv, 0); + rv = callback->GetResult(rv); + EXPECT_GT(rv, 0); bytes_read += rv; } return static_cast<int>(bytes_read); } -void TransportClientSocketTest::SendClientRequest() { +void TransportClientSocketTest::EstablishConnection( + TestCompletionCallback* callback) { + int rv = sock_->Connect(callback->callback()); + // Wait for |listen_sock_| to accept a connection. + connect_loop_.Run(); + // Now wait for the client socket to accept the connection. + EXPECT_EQ(OK, callback->GetResult(rv)); +} + +void TransportClientSocketTest::SendRequestAndResponse() { + // Send client request. const char request_text[] = "GET / HTTP/1.0\r\n\r\n"; - scoped_refptr<IOBuffer> request_buffer( - new IOBuffer(arraysize(request_text) - 1)); - TestCompletionCallback callback; - int rv; + int request_len = strlen(request_text); + scoped_refptr<DrainableIOBuffer> request_buffer( + new DrainableIOBuffer(new IOBuffer(request_len), request_len)); + memcpy(request_buffer->data(), request_text, request_len); - memcpy(request_buffer->data(), request_text, arraysize(request_text) - 1); - rv = sock_->Write( - request_buffer.get(), arraysize(request_text) - 1, callback.callback()); - EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); + int bytes_written = 0; + while (request_buffer->BytesRemaining() > 0) { + TestCompletionCallback write_callback; + int write_result = + sock_->Write(request_buffer.get(), request_buffer->BytesRemaining(), + write_callback.callback()); + write_result = write_callback.GetResult(write_result); + ASSERT_GT(write_result, 0); + ASSERT_LE(bytes_written + write_result, request_len); + request_buffer->DidConsume(write_result); + bytes_written += write_result; + } + ASSERT_EQ(request_len, bytes_written); - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); - EXPECT_EQ(rv, static_cast<int>(arraysize(request_text) - 1)); + // Confirm that the server receives what client sent. + std::string data_received = ReadServerData(bytes_written); + ASSERT_TRUE(connected_sock_->IsConnectedAndIdle()); + ASSERT_EQ(request_text, data_received); + + // Write server response. + SendServerResponse(); +} + +void TransportClientSocketTest::SendServerResponse() { + // TODO(dkegel): this might not be long enough to tickle some bugs. + int reply_len = strlen(kServerReply); + scoped_refptr<DrainableIOBuffer> write_buffer( + new DrainableIOBuffer(new IOBuffer(reply_len), reply_len)); + memcpy(write_buffer->data(), kServerReply, reply_len); + int bytes_written = 0; + while (write_buffer->BytesRemaining() > 0) { + TestCompletionCallback write_callback; + int write_result = connected_sock_->Write(write_buffer.get(), + write_buffer->BytesRemaining(), + write_callback.callback()); + write_result = write_callback.GetResult(write_result); + ASSERT_GE(write_result, 0); + ASSERT_LE(bytes_written + write_result, reply_len); + write_buffer->DidConsume(write_result); + bytes_written += write_result; + } + if (close_server_socket_on_next_send_) + CloseServerSocket(); +} + +std::string TransportClientSocketTest::ReadServerData(int expected_bytes_read) { + int bytes_read = 0; + scoped_refptr<IOBufferWithSize> read_buffer( + new IOBufferWithSize(expected_bytes_read)); + while (bytes_read < expected_bytes_read) { + TestCompletionCallback read_callback; + int rv = connected_sock_->Read(read_buffer.get(), + expected_bytes_read - bytes_read, + read_callback.callback()); + EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); + rv = read_callback.GetResult(rv); + EXPECT_GE(rv, 0); + bytes_read += rv; + } + EXPECT_EQ(expected_bytes_read, bytes_read); + return std::string(read_buffer->data(), bytes_read); } // TODO(leighton): Add SCTP to this list when it is ready. @@ -184,13 +232,16 @@ EXPECT_FALSE(sock_->IsConnected()); int rv = sock_->Connect(callback.callback()); + // Wait for |listen_sock_| to accept a connection. + connect_loop_.Run(); - net::TestNetLog::CapturedEntryList net_log_entries; + CapturedNetLogEntry::List net_log_entries; net_log_.GetEntries(&net_log_entries); - EXPECT_TRUE(net::LogContainsBeginEvent( - net_log_entries, 0, net::NetLog::TYPE_SOCKET_ALIVE)); - EXPECT_TRUE(net::LogContainsBeginEvent( - net_log_entries, 1, net::NetLog::TYPE_TCP_CONNECT)); + EXPECT_TRUE( + LogContainsBeginEvent(net_log_entries, 0, NetLog::TYPE_SOCKET_ALIVE)); + EXPECT_TRUE( + LogContainsBeginEvent(net_log_entries, 1, NetLog::TYPE_TCP_CONNECT)); + // Now wait for the client socket to accept the connection. if (rv != OK) { ASSERT_EQ(rv, ERR_IO_PENDING); rv = callback.WaitForResult(); @@ -199,8 +250,8 @@ EXPECT_TRUE(sock_->IsConnected()); net_log_.GetEntries(&net_log_entries); - EXPECT_TRUE(net::LogContainsEndEvent( - net_log_entries, -1, net::NetLog::TYPE_TCP_CONNECT)); + EXPECT_TRUE( + LogContainsEndEvent(net_log_entries, -1, NetLog::TYPE_TCP_CONNECT)); sock_->Disconnect(); EXPECT_FALSE(sock_->IsConnected()); @@ -213,17 +264,14 @@ EXPECT_FALSE(sock_->IsConnected()); EXPECT_FALSE(sock_->IsConnectedAndIdle()); - int rv = sock_->Connect(callback.callback()); - if (rv != OK) { - ASSERT_EQ(rv, ERR_IO_PENDING); - rv = callback.WaitForResult(); - EXPECT_EQ(rv, OK); - } + + EstablishConnection(&callback); + EXPECT_TRUE(sock_->IsConnected()); EXPECT_TRUE(sock_->IsConnectedAndIdle()); // Send the request and wait for the server to respond. - SendClientRequest(); + SendRequestAndResponse(); // Drain a single byte so we know we've received some data. bytes_read = DrainClientSocket(buf.get(), 1, 1, &callback); @@ -234,9 +282,9 @@ EXPECT_TRUE(sock_->IsConnected()); EXPECT_FALSE(sock_->IsConnectedAndIdle()); - bytes_read = DrainClientSocket( - buf.get(), 4096, arraysize(kServerReply) - 2, &callback); - ASSERT_EQ(bytes_read, arraysize(kServerReply) - 2); + bytes_read = + DrainClientSocket(buf.get(), 4096, strlen(kServerReply) - 1, &callback); + ASSERT_EQ(bytes_read, strlen(kServerReply) - 1); // After draining the data, the socket should be back to connected // and idle. @@ -245,7 +293,7 @@ // This time close the server socket immediately after the server response. set_close_server_socket_on_next_send(true); - SendClientRequest(); + SendRequestAndResponse(); bytes_read = DrainClientSocket(buf.get(), 1, 1, &callback); ASSERT_EQ(bytes_read, 1u); @@ -254,16 +302,16 @@ EXPECT_TRUE(sock_->IsConnected()); EXPECT_FALSE(sock_->IsConnectedAndIdle()); - bytes_read = DrainClientSocket( - buf.get(), 4096, arraysize(kServerReply) - 2, &callback); - ASSERT_EQ(bytes_read, arraysize(kServerReply) - 2); + bytes_read = + DrainClientSocket(buf.get(), 4096, strlen(kServerReply) - 1, &callback); + ASSERT_EQ(bytes_read, strlen(kServerReply) - 1); // Once the data is drained, the socket should now be seen as not // connected. if (sock_->IsConnected()) { // In the unlikely event that the server's connection closure is not // processed in time, wait for the connection to be closed. - rv = sock_->Read(buf.get(), 4096, callback.callback()); + int rv = sock_->Read(buf.get(), 4096, callback.callback()); EXPECT_EQ(0, callback.GetResult(rv)); EXPECT_FALSE(sock_->IsConnected()); } @@ -272,24 +320,20 @@ TEST_P(TransportClientSocketTest, Read) { TestCompletionCallback callback; - int rv = sock_->Connect(callback.callback()); - if (rv != OK) { - ASSERT_EQ(rv, ERR_IO_PENDING); + EstablishConnection(&callback); - rv = callback.WaitForResult(); - EXPECT_EQ(rv, OK); - } - SendClientRequest(); + SendRequestAndResponse(); scoped_refptr<IOBuffer> buf(new IOBuffer(4096)); - uint32 bytes_read = DrainClientSocket( - buf.get(), 4096, arraysize(kServerReply) - 1, &callback); - ASSERT_EQ(bytes_read, arraysize(kServerReply) - 1); + uint32 bytes_read = + DrainClientSocket(buf.get(), 4096, strlen(kServerReply), &callback); + ASSERT_EQ(bytes_read, strlen(kServerReply)); + ASSERT_EQ(std::string(kServerReply), std::string(buf->data(), bytes_read)); // All data has been read now. Read once more to force an ERR_IO_PENDING, and // then close the server socket, and note the close. - rv = sock_->Read(buf.get(), 4096, callback.callback()); + int rv = sock_->Read(buf.get(), 4096, callback.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); CloseServerSocket(); EXPECT_EQ(0, callback.WaitForResult()); @@ -297,23 +341,17 @@ TEST_P(TransportClientSocketTest, Read_SmallChunks) { TestCompletionCallback callback; - int rv = sock_->Connect(callback.callback()); - if (rv != OK) { - ASSERT_EQ(rv, ERR_IO_PENDING); + EstablishConnection(&callback); - rv = callback.WaitForResult(); - EXPECT_EQ(rv, OK); - } - SendClientRequest(); + SendRequestAndResponse(); scoped_refptr<IOBuffer> buf(new IOBuffer(1)); uint32 bytes_read = 0; - while (bytes_read < arraysize(kServerReply) - 1) { - rv = sock_->Read(buf.get(), 1, callback.callback()); + while (bytes_read < strlen(kServerReply)) { + int rv = sock_->Read(buf.get(), 1, callback.callback()); EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); + rv = callback.GetResult(rv); ASSERT_EQ(1, rv); bytes_read += rv; @@ -322,7 +360,7 @@ // All data has been read now. Read once more to force an ERR_IO_PENDING, and // then close the server socket, and note the close. - rv = sock_->Read(buf.get(), 1, callback.callback()); + int rv = sock_->Read(buf.get(), 1, callback.callback()); ASSERT_EQ(ERR_IO_PENDING, rv); CloseServerSocket(); EXPECT_EQ(0, callback.WaitForResult()); @@ -330,59 +368,48 @@ TEST_P(TransportClientSocketTest, Read_Interrupted) { TestCompletionCallback callback; - int rv = sock_->Connect(callback.callback()); - if (rv != OK) { - ASSERT_EQ(ERR_IO_PENDING, rv); + EstablishConnection(&callback); - rv = callback.WaitForResult(); - EXPECT_EQ(rv, OK); - } - SendClientRequest(); + SendRequestAndResponse(); // Do a partial read and then exit. This test should not crash! scoped_refptr<IOBuffer> buf(new IOBuffer(16)); - rv = sock_->Read(buf.get(), 16, callback.callback()); + int rv = sock_->Read(buf.get(), 16, callback.callback()); EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); - if (rv == ERR_IO_PENDING) - rv = callback.WaitForResult(); + rv = callback.GetResult(rv); EXPECT_NE(0, rv); } -TEST_P(TransportClientSocketTest, DISABLED_FullDuplex_ReadFirst) { +TEST_P(TransportClientSocketTest, FullDuplex_ReadFirst) { TestCompletionCallback callback; - int rv = sock_->Connect(callback.callback()); - if (rv != OK) { - ASSERT_EQ(rv, ERR_IO_PENDING); - - rv = callback.WaitForResult(); - EXPECT_EQ(rv, OK); - } + EstablishConnection(&callback); // Read first. There's no data, so it should return ERR_IO_PENDING. const int kBufLen = 4096; scoped_refptr<IOBuffer> buf(new IOBuffer(kBufLen)); - rv = sock_->Read(buf.get(), kBufLen, callback.callback()); + int rv = sock_->Read(buf.get(), kBufLen, callback.callback()); EXPECT_EQ(ERR_IO_PENDING, rv); - PauseServerReads(); const int kWriteBufLen = 64 * 1024; scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kWriteBufLen)); char* request_data = request_buffer->data(); memset(request_data, 'A', kWriteBufLen); TestCompletionCallback write_callback; + int bytes_written = 0; while (true) { - rv = sock_->Write( - request_buffer.get(), kWriteBufLen, write_callback.callback()); + rv = sock_->Write(request_buffer.get(), kWriteBufLen, + write_callback.callback()); ASSERT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); - if (rv == ERR_IO_PENDING) { - ResumeServerReads(); + ReadServerData(bytes_written); + SendServerResponse(); rv = write_callback.WaitForResult(); break; } + bytes_written += rv; } // At this point, both read and write have returned ERR_IO_PENDING, and the @@ -393,30 +420,25 @@ EXPECT_GE(rv, 0); } -TEST_P(TransportClientSocketTest, DISABLED_FullDuplex_WriteFirst) { +TEST_P(TransportClientSocketTest, FullDuplex_WriteFirst) { TestCompletionCallback callback; - int rv = sock_->Connect(callback.callback()); - if (rv != OK) { - ASSERT_EQ(ERR_IO_PENDING, rv); + EstablishConnection(&callback); - rv = callback.WaitForResult(); - EXPECT_EQ(OK, rv); - } - - PauseServerReads(); const int kWriteBufLen = 64 * 1024; scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kWriteBufLen)); char* request_data = request_buffer->data(); memset(request_data, 'A', kWriteBufLen); TestCompletionCallback write_callback; + int bytes_written = 0; while (true) { - rv = sock_->Write( - request_buffer.get(), kWriteBufLen, write_callback.callback()); + int rv = sock_->Write(request_buffer.get(), kWriteBufLen, + write_callback.callback()); ASSERT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); if (rv == ERR_IO_PENDING) break; + bytes_written += rv; } // Now we have the Write() blocked on ERR_IO_PENDING. It's time to force the @@ -425,7 +447,7 @@ const int kBufLen = 4096; scoped_refptr<IOBuffer> buf(new IOBuffer(kBufLen)); while (true) { - rv = sock_->Read(buf.get(), kBufLen, callback.callback()); + int rv = sock_->Read(buf.get(), kBufLen, callback.callback()); ASSERT_TRUE(rv >= 0 || rv == ERR_IO_PENDING); if (rv == ERR_IO_PENDING) break; @@ -435,8 +457,9 @@ // run the write and read callbacks to make sure they can handle full duplex // communications. - ResumeServerReads(); - rv = write_callback.WaitForResult(); + ReadServerData(bytes_written); + SendServerResponse(); + int rv = write_callback.WaitForResult(); EXPECT_GE(rv, 0); // It's possible the read is blocked because it's already read all the data.
diff --git a/net/spdy/hpack_huffman_table_test.cc b/net/spdy/hpack_huffman_table_test.cc index 6a91149..a8dc196 100644 --- a/net/spdy/hpack_huffman_table_test.cc +++ b/net/spdy/hpack_huffman_table_test.cc
@@ -16,7 +16,6 @@ #include "testing/gtest/include/gtest/gtest.h" using base::StringPiece; -using net::test::a2b_hex; using std::string; using testing::ElementsAreArray; using testing::Pointwise;
diff --git a/net/spdy/spdy_framer_test.cc b/net/spdy/spdy_framer_test.cc index b87748b..fe7d4b8 100644 --- a/net/spdy/spdy_framer_test.cc +++ b/net/spdy/spdy_framer_test.cc
@@ -608,16 +608,12 @@ } // namespace test -} // namespace net - -using net::test::SetFrameLength; -using net::test::SetFrameFlags; -using net::test::CompareCharArraysWithHexError; -using net::test::SpdyFramerTestUtil; -using net::test::TestSpdyVisitor; -using net::test::GetSerializedHeaders; - -namespace net { +using test::SetFrameLength; +using test::SetFrameFlags; +using test::CompareCharArraysWithHexError; +using test::SpdyFramerTestUtil; +using test::TestSpdyVisitor; +using test::GetSerializedHeaders; class SpdyFramerTest : public ::testing::TestWithParam<SpdyMajorVersion> { protected: @@ -5380,8 +5376,8 @@ do { SCOPED_TRACE(testing::Message() << "Flags " << flags); - testing::StrictMock<net::test::MockSpdyFramerVisitor> visitor; - testing::StrictMock<net::test::MockDebugVisitor> debug_visitor; + testing::StrictMock<test::MockSpdyFramerVisitor> visitor; + testing::StrictMock<test::MockDebugVisitor> debug_visitor; SpdyFramer framer(spdy_version_); framer.set_visitor(&visitor); framer.set_debug_visitor(&debug_visitor); @@ -5430,7 +5426,7 @@ SCOPED_TRACE(testing::Message() << "Flags " << flags); testing::StrictMock<test::MockSpdyFramerVisitor> visitor; - testing::StrictMock<net::test::MockDebugVisitor> debug_visitor; + testing::StrictMock<test::MockDebugVisitor> debug_visitor; SpdyFramer framer(spdy_version_); framer.set_visitor(&visitor); framer.set_debug_visitor(&debug_visitor);
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index e5a17141..c84ba5c 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc
@@ -373,7 +373,7 @@ } stream_.reset(); bool invoked_callback = false; - if (status == net::OK) { + if (status == OK) { // We need to complete any pending buffered read now. invoked_callback = DoBufferedReadCallback(); }
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc index aad489b..5c90944e 100644 --- a/net/spdy/spdy_network_transaction_unittest.cc +++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -25,7 +25,9 @@ #include "net/http/http_network_transaction.h" #include "net/http/http_server_properties.h" #include "net/http/http_transaction_test_util.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/client_socket_pool_base.h" #include "net/socket/next_proto.h" #include "net/spdy/buffered_spdy_framer.h" @@ -3676,7 +3678,7 @@ // This test is intentionally non-specific about the exact ordering of the // log; instead we just check to make sure that certain events exist, and that // they are in the right order. - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_LT(0u, entries.size());
diff --git a/net/spdy/spdy_proxy_client_socket_unittest.cc b/net/spdy/spdy_proxy_client_socket_unittest.cc index 14d98dc..8b24e43 100644 --- a/net/spdy/spdy_proxy_client_socket_unittest.cc +++ b/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -13,6 +13,7 @@ #include "net/dns/mock_host_resolver.h" #include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" #include "net/log/test_net_log.h" @@ -110,7 +111,7 @@ data_->Run(); } - void CloseSpdySession(net::Error error, const std::string& description) { + void CloseSpdySession(Error error, const std::string& description) { spdy_session_->CloseSessionOnError(error, description); } @@ -539,7 +540,7 @@ Initialize(reads, arraysize(reads), writes, arraysize(writes)); - net::IPEndPoint addr; + IPEndPoint addr; EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, sock_->GetPeerAddress(&addr)); AssertConnectSucceeds(); @@ -1274,7 +1275,7 @@ NetLog::Source sock_source = sock_->NetLog().source(); sock_.reset(); - TestNetLog::CapturedEntryList entry_list; + CapturedNetLogEntry::List entry_list; net_log_.GetEntriesForSource(sock_source, &entry_list); ASSERT_EQ(entry_list.size(), 10u);
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index e25a88c..44858e97 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc
@@ -59,7 +59,7 @@ scoped_ptr<base::ListValue> SpdyHeaderBlockToListValue( const SpdyHeaderBlock& headers, - net::NetLogCaptureMode capture_mode) { + NetLogCaptureMode capture_mode) { scoped_ptr<base::ListValue> headers_list(new base::ListValue()); for (SpdyHeaderBlock::const_iterator it = headers.begin(); it != headers.end(); ++it) {
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc index c6a44e2..d41ef551 100644 --- a/net/spdy/spdy_session_pool.cc +++ b/net/spdy/spdy_session_pool.cc
@@ -144,7 +144,7 @@ } // Look up the key's from the resolver's cache. - net::HostResolver::RequestInfo resolve_info(key.host_port_pair()); + HostResolver::RequestInfo resolve_info(key.host_port_pair()); AddressList addresses; int rv = resolver_->ResolveFromCache(resolve_info, &addresses, net_log); DCHECK_NE(rv, ERR_IO_PENDING); @@ -234,7 +234,7 @@ // handlers, it doesn't suffice to simply increment the iterator // before closing. -void SpdySessionPool::CloseCurrentSessions(net::Error error) { +void SpdySessionPool::CloseCurrentSessions(Error error) { CloseCurrentSessionsHelper(error, "Closing current sessions.", false /* idle_only */); }
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h index 6ee0c4df..aca0c62 100644 --- a/net/spdy/spdy_session_pool.h +++ b/net/spdy/spdy_session_pool.h
@@ -109,7 +109,7 @@ // Close only the currently existing SpdySessions with |error|. // Let any new ones created while this method is running continue to // live. - void CloseCurrentSessions(net::Error error); + void CloseCurrentSessions(Error error); // Close only the currently existing SpdySessions that are idle. // Let any new ones created while this method is running continue to
diff --git a/net/spdy/spdy_session_pool_unittest.cc b/net/spdy/spdy_session_pool_unittest.cc index f9fba93..4a0841b 100644 --- a/net/spdy/spdy_session_pool_unittest.cc +++ b/net/spdy/spdy_session_pool_unittest.cc
@@ -131,7 +131,7 @@ spdy_stream->SetDelegate(&delegate); // Close the current session. - spdy_session_pool_->CloseCurrentSessions(net::ERR_ABORTED); + spdy_session_pool_->CloseCurrentSessions(ERR_ABORTED); EXPECT_TRUE(HasSpdySession(spdy_session_pool_, test_key)); }
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index a470606..9371012 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc
@@ -15,7 +15,9 @@ #include "net/base/request_priority.h" #include "net/base/test_data_directory.h" #include "net/base/test_data_stream.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/client_socket_pool_manager.h" #include "net/socket/next_proto.h" #include "net/socket/socket_test_util.h" @@ -1632,17 +1634,16 @@ // Flush the read completion task. base::MessageLoop::current()->RunUntilIdle(); - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_LT(0u, entries.size()); // Check that we logged TYPE_HTTP2_SESSION_INITIALIZED correctly. - int pos = net::ExpectLogContainsSomewhere( - entries, 0, net::NetLog::TYPE_HTTP2_SESSION_INITIALIZED, - net::NetLog::PHASE_NONE); + int pos = ExpectLogContainsSomewhere( + entries, 0, NetLog::TYPE_HTTP2_SESSION_INITIALIZED, NetLog::PHASE_NONE); EXPECT_LT(0, pos); - TestNetLog::CapturedEntry entry = entries[pos]; + CapturedNetLogEntry entry = entries[pos]; NetLog::Source socket_source; EXPECT_TRUE(NetLog::Source::FromEventParameters(entry.params.get(), &socket_source)); @@ -1678,17 +1679,16 @@ EXPECT_TRUE(session == NULL); // Check that the NetLog was filled reasonably. - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_LT(0u, entries.size()); // Check that we logged SPDY_SESSION_CLOSE correctly. - int pos = net::ExpectLogContainsSomewhere( - entries, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE, - net::NetLog::PHASE_NONE); + int pos = ExpectLogContainsSomewhere( + entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE); if (pos < static_cast<int>(entries.size())) { - TestNetLog::CapturedEntry entry = entries[pos]; + CapturedNetLogEntry entry = entries[pos]; int error_code = 0; ASSERT_TRUE(entry.GetNetErrorCode(&error_code)); EXPECT_EQ(OK, error_code); @@ -1723,17 +1723,16 @@ EXPECT_TRUE(session == NULL); // Check that the NetLog was filled reasonably. - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_LT(0u, entries.size()); // Check that we logged SPDY_SESSION_CLOSE correctly. - int pos = net::ExpectLogContainsSomewhere( - entries, 0, net::NetLog::TYPE_HTTP2_SESSION_CLOSE, - net::NetLog::PHASE_NONE); + int pos = ExpectLogContainsSomewhere( + entries, 0, NetLog::TYPE_HTTP2_SESSION_CLOSE, NetLog::PHASE_NONE); if (pos < static_cast<int>(entries.size())) { - TestNetLog::CapturedEntry entry = entries[pos]; + CapturedNetLogEntry entry = entries[pos]; int error_code = 0; ASSERT_TRUE(entry.GetNetErrorCode(&error_code)); EXPECT_EQ(ERR_CONNECTION_CLOSED, error_code); @@ -2702,7 +2701,7 @@ const int kPayloadSize = kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); TestDataStream test_stream; - scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); + scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize)); char* payload_data = payload->data(); test_stream.GetBytes(payload_data, kPayloadSize); @@ -2793,7 +2792,7 @@ const int kPayloadSize = kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); TestDataStream test_stream; - scoped_refptr<net::IOBuffer> payload(new net::IOBuffer(kPayloadSize)); + scoped_refptr<IOBuffer> payload(new IOBuffer(kPayloadSize)); char* payload_data = payload->data(); test_stream.GetBytes(payload_data, kPayloadSize); @@ -2891,16 +2890,14 @@ TestDataStream test_stream; const int kEightKPayloadSize = kMaxReadBytesWithoutYielding / 4 - framer.GetControlFrameHeaderSize(); - scoped_refptr<net::IOBuffer> eightk_payload( - new net::IOBuffer(kEightKPayloadSize)); + scoped_refptr<IOBuffer> eightk_payload(new IOBuffer(kEightKPayloadSize)); char* eightk_payload_data = eightk_payload->data(); test_stream.GetBytes(eightk_payload_data, kEightKPayloadSize); // Build buffer of 2k size. TestDataStream test_stream2; const int kTwoKPayloadSize = kEightKPayloadSize - 6 * 1024; - scoped_refptr<net::IOBuffer> twok_payload( - new net::IOBuffer(kTwoKPayloadSize)); + scoped_refptr<IOBuffer> twok_payload(new IOBuffer(kTwoKPayloadSize)); char* twok_payload_data = twok_payload->data(); test_stream2.GetBytes(twok_payload_data, kTwoKPayloadSize); @@ -3654,6 +3651,61 @@ data.RunFor(1); } +// Peer sends more data than stream level receiving flow control window. +TEST_P(SpdySessionTest, StreamFlowControlTooMuchData) { + const int32 stream_max_recv_window_size = 1024; + const int32 data_frame_size = 2 * stream_max_recv_window_size; + + scoped_ptr<SpdyFrame> req( + spdy_util_.ConstructSpdyGet(NULL, 0, false, 1, LOWEST, true)); + MockWrite writes[] = { + CreateMockWrite(*req, 0), + }; + + scoped_ptr<SpdyFrame> resp(spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1)); + const std::string payload(data_frame_size, 'a'); + scoped_ptr<SpdyFrame> data_frame(spdy_util_.ConstructSpdyBodyFrame( + 1, payload.data(), data_frame_size, false)); + MockRead reads[] = { + CreateMockRead(*resp, 1), + CreateMockRead(*data_frame, 2), + MockRead(ASYNC, 0, 3), + }; + + DeterministicSocketData data(reads, arraysize(reads), writes, + arraysize(writes)); + data.set_connect_data(MockConnect(SYNCHRONOUS, OK)); + session_deps_.deterministic_socket_factory->AddSocketDataProvider(&data); + CreateDeterministicNetworkSession(); + + SpdySessionPoolPeer pool_peer(spdy_session_pool_); + pool_peer.SetStreamInitialRecvWindowSize(stream_max_recv_window_size); + base::WeakPtr<SpdySession> session = + CreateInsecureSpdySession(http_session_, key_, BoundNetLog()); + EXPECT_LE(SpdySession::FLOW_CONTROL_STREAM, session->flow_control_state()); + + GURL url(kDefaultURL); + base::WeakPtr<SpdyStream> spdy_stream = CreateStreamSynchronously( + SPDY_REQUEST_RESPONSE_STREAM, session, url, LOWEST, BoundNetLog()); + EXPECT_EQ(stream_max_recv_window_size, spdy_stream->recv_window_size()); + + test::StreamDelegateDoNothing delegate(spdy_stream); + spdy_stream->SetDelegate(&delegate); + + scoped_ptr<SpdyHeaderBlock> headers( + spdy_util_.ConstructGetHeaderBlock(kDefaultURL)); + EXPECT_EQ(ERR_IO_PENDING, spdy_stream->SendRequestHeaders( + headers.Pass(), NO_MORE_DATA_TO_SEND)); + + // Request and response. + data.RunFor(2); + EXPECT_EQ(1u, spdy_stream->stream_id()); + + // Too large data frame causes flow control error, should close stream. + data.RunFor(1); + EXPECT_EQ(nullptr, spdy_stream.get()); +} + // A delegate that drops any received data. class DropReceivedDataDelegate : public test::StreamDelegateSendImmediate { public:
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc index f841be1..31bc0ae 100644 --- a/net/spdy/spdy_stream.cc +++ b/net/spdy/spdy_stream.cc
@@ -510,7 +510,11 @@ size_t length = buffer->GetRemainingSize(); DCHECK_LE(length, session_->GetDataFrameMaximumPayload()); if (session_->flow_control_state() >= SpdySession::FLOW_CONTROL_STREAM) { + base::WeakPtr<SpdyStream> weak_this = GetWeakPtr(); + // May close the stream. DecreaseRecvWindowSize(static_cast<int32>(length)); + if (!weak_this) + return; buffer->AddConsumeCallback( base::Bind(&SpdyStream::OnReadBufferConsumed, GetWeakPtr())); } @@ -529,7 +533,11 @@ // Increase window size because padding bytes are consumed (by discarding). // Net result: |unacked_recv_window_bytes_| increases by |len|, // |recv_window_size_| does not change. + base::WeakPtr<SpdyStream> weak_this = GetWeakPtr(); + // May close the stream. DecreaseRecvWindowSize(static_cast<int32>(len)); + if (!weak_this) + return; IncreaseRecvWindowSize(static_cast<int32>(len)); } }
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h index d21ee6d..a1821a35 100644 --- a/net/spdy/spdy_stream.h +++ b/net/spdy/spdy_stream.h
@@ -263,8 +263,8 @@ // Called by OnDataReceived or OnPaddingConsumed (which are in turn called by // the session) to decrease this stream's receive window size by - // |delta_window_size|, which must be at least 1 and must not cause - // this stream's receive window size to go negative. + // |delta_window_size|, which must be at least 1. May close the stream on + // flow control error. // // If stream flow control is turned off or the stream is not active, // this must not be called.
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc index 15f67301..2db76ed 100644 --- a/net/spdy/spdy_stream_unittest.cc +++ b/net/spdy/spdy_stream_unittest.cc
@@ -12,7 +12,9 @@ #include "base/strings/string_piece.h" #include "net/base/completion_callback.h" #include "net/base/request_priority.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/socket/next_proto.h" #include "net/socket/socket_test_util.h" #include "net/spdy/buffered_spdy_framer.h" @@ -293,14 +295,13 @@ EXPECT_TRUE(data.at_write_eof()); // Check that the NetLog was filled reasonably. - net::TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; log.GetEntries(&entries); EXPECT_LT(0u, entries.size()); // Check that we logged SPDY_STREAM_ERROR correctly. - int pos = net::ExpectLogContainsSomewhere( - entries, 0, net::NetLog::TYPE_HTTP2_STREAM_ERROR, - net::NetLog::PHASE_NONE); + int pos = ExpectLogContainsSomewhere( + entries, 0, NetLog::TYPE_HTTP2_STREAM_ERROR, NetLog::PHASE_NONE); int stream_id2; ASSERT_TRUE(entries[pos].GetIntegerValue("stream_id", &stream_id2));
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc index 654aedb2..b675374 100644 --- a/net/spdy/spdy_test_util_common.cc +++ b/net/spdy/spdy_test_util_common.cc
@@ -417,7 +417,7 @@ // static HttpNetworkSession* SpdySessionDependencies::SpdyCreateSession( SpdySessionDependencies* session_deps) { - net::HttpNetworkSession::Params params = CreateSessionParams(session_deps); + HttpNetworkSession::Params params = CreateSessionParams(session_deps); params.client_socket_factory = session_deps->socket_factory.get(); HttpNetworkSession* http_session = new HttpNetworkSession(params); SpdySessionPoolPeer pool_peer(http_session->spdy_session_pool()); @@ -428,7 +428,7 @@ // static HttpNetworkSession* SpdySessionDependencies::SpdyCreateSessionDeterministic( SpdySessionDependencies* session_deps) { - net::HttpNetworkSession::Params params = CreateSessionParams(session_deps); + HttpNetworkSession::Params params = CreateSessionParams(session_deps); params.client_socket_factory = session_deps->deterministic_socket_factory.get(); HttpNetworkSession* http_session = new HttpNetworkSession(params); @@ -438,12 +438,12 @@ } // static -net::HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams( +HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams( SpdySessionDependencies* session_deps) { DCHECK(next_proto_is_spdy(session_deps->protocol)) << "Invalid protocol: " << session_deps->protocol; - net::HttpNetworkSession::Params params; + HttpNetworkSession::Params params; params.host_resolver = session_deps->host_resolver.get(); params.cert_verifier = session_deps->cert_verifier.get(); params.transport_security_state = @@ -485,7 +485,7 @@ storage_.set_http_server_properties( scoped_ptr<HttpServerProperties>(new HttpServerPropertiesImpl())); storage_.set_job_factory(new URLRequestJobFactoryImpl()); - net::HttpNetworkSession::Params params; + HttpNetworkSession::Params params; params.client_socket_factory = &socket_factory_; params.host_resolver = host_resolver(); params.cert_verifier = cert_verifier();
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h index 781dbb2..74bf694 100644 --- a/net/spdy/spdy_test_util_common.h +++ b/net/spdy/spdy_test_util_common.h
@@ -233,7 +233,7 @@ private: MockClientSocketFactory socket_factory_; - net::URLRequestContextStorage storage_; + URLRequestContextStorage storage_; }; // Equivalent to pool->GetIfExists(spdy_session_key, BoundNetLog()) != NULL.
diff --git a/net/spdy/write_blocked_list.h b/net/spdy/write_blocked_list.h index 654c21e63..c6d60b3 100644 --- a/net/spdy/write_blocked_list.h +++ b/net/spdy/write_blocked_list.h
@@ -12,12 +12,12 @@ #include "base/logging.h" #include "net/spdy/spdy_protocol.h" -namespace { -class WriteBlockedListPeer; -} - namespace net { +namespace test { +class WriteBlockedListPeer; +} // namespace test + const int kHighestPriority = 0; const int kLowestPriority = 7; @@ -164,7 +164,7 @@ bool avoids_inserting_duplicates() const { return use_stream_to_priority_; } private: - friend WriteBlockedListPeer; + friend class net::test::WriteBlockedListPeer; typedef base::hash_map<IdType, SpdyPriority> StreamToPriorityMap;
diff --git a/net/spdy/write_blocked_list_test.cc b/net/spdy/write_blocked_list_test.cc index ef5ea50..50c3f35 100644 --- a/net/spdy/write_blocked_list_test.cc +++ b/net/spdy/write_blocked_list_test.cc
@@ -8,22 +8,19 @@ #include "testing/gtest/include/gtest/gtest.h" -namespace { +namespace net { +namespace test { class WriteBlockedListPeer { public: - static std::deque<int>* GetWriteBlockedList( - int i, - net::WriteBlockedList<int>* list) { + static std::deque<int>* GetWriteBlockedList(int i, + WriteBlockedList<int>* list) { return &list->write_blocked_lists_[i]; } }; -} // namespace - -namespace net { -namespace test { namespace { + typedef WriteBlockedList<int> IntWriteBlockedList; class WriteBlockedListTest : public ::testing::TestWithParam<bool> { @@ -166,5 +163,6 @@ } } // namespace + } // namespace test } // namespace net
diff --git a/net/ssl/client_cert_store_chromeos_unittest.cc b/net/ssl/client_cert_store_chromeos_unittest.cc index ca2c0494..94acac62 100644 --- a/net/ssl/client_cert_store_chromeos_unittest.cc +++ b/net/ssl/client_cert_store_chromeos_unittest.cc
@@ -20,7 +20,7 @@ namespace { -class TestCertFilter : public net::ClientCertStoreChromeOS::CertFilter { +class TestCertFilter : public ClientCertStoreChromeOS::CertFilter { public: explicit TestCertFilter(bool init_finished) : init_finished_(init_finished), init_called_(false) {} @@ -36,7 +36,7 @@ } bool IsCertAllowed( - const scoped_refptr<net::X509Certificate>& cert) const override { + const scoped_refptr<X509Certificate>& cert) const override { if (not_allowed_cert_.get() && cert->Equals(not_allowed_cert_.get())) return false; return true;
diff --git a/net/test/embedded_test_server/http_request.h b/net/test/embedded_test_server/http_request.h index 3cd1ac77..c299378 100644 --- a/net/test/embedded_test_server/http_request.h +++ b/net/test/embedded_test_server/http_request.h
@@ -111,7 +111,7 @@ // Content length of the request currently being parsed. size_t declared_content_length_; - scoped_ptr<net::HttpChunkedDecoder> chunked_decoder_; + scoped_ptr<HttpChunkedDecoder> chunked_decoder_; DISALLOW_COPY_AND_ASSIGN(HttpRequestParser); };
diff --git a/net/test/spawned_test_server/base_test_server.cc b/net/test/spawned_test_server/base_test_server.cc index b8ded1f..c5a9b6f4 100644 --- a/net/test/spawned_test_server/base_test_server.cc +++ b/net/test/spawned_test_server/base_test_server.cc
@@ -245,7 +245,7 @@ BoundNetLog()); if (rv == ERR_IO_PENDING) rv = callback.WaitForResult(); - if (rv != net::OK) { + if (rv != OK) { LOG(ERROR) << "Failed to resolve hostname: " << host_port_pair_.host(); return false; }
diff --git a/net/test/spawned_test_server/spawner_communicator.h b/net/test/spawned_test_server/spawner_communicator.h index ba8bfcab..15ae0c5e 100644 --- a/net/test/spawned_test_server/spawner_communicator.h +++ b/net/test/spawned_test_server/spawner_communicator.h
@@ -29,7 +29,7 @@ // themselves continue running on the device. To control the test server on the // host machine, a second HTTP server is started, the spawner server, which // controls the life cycle of remote test servers. Calls to start/kill the -// net::SpawnedTestServer are then redirected to the spawner server via +// SpawnedTestServer are then redirected to the spawner server via // this spawner communicator. // // Currently only three commands are supported by spawner. @@ -58,7 +58,7 @@ // The internal I/O thread is required by net stack to perform net I/O. // The Start/StopServer methods block the caller thread until result is // fetched from spawner server or timed-out. -class SpawnerCommunicator : public net::URLRequest::Delegate { +class SpawnerCommunicator : public URLRequest::Delegate { public: explicit SpawnerCommunicator(uint16 port); ~SpawnerCommunicator() override;
diff --git a/net/test/url_request/url_request_failed_job.cc b/net/test/url_request/url_request_failed_job.cc index c13c3c8c..b0e2536f 100644 --- a/net/test/url_request/url_request_failed_job.cc +++ b/net/test/url_request/url_request_failed_job.cc
@@ -19,35 +19,36 @@ // Gets the numeric net error code from URL of the form: // scheme://kMockHostname/error_code. The error code must be a valid -// net error code, and not net::OK or net::ERR_IO_PENDING. -int GetErrorCode(net::URLRequest* request) { +// net error code, and not OK or ERR_IO_PENDING. +int GetErrorCode(URLRequest* request) { int net_error; std::string path = request->url().path(); if (path[0] == '/' && base::StringToInt(path.c_str() + 1, &net_error)) { CHECK_LT(net_error, 0); - CHECK_NE(net_error, net::ERR_IO_PENDING); + CHECK_NE(net_error, ERR_IO_PENDING); return net_error; } NOTREACHED(); - return net::ERR_UNEXPECTED; + return ERR_UNEXPECTED; } GURL GetMockUrl(const std::string& scheme, const std::string& hostname, int net_error) { CHECK_LT(net_error, 0); - CHECK_NE(net_error, net::ERR_IO_PENDING); + CHECK_NE(net_error, ERR_IO_PENDING); return GURL(scheme + "://" + hostname + "/" + base::IntToString(net_error)); } } // namespace -URLRequestFailedJob::URLRequestFailedJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, +URLRequestFailedJob::URLRequestFailedJob(URLRequest* request, + NetworkDelegate* network_delegate, int net_error) - : net::URLRequestJob(request, network_delegate), + : URLRequestJob(request, network_delegate), net_error_(net_error), - weak_factory_(this) {} + weak_factory_(this) { +} void URLRequestFailedJob::Start() { base::MessageLoop::current()->PostTask( @@ -63,8 +64,8 @@ // static void URLRequestFailedJob::AddUrlHandlerForHostname( const std::string& hostname) { - // Add |hostname| to net::URLRequestFilter for HTTP and HTTPS. - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); + // Add |hostname| to URLRequestFilter for HTTP and HTTPS. + URLRequestFilter* filter = URLRequestFilter::GetInstance(); filter->AddHostnameHandler("http", hostname, URLRequestFailedJob::Factory); filter->AddHostnameHandler("https", hostname, URLRequestFailedJob::Factory); } @@ -94,17 +95,15 @@ URLRequestFailedJob::~URLRequestFailedJob() {} // static -net::URLRequestJob* URLRequestFailedJob::Factory( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& scheme) { +URLRequestJob* URLRequestFailedJob::Factory(URLRequest* request, + NetworkDelegate* network_delegate, + const std::string& scheme) { return new URLRequestFailedJob( request, network_delegate, GetErrorCode(request)); } void URLRequestFailedJob::StartAsync() { - NotifyStartError(net::URLRequestStatus(net::URLRequestStatus::FAILED, - net_error_)); + NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, net_error_)); } } // namespace net
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 1333495..5425816 100644 --- a/net/test/url_request/url_request_mock_data_job.cc +++ b/net/test/url_request/url_request_mock_data_job.cc
@@ -22,7 +22,7 @@ // Gets the data from URL of the form: // scheme://kMockHostname/?data=abc&repeat_count=nnn. -std::string GetDataFromRequest(const net::URLRequest& request) { +std::string GetDataFromRequest(const URLRequest& request) { std::string value; if (!GetValueForKeyInQuery(request.url(), "data", &value)) return "default_data"; @@ -31,7 +31,7 @@ // Gets the numeric repeat count from URL of the form: // scheme://kMockHostname/?data=abc&repeat_count=nnn. -int GetRepeatCountFromRequest(const net::URLRequest& request) { +int GetRepeatCountFromRequest(const URLRequest& request) { std::string value; if (!GetValueForKeyInQuery(request.url(), "repeat", &value)) return 1; @@ -58,15 +58,15 @@ return GURL(url); } -class MockJobInterceptor : public net::URLRequestInterceptor { +class MockJobInterceptor : public URLRequestInterceptor { public: MockJobInterceptor() {} ~MockJobInterceptor() override {} - // net::URLRequestInterceptor implementation - net::URLRequestJob* MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { + // URLRequestInterceptor implementation + URLRequestJob* MaybeInterceptRequest( + URLRequest* request, + NetworkDelegate* network_delegate) const override { return new URLRequestMockDataJob(request, network_delegate, GetDataFromRequest(*request), GetRepeatCountFromRequest(*request)); @@ -114,7 +114,7 @@ } int URLRequestMockDataJob::GetResponseCode() const { - net::HttpResponseInfo info; + HttpResponseInfo info; GetResponseInfoConst(&info); return info.headers->response_code(); } @@ -134,7 +134,7 @@ "Content-type: text/plain\n"); raw_headers.append(base::StringPrintf("Content-Length: %1d\n", static_cast<int>(data_.length()))); - info->headers = new HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders( + info->headers = new HttpResponseHeaders(HttpUtil::AssembleRawHeaders( raw_headers.c_str(), static_cast<int>(raw_headers.length()))); } @@ -154,8 +154,8 @@ // static void URLRequestMockDataJob::AddUrlHandlerForHostname( const std::string& hostname) { - // Add |hostname| to net::URLRequestFilter for HTTP and HTTPS. - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); + // Add |hostname| to URLRequestFilter for HTTP and HTTPS. + URLRequestFilter* filter = URLRequestFilter::GetInstance(); filter->AddHostnameInterceptor("http", hostname, make_scoped_ptr(new MockJobInterceptor())); filter->AddHostnameInterceptor("https", hostname,
diff --git a/net/test/url_request/url_request_mock_http_job.cc b/net/test/url_request/url_request_mock_http_job.cc index e0905f2..012a335 100644 --- a/net/test/url_request/url_request_mock_http_job.cc +++ b/net/test/url_request/url_request_mock_http_job.cc
@@ -35,7 +35,7 @@ "readsync", // READ_SYNC }; -class MockJobInterceptor : public net::URLRequestInterceptor { +class MockJobInterceptor : public URLRequestInterceptor { public: // When |map_all_requests_to_base_path| is true, all request should return the // contents of the file at |base_path|. When |map_all_requests_to_base_path| @@ -50,10 +50,10 @@ worker_pool_(worker_pool) {} ~MockJobInterceptor() override {} - // net::URLRequestJobFactory::ProtocolHandler implementation - net::URLRequestJob* MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { + // URLRequestJobFactory::ProtocolHandler implementation + URLRequestJob* MaybeInterceptRequest( + URLRequest* request, + NetworkDelegate* network_delegate) const override { return new URLRequestMockHTTPJob( request, network_delegate, @@ -63,15 +63,15 @@ } private: - base::FilePath GetOnDiskPath(net::URLRequest* request) const { + base::FilePath GetOnDiskPath(URLRequest* request) const { // Conceptually we just want to "return base_path_ + request->url().path()". // But path in the request URL is in URL space (i.e. %-encoded spaces). // So first we convert base FilePath to a URL, then append the URL // path to that, and convert the final URL back to a FilePath. - GURL file_url(net::FilePathToFileURL(base_path_)); + GURL file_url(FilePathToFileURL(base_path_)); std::string url = file_url.spec() + request->url().path(); base::FilePath file_path; - net::FileURLToFilePath(GURL(url), &file_path); + FileURLToFilePath(GURL(url), &file_path); return file_path; } @@ -113,8 +113,8 @@ void URLRequestMockHTTPJob::AddUrlHandlers( const base::FilePath& base_path, const scoped_refptr<base::SequencedWorkerPool>& worker_pool) { - // Add kMockHostname to net::URLRequestFilter, for both HTTP and HTTPS. - net::URLRequestFilter* filter = net::URLRequestFilter::GetInstance(); + // Add kMockHostname to URLRequestFilter, for both HTTP and HTTPS. + URLRequestFilter* filter = URLRequestFilter::GetInstance(); filter->AddHostnameInterceptor( "http", kMockHostname, CreateInterceptor(base_path, worker_pool)); filter->AddHostnameInterceptor("https", kMockHostname, @@ -148,28 +148,28 @@ } // static -scoped_ptr<net::URLRequestInterceptor> URLRequestMockHTTPJob::CreateInterceptor( +scoped_ptr<URLRequestInterceptor> URLRequestMockHTTPJob::CreateInterceptor( const base::FilePath& base_path, const scoped_refptr<base::SequencedWorkerPool>& worker_pool) { - return scoped_ptr<net::URLRequestInterceptor>( + return scoped_ptr<URLRequestInterceptor>( new MockJobInterceptor(base_path, false, worker_pool)); } // static -scoped_ptr<net::URLRequestInterceptor> +scoped_ptr<URLRequestInterceptor> URLRequestMockHTTPJob::CreateInterceptorForSingleFile( const base::FilePath& file, const scoped_refptr<base::SequencedWorkerPool>& worker_pool) { - return scoped_ptr<net::URLRequestInterceptor>( + return scoped_ptr<URLRequestInterceptor>( new MockJobInterceptor(file, true, worker_pool)); } URLRequestMockHTTPJob::URLRequestMockHTTPJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, + URLRequest* request, + NetworkDelegate* network_delegate, const base::FilePath& file_path, const scoped_refptr<base::TaskRunner>& task_runner) - : net::URLRequestFileJob(request, network_delegate, file_path, task_runner), + : URLRequestFileJob(request, network_delegate, file_path, task_runner), task_runner_(task_runner), weak_ptr_factory_(this) { } @@ -178,16 +178,16 @@ } // Public virtual version. -void URLRequestMockHTTPJob::GetResponseInfo(net::HttpResponseInfo* info) { +void URLRequestMockHTTPJob::GetResponseInfo(HttpResponseInfo* info) { // Forward to private const version. GetResponseInfoConst(info); } bool URLRequestMockHTTPJob::IsRedirectResponse(GURL* location, int* http_status_code) { - // Override the net::URLRequestFileJob implementation to invoke the default + // Override the URLRequestFileJob implementation to invoke the default // one based on HttpResponseInfo. - return net::URLRequestJob::IsRedirectResponse(location, http_status_code); + return URLRequestJob::IsRedirectResponse(location, http_status_code); } // Public virtual version. @@ -237,50 +237,48 @@ if (!base::StringToInt(phase_error_string, &net_error)) return false; - if (net_error != net::ERR_IO_PENDING && + if (net_error != ERR_IO_PENDING && (current_phase == START || current_phase == READ_SYNC)) { - NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, net_error)); + NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, net_error)); return true; } - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); if (current_phase != READ_ASYNC) return true; base::MessageLoopProxy::current()->PostTask( FROM_HERE, - base::Bind( - &URLRequestMockHTTPJob::NotifyDone, - weak_ptr_factory_.GetWeakPtr(), - net::URLRequestStatus(net::URLRequestStatus::FAILED, net_error))); + base::Bind(&URLRequestMockHTTPJob::NotifyDone, + weak_ptr_factory_.GetWeakPtr(), + URLRequestStatus(URLRequestStatus::FAILED, net_error))); return true; } // Private const version. -void URLRequestMockHTTPJob::GetResponseInfoConst( - net::HttpResponseInfo* info) const { - info->headers = new net::HttpResponseHeaders(raw_headers_); +void URLRequestMockHTTPJob::GetResponseInfoConst(HttpResponseInfo* info) const { + info->headers = new HttpResponseHeaders(raw_headers_); } bool URLRequestMockHTTPJob::GetMimeType(std::string* mime_type) const { - net::HttpResponseInfo info; + HttpResponseInfo info; GetResponseInfoConst(&info); return info.headers.get() && info.headers->GetMimeType(mime_type); } int URLRequestMockHTTPJob::GetResponseCode() const { - net::HttpResponseInfo info; + HttpResponseInfo info; GetResponseInfoConst(&info); // If we have headers, get the response code from them. if (info.headers.get()) return info.headers->response_code(); - return net::URLRequestJob::GetResponseCode(); + return URLRequestJob::GetResponseCode(); } bool URLRequestMockHTTPJob::GetCharset(std::string* charset) { - net::HttpResponseInfo info; + HttpResponseInfo info; GetResponseInfo(&info); return info.headers.get() && info.headers->GetCharset(charset); }
diff --git a/net/udp/udp_socket_perftest.cc b/net/udp/udp_socket_perftest.cc index df36c46..8d237b8 100644 --- a/net/udp/udp_socket_perftest.cc +++ b/net/udp/udp_socket_perftest.cc
@@ -21,14 +21,16 @@ #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" +namespace net { + namespace { class UDPSocketPerfTest : public PlatformTest { public: UDPSocketPerfTest() - : buffer_(new net::IOBufferWithSize(kPacketSize)), weak_factory_(this) {} + : buffer_(new IOBufferWithSize(kPacketSize)), weak_factory_(this) {} - void DoneWritePacketsToSocket(net::UDPClientSocket* socket, + void DoneWritePacketsToSocket(UDPClientSocket* socket, int num_of_packets, base::Closure done_callback, int error) { @@ -36,7 +38,7 @@ } // Send |num_of_packets| to |socket|. Invoke |done_callback| when done. - void WritePacketsToSocket(net::UDPClientSocket* socket, + void WritePacketsToSocket(UDPClientSocket* socket, int num_of_packets, base::Closure done_callback); @@ -46,26 +48,23 @@ protected: static const int kPacketSize = 1024; - scoped_refptr<net::IOBufferWithSize> buffer_; + scoped_refptr<IOBufferWithSize> buffer_; base::WeakPtrFactory<UDPSocketPerfTest> weak_factory_; }; // Creates and address from an ip/port and returns it in |address|. -void CreateUDPAddress(std::string ip_str, - uint16 port, - net::IPEndPoint* address) { - net::IPAddressNumber ip_number; - bool rv = net::ParseIPLiteralToNumber(ip_str, &ip_number); +void CreateUDPAddress(std::string ip_str, uint16 port, IPEndPoint* address) { + IPAddressNumber ip_number; + bool rv = ParseIPLiteralToNumber(ip_str, &ip_number); if (!rv) return; - *address = net::IPEndPoint(ip_number, port); + *address = IPEndPoint(ip_number, port); } -void UDPSocketPerfTest::WritePacketsToSocket(net::UDPClientSocket* socket, +void UDPSocketPerfTest::WritePacketsToSocket(UDPClientSocket* socket, int num_of_packets, base::Closure done_callback) { - scoped_refptr<net::IOBufferWithSize> io_buffer( - new net::IOBufferWithSize(kPacketSize)); + scoped_refptr<IOBufferWithSize> io_buffer(new IOBufferWithSize(kPacketSize)); memset(io_buffer->data(), 'G', kPacketSize); while (num_of_packets) { @@ -74,7 +73,7 @@ base::Bind(&UDPSocketPerfTest::DoneWritePacketsToSocket, weak_factory_.GetWeakPtr(), socket, num_of_packets - 1, done_callback)); - if (rv == net::ERR_IO_PENDING) + if (rv == ERR_IO_PENDING) break; --num_of_packets; } @@ -89,31 +88,31 @@ const uint16 kPort = 9999; // Setup the server to listen. - net::IPEndPoint bind_address; + IPEndPoint bind_address; CreateUDPAddress("127.0.0.1", kPort, &bind_address); - net::TestNetLog server_log; - scoped_ptr<net::UDPServerSocket> server( - new net::UDPServerSocket(&server_log, net::NetLog::Source())); + TestNetLog server_log; + scoped_ptr<UDPServerSocket> server( + new UDPServerSocket(&server_log, NetLog::Source())); #if defined(OS_WIN) if (use_nonblocking_io) server->UseNonBlockingIO(); #endif int rv = server->Listen(bind_address); - ASSERT_EQ(net::OK, rv); + ASSERT_EQ(OK, rv); // Setup the client. - net::IPEndPoint server_address; + IPEndPoint server_address; CreateUDPAddress("127.0.0.1", kPort, &server_address); - net::TestNetLog client_log; - scoped_ptr<net::UDPClientSocket> client(new net::UDPClientSocket( - net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(), &client_log, - net::NetLog::Source())); + TestNetLog client_log; + scoped_ptr<UDPClientSocket> client( + new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(), + &client_log, NetLog::Source())); #if defined(OS_WIN) if (use_nonblocking_io) client->UseNonBlockingIO(); #endif rv = client->Connect(server_address); - EXPECT_EQ(net::OK, rv); + EXPECT_EQ(OK, rv); base::RunLoop run_loop; base::TimeTicks start_ticks = base::TimeTicks::Now(); @@ -139,3 +138,5 @@ #endif } // namespace + +} // namespace net
diff --git a/net/udp/udp_socket_unittest.cc b/net/udp/udp_socket_unittest.cc index d422e4a..f356cee0 100644 --- a/net/udp/udp_socket_unittest.cc +++ b/net/udp/udp_socket_unittest.cc
@@ -19,7 +19,9 @@ #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/base/test_completion_callback.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log_unittest.h" +#include "net/log/test_net_log.h" #include "net/test/net_test_suite.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -213,7 +215,7 @@ client.reset(); // Check the server's log. - TestNetLog::CapturedEntryList server_entries; + CapturedNetLogEntry::List server_entries; server_log.GetEntries(&server_entries); EXPECT_EQ(5u, server_entries.size()); EXPECT_TRUE( @@ -228,7 +230,7 @@ LogContainsEndEvent(server_entries, 4, NetLog::TYPE_SOCKET_ALIVE)); // Check the client's log. - TestNetLog::CapturedEntryList client_entries; + CapturedNetLogEntry::List client_entries; client_log.GetEntries(&client_entries); EXPECT_EQ(7u, client_entries.size()); EXPECT_TRUE(
diff --git a/net/url_request/sdch_dictionary_fetcher_unittest.cc b/net/url_request/sdch_dictionary_fetcher_unittest.cc index f6db83f..98eecaa 100644 --- a/net/url_request/sdch_dictionary_fetcher_unittest.cc +++ b/net/url_request/sdch_dictionary_fetcher_unittest.cc
@@ -124,13 +124,12 @@ new SpecifiedResponseJobInterceptor(http_response_info, lifecycle_callback)); - net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( - "http", kTestDomain, interceptor.Pass()); + URLRequestFilter::GetInstance()->AddHostnameInterceptor("http", kTestDomain, + interceptor.Pass()); } static void Unregister() { - net::URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", - kTestDomain); + URLRequestFilter::GetInstance()->RemoveHostnameHandler("http", kTestDomain); } private:
diff --git a/net/url_request/test_url_request_interceptor.cc b/net/url_request/test_url_request_interceptor.cc index b0fd315..72aeea26 100644 --- a/net/url_request/test_url_request_interceptor.cc +++ b/net/url_request/test_url_request_interceptor.cc
@@ -17,18 +17,18 @@ namespace { -// This class is needed because net::URLRequestFileJob always returns a -1 +// This class is needed because URLRequestFileJob always returns a -1 // HTTP response status code. -class TestURLRequestJob : public net::URLRequestFileJob { +class TestURLRequestJob : public URLRequestFileJob { public: - TestURLRequestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, + TestURLRequestJob(URLRequest* request, + NetworkDelegate* network_delegate, const base::FilePath& file_path, const scoped_refptr<base::TaskRunner>& worker_task_runner) - : net::URLRequestFileJob(request, - network_delegate, - file_path, - worker_task_runner) {} + : URLRequestFileJob(request, + network_delegate, + file_path, + worker_task_runner) {} int GetResponseCode() const override { return 200; } @@ -42,8 +42,8 @@ // This class handles the actual URL request interception. It may be constructed // on any thread, but all other methods are called on the |network_task_runner| -// thread. It is destroyed by the net::URLRequestFilter singleton. -class TestURLRequestInterceptor::Delegate : public net::URLRequestInterceptor { +// thread. It is destroyed by the URLRequestFilter singleton. +class TestURLRequestInterceptor::Delegate : public URLRequestInterceptor { public: Delegate(const std::string& scheme, const std::string& hostname, @@ -57,14 +57,13 @@ ~Delegate() override {} void Register() { - net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( - scheme_, hostname_, scoped_ptr<net::URLRequestInterceptor>(this)); + URLRequestFilter::GetInstance()->AddHostnameInterceptor( + scheme_, hostname_, scoped_ptr<URLRequestInterceptor>(this)); } static void Unregister(const std::string& scheme, const std::string& hostname) { - net::URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme, - hostname); + URLRequestFilter::GetInstance()->RemoveHostnameHandler(scheme, hostname); } // When requests for |url| arrive, respond with the contents of |path|. The @@ -91,9 +90,9 @@ typedef std::map<GURL, base::FilePath> ResponseMap; // When computing matches, this ignores the query parameters of the url. - net::URLRequestJob* MaybeInterceptRequest( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { + URLRequestJob* MaybeInterceptRequest( + URLRequest* request, + NetworkDelegate* network_delegate) const override { DCHECK(network_task_runner_->RunsTasksOnCurrentThread()); if (request->url().scheme() != scheme_ || request->url().host() != hostname_) {
diff --git a/net/url_request/url_fetcher.cc b/net/url_request/url_fetcher.cc index ddad12d..faf70175 100644 --- a/net/url_request/url_fetcher.cc +++ b/net/url_request/url_fetcher.cc
@@ -12,31 +12,29 @@ URLFetcher::~URLFetcher() {} // static -URLFetcher* net::URLFetcher::Create( - const GURL& url, - URLFetcher::RequestType request_type, - URLFetcherDelegate* d) { +URLFetcher* URLFetcher::Create(const GURL& url, + URLFetcher::RequestType request_type, + URLFetcherDelegate* d) { return URLFetcher::Create(0, url, request_type, d); } // static -URLFetcher* net::URLFetcher::Create( - int id, - const GURL& url, - URLFetcher::RequestType request_type, - URLFetcherDelegate* d) { +URLFetcher* URLFetcher::Create(int id, + const GURL& url, + URLFetcher::RequestType request_type, + URLFetcherDelegate* d) { URLFetcherFactory* factory = URLFetcherImpl::factory(); return factory ? factory->CreateURLFetcher(id, url, request_type, d) : new URLFetcherImpl(url, request_type, d); } // static -void net::URLFetcher::CancelAll() { +void URLFetcher::CancelAll() { URLFetcherImpl::CancelAll(); } // static -void net::URLFetcher::SetIgnoreCertificateRequests(bool ignored) { +void URLFetcher::SetIgnoreCertificateRequests(bool ignored) { URLFetcherImpl::SetIgnoreCertificateRequests(ignored); }
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc index 36aeb5e62..b3d6336 100644 --- a/net/url_request/url_fetcher_impl_unittest.cc +++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -76,16 +76,15 @@ // Creates a URLFetcher that runs network tasks on the current message loop. void CreateFetcherWithContext(const GURL& url, URLFetcher::RequestType request_type, - net::URLRequestContext* context) { + URLRequestContext* context) { CreateFetcherWithContextGetter( url, request_type, new TrivialURLRequestContextGetter( context, base::MessageLoopProxy::current())); } - void CreateFetcherWithContextGetter( - const GURL& url, - URLFetcher::RequestType request_type, - net::URLRequestContextGetter* context_getter) { + void CreateFetcherWithContextGetter(const GURL& url, + URLFetcher::RequestType request_type, + URLRequestContextGetter* context_getter) { fetcher_.reset(new URLFetcherImpl(url, request_type, this)); fetcher_->SetRequestContext(context_getter); }
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 213307c..6032c4c 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -94,8 +94,7 @@ // completed. // // This functions fixes both those cases. -void ConvertRealLoadTimesToBlockingTimes( - net::LoadTimingInfo* load_timing_info) { +void ConvertRealLoadTimesToBlockingTimes(LoadTimingInfo* load_timing_info) { DCHECK(!load_timing_info->request_start.is_null()); // Earliest time possible for the request to be blocking on connect events. @@ -116,7 +115,7 @@ // Make sure connection times are after start and proxy times. - net::LoadTimingInfo::ConnectTiming* connect_timing = + LoadTimingInfo::ConnectTiming* connect_timing = &load_timing_info->connect_timing; if (!connect_timing->dns_start.is_null()) { DCHECK(!connect_timing->dns_end.is_null()); @@ -517,6 +516,10 @@ return; } + // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed. + tracked_objects::ScopedTracker tracking_profile2( + FROM_HERE_WITH_EXPLICIT_FUNCTION("456327 URLRequest::Start 2")); + StartJob(URLRequestJobManager::GetInstance()->CreateJob( this, network_delegate_)); } @@ -590,6 +593,10 @@ } void URLRequest::StartJob(URLRequestJob* job) { + // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION("456327 URLRequest::StartJob")); + DCHECK(!is_pending_); DCHECK(!job_.get());
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index aa589f56..bcb5c68 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -112,7 +112,7 @@ return true; } - bool OnCanAccessFile(const net::URLRequest& request, + bool OnCanAccessFile(const URLRequest& request, const base::FilePath& path) const override { return true; } @@ -189,7 +189,7 @@ URLRequestContextBuilder::SchemeFactory::SchemeFactory( const std::string& auth_scheme, - net::HttpAuthHandlerFactory* auth_handler_factory) + HttpAuthHandlerFactory* auth_handler_factory) : scheme(auth_scheme), factory(auth_handler_factory) { } @@ -256,12 +256,11 @@ if (net_log_) { storage->set_net_log(net_log_.release()); } else { - storage->set_net_log(new net::NetLog); + storage->set_net_log(new NetLog); } if (!host_resolver_) { - host_resolver_ = net::HostResolver::CreateDefaultResolver( - context->net_log()); + host_resolver_ = HostResolver::CreateDefaultResolver(context->net_log()); } storage->set_host_resolver(host_resolver_.Pass()); @@ -288,10 +287,9 @@ } storage->set_proxy_service(proxy_service_.release()); - storage->set_ssl_config_service(new net::SSLConfigServiceDefaults); + storage->set_ssl_config_service(new SSLConfigServiceDefaults); HttpAuthHandlerRegistryFactory* http_auth_handler_registry_factory = - net::HttpAuthHandlerRegistryFactory::CreateDefault( - context->host_resolver()); + HttpAuthHandlerRegistryFactory::CreateDefault(context->host_resolver()); for (size_t i = 0; i < extra_http_auth_handlers_.size(); ++i) { http_auth_handler_registry_factory->RegisterSchemeFactory( extra_http_auth_handlers_[i].scheme, @@ -310,7 +308,7 @@ new DefaultChannelIDStore(NULL), context->GetFileTaskRunner()))); } - storage->set_transport_security_state(new net::TransportSecurityState()); + storage->set_transport_security_state(new TransportSecurityState()); if (!transport_security_persister_path_.empty()) { context->set_transport_security_persister( make_scoped_ptr<TransportSecurityPersister>( @@ -321,14 +319,13 @@ } storage->set_http_server_properties( - scoped_ptr<net::HttpServerProperties>( - new net::HttpServerPropertiesImpl())); + scoped_ptr<HttpServerProperties>(new HttpServerPropertiesImpl())); storage->set_cert_verifier(CertVerifier::CreateDefault()); if (throttling_enabled_) storage->set_throttler_manager(new URLRequestThrottlerManager()); - net::HttpNetworkSession::Params network_session_params; + HttpNetworkSession::Params network_session_params; network_session_params.host_resolver = context->host_resolver(); network_session_params.cert_verifier = context->cert_verifier(); network_session_params.transport_security_state = @@ -367,7 +364,7 @@ HttpCache::BackendFactory* http_cache_backend = NULL; if (http_cache_params_.type == HttpCacheParams::DISK) { http_cache_backend = new HttpCache::DefaultBackend( - DISK_CACHE, net::CACHE_BACKEND_DEFAULT, http_cache_params_.path, + DISK_CACHE, CACHE_BACKEND_DEFAULT, http_cache_params_.path, http_cache_params_.max_size, context->GetFileTaskRunner()); } else { http_cache_backend = @@ -377,8 +374,8 @@ http_transaction_factory = new HttpCache( network_session_params, http_cache_backend); } else { - scoped_refptr<net::HttpNetworkSession> network_session( - new net::HttpNetworkSession(network_session_params)); + scoped_refptr<HttpNetworkSession> network_session( + new HttpNetworkSession(network_session_params)); http_transaction_factory = new HttpNetworkLayer(network_session.get()); }
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h index 53a1792a..b21a652 100644 --- a/net/url_request/url_request_context_builder.h +++ b/net/url_request/url_request_context_builder.h
@@ -70,7 +70,7 @@ HttpNetworkSessionParams(); ~HttpNetworkSessionParams(); - // These fields mirror those in net::HttpNetworkSession::Params; + // These fields mirror those in HttpNetworkSession::Params; bool ignore_certificate_errors; HostMappingRules* host_mapping_rules; uint16 testing_fixed_http_port; @@ -147,7 +147,7 @@ // and |factory| are provided. The builder takes ownership of the factory and // Build() must be called after this method. void add_http_auth_handler_factory(const std::string& scheme, - net::HttpAuthHandlerFactory* factory) { + HttpAuthHandlerFactory* factory) { extra_http_auth_handlers_.push_back(SchemeFactory(scheme, factory)); } @@ -155,7 +155,7 @@ void EnableHttpCache(const HttpCacheParams& params); void DisableHttpCache(); - // Override default net::HttpNetworkSession::Params settings. + // Override default HttpNetworkSession::Params settings. void set_http_network_session_params( const HttpNetworkSessionParams& http_network_session_params) { http_network_session_params_ = http_network_session_params; @@ -200,12 +200,11 @@ private: struct NET_EXPORT SchemeFactory { - SchemeFactory(const std::string& scheme, - net::HttpAuthHandlerFactory* factory); + SchemeFactory(const std::string& scheme, HttpAuthHandlerFactory* factory); ~SchemeFactory(); std::string scheme; - net::HttpAuthHandlerFactory* factory; + HttpAuthHandlerFactory* factory; }; std::string accept_language_;
diff --git a/net/url_request/url_request_context_builder_unittest.cc b/net/url_request/url_request_context_builder_unittest.cc index df1edafd..2252623aef 100644 --- a/net/url_request/url_request_context_builder_unittest.cc +++ b/net/url_request/url_request_context_builder_unittest.cc
@@ -106,7 +106,7 @@ TEST_F(URLRequestContextBuilderTest, ExtraHttpAuthHandlerFactory) { GURL gurl("www.google.com"); - const int kBasicReturnCode = net::OK; + const int kBasicReturnCode = OK; MockHttpAuthHandlerFactory* mock_factory_basic = new MockHttpAuthHandlerFactory(kBasicReturnCode); scoped_ptr<HttpAuthHandler> handler;
diff --git a/net/url_request/url_request_context_getter.cc b/net/url_request/url_request_context_getter.cc index 721a709..d743885 100644 --- a/net/url_request/url_request_context_getter.cc +++ b/net/url_request/url_request_context_getter.cc
@@ -36,14 +36,14 @@ } TrivialURLRequestContextGetter::TrivialURLRequestContextGetter( - net::URLRequestContext* context, + URLRequestContext* context, const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) - : context_(context), main_task_runner_(main_task_runner) {} + : context_(context), main_task_runner_(main_task_runner) { +} TrivialURLRequestContextGetter::~TrivialURLRequestContextGetter() {} -net::URLRequestContext* -TrivialURLRequestContextGetter::GetURLRequestContext() { +URLRequestContext* TrivialURLRequestContextGetter::GetURLRequestContext() { return context_; }
diff --git a/net/url_request/url_request_context_getter.h b/net/url_request/url_request_context_getter.h index 17d17bd0..3f3a850d 100644 --- a/net/url_request/url_request_context_getter.h +++ b/net/url_request/url_request_context_getter.h
@@ -19,7 +19,7 @@ struct URLRequestContextGetterTraits; -// Interface for retrieving an net::URLRequestContext. +// Interface for retrieving an URLRequestContext. class NET_EXPORT URLRequestContextGetter : public base::RefCountedThreadSafe<URLRequestContextGetter, URLRequestContextGetterTraits> { @@ -28,7 +28,7 @@ // Returns a SingleThreadTaskRunner corresponding to the thread on // which the network IO happens (the thread on which the returned - // net::URLRequestContext may be used). + // URLRequestContext may be used). virtual scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const = 0; @@ -57,12 +57,12 @@ class NET_EXPORT TrivialURLRequestContextGetter : public URLRequestContextGetter { public: - TrivialURLRequestContextGetter( - net::URLRequestContext* context, - const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner); + TrivialURLRequestContextGetter( + URLRequestContext* context, + const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner); - // net::URLRequestContextGetter implementation: - net::URLRequestContext* GetURLRequestContext() override; + // URLRequestContextGetter implementation: + URLRequestContext* GetURLRequestContext() override; scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner() const override; @@ -70,7 +70,7 @@ private: ~TrivialURLRequestContextGetter() override; - net::URLRequestContext* context_; + URLRequestContext* context_; const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; DISALLOW_COPY_AND_ASSIGN(TrivialURLRequestContextGetter);
diff --git a/net/url_request/url_request_data_job.cc b/net/url_request/url_request_data_job.cc index e074646..b4c7a67 100644 --- a/net/url_request/url_request_data_job.cc +++ b/net/url_request/url_request_data_job.cc
@@ -18,10 +18,10 @@ std::string* charset, std::string* data, HttpResponseHeaders* headers) { - if (!net::DataURL::Parse(url, mime_type, charset, data)) - return net::ERR_INVALID_URL; + if (!DataURL::Parse(url, mime_type, charset, data)) + return ERR_INVALID_URL; - // |mime_type| set by net::DataURL::Parse() is guaranteed to be in + // |mime_type| set by DataURL::Parse() is guaranteed to be in // token "/" token // form. |charset| is also guaranteed to be a token. @@ -40,7 +40,7 @@ headers->AddHeader("Access-Control-Allow-Origin: *"); } - return net::OK; + return OK; } URLRequestDataJob::URLRequestDataJob(
diff --git a/net/url_request/url_request_data_job_unittest.cc b/net/url_request/url_request_data_job_unittest.cc index 49a7ecd..8c6d0939 100644 --- a/net/url_request/url_request_data_job_unittest.cc +++ b/net/url_request/url_request_data_job_unittest.cc
@@ -18,19 +18,18 @@ std::string mime_type; std::string charset; std::string data; - scoped_refptr<net::HttpResponseHeaders> headers( - new net::HttpResponseHeaders(std::string())); + scoped_refptr<HttpResponseHeaders> headers( + new HttpResponseHeaders(std::string())); - ASSERT_EQ( - net::OK, - URLRequestDataJob::BuildResponse( - GURL("data:,Hello"), &mime_type, &charset, &data, headers.get())); + ASSERT_EQ(OK, + URLRequestDataJob::BuildResponse(GURL("data:,Hello"), &mime_type, + &charset, &data, headers.get())); EXPECT_EQ("text/plain", mime_type); EXPECT_EQ("US-ASCII", charset); EXPECT_EQ("Hello", data); - const net::HttpVersion& version = headers->GetParsedHttpVersion(); + const HttpVersion& version = headers->GetParsedHttpVersion(); EXPECT_EQ(1, version.major_value()); EXPECT_EQ(1, version.minor_value()); EXPECT_EQ("OK", headers->GetStatusText()); @@ -47,29 +46,26 @@ std::string mime_type; std::string charset; std::string data; - scoped_refptr<net::HttpResponseHeaders> headers( - new net::HttpResponseHeaders(std::string())); + scoped_refptr<HttpResponseHeaders> headers( + new HttpResponseHeaders(std::string())); - EXPECT_EQ( - net::ERR_INVALID_URL, - URLRequestDataJob::BuildResponse( - GURL("bogus"), &mime_type, &charset, &data, headers.get())); + EXPECT_EQ(ERR_INVALID_URL, + URLRequestDataJob::BuildResponse(GURL("bogus"), &mime_type, + &charset, &data, headers.get())); } TEST(BuildResponseTest, InvalidMimeType) { std::string mime_type; std::string charset; std::string data; - scoped_refptr<net::HttpResponseHeaders> headers( - new net::HttpResponseHeaders(std::string())); + scoped_refptr<HttpResponseHeaders> headers( + new HttpResponseHeaders(std::string())); // MIME type contains delimiters. Must be accepted but Content-Type header // should be generated as if the mediatype was text/plain. - EXPECT_EQ( - net::OK, - URLRequestDataJob::BuildResponse( - GURL("data:f(o/b)r,test"), - &mime_type, &charset, &data, headers.get())); + EXPECT_EQ(OK, URLRequestDataJob::BuildResponse(GURL("data:f(o/b)r,test"), + &mime_type, &charset, &data, + headers.get())); std::string value; EXPECT_TRUE(headers->GetNormalizedHeader("Content-Type", &value)); @@ -80,15 +76,13 @@ std::string mime_type; std::string charset; std::string data; - scoped_refptr<net::HttpResponseHeaders> headers( - new net::HttpResponseHeaders(std::string())); + scoped_refptr<HttpResponseHeaders> headers( + new HttpResponseHeaders(std::string())); // MIME type contains delimiters. Must be rejected. - EXPECT_EQ( - net::ERR_INVALID_URL, - URLRequestDataJob::BuildResponse( - GURL("data:text/html;charset=(),test"), - &mime_type, &charset, &data, headers.get())); + EXPECT_EQ(ERR_INVALID_URL, URLRequestDataJob::BuildResponse( + GURL("data:text/html;charset=(),test"), + &mime_type, &charset, &data, headers.get())); } } // namespace net
diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc index b1399189..864001e 100644 --- a/net/url_request/url_request_file_job.cc +++ b/net/url_request/url_request_file_job.cc
@@ -198,7 +198,7 @@ void URLRequestFileJob::OnSeekComplete(int64 result) { } -void URLRequestFileJob::OnReadComplete(net::IOBuffer* buf, int result) { +void URLRequestFileJob::OnReadComplete(IOBuffer* buf, int result) { } URLRequestFileJob::~URLRequestFileJob() { @@ -294,7 +294,7 @@ NotifyHeadersComplete(); } -void URLRequestFileJob::DidRead(scoped_refptr<net::IOBuffer> buf, int result) { +void URLRequestFileJob::DidRead(scoped_refptr<IOBuffer> buf, int result) { if (result > 0) { SetStatus(URLRequestStatus()); // Clear the IO_PENDING status remaining_bytes_ -= result;
diff --git a/net/url_request/url_request_file_job.h b/net/url_request/url_request_file_job.h index fe7c6e9..0436dac5 100644 --- a/net/url_request/url_request_file_job.h +++ b/net/url_request/url_request_file_job.h
@@ -46,7 +46,7 @@ // An interface for subclasses who wish to monitor read operations. virtual void OnSeekComplete(int64 result); - virtual void OnReadComplete(net::IOBuffer* buf, int result); + virtual void OnReadComplete(IOBuffer* buf, int result); protected: ~URLRequestFileJob() override; @@ -91,7 +91,7 @@ void DidSeek(int64 result); // Callback after data is asynchronously read from the file into |buf|. - void DidRead(scoped_refptr<net::IOBuffer> buf, int result); + void DidRead(scoped_refptr<IOBuffer> buf, int result); scoped_ptr<FileStream> stream_; FileMetaInfo meta_info_;
diff --git a/net/url_request/url_request_file_job_unittest.cc b/net/url_request/url_request_file_job_unittest.cc index af05259..427ed3d0 100644 --- a/net/url_request/url_request_file_job_unittest.cc +++ b/net/url_request/url_request_file_job_unittest.cc
@@ -82,16 +82,15 @@ return job; } - net::URLRequestJob* MaybeInterceptRedirect( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const GURL& location) const override { + URLRequestJob* MaybeInterceptRedirect(URLRequest* request, + NetworkDelegate* network_delegate, + const GURL& location) const override { return nullptr; } - net::URLRequestJob* MaybeInterceptResponse( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { + URLRequestJob* MaybeInterceptResponse( + URLRequest* request, + NetworkDelegate* network_delegate) const override { return nullptr; }
diff --git a/net/url_request/url_request_filter_unittest.cc b/net/url_request/url_request_filter_unittest.cc index 54e140142..fb66587d 100644 --- a/net/url_request/url_request_filter_unittest.cc +++ b/net/url_request/url_request_filter_unittest.cc
@@ -114,7 +114,7 @@ EXPECT_EQ(0, filter->hit_count()); filter->AddHostnameInterceptor( kUrl1.scheme(), kUrl1.host(), - scoped_ptr<net::URLRequestInterceptor>(new TestURLRequestInterceptor())); + scoped_ptr<URLRequestInterceptor>(new TestURLRequestInterceptor())); { scoped_refptr<URLRequestJob> found = filter->MaybeInterceptRequest(request1.get(), NULL); @@ -127,9 +127,8 @@ // Check URLRequestInterceptor URL matching. filter->ClearHandlers(); EXPECT_EQ(0, filter->hit_count()); - filter->AddUrlInterceptor( - kUrl2, - scoped_ptr<net::URLRequestInterceptor>(new TestURLRequestInterceptor())); + filter->AddUrlInterceptor(kUrl2, scoped_ptr<URLRequestInterceptor>( + new TestURLRequestInterceptor())); { scoped_refptr<URLRequestJob> found = filter->MaybeInterceptRequest(request2.get(), NULL);
diff --git a/net/url_request/url_request_ftp_job_unittest.cc b/net/url_request/url_request_ftp_job_unittest.cc index cbbf407..c7cdecf1 100644 --- a/net/url_request/url_request_ftp_job_unittest.cc +++ b/net/url_request/url_request_ftp_job_unittest.cc
@@ -36,7 +36,7 @@ int CreateProxyResolver( const scoped_refptr<ProxyResolverScriptData>& pac_script, scoped_ptr<ProxyResolver>* resolver, - const net::CompletionCallback& callback, + const CompletionCallback& callback, scoped_ptr<Request>* request) override { resolver->reset(new MockAsyncProxyResolver()); return OK; @@ -287,7 +287,7 @@ EXPECT_TRUE(url_request->status().is_success()); EXPECT_TRUE(url_request->proxy_server().Equals( - net::HostPortPair::FromString("localhost:80"))); + HostPortPair::FromString("localhost:80"))); EXPECT_EQ(1, network_delegate()->completed_requests()); EXPECT_EQ(0, network_delegate()->error_count()); EXPECT_FALSE(request_delegate.auth_required_called()); @@ -337,7 +337,7 @@ EXPECT_TRUE(url_request->status().is_success()); EXPECT_TRUE(url_request->proxy_server().Equals( - net::HostPortPair::FromString("localhost:80"))); + HostPortPair::FromString("localhost:80"))); EXPECT_EQ(1, network_delegate()->completed_requests()); EXPECT_EQ(0, network_delegate()->error_count()); EXPECT_TRUE(request_delegate.auth_required_called()); @@ -627,7 +627,7 @@ EXPECT_TRUE(url_request1->status().is_success()); EXPECT_TRUE(url_request1->proxy_server().Equals( - net::HostPortPair::FromString("localhost:80"))); + HostPortPair::FromString("localhost:80"))); EXPECT_EQ(1, network_delegate()->completed_requests()); EXPECT_EQ(0, network_delegate()->error_count()); EXPECT_FALSE(request_delegate1.auth_required_called());
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 91ba0fb..114a8bd 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -225,6 +225,10 @@ } void URLRequestHttpJob::Start() { + // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION("456327 URLRequestHttpJob::Start")); + DCHECK(!transaction_.get()); // URLRequest::SetReferrer ensures that we do not send username and password @@ -398,6 +402,11 @@ } void URLRequestHttpJob::StartTransaction() { + // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "456327 URLRequestHttpJob::StartTransaction")); + if (network_delegate()) { OnCallToDelegate(); int rv = network_delegate()->NotifyBeforeSendHeaders( @@ -421,6 +430,11 @@ } void URLRequestHttpJob::MaybeStartTransactionInternal(int result) { + // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed. + tracked_objects::ScopedTracker tracking_profile( + FROM_HERE_WITH_EXPLICIT_FUNCTION( + "456327 URLRequestHttpJob::MaybeStartTransactionInternal")); + OnCallToDelegateComplete(); if (result == OK) { StartTransactionInternal(); @@ -660,7 +674,7 @@ // End of the call started in OnStartCompleted. OnCallToDelegateComplete(); - if (result != net::OK) { + if (result != OK) { std::string source("delegate"); request_->net_log().AddEvent(NetLog::TYPE_CANCELLED, NetLog::StringCallback("source", &source)); @@ -708,11 +722,9 @@ options.set_include_httponly(); options.set_server_time(response_date_); - net::CookieStore::SetCookiesCallback callback( - base::Bind(&URLRequestHttpJob::OnCookieSaved, - weak_factory_.GetWeakPtr(), - save_next_cookie_running, - callback_pending)); + CookieStore::SetCookiesCallback callback(base::Bind( + &URLRequestHttpJob::OnCookieSaved, weak_factory_.GetWeakPtr(), + save_next_cookie_running, callback_pending)); // Loop through the cookies as long as SetCookieWithOptionsAsync completes // synchronously. @@ -884,8 +896,8 @@ headers.get(), &override_response_headers_, &allowed_unsafe_redirect_url_); - if (error != net::OK) { - if (error == net::ERR_IO_PENDING) { + if (error != OK) { + if (error == ERR_IO_PENDING) { awaiting_callback_ = true; } else { std::string source("delegate"); @@ -899,7 +911,7 @@ } } - SaveCookiesAndNotifyHeadersComplete(net::OK); + SaveCookiesAndNotifyHeadersComplete(OK); } else if (IsCertificateError(result)) { // We encountered an SSL certificate error. if (result == ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY || @@ -1255,8 +1267,8 @@ // the uncompressed size. Although this violates the HTTP spec we want to // support it (as IE and FireFox do), but *only* for an exact match. // See http://crbug.com/79694. - if (rv == net::ERR_CONTENT_LENGTH_MISMATCH || - rv == net::ERR_INCOMPLETE_CHUNKED_ENCODING) { + if (rv == ERR_CONTENT_LENGTH_MISMATCH || + rv == ERR_INCOMPLETE_CHUNKED_ENCODING) { if (request_ && request_->response_headers()) { int64 expected_length = request_->response_headers()->GetContentLength(); VLOG(1) << __FUNCTION__ << "() "
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h index 1931b70..f45058e 100644 --- a/net/url_request/url_request_http_job.h +++ b/net/url_request/url_request_http_job.h
@@ -87,7 +87,7 @@ // Processes the Public-Key-Pins header, if one exists. void ProcessPublicKeyPinsHeader(); - // |result| should be net::OK, or the request is canceled. + // |result| should be OK, or the request is canceled. void OnHeadersReceivedCallback(int result); void OnStartCompleted(int result); void OnReadCompleted(int result); @@ -138,7 +138,7 @@ // Starts the transaction if extensions using the webrequest API do not // object. void StartTransaction(); - // If |result| is net::OK, calls StartTransactionInternal. Otherwise notifies + // If |result| is OK, calls StartTransactionInternal. Otherwise notifies // cancellation. void MaybeStartTransactionInternal(int result); void StartTransactionInternal();
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index 106cb856..5b14b6b 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc
@@ -280,8 +280,8 @@ const GURL& redirect_destination) { GURL original_referrer(referrer); bool secure_referrer_but_insecure_destination = - original_referrer.SchemeIsSecure() && - !redirect_destination.SchemeIsSecure(); + original_referrer.SchemeIsCryptographic() && + !redirect_destination.SchemeIsCryptographic(); bool same_origin = original_referrer.GetOrigin() == redirect_destination.GetOrigin(); switch (policy) {
diff --git a/net/url_request/url_request_redirect_job.cc b/net/url_request/url_request_redirect_job.cc index 09e4abc..3901aa5 100644 --- a/net/url_request/url_request_redirect_job.cc +++ b/net/url_request/url_request_redirect_job.cc
@@ -91,8 +91,7 @@ redirect_reason_.c_str()); std::string http_origin; - const net::HttpRequestHeaders& request_headers = - request_->extra_request_headers(); + const HttpRequestHeaders& request_headers = request_->extra_request_headers(); if (request_headers.GetHeader("Origin", &http_origin)) { // If this redirect is used in a cross-origin request, add CORS headers to // make sure that the redirect gets through. Note that the destination URL
diff --git a/net/url_request/url_request_simple_job.cc b/net/url_request/url_request_simple_job.cc index 46d9c38a9..bbb9178 100644 --- a/net/url_request/url_request_simple_job.cc +++ b/net/url_request/url_request_simple_job.cc
@@ -77,12 +77,12 @@ base::Bind(&URLRequestSimpleJob::OnReadCompleted, weak_factory_.GetWeakPtr(), buf_size)); next_data_offset_ += buf_size; - SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0)); + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); return false; } void URLRequestSimpleJob::OnReadCompleted(int bytes_read) { - SetStatus(net::URLRequestStatus()); + SetStatus(URLRequestStatus()); NotifyReadComplete(bytes_read); }
diff --git a/net/url_request/url_request_simple_job_unittest.cc b/net/url_request/url_request_simple_job_unittest.cc index cf8e34a..1f8d5a4 100644 --- a/net/url_request/url_request_simple_job_unittest.cc +++ b/net/url_request/url_request_simple_job_unittest.cc
@@ -68,12 +68,12 @@ DISALLOW_COPY_AND_ASSIGN(MockSimpleJob); }; -class CancelURLRequestDelegate : public net::URLRequest::Delegate { +class CancelURLRequestDelegate : public URLRequest::Delegate { public: explicit CancelURLRequestDelegate() : buf_(new IOBuffer(kBufferSize)), run_loop_(new base::RunLoop) {} - void OnResponseStarted(net::URLRequest* request) override { + void OnResponseStarted(URLRequest* request) override { int bytes_read = 0; EXPECT_FALSE(request->Read(buf_.get(), kBufferSize, &bytes_read)); EXPECT_TRUE(request->status().is_io_pending());
diff --git a/net/url_request/url_request_test_job.h b/net/url_request/url_request_test_job.h index fbdbe0f..cb8dcd9 100644 --- a/net/url_request/url_request_test_job.h +++ b/net/url_request/url_request_test_job.h
@@ -53,7 +53,7 @@ // url. The headers should include the HTTP status line and be formatted as // expected by HttpResponseHeaders. URLRequestTestJob(URLRequest* request, - net::NetworkDelegate* network_delegate, + NetworkDelegate* network_delegate, const std::string& response_headers, const std::string& response_data, bool auto_advance);
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index ebccd876..f402aa5 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc
@@ -394,9 +394,9 @@ } void TestNetworkDelegate::OnBeforeSendProxyHeaders( - net::URLRequest* request, - const net::ProxyInfo& proxy_info, - net::HttpRequestHeaders* headers) { + URLRequest* request, + const ProxyInfo& proxy_info, + HttpRequestHeaders* headers) { ++observed_before_proxy_headers_sent_callbacks_; last_observed_proxy_ = proxy_info.proxy_server().host_port_pair(); } @@ -439,7 +439,7 @@ if (!redirect_on_headers_received_url_.is_empty()) { *override_response_headers = - new net::HttpResponseHeaders(original_response_headers->raw_headers()); + new HttpResponseHeaders(original_response_headers->raw_headers()); (*override_response_headers)->ReplaceStatusLine("HTTP/1.1 302 Found"); (*override_response_headers)->RemoveHeader("Location"); (*override_response_headers)->AddHeader(
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index c856c985..cfa75f007 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h
@@ -300,9 +300,9 @@ int OnBeforeSendHeaders(URLRequest* request, const CompletionCallback& callback, HttpRequestHeaders* headers) override; - void OnBeforeSendProxyHeaders(net::URLRequest* request, - const net::ProxyInfo& proxy_info, - net::HttpRequestHeaders* headers) override; + void OnBeforeSendProxyHeaders(URLRequest* request, + const ProxyInfo& proxy_info, + HttpRequestHeaders* headers) override; void OnSendHeaders(URLRequest* request, const HttpRequestHeaders& headers) override; int OnHeadersReceived(
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 18ec0f3..ded1f5cc 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -58,6 +58,7 @@ #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/http/http_util.h" +#include "net/log/captured_net_log_entry.h" #include "net/log/net_log.h" #include "net/log/net_log_unittest.h" #include "net/log/test_net_log.h" @@ -4163,7 +4164,7 @@ // DELEGATE_INFO NetLog events that an AsyncDelegateLogger should have // recorded. Returns the index of entry after the expected number of // events this logged, or entries.size() if there aren't enough entries. - static size_t CheckDelegateInfo(const TestNetLog::CapturedEntryList& entries, + static size_t CheckDelegateInfo(const CapturedNetLogEntry::List& entries, size_t log_position) { // There should be 4 DELEGATE_INFO events: Two begins and two ends. if (log_position + 3 >= entries.size()) { @@ -4198,7 +4199,7 @@ // Find delegate request begin and end messages for OnBeforeNetworkStart. // Returns the position of the end message. static size_t ExpectBeforeNetworkEvents( - const TestNetLog::CapturedEntryList& entries, + const CapturedNetLogEntry::List& entries, size_t log_position) { log_position = ExpectLogContainsSomewhereAfter(entries, @@ -4465,7 +4466,7 @@ EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status()); } - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log_.GetEntries(&entries); size_t log_position = ExpectLogContainsSomewhereAfter( entries, @@ -4510,7 +4511,7 @@ EXPECT_EQ(1, network_delegate.destroyed_requests()); size_t log_position = 0; - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log_.GetEntries(&entries); for (size_t i = 0; i < 3; ++i) { log_position = ExpectLogContainsSomewhereAfter( @@ -4567,7 +4568,7 @@ EXPECT_EQ(1, network_delegate.destroyed_requests()); size_t log_position = 0; - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log_.GetEntries(&entries); // The NetworkDelegate logged information in OnBeforeURLRequest, // OnBeforeSendHeaders, and OnHeadersReceived. @@ -4649,7 +4650,7 @@ EXPECT_EQ(1, network_delegate.destroyed_requests()); size_t log_position = 0; - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log_.GetEntries(&entries); // The NetworkDelegate should have logged information in OnBeforeURLRequest, // OnBeforeSendHeaders, OnHeadersReceived, OnAuthRequired, and then again in @@ -4706,7 +4707,7 @@ EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status()); } - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log_.GetEntries(&entries); size_t log_position = 0; @@ -4759,7 +4760,7 @@ EXPECT_EQ(URLRequestStatus::SUCCESS, r->status().status()); } - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log_.GetEntries(&entries); // Delegate info should only have been logged in OnReceivedRedirect and @@ -4821,7 +4822,7 @@ EXPECT_EQ(URLRequestStatus::CANCELED, r->status().status()); } - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log.GetEntries(&entries); // Delegate info is always logged in both OnReceivedRedirect and @@ -7301,7 +7302,7 @@ EXPECT_EQ(expected_version, SSLConnectionStatusToVersion(r->ssl_info().connection_status)); - TestNetLog::CapturedEntryList entries; + CapturedNetLogEntry::List entries; net_log.GetEntries(&entries); ExpectLogContainsSomewhere(entries, 0, NetLog::TYPE_SSL_CIPHER_FALLBACK, NetLog::PHASE_NONE);
diff --git a/net/url_request/view_cache_helper_unittest.cc b/net/url_request/view_cache_helper_unittest.cc index 097eade9..213a6f1 100644 --- a/net/url_request/view_cache_helper_unittest.cc +++ b/net/url_request/view_cache_helper_unittest.cc
@@ -51,7 +51,7 @@ reinterpret_cast<const char*>(pickle.data()))); int len = static_cast<int>(pickle.size()); - net::TestCompletionCallback cb; + TestCompletionCallback cb; int rv = entry->WriteData(0, 0, buf.get(), len, cb.callback(), true); ASSERT_EQ(len, cb.GetResult(rv)); } @@ -64,7 +64,7 @@ scoped_refptr<IOBuffer> buf(new IOBuffer(len)); memcpy(buf->data(), data.data(), data.length()); - net::TestCompletionCallback cb; + TestCompletionCallback cb; int rv = entry->WriteData(index, 0, buf.get(), len, cb.callback(), true); ASSERT_EQ(len, cb.GetResult(rv)); } @@ -72,7 +72,7 @@ void WriteToEntry(disk_cache::Backend* cache, const std::string& key, const std::string& data0, const std::string& data1, const std::string& data2) { - net::TestCompletionCallback cb; + TestCompletionCallback cb; disk_cache::Entry* entry; int rv = cache->CreateEntry(key, &entry, cb.callback()); rv = cb.GetResult(rv); @@ -89,7 +89,7 @@ } void FillCache(URLRequestContext* context) { - net::TestCompletionCallback cb; + TestCompletionCallback cb; disk_cache::Backend* cache; int rv = context->http_transaction_factory()->GetCache()->GetBackend( @@ -185,7 +185,7 @@ TestURLRequestContext context; ViewCacheHelper helper; - net::TestCompletionCallback cb; + TestCompletionCallback cb; disk_cache::Backend* cache; int rv = context.http_transaction_factory()->GetCache()->GetBackend(
diff --git a/net/websockets/websocket_frame.cc b/net/websockets/websocket_frame.cc index a90cc0a..3782f282 100644 --- a/net/websockets/websocket_frame.cc +++ b/net/websockets/websocket_frame.cc
@@ -13,6 +13,8 @@ #include "net/base/io_buffer.h" #include "net/base/net_errors.h" +namespace net { + namespace { const uint8 kFinalBit = 0x80; @@ -26,20 +28,18 @@ const uint64 kPayloadLengthWithEightByteExtendedLengthField = 127; inline void MaskWebSocketFramePayloadByBytes( - const net::WebSocketMaskingKey& masking_key, + const WebSocketMaskingKey& masking_key, size_t masking_key_offset, char* const begin, char* const end) { for (char* masked = begin; masked != end; ++masked) { *masked ^= masking_key.key[masking_key_offset++]; - if (masking_key_offset == net::WebSocketFrameHeader::kMaskingKeyLength) + if (masking_key_offset == WebSocketFrameHeader::kMaskingKeyLength) masking_key_offset = 0; } } -} // Unnamed namespace. - -namespace net { +} // namespace scoped_ptr<WebSocketFrameHeader> WebSocketFrameHeader::Clone() const { scoped_ptr<WebSocketFrameHeader> ret(new WebSocketFrameHeader(opcode));
diff --git a/ppapi/BUILD.gn b/ppapi/BUILD.gn index 726577e..07b5877 100644 --- a/ppapi/BUILD.gn +++ b/ppapi/BUILD.gn
@@ -44,6 +44,18 @@ ] } +shared_library("power_saver_test_plugin") { + sources = [ + "tests/power_saver_test_plugin.cc", + "tests/test_utils.cc", + ] + + deps = [ + "//ppapi/cpp", + "//ppapi/shared_impl", + ] +} + test("ppapi_unittests") { sources = [ "host/resource_message_filter_unittest.cc",
diff --git a/ppapi/api/private/ppb_testing_private.idl b/ppapi/api/private/ppb_testing_private.idl index 0ede2de2..8de73f7 100644 --- a/ppapi/api/private/ppb_testing_private.idl +++ b/ppapi/api/private/ppb_testing_private.idl
@@ -77,6 +77,11 @@ * otherwise. */ PP_Bool IsOutOfProcess(); + + /** + * Returns PP_TRUE if the plugin is peripheral, PP_FALSE otherwise. + */ + PP_Bool IsPeripheral([in] PP_Instance instance); /** * Passes the input event to the browser, which sends it back to the
diff --git a/ppapi/c/private/ppb_testing_private.h b/ppapi/c/private/ppb_testing_private.h index 3d35ec7..5003d75 100644 --- a/ppapi/c/private/ppb_testing_private.h +++ b/ppapi/c/private/ppb_testing_private.h
@@ -93,6 +93,10 @@ */ PP_Bool (*IsOutOfProcess)(void); /** + * Returns PP_TRUE if the plugin is peripheral, PP_FALSE otherwise. + */ + PP_Bool (*IsPeripheral)(PP_Instance instance); + /** * Passes the input event to the browser, which sends it back to the * plugin. The plugin should implement PPP_InputEvent and register for * the input event type.
diff --git a/ppapi/host/ppapi_host.h b/ppapi/host/ppapi_host.h index 3f6e80de..d4361dfe 100644 --- a/ppapi/host/ppapi_host.h +++ b/ppapi/host/ppapi_host.h
@@ -46,15 +46,15 @@ // (AddHostFactoryFilter) and instance messages (AddInstanceMessageFilter) // after construction. PpapiHost(IPC::Sender* sender, const PpapiPermissions& perms); - virtual ~PpapiHost(); + ~PpapiHost() override; const PpapiPermissions& permissions() const { return permissions_; } // Sender implementation. Forwards to the sender_. - virtual bool Send(IPC::Message* msg) override; + bool Send(IPC::Message* msg) override; // Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; // Sends the given reply message to the plugin. void SendReply(const ReplyMessageContext& context,
diff --git a/ppapi/host/resource_host.h b/ppapi/host/resource_host.h index 517cf0a..6bf4996 100644 --- a/ppapi/host/resource_host.h +++ b/ppapi/host/resource_host.h
@@ -31,7 +31,7 @@ class PPAPI_HOST_EXPORT ResourceHost : public ResourceMessageHandler { public: ResourceHost(PpapiHost* host, PP_Instance instance, PP_Resource resource); - virtual ~ResourceHost(); + ~ResourceHost() override; PpapiHost* host() { return host_; } PP_Instance pp_instance() const { return pp_instance_; } @@ -40,8 +40,8 @@ // This runs any message filters in |message_filters_|. If the message is not // handled by these filters then the host's own message handler is run. True // is always returned (the message will always be handled in some way). - virtual bool HandleMessage(const IPC::Message& msg, - HostMessageContext* context) override; + bool HandleMessage(const IPC::Message& msg, + HostMessageContext* context) override; // Sets the PP_Resource ID when the plugin attaches to a pending resource // host. This will notify subclasses by calling @@ -51,8 +51,8 @@ // PpapiHostMsg_AttachToPendingHost. void SetPPResourceForPendingHost(PP_Resource pp_resource); - virtual void SendReply(const ReplyMessageContext& context, - const IPC::Message& msg) override; + void SendReply(const ReplyMessageContext& context, + const IPC::Message& msg) override; // Simple RTTI. A subclass that is a host for one of these APIs will override // the appropriate function and return true.
diff --git a/ppapi/host/resource_message_filter.h b/ppapi/host/resource_message_filter.h index af7a4f6..5488f98 100644 --- a/ppapi/host/resource_message_filter.h +++ b/ppapi/host/resource_message_filter.h
@@ -48,16 +48,15 @@ // subclass as follows: // class MyMessageFilter : public ResourceMessageFilter { // protected: -// virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage( +// scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage( // const IPC::Message& message) override { // if (message.type() == MyMessage::ID) // return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); // return NULL; // } // -// virtual int32_t OnResourceMessageReceived( -// const IPC::Message& msg, -// HostMessageContext* context) override { +// int32_t OnResourceMessageReceived(const IPC::Message& msg, +// HostMessageContext* context) override { // IPC_BEGIN_MESSAGE_MAP(MyMessageFilter, msg) // PPAPI_DISPATCH_HOST_RESOURCE_CALL(MyMessage, OnMyMessage) // IPC_END_MESSAGE_MAP() @@ -96,15 +95,15 @@ // This will dispatch the message handler on the target thread. It returns // true if the message was handled by this filter and false otherwise. - virtual bool HandleMessage(const IPC::Message& msg, - HostMessageContext* context) override; + bool HandleMessage(const IPC::Message& msg, + HostMessageContext* context) override; // This can be called from any thread. - virtual void SendReply(const ReplyMessageContext& context, - const IPC::Message& msg) override; + void SendReply(const ReplyMessageContext& context, + const IPC::Message& msg) override; protected: - virtual ~ResourceMessageFilter(); + ~ResourceMessageFilter() override; // Please see the comments of |resource_host_| for on which thread it can be // used and when it is NULL.
diff --git a/ppapi/host/resource_message_filter_unittest.cc b/ppapi/host/resource_message_filter_unittest.cc index fbd8de4..59bbc59 100644 --- a/ppapi/host/resource_message_filter_unittest.cc +++ b/ppapi/host/resource_message_filter_unittest.cc
@@ -59,9 +59,8 @@ AddFilter(filter); } - virtual int32_t OnResourceMessageReceived( - const IPC::Message& msg, - HostMessageContext* context) override { + int32_t OnResourceMessageReceived(const IPC::Message& msg, + HostMessageContext* context) override { last_handled_msg_ = msg; if (msg.type() == msg_type_) { context->reply_msg = IPC::Message(0, reply_msg_type_, @@ -71,8 +70,8 @@ return PP_ERROR_FAILED; } - virtual void SendReply(const ReplyMessageContext& context, - const IPC::Message& msg) override { + void SendReply(const ReplyMessageContext& context, + const IPC::Message& msg) override { last_reply_msg_ = msg; last_reply_message_loop_ = base::MessageLoop::current(); g_handler_completion.Signal(); @@ -110,14 +109,14 @@ const IPC::Message& last_handled_msg() const { return last_handled_msg_; } base::MessageLoop* last_message_loop() const { return last_message_loop_; } - virtual scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage( + scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage( const IPC::Message& msg) override { if (msg.type() == msg_type_) return message_loop_proxy_; return NULL; } - virtual int32_t OnResourceMessageReceived( + int32_t OnResourceMessageReceived( const IPC::Message& msg, HostMessageContext* context) override { last_handled_msg_ = msg;
diff --git a/ppapi/nacl_irt/irt_ppapi.cc b/ppapi/nacl_irt/irt_ppapi.cc index a298a23..a9c13eb8 100644 --- a/ppapi/nacl_irt/irt_ppapi.cc +++ b/ppapi/nacl_irt/irt_ppapi.cc
@@ -5,7 +5,6 @@ #include <unistd.h> #include "build/build_config.h" -#include "mojo/nacl/mojo_irt.h" #include "native_client/src/public/irt_core.h" #include "native_client/src/trusted/service_runtime/include/sys/unistd.h" #include "native_client/src/untrusted/irt/irt.h" @@ -92,11 +91,5 @@ if (result != 0) return result; -#if defined(OS_NACL_SFI) - result = mojo_irt_query(interface_ident, table, tablesize); - if (result != 0) - return result; -#endif - return nacl_irt_query_core(interface_ident, table, tablesize); }
diff --git a/ppapi/nacl_irt/manifest_service.cc b/ppapi/nacl_irt/manifest_service.cc index cc5a267..a97c5d4 100644 --- a/ppapi/nacl_irt/manifest_service.cc +++ b/ppapi/nacl_irt/manifest_service.cc
@@ -33,7 +33,7 @@ true /* manual_reset */, false /* initially_signaled */) { } - virtual bool Send(IPC::Message* message) override { + bool Send(IPC::Message* message) override { // Wait until set up is actually done. connected_event_.Wait(); return SyncMessageFilter::Send(message); @@ -41,19 +41,19 @@ // When set up is done, OnFilterAdded is called on IO thread. Unblocks the // Send(). - virtual void OnFilterAdded(IPC::Sender* sender) override { + void OnFilterAdded(IPC::Sender* sender) override { SyncMessageFilter::OnFilterAdded(sender); connected_event_.Signal(); } // If an error is found, unblocks the Send(), too, to return an error. - virtual void OnChannelError() override { + void OnChannelError() override { SyncMessageFilter::OnChannelError(); connected_event_.Signal(); } // Similar to OnChannelError, unblocks the Send() on the channel closing. - virtual void OnChannelClosing() override { + void OnChannelClosing() override { SyncMessageFilter::OnChannelClosing(); connected_event_.Signal(); }
diff --git a/ppapi/nacl_irt/ppapi_dispatcher.h b/ppapi/nacl_irt/ppapi_dispatcher.h index 0b43606..c03b8b0 100644 --- a/ppapi/nacl_irt/ppapi_dispatcher.h +++ b/ppapi/nacl_irt/ppapi_dispatcher.h
@@ -52,34 +52,32 @@ int renderer_ipc_fd); // PluginDispatcher::PluginDelegate implementation. - virtual base::MessageLoopProxy* GetIPCMessageLoop() override; - virtual base::WaitableEvent* GetShutdownEvent() override; - virtual IPC::PlatformFileForTransit ShareHandleWithRemote( + base::MessageLoopProxy* GetIPCMessageLoop() override; + base::WaitableEvent* GetShutdownEvent() override; + IPC::PlatformFileForTransit ShareHandleWithRemote( base::PlatformFile handle, base::ProcessId peer_pid, bool should_close_source) override; - virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() override; - virtual uint32 Register( - proxy::PluginDispatcher* plugin_dispatcher) override; - virtual void Unregister(uint32 plugin_dispatcher_id) override; + std::set<PP_Instance>* GetGloballySeenInstanceIDSet() override; + uint32 Register(proxy::PluginDispatcher* plugin_dispatcher) override; + void Unregister(uint32 plugin_dispatcher_id) override; // PluginProxyDelegate implementation. - virtual IPC::Sender* GetBrowserSender() override; - virtual std::string GetUILanguage() override; - virtual void PreCacheFont(const void* logfontw) override; - virtual void SetActiveURL(const std::string& url) override; - virtual PP_Resource CreateBrowserFont( - proxy::Connection connection, - PP_Instance instance, - const PP_BrowserFont_Trusted_Description& desc, - const Preferences& prefs) override; + IPC::Sender* GetBrowserSender() override; + std::string GetUILanguage() override; + void PreCacheFont(const void* logfontw) override; + void SetActiveURL(const std::string& url) override; + PP_Resource CreateBrowserFont(proxy::Connection connection, + PP_Instance instance, + const PP_BrowserFont_Trusted_Description& desc, + const Preferences& prefs) override; // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void OnChannelError() override; + bool OnMessageReceived(const IPC::Message& message) override; + void OnChannelError() override; // IPC::Sender implementation - virtual bool Send(IPC::Message* message) override; + bool Send(IPC::Message* message) override; private: void OnMsgInitializeNaClDispatcher(const PpapiNaClPluginArgs& args);
diff --git a/ppapi/native_client/BUILD.gn b/ppapi/native_client/BUILD.gn index 0cb4c00..488f44f3 100644 --- a/ppapi/native_client/BUILD.gn +++ b/ppapi/native_client/BUILD.gn
@@ -22,7 +22,6 @@ "//gpu/ipc", "//ipc", "//media:shared_memory_support", - "//mojo/nacl:irt_mojo_sources", "//native_client/src/untrusted/irt:irt_core_lib", "//native_client/src/shared/srpc", "//native_client/src/shared/platform",
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c index 228c75ce..022430a0 100644 --- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c +++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
@@ -4133,6 +4133,11 @@ return iface->IsOutOfProcess(); } +static PP_Bool Pnacl_M33_PPB_Testing_Private_IsPeripheral(PP_Instance instance) { + const struct PPB_Testing_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_Testing_Private_1_0.real_iface; + return iface->IsPeripheral(instance); +} + static void Pnacl_M33_PPB_Testing_Private_SimulateInputEvent(PP_Instance instance, PP_Resource input_event) { const struct PPB_Testing_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_Testing_Private_1_0.real_iface; iface->SimulateInputEvent(instance, input_event); @@ -5628,6 +5633,7 @@ .QuitMessageLoop = (void (*)(PP_Instance instance))&Pnacl_M33_PPB_Testing_Private_QuitMessageLoop, .GetLiveObjectsForInstance = (uint32_t (*)(PP_Instance instance))&Pnacl_M33_PPB_Testing_Private_GetLiveObjectsForInstance, .IsOutOfProcess = (PP_Bool (*)(void))&Pnacl_M33_PPB_Testing_Private_IsOutOfProcess, + .IsPeripheral = (PP_Bool (*)(PP_Instance instance))&Pnacl_M33_PPB_Testing_Private_IsPeripheral, .SimulateInputEvent = (void (*)(PP_Instance instance, PP_Resource input_event))&Pnacl_M33_PPB_Testing_Private_SimulateInputEvent, .GetDocumentURL = (struct PP_Var (*)(PP_Instance instance, struct PP_URLComponents_Dev* components))&Pnacl_M33_PPB_Testing_Private_GetDocumentURL, .GetLiveVars = (uint32_t (*)(struct PP_Var live_vars[], uint32_t array_size))&Pnacl_M33_PPB_Testing_Private_GetLiveVars,
diff --git a/ppapi/ppapi_proxy_nacl.gyp b/ppapi/ppapi_proxy_nacl.gyp index 7740a4e7..d015758 100644 --- a/ppapi/ppapi_proxy_nacl.gyp +++ b/ppapi/ppapi_proxy_nacl.gyp
@@ -41,7 +41,6 @@ '../gpu/gpu_nacl.gyp:gpu_ipc_nacl', '../ipc/ipc_nacl.gyp:ipc_nacl', '../ipc/ipc_nacl.gyp:ipc_nacl_nonsfi', - '../mojo/mojo_nacl.gyp:monacl_codegen', '../ppapi/ppapi_ipc_nacl.gyp:ppapi_ipc_nacl', '../ppapi/ppapi_shared_nacl.gyp:ppapi_shared_nacl', '../third_party/WebKit/public/blink_headers.gyp:blink_headers',
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi index 09d1c6c..ea23adb9 100644 --- a/ppapi/ppapi_tests.gypi +++ b/ppapi/ppapi_tests.gypi
@@ -80,6 +80,26 @@ # ], }, { + # GN version: //ppapi:power_saver_test_plugin + 'target_name': 'power_saver_test_plugin', + 'type': 'loadable_module', + 'sources': [ + 'tests/power_saver_test_plugin.cc', + 'tests/test_utils.cc', + ], + 'dependencies': [ + 'ppapi.gyp:ppapi_cpp', + 'ppapi_internal.gyp:ppapi_shared', + ], + 'conditions': [ + ['OS=="mac"', { + 'mac_bundle': 1, + 'product_name': 'power_saver_test_plugin', + 'product_extension': 'plugin', + }], + ], + }, + { # GN version: //ppapi/proxy:test_support # //ppapi/shared_impl:test_support 'target_name': 'ppapi_unittest_shared',
diff --git a/ppapi/ppapi_tests_mojo.gyp b/ppapi/ppapi_tests_mojo.gyp deleted file mode 100644 index 794a8b64..0000000 --- a/ppapi/ppapi_tests_mojo.gyp +++ /dev/null
@@ -1,51 +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. - -{ - 'includes': [ - 'ppapi_nacl_test_common.gypi', - ], - 'targets': [ - { - 'target_name': 'ppapi_tests_mojo', - 'type': 'none', - 'variables': { - 'nexe_target': 'ppapi_tests_mojo', - # Only the pnacl toolchain can be used with mojo dependencies - # currently. - 'build_newlib': 0, - 'build_glibc': 0, - 'build_pnacl_newlib': 1, - # TODO(teravest): Build a translated nexe as well. - 'nexe_destination_dir': 'test_data/ppapi/tests/mojo', - 'sources': [ - 'tests/mojo/test_mojo.cc', - 'tests/mojo/test_mojo.h', - - # Test support files. - 'tests/test_case.cc', - 'tests/test_case.h', - 'tests/test_utils.cc', - 'tests/test_utils.h', - 'tests/testing_instance.cc', - 'tests/testing_instance.h', - ], - 'link_flags': [ - '-lmojo', - '-limc_syscalls', - '-lppapi_cpp', - '-lppapi', - ], - }, - 'dependencies': [ - '../mojo/mojo_nacl_untrusted.gyp:libmojo', - '../mojo/mojo_nacl.gyp:monacl_codegen', - '../native_client/src/untrusted/nacl/nacl.gyp:imc_syscalls_lib', - '../third_party/mojo/mojo_public.gyp:mojo_system_placeholder', - 'native_client/native_client.gyp:ppapi_lib', - 'ppapi_nacl.gyp:ppapi_cpp_lib', - ], - }, - ], -}
diff --git a/ppapi/proxy/BUILD.gn b/ppapi/proxy/BUILD.gn index f3f07f39..8e260088 100644 --- a/ppapi/proxy/BUILD.gn +++ b/ppapi/proxy/BUILD.gn
@@ -276,10 +276,7 @@ ] if (is_nacl) { - deps += [ - "//ui/events:latency_info", - "//mojo/nacl:mojo", - ] + deps += [ "//ui/events:latency_info" ] } else { deps += [ "//base/third_party/dynamic_annotations",
diff --git a/ppapi/proxy/audio_buffer_resource.h b/ppapi/proxy/audio_buffer_resource.h index ea5adec..8f1e22f 100644 --- a/ppapi/proxy/audio_buffer_resource.h +++ b/ppapi/proxy/audio_buffer_resource.h
@@ -25,23 +25,23 @@ int32_t index, MediaStreamBuffer* buffer); - virtual ~AudioBufferResource(); + ~AudioBufferResource() override; // PluginResource overrides: - virtual thunk::PPB_AudioBuffer_API* AsPPB_AudioBuffer_API() override; + thunk::PPB_AudioBuffer_API* AsPPB_AudioBuffer_API() override; // PPB_AudioBuffer_API overrides: - virtual PP_TimeDelta GetTimestamp() override; - virtual void SetTimestamp(PP_TimeDelta timestamp) override; - virtual PP_AudioBuffer_SampleRate GetSampleRate() override; - virtual PP_AudioBuffer_SampleSize GetSampleSize() override; - virtual uint32_t GetNumberOfChannels() override; - virtual uint32_t GetNumberOfSamples() override; - virtual void* GetDataBuffer() override; - virtual uint32_t GetDataBufferSize() override; - virtual MediaStreamBuffer* GetBuffer() override; - virtual int32_t GetBufferIndex() override; - virtual void Invalidate() override; + PP_TimeDelta GetTimestamp() override; + void SetTimestamp(PP_TimeDelta timestamp) override; + PP_AudioBuffer_SampleRate GetSampleRate() override; + PP_AudioBuffer_SampleSize GetSampleSize() override; + uint32_t GetNumberOfChannels() override; + uint32_t GetNumberOfSamples() override; + void* GetDataBuffer() override; + uint32_t GetDataBufferSize() override; + MediaStreamBuffer* GetBuffer() override; + int32_t GetBufferIndex() override; + void Invalidate() override; // Buffer index int32_t index_;
diff --git a/ppapi/proxy/audio_input_resource.h b/ppapi/proxy/audio_input_resource.h index 1d4fc06..a94ff9c 100644 --- a/ppapi/proxy/audio_input_resource.h +++ b/ppapi/proxy/audio_input_resource.h
@@ -31,38 +31,36 @@ public base::DelegateSimpleThread::Delegate { public: AudioInputResource(Connection connection, PP_Instance instance); - virtual ~AudioInputResource(); + ~AudioInputResource() override; // Resource overrides. - virtual thunk::PPB_AudioInput_API* AsPPB_AudioInput_API() override; - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + thunk::PPB_AudioInput_API* AsPPB_AudioInput_API() override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; // PPB_AudioInput_API implementation. - virtual int32_t EnumerateDevices( - const PP_ArrayOutput& output, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t MonitorDeviceChange( - PP_MonitorDeviceChangeCallback callback, - void* user_data) override; - virtual int32_t Open0_3(PP_Resource device_ref, - PP_Resource config, - PPB_AudioInput_Callback_0_3 audio_input_callback_0_3, - void* user_data, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Open(PP_Resource device_ref, - PP_Resource config, - PPB_AudioInput_Callback audio_input_callback, - void* user_data, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Resource GetCurrentConfig() override; - virtual PP_Bool StartCapture() override; - virtual PP_Bool StopCapture() override; - virtual void Close() override; + int32_t EnumerateDevices(const PP_ArrayOutput& output, + scoped_refptr<TrackedCallback> callback) override; + int32_t MonitorDeviceChange(PP_MonitorDeviceChangeCallback callback, + void* user_data) override; + int32_t Open0_3(PP_Resource device_ref, + PP_Resource config, + PPB_AudioInput_Callback_0_3 audio_input_callback_0_3, + void* user_data, + scoped_refptr<TrackedCallback> callback) override; + int32_t Open(PP_Resource device_ref, + PP_Resource config, + PPB_AudioInput_Callback audio_input_callback, + void* user_data, + scoped_refptr<TrackedCallback> callback) override; + PP_Resource GetCurrentConfig() override; + PP_Bool StartCapture() override; + PP_Bool StopCapture() override; + void Close() override; protected: // Resource override. - virtual void LastPluginRefWasDeleted() override; + void LastPluginRefWasDeleted() override; private: enum OpenState { @@ -87,7 +85,7 @@ // DelegateSimpleThread::Delegate implementation. // Run on the audio input thread. - virtual void Run() override; + void Run() override; int32_t CommonOpen(PP_Resource device_ref, PP_Resource config,
diff --git a/ppapi/proxy/broker_dispatcher.h b/ppapi/proxy/broker_dispatcher.h index ea2b477..828dac6 100644 --- a/ppapi/proxy/broker_dispatcher.h +++ b/ppapi/proxy/broker_dispatcher.h
@@ -14,7 +14,7 @@ class PPAPI_PROXY_EXPORT BrokerDispatcher : public ProxyChannel { public: - virtual ~BrokerDispatcher(); + ~BrokerDispatcher() override; // You must call this function before anything else. Returns true on success. // The delegate pointer must outlive this class, ownership is not @@ -25,7 +25,7 @@ bool is_client); // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; protected: // You must call InitBrokerWithChannel after the constructor. @@ -47,7 +47,7 @@ BrokerHostDispatcher(); // IPC::Listener implementation. - virtual void OnChannelError() override; + void OnChannelError() override; }; // The dispatcher for the broker side of the broker channel. @@ -56,7 +56,7 @@ explicit BrokerSideDispatcher(PP_ConnectInstance_Func connect_instance); // IPC::Listener implementation. - virtual void OnChannelError() override; + void OnChannelError() override; }; } // namespace proxy
diff --git a/ppapi/proxy/broker_resource.h b/ppapi/proxy/broker_resource.h index b2fd437..23310934 100644 --- a/ppapi/proxy/broker_resource.h +++ b/ppapi/proxy/broker_resource.h
@@ -17,13 +17,13 @@ public thunk::PPB_Broker_Instance_API { public: BrokerResource(Connection connection, PP_Instance instance); - virtual ~BrokerResource(); + ~BrokerResource() override; // Resource override. - virtual thunk::PPB_Broker_Instance_API* AsPPB_Broker_Instance_API() override; + thunk::PPB_Broker_Instance_API* AsPPB_Broker_Instance_API() override; // thunk::PPB_Broker_Instance_API implementation. - virtual PP_Bool IsAllowed() override; + PP_Bool IsAllowed() override; private: DISALLOW_COPY_AND_ASSIGN(BrokerResource);
diff --git a/ppapi/proxy/browser_font_singleton_resource.h b/ppapi/proxy/browser_font_singleton_resource.h index 85e2dc6e..ddbb690 100644 --- a/ppapi/proxy/browser_font_singleton_resource.h +++ b/ppapi/proxy/browser_font_singleton_resource.h
@@ -19,14 +19,14 @@ public thunk::PPB_BrowserFont_Singleton_API { public: BrowserFontSingletonResource(Connection connection, PP_Instance instance); - virtual ~BrowserFontSingletonResource(); + ~BrowserFontSingletonResource() override; // Resource override. - virtual thunk::PPB_BrowserFont_Singleton_API* + thunk::PPB_BrowserFont_Singleton_API* AsPPB_BrowserFont_Singleton_API() override; // thunk::PPB_BrowserFontSingleton_API implementation. - virtual PP_Var GetFontFamilies(PP_Instance instance) override; + PP_Var GetFontFamilies(PP_Instance instance) override; private: // Lazily-filled-in list of font families.
diff --git a/ppapi/proxy/compositor_layer_resource.h b/ppapi/proxy/compositor_layer_resource.h index 56097409..dc6024f 100644 --- a/ppapi/proxy/compositor_layer_resource.h +++ b/ppapi/proxy/compositor_layer_resource.h
@@ -42,38 +42,38 @@ TYPE_IMAGE, }; - virtual ~CompositorLayerResource(); + ~CompositorLayerResource() override; // Resource overrides: - virtual thunk::PPB_CompositorLayer_API* AsPPB_CompositorLayer_API() override; + thunk::PPB_CompositorLayer_API* AsPPB_CompositorLayer_API() override; // thunk::PPB_Compositor_API overrides: - virtual int32_t SetColor(float red, - float green, - float blue, - float alpha, - const PP_Size* size) override; - virtual int32_t SetTexture0_1( + int32_t SetColor(float red, + float green, + float blue, + float alpha, + const PP_Size* size) override; + int32_t SetTexture0_1( PP_Resource context, uint32_t texture, const PP_Size* size, const scoped_refptr<ppapi::TrackedCallback>& callback) override; - virtual int32_t SetTexture( + int32_t SetTexture( PP_Resource context, uint32_t target, uint32_t texture, const PP_Size* size, const scoped_refptr<TrackedCallback>& callback) override; - virtual int32_t SetImage( + int32_t SetImage( PP_Resource image_data, const PP_Size* size, const scoped_refptr<TrackedCallback>& callback) override; - virtual int32_t SetClipRect(const PP_Rect* rect) override; - virtual int32_t SetTransform(const float matrix[16]) override; - virtual int32_t SetOpacity(float opacity) override; - virtual int32_t SetBlendMode(PP_BlendMode mode) override; - virtual int32_t SetSourceRect(const PP_FloatRect* rect) override; - virtual int32_t SetPremultipliedAlpha(PP_Bool premult) override; + int32_t SetClipRect(const PP_Rect* rect) override; + int32_t SetTransform(const float matrix[16]) override; + int32_t SetOpacity(float opacity) override; + int32_t SetBlendMode(PP_BlendMode mode) override; + int32_t SetSourceRect(const PP_FloatRect* rect) override; + int32_t SetPremultipliedAlpha(PP_Bool premult) override; bool SetType(LayerType type); int32_t CheckForSetTextureAndImage(
diff --git a/ppapi/proxy/compositor_resource.h b/ppapi/proxy/compositor_resource.h index 82828d92..0d3161d 100644 --- a/ppapi/proxy/compositor_resource.h +++ b/ppapi/proxy/compositor_resource.h
@@ -28,20 +28,19 @@ int32_t GenerateResourceId() const; private: - virtual ~CompositorResource(); + ~CompositorResource() override; // Resource overrides: - virtual thunk::PPB_Compositor_API* AsPPB_Compositor_API() override; + thunk::PPB_Compositor_API* AsPPB_Compositor_API() override; // PluginResource overrides: - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; // thunk::PPB_Compositor_API overrides: - virtual PP_Resource AddLayer() override; - virtual int32_t CommitLayers( - const scoped_refptr<TrackedCallback>& callback) override; - virtual int32_t ResetLayers() override; + PP_Resource AddLayer() override; + int32_t CommitLayers(const scoped_refptr<TrackedCallback>& callback) override; + int32_t ResetLayers() override; // IPC msg handlers: void OnPluginMsgCommitLayersReply(const ResourceMessageReplyParams& params);
diff --git a/ppapi/proxy/device_enumeration_resource_helper_unittest.cc b/ppapi/proxy/device_enumeration_resource_helper_unittest.cc index a8fa24c..32bc68a 100644 --- a/ppapi/proxy/device_enumeration_resource_helper_unittest.cc +++ b/ppapi/proxy/device_enumeration_resource_helper_unittest.cc
@@ -71,10 +71,10 @@ device_enumeration_(this) { } - virtual ~TestResource() {} + ~TestResource() override {} - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override { + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override { if (!device_enumeration_.HandleReply(params, msg)) PluginResource::OnReplyReceived(params, msg); }
diff --git a/ppapi/proxy/dispatcher.h b/ppapi/proxy/dispatcher.h index 38ec51c..3028841 100644 --- a/ppapi/proxy/dispatcher.h +++ b/ppapi/proxy/dispatcher.h
@@ -48,7 +48,7 @@ // | class PPAPI_PROXY_EXPORT Dispatcher : public ProxyChannel { public: - virtual ~Dispatcher(); + ~Dispatcher() override; // Returns true if the dispatcher is on the plugin side, or false if it's the // browser side. @@ -67,7 +67,7 @@ void AddIOThreadMessageFilter(scoped_refptr<IPC::MessageFilter> filter); // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; PP_GetInterface_Func local_get_interface() const { return local_get_interface_;
diff --git a/ppapi/proxy/file_chooser_resource.h b/ppapi/proxy/file_chooser_resource.h index c60f99d..0347fb07 100644 --- a/ppapi/proxy/file_chooser_resource.h +++ b/ppapi/proxy/file_chooser_resource.h
@@ -29,22 +29,22 @@ PP_Instance instance, PP_FileChooserMode_Dev mode, const std::string& accept_types); - virtual ~FileChooserResource(); + ~FileChooserResource() override; // Resource overrides. - virtual thunk::PPB_FileChooser_API* AsPPB_FileChooser_API() override; + thunk::PPB_FileChooser_API* AsPPB_FileChooser_API() override; // PPB_FileChooser_API. - virtual int32_t Show(const PP_ArrayOutput& output, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t ShowWithoutUserGesture( + int32_t Show(const PP_ArrayOutput& output, + scoped_refptr<TrackedCallback> callback) override; + int32_t ShowWithoutUserGesture( PP_Bool save_as, PP_Var suggested_file_name, const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Show0_5(scoped_refptr<TrackedCallback> callback) override; - virtual PP_Resource GetNextChosenFile() override; - virtual int32_t ShowWithoutUserGesture0_5( + int32_t Show0_5(scoped_refptr<TrackedCallback> callback) override; + PP_Resource GetNextChosenFile() override; + int32_t ShowWithoutUserGesture0_5( PP_Bool save_as, PP_Var suggested_file_name, scoped_refptr<TrackedCallback> callback) override;
diff --git a/ppapi/proxy/file_io_resource.h b/ppapi/proxy/file_io_resource.h index fed4cae..f32879a43 100644 --- a/ppapi/proxy/file_io_resource.h +++ b/ppapi/proxy/file_io_resource.h
@@ -30,44 +30,42 @@ public thunk::PPB_FileIO_API { public: FileIOResource(Connection connection, PP_Instance instance); - virtual ~FileIOResource(); + ~FileIOResource() override; // Resource overrides. - virtual thunk::PPB_FileIO_API* AsPPB_FileIO_API() override; + thunk::PPB_FileIO_API* AsPPB_FileIO_API() override; // PPB_FileIO_API implementation. - virtual int32_t Open(PP_Resource file_ref, - int32_t open_flags, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Query(PP_FileInfo* info, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Touch(PP_Time last_access_time, - PP_Time last_modified_time, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Read(int64_t offset, - char* buffer, - int32_t bytes_to_read, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t ReadToArray(int64_t offset, - int32_t max_read_length, - PP_ArrayOutput* array_output, + int32_t Open(PP_Resource file_ref, + int32_t open_flags, + scoped_refptr<TrackedCallback> callback) override; + int32_t Query(PP_FileInfo* info, + scoped_refptr<TrackedCallback> callback) override; + int32_t Touch(PP_Time last_access_time, + PP_Time last_modified_time, + scoped_refptr<TrackedCallback> callback) override; + int32_t Read(int64_t offset, + char* buffer, + int32_t bytes_to_read, + scoped_refptr<TrackedCallback> callback) override; + int32_t ReadToArray(int64_t offset, + int32_t max_read_length, + PP_ArrayOutput* array_output, + scoped_refptr<TrackedCallback> callback) override; + int32_t Write(int64_t offset, + const char* buffer, + int32_t bytes_to_write, + scoped_refptr<TrackedCallback> callback) override; + int32_t SetLength(int64_t length, + scoped_refptr<TrackedCallback> callback) override; + int64_t GetMaxWrittenOffset() const override; + int64_t GetAppendModeWriteAmount() const override; + void SetMaxWrittenOffset(int64_t max_written_offset) override; + void SetAppendModeWriteAmount(int64_t append_mode_write_amount) override; + int32_t Flush(scoped_refptr<TrackedCallback> callback) override; + void Close() override; + int32_t RequestOSFileHandle(PP_FileHandle* handle, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Write(int64_t offset, - const char* buffer, - int32_t bytes_to_write, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t SetLength(int64_t length, - scoped_refptr<TrackedCallback> callback) override; - virtual int64_t GetMaxWrittenOffset() const override; - virtual int64_t GetAppendModeWriteAmount() const override; - virtual void SetMaxWrittenOffset(int64_t max_written_offset) override; - virtual void SetAppendModeWriteAmount( - int64_t append_mode_write_amount) override; - virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) override; - virtual void Close() override; - virtual int32_t RequestOSFileHandle( - PP_FileHandle* handle, - scoped_refptr<TrackedCallback> callback) override; // FileHolder is used to guarantee that file operations will have a valid FD // to operate on, even if they're in a different thread.
diff --git a/ppapi/proxy/file_ref_resource.h b/ppapi/proxy/file_ref_resource.h index 6db04ac..59e7b7c9 100644 --- a/ppapi/proxy/file_ref_resource.h +++ b/ppapi/proxy/file_ref_resource.h
@@ -31,34 +31,33 @@ PP_Instance instance, const FileRefCreateInfo& info); - virtual ~FileRefResource(); + ~FileRefResource() override; // Resource implementation. - virtual thunk::PPB_FileRef_API* AsPPB_FileRef_API() override; + thunk::PPB_FileRef_API* AsPPB_FileRef_API() override; // PPB_FileRef_API implementation. - virtual PP_FileSystemType GetFileSystemType() const override; - virtual PP_Var GetName() const override; - virtual PP_Var GetPath() const override; - virtual PP_Resource GetParent() override; - virtual int32_t MakeDirectory( - int32_t make_directory_flags, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Touch(PP_Time last_access_time, - PP_Time last_modified_time, + PP_FileSystemType GetFileSystemType() const override; + PP_Var GetName() const override; + PP_Var GetPath() const override; + PP_Resource GetParent() override; + int32_t MakeDirectory(int32_t make_directory_flags, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Delete(scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Rename(PP_Resource new_file_ref, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Query(PP_FileInfo* info, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t ReadDirectoryEntries( + int32_t Touch(PP_Time last_access_time, + PP_Time last_modified_time, + scoped_refptr<TrackedCallback> callback) override; + int32_t Delete(scoped_refptr<TrackedCallback> callback) override; + int32_t Rename(PP_Resource new_file_ref, + scoped_refptr<TrackedCallback> callback) override; + int32_t Query(PP_FileInfo* info, + scoped_refptr<TrackedCallback> callback) override; + int32_t ReadDirectoryEntries( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) override; - virtual const FileRefCreateInfo& GetCreateInfo() const override; + const FileRefCreateInfo& GetCreateInfo() const override; // Private API - virtual PP_Var GetAbsolutePath() override; + PP_Var GetAbsolutePath() override; private: FileRefResource(Connection connection,
diff --git a/ppapi/proxy/file_system_resource.h b/ppapi/proxy/file_system_resource.h index fef6b0b..5b35f86 100644 --- a/ppapi/proxy/file_system_resource.h +++ b/ppapi/proxy/file_system_resource.h
@@ -42,20 +42,20 @@ int pending_renderer_id, int pending_browser_id, PP_FileSystemType type); - virtual ~FileSystemResource(); + ~FileSystemResource() override; // Resource overrides. - virtual thunk::PPB_FileSystem_API* AsPPB_FileSystem_API() override; + thunk::PPB_FileSystem_API* AsPPB_FileSystem_API() override; // PPB_FileSystem_API implementation. - virtual int32_t Open(int64_t expected_size, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_FileSystemType GetType() override; - virtual void OpenQuotaFile(PP_Resource file_io) override; - virtual void CloseQuotaFile(PP_Resource file_io) override; + int32_t Open(int64_t expected_size, + scoped_refptr<TrackedCallback> callback) override; + PP_FileSystemType GetType() override; + void OpenQuotaFile(PP_Resource file_io) override; + void CloseQuotaFile(PP_Resource file_io) override; typedef base::Callback<void(int64_t)> RequestQuotaCallback; - virtual int64_t RequestQuota(int64_t amount, - const RequestQuotaCallback& callback) override; + int64_t RequestQuota(int64_t amount, + const RequestQuotaCallback& callback) override; int32_t InitIsolatedFileSystem(const std::string& fsid, PP_IsolatedFileSystemType_Private type,
diff --git a/ppapi/proxy/flash_clipboard_resource.h b/ppapi/proxy/flash_clipboard_resource.h index 85181bc..cd607d6 100644 --- a/ppapi/proxy/flash_clipboard_resource.h +++ b/ppapi/proxy/flash_clipboard_resource.h
@@ -18,26 +18,26 @@ public NON_EXPORTED_BASE(thunk::PPB_Flash_Clipboard_API) { public: FlashClipboardResource(Connection connection, PP_Instance instance); - virtual ~FlashClipboardResource(); + ~FlashClipboardResource() override; // Resource implementation. - virtual thunk::PPB_Flash_Clipboard_API* AsPPB_Flash_Clipboard_API() override; + thunk::PPB_Flash_Clipboard_API* AsPPB_Flash_Clipboard_API() override; // PPB_Flash_Clipboard_API implementation. - virtual uint32_t RegisterCustomFormat(PP_Instance instance, - const char* format_name) override; - virtual PP_Bool IsFormatAvailable(PP_Instance instance, - PP_Flash_Clipboard_Type clipboard_type, - uint32_t format) override; - virtual PP_Var ReadData(PP_Instance instance, - PP_Flash_Clipboard_Type clipboard_type, - uint32_t format) override; - virtual int32_t WriteData(PP_Instance instance, + uint32_t RegisterCustomFormat(PP_Instance instance, + const char* format_name) override; + PP_Bool IsFormatAvailable(PP_Instance instance, PP_Flash_Clipboard_Type clipboard_type, - uint32_t data_item_count, - const uint32_t formats[], - const PP_Var data_items[]) override; - virtual PP_Bool GetSequenceNumber( + uint32_t format) override; + PP_Var ReadData(PP_Instance instance, + PP_Flash_Clipboard_Type clipboard_type, + uint32_t format) override; + int32_t WriteData(PP_Instance instance, + PP_Flash_Clipboard_Type clipboard_type, + uint32_t data_item_count, + const uint32_t formats[], + const PP_Var data_items[]) override; + PP_Bool GetSequenceNumber( PP_Instance instance, PP_Flash_Clipboard_Type clipboard_type, uint64_t* sequence_number) override;
diff --git a/ppapi/proxy/flash_drm_resource.h b/ppapi/proxy/flash_drm_resource.h index 53a6611..fc773c4 100644 --- a/ppapi/proxy/flash_drm_resource.h +++ b/ppapi/proxy/flash_drm_resource.h
@@ -23,19 +23,19 @@ public: FlashDRMResource(Connection connection, PP_Instance instance); - virtual ~FlashDRMResource(); + ~FlashDRMResource() override; // Resource override. - virtual thunk::PPB_Flash_DRM_API* AsPPB_Flash_DRM_API() override; + thunk::PPB_Flash_DRM_API* AsPPB_Flash_DRM_API() override; // PPB_Flash_DRM_API implementation. - virtual int32_t GetDeviceID(PP_Var* id, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Bool GetHmonitor(int64_t* hmonitor) override; - virtual int32_t GetVoucherFile( + int32_t GetDeviceID(PP_Var* id, + scoped_refptr<TrackedCallback> callback) override; + PP_Bool GetHmonitor(int64_t* hmonitor) override; + int32_t GetVoucherFile( PP_Resource* file_ref, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t MonitorIsExternal( + int32_t MonitorIsExternal( PP_Bool* is_external, scoped_refptr<TrackedCallback> callback) override;
diff --git a/ppapi/proxy/flash_file_resource.h b/ppapi/proxy/flash_file_resource.h index 04d6ed9..ea35152 100644 --- a/ppapi/proxy/flash_file_resource.h +++ b/ppapi/proxy/flash_file_resource.h
@@ -20,40 +20,40 @@ public thunk::PPB_Flash_File_API { public: FlashFileResource(Connection connection, PP_Instance instance); - virtual ~FlashFileResource(); + ~FlashFileResource() override; // Resource overrides. - virtual thunk::PPB_Flash_File_API* AsPPB_Flash_File_API() override; + thunk::PPB_Flash_File_API* AsPPB_Flash_File_API() override; // PPB_Flash_Functions_API. - virtual int32_t OpenFile(PP_Instance instance, - const char* path, - int32_t mode, - PP_FileHandle* file) override; - virtual int32_t RenameFile(PP_Instance instance, - const char* path_from, - const char* path_to) override; - virtual int32_t DeleteFileOrDir(PP_Instance instance, - const char* path, - PP_Bool recursive) override; - virtual int32_t CreateDir(PP_Instance instance, const char* path) override; - virtual int32_t QueryFile(PP_Instance instance, - const char* path, - PP_FileInfo* info) override; - virtual int32_t GetDirContents(PP_Instance instance, - const char* path, - PP_DirContents_Dev** contents) override; - virtual void FreeDirContents(PP_Instance instance, - PP_DirContents_Dev* contents) override; - virtual int32_t CreateTemporaryFile(PP_Instance instance, - PP_FileHandle* file) override; - virtual int32_t OpenFileRef(PP_Instance instance, - PP_Resource file_ref, - int32_t mode, + int32_t OpenFile(PP_Instance instance, + const char* path, + int32_t mode, + PP_FileHandle* file) override; + int32_t RenameFile(PP_Instance instance, + const char* path_from, + const char* path_to) override; + int32_t DeleteFileOrDir(PP_Instance instance, + const char* path, + PP_Bool recursive) override; + int32_t CreateDir(PP_Instance instance, const char* path) override; + int32_t QueryFile(PP_Instance instance, + const char* path, + PP_FileInfo* info) override; + int32_t GetDirContents(PP_Instance instance, + const char* path, + PP_DirContents_Dev** contents) override; + void FreeDirContents(PP_Instance instance, + PP_DirContents_Dev* contents) override; + int32_t CreateTemporaryFile(PP_Instance instance, PP_FileHandle* file) override; - virtual int32_t QueryFileRef(PP_Instance instance, - PP_Resource file_ref, - PP_FileInfo* info) override; + int32_t OpenFileRef(PP_Instance instance, + PP_Resource file_ref, + int32_t mode, + PP_FileHandle* file) override; + int32_t QueryFileRef(PP_Instance instance, + PP_Resource file_ref, + PP_FileInfo* info) override; private: int32_t OpenFileHelper(const std::string& path,
diff --git a/ppapi/proxy/flash_font_file_resource.h b/ppapi/proxy/flash_font_file_resource.h index b471307..e1b32d5 100644 --- a/ppapi/proxy/flash_font_file_resource.h +++ b/ppapi/proxy/flash_font_file_resource.h
@@ -29,15 +29,15 @@ PP_Instance instance, const PP_BrowserFont_Trusted_Description* description, PP_PrivateFontCharset charset); - virtual ~FlashFontFileResource(); + ~FlashFontFileResource() override; // Resource overrides. - virtual thunk::PPB_Flash_FontFile_API* AsPPB_Flash_FontFile_API() override; + thunk::PPB_Flash_FontFile_API* AsPPB_Flash_FontFile_API() override; // PPB_Flash_FontFile_API. - virtual PP_Bool GetFontTable(uint32_t table, - void* output, - uint32_t* output_length) override; + PP_Bool GetFontTable(uint32_t table, + void* output, + uint32_t* output_length) override; private: // Sees if we have a cache of the font table and returns a pointer to it.
diff --git a/ppapi/proxy/flash_fullscreen_resource.h b/ppapi/proxy/flash_fullscreen_resource.h index 06b2722..b193e30 100644 --- a/ppapi/proxy/flash_fullscreen_resource.h +++ b/ppapi/proxy/flash_fullscreen_resource.h
@@ -18,18 +18,16 @@ public: FlashFullscreenResource(Connection connection, PP_Instance instance); - virtual ~FlashFullscreenResource(); + ~FlashFullscreenResource() override; // Resource overrides. - virtual thunk::PPB_Flash_Fullscreen_API* - AsPPB_Flash_Fullscreen_API() override; + thunk::PPB_Flash_Fullscreen_API* AsPPB_Flash_Fullscreen_API() override; // PPB_Flash_Fullscreen_API implementation. - virtual PP_Bool IsFullscreen(PP_Instance instance) override; - virtual PP_Bool SetFullscreen(PP_Instance instance, - PP_Bool fullscreen) override; - virtual void SetLocalIsFullscreen(PP_Instance instance, - PP_Bool is_fullscreen) override; + PP_Bool IsFullscreen(PP_Instance instance) override; + PP_Bool SetFullscreen(PP_Instance instance, PP_Bool fullscreen) override; + void SetLocalIsFullscreen(PP_Instance instance, + PP_Bool is_fullscreen) override; private: PP_Bool is_fullscreen_;
diff --git a/ppapi/proxy/flash_menu_resource.h b/ppapi/proxy/flash_menu_resource.h index 337e953..23b7487 100644 --- a/ppapi/proxy/flash_menu_resource.h +++ b/ppapi/proxy/flash_menu_resource.h
@@ -22,7 +22,7 @@ public: // You must call Initialize after construction. FlashMenuResource(Connection connection, PP_Instance instance); - virtual ~FlashMenuResource(); + ~FlashMenuResource() override; // Returns true on success. False means that this object can not be used. // This has to be separate from the constructor because the menu data could @@ -30,16 +30,16 @@ bool Initialize(const PP_Flash_Menu* menu_data); // Resource overrides. - virtual thunk::PPB_Flash_Menu_API* AsPPB_Flash_Menu_API() override; + thunk::PPB_Flash_Menu_API* AsPPB_Flash_Menu_API() override; // PPB_Flash_Menu_API. - virtual int32_t Show(const PP_Point* location, - int32_t* selected_id, - scoped_refptr<TrackedCallback> callback) override; + int32_t Show(const PP_Point* location, + int32_t* selected_id, + scoped_refptr<TrackedCallback> callback) override; private: - virtual void OnReplyReceived(const proxy::ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const proxy::ResourceMessageReplyParams& params, + const IPC::Message& msg) override; void OnShowReply( const proxy::ResourceMessageReplyParams& params,
diff --git a/ppapi/proxy/flash_resource.h b/ppapi/proxy/flash_resource.h index 891de4c1..21cdbb73 100644 --- a/ppapi/proxy/flash_resource.h +++ b/ppapi/proxy/flash_resource.h
@@ -24,25 +24,21 @@ FlashResource(Connection connection, PP_Instance instance, PluginDispatcher* plugin_dispatcher); - virtual ~FlashResource(); + ~FlashResource() override; // Resource override. - virtual thunk::PPB_Flash_Functions_API* AsPPB_Flash_Functions_API() override; + thunk::PPB_Flash_Functions_API* AsPPB_Flash_Functions_API() override; // PPB_Flash_Functions_API implementation. - virtual PP_Var GetProxyForURL(PP_Instance instance, - const std::string& url) override; - virtual void UpdateActivity(PP_Instance instance) override; - virtual PP_Bool SetCrashData(PP_Instance instance, - PP_FlashCrashKey key, - PP_Var value) override; - virtual double GetLocalTimeZoneOffset(PP_Instance instance, - PP_Time t) override; - virtual PP_Var GetSetting(PP_Instance instance, - PP_FlashSetting setting) override; - virtual void SetInstanceAlwaysOnTop(PP_Instance instance, - PP_Bool on_top) override; - virtual PP_Bool DrawGlyphs( + PP_Var GetProxyForURL(PP_Instance instance, const std::string& url) override; + void UpdateActivity(PP_Instance instance) override; + PP_Bool SetCrashData(PP_Instance instance, + PP_FlashCrashKey key, + PP_Var value) override; + double GetLocalTimeZoneOffset(PP_Instance instance, PP_Time t) override; + PP_Var GetSetting(PP_Instance instance, PP_FlashSetting setting) override; + void SetInstanceAlwaysOnTop(PP_Instance instance, PP_Bool on_top) override; + PP_Bool DrawGlyphs( PP_Instance instance, PP_Resource pp_image_data, const PP_BrowserFont_Trusted_Description* font_desc, @@ -54,13 +50,12 @@ uint32_t glyph_count, const uint16_t glyph_indices[], const PP_Point glyph_advances[]) override; - virtual int32_t Navigate(PP_Instance instance, - PP_Resource request_info, - const char* target, - PP_Bool from_user_action) override; - virtual PP_Bool IsRectTopmost(PP_Instance instance, - const PP_Rect* rect) override; - virtual void InvokePrinting(PP_Instance instance) override; + int32_t Navigate(PP_Instance instance, + PP_Resource request_info, + const char* target, + PP_Bool from_user_action) override; + PP_Bool IsRectTopmost(PP_Instance instance, const PP_Rect* rect) override; + void InvokePrinting(PP_Instance instance) override; private: // Non-owning pointer to the PluginDispatcher that owns this object.
diff --git a/ppapi/proxy/gamepad_resource.h b/ppapi/proxy/gamepad_resource.h index 807cc5c..4851d69c 100644 --- a/ppapi/proxy/gamepad_resource.h +++ b/ppapi/proxy/gamepad_resource.h
@@ -33,14 +33,13 @@ public thunk::PPB_Gamepad_API { public: GamepadResource(Connection connection, PP_Instance instance); - virtual ~GamepadResource(); + ~GamepadResource() override; // Resource implementation. - virtual thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() override; + thunk::PPB_Gamepad_API* AsPPB_Gamepad_API() override; // PPB_Gamepad_API. - virtual void Sample(PP_Instance instance, - PP_GamepadsSampleData* data) override; + void Sample(PP_Instance instance, PP_GamepadsSampleData* data) override; private: void OnPluginMsgSendMemory(const ResourceMessageReplyParams& params);
diff --git a/ppapi/proxy/graphics_2d_resource.h b/ppapi/proxy/graphics_2d_resource.h index e8f4e99..efd7d760 100644 --- a/ppapi/proxy/graphics_2d_resource.h +++ b/ppapi/proxy/graphics_2d_resource.h
@@ -25,24 +25,22 @@ const PP_Size& size, PP_Bool is_always_opaque); - virtual ~Graphics2DResource(); + ~Graphics2DResource() override; // Resource overrides. - virtual thunk::PPB_Graphics2D_API* AsPPB_Graphics2D_API() override; + thunk::PPB_Graphics2D_API* AsPPB_Graphics2D_API() override; // PPB_Graphics2D_API overrides. - virtual PP_Bool Describe(PP_Size* size, PP_Bool* is_always_opaque) override; - virtual void PaintImageData(PP_Resource image_data, - const PP_Point* top_left, - const PP_Rect* src_rect) override; - virtual void Scroll(const PP_Rect* clip_rect, - const PP_Point* amount) override; - virtual void ReplaceContents(PP_Resource image_data) override; - virtual PP_Bool SetScale(float scale) override; - virtual float GetScale() override; - virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) override; - virtual bool ReadImageData(PP_Resource image, - const PP_Point* top_left) override; + PP_Bool Describe(PP_Size* size, PP_Bool* is_always_opaque) override; + void PaintImageData(PP_Resource image_data, + const PP_Point* top_left, + const PP_Rect* src_rect) override; + void Scroll(const PP_Rect* clip_rect, const PP_Point* amount) override; + void ReplaceContents(PP_Resource image_data) override; + PP_Bool SetScale(float scale) override; + float GetScale() override; + int32_t Flush(scoped_refptr<TrackedCallback> callback) override; + bool ReadImageData(PP_Resource image, const PP_Point* top_left) override; private: void OnPluginMsgFlushACK(const ResourceMessageReplyParams& params);
diff --git a/ppapi/proxy/host_resolver_private_resource.h b/ppapi/proxy/host_resolver_private_resource.h index 6af6a2d..d83b707b 100644 --- a/ppapi/proxy/host_resolver_private_resource.h +++ b/ppapi/proxy/host_resolver_private_resource.h
@@ -20,21 +20,20 @@ public: HostResolverPrivateResource(Connection connection, PP_Instance instance); - virtual ~HostResolverPrivateResource(); + ~HostResolverPrivateResource() override; // PluginResource overrides. - virtual thunk::PPB_HostResolver_Private_API* - AsPPB_HostResolver_Private_API() override; + thunk::PPB_HostResolver_Private_API* AsPPB_HostResolver_Private_API() + override; // PPB_HostResolver_Private_API implementation. - virtual int32_t Resolve(const char* host, - uint16_t port, - const PP_HostResolver_Private_Hint* hint, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Var GetCanonicalName() override; - virtual uint32_t GetSize() override; - virtual bool GetNetAddress(uint32_t index, - PP_NetAddress_Private* address) override; + int32_t Resolve(const char* host, + uint16_t port, + const PP_HostResolver_Private_Hint* hint, + scoped_refptr<TrackedCallback> callback) override; + PP_Var GetCanonicalName() override; + uint32_t GetSize() override; + bool GetNetAddress(uint32_t index, PP_NetAddress_Private* address) override; private: DISALLOW_COPY_AND_ASSIGN(HostResolverPrivateResource);
diff --git a/ppapi/proxy/host_resolver_resource.h b/ppapi/proxy/host_resolver_resource.h index d6e41b3..ae6c524d 100644 --- a/ppapi/proxy/host_resolver_resource.h +++ b/ppapi/proxy/host_resolver_resource.h
@@ -19,19 +19,19 @@ public thunk::PPB_HostResolver_API { public: HostResolverResource(Connection connection, PP_Instance instance); - virtual ~HostResolverResource(); + ~HostResolverResource() override; // PluginResource overrides. - virtual thunk::PPB_HostResolver_API* AsPPB_HostResolver_API() override; + thunk::PPB_HostResolver_API* AsPPB_HostResolver_API() override; // thunk::PPB_HostResolver_API implementation. - virtual int32_t Resolve(const char* host, - uint16_t port, - const PP_HostResolver_Hint* hint, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Var GetCanonicalName() override; - virtual uint32_t GetNetAddressCount() override; - virtual PP_Resource GetNetAddress(uint32_t index) override; + int32_t Resolve(const char* host, + uint16_t port, + const PP_HostResolver_Hint* hint, + scoped_refptr<TrackedCallback> callback) override; + PP_Var GetCanonicalName() override; + uint32_t GetNetAddressCount() override; + PP_Resource GetNetAddress(uint32_t index) override; private: DISALLOW_COPY_AND_ASSIGN(HostResolverResource);
diff --git a/ppapi/proxy/isolated_file_system_private_resource.h b/ppapi/proxy/isolated_file_system_private_resource.h index 4f826fe..55ff23e 100644 --- a/ppapi/proxy/isolated_file_system_private_resource.h +++ b/ppapi/proxy/isolated_file_system_private_resource.h
@@ -41,17 +41,17 @@ public: IsolatedFileSystemPrivateResource( Connection connection, PP_Instance instance); - virtual ~IsolatedFileSystemPrivateResource(); + ~IsolatedFileSystemPrivateResource() override; // Resource overrides. - virtual thunk::PPB_IsolatedFileSystem_Private_API* + thunk::PPB_IsolatedFileSystem_Private_API* AsPPB_IsolatedFileSystem_Private_API() override; // PPB_IsolatedFileSystem_Private_API implementation. - virtual int32_t Open(PP_Instance instance, - PP_IsolatedFileSystemType_Private type, - PP_Resource* file_system_resource, - scoped_refptr<TrackedCallback> callback) override; + int32_t Open(PP_Instance instance, + PP_IsolatedFileSystemType_Private type, + PP_Resource* file_system_resource, + scoped_refptr<TrackedCallback> callback) override; private: void OnBrowserOpenComplete(PP_IsolatedFileSystemType_Private type,
diff --git a/ppapi/proxy/media_stream_audio_track_resource.h b/ppapi/proxy/media_stream_audio_track_resource.h index 3dece83..566f42d9 100644 --- a/ppapi/proxy/media_stream_audio_track_resource.h +++ b/ppapi/proxy/media_stream_audio_track_resource.h
@@ -27,27 +27,26 @@ int pending_renderer_id, const std::string& id); - virtual ~MediaStreamAudioTrackResource(); + ~MediaStreamAudioTrackResource() override; // Resource overrides: - virtual thunk::PPB_MediaStreamAudioTrack_API* - AsPPB_MediaStreamAudioTrack_API() override; + thunk::PPB_MediaStreamAudioTrack_API* AsPPB_MediaStreamAudioTrack_API() + override; // PPB_MediaStreamAudioTrack_API overrides: - virtual PP_Var GetId() override; - virtual PP_Bool HasEnded() override; - virtual int32_t Configure(const int32_t attrib_list[], - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetAttrib(PP_MediaStreamAudioTrack_Attrib attrib, - int32_t* value) override; - virtual int32_t GetBuffer( - PP_Resource* buffer, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t RecycleBuffer(PP_Resource buffer) override; - virtual void Close() override; + PP_Var GetId() override; + PP_Bool HasEnded() override; + int32_t Configure(const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) override; + int32_t GetAttrib(PP_MediaStreamAudioTrack_Attrib attrib, + int32_t* value) override; + int32_t GetBuffer(PP_Resource* buffer, + scoped_refptr<TrackedCallback> callback) override; + int32_t RecycleBuffer(PP_Resource buffer) override; + void Close() override; // MediaStreamBufferManager::Delegate overrides: - virtual void OnNewBufferEnqueued() override; + void OnNewBufferEnqueued() override; private: PP_Resource GetAudioBuffer();
diff --git a/ppapi/proxy/media_stream_track_resource_base.h b/ppapi/proxy/media_stream_track_resource_base.h index 2dc2e36d..0e7e9cc 100644 --- a/ppapi/proxy/media_stream_track_resource_base.h +++ b/ppapi/proxy/media_stream_track_resource_base.h
@@ -23,7 +23,7 @@ MediaStreamTrackResourceBase(Connection connection, PP_Instance instance); - virtual ~MediaStreamTrackResourceBase(); + ~MediaStreamTrackResourceBase() override; std::string id() const { return id_; } @@ -42,8 +42,8 @@ void SendEnqueueBufferMessageToHost(int32_t index); // PluginResource overrides: - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; private: // Message handlers:
diff --git a/ppapi/proxy/media_stream_video_track_resource.h b/ppapi/proxy/media_stream_video_track_resource.h index 2bdbb72..b6102ec 100644 --- a/ppapi/proxy/media_stream_video_track_resource.h +++ b/ppapi/proxy/media_stream_video_track_resource.h
@@ -28,29 +28,29 @@ MediaStreamVideoTrackResource(Connection connection, PP_Instance instance); - virtual ~MediaStreamVideoTrackResource(); + ~MediaStreamVideoTrackResource() override; // Resource overrides: - virtual thunk::PPB_MediaStreamVideoTrack_API* - AsPPB_MediaStreamVideoTrack_API() override; + thunk::PPB_MediaStreamVideoTrack_API* AsPPB_MediaStreamVideoTrack_API() + override; // PPB_MediaStreamVideoTrack_API overrides: - virtual PP_Var GetId() override; - virtual PP_Bool HasEnded() override; - virtual int32_t Configure(const int32_t attrib_list[], - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetAttrib(PP_MediaStreamVideoTrack_Attrib attrib, - int32_t* value) override; - virtual int32_t GetFrame(PP_Resource* frame, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t RecycleFrame(PP_Resource frame) override; - virtual void Close() override; - virtual int32_t GetEmptyFrame( - PP_Resource* frame, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t PutFrame(PP_Resource frame) override; + PP_Var GetId() override; + PP_Bool HasEnded() override; + int32_t Configure(const int32_t attrib_list[], + scoped_refptr<TrackedCallback> callback) override; + int32_t GetAttrib(PP_MediaStreamVideoTrack_Attrib attrib, + int32_t* value) override; + int32_t GetFrame(PP_Resource* frame, + scoped_refptr<TrackedCallback> callback) override; + int32_t RecycleFrame(PP_Resource frame) override; + void Close() override; + int32_t GetEmptyFrame(PP_Resource* frame, + scoped_refptr<TrackedCallback> callback) override; + int32_t PutFrame(PP_Resource frame) override; // MediaStreamBufferManager::Delegate overrides: - virtual void OnNewBufferEnqueued() override; + void OnNewBufferEnqueued() override; private: PP_Resource GetVideoFrame();
diff --git a/ppapi/proxy/net_address_resource.h b/ppapi/proxy/net_address_resource.h index c937521..fe17ec6 100644 --- a/ppapi/proxy/net_address_resource.h +++ b/ppapi/proxy/net_address_resource.h
@@ -28,19 +28,17 @@ PP_Instance instance, const PP_NetAddress_Private& private_addr); - virtual ~NetAddressResource(); + ~NetAddressResource() override; // PluginResource implementation. - virtual thunk::PPB_NetAddress_API* AsPPB_NetAddress_API() override; + thunk::PPB_NetAddress_API* AsPPB_NetAddress_API() override; // PPB_NetAddress_API implementation. - virtual PP_NetAddress_Family GetFamily() override; - virtual PP_Var DescribeAsString(PP_Bool include_port) override; - virtual PP_Bool DescribeAsIPv4Address( - PP_NetAddress_IPv4* ipv4_addr) override; - virtual PP_Bool DescribeAsIPv6Address( - PP_NetAddress_IPv6* ipv6_addr) override; - virtual const PP_NetAddress_Private& GetNetAddressPrivate() override; + PP_NetAddress_Family GetFamily() override; + PP_Var DescribeAsString(PP_Bool include_port) override; + PP_Bool DescribeAsIPv4Address(PP_NetAddress_IPv4* ipv4_addr) override; + PP_Bool DescribeAsIPv6Address(PP_NetAddress_IPv6* ipv6_addr) override; + const PP_NetAddress_Private& GetNetAddressPrivate() override; private: // TODO(yzshen): Refactor the code so that PPB_NetAddress resource doesn't
diff --git a/ppapi/proxy/network_list_resource.h b/ppapi/proxy/network_list_resource.h index 71fb856d..005b752b 100644 --- a/ppapi/proxy/network_list_resource.h +++ b/ppapi/proxy/network_list_resource.h
@@ -25,20 +25,19 @@ public: NetworkListResource(PP_Instance instance, const SerializedNetworkList& list); - virtual ~NetworkListResource(); + ~NetworkListResource() override; // Resource override. - virtual thunk::PPB_NetworkList_API* AsPPB_NetworkList_API() override; + thunk::PPB_NetworkList_API* AsPPB_NetworkList_API() override; // PPB_NetworkList_API implementation. - virtual uint32_t GetCount() override; - virtual PP_Var GetName(uint32_t index) override; - virtual PP_NetworkList_Type GetType(uint32_t index) override; - virtual PP_NetworkList_State GetState(uint32_t index) override; - virtual int32_t GetIpAddresses(uint32_t index, - const PP_ArrayOutput& output) override; - virtual PP_Var GetDisplayName(uint32_t index) override; - virtual uint32_t GetMTU(uint32_t index) override; + uint32_t GetCount() override; + PP_Var GetName(uint32_t index) override; + PP_NetworkList_Type GetType(uint32_t index) override; + PP_NetworkList_State GetState(uint32_t index) override; + int32_t GetIpAddresses(uint32_t index, const PP_ArrayOutput& output) override; + PP_Var GetDisplayName(uint32_t index) override; + uint32_t GetMTU(uint32_t index) override; private: SerializedNetworkList list_;
diff --git a/ppapi/proxy/network_monitor_resource.h b/ppapi/proxy/network_monitor_resource.h index 529dd6e..e63ae390f 100644 --- a/ppapi/proxy/network_monitor_resource.h +++ b/ppapi/proxy/network_monitor_resource.h
@@ -24,15 +24,15 @@ public: explicit NetworkMonitorResource(Connection connection, PP_Instance instance); - virtual ~NetworkMonitorResource(); + ~NetworkMonitorResource() override; // PluginResource overrides. ppapi::thunk::PPB_NetworkMonitor_API* AsPPB_NetworkMonitor_API() override; - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; // thunk::PPB_NetworkMonitor_API interface - virtual int32_t UpdateNetworkList( + int32_t UpdateNetworkList( PP_Resource* network_list, scoped_refptr<TrackedCallback> callback) override;
diff --git a/ppapi/proxy/network_proxy_resource.h b/ppapi/proxy/network_proxy_resource.h index ba1236e5..b48089d 100644 --- a/ppapi/proxy/network_proxy_resource.h +++ b/ppapi/proxy/network_proxy_resource.h
@@ -18,14 +18,14 @@ public thunk::PPB_NetworkProxy_API { public: NetworkProxyResource(Connection connection, PP_Instance instance); - virtual ~NetworkProxyResource(); + ~NetworkProxyResource() override; private: // Resource implementation. - virtual thunk::PPB_NetworkProxy_API* AsPPB_NetworkProxy_API() override; + thunk::PPB_NetworkProxy_API* AsPPB_NetworkProxy_API() override; // PPB_NetworkProxy_API implementation. - virtual int32_t GetProxyForURL( + int32_t GetProxyForURL( PP_Instance instance, PP_Var url, PP_Var* proxy_string,
diff --git a/ppapi/proxy/output_protection_resource.h b/ppapi/proxy/output_protection_resource.h index 6b80b910..25dcc53 100644 --- a/ppapi/proxy/output_protection_resource.h +++ b/ppapi/proxy/output_protection_resource.h
@@ -22,18 +22,17 @@ PP_Instance instance); private: - virtual ~OutputProtectionResource(); + ~OutputProtectionResource() override; // PluginResource overrides. - virtual thunk::PPB_OutputProtection_API* AsPPB_OutputProtection_API() - override; + thunk::PPB_OutputProtection_API* AsPPB_OutputProtection_API() override; // PPB_OutputProtection_API implementation. - virtual int32_t QueryStatus( + int32_t QueryStatus( uint32_t* link_mask, uint32_t* protection_mask, const scoped_refptr<TrackedCallback>& callback) override; - virtual int32_t EnableProtection( + int32_t EnableProtection( uint32_t desired_method_mask, const scoped_refptr<TrackedCallback>& callback) override;
diff --git a/ppapi/proxy/pdf_resource.h b/ppapi/proxy/pdf_resource.h index 9ca82c63..f68c1a2d 100644 --- a/ppapi/proxy/pdf_resource.h +++ b/ppapi/proxy/pdf_resource.h
@@ -25,7 +25,7 @@ public thunk::PPB_PDF_API { public: PDFResource(Connection connection, PP_Instance instance); - virtual ~PDFResource(); + ~PDFResource() override; // For unittesting with a given locale. void SetLocaleForTest(const std::string& locale) { @@ -33,34 +33,34 @@ } // Resource override. - virtual thunk::PPB_PDF_API* AsPPB_PDF_API() override; + thunk::PPB_PDF_API* AsPPB_PDF_API() override; // PPB_PDF_API implementation. PP_Var GetLocalizedString(PP_ResourceString string_id) override; - virtual void SearchString(const unsigned short* input_string, - const unsigned short* input_term, - bool case_sensitive, - PP_PrivateFindResult** results, - int* count) override; - virtual void DidStartLoading() override; - virtual void DidStopLoading() override; - virtual void SetContentRestriction(int restrictions) override; - virtual void HistogramPDFPageCount(int count) override; - virtual void UserMetricsRecordAction(const PP_Var& action) override; - virtual void HasUnsupportedFeature() override; - virtual void Print() override; - virtual void SaveAs() override; - virtual PP_Bool IsFeatureEnabled(PP_PDFFeature feature) override; - virtual PP_Resource GetResourceImageForScale(PP_ResourceImage image_id, - float scale) override; - virtual PP_Resource GetResourceImage(PP_ResourceImage image_id) override; - virtual PP_Bool IsOutOfProcess() override; - virtual void SetSelectedText(const char* selected_text) override; - virtual void SetLinkUnderCursor(const char* url) override; - virtual void GetV8ExternalSnapshotData(const char** natives_data_out, - int* natives_size_out, - const char** snapshot_data_out, - int* snapshot_size_out) override; + void SearchString(const unsigned short* input_string, + const unsigned short* input_term, + bool case_sensitive, + PP_PrivateFindResult** results, + int* count) override; + void DidStartLoading() override; + void DidStopLoading() override; + void SetContentRestriction(int restrictions) override; + void HistogramPDFPageCount(int count) override; + void UserMetricsRecordAction(const PP_Var& action) override; + void HasUnsupportedFeature() override; + void Print() override; + void SaveAs() override; + PP_Bool IsFeatureEnabled(PP_PDFFeature feature) override; + PP_Resource GetResourceImageForScale(PP_ResourceImage image_id, + float scale) override; + PP_Resource GetResourceImage(PP_ResourceImage image_id) override; + PP_Bool IsOutOfProcess() override; + void SetSelectedText(const char* selected_text) override; + void SetLinkUnderCursor(const char* url) override; + void GetV8ExternalSnapshotData(const char** natives_data_out, + int* natives_size_out, + const char** snapshot_data_out, + int* snapshot_size_out) override; private: std::string locale_;
diff --git a/ppapi/proxy/platform_verification_private_resource.h b/ppapi/proxy/platform_verification_private_resource.h index 424b30d6..072b3f8 100644 --- a/ppapi/proxy/platform_verification_private_resource.h +++ b/ppapi/proxy/platform_verification_private_resource.h
@@ -27,14 +27,14 @@ scoped_refptr<TrackedCallback> callback; }; - virtual ~PlatformVerificationPrivateResource(); + ~PlatformVerificationPrivateResource() override; // PluginResource overrides. - virtual thunk::PPB_PlatformVerification_API* - AsPPB_PlatformVerification_API() override; + thunk::PPB_PlatformVerification_API* AsPPB_PlatformVerification_API() + override; // PPB_PlatformVerification_API implementation. - virtual int32_t ChallengePlatform( + int32_t ChallengePlatform( const PP_Var& service_id, const PP_Var& challenge, PP_Var* signed_data,
diff --git a/ppapi/proxy/plugin_array_buffer_var.h b/ppapi/proxy/plugin_array_buffer_var.h index efe9040..ee9b9306 100644 --- a/ppapi/proxy/plugin_array_buffer_var.h +++ b/ppapi/proxy/plugin_array_buffer_var.h
@@ -23,13 +23,13 @@ explicit PluginArrayBufferVar(uint32 size_in_bytes); PluginArrayBufferVar(uint32 size_in_bytes, base::SharedMemoryHandle plugin_handle); - virtual ~PluginArrayBufferVar(); + ~PluginArrayBufferVar() override; // ArrayBufferVar implementation. - virtual void* Map() override; - virtual void Unmap() override; - virtual uint32 ByteLength() override; - virtual bool CopyToNewShmem( + void* Map() override; + void Unmap() override; + uint32 ByteLength() override; + bool CopyToNewShmem( PP_Instance instance, int* host_handle, base::SharedMemoryHandle* plugin_handle) override;
diff --git a/ppapi/proxy/plugin_globals.cc b/ppapi/proxy/plugin_globals.cc index ad3ad24..060aa71 100644 --- a/ppapi/proxy/plugin_globals.cc +++ b/ppapi/proxy/plugin_globals.cc
@@ -31,10 +31,10 @@ : underlying_sender_(underlying_sender) { } - virtual ~BrowserSender() {} + ~BrowserSender() override {} // IPC::Sender implementation. - virtual bool Send(IPC::Message* msg) override { + bool Send(IPC::Message* msg) override { if (msg->is_sync()) { // Synchronous messages might be re-entrant, so we need to drop the lock. ProxyAutoUnlock unlock;
diff --git a/ppapi/proxy/plugin_globals.h b/ppapi/proxy/plugin_globals.h index fe24ed6..28cfe48 100644 --- a/ppapi/proxy/plugin_globals.h +++ b/ppapi/proxy/plugin_globals.h
@@ -44,7 +44,7 @@ explicit PluginGlobals(const scoped_refptr<base::TaskRunner>& task_runner); PluginGlobals(PpapiGlobals::PerThreadForTest, const scoped_refptr<base::TaskRunner>& task_runner); - virtual ~PluginGlobals(); + ~PluginGlobals() override; // Getter for the global singleton. Generally, you should use // PpapiGlobals::Get() when possible. Use this only when you need some @@ -57,28 +57,26 @@ } // PpapiGlobals implementation. - virtual ResourceTracker* GetResourceTracker() override; - virtual VarTracker* GetVarTracker() override; - virtual CallbackTracker* GetCallbackTrackerForInstance( + ResourceTracker* GetResourceTracker() override; + VarTracker* GetVarTracker() override; + CallbackTracker* GetCallbackTrackerForInstance(PP_Instance instance) override; + thunk::PPB_Instance_API* GetInstanceAPI(PP_Instance instance) override; + thunk::ResourceCreationAPI* GetResourceCreationAPI( PP_Instance instance) override; - virtual thunk::PPB_Instance_API* GetInstanceAPI( - PP_Instance instance) override; - virtual thunk::ResourceCreationAPI* GetResourceCreationAPI( - PP_Instance instance) override; - virtual PP_Module GetModuleForInstance(PP_Instance instance) override; - virtual std::string GetCmdLine() override; - virtual void PreCacheFontForFlash(const void* logfontw) override; - virtual void LogWithSource(PP_Instance instance, - PP_LogLevel level, - const std::string& source, - const std::string& value) override; - virtual void BroadcastLogWithSource(PP_Module module, - PP_LogLevel level, - const std::string& source, - const std::string& value) override; - virtual MessageLoopShared* GetCurrentMessageLoop() override; + PP_Module GetModuleForInstance(PP_Instance instance) override; + std::string GetCmdLine() override; + void PreCacheFontForFlash(const void* logfontw) override; + void LogWithSource(PP_Instance instance, + PP_LogLevel level, + const std::string& source, + const std::string& value) override; + void BroadcastLogWithSource(PP_Module module, + PP_LogLevel level, + const std::string& source, + const std::string& value) override; + MessageLoopShared* GetCurrentMessageLoop() override; base::TaskRunner* GetFileTaskRunner() override; - virtual void MarkPluginIsActive() override; + void MarkPluginIsActive() override; // Returns the channel for sending to the browser. IPC::Sender* GetBrowserSender(); @@ -159,7 +157,7 @@ class BrowserSender; // PpapiGlobals overrides. - virtual bool IsPluginGlobals() const override; + bool IsPluginGlobals() const override; // Locks the proxy lock and releases the throttle on keepalive IPC messages. void OnReleaseKeepaliveThrottle();
diff --git a/ppapi/proxy/plugin_message_filter.h b/ppapi/proxy/plugin_message_filter.h index e8d8940a..b41a71d 100644 --- a/ppapi/proxy/plugin_message_filter.h +++ b/ppapi/proxy/plugin_message_filter.h
@@ -40,15 +40,15 @@ PluginMessageFilter( std::set<PP_Instance>* seen_instance_ids, scoped_refptr<ResourceReplyThreadRegistrar> thread_registrar); - virtual ~PluginMessageFilter(); + ~PluginMessageFilter() override; // MessageFilter implementation. - virtual void OnFilterAdded(IPC::Sender* sender) override; - virtual void OnFilterRemoved() override; - virtual bool OnMessageReceived(const IPC::Message& message) override; + void OnFilterAdded(IPC::Sender* sender) override; + void OnFilterRemoved() override; + bool OnMessageReceived(const IPC::Message& message) override; // IPC::Sender implementation. - virtual bool Send(IPC::Message* msg) override; + bool Send(IPC::Message* msg) override; void AddResourceMessageFilter( const scoped_refptr<ResourceMessageFilter>& filter);
diff --git a/ppapi/proxy/plugin_resource.h b/ppapi/proxy/plugin_resource.h index fd905cf..0f21240 100644 --- a/ppapi/proxy/plugin_resource.h +++ b/ppapi/proxy/plugin_resource.h
@@ -34,7 +34,7 @@ }; PluginResource(Connection connection, PP_Instance instance); - virtual ~PluginResource(); + ~PluginResource() override; // Returns true if we've previously sent a create message to the browser // or renderer. Generally resources will use these to tell if they should @@ -45,16 +45,15 @@ // This handles a reply to a resource call. It works by looking up the // callback that was registered when CallBrowser/CallRenderer was called // and calling it with |params| and |msg|. - virtual void OnReplyReceived(const proxy::ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const proxy::ResourceMessageReplyParams& params, + const IPC::Message& msg) override; // Resource overrides. // Note: Subclasses shouldn't override these methods directly. Instead, they // should implement LastPluginRefWasDeleted() or InstanceWasDeleted() to get // notified. - virtual void NotifyLastPluginRefWasDeleted() override; - virtual void NotifyInstanceWasDeleted() override; - + void NotifyLastPluginRefWasDeleted() override; + void NotifyInstanceWasDeleted() override; // Sends a create message to the browser or renderer for the current resource. void SendCreate(Destination dest, const IPC::Message& msg);
diff --git a/ppapi/proxy/plugin_resource_callback.h b/ppapi/proxy/plugin_resource_callback.h index 9c443d8..ecde1c2 100644 --- a/ppapi/proxy/plugin_resource_callback.h +++ b/ppapi/proxy/plugin_resource_callback.h
@@ -33,7 +33,7 @@ explicit PluginResourceCallback(const CallbackType& callback) : callback_(callback) {} - virtual void Run( + void Run( const ResourceMessageReplyParams& reply_params, const IPC::Message& msg) override { DispatchResourceReplyOrDefaultParams<MsgClass>( @@ -41,7 +41,7 @@ } private: - virtual ~PluginResourceCallback() {} + ~PluginResourceCallback() override {} CallbackType callback_; };
diff --git a/ppapi/proxy/plugin_resource_tracker.h b/ppapi/proxy/plugin_resource_tracker.h index 21c7fc5..73a2db3 100644 --- a/ppapi/proxy/plugin_resource_tracker.h +++ b/ppapi/proxy/plugin_resource_tracker.h
@@ -27,7 +27,7 @@ class PPAPI_PROXY_EXPORT PluginResourceTracker : public ResourceTracker { public: PluginResourceTracker(); - virtual ~PluginResourceTracker(); + ~PluginResourceTracker() override; // Given a host resource, maps it to an existing plugin resource ID if it // exists, or returns 0 on failure. @@ -36,8 +36,8 @@ protected: // ResourceTracker overrides. - virtual PP_Resource AddResource(Resource* object) override; - virtual void RemoveResource(Resource* object) override; + PP_Resource AddResource(Resource* object) override; + void RemoveResource(Resource* object) override; private: // Map of host instance/resource pairs to a plugin resource ID.
diff --git a/ppapi/proxy/plugin_resource_var.h b/ppapi/proxy/plugin_resource_var.h index edfe47b4..461dbfd 100644 --- a/ppapi/proxy/plugin_resource_var.h +++ b/ppapi/proxy/plugin_resource_var.h
@@ -22,13 +22,13 @@ explicit PluginResourceVar(ppapi::Resource* resource); // ResourceVar override. - virtual PP_Resource GetPPResource() const override; - virtual bool IsPending() const override; + PP_Resource GetPPResource() const override; + bool IsPending() const override; scoped_refptr<ppapi::Resource> resource() const { return resource_; } protected: - virtual ~PluginResourceVar(); + ~PluginResourceVar() override; private: // If NULL, this represents the PP_Resource 0.
diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h index 24be5a2..671dffe 100644 --- a/ppapi/proxy/plugin_var_tracker.h +++ b/ppapi/proxy/plugin_var_tracker.h
@@ -32,7 +32,7 @@ class PPAPI_PROXY_EXPORT PluginVarTracker : public VarTracker { public: PluginVarTracker(); - ~PluginVarTracker(); + ~PluginVarTracker() override; // Manages tracking for receiving a VARTYPE_OBJECT from the remote side // (either the plugin or the renderer) that has already had its reference @@ -59,20 +59,19 @@ const PP_Var& host_object); // VarTracker public overrides. - virtual PP_Var MakeResourcePPVarFromMessage( - PP_Instance instance, - const IPC::Message& creation_message, - int pending_renderer_id, - int pending_browser_id) override; - virtual ResourceVar* MakeResourceVar(PP_Resource pp_resource) override; - virtual void DidDeleteInstance(PP_Instance instance) override; - virtual int TrackSharedMemoryHandle(PP_Instance instance, - base::SharedMemoryHandle file, - uint32 size_in_bytes) override; - virtual bool StopTrackingSharedMemoryHandle(int id, - PP_Instance instance, - base::SharedMemoryHandle* handle, - uint32* size_in_bytes) override; + PP_Var MakeResourcePPVarFromMessage(PP_Instance instance, + const IPC::Message& creation_message, + int pending_renderer_id, + int pending_browser_id) override; + ResourceVar* MakeResourceVar(PP_Resource pp_resource) override; + void DidDeleteInstance(PP_Instance instance) override; + int TrackSharedMemoryHandle(PP_Instance instance, + base::SharedMemoryHandle file, + uint32 size_in_bytes) override; + bool StopTrackingSharedMemoryHandle(int id, + PP_Instance instance, + base::SharedMemoryHandle* handle, + uint32* size_in_bytes) override; // Notification that a plugin-implemented object (PPP_Class) was created by // the plugin or deallocated by WebKit over IPC. @@ -97,12 +96,12 @@ private: // VarTracker protected overrides. - virtual int32 AddVarInternal(Var* var, AddVarRefMode mode) override; - virtual void TrackedObjectGettingOneRef(VarMap::const_iterator iter) override; - virtual void ObjectGettingZeroRef(VarMap::iterator iter) override; - virtual bool DeleteObjectInfoIfNecessary(VarMap::iterator iter) override; - virtual ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) override; - virtual ArrayBufferVar* CreateShmArrayBuffer( + int32 AddVarInternal(Var* var, AddVarRefMode mode) override; + void TrackedObjectGettingOneRef(VarMap::const_iterator iter) override; + void ObjectGettingZeroRef(VarMap::iterator iter) override; + bool DeleteObjectInfoIfNecessary(VarMap::iterator iter) override; + ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) override; + ArrayBufferVar* CreateShmArrayBuffer( uint32 size_in_bytes, base::SharedMemoryHandle handle) override;
diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.h b/ppapi/proxy/ppapi_command_buffer_proxy.h index 436a687f..62f77a4 100644 --- a/ppapi/proxy/ppapi_command_buffer_proxy.h +++ b/ppapi/proxy/ppapi_command_buffer_proxy.h
@@ -31,41 +31,40 @@ PluginDispatcher* dispatcher, const gpu::Capabilities& capabilities, const SerializedHandle& shared_state); - virtual ~PpapiCommandBufferProxy(); + ~PpapiCommandBufferProxy() override; // gpu::CommandBuffer implementation: - virtual bool Initialize() override; - virtual State GetLastState() override; - virtual int32 GetLastToken() override; - virtual void Flush(int32 put_offset) override; - virtual void OrderingBarrier(int32 put_offset) override; - virtual void WaitForTokenInRange(int32 start, int32 end) override; - virtual void WaitForGetOffsetInRange(int32 start, int32 end) override; - virtual void SetGetBuffer(int32 transfer_buffer_id) override; - virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size, - int32* id) override; - virtual void DestroyTransferBuffer(int32 id) override; + bool Initialize() override; + State GetLastState() override; + int32 GetLastToken() override; + void Flush(int32 put_offset) override; + void OrderingBarrier(int32 put_offset) override; + void WaitForTokenInRange(int32 start, int32 end) override; + void WaitForGetOffsetInRange(int32 start, int32 end) override; + void SetGetBuffer(int32 transfer_buffer_id) override; + scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size, + int32* id) override; + void DestroyTransferBuffer(int32 id) override; // gpu::GpuControl implementation: - virtual gpu::Capabilities GetCapabilities() override; - virtual int32 CreateImage(ClientBuffer buffer, - size_t width, - size_t height, - unsigned internalformat) override; - virtual void DestroyImage(int32 id) override; - virtual int32 CreateGpuMemoryBufferImage(size_t width, - size_t height, - unsigned internalformat, - unsigned usage) override; - virtual uint32 InsertSyncPoint() override; - virtual uint32 InsertFutureSyncPoint() override; - virtual void RetireSyncPoint(uint32 sync_point) override; - virtual void SignalSyncPoint(uint32 sync_point, - const base::Closure& callback) override; - virtual void SignalQuery(uint32 query, - const base::Closure& callback) override; - virtual void SetSurfaceVisible(bool visible) override; - virtual uint32 CreateStreamTexture(uint32 texture_id) override; + gpu::Capabilities GetCapabilities() override; + int32 CreateImage(ClientBuffer buffer, + size_t width, + size_t height, + unsigned internalformat) override; + void DestroyImage(int32 id) override; + int32 CreateGpuMemoryBufferImage(size_t width, + size_t height, + unsigned internalformat, + unsigned usage) override; + uint32 InsertSyncPoint() override; + uint32 InsertFutureSyncPoint() override; + void RetireSyncPoint(uint32 sync_point) override; + void SignalSyncPoint(uint32 sync_point, + const base::Closure& callback) override; + void SignalQuery(uint32 query, const base::Closure& callback) override; + void SetSurfaceVisible(bool visible) override; + uint32 CreateStreamTexture(uint32 texture_id) override; void SetLock(base::Lock*) override; private:
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h index cd94bfd..1c978843 100644 --- a/ppapi/proxy/ppapi_messages.h +++ b/ppapi/proxy/ppapi_messages.h
@@ -1204,6 +1204,9 @@ IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance, PP_Instance /* instance */, uint32 /* result */) +IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBTesting_IsPeripheral, + PP_Instance /* instance */, + PP_Bool /* result */) IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBTesting_SimulateInputEvent, PP_Instance /* instance */, ppapi::InputEventData /* input_event */)
diff --git a/ppapi/proxy/ppapi_proxy_test.h b/ppapi/proxy/ppapi_proxy_test.h index ef48250..ab6c8b2c 100644 --- a/ppapi/proxy/ppapi_proxy_test.h +++ b/ppapi/proxy/ppapi_proxy_test.h
@@ -120,7 +120,7 @@ public PluginProxyDelegate { public: PluginDelegateMock() : ipc_message_loop_(NULL), shutdown_event_() {} - virtual ~PluginDelegateMock() {} + ~PluginDelegateMock() override {} void Init(base::MessageLoopProxy* ipc_message_loop, base::WaitableEvent* shutdown_event) { @@ -133,24 +133,24 @@ } // ProxyChannel::Delegate implementation. - virtual base::MessageLoopProxy* GetIPCMessageLoop() override; - virtual base::WaitableEvent* GetShutdownEvent() override; - virtual IPC::PlatformFileForTransit ShareHandleWithRemote( + base::MessageLoopProxy* GetIPCMessageLoop() override; + base::WaitableEvent* GetShutdownEvent() override; + IPC::PlatformFileForTransit ShareHandleWithRemote( base::PlatformFile handle, base::ProcessId remote_pid, bool should_close_source) override; // PluginDispatcher::PluginDelegate implementation. - virtual std::set<PP_Instance>* GetGloballySeenInstanceIDSet() override; - virtual uint32 Register(PluginDispatcher* plugin_dispatcher) override; - virtual void Unregister(uint32 plugin_dispatcher_id) override; + std::set<PP_Instance>* GetGloballySeenInstanceIDSet() override; + uint32 Register(PluginDispatcher* plugin_dispatcher) override; + void Unregister(uint32 plugin_dispatcher_id) override; // PluginProxyDelegate implementation. - virtual IPC::Sender* GetBrowserSender() override; - virtual std::string GetUILanguage() override; - virtual void PreCacheFont(const void* logfontw) override; - virtual void SetActiveURL(const std::string& url) override; - virtual PP_Resource CreateBrowserFont( + IPC::Sender* GetBrowserSender() override; + std::string GetUILanguage() override; + void PreCacheFont(const void* logfontw) override; + void SetActiveURL(const std::string& url) override; + PP_Resource CreateBrowserFont( Connection connection, PP_Instance instance, const PP_BrowserFont_Trusted_Description& desc, @@ -198,7 +198,7 @@ public base::DelegateSimpleThread::Delegate { public: PluginProxyMultiThreadTest(); - virtual ~PluginProxyMultiThreadTest(); + ~PluginProxyMultiThreadTest() override; // Called before the secondary thread is started, but after all the member // variables, including |secondary_thread_| and @@ -226,7 +226,7 @@ private: // base::DelegateSimpleThread::Delegate implementation. - virtual void Run() override; + void Run() override; void QuitNestedLoop(); @@ -264,7 +264,7 @@ public: DelegateMock() : ipc_message_loop_(NULL), shutdown_event_(NULL) { } - virtual ~DelegateMock() {} + ~DelegateMock() override {} void Init(base::MessageLoopProxy* ipc_message_loop, base::WaitableEvent* shutdown_event) { @@ -273,9 +273,9 @@ } // ProxyChannel::Delegate implementation. - virtual base::MessageLoopProxy* GetIPCMessageLoop(); - virtual base::WaitableEvent* GetShutdownEvent(); - virtual IPC::PlatformFileForTransit ShareHandleWithRemote( + base::MessageLoopProxy* GetIPCMessageLoop() override; + base::WaitableEvent* GetShutdownEvent() override; + IPC::PlatformFileForTransit ShareHandleWithRemote( base::PlatformFile handle, base::ProcessId remote_pid, bool should_close_source) override;
diff --git a/ppapi/proxy/ppb_broker_proxy.cc b/ppapi/proxy/ppb_broker_proxy.cc index ed7ed425..e1d38ea 100644 --- a/ppapi/proxy/ppb_broker_proxy.cc +++ b/ppapi/proxy/ppb_broker_proxy.cc
@@ -27,15 +27,14 @@ class Broker : public PPB_Broker_API, public Resource { public: explicit Broker(const HostResource& resource); - virtual ~Broker(); + ~Broker() override; // Resource overrides. - virtual PPB_Broker_API* AsPPB_Broker_API() override; + PPB_Broker_API* AsPPB_Broker_API() override; // PPB_Broker_API implementation. - virtual int32_t Connect( - scoped_refptr<TrackedCallback> connect_callback) override; - virtual int32_t GetHandle(int32_t* handle) override; + int32_t Connect(scoped_refptr<TrackedCallback> connect_callback) override; + int32_t GetHandle(int32_t* handle) override; // Called by the proxy when the host side has completed the request. void ConnectComplete(IPC::PlatformFileForTransit socket_handle,
diff --git a/ppapi/proxy/ppb_buffer_proxy.h b/ppapi/proxy/ppb_buffer_proxy.h index 7566c08c..b148494 100644 --- a/ppapi/proxy/ppb_buffer_proxy.h +++ b/ppapi/proxy/ppb_buffer_proxy.h
@@ -24,19 +24,19 @@ Buffer(const HostResource& resource, const base::SharedMemoryHandle& shm_handle, uint32_t size); - virtual ~Buffer(); + ~Buffer() override; // Resource overrides. - virtual thunk::PPB_Buffer_API* AsPPB_Buffer_API() override; + thunk::PPB_Buffer_API* AsPPB_Buffer_API() override; // PPB_Buffer_API implementation. - virtual PP_Bool Describe(uint32_t* size_in_bytes) override; - virtual PP_Bool IsMapped() override; - virtual void* Map() override; - virtual void Unmap() override; + PP_Bool Describe(uint32_t* size_in_bytes) override; + PP_Bool IsMapped() override; + void* Map() override; + void Unmap() override; // Trusted - virtual int32_t GetSharedMemory(int* handle) override; + int32_t GetSharedMemory(int* handle) override; private: base::SharedMemory shm_;
diff --git a/ppapi/proxy/ppb_flash_message_loop_proxy.cc b/ppapi/proxy/ppb_flash_message_loop_proxy.cc index e4e92e9..1b332185 100644 --- a/ppapi/proxy/ppb_flash_message_loop_proxy.cc +++ b/ppapi/proxy/ppb_flash_message_loop_proxy.cc
@@ -24,16 +24,15 @@ class FlashMessageLoop : public PPB_Flash_MessageLoop_API, public Resource { public: explicit FlashMessageLoop(const HostResource& resource); - virtual ~FlashMessageLoop(); + ~FlashMessageLoop() override; // Resource overrides. - virtual PPB_Flash_MessageLoop_API* AsPPB_Flash_MessageLoop_API() override; + PPB_Flash_MessageLoop_API* AsPPB_Flash_MessageLoop_API() override; // PPB_Flash_MesssageLoop_API implementation. - virtual int32_t Run() override; - virtual void Quit() override; - virtual void RunFromHostProxy( - const RunFromHostProxyCallback& callback) override; + int32_t Run() override; + void Quit() override; + void RunFromHostProxy(const RunFromHostProxyCallback& callback) override; private: DISALLOW_COPY_AND_ASSIGN(FlashMessageLoop);
diff --git a/ppapi/proxy/ppb_flash_message_loop_proxy.h b/ppapi/proxy/ppb_flash_message_loop_proxy.h index 9dfcca99..a28bbda 100644 --- a/ppapi/proxy/ppb_flash_message_loop_proxy.h +++ b/ppapi/proxy/ppb_flash_message_loop_proxy.h
@@ -28,12 +28,12 @@ public base::SupportsWeakPtr<PPB_Flash_MessageLoop_Proxy> { public: explicit PPB_Flash_MessageLoop_Proxy(Dispatcher* dispatcher); - virtual ~PPB_Flash_MessageLoop_Proxy(); + ~PPB_Flash_MessageLoop_Proxy() override; static PP_Resource CreateProxyResource(PP_Instance instance); // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; static const ApiID kApiID = API_ID_PPB_FLASH_MESSAGELOOP;
diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.h b/ppapi/proxy/ppb_graphics_3d_proxy.h index 848281e..98e7d3c 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.h +++ b/ppapi/proxy/ppb_graphics_3d_proxy.h
@@ -34,32 +34,31 @@ class PPAPI_PROXY_EXPORT Graphics3D : public PPB_Graphics3D_Shared { public: explicit Graphics3D(const HostResource& resource); - virtual ~Graphics3D(); + ~Graphics3D() override; bool Init(gpu::gles2::GLES2Implementation* share_gles2, const gpu::Capabilities& capabilities, const SerializedHandle& shared_state); // Graphics3DTrusted API. These are not implemented in the proxy. - virtual PP_Bool SetGetBuffer(int32_t shm_id) override; - virtual PP_Bool Flush(int32_t put_offset) override; - virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(uint32_t size, - int32* id) override; - virtual PP_Bool DestroyTransferBuffer(int32_t id) override; - virtual gpu::CommandBuffer::State WaitForTokenInRange(int32_t start, - int32_t end) override; - virtual gpu::CommandBuffer::State WaitForGetOffsetInRange(int32_t start, - int32_t end) - override; - virtual uint32_t InsertSyncPoint() override; - virtual uint32_t InsertFutureSyncPoint() override; - virtual void RetireSyncPoint(uint32_t sync_point) override; + PP_Bool SetGetBuffer(int32_t shm_id) override; + PP_Bool Flush(int32_t put_offset) override; + scoped_refptr<gpu::Buffer> CreateTransferBuffer(uint32_t size, + int32* id) override; + PP_Bool DestroyTransferBuffer(int32_t id) override; + gpu::CommandBuffer::State WaitForTokenInRange(int32_t start, + int32_t end) override; + gpu::CommandBuffer::State WaitForGetOffsetInRange(int32_t start, + int32_t end) override; + uint32_t InsertSyncPoint() override; + uint32_t InsertFutureSyncPoint() override; + void RetireSyncPoint(uint32_t sync_point) override; private: // PPB_Graphics3D_Shared overrides. - virtual gpu::CommandBuffer* GetCommandBuffer() override; - virtual gpu::GpuControl* GetGpuControl() override; - virtual int32 DoSwapBuffers() override; + gpu::CommandBuffer* GetCommandBuffer() override; + gpu::GpuControl* GetGpuControl() override; + int32 DoSwapBuffers() override; scoped_ptr<PpapiCommandBufferProxy> command_buffer_; @@ -69,7 +68,7 @@ class PPB_Graphics3D_Proxy : public InterfaceProxy { public: PPB_Graphics3D_Proxy(Dispatcher* dispatcher); - virtual ~PPB_Graphics3D_Proxy(); + ~PPB_Graphics3D_Proxy(); static PP_Resource CreateProxyResource( PP_Instance instance, @@ -77,7 +76,7 @@ const int32_t* attrib_list); // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg); + bool OnMessageReceived(const IPC::Message& msg) override; static const ApiID kApiID = API_ID_PPB_GRAPHICS_3D;
diff --git a/ppapi/proxy/ppb_image_data_proxy.h b/ppapi/proxy/ppb_image_data_proxy.h index c321e452..6cd8ba31 100644 --- a/ppapi/proxy/ppb_image_data_proxy.h +++ b/ppapi/proxy/ppb_image_data_proxy.h
@@ -39,17 +39,17 @@ public NON_EXPORTED_BASE(ppapi::thunk::PPB_ImageData_API), public ppapi::PPB_ImageData_Shared { public: - virtual ~ImageData(); + ~ImageData() override; // Resource overrides. - virtual ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() override; - virtual void LastPluginRefWasDeleted() override; - virtual void InstanceWasDeleted() override; + ppapi::thunk::PPB_ImageData_API* AsPPB_ImageData_API() override; + void LastPluginRefWasDeleted() override; + void InstanceWasDeleted() override; // PPB_ImageData API. - virtual PP_Bool Describe(PP_ImageDataDesc* desc) override; - virtual int32_t GetSharedMemory(int* handle, uint32_t* byte_count) override; - virtual void SetIsCandidateForReuse() override; + PP_Bool Describe(PP_ImageDataDesc* desc) override; + int32_t GetSharedMemory(int* handle, uint32_t* byte_count) override; + void SetIsCandidateForReuse() override; PPB_ImageData_Shared::ImageDataType type() const { return type_; } const PP_ImageDataDesc& desc() const { return desc_; } @@ -81,13 +81,13 @@ PlatformImageData(const ppapi::HostResource& resource, const PP_ImageDataDesc& desc, ImageHandle handle); - virtual ~PlatformImageData(); + ~PlatformImageData() override; // PPB_ImageData API. - virtual void* Map() override; - virtual void Unmap() override; - virtual SkCanvas* GetPlatformCanvas() override; - virtual SkCanvas* GetCanvas() override; + void* Map() override; + void Unmap() override; + SkCanvas* GetPlatformCanvas() override; + SkCanvas* GetCanvas() override; static ImageHandle NullHandle(); static ImageHandle HandleFromInt(int32_t i); @@ -110,13 +110,13 @@ SimpleImageData(const ppapi::HostResource& resource, const PP_ImageDataDesc& desc, const base::SharedMemoryHandle& handle); - virtual ~SimpleImageData(); + ~SimpleImageData() override; // PPB_ImageData API. - virtual void* Map() override; - virtual void Unmap() override; - virtual SkCanvas* GetPlatformCanvas() override; - virtual SkCanvas* GetCanvas() override; + void* Map() override; + void Unmap() override; + SkCanvas* GetPlatformCanvas() override; + SkCanvas* GetCanvas() override; private: base::SharedMemory shm_; @@ -129,7 +129,7 @@ class PPB_ImageData_Proxy : public InterfaceProxy { public: PPB_ImageData_Proxy(Dispatcher* dispatcher); - virtual ~PPB_ImageData_Proxy(); + ~PPB_ImageData_Proxy() override; static PP_Resource CreateProxyResource( PP_Instance instance, @@ -139,7 +139,7 @@ PP_Bool init_to_zero); // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg); + bool OnMessageReceived(const IPC::Message& msg) override; // Utility for creating ImageData resources. // This can only be called on the host side of the proxy.
diff --git a/ppapi/proxy/ppb_message_loop_proxy.h b/ppapi/proxy/ppb_message_loop_proxy.h index 73df5f1c..0aa07fe 100644 --- a/ppapi/proxy/ppb_message_loop_proxy.h +++ b/ppapi/proxy/ppb_message_loop_proxy.h
@@ -26,17 +26,16 @@ // Construct the one MessageLoopResource for the main thread. This must be // invoked on the main thread. explicit MessageLoopResource(ForMainThread); - virtual ~MessageLoopResource(); + ~MessageLoopResource() override; // Resource overrides. - virtual thunk::PPB_MessageLoop_API* AsPPB_MessageLoop_API() override; + thunk::PPB_MessageLoop_API* AsPPB_MessageLoop_API() override; // PPB_MessageLoop_API implementation. - virtual int32_t AttachToCurrentThread() override; - virtual int32_t Run() override; - virtual int32_t PostWork(PP_CompletionCallback callback, - int64_t delay_ms) override; - virtual int32_t PostQuit(PP_Bool should_destroy) override; + int32_t AttachToCurrentThread() override; + int32_t Run() override; + int32_t PostWork(PP_CompletionCallback callback, int64_t delay_ms) override; + int32_t PostQuit(PP_Bool should_destroy) override; static MessageLoopResource* GetCurrent(); void DetachFromThread(); @@ -69,11 +68,11 @@ // NOTE: The given closure will be run *WITHOUT* acquiring the Proxy lock. // This only makes sense for user code and completely thread-safe // proxy operations (e.g., MessageLoop::QuitClosure). - virtual void PostClosure(const tracked_objects::Location& from_here, - const base::Closure& closure, - int64 delay_ms) override; - virtual base::MessageLoopProxy* GetMessageLoopProxy() override; - virtual bool CurrentlyHandlingBlockingMessage() override; + void PostClosure(const tracked_objects::Location& from_here, + const base::Closure& closure, + int64 delay_ms) override; + base::MessageLoopProxy* GetMessageLoopProxy() override; + bool CurrentlyHandlingBlockingMessage() override; // TLS destructor function. static void ReleaseMessageLoop(void* value);
diff --git a/ppapi/proxy/ppb_testing_proxy.cc b/ppapi/proxy/ppb_testing_proxy.cc index 606cdc31..914eb44 100644 --- a/ppapi/proxy/ppb_testing_proxy.cc +++ b/ppapi/proxy/ppb_testing_proxy.cc
@@ -80,6 +80,18 @@ return PP_TRUE; } +PP_Bool IsPeripheral(PP_Instance instance_id) { + ProxyAutoLock lock; + PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id); + if (!dispatcher) + return PP_FALSE; + + PP_Bool result = PP_FALSE; + dispatcher->Send(new PpapiHostMsg_PPBTesting_IsPeripheral( + API_ID_PPB_TESTING, instance_id, &result)); + return result; +} + void SimulateInputEvent(PP_Instance instance_id, PP_Resource input_event) { ProxyAutoLock lock; PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance_id); @@ -133,17 +145,17 @@ } const PPB_Testing_Private testing_interface = { - &ReadImageData, - &RunMessageLoop, - &QuitMessageLoop, - &GetLiveObjectsForInstance, - &IsOutOfProcess, - &SimulateInputEvent, - &GetDocumentURL, - &GetLiveVars, - &SetMinimumArrayBufferSizeForShmem, - &RunV8GC -}; + &ReadImageData, + &RunMessageLoop, + &QuitMessageLoop, + &GetLiveObjectsForInstance, + &IsOutOfProcess, + &IsPeripheral, + &SimulateInputEvent, + &GetDocumentURL, + &GetLiveVars, + &SetMinimumArrayBufferSizeForShmem, + &RunV8GC}; } // namespace @@ -174,6 +186,7 @@ OnMsgReadImageData) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_GetLiveObjectsForInstance, OnMsgGetLiveObjectsForInstance) + IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_IsPeripheral, OnMsgIsPeripheral) IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBTesting_SimulateInputEvent, OnMsgSimulateInputEvent) IPC_MESSAGE_HANDLER( @@ -206,6 +219,11 @@ *result = ppb_testing_impl_->GetLiveObjectsForInstance(instance); } +void PPB_Testing_Proxy::OnMsgIsPeripheral(PP_Instance instance, + PP_Bool* result) { + *result = ppb_testing_impl_->IsPeripheral(instance); +} + void PPB_Testing_Proxy::OnMsgSimulateInputEvent( PP_Instance instance, const InputEventData& input_event) {
diff --git a/ppapi/proxy/ppb_testing_proxy.h b/ppapi/proxy/ppb_testing_proxy.h index bcdb53b4..dd8a6e83 100644 --- a/ppapi/proxy/ppb_testing_proxy.h +++ b/ppapi/proxy/ppb_testing_proxy.h
@@ -39,6 +39,7 @@ void OnMsgRunMessageLoop(PP_Instance instance); void OnMsgQuitMessageLoop(PP_Instance instance); void OnMsgGetLiveObjectsForInstance(PP_Instance instance, uint32_t* result); + void OnMsgIsPeripheral(PP_Instance instance, PP_Bool* result); void OnMsgSimulateInputEvent(PP_Instance instance, const ppapi::InputEventData& input_event); void OnMsgSetMinimumArrayBufferSizeForShmem(uint32_t threshold);
diff --git a/ppapi/proxy/ppb_video_decoder_proxy.cc b/ppapi/proxy/ppb_video_decoder_proxy.cc index 779294f..e63423d 100644 --- a/ppapi/proxy/ppb_video_decoder_proxy.cc +++ b/ppapi/proxy/ppb_video_decoder_proxy.cc
@@ -28,21 +28,21 @@ public: // You must call Init() before using this class. explicit VideoDecoder(const HostResource& resource); - virtual ~VideoDecoder(); + ~VideoDecoder() override; static VideoDecoder* Create(const HostResource& resource, PP_Resource graphics_context, PP_VideoDecoder_Profile profile); // PPB_VideoDecoder_Dev_API implementation. - virtual int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer, - scoped_refptr<TrackedCallback> callback) override; - virtual void AssignPictureBuffers( - uint32_t no_of_buffers, const PP_PictureBuffer_Dev* buffers) override; - virtual void ReusePictureBuffer(int32_t picture_buffer_id) override; - virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Reset(scoped_refptr<TrackedCallback> callback) override; - virtual void Destroy() override; + int32_t Decode(const PP_VideoBitstreamBuffer_Dev* bitstream_buffer, + scoped_refptr<TrackedCallback> callback) override; + void AssignPictureBuffers(uint32_t no_of_buffers, + const PP_PictureBuffer_Dev* buffers) override; + void ReusePictureBuffer(int32_t picture_buffer_id) override; + int32_t Flush(scoped_refptr<TrackedCallback> callback) override; + int32_t Reset(scoped_refptr<TrackedCallback> callback) override; + void Destroy() override; private: friend class PPB_VideoDecoder_Proxy;
diff --git a/ppapi/proxy/ppb_x509_certificate_private_proxy.cc b/ppapi/proxy/ppb_x509_certificate_private_proxy.cc index bebea91..df58f43 100644 --- a/ppapi/proxy/ppb_x509_certificate_private_proxy.cc +++ b/ppapi/proxy/ppb_x509_certificate_private_proxy.cc
@@ -17,10 +17,10 @@ class X509CertificatePrivate : public PPB_X509Certificate_Private_Shared { public: X509CertificatePrivate(PP_Instance instance); - virtual ~X509CertificatePrivate(); + ~X509CertificatePrivate() override; - virtual bool ParseDER(const std::vector<char>& der, - PPB_X509Certificate_Fields* result) override; + bool ParseDER(const std::vector<char>& der, + PPB_X509Certificate_Fields* result) override; private: void SendToBrowser(IPC::Message* msg);
diff --git a/ppapi/proxy/ppb_x509_certificate_private_proxy.h b/ppapi/proxy/ppb_x509_certificate_private_proxy.h index b9ad5dfd..95d8f2cd 100644 --- a/ppapi/proxy/ppb_x509_certificate_private_proxy.h +++ b/ppapi/proxy/ppb_x509_certificate_private_proxy.h
@@ -18,11 +18,11 @@ : public InterfaceProxy { public: explicit PPB_X509Certificate_Private_Proxy(Dispatcher* dispatcher); - virtual ~PPB_X509Certificate_Private_Proxy(); + ~PPB_X509Certificate_Private_Proxy() override; static PP_Resource CreateProxyResource(PP_Instance instance); // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; static const ApiID kApiID = API_ID_PPB_X509_CERTIFICATE_PRIVATE;
diff --git a/ppapi/proxy/ppp_instance_private_proxy_unittest.cc b/ppapi/proxy/ppp_instance_private_proxy_unittest.cc index e373c48..8b758d9 100644 --- a/ppapi/proxy/ppp_instance_private_proxy_unittest.cc +++ b/ppapi/proxy/ppp_instance_private_proxy_unittest.cc
@@ -25,11 +25,11 @@ class V8ObjectVar : public ppapi::Var { public: V8ObjectVar() {} - virtual ~V8ObjectVar() {} + ~V8ObjectVar() override {} // Var overrides. - virtual V8ObjectVar* AsV8ObjectVar() override { return this; } - virtual PP_VarType GetType() const override { return PP_VARTYPE_OBJECT; } + V8ObjectVar* AsV8ObjectVar() override { return this; } + PP_VarType GetType() const override { return PP_VARTYPE_OBJECT; } }; namespace proxy {
diff --git a/ppapi/proxy/ppp_messaging_proxy.h b/ppapi/proxy/ppp_messaging_proxy.h index 90b674c..f232c6b 100644 --- a/ppapi/proxy/ppp_messaging_proxy.h +++ b/ppapi/proxy/ppp_messaging_proxy.h
@@ -18,10 +18,10 @@ class PPP_Messaging_Proxy : public InterfaceProxy { public: PPP_Messaging_Proxy(Dispatcher* dispatcher); - virtual ~PPP_Messaging_Proxy(); + ~PPP_Messaging_Proxy() override; // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; private: // Message handlers.
diff --git a/ppapi/proxy/ppp_mouse_lock_proxy.h b/ppapi/proxy/ppp_mouse_lock_proxy.h index 3685e82..f04d7f3 100644 --- a/ppapi/proxy/ppp_mouse_lock_proxy.h +++ b/ppapi/proxy/ppp_mouse_lock_proxy.h
@@ -16,12 +16,12 @@ class PPP_MouseLock_Proxy : public InterfaceProxy { public: PPP_MouseLock_Proxy(Dispatcher* dispatcher); - virtual ~PPP_MouseLock_Proxy(); + ~PPP_MouseLock_Proxy() override; static const PPP_MouseLock* GetProxyInterface(); // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; private: // Message handlers.
diff --git a/ppapi/proxy/ppp_text_input_proxy.h b/ppapi/proxy/ppp_text_input_proxy.h index 59c7a9d..0ae023c 100644 --- a/ppapi/proxy/ppp_text_input_proxy.h +++ b/ppapi/proxy/ppp_text_input_proxy.h
@@ -16,12 +16,12 @@ class PPP_TextInput_Proxy : public InterfaceProxy { public: PPP_TextInput_Proxy(Dispatcher* dispatcher); - virtual ~PPP_TextInput_Proxy(); + ~PPP_TextInput_Proxy() override; static const PPP_TextInput_Dev* GetProxyInterface(); // InterfaceProxy implementation. - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; private: // Message handlers.
diff --git a/ppapi/proxy/printing_resource.h b/ppapi/proxy/printing_resource.h index 0ea6775..deaa1f5c 100644 --- a/ppapi/proxy/printing_resource.h +++ b/ppapi/proxy/printing_resource.h
@@ -20,13 +20,13 @@ public: PrintingResource(Connection connection, PP_Instance instance); - virtual ~PrintingResource(); + ~PrintingResource() override; // Resource overrides. - virtual thunk::PPB_Printing_API* AsPPB_Printing_API() override; + thunk::PPB_Printing_API* AsPPB_Printing_API() override; // PPB_Printing_API. - virtual int32_t GetDefaultPrintSettings( + int32_t GetDefaultPrintSettings( PP_PrintSettings_Dev* print_settings, scoped_refptr<TrackedCallback> callback) override;
diff --git a/ppapi/proxy/proxy_channel.h b/ppapi/proxy/proxy_channel.h index 97069beb..ffa906e 100644 --- a/ppapi/proxy/proxy_channel.h +++ b/ppapi/proxy/proxy_channel.h
@@ -52,7 +52,7 @@ bool should_close_source) = 0; }; - virtual ~ProxyChannel(); + ~ProxyChannel() override; // Alternative to InitWithChannel() for unit tests that want to send all // messages sent via this channel to the given test sink. The test sink @@ -71,10 +71,10 @@ bool should_close_source); // IPC::Sender implementation. - virtual bool Send(IPC::Message* msg) override; + bool Send(IPC::Message* msg) override; // IPC::Listener implementation. - virtual void OnChannelError() override; + void OnChannelError() override; // Will be NULL in some unit tests and if the remote side has crashed. IPC::SyncChannel* channel() const {
diff --git a/ppapi/proxy/proxy_object_var.h b/ppapi/proxy/proxy_object_var.h index e90b29f..a3ba153 100644 --- a/ppapi/proxy/proxy_object_var.h +++ b/ppapi/proxy/proxy_object_var.h
@@ -23,11 +23,11 @@ ProxyObjectVar(proxy::PluginDispatcher* dispatcher, int32 host_var_id); - virtual ~ProxyObjectVar(); + ~ProxyObjectVar() override; // Var overrides. - virtual ProxyObjectVar* AsProxyObjectVar() override; - virtual PP_VarType GetType() const override; + ProxyObjectVar* AsProxyObjectVar() override; + PP_VarType GetType() const override; proxy::PluginDispatcher* dispatcher() const { return dispatcher_; } int32 host_var_id() const { return host_var_id_; }
diff --git a/ppapi/proxy/raw_var_data.h b/ppapi/proxy/raw_var_data.h index 4387eb2..08b85fa 100644 --- a/ppapi/proxy/raw_var_data.h +++ b/ppapi/proxy/raw_var_data.h
@@ -129,19 +129,18 @@ class BasicRawVarData : public RawVarData { public: BasicRawVarData(); - virtual ~BasicRawVarData(); + ~BasicRawVarData() override; // RawVarData implementation. - virtual PP_VarType Type() override; - virtual bool Init(const PP_Var& var, PP_Instance instance) override; - virtual PP_Var CreatePPVar(PP_Instance instance) override; - virtual void PopulatePPVar(const PP_Var& var, - const std::vector<PP_Var>& graph) override; - virtual void Write(IPC::Message* m, - const HandleWriter& handle_writer) override; - virtual bool Read(PP_VarType type, - const IPC::Message* m, - PickleIterator* iter) override; + PP_VarType Type() override; + bool Init(const PP_Var& var, PP_Instance instance) override; + PP_Var CreatePPVar(PP_Instance instance) override; + void PopulatePPVar(const PP_Var& var, + const std::vector<PP_Var>& graph) override; + void Write(IPC::Message* m, const HandleWriter& handle_writer) override; + bool Read(PP_VarType type, + const IPC::Message* m, + PickleIterator* iter) override; private: PP_Var var_; @@ -151,19 +150,18 @@ class StringRawVarData : public RawVarData { public: StringRawVarData(); - virtual ~StringRawVarData(); + ~StringRawVarData() override; // RawVarData implementation. - virtual PP_VarType Type() override; - virtual bool Init(const PP_Var& var, PP_Instance instance) override; - virtual PP_Var CreatePPVar(PP_Instance instance) override; - virtual void PopulatePPVar(const PP_Var& var, - const std::vector<PP_Var>& graph) override; - virtual void Write(IPC::Message* m, - const HandleWriter& handle_writer) override; - virtual bool Read(PP_VarType type, - const IPC::Message* m, - PickleIterator* iter) override; + PP_VarType Type() override; + bool Init(const PP_Var& var, PP_Instance instance) override; + PP_Var CreatePPVar(PP_Instance instance) override; + void PopulatePPVar(const PP_Var& var, + const std::vector<PP_Var>& graph) override; + void Write(IPC::Message* m, const HandleWriter& handle_writer) override; + bool Read(PP_VarType type, + const IPC::Message* m, + PickleIterator* iter) override; private: // The data in the string. @@ -181,20 +179,19 @@ }; ArrayBufferRawVarData(); - virtual ~ArrayBufferRawVarData(); + ~ArrayBufferRawVarData() override; // RawVarData implementation. - virtual PP_VarType Type() override; - virtual bool Init(const PP_Var& var, PP_Instance instance) override; - virtual PP_Var CreatePPVar(PP_Instance instance) override; - virtual void PopulatePPVar(const PP_Var& var, - const std::vector<PP_Var>& graph) override; - virtual void Write(IPC::Message* m, - const HandleWriter& handle_writer) override; - virtual bool Read(PP_VarType type, - const IPC::Message* m, - PickleIterator* iter) override; - virtual SerializedHandle* GetHandle() override; + PP_VarType Type() override; + bool Init(const PP_Var& var, PP_Instance instance) override; + PP_Var CreatePPVar(PP_Instance instance) override; + void PopulatePPVar(const PP_Var& var, + const std::vector<PP_Var>& graph) override; + void Write(IPC::Message* m, const HandleWriter& handle_writer) override; + bool Read(PP_VarType type, + const IPC::Message* m, + PickleIterator* iter) override; + SerializedHandle* GetHandle() override; private: // The type of the storage underlying the array buffer. @@ -211,21 +208,20 @@ class ArrayRawVarData : public RawVarData { public: ArrayRawVarData(); - virtual ~ArrayRawVarData(); + ~ArrayRawVarData() override; void AddChild(size_t element); // RawVarData implementation. - virtual PP_VarType Type() override; - virtual bool Init(const PP_Var& var, PP_Instance instance) override; - virtual PP_Var CreatePPVar(PP_Instance instance) override; - virtual void PopulatePPVar(const PP_Var& var, - const std::vector<PP_Var>& graph) override; - virtual void Write(IPC::Message* m, - const HandleWriter& handle_writer) override; - virtual bool Read(PP_VarType type, - const IPC::Message* m, - PickleIterator* iter) override; + PP_VarType Type() override; + bool Init(const PP_Var& var, PP_Instance instance) override; + PP_Var CreatePPVar(PP_Instance instance) override; + void PopulatePPVar(const PP_Var& var, + const std::vector<PP_Var>& graph) override; + void Write(IPC::Message* m, const HandleWriter& handle_writer) override; + bool Read(PP_VarType type, + const IPC::Message* m, + PickleIterator* iter) override; private: std::vector<size_t> children_; @@ -235,21 +231,20 @@ class DictionaryRawVarData : public RawVarData { public: DictionaryRawVarData(); - virtual ~DictionaryRawVarData(); + ~DictionaryRawVarData() override; void AddChild(const std::string& key, size_t value); // RawVarData implementation. - virtual PP_VarType Type() override; - virtual bool Init(const PP_Var& var, PP_Instance instance) override; - virtual PP_Var CreatePPVar(PP_Instance instance) override; - virtual void PopulatePPVar(const PP_Var& var, - const std::vector<PP_Var>& graph) override; - virtual void Write(IPC::Message* m, - const HandleWriter& handle_writer) override; - virtual bool Read(PP_VarType type, - const IPC::Message* m, - PickleIterator* iter) override; + PP_VarType Type() override; + bool Init(const PP_Var& var, PP_Instance instance) override; + PP_Var CreatePPVar(PP_Instance instance) override; + void PopulatePPVar(const PP_Var& var, + const std::vector<PP_Var>& graph) override; + void Write(IPC::Message* m, const HandleWriter& handle_writer) override; + bool Read(PP_VarType type, + const IPC::Message* m, + PickleIterator* iter) override; private: std::vector<std::pair<std::string, size_t> > children_; @@ -264,19 +259,18 @@ class ResourceRawVarData : public RawVarData { public: ResourceRawVarData(); - virtual ~ResourceRawVarData(); + ~ResourceRawVarData() override; // RawVarData implementation. - virtual PP_VarType Type() override; - virtual bool Init(const PP_Var& var, PP_Instance instance) override; - virtual PP_Var CreatePPVar(PP_Instance instance) override; - virtual void PopulatePPVar(const PP_Var& var, - const std::vector<PP_Var>& graph) override; - virtual void Write(IPC::Message* m, - const HandleWriter& handle_writer) override; - virtual bool Read(PP_VarType type, - const IPC::Message* m, - PickleIterator* iter) override; + PP_VarType Type() override; + bool Init(const PP_Var& var, PP_Instance instance) override; + PP_Var CreatePPVar(PP_Instance instance) override; + void PopulatePPVar(const PP_Var& var, + const std::vector<PP_Var>& graph) override; + void Write(IPC::Message* m, const HandleWriter& handle_writer) override; + bool Read(PP_VarType type, + const IPC::Message* m, + PickleIterator* iter) override; private: // Resource ID in the plugin. If one has not yet been created, this is 0.
diff --git a/ppapi/proxy/resource_creation_proxy.h b/ppapi/proxy/resource_creation_proxy.h index bdbc83a4..1e6d901 100644 --- a/ppapi/proxy/resource_creation_proxy.h +++ b/ppapi/proxy/resource_creation_proxy.h
@@ -30,36 +30,36 @@ public thunk::ResourceCreationAPI { public: explicit ResourceCreationProxy(Dispatcher* dispatcher); - virtual ~ResourceCreationProxy(); + ~ResourceCreationProxy() override; // Factory function used for registration (normal code can just use the // constructor). static InterfaceProxy* Create(Dispatcher* dispatcher); // ResourceCreationAPI (called in plugin). - virtual PP_Resource CreateFileIO(PP_Instance instance) override; - virtual PP_Resource CreateFileRef( + PP_Resource CreateFileIO(PP_Instance instance) override; + PP_Resource CreateFileRef( PP_Instance instance, const FileRefCreateInfo& create_info) override; - virtual PP_Resource CreateFileSystem(PP_Instance instance, - PP_FileSystemType type) override; - virtual PP_Resource CreateIMEInputEvent(PP_Instance instance, - PP_InputEvent_Type type, - PP_TimeTicks time_stamp, - struct PP_Var text, - uint32_t segment_number, - const uint32_t* segment_offsets, - int32_t target_segment, - uint32_t selection_start, - uint32_t selection_end) override; - virtual PP_Resource CreateKeyboardInputEvent_1_0( + PP_Resource CreateFileSystem(PP_Instance instance, + PP_FileSystemType type) override; + PP_Resource CreateIMEInputEvent(PP_Instance instance, + PP_InputEvent_Type type, + PP_TimeTicks time_stamp, + struct PP_Var text, + uint32_t segment_number, + const uint32_t* segment_offsets, + int32_t target_segment, + uint32_t selection_start, + uint32_t selection_end) override; + PP_Resource CreateKeyboardInputEvent_1_0( PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers, uint32_t key_code, PP_Var character_text) override; - virtual PP_Resource CreateKeyboardInputEvent_1_2( + PP_Resource CreateKeyboardInputEvent_1_2( PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, @@ -67,7 +67,7 @@ uint32_t key_code, PP_Var character_text, PP_Var code) override; - virtual PP_Resource CreateMouseInputEvent( + PP_Resource CreateMouseInputEvent( PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, @@ -76,121 +76,114 @@ const PP_Point* mouse_position, int32_t click_count, const PP_Point* mouse_movement) override; - virtual PP_Resource CreateTouchInputEvent( + PP_Resource CreateTouchInputEvent( PP_Instance instance, PP_InputEvent_Type type, PP_TimeTicks time_stamp, uint32_t modifiers) override; - virtual PP_Resource CreateTrueTypeFont( + PP_Resource CreateTrueTypeFont( PP_Instance instance, const PP_TrueTypeFontDesc_Dev* desc) override; - virtual PP_Resource CreateURLLoader(PP_Instance instance) override; - virtual PP_Resource CreateURLRequestInfo( - PP_Instance instance) override; - virtual PP_Resource CreateWheelInputEvent( + PP_Resource CreateURLLoader(PP_Instance instance) override; + PP_Resource CreateURLRequestInfo(PP_Instance instance) override; + PP_Resource CreateWheelInputEvent( PP_Instance instance, PP_TimeTicks time_stamp, uint32_t modifiers, const PP_FloatPoint* wheel_delta, const PP_FloatPoint* wheel_ticks, PP_Bool scroll_by_page) override; - virtual PP_Resource CreateAudio1_0(PP_Instance instance, - PP_Resource config_id, - PPB_Audio_Callback_1_0 audio_callback, - void* user_data) override; - virtual PP_Resource CreateAudio(PP_Instance instance, - PP_Resource config_id, - PPB_Audio_Callback audio_callback, - void* user_data) override; - virtual PP_Resource CreateAudioTrusted(PP_Instance instance) override; - virtual PP_Resource CreateAudioConfig(PP_Instance instance, - PP_AudioSampleRate sample_rate, - uint32_t sample_frame_count) override; - virtual PP_Resource CreateCameraDevicePrivate(PP_Instance instance) override; - virtual PP_Resource CreateCompositor(PP_Instance instance) override; - virtual PP_Resource CreateFileChooser(PP_Instance instance, - PP_FileChooserMode_Dev mode, - const PP_Var& accept_types) override; - virtual PP_Resource CreateGraphics2D(PP_Instance pp_instance, - const PP_Size* size, - PP_Bool is_always_opaque) override; - virtual PP_Resource CreateGraphics3D(PP_Instance instance, - PP_Resource share_context, - const int32_t* attrib_list) override; - virtual PP_Resource CreateGraphics3DRaw( + PP_Resource CreateAudio1_0(PP_Instance instance, + PP_Resource config_id, + PPB_Audio_Callback_1_0 audio_callback, + void* user_data) override; + PP_Resource CreateAudio(PP_Instance instance, + PP_Resource config_id, + PPB_Audio_Callback audio_callback, + void* user_data) override; + PP_Resource CreateAudioTrusted(PP_Instance instance) override; + PP_Resource CreateAudioConfig(PP_Instance instance, + PP_AudioSampleRate sample_rate, + uint32_t sample_frame_count) override; + PP_Resource CreateCameraDevicePrivate(PP_Instance instance) override; + PP_Resource CreateCompositor(PP_Instance instance) override; + PP_Resource CreateFileChooser(PP_Instance instance, + PP_FileChooserMode_Dev mode, + const PP_Var& accept_types) override; + PP_Resource CreateGraphics2D(PP_Instance pp_instance, + const PP_Size* size, + PP_Bool is_always_opaque) override; + PP_Resource CreateGraphics3D(PP_Instance instance, + PP_Resource share_context, + const int32_t* attrib_list) override; + PP_Resource CreateGraphics3DRaw( PP_Instance instance, PP_Resource share_context, const int32_t* attrib_list, gpu::Capabilities* capabilities, base::SharedMemoryHandle* shared_state) override; - virtual PP_Resource CreateHostResolver(PP_Instance instance) override; - virtual PP_Resource CreateHostResolverPrivate(PP_Instance instance) override; - virtual PP_Resource CreateImageData(PP_Instance instance, - PP_ImageDataFormat format, - const PP_Size* size, - PP_Bool init_to_zero) override; - virtual PP_Resource CreateImageDataSimple(PP_Instance instance, - PP_ImageDataFormat format, - const PP_Size* size, - PP_Bool init_to_zero) override; - virtual PP_Resource CreateMediaStreamVideoTrack( - PP_Instance instance) override; - virtual PP_Resource CreateNetAddressFromIPv4Address( + PP_Resource CreateHostResolver(PP_Instance instance) override; + PP_Resource CreateHostResolverPrivate(PP_Instance instance) override; + PP_Resource CreateImageData(PP_Instance instance, + PP_ImageDataFormat format, + const PP_Size* size, + PP_Bool init_to_zero) override; + PP_Resource CreateImageDataSimple(PP_Instance instance, + PP_ImageDataFormat format, + const PP_Size* size, + PP_Bool init_to_zero) override; + PP_Resource CreateMediaStreamVideoTrack(PP_Instance instance) override; + PP_Resource CreateNetAddressFromIPv4Address( PP_Instance instance, const PP_NetAddress_IPv4* ipv4_addr) override; - virtual PP_Resource CreateNetAddressFromIPv6Address( + PP_Resource CreateNetAddressFromIPv6Address( PP_Instance instance, const PP_NetAddress_IPv6* ipv6_addr) override; - virtual PP_Resource CreateNetAddressFromNetAddressPrivate( + PP_Resource CreateNetAddressFromNetAddressPrivate( PP_Instance instance, const PP_NetAddress_Private& private_addr) override; - virtual PP_Resource CreateNetworkMonitor(PP_Instance instance) override; - virtual PP_Resource CreateOutputProtectionPrivate( - PP_Instance instance) override; - virtual PP_Resource CreatePrinting(PP_Instance) override; - virtual PP_Resource CreateTCPServerSocketPrivate( - PP_Instance instance) override; - virtual PP_Resource CreateTCPSocket1_0(PP_Instance instance) override; - virtual PP_Resource CreateTCPSocket(PP_Instance instance) override; - virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) override; - virtual PP_Resource CreateUDPSocket(PP_Instance instance) override; - virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) override; - virtual PP_Resource CreateVideoDecoder(PP_Instance instance) override; - virtual PP_Resource CreateVideoDestination(PP_Instance instance) override; - virtual PP_Resource CreateVideoEncoder(PP_Instance instance) override; - virtual PP_Resource CreateVideoSource(PP_Instance instance) override; - virtual PP_Resource CreateWebSocket(PP_Instance instance) override; - virtual PP_Resource CreateX509CertificatePrivate( - PP_Instance instance) override; + PP_Resource CreateNetworkMonitor(PP_Instance instance) override; + PP_Resource CreateOutputProtectionPrivate(PP_Instance instance) override; + PP_Resource CreatePrinting(PP_Instance) override; + PP_Resource CreateTCPServerSocketPrivate(PP_Instance instance) override; + PP_Resource CreateTCPSocket1_0(PP_Instance instance) override; + PP_Resource CreateTCPSocket(PP_Instance instance) override; + PP_Resource CreateTCPSocketPrivate(PP_Instance instance) override; + PP_Resource CreateUDPSocket(PP_Instance instance) override; + PP_Resource CreateUDPSocketPrivate(PP_Instance instance) override; + PP_Resource CreateVideoDecoder(PP_Instance instance) override; + PP_Resource CreateVideoDestination(PP_Instance instance) override; + PP_Resource CreateVideoEncoder(PP_Instance instance) override; + PP_Resource CreateVideoSource(PP_Instance instance) override; + PP_Resource CreateWebSocket(PP_Instance instance) override; + PP_Resource CreateX509CertificatePrivate(PP_Instance instance) override; #if !defined(OS_NACL) - virtual PP_Resource CreateAudioInput(PP_Instance instance) override; - virtual PP_Resource CreateBroker(PP_Instance instance) override; - virtual PP_Resource CreateBrowserFont( + PP_Resource CreateAudioInput(PP_Instance instance) override; + PP_Resource CreateBroker(PP_Instance instance) override; + PP_Resource CreateBrowserFont( PP_Instance instance, const PP_BrowserFont_Trusted_Description* description) override; - virtual PP_Resource CreateBuffer(PP_Instance instance, - uint32_t size) override; - virtual PP_Resource CreateFlashDRM(PP_Instance instance) override; - virtual PP_Resource CreateFlashFontFile( + PP_Resource CreateBuffer(PP_Instance instance, uint32_t size) override; + PP_Resource CreateFlashDRM(PP_Instance instance) override; + PP_Resource CreateFlashFontFile( PP_Instance instance, const PP_BrowserFont_Trusted_Description* description, PP_PrivateFontCharset charset) override; - virtual PP_Resource CreateFlashMenu(PP_Instance instance, - const PP_Flash_Menu* menu_data) override; - virtual PP_Resource CreateFlashMessageLoop(PP_Instance instance) override; - virtual PP_Resource CreatePlatformVerificationPrivate( - PP_Instance instance) override; - virtual PP_Resource CreateScrollbar(PP_Instance instance, - PP_Bool vertical) override; - virtual PP_Resource CreateVideoCapture(PP_Instance instance) override; - virtual PP_Resource CreateVideoDecoderDev( + PP_Resource CreateFlashMenu(PP_Instance instance, + const PP_Flash_Menu* menu_data) override; + PP_Resource CreateFlashMessageLoop(PP_Instance instance) override; + PP_Resource CreatePlatformVerificationPrivate(PP_Instance instance) override; + PP_Resource CreateScrollbar(PP_Instance instance, + PP_Bool vertical) override; + PP_Resource CreateVideoCapture(PP_Instance instance) override; + PP_Resource CreateVideoDecoderDev( PP_Instance instance, PP_Resource context3d_id, PP_VideoDecoder_Profile profile) override; #endif // !defined(OS_NACL) - virtual bool Send(IPC::Message* msg) override; - virtual bool OnMessageReceived(const IPC::Message& msg) override; + bool Send(IPC::Message* msg) override; + bool OnMessageReceived(const IPC::Message& msg) override; private: Connection GetConnection();
diff --git a/ppapi/proxy/resource_message_params.h b/ppapi/proxy/resource_message_params.h index 2e21e75..da945b3 100644 --- a/ppapi/proxy/resource_message_params.h +++ b/ppapi/proxy/resource_message_params.h
@@ -139,14 +139,13 @@ public: ResourceMessageCallParams(); ResourceMessageCallParams(PP_Resource resource, int32_t sequence); - virtual ~ResourceMessageCallParams(); + ~ResourceMessageCallParams() override; void set_has_callback() { has_callback_ = true; } bool has_callback() const { return has_callback_; } - virtual void Serialize(IPC::Message* msg) const override; - virtual bool Deserialize(const IPC::Message* msg, - PickleIterator* iter) override; + void Serialize(IPC::Message* msg) const override; + bool Deserialize(const IPC::Message* msg, PickleIterator* iter) override; private: bool has_callback_; @@ -158,14 +157,13 @@ public: ResourceMessageReplyParams(); ResourceMessageReplyParams(PP_Resource resource, int32_t sequence); - virtual ~ResourceMessageReplyParams(); + ~ResourceMessageReplyParams() override; void set_result(int32_t r) { result_ = r; } int32_t result() const { return result_; } - virtual void Serialize(IPC::Message* msg) const override; - virtual bool Deserialize(const IPC::Message* msg, - PickleIterator* iter) override; + void Serialize(IPC::Message* msg) const override; + bool Deserialize(const IPC::Message* msg, PickleIterator* iter) override; // Writes everything except the handles to |msg|. void WriteReplyHeader(IPC::Message* msg) const;
diff --git a/ppapi/proxy/resource_message_test_sink.h b/ppapi/proxy/resource_message_test_sink.h index 9c7513f..3e40e310 100644 --- a/ppapi/proxy/resource_message_test_sink.h +++ b/ppapi/proxy/resource_message_test_sink.h
@@ -21,11 +21,11 @@ class ResourceMessageTestSink : public IPC::TestSink { public: ResourceMessageTestSink(); - virtual ~ResourceMessageTestSink(); + ~ResourceMessageTestSink() override; // IPC::TestSink. // Overridden to handle sync messages. - virtual bool Send(IPC::Message* msg) override; + bool Send(IPC::Message* msg) override; // Sets the reply message that will be returned to the next sync message sent. // This test sink owns any reply messages passed into this method. @@ -82,10 +82,10 @@ uint32 incoming_type, int32_t result, const IPC::Message& reply_msg); - virtual ~ResourceSyncCallHandler(); + ~ResourceSyncCallHandler() override; // IPC::Listener. - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; IPC::Message last_handled_msg() { return last_handled_msg_; }
diff --git a/ppapi/proxy/tcp_server_socket_private_resource.h b/ppapi/proxy/tcp_server_socket_private_resource.h index dad3fd8..055b3b0 100644 --- a/ppapi/proxy/tcp_server_socket_private_resource.h +++ b/ppapi/proxy/tcp_server_socket_private_resource.h
@@ -21,20 +21,20 @@ public thunk::PPB_TCPServerSocket_Private_API { public: TCPServerSocketPrivateResource(Connection connection, PP_Instance instance); - virtual ~TCPServerSocketPrivateResource(); + ~TCPServerSocketPrivateResource() override; // PluginResource implementation. - virtual thunk::PPB_TCPServerSocket_Private_API* - AsPPB_TCPServerSocket_Private_API() override; + thunk::PPB_TCPServerSocket_Private_API* AsPPB_TCPServerSocket_Private_API() + override; // PPB_TCPServerSocket_Private_API implementation. - virtual int32_t Listen(const PP_NetAddress_Private* addr, - int32_t backlog, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Accept(PP_Resource* tcp_socket, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetLocalAddress(PP_NetAddress_Private* addr) override; - virtual void StopListening() override; + int32_t Listen(const PP_NetAddress_Private* addr, + int32_t backlog, + scoped_refptr<TrackedCallback> callback) override; + int32_t Accept(PP_Resource* tcp_socket, + scoped_refptr<TrackedCallback> callback) override; + int32_t GetLocalAddress(PP_NetAddress_Private* addr) override; + void StopListening() override; private: enum State {
diff --git a/ppapi/proxy/tcp_socket_private_resource.h b/ppapi/proxy/tcp_socket_private_resource.h index 9c0b182..bbc5b1cc 100644 --- a/ppapi/proxy/tcp_socket_private_resource.h +++ b/ppapi/proxy/tcp_socket_private_resource.h
@@ -27,40 +27,40 @@ const PP_NetAddress_Private& local_addr, const PP_NetAddress_Private& remote_addr); - virtual ~TCPSocketPrivateResource(); + ~TCPSocketPrivateResource() override; // PluginResource overrides. - virtual PPB_TCPSocket_Private_API* AsPPB_TCPSocket_Private_API() override; + PPB_TCPSocket_Private_API* AsPPB_TCPSocket_Private_API() override; // PPB_TCPSocket_Private_API implementation. - virtual int32_t Connect(const char* host, - uint16_t port, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t ConnectWithNetAddress( + int32_t Connect(const char* host, + uint16_t port, + scoped_refptr<TrackedCallback> callback) override; + int32_t ConnectWithNetAddress( const PP_NetAddress_Private* addr, scoped_refptr<TrackedCallback> callback) override; - virtual PP_Bool GetLocalAddress(PP_NetAddress_Private* local_addr) override; - virtual PP_Bool GetRemoteAddress(PP_NetAddress_Private* remote_addr) override; - virtual int32_t SSLHandshake( + PP_Bool GetLocalAddress(PP_NetAddress_Private* local_addr) override; + PP_Bool GetRemoteAddress(PP_NetAddress_Private* remote_addr) override; + int32_t SSLHandshake( const char* server_name, uint16_t server_port, scoped_refptr<TrackedCallback> callback) override; - virtual PP_Resource GetServerCertificate() override; - virtual PP_Bool AddChainBuildingCertificate(PP_Resource certificate, - PP_Bool trusted) override; - virtual int32_t Read(char* buffer, - int32_t bytes_to_read, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Write(const char* buffer, - int32_t bytes_to_write, - scoped_refptr<TrackedCallback> callback) override; - virtual void Disconnect() override; - virtual int32_t SetOption(PP_TCPSocketOption_Private name, - const PP_Var& value, - scoped_refptr<TrackedCallback> callback) override; + PP_Resource GetServerCertificate() override; + PP_Bool AddChainBuildingCertificate(PP_Resource certificate, + PP_Bool trusted) override; + int32_t Read(char* buffer, + int32_t bytes_to_read, + scoped_refptr<TrackedCallback> callback) override; + int32_t Write(const char* buffer, + int32_t bytes_to_write, + scoped_refptr<TrackedCallback> callback) override; + void Disconnect() override; + int32_t SetOption(PP_TCPSocketOption_Private name, + const PP_Var& value, + scoped_refptr<TrackedCallback> callback) override; // TCPSocketResourceBase implementation. - virtual PP_Resource CreateAcceptedSocket( + PP_Resource CreateAcceptedSocket( int pending_host_id, const PP_NetAddress_Private& local_addr, const PP_NetAddress_Private& remote_addr) override;
diff --git a/ppapi/proxy/tcp_socket_resource.h b/ppapi/proxy/tcp_socket_resource.h index 6ac09298..449cab6 100644 --- a/ppapi/proxy/tcp_socket_resource.h +++ b/ppapi/proxy/tcp_socket_resource.h
@@ -24,39 +24,39 @@ PP_Instance instance, TCPSocketVersion version); - virtual ~TCPSocketResource(); + ~TCPSocketResource() override; // PluginResource overrides. - virtual thunk::PPB_TCPSocket_API* AsPPB_TCPSocket_API() override; + thunk::PPB_TCPSocket_API* AsPPB_TCPSocket_API() override; // thunk::PPB_TCPSocket_API implementation. - virtual int32_t Bind(PP_Resource addr, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Connect(PP_Resource addr, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Resource GetLocalAddress() override; - virtual PP_Resource GetRemoteAddress() override; - virtual int32_t Read(char* buffer, - int32_t bytes_to_read, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Write(const char* buffer, - int32_t bytes_to_write, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Listen(int32_t backlog, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Accept(PP_Resource* accepted_tcp_socket, - scoped_refptr<TrackedCallback> callback) override; - virtual void Close() override; - virtual int32_t SetOption1_1( + int32_t Bind(PP_Resource addr, + scoped_refptr<TrackedCallback> callback) override; + int32_t Connect(PP_Resource addr, + scoped_refptr<TrackedCallback> callback) override; + PP_Resource GetLocalAddress() override; + PP_Resource GetRemoteAddress() override; + int32_t Read(char* buffer, + int32_t bytes_to_read, + scoped_refptr<TrackedCallback> callback) override; + int32_t Write(const char* buffer, + int32_t bytes_to_write, + scoped_refptr<TrackedCallback> callback) override; + int32_t Listen(int32_t backlog, + scoped_refptr<TrackedCallback> callback) override; + int32_t Accept(PP_Resource* accepted_tcp_socket, + scoped_refptr<TrackedCallback> callback) override; + void Close() override; + int32_t SetOption1_1( PP_TCPSocket_Option name, const PP_Var& value, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t SetOption(PP_TCPSocket_Option name, - const PP_Var& value, - scoped_refptr<TrackedCallback> callback) override; + int32_t SetOption(PP_TCPSocket_Option name, + const PP_Var& value, + scoped_refptr<TrackedCallback> callback) override; // TCPSocketResourceBase implementation. - virtual PP_Resource CreateAcceptedSocket( + PP_Resource CreateAcceptedSocket( int pending_host_id, const PP_NetAddress_Private& local_addr, const PP_NetAddress_Private& remote_addr) override;
diff --git a/ppapi/proxy/truetype_font_resource.h b/ppapi/proxy/truetype_font_resource.h index fb5f5c2..2f44365 100644 --- a/ppapi/proxy/truetype_font_resource.h +++ b/ppapi/proxy/truetype_font_resource.h
@@ -30,19 +30,19 @@ TrueTypeFontResource(Connection connection, PP_Instance instance, const PP_TrueTypeFontDesc_Dev& desc); - virtual ~TrueTypeFontResource(); + ~TrueTypeFontResource() override; // Resource implementation. - virtual thunk::PPB_TrueTypeFont_API* AsPPB_TrueTypeFont_API() override; + thunk::PPB_TrueTypeFont_API* AsPPB_TrueTypeFont_API() override; // PPB_TrueTypeFont_API implementation. - virtual int32_t Describe( + int32_t Describe( PP_TrueTypeFontDesc_Dev* desc, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetTableTags( + int32_t GetTableTags( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetTable( + int32_t GetTable( uint32_t table, int32_t offset, int32_t max_data_length, @@ -50,8 +50,8 @@ scoped_refptr<TrackedCallback> callback) override; // PluginResource implementation. - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; private: void OnPluginMsgCreateComplete(
diff --git a/ppapi/proxy/truetype_font_singleton_resource.h b/ppapi/proxy/truetype_font_singleton_resource.h index 78d02a6c..df09471 100644 --- a/ppapi/proxy/truetype_font_singleton_resource.h +++ b/ppapi/proxy/truetype_font_singleton_resource.h
@@ -27,18 +27,18 @@ public thunk::PPB_TrueTypeFont_Singleton_API { public: TrueTypeFontSingletonResource(Connection connection, PP_Instance instance); - virtual ~TrueTypeFontSingletonResource(); + ~TrueTypeFontSingletonResource() override; // Resource override. - virtual thunk::PPB_TrueTypeFont_Singleton_API* - AsPPB_TrueTypeFont_Singleton_API() override; + thunk::PPB_TrueTypeFont_Singleton_API* AsPPB_TrueTypeFont_Singleton_API() + override; // thunk::PPB_TrueTypeFont_Singleton_API implementation. - virtual int32_t GetFontFamilies( + int32_t GetFontFamilies( PP_Instance instance, const PP_ArrayOutput& output, const scoped_refptr<TrackedCallback>& callback) override; - virtual int32_t GetFontsInFamily( + int32_t GetFontsInFamily( PP_Instance instance, PP_Var family, const PP_ArrayOutput& output,
diff --git a/ppapi/proxy/udp_socket_private_resource.h b/ppapi/proxy/udp_socket_private_resource.h index 899c5886..f335c6c9 100644 --- a/ppapi/proxy/udp_socket_private_resource.h +++ b/ppapi/proxy/udp_socket_private_resource.h
@@ -19,27 +19,26 @@ public thunk::PPB_UDPSocket_Private_API { public: UDPSocketPrivateResource(Connection connection, PP_Instance instance); - virtual ~UDPSocketPrivateResource(); + ~UDPSocketPrivateResource() override; // PluginResource implementation. - virtual thunk::PPB_UDPSocket_Private_API* - AsPPB_UDPSocket_Private_API() override; + thunk::PPB_UDPSocket_Private_API* AsPPB_UDPSocket_Private_API() override; // PPB_UDPSocket_Private_API implementation. - virtual int32_t SetSocketFeature(PP_UDPSocketFeature_Private name, - PP_Var value) override; - virtual int32_t Bind(const PP_NetAddress_Private* addr, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Bool GetBoundAddress(PP_NetAddress_Private* addr) override; - virtual int32_t RecvFrom(char* buffer, - int32_t num_bytes, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Bool GetRecvFromAddress(PP_NetAddress_Private* addr) override; - virtual int32_t SendTo(const char* buffer, - int32_t num_bytes, - const PP_NetAddress_Private* addr, - scoped_refptr<TrackedCallback> callback) override; - virtual void Close() override; + int32_t SetSocketFeature(PP_UDPSocketFeature_Private name, + PP_Var value) override; + int32_t Bind(const PP_NetAddress_Private* addr, + scoped_refptr<TrackedCallback> callback) override; + PP_Bool GetBoundAddress(PP_NetAddress_Private* addr) override; + int32_t RecvFrom(char* buffer, + int32_t num_bytes, + scoped_refptr<TrackedCallback> callback) override; + PP_Bool GetRecvFromAddress(PP_NetAddress_Private* addr) override; + int32_t SendTo(const char* buffer, + int32_t num_bytes, + const PP_NetAddress_Private* addr, + scoped_refptr<TrackedCallback> callback) override; + void Close() override; private: DISALLOW_COPY_AND_ASSIGN(UDPSocketPrivateResource);
diff --git a/ppapi/proxy/udp_socket_resource.h b/ppapi/proxy/udp_socket_resource.h index 1516067..5217d969 100644 --- a/ppapi/proxy/udp_socket_resource.h +++ b/ppapi/proxy/udp_socket_resource.h
@@ -18,39 +18,39 @@ public thunk::PPB_UDPSocket_API { public: UDPSocketResource(Connection connection, PP_Instance instance); - virtual ~UDPSocketResource(); + ~UDPSocketResource() override; // PluginResource implementation. - virtual thunk::PPB_UDPSocket_API* AsPPB_UDPSocket_API() override; + thunk::PPB_UDPSocket_API* AsPPB_UDPSocket_API() override; // thunk::PPB_UDPSocket_API implementation. - virtual int32_t Bind(PP_Resource addr, - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Resource GetBoundAddress() override; - virtual int32_t RecvFrom(char* buffer, - int32_t num_bytes, - PP_Resource* addr, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t SendTo(const char* buffer, - int32_t num_bytes, - PP_Resource addr, - scoped_refptr<TrackedCallback> callback) override; - virtual void Close() override; - virtual int32_t SetOption1_0( + int32_t Bind(PP_Resource addr, + scoped_refptr<TrackedCallback> callback) override; + PP_Resource GetBoundAddress() override; + int32_t RecvFrom(char* buffer, + int32_t num_bytes, + PP_Resource* addr, + scoped_refptr<TrackedCallback> callback) override; + int32_t SendTo(const char* buffer, + int32_t num_bytes, + PP_Resource addr, + scoped_refptr<TrackedCallback> callback) override; + void Close() override; + int32_t SetOption1_0( PP_UDPSocket_Option name, const PP_Var& value, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t SetOption1_1( + int32_t SetOption1_1( PP_UDPSocket_Option name, const PP_Var& value, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t SetOption(PP_UDPSocket_Option name, - const PP_Var& value, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t JoinGroup(PP_Resource group, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t LeaveGroup(PP_Resource group, - scoped_refptr<TrackedCallback> callback) override; + int32_t SetOption(PP_UDPSocket_Option name, + const PP_Var& value, + scoped_refptr<TrackedCallback> callback) override; + int32_t JoinGroup(PP_Resource group, + scoped_refptr<TrackedCallback> callback) override; + int32_t LeaveGroup(PP_Resource group, + scoped_refptr<TrackedCallback> callback) override; private: DISALLOW_COPY_AND_ASSIGN(UDPSocketResource);
diff --git a/ppapi/proxy/uma_private_resource.h b/ppapi/proxy/uma_private_resource.h index 2057ff0..3215e64 100644 --- a/ppapi/proxy/uma_private_resource.h +++ b/ppapi/proxy/uma_private_resource.h
@@ -19,32 +19,32 @@ public thunk::PPB_UMA_Singleton_API { public: UMAPrivateResource(Connection connection, PP_Instance instance); - virtual ~UMAPrivateResource(); + ~UMAPrivateResource() override; // Resource overrides. - virtual thunk::PPB_UMA_Singleton_API* AsPPB_UMA_Singleton_API() override; + thunk::PPB_UMA_Singleton_API* AsPPB_UMA_Singleton_API() override; // PPB_UMA_Singleton_API implementation. - virtual void HistogramCustomTimes(PP_Instance instance, - struct PP_Var name, - int64_t sample, - int64_t min, - int64_t max, - uint32_t bucket_count) override; + void HistogramCustomTimes(PP_Instance instance, + struct PP_Var name, + int64_t sample, + int64_t min, + int64_t max, + uint32_t bucket_count) override; - virtual void HistogramCustomCounts(PP_Instance instance, - struct PP_Var name, - int32_t sample, - int32_t min, - int32_t max, - uint32_t bucket_count) override; + void HistogramCustomCounts(PP_Instance instance, + struct PP_Var name, + int32_t sample, + int32_t min, + int32_t max, + uint32_t bucket_count) override; - virtual void HistogramEnumeration(PP_Instance instance, - struct PP_Var name, - int32_t sample, - int32_t boundary_value) override; + void HistogramEnumeration(PP_Instance instance, + struct PP_Var name, + int32_t sample, + int32_t boundary_value) override; - virtual int32_t IsCrashReportingEnabled( + int32_t IsCrashReportingEnabled( PP_Instance instance, scoped_refptr<TrackedCallback> callback) override;
diff --git a/ppapi/proxy/url_loader_resource.h b/ppapi/proxy/url_loader_resource.h index 457dd4a..f96c1aba 100644 --- a/ppapi/proxy/url_loader_resource.h +++ b/ppapi/proxy/url_loader_resource.h
@@ -36,39 +36,38 @@ int pending_main_document_loader_id, const URLResponseInfoData& data); - virtual ~URLLoaderResource(); + ~URLLoaderResource() override; // Resource override. thunk::PPB_URLLoader_API* AsPPB_URLLoader_API() override; // PPB_URLLoader_API implementation. - virtual int32_t Open(PP_Resource request_id, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Open(const URLRequestInfoData& data, - int requestor_pid, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t FollowRedirect( - scoped_refptr<TrackedCallback> callback) override; - virtual PP_Bool GetUploadProgress(int64_t* bytes_sent, - int64_t* total_bytes_to_be_sent) override; - virtual PP_Bool GetDownloadProgress( + int32_t Open(PP_Resource request_id, + scoped_refptr<TrackedCallback> callback) override; + int32_t Open(const URLRequestInfoData& data, + int requestor_pid, + scoped_refptr<TrackedCallback> callback) override; + int32_t FollowRedirect(scoped_refptr<TrackedCallback> callback) override; + PP_Bool GetUploadProgress(int64_t* bytes_sent, + int64_t* total_bytes_to_be_sent) override; + PP_Bool GetDownloadProgress( int64_t* bytes_received, int64_t* total_bytes_to_be_received) override; - virtual PP_Resource GetResponseInfo() override; - virtual int32_t ReadResponseBody( + PP_Resource GetResponseInfo() override; + int32_t ReadResponseBody( void* buffer, int32_t bytes_to_read, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t FinishStreamingToFile( + int32_t FinishStreamingToFile( scoped_refptr<TrackedCallback> callback) override; - virtual void Close() override; - virtual void GrantUniversalAccess() override; - virtual void RegisterStatusCallback( + void Close() override; + void GrantUniversalAccess() override; + void RegisterStatusCallback( PP_URLLoaderTrusted_StatusCallback callback) override; // PluginResource implementation. - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; private: enum Mode {
diff --git a/ppapi/proxy/url_request_info_resource.h b/ppapi/proxy/url_request_info_resource.h index 8b07c7a3..318668f 100644 --- a/ppapi/proxy/url_request_info_resource.h +++ b/ppapi/proxy/url_request_info_resource.h
@@ -21,21 +21,20 @@ public: URLRequestInfoResource(Connection connection, PP_Instance instance, const URLRequestInfoData& data); - virtual ~URLRequestInfoResource(); + ~URLRequestInfoResource() override; // Resource overrides. - virtual thunk::PPB_URLRequestInfo_API* AsPPB_URLRequestInfo_API() override; + thunk::PPB_URLRequestInfo_API* AsPPB_URLRequestInfo_API() override; // PPB_URLRequestInfo_API implementation. - virtual PP_Bool SetProperty(PP_URLRequestProperty property, - PP_Var var) override; - virtual PP_Bool AppendDataToBody(const void* data, uint32_t len) override; - virtual PP_Bool AppendFileToBody( + PP_Bool SetProperty(PP_URLRequestProperty property, PP_Var var) override; + PP_Bool AppendDataToBody(const void* data, uint32_t len) override; + PP_Bool AppendFileToBody( PP_Resource file_ref, int64_t start_offset, int64_t number_of_bytes, PP_Time expected_last_modified_time) override; - virtual const URLRequestInfoData& GetData() const override; + const URLRequestInfoData& GetData() const override; bool SetUndefinedProperty(PP_URLRequestProperty property); bool SetBooleanProperty(PP_URLRequestProperty property, bool value);
diff --git a/ppapi/proxy/url_response_info_resource.h b/ppapi/proxy/url_response_info_resource.h index 1cf83366..e20417f 100644 --- a/ppapi/proxy/url_response_info_resource.h +++ b/ppapi/proxy/url_response_info_resource.h
@@ -28,14 +28,14 @@ PP_Instance instance, const URLResponseInfoData& data, PP_Resource file_ref_resource); - virtual ~URLResponseInfoResource(); + ~URLResponseInfoResource() override; // Resource override. - virtual PPB_URLResponseInfo_API* AsPPB_URLResponseInfo_API() override; + PPB_URLResponseInfo_API* AsPPB_URLResponseInfo_API() override; // PPB_URLResponseInfo_API implementation. - virtual PP_Var GetProperty(PP_URLResponseProperty property) override; - virtual PP_Resource GetBodyAsFileRef() override; + PP_Var GetProperty(PP_URLResponseProperty property) override; + PP_Resource GetBodyAsFileRef() override; const URLResponseInfoData& data() const { return data_; }
diff --git a/ppapi/proxy/video_capture_resource.h b/ppapi/proxy/video_capture_resource.h index d0ea0a7..add9713 100644 --- a/ppapi/proxy/video_capture_resource.h +++ b/ppapi/proxy/video_capture_resource.h
@@ -21,33 +21,33 @@ VideoCaptureResource(Connection connection, PP_Instance instance, PluginDispatcher* dispatcher); - virtual ~VideoCaptureResource(); + ~VideoCaptureResource() override; // PluginResource override. - virtual thunk::PPB_VideoCapture_API* AsPPB_VideoCapture_API() override { + thunk::PPB_VideoCapture_API* AsPPB_VideoCapture_API() override { return this; } // PPB_VideoCapture_API implementation. - virtual int32_t EnumerateDevices( + int32_t EnumerateDevices( const PP_ArrayOutput& output, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t MonitorDeviceChange( + int32_t MonitorDeviceChange( PP_MonitorDeviceChangeCallback callback, void* user_data) override; - virtual int32_t Open(const std::string& device_id, - const PP_VideoCaptureDeviceInfo_Dev& requested_info, - uint32_t buffer_count, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t StartCapture() override; - virtual int32_t ReuseBuffer(uint32_t buffer) override; - virtual int32_t StopCapture() override; - virtual void Close() override; - virtual int32_t EnumerateDevicesSync(const PP_ArrayOutput& devices) override; + int32_t Open(const std::string& device_id, + const PP_VideoCaptureDeviceInfo_Dev& requested_info, + uint32_t buffer_count, + scoped_refptr<TrackedCallback> callback) override; + int32_t StartCapture() override; + int32_t ReuseBuffer(uint32_t buffer) override; + int32_t StopCapture() override; + void Close() override; + int32_t EnumerateDevicesSync(const PP_ArrayOutput& devices) override; protected: // Resource override. - virtual void LastPluginRefWasDeleted() override; + void LastPluginRefWasDeleted() override; private: enum OpenState { @@ -57,8 +57,8 @@ }; // PluginResource overrides. - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; void OnPluginMsgOnDeviceInfo(const ResourceMessageReplyParams& params, const struct PP_VideoCaptureDeviceInfo_Dev& info,
diff --git a/ppapi/proxy/video_decoder_resource.h b/ppapi/proxy/video_decoder_resource.h index bcc89069..aaa1b95 100644 --- a/ppapi/proxy/video_decoder_resource.h +++ b/ppapi/proxy/video_decoder_resource.h
@@ -37,37 +37,37 @@ public thunk::PPB_VideoDecoder_API { public: VideoDecoderResource(Connection connection, PP_Instance instance); - virtual ~VideoDecoderResource(); + ~VideoDecoderResource() override; // Resource overrides. - virtual thunk::PPB_VideoDecoder_API* AsPPB_VideoDecoder_API() override; + thunk::PPB_VideoDecoder_API* AsPPB_VideoDecoder_API() override; // PPB_VideoDecoder_API implementation. - virtual int32_t Initialize0_1( + int32_t Initialize0_1( PP_Resource graphics_context, PP_VideoProfile profile, PP_Bool allow_software_fallback, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Initialize(PP_Resource graphics_context, - PP_VideoProfile profile, - PP_HardwareAcceleration acceleration, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Decode(uint32_t decode_id, - uint32_t size, - const void* buffer, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetPicture0_1( + int32_t Initialize(PP_Resource graphics_context, + PP_VideoProfile profile, + PP_HardwareAcceleration acceleration, + scoped_refptr<TrackedCallback> callback) override; + int32_t Decode(uint32_t decode_id, + uint32_t size, + const void* buffer, + scoped_refptr<TrackedCallback> callback) override; + int32_t GetPicture0_1( PP_VideoPicture_0_1* picture, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetPicture(PP_VideoPicture* picture, - scoped_refptr<TrackedCallback> callback) override; - virtual void RecyclePicture(const PP_VideoPicture* picture) override; - virtual int32_t Flush(scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Reset(scoped_refptr<TrackedCallback> callback) override; + int32_t GetPicture(PP_VideoPicture* picture, + scoped_refptr<TrackedCallback> callback) override; + void RecyclePicture(const PP_VideoPicture* picture) override; + int32_t Flush(scoped_refptr<TrackedCallback> callback) override; + int32_t Reset(scoped_refptr<TrackedCallback> callback) override; // PluginResource implementation. - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; // Called only by unit tests. This bypasses Graphics3D setup, which doesn't // work in ppapi::proxy::PluginProxyTest.
diff --git a/ppapi/proxy/video_destination_resource.h b/ppapi/proxy/video_destination_resource.h index bf22161..2e545a3 100644 --- a/ppapi/proxy/video_destination_resource.h +++ b/ppapi/proxy/video_destination_resource.h
@@ -27,18 +27,18 @@ public: VideoDestinationResource(Connection connection, PP_Instance instance); - virtual ~VideoDestinationResource(); + ~VideoDestinationResource() override; // Resource overrides. - virtual thunk::PPB_VideoDestination_Private_API* - AsPPB_VideoDestination_Private_API() override; + thunk::PPB_VideoDestination_Private_API* AsPPB_VideoDestination_Private_API() + override; // PPB_VideoDestination_Private_API implementation. - virtual int32_t Open( + int32_t Open( const PP_Var& stream_url, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t PutFrame(const PP_VideoFrame_Private& frame) override; - virtual void Close() override; + int32_t PutFrame(const PP_VideoFrame_Private& frame) override; + void Close() override; private: void OnPluginMsgOpenComplete(
diff --git a/ppapi/proxy/video_frame_resource.h b/ppapi/proxy/video_frame_resource.h index 13901a6..e796eed 100644 --- a/ppapi/proxy/video_frame_resource.h +++ b/ppapi/proxy/video_frame_resource.h
@@ -22,21 +22,21 @@ int32_t index, MediaStreamBuffer* buffer); - virtual ~VideoFrameResource(); + ~VideoFrameResource() override; // PluginResource overrides: - virtual thunk::PPB_VideoFrame_API* AsPPB_VideoFrame_API() override; + thunk::PPB_VideoFrame_API* AsPPB_VideoFrame_API() override; // PPB_VideoFrame_API overrides: - virtual PP_TimeDelta GetTimestamp() override; - virtual void SetTimestamp(PP_TimeDelta timestamp) override; - virtual PP_VideoFrame_Format GetFormat() override; - virtual PP_Bool GetSize(PP_Size* size) override; - virtual void* GetDataBuffer() override; - virtual uint32_t GetDataBufferSize() override; - virtual MediaStreamBuffer* GetBuffer() override; - virtual int32_t GetBufferIndex() override; - virtual void Invalidate() override; + PP_TimeDelta GetTimestamp() override; + void SetTimestamp(PP_TimeDelta timestamp) override; + PP_VideoFrame_Format GetFormat() override; + PP_Bool GetSize(PP_Size* size) override; + void* GetDataBuffer() override; + uint32_t GetDataBufferSize() override; + MediaStreamBuffer* GetBuffer() override; + int32_t GetBufferIndex() override; + void Invalidate() override; // Frame index int32_t index_;
diff --git a/ppapi/proxy/video_source_resource.h b/ppapi/proxy/video_source_resource.h index a2c587d..56cd7dd 100644 --- a/ppapi/proxy/video_source_resource.h +++ b/ppapi/proxy/video_source_resource.h
@@ -29,20 +29,19 @@ public: VideoSourceResource(Connection connection, PP_Instance instance); - virtual ~VideoSourceResource(); + ~VideoSourceResource() override; // Resource overrides. - virtual thunk::PPB_VideoSource_Private_API* - AsPPB_VideoSource_Private_API() override; + thunk::PPB_VideoSource_Private_API* AsPPB_VideoSource_Private_API() override; // PPB_VideoSource_Private_API implementation. - virtual int32_t Open( + int32_t Open( const PP_Var& stream_url, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetFrame( + int32_t GetFrame( PP_VideoFrame_Private* frame, scoped_refptr<TrackedCallback> callback) override; - virtual void Close() override; + void Close() override; private: void OnPluginMsgOpenComplete(
diff --git a/ppapi/proxy/websocket_resource.h b/ppapi/proxy/websocket_resource.h index 8106abd..51fb52d 100644 --- a/ppapi/proxy/websocket_resource.h +++ b/ppapi/proxy/websocket_resource.h
@@ -26,36 +26,36 @@ public NON_EXPORTED_BASE(thunk::PPB_WebSocket_API) { public: WebSocketResource(Connection connection, PP_Instance instance); - virtual ~WebSocketResource(); + ~WebSocketResource() override; // PluginResource implementation. - virtual thunk::PPB_WebSocket_API* AsPPB_WebSocket_API() override; + thunk::PPB_WebSocket_API* AsPPB_WebSocket_API() override; // PPB_WebSocket_API implementation. - virtual int32_t Connect(const PP_Var& url, - const PP_Var protocols[], - uint32_t protocol_count, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t Close(uint16_t code, - const PP_Var& reason, - scoped_refptr<TrackedCallback> callback) override; - virtual int32_t ReceiveMessage( + int32_t Connect(const PP_Var& url, + const PP_Var protocols[], + uint32_t protocol_count, + scoped_refptr<TrackedCallback> callback) override; + int32_t Close(uint16_t code, + const PP_Var& reason, + scoped_refptr<TrackedCallback> callback) override; + int32_t ReceiveMessage( PP_Var* message, scoped_refptr<TrackedCallback> callback) override; - virtual int32_t SendMessage(const PP_Var& message) override; - virtual uint64_t GetBufferedAmount() override; - virtual uint16_t GetCloseCode() override; - virtual PP_Var GetCloseReason() override; - virtual PP_Bool GetCloseWasClean() override; - virtual PP_Var GetExtensions() override; - virtual PP_Var GetProtocol() override; - virtual PP_WebSocketReadyState GetReadyState() override; - virtual PP_Var GetURL() override; + int32_t SendMessage(const PP_Var& message) override; + uint64_t GetBufferedAmount() override; + uint16_t GetCloseCode() override; + PP_Var GetCloseReason() override; + PP_Bool GetCloseWasClean() override; + PP_Var GetExtensions() override; + PP_Var GetProtocol() override; + PP_WebSocketReadyState GetReadyState() override; + PP_Var GetURL() override; private: // PluginResource override. - virtual void OnReplyReceived(const ResourceMessageReplyParams& params, - const IPC::Message& msg) override; + void OnReplyReceived(const ResourceMessageReplyParams& params, + const IPC::Message& msg) override; // IPC message handlers. void OnPluginMsgConnectReply(const ResourceMessageReplyParams& params,
diff --git a/ppapi/shared_impl/array_var.h b/ppapi/shared_impl/array_var.h index 84515d0..2e3ab028 100644 --- a/ppapi/shared_impl/array_var.h +++ b/ppapi/shared_impl/array_var.h
@@ -28,8 +28,8 @@ static ArrayVar* FromPPVar(const PP_Var& var); // Var overrides. - virtual ArrayVar* AsArrayVar() override; - virtual PP_VarType GetType() const override; + ArrayVar* AsArrayVar() override; + PP_VarType GetType() const override; // The returned PP_Var has had a ref added on behalf of the caller. PP_Var Get(uint32_t index) const; @@ -42,7 +42,7 @@ ElementVector& elements() { return elements_; } protected: - virtual ~ArrayVar(); + ~ArrayVar() override; private: ElementVector elements_;
diff --git a/ppapi/shared_impl/dictionary_var.h b/ppapi/shared_impl/dictionary_var.h index 628fdee..06f9502 100644 --- a/ppapi/shared_impl/dictionary_var.h +++ b/ppapi/shared_impl/dictionary_var.h
@@ -29,8 +29,8 @@ static DictionaryVar* FromPPVar(const PP_Var& var); // Var overrides. - virtual DictionaryVar* AsDictionaryVar() override; - virtual PP_VarType GetType() const override; + DictionaryVar* AsDictionaryVar() override; + PP_VarType GetType() const override; // The returned PP_Var has had a ref added on behalf of the caller. PP_Var Get(const PP_Var& key) const; @@ -48,7 +48,7 @@ const KeyValueMap& key_value_map() const { return key_value_map_; } protected: - virtual ~DictionaryVar(); + ~DictionaryVar() override; private: KeyValueMap key_value_map_;
diff --git a/ppapi/shared_impl/media_stream_buffer_manager_unittest.cc b/ppapi/shared_impl/media_stream_buffer_manager_unittest.cc index a7f0ec7..3db0117 100644 --- a/ppapi/shared_impl/media_stream_buffer_manager_unittest.cc +++ b/ppapi/shared_impl/media_stream_buffer_manager_unittest.cc
@@ -30,7 +30,7 @@ class MockDelegate : public MediaStreamBufferManager::Delegate { public: MockDelegate() : new_buffer_enqueue_counter_(0) {} - virtual void OnNewBufferEnqueued() override { + void OnNewBufferEnqueued() override { new_buffer_enqueue_counter_++; }
diff --git a/ppapi/shared_impl/ppapi_constants.h b/ppapi/shared_impl/ppapi_constants.h index dcc9b29..d5b71aa 100644 --- a/ppapi/shared_impl/ppapi_constants.h +++ b/ppapi/shared_impl/ppapi_constants.h
@@ -14,6 +14,14 @@ // used to kill inactive plugins by the embedder host. const unsigned kKeepaliveThrottleIntervalDefaultMilliseconds = 5000; +#if defined(OS_WIN) +const char kPowerSaverTestPluginName[] = "power_saver_test_plugin.dll"; +#elif defined(OS_MACOSX) +const char kPowerSaverTestPluginName[] = "power_saver_test_plugin.plugin"; +#elif defined(OS_POSIX) +const char kPowerSaverTestPluginName[] = "libpower_saver_test_plugin.so"; +#endif + } // namespace ppapi #endif // PPAPI_SHARED_IMPL_PPAPI_CONSTANTS_H_
diff --git a/ppapi/shared_impl/ppb_audio_config_shared.h b/ppapi/shared_impl/ppb_audio_config_shared.h index 59c6cbb..5e7d359 100644 --- a/ppapi/shared_impl/ppb_audio_config_shared.h +++ b/ppapi/shared_impl/ppb_audio_config_shared.h
@@ -24,7 +24,7 @@ : public Resource, public thunk::PPB_AudioConfig_API { public: - virtual ~PPB_AudioConfig_Shared(); + ~PPB_AudioConfig_Shared() override; static PP_Resource Create(ResourceObjectType type, PP_Instance instance, @@ -40,11 +40,11 @@ static PP_AudioSampleRate RecommendSampleRate(PP_Instance); // Resource overrides. - virtual thunk::PPB_AudioConfig_API* AsPPB_AudioConfig_API() override; + thunk::PPB_AudioConfig_API* AsPPB_AudioConfig_API() override; // PPB_AudioConfig_API implementation. - virtual PP_AudioSampleRate GetSampleRate() override; - virtual uint32_t GetSampleFrameCount() override; + PP_AudioSampleRate GetSampleRate() override; + uint32_t GetSampleFrameCount() override; private: // You must call Init before using this object.
diff --git a/ppapi/shared_impl/ppb_device_ref_shared.h b/ppapi/shared_impl/ppb_device_ref_shared.h index e9bccab..aac1206 100644 --- a/ppapi/shared_impl/ppb_device_ref_shared.h +++ b/ppapi/shared_impl/ppb_device_ref_shared.h
@@ -38,12 +38,12 @@ const DeviceRefData& data); // Resource overrides. - virtual PPB_DeviceRef_API* AsPPB_DeviceRef_API() override; + PPB_DeviceRef_API* AsPPB_DeviceRef_API() override; // PPB_DeviceRef_API implementation. - virtual const DeviceRefData& GetDeviceRefData() const override; - virtual PP_DeviceType_Dev GetType() override; - virtual PP_Var GetName() override; + const DeviceRefData& GetDeviceRefData() const override; + PP_DeviceType_Dev GetType() override; + PP_Var GetName() override; private: DeviceRefData data_;
diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.h b/ppapi/shared_impl/ppb_graphics_3d_shared.h index 8df6219..09bc0f53 100644 --- a/ppapi/shared_impl/ppb_graphics_3d_shared.h +++ b/ppapi/shared_impl/ppb_graphics_3d_shared.h
@@ -30,26 +30,26 @@ public thunk::PPB_Graphics3D_API { public: // Resource overrides. - virtual thunk::PPB_Graphics3D_API* AsPPB_Graphics3D_API() override; + thunk::PPB_Graphics3D_API* AsPPB_Graphics3D_API() override; // PPB_Graphics3D_API implementation. - virtual int32_t GetAttribs(int32_t attrib_list[]) override; - virtual int32_t SetAttribs(const int32_t attrib_list[]) override; - virtual int32_t GetError() override; - virtual int32_t ResizeBuffers(int32_t width, int32_t height) override; - virtual int32_t SwapBuffers(scoped_refptr<TrackedCallback> callback) override; - virtual int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) override; + int32_t GetAttribs(int32_t attrib_list[]) override; + int32_t SetAttribs(const int32_t attrib_list[]) override; + int32_t GetError() override; + int32_t ResizeBuffers(int32_t width, int32_t height) override; + int32_t SwapBuffers(scoped_refptr<TrackedCallback> callback) override; + int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) override; - virtual void* MapTexSubImage2DCHROMIUM(GLenum target, - GLint level, - GLint xoffset, - GLint yoffset, - GLsizei width, - GLsizei height, - GLenum format, - GLenum type, - GLenum access) override; - virtual void UnmapTexSubImage2DCHROMIUM(const void* mem) override; + void* MapTexSubImage2DCHROMIUM(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLenum access) override; + void UnmapTexSubImage2DCHROMIUM(const void* mem) override; gpu::gles2::GLES2Implementation* gles2_impl() { return gles2_impl_.get(); } @@ -59,7 +59,7 @@ protected: PPB_Graphics3D_Shared(PP_Instance instance); PPB_Graphics3D_Shared(const HostResource& host_resource); - virtual ~PPB_Graphics3D_Shared(); + ~PPB_Graphics3D_Shared() override; virtual gpu::CommandBuffer* GetCommandBuffer() = 0; virtual gpu::GpuControl* GetGpuControl() = 0;
diff --git a/ppapi/shared_impl/ppb_input_event_shared.h b/ppapi/shared_impl/ppb_input_event_shared.h index bd0d17559..92d31088 100644 --- a/ppapi/shared_impl/ppb_input_event_shared.h +++ b/ppapi/shared_impl/ppb_input_event_shared.h
@@ -72,35 +72,33 @@ const InputEventData& data); // Resource overrides. - virtual PPB_InputEvent_API* AsPPB_InputEvent_API() override; + PPB_InputEvent_API* AsPPB_InputEvent_API() override; // PPB_InputEvent_API implementation. - virtual const InputEventData& GetInputEventData() const override; - virtual PP_InputEvent_Type GetType() override; - virtual PP_TimeTicks GetTimeStamp() override; - virtual uint32_t GetModifiers() override; - virtual PP_InputEvent_MouseButton GetMouseButton() override; - virtual PP_Point GetMousePosition() override; - virtual int32_t GetMouseClickCount() override; - virtual PP_Point GetMouseMovement() override; - virtual PP_FloatPoint GetWheelDelta() override; - virtual PP_FloatPoint GetWheelTicks() override; - virtual PP_Bool GetWheelScrollByPage() override; - virtual uint32_t GetKeyCode() override; - virtual PP_Var GetCharacterText() override; - virtual PP_Var GetCode() override; - virtual uint32_t GetIMESegmentNumber() override; - virtual uint32_t GetIMESegmentOffset(uint32_t index) override; - virtual int32_t GetIMETargetSegment() override; - virtual void GetIMESelection(uint32_t* start, uint32_t* end) override; - virtual void AddTouchPoint(PP_TouchListType list, - const PP_TouchPoint& point) override; - virtual uint32_t GetTouchCount(PP_TouchListType list) override; - virtual PP_TouchPoint GetTouchByIndex(PP_TouchListType list, - uint32_t index) override; - virtual PP_TouchPoint GetTouchById(PP_TouchListType list, - uint32_t id) override; - virtual PP_Bool TraceInputLatency(PP_Bool has_damage) override; + const InputEventData& GetInputEventData() const override; + PP_InputEvent_Type GetType() override; + PP_TimeTicks GetTimeStamp() override; + uint32_t GetModifiers() override; + PP_InputEvent_MouseButton GetMouseButton() override; + PP_Point GetMousePosition() override; + int32_t GetMouseClickCount() override; + PP_Point GetMouseMovement() override; + PP_FloatPoint GetWheelDelta() override; + PP_FloatPoint GetWheelTicks() override; + PP_Bool GetWheelScrollByPage() override; + uint32_t GetKeyCode() override; + PP_Var GetCharacterText() override; + PP_Var GetCode() override; + uint32_t GetIMESegmentNumber() override; + uint32_t GetIMESegmentOffset(uint32_t index) override; + int32_t GetIMETargetSegment() override; + void GetIMESelection(uint32_t* start, uint32_t* end) override; + void AddTouchPoint(PP_TouchListType list, + const PP_TouchPoint& point) override; + uint32_t GetTouchCount(PP_TouchListType list) override; + PP_TouchPoint GetTouchByIndex(PP_TouchListType list, uint32_t index) override; + PP_TouchPoint GetTouchById(PP_TouchListType list, uint32_t id) override; + PP_Bool TraceInputLatency(PP_Bool has_damage) override; // Implementations for event creation. static PP_Resource CreateIMEInputEvent(ResourceObjectType type,
diff --git a/ppapi/shared_impl/ppb_instance_shared.h b/ppapi/shared_impl/ppb_instance_shared.h index 717adedd..bcd284e4 100644 --- a/ppapi/shared_impl/ppb_instance_shared.h +++ b/ppapi/shared_impl/ppb_instance_shared.h
@@ -15,16 +15,14 @@ class PPAPI_SHARED_EXPORT PPB_Instance_Shared : NON_EXPORTED_BASE(public thunk::PPB_Instance_API) { public: - virtual ~PPB_Instance_Shared(); + ~PPB_Instance_Shared() override; // Implementation of some shared PPB_Instance_FunctionAPI functions. - virtual void Log(PP_Instance instance, - PP_LogLevel log_level, - PP_Var value) override; - virtual void LogWithSource(PP_Instance instance, - PP_LogLevel log_level, - PP_Var source, - PP_Var value) override; + void Log(PP_Instance instance, PP_LogLevel log_level, PP_Var value) override; + void LogWithSource(PP_Instance instance, + PP_LogLevel log_level, + PP_Var source, + PP_Var value) override; // Error checks the given resquest to Request[Filtering]InputEvents. Returns // PP_OK if the given classes are all valid, PP_ERROR_NOTSUPPORTED if not.
diff --git a/ppapi/shared_impl/ppb_video_decoder_shared.h b/ppapi/shared_impl/ppb_video_decoder_shared.h index e08493e9..23c8608 100644 --- a/ppapi/shared_impl/ppb_video_decoder_shared.h +++ b/ppapi/shared_impl/ppb_video_decoder_shared.h
@@ -31,14 +31,13 @@ public: explicit PPB_VideoDecoder_Shared(PP_Instance instance); explicit PPB_VideoDecoder_Shared(const HostResource& host_resource); - virtual ~PPB_VideoDecoder_Shared(); + ~PPB_VideoDecoder_Shared() override; // Resource overrides. - virtual thunk::PPB_VideoDecoder_Dev_API* AsPPB_VideoDecoder_Dev_API() - override; + thunk::PPB_VideoDecoder_Dev_API* AsPPB_VideoDecoder_Dev_API() override; // PPB_VideoDecoder_Dev_API implementation. - virtual void Destroy() override; + void Destroy() override; protected: bool SetFlushCallback(scoped_refptr<TrackedCallback> callback);
diff --git a/ppapi/shared_impl/ppb_view_shared.h b/ppapi/shared_impl/ppb_view_shared.h index 32bfb35..a0e3794 100644 --- a/ppapi/shared_impl/ppb_view_shared.h +++ b/ppapi/shared_impl/ppb_view_shared.h
@@ -36,21 +36,21 @@ PPB_View_Shared(ResourceObjectType type, PP_Instance instance, const ViewData& data); - virtual ~PPB_View_Shared(); + ~PPB_View_Shared() override; // Resource overrides. - virtual thunk::PPB_View_API* AsPPB_View_API() override; + thunk::PPB_View_API* AsPPB_View_API() override; // PPB_View_API implementation. - virtual const ViewData& GetData() const override; - virtual PP_Bool GetRect(PP_Rect* viewport) const override; - virtual PP_Bool IsFullscreen() const override; - virtual PP_Bool IsVisible() const override; - virtual PP_Bool IsPageVisible() const override; - virtual PP_Bool GetClipRect(PP_Rect* clip) const override; - virtual float GetDeviceScale() const override; - virtual float GetCSSScale() const override; - virtual PP_Bool GetScrollOffset(PP_Point* scroll_offset) const override; + const ViewData& GetData() const override; + PP_Bool GetRect(PP_Rect* viewport) const override; + PP_Bool IsFullscreen() const override; + PP_Bool IsVisible() const override; + PP_Bool IsPageVisible() const override; + PP_Bool GetClipRect(PP_Rect* clip) const override; + float GetDeviceScale() const override; + float GetCSSScale() const override; + PP_Bool GetScrollOffset(PP_Point* scroll_offset) const override; private: ViewData data_;
diff --git a/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h b/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h index 727f552..1eaedbb 100644 --- a/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h +++ b/ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h
@@ -49,15 +49,14 @@ PPB_X509Certificate_Private_Shared(ResourceObjectType type, PP_Instance instance, const PPB_X509Certificate_Fields& fields); - virtual ~PPB_X509Certificate_Private_Shared(); + ~PPB_X509Certificate_Private_Shared() override; // Resource overrides. - virtual PPB_X509Certificate_Private_API* - AsPPB_X509Certificate_Private_API() override; + PPB_X509Certificate_Private_API* AsPPB_X509Certificate_Private_API() override; // PPB_X509Certificate_Private_API implementation. - virtual PP_Bool Initialize(const char* bytes, uint32_t length) override; - virtual PP_Var GetField(PP_X509Certificate_Private_Field field) override; + PP_Bool Initialize(const char* bytes, uint32_t length) override; + PP_Var GetField(PP_X509Certificate_Private_Field field) override; protected: virtual bool ParseDER(const std::vector<char>& der,
diff --git a/ppapi/shared_impl/resource_tracker_unittest.cc b/ppapi/shared_impl/resource_tracker_unittest.cc index 31c61b3..a8fac3b 100644 --- a/ppapi/shared_impl/resource_tracker_unittest.cc +++ b/ppapi/shared_impl/resource_tracker_unittest.cc
@@ -23,12 +23,12 @@ MyMockResource(PP_Instance instance) : Resource(OBJECT_IS_IMPL, instance) { mock_resource_alive_count++; } - virtual ~MyMockResource() { mock_resource_alive_count--; } + ~MyMockResource() override { mock_resource_alive_count--; } - virtual void LastPluginRefWasDeleted() override { + void LastPluginRefWasDeleted() override { last_plugin_ref_was_deleted_count++; } - virtual void InstanceWasDeleted() override { instance_was_deleted_count++; } + void InstanceWasDeleted() override { instance_was_deleted_count++; } }; } // namespace @@ -38,12 +38,12 @@ ResourceTrackerTest() {} // Test implementation. - virtual void SetUp() override { + void SetUp() override { ASSERT_EQ(0, mock_resource_alive_count); last_plugin_ref_was_deleted_count = 0; instance_was_deleted_count = 0; } - virtual void TearDown() override {} + void TearDown() override {} ResourceTracker& resource_tracker() { return *globals_.GetResourceTracker(); }
diff --git a/ppapi/shared_impl/resource_var.h b/ppapi/shared_impl/resource_var.h index 121859ae..0696d57e 100644 --- a/ppapi/shared_impl/resource_var.h +++ b/ppapi/shared_impl/resource_var.h
@@ -41,8 +41,8 @@ virtual bool IsPending() const = 0; // Var override. - virtual ResourceVar* AsResourceVar() override; - virtual PP_VarType GetType() const override; + ResourceVar* AsResourceVar() override; + PP_VarType GetType() const override; // Helper function that converts a PP_Var to a ResourceVar. This will // return NULL if the PP_Var is not of Resource type. @@ -51,7 +51,7 @@ protected: ResourceVar(); - virtual ~ResourceVar(); + ~ResourceVar() override; private: DISALLOW_COPY_AND_ASSIGN(ResourceVar);
diff --git a/ppapi/shared_impl/test_globals.h b/ppapi/shared_impl/test_globals.h index a01eeff..fba9a57 100644 --- a/ppapi/shared_impl/test_globals.h +++ b/ppapi/shared_impl/test_globals.h
@@ -17,35 +17,35 @@ class TestVarTracker : public VarTracker { public: TestVarTracker() : VarTracker(THREAD_SAFE) {} - virtual ~TestVarTracker() {} - virtual PP_Var MakeResourcePPVarFromMessage( + ~TestVarTracker() override {} + PP_Var MakeResourcePPVarFromMessage( PP_Instance instance, const IPC::Message& creation_message, int pending_renderer_id, int pending_browser_id) override { return PP_MakeNull(); } - virtual ResourceVar* MakeResourceVar(PP_Resource pp_resource) override { + ResourceVar* MakeResourceVar(PP_Resource pp_resource) override { return NULL; } - virtual ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) override { + ArrayBufferVar* CreateArrayBuffer(uint32 size_in_bytes) override { return NULL; } - virtual ArrayBufferVar* CreateShmArrayBuffer(uint32 size_in_bytes, - base::SharedMemoryHandle handle) - override { + ArrayBufferVar* CreateShmArrayBuffer( + uint32 size_in_bytes, + base::SharedMemoryHandle handle) override { return NULL; } - virtual void DidDeleteInstance(PP_Instance instance) override {} - virtual int TrackSharedMemoryHandle(PP_Instance instance, - base::SharedMemoryHandle handle, - uint32 size_in_bytes) override { + void DidDeleteInstance(PP_Instance instance) override {} + int TrackSharedMemoryHandle(PP_Instance instance, + base::SharedMemoryHandle handle, + uint32 size_in_bytes) override { return -1; } - virtual bool StopTrackingSharedMemoryHandle(int id, - PP_Instance instance, - base::SharedMemoryHandle* handle, - uint32* size_in_bytes) override { + bool StopTrackingSharedMemoryHandle(int id, + PP_Instance instance, + base::SharedMemoryHandle* handle, + uint32* size_in_bytes) override { return false; } }; @@ -56,33 +56,31 @@ public: TestGlobals(); explicit TestGlobals(PpapiGlobals::PerThreadForTest); - virtual ~TestGlobals(); + ~TestGlobals() override; // PpapiGlobals implementation. - virtual ResourceTracker* GetResourceTracker() override; - virtual VarTracker* GetVarTracker() override; - virtual CallbackTracker* GetCallbackTrackerForInstance(PP_Instance instance) - override; - virtual thunk::PPB_Instance_API* GetInstanceAPI(PP_Instance instance) - override; - virtual thunk::ResourceCreationAPI* GetResourceCreationAPI( + ResourceTracker* GetResourceTracker() override; + VarTracker* GetVarTracker() override; + CallbackTracker* GetCallbackTrackerForInstance(PP_Instance instance) override; + thunk::PPB_Instance_API* GetInstanceAPI(PP_Instance instance) override; + thunk::ResourceCreationAPI* GetResourceCreationAPI( PP_Instance instance) override; - virtual PP_Module GetModuleForInstance(PP_Instance instance) override; - virtual std::string GetCmdLine() override; - virtual void PreCacheFontForFlash(const void* logfontw) override; - virtual void LogWithSource(PP_Instance instance, - PP_LogLevel level, - const std::string& source, - const std::string& value) override; - virtual void BroadcastLogWithSource(PP_Module module, - PP_LogLevel level, - const std::string& source, - const std::string& value) override; - virtual MessageLoopShared* GetCurrentMessageLoop() override; - virtual base::TaskRunner* GetFileTaskRunner() override; + PP_Module GetModuleForInstance(PP_Instance instance) override; + std::string GetCmdLine() override; + void PreCacheFontForFlash(const void* logfontw) override; + void LogWithSource(PP_Instance instance, + PP_LogLevel level, + const std::string& source, + const std::string& value) override; + void BroadcastLogWithSource(PP_Module module, + PP_LogLevel level, + const std::string& source, + const std::string& value) override; + MessageLoopShared* GetCurrentMessageLoop() override; + base::TaskRunner* GetFileTaskRunner() override; // PpapiGlobals overrides: - virtual bool IsHostGlobals() const override; + bool IsHostGlobals() const override; private: ResourceTracker resource_tracker_;
diff --git a/ppapi/shared_impl/thread_aware_callback_unittest.cc b/ppapi/shared_impl/thread_aware_callback_unittest.cc index 9e9189b..7081daa 100644 --- a/ppapi/shared_impl/thread_aware_callback_unittest.cc +++ b/ppapi/shared_impl/thread_aware_callback_unittest.cc
@@ -53,19 +53,19 @@ : public proxy::PluginProxyMultiThreadTest { public: ThreadAwareCallbackMultiThreadTest() : main_thread_callback_called_(false) {} - virtual ~ThreadAwareCallbackMultiThreadTest() { + ~ThreadAwareCallbackMultiThreadTest() override { CHECK(main_thread_callback_called_); } // proxy::PluginProxyMultiThreadTest implementation. - virtual void SetUpTestOnMainThread() override { + void SetUpTestOnMainThread() override { ProxyAutoLock auto_lock; main_thread_callback_.reset( ThreadAwareCallback<CallbackFunc>::Create(&MainThreadCallbackBody)); } - virtual void SetUpTestOnSecondaryThread() override { + void SetUpTestOnSecondaryThread() override { { ProxyAutoLock auto_lock; main_thread_callback_->RunOnTargetThread(this); @@ -100,17 +100,17 @@ class ThreadAwareCallbackAbortTest : public proxy::PluginProxyMultiThreadTest { public: ThreadAwareCallbackAbortTest() {} - virtual ~ThreadAwareCallbackAbortTest() {} + ~ThreadAwareCallbackAbortTest() override {} // proxy::PluginProxyMultiThreadTest implementation. - virtual void SetUpTestOnMainThread() override { + void SetUpTestOnMainThread() override { ProxyAutoLock auto_lock; main_thread_callback_.reset( ThreadAwareCallback<CallbackFunc>::Create(&MainThreadCallbackBody)); } - virtual void SetUpTestOnSecondaryThread() override { + void SetUpTestOnSecondaryThread() override { { ProxyAutoLock auto_lock; main_thread_message_loop_proxy_->PostTask(
diff --git a/ppapi/shared_impl/var.h b/ppapi/shared_impl/var.h index 67b0e3a..5e46864 100644 --- a/ppapi/shared_impl/var.h +++ b/ppapi/shared_impl/var.h
@@ -101,7 +101,7 @@ public: explicit StringVar(const std::string& str); StringVar(const char* str, uint32 len); - virtual ~StringVar(); + ~StringVar() override; const std::string& value() const { return value_; } // Return a pointer to the internal string. This allows other objects to @@ -112,8 +112,8 @@ const std::string* ptr() const { return &value_; } // Var override. - virtual StringVar* AsStringVar() override; - virtual PP_VarType GetType() const override; + StringVar* AsStringVar() override; + PP_VarType GetType() const override; // Helper function to create a PP_Var of type string that contains a copy of // the given string. The input data must be valid UTF-8 encoded text, if it @@ -158,7 +158,7 @@ class PPAPI_SHARED_EXPORT ArrayBufferVar : public Var { public: ArrayBufferVar(); - virtual ~ArrayBufferVar(); + ~ArrayBufferVar() override; virtual void* Map() = 0; virtual void Unmap() = 0; @@ -176,8 +176,8 @@ base::SharedMemoryHandle* plugin_shm_handle) = 0; // Var override. - virtual ArrayBufferVar* AsArrayBufferVar() override; - virtual PP_VarType GetType() const override; + ArrayBufferVar* AsArrayBufferVar() override; + PP_VarType GetType() const override; // Helper function that converts a PP_Var to an ArrayBufferVar. This will // return NULL if the PP_Var is not of ArrayBuffer type.
diff --git a/ppapi/shared_impl/var_tracker_unittest.cc b/ppapi/shared_impl/var_tracker_unittest.cc index fb8fda3..9dd03b3 100644 --- a/ppapi/shared_impl/var_tracker_unittest.cc +++ b/ppapi/shared_impl/var_tracker_unittest.cc
@@ -21,15 +21,15 @@ MockStringVar(const std::string& str) : StringVar(str) { mock_var_alive_count++; } - virtual ~MockStringVar() { mock_var_alive_count--; } + ~MockStringVar() override { mock_var_alive_count--; } bool HasValidVarID() { return GetExistingVarID() != 0; } }; class MockObjectVar : public Var { public: MockObjectVar() : Var() { mock_var_alive_count++; } - virtual ~MockObjectVar() { mock_var_alive_count--; } - virtual PP_VarType GetType() const override { return PP_VARTYPE_OBJECT; } + ~MockObjectVar() override { mock_var_alive_count--; } + PP_VarType GetType() const override { return PP_VARTYPE_OBJECT; } bool HasValidVarID() { return GetExistingVarID() != 0; } }; @@ -40,10 +40,10 @@ VarTrackerTest() {} // Test implementation. - virtual void SetUp() override { + void SetUp() override { ASSERT_EQ(0, mock_var_alive_count); } - virtual void TearDown() override {} + void TearDown() override {} VarTracker& var_tracker() { return *globals_.GetVarTracker(); }
diff --git a/ppapi/tests/mojo/DEPS b/ppapi/tests/mojo/DEPS deleted file mode 100644 index 5f8633a..0000000 --- a/ppapi/tests/mojo/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - "+third_party/mojo/src/mojo/public", -]
diff --git a/ppapi/tests/mojo/README b/ppapi/tests/mojo/README deleted file mode 100644 index d26906e7..0000000 --- a/ppapi/tests/mojo/README +++ /dev/null
@@ -1,4 +0,0 @@ -Pepper Mojo tests are split apart from the rest of the Pepper tests because: - - They require additional Mojo dependencies to work, and - - Mojo libraries require building with C++11 support, which is only supported - by pnacl-clang.
diff --git a/ppapi/tests/mojo/test_mojo.cc b/ppapi/tests/mojo/test_mojo.cc deleted file mode 100644 index 3d1af46..0000000 --- a/ppapi/tests/mojo/test_mojo.cc +++ /dev/null
@@ -1,25 +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 "ppapi/tests/mojo/test_mojo.h" - -#include "third_party/mojo/src/mojo/public/cpp/system/message_pipe.h" - -REGISTER_TEST_CASE(Mojo); - -TestMojo::TestMojo(TestingInstance* instance) : TestCase(instance) { } -bool TestMojo::Init() { - return true; -} - -void TestMojo::RunTests(const std::string& filter) { - RUN_TEST(CreateMessagePipe, filter); -} - -std::string TestMojo::TestCreateMessagePipe() { - MojoHandle h0; - MojoHandle h1; - ASSERT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(NULL, &h0, &h1)); - PASS(); -}
diff --git a/ppapi/tests/mojo/test_mojo.h b/ppapi/tests/mojo/test_mojo.h deleted file mode 100644 index cbf6a82..0000000 --- a/ppapi/tests/mojo/test_mojo.h +++ /dev/null
@@ -1,21 +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 PPAPI_TESTS_MOJO_TEST_MOJO_H_ -#define PPAPI_TESTS_MOJO_TEST_MOJO_H_ - -#include "ppapi/tests/test_case.h" -#include "ppapi/tests/test_utils.h" - -class TestMojo : public TestCase { - public: - explicit TestMojo(TestingInstance* instance); - // TestCase implementation. - virtual bool Init(); - virtual void RunTests(const std::string& test_filter); - private: - std::string TestCreateMessagePipe(); -}; - -#endif // PPAPI_TESTS_MOJO_TEST_MOJO_H_
diff --git a/ppapi/tests/power_saver_test_plugin.cc b/ppapi/tests/power_saver_test_plugin.cc new file mode 100644 index 0000000..f14c5fe --- /dev/null +++ b/ppapi/tests/power_saver_test_plugin.cc
@@ -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. + +#include <algorithm> + +#include "ppapi/cpp/instance.h" +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/var.h" +#include "ppapi/cpp/var_dictionary.h" +#include "ppapi/tests/test_utils.h" + +// Windows defines 'PostMessage', so we have to undef it. +#ifdef PostMessage +#undef PostMessage +#endif + +// This is a simple C++ Pepper plugin that enables Plugin Power Saver tests. +class PowerSaverTestInstance : public pp::Instance { + public: + explicit PowerSaverTestInstance(PP_Instance instance) + : pp::Instance(instance), received_first_did_change_view_(false) {} + ~PowerSaverTestInstance() override {} + + // For browser tests, responds to: + // - When postMessage("isPeripheral") is called on the plugin DOM element. + // - When the plugin throttler posts a message notifying us that our + // peripheral status has changed. + void HandleMessage(const pp::Var& message_data) override { + if (message_data.is_string()) { + if (message_data.AsString() == "getPeripheralStatus") + BroadcastIsPeripheralStatus("getPeripheralStatusResponse"); + else if (message_data.AsString() == "peripheralStatusChange") + BroadcastIsPeripheralStatus("peripheralStatusChange"); + } + } + + // Broadcast our peripheral status after the initial view data. This is for + // tests that await initial plugin creation. + void DidChangeView(const pp::View& view) override { + if (!received_first_did_change_view_) { + BroadcastIsPeripheralStatus("initial"); + received_first_did_change_view_ = true; + } + } + + private: + void BroadcastIsPeripheralStatus(const std::string& source) { + pp::VarDictionary message; + message.Set( + "isPeripheral", + pp::Var(PP_ToBool(GetTestingInterface()->IsPeripheral(pp_instance())))); + message.Set("source", pp::Var(source)); + PostMessage(message); + } + + bool received_first_did_change_view_; +}; + +class PowerSaverTestModule : public pp::Module { + public: + PowerSaverTestModule() : pp::Module() {} + virtual ~PowerSaverTestModule() {} + + virtual pp::Instance* CreateInstance(PP_Instance instance) { + return new PowerSaverTestInstance(instance); + } +}; + +namespace pp { + +Module* CreateModule() { + return new PowerSaverTestModule(); +} + +} // namespace pp
diff --git a/ppapi/tests/test_flash_fullscreen_for_browser_ui.h b/ppapi/tests/test_flash_fullscreen_for_browser_ui.h index 5c1a263..0ae3741 100644 --- a/ppapi/tests/test_flash_fullscreen_for_browser_ui.h +++ b/ppapi/tests/test_flash_fullscreen_for_browser_ui.h
@@ -29,13 +29,13 @@ class TestFlashFullscreenForBrowserUI : public TestCase { public: explicit TestFlashFullscreenForBrowserUI(TestingInstance* instance); - virtual ~TestFlashFullscreenForBrowserUI(); + ~TestFlashFullscreenForBrowserUI() override; // TestCase implementation. - virtual bool Init() override; - virtual void RunTests(const std::string& filter) override; - virtual void DidChangeView(const pp::View& view) override; - virtual bool HandleInputEvent(const pp::InputEvent& event) override; + bool Init() override; + void RunTests(const std::string& filter) override; + void DidChangeView(const pp::View& view) override; + bool HandleInputEvent(const pp::InputEvent& event) override; private: std::string TestEnterFullscreen();
diff --git a/printing/backend/print_backend_win.cc b/printing/backend/print_backend_win.cc index a95c98be..fa697b4 100644 --- a/printing/backend/print_backend_win.cc +++ b/printing/backend/print_backend_win.cc
@@ -157,20 +157,20 @@ PrintBackendWin() {} // PrintBackend implementation. - virtual bool EnumeratePrinters(PrinterList* printer_list) override; - virtual std::string GetDefaultPrinterName() override; - virtual bool GetPrinterSemanticCapsAndDefaults( + bool EnumeratePrinters(PrinterList* printer_list) override; + std::string GetDefaultPrinterName() override; + bool GetPrinterSemanticCapsAndDefaults( const std::string& printer_name, PrinterSemanticCapsAndDefaults* printer_info) override; - virtual bool GetPrinterCapsAndDefaults( + bool GetPrinterCapsAndDefaults( const std::string& printer_name, PrinterCapsAndDefaults* printer_info) override; - virtual std::string GetPrinterDriverInfo( + std::string GetPrinterDriverInfo( const std::string& printer_name) override; - virtual bool IsValidPrinter(const std::string& printer_name) override; + bool IsValidPrinter(const std::string& printer_name) override; protected: - virtual ~PrintBackendWin() {} + ~PrintBackendWin() override {} }; bool PrintBackendWin::EnumeratePrinters(PrinterList* printer_list) {
diff --git a/printing/emf_win.h b/printing/emf_win.h index 1da9364..e301988 100644 --- a/printing/emf_win.h +++ b/printing/emf_win.h
@@ -41,7 +41,7 @@ // Generates a virtual HDC that will record every GDI commands and compile // it in a EMF data stream. Emf(); - virtual ~Emf(); + ~Emf() override; // Closes metafile. void Close(); @@ -54,34 +54,34 @@ bool InitFromFile(const base::FilePath& metafile_path); // Metafile methods. - virtual bool Init() override; - virtual bool InitFromData(const void* src_buffer, - uint32 src_buffer_size) override; + bool Init() override; + bool InitFromData(const void* src_buffer, + uint32 src_buffer_size) override; // Inserts a custom GDICOMMENT records indicating StartPage/EndPage calls // (since StartPage and EndPage do not work in a metafile DC). Only valid // when hdc_ is non-NULL. |page_size|, |content_area|, and |scale_factor| are // ignored. - virtual bool StartPage(const gfx::Size& page_size, - const gfx::Rect& content_area, - const float& scale_factor) override; - virtual bool FinishPage() override; - virtual bool FinishDocument() override; + bool StartPage(const gfx::Size& page_size, + const gfx::Rect& content_area, + const float& scale_factor) override; + bool FinishPage() override; + bool FinishDocument() override; - virtual uint32 GetDataSize() const override; - virtual bool GetData(void* buffer, uint32 size) const override; + uint32 GetDataSize() const override; + bool GetData(void* buffer, uint32 size) const override; // Should be passed to Playback to keep the exact same size. - virtual gfx::Rect GetPageBounds(unsigned int page_number) const override; + gfx::Rect GetPageBounds(unsigned int page_number) const override; - virtual unsigned int GetPageCount() const override { return 1; } + unsigned int GetPageCount() const override { return 1; } - virtual HDC context() const override { + HDC context() const override { return hdc_; } - virtual bool Playback(HDC hdc, const RECT* rect) const override; - virtual bool SafePlayback(HDC hdc) const override; + bool Playback(HDC hdc, const RECT* rect) const override; + bool SafePlayback(HDC hdc) const override; HENHMETAFILE emf() const { return emf_; }
diff --git a/printing/emf_win_unittest.cc b/printing/emf_win_unittest.cc index 247da12..0f20586 100644 --- a/printing/emf_win_unittest.cc +++ b/printing/emf_win_unittest.cc
@@ -41,8 +41,8 @@ } // PrintingContext::Delegate methods. - virtual gfx::NativeView GetParentView() override { return NULL; } - virtual std::string GetAppLocale() override { return std::string(); } + gfx::NativeView GetParentView() override { return NULL; } + std::string GetAppLocale() override { return std::string(); } }; const uint32 EMF_HEADER_SIZE = 128;
diff --git a/printing/pdf_metafile_skia.h b/printing/pdf_metafile_skia.h index edd12db..cab518a 100644 --- a/printing/pdf_metafile_skia.h +++ b/printing/pdf_metafile_skia.h
@@ -53,9 +53,9 @@ gfx::NativeDrawingContext context() const override; #if defined(OS_WIN) - virtual bool Playback(gfx::NativeDrawingContext hdc, - const RECT* rect) const override; - virtual bool SafePlayback(gfx::NativeDrawingContext hdc) const override; + bool Playback(gfx::NativeDrawingContext hdc, + const RECT* rect) const override; + bool SafePlayback(gfx::NativeDrawingContext hdc) const override; #elif defined(OS_MACOSX) bool RenderPage(unsigned int page_number, gfx::NativeDrawingContext context,
diff --git a/printing/printing_context_system_dialog_win.h b/printing/printing_context_system_dialog_win.h index 5e11aa5d..bafc478c 100644 --- a/printing/printing_context_system_dialog_win.h +++ b/printing/printing_context_system_dialog_win.h
@@ -19,10 +19,10 @@ : public PrintingContextWin { public: explicit PrintingContextSytemDialogWin(Delegate* delegate); - virtual ~PrintingContextSytemDialogWin(); + ~PrintingContextSytemDialogWin() override; // PrintingContext implementation. - virtual void AskUserForSettings( + void AskUserForSettings( int max_pages, bool has_selection, bool is_scripted,
diff --git a/printing/printing_context_win.h b/printing/printing_context_win.h index 7ed8b27..9dba3ca 100644 --- a/printing/printing_context_win.h +++ b/printing/printing_context_win.h
@@ -18,26 +18,26 @@ class PRINTING_EXPORT PrintingContextWin : public PrintingContext { public: explicit PrintingContextWin(Delegate* delegate); - virtual ~PrintingContextWin(); + ~PrintingContextWin() override; // PrintingContext implementation. - virtual void AskUserForSettings( + void AskUserForSettings( int max_pages, bool has_selection, bool is_scripted, const PrintSettingsCallback& callback) override; - virtual Result UseDefaultSettings() override; - virtual gfx::Size GetPdfPaperSizeDeviceUnits() override; - virtual Result UpdatePrinterSettings(bool external_preview, - bool show_system_dialog) override; - virtual Result InitWithSettings(const PrintSettings& settings) override; - virtual Result NewDocument(const base::string16& document_name) override; - virtual Result NewPage() override; - virtual Result PageDone() override; - virtual Result DocumentDone() override; - virtual void Cancel() override; - virtual void ReleaseContext() override; - virtual gfx::NativeDrawingContext context() const override; + Result UseDefaultSettings() override; + gfx::Size GetPdfPaperSizeDeviceUnits() override; + Result UpdatePrinterSettings(bool external_preview, + bool show_system_dialog) override; + Result InitWithSettings(const PrintSettings& settings) override; + Result NewDocument(const base::string16& document_name) override; + Result NewPage() override; + Result PageDone() override; + Result DocumentDone() override; + void Cancel() override; + void ReleaseContext() override; + gfx::NativeDrawingContext context() const override; protected: static HWND GetRootWindow(gfx::NativeView view);
diff --git a/printing/printing_context_win_unittest.cc b/printing/printing_context_win_unittest.cc index a758ca61..a9f1dc5c 100644 --- a/printing/printing_context_win_unittest.cc +++ b/printing/printing_context_win_unittest.cc
@@ -24,8 +24,8 @@ } // PrintingContext::Delegate methods. - virtual gfx::NativeView GetParentView() override { return NULL; } - virtual std::string GetAppLocale() override { return std::string(); } + gfx::NativeView GetParentView() override { return NULL; } + std::string GetAppLocale() override { return std::string(); } protected: PrintingContext::Result result() const { return result_; }
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn index 02adc68d..fb75dba 100644 --- a/remoting/BUILD.gn +++ b/remoting/BUILD.gn
@@ -24,12 +24,8 @@ #"//app_remoting_webapp.gyp:ar_sample_app", ] - if ((is_linux && !is_chromeos) || is_mac) { - deps += [ - # TODO(gyp) Enable this for Windows once the webapp can be built without - # exceeding the 8k cmd line limit on Windows. - "//remoting/webapp", - ] + if ((is_linux && !is_chromeos) || is_mac || is_win) { + deps += [ "//remoting/webapp" ] } if (is_win) {
diff --git a/remoting/app_remoting_webapp_build.gypi b/remoting/app_remoting_webapp_build.gypi index aae7f99d..9f7572cb 100644 --- a/remoting/app_remoting_webapp_build.gypi +++ b/remoting/app_remoting_webapp_build.gypi
@@ -37,8 +37,10 @@ '>(ar_app_path)/icon16.png', '>(ar_app_path)/icon48.png', '>(ar_app_path)/icon128.png', + '>(ar_app_path)/loading_splash.png', ], 'ar_generated_html_files': [ + '<(SHARED_INTERMEDIATE_DIR)/>(_target_name)/loading_window.html', '<(SHARED_INTERMEDIATE_DIR)/>(_target_name)/main.html', '<(SHARED_INTERMEDIATE_DIR)/>(_target_name)/message_window.html', '<(SHARED_INTERMEDIATE_DIR)/>(_target_name)/wcs_sandbox.html', @@ -177,6 +179,24 @@ ], }, { + 'action_name': 'Build ">(ar_app_name)" loading_window.html', + 'inputs': [ + '<(DEPTH)/remoting/webapp/build-html.py', + '<(ar_loading_window_template)', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/>(_target_name)/loading_window.html', + ], + 'action': [ + 'python', '<(DEPTH)/remoting/webapp/build-html.py', + '<(SHARED_INTERMEDIATE_DIR)/>(_target_name)/loading_window.html', + '<(ar_loading_window_template)', + # The loading window is just a reskin of the message window--all + # JS code is shared. + '--js', '<@(remoting_webapp_message_window_html_all_js_files)', + ], + }, + { 'action_name': 'Build ">(ar_app_name)" message_window.html', 'inputs': [ '<(DEPTH)/remoting/webapp/build-html.py',
diff --git a/remoting/app_remoting_webapp_files.gypi b/remoting/app_remoting_webapp_files.gypi index 203ffdd5..003b2e1 100644 --- a/remoting/app_remoting_webapp_files.gypi +++ b/remoting/app_remoting_webapp_files.gypi
@@ -8,6 +8,7 @@ 'webapp/app_remoting/html/ar_dialog.css', 'webapp/app_remoting/html/ar_main.css', 'webapp/app_remoting/html/feedback_consent.css', + 'webapp/app_remoting/html/loading_window.css', 'webapp/app_remoting/html/context_menu.css', 'resources/drag.webp', '<@(remoting_webapp_resource_files)', @@ -35,6 +36,11 @@ 'webapp/crd/js/xhr.js', ], + # Variables for loading_window.html. Note that the JS files are the same as + # for message_window.html, and are not duplicated here. + 'ar_loading_window_template': + '<(DEPTH)/remoting/webapp/app_remoting/html/template_loading_window.html', + # Variables for main.html. # These template files are used to construct the webapp html files. 'ar_main_template': @@ -95,6 +101,7 @@ '<(ar_main_template)', '<@(ar_main_template_files)', '<(ar_feedback_consent_template)', + '<(ar_loading_window_template)', '<(remoting_webapp_template_message_window)', '<(remoting_webapp_template_wcs_sandbox)', '<@(ar_all_js_files)',
diff --git a/remoting/base/breakpad_win_unittest.cc b/remoting/base/breakpad_win_unittest.cc index da554b2..78ab02a 100644 --- a/remoting/base/breakpad_win_unittest.cc +++ b/remoting/base/breakpad_win_unittest.cc
@@ -69,9 +69,9 @@ class BreakpadWinDeathTest : public testing::Test { public: BreakpadWinDeathTest(); - virtual ~BreakpadWinDeathTest(); + ~BreakpadWinDeathTest() override; - virtual void SetUp() override; + void SetUp() override; protected: scoped_ptr<google_breakpad::CrashGenerationServer> crash_server_;
diff --git a/remoting/base/url_request_context_getter.cc b/remoting/base/url_request_context_getter.cc index f61aa9b..4c9c272 100644 --- a/remoting/base/url_request_context_getter.cc +++ b/remoting/base/url_request_context_getter.cc
@@ -15,7 +15,8 @@ URLRequestContextGetter::URLRequestContextGetter( scoped_refptr<base::SingleThreadTaskRunner> network_task_runner, scoped_refptr<base::SingleThreadTaskRunner> file_task_runner) - : network_task_runner_(network_task_runner) { + : network_task_runner_(network_task_runner), + file_task_runner_(file_task_runner) { proxy_config_service_.reset(net::ProxyService::CreateSystemProxyConfigService( network_task_runner_, file_task_runner)); } @@ -23,6 +24,7 @@ net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() { if (!url_request_context_.get()) { net::URLRequestContextBuilder builder; + builder.SetFileTaskRunner(file_task_runner_); builder.set_net_log(new VlogNetLog()); builder.DisableHttpCache(); builder.set_proxy_config_service(proxy_config_service_.release());
diff --git a/remoting/base/url_request_context_getter.h b/remoting/base/url_request_context_getter.h index bba530ff..e37b3a8 100644 --- a/remoting/base/url_request_context_getter.h +++ b/remoting/base/url_request_context_getter.h
@@ -35,6 +35,7 @@ private: scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; + scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_; scoped_ptr<net::ProxyConfigService> proxy_config_service_; scoped_ptr<net::URLRequestContext> url_request_context_;
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc index 33bd2466..fd19dea 100644 --- a/remoting/client/jni/chromoting_jni_instance.cc +++ b/remoting/client/jni/chromoting_jni_instance.cc
@@ -434,7 +434,8 @@ scoped_ptr<protocol::TransportFactory> transport_factory( new protocol::LibjingleTransportFactory( - signaling_.get(), port_allocator.Pass(), network_settings)); + signaling_.get(), port_allocator.Pass(), network_settings, + protocol::TransportRole::CLIENT)); client_->Start(signaling_.get(), authenticator_.Pass(), transport_factory.Pass(), host_jid_, capabilities_);
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index 262bbbd..3faab96 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc
@@ -14,6 +14,7 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/callback_helpers.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/lazy_instance.h" @@ -712,10 +713,10 @@ // Create TransportFactory. scoped_ptr<protocol::TransportFactory> transport_factory( new protocol::LibjingleTransportFactory( - signal_strategy_.get(), - PepperPortAllocator::Create(this).Pass(), + signal_strategy_.get(), PepperPortAllocator::Create(this).Pass(), protocol::NetworkSettings( - protocol::NetworkSettings::NAT_TRAVERSAL_FULL))); + protocol::NetworkSettings::NAT_TRAVERSAL_FULL), + protocol::TransportRole::CLIENT)); // Create Authenticator. scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher> @@ -905,8 +906,7 @@ return; } if (!secret_fetched_callback_.is_null()) { - secret_fetched_callback_.Run(pin); - secret_fetched_callback_.Reset(); + base::ResetAndReturn(&secret_fetched_callback_).Run(pin); } else { LOG(WARNING) << "Ignored OnPinFetched received without a pending fetch."; }
diff --git a/remoting/client/plugin/pepper_module.cc b/remoting/client/plugin/pepper_module.cc index 557a70d..7082967 100644 --- a/remoting/client/plugin/pepper_module.cc +++ b/remoting/client/plugin/pepper_module.cc
@@ -12,7 +12,7 @@ class ChromotingModule : public pp::Module { protected: - virtual pp::Instance* CreateInstance(PP_Instance instance) override { + pp::Instance* CreateInstance(PP_Instance instance) override { pp::Instance* result = new ChromotingInstance(instance); return result; }
diff --git a/remoting/client/plugin/pepper_mouse_locker.cc b/remoting/client/plugin/pepper_mouse_locker.cc index 8b0338a8..b8cc19f7 100644 --- a/remoting/client/plugin/pepper_mouse_locker.cc +++ b/remoting/client/plugin/pepper_mouse_locker.cc
@@ -58,6 +58,7 @@ // See if the operation succeeded. if (error == PP_OK) { mouse_lock_state_ = MouseLockOn; + enable_mouse_deltas_.Run(true); } else { OnMouseLockOff(); } @@ -70,6 +71,7 @@ void PepperMouseLocker::OnMouseLockOff() { mouse_lock_state_ = MouseLockOff; cursor_stub_->SetCursorShape(*cursor_shape_); + enable_mouse_deltas_.Run(false); } void PepperMouseLocker::RequestMouseLock() {
diff --git a/remoting/client/token_fetcher_proxy.cc b/remoting/client/token_fetcher_proxy.cc index c1082b2..1079290 100644 --- a/remoting/client/token_fetcher_proxy.cc +++ b/remoting/client/token_fetcher_proxy.cc
@@ -4,6 +4,8 @@ #include "remoting/client/token_fetcher_proxy.h" +#include "base/callback_helpers.h" + namespace remoting { TokenFetcherProxy::TokenFetcherProxy( @@ -29,8 +31,7 @@ void TokenFetcherProxy::OnTokenFetched( const std::string& token, const std::string& shared_secret) { if (!token_fetched_callback_.is_null()) { - token_fetched_callback_.Run(token, shared_secret); - token_fetched_callback_.Reset(); + base::ResetAndReturn(&token_fetched_callback_).Run(token, shared_secret); } }
diff --git a/remoting/codec/video_encoder_vpx.cc b/remoting/codec/video_encoder_vpx.cc index e0d768b..724fbecd 100644 --- a/remoting/codec/video_encoder_vpx.cc +++ b/remoting/codec/video_encoder_vpx.cc
@@ -45,10 +45,6 @@ config->g_timebase.num = 1; config->g_timebase.den = 1000; - // Adjust default target bit-rate to account for actual desktop size. - config->rc_target_bitrate = size.width() * size.height() * - config->rc_target_bitrate / config->g_w / config->g_h; - config->g_w = size.width(); config->g_h = size.height(); config->g_pass = VPX_RC_ONE_PASS; @@ -71,6 +67,10 @@ void SetVp8CodecParameters(vpx_codec_enc_cfg_t* config, const webrtc::DesktopSize& size) { + // Adjust default target bit-rate to account for actual desktop size. + config->rc_target_bitrate = size.width() * size.height() * + config->rc_target_bitrate / config->g_w / config->g_h; + SetCommonCodecParameters(config, size); // Value of 2 means using the real time profile. This is basically a @@ -97,10 +97,14 @@ // Disable quantization entirely, putting the encoder in "lossless" mode. config->rc_min_quantizer = 0; config->rc_max_quantizer = 0; + config->rc_end_usage = VPX_VBR; } else { - // Lossy encode using the same settings as for VP8. - config->rc_min_quantizer = 20; + config->rc_min_quantizer = 4; config->rc_max_quantizer = 30; + config->rc_end_usage = VPX_CBR; + // In the absence of a good bandwidth estimator set the target bitrate to a + // conservative default. + config->rc_target_bitrate = 500; } }
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index 8e71b25..722b9355 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -84,6 +84,12 @@ } if (is_chromeos) { + # TODO(GYP): crbug.com/481627. These should only be included + # when enable_me2me_host is true. + sources -= [ + "me2me_desktop_environment.cc", + "me2me_desktop_environment.h", + ] deps += [ "//cc", "//ppapi/host", @@ -146,6 +152,10 @@ if (enable_webrtc) { deps += [ + # TODO(GYP): crbug.com/481633. We should probably not have to depend on + # libjingle_webrtc; that should be pulled in automatically by + # libpeerconnection instead. + "//third_party/libjingle:libjingle_webrtc", "//third_party/libjingle:libpeerconnection", "//third_party/webrtc/modules/desktop_capture", ] @@ -235,6 +245,7 @@ "screen_resolution_unittest.cc", "server_log_entry_host_unittest.cc", "setup/me2me_native_messaging_host_unittest.cc", + "setup/mock_oauth_client.cc", "setup/oauth_helper_unittest.cc", "setup/pin_validator_unittest.cc", "shaped_desktop_capturer_unittest.cc",
diff --git a/remoting/host/audio_capturer_win.h b/remoting/host/audio_capturer_win.h index c9f19d3c..49477fad 100644 --- a/remoting/host/audio_capturer_win.h +++ b/remoting/host/audio_capturer_win.h
@@ -23,10 +23,10 @@ class AudioCapturerWin : public AudioCapturer { public: AudioCapturerWin(); - virtual ~AudioCapturerWin(); + ~AudioCapturerWin() override; // AudioCapturer interface. - virtual bool Start(const PacketCapturedCallback& callback) override; + bool Start(const PacketCapturedCallback& callback) override; private: // Receives all packets from the audio capture endpoint buffer and pushes them
diff --git a/remoting/host/chromeos/aura_desktop_capturer_unittest.cc b/remoting/host/chromeos/aura_desktop_capturer_unittest.cc index 9095cba..42dee81 100644 --- a/remoting/host/chromeos/aura_desktop_capturer_unittest.cc +++ b/remoting/host/chromeos/aura_desktop_capturer_unittest.cc
@@ -39,7 +39,7 @@ public: AuraDesktopCapturerTest() {} - virtual void SetUp() override; + void SetUp() override; MOCK_METHOD1(CreateSharedMemory, webrtc::SharedMemory*(size_t size)); MOCK_METHOD1(OnCaptureCompleted, void(webrtc::DesktopFrame* frame));
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 346e887f..57f0f9b6 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc
@@ -285,15 +285,17 @@ return; } - protocol::SessionConfig config; - if (!protocol_config_->Select(session->candidate_config(), &config)) { + scoped_ptr<protocol::SessionConfig> config = + protocol::SessionConfig::SelectCommon(session->candidate_config(), + protocol_config_.get()); + if (!config) { LOG(WARNING) << "Rejecting connection from " << session->jid() << " because no compatible configuration has been found."; *response = protocol::SessionManager::INCOMPATIBLE; return; } - session->set_config(config); + session->set_config(config.Pass()); *response = protocol::SessionManager::ACCEPT;
diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc index 19efc25..b7d6d65c 100644 --- a/remoting/host/chromoting_host_unittest.cc +++ b/remoting/host/chromoting_host_unittest.cc
@@ -108,9 +108,7 @@ session_jid1_ = "user@domain/rest-of-jid"; session_config2_ = SessionConfig::ForTest(); session_jid2_ = "user2@domain/rest-of-jid"; - session_unowned_config1_ = SessionConfig::ForTest(); session_unowned_jid1_ = "user3@doman/rest-of-jid"; - session_unowned_config2_ = SessionConfig::ForTest(); session_unowned_jid2_ = "user4@doman/rest-of-jid"; EXPECT_CALL(*session1_, jid()) @@ -132,9 +130,9 @@ .Times(AnyNumber()) .WillRepeatedly(SaveArg<0>(&session_unowned2_event_handler_)); EXPECT_CALL(*session1_, config()) - .WillRepeatedly(ReturnRef(session_config1_)); + .WillRepeatedly(ReturnRef(*session_config1_)); EXPECT_CALL(*session2_, config()) - .WillRepeatedly(ReturnRef(session_config2_)); + .WillRepeatedly(ReturnRef(*session_config2_)); owned_connection1_.reset(new MockConnectionToClient(session1_, &host_stub1_)); @@ -421,7 +419,7 @@ ClientSession* client1_; std::string session_jid1_; MockSession* session1_; // Owned by |connection_|. - SessionConfig session_config1_; + scoped_ptr<SessionConfig> session_config1_; MockVideoStub video_stub1_; MockClientStub client_stub1_; MockHostStub host_stub1_; @@ -430,15 +428,13 @@ ClientSession* client2_; std::string session_jid2_; MockSession* session2_; // Owned by |connection2_|. - SessionConfig session_config2_; + scoped_ptr<SessionConfig> session_config2_; MockVideoStub video_stub2_; MockClientStub client_stub2_; MockHostStub host_stub2_; scoped_ptr<MockSession> session_unowned1_; // Not owned by a connection. - SessionConfig session_unowned_config1_; std::string session_unowned_jid1_; scoped_ptr<MockSession> session_unowned2_; // Not owned by a connection. - SessionConfig session_unowned_config2_; std::string session_unowned_jid2_; protocol::Session::EventHandler* session_unowned1_event_handler_; protocol::Session::EventHandler* session_unowned2_event_handler_; @@ -599,7 +595,7 @@ ExpectHostAndSessionManagerStart(); EXPECT_CALL(*session_unowned1_, candidate_config()).WillOnce(Return( default_candidate_config_.get())); - EXPECT_CALL(*session_unowned1_, set_config(_)); + EXPECT_CALL(*session_unowned1_, set_config_ptr(_)); EXPECT_CALL(*session_unowned1_, Close()).WillOnce(InvokeWithoutArgs( this, &ChromotingHostTest::NotifyConnectionClosed1)); EXPECT_CALL(host_status_observer_, OnAccessDenied(_)); @@ -620,7 +616,7 @@ ExpectHostAndSessionManagerStart(); EXPECT_CALL(*session_unowned1_, candidate_config()).WillOnce( Return(default_candidate_config_.get())); - EXPECT_CALL(*session_unowned1_, set_config(_)); + EXPECT_CALL(*session_unowned1_, set_config_ptr(_)); EXPECT_CALL(*session_unowned1_, Close()).WillOnce( InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed1)); EXPECT_CALL(host_status_observer_, OnAccessDenied(_)); @@ -646,13 +642,13 @@ Expectation start = ExpectHostAndSessionManagerStart(); EXPECT_CALL(*session_unowned1_, candidate_config()).WillOnce( Return(default_candidate_config_.get())); - EXPECT_CALL(*session_unowned1_, set_config(_)); + EXPECT_CALL(*session_unowned1_, set_config_ptr(_)); EXPECT_CALL(*session_unowned1_, Close()).WillOnce( InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed1)); EXPECT_CALL(*session_unowned2_, candidate_config()).WillOnce( Return(default_candidate_config_.get())); - EXPECT_CALL(*session_unowned2_, set_config(_)); + EXPECT_CALL(*session_unowned2_, set_config_ptr(_)); EXPECT_CALL(*session_unowned2_, Close()).WillOnce( InvokeWithoutArgs(this, &ChromotingHostTest::NotifyConnectionClosed2));
diff --git a/remoting/host/client_session_unittest.cc b/remoting/host/client_session_unittest.cc index 5d94591..8af1e6c 100644 --- a/remoting/host/client_session_unittest.cc +++ b/remoting/host/client_session_unittest.cc
@@ -178,7 +178,7 @@ MockClientSessionEventHandler session_event_handler_; // Storage for values to be returned by the protocol::Session mock. - SessionConfig session_config_; + scoped_ptr<SessionConfig> session_config_; const std::string client_jid_; // Stubs returned to |client_session_| components by |connection_|. @@ -224,7 +224,7 @@ void ClientSessionTest::CreateClientSession() { // Mock protocol::Session APIs called directly by ClientSession. protocol::MockSession* session = new MockSession(); - EXPECT_CALL(*session, config()).WillRepeatedly(ReturnRef(session_config_)); + EXPECT_CALL(*session, config()).WillRepeatedly(ReturnRef(*session_config_)); EXPECT_CALL(*session, jid()).WillRepeatedly(ReturnRef(client_jid_)); EXPECT_CALL(*session, SetEventHandler(_));
diff --git a/remoting/host/clipboard_win.cc b/remoting/host/clipboard_win.cc index 7c25ec2e..956cb3f 100644 --- a/remoting/host/clipboard_win.cc +++ b/remoting/host/clipboard_win.cc
@@ -109,9 +109,9 @@ ClipboardWin(); ~ClipboardWin() override; - virtual void Start( + void Start( scoped_ptr<protocol::ClipboardStub> client_clipboard) override; - virtual void InjectClipboardEvent( + void InjectClipboardEvent( const protocol::ClipboardEvent& event) override; private:
diff --git a/remoting/host/continue_window_win.cc b/remoting/host/continue_window_win.cc index cb690e5..36aaba9 100644 --- a/remoting/host/continue_window_win.cc +++ b/remoting/host/continue_window_win.cc
@@ -22,12 +22,12 @@ class ContinueWindowWin : public ContinueWindow { public: ContinueWindowWin(); - virtual ~ContinueWindowWin(); + ~ContinueWindowWin() override; protected: // ContinueWindow overrides. - virtual void ShowUi() override; - virtual void HideUi() override; + void ShowUi() override; + void HideUi() override; private: static BOOL CALLBACK DialogProc(HWND hwmd, UINT msg, WPARAM wParam,
diff --git a/remoting/host/curtain_mode_win.cc b/remoting/host/curtain_mode_win.cc index a9f51c8..0a0f395 100644 --- a/remoting/host/curtain_mode_win.cc +++ b/remoting/host/curtain_mode_win.cc
@@ -16,7 +16,7 @@ CurtainModeWin(); // Overriden from CurtainMode. - virtual bool Activate() override; + bool Activate() override; private: DISALLOW_COPY_AND_ASSIGN(CurtainModeWin);
diff --git a/remoting/host/daemon_process.cc b/remoting/host/daemon_process.cc index 8c9ebbb2..e08677a0 100644 --- a/remoting/host/daemon_process.cc +++ b/remoting/host/daemon_process.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -285,9 +286,7 @@ DCHECK(caller_task_runner()->BelongsToCurrentThread()); if (!stopped_callback_.is_null()) { - base::Closure stopped_callback = stopped_callback_; - stopped_callback_.Reset(); - stopped_callback.Run(); + base::ResetAndReturn(&stopped_callback_).Run(); } }
diff --git a/remoting/host/daemon_process_unittest.cc b/remoting/host/daemon_process_unittest.cc index d1e464b..def799b3 100644 --- a/remoting/host/daemon_process_unittest.cc +++ b/remoting/host/daemon_process_unittest.cc
@@ -54,15 +54,15 @@ scoped_refptr<AutoThreadTaskRunner> caller_task_runner, scoped_refptr<AutoThreadTaskRunner> io_task_runner, const base::Closure& stopped_callback); - virtual ~MockDaemonProcess(); + ~MockDaemonProcess() override; - virtual scoped_ptr<DesktopSession> DoCreateDesktopSession( + scoped_ptr<DesktopSession> DoCreateDesktopSession( int terminal_id, const ScreenResolution& resolution, bool virtual_terminal) override; - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void SendToNetwork(IPC::Message* message) override; + bool OnMessageReceived(const IPC::Message& message) override; + void SendToNetwork(IPC::Message* message) override; MOCK_METHOD1(Received, void(const IPC::Message&)); MOCK_METHOD1(Sent, void(const IPC::Message&));
diff --git a/remoting/host/daemon_process_win.cc b/remoting/host/daemon_process_win.cc index 32bf73a..08ffff6 100644 --- a/remoting/host/daemon_process_win.cc +++ b/remoting/host/daemon_process_win.cc
@@ -68,28 +68,28 @@ scoped_refptr<AutoThreadTaskRunner> caller_task_runner, scoped_refptr<AutoThreadTaskRunner> io_task_runner, const base::Closure& stopped_callback); - virtual ~DaemonProcessWin(); + ~DaemonProcessWin() override; // WorkerProcessIpcDelegate implementation. - virtual void OnChannelConnected(int32 peer_pid) override; - virtual void OnPermanentError(int exit_code) override; + void OnChannelConnected(int32 peer_pid) override; + void OnPermanentError(int exit_code) override; // DaemonProcess overrides. - virtual void SendToNetwork(IPC::Message* message) override; - virtual bool OnDesktopSessionAgentAttached( + void SendToNetwork(IPC::Message* message) override; + bool OnDesktopSessionAgentAttached( int terminal_id, base::ProcessHandle desktop_process, IPC::PlatformFileForTransit desktop_pipe) override; protected: // DaemonProcess implementation. - virtual scoped_ptr<DesktopSession> DoCreateDesktopSession( + scoped_ptr<DesktopSession> DoCreateDesktopSession( int terminal_id, const ScreenResolution& resolution, bool virtual_terminal) override; - virtual void DoCrashNetworkProcess( + void DoCrashNetworkProcess( const tracked_objects::Location& location) override; - virtual void LaunchNetworkProcess() override; + void LaunchNetworkProcess() override; // Changes the service start type to 'manual'. void DisableAutoStart();
diff --git a/remoting/host/desktop_process_unittest.cc b/remoting/host/desktop_process_unittest.cc index 609473a0..39a4e27e 100644 --- a/remoting/host/desktop_process_unittest.cc +++ b/remoting/host/desktop_process_unittest.cc
@@ -41,9 +41,9 @@ class MockDaemonListener : public IPC::Listener { public: MockDaemonListener() {} - virtual ~MockDaemonListener() {} + ~MockDaemonListener() override {} - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit)); MOCK_METHOD1(OnChannelConnected, void(int32)); @@ -56,9 +56,9 @@ class MockNetworkListener : public IPC::Listener { public: MockNetworkListener() {} - virtual ~MockNetworkListener() {} + ~MockNetworkListener() override {} - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; MOCK_METHOD1(OnChannelConnected, void(int32)); MOCK_METHOD0(OnChannelError, void());
diff --git a/remoting/host/desktop_resizer_win.cc b/remoting/host/desktop_resizer_win.cc index f35b39f..de2fd376 100644 --- a/remoting/host/desktop_resizer_win.cc +++ b/remoting/host/desktop_resizer_win.cc
@@ -32,14 +32,14 @@ class DesktopResizerWin : public DesktopResizer { public: DesktopResizerWin(); - virtual ~DesktopResizerWin(); + ~DesktopResizerWin() override; // DesktopResizer interface. - virtual ScreenResolution GetCurrentResolution() override; - virtual std::list<ScreenResolution> GetSupportedResolutions( + ScreenResolution GetCurrentResolution() override; + std::list<ScreenResolution> GetSupportedResolutions( const ScreenResolution& preferred) override; - virtual void SetResolution(const ScreenResolution& resolution) override; - virtual void RestoreResolution(const ScreenResolution& original) override; + void SetResolution(const ScreenResolution& resolution) override; + void RestoreResolution(const ScreenResolution& original) override; private: static bool IsResizeSupported();
diff --git a/remoting/host/desktop_session_win.cc b/remoting/host/desktop_session_win.cc index c98f229..f3c0881 100644 --- a/remoting/host/desktop_session_win.cc +++ b/remoting/host/desktop_session_win.cc
@@ -91,14 +91,14 @@ DaemonProcess* daemon_process, int id, WtsTerminalMonitor* monitor); - virtual ~ConsoleSession(); + ~ConsoleSession() override; protected: // DesktopSession overrides. - virtual void SetScreenResolution(const ScreenResolution& resolution) override; + void SetScreenResolution(const ScreenResolution& resolution) override; // DesktopSessionWin overrides. - virtual void InjectSas() override; + void InjectSas() override; private: scoped_ptr<SasInjector> sas_injector_; @@ -119,7 +119,7 @@ DaemonProcess* daemon_process, int id, WtsTerminalMonitor* monitor); - virtual ~RdpSession(); + ~RdpSession() override; // Performs the part of initialization that can fail. bool Initialize(const ScreenResolution& resolution); @@ -130,10 +130,10 @@ protected: // DesktopSession overrides. - virtual void SetScreenResolution(const ScreenResolution& resolution) override; + void SetScreenResolution(const ScreenResolution& resolution) override; // DesktopSessionWin overrides. - virtual void InjectSas() override; + void InjectSas() override; private: // An implementation of IRdpDesktopSessionEventHandler interface that forwards
diff --git a/remoting/host/desktop_session_win.h b/remoting/host/desktop_session_win.h index 3e21a029..933be24 100644 --- a/remoting/host/desktop_session_win.h +++ b/remoting/host/desktop_session_win.h
@@ -63,7 +63,7 @@ DaemonProcess* daemon_process, int id, WtsTerminalMonitor* monitor); - virtual ~DesktopSessionWin(); + ~DesktopSessionWin() override; const scoped_refptr<AutoThreadTaskRunner>& caller_task_runner() const { return caller_task_runner_; @@ -85,13 +85,13 @@ virtual void InjectSas() = 0; // WorkerProcessIpcDelegate implementation. - virtual void OnChannelConnected(int32 peer_pid) override; - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void OnPermanentError(int exit_code) override; + void OnChannelConnected(int32 peer_pid) override; + bool OnMessageReceived(const IPC::Message& message) override; + void OnPermanentError(int exit_code) override; // WtsTerminalObserver implementation. - virtual void OnSessionAttached(uint32 session_id) override; - virtual void OnSessionDetached() override; + void OnSessionAttached(uint32 session_id) override; + void OnSessionDetached() override; private: // ChromotingDesktopDaemonMsg_DesktopAttached handler.
diff --git a/remoting/host/disconnect_window_win.cc b/remoting/host/disconnect_window_win.cc index fd789d4..7617b091 100644 --- a/remoting/host/disconnect_window_win.cc +++ b/remoting/host/disconnect_window_win.cc
@@ -35,10 +35,10 @@ class DisconnectWindowWin : public HostWindow { public: DisconnectWindowWin(); - virtual ~DisconnectWindowWin(); + ~DisconnectWindowWin() override; // HostWindow overrides. - virtual void Start( + void Start( const base::WeakPtr<ClientSessionControl>& client_session_control) override;
diff --git a/remoting/host/dns_blackhole_checker.cc b/remoting/host/dns_blackhole_checker.cc index 745481e..b92eb12 100644 --- a/remoting/host/dns_blackhole_checker.cc +++ b/remoting/host/dns_blackhole_checker.cc
@@ -4,6 +4,7 @@ #include "remoting/host/dns_blackhole_checker.h" +#include "base/callback_helpers.h" #include "net/url_request/url_fetcher.h" #include "net/url_request/url_request_context_getter.h" #include "remoting/base/logging.h" @@ -40,8 +41,7 @@ HOST_LOG << "Unable to connect to host talkgadget (" << response << ")"; } url_fetcher_.reset(nullptr); - callback_.Run(allow); - callback_.Reset(); + base::ResetAndReturn(&callback_).Run(allow); } void DnsBlackholeChecker::CheckForDnsBlackhole(
diff --git a/remoting/host/gnubby_auth_handler_win.cc b/remoting/host/gnubby_auth_handler_win.cc index e24eb6b1..6b8bd64 100644 --- a/remoting/host/gnubby_auth_handler_win.cc +++ b/remoting/host/gnubby_auth_handler_win.cc
@@ -13,9 +13,9 @@ class GnubbyAuthHandlerWin : public GnubbyAuthHandler { private: // GnubbyAuthHandler interface. - virtual void DeliverClientMessage(const std::string& message) override; - virtual void DeliverHostDataMessage(int connection_id, - const std::string& data) const override; + void DeliverClientMessage(const std::string& message) override; + void DeliverHostDataMessage(int connection_id, + const std::string& data) const override; DISALLOW_COPY_AND_ASSIGN(GnubbyAuthHandlerWin); };
diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc index ae10955..1d1a77d 100644 --- a/remoting/host/heartbeat_sender.cc +++ b/remoting/host/heartbeat_sender.cc
@@ -7,6 +7,7 @@ #include <math.h> #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringize_macros.h" @@ -105,9 +106,7 @@ void HeartbeatSender::OnHostOfflineReasonTimeout() { DCHECK(!host_offline_reason_ack_callback_.is_null()); - base::Callback<void(bool)> local_callback = host_offline_reason_ack_callback_; - host_offline_reason_ack_callback_.Reset(); - local_callback.Run(false); + base::ResetAndReturn(&host_offline_reason_ack_callback_).Run(false); } void HeartbeatSender::OnHostOfflineReasonAck() { @@ -122,11 +121,10 @@ // Run the ACK callback under a clean stack via PostTask() (because the // callback can end up deleting |this| HeartbeatSender [i.e. when used from // HostSignalingManager]). - base::Closure fully_bound_ack_callback = - base::Bind(host_offline_reason_ack_callback_, true); - host_offline_reason_ack_callback_.Reset(); - base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - fully_bound_ack_callback); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(base::ResetAndReturn(&host_offline_reason_ack_callback_), + true)); } void HeartbeatSender::SetHostOfflineReason(
diff --git a/remoting/host/host_event_logger_win.cc b/remoting/host/host_event_logger_win.cc index fa58b52..d8b039f 100644 --- a/remoting/host/host_event_logger_win.cc +++ b/remoting/host/host_event_logger_win.cc
@@ -27,19 +27,19 @@ HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor, const std::string& application_name); - virtual ~HostEventLoggerWin(); + ~HostEventLoggerWin() override; // HostStatusObserver implementation. These methods will be called from the // network thread. - virtual void OnClientAuthenticated(const std::string& jid) override; - virtual void OnClientDisconnected(const std::string& jid) override; - virtual void OnAccessDenied(const std::string& jid) override; - virtual void OnClientRouteChange( + void OnClientAuthenticated(const std::string& jid) override; + void OnClientDisconnected(const std::string& jid) override; + void OnAccessDenied(const std::string& jid) override; + void OnClientRouteChange( const std::string& jid, const std::string& channel_name, const protocol::TransportRoute& route) override; - virtual void OnStart(const std::string& xmpp_login) override; - virtual void OnShutdown() override; + void OnStart(const std::string& xmpp_login) override; + void OnShutdown() override; private: void LogString(WORD type, DWORD event_id, const std::string& string);
diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h index 6ea9d7b1..52d0170 100644 --- a/remoting/host/host_mock_objects.h +++ b/remoting/host/host_mock_objects.h
@@ -30,7 +30,7 @@ class MockDesktopEnvironment : public DesktopEnvironment { public: MockDesktopEnvironment(); - virtual ~MockDesktopEnvironment(); + ~MockDesktopEnvironment() override; MOCK_METHOD0(CreateAudioCapturerPtr, AudioCapturer*()); MOCK_METHOD0(CreateInputInjectorPtr, InputInjector*()); @@ -43,20 +43,20 @@ protocol::ClientStub* client_stub)); // DesktopEnvironment implementation. - virtual scoped_ptr<AudioCapturer> CreateAudioCapturer() override; - virtual scoped_ptr<InputInjector> CreateInputInjector() override; - virtual scoped_ptr<ScreenControls> CreateScreenControls() override; - virtual scoped_ptr<webrtc::DesktopCapturer> CreateVideoCapturer() override; - virtual scoped_ptr<GnubbyAuthHandler> CreateGnubbyAuthHandler( + scoped_ptr<AudioCapturer> CreateAudioCapturer() override; + scoped_ptr<InputInjector> CreateInputInjector() override; + scoped_ptr<ScreenControls> CreateScreenControls() override; + scoped_ptr<webrtc::DesktopCapturer> CreateVideoCapturer() override; + scoped_ptr<GnubbyAuthHandler> CreateGnubbyAuthHandler( protocol::ClientStub* client_stub) override; - virtual scoped_ptr<webrtc::MouseCursorMonitor> CreateMouseCursorMonitor() + scoped_ptr<webrtc::MouseCursorMonitor> CreateMouseCursorMonitor() override; }; class MockClientSessionControl : public ClientSessionControl { public: MockClientSessionControl(); - virtual ~MockClientSessionControl(); + ~MockClientSessionControl() override; MOCK_CONST_METHOD0(client_jid, const std::string&()); MOCK_METHOD0(DisconnectSession, void()); @@ -71,7 +71,7 @@ class MockClientSessionEventHandler : public ClientSession::EventHandler { public: MockClientSessionEventHandler(); - virtual ~MockClientSessionEventHandler(); + ~MockClientSessionEventHandler() override; MOCK_METHOD1(OnSessionAuthenticating, void(ClientSession* client)); MOCK_METHOD1(OnSessionAuthenticated, bool(ClientSession* client)); @@ -90,12 +90,12 @@ class MockDesktopEnvironmentFactory : public DesktopEnvironmentFactory { public: MockDesktopEnvironmentFactory(); - virtual ~MockDesktopEnvironmentFactory(); + ~MockDesktopEnvironmentFactory() override; MOCK_METHOD0(CreatePtr, DesktopEnvironment*()); MOCK_CONST_METHOD0(SupportsAudioCapture, bool()); - virtual scoped_ptr<DesktopEnvironment> Create( + scoped_ptr<DesktopEnvironment> Create( base::WeakPtr<ClientSessionControl> client_session_control) override; private: @@ -105,7 +105,7 @@ class MockInputInjector : public InputInjector { public: MockInputInjector(); - virtual ~MockInputInjector(); + ~MockInputInjector() override; MOCK_METHOD1(InjectClipboardEvent, void(const protocol::ClipboardEvent& event)); @@ -125,7 +125,7 @@ class MockHostStatusObserver : public HostStatusObserver { public: MockHostStatusObserver(); - virtual ~MockHostStatusObserver(); + ~MockHostStatusObserver() override; MOCK_METHOD1(OnAccessDenied, void(const std::string& jid)); MOCK_METHOD1(OnClientAuthenticated, void(const std::string& jid)); @@ -142,7 +142,7 @@ class MockGnubbyAuthHandler : public GnubbyAuthHandler { public: MockGnubbyAuthHandler(); - virtual ~MockGnubbyAuthHandler(); + ~MockGnubbyAuthHandler() override; MOCK_METHOD1(DeliverClientMessage, void(const std::string& message)); MOCK_CONST_METHOD2(DeliverHostDataMessage, @@ -155,7 +155,7 @@ class MockMouseCursorMonitor : public webrtc::MouseCursorMonitor { public: MockMouseCursorMonitor(); - virtual ~MockMouseCursorMonitor(); + ~MockMouseCursorMonitor() override; MOCK_METHOD2(Init, void(Callback* callback, Mode mode)); MOCK_METHOD0(Capture, void());
diff --git a/remoting/host/input_injector_win.cc b/remoting/host/input_injector_win.cc index 37f628ac..58f694e5 100644 --- a/remoting/host/input_injector_win.cc +++ b/remoting/host/input_injector_win.cc
@@ -59,19 +59,19 @@ public: InputInjectorWin(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner); - virtual ~InputInjectorWin(); + ~InputInjectorWin() override; // ClipboardStub interface. - virtual void InjectClipboardEvent(const ClipboardEvent& event) override; + void InjectClipboardEvent(const ClipboardEvent& event) override; // InputStub interface. - virtual void InjectKeyEvent(const KeyEvent& event) override; - virtual void InjectTextEvent(const TextEvent& event) override; - virtual void InjectMouseEvent(const MouseEvent& event) override; - virtual void InjectTouchEvent(const TouchEvent& event) override; + void InjectKeyEvent(const KeyEvent& event) override; + void InjectTextEvent(const TextEvent& event) override; + void InjectMouseEvent(const MouseEvent& event) override; + void InjectTouchEvent(const TouchEvent& event) override; // InputInjector interface. - virtual void Start( + void Start( scoped_ptr<protocol::ClipboardStub> client_clipboard) override; private:
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc index d31d3d46..186574b 100644 --- a/remoting/host/ipc_desktop_environment_unittest.cc +++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -57,10 +57,10 @@ class FakeDaemonSender : public IPC::Sender { public: FakeDaemonSender() {} - virtual ~FakeDaemonSender() {} + ~FakeDaemonSender() override {} // IPC::Sender implementation. - virtual bool Send(IPC::Message* message) override; + bool Send(IPC::Message* message) override; MOCK_METHOD3(ConnectTerminal, void(int, const ScreenResolution&, bool)); MOCK_METHOD1(DisconnectTerminal, void(int)); @@ -76,9 +76,9 @@ class MockDaemonListener : public IPC::Listener { public: MockDaemonListener() {} - virtual ~MockDaemonListener() {} + ~MockDaemonListener() override {} - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; MOCK_METHOD1(OnDesktopAttached, void(IPC::PlatformFileForTransit)); MOCK_METHOD1(OnChannelConnected, void(int32));
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc index 0ea715f3..a67511cb 100644 --- a/remoting/host/it2me/it2me_host.cc +++ b/remoting/host/it2me/it2me_host.cc
@@ -5,6 +5,7 @@ #include "remoting/host/it2me/it2me_host.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/strings/string_util.h" #include "base/threading/platform_thread.h" #include "net/socket/client_socket_factory.h" @@ -371,8 +372,7 @@ policy_received_ = true; if (!pending_connect_.is_null()) { - pending_connect_.Run(); - pending_connect_.Reset(); + base::ResetAndReturn(&pending_connect_).Run(); } }
diff --git a/remoting/host/pairing_registry_delegate_win.h b/remoting/host/pairing_registry_delegate_win.h index 9f9d4dc..f7cf832b 100644 --- a/remoting/host/pairing_registry_delegate_win.h +++ b/remoting/host/pairing_registry_delegate_win.h
@@ -44,7 +44,7 @@ : public protocol::PairingRegistry::Delegate { public: PairingRegistryDelegateWin(); - virtual ~PairingRegistryDelegateWin(); + ~PairingRegistryDelegateWin() override; // Passes the root keys to be used to access the pairing registry store. // |privileged| is optional and may be nullptr. The caller retains ownership @@ -52,12 +52,12 @@ bool SetRootKeys(HKEY privileged, HKEY unprivileged); // PairingRegistry::Delegate interface - virtual scoped_ptr<base::ListValue> LoadAll() override; - virtual bool DeleteAll() override; - virtual protocol::PairingRegistry::Pairing Load( + scoped_ptr<base::ListValue> LoadAll() override; + bool DeleteAll() override; + protocol::PairingRegistry::Pairing Load( const std::string& client_id) override; - virtual bool Save(const protocol::PairingRegistry::Pairing& pairing) override; - virtual bool Delete(const std::string& client_id) override; + bool Save(const protocol::PairingRegistry::Pairing& pairing) override; + bool Delete(const std::string& client_id) override; private: base::win::RegKey privileged_;
diff --git a/remoting/host/pairing_registry_delegate_win_unittest.cc b/remoting/host/pairing_registry_delegate_win_unittest.cc index 7801926..646bd19 100644 --- a/remoting/host/pairing_registry_delegate_win_unittest.cc +++ b/remoting/host/pairing_registry_delegate_win_unittest.cc
@@ -18,7 +18,7 @@ class PairingRegistryDelegateWinTest : public testing::Test { public: - virtual void SetUp() override { + void SetUp() override { key_name_ = base::GenerateGUID(); base::win::RegKey root; @@ -32,7 +32,7 @@ KEY_READ | KEY_WRITE) == ERROR_SUCCESS); } - virtual void TearDown() override { + void TearDown() override { privileged_.Close(); unprivileged_.Close(); EXPECT_TRUE(
diff --git a/remoting/host/register_support_host_request.cc b/remoting/host/register_support_host_request.cc index c0a80d1..b1bdd41 100644 --- a/remoting/host/register_support_host_request.cc +++ b/remoting/host/register_support_host_request.cc
@@ -5,6 +5,7 @@ #include "remoting/host/register_support_host_request.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" @@ -178,9 +179,7 @@ signal_strategy_->RemoveListener(this); signal_strategy_ = nullptr; - RegisterCallback callback = callback_; - callback_.Reset(); - callback.Run(success, support_id, lifetime); + base::ResetAndReturn(&callback_).Run(success, support_id, lifetime); } } // namespace remoting
diff --git a/remoting/host/sas_injector_win.cc b/remoting/host/sas_injector_win.cc index 53e98b1..ec64a11c 100644 --- a/remoting/host/sas_injector_win.cc +++ b/remoting/host/sas_injector_win.cc
@@ -109,10 +109,10 @@ class SasInjectorWin : public SasInjector { public: SasInjectorWin(); - virtual ~SasInjectorWin(); + ~SasInjectorWin() override; // SasInjector implementation. - virtual bool InjectSas() override; + bool InjectSas() override; private: base::ScopedNativeLibrary sas_dll_; @@ -125,10 +125,10 @@ class SasInjectorXp : public SasInjector { public: SasInjectorXp(); - virtual ~SasInjectorXp(); + ~SasInjectorXp() override; // SasInjector implementation. - virtual bool InjectSas() override; + bool InjectSas() override; }; SasInjectorWin::SasInjectorWin() : send_sas_(nullptr) {
diff --git a/remoting/host/session_manager_factory.cc b/remoting/host/session_manager_factory.cc index ad6ac6bb..996bbce 100644 --- a/remoting/host/session_manager_factory.cc +++ b/remoting/host/session_manager_factory.cc
@@ -25,7 +25,8 @@ scoped_ptr<protocol::TransportFactory> transport_factory( new protocol::LibjingleTransportFactory( - signal_strategy, port_allocator.Pass(), network_settings)); + signal_strategy, port_allocator.Pass(), network_settings, + protocol::TransportRole::SERVER)); scoped_ptr<protocol::JingleSessionManager> session_manager( new protocol::JingleSessionManager(transport_factory.Pass()));
diff --git a/remoting/host/setup/daemon_controller_delegate_linux.cc b/remoting/host/setup/daemon_controller_delegate_linux.cc index 3d7fa65..4928b86 100644 --- a/remoting/host/setup/daemon_controller_delegate_linux.cc +++ b/remoting/host/setup/daemon_controller_delegate_linux.cc
@@ -45,17 +45,9 @@ // Timeout for commands that require password prompt - 5 minutes. const int64 kSudoTimeoutSeconds = 5 * 60; -std::string GetMd5(const std::string& value) { - base::MD5Context ctx; - base::MD5Init(&ctx); - base::MD5Update(&ctx, value); - base::MD5Digest digest; - base::MD5Final(&digest, &ctx); - return base::StringToLowerASCII(base::HexEncode(digest.a, sizeof(digest.a))); -} - base::FilePath GetConfigPath() { - std::string filename = "host#" + GetMd5(net::GetHostName()) + ".json"; + std::string filename = + "host#" + base::MD5String(net::GetHostName()) + ".json"; base::FilePath homedir; PathService::Get(base::DIR_HOME, &homedir); return homedir.Append(".config/chrome-remote-desktop").Append(filename);
diff --git a/remoting/host/setup/daemon_controller_delegate_mac.mm b/remoting/host/setup/daemon_controller_delegate_mac.mm index 2fd7daaa..9821f868 100644 --- a/remoting/host/setup/daemon_controller_delegate_mac.mm +++ b/remoting/host/setup/daemon_controller_delegate_mac.mm
@@ -12,6 +12,7 @@ #include "base/basictypes.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -175,12 +176,10 @@ return; } - DCHECK(!current_callback_.is_null()); - DaemonController::CompletionCallback done = current_callback_; - current_callback_.Reset(); - done.Run(result); - DeregisterForPreferencePaneNotifications(); + + DCHECK(!current_callback_.is_null()); + base::ResetAndReturn(¤t_callback_).Run(result); } // static
diff --git a/remoting/host/setup/daemon_controller_delegate_win.h b/remoting/host/setup/daemon_controller_delegate_win.h index 1131045..d7b2582 100644 --- a/remoting/host/setup/daemon_controller_delegate_win.h +++ b/remoting/host/setup/daemon_controller_delegate_win.h
@@ -14,20 +14,20 @@ class DaemonControllerDelegateWin : public DaemonController::Delegate { public: DaemonControllerDelegateWin(); - virtual ~DaemonControllerDelegateWin(); + ~DaemonControllerDelegateWin() override; // DaemonController::Delegate interface. - virtual DaemonController::State GetState() override; - virtual scoped_ptr<base::DictionaryValue> GetConfig() override; - virtual void SetConfigAndStart( + DaemonController::State GetState() override; + scoped_ptr<base::DictionaryValue> GetConfig() override; + void SetConfigAndStart( scoped_ptr<base::DictionaryValue> config, bool consent, const DaemonController::CompletionCallback& done) override; - virtual void UpdateConfig( + void UpdateConfig( scoped_ptr<base::DictionaryValue> config, const DaemonController::CompletionCallback& done) override; - virtual void Stop(const DaemonController::CompletionCallback& done) override; - virtual DaemonController::UsageStatsConsent GetUsageStatsConsent() override; + void Stop(const DaemonController::CompletionCallback& done) override; + DaemonController::UsageStatsConsent GetUsageStatsConsent() override; DISALLOW_COPY_AND_ASSIGN(DaemonControllerDelegateWin); };
diff --git a/remoting/host/setup/gaia_oauth_client.cc b/remoting/host/setup/gaia_oauth_client.cc new file mode 100644 index 0000000..9855dd6 --- /dev/null +++ b/remoting/host/setup/gaia_oauth_client.cc
@@ -0,0 +1,100 @@ +// Copyright 2013 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 "remoting/host/setup/gaia_oauth_client.h" + +#include "base/callback_helpers.h" +#include "base/logging.h" + +namespace { +const int kMaxGaiaRetries = 3; +} // namespace + +namespace remoting { + +GaiaOAuthClient::GaiaOAuthClient( + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) + : gaia_oauth_client_(url_request_context_getter.get()) { +} + +GaiaOAuthClient::~GaiaOAuthClient() { +} + +void GaiaOAuthClient::GetCredentialsFromAuthCode( + const gaia::OAuthClientInfo& oauth_client_info, + const std::string& auth_code, + bool need_user_email, + CompletionCallback on_done) { + if (!on_done_.is_null()) { + pending_requests_.push( + Request(oauth_client_info, auth_code, need_user_email, on_done)); + return; + } + + need_user_email_ = need_user_email; + on_done_ = on_done; + // Map the authorization code to refresh and access tokens. + gaia_oauth_client_.GetTokensFromAuthCode(oauth_client_info, auth_code, + kMaxGaiaRetries, this); +} + +void GaiaOAuthClient::OnGetTokensResponse(const std::string& refresh_token, + const std::string& access_token, + int expires_in_seconds) { + refresh_token_ = refresh_token; + if (need_user_email_) { + // Get the email corresponding to the access token. + gaia_oauth_client_.GetUserEmail(access_token, kMaxGaiaRetries, this); + } else { + SendResponse("", refresh_token_); + } +} + +void GaiaOAuthClient::OnRefreshTokenResponse(const std::string& access_token, + int expires_in_seconds) { + // We never request a refresh token, so this call is not expected. + NOTREACHED(); +} + +void GaiaOAuthClient::SendResponse(const std::string& user_email, + const std::string& refresh_token) { + base::ResetAndReturn(&on_done_).Run(user_email, refresh_token); + + // Process the next request in the queue. + if (pending_requests_.size()) { + Request request = pending_requests_.front(); + pending_requests_.pop(); + // GetCredentialsFromAuthCode is asynchronous, so it's safe to call it here. + GetCredentialsFromAuthCode(request.oauth_client_info, request.auth_code, + request.need_user_email, request.on_done); + } +} + +void GaiaOAuthClient::OnGetUserEmailResponse(const std::string& user_email) { + SendResponse(user_email, refresh_token_); +} + +void GaiaOAuthClient::OnOAuthError() { + SendResponse("", ""); +} + +void GaiaOAuthClient::OnNetworkError(int response_code) { + SendResponse("", ""); +} + +GaiaOAuthClient::Request::Request( + const gaia::OAuthClientInfo& oauth_client_info, + const std::string& auth_code, + bool need_user_email, + CompletionCallback on_done) { + this->oauth_client_info = oauth_client_info; + this->auth_code = auth_code; + this->need_user_email = need_user_email; + this->on_done = on_done; +} + +GaiaOAuthClient::Request::~Request() { +} + +} // namespace remoting
diff --git a/remoting/host/setup/gaia_oauth_client.h b/remoting/host/setup/gaia_oauth_client.h new file mode 100644 index 0000000..d6bb72cb --- /dev/null +++ b/remoting/host/setup/gaia_oauth_client.h
@@ -0,0 +1,83 @@ +// Copyright 2013 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 REMOTING_HOST_SETUP_GAIA_OAUTH_CLIENT_H_ +#define REMOTING_HOST_SETUP_GAIA_OAUTH_CLIENT_H_ + +#include <queue> + +#include "base/memory/ref_counted.h" +#include "google_apis/gaia/gaia_oauth_client.h" +#include "net/url_request/url_request_context_getter.h" + +#include "remoting/host/setup/oauth_client.h" + +namespace net { +class URLRequestContext; +} + +namespace remoting { + +// A wrapper around gaia::GaiaOAuthClient that provides a more +// convenient interface, with queueing of requests and a callback +// rather than a delegate. +class GaiaOAuthClient : public OAuthClient, + public gaia::GaiaOAuthClient::Delegate { + public: + GaiaOAuthClient( + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter); + + ~GaiaOAuthClient() override; + + // Redeems |auth_code| using |oauth_client_info| to obtain |refresh_token| and + // |access_token|, then uses the userinfo endpoint to obtain |user_email|. + // Calls CompletionCallback with |user_email| and |refresh_token| when done, + // or with empty strings on error. + // If a request is received while another one is being processed, it is + // enqueued and processed after the first one is finished. + void GetCredentialsFromAuthCode( + const gaia::OAuthClientInfo& oauth_client_info, + const std::string& auth_code, + bool need_user_email, + CompletionCallback on_done) override; + + // gaia::GaiaOAuthClient::Delegate + void OnGetTokensResponse(const std::string& refresh_token, + const std::string& access_token, + int expires_in_seconds) override; + void OnRefreshTokenResponse(const std::string& access_token, + int expires_in_seconds) override; + void OnGetUserEmailResponse(const std::string& user_email) override; + + void OnOAuthError() override; + void OnNetworkError(int response_code) override; + + private: + struct Request { + Request(const gaia::OAuthClientInfo& oauth_client_info, + const std::string& auth_code, + bool need_user_email, + CompletionCallback on_done); + virtual ~Request(); + gaia::OAuthClientInfo oauth_client_info; + std::string auth_code; + bool need_user_email; + CompletionCallback on_done; + }; + + void SendResponse(const std::string& user_email, + const std::string& refresh_token); + + std::queue<Request> pending_requests_; + gaia::GaiaOAuthClient gaia_oauth_client_; + std::string refresh_token_; + bool need_user_email_; + CompletionCallback on_done_; + + DISALLOW_COPY_AND_ASSIGN(GaiaOAuthClient); +}; + +} // namespace remoting + +#endif // REMOTING_HOST_SETUP_GAIA_OAUTH_CLIENT_H_
diff --git a/remoting/host/setup/host_starter.cc b/remoting/host/setup/host_starter.cc index 127c4a9..5eda05c 100644 --- a/remoting/host/setup/host_starter.cc +++ b/remoting/host/setup/host_starter.cc
@@ -5,6 +5,7 @@ #include "remoting/host/setup/host_starter.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/guid.h" #include "base/location.h" #include "base/thread_task_runner_handle.h" @@ -184,9 +185,7 @@ service_client_->UnregisterHost(host_id_, access_token_, this); return; } - CompletionCallback cb = on_done_; - on_done_.Reset(); - cb.Run(START_COMPLETE); + base::ResetAndReturn(&on_done_).Run(START_COMPLETE); } void HostStarter::OnOAuthError() { @@ -195,14 +194,12 @@ &HostStarter::OnOAuthError, weak_ptr_)); return; } - CompletionCallback cb = on_done_; - on_done_.Reset(); if (unregistering_host_) { LOG(ERROR) << "OAuth error occurred when unregistering host."; - cb.Run(START_ERROR); - } else { - cb.Run(OAUTH_ERROR); } + + base::ResetAndReturn(&on_done_) + .Run(unregistering_host_ ? START_ERROR : OAUTH_ERROR); } void HostStarter::OnNetworkError(int response_code) { @@ -211,14 +208,12 @@ &HostStarter::OnNetworkError, weak_ptr_, response_code)); return; } - CompletionCallback cb = on_done_; - on_done_.Reset(); if (unregistering_host_) { LOG(ERROR) << "Network error occurred when unregistering host."; - cb.Run(START_ERROR); - } else { - cb.Run(NETWORK_ERROR); } + + base::ResetAndReturn(&on_done_) + .Run(unregistering_host_ ? START_ERROR : NETWORK_ERROR); } void HostStarter::OnHostUnregistered() { @@ -227,9 +222,7 @@ &HostStarter::OnHostUnregistered, weak_ptr_)); return; } - CompletionCallback cb = on_done_; - on_done_.Reset(); - cb.Run(START_ERROR); + base::ResetAndReturn(&on_done_).Run(START_ERROR); } } // namespace remoting
diff --git a/remoting/host/setup/me2me_native_messaging_host.cc b/remoting/host/setup/me2me_native_messaging_host.cc index 12e688b1..d2957fd 100644 --- a/remoting/host/setup/me2me_native_messaging_host.cc +++ b/remoting/host/setup/me2me_native_messaging_host.cc
@@ -49,7 +49,8 @@ // Features supported in addition to the base protocol. const char* kSupportedFeatures[] = { "pairingRegistry", - "oauthClient" + "oauthClient", + "getRefreshTokenFromAuthCode", }; // Helper to extract the "config" part of a message as a DictionaryValue. @@ -160,7 +161,11 @@ } else if (type == "getHostClientId") { ProcessGetHostClientId(message_dict.Pass(), response.Pass()); } else if (type == "getCredentialsFromAuthCode") { - ProcessGetCredentialsFromAuthCode(message_dict.Pass(), response.Pass()); + ProcessGetCredentialsFromAuthCode( + message_dict.Pass(), response.Pass(), true); + } else if (type == "getRefreshTokenFromAuthCode") { + ProcessGetCredentialsFromAuthCode( + message_dict.Pass(), response.Pass(), false); } else { LOG(ERROR) << "Unsupported request type: " << type; OnError(); @@ -422,7 +427,8 @@ void Me2MeNativeMessagingHost::ProcessGetCredentialsFromAuthCode( scoped_ptr<base::DictionaryValue> message, - scoped_ptr<base::DictionaryValue> response) { + scoped_ptr<base::DictionaryValue> response, + bool need_user_email) { DCHECK(thread_checker_.CalledOnValidThread()); std::string auth_code; @@ -439,7 +445,7 @@ }; oauth_client_->GetCredentialsFromAuthCode( - oauth_client_info, auth_code, base::Bind( + oauth_client_info, auth_code, need_user_email, base::Bind( &Me2MeNativeMessagingHost::SendCredentialsResponse, weak_ptr_, base::Passed(&response))); } @@ -513,7 +519,9 @@ const std::string& refresh_token) { DCHECK(thread_checker_.CalledOnValidThread()); - response->SetString("userEmail", user_email); + if (!user_email.empty()) { + response->SetString("userEmail", user_email); + } response->SetString("refreshToken", refresh_token); channel_->SendMessage(response.Pass()); }
diff --git a/remoting/host/setup/me2me_native_messaging_host.h b/remoting/host/setup/me2me_native_messaging_host.h index e1ddaed..cdbcb6c5 100644 --- a/remoting/host/setup/me2me_native_messaging_host.h +++ b/remoting/host/setup/me2me_native_messaging_host.h
@@ -100,7 +100,8 @@ scoped_ptr<base::DictionaryValue> response); void ProcessGetCredentialsFromAuthCode( scoped_ptr<base::DictionaryValue> message, - scoped_ptr<base::DictionaryValue> response); + scoped_ptr<base::DictionaryValue> response, + bool need_user_email); // These Send... methods get called on the DaemonController's internal thread, // or on the calling thread if called by the PairingRegistry. @@ -135,8 +136,8 @@ public: ElevatedChannelEventHandler(Me2MeNativeMessagingHost* host); - virtual void OnMessage(scoped_ptr<base::Value> message) override; - virtual void OnDisconnect() override; + void OnMessage(scoped_ptr<base::Value> message) override; + void OnDisconnect() override; private: Me2MeNativeMessagingHost* parent_; };
diff --git a/remoting/host/setup/me2me_native_messaging_host_main.cc b/remoting/host/setup/me2me_native_messaging_host_main.cc index 87aec46..bfc943e5 100644 --- a/remoting/host/setup/me2me_native_messaging_host_main.cc +++ b/remoting/host/setup/me2me_native_messaging_host_main.cc
@@ -19,6 +19,7 @@ #include "remoting/host/logging.h" #include "remoting/host/native_messaging/pipe_messaging_channel.h" #include "remoting/host/pairing_registry_delegate.h" +#include "remoting/host/setup/gaia_oauth_client.h" #include "remoting/host/setup/me2me_native_messaging_host.h" #include "remoting/host/usage_stats_consent.h" @@ -197,7 +198,7 @@ new URLRequestContextGetter(io_thread.task_runner(), file_thread.task_runner())); scoped_ptr<OAuthClient> oauth_client( - new OAuthClient(url_request_context_getter)); + new GaiaOAuthClient(url_request_context_getter)); net::URLFetcher::SetIgnoreCertificateRequests(true);
diff --git a/remoting/host/setup/me2me_native_messaging_host_unittest.cc b/remoting/host/setup/me2me_native_messaging_host_unittest.cc index c9a0ae02..bdd6daf9 100644 --- a/remoting/host/setup/me2me_native_messaging_host_unittest.cc +++ b/remoting/host/setup/me2me_native_messaging_host_unittest.cc
@@ -19,6 +19,7 @@ #include "remoting/base/auto_thread_task_runner.h" #include "remoting/host/native_messaging/pipe_messaging_channel.h" #include "remoting/host/pin_hash.h" +#include "remoting/host/setup/mock_oauth_client.h" #include "remoting/host/setup/test_util.h" #include "remoting/protocol/pairing_registry.h" #include "remoting/protocol/protocol_mock_objects.h" @@ -134,6 +135,18 @@ EXPECT_EQ("OK", value); } +void VerifyGetCredentialsFromAuthCodeResponse( + scoped_ptr<base::DictionaryValue> response) { + ASSERT_TRUE(response); + std::string value; + EXPECT_TRUE(response->GetString("type", &value)); + EXPECT_EQ("getCredentialsFromAuthCodeResponse", value); + EXPECT_TRUE(response->GetString("userEmail", &value)); + EXPECT_EQ("fake_user_email", value); + EXPECT_TRUE(response->GetString("refreshToken", &value)); + EXPECT_EQ("fake_refresh_token", value); +} + } // namespace namespace remoting { @@ -313,8 +326,12 @@ new PipeMessagingChannel(input_read_file.Pass(), output_write_file.Pass())); - host_.reset(new Me2MeNativeMessagingHost( - false, 0, channel.Pass(), daemon_controller, pairing_registry, nullptr)); + scoped_ptr<OAuthClient> oauth_client( + new MockOAuthClient("fake_user_email", "fake_refresh_token")); + + host_.reset(new Me2MeNativeMessagingHost(false, 0, channel.Pass(), + daemon_controller, pairing_registry, + oauth_client.Pass())); host_->Start(base::Bind(&Me2MeNativeMessagingHostTest::StopHost, base::Unretained(this))); @@ -474,17 +491,23 @@ message.SetString("type", "startDaemon"); WriteMessageToInputPipe(message); + message.SetInteger("id", next_id++); + message.SetString("type", "getCredentialsFromAuthCode"); + message.SetString("authorizationCode", "fake_auth_code"); + WriteMessageToInputPipe(message); + void (*verify_routines[])(scoped_ptr<base::DictionaryValue>) = { - &VerifyHelloResponse, - &VerifyGetHostNameResponse, - &VerifyGetPinHashResponse, - &VerifyGenerateKeyPairResponse, - &VerifyGetDaemonConfigResponse, - &VerifyGetUsageStatsConsentResponse, - &VerifyStopDaemonResponse, - &VerifyGetDaemonStateResponse, - &VerifyUpdateDaemonConfigResponse, - &VerifyStartDaemonResponse, + &VerifyHelloResponse, + &VerifyGetHostNameResponse, + &VerifyGetPinHashResponse, + &VerifyGenerateKeyPairResponse, + &VerifyGetDaemonConfigResponse, + &VerifyGetUsageStatsConsentResponse, + &VerifyStopDaemonResponse, + &VerifyGetDaemonStateResponse, + &VerifyUpdateDaemonConfigResponse, + &VerifyStartDaemonResponse, + &VerifyGetCredentialsFromAuthCodeResponse, }; ASSERT_EQ(arraysize(verify_routines), static_cast<size_t>(next_id)); @@ -585,4 +608,11 @@ TestBadRequest(message); } +// Verify rejection if getCredentialsFromAuthCode has no auth code. +TEST_F(Me2MeNativeMessagingHostTest, GetCredentialsFromAuthCodeNoAuthCode) { + base::DictionaryValue message; + message.SetString("type", "getCredentialsFromAuthCode"); + TestBadRequest(message); +} + } // namespace remoting
diff --git a/remoting/host/setup/mock_oauth_client.cc b/remoting/host/setup/mock_oauth_client.cc new file mode 100644 index 0000000..bd78aa64 --- /dev/null +++ b/remoting/host/setup/mock_oauth_client.cc
@@ -0,0 +1,25 @@ +// 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 "remoting/host/setup/mock_oauth_client.h" + +namespace remoting { + +MockOAuthClient::MockOAuthClient(const std::string& user_email, + const std::string& refresh_token) + : user_email_(user_email), refresh_token_(refresh_token) { +} + +MockOAuthClient::~MockOAuthClient() { +} + +void MockOAuthClient::GetCredentialsFromAuthCode( + const gaia::OAuthClientInfo& oauth_client_info, + const std::string& auth_code, + bool need_user_email, + CompletionCallback on_done) { + on_done.Run(need_user_email ? user_email_ : "", refresh_token_); +} + +} // namespace remoting
diff --git a/remoting/host/setup/mock_oauth_client.h b/remoting/host/setup/mock_oauth_client.h new file mode 100644 index 0000000..db235a5 --- /dev/null +++ b/remoting/host/setup/mock_oauth_client.h
@@ -0,0 +1,32 @@ +// 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 REMOTING_HOST_SETUP_MOCK_OAUTH_CLIENT_H_ +#define REMOTING_HOST_SETUP_MOCK_OAUTH_CLIENT_H_ + +#include "remoting/host/setup/oauth_client.h" + +namespace remoting { + +class MockOAuthClient : public OAuthClient { + public: + MockOAuthClient(const std::string& user_email, + const std::string& refresh_token); + + ~MockOAuthClient() override; + + void GetCredentialsFromAuthCode( + const gaia::OAuthClientInfo& oauth_client_info, + const std::string& auth_code, + bool need_user_email, + CompletionCallback on_done) override; + + private: + std::string user_email_; + std::string refresh_token_; +}; + +} // namespace remoting + +#endif // REMOTING_HOST_SETUP_MOCK_OAUTH_CLIENT_H_
diff --git a/remoting/host/setup/oauth_client.cc b/remoting/host/setup/oauth_client.cc deleted file mode 100644 index 684ab2c..0000000 --- a/remoting/host/setup/oauth_client.cc +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright 2013 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 "remoting/host/setup/oauth_client.h" - -#include "base/logging.h" - -namespace { -const int kMaxGaiaRetries = 3; -} // namespace - -namespace remoting { - -OAuthClient::OAuthClient( - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) - : gaia_oauth_client_(url_request_context_getter.get()) { -} - -OAuthClient::~OAuthClient() { -} - -void OAuthClient::GetCredentialsFromAuthCode( - const gaia::OAuthClientInfo& oauth_client_info, - const std::string& auth_code, - CompletionCallback on_done) { - - if (!on_done_.is_null()) { - pending_requests_.push(Request(oauth_client_info, auth_code, on_done)); - return; - } - - on_done_ = on_done; - // Map the authorization code to refresh and access tokens. - gaia_oauth_client_.GetTokensFromAuthCode(oauth_client_info, auth_code, - kMaxGaiaRetries, this); -} - -void OAuthClient::OnGetTokensResponse( - const std::string& refresh_token, - const std::string& access_token, - int expires_in_seconds) { - refresh_token_ = refresh_token; - // Get the email corresponding to the access token. - gaia_oauth_client_.GetUserEmail(access_token, kMaxGaiaRetries, this); -} - -void OAuthClient::OnRefreshTokenResponse( - const std::string& access_token, - int expires_in_seconds) { - // We never request a refresh token, so this call is not expected. - NOTREACHED(); -} - -void OAuthClient::SendResponse(const std::string& user_email, - const std::string& refresh_token) { - CompletionCallback on_done = on_done_; - on_done_.Reset(); - on_done.Run(user_email, refresh_token); - - // Process the next request in the queue. - if (pending_requests_.size()) { - Request request = pending_requests_.front(); - pending_requests_.pop(); - // GetCredentialsFromAuthCode is asynchronous, so it's safe to call it here. - GetCredentialsFromAuthCode( - request.oauth_client_info, request.auth_code, request.on_done); - } -} - -void OAuthClient::OnGetUserEmailResponse(const std::string& user_email) { - SendResponse(user_email, refresh_token_); -} - -void OAuthClient::OnOAuthError() { - SendResponse("", ""); -} - -void OAuthClient::OnNetworkError(int response_code) { - SendResponse("", ""); -} - -OAuthClient::Request::Request( - const gaia::OAuthClientInfo& oauth_client_info, - const std::string& auth_code, - CompletionCallback on_done) { - this->oauth_client_info = oauth_client_info; - this->auth_code = auth_code; - this->on_done = on_done; -} - -OAuthClient::Request::~Request() { -} - -} // namespace remoting
diff --git a/remoting/host/setup/oauth_client.h b/remoting/host/setup/oauth_client.h index 5cc8f1f..8da652be 100644 --- a/remoting/host/setup/oauth_client.h +++ b/remoting/host/setup/oauth_client.h
@@ -2,26 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef REMOTING_HOST_SETUP_OAUTH_CLIENT -#define REMOTING_HOST_SETUP_OAUTH_CLIENT +#ifndef REMOTING_HOST_SETUP_OAUTH_CLIENT_H_ +#define REMOTING_HOST_SETUP_OAUTH_CLIENT_H_ -#include <queue> #include <string> #include "base/callback.h" -#include "base/memory/ref_counted.h" -#include "google_apis/gaia/gaia_oauth_client.h" -#include "net/url_request/url_request_context_getter.h" -namespace net { -class URLRequestContext; +namespace gaia { +struct OAuthClientInfo; } namespace remoting { -// A wrapper around GaiaOAuthClient that provides a more convenient interface, -// with queueing of requests and a callback rather than a delegate. -class OAuthClient : public gaia::GaiaOAuthClient::Delegate { +class OAuthClient { public: // Called when GetCredentialsFromAuthCode is completed, with the |user_email| // and |refresh_token| that correspond to the given |auth_code|, or with empty @@ -30,55 +24,22 @@ const std::string& user_email, const std::string& refresh_token)> CompletionCallback; - OAuthClient( - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter); + virtual ~OAuthClient() {} - ~OAuthClient() override; - - // Redeems |auth_code| using |oauth_client_info| to obtain |refresh_token| and - // |access_token|, then uses the userinfo endpoint to obtain |user_email|. - // Calls CompletionCallback with |user_email| and |refresh_token| when done, - // or with empty strings on error. - // If a request is received while another one is being processed, it is - // enqueued and processed after the first one is finished. - void GetCredentialsFromAuthCode( + // Redeems |auth_code| using |oauth_client_info| to obtain + // |refresh_token| and |access_token|, then, if |need_user_email| is + // true, uses the userinfo endpoint to obtain |user_email|. Calls + // CompletionCallback with |user_email| and |refresh_token| when + // done, or with empty strings on error. If a request is received + // while another one is being processed, it is enqueued and + // processed after the first one is finished. + virtual void GetCredentialsFromAuthCode( const gaia::OAuthClientInfo& oauth_client_info, const std::string& auth_code, - CompletionCallback on_done); - - // gaia::GaiaOAuthClient::Delegate - void OnGetTokensResponse(const std::string& refresh_token, - const std::string& access_token, - int expires_in_seconds) override; - void OnRefreshTokenResponse(const std::string& access_token, - int expires_in_seconds) override; - void OnGetUserEmailResponse(const std::string& user_email) override; - - void OnOAuthError() override; - void OnNetworkError(int response_code) override; - - private: - struct Request { - Request(const gaia::OAuthClientInfo& oauth_client_info, - const std::string& auth_code, - CompletionCallback on_done); - virtual ~Request(); - gaia::OAuthClientInfo oauth_client_info; - std::string auth_code; - CompletionCallback on_done; - }; - - void SendResponse(const std::string& user_email, - const std::string& refresh_token); - - std::queue<Request> pending_requests_; - gaia::GaiaOAuthClient gaia_oauth_client_; - std::string refresh_token_; - CompletionCallback on_done_; - - DISALLOW_COPY_AND_ASSIGN(OAuthClient); + bool need_user_email, + CompletionCallback on_done) = 0; }; } // namespace remoting -#endif // REMOTING_HOST_SETUP_OAUTH_CLIENT +#endif // REMOTING_HOST_SETUP_OAUTH_CLIENT_H_
diff --git a/remoting/host/win/chromoting_module.h b/remoting/host/win/chromoting_module.h index b20184a8..867deee 100644 --- a/remoting/host/win/chromoting_module.h +++ b/remoting/host/win/chromoting_module.h
@@ -36,7 +36,7 @@ // Initializes the module. |classes| and |classes_end| must outlive |this|. ChromotingModule(ATL::_ATL_OBJMAP_ENTRY* classes, ATL::_ATL_OBJMAP_ENTRY* classes_end); - virtual ~ChromotingModule(); + ~ChromotingModule() override; // Returns the task runner used by the module. Returns nullptr if the task // runner hasn't been registered yet or if the server is shutting down. @@ -47,7 +47,7 @@ bool Run(); // ATL::CAtlModuleT<> overrides - virtual LONG Unlock() override; + LONG Unlock() override; DECLARE_LIBID(LIBID_ChromotingLib)
diff --git a/remoting/host/win/host_service.h b/remoting/host/win/host_service.h index 96cfff2..0ab78fee 100644 --- a/remoting/host/win/host_service.h +++ b/remoting/host/win/host_service.h
@@ -37,14 +37,14 @@ int Run(); // WtsTerminalMonitor implementation - virtual bool AddWtsTerminalObserver(const std::string& terminal_id, + bool AddWtsTerminalObserver(const std::string& terminal_id, WtsTerminalObserver* observer) override; - virtual void RemoveWtsTerminalObserver( + void RemoveWtsTerminalObserver( WtsTerminalObserver* observer) override; private: HostService(); - ~HostService(); + ~HostService() override; // Notifies the service of changes in session state. void OnSessionChange(uint32 event, uint32 session_id);
diff --git a/remoting/host/win/rdp_client.cc b/remoting/host/win/rdp_client.cc index f41db10..8f029ef 100644 --- a/remoting/host/win/rdp_client.cc +++ b/remoting/host/win/rdp_client.cc
@@ -56,12 +56,12 @@ void InjectSas(); // RdpClientWindow::EventHandler interface. - virtual void OnConnected() override; - virtual void OnDisconnected() override; + void OnConnected() override; + void OnDisconnected() override; private: friend class base::RefCountedThreadSafe<Core>; - virtual ~Core(); + ~Core() override; // Helpers for the event handler's methods that make sure that OnRdpClosed() // is the last notification delivered and is delevered only once.
diff --git a/remoting/host/win/rdp_client_unittest.cc b/remoting/host/win/rdp_client_unittest.cc index 1b37d5c..2093aeb 100644 --- a/remoting/host/win/rdp_client_unittest.cc +++ b/remoting/host/win/rdp_client_unittest.cc
@@ -79,10 +79,10 @@ class RdpClientTest : public testing::Test { public: RdpClientTest(); - virtual ~RdpClientTest(); + ~RdpClientTest() override; - virtual void SetUp() override; - virtual void TearDown() override; + void SetUp() override; + void TearDown() override; // Caaled when an RDP connection is established. void OnRdpConnected();
diff --git a/remoting/host/win/rdp_desktop_session.h b/remoting/host/win/rdp_desktop_session.h index 9f086928..18a1eb4c 100644 --- a/remoting/host/win/rdp_desktop_session.h +++ b/remoting/host/win/rdp_desktop_session.h
@@ -49,8 +49,8 @@ private: // RdpClient::EventHandler interface. - virtual void OnRdpConnected() override; - virtual void OnRdpClosed() override; + void OnRdpConnected() override; + void OnRdpClosed() override; BEGIN_COM_MAP(RdpDesktopSession) COM_INTERFACE_ENTRY(IRdpDesktopSession)
diff --git a/remoting/host/win/session_desktop_environment.h b/remoting/host/win/session_desktop_environment.h index 949fa5eb..233938f 100644 --- a/remoting/host/win/session_desktop_environment.h +++ b/remoting/host/win/session_desktop_environment.h
@@ -17,10 +17,10 @@ // with Windows sessions. class SessionDesktopEnvironment : public Me2MeDesktopEnvironment { public: - virtual ~SessionDesktopEnvironment(); + ~SessionDesktopEnvironment() override; // DesktopEnvironment implementation. - virtual scoped_ptr<InputInjector> CreateInputInjector() override; + scoped_ptr<InputInjector> CreateInputInjector() override; private: friend class SessionDesktopEnvironmentFactory; @@ -44,10 +44,10 @@ scoped_refptr<base::SingleThreadTaskRunner> input_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, const base::Closure& inject_sas); - virtual ~SessionDesktopEnvironmentFactory(); + ~SessionDesktopEnvironmentFactory() override; // DesktopEnvironmentFactory implementation. - virtual scoped_ptr<DesktopEnvironment> Create( + scoped_ptr<DesktopEnvironment> Create( base::WeakPtr<ClientSessionControl> client_session_control) override; private:
diff --git a/remoting/host/win/session_input_injector.cc b/remoting/host/win/session_input_injector.cc index bf8158ee..60fe8932 100644 --- a/remoting/host/win/session_input_injector.cc +++ b/remoting/host/win/session_input_injector.cc
@@ -56,20 +56,20 @@ const base::Closure& inject_sas); // InputInjector implementation. - virtual void Start(scoped_ptr<ClipboardStub> client_clipboard) override; + void Start(scoped_ptr<ClipboardStub> client_clipboard) override; // protocol::ClipboardStub implementation. - virtual void InjectClipboardEvent(const ClipboardEvent& event) override; + void InjectClipboardEvent(const ClipboardEvent& event) override; // protocol::InputStub implementation. - virtual void InjectKeyEvent(const KeyEvent& event) override; - virtual void InjectTextEvent(const TextEvent& event) override; - virtual void InjectMouseEvent(const MouseEvent& event) override; - virtual void InjectTouchEvent(const TouchEvent& event) override; + void InjectKeyEvent(const KeyEvent& event) override; + void InjectTextEvent(const TextEvent& event) override; + void InjectMouseEvent(const MouseEvent& event) override; + void InjectTouchEvent(const TouchEvent& event) override; private: friend class base::RefCountedThreadSafe<Core>; - virtual ~Core(); + ~Core() override; // Switches to the desktop receiving a user input if different from // the current one.
diff --git a/remoting/host/win/session_input_injector.h b/remoting/host/win/session_input_injector.h index 99ee83d..60a626c 100644 --- a/remoting/host/win/session_input_injector.h +++ b/remoting/host/win/session_input_injector.h
@@ -29,21 +29,21 @@ scoped_ptr<InputInjector> nested_executor, scoped_refptr<base::SingleThreadTaskRunner> inject_sas_task_runner, const base::Closure& inject_sas); - virtual ~SessionInputInjectorWin(); + ~SessionInputInjectorWin() override; // InputInjector implementation. - virtual void Start( + void Start( scoped_ptr<protocol::ClipboardStub> client_clipboard) override; // protocol::ClipboardStub implementation. - virtual void InjectClipboardEvent( + void InjectClipboardEvent( const protocol::ClipboardEvent& event) override; // protocol::InputStub implementation. - virtual void InjectKeyEvent(const protocol::KeyEvent& event) override; - virtual void InjectTextEvent(const protocol::TextEvent& event) override; - virtual void InjectMouseEvent(const protocol::MouseEvent& event) override; - virtual void InjectTouchEvent(const protocol::TouchEvent& event) override; + void InjectKeyEvent(const protocol::KeyEvent& event) override; + void InjectTextEvent(const protocol::TextEvent& event) override; + void InjectMouseEvent(const protocol::MouseEvent& event) override; + void InjectTouchEvent(const protocol::TouchEvent& event) override; private: // The actual implementation resides in SessionInputInjectorWin::Core class.
diff --git a/remoting/host/win/unprivileged_process_delegate.h b/remoting/host/win/unprivileged_process_delegate.h index 74cd8ea..8de011f 100644 --- a/remoting/host/win/unprivileged_process_delegate.h +++ b/remoting/host/win/unprivileged_process_delegate.h
@@ -37,19 +37,19 @@ UnprivilegedProcessDelegate( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, scoped_ptr<base::CommandLine> target_command); - virtual ~UnprivilegedProcessDelegate(); + ~UnprivilegedProcessDelegate() override; // WorkerProcessLauncher::Delegate implementation. - virtual void LaunchProcess(WorkerProcessLauncher* event_handler) override; - virtual void Send(IPC::Message* message) override; - virtual void CloseChannel() override; - virtual void KillProcess() override; + void LaunchProcess(WorkerProcessLauncher* event_handler) override; + void Send(IPC::Message* message) override; + void CloseChannel() override; + void KillProcess() override; private: // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void OnChannelConnected(int32 peer_pid) override; - virtual void OnChannelError() override; + bool OnMessageReceived(const IPC::Message& message) override; + void OnChannelConnected(int32 peer_pid) override; + void OnChannelError() override; void ReportFatalError(); void ReportProcessLaunched(base::win::ScopedHandle worker_process);
diff --git a/remoting/host/win/worker_process_launcher.h b/remoting/host/win/worker_process_launcher.h index d48b9dc..f512a2b 100644 --- a/remoting/host/win/worker_process_launcher.h +++ b/remoting/host/win/worker_process_launcher.h
@@ -66,7 +66,7 @@ // |ipc_handler| must outlive this object. WorkerProcessLauncher(scoped_ptr<Delegate> launcher_delegate, WorkerProcessIpcDelegate* ipc_handler); - virtual ~WorkerProcessLauncher(); + ~WorkerProcessLauncher() override; // Asks the worker process to crash and generate a dump, and closes the IPC // channel. |location| is passed to the worker so that it is on the stack in @@ -102,7 +102,7 @@ // base::win::ObjectWatcher::Delegate implementation used to watch for // the worker process exiting. - virtual void OnObjectSignaled(HANDLE object) override; + void OnObjectSignaled(HANDLE object) override; // Returns true when the object is being destroyed. bool stopping() const { return ipc_handler_ == nullptr; }
diff --git a/remoting/host/win/worker_process_launcher_unittest.cc b/remoting/host/win/worker_process_launcher_unittest.cc index aa6f095..9ace9a5 100644 --- a/remoting/host/win/worker_process_launcher_unittest.cc +++ b/remoting/host/win/worker_process_launcher_unittest.cc
@@ -42,7 +42,7 @@ class MockProcessLauncherDelegate : public WorkerProcessLauncher::Delegate { public: MockProcessLauncherDelegate() {} - virtual ~MockProcessLauncherDelegate() {} + ~MockProcessLauncherDelegate() override {} // WorkerProcessLauncher::Delegate interface. MOCK_METHOD1(LaunchProcess, void(WorkerProcessLauncher*)); @@ -57,7 +57,7 @@ class MockIpcDelegate : public WorkerProcessIpcDelegate { public: MockIpcDelegate() {} - virtual ~MockIpcDelegate() {} + ~MockIpcDelegate() override {} // WorkerProcessIpcDelegate interface. MOCK_METHOD1(OnChannelConnected, void(int32)); @@ -71,12 +71,12 @@ class MockWorkerListener : public IPC::Listener { public: MockWorkerListener() {} - virtual ~MockWorkerListener() {} + ~MockWorkerListener() override {} MOCK_METHOD3(OnCrash, void(const std::string&, const std::string&, int)); // IPC::Listener implementation - virtual bool OnMessageReceived(const IPC::Message& message) override; + bool OnMessageReceived(const IPC::Message& message) override; private: DISALLOW_COPY_AND_ASSIGN(MockWorkerListener); @@ -101,15 +101,15 @@ public IPC::Listener { public: WorkerProcessLauncherTest(); - virtual ~WorkerProcessLauncherTest(); + ~WorkerProcessLauncherTest() override; - virtual void SetUp() override; - virtual void TearDown() override; + void SetUp() override; + void TearDown() override; // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void OnChannelConnected(int32 peer_pid) override; - virtual void OnChannelError() override; + bool OnMessageReceived(const IPC::Message& message) override; + void OnChannelConnected(int32 peer_pid) override; + void OnChannelError() override; // WorkerProcessLauncher::Delegate mocks void LaunchProcess(
diff --git a/remoting/host/win/wts_session_process_delegate.cc b/remoting/host/win/wts_session_process_delegate.cc index 66d7f0c02..8130599 100644 --- a/remoting/host/win/wts_session_process_delegate.cc +++ b/remoting/host/win/wts_session_process_delegate.cc
@@ -63,17 +63,17 @@ private: friend class base::RefCountedThreadSafe<Core>; - virtual ~Core(); + ~Core() override; // base::MessagePumpForIO::IOHandler implementation. - virtual void OnIOCompleted(base::MessagePumpForIO::IOContext* context, - DWORD bytes_transferred, - DWORD error) override; + void OnIOCompleted(base::MessagePumpForIO::IOContext* context, + DWORD bytes_transferred, + DWORD error) override; // IPC::Listener implementation. - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void OnChannelConnected(int32 peer_pid) override; - virtual void OnChannelError() override; + bool OnMessageReceived(const IPC::Message& message) override; + void OnChannelConnected(int32 peer_pid) override; + void OnChannelError() override; // The actual implementation of LaunchProcess() void DoLaunchProcess();
diff --git a/remoting/host/win/wts_session_process_delegate.h b/remoting/host/win/wts_session_process_delegate.h index 625c8462..e99db67 100644 --- a/remoting/host/win/wts_session_process_delegate.h +++ b/remoting/host/win/wts_session_process_delegate.h
@@ -34,16 +34,16 @@ scoped_ptr<base::CommandLine> target, bool launch_elevated, const std::string& channel_security); - ~WtsSessionProcessDelegate(); + ~WtsSessionProcessDelegate() override; // Initializes the object returning true on success. bool Initialize(uint32 session_id); // WorkerProcessLauncher::Delegate implementation. - virtual void LaunchProcess(WorkerProcessLauncher* event_handler) override; - virtual void Send(IPC::Message* message) override; - virtual void CloseChannel() override; - virtual void KillProcess() override; + void LaunchProcess(WorkerProcessLauncher* event_handler) override; + void Send(IPC::Message* message) override; + void CloseChannel() override; + void KillProcess() override; private: // The actual implementation resides in WtsSessionProcessDelegate::Core class.
diff --git a/remoting/protocol/content_description.cc b/remoting/protocol/content_description.cc index 5d8aaac..a48c57b 100644 --- a/remoting/protocol/content_description.cc +++ b/remoting/protocol/content_description.cc
@@ -25,6 +25,7 @@ // Following constants are used to format session description in XML. const char kDescriptionTag[] = "description"; +const char kStandardIceTag[] = "standard-ice"; const char kControlTag[] = "control"; const char kEventTag[] = "event"; const char kVideoTag[] = "video"; @@ -121,17 +122,10 @@ ContentDescription::~ContentDescription() { } -ContentDescription* ContentDescription::Copy() const { - if (!candidate_config_.get() || !authenticator_message_.get()) { - return nullptr; - } - scoped_ptr<XmlElement> message(new XmlElement(*authenticator_message_)); - return new ContentDescription(candidate_config_->Clone(), message.Pass()); -} - // ToXml() creates content description for chromoting session. The // description looks as follows: // <description xmlns="google:remoting"> +// <standard-ice/> // <control transport="stream" version="1" /> // <event transport="datagram" version="1" /> // <video transport="stream" codec="vp8" version="1" /> @@ -145,27 +139,25 @@ XmlElement* root = new XmlElement( QName(kChromotingXmlNamespace, kDescriptionTag), true); - std::list<ChannelConfig>::const_iterator it; - - for (it = config()->control_configs().begin(); - it != config()->control_configs().end(); ++it) { - root->AddElement(FormatChannelConfig(*it, kControlTag)); + if (config()->standard_ice()) { + root->AddElement( + new buzz::XmlElement(QName(kChromotingXmlNamespace, kStandardIceTag))); } - for (it = config()->event_configs().begin(); - it != config()->event_configs().end(); ++it) { - root->AddElement(FormatChannelConfig(*it, kEventTag)); + for (const ChannelConfig& channel_config : config()->control_configs()) { + root->AddElement(FormatChannelConfig(channel_config, kControlTag)); } - for (it = config()->video_configs().begin(); - it != config()->video_configs().end(); ++it) { - root->AddElement(FormatChannelConfig(*it, kVideoTag)); + for (const ChannelConfig& channel_config : config()->event_configs()) { + root->AddElement(FormatChannelConfig(channel_config, kEventTag)); } - for (it = config()->audio_configs().begin(); - it != config()->audio_configs().end(); ++it) { - ChannelConfig config = *it; - root->AddElement(FormatChannelConfig(config, kAudioTag)); + for (const ChannelConfig& channel_config : config()->video_configs()) { + root->AddElement(FormatChannelConfig(channel_config, kVideoTag)); + } + + for (const ChannelConfig& channel_config : config()->audio_configs()) { + root->AddElement(FormatChannelConfig(channel_config, kAudioTag)); } // Older endpoints require an initial-resolution tag, but otherwise ignore it. @@ -192,7 +184,6 @@ bool codec_required, bool optional, std::list<ChannelConfig>* const configs) { - QName tag(kChromotingXmlNamespace, tag_name); const XmlElement* child = element->FirstNamed(tag); while (child) { @@ -218,6 +209,11 @@ } scoped_ptr<CandidateSessionConfig> config( CandidateSessionConfig::CreateEmpty()); + + config->set_standard_ice( + element->FirstNamed(QName(kChromotingXmlNamespace, kStandardIceTag)) != + nullptr); + if (!ParseChannelConfigs(element, kControlTag, false, false, config->mutable_control_configs()) || !ParseChannelConfigs(element, kEventTag, false, false,
diff --git a/remoting/protocol/content_description.h b/remoting/protocol/content_description.h index 748b0f9..f12582f 100644 --- a/remoting/protocol/content_description.h +++ b/remoting/protocol/content_description.h
@@ -10,7 +10,6 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "remoting/protocol/session_config.h" -#include "third_party/webrtc/p2p/base/sessiondescription.h" namespace buzz { class XmlElement; @@ -24,15 +23,13 @@ // // This class also provides a type abstraction so that the Chromotocol Session // interface does not need to depend on libjingle. -class ContentDescription : public cricket::ContentDescription { +class ContentDescription { public: static const char kChromotingContentName[]; ContentDescription(scoped_ptr<CandidateSessionConfig> config, scoped_ptr<buzz::XmlElement> authenticator_message); - ~ContentDescription() override; - - ContentDescription* Copy() const override; + ~ContentDescription(); const CandidateSessionConfig* config() const { return candidate_config_.get();
diff --git a/remoting/protocol/fake_authenticator.cc b/remoting/protocol/fake_authenticator.cc index c816cfa0..d597568 100644 --- a/remoting/protocol/fake_authenticator.cc +++ b/remoting/protocol/fake_authenticator.cc
@@ -4,6 +4,7 @@ #include "remoting/protocol/fake_authenticator.h" +#include "base/callback_helpers.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" #include "net/base/io_buffer.h" @@ -82,11 +83,9 @@ } void FakeChannelAuthenticator::CallDoneCallback() { - DoneCallback callback = done_callback_; - done_callback_.Reset(); if (result_ != net::OK) socket_.reset(); - callback.Run(result_, socket_.Pass()); + base::ResetAndReturn(&done_callback_).Run(result_, socket_.Pass()); } FakeAuthenticator::FakeAuthenticator(
diff --git a/remoting/protocol/fake_connection_to_host.cc b/remoting/protocol/fake_connection_to_host.cc index 025f720..6567d92 100644 --- a/remoting/protocol/fake_connection_to_host.cc +++ b/remoting/protocol/fake_connection_to_host.cc
@@ -85,7 +85,7 @@ } const protocol::SessionConfig& FakeConnectionToHost::config() { - return session_config_; + return *session_config_; } protocol::ClipboardStub* FakeConnectionToHost::clipboard_forwarder() {
diff --git a/remoting/protocol/fake_connection_to_host.h b/remoting/protocol/fake_connection_to_host.h index 8220a96..1c3fe40 100644 --- a/remoting/protocol/fake_connection_to_host.h +++ b/remoting/protocol/fake_connection_to_host.h
@@ -54,7 +54,7 @@ testing::NiceMock<protocol::MockClipboardStub> mock_clipboard_stub_; testing::NiceMock<protocol::MockHostStub> mock_host_stub_; testing::NiceMock<protocol::MockInputStub> mock_input_stub_; - protocol::SessionConfig session_config_; + scoped_ptr<protocol::SessionConfig> session_config_; DISALLOW_COPY_AND_ASSIGN(FakeConnectionToHost); };
diff --git a/remoting/protocol/fake_datagram_socket.cc b/remoting/protocol/fake_datagram_socket.cc index 75a50b3..9bd4ede 100644 --- a/remoting/protocol/fake_datagram_socket.cc +++ b/remoting/protocol/fake_datagram_socket.cc
@@ -5,6 +5,7 @@ #include "remoting/protocol/fake_datagram_socket.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "net/base/address_list.h" @@ -36,9 +37,7 @@ int result = CopyReadData(read_buffer_.get(), read_buffer_size_); read_buffer_ = nullptr; - net::CompletionCallback callback = read_callback_; - read_callback_.Reset(); - callback.Run(result); + base::ResetAndReturn(&read_callback_).Run(result); } }
diff --git a/remoting/protocol/fake_session.cc b/remoting/protocol/fake_session.cc index ba6a5a97..68a78ca7 100644 --- a/remoting/protocol/fake_session.cc +++ b/remoting/protocol/fake_session.cc
@@ -36,11 +36,11 @@ } const SessionConfig& FakeSession::config() { - return config_; + return *config_; } -void FakeSession::set_config(const SessionConfig& config) { - config_ = config; +void FakeSession::set_config(scoped_ptr<SessionConfig> config) { + config_ = config.Pass(); } StreamChannelFactory* FakeSession::GetTransportChannelFactory() {
diff --git a/remoting/protocol/fake_session.h b/remoting/protocol/fake_session.h index 2e5d5ce..e8ea472 100644 --- a/remoting/protocol/fake_session.h +++ b/remoting/protocol/fake_session.h
@@ -39,7 +39,7 @@ const std::string& jid() override; const CandidateSessionConfig* candidate_config() override; const SessionConfig& config() override; - void set_config(const SessionConfig& config) override; + void set_config(scoped_ptr<SessionConfig> config) override; StreamChannelFactory* GetTransportChannelFactory() override; StreamChannelFactory* GetMultiplexedChannelFactory() override; void Close() override; @@ -47,7 +47,7 @@ public: EventHandler* event_handler_; scoped_ptr<const CandidateSessionConfig> candidate_config_; - SessionConfig config_; + scoped_ptr<SessionConfig> config_; FakeStreamChannelFactory channel_factory_;
diff --git a/remoting/protocol/fake_stream_socket.cc b/remoting/protocol/fake_stream_socket.cc index 678b9f5c..7e1519a 100644 --- a/remoting/protocol/fake_stream_socket.cc +++ b/remoting/protocol/fake_stream_socket.cc
@@ -5,6 +5,7 @@ #include "remoting/protocol/fake_stream_socket.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "net/base/address_list.h" @@ -45,9 +46,17 @@ input_pos_ += result; read_buffer_ = nullptr; - net::CompletionCallback callback = read_callback_; - read_callback_.Reset(); - callback.Run(result); + base::ResetAndReturn(&read_callback_).Run(result); + } +} + +void FakeStreamSocket::AppendReadError(int error) { + EXPECT_TRUE(task_runner_->BelongsToCurrentThread()); + // Complete pending read if any. + if (!read_callback_.is_null()) { + base::ResetAndReturn(&read_callback_).Run(error); + } else { + next_read_error_ = error; } } @@ -65,18 +74,16 @@ const net::CompletionCallback& callback) { EXPECT_TRUE(task_runner_->BelongsToCurrentThread()); - if (next_read_error_ != net::OK) { - int r = next_read_error_; - next_read_error_ = net::OK; - return r; - } - if (input_pos_ < static_cast<int>(input_data_.size())) { int result = std::min(buf_len, static_cast<int>(input_data_.size()) - input_pos_); memcpy(buf->data(), &(*input_data_.begin()) + input_pos_, result); input_pos_ += result; return result; + } else if (next_read_error_ != net::OK) { + int r = next_read_error_; + next_read_error_ = net::OK; + return r; } else { read_buffer_ = buf; read_buffer_size_ = buf_len; @@ -159,6 +166,14 @@ void FakeStreamSocket::Disconnect() { EXPECT_TRUE(task_runner_->BelongsToCurrentThread()); + + if (peer_socket_.get()) { + task_runner_->PostTask( + FROM_HERE, + base::Bind(&FakeStreamSocket::AppendReadError, + peer_socket_, + net::ERR_CONNECTION_CLOSED)); + } peer_socket_.reset(); }
diff --git a/remoting/protocol/fake_stream_socket.h b/remoting/protocol/fake_stream_socket.h index cb17e892..ac20e38 100644 --- a/remoting/protocol/fake_stream_socket.h +++ b/remoting/protocol/fake_stream_socket.h
@@ -45,14 +45,17 @@ // Enables asynchronous Write(). void set_async_write(bool async_write) { async_write_ = async_write; } - // Set error codes for the next Read() and Write() calls. Once returned the - // values are automatically reset to net::OK . - void set_next_read_error(int error) { next_read_error_ = error; } + // Set error codes for the next Write() call. Once returned the + // value is automatically reset to net::OK . void set_next_write_error(int error) { next_write_error_ = error; } // Appends |data| to the read buffer. void AppendInputData(const std::string& data); + // Causes Read() to fail with |error| once the read buffer is exhausted. If + // there is a currently pending Read, it is interrupted. + void AppendReadError(int error); + // Pairs the socket with |peer_socket|. Deleting either of the paired sockets // unpairs them. void PairWith(FakeStreamSocket* peer_socket);
diff --git a/remoting/protocol/jingle_messages.cc b/remoting/protocol/jingle_messages.cc index c2c9b80..7e4c21ee 100644 --- a/remoting/protocol/jingle_messages.cc +++ b/remoting/protocol/jingle_messages.cc
@@ -17,11 +17,16 @@ namespace remoting { namespace protocol { +namespace { + const char kJabberNamespace[] = "jabber:client"; const char kJingleNamespace[] = "urn:xmpp:jingle:1"; -const char kP2PTransportNamespace[] = "http://www.google.com/transport/p2p"; -namespace { +// Namespace for transport messages for legacy GICE. +const char kGiceTransportNamespace[] = "http://www.google.com/transport/p2p"; + +// Namespace for transport messages when using standard ICE. +const char kIceTransportNamespace[] = "google:remoting:ice"; const char kEmptyNamespace[] = ""; const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace"; @@ -45,9 +50,101 @@ { JingleMessage::INCOMPATIBLE_PARAMETERS, "incompatible-parameters" }, }; -bool ParseCandidate(const buzz::XmlElement* element, - JingleMessage::NamedCandidate* candidate) { - DCHECK(element->Name() == QName(kP2PTransportNamespace, "candidate")); +bool ParseIceCredentials(const buzz::XmlElement* element, + JingleMessage::IceCredentials* credentials) { + DCHECK(element->Name() == QName(kIceTransportNamespace, "credentials")); + + const std::string& channel = element->Attr(QName(kEmptyNamespace, "channel")); + const std::string& ufrag = + element->Attr(QName(kEmptyNamespace, "ufrag")); + const std::string& password = + element->Attr(QName(kEmptyNamespace, "password")); + + if (channel.empty() || ufrag.empty() || password.empty()) { + return false; + } + + credentials->channel = channel; + credentials->ufrag = ufrag; + credentials->password = password; + + return true; +} + +bool ParseIceCandidate(const buzz::XmlElement* element, + JingleMessage::NamedCandidate* candidate) { + DCHECK(element->Name() == QName(kIceTransportNamespace, "candidate")); + + const std::string& name = element->Attr(QName(kEmptyNamespace, "name")); + const std::string& foundation = + element->Attr(QName(kEmptyNamespace, "foundation")); + const std::string& address = element->Attr(QName(kEmptyNamespace, "address")); + const std::string& port_str = element->Attr(QName(kEmptyNamespace, "port")); + const std::string& type = element->Attr(QName(kEmptyNamespace, "type")); + const std::string& protocol = + element->Attr(QName(kEmptyNamespace, "protocol")); + const std::string& priority_str = + element->Attr(QName(kEmptyNamespace, "priority")); + const std::string& generation_str = + element->Attr(QName(kEmptyNamespace, "generation")); + + int port; + unsigned priority; + int generation; + if (name.empty() || foundation.empty() || address.empty() || + !base::StringToInt(port_str, &port) || port < kPortMin || + port > kPortMax || type.empty() || protocol.empty() || + !base::StringToUint(priority_str, &priority) || + !base::StringToInt(generation_str, &generation)) { + return false; + } + + candidate->name = name; + + candidate->candidate.set_foundation(foundation); + candidate->candidate.set_address(rtc::SocketAddress(address, port)); + candidate->candidate.set_type(type); + candidate->candidate.set_protocol(protocol); + candidate->candidate.set_priority(priority); + candidate->candidate.set_generation(generation); + + return true; +} + +bool ParseIceTransportInfo( + const buzz::XmlElement* element, + std::list<JingleMessage::IceCredentials>* ice_credentials, + std::list<JingleMessage::NamedCandidate>* candidates) { + DCHECK(element->Name() == QName(kIceTransportNamespace, "transport")); + + ice_credentials->clear(); + candidates->clear(); + + QName qn_credentials(kIceTransportNamespace, "credentials"); + for (const XmlElement* credentials_tag = element->FirstNamed(qn_credentials); + credentials_tag; + credentials_tag = credentials_tag->NextNamed(qn_credentials)) { + JingleMessage::IceCredentials credentials; + if (!ParseIceCredentials(credentials_tag, &credentials)) + return false; + ice_credentials->push_back(credentials); + } + + QName qn_candidate(kIceTransportNamespace, "candidate"); + for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate); + candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) { + JingleMessage::NamedCandidate candidate; + if (!ParseIceCandidate(candidate_tag, &candidate)) + return false; + candidates->push_back(candidate); + } + + return true; +} + +bool ParseGiceCandidate(const buzz::XmlElement* element, + JingleMessage::NamedCandidate* candidate) { + DCHECK(element->Name() == QName(kGiceTransportNamespace, "candidate")); const std::string& name = element->Attr(QName(kEmptyNamespace, "name")); const std::string& address = element->Attr(QName(kEmptyNamespace, "address")); @@ -88,9 +185,59 @@ return true; } -XmlElement* FormatCandidate(const JingleMessage::NamedCandidate& candidate) { +bool ParseGiceTransportInfo( + const buzz::XmlElement* element, + std::list<JingleMessage::NamedCandidate>* candidates) { + DCHECK(element->Name() == QName(kGiceTransportNamespace, "transport")); + + candidates->clear(); + + QName qn_candidate(kGiceTransportNamespace, "candidate"); + for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate); + candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) { + JingleMessage::NamedCandidate candidate; + if (!ParseGiceCandidate(candidate_tag, &candidate)) + return false; + candidates->push_back(candidate); + } + + return true; +} + +XmlElement* FormatIceCredentials( + const JingleMessage::IceCredentials& credentials) { XmlElement* result = - new XmlElement(QName(kP2PTransportNamespace, "candidate")); + new XmlElement(QName(kIceTransportNamespace, "credentials")); + result->SetAttr(QName(kEmptyNamespace, "channel"), credentials.channel); + result->SetAttr(QName(kEmptyNamespace, "ufrag"), credentials.ufrag); + result->SetAttr(QName(kEmptyNamespace, "password"), credentials.password); + return result; +} + +XmlElement* FormatIceCandidate(const JingleMessage::NamedCandidate& candidate) { + XmlElement* result = + new XmlElement(QName(kIceTransportNamespace, "candidate")); + result->SetAttr(QName(kEmptyNamespace, "name"), candidate.name); + result->SetAttr(QName(kEmptyNamespace, "foundation"), + candidate.candidate.foundation()); + result->SetAttr(QName(kEmptyNamespace, "address"), + candidate.candidate.address().ipaddr().ToString()); + result->SetAttr(QName(kEmptyNamespace, "port"), + base::IntToString(candidate.candidate.address().port())); + result->SetAttr(QName(kEmptyNamespace, "type"), candidate.candidate.type()); + result->SetAttr(QName(kEmptyNamespace, "protocol"), + candidate.candidate.protocol()); + result->SetAttr(QName(kEmptyNamespace, "priority"), + base::DoubleToString(candidate.candidate.priority())); + result->SetAttr(QName(kEmptyNamespace, "generation"), + base::IntToString(candidate.candidate.generation())); + return result; +} + +XmlElement* FormatGiceCandidate( + const JingleMessage::NamedCandidate& candidate) { + XmlElement* result = + new XmlElement(QName(kGiceTransportNamespace, "candidate")); result->SetAttr(QName(kEmptyNamespace, "name"), candidate.name); result->SetAttr(QName(kEmptyNamespace, "address"), candidate.candidate.address().ipaddr().ToString()); @@ -112,9 +259,6 @@ } // namespace -JingleMessage::NamedCandidate::NamedCandidate() { -} - JingleMessage::NamedCandidate::NamedCandidate( const std::string& name, const cricket::Candidate& candidate) @@ -122,6 +266,12 @@ candidate(candidate) { } +JingleMessage::IceCredentials::IceCredentials(std::string channel, + std::string ufrag, + std::string password) + : channel(channel), ufrag(ufrag), password(password) { +} + // static bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) { return stanza->Name() == QName(kJabberNamespace, "iq") && @@ -134,19 +284,13 @@ return ValueToName(kActionTypes, action); } -JingleMessage::JingleMessage() - : action(UNKNOWN_ACTION), - reason(UNKNOWN_REASON) { +JingleMessage::JingleMessage() { } -JingleMessage::JingleMessage( - const std::string& to_value, - ActionType action_value, - const std::string& sid_value) - : to(to_value), - action(action_value), - sid(sid_value), - reason(UNKNOWN_REASON) { +JingleMessage::JingleMessage(const std::string& to, + ActionType action, + const std::string& sid) + : to(to), action(action), sid(sid) { } JingleMessage::~JingleMessage() { @@ -240,21 +384,26 @@ } } - candidates.clear(); - const XmlElement* transport_tag = content_tag->FirstNamed( - QName(kP2PTransportNamespace, "transport")); - if (transport_tag) { - QName qn_candidate(kP2PTransportNamespace, "candidate"); - for (const XmlElement* candidate_tag = - transport_tag->FirstNamed(qn_candidate); - candidate_tag != nullptr; - candidate_tag = candidate_tag->NextNamed(qn_candidate)) { - NamedCandidate candidate; - if (!ParseCandidate(candidate_tag, &candidate)) { - *error = "Failed to parse candidates"; - return false; - } - candidates.push_back(candidate); + const XmlElement* ice_transport_tag = content_tag->FirstNamed( + QName(kIceTransportNamespace, "transport")); + const XmlElement* gice_transport_tag = content_tag->FirstNamed( + QName(kGiceTransportNamespace, "transport")); + if (ice_transport_tag && gice_transport_tag) { + *error = "ICE and GICE transport information is found in the same message"; + return false; + } else if (ice_transport_tag) { + standard_ice = true; + if (!ParseIceTransportInfo(ice_transport_tag, &ice_credentials, + &candidates)) { + *error = "Failed to parse transport info"; + return false; + } + } else if (gice_transport_tag) { + standard_ice = false; + ice_credentials.clear(); + if (!ParseGiceTransportInfo(gice_transport_tag, &candidates)) { + *error = "Failed to parse transport info"; + return false; } } @@ -313,12 +462,27 @@ if (description.get()) content_tag->AddElement(description->ToXml()); - XmlElement* transport_tag = - new XmlElement(QName(kP2PTransportNamespace, "transport"), true); - content_tag->AddElement(transport_tag); - for (std::list<NamedCandidate>::const_iterator it = candidates.begin(); - it != candidates.end(); ++it) { - transport_tag->AddElement(FormatCandidate(*it)); + if (standard_ice) { + XmlElement* transport_tag = + new XmlElement(QName(kIceTransportNamespace, "transport"), true); + content_tag->AddElement(transport_tag); + for (std::list<IceCredentials>::const_iterator it = + ice_credentials.begin(); + it != ice_credentials.end(); ++it) { + transport_tag->AddElement(FormatIceCredentials(*it)); + } + for (std::list<NamedCandidate>::const_iterator it = candidates.begin(); + it != candidates.end(); ++it) { + transport_tag->AddElement(FormatIceCandidate(*it)); + } + } else { + XmlElement* transport_tag = + new XmlElement(QName(kGiceTransportNamespace, "transport"), true); + content_tag->AddElement(transport_tag); + for (std::list<NamedCandidate>::const_iterator it = candidates.begin(); + it != candidates.end(); ++it) { + transport_tag->AddElement(FormatGiceCandidate(*it)); + } } }
diff --git a/remoting/protocol/jingle_messages.h b/remoting/protocol/jingle_messages.h index e12c854..c83776ad 100644 --- a/remoting/protocol/jingle_messages.h +++ b/remoting/protocol/jingle_messages.h
@@ -12,16 +12,11 @@ #include "third_party/webrtc/libjingle/xmllite/xmlelement.h" #include "third_party/webrtc/p2p/base/candidate.h" - namespace remoting { namespace protocol { class ContentDescription; -extern const char kJabberNamespace[]; -extern const char kJingleNamespace[]; -extern const char kP2PTransportNamespace[]; - struct JingleMessage { enum ActionType { UNKNOWN_ACTION, @@ -42,7 +37,7 @@ }; struct NamedCandidate { - NamedCandidate(); + NamedCandidate() = default; NamedCandidate(const std::string& name, const cricket::Candidate& candidate); @@ -50,6 +45,17 @@ cricket::Candidate candidate; }; + struct IceCredentials { + IceCredentials() = default; + IceCredentials(std::string channel, + std::string ufrag, + std::string password); + + std::string channel; + std::string ufrag; + std::string password; + }; + JingleMessage(); JingleMessage(const std::string& to_value, ActionType action_value, @@ -68,12 +74,15 @@ std::string from; std::string to; - ActionType action; + ActionType action = UNKNOWN_ACTION; std::string sid; std::string initiator; scoped_ptr<ContentDescription> description; + + bool standard_ice = true; + std::list<IceCredentials> ice_credentials; std::list<NamedCandidate> candidates; // Content of session-info messages. @@ -82,7 +91,7 @@ // Value from the <reason> tag if it is present in the // message. Useful mainly for session-terminate messages, but Jingle // spec allows it in any message. - Reason reason; + Reason reason = UNKNOWN_REASON; }; struct JingleMessageReply {
diff --git a/remoting/protocol/jingle_messages_unittest.cc b/remoting/protocol/jingle_messages_unittest.cc index de58443..aa95d07 100644 --- a/remoting/protocol/jingle_messages_unittest.cc +++ b/remoting/protocol/jingle_messages_unittest.cc
@@ -105,6 +105,7 @@ "initiator='user@gmail.com/chromiumsy5C6A652D'>" "<content name='chromoting' creator='initiator'>" "<description xmlns='google:remoting'>" + "<standard-ice/>" "<control transport='stream' version='2'/>" "<event transport='stream' version='2'/>" "<video transport='stream' version='2' codec='vp8'/>" @@ -145,6 +146,7 @@ "xmlns='urn:xmpp:jingle:1'>i" "<content creator='initiator' name='chromoting'>" "<description xmlns='google:remoting'>" + "<standard-ice/>" "<control transport='stream' version='2'/>" "<event transport='stream' version='2'/>" "<video codec='vp8' transport='stream' version='2'/>" @@ -177,23 +179,112 @@ << error; } -TEST(JingleMessageTest, TransportInfo) { - const char* kTestTransportInfoMessage = - "<cli:iq to='user@gmail.com/chromoting016DBB07' type='set' " - "xmlns:cli='jabber:client'><jingle xmlns='urn:xmpp:jingle:1' " - "action='transport-info' sid='2227053353'><content name='chromoting' " - "creator='initiator'><transport " - "xmlns='http://www.google.com/transport/p2p'><candidate name='event' " - "address='172.23.164.186' port='57040' preference='1' " - "username='tPUyEAmQrEw3y7hi' protocol='udp' generation='0' " - "password='2iRdhLfawKZC5ydJ' type='local'/><candidate name='video' " - "address='172.23.164.186' port='42171' preference='1' " - "username='EPK3CXo5sTLJSez0' protocol='udp' generation='0' " - "password='eM0VUfUkZ+1Pyi0M' type='local'/></transport></content>" - "</jingle></cli:iq>"; +TEST(JingleMessageTest, SessionAcceptNoIce) { + const char* kTestSessionAcceptMessage = + "<cli:iq from='user@gmail.com/chromoting016DBB07' " + "to='user@gmail.com/chromiumsy5C6A652D' type='set' " + "xmlns:cli='jabber:client'>" + "<jingle action='session-accept' sid='2227053353' " + "xmlns='urn:xmpp:jingle:1'>i" + "<content creator='initiator' name='chromoting'>" + "<description xmlns='google:remoting'>" + "<control transport='stream' version='2'/>" + "<event transport='stream' version='2'/>" + "<video codec='vp8' transport='stream' version='2'/>" + "<audio transport='stream' version='2' codec='verbatim'/>" + "<initial-resolution height='480' width='640'/>" + "<authentication><certificate>" + "MIICpjCCAY6gW0Cert0TANBgkqhkiG9w0BAQUFA=" + "</certificate></authentication>" + "</description>" + "<transport xmlns='http://www.google.com/transport/p2p'/>" + "</content>" + "</jingle>" + "</cli:iq>"; scoped_ptr<XmlElement> source_message( - XmlElement::ForStr(kTestTransportInfoMessage)); + XmlElement::ForStr(kTestSessionAcceptMessage)); + ASSERT_TRUE(source_message.get()); + + EXPECT_TRUE(JingleMessage::IsJingleMessage(source_message.get())); + + JingleMessage message; + std::string error; + EXPECT_TRUE(message.ParseXml(source_message.get(), &error)) << error; + + EXPECT_EQ(message.action, JingleMessage::SESSION_ACCEPT); + + scoped_ptr<XmlElement> formatted_message(message.ToXml()); + ASSERT_TRUE(formatted_message.get()); + EXPECT_TRUE(VerifyXml(source_message.get(), formatted_message.get(), &error)) + << error; +} + +TEST(JingleMessageTest, IceTransportInfo) { + const char* kTestIceTransportInfoMessage = + "<cli:iq to='user@gmail.com/chromoting016DBB07' type='set' " + "xmlns:cli='jabber:client'>" + "<jingle xmlns='urn:xmpp:jingle:1' action='transport-info' " + "sid='2227053353'>" + "<content name='chromoting' creator='initiator'>" + "<transport xmlns='google:remoting:ice'>" + "<credentials channel='event' ufrag='tPUyEAmQrEw3y7hi' " + "password='2iRdhLfawKZC5ydJ'/>" + "<credentials channel='video' ufrag='EPK3CXo5sTLJSez0' " + "password='eM0VUfUkZ+1Pyi0M'/>" + "<candidate name='event' foundation='725747215' " + "address='172.23.164.186' port='59089' type='local' " + "protocol='udp' priority='2122194688' generation='0'/>" + "<candidate name='video' foundation='3623806809' " + "address='172.23.164.186' port='57040' type='local' " + "protocol='udp' priority='2122194688' generation='0'/>" + "</transport>" + "</content>" + "</jingle>" + "</cli:iq>"; + + scoped_ptr<XmlElement> source_message( + XmlElement::ForStr(kTestIceTransportInfoMessage)); + ASSERT_TRUE(source_message.get()); + + EXPECT_TRUE(JingleMessage::IsJingleMessage(source_message.get())); + + JingleMessage message; + std::string error; + EXPECT_TRUE(message.ParseXml(source_message.get(), &error)) << error; + + EXPECT_EQ(message.action, JingleMessage::TRANSPORT_INFO); + EXPECT_EQ(message.candidates.size(), 2U); + + scoped_ptr<XmlElement> formatted_message(message.ToXml()); + ASSERT_TRUE(formatted_message.get()); + EXPECT_TRUE(VerifyXml(source_message.get(), formatted_message.get(), &error)) + << error; +} + +TEST(JingleMessageTest, GiceTransportInfo) { + const char* kTestGiceTransportInfoMessage = + "<cli:iq to='user@gmail.com/chromoting016DBB07' type='set' " + "xmlns:cli='jabber:client'>" + "<jingle xmlns='urn:xmpp:jingle:1' action='transport-info' " + "sid='2227053353'>" + "<content name='chromoting' creator='initiator'>" + "<transport xmlns='http://www.google.com/transport/p2p'>" + "<candidate name='event' address='172.23.164.186' port='57040' " + "preference='1' username='tPUyEAmQrEw3y7hi' " + "protocol='udp' generation='0' " + "password='2iRdhLfawKZC5ydJ' type='local'/>" + "<candidate name='video' address='172.23.164.186' port='42171' " + "preference='1' username='EPK3CXo5sTLJSez0' " + "protocol='udp' generation='0' " + "password='eM0VUfUkZ+1Pyi0M' type='local'/>" + "</transport>" + "</content>" + "</jingle>" + "</cli:iq>"; + + scoped_ptr<XmlElement> source_message( + XmlElement::ForStr(kTestGiceTransportInfoMessage)); ASSERT_TRUE(source_message.get()); EXPECT_TRUE(JingleMessage::IsJingleMessage(source_message.get()));
diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc index edc48eea..0f4f0a2e 100644 --- a/remoting/protocol/jingle_session.cc +++ b/remoting/protocol/jingle_session.cc
@@ -32,12 +32,11 @@ namespace protocol { namespace { -// Delay after candidate creation before sending transport-info -// message. This is neccessary to be able to pack multiple candidates -// into one transport-info messages. The value needs to be greater -// than zero because ports are opened asynchronously in the browser -// process. -const int kTransportInfoSendDelayMs = 2; + +// Delay after candidate creation before sending transport-info message to +// accumulate multiple candidates. This is an optimization to reduce number of +// transport-info messages. +const int kTransportInfoSendDelayMs = 20; // How long we should wait for a response from the other end. This value is used // for all requests except |transport-info|. @@ -74,7 +73,6 @@ event_handler_(nullptr), state_(INITIALIZING), error_(OK), - config_is_set_(false), weak_factory_(this) { } @@ -149,7 +147,7 @@ void JingleSession::AcceptIncomingConnection( const JingleMessage& initiate_message) { - DCHECK(config_is_set_); + DCHECK(config_); // Process the first authentication message. const buzz::XmlElement* first_auth_message = @@ -184,7 +182,7 @@ auth_message = authenticator_->GetNextMessage(); message.description.reset( - new ContentDescription(CandidateSessionConfig::CreateFrom(config_), + new ContentDescription(CandidateSessionConfig::CreateFrom(*config_), auth_message.Pass())); SendMessage(message); @@ -213,14 +211,13 @@ const SessionConfig& JingleSession::config() { DCHECK(CalledOnValidThread()); - return config_; + return *config_; } -void JingleSession::set_config(const SessionConfig& config) { +void JingleSession::set_config(scoped_ptr<SessionConfig> config) { DCHECK(CalledOnValidThread()); - DCHECK(!config_is_set_); - config_ = config; - config_is_set_ = true; + DCHECK(!config_); + config_ = config.Pass(); } StreamChannelFactory* JingleSession::GetTransportChannelFactory() { @@ -243,16 +240,26 @@ CloseInternal(OK); } -void JingleSession::AddPendingRemoteCandidates(Transport* channel, - const std::string& name) { - std::list<JingleMessage::NamedCandidate>::iterator it = - pending_remote_candidates_.begin(); - while(it != pending_remote_candidates_.end()) { - if (it->name == name) { - channel->AddRemoteCandidate(it->candidate); - it = pending_remote_candidates_.erase(it); +void JingleSession::AddPendingRemoteTransportInfo(Transport* channel) { + std::list<JingleMessage::IceCredentials>::iterator credentials = + pending_remote_ice_credentials_.begin(); + while (credentials != pending_remote_ice_credentials_.end()) { + if (credentials->channel == channel->name()) { + channel->SetRemoteCredentials(credentials->ufrag, credentials->password); + credentials = pending_remote_ice_credentials_.erase(credentials); } else { - ++it; + ++credentials; + } + } + + std::list<JingleMessage::NamedCandidate>::iterator candidate = + pending_remote_candidates_.begin(); + while (candidate != pending_remote_candidates_.end()) { + if (candidate->name == channel->name()) { + channel->AddRemoteCandidate(candidate->candidate); + candidate = pending_remote_candidates_.erase(candidate); + } else { + ++candidate; } } } @@ -263,8 +270,9 @@ scoped_ptr<Transport> channel = session_manager_->transport_factory_->CreateTransport(); + channel->SetUseStandardIce(config_->standard_ice()); channel->Connect(name, this, callback); - AddPendingRemoteCandidates(channel.get(), name); + AddPendingRemoteTransportInfo(channel.get()); channels_[name] = channel.release(); } @@ -277,18 +285,19 @@ } } +void JingleSession::OnTransportIceCredentials(Transport* transport, + const std::string& ufrag, + const std::string& password) { + EnsurePendingTransportInfoMessage(); + pending_transport_info_message_->ice_credentials.push_back( + JingleMessage::IceCredentials(transport->name(), ufrag, password)); +} + void JingleSession::OnTransportCandidate(Transport* transport, const cricket::Candidate& candidate) { - pending_candidates_.push_back(JingleMessage::NamedCandidate( - transport->name(), candidate)); - - if (!transport_infos_timer_.IsRunning()) { - // Delay sending the new candidates in case we get more candidates - // that we can send in one message. - transport_infos_timer_.Start( - FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs), - this, &JingleSession::SendTransportInfo); - } + EnsurePendingTransportInfoMessage(); + pending_transport_info_message_->candidates.push_back( + JingleMessage::NamedCandidate(transport->name(), candidate)); } void JingleSession::OnTransportRouteChange(Transport* transport, @@ -362,14 +371,33 @@ } } +void JingleSession::EnsurePendingTransportInfoMessage() { + // |transport_info_timer_| must be running iff + // |pending_transport_info_message_| exists. + DCHECK_EQ(pending_transport_info_message_ != nullptr, + transport_info_timer_.IsRunning()); + + if (!pending_transport_info_message_) { + pending_transport_info_message_.reset(new JingleMessage( + peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_)); + pending_transport_info_message_->standard_ice = config_->standard_ice(); + + // Delay sending the new candidates in case we get more candidates + // that we can send in one message. + transport_info_timer_.Start( + FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs), + this, &JingleSession::SendTransportInfo); + } +} + void JingleSession::SendTransportInfo() { - JingleMessage message(peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_); - message.candidates.swap(pending_candidates_); + DCHECK(pending_transport_info_message_); scoped_ptr<IqRequest> request = session_manager_->iq_sender()->SendIq( - message.ToXml(), + pending_transport_info_message_->ToXml(), base::Bind(&JingleSession::OnTransportInfoResponse, base::Unretained(this))); + pending_transport_info_message_.reset(); if (request) { request->SetTimeout(base::TimeDelta::FromSeconds(kTransportInfoTimeout)); transport_info_requests_.push_back(request.release()); @@ -463,9 +491,6 @@ return; } - // In case there is transport information in the accept message. - ProcessTransportInfo(message); - SetState(CONNECTED); DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE); @@ -497,6 +522,27 @@ } void JingleSession::ProcessTransportInfo(const JingleMessage& message) { + // Check if the transport information version matches what was negotiated. + if (message.standard_ice != config_->standard_ice()) { + LOG(ERROR) << "Received transport-info message in format different from " + "negotiated."; + CloseInternal(INCOMPATIBLE_PROTOCOL); + return; + } + + for (std::list<JingleMessage::IceCredentials>::const_iterator it = + message.ice_credentials.begin(); + it != message.ice_credentials.end(); ++it) { + ChannelsMap::iterator channel = channels_.find(it->channel); + if (channel != channels_.end()) { + channel->second->SetRemoteCredentials(it->ufrag, it->password); + } else { + // Transport info was received before the channel was created. + // This could happen due to messages being reordered on the wire. + pending_remote_ice_credentials_.push_back(*it); + } + } + for (std::list<JingleMessage::NamedCandidate>::const_iterator it = message.candidates.begin(); it != message.candidates.end(); ++it) { @@ -555,12 +601,12 @@ bool JingleSession::InitializeConfigFromDescription( const ContentDescription* description) { DCHECK(description); - - if (!description->config()->GetFinalConfig(&config_)) { + config_ = SessionConfig::GetFinalConfig(description->config()); + if (!config_) { LOG(ERROR) << "session-accept does not specify configuration"; return false; } - if (!candidate_config()->IsSupported(config_)) { + if (!candidate_config()->IsSupported(*config_)) { LOG(ERROR) << "session-accept specifies an invalid configuration"; return false; }
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h index eb30e50f..584aeae 100644 --- a/remoting/protocol/jingle_session.h +++ b/remoting/protocol/jingle_session.h
@@ -51,7 +51,7 @@ const std::string& jid() override; const CandidateSessionConfig* candidate_config() override; const SessionConfig& config() override; - void set_config(const SessionConfig& config) override; + void set_config(scoped_ptr<SessionConfig> config) override; StreamChannelFactory* GetTransportChannelFactory() override; StreamChannelFactory* GetMultiplexedChannelFactory() override; void Close() override; @@ -62,6 +62,9 @@ void CancelChannelCreation(const std::string& name) override; // Transport::EventHandler interface. + void OnTransportIceCredentials(Transport* transport, + const std::string& ufrag, + const std::string& password) override; void OnTransportCandidate(Transport* transport, const cricket::Candidate& candidate) override; void OnTransportRouteChange(Transport* transport, @@ -82,8 +85,9 @@ scoped_ptr<Authenticator> authenticator, scoped_ptr<CandidateSessionConfig> config); - // Adds to a new channel the remote candidates received before it was created. - void AddPendingRemoteCandidates(Transport* channel, const std::string& name); + // Passes transport info to a new |channel| in case it was received before the + // channel was created. + void AddPendingRemoteTransportInfo(Transport* channel); // Called by JingleSessionManager for incoming connections. void InitializeIncomingConnection(const JingleMessage& initiate_message, @@ -100,6 +104,10 @@ IqRequest* request, const buzz::XmlElement* response); + // Creates empty |pending_transport_info_message_| and schedules timer for + // SentTransportInfo() to sent the message later. + void EnsurePendingTransportInfoMessage(); + // Sends transport-info message with candidates from |pending_candidates_|. void SendTransportInfo(); @@ -158,8 +166,7 @@ State state_; ErrorCode error_; - SessionConfig config_; - bool config_is_set_; + scoped_ptr<SessionConfig> config_; scoped_ptr<Authenticator> authenticator_; @@ -174,10 +181,12 @@ scoped_ptr<SecureChannelFactory> secure_channel_factory_; scoped_ptr<ChannelMultiplexer> channel_multiplexer_; - base::OneShotTimer<JingleSession> transport_infos_timer_; - std::list<JingleMessage::NamedCandidate> pending_candidates_; + scoped_ptr<JingleMessage> pending_transport_info_message_; + base::OneShotTimer<JingleSession> transport_info_timer_; - // Pending remote candidates, received before the local channels were created. + // Pending remote transport info received before the local channels were + // created. + std::list<JingleMessage::IceCredentials> pending_remote_ice_credentials_; std::list<JingleMessage::NamedCandidate> pending_remote_candidates_; base::WeakPtrFactory<JingleSession> weak_factory_;
diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc index 9ec24b9..9eb829d 100644 --- a/remoting/protocol/jingle_session_unittest.cc +++ b/remoting/protocol/jingle_session_unittest.cc
@@ -105,7 +105,8 @@ host_session_.reset(session); host_session_->SetEventHandler(&host_session_event_handler_); - session->set_config(SessionConfig::ForTest()); + session->set_config(standard_ice_ ? SessionConfig::ForTest() + : SessionConfig::WithLegacyIceForTest()); } void DeleteSession() { @@ -153,7 +154,7 @@ scoped_ptr<TransportFactory> host_transport(new LibjingleTransportFactory( nullptr, ChromiumPortAllocator::Create(nullptr, network_settings).Pass(), - network_settings)); + network_settings, TransportRole::SERVER)); host_server_.reset(new JingleSessionManager(host_transport.Pass())); host_server_->Init(host_signal_strategy_.get(), &host_server_listener_); @@ -167,7 +168,7 @@ scoped_ptr<TransportFactory> client_transport(new LibjingleTransportFactory( nullptr, ChromiumPortAllocator::Create(nullptr, network_settings).Pass(), - network_settings)); + network_settings, TransportRole::CLIENT)); client_server_.reset( new JingleSessionManager(client_transport.Pass())); client_server_->Init(client_signal_strategy_.get(), @@ -290,6 +291,8 @@ scoped_ptr<base::MessageLoopForIO> message_loop_; + bool standard_ice_ = true; + scoped_ptr<FakeSignalStrategy> host_signal_strategy_; scoped_ptr<FakeSignalStrategy> client_signal_strategy_; @@ -352,7 +355,7 @@ const buzz::XmlElement* initiate_xml = host_signal_strategy_->received_messages().front(); const buzz::XmlElement* jingle_element = - initiate_xml->FirstNamed(buzz::QName(kJingleNamespace, "jingle")); + initiate_xml->FirstNamed(buzz::QName("urn:xmpp:jingle:1", "jingle")); ASSERT_TRUE(jingle_element); ASSERT_EQ(kClientJid, jingle_element->Attr(buzz::QName(std::string(), "initiator"))); @@ -391,6 +394,23 @@ tester.CheckResults(); } +// Verify that we can still connect using legacy GICE transport. +TEST_F(JingleSessionTest, TestLegacyIceConnection) { + standard_ice_ = false; + + CreateSessionManagers(1, FakeAuthenticator::ACCEPT); + ASSERT_NO_FATAL_FAILURE( + InitiateConnection(1, FakeAuthenticator::ACCEPT, false)); + + ASSERT_NO_FATAL_FAILURE(CreateChannel()); + + StreamConnectionTester tester(host_socket_.get(), client_socket_.get(), + kMessageSize, kMessages); + tester.Start(); + message_loop_->Run(); + tester.CheckResults(); +} + TEST_F(JingleSessionTest, DeleteSessionOnIncomingConnection) { CreateSessionManagers(3, FakeAuthenticator::ACCEPT);
diff --git a/remoting/protocol/libjingle_transport_factory.cc b/remoting/protocol/libjingle_transport_factory.cc index 151d329f..10124bd0 100644 --- a/remoting/protocol/libjingle_transport_factory.cc +++ b/remoting/protocol/libjingle_transport_factory.cc
@@ -41,7 +41,7 @@ const std::string& candidate_type) { if (candidate_type == "local") { return TransportRoute::DIRECT; - } else if (candidate_type == "stun") { + } else if (candidate_type == "stun" || candidate_type == "prflx") { return TransportRoute::STUN; } else if (candidate_type == "relay") { return TransportRoute::RELAY; @@ -57,7 +57,8 @@ public sigslot::has_slots<> { public: LibjingleTransport(cricket::PortAllocator* port_allocator, - const NetworkSettings& network_settings); + const NetworkSettings& network_settings, + TransportRole role); ~LibjingleTransport() override; // Called by JingleTransportFactory when it has fresh Jingle info. @@ -67,9 +68,12 @@ void Connect(const std::string& name, Transport::EventHandler* event_handler, const Transport::ConnectedCallback& callback) override; + void SetRemoteCredentials(const std::string& ufrag, + const std::string& password) override; void AddRemoteCandidate(const cricket::Candidate& candidate) override; const std::string& name() const override; bool is_connected() const override; + void SetUseStandardIce(bool use_standard_ice) override; private: void DoStart(); @@ -94,15 +98,19 @@ cricket::PortAllocator* port_allocator_; NetworkSettings network_settings_; + TransportRole role_; + + bool use_standard_ice_ = true; std::string name_; EventHandler* event_handler_; Transport::ConnectedCallback callback_; std::string ice_username_fragment_; - std::string ice_password_; bool can_start_; + std::string remote_ice_username_fragment_; + std::string remote_ice_password_; std::list<cricket::Candidate> pending_candidates_; scoped_ptr<cricket::P2PTransportChannel> channel_; int connect_attempts_left_; @@ -114,18 +122,18 @@ }; LibjingleTransport::LibjingleTransport(cricket::PortAllocator* port_allocator, - const NetworkSettings& network_settings) + const NetworkSettings& network_settings, + TransportRole role) : port_allocator_(port_allocator), network_settings_(network_settings), + role_(role), event_handler_(nullptr), ice_username_fragment_( rtc::CreateRandomString(cricket::ICE_UFRAG_LENGTH)), - ice_password_(rtc::CreateRandomString(cricket::ICE_PWD_LENGTH)), can_start_(false), connect_attempts_left_(kMaxReconnectAttempts), weak_factory_(this) { DCHECK(!ice_username_fragment_.empty()); - DCHECK(!ice_password_.empty()); } LibjingleTransport::~LibjingleTransport() { @@ -149,9 +157,17 @@ if (!callback_.is_null()) DoStart(); + // Pass pending ICE credentials and candidates to the channel. + if (!remote_ice_username_fragment_.empty()) { + channel_->SetRemoteIceCredentials(remote_ice_username_fragment_, + remote_ice_password_); + } + while (!pending_candidates_.empty()) { - channel_->SetRemoteIceCredentials(pending_candidates_.front().username(), - pending_candidates_.front().password()); + if (!use_standard_ice_) { + channel_->SetRemoteIceCredentials(pending_candidates_.front().username(), + pending_candidates_.front().password()); + } channel_->OnCandidate(pending_candidates_.front()); pending_candidates_.pop_front(); } @@ -182,8 +198,18 @@ // TODO(sergeyu): Specify correct component ID for the channel. channel_.reset(new cricket::P2PTransportChannel( std::string(), 0, nullptr, port_allocator_)); - channel_->SetIceProtocolType(cricket::ICEPROTO_GOOGLE); - channel_->SetIceCredentials(ice_username_fragment_, ice_password_); + std::string ice_password = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH); + if (use_standard_ice_) { + channel_->SetIceProtocolType(cricket::ICEPROTO_RFC5245); + channel_->SetIceRole((role_ == TransportRole::CLIENT) + ? cricket::ICEROLE_CONTROLLING + : cricket::ICEROLE_CONTROLLED); + event_handler_->OnTransportIceCredentials(this, ice_username_fragment_, + ice_password); + } else { + channel_->SetIceProtocolType(cricket::ICEPROTO_GOOGLE); + } + channel_->SetIceCredentials(ice_username_fragment_, ice_password); channel_->SignalRequestSignaling.connect( this, &LibjingleTransport::OnRequestSignaling); channel_->SignalCandidateReady.connect( @@ -218,6 +244,17 @@ base::ResetAndReturn(&callback_).Run(socket.Pass()); } +void LibjingleTransport::SetRemoteCredentials(const std::string& ufrag, + const std::string& password) { + DCHECK(CalledOnValidThread()); + + remote_ice_username_fragment_ = ufrag; + remote_ice_password_ = password; + + if (channel_) + channel_->SetRemoteIceCredentials(ufrag, password); +} + void LibjingleTransport::AddRemoteCandidate( const cricket::Candidate& candidate) { DCHECK(CalledOnValidThread()); @@ -230,8 +267,10 @@ return; if (channel_) { - channel_->SetRemoteIceCredentials(candidate.username(), - candidate.password()); + if (!use_standard_ice_) { + channel_->SetRemoteIceCredentials(candidate.username(), + candidate.password()); + } channel_->OnCandidate(candidate); } else { pending_candidates_.push_back(candidate); @@ -248,6 +287,12 @@ return callback_.is_null(); } +void LibjingleTransport::SetUseStandardIce(bool use_standard_ice) { + DCHECK(CalledOnValidThread()); + DCHECK(!channel_); + use_standard_ice_ = use_standard_ice; +} + void LibjingleTransport::OnRequestSignaling( cricket::TransportChannelImpl* channel) { DCHECK(CalledOnValidThread()); @@ -339,8 +384,10 @@ --connect_attempts_left_; // Restart ICE by resetting ICE password. - ice_password_ = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH); - channel_->SetIceCredentials(ice_username_fragment_, ice_password_); + std::string ice_password = rtc::CreateRandomString(cricket::ICE_PWD_LENGTH); + event_handler_->OnTransportIceCredentials(this, ice_username_fragment_, + ice_password); + channel_->SetIceCredentials(ice_username_fragment_, ice_password); } } // namespace @@ -348,10 +395,12 @@ LibjingleTransportFactory::LibjingleTransportFactory( SignalStrategy* signal_strategy, scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator, - const NetworkSettings& network_settings) + const NetworkSettings& network_settings, + TransportRole role) : signal_strategy_(signal_strategy), port_allocator_(port_allocator.Pass()), - network_settings_(network_settings) { + network_settings_(network_settings), + role_(role) { } LibjingleTransportFactory::~LibjingleTransportFactory() { @@ -368,7 +417,7 @@ scoped_ptr<Transport> LibjingleTransportFactory::CreateTransport() { scoped_ptr<LibjingleTransport> result( - new LibjingleTransport(port_allocator_.get(), network_settings_)); + new LibjingleTransport(port_allocator_.get(), network_settings_, role_)); EnsureFreshJingleInfo();
diff --git a/remoting/protocol/libjingle_transport_factory.h b/remoting/protocol/libjingle_transport_factory.h index f6af301..1fd8855d 100644 --- a/remoting/protocol/libjingle_transport_factory.h +++ b/remoting/protocol/libjingle_transport_factory.h
@@ -41,7 +41,8 @@ LibjingleTransportFactory( SignalStrategy* signal_strategy, scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator, - const NetworkSettings& network_settings); + const NetworkSettings& network_settings, + TransportRole role); ~LibjingleTransportFactory() override; @@ -58,6 +59,7 @@ SignalStrategy* signal_strategy_; scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator_; NetworkSettings network_settings_; + TransportRole role_; base::TimeTicks last_jingle_info_update_time_; scoped_ptr<JingleInfoRequest> jingle_info_request_;
diff --git a/remoting/protocol/message_reader_unittest.cc b/remoting/protocol/message_reader_unittest.cc index 68bcde6..f8bf2d90 100644 --- a/remoting/protocol/message_reader_unittest.cc +++ b/remoting/protocol/message_reader_unittest.cc
@@ -279,7 +279,7 @@ // Read() returns error. TEST_F(MessageReaderTest, ReadError) { - socket_.set_next_read_error(net::ERR_FAILED); + socket_.AppendReadError(net::ERR_FAILED); // Add a message. It should never be read after the error above. AddMessage(kTestMessage1);
diff --git a/remoting/protocol/monitored_video_stub_unittest.cc b/remoting/protocol/monitored_video_stub_unittest.cc index 67162c3..e98c0d1 100644 --- a/remoting/protocol/monitored_video_stub_unittest.cc +++ b/remoting/protocol/monitored_video_stub_unittest.cc
@@ -24,7 +24,7 @@ class MonitoredVideoStubTest : public testing::Test { protected: - virtual void SetUp() override { + void SetUp() override { packet_.reset(new VideoPacket()); monitor_.reset(new MonitoredVideoStub( &video_stub_,
diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h index 2484e9a..b3fca8ed 100644 --- a/remoting/protocol/protocol_mock_objects.h +++ b/remoting/protocol/protocol_mock_objects.h
@@ -207,7 +207,10 @@ MOCK_METHOD0(jid, const std::string&()); MOCK_METHOD0(candidate_config, const CandidateSessionConfig*()); MOCK_METHOD0(config, const SessionConfig&()); - MOCK_METHOD1(set_config, void(const SessionConfig& config)); + MOCK_METHOD1(set_config_ptr, void(const SessionConfig* config)); + void set_config(scoped_ptr<SessionConfig> config) override { + set_config_ptr(config.get()); + } MOCK_METHOD0(initiator_token, const std::string&()); MOCK_METHOD1(set_initiator_token, void(const std::string& initiator_token)); MOCK_METHOD0(receiver_token, const std::string&());
diff --git a/remoting/protocol/session.h b/remoting/protocol/session.h index f806e21db..b4a0d03 100644 --- a/remoting/protocol/session.h +++ b/remoting/protocol/session.h
@@ -94,7 +94,7 @@ // Set protocol configuration for an incoming session. Must be // called on the host before the connection is accepted, from // ChromotocolServer::IncomingConnectionCallback. - virtual void set_config(const SessionConfig& config) = 0; + virtual void set_config(scoped_ptr<SessionConfig> config) = 0; // GetTransportChannelFactory() returns a factory that creates a new transport // channel for each logical channel. GetMultiplexedChannelFactory() channels
diff --git a/remoting/protocol/session_config.cc b/remoting/protocol/session_config.cc index 460da28..f6163f4f 100644 --- a/remoting/protocol/session_config.cc +++ b/remoting/protocol/session_config.cc
@@ -9,6 +9,30 @@ namespace remoting { namespace protocol { +namespace { + +bool IsChannelConfigSupported(const std::list<ChannelConfig>& list, + const ChannelConfig& value) { + return std::find(list.begin(), list.end(), value) != list.end(); +} + +bool SelectCommonChannelConfig(const std::list<ChannelConfig>& host_configs, + const std::list<ChannelConfig>& client_configs, + ChannelConfig* config) { + // Usually each of these lists will contain just a few elements, so iterating + // over all of them is not a problem. + std::list<ChannelConfig>::const_iterator it; + for (it = client_configs.begin(); it != client_configs.end(); ++it) { + if (IsChannelConfigSupported(host_configs, *it)) { + *config = *it; + return true; + } + } + return false; +} + +} // namespace + const int kDefaultStreamVersion = 2; const int kControlStreamVersion = 3; @@ -16,12 +40,6 @@ return ChannelConfig(); } -ChannelConfig::ChannelConfig() - : transport(TRANSPORT_NONE), - version(0), - codec(CODEC_UNDEFINED) { -} - ChannelConfig::ChannelConfig(TransportType transport, int version, Codec codec) : transport(transport), version(version), @@ -35,32 +53,93 @@ return transport == b.transport && version == b.version && codec == b.codec; } -SessionConfig::SessionConfig() { +// static +scoped_ptr<SessionConfig> SessionConfig::SelectCommon( + const CandidateSessionConfig* client_config, + const CandidateSessionConfig* host_config) { + scoped_ptr<SessionConfig> result(new SessionConfig()); + ChannelConfig control_config; + ChannelConfig event_config; + ChannelConfig video_config; + ChannelConfig audio_config; + + result->standard_ice_ = + host_config->standard_ice() && client_config->standard_ice(); + + if (!SelectCommonChannelConfig(host_config->control_configs(), + client_config->control_configs(), + &result->control_config_) || + !SelectCommonChannelConfig(host_config->event_configs(), + client_config->event_configs(), + &result->event_config_) || + !SelectCommonChannelConfig(host_config->video_configs(), + client_config->video_configs(), + &result->video_config_) || + !SelectCommonChannelConfig(host_config->audio_configs(), + client_config->audio_configs(), + &result->audio_config_)) { + return nullptr; + } + + return result; } // static -SessionConfig SessionConfig::ForTest() { - SessionConfig result; - result.set_control_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, - kControlStreamVersion, - ChannelConfig::CODEC_UNDEFINED)); - result.set_event_config(ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, - kDefaultStreamVersion, - ChannelConfig::CODEC_UNDEFINED)); - result.set_video_config(ChannelConfig(ChannelConfig::TRANSPORT_STREAM, - kDefaultStreamVersion, - ChannelConfig::CODEC_VP8)); - result.set_audio_config(ChannelConfig(ChannelConfig::TRANSPORT_NONE, - kDefaultStreamVersion, - ChannelConfig::CODEC_UNDEFINED)); - return result; +scoped_ptr<SessionConfig> SessionConfig::GetFinalConfig( + const CandidateSessionConfig* candidate_config) { + if (candidate_config->control_configs().size() != 1 || + candidate_config->event_configs().size() != 1 || + candidate_config->video_configs().size() != 1 || + candidate_config->audio_configs().size() != 1) { + return nullptr; + } + + scoped_ptr<SessionConfig> result(new SessionConfig()); + result->standard_ice_ = candidate_config->standard_ice(); + result->control_config_ = candidate_config->control_configs().front(); + result->event_config_ = candidate_config->event_configs().front(); + result->video_config_ = candidate_config->video_configs().front(); + result->audio_config_ = candidate_config->audio_configs().front(); + + return result.Pass(); } +// static +scoped_ptr<SessionConfig> SessionConfig::ForTest() { + scoped_ptr<SessionConfig> result(new SessionConfig()); + result->standard_ice_ = true; + result->control_config_ = ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, + kControlStreamVersion, + ChannelConfig::CODEC_UNDEFINED); + result->event_config_ = ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM, + kDefaultStreamVersion, + ChannelConfig::CODEC_UNDEFINED); + result->video_config_ = ChannelConfig(ChannelConfig::TRANSPORT_STREAM, + kDefaultStreamVersion, + ChannelConfig::CODEC_VP8); + result->audio_config_ = ChannelConfig(ChannelConfig::TRANSPORT_NONE, + kDefaultStreamVersion, + ChannelConfig::CODEC_UNDEFINED); + return result.Pass(); +} + +// static +scoped_ptr<SessionConfig> SessionConfig::WithLegacyIceForTest() { + scoped_ptr<SessionConfig> result = ForTest(); + result->standard_ice_ = false; + return result.Pass(); +} + +SessionConfig::SessionConfig() { +} + + CandidateSessionConfig::CandidateSessionConfig() { } CandidateSessionConfig::CandidateSessionConfig( const CandidateSessionConfig& config) - : control_configs_(config.control_configs_), + : standard_ice_(true), + control_configs_(config.control_configs_), event_configs_(config.event_configs_), video_configs_(config.video_configs_), audio_configs_(config.audio_configs_) { @@ -68,33 +147,6 @@ CandidateSessionConfig::~CandidateSessionConfig() { } -bool CandidateSessionConfig::Select( - const CandidateSessionConfig* client_config, - SessionConfig* result) { - ChannelConfig control_config; - ChannelConfig event_config; - ChannelConfig video_config; - ChannelConfig audio_config; - - if (!SelectCommonChannelConfig( - control_configs_, client_config->control_configs_, &control_config) || - !SelectCommonChannelConfig( - event_configs_, client_config->event_configs_, &event_config) || - !SelectCommonChannelConfig( - video_configs_, client_config->video_configs_, &video_config) || - !SelectCommonChannelConfig( - audio_configs_, client_config->audio_configs_, &audio_config)) { - return false; - } - - result->set_control_config(control_config); - result->set_event_config(event_config); - result->set_video_config(video_config); - result->set_audio_config(audio_config); - - return true; -} - bool CandidateSessionConfig::IsSupported( const SessionConfig& config) const { return @@ -104,46 +156,6 @@ IsChannelConfigSupported(audio_configs_, config.audio_config()); } -bool CandidateSessionConfig::GetFinalConfig(SessionConfig* result) const { - if (control_configs_.size() != 1 || - event_configs_.size() != 1 || - video_configs_.size() != 1 || - audio_configs_.size() != 1) { - return false; - } - - result->set_control_config(control_configs_.front()); - result->set_event_config(event_configs_.front()); - result->set_video_config(video_configs_.front()); - result->set_audio_config(audio_configs_.front()); - - return true; -} - -// static -bool CandidateSessionConfig::SelectCommonChannelConfig( - const std::list<ChannelConfig>& host_configs, - const std::list<ChannelConfig>& client_configs, - ChannelConfig* config) { - // Usually each of these vectors will contain just several elements, - // so iterating over all of them is not a problem. - std::list<ChannelConfig>::const_iterator it; - for (it = client_configs.begin(); it != client_configs.end(); ++it) { - if (IsChannelConfigSupported(host_configs, *it)) { - *config = *it; - return true; - } - } - return false; -} - -// static -bool CandidateSessionConfig::IsChannelConfigSupported( - const std::list<ChannelConfig>& vector, - const ChannelConfig& value) { - return std::find(vector.begin(), vector.end(), value) != vector.end(); -} - scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::Clone() const { return make_scoped_ptr(new CandidateSessionConfig(*this)); } @@ -157,6 +169,7 @@ scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateFrom( const SessionConfig& config) { scoped_ptr<CandidateSessionConfig> result = CreateEmpty(); + result->set_standard_ice(config.standard_ice()); result->mutable_control_configs()->push_back(config.control_config()); result->mutable_event_configs()->push_back(config.event_config()); result->mutable_video_configs()->push_back(config.video_config()); @@ -168,6 +181,8 @@ scoped_ptr<CandidateSessionConfig> CandidateSessionConfig::CreateDefault() { scoped_ptr<CandidateSessionConfig> result = CreateEmpty(); + result->set_standard_ice(true); + // Control channel. result->mutable_control_configs()->push_back( ChannelConfig(ChannelConfig::TRANSPORT_MUX_STREAM,
diff --git a/remoting/protocol/session_config.h b/remoting/protocol/session_config.h index c0313a0..acd3dba2 100644 --- a/remoting/protocol/session_config.h +++ b/remoting/protocol/session_config.h
@@ -42,7 +42,7 @@ static ChannelConfig None(); // Default constructor. Equivalent to None(). - ChannelConfig(); + ChannelConfig() = default; // Creates a channel config with the specified parameters. ChannelConfig(TransportType transport, int version, Codec codec); @@ -51,42 +51,53 @@ // std::list<ChannelConfig>. bool operator==(const ChannelConfig& b) const; - TransportType transport; - int version; - Codec codec; + TransportType transport = TRANSPORT_NONE; + int version = 0; + Codec codec = CODEC_UNDEFINED; }; +class CandidateSessionConfig; + // SessionConfig is used by the chromoting Session to store negotiated // chromotocol configuration. class SessionConfig { public: - SessionConfig(); + // Selects session configuration that is supported by both participants. + // nullptr is returned if such configuration doesn't exist. When selecting + // channel configuration priority is given to the configs listed first + // in |client_config|. + static scoped_ptr<SessionConfig> SelectCommon( + const CandidateSessionConfig* client_config, + const CandidateSessionConfig* host_config); - void set_control_config(const ChannelConfig& control_config) { - control_config_ = control_config; - } + // Extracts final protocol configuration. Must be used for the description + // received in the session-accept stanza. If the selection is ambiguous + // (e.g. there is more than one configuration for one of the channel) + // or undefined (e.g. no configurations for a channel) then nullptr is + // returned. + static scoped_ptr<SessionConfig> GetFinalConfig( + const CandidateSessionConfig* candidate_config); + + // Returns a suitable session configuration for use in tests. + static scoped_ptr<SessionConfig> ForTest(); + static scoped_ptr<SessionConfig> WithLegacyIceForTest(); + + bool standard_ice() const { return standard_ice_; } + const ChannelConfig& control_config() const { return control_config_; } - void set_event_config(const ChannelConfig& event_config) { - event_config_ = event_config; - } const ChannelConfig& event_config() const { return event_config_; } - void set_video_config(const ChannelConfig& video_config) { - video_config_ = video_config; - } const ChannelConfig& video_config() const { return video_config_; } - void set_audio_config(const ChannelConfig& audio_config) { - audio_config_ = audio_config; - } const ChannelConfig& audio_config() const { return audio_config_; } bool is_audio_enabled() const { return audio_config_.transport != ChannelConfig::TRANSPORT_NONE; } - // Returns a suitable session configuration for use in tests. - static SessionConfig ForTest(); - private: + SessionConfig(); + + bool standard_ice_ = true; + ChannelConfig control_config_; ChannelConfig event_config_; ChannelConfig video_config_; @@ -105,6 +116,9 @@ ~CandidateSessionConfig(); + bool standard_ice() const { return standard_ice_; } + void set_standard_ice(bool standard_ice) { standard_ice_ = standard_ice; } + const std::list<ChannelConfig>& control_configs() const { return control_configs_; } @@ -137,23 +151,9 @@ return &audio_configs_; } - // Selects session configuration that is supported by both participants. - // nullptr is returned if such configuration doesn't exist. When selecting - // channel configuration priority is given to the configs listed first - // in |client_config|. - bool Select(const CandidateSessionConfig* client_config, - SessionConfig* result); - // Returns true if |config| is supported. bool IsSupported(const SessionConfig& config) const; - // Extracts final protocol configuration. Must be used for the description - // received in the session-accept stanza. If the selection is ambiguous - // (e.g. there is more than one configuration for one of the channel) - // or undefined (e.g. no configurations for a channel) then nullptr is - // returned. - bool GetFinalConfig(SessionConfig* result) const; - scoped_ptr<CandidateSessionConfig> Clone() const; // Helpers for enabling/disabling specific features. @@ -165,12 +165,7 @@ explicit CandidateSessionConfig(const CandidateSessionConfig& config); CandidateSessionConfig& operator=(const CandidateSessionConfig& b); - static bool SelectCommonChannelConfig( - const std::list<ChannelConfig>& host_configs_, - const std::list<ChannelConfig>& client_configs_, - ChannelConfig* config); - static bool IsChannelConfigSupported(const std::list<ChannelConfig>& list, - const ChannelConfig& value); + bool standard_ice_ = true; std::list<ChannelConfig> control_configs_; std::list<ChannelConfig> event_configs_;
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.cc b/remoting/protocol/ssl_hmac_channel_authenticator.cc index e01998d..d8385c3f 100644 --- a/remoting/protocol/ssl_hmac_channel_authenticator.cc +++ b/remoting/protocol/ssl_hmac_channel_authenticator.cc
@@ -6,10 +6,14 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/callback_helpers.h" +#include "base/logging.h" #include "crypto/secure_util.h" #include "net/base/host_port_pair.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" +#include "net/cert/cert_status_flags.h" +#include "net/cert/cert_verifier.h" #include "net/cert/x509_certificate.h" #include "net/http/transport_security_state.h" #include "net/socket/client_socket_factory.h" @@ -24,6 +28,35 @@ namespace remoting { namespace protocol { +namespace { + +// A CertVerifier which rejects every certificate. +class FailingCertVerifier : public net::CertVerifier { + public: + FailingCertVerifier() {} + ~FailingCertVerifier() override {} + + int Verify(net::X509Certificate* cert, + const std::string& hostname, + const std::string& ocsp_response, + int flags, + net::CRLSet* crl_set, + net::CertVerifyResult* verify_result, + const net::CompletionCallback& callback, + RequestHandle* out_req, + const net::BoundNetLog& net_log) override { + verify_result->verified_cert = cert; + verify_result->cert_status = net::CERT_STATUS_INVALID; + return net::ERR_CERT_INVALID; + } + + void CancelRequest(RequestHandle req) override { + NOTIMPLEMENTED(); + } +}; + +} // namespace + // static scoped_ptr<SslHmacChannelAuthenticator> SslHmacChannelAuthenticator::CreateForClient( @@ -95,6 +128,7 @@ #endif } else { transport_security_state_.reset(new net::TransportSecurityState); + cert_verifier_.reset(new FailingCertVerifier); net::SSLConfig::CertAndStatus cert_and_status; cert_and_status.cert_status = net::CERT_STATUS_AUTHORITY_INVALID; @@ -112,6 +146,7 @@ net::HostPortPair host_and_port(kSslFakeHostName, 0); net::SSLClientSocketContext context; context.transport_security_state = transport_security_state_.get(); + context.cert_verifier = cert_verifier_.get(); scoped_ptr<net::ClientSocketHandle> socket_handle( new net::ClientSocketHandle); socket_handle->SetSocket(socket.Pass()); @@ -280,20 +315,12 @@ if (callback_called) *callback_called = true; - CallDoneCallback(net::OK, socket_.Pass()); + base::ResetAndReturn(&done_callback_).Run(net::OK, socket_.Pass()); } } void SslHmacChannelAuthenticator::NotifyError(int error) { - CallDoneCallback(error, nullptr); -} - -void SslHmacChannelAuthenticator::CallDoneCallback( - int error, - scoped_ptr<net::StreamSocket> socket) { - DoneCallback callback = done_callback_; - done_callback_.Reset(); - callback.Run(error, socket.Pass()); + base::ResetAndReturn(&done_callback_).Run(error, nullptr); } } // namespace protocol
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.h b/remoting/protocol/ssl_hmac_channel_authenticator.h index ece68fd..6bd9006 100644 --- a/remoting/protocol/ssl_hmac_channel_authenticator.h +++ b/remoting/protocol/ssl_hmac_channel_authenticator.h
@@ -14,6 +14,7 @@ #include "remoting/protocol/channel_authenticator.h" namespace net { +class CertVerifier; class DrainableIOBuffer; class GrowableIOBuffer; class SSLSocket; @@ -77,7 +78,6 @@ void CheckDone(bool* callback_called); void NotifyError(int error); - void CallDoneCallback(int error, scoped_ptr<net::StreamSocket> socket); // The mutual secret used for authentication. std::string auth_key_; @@ -89,6 +89,7 @@ // Used in the CLIENT mode only. std::string remote_cert_; scoped_ptr<net::TransportSecurityState> transport_security_state_; + scoped_ptr<net::CertVerifier> cert_verifier_; scoped_ptr<net::SSLSocket> socket_; DoneCallback done_callback_;
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc b/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc index c0c61f8..bc9ee86f 100644 --- a/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc +++ b/remoting/protocol/ssl_hmac_channel_authenticator_unittest.cc
@@ -14,6 +14,7 @@ #include "crypto/rsa_private_key.h" #include "net/base/net_errors.h" #include "net/base/test_data_directory.h" +#include "net/test/cert_test_util.h" #include "remoting/base/rsa_key_pair.h" #include "remoting/protocol/connection_tester.h" #include "remoting/protocol/fake_session.h" @@ -68,7 +69,7 @@ ASSERT_TRUE(key_pair_.get()); } - void RunChannelAuth(bool expected_fail) { + void RunChannelAuth(int expected_client_error, int expected_host_error) { client_fake_socket_.reset(new FakeStreamSocket()); host_fake_socket_.reset(new FakeStreamSocket()); client_fake_socket_->PairWith(host_fake_socket_.get()); @@ -87,14 +88,18 @@ // callback. int callback_counter = 2; - if (expected_fail) { - EXPECT_CALL(client_callback_, OnDone(net::ERR_FAILED, nullptr)) - .WillOnce(QuitThreadOnCounter(&callback_counter)); - EXPECT_CALL(host_callback_, OnDone(net::ERR_FAILED, nullptr)) + if (expected_client_error != net::OK) { + EXPECT_CALL(client_callback_, OnDone(expected_client_error, nullptr)) .WillOnce(QuitThreadOnCounter(&callback_counter)); } else { EXPECT_CALL(client_callback_, OnDone(net::OK, NotNull())) .WillOnce(QuitThreadOnCounter(&callback_counter)); + } + + if (expected_host_error != net::OK) { + EXPECT_CALL(host_callback_, OnDone(expected_host_error, nullptr)) + .WillOnce(QuitThreadOnCounter(&callback_counter)); + } else { EXPECT_CALL(host_callback_, OnDone(net::OK, NotNull())) .WillOnce(QuitThreadOnCounter(&callback_counter)); } @@ -149,7 +154,7 @@ host_auth_ = SslHmacChannelAuthenticator::CreateForHost( host_cert_, key_pair_, kTestSharedSecret); - RunChannelAuth(false); + RunChannelAuth(net::OK, net::OK); ASSERT_TRUE(client_socket_.get() != nullptr); ASSERT_TRUE(host_socket_.get() != nullptr); @@ -169,7 +174,26 @@ host_auth_ = SslHmacChannelAuthenticator::CreateForHost( host_cert_, key_pair_, kTestSharedSecret); - RunChannelAuth(true); + RunChannelAuth(net::ERR_FAILED, net::ERR_FAILED); + + ASSERT_TRUE(host_socket_.get() == nullptr); +} + +// Verify that channels cannot be using invalid certificate. +TEST_F(SslHmacChannelAuthenticatorTest, InvalidCertificate) { + // Import a second certificate for the client to expect. + scoped_refptr<net::X509Certificate> host_cert2( + net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem")); + std::string host_cert2_der; + ASSERT_TRUE(net::X509Certificate::GetDEREncoded(host_cert2->os_cert_handle(), + &host_cert2_der)); + + client_auth_ = SslHmacChannelAuthenticator::CreateForClient( + host_cert2_der, kTestSharedSecret); + host_auth_ = SslHmacChannelAuthenticator::CreateForHost( + host_cert_, key_pair_, kTestSharedSecret); + + RunChannelAuth(net::ERR_CERT_INVALID, net::ERR_CONNECTION_CLOSED); ASSERT_TRUE(host_socket_.get() == nullptr); }
diff --git a/remoting/protocol/third_party_authenticator_unittest.cc b/remoting/protocol/third_party_authenticator_unittest.cc index 770907db..9f6dde1de 100644 --- a/remoting/protocol/third_party_authenticator_unittest.cc +++ b/remoting/protocol/third_party_authenticator_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/bind.h" +#include "base/callback_helpers.h" #include "net/base/net_errors.h" #include "remoting/base/rsa_key_pair.h" #include "remoting/protocol/authenticator_test_base.h" @@ -53,9 +54,7 @@ void OnTokenFetched(const std::string& token, const std::string& shared_secret) { ASSERT_FALSE(on_token_fetched_.is_null()); - TokenFetchedCallback on_token_fetched = on_token_fetched_; - on_token_fetched_.Reset(); - on_token_fetched.Run(token, shared_secret); + base::ResetAndReturn(&on_token_fetched_).Run(token, shared_secret); } private: @@ -79,9 +78,7 @@ void OnTokenValidated(const std::string& shared_secret) { ASSERT_FALSE(on_token_validated_.is_null()); - TokenValidatedCallback on_token_validated = on_token_validated_; - on_token_validated_.Reset(); - on_token_validated.Run(shared_secret); + base::ResetAndReturn(&on_token_validated_).Run(shared_secret); } const GURL& token_url() const override { return token_url_; }
diff --git a/remoting/protocol/transport.h b/remoting/protocol/transport.h index d4c4b3f..4223796a 100644 --- a/remoting/protocol/transport.h +++ b/remoting/protocol/transport.h
@@ -44,6 +44,11 @@ class ChannelAuthenticator; +enum class TransportRole { + SERVER, + CLIENT, +}; + struct TransportRoute { enum RouteType { DIRECT, @@ -69,6 +74,12 @@ EventHandler() {}; virtual ~EventHandler() {}; + // Called to pass ICE credentials to the session. Used only for STANDARD + // version of ICE, see SetIceVersion(). + virtual void OnTransportIceCredentials(Transport* transport, + const std::string& ufrag, + const std::string& password) = 0; + // Called when the transport generates a new candidate that needs // to be passed to the AddRemoteCandidate() method on the remote // end of the connection. @@ -97,6 +108,10 @@ Transport::EventHandler* event_handler, const ConnectedCallback& callback) = 0; + // Sets remote ICE credentials. + virtual void SetRemoteCredentials(const std::string& ufrag, + const std::string& password) = 0; + // Adds |candidate| received from the peer. virtual void AddRemoteCandidate(const cricket::Candidate& candidate) = 0; @@ -108,6 +123,12 @@ // Returns true if the channel is already connected. virtual bool is_connected() const = 0; + // Sets ICE version for the transport. + // + // TODO(sergeyu): Remove this when support for legacy ICE is removed. + // crbug.com/473758 + virtual void SetUseStandardIce(bool use_standard_ice) {} + private: DISALLOW_COPY_AND_ASSIGN(Transport); };
diff --git a/remoting/remoting_host_srcs.gypi b/remoting/remoting_host_srcs.gypi index b260c87..de3eb37 100644 --- a/remoting/remoting_host_srcs.gypi +++ b/remoting/remoting_host_srcs.gypi
@@ -270,9 +270,10 @@ 'host/setup/daemon_controller_delegate_mac.mm', 'host/setup/daemon_controller_delegate_win.cc', 'host/setup/daemon_controller_delegate_win.h', + 'host/setup/gaia_oauth_client.cc', + 'host/setup/gaia_oauth_client.h', 'host/setup/me2me_native_messaging_host.cc', 'host/setup/me2me_native_messaging_host.h', - 'host/setup/oauth_client.cc', 'host/setup/oauth_client.h', 'host/setup/oauth_helper.cc', 'host/setup/oauth_helper.h',
diff --git a/remoting/remoting_locales.gni b/remoting/remoting_locales.gni index d4dd4e8..b37d177b 100644 --- a/remoting/remoting_locales.gni +++ b/remoting/remoting_locales.gni
@@ -6,11 +6,11 @@ # See also remoting_locales_with_underscores below. remoting_locales = [ - #"am", + "am", "ar", "bg", - #"bn", + "bn", "ca", "cs", "da", @@ -22,13 +22,13 @@ "es-419", "et", - #"fa", - #"fake-bidi", + "fa", + "fake-bidi", "fi", "fil", "fr", - #"gu", + "gu", "he", "hi", "hr", @@ -37,14 +37,14 @@ "it", "ja", - #"kn", + "kn", "ko", "lt", "lv", - #"ml", - #"mr", - #"ms", + "ml", + "mr", + "ms", "nb", "nl", "pl", @@ -57,9 +57,9 @@ "sr", "sv", - #"sw", - #"ta", - #"te", + "sw", + "ta", + "te", "th", "tr", "uk", @@ -75,7 +75,7 @@ "en-GB", "es-419", - #"fake-bidi", + "fake-bidi", "pt-BR", "pt-PT", "zh-CN", @@ -85,7 +85,7 @@ "en_GB", "es_419", - #"fake_bidi", + "fake_bidi", "pt_BR", "pt_PT", "zh_CN",
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi index 5a01d1f..ee5c5a70 100644 --- a/remoting/remoting_test.gypi +++ b/remoting/remoting_test.gypi
@@ -208,6 +208,8 @@ 'host/resizing_host_observer_unittest.cc', 'host/screen_resolution_unittest.cc', 'host/server_log_entry_host_unittest.cc', + 'host/setup/mock_oauth_client.cc', + 'host/setup/mock_oauth_client.h', 'host/setup/me2me_native_messaging_host.cc', 'host/setup/me2me_native_messaging_host.h', 'host/setup/me2me_native_messaging_host_unittest.cc', @@ -334,6 +336,7 @@ 'destination': '<(PRODUCT_DIR)/remoting/browser_test_resources', 'files': [ '<@(remoting_webapp_browsertest_all_js_files)', + '../third_party/sinonjs/src/sinon.js', ], }, ], # end of copies @@ -344,7 +347,7 @@ 'variables': { 'output_dir': '<(PRODUCT_DIR)/remoting/unittests', 'webapp_js_files': [ - '<@(remoting_webapp_shared_main_html_js_files)', + '<@(remoting_webapp_unittest_html_all_js_files)', '<@(remoting_webapp_wcs_sandbox_html_js_files)', '<@(remoting_webapp_background_html_js_files)', ]
diff --git a/remoting/remoting_webapp_files.gypi b/remoting/remoting_webapp_files.gypi index 2e98b04..60d7b4b 100644 --- a/remoting/remoting_webapp_files.gypi +++ b/remoting/remoting_webapp_files.gypi
@@ -71,9 +71,9 @@ 'webapp/base/js/base_inherits_unittest.js', 'webapp/base/js/ipc_unittest.js', 'webapp/base/js/protocol_extension_manager_unittest.js', + 'webapp/base/js/viewport_unittest.js', 'webapp/crd/js/apps_v2_migration_unittest.js', 'webapp/crd/js/client_session_unittest.js', - 'webapp/crd/js/desktop_viewport_unittest.js', 'webapp/crd/js/client_session_factory_unittest.js', 'webapp/crd/js/dns_blackhole_checker_unittest.js', 'webapp/crd/js/error_unittest.js', @@ -167,7 +167,6 @@ 'webapp/crd/js/connected_view.js', 'webapp/crd/js/connection_info.js', 'webapp/crd/js/credentials_provider.js', - 'webapp/crd/js/desktop_connected_view.js', 'webapp/crd/js/host_desktop.js', 'webapp/crd/js/smart_reconnector.js', 'webapp/crd/js/video_frame_recorder.js', @@ -216,6 +215,7 @@ 'remoting_webapp_js_host_display_files': [ 'webapp/crd/js/host_list.js', 'webapp/crd/js/host_list_api.js', + 'webapp/crd/js/host_list_api_gcd_impl.js', 'webapp/crd/js/host_list_api_impl.js', 'webapp/crd/js/host_table_entry.js', 'webapp/crd/js/local_host_section.js', @@ -239,21 +239,38 @@ 'webapp/crd/js/xmpp_login_handler.js', 'webapp/crd/js/xmpp_stream_parser.js', ], - # UI JavaScript files. + # Shared UI JavaScript files. 'remoting_webapp_js_ui_files': [ + 'webapp/base/js/viewport.js', 'webapp/base/js/window_shape.js', + 'webapp/crd/js/connection_stats.js', + 'webapp/crd/js/feedback.js', + 'webapp/crd/js/l10n.js', + 'webapp/crd/js/ui_mode.js', + ], + + # + # DesktopRemoting-specific JS files. + # + + # The CRD-specific JavaScript files required by main.html. + 'remoting_webapp_crd_js_ui_files': [ 'webapp/crd/js/bump_scroller.js', 'webapp/crd/js/butter_bar.js', - 'webapp/crd/js/connection_stats.js', + 'webapp/crd/js/crd_auth_dialog.js', + 'webapp/crd/js/crd_event_handlers.js', + 'webapp/crd/js/crd_experimental.js', + 'webapp/crd/js/desktop_connected_view.js', + 'webapp/crd/js/desktop_remoting.js', + 'webapp/crd/js/desktop_remoting_activity.js', 'webapp/crd/js/desktop_viewport.js', - 'webapp/crd/js/feedback.js', 'webapp/crd/js/fullscreen.js', 'webapp/crd/js/fullscreen_v1.js', 'webapp/crd/js/fullscreen_v2.js', - 'webapp/crd/js/l10n.js', + 'webapp/crd/js/it2me_activity.js', + 'webapp/crd/js/me2me_activity.js', 'webapp/crd/js/menu_button.js', 'webapp/crd/js/options_menu.js', - 'webapp/crd/js/ui_mode.js', 'webapp/crd/js/toolbar.js', 'webapp/crd/js/window_frame.js', ], @@ -286,17 +303,17 @@ #'<@(remoting_webapp_browsertest_all_js_files)', ], + # The JS files required by unittest.html. + 'remoting_webapp_unittest_html_all_js_files': [ + '<@(remoting_webapp_shared_main_html_js_files)', + '<@(remoting_webapp_crd_js_ui_files)', + ], + # The CRD-specific JavaScript files required by main.html. 'remoting_webapp_crd_main_html_all_js_files': [ '<@(remoting_webapp_shared_main_html_js_files)', - 'webapp/crd/js/crd_auth_dialog.js', - 'webapp/crd/js/crd_event_handlers.js', - 'webapp/crd/js/crd_experimental.js', + '<@(remoting_webapp_crd_js_ui_files)', 'webapp/crd/js/crd_main.js', - 'webapp/crd/js/desktop_remoting.js', - 'webapp/crd/js/desktop_remoting_activity.js', - 'webapp/crd/js/it2me_activity.js', - 'webapp/crd/js/me2me_activity.js', ], # These template files are used to construct main.html.
diff --git a/remoting/signaling/iq_sender.cc b/remoting/signaling/iq_sender.cc index d3e7432..7fefc71e 100644 --- a/remoting/signaling/iq_sender.cc +++ b/remoting/signaling/iq_sender.cc
@@ -5,6 +5,7 @@ #include "remoting/signaling/iq_sender.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/location.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -138,11 +139,8 @@ } void IqRequest::CallCallback(const buzz::XmlElement* stanza) { - if (!callback_.is_null()) { - IqSender::ReplyCallback callback(callback_); - callback_.Reset(); - callback.Run(this, stanza); - } + if (!callback_.is_null()) + base::ResetAndReturn(&callback_).Run(this, stanza); } void IqRequest::OnTimeout() {
diff --git a/remoting/signaling/mock_signal_strategy.h b/remoting/signaling/mock_signal_strategy.h index c39eba73..3245931 100644 --- a/remoting/signaling/mock_signal_strategy.h +++ b/remoting/signaling/mock_signal_strategy.h
@@ -13,7 +13,7 @@ class MockSignalStrategy : public SignalStrategy { public: MockSignalStrategy(); - virtual ~MockSignalStrategy(); + ~MockSignalStrategy() override; MOCK_METHOD0(Connect, void()); MOCK_METHOD0(Disconnect, void()); @@ -27,7 +27,7 @@ // GMock currently doesn't support move-only arguments, so we have // to use this hack here. MOCK_METHOD1(SendStanzaPtr, bool(buzz::XmlElement* stanza)); - virtual bool SendStanza(scoped_ptr<buzz::XmlElement> stanza) override { + bool SendStanza(scoped_ptr<buzz::XmlElement> stanza) override { return SendStanzaPtr(stanza.release()); } };
diff --git a/remoting/test/access_token_fetcher.cc b/remoting/test/access_token_fetcher.cc index 4fa690e..a7f0dcb 100644 --- a/remoting/test/access_token_fetcher.cc +++ b/remoting/test/access_token_fetcher.cc
@@ -8,6 +8,7 @@ #include <vector> #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/thread_task_runner_handle.h" @@ -149,8 +150,8 @@ DVLOG(1) << "Access Token has been validated"; } - access_token_callback_.Run(access_token_, refresh_token_); - access_token_callback_.Reset(); + base::ResetAndReturn(&access_token_callback_) + .Run(access_token_, refresh_token_); } void AccessTokenFetcher::OnOAuthError() { @@ -159,8 +160,8 @@ access_token_.clear(); refresh_token_.clear(); - access_token_callback_.Run(access_token_, refresh_token_); - access_token_callback_.Reset(); + base::ResetAndReturn(&access_token_callback_) + .Run(access_token_, refresh_token_); } void AccessTokenFetcher::OnNetworkError(int response_code) { @@ -170,8 +171,8 @@ access_token_.clear(); refresh_token_.clear(); - access_token_callback_.Run(access_token_, refresh_token_); - access_token_callback_.Reset(); + base::ResetAndReturn(&access_token_callback_) + .Run(access_token_, refresh_token_); } void AccessTokenFetcher::ValidateAccessToken() {
diff --git a/remoting/test/app_remoting_test_driver.cc b/remoting/test/app_remoting_test_driver.cc index 57f29470..0d8af2b 100644 --- a/remoting/test/app_remoting_test_driver.cc +++ b/remoting/test/app_remoting_test_driver.cc
@@ -120,7 +120,7 @@ int main(int argc, char** argv) { testing::InitGoogleTest(&argc, argv); - TestSuite test_suite(argc, argv); + base::TestSuite test_suite(argc, argv); // The pointer returned here refers to a singleton, since we don't own the // lifetime of the object, don't wrap in a scoped_ptr construct or release it.
diff --git a/remoting/test/protocol_perftest.cc b/remoting/test/protocol_perftest.cc index 6401c46..6959edb 100644 --- a/remoting/test/protocol_perftest.cc +++ b/remoting/test/protocol_perftest.cc
@@ -235,9 +235,8 @@ GetParam().out_of_order_rate); scoped_ptr<protocol::TransportFactory> host_transport_factory( new protocol::LibjingleTransportFactory( - host_signaling_.get(), - port_allocator.Pass(), - network_settings)); + host_signaling_.get(), port_allocator.Pass(), network_settings, + protocol::TransportRole::SERVER)); scoped_ptr<protocol::SessionManager> session_manager( new protocol::JingleSessionManager(host_transport_factory.Pass())); @@ -306,9 +305,8 @@ GetParam().out_of_order_rate); scoped_ptr<protocol::TransportFactory> client_transport_factory( new protocol::LibjingleTransportFactory( - client_signaling_.get(), - port_allocator.Pass(), - network_settings)); + client_signaling_.get(), port_allocator.Pass(), network_settings, + protocol::TransportRole::CLIENT)); std::vector<protocol::AuthenticationMethod> auth_methods; auth_methods.push_back(protocol::AuthenticationMethod::Spake2(
diff --git a/remoting/test/remote_host_info_fetcher.cc b/remoting/test/remote_host_info_fetcher.cc index f2b0e8fd..e386bf8 100644 --- a/remoting/test/remote_host_info_fetcher.cc +++ b/remoting/test/remote_host_info_fetcher.cc
@@ -5,6 +5,7 @@ #include "remoting/test/remote_host_info_fetcher.h" #include "base/bind.h" +#include "base/callback_helpers.h" #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/logging.h" @@ -88,16 +89,14 @@ if (response_code != net::HTTP_OK) { LOG(ERROR) << "RemoteHostInfo request failed with error code: " << response_code; - remote_host_info_callback_.Run(remote_host_info); - remote_host_info_callback_.Reset(); + base::ResetAndReturn(&remote_host_info_callback_).Run(remote_host_info); return; } std::string response_string; if (!request_->GetResponseAsString(&response_string)) { LOG(ERROR) << "Failed to retrieve RemoteHostInfo response data"; - remote_host_info_callback_.Run(remote_host_info); - remote_host_info_callback_.Reset(); + base::ResetAndReturn(&remote_host_info_callback_).Run(remote_host_info); return; } @@ -106,8 +105,7 @@ if (!response_value || !response_value->IsType(base::Value::TYPE_DICTIONARY)) { LOG(ERROR) << "Failed to parse response string to JSON"; - remote_host_info_callback_.Run(remote_host_info); - remote_host_info_callback_.Reset(); + base::ResetAndReturn(&remote_host_info_callback_).Run(remote_host_info); return; } @@ -117,8 +115,7 @@ response->GetString("status", &remote_host_status); } else { LOG(ERROR) << "Failed to convert parsed JSON to a dictionary object"; - remote_host_info_callback_.Run(remote_host_info); - remote_host_info_callback_.Reset(); + base::ResetAndReturn(&remote_host_info_callback_).Run(remote_host_info); return; } @@ -133,8 +130,7 @@ response->GetString("sharedSecret", &remote_host_info.shared_secret); } - remote_host_info_callback_.Run(remote_host_info); - remote_host_info_callback_.Reset(); + base::ResetAndReturn(&remote_host_info_callback_).Run(remote_host_info); } } // namespace test
diff --git a/remoting/test/test_chromoting_client.cc b/remoting/test/test_chromoting_client.cc index adf1093..5f2e537 100644 --- a/remoting/test/test_chromoting_client.cc +++ b/remoting/test/test_chromoting_client.cc
@@ -191,7 +191,8 @@ scoped_ptr<protocol::TransportFactory> transport_factory( new protocol::LibjingleTransportFactory( - signal_strategy_.get(), port_allocator.Pass(), network_settings)); + signal_strategy_.get(), port_allocator.Pass(), network_settings, + protocol::TransportRole::CLIENT)); scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher> token_fetcher(new TokenFetcherProxy(
diff --git a/remoting/webapp/app_remoting/apps/sample_app/loading_splash.png b/remoting/webapp/app_remoting/apps/sample_app/loading_splash.png new file mode 100644 index 0000000..047e486f --- /dev/null +++ b/remoting/webapp/app_remoting/apps/sample_app/loading_splash.png Binary files differ
diff --git a/remoting/webapp/app_remoting/html/loading_window.css b/remoting/webapp/app_remoting/html/loading_window.css new file mode 100644 index 0000000..9d3ac43 --- /dev/null +++ b/remoting/webapp/app_remoting/html/loading_window.css
@@ -0,0 +1,40 @@ +/* Copyright (c) 2013 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. + */ + +body { + /* + * Ensure that the scrollWidth of the <html> element takes into account + * content outside the window borders. Without this, resizeWindowToContent + * cannot set the required window width. + */ + overflow: visible; + + /* Eliminate the gap between the background image and the message. */ + line-height: 0; +} + +.message-container { + padding: 20px; + line-height: 16px; +} + +body .message-container { + padding: 12px; +} + +body .button-row { + margin-top: 0; +} + +#splash-image { + -webkit-app-region: drag; +} + +#infobox { + margin-top: 10px; + margin-bottom: 10px; + position: fixed; + top: 0; +}
diff --git a/remoting/webapp/app_remoting/html/template_loading_window.html b/remoting/webapp/app_remoting/html/template_loading_window.html new file mode 100644 index 0000000..b69432e --- /dev/null +++ b/remoting/webapp/app_remoting/html/template_loading_window.html
@@ -0,0 +1,31 @@ +<!doctype html> +<!-- +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. +--> + +<html> + <head> + <meta charset="utf-8"> + <link rel="stylesheet" href="open_sans.css"> + <link rel="stylesheet" href="main.css"> + <link rel="stylesheet" href="loading_window.css"> + + <meta-include type="javascript"/> + + <title></title> + </head> + <body> + <img src="loading_splash.png" id="splash-image"> + <div class="message-container"> + <div id="title" hidden></div> + <p id="infobox" class="information-box"></p> + <div class="button-row"> + <span id="message"></span> + <button id="button-primary" autofocus="autofocus"></button> + <button id="button-secondary"></button> + </div> + </div> + </body> +</html>
diff --git a/remoting/webapp/app_remoting/js/app_connected_view.js b/remoting/webapp/app_remoting/js/app_connected_view.js index a676551..73c3088 100644 --- a/remoting/webapp/app_remoting/js/app_connected_view.js +++ b/remoting/webapp/app_remoting/js/app_connected_view.js
@@ -122,7 +122,7 @@ var hostSize = { width: hostDesktop.width, height: hostDesktop.height }; var hostDpi = { x: hostDesktop.xDpi, y: hostDesktop.yDpi }; var clientArea = { width: window.innerWidth, height: window.innerHeight }; - var newSize = remoting.DesktopViewport.choosePluginSize( + var newSize = remoting.Viewport.choosePluginSize( clientArea, window.devicePixelRatio, hostSize, hostDpi, this.host_.options.desktopScale, true /* fullscreen */ , true /* shrinkToFit */ );
diff --git a/remoting/webapp/app_remoting/js/app_remoting.js b/remoting/webapp/app_remoting/js/app_remoting.js index cbb1506..65bc53ef 100644 --- a/remoting/webapp/app_remoting/js/app_remoting.js +++ b/remoting/webapp/app_remoting/js/app_remoting.js
@@ -48,7 +48,7 @@ */ remoting.AppRemoting.prototype.signInFailed_ = function(error) { remoting.MessageWindow.showErrorMessage( - chrome.i18n.getMessage(/*i18n-content*/'CONNECTION_FAILED'), + this.getApplicationName(), chrome.i18n.getMessage(error.getTag())); };
diff --git a/remoting/webapp/app_remoting/js/app_remoting_activity.js b/remoting/webapp/app_remoting/js/app_remoting_activity.js index fecd55d5..8afef921 100644 --- a/remoting/webapp/app_remoting/js/app_remoting_activity.js +++ b/remoting/webapp/app_remoting/js/app_remoting_activity.js
@@ -140,12 +140,18 @@ session.connect(host, credentialsProvider); }); } else if (response && response.status == 'pending') { - this.onError(new remoting.Error( + this.onConnectionFailed(new remoting.Error( remoting.Error.Tag.SERVICE_UNAVAILABLE)); } } else { console.error('Invalid "runApplication" response from server.'); - this.onError(remoting.Error.fromHttpStatus(xhrResponse.status)); + // The orchestrator returns 403 if the user is not whitelisted to run the + // app, which gets translated to a generic error message, so pick something + // a bit more user-friendly. + var error = xhrResponse.status == 403 ? + new remoting.Error(remoting.Error.Tag.APP_NOT_AUTHORIZED) : + remoting.Error.fromHttpStatus(xhrResponse.status); + this.onConnectionFailed(error); } }; @@ -166,28 +172,36 @@ } }; -remoting.AppRemotingActivity.prototype.onDisconnected = function() { +/** + * @param {remoting.Error} error + */ +remoting.AppRemotingActivity.prototype.onDisconnected = function(error) { + if (error.isNone()) { + chrome.app.window.current().close(); + } else { + this.showErrorMessage_(error); + } this.cleanup_(); - chrome.app.window.current().close(); }; /** * @param {!remoting.Error} error */ remoting.AppRemotingActivity.prototype.onConnectionFailed = function(error) { - this.onError(error); + remoting.LoadingWindow.close(); + this.showErrorMessage_(error); + this.cleanup_(); }; /** * @param {!remoting.Error} error The error to be localized and displayed. + * @private */ -remoting.AppRemotingActivity.prototype.onError = function(error) { +remoting.AppRemotingActivity.prototype.showErrorMessage_ = function(error) { console.error('Connection failed: ' + error.toString()); - remoting.LoadingWindow.close(); remoting.MessageWindow.showErrorMessage( - chrome.i18n.getMessage(/*i18n-content*/'CONNECTION_FAILED'), + remoting.app.getApplicationName(), chrome.i18n.getMessage(error.getTag())); - this.cleanup_(); }; })();
diff --git a/remoting/webapp/app_remoting/js/loading_window.js b/remoting/webapp/app_remoting/js/loading_window.js index b14f19db..e70c35e 100644 --- a/remoting/webapp/app_remoting/js/loading_window.js +++ b/remoting/webapp/app_remoting/js/loading_window.js
@@ -42,19 +42,22 @@ // Timeout is currently 15min to handle when we need to spin up a new VM. var kConnectionTimeout = 15 * 60 * 1000; + var options = /** @type {remoting.MessageWindowOptions} */ ({ + title: remoting.app.getApplicationName(), + message: chrome.i18n.getMessage(/*i18n-content*/'FOOTER_CONNECTING'), + buttonLabel: chrome.i18n.getMessage(/*i18n-content*/'CANCEL'), + onResult: remoting.MessageWindow.quitApp, + duration: kConnectionTimeout, + onTimeout: remoting.LoadingWindow.onTimeout_, + htmlFile: 'loading_window.html', + frame: 'none' + }); var transparencyWarning = ''; if (remoting.platformIsMac()) { - transparencyWarning = + options.infoBox = chrome.i18n.getMessage(/*i18n-content*/'NO_TRANSPARENCY_WARNING'); } - remoting.loadingWindow_ = remoting.MessageWindow.showTimedMessageWindow( - remoting.app.getApplicationName(), - chrome.i18n.getMessage(/*i18n-content*/'FOOTER_CONNECTING'), - transparencyWarning, - chrome.i18n.getMessage(/*i18n-content*/'CANCEL'), - remoting.MessageWindow.quitApp, - kConnectionTimeout, - remoting.LoadingWindow.onTimeout_); + remoting.loadingWindow_ = new remoting.MessageWindow(options); }; /**
diff --git a/remoting/webapp/app_remoting/manifest_common.json.jinja2 b/remoting/webapp/app_remoting/manifest_common.json.jinja2 index 17040bdd..b0c2676 100644 --- a/remoting/webapp/app_remoting/manifest_common.json.jinja2 +++ b/remoting/webapp/app_remoting/manifest_common.json.jinja2
@@ -27,7 +27,6 @@ "clipboardRead", "clipboardWrite", "contextMenus", - "experimental", "fileSystem", "fullscreen", "https://relay.google.com/*",
diff --git a/remoting/webapp/base/html/message_window.css b/remoting/webapp/base/html/message_window.css index a053df3..2c16db1 100644 --- a/remoting/webapp/base/html/message_window.css +++ b/remoting/webapp/base/html/message_window.css
@@ -11,7 +11,3 @@ margin-top: 10px; margin-bottom: 10px; } - -.insetList { - list-style-position: inside; -} \ No newline at end of file
diff --git a/remoting/webapp/base/js/base.js b/remoting/webapp/base/js/base.js index 3be8c8fb..48e2a84 100644 --- a/remoting/webapp/base/js/base.js +++ b/remoting/webapp/base/js/base.js
@@ -783,14 +783,27 @@ }; /** - * Size the current window to fit its content vertically. + * Size the current window to fit its content. + * @param {boolean=} opt_centerWindow If true, position the window in the + * center of the screen after resizing it. */ -base.resizeWindowToContent = function() { +base.resizeWindowToContent = function(opt_centerWindow) { var appWindow = chrome.app.window.current(); var outerBounds = appWindow.outerBounds; + var borderX = outerBounds.width - appWindow.innerBounds.width; var borderY = outerBounds.height - appWindow.innerBounds.height; - appWindow.resizeTo(outerBounds.width, document.body.clientHeight + borderY); + var newWidth = document.documentElement.scrollWidth + borderX; + var newHeight = document.documentElement.scrollHeight + borderY; + appWindow.resizeTo(newWidth, newHeight); + var left = outerBounds.left; + var top = outerBounds.top; + if (opt_centerWindow) { + var screenWidth = screen.availWidth; + var screenHeight = screen.availHeight; + left = (screenWidth - newWidth) / 2; + top = (screenHeight - newHeight) / 2; + } // Sometimes, resizing the window causes its position to be reset to (0, 0), - // so restore it explicitly. - appWindow.moveTo(outerBounds.left, outerBounds.top); + // so restore it explicitly, even if it doesn't need to be centered. + appWindow.moveTo(left, top); };
diff --git a/remoting/webapp/base/js/message_window.js b/remoting/webapp/base/js/message_window.js index 452b95ee..f110e6f 100644 --- a/remoting/webapp/base/js/message_window.js +++ b/remoting/webapp/base/js/message_window.js
@@ -144,7 +144,7 @@ var messageDiv = document.getElementById('message'); messageDiv.innerText = message; - base.resizeWindowToContent(); + base.resizeWindowToContent(true); break; default:
diff --git a/remoting/webapp/base/js/message_window_helper.js b/remoting/webapp/base/js/message_window_helper.js index a4d564d..90267add 100644 --- a/remoting/webapp/base/js/message_window_helper.js +++ b/remoting/webapp/base/js/message_window_helper.js
@@ -32,6 +32,12 @@ /** @type {?function():void} */ this.onTimeout = function() {}; + + /** @type {string} */ + this.htmlFile = ''; + + /** @type {string} */ + this.frame = ''; }; /** @@ -93,7 +99,8 @@ width: 400, height: 100 }, - resizable: false + resizable: false, + frame: options.frame || 'chrome' }; /** @type {remoting.MessageWindow} */ @@ -108,7 +115,8 @@ appWindow.contentWindow.addEventListener('load', onLoad, false); }; - chrome.app.window.create('message_window.html', windowAttributes, onCreate); + var htmlFile = options.htmlFile || 'message_window.html'; + chrome.app.window.create(htmlFile, windowAttributes, onCreate); if (duration != 0) { this.timer_ = window.setTimeout(this.onTimeoutHandler_.bind(this), @@ -258,34 +266,6 @@ }; /** - * Static method to create and show a timed message box. - * - * @param {string} title The title of the message box. - * @param {string} message The message. - * @param {string} infobox Additional information to be displayed in an infobox, - * or the empty string if there is no additional information. - * @param {string} buttonLabel The text for the primary button. - * @param {function(number):void} onResult The callback to invoke when the - * user closes the message window. - * @param {number} duration Time for wait before calling onTime - * @param {?function():void} onTimeout Callback function. - * @return {remoting.MessageWindow} - */ -remoting.MessageWindow.showTimedMessageWindow = function( - title, message, infobox, buttonLabel, onResult, duration, onTimeout) { - var options = /** @type {remoting.MessageWindowOptions} */ ({ - title: title, - message: message, - infobox: infobox, - buttonLabel: buttonLabel, - onResult: onResult, - duration: duration, - onTimeout: onTimeout - }); - return new remoting.MessageWindow(options); -}; - -/** * Cancel the current connection and close all app windows. * * @param {number} result The dialog result.
diff --git a/remoting/webapp/base/js/modal_dialogs.js b/remoting/webapp/base/js/modal_dialogs.js index f8837e5..9c489b3 100644 --- a/remoting/webapp/base/js/modal_dialogs.js +++ b/remoting/webapp/base/js/modal_dialogs.js
@@ -56,17 +56,17 @@ /** @return {HTMLElement} */ remoting.InputDialog.prototype.inputField = function() { return this.inputField_; -} +}; /** @private */ remoting.InputDialog.prototype.onSubmit_ = function() { this.deferred_.resolve(this.inputField_.value); -} +}; /** @private */ remoting.InputDialog.prototype.onCancel_ = function() { this.deferred_.reject(new remoting.Error(remoting.Error.Tag.CANCELLED)); -} +}; /** * @param {function():void} handler @@ -97,7 +97,9 @@ * @param {remoting.AppMode} mode * @param {HTMLElement} primaryButton * @param {HTMLElement=} opt_secondaryButton + * * @constructor + * @implements {base.Disposable} */ remoting.MessageDialog = function(mode, primaryButton, opt_secondaryButton) { /** @private @const */ @@ -136,6 +138,15 @@ return this.deferred_.promise(); }; +remoting.MessageDialog.prototype.dispose = function() { + base.dispose(this.eventHooks_); + this.eventHooks_ = null; + if (this.deferred_) { + this.deferred_.reject(new remoting.Error(remoting.Error.Tag.CANCELLED)); + } + this.deferred_ = null; +}; + /** * @param {remoting.MessageDialog.Result} result * @return {Function} @@ -143,9 +154,35 @@ */ remoting.MessageDialog.prototype.onClicked_ = function(result) { this.deferred_.resolve(result); - base.dispose(this.eventHooks_); - this.eventHooks_ = null; this.deferred_ = null; + this.dispose(); +}; + +/** + * @param {Function} cancelCallback The callback to invoke when the user clicks + * on the cancel button. + * @constructor + */ +remoting.ConnectingDialog = function(cancelCallback) { + /** @private */ + this.dialog_ = new remoting.MessageDialog( + remoting.AppMode.CLIENT_CONNECTING, + document.getElementById('cancel-connect-button')); + /** @private */ + this.onCancel_ = cancelCallback; +}; + +remoting.ConnectingDialog.prototype.show = function() { + var that = this; + this.dialog_.show().then(function() { + remoting.setMode(remoting.AppMode.HOME); + that.onCancel_(); + // The promise rejects when the dialog is hidden. Don't report that as error. + }).catch(remoting.Error.handler(base.doNothing)); +}; + +remoting.ConnectingDialog.prototype.hide = function() { + this.dialog_.dispose(); }; })();
diff --git a/remoting/webapp/base/js/viewport.js b/remoting/webapp/base/js/viewport.js new file mode 100644 index 0000000..8f35cff --- /dev/null +++ b/remoting/webapp/base/js/viewport.js
@@ -0,0 +1,153 @@ +// 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 + * Provides shared view port management utilities. + */ + +/** @suppress {duplicate} */ +var remoting = remoting || {}; + +(function() { + +'use strict'; + +/** @type {Object} */ +remoting.Viewport = {}; + +/** + * Helper function accepting client and host dimensions, and returning a chosen + * size for the plugin element, in DIPs. + * + * @param {{width: number, height: number}} clientSizeDips Available client + * dimensions, in DIPs. + * @param {number} clientPixelRatio Number of physical pixels per client DIP. + * @param {{width: number, height: number}} desktopSize Size of the host desktop + * in physical pixels. + * @param {{x: number, y: number}} desktopDpi DPI of the host desktop in both + * dimensions. + * @param {number} desktopScale The scale factor configured for the host. + * @param {boolean} isFullscreen True if full-screen mode is active. + * @param {boolean} shrinkToFit True if shrink-to-fit should be applied. + * @return {{width: number, height: number}} Chosen plugin dimensions, in DIPs. + */ +remoting.Viewport.choosePluginSize = function( + clientSizeDips, clientPixelRatio, desktopSize, desktopDpi, desktopScale, + isFullscreen, shrinkToFit) { + base.debug.assert(clientSizeDips.width > 0); + base.debug.assert(clientSizeDips.height > 0); + base.debug.assert(clientPixelRatio >= 1.0); + base.debug.assert(desktopSize.width > 0); + base.debug.assert(desktopSize.height > 0); + base.debug.assert(desktopDpi.x > 0); + base.debug.assert(desktopDpi.y > 0); + base.debug.assert(desktopScale > 0); + + // We have the following goals in sizing the desktop display at the client: + // 1. Avoid losing detail by down-scaling beyond 1:1 host:device pixels. + // 2. Avoid up-scaling if that will cause the client to need scrollbars. + // 3. Avoid introducing blurriness with non-integer up-scaling factors. + // 4. Avoid having huge "letterboxes" around the desktop, if it's really + // small. + // 5. Compensate for mismatched DPIs, so that the behaviour of features like + // shrink-to-fit matches their "natural" rather than their pixel size. + // e.g. with shrink-to-fit active a 1024x768 low-DPI host on a 640x480 + // high-DPI client will be up-scaled to 1280x960, rather than displayed + // at 1:1 host:physical client pixels. + // + // To determine the ideal size we follow a four-stage process: + // 1. Determine the "natural" size at which to display the desktop. + // a. Initially assume 1:1 mapping of desktop to client device pixels. + // b. If host DPI is less than the client's then up-scale accordingly. + // c. If desktopScale is configured for the host then allow that to + // reduce the amount of up-scaling from (b). e.g. if the client:host + // DPIs are 2:1 then a desktopScale of 1.5 would reduce the up-scale + // to 4:3, while a desktopScale of 3.0 would result in no up-scaling. + // 2. If the natural size of the desktop is smaller than the client device + // then apply up-scaling by an integer scale factor to avoid excessive + // letterboxing. + // 3. If shrink-to-fit is configured then: + // a. If the natural size exceeds the client size then apply down-scaling + // by an arbitrary scale factor. + // b. If we're in full-screen mode and the client & host aspect-ratios + // are radically different (e.g. the host is actually multi-monitor) + // then shrink-to-fit to the shorter dimension, rather than leaving + // huge letterboxes; the user can then bump-scroll around the desktop. + // 4. If the overall scale factor is fractionally over an integer factor + // then reduce it to that integer factor, to avoid blurring. + + // All calculations are performed in device pixels. + var clientWidth = clientSizeDips.width * clientPixelRatio; + var clientHeight = clientSizeDips.height * clientPixelRatio; + + // 1. Determine a "natural" size at which to display the desktop. + var scale = 1.0; + + // Determine the effective host device pixel ratio. + // Note that we round up or down to the closest integer pixel ratio. + var hostPixelRatioX = Math.round(desktopDpi.x / 96); + var hostPixelRatioY = Math.round(desktopDpi.y / 96); + var hostPixelRatio = Math.min(hostPixelRatioX, hostPixelRatioY); + + // Allow up-scaling to account for DPI. + scale = Math.max(scale, clientPixelRatio / hostPixelRatio); + + // Allow some or all of the up-scaling to be cancelled by the desktopScale. + if (desktopScale > 1.0) { + scale = Math.max(1.0, scale / desktopScale); + } + + // 2. If the host is still much smaller than the client, then up-scale to + // avoid wasting space, but only by an integer factor, to avoid blurring. + if (desktopSize.width * scale <= clientWidth && + desktopSize.height * scale <= clientHeight) { + var scaleX = Math.floor(clientWidth / desktopSize.width); + var scaleY = Math.floor(clientHeight / desktopSize.height); + scale = Math.min(scaleX, scaleY); + base.debug.assert(scale >= 1.0); + } + + // 3. Apply shrink-to-fit, if configured. + if (shrinkToFit) { + var scaleFitWidth = Math.min(scale, clientWidth / desktopSize.width); + var scaleFitHeight = Math.min(scale, clientHeight / desktopSize.height); + scale = Math.min(scaleFitHeight, scaleFitWidth); + + // If we're running full-screen then try to handle common side-by-side + // multi-monitor combinations more intelligently. + if (isFullscreen) { + // If the host has two monitors each the same size as the client then + // scale-to-fit will have the desktop occupy only 50% of the client area, + // in which case it would be preferable to down-scale less and let the + // user bump-scroll around ("scale-and-pan"). + // Triggering scale-and-pan if less than 65% of the client area would be + // used adds enough fuzz to cope with e.g. 1280x800 client connecting to + // a (2x1280)x1024 host nicely. + // Note that we don't need to account for scrollbars while fullscreen. + if (scale <= scaleFitHeight * 0.65) { + scale = scaleFitHeight; + } + if (scale <= scaleFitWidth * 0.65) { + scale = scaleFitWidth; + } + } + } + + // 4. Avoid blurring for close-to-integer up-scaling factors. + if (scale > 1.0) { + var scaleBlurriness = scale / Math.floor(scale); + if (scaleBlurriness < 1.1) { + scale = Math.floor(scale); + } + } + + // Return the necessary plugin dimensions in DIPs. + scale = scale / clientPixelRatio; + var pluginWidth = Math.round(desktopSize.width * scale); + var pluginHeight = Math.round(desktopSize.height * scale); + return { width: pluginWidth, height: pluginHeight }; +}; + +}());
diff --git a/remoting/webapp/base/js/viewport_unittest.js b/remoting/webapp/base/js/viewport_unittest.js new file mode 100644 index 0000000..71d9d88 --- /dev/null +++ b/remoting/webapp/base/js/viewport_unittest.js
@@ -0,0 +1,329 @@ +// 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. + +(function() { + +'use strict'; + +/** + * @param {number} width + * @param {number} height + * @return {{width:number, height:number}} + */ +function size(width, height) { + return {width: width, height: height}; +} + +/** + * @param {number} x + * @param {number} y + * @return {{x:number, y:number}} + */ +function dpi(x, y) { + return {x: x, y: y}; +} + +QUnit.module('Viewport'); + +QUnit.test('choosePluginSize() handles low-DPI client & host', + function(assert) { + // 1. Client & host size the same. + var pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(640, 480), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 480)); + + // 2. Client logical dimensions smaller than host's. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(1024, 600), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); + + // 3. Client Y dimension larger than host's, X dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 640), 1.0, size(1024, 600), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); + + // 4. Client dimensions larger than host's by <2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 900), 1.0, size(640, 480), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 480)); + + // 5. Client dimensions larger than host's by >2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 1024), 1.0, size(640, 480), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(2 * 640, 2 * 480)); + + // 6. Client X dimension larger than host's, Y dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(1152, 600), 1.0, size(1024, 768), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 * (600 / 768), 600)); +}); + +QUnit.test('choosePluginSize() handles high-DPI client, low-DPI host', + function(assert) { + // 1. Client & host size the same. + var pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(640, 480), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 480)); + + // 2. Client logical dimensions smaller than host's. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(1024, 600), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); + + // 3. Client Y dimension larger than host's, X dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 640), 2.0, size(1024, 600), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); + + // 4. Client logical dimensions larger than host's by <2x. + // Host dimensions fit into the client's _device_ dimensions 3x, so the + // size in client DIPs should be 1:3/2. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 900), 2.0, size(640, 480), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(640 * 3 / 2.0, 480 * 3 / 2.0)); + + // 5. Client dimensions larger than host's by >2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 1024), 2.0, size(640, 480), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); + + // 6. Client X dimension larger than host's, Y dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(1152, 600), 2.0, size(1024, 768), dpi(96, 96), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 * (600 / 768), 600)); +}); + +QUnit.test('choosePluginSize() handles low-DPI client, high-DPI host', + function(assert) { + // 1. Client & host size the same. + var pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(640, 480), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 480)); + + // 2. Client logical dimensions smaller than host's. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(1024, 600), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); + + // 3. Client Y dimension larger than host's, X dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 640), 1.0, size(1024, 600), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); + + // 4. Client dimensions larger than host's by <2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 900), 1.0, size(640, 480), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 480)); + + // 5. Client dimensions larger than host's by >2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 1024), 1.0, size(640, 480), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); + + // 6. Client X dimension larger than host's, Y dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(1152, 600), 1.0, size(1024, 768), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 * (600 / 768), 600)); +}); + +QUnit.test('choosePluginSize() handles high-DPI client and host', + function(assert) { + // 1. Client & host size the same. + var pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(640, 480), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 480)); + + // 2. Client logical dimensions smaller than host's. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(1024, 600), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 / 2.0, 600 / 2.0)); + + // 3. Client Y dimension larger than host's, X dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 640), 2.0, size(1024, 600), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 / 2.0, 600 / 2.0)); + + // 4. Client logical dimensions larger than host's by <2x. + // Host dimensions fit into the client's _device_ dimensions 3x, so the + // size in client DIPs should be 1:3/2. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 900), 2.0, size(640, 480), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(640 * 3 / 2.0, 480 * 3 / 2.0)); + + // 5. Client dimensions larger than host's by >2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 1024), 2.0, size(640, 480), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); + + // 6. Client X dimension larger than host's, Y dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(1152, 600), 2.0, size(1024, 768), dpi(192, 192), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 / 2.0, 768 / 2.0)); +}); + +QUnit.test('choosePluginSize() handles high-DPI client, 150% DPI host', + function(assert) { + // 1. Client & host size the same. + var pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(640, 480), dpi(144, 144), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 480)); + + // 2. Client dimensions smaller than host's. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(1024, 600), dpi(144, 144), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 / 2.0, 600 / 2.0)); + + // 3. Client Y dimension larger than host's, X dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 640), 2.0, size(1024, 600), dpi(144, 144), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 / 2.0, 600 / 2.0)); + + // 4. Client dimensions larger than host's by <2x. + // Host dimensions fit into the client's _device_ dimensions 3x, so the + // size in client DIPs should be 1:3/2. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 900), 2.0, size(640, 480), dpi(144, 144), 1.0, false, true); + assert.deepEqual(pluginSize, size(640 * 3 / 2.0, 480 * 3 / 2.0)); + + // 5. Client dimensions larger than host's by >2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 1024), 2.0, size(640, 480), dpi(144, 144), 1.0, false, true); + assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); + + // 6. Client X dimension larger than host's, Y dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(1152, 600), 2.0, size(1024, 768), dpi(144, 144), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 / 2.0, 768 / 2.0)); +}); + +QUnit.test('choosePluginSize() handles high-DPI client, 125% DPI host', + function(assert) { + // 1. Client & host size the same. + var pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(640, 480), dpi(120, 120), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 480)); + + // 2. Client dimensions smaller than host's. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(1024, 600), dpi(120, 120), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 600 * (640 / 1024))); + + // 3. Client Y dimension larger than host's, X dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 640), 2.0, size(1024, 600), dpi(120, 120), 1.0, false, true); + assert.deepEqual(pluginSize, size(640, 600 * (640 / 1024))); + + // 4. Client dimensions larger than host's by <2x. + // Host dimensions fit into the client's _device_ dimensions 3x, so the + // size in client DIPs should be 1:3/2. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 900), 2.0, size(640, 480), dpi(120, 120), 1.0, false, true); + assert.deepEqual(pluginSize, size(640 * 3 / 2.0, 480 * 3 / 2.0)); + + // 5. Client dimensions larger than host's by >2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 1024), 2.0, size(640, 480), dpi(120, 120), 1.0, false, true); + assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); + + // 6. Client X dimension larger than host's, Y dimension smaller. + pluginSize = remoting.Viewport.choosePluginSize( + size(1152, 600), 2.0, size(1024, 768), dpi(120, 120), 1.0, false, true); + assert.deepEqual(pluginSize, size(1024 * (600 / 768), 600)); +}); + +QUnit.test('choosePluginSize() with shrink-to-fit disabled', + function(assert) { + // 1. Client & host size the same. + var pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(640, 480), dpi(96, 96), 1.0, false, false); + assert.deepEqual(pluginSize, size(640, 480)); + + // 2. Client logical dimensions smaller than host's. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(1024, 600), dpi(96, 96), 1.0, false, false); + assert.deepEqual(pluginSize, size(1024, 600)); + + // 3. Client dimensions larger than host's by <2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 900), 1.0, size(640, 480), dpi(96, 96), 1.0, false, false); + assert.deepEqual(pluginSize, size(640, 480)); + + // 4. Client dimensions larger than host's by >2x. + pluginSize = remoting.Viewport.choosePluginSize( + size(1280, 1024), 1.0, size(640, 480), dpi(96, 96), 1.0, false, false); + assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); + + // 5. Client smaller than host, client high-DPI, host low-DPI. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(1024, 600), dpi(96, 96), 1.0, false, false); + assert.deepEqual(pluginSize, size(1024, 600)); + + // 6. Client smaller than host, client low-DPI, host high-DPI. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(1024, 600), dpi(192, 192), 1.0, false, false); + assert.deepEqual(pluginSize, size(1024, 600)); + + // 7. Client smaller than host, both high-DPI. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(1024, 600), dpi(192, 192), 1.0, false, false); + assert.deepEqual(pluginSize, size(512, (512 / 1024) * 600)); + + // 8. Client smaller than host, client high-DPI, host 150% DPI. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(1024, 600), dpi(144, 144), 1.0, false, false); + assert.deepEqual(pluginSize, size(512, (512 / 1024) * 600)); +}); + +QUnit.test('choosePluginSize() full-screen multi-monitor optimization', + function(assert) { + // Each test has a host sized to approximate two or more monitors. + + // 1. Client & host per-monitor dimensions match, two monitors side-by-side. + var pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(2 * 640, 480), dpi(96, 96), 1.0, true, true); + assert.deepEqual(pluginSize, size(2 * 640, 480)); + + // 2. Client & host per-monitor dimensions match, two monitors stacked. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(640, 2 * 480), dpi(96, 96), 1.0, true, true); + assert.deepEqual(pluginSize, size(640, 2 * 480)); + + // 3. Client larger, two monitors stacked. + pluginSize = remoting.Viewport.choosePluginSize( + size(1024, 768), 1.0, size(640, 2 * 480), dpi(96, 96), 1.0, true, true); + assert.deepEqual(pluginSize, size(640 * (768 / (2 * 480)), 768)); + + // 4. Client smaller, two monitors stacked. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(1024, 2 * 768), dpi(96, 96), 1.0, true, true); + assert.deepEqual(pluginSize, size(640, 2 * 768 * (640 / 1024))); + + // 5. Client wide-screen, host two standard monitors stacked. + pluginSize = remoting.Viewport.choosePluginSize( + size(1920, 1080), 1.0, size(1024, 2 * 768), dpi(96, 96), 1.0, + true, true); + assert.deepEqual(pluginSize, size(1024 * (1080 / (2 * 768)), 1080)); + + // 6. Client & host per-monitor dimensions match, two monitors stacked, + // high-DPI client. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(640, 2 * 480), dpi(96, 96), 1.0, true, true); + assert.deepEqual(pluginSize, size(640, 2 * 480)); + + // 7. Client & host per-monitor dimensions match, two monitors stacked, + // high-DPI host. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 1.0, size(640, 2 * 480), dpi(192, 192), + 1.0, true, true); + assert.deepEqual(pluginSize, size(640, 2 * 480)); + + // 8. Client & host per-monitor dimensions match, two monitors stacked, + // high-DPI client & host. + pluginSize = remoting.Viewport.choosePluginSize( + size(640, 480), 2.0, size(640, 2 * 480), dpi(192, 192), + 1.0, true, true); + assert.deepEqual(pluginSize, size(640 / 2.0, (2 * 480) / 2.0)); +}); + +})();
diff --git a/remoting/webapp/browser_test/bump_scroll_browser_test.js b/remoting/webapp/browser_test/bump_scroll_browser_test.js index a90d5b1..38eea467 100644 --- a/remoting/webapp/browser_test/bump_scroll_browser_test.js +++ b/remoting/webapp/browser_test/bump_scroll_browser_test.js
@@ -84,7 +84,16 @@ if (!base.isAppsV2()) { browserTest.fail( 'Bump-scroll requires full-screen, which can only be activated ' + - 'programmatically in apps v2.') + 'programmatically in apps v2.'); + } + + var mockConnection = new remoting.MockConnection(); + mockConnection.plugin().mock$useDefaultBehavior( + remoting.MockClientPlugin.AuthMethod.PIN); + + function cleanup() { + mockConnection.restore(); + browserTest.disconnect(); } this.testVerifyScroll().then(function() { @@ -109,11 +118,11 @@ this.scrollDirection.bind(this, 0.5, 0.0) // Top edge ).then( function(value) { - browserTest.disconnect(); + cleanup(); return browserTest.pass(value); }, function(error) { - browserTest.disconnect(); + cleanup(); return browserTest.fail(error); } );
diff --git a/remoting/webapp/build-webapp.py b/remoting/webapp/build-webapp.py index 979b593..9ed59d8 100755 --- a/remoting/webapp/build-webapp.py +++ b/remoting/webapp/build-webapp.py
@@ -109,7 +109,8 @@ def buildWebApp(buildtype, version, destination, zip_path, manifest_template, webapp_type, appid, app_client_id, app_name, app_description, app_capabilities, manifest_key, files, - locales_listfile, jinja_paths, service_environment, use_gcd): + files_listfile, locales_listfile, jinja_paths, + service_environment, use_gcd): """Does the main work of building the webapp directory and zipfile. Args: @@ -121,8 +122,8 @@ manifest_template: jinja2 template file for manifest. webapp_type: webapp type ("v1", "v2", "v2_pnacl" or "app_remoting"). appid: A string with the Remoting Application Id (only used for app - remoting webapps). If supplied, it defaults to using the - test API server. + remoting webapps). If supplied, it defaults to using the + test API server. app_client_id: The OAuth2 client ID for the webapp. app_name: A string with the name of the application. app_description: A string with the description of the application. @@ -131,9 +132,14 @@ manifest_key: The manifest key for the webapp. files: An array of strings listing the paths for resources to include in this webapp. + files_listfile: The name of a file containing a list of files, one per + line, identifying the resources to include in this webapp. + This is an alternate to specifying the files directly via + the 'files' option. The files listed in this file are + appended to the files passed via the 'files' option, if any. locales_listfile: The name of a file containing a list of locales, one per - line, which are copied, along with their directory structure, from - the _locales directory down. + line, which are copied, along with their directory + structure, from the _locales directory down. jinja_paths: An array of paths to search for {%include} directives in addition to the directory containing the manifest template. service_environment: Used to point the webapp to one of the @@ -149,6 +155,12 @@ for s in input: locales.append(s.rstrip()) + # Load the files from the files_listfile. + if files_listfile: + with open(files_listfile) as input: + for s in input: + files.append(s.rstrip()) + # Ensure a fresh directory. try: shutil.rmtree(destination) @@ -350,6 +362,7 @@ # For overriding the client ID/secret via env vars, see google_api_keys.py. apiClientId = google_api_keys.GetClientID('REMOTING') apiClientSecret = google_api_keys.GetClientSecret('REMOTING') + apiKey = google_api_keys.GetAPIKeyRemoting() if is_app_remoting_webapp and buildtype != 'Dev': if not app_client_id: @@ -361,6 +374,7 @@ replaceString(destination, 'API_CLIENT_ID', apiClientId) replaceString(destination, 'API_CLIENT_SECRET', apiClientSecret) + replaceString(destination, 'API_KEY', apiKey) # Write the application capabilities. appCapabilities = ','.join( @@ -437,6 +451,7 @@ parser.add_argument('--appid') parser.add_argument('--app_client_id', default='') parser.add_argument('--manifest_key', default='') + parser.add_argument('--files_listfile', default='', metavar='PATH') parser.add_argument('--locales_listfile', default='', metavar='PATH') parser.add_argument('--jinja_paths', nargs='*', default=[], metavar='PATH') parser.add_argument('--service_environment', default='', metavar='ENV')
diff --git a/remoting/webapp/build_template.gni b/remoting/webapp/build_template.gni index d1e2265..70ff555 100644 --- a/remoting/webapp/build_template.gni +++ b/remoting/webapp/build_template.gni
@@ -72,6 +72,16 @@ "$target_gen_dir/wcs_sandbox.html", ] + # Create a file that contains a list of all the resource files needed + # to build the webapp. This is needed to avoid problems on platforms that + # limit the size of a command line. + file_list = "$target_gen_dir/${target_name}_file_list.txt" + files = [] + files += rebase_path(generated_html_files, root_build_dir) + files += rebase_path(remoting_webapp_crd_files, root_build_dir) + files += rebase_path(extra_files, root_build_dir) + write_file(file_list, files) + args = [ buildtype, version_full, @@ -80,9 +90,10 @@ rebase_path("crd/manifest.json.jinja2", root_build_dir), webapp_type, ] - args += rebase_path(generated_html_files, root_build_dir) - args += rebase_path(remoting_webapp_crd_files, root_build_dir) - args += rebase_path(extra_files, root_build_dir) + args += [ + "--files_listfile", + rebase_path(file_list, root_build_dir), + ] args += [ "--locales_listfile", listfile_rel,
diff --git a/remoting/webapp/crd/js/client_session.js b/remoting/webapp/crd/js/client_session.js index 8a6bdb87..a51f7a5 100644 --- a/remoting/webapp/crd/js/client_session.js +++ b/remoting/webapp/crd/js/client_session.js
@@ -88,17 +88,15 @@ /** @enum {string} */ remoting.ClientSession.Events = { - stateChanged: 'stateChanged', // deprecated. - videoChannelStateChanged: 'videoChannelStateChanged', + videoChannelStateChanged: 'videoChannelStateChanged' }; /** * @interface * [START]-------> [onConnected] ------> [onDisconnected] - * | | - * |-----> [OnConnectionFailed] |----> [onError] + * | + * |-----> [OnConnectionFailed] * - * TODO(kelvinp): Route session state changes through this interface. */ remoting.ClientSession.EventHandler = function() {}; @@ -112,7 +110,7 @@ /** * Called when a new session has been connected. The |connectionInfo| will be - * valid until onDisconnected() or onError() is called. + * valid until onDisconnected() is called. * * @param {!remoting.ConnectionInfo} connectionInfo */ @@ -121,14 +119,12 @@ /** * Called when the current session has been disconnected. + * + * @param {!remoting.Error} reason Reason that the session is disconnected. + * Set to remoting.Error.none() if there is no error. */ -remoting.ClientSession.EventHandler.prototype.onDisconnected = function() {}; - -/** - * Called when an error needs to be displayed to the user. - * @param {!remoting.Error} error - */ -remoting.ClientSession.EventHandler.prototype.onError = function(error) {}; +remoting.ClientSession.EventHandler.prototype.onDisconnected = + function(reason) {}; // Note that the positive values in both of these enums are copied directly // from connection_to_host.h and must be kept in sync. Code in @@ -165,19 +161,6 @@ return remoting.ClientSession.State[state]; }; -/** - @param {remoting.ClientSession.State} current - @param {remoting.ClientSession.State} previous - @constructor -*/ -remoting.ClientSession.StateEvent = function(current, previous) { - /** @type {remoting.ClientSession.State} */ - this.previous = previous - - /** @type {remoting.ClientSession.State} */ - this.current = current; -}; - /** @enum {number} */ remoting.ClientSession.ConnectionError = { UNKNOWN: -1, @@ -285,6 +268,12 @@ * @return {void} Nothing. */ remoting.ClientSession.prototype.disconnect = function(error) { + if (this.isFinished()) { + // Do not send the session-terminate Iq if disconnect() is already called or + // if it is initiated by the host. + return; + } + this.sendIq_( '<cli:iq ' + 'to="' + this.host_.jabberId + '" ' + @@ -551,7 +540,7 @@ case remoting.ClientSession.State.CLOSED: console.log('Connection closed.'); - this.listener_.onDisconnected(); + this.listener_.onDisconnected(remoting.Error.none()); break; case remoting.ClientSession.State.CONNECTION_CANCELED: @@ -566,20 +555,12 @@ case remoting.ClientSession.State.CONNECTION_DROPPED: error = this.getError(); console.error('Connection dropped: ' + error.toString()); - this.listener_.onError(error); + this.listener_.onDisconnected(error); break; default: console.error('Unexpected client plugin state: ' + newState); - // This should only happen if the web-app and client plugin get out of - // sync, and even then the version check should ensure compatibility. - this.listener_.onError( - new remoting.Error(remoting.Error.Tag.MISSING_PLUGIN)); } - - this.raiseEvent(remoting.ClientSession.Events.stateChanged, - new remoting.ClientSession.StateEvent(newState, oldState) - ); }; /**
diff --git a/remoting/webapp/crd/js/client_session_factory_unittest.js b/remoting/webapp/crd/js/client_session_factory_unittest.js index 819378c1..5ca8c023 100644 --- a/remoting/webapp/crd/js/client_session_factory_unittest.js +++ b/remoting/webapp/crd/js/client_session_factory_unittest.js
@@ -20,7 +20,7 @@ var SessionListener = function() {}; SessionListener.prototype.onConnectionFailed = function(error) {}; SessionListener.prototype.onConnected = function(connectionInfo) {}; -SessionListener.prototype.onDisconnected = function() {}; +SessionListener.prototype.onDisconnected = function(reason) {}; SessionListener.prototype.onError = function(error) {}; QUnit.module('ClientSessionFactory', {
diff --git a/remoting/webapp/crd/js/client_session_unittest.js b/remoting/webapp/crd/js/client_session_unittest.js index 503b83d..b178c8e0 100644 --- a/remoting/webapp/crd/js/client_session_unittest.js +++ b/remoting/webapp/crd/js/client_session_unittest.js
@@ -22,8 +22,7 @@ var SessionListener = function() {}; SessionListener.prototype.onConnectionFailed = function(error) {}; SessionListener.prototype.onConnected = function(connectionInfo) {}; -SessionListener.prototype.onDisconnected = function() {}; -SessionListener.prototype.onError = function(error) {}; +SessionListener.prototype.onDisconnected = function(error) {}; /** * @param {remoting.ClientSession.ConnectionError=} opt_error @@ -142,9 +141,9 @@ var State = remoting.ClientSession.State; return connect().then(function() { - var onError = sinon.stub(listener, 'onError'); + var onDisconnected = sinon.stub(listener, 'onDisconnected'); session.disconnect(new remoting.Error(remoting.Error.Tag.P2P_FAILURE)); - assert.equal(onError.callCount, 1); + assert.equal(onDisconnected.callCount, 1); assert.equal(logToServerStub.args[2][0], State.CONNECTION_DROPPED); }); });
diff --git a/remoting/webapp/crd/js/crd_event_handlers.js b/remoting/webapp/crd/js/crd_event_handlers.js index 01439fa..782004d 100644 --- a/remoting/webapp/crd/js/crd_event_handlers.js +++ b/remoting/webapp/crd/js/crd_event_handlers.js
@@ -11,13 +11,6 @@ var goHome = function() { remoting.setMode(remoting.AppMode.HOME); }; - var goFinishedIT2Me = function() { - if (remoting.currentMode == remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME) { - remoting.setMode(remoting.AppMode.CLIENT_UNCONNECTED); - } else { - goHome(); - } - }; /** @type {Array<{event: string, id: string, fn: function(Event):void}>} */ var it2me_actions = [ { event: 'click', id: 'cancel-share-button', fn: remoting.cancelShare }, @@ -44,7 +37,6 @@ ]; /** @type {Array<{event: string, id: string, fn: function(Event):void}>} */ var auth_actions = [ - { event: 'click', id: 'cancel-connect-button', fn: goHome }, { event: 'click', id: 'sign-out', fn:remoting.signOut }, { event: 'click', id: 'token-refresh-error-ok', fn: goHome }, { event: 'click', id: 'token-refresh-error-sign-in',
diff --git a/remoting/webapp/crd/js/desktop_remoting.js b/remoting/webapp/crd/js/desktop_remoting.js index a8b1cf2..39dfe56 100644 --- a/remoting/webapp/crd/js/desktop_remoting.js +++ b/remoting/webapp/crd/js/desktop_remoting.js
@@ -209,7 +209,7 @@ remoting.DesktopRemoting.prototype.connectMe2Me_ = function(hostId) { var host = remoting.hostList.getHostForId(hostId); base.dispose(this.activity_); - this.activity_ = new remoting.Me2MeActivity(host); + this.activity_ = new remoting.Me2MeActivity(host, remoting.hostList); this.activity_.start(); };
diff --git a/remoting/webapp/crd/js/desktop_remoting_activity.js b/remoting/webapp/crd/js/desktop_remoting_activity.js index f961403..b491325 100644 --- a/remoting/webapp/crd/js/desktop_remoting_activity.js +++ b/remoting/webapp/crd/js/desktop_remoting_activity.js
@@ -30,6 +30,9 @@ remoting.app_capabilities()); /** @private {remoting.ClientSession} */ this.session_ = null; + /** @private {remoting.ConnectingDialog} */ + this.connectingDialog_ = + new remoting.ConnectingDialog(parentActivity.stop.bind(parentActivity)); }; /** @@ -47,8 +50,12 @@ function(/** remoting.ClientSession */ session) { that.session_ = session; session.logHostOfflineErrors(!opt_suppressOfflineError); + session.getLogger().setHostVersion(host.hostVersion); session.connect(host, credentialsProvider); - }); + }).catch(remoting.Error.handler( + function(/** !remoting.Error */ error) { + that.parentActivity_.onConnectionFailed(error); + })); }; remoting.DesktopRemotingActivity.prototype.stop = function() { @@ -63,6 +70,7 @@ */ remoting.DesktopRemotingActivity.prototype.onConnected = function(connectionInfo) { + this.connectingDialog_.hide(); remoting.setMode(remoting.AppMode.IN_SESSION); if (!base.isAppsV2()) { remoting.toolbar.center(); @@ -88,9 +96,11 @@ this.parentActivity_.onConnected(connectionInfo); }; -remoting.DesktopRemotingActivity.prototype.onDisconnected = function() { - this.parentActivity_.onDisconnected(); - this.dispose(); +remoting.DesktopRemotingActivity.prototype.onDisconnected = function(reason) { + if (this.handleError_(reason)) { + return; + } + this.parentActivity_.onDisconnected(reason); }; /** @@ -98,24 +108,24 @@ */ remoting.DesktopRemotingActivity.prototype.onConnectionFailed = function(error) { + if (this.handleError_(error)) { + return; + } this.parentActivity_.onConnectionFailed(error); }; /** * @param {!remoting.Error} error The error to be localized and displayed. + * @return {boolean} returns true if the error is handled. + * @private */ -remoting.DesktopRemotingActivity.prototype.onError = function(error) { - console.error('Connection failed: ' + error.toString()); - +remoting.DesktopRemotingActivity.prototype.handleError_ = function(error) { if (error.hasTag(remoting.Error.Tag.AUTHENTICATION_FAILED)) { remoting.setMode(remoting.AppMode.HOME); remoting.handleAuthFailureAndRelaunch(); - return; + return true; } - - this.parentActivity_.onError(error); - - this.dispose(); + return false; }; remoting.DesktopRemotingActivity.prototype.dispose = function() { @@ -123,6 +133,7 @@ this.connectedView_ = null; base.dispose(this.session_); this.session_ = null; + this.connectingDialog_.hide(); }; /** @return {remoting.DesktopConnectedView} */ @@ -137,4 +148,9 @@ return this.session_; }; +/** @return {remoting.ConnectingDialog} */ +remoting.DesktopRemotingActivity.prototype.getConnectingDialog = function() { + return this.connectingDialog_; +}; + })();
diff --git a/remoting/webapp/crd/js/desktop_viewport.js b/remoting/webapp/crd/js/desktop_viewport.js index 5496ec46..0eae605 100644 --- a/remoting/webapp/crd/js/desktop_viewport.js +++ b/remoting/webapp/crd/js/desktop_viewport.js
@@ -330,7 +330,7 @@ height: dimensions.height }; var desktopDpi = { x: dimensions.xDpi, y: dimensions.yDpi }; - var newSize = remoting.DesktopViewport.choosePluginSize( + var newSize = remoting.Viewport.choosePluginSize( this.getClientArea(), window.devicePixelRatio, desktopSize, desktopDpi, this.hostOptions_.desktopScale, remoting.fullscreen.isActive(), this.hostOptions_.shrinkToFit); @@ -341,139 +341,6 @@ this.pluginElement_.style.height = newSize.height + 'px'; }; -/** - * Helper function accepting client and host dimensions, and returning a chosen - * size for the plugin element, in DIPs. - * - * @param {{width: number, height: number}} clientSizeDips Available client - * dimensions, in DIPs. - * @param {number} clientPixelRatio Number of physical pixels per client DIP. - * @param {{width: number, height: number}} desktopSize Size of the host desktop - * in physical pixels. - * @param {{x: number, y: number}} desktopDpi DPI of the host desktop in both - * dimensions. - * @param {number} desktopScale The scale factor configured for the host. - * @param {boolean} isFullscreen True if full-screen mode is active. - * @param {boolean} shrinkToFit True if shrink-to-fit should be applied. - * @return {{width: number, height: number}} Chosen plugin dimensions, in DIPs. - */ -remoting.DesktopViewport.choosePluginSize = function( - clientSizeDips, clientPixelRatio, desktopSize, desktopDpi, desktopScale, - isFullscreen, shrinkToFit) { - base.debug.assert(clientSizeDips.width > 0); - base.debug.assert(clientSizeDips.height > 0); - base.debug.assert(clientPixelRatio >= 1.0); - base.debug.assert(desktopSize.width > 0); - base.debug.assert(desktopSize.height > 0); - base.debug.assert(desktopDpi.x > 0); - base.debug.assert(desktopDpi.y > 0); - base.debug.assert(desktopScale > 0); - - // We have the following goals in sizing the desktop display at the client: - // 1. Avoid losing detail by down-scaling beyond 1:1 host:device pixels. - // 2. Avoid up-scaling if that will cause the client to need scrollbars. - // 3. Avoid introducing blurriness with non-integer up-scaling factors. - // 4. Avoid having huge "letterboxes" around the desktop, if it's really - // small. - // 5. Compensate for mismatched DPIs, so that the behaviour of features like - // shrink-to-fit matches their "natural" rather than their pixel size. - // e.g. with shrink-to-fit active a 1024x768 low-DPI host on a 640x480 - // high-DPI client will be up-scaled to 1280x960, rather than displayed - // at 1:1 host:physical client pixels. - // - // To determine the ideal size we follow a four-stage process: - // 1. Determine the "natural" size at which to display the desktop. - // a. Initially assume 1:1 mapping of desktop to client device pixels. - // b. If host DPI is less than the client's then up-scale accordingly. - // c. If desktopScale is configured for the host then allow that to - // reduce the amount of up-scaling from (b). e.g. if the client:host - // DPIs are 2:1 then a desktopScale of 1.5 would reduce the up-scale - // to 4:3, while a desktopScale of 3.0 would result in no up-scaling. - // 2. If the natural size of the desktop is smaller than the client device - // then apply up-scaling by an integer scale factor to avoid excessive - // letterboxing. - // 3. If shrink-to-fit is configured then: - // a. If the natural size exceeds the client size then apply down-scaling - // by an arbitrary scale factor. - // b. If we're in full-screen mode and the client & host aspect-ratios - // are radically different (e.g. the host is actually multi-monitor) - // then shrink-to-fit to the shorter dimension, rather than leaving - // huge letterboxes; the user can then bump-scroll around the desktop. - // 4. If the overall scale factor is fractionally over an integer factor - // then reduce it to that integer factor, to avoid blurring. - - // All calculations are performed in device pixels. - var clientWidth = clientSizeDips.width * clientPixelRatio; - var clientHeight = clientSizeDips.height * clientPixelRatio; - - // 1. Determine a "natural" size at which to display the desktop. - var scale = 1.0; - - // Determine the effective host device pixel ratio. - // Note that we round up or down to the closest integer pixel ratio. - var hostPixelRatioX = Math.round(desktopDpi.x / 96); - var hostPixelRatioY = Math.round(desktopDpi.y / 96); - var hostPixelRatio = Math.min(hostPixelRatioX, hostPixelRatioY); - - // Allow up-scaling to account for DPI. - scale = Math.max(scale, clientPixelRatio / hostPixelRatio); - - // Allow some or all of the up-scaling to be cancelled by the desktopScale. - if (desktopScale > 1.0) { - scale = Math.max(1.0, scale / desktopScale); - } - - // 2. If the host is still much smaller than the client, then up-scale to - // avoid wasting space, but only by an integer factor, to avoid blurring. - if (desktopSize.width * scale <= clientWidth && - desktopSize.height * scale <= clientHeight) { - var scaleX = Math.floor(clientWidth / desktopSize.width); - var scaleY = Math.floor(clientHeight / desktopSize.height); - scale = Math.min(scaleX, scaleY); - base.debug.assert(scale >= 1.0); - } - - // 3. Apply shrink-to-fit, if configured. - if (shrinkToFit) { - var scaleFitWidth = Math.min(scale, clientWidth / desktopSize.width); - var scaleFitHeight = Math.min(scale, clientHeight / desktopSize.height); - scale = Math.min(scaleFitHeight, scaleFitWidth); - - // If we're running full-screen then try to handle common side-by-side - // multi-monitor combinations more intelligently. - if (isFullscreen) { - // If the host has two monitors each the same size as the client then - // scale-to-fit will have the desktop occupy only 50% of the client area, - // in which case it would be preferable to down-scale less and let the - // user bump-scroll around ("scale-and-pan"). - // Triggering scale-and-pan if less than 65% of the client area would be - // used adds enough fuzz to cope with e.g. 1280x800 client connecting to - // a (2x1280)x1024 host nicely. - // Note that we don't need to account for scrollbars while fullscreen. - if (scale <= scaleFitHeight * 0.65) { - scale = scaleFitHeight; - } - if (scale <= scaleFitWidth * 0.65) { - scale = scaleFitWidth; - } - } - } - - // 4. Avoid blurring for close-to-integer up-scaling factors. - if (scale > 1.0) { - var scaleBlurriness = scale / Math.floor(scale); - if (scaleBlurriness < 1.1) { - scale = Math.floor(scale); - } - } - - // Return the necessary plugin dimensions in DIPs. - scale = scale / clientPixelRatio; - var pluginWidth = Math.round(desktopSize.width * scale); - var pluginHeight = Math.round(desktopSize.height * scale); - return { width: pluginWidth, height: pluginHeight }; -}; - /** @private */ remoting.DesktopViewport.prototype.resetScroll_ = function() { this.pluginContainer_.style.marginTop = '0px';
diff --git a/remoting/webapp/crd/js/desktop_viewport_unittest.js b/remoting/webapp/crd/js/desktop_viewport_unittest.js deleted file mode 100644 index e9a3ddb..0000000 --- a/remoting/webapp/crd/js/desktop_viewport_unittest.js +++ /dev/null
@@ -1,329 +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. - -(function() { - -'use strict'; - -/** - * @param {number} width - * @param {number} height - * @return {{width:number, height:number}} - */ -function size(width, height) { - return {width: width, height: height}; -} - -/** - * @param {number} x - * @param {number} y - * @return {{x:number, y:number}} - */ -function dpi(x, y) { - return {x: x, y: y}; -} - -QUnit.module('DesktopViewport'); - -QUnit.test('choosePluginSize() handles low-DPI client & host', - function(assert) { - // 1. Client & host size the same. - var pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(640, 480), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 480)); - - // 2. Client logical dimensions smaller than host's. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(1024, 600), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); - - // 3. Client Y dimension larger than host's, X dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 640), 1.0, size(1024, 600), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); - - // 4. Client dimensions larger than host's by <2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 900), 1.0, size(640, 480), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 480)); - - // 5. Client dimensions larger than host's by >2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 1024), 1.0, size(640, 480), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(2 * 640, 2 * 480)); - - // 6. Client X dimension larger than host's, Y dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1152, 600), 1.0, size(1024, 768), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 * (600 / 768), 600)); -}); - -QUnit.test('choosePluginSize() handles high-DPI client, low-DPI host', - function(assert) { - // 1. Client & host size the same. - var pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(640, 480), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 480)); - - // 2. Client logical dimensions smaller than host's. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(1024, 600), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); - - // 3. Client Y dimension larger than host's, X dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 640), 2.0, size(1024, 600), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); - - // 4. Client logical dimensions larger than host's by <2x. - // Host dimensions fit into the client's _device_ dimensions 3x, so the - // size in client DIPs should be 1:3/2. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 900), 2.0, size(640, 480), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(640 * 3 / 2.0, 480 * 3 / 2.0)); - - // 5. Client dimensions larger than host's by >2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 1024), 2.0, size(640, 480), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); - - // 6. Client X dimension larger than host's, Y dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1152, 600), 2.0, size(1024, 768), dpi(96, 96), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 * (600 / 768), 600)); -}); - -QUnit.test('choosePluginSize() handles low-DPI client, high-DPI host', - function(assert) { - // 1. Client & host size the same. - var pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(640, 480), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 480)); - - // 2. Client logical dimensions smaller than host's. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(1024, 600), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); - - // 3. Client Y dimension larger than host's, X dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 640), 1.0, size(1024, 600), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, (640 / 1024) * 600)); - - // 4. Client dimensions larger than host's by <2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 900), 1.0, size(640, 480), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 480)); - - // 5. Client dimensions larger than host's by >2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 1024), 1.0, size(640, 480), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); - - // 6. Client X dimension larger than host's, Y dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1152, 600), 1.0, size(1024, 768), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 * (600 / 768), 600)); -}); - -QUnit.test('choosePluginSize() handles high-DPI client and host', - function(assert) { - // 1. Client & host size the same. - var pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(640, 480), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 480)); - - // 2. Client logical dimensions smaller than host's. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(1024, 600), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 / 2.0, 600 / 2.0)); - - // 3. Client Y dimension larger than host's, X dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 640), 2.0, size(1024, 600), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 / 2.0, 600 / 2.0)); - - // 4. Client logical dimensions larger than host's by <2x. - // Host dimensions fit into the client's _device_ dimensions 3x, so the - // size in client DIPs should be 1:3/2. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 900), 2.0, size(640, 480), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(640 * 3 / 2.0, 480 * 3 / 2.0)); - - // 5. Client dimensions larger than host's by >2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 1024), 2.0, size(640, 480), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); - - // 6. Client X dimension larger than host's, Y dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1152, 600), 2.0, size(1024, 768), dpi(192, 192), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 / 2.0, 768 / 2.0)); -}); - -QUnit.test('choosePluginSize() handles high-DPI client, 150% DPI host', - function(assert) { - // 1. Client & host size the same. - var pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(640, 480), dpi(144, 144), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 480)); - - // 2. Client dimensions smaller than host's. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(1024, 600), dpi(144, 144), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 / 2.0, 600 / 2.0)); - - // 3. Client Y dimension larger than host's, X dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 640), 2.0, size(1024, 600), dpi(144, 144), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 / 2.0, 600 / 2.0)); - - // 4. Client dimensions larger than host's by <2x. - // Host dimensions fit into the client's _device_ dimensions 3x, so the - // size in client DIPs should be 1:3/2. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 900), 2.0, size(640, 480), dpi(144, 144), 1.0, false, true); - assert.deepEqual(pluginSize, size(640 * 3 / 2.0, 480 * 3 / 2.0)); - - // 5. Client dimensions larger than host's by >2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 1024), 2.0, size(640, 480), dpi(144, 144), 1.0, false, true); - assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); - - // 6. Client X dimension larger than host's, Y dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1152, 600), 2.0, size(1024, 768), dpi(144, 144), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 / 2.0, 768 / 2.0)); -}); - -QUnit.test('choosePluginSize() handles high-DPI client, 125% DPI host', - function(assert) { - // 1. Client & host size the same. - var pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(640, 480), dpi(120, 120), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 480)); - - // 2. Client dimensions smaller than host's. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(1024, 600), dpi(120, 120), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 600 * (640 / 1024))); - - // 3. Client Y dimension larger than host's, X dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 640), 2.0, size(1024, 600), dpi(120, 120), 1.0, false, true); - assert.deepEqual(pluginSize, size(640, 600 * (640 / 1024))); - - // 4. Client dimensions larger than host's by <2x. - // Host dimensions fit into the client's _device_ dimensions 3x, so the - // size in client DIPs should be 1:3/2. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 900), 2.0, size(640, 480), dpi(120, 120), 1.0, false, true); - assert.deepEqual(pluginSize, size(640 * 3 / 2.0, 480 * 3 / 2.0)); - - // 5. Client dimensions larger than host's by >2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 1024), 2.0, size(640, 480), dpi(120, 120), 1.0, false, true); - assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); - - // 6. Client X dimension larger than host's, Y dimension smaller. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1152, 600), 2.0, size(1024, 768), dpi(120, 120), 1.0, false, true); - assert.deepEqual(pluginSize, size(1024 * (600 / 768), 600)); -}); - -QUnit.test('choosePluginSize() with shrink-to-fit disabled', - function(assert) { - // 1. Client & host size the same. - var pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(640, 480), dpi(96, 96), 1.0, false, false); - assert.deepEqual(pluginSize, size(640, 480)); - - // 2. Client logical dimensions smaller than host's. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(1024, 600), dpi(96, 96), 1.0, false, false); - assert.deepEqual(pluginSize, size(1024, 600)); - - // 3. Client dimensions larger than host's by <2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 900), 1.0, size(640, 480), dpi(96, 96), 1.0, false, false); - assert.deepEqual(pluginSize, size(640, 480)); - - // 4. Client dimensions larger than host's by >2x. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1280, 1024), 1.0, size(640, 480), dpi(96, 96), 1.0, false, false); - assert.deepEqual(pluginSize, size(1280, (1280 / 640) * 480)); - - // 5. Client smaller than host, client high-DPI, host low-DPI. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(1024, 600), dpi(96, 96), 1.0, false, false); - assert.deepEqual(pluginSize, size(1024, 600)); - - // 6. Client smaller than host, client low-DPI, host high-DPI. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(1024, 600), dpi(192, 192), 1.0, false, false); - assert.deepEqual(pluginSize, size(1024, 600)); - - // 7. Client smaller than host, both high-DPI. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(1024, 600), dpi(192, 192), 1.0, false, false); - assert.deepEqual(pluginSize, size(512, (512 / 1024) * 600)); - - // 8. Client smaller than host, client high-DPI, host 150% DPI. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(1024, 600), dpi(144, 144), 1.0, false, false); - assert.deepEqual(pluginSize, size(512, (512 / 1024) * 600)); -}); - -QUnit.test('choosePluginSize() full-screen multi-monitor optimization', - function(assert) { - // Each test has a host sized to approximate two or more monitors. - - // 1. Client & host per-monitor dimensions match, two monitors side-by-side. - var pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(2 * 640, 480), dpi(96, 96), 1.0, true, true); - assert.deepEqual(pluginSize, size(2 * 640, 480)); - - // 2. Client & host per-monitor dimensions match, two monitors stacked. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(640, 2 * 480), dpi(96, 96), 1.0, true, true); - assert.deepEqual(pluginSize, size(640, 2 * 480)); - - // 3. Client larger, two monitors stacked. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1024, 768), 1.0, size(640, 2 * 480), dpi(96, 96), 1.0, true, true); - assert.deepEqual(pluginSize, size(640 * (768 / (2 * 480)), 768)); - - // 4. Client smaller, two monitors stacked. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(1024, 2 * 768), dpi(96, 96), 1.0, true, true); - assert.deepEqual(pluginSize, size(640, 2 * 768 * (640 / 1024))); - - // 5. Client wide-screen, host two standard monitors stacked. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(1920, 1080), 1.0, size(1024, 2 * 768), dpi(96, 96), 1.0, - true, true); - assert.deepEqual(pluginSize, size(1024 * (1080 / (2 * 768)), 1080)); - - // 6. Client & host per-monitor dimensions match, two monitors stacked, - // high-DPI client. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(640, 2 * 480), dpi(96, 96), 1.0, true, true); - assert.deepEqual(pluginSize, size(640, 2 * 480)); - - // 7. Client & host per-monitor dimensions match, two monitors stacked, - // high-DPI host. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 1.0, size(640, 2 * 480), dpi(192, 192), - 1.0, true, true); - assert.deepEqual(pluginSize, size(640, 2 * 480)); - - // 8. Client & host per-monitor dimensions match, two monitors stacked, - // high-DPI client & host. - pluginSize = remoting.DesktopViewport.choosePluginSize( - size(640, 480), 2.0, size(640, 2 * 480), dpi(192, 192), - 1.0, true, true); - assert.deepEqual(pluginSize, size(640 / 2.0, (2 * 480) / 2.0)); -}); - -})();
diff --git a/remoting/webapp/crd/js/gcd_client.js b/remoting/webapp/crd/js/gcd_client.js index ec5178b..173a10a 100644 --- a/remoting/webapp/crd/js/gcd_client.js +++ b/remoting/webapp/crd/js/gcd_client.js
@@ -32,7 +32,8 @@ /** * TODO: Flesh out with typical fields. * @typedef {{ - * id:string + * id:string, + * name:string * }} */ remoting.gcd.Device; @@ -115,8 +116,7 @@ * specific base URL, and OAuth2 client ID. * @param {{ * apiKey: string, - * apiBaseUrl: (string|undefined), - * oauthClientId: (string|undefined) + * apiBaseUrl: (string|undefined) * }} options * @constructor */ @@ -126,9 +126,6 @@ /** @const */ this.apiBaseUrl_ = options.apiBaseUrl || 'https://www.googleapis.com/clouddevices/v1'; - /** @const */ - this.oauthClientId_ = options.oauthClientId || - remoting.settings.OAUTH2_CLIENT_ID; }; /** @@ -157,18 +154,21 @@ * TODO: Add link to GCD docs. * @param {string} ticketId * @param {!Object<string,*>} deviceDraft + * @param {string} oauthClientId * @return {!Promise<remoting.gcd.RegistrationTicket>} */ remoting.gcd.Client.prototype.patchRegistrationTicket = function( - ticketId, deviceDraft) { + ticketId, deviceDraft, oauthClientId) { return new remoting.Xhr({ - method: 'POST', + method: 'PATCH', url: this.apiBaseUrl_ + '/registrationTickets/' + encodeURIComponent(ticketId), - useIdentity: true, + urlParams: { + 'key': this.apiKey_ + }, jsonContent: { 'deviceDraft': deviceDraft, - 'oauthClientId': this.oauthClientId_ + 'oauthClientId': oauthClientId }, acceptJson: true }).start().then(function(response) { @@ -207,17 +207,23 @@ /** * Lists devices user has access to. * TODO: Add link to GCD docs. + * @param {string=} opt_nameSubstring If present, the list of devices + * is filtered by GCD such that every device returned contains + * this string as as a substring of its |name| or |displayName|. * @return {!Promise<!Array<remoting.gcd.Device>>} */ -remoting.gcd.Client.prototype.listDevices = function() { +remoting.gcd.Client.prototype.listDevices = function(opt_nameSubstring) { return new remoting.Xhr({ method: 'GET', url: this.apiBaseUrl_ + '/devices', + urlParams: { + nameSubstring: opt_nameSubstring || null + }, useIdentity: true, acceptJson: true }).start().then(function(response) { if (response.isError()) { - console.error('error patching registration ticket'); + console.error('error getting device list'); throw remoting.Error.unexpected(); } var hosts = responseAsGcdDeviceListResponse(response); @@ -242,7 +248,7 @@ return false; } if (response.isError()) { - console.warn('error deleting device'); + console.error('error deleting device'); throw remoting.Error.unexpected(); } return true; @@ -272,4 +278,4 @@ }); }; -})(); \ No newline at end of file +})();
diff --git a/remoting/webapp/crd/js/gcd_client_unittest.js b/remoting/webapp/crd/js/gcd_client_unittest.js index fca444a4..38d9c0d 100644 --- a/remoting/webapp/crd/js/gcd_client_unittest.js +++ b/remoting/webapp/crd/js/gcd_client_unittest.js
@@ -59,8 +59,7 @@ chromeMocks.identity.mock$setToken('fake_token'); client = new remoting.gcd.Client({ apiBaseUrl: 'https://fake.api', - apiKey: 'fake_key', - oauthClientId: 'fake_client_id' + apiKey: 'fake_key' }); }, teardown: function() { @@ -110,12 +109,10 @@ 200, {'Content-type': 'application/json'}, JSON.stringify(FAKE_REGISTRATION_TICKET), function() { - assert.equal(fakeXhr.method, 'POST'); + assert.equal(fakeXhr.method, 'PATCH'); assert.equal( fakeXhr.url, - 'https://fake.api/registrationTickets/fake_ticket_id'); - assert.equal(fakeXhr.requestHeaders['Authorization'], - 'Bearer fake_token'); + 'https://fake.api/registrationTickets/fake_ticket_id?key=fake_key'); assert.deepEqual( JSON.parse(fakeXhr.requestBody || ''), { deviceDraft: { 'fake_device_draft': true }, @@ -124,7 +121,7 @@ }); return client.patchRegistrationTicket('fake_ticket_id', { 'fake_device_draft': true - }).then(function(ticket) { + }, 'fake_client_id').then(function(ticket) { assert.deepEqual(ticket, FAKE_REGISTRATION_TICKET); }); });
diff --git a/remoting/webapp/crd/js/gcd_client_with_mock_xhr_unittest.js b/remoting/webapp/crd/js/gcd_client_with_mock_xhr_unittest.js index 2dedf52c..5865841 100644 --- a/remoting/webapp/crd/js/gcd_client_with_mock_xhr_unittest.js +++ b/remoting/webapp/crd/js/gcd_client_with_mock_xhr_unittest.js
@@ -45,8 +45,7 @@ chromeMocks.identity.mock$setToken('fake_token'); client = new remoting.gcd.Client({ apiBaseUrl: 'https://fake.api', - apiKey: 'fake_key', - oauthClientId: 'fake_client_id' + apiKey: 'fake_key' }); }, afterEach: function() { @@ -73,9 +72,13 @@ QUnit.test('patchRegistrationTicket', function(assert) { remoting.MockXhr.setResponseFor( - 'POST', 'https://fake.api/registrationTickets/fake_ticket_id', + 'PATCH', 'https://fake.api/registrationTickets/fake_ticket_id', function(/** remoting.MockXhr */ xhr) { - assert.equal(xhr.params.useIdentity, true); + assert.equal(xhr.params.useIdentity, false); + assert.deepEqual( + xhr.params.urlParams, { + key: 'fake_key' + }); assert.deepEqual( xhr.params.jsonContent, { deviceDraft: { 'fake_device_draft': true }, @@ -85,13 +88,11 @@ }); return client.patchRegistrationTicket('fake_ticket_id', { 'fake_device_draft': true - }).then(function(ticket) { + }, 'fake_client_id').then(function(ticket) { assert.deepEqual(ticket, FAKE_REGISTRATION_TICKET); }); }); - - QUnit.test('finalizeRegistrationTicket', function(assert) { remoting.MockXhr.setResponseFor( 'POST', 'https://fake.api/registrationTickets/fake_ticket_id/finalize',
diff --git a/remoting/webapp/crd/js/host_controller.js b/remoting/webapp/crd/js/host_controller.js index 8df1614a..b8015721 100644 --- a/remoting/webapp/crd/js/host_controller.js +++ b/remoting/webapp/crd/js/host_controller.js
@@ -182,21 +182,21 @@ var hostName = /** @type {string} */ (a[1]); var keyPair = /** @type {remoting.KeyPair} */ (a[2]); - return remoting.hostListApi.register( + return remoting.HostListApi.getInstance().register( newHostId, hostName, keyPair.publicKey, hostClientId); - }).then(function(/** string */ authCode) { + }).then(function(/** string */ result) { hostRegistered = true; - return authCode; + return result; }); // Get XMPP creditials. var xmppCredsPromise = authCodePromise.then(function(authCode) { if (authCode) { - // Use auth code supplied by registry. + // Use auth code supplied by Chromoting registry. return that.hostDaemonFacade_.getCredentialsFromAuthCode(authCode); } else { // No authorization code returned, use regular Chrome - // identitial credential flow. + // identity credential flow. return remoting.identity.getEmail().then(function(/** string */ email) { return { userEmail: email,
diff --git a/remoting/webapp/crd/js/host_controller_unittest.js b/remoting/webapp/crd/js/host_controller_unittest.js index daa41d8..d586130ae 100644 --- a/remoting/webapp/crd/js/host_controller_unittest.js +++ b/remoting/webapp/crd/js/host_controller_unittest.js
@@ -82,7 +82,7 @@ remoting.identity = new remoting.Identity(); mockHostListApi = new remoting.MockHostListApi; mockHostListApi.registerResult = FAKE_AUTH_CODE; - remoting.hostListApi = mockHostListApi; + remoting.HostListApi.setInstance(mockHostListApi); base.debug.assert(remoting.oauth2 === null); remoting.oauth2 = new remoting.OAuth2(); base.debug.assert(remoting.hostList === null); @@ -173,7 +173,7 @@ remoting.hostList = null; remoting.oauth2 = null; chromeMocks.restore(); - remoting.hostListApi = null; + remoting.HostListApi.setInstance(null); remoting.identity = null; } });
diff --git a/remoting/webapp/crd/js/host_daemon_facade.js b/remoting/webapp/crd/js/host_daemon_facade.js index 0596b57..7da4a916 100644 --- a/remoting/webapp/crd/js/host_daemon_facade.js +++ b/remoting/webapp/crd/js/host_daemon_facade.js
@@ -84,12 +84,19 @@ * @private */ remoting.HostDaemonFacade.prototype.connectNative_ = function() { + var that = this; try { this.port_ = chrome.runtime.connectNative( 'com.google.chrome.remote_desktop'); this.port_.onMessage.addListener(this.onIncomingMessageCallback_); this.port_.onDisconnect.addListener(this.onDisconnectCallback_); - return this.postMessageInternal_({type: 'hello'}); + return this.postMessageInternal_({type: 'hello'}).then(function(reply) { + that.version_ = base.getStringAttr(reply, 'version'); + // Old versions of the native messaging host do not return this list. + // Those versions default to the empty list of supported features. + that.supportedFeatures_ = + base.getArrayAttr(reply, 'supportedFeatures', []); + }); } catch (/** @type {*} */ err) { console.log('Native Messaging initialization failed: ', err); throw remoting.Error.unexpected(); @@ -131,7 +138,7 @@ * Initializes that the Daemon if necessary and posts the supplied message. * * @param {{type: string}} message The message to post. - * @return {!Promise} + * @return {!Promise<!Object>} * @private */ remoting.HostDaemonFacade.prototype.postMessage_ = @@ -152,7 +159,7 @@ * any other fields set depending on the message type. * * @param {{type: string}} message The message to post. - * @return {!Promise} + * @return {!Promise<!Object>} * @private */ remoting.HostDaemonFacade.prototype.postMessageInternal_ = function(message) { @@ -191,8 +198,7 @@ if (type != reply.type) { throw 'Expected reply type: ' + reply.type + ', got: ' + type; } - - reply.deferred.resolve(this.handleIncomingMessage_(message)); + reply.deferred.resolve(message); } catch (/** @type {*} */ e) { console.error('Error while processing native message', e); reply.deferred.reject(remoting.Error.unexpected()); @@ -200,106 +206,6 @@ }; /** - * Handler for incoming Native Messages. - * - * TODO(jrw) Consider refactoring so each method handles its own - * response, e.g.: - * - * remoting.HostDaemonFacade.prototype.generateKeyPair = function() { - * this.postMessage_({type: 'generateKeyPair'}).then(function(message) { - * return { - * privateKey: base.getStringAttr(message, 'privateKey'), - * publicKey: base.getStringAttr(message, 'publicKey') - * } - * }); - * }; - * - * @param {Object} message The received message. - * @return {*} - * @private - */ -remoting.HostDaemonFacade.prototype.handleIncomingMessage_ = - function(message) { - var type = base.getStringAttr(message, 'type'); - - switch (type) { - case 'helloResponse': - this.version_ = base.getStringAttr(message, 'version'); - // Old versions of the native messaging host do not return this list. - // Those versions default to the empty list of supported features. - this.supportedFeatures_ = - base.getArrayAttr(message, 'supportedFeatures', []); - return null; - - case 'getHostNameResponse': - return base.getStringAttr(message, 'hostname'); - - case 'getPinHashResponse': - return base.getStringAttr(message, 'hash'); - - case 'generateKeyPairResponse': - return { - privateKey: base.getStringAttr(message, 'privateKey'), - publicKey: base.getStringAttr(message, 'publicKey') - }; - - case 'updateDaemonConfigResponse': - return remoting.HostController.AsyncResult.fromString( - base.getStringAttr(message, 'result')); - - case 'getDaemonConfigResponse': - return base.getObjectAttr(message, 'config'); - - case 'getUsageStatsConsentResponse': - return { - supported: base.getBooleanAttr(message, 'supported'), - allowed: base.getBooleanAttr(message, 'allowed'), - setByPolicy: base.getBooleanAttr(message, 'setByPolicy') - }; - - case 'startDaemonResponse': - case 'stopDaemonResponse': - return remoting.HostController.AsyncResult.fromString( - base.getStringAttr(message, 'result')); - - case 'getDaemonStateResponse': - return remoting.HostController.State.fromString( - base.getStringAttr(message, 'state')); - - case 'getPairedClientsResponse': - var pairedClients = remoting.PairedClient.convertToPairedClientArray( - message['pairedClients']); - if (pairedClients != null) { - return pairedClients; - } else { - throw 'No paired clients!'; - } - - case 'clearPairedClientsResponse': - case 'deletePairedClientResponse': - return base.getBooleanAttr(message, 'result'); - - case 'getHostClientIdResponse': - return base.getStringAttr(message, 'clientId'); - - case 'getCredentialsFromAuthCodeResponse': - var userEmail = base.getStringAttr(message, 'userEmail'); - var refreshToken = base.getStringAttr(message, 'refreshToken'); - if (userEmail && refreshToken) { - return { - userEmail: userEmail, - refreshToken: refreshToken - }; - } else { - throw 'Missing userEmail or refreshToken'; - } - - default: - throw 'Unexpected native message: ' + message; - } -}; - -/** * @return {void} Nothing. * @private */ @@ -331,7 +237,9 @@ * @return {!Promise<string>} */ remoting.HostDaemonFacade.prototype.getHostName = function() { - return this.postMessage_({type: 'getHostName'}); + return this.postMessage_({type: 'getHostName'}).then(function(reply) { + return base.getStringAttr(reply, 'hostname'); + }); }; /** @@ -347,6 +255,8 @@ type: 'getPinHash', hostId: hostId, pin: pin + }).then(function(reply) { + return base.getStringAttr(reply, 'hash'); }); }; @@ -358,7 +268,12 @@ * @return {!Promise<remoting.KeyPair>} */ remoting.HostDaemonFacade.prototype.generateKeyPair = function() { - return this.postMessage_({type: 'generateKeyPair'}); + return this.postMessage_({type: 'generateKeyPair'}).then(function(reply) { + return { + privateKey: base.getStringAttr(reply, 'privateKey'), + publicKey: base.getStringAttr(reply, 'publicKey') + }; + }); }; /** @@ -378,6 +293,9 @@ return this.postMessage_({ type: 'updateDaemonConfig', config: config + }).then(function(reply) { + return remoting.HostController.AsyncResult.fromString( + base.getStringAttr(reply, 'result')); }); }; @@ -387,7 +305,9 @@ * @return {!Promise<Object>} */ remoting.HostDaemonFacade.prototype.getDaemonConfig = function() { - return this.postMessage_({type: 'getDaemonConfig'}); + return this.postMessage_({type: 'getDaemonConfig'}).then(function(reply) { + return base.getObjectAttr(reply, 'config'); + }); }; /** @@ -413,7 +333,14 @@ * @return {!Promise<remoting.UsageStatsConsent>} */ remoting.HostDaemonFacade.prototype.getUsageStatsConsent = function() { - return this.postMessage_({type: 'getUsageStatsConsent'}); + return this.postMessage_({type: 'getUsageStatsConsent'}). + then(function(reply) { + return { + supported: base.getBooleanAttr(reply, 'supported'), + allowed: base.getBooleanAttr(reply, 'allowed'), + setByPolicy: base.getBooleanAttr(reply, 'setByPolicy') + }; + }); }; /** @@ -430,6 +357,9 @@ type: 'startDaemon', config: config, consent: consent + }).then(function(reply) { + return remoting.HostController.AsyncResult.fromString( + base.getStringAttr(reply, 'result')); }); }; @@ -442,7 +372,10 @@ */ remoting.HostDaemonFacade.prototype.stopDaemon = function() { - return this.postMessage_({type: 'stopDaemon'}); + return this.postMessage_({type: 'stopDaemon'}).then(function(reply) { + return remoting.HostController.AsyncResult.fromString( + base.getStringAttr(reply, 'result')); + }); }; /** @@ -451,7 +384,10 @@ * @return {!Promise<remoting.HostController.State>} */ remoting.HostDaemonFacade.prototype.getDaemonState = function() { - return this.postMessage_({type: 'getDaemonState'}); + return this.postMessage_({type: 'getDaemonState'}).then(function(reply) { + return remoting.HostController.State.fromString( + base.getStringAttr(reply, 'state')); + }); }; /** @@ -460,7 +396,15 @@ * @return {!Promise<Array<remoting.PairedClient>>} */ remoting.HostDaemonFacade.prototype.getPairedClients = function() { - return this.postMessage_({type: 'getPairedClients'}); + return this.postMessage_({type: 'getPairedClients'}).then(function(reply) { + var pairedClients =remoting.PairedClient.convertToPairedClientArray( + reply['pairedClients']); + if (pairedClients != null) { + return pairedClients; + } else { + throw remoting.Error.unexpected('No paired clients!'); + } + }); }; /** @@ -469,7 +413,9 @@ * @return {!Promise<boolean>} */ remoting.HostDaemonFacade.prototype.clearPairedClients = function() { - return this.postMessage_({type: 'clearPairedClients'}); + return this.postMessage_({type: 'clearPairedClients'}).then(function(reply) { + return base.getBooleanAttr(reply, 'result'); + }); }; /** @@ -482,6 +428,8 @@ return this.postMessage_({ type: 'deletePairedClient', clientId: client + }).then(function(reply) { + return base.getBooleanAttr(reply, 'result'); }); }; @@ -491,11 +439,12 @@ * @return {!Promise<string>} */ remoting.HostDaemonFacade.prototype.getHostClientId = function() { - return this.postMessage_({type: 'getHostClientId'}); + return this.postMessage_({type: 'getHostClientId'}).then(function(reply) { + return base.getStringAttr(reply, 'clientId'); + }); }; /** - * * @param {string} authorizationCode OAuth authorization code. * @return {!Promise<{remoting.XmppCredentials}>} */ @@ -504,5 +453,35 @@ return this.postMessage_({ type: 'getCredentialsFromAuthCode', authorizationCode: authorizationCode + }).then(function(reply) { + var userEmail = base.getStringAttr(reply, 'userEmail'); + var refreshToken = base.getStringAttr(reply, 'refreshToken'); + if (userEmail && refreshToken) { + return { + userEmail: userEmail, + refreshToken: refreshToken + }; + } else { + throw remoting.Error.unexpected('Missing userEmail or refreshToken'); + } + }); +}; + +/** + * @param {string} authorizationCode OAuth authorization code. + * @return {!Promise<string>} + */ +remoting.HostDaemonFacade.prototype.getRefreshTokenFromAuthCode = + function(authorizationCode) { + return this.postMessage_({ + type: 'getRefreshTokenFromAuthCode', + authorizationCode: authorizationCode + }).then(function(reply) { + var refreshToken = base.getStringAttr(reply, 'refreshToken'); + if (refreshToken) { + return refreshToken + } else { + throw remoting.Error.unexpected('Missing refreshToken'); + } }); };
diff --git a/remoting/webapp/crd/js/host_list.js b/remoting/webapp/crd/js/host_list.js index 1678464..1262cd82 100644 --- a/remoting/webapp/crd/js/host_list.js +++ b/remoting/webapp/crd/js/host_list.js
@@ -152,7 +152,7 @@ that.lastError_ = error; onDone(false); }; - remoting.hostListApi.get().then(function(hosts) { + remoting.HostListApi.getInstance().get().then(function(hosts) { onDone(that.onHostListResponse_(hosts)); }).catch( remoting.Error.handler(onError) @@ -306,7 +306,7 @@ if (index != -1) { this.hostTableEntries_.splice(index, 1); } - remoting.hostListApi.remove(hostTableEntry.host.hostId). + remoting.HostListApi.getInstance().remove(hostTableEntry.host.hostId). catch(this.onError_); }; @@ -324,9 +324,10 @@ } this.save_(); - remoting.hostListApi.put(hostTableEntry.host.hostId, - hostTableEntry.host.hostName, - hostTableEntry.host.publicKey). + var hostListApi = remoting.HostListApi.getInstance(); + hostListApi.put(hostTableEntry.host.hostId, + hostTableEntry.host.hostName, + hostTableEntry.host.publicKey). catch(this.onError_); }; @@ -348,7 +349,7 @@ return; } - remoting.hostListApi.remove(hostId). + remoting.HostListApi.getInstance().remove(hostId). then(function() { that.refresh(function() { that.display();
diff --git a/remoting/webapp/crd/js/host_list_api.js b/remoting/webapp/crd/js/host_list_api.js index 9b63ccb..4e6cd72ba 100644 --- a/remoting/webapp/crd/js/host_list_api.js +++ b/remoting/webapp/crd/js/host_list_api.js
@@ -7,23 +7,30 @@ * API for host-list management. */ -'use strict'; - /** @suppress {duplicate} */ var remoting = remoting || {}; +(function() { + +'use strict'; + /** @interface */ remoting.HostListApi = function() { }; /** - * @param {string} newHostId - * @param {string} hostName - * @param {string} publicKey - * @param {?string} hostClientId + * Registers a new host with the host registry service (either the + * Chromoting registry or GCD). + * + * @param {string} newHostId The ID of the new host to register. + * @param {string} hostName The user-visible name of the new host. + * @param {string} publicKey The public half of the host's key pair. + * @param {string} hostClientId The OAuth2 client ID of the host. * @return {!Promise<string>} An OAuth2 auth code or the empty string. */ -remoting.HostListApi.prototype.register; +remoting.HostListApi.prototype.register = function( + newHostId, hostName, publicKey, hostClientId) { +}; /** * Fetch the list of hosts for a user. @@ -53,3 +60,30 @@ */ remoting.HostListApi.prototype.remove = function(hostId) { }; + +/** + * @private {remoting.HostListApi} + */ +var instance = null; + +/** + * @return {!remoting.HostListApi} + */ +remoting.HostListApi.getInstance = function() { + if (instance == null) { + instance = remoting.settings.USE_GCD ? + new remoting.HostListApiGcdImpl() : + new remoting.HostListApiImpl(); + } + return instance; +}; + +/** + * For testing. + * @param {remoting.HostListApi} newInstance + */ +remoting.HostListApi.setInstance = function(newInstance) { + instance = newInstance; +}; + +})();
diff --git a/remoting/webapp/crd/js/host_list_api_gcd_impl.js b/remoting/webapp/crd/js/host_list_api_gcd_impl.js new file mode 100644 index 0000000..005b237 --- /dev/null +++ b/remoting/webapp/crd/js/host_list_api_gcd_impl.js
@@ -0,0 +1,134 @@ +// 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. + +/** + * @fileoverview + * REST API for host-list management. + */ + +/** @suppress {duplicate} */ +var remoting = remoting || {}; + +(function() { + +'use strict'; + +/** + * @constructor + * @implements {remoting.HostListApi} + */ +remoting.HostListApiGcdImpl = function() { + this.gcd_ = new remoting.gcd.Client({ + apiKey: remoting.settings.GOOGLE_API_KEY + }); +}; + +/** @override */ +remoting.HostListApiGcdImpl.prototype.register = function( + newHostId, hostName, publicKey, hostClientId) { + var self = this; + var deviceDraft = { + channel: { + supportedType: 'xmpp' + }, + deviceKind: 'vendor', + name: newHostId, + displayName: hostName, + state: { + 'publicKey': publicKey + } + }; + + return /** @type {!Promise<string>} */ ( + this.gcd_.insertRegistrationTicket(). + then(function(ticket) { + return self.gcd_.patchRegistrationTicket( + ticket.id, deviceDraft, hostClientId); + }). + then(function(/**remoting.gcd.RegistrationTicket*/ ticket) { + return self.gcd_.finalizeRegistrationTicket(ticket.id); + }). + then(function(/**remoting.gcd.RegistrationTicket*/ ticket) { + return ticket.robotAccountAuthorizationCode; + }). + catch(function(error) { + console.error('Error registering device with GCD: ' + error); + throw new remoting.Error(remoting.Error.Tag.REGISTRATION_FAILED); + })); +}; + +/** @override */ +remoting.HostListApiGcdImpl.prototype.get = function() { + return this.gcd_.listDevices(). + then(function(devices) { + var hosts = []; + devices.forEach(function(device) { + try { + hosts.push(remoting.HostListApiGcdImpl.deviceToHost(device)); + } catch (/** @type {*} */ error) { + console.warn('Invalid device spec:', error); + } + }); + return hosts; + }); +}; + +/** @override */ +remoting.HostListApiGcdImpl.prototype.put = + function(hostId, hostName, hostPublicKey) { + // TODO(jrw) + throw new Error('Not implemented'); +}; + +/** @override */ +remoting.HostListApiGcdImpl.prototype.remove = function(hostId) { + var that = this; + return this.gcd_.listDevices(hostId).then(function(devices) { + var gcdId = null; + for (var i = 0; i < devices.length; i++) { + var device = devices[i]; + // The "name" field in GCD holds what Chromoting considers to be + // the host ID. + if (device.name == hostId) { + gcdId = device.id; + } + } + if (gcdId == null) { + return false; + } else { + return that.gcd_.deleteDevice(gcdId); + } + }); +}; + +/** + * @param {!Object} device + * @return {!remoting.Host} + */ +remoting.HostListApiGcdImpl.deviceToHost = function(device) { + var statusMap = { + 'online': 'ONLINE', + 'offline': 'OFFLINE' + }; + var hostId = base.getStringAttr(device, 'name'); + var host = new remoting.Host(hostId); + host.hostName = base.getStringAttr(device, 'displayName'); + host.status = base.getStringAttr( + statusMap, base.getStringAttr(device, 'connectionStatus')); + var state = base.getObjectAttr(device, 'state', {}); + host.publicKey = base.getStringAttr(state, 'publicKey'); + host.jabberId = base.getStringAttr(state, 'jabberId', ''); + host.hostVersion = base.getStringAttr(state, 'hostVersion', ''); + var creationTimeMs = base.getNumberAttr(device, 'creationTimeMs', 0); + if (creationTimeMs) { + host.createdTime = new Date(creationTimeMs).toISOString(); + } + var lastUpdateTimeMs = base.getNumberAttr(device, 'lastUpdateTimeMs', 0); + if (lastUpdateTimeMs) { + host.updatedTime = new Date(lastUpdateTimeMs).toISOString(); + } + return host; +}; + +})();
diff --git a/remoting/webapp/crd/js/host_list_api_impl.js b/remoting/webapp/crd/js/host_list_api_impl.js index 9cfff10..542e3f0e 100644 --- a/remoting/webapp/crd/js/host_list_api_impl.js +++ b/remoting/webapp/crd/js/host_list_api_impl.js
@@ -159,7 +159,4 @@ return result; }; -/** @type {remoting.HostListApi} */ -remoting.hostListApi = new remoting.HostListApiImpl(); - })();
diff --git a/remoting/webapp/crd/js/it2me_activity.js b/remoting/webapp/crd/js/it2me_activity.js index e5dc2db..8140c9f 100644 --- a/remoting/webapp/crd/js/it2me_activity.js +++ b/remoting/webapp/crd/js/it2me_activity.js
@@ -44,8 +44,11 @@ remoting.It2MeActivity.prototype.start = function() { var that = this; + this.desktopActivity_ = new remoting.DesktopRemotingActivity(this); + remoting.app.setConnectionMode(remoting.Application.Mode.IT2ME); + this.accessCodeDialog_.show().then(function(/** string */ accessCode) { - remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); + that.desktopActivity_.getConnectingDialog().show(); return that.verifyAccessCode_(accessCode); }).then(function() { return remoting.identity.getToken(); @@ -55,7 +58,7 @@ return that.onHostInfo_(response); }).then(function(/** remoting.Host */ host) { that.connect_(host); - }).catch(function(/** remoting.Error */ error) { + }).catch(remoting.Error.handler(function(/** remoting.Error */ error) { if (error.hasTag(remoting.Error.Tag.CANCELLED)) { remoting.setMode(remoting.AppMode.HOME); } else { @@ -63,7 +66,7 @@ l10n.localizeElementFromTag(errorDiv, error.getTag()); remoting.setMode(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME); } - }); + })); }; remoting.It2MeActivity.prototype.stop = function() { @@ -74,7 +77,9 @@ * @param {!remoting.Error} error */ remoting.It2MeActivity.prototype.onConnectionFailed = function(error) { - this.onError(error); + this.showErrorMessage_(error); + base.dispose(this.desktopActivity_); + this.desktopActivity_ = null; }; /** @@ -84,14 +89,22 @@ this.accessCodeDialog_.inputField().value = ''; }; -remoting.It2MeActivity.prototype.onDisconnected = function() { - this.showFinishDialog_(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME); +remoting.It2MeActivity.prototype.onDisconnected = function(error) { + if (error.isNone()) { + this.showFinishDialog_(remoting.AppMode.CLIENT_SESSION_FINISHED_IT2ME); + } else { + this.showErrorMessage_(error); + } + + base.dispose(this.desktopActivity_); + this.desktopActivity_ = null; }; /** * @param {!remoting.Error} error + * @private */ -remoting.It2MeActivity.prototype.onError = function(error) { +remoting.It2MeActivity.prototype.showErrorMessage_ = function(error) { var errorDiv = document.getElementById('connect-error-message'); l10n.localizeElementFromTag(errorDiv, error.getTag()); this.showFinishDialog_(remoting.AppMode.CLIENT_CONNECT_FAILED_IT2ME); @@ -183,9 +196,6 @@ * @private */ remoting.It2MeActivity.prototype.connect_ = function(host) { - base.dispose(this.desktopActivity_); - this.desktopActivity_ = new remoting.DesktopRemotingActivity(this); - remoting.app.setConnectionMode(remoting.Application.Mode.IT2ME); this.desktopActivity_.start( host, new remoting.CredentialsProvider({ accessCode: this.passCode_ })); };
diff --git a/remoting/webapp/crd/js/log_to_server.js b/remoting/webapp/crd/js/log_to_server.js index e76f67a..ad0742b 100644 --- a/remoting/webapp/crd/js/log_to_server.js +++ b/remoting/webapp/crd/js/log_to_server.js
@@ -31,6 +31,8 @@ this.connectionType_ = ''; /** @private */ this.authTotalTime_ = 0; + /** @private {string} */ + this.hostVersion_ = ''; this.setSessionId_(); signalStrategy.sendConnectionSetupResults(this); @@ -62,7 +64,7 @@ // Log the session state change. var entry = remoting.ServerLogEntry.makeClientSessionStateChange( state, connectionError); - entry.addHostFields(); + entry.addClientOSFields(); entry.addChromeVersionField(); entry.addWebappVersionField(); entry.addSessionIdField(this.sessionId_); @@ -156,7 +158,7 @@ var entry = remoting.ServerLogEntry.makeStats(this.statsAccumulator_, this.connectionType_); if (entry) { - entry.addHostFields(); + entry.addClientOSFields(); entry.addChromeVersionField(); entry.addWebappVersionField(); entry.addSessionIdField(this.sessionId_); @@ -178,6 +180,9 @@ (new Date().getTime() - this.sessionStartTime_ - this.authTotalTime_) / 1000.0; entry.addSessionDuration(sessionDurationInSeconds); + // The host-version will be blank for logs before a session has been created. + // For example, the signal-strategy log-entries won't have host version info. + entry.addHostVersion(this.hostVersion_); // Send the stanza to the debug log. console.log('Enqueueing log entry:'); @@ -260,3 +265,11 @@ this.authTotalTime_ = totalTime; }; +/** + * @param {string} hostVersion Version of the host for current session. + * @return {void} Nothing. + */ +remoting.LogToServer.prototype.setHostVersion = function(hostVersion) { + this.hostVersion_ = hostVersion; +}; +
diff --git a/remoting/webapp/crd/js/me2me_activity.js b/remoting/webapp/crd/js/me2me_activity.js index 0618464..193ba0c 100644 --- a/remoting/webapp/crd/js/me2me_activity.js +++ b/remoting/webapp/crd/js/me2me_activity.js
@@ -11,14 +11,17 @@ /** * @param {remoting.Host} host + * @param {remoting.HostList} hostList * * @constructor * @implements {remoting.Activity} */ -remoting.Me2MeActivity = function(host) { +remoting.Me2MeActivity = function(host, hostList) { /** @private */ this.host_ = host; /** @private */ + this.hostList_ = hostList; + /** @private */ this.pinDialog_ = new remoting.PinDialog(document.getElementById('pin-dialog'), host); /** @private */ @@ -48,11 +51,11 @@ return that.host_.options.load(); }).then(function() { that.connect_(true); - }).catch(function(/** remoting.Error */ error) { + }).catch(remoting.Error.handler(function(/** remoting.Error */ error) { if (error.hasTag(remoting.Error.Tag.CANCELLED)) { remoting.setMode(remoting.AppMode.HOME); } - }); + })); }; remoting.Me2MeActivity.prototype.stop = function() { @@ -69,9 +72,9 @@ * @private */ remoting.Me2MeActivity.prototype.connect_ = function(suppressHostOfflineError) { - remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); base.dispose(this.desktopActivity_); this.desktopActivity_ = new remoting.DesktopRemotingActivity(this); + this.desktopActivity_.getConnectingDialog().show(); remoting.app.setConnectionMode(remoting.Application.Mode.ME2ME); this.desktopActivity_.start(this.host_, this.createCredentialsProvider_(), suppressHostOfflineError); @@ -106,16 +109,18 @@ var requestPin = function(supportsPairing, onPinFetched) { // Set time when PIN was requested. var authStartTime = new Date().getTime(); + that.desktopActivity_.getConnectingDialog().hide(); that.pinDialog_.show(supportsPairing).then(function(/** string */ pin) { remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); // Done obtaining PIN information. Log time taken for PIN entry. var logToServer = that.desktopActivity_.getSession().getLogger(); logToServer.setAuthTotalTime(new Date().getTime() - authStartTime); onPinFetched(pin); - }).catch(function(/** remoting.Error */ error) { + }).catch(remoting.Error.handler(function(/** remoting.Error */ error) { base.debug.assert(error.hasTag(remoting.Error.Tag.CANCELLED)); remoting.setMode(remoting.AppMode.HOME); - }); + that.stop(); + })); }; return new remoting.CredentialsProvider({ @@ -136,19 +141,22 @@ var onHostListRefresh = function(/** boolean */ success) { if (success) { // Get the host from the hostList for the refreshed JID. - that.host_ = remoting.hostList.getHostForId(that.host_.hostId); + that.host_ = that.hostList_.getHostForId(that.host_.hostId); that.connect_(false); return; } - that.onError(error); + that.showErrorMessage_(error); }; this.retryOnHostOffline_ = false; // The plugin will be re-created when the host finished refreshing - remoting.hostList.refresh(onHostListRefresh); - } else { - this.onError(error); + this.hostList_.refresh(onHostListRefresh); + } else if (!error.isNone()) { + this.showErrorMessage_(error); } + + base.dispose(this.desktopActivity_); + this.desktopActivity_ = null; }; /** @@ -167,19 +175,29 @@ base.dispose(this.reconnector_); this.reconnector_ = new remoting.SmartReconnector( + this.desktopActivity_.getConnectingDialog(), this.connect_.bind(this, false), this.stop.bind(this), connectionInfo.session()); }; -remoting.Me2MeActivity.prototype.onDisconnected = function() { - this.showFinishDialog_(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME); +remoting.Me2MeActivity.prototype.onDisconnected = function(error) { + if (error.isNone()) { + this.showFinishDialog_(remoting.AppMode.CLIENT_SESSION_FINISHED_ME2ME); + } else { + this.reconnector_.onConnectionDropped(error); + this.showErrorMessage_(error); + } + + base.dispose(this.desktopActivity_); + this.desktopActivity_ = null; }; /** * @param {!remoting.Error} error + * @private */ -remoting.Me2MeActivity.prototype.onError = function(error) { +remoting.Me2MeActivity.prototype.showErrorMessage_ = function(error) { var errorDiv = document.getElementById('connect-error-message'); l10n.localizeElementFromTag(errorDiv, error.getTag()); this.showFinishDialog_(remoting.AppMode.CLIENT_CONNECT_FAILED_ME2ME);
diff --git a/remoting/webapp/crd/js/mock_client_plugin.js b/remoting/webapp/crd/js/mock_client_plugin.js index 1f2ba5c..68be5e1 100644 --- a/remoting/webapp/crd/js/mock_client_plugin.js +++ b/remoting/webapp/crd/js/mock_client_plugin.js
@@ -29,6 +29,10 @@ new remoting.ClientPlugin.HostDesktopImpl(this, base.doNothing); /** @private */ this.extensions_ = new remoting.ProtocolExtensionManager(base.doNothing); + + /** @private {remoting.CredentialsProvider} */ + this.credentials_ = null; + /** @private {remoting.ClientPlugin.ConnectionEventHandler} */ this.connectionEventHandler_ = null; @@ -73,6 +77,7 @@ remoting.MockClientPlugin.prototype.connect = function(host, localJid, credentialsProvider) { + this.credentials_ = credentialsProvider; this.onConnectDeferred_.resolve(); }; @@ -163,6 +168,50 @@ }; /** + * @param {remoting.MockClientPlugin.AuthMethod} authMethod + * @return {Promise} + */ +remoting.MockClientPlugin.prototype.mock$authenticate = function(authMethod) { + var AuthMethod = remoting.MockClientPlugin.AuthMethod; + var deferred = new base.Deferred(); + + var that = this; + switch(authMethod) { + case AuthMethod.PIN: + case AuthMethod.ACCESS_CODE: + this.credentials_.getPIN(true).then(function() { + deferred.resolve(); + }); + break; + case AuthMethod.THIRD_PARTY: + this.credentials_.getThirdPartyToken( + 'fake_token_url', 'fake_host_publicKey', 'fake_scope' + ).then(function() { + deferred.resolve(); + }); + break; + case AuthMethod.PAIRING: + deferred.resolve(); + } + return deferred.promise(); +}; + +/** + * @param {remoting.MockClientPlugin.AuthMethod} authMethod + */ +remoting.MockClientPlugin.prototype.mock$useDefaultBehavior = + function(authMethod) { + var that = this; + var State = remoting.ClientSession.State; + this.mock$onConnect().then(function() { + that.mock$setConnectionStatus(State.CONNECTING); + return that.mock$authenticate(authMethod); + }).then(function() { + that.mock$setConnectionStatus(State.CONNECTED); + }); +}; + +/** * @constructor * @implements {remoting.ClientPluginFactory} */ @@ -235,4 +284,12 @@ this.createSignalStrategyStub_.restore(); }; -})(); \ No newline at end of file +})(); + +/** @enum {string} */ +remoting.MockClientPlugin.AuthMethod = { + ACCESS_CODE: 'accessCode', + PIN: 'pin', + THIRD_PARTY: 'thirdParty', + PAIRING: 'pairing' +}; \ No newline at end of file
diff --git a/remoting/webapp/crd/js/mock_host_list_api.js b/remoting/webapp/crd/js/mock_host_list_api.js index b21462db..1d9b151 100644 --- a/remoting/webapp/crd/js/mock_host_list_api.js +++ b/remoting/webapp/crd/js/mock_host_list_api.js
@@ -52,7 +52,9 @@ newHostId, hostName, publicKey, hostClientId) { if (this.registerResult === null) { return Promise.reject( - new remoting.Error(remoting.Error.Tag.REGISTRATION_FAILED)); + new remoting.Error( + remoting.Error.Tag.REGISTRATION_FAILED, + 'MockHostListApi.register')); } else { return Promise.resolve(this.registerResult); } @@ -61,13 +63,18 @@ /** @override */ remoting.MockHostListApi.prototype.get = function() { var that = this; - new Promise(function(resolve, reject) { + return new Promise(function(resolve, reject) { remoting.mockIdentity.validateTokenAndCall( resolve, remoting.Error.handler(reject), [that.hosts]); }); }; -/** @override */ +/** + * @override + * @param {string} hostId + * @param {string} hostName + * @param {string} hostPublicKey + */ remoting.MockHostListApi.prototype.put = function(hostId, hostName, hostPublicKey) { /** @type {remoting.MockHostListApi} */ @@ -91,7 +98,10 @@ }); }; -/** @override */ +/** + * @override + * @param {string} hostId + */ remoting.MockHostListApi.prototype.remove = function(hostId) { /** @type {remoting.MockHostListApi} */ var that = this; @@ -116,6 +126,6 @@ * @param {boolean} active */ remoting.MockHostListApi.setActive = function(active) { - remoting.hostListApi = active ? new remoting.MockHostListApi() - : new remoting.HostListApiImpl(); + remoting.HostListApi.setInstance( + active ? new remoting.MockHostListApi() : null); };
diff --git a/remoting/webapp/crd/js/plugin_settings.js b/remoting/webapp/crd/js/plugin_settings.js index bbc4df8..a4b56d2d 100644 --- a/remoting/webapp/crd/js/plugin_settings.js +++ b/remoting/webapp/crd/js/plugin_settings.js
@@ -23,6 +23,8 @@ remoting.Settings.prototype.OAUTH2_CLIENT_ID = 'API_CLIENT_ID'; /** @type {string} API client secret.*/ remoting.Settings.prototype.OAUTH2_CLIENT_SECRET = 'API_CLIENT_SECRET'; +/** @type {string} Google API Key.*/ +remoting.Settings.prototype.GOOGLE_API_KEY = 'API_KEY'; /** @type {string} Base URL for OAuth2 authentication. */ remoting.Settings.prototype.OAUTH2_BASE_URL = 'OAUTH2_BASE_URL';
diff --git a/remoting/webapp/crd/js/server_log_entry.js b/remoting/webapp/crd/js/server_log_entry.js index 00cab938..2b3b5aca 100644 --- a/remoting/webapp/crd/js/server_log_entry.js +++ b/remoting/webapp/crd/js/server_log_entry.js
@@ -159,6 +159,9 @@ remoting.ServerLogEntry.KEY_WEBAPP_VERSION_ = 'webapp-version'; /** @private */ +remoting.ServerLogEntry.KEY_HOST_VERSION_ = 'host-version'; + +/** @private */ remoting.ServerLogEntry.VALUE_EVENT_NAME_SESSION_ID_OLD_ = 'session-id-old'; /** @private */ @@ -367,7 +370,7 @@ /** * Adds fields describing the host to this log entry. */ -remoting.ServerLogEntry.prototype.addHostFields = function() { +remoting.ServerLogEntry.prototype.addClientOSFields = function() { var host = remoting.ServerLogEntry.getHostData_(); if (host) { if (host.os_name.length > 0) { @@ -477,6 +480,15 @@ }; /** + * Adds a field specifying the host version to this log entry. + * @param {string} hostVersion Version of the host for current session. + * @return {void} Nothing. + */ +remoting.ServerLogEntry.prototype.addHostVersion = function(hostVersion) { + this.set_(remoting.ServerLogEntry.KEY_HOST_VERSION_, hostVersion); +}; + +/** * Adds a field specifying the mode to this log entry. */ remoting.ServerLogEntry.prototype.addModeField = function() {
diff --git a/remoting/webapp/crd/js/smart_reconnector.js b/remoting/webapp/crd/js/smart_reconnector.js index 3ad4d6f4..afb6975 100644 --- a/remoting/webapp/crd/js/smart_reconnector.js +++ b/remoting/webapp/crd/js/smart_reconnector.js
@@ -21,6 +21,7 @@ /** * @constructor + * @param {remoting.ConnectingDialog} connectingDialog * @param {function()} reconnectCallback * @param {function()} disconnectCallback * @param {remoting.ClientSession} clientSession This represents the current @@ -28,8 +29,8 @@ * connection state. * @implements {base.Disposable} */ -remoting.SmartReconnector = - function(reconnectCallback, disconnectCallback, clientSession) { +remoting.SmartReconnector = function(connectingDialog, reconnectCallback, + disconnectCallback, clientSession) { /** @private */ this.reconnectCallback_ = reconnectCallback; @@ -47,13 +48,14 @@ */ this.pending_ = null; + /** @private */ + this.connectingDialog_ = connectingDialog; + var Events = remoting.ClientSession.Events; /** @private */ - this.eventHooks_ = new base.Disposables( - new base.EventHook(clientSession, Events.stateChanged, - this.stateChanged_.bind(this)), + this.eventHook_ = new base.EventHook(clientSession, Events.videoChannelStateChanged, - this.videoChannelStateChanged_.bind(this))); + this.videoChannelStateChanged_.bind(this)); }; // The online event only means the network adapter is enabled, but @@ -68,30 +70,26 @@ remoting.SmartReconnector.prototype.reconnect_ = function() { this.cancelPending_(); this.disconnectCallback_(); - remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); this.reconnectCallback_(); }; remoting.SmartReconnector.prototype.reconnectAsync_ = function() { this.cancelPending_(); - remoting.setMode(remoting.AppMode.CLIENT_CONNECTING); + this.connectingDialog_.show(); this.pending_ = new base.OneShotTimer(this.reconnect_.bind(this), RECONNECT_DELAY_MS); }; /** - * @param {remoting.ClientSession.StateEvent=} event + * @param {!remoting.Error} reason */ -remoting.SmartReconnector.prototype.stateChanged_ = function(event) { - var State = remoting.ClientSession.State; - if (event.previous === State.CONNECTED && event.current === State.FAILED) { - this.cancelPending_(); - if (navigator.onLine) { - this.reconnect_(); - } else { - this.pending_ = new base.DomEventHook( - window, 'online', this.reconnectAsync_.bind(this), false); - } +remoting.SmartReconnector.prototype.onConnectionDropped = function(reason) { + this.cancelPending_(); + if (navigator.onLine) { + this.reconnect_(); + } else { + this.pending_ = new base.DomEventHook( + window, 'online', this.reconnectAsync_.bind(this), false); } }; @@ -121,8 +119,8 @@ remoting.SmartReconnector.prototype.dispose = function() { this.cancelPending_(); - base.dispose(this.eventHooks_); - this.eventHooks_ = null; + base.dispose(this.eventHook_); + this.eventHook_ = null; }; })();
diff --git a/remoting/webapp/files.gni b/remoting/webapp/files.gni index 1a006c04..ad84123 100644 --- a/remoting/webapp/files.gni +++ b/remoting/webapp/files.gni
@@ -71,9 +71,9 @@ "base/js/base_inherits_unittest.js", "base/js/ipc_unittest.js", "base/js/protocol_extension_manager_unittest.js", + "base/js/viewport_unittest.js", "crd/js/apps_v2_migration_unittest.js", "crd/js/client_session_unittest.js", - "crd/js/desktop_viewport_unittest.js", "crd/js/dns_blackhole_checker_unittest.js", "crd/js/error_unittest.js", "crd/js/fallback_signal_strategy_unittest.js", @@ -165,7 +165,6 @@ "crd/js/connected_view.js", "crd/js/connection_info.js", "crd/js/credentials_provider.js", - "crd/js/desktop_connected_view.js", "crd/js/host_desktop.js", "crd/js/smart_reconnector.js", "crd/js/video_frame_recorder.js", @@ -245,19 +244,37 @@ # UI JavaScript files. remoting_webapp_js_ui_files = [ + "base/js/viewport.js", "base/js/window_shape.js", + "crd/js/connection_stats.js", + "crd/js/feedback.js", + "crd/js/l10n.js", + "crd/js/ui_mode.js", +] + +# +# DesktopRemoting-specific JS files. +# + +# The CRD-specific JavaScript files required by main.html. +remoting_webapp_crd_js_ui_files = [ "crd/js/bump_scroller.js", "crd/js/butter_bar.js", - "crd/js/connection_stats.js", + "crd/js/crd_auth_dialog.js", + "crd/js/crd_event_handlers.js", + "crd/js/crd_experimental.js", + "crd/js/crd_main.js", + "crd/js/desktop_connected_view.js", + "crd/js/desktop_remoting.js", + "crd/js/desktop_remoting_activity.js", "crd/js/desktop_viewport.js", - "crd/js/feedback.js", "crd/js/fullscreen.js", "crd/js/fullscreen_v1.js", "crd/js/fullscreen_v2.js", - "crd/js/l10n.js", + "crd/js/it2me_activity.js", + "crd/js/me2me_activity.js", "crd/js/menu_button.js", "crd/js/options_menu.js", - "crd/js/ui_mode.js", "crd/js/toolbar.js", "crd/js/window_frame.js", ] @@ -286,17 +303,7 @@ # The CRD-specific JavaScript files required by main.html. remoting_webapp_crd_main_html_all_js_files = - remoting_webapp_shared_main_html_js_files -remoting_webapp_crd_main_html_all_js_files += [ - "crd/js/crd_auth_dialog.js", - "crd/js/crd_event_handlers.js", - "crd/js/crd_experimental.js", - "crd/js/crd_main.js", - "crd/js/desktop_remoting.js", - "crd/js/desktop_remoting_activity.js", - "crd/js/it2me_activity.js", - "crd/js/me2me_activity.js", -] + remoting_webapp_shared_main_html_js_files + remoting_webapp_crd_js_ui_files # These template files are used to construct main.html. remoting_webapp_template_files = [
diff --git a/rlz/lib/recursive_cross_process_lock_posix.cc b/rlz/lib/recursive_cross_process_lock_posix.cc index c44cacfd..965bd9ac 100644 --- a/rlz/lib/recursive_cross_process_lock_posix.cc +++ b/rlz/lib/recursive_cross_process_lock_posix.cc
@@ -43,7 +43,7 @@ CHECK(file_lock_ == -1); file_lock_ = open(lock_filename.value().c_str(), O_RDWR | O_CREAT, 0666); if (file_lock_ == -1) { - perror("open"); + VPLOG(1) << "Failed to open: " << lock_filename.value(); return false; } @@ -58,7 +58,7 @@ } if (flock_result == -1) { - perror("flock"); + VPLOG(1) << "Failed flock: " << lock_filename.value(); close(file_lock_); file_lock_ = -1; return false;
diff --git a/rlz/win/lib/rlz_value_store_registry.h b/rlz/win/lib/rlz_value_store_registry.h index f00dd460..d058d668 100644 --- a/rlz/win/lib/rlz_value_store_registry.h +++ b/rlz/win/lib/rlz_value_store_registry.h
@@ -15,33 +15,33 @@ public: static std::wstring GetWideLibKeyName(); - virtual bool HasAccess(AccessType type) override; + bool HasAccess(AccessType type) override; - virtual bool WritePingTime(Product product, int64 time) override; - virtual bool ReadPingTime(Product product, int64* time) override; - virtual bool ClearPingTime(Product product) override; + bool WritePingTime(Product product, int64 time) override; + bool ReadPingTime(Product product, int64* time) override; + bool ClearPingTime(Product product) override; - virtual bool WriteAccessPointRlz(AccessPoint access_point, + bool WriteAccessPointRlz(AccessPoint access_point, const char* new_rlz) override; - virtual bool ReadAccessPointRlz(AccessPoint access_point, + bool ReadAccessPointRlz(AccessPoint access_point, char* rlz, size_t rlz_size) override; - virtual bool ClearAccessPointRlz(AccessPoint access_point) override; + bool ClearAccessPointRlz(AccessPoint access_point) override; - virtual bool AddProductEvent(Product product, const char* event_rlz) override; - virtual bool ReadProductEvents(Product product, + bool AddProductEvent(Product product, const char* event_rlz) override; + bool ReadProductEvents(Product product, std::vector<std::string>* events) override; - virtual bool ClearProductEvent(Product product, + bool ClearProductEvent(Product product, const char* event_rlz) override; - virtual bool ClearAllProductEvents(Product product) override; + bool ClearAllProductEvents(Product product) override; - virtual bool AddStatefulEvent(Product product, + bool AddStatefulEvent(Product product, const char* event_rlz) override; - virtual bool IsStatefulEvent(Product product, + bool IsStatefulEvent(Product product, const char* event_rlz) override; - virtual bool ClearAllStatefulEvents(Product product) override; + bool ClearAllStatefulEvents(Product product) override; - virtual void CollectGarbage() override; + void CollectGarbage() override; private: RlzValueStoreRegistry() {}
diff --git a/sandbox/linux/BUILD.gn b/sandbox/linux/BUILD.gn index 21f856b..8496685 100644 --- a/sandbox/linux/BUILD.gn +++ b/sandbox/linux/BUILD.gn
@@ -117,6 +117,7 @@ "seccomp-bpf/errorcode_unittest.cc", "seccomp-bpf/sandbox_bpf_unittest.cc", "seccomp-bpf/syscall_unittest.cc", + "seccomp-bpf/trap_unittest.cc", ] } if (compile_credentials) { @@ -288,15 +289,16 @@ source_set("sandbox_services_headers") { sources = [ - "system_headers/android_arm64_ucontext.h", - "system_headers/android_arm_ucontext.h", - "system_headers/android_i386_ucontext.h", - "system_headers/android_ucontext.h", "system_headers/arm64_linux_syscalls.h", + "system_headers/arm64_linux_ucontext.h", "system_headers/arm_linux_syscalls.h", + "system_headers/arm_linux_ucontext.h", + "system_headers/i386_linux_ucontext.h", "system_headers/linux_futex.h", "system_headers/linux_seccomp.h", + "system_headers/linux_signal.h", "system_headers/linux_syscalls.h", + "system_headers/linux_ucontext.h", "system_headers/x86_32_linux_syscalls.h", "system_headers/x86_64_linux_syscalls.h", ]
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl.h b/sandbox/linux/bpf_dsl/bpf_dsl.h index 63b095d..365e9b5 100644 --- a/sandbox/linux/bpf_dsl/bpf_dsl.h +++ b/sandbox/linux/bpf_dsl/bpf_dsl.h
@@ -33,8 +33,8 @@ // class SillyPolicy : public Policy { // public: // SillyPolicy() {} -// virtual ~SillyPolicy() {} -// virtual ResultExpr EvaluateSyscall(int sysno) const override { +// ~SillyPolicy() override {} +// ResultExpr EvaluateSyscall(int sysno) const override { // if (sysno == __NR_fcntl) { // Arg<int> fd(0), cmd(1); // Arg<unsigned long> flags(2);
diff --git a/sandbox/linux/sandbox_linux.gypi b/sandbox/linux/sandbox_linux.gypi index 1cf3b2d..7724223 100644 --- a/sandbox/linux/sandbox_linux.gypi +++ b/sandbox/linux/sandbox_linux.gypi
@@ -278,18 +278,18 @@ { 'target_name': 'sandbox_services_headers', 'type': 'none', 'sources': [ - 'system_headers/android_arm64_ucontext.h', - 'system_headers/android_arm_ucontext.h', - 'system_headers/android_i386_ucontext.h', - 'system_headers/android_mips_ucontext.h', - 'system_headers/android_ucontext.h', 'system_headers/arm64_linux_syscalls.h', + 'system_headers/arm64_linux_ucontext.h', 'system_headers/arm_linux_syscalls.h', + 'system_headers/arm_linux_ucontext.h', 'system_headers/capability.h', + 'system_headers/i386_linux_ucontext.h', 'system_headers/linux_futex.h', 'system_headers/linux_seccomp.h', 'system_headers/linux_syscalls.h', + 'system_headers/linux_ucontext.h', 'system_headers/mips_linux_syscalls.h', + 'system_headers/mips_linux_ucontext.h', 'system_headers/x86_32_linux_syscalls.h', 'system_headers/x86_64_linux_syscalls.h', ],
diff --git a/sandbox/linux/sandbox_linux_test_sources.gypi b/sandbox/linux/sandbox_linux_test_sources.gypi index c558a0d7..ce7817d7 100644 --- a/sandbox/linux/sandbox_linux_test_sources.gypi +++ b/sandbox/linux/sandbox_linux_test_sources.gypi
@@ -53,6 +53,7 @@ 'seccomp-bpf/errorcode_unittest.cc', 'seccomp-bpf/sandbox_bpf_unittest.cc', 'seccomp-bpf/syscall_unittest.cc', + 'seccomp-bpf/trap_unittest.cc', ], }], [ 'compile_credentials==1', {
diff --git a/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h index 1869913..7736c150 100644 --- a/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h +++ b/sandbox/linux/seccomp-bpf/bpf_tester_compatibility_delegate.h
@@ -25,9 +25,9 @@ explicit BPFTesterCompatibilityDelegate(TestFunction test_function) : aux_(), test_function_(test_function) {} - virtual ~BPFTesterCompatibilityDelegate() {} + ~BPFTesterCompatibilityDelegate() override {} - virtual scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override { + scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override { // The current method is guaranteed to only run in the child process // running the test. In this process, the current object is guaranteed // to live forever. So it's ok to pass aux_pointer_for_policy_ to @@ -35,7 +35,7 @@ return scoped_ptr<bpf_dsl::Policy>(new Policy(&aux_)); } - virtual void RunTestFunction() override { + void RunTestFunction() override { // Run the actual test. // The current object is guaranteed to live forever in the child process // where this will run.
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests.h b/sandbox/linux/seccomp-bpf/bpf_tests.h index 57de1dd8..cc4debd 100644 --- a/sandbox/linux/seccomp-bpf/bpf_tests.h +++ b/sandbox/linux/seccomp-bpf/bpf_tests.h
@@ -102,12 +102,12 @@ public: explicit BPFTesterSimpleDelegate(void (*test_function)(void)) : test_function_(test_function) {} - virtual ~BPFTesterSimpleDelegate() {} + ~BPFTesterSimpleDelegate() override {} - virtual scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override { + scoped_ptr<bpf_dsl::Policy> GetSandboxBPFPolicy() override { return scoped_ptr<bpf_dsl::Policy>(new PolicyClass()); } - virtual void RunTestFunction() override { + void RunTestFunction() override { DCHECK(test_function_); test_function_(); }
diff --git a/sandbox/linux/seccomp-bpf/die.cc b/sandbox/linux/seccomp-bpf/die.cc index 777c9d1..3baf1f1 100644 --- a/sandbox/linux/seccomp-bpf/die.cc +++ b/sandbox/linux/seccomp-bpf/die.cc
@@ -16,6 +16,8 @@ #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "sandbox/linux/seccomp-bpf/syscall.h" +#include "sandbox/linux/services/syscall_wrappers.h" +#include "sandbox/linux/system_headers/linux_signal.h" namespace sandbox { @@ -32,7 +34,10 @@ // to a defined state; but we have not way to verify whether we actually // succeeded in doing so. Nonetheless, triggering a fatal signal could help // us terminate. - signal(SIGSEGV, SIG_DFL); + struct sigaction sa = {}; + sa.sa_handler = LINUX_SIG_DFL; + sa.sa_flags = LINUX_SA_RESTART; + sys_sigaction(LINUX_SIGSEGV, &sa, nullptr); Syscall::Call(__NR_prctl, PR_SET_DUMPABLE, (void*)0, (void*)0, (void*)0); if (*(volatile char*)0) { }
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc index af397df..239043eb 100644 --- a/sandbox/linux/seccomp-bpf/sandbox_bpf.cc +++ b/sandbox/linux/seccomp-bpf/sandbox_bpf.cc
@@ -59,9 +59,40 @@ return false; } +// LG introduced a buggy syscall, sys_set_media_ext, with the same number as +// seccomp. Return true if the current kernel has this buggy syscall. +// +// We want this to work with upcoming versions of seccomp, so we pass bogus +// flags that are unlikely to ever be used by the kernel. A normal kernel would +// return -EINVAL, but a buggy LG kernel would return 1. +bool KernelHasLGBug() { +#if defined(OS_ANDROID) + // sys_set_media will see this as NULL, which should be a safe (non-crashing) + // way to invoke it. A genuine seccomp syscall will see it as + // SECCOMP_SET_MODE_STRICT. + const unsigned int operation = 0; + // Chosen by fair dice roll. Guaranteed to be random. + const unsigned int flags = 0xf7a46a5c; + const int rv = sys_seccomp(operation, flags, nullptr); + // A genuine kernel would return -EINVAL (which would set rv to -1 and errno + // to EINVAL), or at the very least return some kind of error (which would + // set rv to -1). Any other behavior indicates that whatever code received + // our syscall was not the real seccomp. + if (rv != -1) { + return true; + } +#endif // defined(OS_ANDROID) + + return false; +} + // Check if the kernel supports seccomp-filter via the seccomp system call // and the TSYNC feature to enable seccomp on all threads. bool KernelSupportsSeccompTsync() { + if (KernelHasLGBug()) { + return false; + } + errno = 0; const int rv = sys_seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, nullptr);
diff --git a/sandbox/linux/seccomp-bpf/syscall.h b/sandbox/linux/seccomp-bpf/syscall.h index dfb44eb..ccfc88d 100644 --- a/sandbox/linux/seccomp-bpf/syscall.h +++ b/sandbox/linux/seccomp-bpf/syscall.h
@@ -9,13 +9,9 @@ #include <stdint.h> #include "base/macros.h" +#include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/sandbox_export.h" -// Android's signal.h doesn't define ucontext etc. -#if defined(OS_ANDROID) -#include "sandbox/linux/system_headers/android_ucontext.h" -#endif - namespace sandbox { // This purely static class can be used to perform system calls with some
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc index 145e6246..79b7569 100644 --- a/sandbox/linux/seccomp-bpf/trap.cc +++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -17,12 +17,9 @@ #include "sandbox/linux/bpf_dsl/seccomp_macros.h" #include "sandbox/linux/seccomp-bpf/die.h" #include "sandbox/linux/seccomp-bpf/syscall.h" +#include "sandbox/linux/services/syscall_wrappers.h" #include "sandbox/linux/system_headers/linux_seccomp.h" - -// Android's signal.h doesn't define ucontext etc. -#if defined(OS_ANDROID) -#include "sandbox/linux/system_headers/android_ucontext.h" -#endif +#include "sandbox/linux/system_headers/linux_signal.h" namespace { @@ -53,13 +50,13 @@ // possibly even worse. bool GetIsInSigHandler(const ucontext_t* ctx) { // Note: on Android, sigismember does not take a pointer to const. - return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), SIGBUS); + return sigismember(const_cast<sigset_t*>(&ctx->uc_sigmask), LINUX_SIGBUS); } void SetIsInSigHandler() { sigset_t mask; - if (sigemptyset(&mask) || sigaddset(&mask, SIGBUS) || - sigprocmask(SIG_BLOCK, &mask, NULL)) { + if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGBUS) || + sandbox::sys_sigprocmask(LINUX_SIG_BLOCK, &mask, NULL)) { SANDBOX_DIE("Failed to block SIGBUS"); } } @@ -82,10 +79,13 @@ has_unsafe_traps_(false) { // Set new SIGSYS handler struct sigaction sa = {}; - sa.sa_sigaction = SigSysAction; - sa.sa_flags = SA_SIGINFO | SA_NODEFER; - struct sigaction old_sa; - if (sigaction(SIGSYS, &sa, &old_sa) < 0) { + // In some toolchain, sa_sigaction is not declared in struct sigaction. + // So, here cast the pointer to the sa_handler's type. This works because + // |sa_handler| and |sa_sigaction| shares the same memory. + sa.sa_handler = reinterpret_cast<void (*)(int)>(SigSysAction); + sa.sa_flags = LINUX_SA_SIGINFO | LINUX_SA_NODEFER; + struct sigaction old_sa = {}; + if (sys_sigaction(LINUX_SIGSYS, &sa, &old_sa) < 0) { SANDBOX_DIE("Failed to configure SIGSYS handler"); } @@ -99,8 +99,8 @@ // Unmask SIGSYS sigset_t mask; - if (sigemptyset(&mask) || sigaddset(&mask, SIGSYS) || - sigprocmask(SIG_UNBLOCK, &mask, NULL)) { + if (sigemptyset(&mask) || sigaddset(&mask, LINUX_SIGSYS) || + sys_sigprocmask(LINUX_SIG_UNBLOCK, &mask, NULL)) { SANDBOX_DIE("Failed to configure SIGSYS handler"); } } @@ -120,7 +120,7 @@ return global_trap_; } -void Trap::SigSysAction(int nr, siginfo_t* info, void* void_context) { +void Trap::SigSysAction(int nr, LinuxSigInfo* info, void* void_context) { if (!global_trap_) { RAW_SANDBOX_DIE( "This can't happen. Found no global singleton instance " @@ -129,7 +129,7 @@ global_trap_->SigSys(nr, info, void_context); } -void Trap::SigSys(int nr, siginfo_t* info, void* void_context) { +void Trap::SigSys(int nr, LinuxSigInfo* info, void* void_context) { // Signal handlers should always preserve "errno". Otherwise, we could // trigger really subtle bugs. const int old_errno = errno; @@ -137,7 +137,7 @@ // Various sanity checks to make sure we actually received a signal // triggered by a BPF filter. If something else triggered SIGSYS // (e.g. kill()), there is really nothing we can do with this signal. - if (nr != SIGSYS || info->si_code != SYS_SECCOMP || !void_context || + if (nr != LINUX_SIGSYS || info->si_code != SYS_SECCOMP || !void_context || info->si_errno <= 0 || static_cast<size_t>(info->si_errno) > trap_array_size_) { // ATI drivers seem to send SIGSYS, so this cannot be FATAL.
diff --git a/sandbox/linux/seccomp-bpf/trap.h b/sandbox/linux/seccomp-bpf/trap.h index 4073bfe1..bbddeb7 100644 --- a/sandbox/linux/seccomp-bpf/trap.h +++ b/sandbox/linux/seccomp-bpf/trap.h
@@ -5,13 +5,13 @@ #ifndef SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ #define SANDBOX_LINUX_SECCOMP_BPF_TRAP_H__ -#include <signal.h> #include <stdint.h> #include <map> #include "base/macros.h" #include "sandbox/linux/bpf_dsl/trap_registry.h" +#include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/sandbox_export.h" namespace sandbox { @@ -57,11 +57,11 @@ // break subsequent system calls that trigger a SIGSYS. ~Trap() = delete; - static void SigSysAction(int nr, siginfo_t* info, void* void_context); + static void SigSysAction(int nr, LinuxSigInfo* info, void* void_context); // Make sure that SigSys is not inlined in order to get slightly better crash // dumps. - void SigSys(int nr, siginfo_t* info, void* void_context) + void SigSys(int nr, LinuxSigInfo* info, void* void_context) __attribute__((noinline)); // We have a global singleton that handles all of our SIGSYS traps. This // variable must never be deallocated after it has been set up initially, as
diff --git a/sandbox/linux/seccomp-bpf/trap_unittest.cc b/sandbox/linux/seccomp-bpf/trap_unittest.cc new file mode 100644 index 0000000..99f94bfb --- /dev/null +++ b/sandbox/linux/seccomp-bpf/trap_unittest.cc
@@ -0,0 +1,28 @@ +// 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 "sandbox/linux/seccomp-bpf/trap.h" + +#include <signal.h> + +#include "sandbox/linux/tests/unit_tests.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace sandbox { +namespace { + +SANDBOX_TEST_ALLOW_NOISE(Trap, SigSysAction) { + // This creates a global Trap instance, and registers the signal handler + // (Trap::SigSysAction). + Trap::Registry(); + + // Send SIGSYS to self. If signal handler (SigSysAction) is not registered, + // the process will be terminated with status code -SIGSYS. + // Note that, SigSysAction handler would output an error message + // "Unexpected SIGSYS received." so it is necessary to allow the noise. + raise(SIGSYS); +} + +} // namespace +} // namespace sandbox
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc index b562d8b7..35bb4dc 100644 --- a/sandbox/linux/services/credentials.cc +++ b/sandbox/linux/services/credentials.cc
@@ -27,16 +27,12 @@ #include "sandbox/linux/services/syscall_wrappers.h" #include "sandbox/linux/services/thread_helpers.h" #include "sandbox/linux/system_headers/capability.h" +#include "sandbox/linux/system_headers/linux_signal.h" namespace sandbox { namespace { -// Signal ABI for some toolchain is incompatible with Linux's. In particular, -// PNaCl toolchain defines SIGCHLD = 20. So, here, directly define Linux's -// value. -const int kLinuxSIGCHLD = 17; - bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; } // Checks that the set of RES-uids and the set of RES-gids have @@ -96,8 +92,8 @@ #endif pid = clone(ChrootToSelfFdinfo, stack, - CLONE_VM | CLONE_VFORK | CLONE_FS | kLinuxSIGCHLD, - nullptr, nullptr, nullptr, nullptr); + CLONE_VM | CLONE_VFORK | CLONE_FS | LINUX_SIGCHLD, nullptr, + nullptr, nullptr, nullptr); PCHECK(pid != -1); int status = -1;
diff --git a/sandbox/linux/services/syscall_wrappers.cc b/sandbox/linux/services/syscall_wrappers.cc index e793fad5..a84d3299 100644 --- a/sandbox/linux/services/syscall_wrappers.cc +++ b/sandbox/linux/services/syscall_wrappers.cc
@@ -12,12 +12,14 @@ #include <sys/time.h> #include <sys/types.h> #include <unistd.h> +#include <cstring> #include "base/compiler_specific.h" #include "base/logging.h" #include "base/third_party/valgrind/valgrind.h" #include "build/build_config.h" #include "sandbox/linux/system_headers/capability.h" +#include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/linux/system_headers/linux_syscalls.h" namespace sandbox { @@ -137,4 +139,101 @@ return syscall(__NR_unshare, flags); } +int sys_sigprocmask(int how, const sigset_t* set, decltype(nullptr) oldset) { + // In some toolchain (in particular Android and PNaCl toolchain), + // sigset_t is 32 bits, but Linux ABI requires 64 bits. + uint64_t linux_value = 0; + std::memcpy(&linux_value, set, std::min(sizeof(sigset_t), sizeof(uint64_t))); + return syscall(__NR_rt_sigprocmask, how, &linux_value, nullptr, + sizeof(linux_value)); +} + +#if defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \ + (defined(ARCH_CPU_X86_64) && !defined(__clang__)) +// If MEMORY_SANITIZER or THREAD_SANITIZER is enabled, it is necessary to call +// sigaction() here, rather than the direct syscall (sys_sigaction() defined +// by ourselves). +// It is because, if MEMORY_SANITIZER or THREAD_SANITIZER is enabled, sigaction +// is wrapped, and |act->sa_handler| is injected in order to unpoisonize the +// memory passed via callback's arguments for MEMORY_SANITIZER, or handle +// signals to check thread consistency for THREAD_SANITIZER. Please see +// msan_interceptors.cc and tsan_interceptors.cc for more details. +// So, specifically, if MEMORY_SANITIZER is enabled while the direct syscall is +// used, as MEMORY_SANITIZER does not know about it, sigaction() invocation in +// other places would be broken (in more precise, returned |oldact| would have +// a broken |sa_handler| callback). +// Practically, it would break NaCl's signal handler installation. +// cf) native_client/src/trusted/service_runtime/linux/nacl_signal.c. +// As for THREAD_SANITIZER, the intercepted signal handlers are processed more +// in other libc functions' interceptors (such as for raise()), so that it +// would not work properly. +// +// Also on x86_64 architecture, we need naked function for rt_sigreturn. +// However, there is no simple way to define it with GCC. Note that the body +// of function is actually very small (only two instructions), but we need to +// define much debug information in addition, otherwise backtrace() used by +// base::StackTrace would not work so that some tests would fail. +int sys_sigaction(int signum, + const struct sigaction* act, + struct sigaction* oldact) { + return sigaction(signum, act, oldact); +} +#else +// struct sigaction is different ABI from the Linux's. +struct KernelSigAction { + void (*kernel_handler)(int); + uint32_t sa_flags; + void (*sa_restorer)(void); + uint64_t sa_mask; +}; + +// On X86_64 arch, it is necessary to set sa_restorer always. +#if defined(ARCH_CPU_X86_64) +#if !defined(SA_RESTORER) +#define SA_RESTORER 0x04000000 +#endif + +// rt_sigreturn is a special system call that interacts with the user land +// stack. Thus, here prologue must not be created, which implies syscall() +// does not work properly, too. Note that rt_sigreturn will never return. +static __attribute__((naked)) void sys_rt_sigreturn() { + // Just invoke rt_sigreturn system call. + asm volatile ("syscall\n" + :: "a"(__NR_rt_sigreturn)); +} +#endif + +int sys_sigaction(int signum, + const struct sigaction* act, + struct sigaction* oldact) { + KernelSigAction kernel_act = {}; + if (act) { + kernel_act.kernel_handler = act->sa_handler; + std::memcpy(&kernel_act.sa_mask, &act->sa_mask, + std::min(sizeof(kernel_act.sa_mask), sizeof(act->sa_mask))); + kernel_act.sa_flags = act->sa_flags; + +#if defined(ARCH_CPU_X86_64) + if (!(kernel_act.sa_flags & SA_RESTORER)) { + kernel_act.sa_flags |= SA_RESTORER; + kernel_act.sa_restorer = sys_rt_sigreturn; + } +#endif + } + + KernelSigAction kernel_oldact = {}; + int result = syscall(__NR_rt_sigaction, signum, act ? &kernel_act : nullptr, + oldact ? &kernel_oldact : nullptr, sizeof(uint64_t)); + if (result == 0 && oldact) { + oldact->sa_handler = kernel_oldact.kernel_handler; + sigemptyset(&oldact->sa_mask); + std::memcpy(&oldact->sa_mask, &kernel_oldact.sa_mask, + std::min(sizeof(kernel_act.sa_mask), sizeof(act->sa_mask))); + oldact->sa_flags = kernel_oldact.sa_flags; + } + return result; +} + +#endif // defined(MEMORY_SANITIZER) + } // namespace sandbox
diff --git a/sandbox/linux/services/syscall_wrappers.h b/sandbox/linux/services/syscall_wrappers.h index 4558adf..581425a 100644 --- a/sandbox/linux/services/syscall_wrappers.h +++ b/sandbox/linux/services/syscall_wrappers.h
@@ -5,6 +5,7 @@ #ifndef SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ #define SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_ +#include <signal.h> #include <stdint.h> #include <sys/types.h> @@ -66,6 +67,17 @@ // Some libcs do not expose a unshare wrapper. SANDBOX_EXPORT int sys_unshare(int flags); +// Some libcs do not expose a sigprocmask. Note that oldset must be a nullptr, +// because of some ABI gap between toolchain's and Linux's. +SANDBOX_EXPORT int sys_sigprocmask(int how, + const sigset_t* set, + decltype(nullptr) oldset); + +// Some libcs do not expose a sigaction(). +SANDBOX_EXPORT int sys_sigaction(int signum, + const struct sigaction* act, + struct sigaction* oldact); + } // namespace sandbox #endif // SANDBOX_LINUX_SERVICES_SYSCALL_WRAPPERS_H_
diff --git a/sandbox/linux/services/syscall_wrappers_unittest.cc b/sandbox/linux/services/syscall_wrappers_unittest.cc index 6a70beb..1878ff3 100644 --- a/sandbox/linux/services/syscall_wrappers_unittest.cc +++ b/sandbox/linux/services/syscall_wrappers_unittest.cc
@@ -8,11 +8,13 @@ #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> +#include <cstring> #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/third_party/valgrind/valgrind.h" #include "build/build_config.h" +#include "sandbox/linux/system_headers/linux_signal.h" #include "sandbox/linux/tests/test_utils.h" #include "sandbox/linux/tests/unit_tests.h" #include "testing/gtest/include/gtest/gtest.h" @@ -80,6 +82,18 @@ EXPECT_EQ(sgid, sys_sgid); } +TEST(SyscallWrappers, LinuxSigSet) { + sigset_t sigset; + ASSERT_EQ(0, sigemptyset(&sigset)); + ASSERT_EQ(0, sigaddset(&sigset, LINUX_SIGSEGV)); + ASSERT_EQ(0, sigaddset(&sigset, LINUX_SIGBUS)); + uint64_t linux_sigset = 0; + std::memcpy(&linux_sigset, &sigset, + std::min(sizeof(sigset), sizeof(linux_sigset))); + EXPECT_EQ((1ULL << (LINUX_SIGSEGV - 1)) | (1ULL << (LINUX_SIGBUS - 1)), + linux_sigset); +} + } // namespace } // namespace sandbox
diff --git a/sandbox/linux/system_headers/android_arm64_ucontext.h b/sandbox/linux/system_headers/android_arm64_ucontext.h deleted file mode 100644 index df2b66a..0000000 --- a/sandbox/linux/system_headers/android_arm64_ucontext.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 SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_ - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#include <asm/sigcontext.h> -#include <signal.h> -// We also need greg_t for the sandbox, include it in this header as well. -typedef uint64_t greg_t; - -struct ucontext_t { - unsigned long uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - sigset_t uc_sigmask; - /* glibc uses a 1024-bit sigset_t */ - uint8_t unused[1024 / 8 - sizeof(sigset_t)]; - /* last for future expansion */ - struct sigcontext uc_mcontext; -}; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM64_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_arm_ucontext.h b/sandbox/linux/system_headers/android_arm_ucontext.h deleted file mode 100644 index a380499..0000000 --- a/sandbox/linux/system_headers/android_arm_ucontext.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_ - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#include <asm/sigcontext.h> - -// We also need greg_t for the sandbox, include it in this header as well. -typedef unsigned long greg_t; - -//typedef unsigned long sigset_t; -typedef struct ucontext { - unsigned long uc_flags; - struct ucontext *uc_link; - stack_t uc_stack; - struct sigcontext uc_mcontext; - sigset_t uc_sigmask; - /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */ - int __not_used[32 - (sizeof (sigset_t) / sizeof (int))]; - /* Last for extensibility. Eight byte aligned because some - coprocessors require eight byte alignment. */ - unsigned long uc_regspace[128] __attribute__((__aligned__(8))); -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_ARM_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_i386_ucontext.h b/sandbox/linux/system_headers/android_i386_ucontext.h deleted file mode 100644 index 868016b5..0000000 --- a/sandbox/linux/system_headers/android_i386_ucontext.h +++ /dev/null
@@ -1,79 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_ - -// We do something compatible with glibc. Hopefully, at some point Android will -// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. -// This is mostly copied from breakpad (common/android/include/sys/ucontext.h), -// except we do use sigset_t for uc_sigmask instead of a custom type. - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#include <asm/sigcontext.h> - -/* 80-bit floating-point register */ -struct _libc_fpreg { - unsigned short significand[4]; - unsigned short exponent; -}; - -/* Simple floating-point state, see FNSTENV instruction */ -struct _libc_fpstate { - unsigned long cw; - unsigned long sw; - unsigned long tag; - unsigned long ipoff; - unsigned long cssel; - unsigned long dataoff; - unsigned long datasel; - struct _libc_fpreg _st[8]; - unsigned long status; -}; - -typedef uint32_t greg_t; - -typedef struct { - uint32_t gregs[19]; - struct _libc_fpstate* fpregs; - uint32_t oldmask; - uint32_t cr2; -} mcontext_t; - -enum { - REG_GS = 0, - REG_FS, - REG_ES, - REG_DS, - REG_EDI, - REG_ESI, - REG_EBP, - REG_ESP, - REG_EBX, - REG_EDX, - REG_ECX, - REG_EAX, - REG_TRAPNO, - REG_ERR, - REG_EIP, - REG_CS, - REG_EFL, - REG_UESP, - REG_SS, -}; - -typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - struct _libc_fpstate __fpregs_mem; -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_mips_ucontext.h b/sandbox/linux/system_headers/android_mips_ucontext.h deleted file mode 100644 index ec3aa63..0000000 --- a/sandbox/linux/system_headers/android_mips_ucontext.h +++ /dev/null
@@ -1,51 +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 SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_ - -// This is mostly copied from breakpad (common/android/include/sys/ucontext.h), -// except we do use sigset_t for uc_sigmask instead of a custom type. -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -// Ensure that 'stack_t' is defined. -#include <asm/signal.h> - -// We also need greg_t for the sandbox, include it in this header as well. -typedef unsigned long greg_t; - -typedef struct { - uint32_t regmask; - uint32_t status; - uint64_t pc; - uint64_t gregs[32]; - uint64_t fpregs[32]; - uint32_t acx; - uint32_t fpc_csr; - uint32_t fpc_eir; - uint32_t used_math; - uint32_t dsp; - uint64_t mdhi; - uint64_t mdlo; - uint32_t hi1; - uint32_t lo1; - uint32_t hi2; - uint32_t lo2; - uint32_t hi3; - uint32_t lo3; -} mcontext_t; - -typedef struct ucontext { - uint32_t uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - // Other fields are not used by Google Breakpad. Don't define them. -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_MIPS_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_ucontext.h b/sandbox/linux/system_headers/android_ucontext.h deleted file mode 100644 index 8e873be..0000000 --- a/sandbox/linux/system_headers/android_ucontext.h +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright (c) 2013 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 SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_ - -#if defined(__ANDROID__) - -#if defined(__arm__) -#include "sandbox/linux/system_headers/android_arm_ucontext.h" -#elif defined(__i386__) -#include "sandbox/linux/system_headers/android_i386_ucontext.h" -#elif defined(__x86_64__) -#include "sandbox/linux/system_headers/android_x86_64_ucontext.h" -#elif defined(__mips__) -#include "sandbox/linux/system_headers/android_mips_ucontext.h" -#elif defined(__aarch64__) -#include "sandbox/linux/system_headers/android_arm64_ucontext.h" -#else -#error "No support for your architecture in Android header" -#endif - -#else // __ANDROID__ -#error "Android header file included on non Android." -#endif // __ANDROID__ - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/android_x86_64_ucontext.h b/sandbox/linux/system_headers/android_x86_64_ucontext.h deleted file mode 100644 index 778e6d0..0000000 --- a/sandbox/linux/system_headers/android_x86_64_ucontext.h +++ /dev/null
@@ -1,88 +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 SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_ -#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_ - -// We do something compatible with glibc. Hopefully, at some point Android will -// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. -// Spec: -// http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/libc-ddefs.html#AEN5668 - -#if !defined(__BIONIC_HAVE_UCONTEXT_T) -#include <asm/sigcontext.h> - -struct _libc_fpxreg { - unsigned short significand[4]; - unsigned short exponent; - unsigned short padding[3]; -}; - -struct _libc_xmmreg { - uint32_t element[4]; -}; - -struct _libc_fpstate { - uint16_t cwd; - uint16_t swd; - uint16_t twd; - uint16_t fop; - uint64_t rip; - uint64_t rdp; - uint32_t mxcsr; - uint32_t mxcsr_mask; - struct _libc_fpxreg _st[8]; - struct _libc_xmmreg _xmm[16]; - uint32_t padding[24]; -}; - -typedef uint64_t greg_t; - -typedef struct { - greg_t gregs[23]; - struct _libc_fpstate* fpregs; - unsigned long __reserved1[8]; -} mcontext_t; - -enum { - REG_R8 = 0, - REG_R9, - REG_R10, - REG_R11, - REG_R12, - REG_R13, - REG_R14, - REG_R15, - REG_RDI, - REG_RSI, - REG_RBP, - REG_RBX, - REG_RDX, - REG_RAX, - REG_RCX, - REG_RSP, - REG_RIP, - REG_EFL, - REG_CSGSFS, - REG_ERR, - REG_TRAPNO, - REG_OLDMASK, - REG_CR2, - NGREG, -}; - -typedef struct ucontext { - unsigned long uc_flags; - struct ucontext* uc_link; - stack_t uc_stack; - mcontext_t uc_mcontext; - sigset_t uc_sigmask; - struct _libc_fpstate __fpregs_mem; -} ucontext_t; - -#else -#include <sys/ucontext.h> -#endif // __BIONIC_HAVE_UCONTEXT_T - -#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_X86_64_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/arm64_linux_ucontext.h b/sandbox/linux/system_headers/arm64_linux_ucontext.h new file mode 100644 index 0000000..46e0407 --- /dev/null +++ b/sandbox/linux/system_headers/arm64_linux_ucontext.h
@@ -0,0 +1,29 @@ +// 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 SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_ + +#if !defined(__BIONIC_HAVE_UCONTEXT_T) +#include <asm/sigcontext.h> +#include <signal.h> +// We also need greg_t for the sandbox, include it in this header as well. +typedef uint64_t greg_t; + +struct ucontext_t { + unsigned long uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + sigset_t uc_sigmask; + /* glibc uses a 1024-bit sigset_t */ + uint8_t unused[1024 / 8 - sizeof(sigset_t)]; + /* last for future expansion */ + struct sigcontext uc_mcontext; +}; + +#else +#include <sys/ucontext.h> +#endif // __BIONIC_HAVE_UCONTEXT_T + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM64_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/arm_linux_ucontext.h b/sandbox/linux/system_headers/arm_linux_ucontext.h new file mode 100644 index 0000000..0eb723a --- /dev/null +++ b/sandbox/linux/system_headers/arm_linux_ucontext.h
@@ -0,0 +1,67 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_ + +#if !defined(__BIONIC_HAVE_UCONTEXT_T) +#if !defined(__native_client_nonsfi__) +#include <asm/sigcontext.h> +#else +// In PNaCl toolchain, sigcontext and stack_t is not defined. So here declare +// them. +struct sigcontext { + unsigned long trap_no; + unsigned long error_code; + unsigned long oldmask; + unsigned long arm_r0; + unsigned long arm_r1; + unsigned long arm_r2; + unsigned long arm_r3; + unsigned long arm_r4; + unsigned long arm_r5; + unsigned long arm_r6; + unsigned long arm_r7; + unsigned long arm_r8; + unsigned long arm_r9; + unsigned long arm_r10; + unsigned long arm_fp; + unsigned long arm_ip; + unsigned long arm_sp; + unsigned long arm_lr; + unsigned long arm_pc; + unsigned long arm_cpsr; + unsigned long fault_address; +}; + +typedef struct sigaltstack { + void* ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; + +#endif + +// We also need greg_t for the sandbox, include it in this header as well. +typedef unsigned long greg_t; + +// typedef unsigned long sigset_t; +typedef struct ucontext { + unsigned long uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + struct sigcontext uc_mcontext; + sigset_t uc_sigmask; + /* Allow for uc_sigmask growth. Glibc uses a 1024-bit sigset_t. */ + int __not_used[32 - (sizeof(sigset_t) / sizeof(int))]; + /* Last for extensibility. Eight byte aligned because some + coprocessors require eight byte alignment. */ + unsigned long uc_regspace[128] __attribute__((__aligned__(8))); +} ucontext_t; + +#else +#include <sys/ucontext.h> +#endif // __BIONIC_HAVE_UCONTEXT_T + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ARM_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/i386_linux_ucontext.h b/sandbox/linux/system_headers/i386_linux_ucontext.h new file mode 100644 index 0000000..61d9f7a --- /dev/null +++ b/sandbox/linux/system_headers/i386_linux_ucontext.h
@@ -0,0 +1,93 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_ + +// We do something compatible with glibc. Hopefully, at some point Android will +// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. +// This is mostly copied from breakpad (common/android/include/sys/ucontext.h), +// except we do use sigset_t for uc_sigmask instead of a custom type. + +#if !defined(__BIONIC_HAVE_UCONTEXT_T) +#if !defined(__native_client_nonsfi__) +#include <asm/sigcontext.h> +#else +// In PNaCl toolchain, sigcontext is not defined. So here declare it. +typedef struct sigaltstack { + void* ss_sp; + int ss_flags; + size_t ss_size; +} stack_t; +#endif + +/* 80-bit floating-point register */ +struct _libc_fpreg { + unsigned short significand[4]; + unsigned short exponent; +}; + +/* Simple floating-point state, see FNSTENV instruction */ +struct _libc_fpstate { + unsigned long cw; + unsigned long sw; + unsigned long tag; + unsigned long ipoff; + unsigned long cssel; + unsigned long dataoff; + unsigned long datasel; + struct _libc_fpreg _st[8]; + unsigned long status; +}; + +typedef uint32_t greg_t; + +typedef struct { + uint32_t gregs[19]; + struct _libc_fpstate* fpregs; + uint32_t oldmask; + uint32_t cr2; +} mcontext_t; + +enum { + REG_GS = 0, + REG_FS, + REG_ES, + REG_DS, + REG_EDI, + REG_ESI, + REG_EBP, + REG_ESP, + REG_EBX, + REG_EDX, + REG_ECX, + REG_EAX, + REG_TRAPNO, + REG_ERR, + REG_EIP, + REG_CS, + REG_EFL, + REG_UESP, + REG_SS, +}; + +typedef struct ucontext { + uint32_t uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + // Android and PNaCl toolchain's sigset_t has only 32 bits, though Linux + // ABI requires 64 bits. + union { + sigset_t uc_sigmask; + uint32_t kernel_sigmask[2]; + }; + struct _libc_fpstate __fpregs_mem; +} ucontext_t; + +#else +#include <sys/ucontext.h> +#endif // __BIONIC_HAVE_UCONTEXT_T + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_ANDROID_I386_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/linux_signal.h b/sandbox/linux/system_headers/linux_signal.h new file mode 100644 index 0000000..5db7fc5 --- /dev/null +++ b/sandbox/linux/system_headers/linux_signal.h
@@ -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. + +#ifndef SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_ + +// NOTE: On some toolchains, signal related ABI is incompatible with Linux's +// (not undefined, but defined different values and in different memory +// layouts). So, fill the gap here. + +#if defined(__native_client_nonsfi__) +#if !defined(__i386__) && !defined(__arm__) +#error "Unsupported platform" +#endif + +#include <signal.h> + +#define LINUX_SIGBUS 7 // 10 in PNaCl toolchain. +#define LINUX_SIGSEGV 11 // 11 in PNaCl toolchain. Defined for consistency. +#define LINUX_SIGCHLD 17 // 20 in PNaCl toolchain. +#define LINUX_SIGSYS 31 // 12 in PNaCl toolchain. + +#define LINUX_SIG_BLOCK 0 // 1 in PNaCl toolchain. +#define LINUX_SIG_UNBLOCK 1 // 2 in PNaCl toolchain. + +#define LINUX_SA_SIGINFO 4 // 2 in PNaCl toolchain. +#define LINUX_SA_NODEFER 0x40000000 // Undefined in PNaCl toolchain. +#define LINUX_SA_RESTART 0x10000000 // Undefined in PNaCl toolchain. + +#define LINUX_SIG_DFL 0 // In PNaCl toolchain, unneeded cast is applied. + +struct LinuxSigInfo { + int si_signo; + int si_errno; + int si_code; + + // Extra data is followed by the |si_code|. The length depends on the + // signal number. + char _sifields[1]; +}; + +#include "sandbox/linux/system_headers/linux_ucontext.h" + +#else // !defined(__native_client_nonsfi__) + +// Just alias the toolchain's value. +#include <signal.h> + +#define LINUX_SIGBUS SIGBUS +#define LINUX_SIGSEGV SIGSEGV +#define LINUX_SIGCHLD SIGCHLD +#define LINUX_SIGSYS SIGSYS + +#define LINUX_SIG_BLOCK SIG_BLOCK +#define LINUX_SIG_UNBLOCK SIG_UNBLOCK + +#define LINUX_SA_SIGINFO SA_SIGINFO +#define LINUX_SA_NODEFER SA_NODEFER +#define LINUX_SA_RESTART SA_RESTART + +#define LINUX_SIG_DFL SIG_DFL + +typedef siginfo_t LinuxSigInfo; + +#if defined(__ANDROID__) +// Android's signal.h doesn't define ucontext etc. +#include "sandbox/linux/system_headers/linux_ucontext.h" +#endif // defined(__ANDROID__) + +#endif // !defined(__native_client_nonsfi__) + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SIGNAL_H_
diff --git a/sandbox/linux/system_headers/linux_ucontext.h b/sandbox/linux/system_headers/linux_ucontext.h new file mode 100644 index 0000000..ea4d8a6 --- /dev/null +++ b/sandbox/linux/system_headers/linux_ucontext.h
@@ -0,0 +1,28 @@ +// Copyright (c) 2013 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 SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_ + +#if defined(__ANDROID__) || defined(__native_client_nonsfi__) + +#if defined(__arm__) +#include "sandbox/linux/system_headers/arm_linux_ucontext.h" +#elif defined(__i386__) +#include "sandbox/linux/system_headers/i386_linux_ucontext.h" +#elif defined(__x86_64__) +#include "sandbox/linux/system_headers/x86_64_linux_ucontext.h" +#elif defined(__mips__) +#include "sandbox/linux/system_headers/mips_linux_ucontext.h" +#elif defined(__aarch64__) +#include "sandbox/linux/system_headers/arm64_linux_ucontext.h" +#else +#error "No support for your architecture in Android or PNaCl header" +#endif + +#else // defined(__ANDROID__) || defined(__native_client_nonsfi__) +#error "The header file included on non Android and non PNaCl." +#endif // defined(__ANDROID__) || defined(__native_client_nonsfi__) + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/mips_linux_ucontext.h b/sandbox/linux/system_headers/mips_linux_ucontext.h new file mode 100644 index 0000000..27b37635 --- /dev/null +++ b/sandbox/linux/system_headers/mips_linux_ucontext.h
@@ -0,0 +1,51 @@ +// 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 SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_ + +// This is mostly copied from breakpad (common/android/include/sys/ucontext.h), +// except we do use sigset_t for uc_sigmask instead of a custom type. +#if !defined(__BIONIC_HAVE_UCONTEXT_T) +// Ensure that 'stack_t' is defined. +#include <asm/signal.h> + +// We also need greg_t for the sandbox, include it in this header as well. +typedef unsigned long greg_t; + +typedef struct { + uint32_t regmask; + uint32_t status; + uint64_t pc; + uint64_t gregs[32]; + uint64_t fpregs[32]; + uint32_t acx; + uint32_t fpc_csr; + uint32_t fpc_eir; + uint32_t used_math; + uint32_t dsp; + uint64_t mdhi; + uint64_t mdlo; + uint32_t hi1; + uint32_t lo1; + uint32_t hi2; + uint32_t lo2; + uint32_t hi3; + uint32_t lo3; +} mcontext_t; + +typedef struct ucontext { + uint32_t uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + sigset_t uc_sigmask; + // Other fields are not used by Google Breakpad. Don't define them. +} ucontext_t; + +#else +#include <sys/ucontext.h> +#endif // __BIONIC_HAVE_UCONTEXT_T + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_MIPS_LINUX_UCONTEXT_H_
diff --git a/sandbox/linux/system_headers/x86_64_linux_ucontext.h b/sandbox/linux/system_headers/x86_64_linux_ucontext.h new file mode 100644 index 0000000..57b8919 --- /dev/null +++ b/sandbox/linux/system_headers/x86_64_linux_ucontext.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 SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ +#define SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_ + +// We do something compatible with glibc. Hopefully, at some point Android will +// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined. +// Spec: +// http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/libc-ddefs.html#AEN5668 + +#if !defined(__BIONIC_HAVE_UCONTEXT_T) +#include <asm/sigcontext.h> + +struct _libc_fpxreg { + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _libc_xmmreg { + uint32_t element[4]; +}; + +struct _libc_fpstate { + uint16_t cwd; + uint16_t swd; + uint16_t twd; + uint16_t fop; + uint64_t rip; + uint64_t rdp; + uint32_t mxcsr; + uint32_t mxcsr_mask; + struct _libc_fpxreg _st[8]; + struct _libc_xmmreg _xmm[16]; + uint32_t padding[24]; +}; + +typedef uint64_t greg_t; + +typedef struct { + greg_t gregs[23]; + struct _libc_fpstate* fpregs; + unsigned long __reserved1[8]; +} mcontext_t; + +enum { + REG_R8 = 0, + REG_R9, + REG_R10, + REG_R11, + REG_R12, + REG_R13, + REG_R14, + REG_R15, + REG_RDI, + REG_RSI, + REG_RBP, + REG_RBX, + REG_RDX, + REG_RAX, + REG_RCX, + REG_RSP, + REG_RIP, + REG_EFL, + REG_CSGSFS, + REG_ERR, + REG_TRAPNO, + REG_OLDMASK, + REG_CR2, + NGREG, +}; + +typedef struct ucontext { + unsigned long uc_flags; + struct ucontext* uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; +} ucontext_t; + +#else +#include <sys/ucontext.h> +#endif // __BIONIC_HAVE_UCONTEXT_T + +#endif // SANDBOX_LINUX_SYSTEM_HEADERS_X86_64_LINUX_UCONTEXT_H_
diff --git a/sandbox/win/src/broker_services.h b/sandbox/win/src/broker_services.h index 76011e5..3e7a179 100644 --- a/sandbox/win/src/broker_services.h +++ b/sandbox/win/src/broker_services.h
@@ -45,17 +45,17 @@ ~BrokerServicesBase(); // BrokerServices interface. - virtual ResultCode Init() override; - virtual TargetPolicy* CreatePolicy() override; - virtual ResultCode SpawnTarget(const wchar_t* exe_path, - const wchar_t* command_line, - TargetPolicy* policy, - PROCESS_INFORMATION* target) override; - virtual ResultCode WaitForAllTargets() override; - virtual ResultCode AddTargetPeer(HANDLE peer_process) override; - virtual ResultCode InstallAppContainer(const wchar_t* sid, - const wchar_t* name) override; - virtual ResultCode UninstallAppContainer(const wchar_t* sid) override; + ResultCode Init() override; + TargetPolicy* CreatePolicy() override; + ResultCode SpawnTarget(const wchar_t* exe_path, + const wchar_t* command_line, + TargetPolicy* policy, + PROCESS_INFORMATION* target) override; + ResultCode WaitForAllTargets() override; + ResultCode AddTargetPeer(HANDLE peer_process) override; + ResultCode InstallAppContainer(const wchar_t* sid, + const wchar_t* name) override; + ResultCode UninstallAppContainer(const wchar_t* sid) override; // Checks if the supplied process ID matches one of the broker's active // target processes
diff --git a/sandbox/win/src/crosscall_server.cc b/sandbox/win/src/crosscall_server.cc index a01af66..6f8bd74 100644 --- a/sandbox/win/src/crosscall_server.cc +++ b/sandbox/win/src/crosscall_server.cc
@@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "sandbox/win/src/crosscall_server.h" + #include <string> #include <vector> -#include "sandbox/win/src/crosscall_server.h" #include "sandbox/win/src/crosscall_params.h" #include "sandbox/win/src/crosscall_client.h" #include "base/logging.h" @@ -297,4 +298,10 @@ return NULL; } +Dispatcher::Dispatcher() { +} + +Dispatcher::~Dispatcher() { +} + } // namespace sandbox
diff --git a/sandbox/win/src/crosscall_server.h b/sandbox/win/src/crosscall_server.h index e754006..41888c1 100644 --- a/sandbox/win/src/crosscall_server.h +++ b/sandbox/win/src/crosscall_server.h
@@ -207,7 +207,8 @@ // with the given service (IPC). virtual bool SetupService(InterceptionManager* manager, int service) = 0; - virtual ~Dispatcher() {} + Dispatcher(); + virtual ~Dispatcher(); protected: // Structure that defines an IPC Call with all the parameters and the handler.
diff --git a/sandbox/win/src/handle_closer.cc b/sandbox/win/src/handle_closer.cc index 4111623..2e3a782 100644 --- a/sandbox/win/src/handle_closer.cc +++ b/sandbox/win/src/handle_closer.cc
@@ -32,7 +32,11 @@ // Memory buffer mapped from the parent, with the list of handles. SANDBOX_INTERCEPT HandleCloserInfo* g_handles_to_close; -HandleCloser::HandleCloser() {} +HandleCloser::HandleCloser() { +} + +HandleCloser::~HandleCloser() { +} ResultCode HandleCloser::AddHandle(const base::char16* handle_type, const base::char16* handle_name) {
diff --git a/sandbox/win/src/handle_closer.h b/sandbox/win/src/handle_closer.h index fa65695..2b43a6ea 100644 --- a/sandbox/win/src/handle_closer.h +++ b/sandbox/win/src/handle_closer.h
@@ -42,6 +42,7 @@ class HandleCloser { public: HandleCloser(); + ~HandleCloser(); // Adds a handle that will be closed in the target process after lockdown. // A NULL value for handle_name indicates all handles of the specified type.
diff --git a/sandbox/win/src/handle_table.cc b/sandbox/win/src/handle_table.cc index 5575dc0..5ebcf99 100644 --- a/sandbox/win/src/handle_table.cc +++ b/sandbox/win/src/handle_table.cc
@@ -64,6 +64,9 @@ handle_info_internal()->NumberOfHandles, CompareHandleEntries); } +HandleTable::~HandleTable() { +} + HandleTable::Iterator HandleTable::HandlesForProcess(ULONG process_id) const { SYSTEM_HANDLE_INFORMATION key; key.ProcessId = static_cast<USHORT>(process_id); @@ -84,6 +87,9 @@ : handle_entry_(handle_info_entry), last_entry_(0) { } +HandleTable::HandleEntry::~HandleEntry() { +} + void HandleTable::HandleEntry::UpdateInfo(UpdateType flag) { static NtQueryObject QueryObject = NULL; if (!QueryObject)
diff --git a/sandbox/win/src/handle_table.h b/sandbox/win/src/handle_table.h index 1b553fa..47f625d9 100644 --- a/sandbox/win/src/handle_table.h +++ b/sandbox/win/src/handle_table.h
@@ -40,6 +40,8 @@ // Used by the iterator to provide simple caching accessors to handle data. class HandleEntry { public: + ~HandleEntry(); + bool operator==(const HandleEntry& rhs) const { return handle_entry_ == rhs.handle_entry_; } @@ -126,6 +128,7 @@ }; HandleTable(); + ~HandleTable(); Iterator begin() const { return Iterator(*this, handle_info()->Information,
diff --git a/sandbox/win/src/policy_low_level.cc b/sandbox/win/src/policy_low_level.cc index ef9b4e1f..739321c 100644 --- a/sandbox/win/src/policy_low_level.cc +++ b/sandbox/win/src/policy_low_level.cc
@@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "sandbox/win/src/policy_low_level.h" + #include <string> #include <map> -#include "sandbox/win/src/policy_low_level.h" #include "base/basictypes.h" namespace { @@ -31,6 +32,10 @@ namespace sandbox { +LowLevelPolicy::LowLevelPolicy(PolicyGlobal* policy_store) + : policy_store_(policy_store) { +} + // Adding a rule is nothing more than pushing it into an stl container. Done() // is called for the rule in case the code that made the rule in the first // place has not done it.
diff --git a/sandbox/win/src/policy_low_level.h b/sandbox/win/src/policy_low_level.h index 7abc0ef..6a62631 100644 --- a/sandbox/win/src/policy_low_level.h +++ b/sandbox/win/src/policy_low_level.h
@@ -82,9 +82,7 @@ public: // policy_store: must contain allocated memory and the internal // size fields set to correct values. - explicit LowLevelPolicy(PolicyGlobal* policy_store) - : policy_store_(policy_store) { - } + explicit LowLevelPolicy(PolicyGlobal* policy_store); // Destroys all the policy rules. ~LowLevelPolicy();
diff --git a/sandbox/win/src/restricted_token.cc b/sandbox/win/src/restricted_token.cc index 3960926..7ebef3de 100644 --- a/sandbox/win/src/restricted_token.cc +++ b/sandbox/win/src/restricted_token.cc
@@ -10,9 +10,19 @@ #include "sandbox/win/src/acl.h" #include "sandbox/win/src/win_utils.h" - namespace sandbox { +RestrictedToken::RestrictedToken() + : init_(false), + effective_token_(NULL), + integrity_level_(INTEGRITY_LEVEL_LAST) { +} + +RestrictedToken::~RestrictedToken() { + if (effective_token_) + CloseHandle(effective_token_); +} + unsigned RestrictedToken::Init(const HANDLE effective_token) { if (init_) return ERROR_ALREADY_INITIALIZED;
diff --git a/sandbox/win/src/restricted_token.h b/sandbox/win/src/restricted_token.h index 6d8e550..565880e 100644 --- a/sandbox/win/src/restricted_token.h +++ b/sandbox/win/src/restricted_token.h
@@ -45,14 +45,8 @@ class RestrictedToken { public: // Init() has to be called before calling any other method in the class. - RestrictedToken() - : init_(false), effective_token_(NULL), - integrity_level_(INTEGRITY_LEVEL_LAST) { } - - ~RestrictedToken() { - if (effective_token_) - CloseHandle(effective_token_); - } + RestrictedToken(); + ~RestrictedToken(); // Initializes the RestrictedToken object with effective_token. // If effective_token is NULL, it initializes the RestrictedToken object with
diff --git a/sandbox/win/src/sandbox_policy_base.h b/sandbox/win/src/sandbox_policy_base.h index ea0f3e6..587d793 100644 --- a/sandbox/win/src/sandbox_policy_base.h +++ b/sandbox/win/src/sandbox_policy_base.h
@@ -37,45 +37,41 @@ PolicyBase(); // TargetPolicy: - virtual void AddRef() override; - virtual void Release() override; - virtual ResultCode SetTokenLevel(TokenLevel initial, - TokenLevel lockdown) override; - virtual TokenLevel GetInitialTokenLevel() const override; - virtual TokenLevel GetLockdownTokenLevel() const override; - virtual ResultCode SetJobLevel(JobLevel job_level, - uint32 ui_exceptions) override; - virtual ResultCode SetJobMemoryLimit(size_t memory_limit) override; - virtual ResultCode SetAlternateDesktop(bool alternate_winstation) override; - virtual base::string16 GetAlternateDesktop() const override; - virtual ResultCode CreateAlternateDesktop(bool alternate_winstation) override; - virtual void DestroyAlternateDesktop() override; - virtual ResultCode SetIntegrityLevel(IntegrityLevel integrity_level) override; - virtual IntegrityLevel GetIntegrityLevel() const override; - virtual ResultCode SetDelayedIntegrityLevel( - IntegrityLevel integrity_level) override; - virtual ResultCode SetAppContainer(const wchar_t* sid) override; - virtual ResultCode SetCapability(const wchar_t* sid) override; - virtual ResultCode SetLowBox(const wchar_t* sid) override; - virtual ResultCode SetProcessMitigations(MitigationFlags flags) override; - virtual MitigationFlags GetProcessMitigations() override; - virtual ResultCode SetDelayedProcessMitigations( - MitigationFlags flags) override; - virtual MitigationFlags GetDelayedProcessMitigations() const override; - virtual void SetStrictInterceptions() override; - virtual ResultCode SetStdoutHandle(HANDLE handle) override; - virtual ResultCode SetStderrHandle(HANDLE handle) override; - virtual ResultCode AddRule(SubSystem subsystem, Semantics semantics, - const wchar_t* pattern) override; - virtual ResultCode AddDllToUnload(const wchar_t* dll_name) override; - virtual ResultCode AddKernelObjectToClose( - const base::char16* handle_type, - const base::char16* handle_name) override; + void AddRef() override; + void Release() override; + ResultCode SetTokenLevel(TokenLevel initial, TokenLevel lockdown) override; + TokenLevel GetInitialTokenLevel() const override; + TokenLevel GetLockdownTokenLevel() const override; + ResultCode SetJobLevel(JobLevel job_level, uint32 ui_exceptions) override; + ResultCode SetJobMemoryLimit(size_t memory_limit) override; + ResultCode SetAlternateDesktop(bool alternate_winstation) override; + base::string16 GetAlternateDesktop() const override; + ResultCode CreateAlternateDesktop(bool alternate_winstation) override; + void DestroyAlternateDesktop() override; + ResultCode SetIntegrityLevel(IntegrityLevel integrity_level) override; + IntegrityLevel GetIntegrityLevel() const override; + ResultCode SetDelayedIntegrityLevel(IntegrityLevel integrity_level) override; + ResultCode SetAppContainer(const wchar_t* sid) override; + ResultCode SetCapability(const wchar_t* sid) override; + ResultCode SetLowBox(const wchar_t* sid) override; + ResultCode SetProcessMitigations(MitigationFlags flags) override; + MitigationFlags GetProcessMitigations() override; + ResultCode SetDelayedProcessMitigations(MitigationFlags flags) override; + MitigationFlags GetDelayedProcessMitigations() const override; + void SetStrictInterceptions() override; + ResultCode SetStdoutHandle(HANDLE handle) override; + ResultCode SetStderrHandle(HANDLE handle) override; + ResultCode AddRule(SubSystem subsystem, + Semantics semantics, + const wchar_t* pattern) override; + ResultCode AddDllToUnload(const wchar_t* dll_name) override; + ResultCode AddKernelObjectToClose(const base::char16* handle_type, + const base::char16* handle_name) override; // Dispatcher: - virtual Dispatcher* OnMessageReady(IPCParams* ipc, - CallbackGeneric* callback) override; - virtual bool SetupService(InterceptionManager* manager, int service) override; + Dispatcher* OnMessageReady(IPCParams* ipc, + CallbackGeneric* callback) override; + bool SetupService(InterceptionManager* manager, int service) override; // Creates a Job object with the level specified in a previous call to // SetJobLevel(). @@ -104,7 +100,7 @@ HANDLE GetStderrHandle(); private: - ~PolicyBase(); + ~PolicyBase() override; // Test IPC providers. bool Ping(IPCInfo* ipc, void* cookie);
diff --git a/sandbox/win/src/win2k_threadpool.cc b/sandbox/win/src/win2k_threadpool.cc index 24cbacf2..051cfc1 100644 --- a/sandbox/win/src/win2k_threadpool.cc +++ b/sandbox/win/src/win2k_threadpool.cc
@@ -8,6 +8,10 @@ namespace sandbox { +Win2kThreadPool::Win2kThreadPool() { + ::InitializeCriticalSection(&lock_); +} + bool Win2kThreadPool::RegisterWait(const void* cookie, HANDLE waitable_object, CrossCallIPCCallback callback, void* context) {
diff --git a/sandbox/win/src/win2k_threadpool.h b/sandbox/win/src/win2k_threadpool.h index 0abb358..41cd5f1 100644 --- a/sandbox/win/src/win2k_threadpool.h +++ b/sandbox/win/src/win2k_threadpool.h
@@ -24,9 +24,7 @@ // This implementation simply thunks to the nice thread pool API of win2k. class Win2kThreadPool : public ThreadProvider { public: - Win2kThreadPool() { - ::InitializeCriticalSection(&lock_); - } + Win2kThreadPool(); virtual ~Win2kThreadPool(); virtual bool RegisterWait(const void* cookie, HANDLE waitable_object, @@ -50,6 +48,7 @@ PoolObjects pool_objects_; // This lock protects the list of pool wait objects. CRITICAL_SECTION lock_; + DISALLOW_COPY_AND_ASSIGN(Win2kThreadPool); };
diff --git a/sandbox/win/tests/integration_tests/integration_tests.cc b/sandbox/win/tests/integration_tests/integration_tests.cc index bb80931..3920da1 100644 --- a/sandbox/win/tests/integration_tests/integration_tests.cc +++ b/sandbox/win/tests/integration_tests/integration_tests.cc
@@ -16,7 +16,7 @@ return sandbox::DispatchCall(argc, argv); } - TestSuite test_suite(argc, argv); + base::TestSuite test_suite(argc, argv); return base::LaunchUnitTests( argc, argv,
diff --git a/sandbox/win/tests/unit_tests/unit_tests.cc b/sandbox/win/tests/unit_tests/unit_tests.cc index df98ba2f..bd56ab0 100644 --- a/sandbox/win/tests/unit_tests/unit_tests.cc +++ b/sandbox/win/tests/unit_tests/unit_tests.cc
@@ -14,7 +14,7 @@ return 0; } - TestSuite test_suite(argc, argv); + base::TestSuite test_suite(argc, argv); return base::LaunchUnitTests( argc, argv,
diff --git a/sandbox/win/tests/validation_tests/unit_tests.cc b/sandbox/win/tests/validation_tests/unit_tests.cc index d3fd913..592b6c0 100644 --- a/sandbox/win/tests/validation_tests/unit_tests.cc +++ b/sandbox/win/tests/validation_tests/unit_tests.cc
@@ -14,7 +14,7 @@ return sandbox::DispatchCall(argc, argv); } - TestSuite test_suite(argc, argv); + base::TestSuite test_suite(argc, argv); return base::LaunchUnitTests( argc, argv,
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 81655e3..ec2248b 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -261,6 +261,10 @@ # define SK_IGNORE_ETC1_SUPPORT #endif +#ifndef SK_SUPPORT_LEGACY_RADIAL_GRADIENT_SQRT +# define SK_SUPPORT_LEGACY_RADIAL_GRADIENT_SQRT +#endif + #ifndef SK_SUPPORT_LEGACY_BOOL_ONGETINFO # define SK_SUPPORT_LEGACY_BOOL_ONGETINFO #endif @@ -277,10 +281,6 @@ # define SK_LEGACY_STROKE_CURVES #endif -#ifndef SK_SUPPORT_LEGACY_COLOR32_MATH -# define SK_SUPPORT_LEGACY_COLOR32_MATH -#endif - ///////////////////////// Imported from BUILD.gn and skia_common.gypi /* In some places Skia can use static initializers for global initialization,
diff --git a/sync/BUILD.gn b/sync/BUILD.gn index 6b106dda..bfb3566f 100644 --- a/sync/BUILD.gn +++ b/sync/BUILD.gn
@@ -400,6 +400,9 @@ "util/time.h", ] + public_deps = [ + "//sync/internal_api/attachments/proto", + ] deps = [ "//base", "//base:i18n", @@ -411,7 +414,6 @@ "//third_party/leveldatabase", "//third_party/zlib", "//url", - "//sync/internal_api/attachments/proto", "//sync/protocol", ] @@ -442,6 +444,8 @@ "sessions/test_util.cc", "sessions/test_util.h", "test/callback_counter.h", + "test/directory_backing_store_corruption_testing.cc", + "test/directory_backing_store_corruption_testing.h", "test/engine/fake_model_worker.cc", "test/engine/fake_model_worker.h", "test/engine/fake_sync_scheduler.cc", @@ -486,6 +490,8 @@ "test/test_transaction_observer.h", "test/trackable_mock_invalidation.cc", "test/trackable_mock_invalidation.h", + "util/mock_unrecoverable_error_handler.cc", + "util/mock_unrecoverable_error_handler.h", "util/test_unrecoverable_error_handler.cc", "util/test_unrecoverable_error_handler.h", ] @@ -651,7 +657,6 @@ "//sql", "//sql:test_support", "//sync", - "//sync/internal_api/attachments/proto", "//sync/protocol", "//testing/gmock", "//testing/gtest",
diff --git a/sync/internal_api/attachments/proto/BUILD.gn b/sync/internal_api/attachments/proto/BUILD.gn index 3408c38d..ac1a4b26 100644 --- a/sync/internal_api/attachments/proto/BUILD.gn +++ b/sync/internal_api/attachments/proto/BUILD.gn
@@ -5,6 +5,9 @@ import("//third_party/protobuf/proto_library.gni") proto_library("proto") { + # This should only get compiled into the sync component. + visibility = [ "//sync:sync_core" ] + sources = [ "attachment_store.proto", ]
diff --git a/sync/internal_api/sync_backup_manager_unittest.cc b/sync/internal_api/sync_backup_manager_unittest.cc index fe638e3..2bf778e 100644 --- a/sync/internal_api/sync_backup_manager_unittest.cc +++ b/sync/internal_api/sync_backup_manager_unittest.cc
@@ -45,7 +45,7 @@ bool, ModelTypeSet)); protected: - virtual void SetUp() override { + void SetUp() override { CHECK(temp_dir_.CreateUniqueTempDir()); }
diff --git a/sync/internal_api/sync_manager_impl_unittest.cc b/sync/internal_api/sync_manager_impl_unittest.cc index daedba2a..80972bff 100644 --- a/sync/internal_api/sync_manager_impl_unittest.cc +++ b/sync/internal_api/sync_manager_impl_unittest.cc
@@ -903,13 +903,13 @@ return GetRoutingInfoTypes(routing_info); } - virtual void OnChangesApplied( + void OnChangesApplied( ModelType model_type, int64 model_version, const BaseTransaction* trans, const ImmutableChangeRecordList& changes) override {} - virtual void OnChangesComplete(ModelType model_type) override {} + void OnChangesComplete(ModelType model_type) override {} // Helper methods. bool SetUpEncryption(NigoriStatus nigori_status,
diff --git a/sync/internal_api/sync_rollback_manager_unittest.cc b/sync/internal_api/sync_rollback_manager_unittest.cc index c03343d..31ffd14 100644 --- a/sync/internal_api/sync_rollback_manager_unittest.cc +++ b/sync/internal_api/sync_rollback_manager_unittest.cc
@@ -68,7 +68,7 @@ class SyncRollbackManagerTest : public testing::Test, public SyncManager::Observer { protected: - virtual void SetUp() override { + void SetUp() override { CHECK(temp_dir_.CreateUniqueTempDir()); worker_ = new FakeModelWorker(GROUP_UI);
diff --git a/sync/sync_tests.gypi b/sync/sync_tests.gypi index 33594a1..69804e1 100644 --- a/sync/sync_tests.gypi +++ b/sync/sync_tests.gypi
@@ -35,6 +35,8 @@ 'sessions/test_util.cc', 'sessions/test_util.h', 'test/callback_counter.h', + "test/directory_backing_store_corruption_testing.cc", + "test/directory_backing_store_corruption_testing.h", 'test/engine/fake_model_worker.cc', 'test/engine/fake_model_worker.h', 'test/engine/fake_sync_scheduler.cc', @@ -79,6 +81,8 @@ 'test/test_transaction_observer.h', 'test/trackable_mock_invalidation.cc', 'test/trackable_mock_invalidation.h', + 'util/mock_unrecoverable_error_handler.cc', + 'util/mock_unrecoverable_error_handler.h', 'util/test_unrecoverable_error_handler.cc', 'util/test_unrecoverable_error_handler.h', ],
diff --git a/sync/syncable/directory.cc b/sync/syncable/directory.cc index 767b807..0f680d22 100644 --- a/sync/syncable/directory.cc +++ b/sync/syncable/directory.cc
@@ -111,12 +111,12 @@ : kernel_(NULL), store_(store), unrecoverable_error_handler_(unrecoverable_error_handler), - report_unrecoverable_error_function_( - report_unrecoverable_error_function), + report_unrecoverable_error_function_(report_unrecoverable_error_function), unrecoverable_error_set_(false), nigori_handler_(nigori_handler), cryptographer_(cryptographer), - invariant_check_level_(VERIFY_CHANGES) { + invariant_check_level_(VERIFY_CHANGES), + weak_ptr_factory_(this) { } Directory::~Directory() { @@ -208,6 +208,12 @@ if (!SaveChanges()) return FAILED_INITIAL_WRITE; + // Now that we've successfully opened the store, install an error handler to + // deal with catastrophic errors that may occur later on. Use a weak pointer + // because we cannot guarantee that this Directory will outlive the Closure. + store_->SetCatastrophicErrorHandler(base::Bind( + &Directory::OnCatastrophicError, weak_ptr_factory_.GetWeakPtr())); + return OPENED; } @@ -1554,6 +1560,12 @@ std::back_inserter(*ids)); } +void Directory::OnCatastrophicError() { + ReadTransaction trans(FROM_HERE, this); + OnUnrecoverableError(&trans, FROM_HERE, + "Catastrophic error detected, Sync DB is unrecoverable"); +} + Directory::Kernel* Directory::kernel() { return kernel_; }
diff --git a/sync/syncable/directory.h b/sync/syncable/directory.h index 7f6ae0e..4f45cdf 100644 --- a/sync/syncable/directory.h +++ b/sync/syncable/directory.h
@@ -533,6 +533,7 @@ TakeSnapshotGetsOnlyDirtyHandlesTest); FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, TakeSnapshotGetsMetahandlesToPurge); + FRIEND_TEST_ALL_PREFIXES(SyncableDirectoryTest, CatastrophicError); // You'll notice that some of the methods below are private overloads of the // public ones declared above. The general pattern is that the public overload @@ -622,6 +623,10 @@ ModelType type, std::vector<int64>* result); + // Invoked by DirectoryBackingStore when a catastrophic database error is + // detected. + void OnCatastrophicError(); + // Returns true if the initial sync for |type| has completed. bool InitialSyncEndedForType(BaseTransaction* trans, ModelType type); @@ -653,6 +658,8 @@ // are deleted in native models as well. scoped_ptr<DeleteJournal> delete_journal_; + base::WeakPtrFactory<Directory> weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(Directory); };
diff --git a/sync/syncable/directory_backing_store.h b/sync/syncable/directory_backing_store.h index 6d6efd4..5e0c80b 100644 --- a/sync/syncable/directory_backing_store.h +++ b/sync/syncable/directory_backing_store.h
@@ -187,7 +187,10 @@ FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, CatastrophicErrorHandler_KeptAcrossReset); FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, - CatastrophicErrorHandler_Invocation); + CatastrophicErrorHandler_InvocationDuringLoad); + FRIEND_TEST_ALL_PREFIXES( + DirectoryBackingStoreTest, + CatastrophicErrorHandler_InvocationDuringSaveChanges); // Drop all tables in preparation for reinitialization. void DropAllTables();
diff --git a/sync/syncable/directory_backing_store_unittest.cc b/sync/syncable/directory_backing_store_unittest.cc index 470e858e..0cc723fc7 100644 --- a/sync/syncable/directory_backing_store_unittest.cc +++ b/sync/syncable/directory_backing_store_unittest.cc
@@ -7,7 +7,6 @@ #include <string> #include "base/files/file_path.h" -#include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" #include "base/message_loop/message_loop.h" @@ -26,10 +25,13 @@ #include "sync/syncable/directory_backing_store.h" #include "sync/syncable/on_disk_directory_backing_store.h" #include "sync/syncable/syncable-inl.h" +#include "sync/test/directory_backing_store_corruption_testing.h" #include "sync/test/test_directory_backing_store.h" #include "sync/util/time.h" #include "testing/gtest/include/gtest/gtest-param-test.h" +namespace syncer { +namespace syncable { namespace { // A handler that simply sets |catastrophic_error_handler_was_called| to true. @@ -37,10 +39,16 @@ *catastrophic_error_handler_was_called = true; } -} // namespace +// Create a dirty EntryKernel with an ID derived from |id|. +scoped_ptr<EntryKernel> CreateEntry(int id) { + scoped_ptr<EntryKernel> entry(new EntryKernel()); + entry->put(ID, Id::CreateFromClientString(base::Int64ToString(id))); + entry->put(META_HANDLE, id); + entry->mark_dirty(NULL); + return entry; +} -namespace syncer { -namespace syncable { +} // namespace SYNC_EXPORT_PRIVATE extern const int32 kCurrentDBVersion; @@ -4025,8 +4033,10 @@ ASSERT_TRUE(dbs->db_->has_error_callback()); } -// Verify that database corruption will trigger the catastrohpic error handler. -TEST_F(DirectoryBackingStoreTest, CatastrophicErrorHandler_Invocation) { +// Verify that database corruption encountered during Load will trigger the +// catastrohpic error handler. +TEST_F(DirectoryBackingStoreTest, + CatastrophicErrorHandler_InvocationDuringLoad) { bool was_called = false; const base::Closure handler = base::Bind(&CatastrophicErrorHandler, &was_called); @@ -4040,11 +4050,7 @@ ASSERT_TRUE(LoadAndIgnoreReturnedData(dbs.get())); ASSERT_FALSE(dbs->DidFailFirstOpenAttempt()); Directory::SaveChangesSnapshot snapshot; - scoped_ptr<EntryKernel> entry(new EntryKernel()); - entry->put(ID, Id::CreateFromClientString("test_entry")); - entry->put(META_HANDLE, 2); - entry->mark_dirty(NULL); - snapshot.dirty_metas.insert(entry.release()); + snapshot.dirty_metas.insert(CreateEntry(2).release()); ASSERT_TRUE(dbs->SaveChanges(snapshot)); } @@ -4081,5 +4087,41 @@ ASSERT_TRUE(was_called); } +// Verify that database corruption encountered during SaveChanges will trigger +// the catastrohpic error handler. +TEST_F(DirectoryBackingStoreTest, + CatastrophicErrorHandler_InvocationDuringSaveChanges) { + bool was_called = false; + const base::Closure handler = + base::Bind(&CatastrophicErrorHandler, &was_called); + // Create a DB with many entries. + scoped_ptr<OnDiskDirectoryBackingStoreForTest> dbs( + new OnDiskDirectoryBackingStoreForTest(GetUsername(), GetDatabasePath())); + dbs->SetCatastrophicErrorHandler(handler); + ASSERT_TRUE(dbs->db_->has_error_callback()); + ASSERT_TRUE(LoadAndIgnoreReturnedData(dbs.get())); + ASSERT_FALSE(dbs->DidFailFirstOpenAttempt()); + Directory::SaveChangesSnapshot snapshot; + for (int i = 0; i < corruption_testing::kNumEntriesRequiredForCorruption; + ++i) { + snapshot.dirty_metas.insert(CreateEntry(i).release()); + } + ASSERT_TRUE(dbs->SaveChanges(snapshot)); + // Corrupt it. + ASSERT_TRUE(corruption_testing::CorruptDatabase(GetDatabasePath())); + // Attempt to save all those entries again. See that it fails (because of the + // corruption). + // + // If this test fails because SaveChanges returned true, it may mean you need + // to increase the number of entries written to the DB. See also + // |kNumEntriesRequiredForCorruption|. + ASSERT_FALSE(dbs->SaveChanges(snapshot)); + // At this point the handler has been posted but not executed. + ASSERT_FALSE(was_called); + // Pump the message loop and see that it is executed. + base::RunLoop().RunUntilIdle(); + ASSERT_TRUE(was_called); +} + } // namespace syncable } // namespace syncer
diff --git a/sync/syncable/directory_unittest.cc b/sync/syncable/directory_unittest.cc index d802d4f2..690af4f 100644 --- a/sync/syncable/directory_unittest.cc +++ b/sync/syncable/directory_unittest.cc
@@ -12,6 +12,7 @@ #include "sync/syncable/syncable_write_transaction.h" #include "sync/test/engine/test_syncable_utils.h" #include "sync/test/test_directory_backing_store.h" +#include "sync/util/mock_unrecoverable_error_handler.h" using base::ExpectDictBooleanValue; using base::ExpectDictStringValue; @@ -2030,6 +2031,25 @@ snapshot.delete_journals_to_purge.clear(); } +// Verify that Directory triggers an unrecoverable error when a catastrophic +// DirectoryBackingStore error is detected. +TEST_F(SyncableDirectoryTest, CatastrophicError) { + MockUnrecoverableErrorHandler unrecoverable_error_handler; + Directory dir(new InMemoryDirectoryBackingStore("catastrophic_error"), + &unrecoverable_error_handler, nullptr, nullptr, nullptr); + ASSERT_EQ(OPENED, dir.Open(kDirectoryName, directory_change_delegate(), + NullTransactionObserver())); + ASSERT_EQ(0, unrecoverable_error_handler.invocation_count()); + + // Fire off two catastrophic errors. Call it twice to ensure Directory is + // tolerant of multiple invocations since that may happen in the real world. + dir.OnCatastrophicError(); + dir.OnCatastrophicError(); + + // See that the unrecoverable error handler has been invoked twice. + ASSERT_EQ(2, unrecoverable_error_handler.invocation_count()); +} + } // namespace syncable } // namespace syncer
diff --git a/sync/syncable/on_disk_directory_backing_store.cc b/sync/syncable/on_disk_directory_backing_store.cc index 918dc07c..3a37847 100644 --- a/sync/syncable/on_disk_directory_backing_store.cc +++ b/sync/syncable/on_disk_directory_backing_store.cc
@@ -26,9 +26,8 @@ OnDiskDirectoryBackingStore::OnDiskDirectoryBackingStore( const std::string& dir_name, const base::FilePath& backing_file_path) - : DirectoryBackingStore(dir_name), - allow_failure_for_test_(false), - backing_file_path_(backing_file_path) { + : DirectoryBackingStore(dir_name), backing_file_path_(backing_file_path) { + DCHECK(backing_file_path_.IsAbsolute()); } OnDiskDirectoryBackingStore::~OnDiskDirectoryBackingStore() {
diff --git a/sync/syncable/on_disk_directory_backing_store.h b/sync/syncable/on_disk_directory_backing_store.h index 8c604d0..05f4156 100644 --- a/sync/syncable/on_disk_directory_backing_store.h +++ b/sync/syncable/on_disk_directory_backing_store.h
@@ -40,8 +40,8 @@ MetahandleSet* metahandles_to_purge, Directory::KernelLoadInfo* kernel_load_info); - bool allow_failure_for_test_; - base::FilePath backing_file_path_; + // The path to the sync DB. + const base::FilePath backing_file_path_; DISALLOW_COPY_AND_ASSIGN(OnDiskDirectoryBackingStore); };
diff --git a/sync/test/directory_backing_store_corruption_testing.cc b/sync/test/directory_backing_store_corruption_testing.cc new file mode 100644 index 0000000..9767e561 --- /dev/null +++ b/sync/test/directory_backing_store_corruption_testing.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 "sync/test/directory_backing_store_corruption_testing.h" + +#include "base/files/file_util.h" +#include "base/files/scoped_file.h" + +namespace syncer { +namespace syncable { +namespace corruption_testing { + +// This value needs to be large enough to force the underlying DB to be read +// from disk before writing. The value *may* depend on the underlying DB page +// size as well as the DB's cache_size PRAGMA. +const int kNumEntriesRequiredForCorruption = 4000; + +bool CorruptDatabase(const base::FilePath& backing_file_path) { + // Corrupt the DB by write a bunch of zeros at the beginning. + // + // Because the file may already open for writing, it's important that we open + // it in a sharing-compatible way for platforms that have the concept of + // shared/exclusive file access (e.g. Windows). + base::ScopedFILE db_file(base::OpenFile(backing_file_path, "wb")); + if (!db_file.get()) + return false; + const std::string zeros(4096, '\0'); + const int num_written = fwrite(zeros.data(), zeros.size(), 1, db_file.get()); + return num_written == 1U; +} + +} // namespace corruption_util +} // namespace syncable +} // namespace syncer
diff --git a/sync/test/directory_backing_store_corruption_testing.h b/sync/test/directory_backing_store_corruption_testing.h new file mode 100644 index 0000000..5897ec04 --- /dev/null +++ b/sync/test/directory_backing_store_corruption_testing.h
@@ -0,0 +1,27 @@ +// 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_TEST_DIRECTORY_BACKING_STORE_CORRUPTION_TESTING_H_ +#define SYNC_TEST_DIRECTORY_BACKING_STORE_CORRUPTION_TESTING_H_ + +#include "base/files/file_path.h" + +namespace syncer { +namespace syncable { +namespace corruption_testing { + +// The number of DB entries required to reliably trigger detectable corruption +// using |CorruptDatabase|. +extern const int kNumEntriesRequiredForCorruption; + +// Corrupt the sync database at |backing_file_path|. +// +// Returns true if the database was successfully corrupted. +bool CorruptDatabase(const base::FilePath& backing_file_path); + +} // namespace corruption_util +} // namespace syncable +} // namespace syncer + +#endif // SYNC_TEST_DIRECTORY_BACKING_STORE_CORRUPTION_TESTING_H_
diff --git a/sync/util/mock_unrecoverable_error_handler.cc b/sync/util/mock_unrecoverable_error_handler.cc new file mode 100644 index 0000000..bfed1f1e --- /dev/null +++ b/sync/util/mock_unrecoverable_error_handler.cc
@@ -0,0 +1,26 @@ +// 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 "sync/util/mock_unrecoverable_error_handler.h" + +namespace syncer { + +MockUnrecoverableErrorHandler::MockUnrecoverableErrorHandler() + : invocation_count_(0) { +} + +MockUnrecoverableErrorHandler::~MockUnrecoverableErrorHandler() { +} + +void MockUnrecoverableErrorHandler::OnUnrecoverableError( + const tracked_objects::Location& from_here, + const std::string& message) { + ++invocation_count_; +} + +int MockUnrecoverableErrorHandler::invocation_count() const { + return invocation_count_; +} + +} // namespace syncer
diff --git a/sync/util/mock_unrecoverable_error_handler.h b/sync/util/mock_unrecoverable_error_handler.h new file mode 100644 index 0000000..aacde89e --- /dev/null +++ b/sync/util/mock_unrecoverable_error_handler.h
@@ -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. + +#ifndef SYNC_UTIL_MOCK_UNRECOVERABLE_ERROR_HANDLER_H_ +#define SYNC_UTIL_MOCK_UNRECOVERABLE_ERROR_HANDLER_H_ + +#include <string> + +#include "base/macros.h" +#include "sync/internal_api/public/util/unrecoverable_error_handler.h" + +namespace syncer { + +// Mock implementation of UnrecoverableErrorHandler that counts how many times +// it has been invoked. +class MockUnrecoverableErrorHandler : public UnrecoverableErrorHandler { + public: + MockUnrecoverableErrorHandler(); + ~MockUnrecoverableErrorHandler() override; + void OnUnrecoverableError(const tracked_objects::Location& from_here, + const std::string& message) override; + + // Returns the number of times this handler has been invoked. + int invocation_count() const; + + private: + int invocation_count_; + + DISALLOW_COPY_AND_ASSIGN(MockUnrecoverableErrorHandler); +}; + +} // namespace syncer + +#endif // SYNC_UTIL_MOCK_UNRECOVERABLE_ERROR_HANDLER_H_
diff --git a/testing/android/appurify_support.gyp b/testing/android/appurify_support.gyp new file mode 100644 index 0000000..2904368 --- /dev/null +++ b/testing/android/appurify_support.gyp
@@ -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. + +{ + 'conditions': [ + ['OS=="android"', { + 'targets': [ + { + 'target_name': 'appurify_support_java', + 'type': 'none', + 'variables': { + 'java_in_dir': '../../testing/android/appurify_support/java', + }, + 'includes': [ + '../../build/java.gypi', + ], + }, + ], + }], + ], +}
diff --git a/testing/android/appurify_support/BUILD.gn b/testing/android/appurify_support/BUILD.gn new file mode 100644 index 0000000..871f9d0d --- /dev/null +++ b/testing/android/appurify_support/BUILD.gn
@@ -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. + +import("//build/config/android/rules.gni") + +# GYP: //testing/android/appurify_support.gyp:appurify_support_java +android_library("appurify_support_java") { + chromium_code = true + + java_files = [ + "java/src/org/chromium/test/support/ResultsBundleGenerator.java", + "java/src/org/chromium/test/support/RobotiumBundleGenerator.java", + ] +}
diff --git a/testing/android/appurify_support/java/src/org/chromium/test/support/ResultsBundleGenerator.java b/testing/android/appurify_support/java/src/org/chromium/test/support/ResultsBundleGenerator.java new file mode 100644 index 0000000..c9588d90 --- /dev/null +++ b/testing/android/appurify_support/java/src/org/chromium/test/support/ResultsBundleGenerator.java
@@ -0,0 +1,30 @@ +// 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. + +package org.chromium.test.support; + +import android.os.Bundle; + +import java.util.Map; + +/** + * Creates a results Bundle. + */ +public interface ResultsBundleGenerator { + + /** Indicates the state of a test. + */ + static enum TestResult { + PASSED, FAILED, ERROR, UNKNOWN + } + + /** Creates a bundle of test results from the provided raw results. + + Note: actual bundle content and format may vary. + + @param rawResults A map between test names and test results. + */ + Bundle generate(Map<String, TestResult> rawResults); +} +
diff --git a/testing/android/appurify_support/java/src/org/chromium/test/support/RobotiumBundleGenerator.java b/testing/android/appurify_support/java/src/org/chromium/test/support/RobotiumBundleGenerator.java new file mode 100644 index 0000000..167e7b9 --- /dev/null +++ b/testing/android/appurify_support/java/src/org/chromium/test/support/RobotiumBundleGenerator.java
@@ -0,0 +1,56 @@ +// 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. + +package org.chromium.test.support; + +import android.app.Instrumentation; +import android.os.Bundle; +import android.util.Log; + +import java.util.Map; + +/** + * Creates a results bundle that emulates the one created by Robotium. + */ +public class RobotiumBundleGenerator implements ResultsBundleGenerator { + + private static final String TAG = "RobotiumBundleGenerator"; + + public Bundle generate(Map<String, ResultsBundleGenerator.TestResult> rawResults) { + int testsPassed = 0; + int testsFailed = 0; + + for (Map.Entry<String, ResultsBundleGenerator.TestResult> entry : rawResults.entrySet()) { + switch (entry.getValue()) { + case PASSED: + ++testsPassed; + break; + case FAILED: + // TODO(jbudorick): Remove this log message once AMP execution and + // results handling has been stabilized. + Log.d(TAG, "FAILED: " + entry.getKey()); + ++testsFailed; + break; + default: + Log.w(TAG, "Unhandled: " + entry.getKey() + ", " + + entry.getValue().toString()); + break; + } + } + + StringBuilder resultBuilder = new StringBuilder(); + if (testsFailed > 0) { + resultBuilder.append( + "\nFAILURES!!! Tests run: " + Integer.toString(rawResults.size()) + + ", Failures: " + Integer.toString(testsFailed) + ", Errors: 0"); + } else { + resultBuilder.append("\nOK (" + Integer.toString(testsPassed) + " tests)"); + } + + Bundle resultsBundle = new Bundle(); + resultsBundle.putString(Instrumentation.REPORT_KEY_STREAMRESULT, + resultBuilder.toString()); + return resultsBundle; + } +}
diff --git a/testing/android/broker/BUILD.gn b/testing/android/broker/BUILD.gn new file mode 100644 index 0000000..8daa0408 --- /dev/null +++ b/testing/android/broker/BUILD.gn
@@ -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. + +import("//build/config/android/rules.gni") + +# GYP: //testing/android/on_device_instrumentation.gyp:broker_java +android_library("broker_java") { + chromium_code = true + + java_files = + [ "java/src/org/chromium/test/broker/OnDeviceInstrumentationBroker.java" ] +}
diff --git a/testing/android/broker/java/src/org/chromium/test/broker/OnDeviceInstrumentationBroker.java b/testing/android/broker/java/src/org/chromium/test/broker/OnDeviceInstrumentationBroker.java new file mode 100644 index 0000000..cd755d08 --- /dev/null +++ b/testing/android/broker/java/src/org/chromium/test/broker/OnDeviceInstrumentationBroker.java
@@ -0,0 +1,64 @@ +// 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. + +package org.chromium.test.broker; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +/** + * An Activity target for OnDeviceInstrumentationDriver that starts the specified + * Instrumentation test. + */ +public class OnDeviceInstrumentationBroker extends Activity { + + public static final String EXTRA_INSTRUMENTATION_PACKAGE = + "org.chromium.test.broker.OnDeviceInstrumentationBroker." + + "InstrumentationPackage"; + public static final String EXTRA_INSTRUMENTATION_CLASS = + "org.chromium.test.broker.OnDeviceInstrumentationBroker." + + "InstrumentationClass"; + public static final String EXTRA_TARGET_ARGS = + "org.chromium.test.broker.OnDeviceInstrumentationBroker.TargetArgs"; + public static final String EXTRA_TEST = + "org.chromium.test.broker.OnDeviceInstrumentationBroker.Test"; + + private static final String TAG = "OnDeviceInstrumentationBroker"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d(TAG, "onCreate()"); + } + + @Override + public void onStart() { + super.onStart(); + + Intent i = getIntent(); + String instrumentationPackage = i.getStringExtra(EXTRA_INSTRUMENTATION_PACKAGE); + String instrumentationClass = i.getStringExtra(EXTRA_INSTRUMENTATION_CLASS); + Bundle targetArgs = i.getBundleExtra(EXTRA_TARGET_ARGS); + String test = i.getStringExtra(EXTRA_TEST); + + if (instrumentationPackage == null || instrumentationClass == null) { + finish(); + return; + } + + ComponentName instrumentationComponent = + new ComponentName(instrumentationPackage, instrumentationClass); + + if (test != null) { + targetArgs.putString("class", test); + } + + startInstrumentation(instrumentationComponent, null, targetArgs); + finish(); + } +} +
diff --git a/testing/android/driver/BUILD.gn b/testing/android/driver/BUILD.gn new file mode 100644 index 0000000..436ac63c --- /dev/null +++ b/testing/android/driver/BUILD.gn
@@ -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. + +import("//build/config/android/rules.gni") + +# GYP: //testing/android/on_device_instrumentation.gyp:driver_apk +android_apk("driver_apk") { + android_manifest = "java/AndroidManifest.xml" + apk_name = "OnDeviceInstrumentationDriver" + testonly = true + + deps = [ + "//testing/android/appurify_support:appurify_support_java", + "//testing/android/broker:broker_java", + "//testing/android/reporter:reporter_java", + ] + + java_files = + [ "java/src/org/chromium/test/driver/OnDeviceInstrumentationDriver.java" ] +}
diff --git a/testing/android/driver/java/AndroidManifest.xml b/testing/android/driver/java/AndroidManifest.xml new file mode 100644 index 0000000..c7e99ef --- /dev/null +++ b/testing/android/driver/java/AndroidManifest.xml
@@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +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. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.chromium.test.driver" + android:versionCode="1" + android:versionName="1.0"> + + <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" /> + + <application android:label="OnDeviceInstrumentationDriver" /> + + <instrumentation android:name="org.chromium.test.driver.OnDeviceInstrumentationDriver" + android:targetPackage="org.chromium.test.driver" + android:label="OnDeviceInstrumentationDriver"/> + + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> + +</manifest>
diff --git a/testing/android/driver/java/src/org/chromium/test/driver/OnDeviceInstrumentationDriver.java b/testing/android/driver/java/src/org/chromium/test/driver/OnDeviceInstrumentationDriver.java new file mode 100644 index 0000000..78c571a4 --- /dev/null +++ b/testing/android/driver/java/src/org/chromium/test/driver/OnDeviceInstrumentationDriver.java
@@ -0,0 +1,271 @@ +// 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. + +package org.chromium.test.driver; + +import android.app.Activity; +import android.app.Instrumentation; +import android.content.ComponentName; +import android.content.Intent; +import android.os.Bundle; +import android.os.Environment; +import android.test.InstrumentationTestRunner; +import android.util.Log; + +import org.chromium.test.broker.OnDeviceInstrumentationBroker; +import org.chromium.test.reporter.TestStatusReceiver; +import org.chromium.test.reporter.TestStatusReporter; +import org.chromium.test.support.ResultsBundleGenerator; +import org.chromium.test.support.RobotiumBundleGenerator; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.regex.Pattern; + +/** + * An Instrumentation that drives instrumentation tests from outside the app. + */ +public class OnDeviceInstrumentationDriver extends Instrumentation { + + private static final String TAG = "OnDeviceInstrumentationDriver"; + + private static final String EXTRA_TEST_LIST = + "org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList"; + private static final String EXTRA_TEST_LIST_FILE = + "org.chromium.test.driver.OnDeviceInstrumentationDriver.TestListFile"; + private static final String EXTRA_TARGET_PACKAGE = + "org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetPackage"; + private static final String EXTRA_TARGET_CLASS = + "org.chromium.test.driver.OnDeviceInstrumentationDriver.TargetClass"; + + private static final Pattern COMMA = Pattern.compile(","); + private static final int TEST_WAIT_TIMEOUT = 5 * TestStatusReporter.HEARTBEAT_INTERVAL_MS; + + private boolean mDriverStarted; + private Thread mDriverThread; + private Bundle mTargetArgs; + private String mTargetClass; + private String mTargetPackage; + private List<String> mTestClasses; + + /** Parse any arguments and prepare to run tests. + + @param arguments The arguments to parse. + */ + @Override + public void onCreate(Bundle arguments) { + mTargetArgs = new Bundle(arguments); + mTargetPackage = arguments.getString(EXTRA_TARGET_PACKAGE); + if (mTargetPackage == null) { + fail("No target package."); + return; + } + mTargetArgs.remove(EXTRA_TARGET_PACKAGE); + + mTargetClass = arguments.getString(EXTRA_TARGET_CLASS); + if (mTargetClass == null) { + fail("No target class."); + return; + } + mTargetArgs.remove(EXTRA_TARGET_CLASS); + + mTestClasses = new ArrayList<String>(); + String testList = arguments.getString(EXTRA_TEST_LIST); + if (testList != null) { + mTestClasses.addAll(Arrays.asList(COMMA.split(testList))); + mTargetArgs.remove(EXTRA_TEST_LIST); + } + + String testListFilePath = arguments.getString(EXTRA_TEST_LIST_FILE); + if (testListFilePath != null) { + File testListFile = new File(Environment.getExternalStorageDirectory(), + testListFilePath); + try { + BufferedReader testListFileReader = + new BufferedReader(new FileReader(testListFile)); + String test; + while ((test = testListFileReader.readLine()) != null) { + mTestClasses.add(test); + } + testListFileReader.close(); + } catch (IOException e) { + Log.e(TAG, "Error reading " + testListFile.getAbsolutePath(), e); + } + mTargetArgs.remove(EXTRA_TEST_LIST_FILE); + } + + if (mTestClasses.isEmpty()) { + fail("No tests."); + return; + } + + mDriverThread = new Thread( + new Driver(mTargetPackage, mTargetClass, mTargetArgs, mTestClasses)); + + start(); + } + + /** Start running tests. */ + @Override + public void onStart() { + super.onStart(); + + // Start the driver on its own thread s.t. it can block while the main thread's + // Looper receives and handles messages. + if (!mDriverStarted) { + mDriverThread.start(); + mDriverStarted = true; + } + } + + /** Clean up the reporting service. */ + @Override + public void onDestroy() { + super.onDestroy(); + } + + private class Driver implements Runnable { + + private static final String TAG = OnDeviceInstrumentationDriver.TAG + ".Driver"; + + private Bundle mTargetArgs; + private String mTargetClass; + private String mTargetPackage; + private List<String> mTestClasses; + + public Driver(String targetPackage, String targetClass, Bundle targetArgs, + List<String> testClasses) { + mTargetPackage = targetPackage; + mTargetClass = targetClass; + mTargetArgs = targetArgs; + mTestClasses = testClasses; + } + + private void sendTestStatus(int status, String testClass, String testMethod) { + Bundle statusBundle = new Bundle(); + statusBundle.putString(InstrumentationTestRunner.REPORT_KEY_NAME_CLASS, testClass); + statusBundle.putString(InstrumentationTestRunner.REPORT_KEY_NAME_TEST, testMethod); + sendStatus(status, statusBundle); + } + + /** Run the tests. */ + @Override + public void run() { + final HashMap<String, ResultsBundleGenerator.TestResult> finished = + new HashMap<String, ResultsBundleGenerator.TestResult>(); + final Object statusLock = new Object(); + + try { + TestStatusReceiver r = new TestStatusReceiver(); + r.registerCallback(new TestStatusReceiver.StartCallback() { + @Override + public void testStarted(String testClass, String testMethod) { + sendTestStatus(InstrumentationTestRunner.REPORT_VALUE_RESULT_START, + testClass, testMethod); + synchronized (statusLock) { + statusLock.notify(); + } + } + }); + r.registerCallback(new TestStatusReceiver.PassCallback() { + @Override + public void testPassed(String testClass, String testMethod) { + sendTestStatus(InstrumentationTestRunner.REPORT_VALUE_RESULT_OK, testClass, + testMethod); + synchronized (statusLock) { + finished.put(testClass + "#" + testMethod, + ResultsBundleGenerator.TestResult.PASSED); + statusLock.notify(); + } + } + }); + r.registerCallback(new TestStatusReceiver.FailCallback() { + @Override + public void testFailed(String testClass, String testMethod) { + sendTestStatus(InstrumentationTestRunner.REPORT_VALUE_RESULT_ERROR, + testClass, testMethod); + synchronized (statusLock) { + finished.put(testClass + "#" + testMethod, + ResultsBundleGenerator.TestResult.FAILED); + statusLock.notify(); + } + } + }); + r.registerCallback(new TestStatusReceiver.HeartbeatCallback() { + @Override + public void heartbeat() { + Log.i(TAG, "Heartbeat received."); + synchronized (statusLock) { + statusLock.notify(); + } + } + }); + r.register(getContext()); + + for (String t : mTestClasses) { + Intent slaveIntent = new Intent(); + slaveIntent.setComponent(new ComponentName( + mTargetPackage, OnDeviceInstrumentationBroker.class.getName())); + slaveIntent.putExtra( + OnDeviceInstrumentationBroker.EXTRA_INSTRUMENTATION_PACKAGE, + mTargetPackage); + slaveIntent.putExtra( + OnDeviceInstrumentationBroker.EXTRA_INSTRUMENTATION_CLASS, + mTargetClass); + slaveIntent.putExtra(OnDeviceInstrumentationBroker.EXTRA_TEST, t); + slaveIntent.putExtra(OnDeviceInstrumentationBroker.EXTRA_TARGET_ARGS, + mTargetArgs); + slaveIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + getContext().startActivity(slaveIntent); + + synchronized (statusLock) { + while (!finished.containsKey(t)) { + long waitStart = System.currentTimeMillis(); + statusLock.wait(TEST_WAIT_TIMEOUT); + if (System.currentTimeMillis() - waitStart > TEST_WAIT_TIMEOUT) { + Log.e(TAG, t + " has gone missing and is assumed to be dead."); + finished.put(t, ResultsBundleGenerator.TestResult.FAILED); + break; + } + } + } + } + getContext().unregisterReceiver(r); + + } catch (InterruptedException e) { + fail("Interrupted while running tests.", e); + return; + } + pass(new RobotiumBundleGenerator().generate(finished)); + } + + } + + private void fail(String reason) { + Log.e(TAG, reason); + failImpl(reason); + } + + private void fail(String reason, Exception e) { + Log.e(TAG, reason, e); + failImpl(reason); + } + + private void failImpl(String reason) { + Bundle b = new Bundle(); + b.putString("reason", reason); + finish(Activity.RESULT_CANCELED, b); + } + + private void pass(Bundle results) { + finish(Activity.RESULT_OK, results); + } +}
diff --git a/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java b/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java index 4e1a067..25b6570 100644 --- a/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java +++ b/testing/android/native_test/java/src/org/chromium/native_test/ChromeNativeTestInstrumentationTestRunner.java
@@ -12,6 +12,9 @@ import android.os.Environment; import android.util.Log; +import org.chromium.test.support.ResultsBundleGenerator; +import org.chromium.test.support.RobotiumBundleGenerator; + import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.File; @@ -38,10 +41,6 @@ private static final int ACCEPT_TIMEOUT_MS = 5000; private static final Pattern RE_TEST_OUTPUT = Pattern.compile("\\[ *([^ ]*) *\\] ?([^ ]+) .*"); - private static interface ResultsBundleGenerator { - public Bundle generate(Map<String, TestResult> rawResults); - } - private String mCommandLineFile; private String mCommandLineFlags; private File mStdoutFile; @@ -91,7 +90,7 @@ } Log.i(TAG, "Getting results."); - Map<String, TestResult> results = parseResults(activityUnderTest); + Map<String, ResultsBundleGenerator.TestResult> results = parseResults(activityUnderTest); Log.i(TAG, "Parsing results and generating output."); return mBundleGenerator.generate(results); @@ -117,16 +116,14 @@ return startActivitySync(i); } - private static enum TestResult { - PASSED, FAILED, ERROR, UNKNOWN - } - /** * Generates a map between test names and test results from the instrumented Activity's * output. */ - private Map<String, TestResult> parseResults(Activity activityUnderTest) { - Map<String, TestResult> results = new HashMap<String, TestResult>(); + private Map<String, ResultsBundleGenerator.TestResult> parseResults( + Activity activityUnderTest) { + Map<String, ResultsBundleGenerator.TestResult> results = + new HashMap<String, ResultsBundleGenerator.TestResult>(); BufferedReader r = null; @@ -145,14 +142,14 @@ boolean isFailure = false; if (m.matches()) { if (m.group(1).equals("RUN")) { - results.put(m.group(2), TestResult.UNKNOWN); + results.put(m.group(2), ResultsBundleGenerator.TestResult.UNKNOWN); } else if (m.group(1).equals("FAILED")) { - results.put(m.group(2), TestResult.FAILED); + results.put(m.group(2), ResultsBundleGenerator.TestResult.FAILED); isFailure = true; mLogBundle.putString(Instrumentation.REPORT_KEY_STREAMRESULT, l + "\n"); sendStatus(0, mLogBundle); } else if (m.group(1).equals("OK")) { - results.put(m.group(2), TestResult.PASSED); + results.put(m.group(2), ResultsBundleGenerator.TestResult.PASSED); } } @@ -185,46 +182,4 @@ return results; } - /** - * Creates a results bundle that emulates the one created by Robotium. - */ - private static class RobotiumBundleGenerator implements ResultsBundleGenerator { - public Bundle generate(Map<String, TestResult> rawResults) { - Bundle resultsBundle = new Bundle(); - - int testsPassed = 0; - int testsFailed = 0; - - for (Map.Entry<String, TestResult> entry : rawResults.entrySet()) { - switch (entry.getValue()) { - case PASSED: - ++testsPassed; - break; - case FAILED: - // TODO(jbudorick): Remove this log message once AMP execution and - // results handling has been stabilized. - Log.d(TAG, "FAILED: " + entry.getKey()); - ++testsFailed; - break; - default: - Log.w(TAG, "Unhandled: " + entry.getKey() + ", " - + entry.getValue().toString()); - break; - } - } - - StringBuilder resultBuilder = new StringBuilder(); - if (testsFailed > 0) { - resultBuilder.append( - "\nFAILURES!!! Tests run: " + Integer.toString(rawResults.size()) - + ", Failures: " + Integer.toString(testsFailed) + ", Errors: 0"); - } else { - resultBuilder.append("\nOK (" + Integer.toString(testsPassed) + " tests)"); - } - resultsBundle.putString(Instrumentation.REPORT_KEY_STREAMRESULT, - resultBuilder.toString()); - return resultsBundle; - } - } - }
diff --git a/testing/android/on_device_instrumentation.gyp b/testing/android/on_device_instrumentation.gyp new file mode 100644 index 0000000..12e0f35 --- /dev/null +++ b/testing/android/on_device_instrumentation.gyp
@@ -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. + +{ + 'conditions': [ + ['OS=="android"', { + 'variables' : { + 'driver_apk_name': 'OnDeviceInstrumentationDriver', + 'driver_apk_path': '<(PRODUCT_DIR)/apks/<(driver_apk_name).apk' + }, + 'targets': [ + { + 'target_name': 'reporter_java', + 'type': 'none', + 'dependencies': ['../../base/base.gyp:base_java'], + 'variables': { + 'java_in_dir': '../../testing/android/reporter/java', + }, + 'includes': [ + '../../build/java.gypi', + ], + }, + { + 'target_name': 'broker_java', + 'type': 'none', + 'variables': { + 'java_in_dir': '../../testing/android/broker/java', + }, + 'includes': [ + '../../build/java.gypi', + ], + }, + { + 'target_name': 'driver_apk', + 'type': 'none', + 'dependencies': [ + 'broker_java', + 'reporter_java', + 'appurify_support.gyp:appurify_support_java', + ], + 'variables': { + 'apk_name': '<(driver_apk_name)', + 'final_apk_path': '<(driver_apk_path)', + 'java_in_dir': '../../testing/android/driver/java', + }, + 'includes': [ + '../../build/java_apk.gypi', + ], + }, + { + # This emulates gn's datadeps fields, allowing other APKs to declare + # that they require that this APK be built without including the + # driver's code. + 'target_name': 'require_driver_apk', + 'type': 'none', + 'actions': [ + { + 'action_name': 'require_<(driver_apk_name)', + 'message': 'Making sure <(driver_apk_path) has been built.', + 'variables': { + 'required_file': '<(PRODUCT_DIR)/driver_apk/<(driver_apk_name).apk.required', + }, + 'inputs': [ + '<(driver_apk_path)', + ], + 'outputs': [ + '<(required_file)', + ], + 'action': [ + 'python', '../../build/android/gyp/touch.py', '<(required_file)', + ], + }, + ], + }, + ], + }], + ], +}
diff --git a/testing/android/reporter/BUILD.gn b/testing/android/reporter/BUILD.gn new file mode 100644 index 0000000..7086a79 --- /dev/null +++ b/testing/android/reporter/BUILD.gn
@@ -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. + +import("//build/config/android/rules.gni") + +# GYP: //testing/android/on_device_instrumentation.gyp:reporter_java +android_library("reporter_java") { + chromium_code = true + + deps = [ + "//base:base_java", + ] + java_files = [ + "java/src/org/chromium/test/reporter/TestStatusListener.java", + "java/src/org/chromium/test/reporter/TestStatusReceiver.java", + "java/src/org/chromium/test/reporter/TestStatusReporter.java", + ] +}
diff --git a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusListener.java b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusListener.java new file mode 100644 index 0000000..62754181 --- /dev/null +++ b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusListener.java
@@ -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. + +package org.chromium.test.reporter; + +import android.content.Context; +import android.util.Log; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestListener; + +/** + * A TestListener that reports when tests start, pass, or fail. + */ +public class TestStatusListener implements TestListener { + + private static final String TAG = "TestStatusListener"; + + private boolean mFailed; + private final TestStatusReporter mReporter; + + public TestStatusListener(Context context) { + mReporter = new TestStatusReporter(context); + } + + /** Called when an error has occurred while running a test. + + Note that an error usually means a problem with the test or test harness, not with + the code under test. + + @param test The test in which the error occurred. + @param t The exception that was raised. + */ + @Override + public void addError(Test test, Throwable t) { + Log.e(TAG, "Error while running " + test.toString(), t); + mFailed = true; + } + + /** Called when a test has failed. + + @param test The test in which the failure occurred. + @param t The exception that was raised. + */ + public void addFailure(Test test, AssertionFailedError e) { + Log.e(TAG, "Failure while running " + test.toString(), e); + mFailed = true; + } + + /** Called when a test has started. + @param test The test that started. + */ + @Override + public void startTest(Test test) { + mFailed = false; + TestCase testCase = (TestCase) test; + mReporter.startHeartbeat(); + mReporter.testStarted(testCase.getClass().getName(), testCase.getName()); + } + + /** Called when a test has ended. + @param test The test that ended. + */ + @Override + public void endTest(Test test) { + TestCase testCase = (TestCase) test; + if (mFailed) { + mReporter.testFailed(testCase.getClass().getName(), testCase.getName()); + } else { + mReporter.testPassed(testCase.getClass().getName(), testCase.getName()); + } + mReporter.stopHeartbeat(); + } + +}
diff --git a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java new file mode 100644 index 0000000..e4af9b65 --- /dev/null +++ b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReceiver.java
@@ -0,0 +1,128 @@ +// 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. + +package org.chromium.test.reporter; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.util.Log; + +import java.util.ArrayList; +import java.util.List; + +/** Receives test status broadcasts send from + {@link org.chromium.test.reporter.TestStatusReporter}. + */ +public class TestStatusReceiver extends BroadcastReceiver { + + private static final String TAG = "ResultReceiver"; + + private final List<FailCallback> mFailCallbacks = new ArrayList<FailCallback>(); + private final List<HeartbeatCallback> mHeartbeatCallbacks = new ArrayList<HeartbeatCallback>(); + private final List<PassCallback> mPassCallbacks = new ArrayList<PassCallback>(); + private final List<StartCallback> mStartCallbacks = new ArrayList<StartCallback>(); + + /** An IntentFilter that matches the intents that this class can receive. */ + private static final IntentFilter INTENT_FILTER; + static { + IntentFilter filter = new IntentFilter(); + filter.addAction(TestStatusReporter.ACTION_HEARTBEAT); + filter.addAction(TestStatusReporter.ACTION_TEST_FAILED); + filter.addAction(TestStatusReporter.ACTION_TEST_PASSED); + filter.addAction(TestStatusReporter.ACTION_TEST_STARTED); + try { + filter.addDataType(TestStatusReporter.DATA_TYPE_HEARTBEAT); + filter.addDataType(TestStatusReporter.DATA_TYPE_RESULT); + } catch (IntentFilter.MalformedMimeTypeException e) { + Log.wtf(TAG, "Invalid MIME type", e); + } + INTENT_FILTER = filter; + } + + /** A callback used when a test has failed. */ + public interface FailCallback { + void testFailed(String testClass, String testMethod); + } + + /** A callback used when a heartbeat is received. */ + public interface HeartbeatCallback { + void heartbeat(); + } + + /** A callback used when a test has passed. */ + public interface PassCallback { + void testPassed(String testClass, String testMethod); + } + + /** A callback used when a test has started. */ + public interface StartCallback { + void testStarted(String testClass, String testMethod); + } + + /** Register a callback for when a test has failed. */ + public void registerCallback(FailCallback c) { + mFailCallbacks.add(c); + } + + /** Register a callback for when a heartbeat is received. */ + public void registerCallback(HeartbeatCallback c) { + mHeartbeatCallbacks.add(c); + } + + /** Register a callback for when a test has passed. */ + public void registerCallback(PassCallback c) { + mPassCallbacks.add(c); + } + + /** Register a callback for when a test has started. */ + public void registerCallback(StartCallback c) { + mStartCallbacks.add(c); + } + + /** Register this receiver using the provided context. */ + public void register(Context c) { + c.registerReceiver(this, INTENT_FILTER); + } + + /** Receive a broadcast intent. + * + * @param context The Context in which the receiver is running. + * @param intent The intent received. + */ + @Override + public void onReceive(Context context, Intent intent) { + String testClass = intent.getStringExtra(TestStatusReporter.EXTRA_TEST_CLASS); + String testMethod = intent.getStringExtra(TestStatusReporter.EXTRA_TEST_METHOD); + + switch (intent.getAction()) { + case TestStatusReporter.ACTION_TEST_STARTED: + for (StartCallback c : mStartCallbacks) { + c.testStarted(testClass, testMethod); + } + break; + case TestStatusReporter.ACTION_TEST_PASSED: + for (PassCallback c : mPassCallbacks) { + c.testPassed(testClass, testMethod); + } + break; + case TestStatusReporter.ACTION_TEST_FAILED: + for (FailCallback c : mFailCallbacks) { + c.testFailed(testClass, testMethod); + } + break; + case TestStatusReporter.ACTION_HEARTBEAT: + for (HeartbeatCallback c : mHeartbeatCallbacks) { + c.heartbeat(); + } + break; + default: + Log.e(TAG, "Unrecognized intent received: " + intent.toString()); + break; + } + } + +} +
diff --git a/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java new file mode 100644 index 0000000..6ac7312 --- /dev/null +++ b/testing/android/reporter/java/src/org/chromium/test/reporter/TestStatusReporter.java
@@ -0,0 +1,83 @@ +// 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. + +package org.chromium.test.reporter; + +import android.content.Context; +import android.content.Intent; + +import org.chromium.base.ThreadUtils; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Broadcasts test status to any listening {@link org.chromium.test.reporter.TestStatusReceiver}. + */ +public class TestStatusReporter { + + public static final String ACTION_HEARTBEAT = + "org.chromium.test.reporter.TestStatusReporter.HEARTBEAT"; + public static final String ACTION_TEST_STARTED = + "org.chromium.test.reporter.TestStatusReporter.TEST_STARTED"; + public static final String ACTION_TEST_PASSED = + "org.chromium.test.reporter.TestStatusReporter.TEST_PASSED"; + public static final String ACTION_TEST_FAILED = + "org.chromium.test.reporter.TestStatusReporter.TEST_FAILED"; + public static final String DATA_TYPE_HEARTBEAT = "org.chromium.test.reporter/heartbeat"; + public static final String DATA_TYPE_RESULT = "org.chromium.test.reporter/result"; + public static final String EXTRA_TEST_CLASS = + "org.chromium.test.reporter.TestStatusReporter.TEST_CLASS"; + public static final String EXTRA_TEST_METHOD = + "org.chromium.test.reporter.TestStatusReporter.TEST_METHOD"; + + public static final int HEARTBEAT_INTERVAL_MS = 5000; + + private final Context mContext; + private final AtomicBoolean mKeepBeating = new AtomicBoolean(false); + + public TestStatusReporter(Context c) { + mContext = c; + } + + public void startHeartbeat() { + mKeepBeating.set(true); + Runnable heartbeat = new Runnable() { + @Override + public void run() { + Intent i = new Intent(ACTION_HEARTBEAT); + i.setType(DATA_TYPE_HEARTBEAT); + mContext.sendBroadcast(i); + if (mKeepBeating.get()) { + ThreadUtils.postOnUiThreadDelayed(this, HEARTBEAT_INTERVAL_MS); + } + } + }; + ThreadUtils.postOnUiThreadDelayed(heartbeat, HEARTBEAT_INTERVAL_MS); + } + + public void testStarted(String testClass, String testMethod) { + sendBroadcast(testClass, testMethod, ACTION_TEST_STARTED); + } + + public void testPassed(String testClass, String testMethod) { + sendBroadcast(testClass, testMethod, ACTION_TEST_PASSED); + } + + public void testFailed(String testClass, String testMethod) { + sendBroadcast(testClass, testMethod, ACTION_TEST_FAILED); + } + + public void stopHeartbeat() { + mKeepBeating.set(false); + } + + private void sendBroadcast(String testClass, String testMethod, String action) { + Intent i = new Intent(action); + i.setType(DATA_TYPE_RESULT); + i.putExtra(EXTRA_TEST_CLASS, testClass); + i.putExtra(EXTRA_TEST_METHOD, testMethod); + mContext.sendBroadcast(i); + } + +}
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index f1cc8d6..68c741a 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -1,7 +1,54 @@ { "Linux ChromiumOS GN": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "chromedriver_unittests", + "chromeos_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "ui_chromeos_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ { @@ -11,7 +58,51 @@ }, "Linux ChromiumOS GN (dbg)": { "additional_compile_targets": [ - "net_unittests" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "chromedriver_unittests", + "chromeos_unittests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "ui_chromeos_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index e3819f5..88acb35 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -108,7 +108,57 @@ }, "Linux GN": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "nacl_loader_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ { @@ -118,7 +168,56 @@ }, "Linux GN (dbg)": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 2907a38..8883601 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -1,7 +1,32 @@ { "Mac GN": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "base_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "crypto_unittests", + "gcm_unit_tests", + "gn_unittests", + "gpu_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "ppapi_unittests", + "printing_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "url_unittests" ], "gtest_tests": [ { @@ -11,7 +36,32 @@ }, "Mac GN (dbg)": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "base_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "crypto_unittests", + "gcm_unit_tests", + "gn_unittests", + "gpu_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "ppapi_unittests", + "printing_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "url_unittests" ], "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index c8ca107..dcdfe7cd 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -16,7 +16,7 @@ { "swarming": { "can_use_on_swarming_builders": true, - "shards": 5 + "shards": 10 }, "test": "browser_tests" }, @@ -76,7 +76,8 @@ }, { "swarming": { - "can_use_on_swarming_builders": true + "can_use_on_swarming_builders": true, + "shards": 3 }, "test": "interactive_ui_tests" },
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json index f3ad4ca..74cf045 100644 --- a/testing/buildbot/chromium.perf.json +++ b/testing/buildbot/chromium.perf.json
@@ -337,18 +337,6 @@ ] }, "Win 8 Perf (2)": { - "scripts": [ - { - "args": [ - "performance_browser_tests", - "--test-launcher-print-test-stdio=always", - "--gtest_filter=TabCapturePerformanceTest.*:CastV2PerformanceTest.*", - "--test-launcher-jobs=1", - "--enable-gpu" - ], - "name": "performance_browser_tests", - "script": "gtest_perf_test.py" - } - ] + "scripts": [] } }
diff --git a/testing/buildbot/chromium.webkit.json b/testing/buildbot/chromium.webkit.json index 81a0cc63..5742add9 100644 --- a/testing/buildbot/chromium.webkit.json +++ b/testing/buildbot/chromium.webkit.json
@@ -370,7 +370,57 @@ }, "Linux GN": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "nacl_loader_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ { @@ -380,7 +430,56 @@ }, "Linux GN (dbg)": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 493461c..ca0ab239 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -469,7 +469,59 @@ }, "Win x64 GN": { "additional_compile_targets": [ - "net_unittests" + "accessibility_unittests", + "app_list_unittests", + "app_shell_unittests", + "ash_unittests", + "aura_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chrome", + "chrome_elf_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "compositor_unittests", + "content_browsertests", + "content_unittests", + "courgette_unittests", + "crypto_unittests", + "device_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "keyboard_unittests", + "media_unittests", + "message_center_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "ppapi_unittests", + "printing_unittests", + "sbox_integration_tests", + "sbox_unittests", + "sbox_validation_tests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ { @@ -479,7 +531,59 @@ }, "Win x64 GN (dbg)": { "additional_compile_targets": [ - "net_unittests" + "accessibility_unittests", + "app_list_unittests", + "app_shell_unittests", + "ash_unittests", + "aura_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chrome", + "chrome_elf_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "compositor_unittests", + "content_browsertests", + "content_unittests", + "courgette_unittests", + "crypto_unittests", + "device_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "keyboard_unittests", + "media_unittests", + "message_center_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "ppapi_unittests", + "printing_unittests", + "sbox_integration_tests", + "sbox_unittests", + "sbox_validation_tests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ {
diff --git a/testing/buildbot/client.v8.json b/testing/buildbot/client.v8.json index f18c6b92..2f43da04 100644 --- a/testing/buildbot/client.v8.json +++ b/testing/buildbot/client.v8.json
@@ -7,7 +7,57 @@ }, "V8 Linux GN": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "nacl_loader_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [] }
diff --git a/testing/buildbot/manage.py b/testing/buildbot/manage.py index e061ea2..bc362fd 100755 --- a/testing/buildbot/manage.py +++ b/testing/buildbot/manage.py
@@ -97,7 +97,11 @@ filename = os.path.basename(filepath) with open(filepath) as f: content = f.read() - config = json.loads(content) + try: + config = json.loads(content) + except ValueError as e: + print "Exception raised while checking %s: %s" % (filepath, e) + raise for builder, data in sorted(config.iteritems()): if builder in SKIP: # Oddities.
diff --git a/testing/buildbot/tryserver.blink.json b/testing/buildbot/tryserver.blink.json index a09070d..fe4d275 100644 --- a/testing/buildbot/tryserver.blink.json +++ b/testing/buildbot/tryserver.blink.json
@@ -7,7 +7,54 @@ }, "linux_chromium_gn_rel": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "chromedriver_unittests", + "chromeos_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "ui_chromeos_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ {
diff --git a/testing/buildbot/tryserver.chromium.linux.json b/testing/buildbot/tryserver.chromium.linux.json index 0328d5fc3..f068679 100644 --- a/testing/buildbot/tryserver.chromium.linux.json +++ b/testing/buildbot/tryserver.chromium.linux.json
@@ -13,7 +13,51 @@ }, "linux_chromium_gn_chromeos_dbg": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "chromedriver_unittests", + "chromeos_unittests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "ui_chromeos_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ { @@ -23,7 +67,54 @@ }, "linux_chromium_gn_chromeos_rel": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "chromedriver_unittests", + "chromeos_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "ui_chromeos_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ { @@ -33,7 +124,56 @@ }, "linux_chromium_gn_dbg": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ { @@ -43,7 +183,57 @@ }, "linux_chromium_gn_rel": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "nacl_loader_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [ {
diff --git a/testing/buildbot/tryserver.chromium.mac.json b/testing/buildbot/tryserver.chromium.mac.json index 3e49ba2..4a46f9a 100644 --- a/testing/buildbot/tryserver.chromium.mac.json +++ b/testing/buildbot/tryserver.chromium.mac.json
@@ -1,7 +1,32 @@ { "mac_chromium_gn_dbg": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "base_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "crypto_unittests", + "gcm_unit_tests", + "gn_unittests", + "gpu_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "ppapi_unittests", + "printing_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "url_unittests" ], "gtest_tests": [ { @@ -11,7 +36,32 @@ }, "mac_chromium_gn_rel": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "base_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "crypto_unittests", + "gcm_unit_tests", + "gn_unittests", + "gpu_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "ppapi_unittests", + "printing_unittests", + "skia_unittests", + "sql_unittests", + "sync_unit_tests", + "ui_base_unittests", + "url_unittests" ], "gtest_tests": [ {
diff --git a/testing/buildbot/tryserver.chromium.win.json b/testing/buildbot/tryserver.chromium.win.json index 29e5e233..6710973 100644 --- a/testing/buildbot/tryserver.chromium.win.json +++ b/testing/buildbot/tryserver.chromium.win.json
@@ -122,5 +122,129 @@ "test": "base_unittests" } ] + }, + "win_chromium_gn_x64_dbg": { + "additional_compile_targets": [ + "accessibility_unittests", + "app_list_unittests", + "app_shell_unittests", + "ash_unittests", + "aura_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chrome", + "chrome_elf_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "compositor_unittests", + "content_browsertests", + "content_unittests", + "courgette_unittests", + "crypto_unittests", + "device_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "keyboard_unittests", + "media_unittests", + "message_center_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "ppapi_unittests", + "printing_unittests", + "sbox_integration_tests", + "sbox_unittests", + "sbox_validation_tests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "url_unittests", + "views_unittests", + "wm_unittests" + ], + "gtest_tests": [ + { + "test": "base_unittests" + } + ] + }, + "win_chromium_gn_x64_rel": { + "additional_compile_targets": [ + "accessibility_unittests", + "app_list_unittests", + "app_shell_unittests", + "ash_unittests", + "aura_unittests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chrome", + "chrome_elf_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "compositor_unittests", + "content_browsertests", + "content_unittests", + "courgette_unittests", + "crypto_unittests", + "device_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "keyboard_unittests", + "media_unittests", + "message_center_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "ppapi_unittests", + "printing_unittests", + "sbox_integration_tests", + "sbox_unittests", + "sbox_validation_tests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "url_unittests", + "views_unittests", + "wm_unittests" + ], + "gtest_tests": [ + { + "test": "base_unittests" + } + ] } }
diff --git a/testing/buildbot/tryserver.v8.json b/testing/buildbot/tryserver.v8.json index aa8e50d..a92d05d 100644 --- a/testing/buildbot/tryserver.v8.json +++ b/testing/buildbot/tryserver.v8.json
@@ -7,7 +7,57 @@ }, "v8_linux_chromium_gn_rel": { "additional_compile_targets": [ - "all" + "accessibility_unittests", + "app_list_unittests", + "aura_unittests", + "browser_tests", + "cacheinvalidation_unittests", + "cast_unittests", + "cc_unittests", + "chromedriver_unittests", + "components_browsertests", + "components_unittests", + "content_browsertests", + "content_unittests", + "crypto_unittests", + "dbus_unittests", + "device_unittests", + "display_unittests", + "events_unittests", + "extensions_browsertests", + "extensions_unittests", + "gcm_unit_tests", + "gfx_unittests", + "gn_unittests", + "google_apis_unittests", + "gpu_unittests", + "interactive_ui_tests", + "ipc_mojo_unittests", + "ipc_tests", + "jingle_unittests", + "media_unittests", + "mojo_common_unittests", + "mojo_public_bindings_unittests", + "mojo_public_environment_unittests", + "mojo_public_system_unittests", + "mojo_public_utility_unittests", + "mojo_system_unittests", + "nacl_loader_unittests", + "net_unittests", + "ppapi_unittests", + "printing_unittests", + "remoting_unittests", + "sandbox_linux_unittests", + "skia_unittests", + "sql_unittests", + "sync_integration_tests", + "sync_unit_tests", + "ui_base_unittests", + "ui_touch_selection_unittests", + "unit_tests", + "url_unittests", + "views_unittests", + "wm_unittests" ], "gtest_tests": [] }
diff --git a/testing/xvfb.py b/testing/xvfb.py index ce53099..e7280f4d 100755 --- a/testing/xvfb.py +++ b/testing/xvfb.py
@@ -50,7 +50,7 @@ xvfb_path: Path to Xvfb. """ cmd = [xvfb_path, display, '-screen', '0', '1024x768x24', '-ac', - '-nolisten', 'tcp'] + '-nolisten', 'tcp', '-dpi', '96'] try: proc = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
diff --git a/third_party/android_crazy_linker/README.chromium b/third_party/android_crazy_linker/README.chromium index 4a8b658..2699579 100644 --- a/third_party/android_crazy_linker/README.chromium +++ b/third_party/android_crazy_linker/README.chromium
@@ -72,3 +72,9 @@ - Add basic LD_PRELOAD handling, for crbug/448968. +- Speculative fix for crbug/479220. + +- Fix RELRO sharing issue caused by packing relocations. + +- Correct fix for crbug/479220 (replace IsSystemLibrary() with caller flags). +
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp index 3a191b7..1f073566 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp
@@ -220,6 +220,7 @@ context->file_offset, &context->search_paths, false, + false, &context->error); if (!wrap) @@ -253,6 +254,7 @@ context->load_address, &context->search_paths, context->no_map_exec_support_fallback_enabled, + false, &context->error); if (!wrap)
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp index b2b80c1..559c09e 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.cpp
@@ -168,6 +168,9 @@ phdr_ = view->phdr(); phdr_count_ = view->phdr_count(); load_bias_ = view->load_bias(); +#if defined(__arm__) || defined(__aarch64__) + packed_relocations_ = view->packed_relocations(); +#endif // We handle only Rel or Rela, but not both. If DT_RELA or DT_RELASZ // then we require DT_PLTREL to agree. @@ -363,12 +366,9 @@ #if defined(__arm__) || defined(__aarch64__) -void ElfRelocations::RegisterPackedRelocations(uint8_t* packed_relocations) { - packed_relocations_ = packed_relocations; -} - -bool ElfRelocations::ApplyPackedRel(const uint8_t* packed_relocations, - Error* error) { +bool ElfRelocations::ForEachPackedRel(const uint8_t* packed_relocations, + RelRelocationHandler handler, + void* opaque) { Leb128Decoder decoder(packed_relocations); // Find the count of pairs and the start address. @@ -381,7 +381,7 @@ relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); const ELF::Addr sym_addr = 0; const bool resolved = false; - if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) + if (!handler(this, &relocation, opaque)) return false; size_t unpacked_count = 1; @@ -394,7 +394,7 @@ // Emit count relative relocations with delta offset. while (count) { relocation.r_offset += delta; - if (!ApplyRelReloc(&relocation, sym_addr, resolved, error)) + if (!handler(this, &relocation, opaque)) return false; unpacked_count++; count--; @@ -406,8 +406,9 @@ return true; } -bool ElfRelocations::ApplyPackedRela(const uint8_t* packed_relocations, - Error* error) { +bool ElfRelocations::ForEachPackedRela(const uint8_t* packed_relocations, + RelaRelocationHandler handler, + void* opaque) { Sleb128Decoder decoder(packed_relocations); // Find the count of pairs. @@ -430,7 +431,7 @@ relocation.r_offset = offset; relocation.r_info = ELF_R_INFO(0, RELATIVE_RELOCATION_CODE); relocation.r_addend = addend; - if (!ApplyRelaReloc(&relocation, sym_addr, resolved, error)) + if (!handler(this, &relocation, opaque)) return false; unpacked_count++; pairs--; @@ -440,6 +441,36 @@ return true; } +bool ElfRelocations::ApplyPackedRel(ElfRelocations* relocations, + const ELF::Rel* relocation, + void* opaque) { + Error* error = reinterpret_cast<Error*>(opaque); + const ELF::Addr sym_addr = 0; + const bool resolved = false; + return relocations->ApplyRelReloc(relocation, sym_addr, resolved, error); +} + +bool ElfRelocations::ApplyPackedRels(const uint8_t* packed_relocations, + Error* error) { + void* opaque = error; + return ForEachPackedRel(packed_relocations, &ApplyPackedRel, opaque); +} + +bool ElfRelocations::ApplyPackedRela(ElfRelocations* relocations, + const ELF::Rela* relocation, + void* opaque) { + Error* error = reinterpret_cast<Error*>(opaque); + const ELF::Addr sym_addr = 0; + const bool resolved = false; + return relocations->ApplyRelaReloc(relocation, sym_addr, resolved, error); +} + +bool ElfRelocations::ApplyPackedRelas(const uint8_t* packed_relocations, + Error* error) { + void* opaque = error; + return ForEachPackedRela(packed_relocations, &ApplyPackedRela, opaque); +} + bool ElfRelocations::ApplyPackedRelocations(Error* error) { if (!packed_relocations_) return true; @@ -449,7 +480,7 @@ packed_relocations_[1] == 'P' && packed_relocations_[2] == 'R' && packed_relocations_[3] == '1') { - return ApplyPackedRel(packed_relocations_ + 4, error); + return ApplyPackedRels(packed_relocations_ + 4, error); } // Check for an initial APA1 header, packed relocations with addend. @@ -457,7 +488,7 @@ packed_relocations_[1] == 'P' && packed_relocations_[2] == 'A' && packed_relocations_[3] == '1') { - return ApplyPackedRela(packed_relocations_ + 4, error); + return ApplyPackedRelas(packed_relocations_ + 4, error); } error->Format("Bad packed relocations ident, expected APR1 or APA1"); @@ -910,19 +941,124 @@ } } -void ElfRelocations::RelocateRela(size_t src_addr, - size_t dst_addr, - size_t map_addr, - size_t size) { +#if defined(__arm__) || defined(__aarch64__) + +struct AdjustRelocationArgs { + size_t src_addr; + size_t dst_addr; + size_t map_addr; + size_t size; +}; + +template<typename Rel> +bool ElfRelocations::RelocatePackedRelocation(ElfRelocations* relocations, + const Rel* rel, + void* opaque) { + AdjustRelocationArgs* args = reinterpret_cast<AdjustRelocationArgs*>(opaque); + const size_t src_addr = args->src_addr; + const size_t dst_addr = args->dst_addr; + const size_t map_addr = args->map_addr; + const size_t size = args->size; + + const size_t load_bias = relocations->load_bias_; + + const size_t dst_delta = dst_addr - src_addr; + const size_t map_delta = map_addr - src_addr; + + const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); + const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); + ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias); + + if (rel_type == 0 || rel_symbol != 0) { + // Ignore empty and symbolic relocations + return true; + } + + if (src_reloc < src_addr || src_reloc >= src_addr + size) { + // Ignore entries that don't relocate addresses inside the source section. + return true; + } + + relocations->AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); + return true; +} + +template bool ElfRelocations::RelocatePackedRelocation<ELF::Rel>( + ElfRelocations* relocations, const ELF::Rel* rel, void* opaque); + +template bool ElfRelocations::RelocatePackedRelocation<ELF::Rela>( + ElfRelocations* relocations, const ELF::Rela* rel, void* opaque); + +void ElfRelocations::RelocatePackedRels(const uint8_t* packed_relocations, + size_t src_addr, + size_t dst_addr, + size_t map_addr, + size_t size) { + AdjustRelocationArgs args; + args.src_addr = src_addr; + args.dst_addr = dst_addr; + args.map_addr = map_addr; + args.size = size; + ForEachPackedRel(packed_relocations, + &RelocatePackedRelocation<ELF::Rel>, &args); +} + +void ElfRelocations::RelocatePackedRelas(const uint8_t* packed_relocations, + size_t src_addr, + size_t dst_addr, + size_t map_addr, + size_t size) { + AdjustRelocationArgs args; + args.src_addr = src_addr; + args.dst_addr = dst_addr; + args.map_addr = map_addr; + args.size = size; + ForEachPackedRela(packed_relocations, + &RelocatePackedRelocation<ELF::Rela>, &args); +} + +void ElfRelocations::RelocatePackedRelocations(size_t src_addr, + size_t dst_addr, + size_t map_addr, + size_t size) { + if (!packed_relocations_) + return; + + // Check for an initial APR1 header, packed relocations. + if (packed_relocations_[0] == 'A' && + packed_relocations_[1] == 'P' && + packed_relocations_[2] == 'R' && + packed_relocations_[3] == '1') { + RelocatePackedRels(packed_relocations_ + 4, + src_addr, dst_addr, map_addr, size); + } + + // Check for an initial APA1 header, packed relocations with addend. + if (packed_relocations_[0] == 'A' && + packed_relocations_[1] == 'P' && + packed_relocations_[2] == 'A' && + packed_relocations_[3] == '1') { + RelocatePackedRelas(packed_relocations_ + 4, + src_addr, dst_addr, map_addr, size); + } +} + +#endif // __arm__ || __aarch64__ + +template<typename Rel> +void ElfRelocations::RelocateRelocation(size_t src_addr, + size_t dst_addr, + size_t map_addr, + size_t size) { // Add this value to each source address to get the corresponding // destination address. const size_t dst_delta = dst_addr - src_addr; const size_t map_delta = map_addr - src_addr; // Ignore PLT relocations, which all target symbols (ignored here). - const ELF::Rela* rel = reinterpret_cast<ELF::Rela*>(relocations_); - const size_t relocations_count = relocations_size_ / sizeof(ELF::Rela); - const ELF::Rela* rel_limit = rel + relocations_count; + const Rel* rel = reinterpret_cast<Rel*>(relocations_); + const size_t relocations_count = relocations_size_ / sizeof(Rel); + const Rel* rel_limit = rel + relocations_count; for (; rel < rel_limit; ++rel) { const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); @@ -943,38 +1079,11 @@ } } -void ElfRelocations::RelocateRel(size_t src_addr, - size_t dst_addr, - size_t map_addr, - size_t size) { - // Add this value to each source address to get the corresponding - // destination address. - const size_t dst_delta = dst_addr - src_addr; - const size_t map_delta = map_addr - src_addr; +template void ElfRelocations::RelocateRelocation<ELF::Rel>( + size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); - // Ignore PLT relocations, which all target symbols (ignored here). - const ELF::Rel* rel = reinterpret_cast<ELF::Rel*>(relocations_); - const size_t relocations_count = relocations_size_ / sizeof(ELF::Rel); - const ELF::Rel* rel_limit = rel + relocations_count; - - for (; rel < rel_limit; ++rel) { - const ELF::Word rel_type = ELF_R_TYPE(rel->r_info); - const ELF::Word rel_symbol = ELF_R_SYM(rel->r_info); - ELF::Addr src_reloc = static_cast<ELF::Addr>(rel->r_offset + load_bias_); - - if (rel_type == 0 || rel_symbol != 0) { - // Ignore empty and symbolic relocations - continue; - } - - if (src_reloc < src_addr || src_reloc >= src_addr + size) { - // Ignore entries that don't relocate addresses inside the source section. - continue; - } - - AdjustRelocation(rel_type, src_reloc, dst_delta, map_delta); - } -} +template void ElfRelocations::RelocateRelocation<ELF::Rela>( + size_t src_addr, size_t dst_addr, size_t map_addr, size_t size); void ElfRelocations::CopyAndRelocate(size_t src_addr, size_t dst_addr, @@ -985,12 +1094,17 @@ reinterpret_cast<void*>(src_addr), size); +#if defined(__arm__) || defined(__aarch64__) + // Relocate packed relative relocations. + RelocatePackedRelocations(src_addr, dst_addr, map_addr, size); +#endif + // Relocate relocations. if (relocations_type_ == DT_REL) - RelocateRel(src_addr, dst_addr, map_addr, size); + RelocateRelocation<ELF::Rel>(src_addr, dst_addr, map_addr, size); if (relocations_type_ == DT_RELA) - RelocateRela(src_addr, dst_addr, map_addr, size); + RelocateRelocation<ELF::Rela>(src_addr, dst_addr, map_addr, size); #ifdef __mips__ // Add this value to each source address to get the corresponding
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h index 71ed33b1..d57c90f 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_relocations.h
@@ -44,12 +44,6 @@ SymbolResolver* resolver, Error* error); -#if defined(__arm__) || defined(__aarch64__) - // Register packed relocations to apply. - // |packed_relocs| is a pointer to packed relocations data. - void RegisterPackedRelocations(uint8_t* packed_relocations); -#endif - // This function is used to adjust relocated addresses in a copy of an // existing section of an ELF binary. I.e. |src_addr|...|src_addr + size| // must be inside the mapped ELF binary, this function will first copy its @@ -92,24 +86,68 @@ ELF::Addr src_reloc, size_t dst_delta, size_t map_delta); - void RelocateRela(size_t src_addr, - size_t dst_addr, - size_t map_addr, - size_t size); - void RelocateRel(size_t src_addr, - size_t dst_addr, - size_t map_addr, - size_t size); + template<typename Rel> + void RelocateRelocation(size_t src_addr, + size_t dst_addr, + size_t map_addr, + size_t size); #if defined(__arm__) || defined(__aarch64__) - // Apply packed rel or rela relocations. On error, return false. - bool ApplyPackedRel(const uint8_t* packed_relocations, Error* error); - bool ApplyPackedRela(const uint8_t* packed_relocations, Error* error); + // Packed relocations unpackers. Call the given handler for each + // relocation in the unpacking stream. There are two versions, one + // for REL, the other for RELA. + typedef bool (*RelRelocationHandler)(ElfRelocations* relocations, + const ELF::Rel* relocation, + void* opaque); + bool ForEachPackedRel(const uint8_t* packed_relocations, + RelRelocationHandler handler, + void* opaque); - // Apply packed relocations. + typedef bool (*RelaRelocationHandler)(ElfRelocations* relocations, + const ELF::Rela* relocation, + void* opaque); + bool ForEachPackedRela(const uint8_t* packed_relocations, + RelaRelocationHandler handler, + void* opaque); + + // Apply packed REL and RELA relocations. On error, return false. + bool ApplyPackedRels(const uint8_t* packed_relocations, Error* error); + static bool ApplyPackedRel(ElfRelocations* relocations, + const ELF::Rel* relocation, + void* opaque); + bool ApplyPackedRelas(const uint8_t* packed_relocations, Error* error); + static bool ApplyPackedRela(ElfRelocations* relocations, + const ELF::Rela* relocation, + void* opaque); + + // Apply all packed relocations. // On error, return false and set |error| message. No-op if no packed - // relocations were registered. + // relocations are present. bool ApplyPackedRelocations(Error* error); + + // Relocate packed REL and RELA relocations. + template<typename Rel> + static bool RelocatePackedRelocation(ElfRelocations* relocations, + const Rel* rel, + void* opaque); + + void RelocatePackedRels(const uint8_t* packed_relocations, + size_t src_addr, + size_t dst_addr, + size_t map_addr, + size_t size); + void RelocatePackedRelas(const uint8_t* packed_relocations, + size_t src_addr, + size_t dst_addr, + size_t map_addr, + size_t size); + + // Relocate all packed relocations. No-op if no packed relocations + // are present. + void RelocatePackedRelocations(size_t src_addr, + size_t dst_addr, + size_t map_addr, + size_t size); #endif #if defined(__mips__)
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_elf_view.h b/third_party/android_crazy_linker/src/src/crazy_linker_elf_view.h index 6c62d1df..8166123 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_elf_view.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_elf_view.h
@@ -93,6 +93,16 @@ // ELF binary is mapped.On failure, return false and set |error| message. bool ProtectRelroSection(Error* error); +#if defined(__arm__) || defined(__aarch64__) + // Register packed relocations to apply. + // |packed_relocs| is a pointer to packed relocations data. + void RegisterPackedRelocations(uint8_t* packed_relocations) { + packed_relocations_ = packed_relocations; + } + + uint8_t* packed_relocations() const { return packed_relocations_; } +#endif + protected: const ELF::Phdr* phdr_; size_t phdr_count_; @@ -102,6 +112,10 @@ ELF::Addr load_address_; size_t load_size_; size_t load_bias_; + +#if defined(__arm__) || defined(__aarch64__) + uint8_t* packed_relocations_; +#endif }; } // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp index 4c351da..04af624 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp
@@ -135,6 +135,7 @@ 0U /* file offset */, &search_path_list, no_map_exec_support_fallback_enabled, + true /* is_dependency_or_preload */, &error); if (!preload) { LOG("'%s' cannot be preloaded: ignored\n", lib_name.c_str()); @@ -315,6 +316,7 @@ off_t file_offset, SearchPathList* search_path_list, bool no_map_exec_support_fallback_enabled, + bool is_dependency_or_preload, Error* error) { const char* base_name = GetBaseNamePtr(lib_name); @@ -344,9 +346,10 @@ return wrap; } - if (IsSystemLibrary(lib_name)) { - // This is a system library, probably because we're loading the - // library as a dependency. + // If this load is prompted by either dependencies or preloads, open + // normally with dlopen() and do not proceed to try and load the library + // crazily. + if (is_dependency_or_preload) { LOG("%s: Loading system library '%s'\n", __FUNCTION__, lib_name); ::dlerror(); void* system_lib = dlopen(lib_name, dlopen_mode); @@ -412,6 +415,7 @@ 0U /* file offset */, search_path_list, no_map_exec_support_fallback_enabled, + true /* is_dependency_or_preload */, &dep_error); if (!dependency) { error->Format("When loading %s: %s", base_name, dep_error.c_str()); @@ -527,6 +531,7 @@ uintptr_t load_address, SearchPathList* search_path_list, bool no_map_exec_support_fallback_enabled, + bool is_dependency_or_preload, Error* error) { int offset = FindMappableLibraryInZipFile(zip_file_path, lib_name, error); if (offset == CRAZY_OFFSET_FAILED) { @@ -535,7 +540,8 @@ return LoadLibrary( zip_file_path, dlopen_flags, load_address, offset, - search_path_list, no_map_exec_support_fallback_enabled, error); + search_path_list, no_map_exec_support_fallback_enabled, + is_dependency_or_preload, error); } void LibraryList::AddLibrary(LibraryView* wrap) {
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.h b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.h index 0e319fe..c788988e 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.h
@@ -70,6 +70,7 @@ off_t file_offset, SearchPathList* search_path_list, bool no_map_exec_support_fallback_enabled, + bool is_dependency_or_preload, Error* error); // Return the full path of |lib_name| in the zip file @@ -92,6 +93,7 @@ uintptr_t load_address, SearchPathList* search_path_list, bool no_map_exec_support_fallback_enabled, + bool is_dependency_or_preload, Error* error); // Unload a given shared library. This really decrements the library's
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp index 9c50798..eff997d2 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
@@ -417,6 +417,9 @@ LOG("%s: Packed relocations stored at %p\n", __FUNCTION__, packed_relocations_); + + // Add packed relocations to the view. + view_.RegisterPackedRelocations(packed_relocations_); } #endif @@ -436,10 +439,6 @@ if (!relocations.Init(&view_, error)) return false; -#if defined(__arm__) || defined(__aarch64__) - relocations.RegisterPackedRelocations(packed_relocations_); -#endif - SharedLibraryResolver resolver(this, lib_list, preloads, dependencies); if (!relocations.ApplyAll(&symbols_, &resolver, error)) return false;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp index 752acee7..d2f0734 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_system.cpp
@@ -87,26 +87,4 @@ #endif // !UNIT_TESTS -// Returns true iff |lib_name| corresponds to one of the NDK-exposed -// system libraries. -bool IsSystemLibrary(const char* lib_name) { - static const char* const kSystemLibs[] = { - "libandroid.so", "libc.so", "libdl.so", "libjnigraphics.so", - "liblog.so", "libm.so", "libstdc++.so", "libz.so", - "libEGL.so", "libGLESv1_CM.so", "libGLESv2.so", "libGLESv3.so", - "libOpenMAXAL.so", "libOpenSLES.so", "libsigchain.so", }; - const size_t kSize = sizeof(kSystemLibs) / sizeof(kSystemLibs[0]); - const char* base_name = ::strrchr(lib_name, '/'); - if (!base_name) - base_name = lib_name; - else - base_name += 1; - - for (size_t n = 0; n < kSize; ++n) { - if (!strcmp(kSystemLibs[n], base_name)) - return true; - } - return false; -} - } // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_system.h b/third_party/android_crazy_linker/src/src/crazy_linker_system.h index e61e02c..17381a8 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_system.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_system.h
@@ -76,10 +76,6 @@ // Returns the value of a given environment variable. const char* GetEnv(const char* var_name); -// Returns true iff |lib_name| corresponds to one of the NDK-exposed -// system libraries. -bool IsSystemLibrary(const char* lib_name); - } // namespace crazy #endif // CRAZY_LINKER_SYSTEM_H
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_system_unittest.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_system_unittest.cpp index 93ee1af4..8bf082f 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_system_unittest.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_system_unittest.cpp
@@ -39,33 +39,4 @@ EXPECT_FALSE(PathExists("/tmp/foo")); } -TEST(System, IsSystemLibrary) { - SystemMock sys; - static const struct { - const char* name; - bool success; - } kData[] = { - {"libEGL.so", true}, - {"libGLESv1_CM.so", true}, - {"libGLESv1.so", false}, - {"libGLESv2.so", true}, - {"libOpenMAXAL.so", true}, - {"libOpenSLES.so", true}, - {"libandroid.so", true}, - {"libc.so", true}, - {"libdl.so", true}, - {"libjnigraphics.so", true}, - {"libm.so", true}, - {"libstdc++.so", true}, - {"libstlport.so", false}, - {"libz.so", true}, - {"/system/lib/libc.so", true}, - {"/system/libc.so/libfoo.so", false}, - }; - for (size_t n = 0; n < ARRAY_LEN(kData); ++n) { - TEST_TEXT << "Checking " << kData[n].name; - EXPECT_EQ(kData[n].success, IsSystemLibrary(kData[n].name)); - } -} - } // namespace crazy
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp index 4b73969..7f5d7a03 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_wrappers.cpp
@@ -82,6 +82,7 @@ 0U /* file_offset */, Globals::GetSearchPaths(), false, + false, &error); if (wrap) return wrap;
diff --git a/third_party/android_platform/README.chromium b/third_party/android_platform/README.chromium index ef88a226..1dea3b60 100644 --- a/third_party/android_platform/README.chromium +++ b/third_party/android_platform/README.chromium
@@ -41,3 +41,6 @@ Create gyp build Create gn build (currently packer only; no unit tests) Apply https://android-review.googlesource.com/#/c/143878/ + Apply https://android-review.googlesource.com/#/c/147620/ + https://android-review.googlesource.com/#/c/147745/ + https://android-review.googlesource.com/#/c/148073/
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc index 20b25ef..fb74233 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.cc
@@ -190,6 +190,7 @@ // these; both is unsupported. bool has_rel_relocations = false; bool has_rela_relocations = false; + bool has_android_relocations = false; Elf_Scn* section = NULL; while ((section = elf_nextscn(elf, section)) != nullptr) { @@ -209,6 +210,11 @@ if ((name == ".rel.dyn" || name == ".rela.dyn") && section_header->sh_size > 0) { found_relocations_section = section; + + // Note if relocation section is already packed + has_android_relocations = + section_header->sh_type == SHT_ANDROID_REL || + section_header->sh_type == SHT_ANDROID_RELA; } if (section_header->sh_offset == dynamic_program_header->p_offset) { @@ -250,6 +256,7 @@ relocations_section_ = found_relocations_section; dynamic_section_ = found_dynamic_section; relocations_type_ = has_rel_relocations ? REL : RELA; + has_android_relocations_ = has_android_relocations; return true; } @@ -439,6 +446,9 @@ tag == DT_JMPREL || tag == DT_INIT_ARRAY || tag == DT_FINI_ARRAY || + tag == DT_VERSYM || + tag == DT_VERNEED || + tag == DT_VERDEF || tag == DT_ANDROID_REL|| tag == DT_ANDROID_RELA); @@ -586,7 +596,7 @@ const typename ELF::Rel* relocations_base = reinterpret_cast<typename ELF::Rel*>(data->d_buf); ConvertRelArrayToRelaVector(relocations_base, data->d_size / sizeof(typename ELF::Rel), &relocations); - LOG(INFO) << "Relocations : REL"; + VLOG(1) << "Relocations : REL"; } else if (relocations_type_ == RELA) { // Convert data to a vector of relocations with addends. const typename ELF::Rela* relocations_base = reinterpret_cast<typename ELF::Rela*>(data->d_buf); @@ -594,7 +604,7 @@ relocations_base, relocations_base + data->d_size / sizeof(relocations[0])); - LOG(INFO) << "Relocations : RELA"; + VLOG(1) << "Relocations : RELA"; } else { NOTREACHED(); } @@ -607,10 +617,15 @@ bool ElfFile<ELF>::PackTypedRelocations(std::vector<typename ELF::Rela>* relocations) { typedef typename ELF::Rela Rela; + if (has_android_relocations_) { + LOG(ERROR) << "Relocation table is already packed"; + return false; + } + // If no relocations then we have nothing packable. Perhaps // the shared object has already been packed? if (relocations->empty()) { - LOG(ERROR) << "No relocations found (already packed?)"; + LOG(ERROR) << "No relocations found"; return false; } @@ -618,18 +633,18 @@ relocations_type_ == RELA ? sizeof(typename ELF::Rela) : sizeof(typename ELF::Rel); const size_t initial_bytes = relocations->size() * rel_size; - LOG(INFO) << "Unpacked : " << initial_bytes << " bytes"; + VLOG(1) << "Unpacked : " << initial_bytes << " bytes"; std::vector<uint8_t> packed; RelocationPacker<ELF> packer; // Pack relocations: dry run to estimate memory savings. packer.PackRelocations(*relocations, &packed); const size_t packed_bytes_estimate = packed.size() * sizeof(packed[0]); - LOG(INFO) << "Packed (no padding): " << packed_bytes_estimate << " bytes"; + VLOG(1) << "Packed (no padding): " << packed_bytes_estimate << " bytes"; if (packed.empty()) { LOG(INFO) << "Too few relocations to pack"; - return false; + return true; } // Pre-calculate the size of the hole we will close up when we rewrite @@ -646,12 +661,12 @@ // Adjusting for alignment may have removed any packing benefit. if (hole_size == 0) { LOG(INFO) << "Too few relocations to pack after alignment"; - return false; + return true; } if (hole_size <= 0) { LOG(INFO) << "Packing relocations saves no space"; - return false; + return true; } size_t data_padding_bytes = is_padding_relocations_ ? @@ -734,7 +749,7 @@ packed.size() > 3 && packed[0] == 'A' && packed[1] == 'P' && - (packed[2] == 'U' || packed[2] == 'S') && + packed[2] == 'S' && packed[3] == '2') { LOG(INFO) << "Relocations : " << (relocations_type_ == REL ? "REL" : "RELA"); } else {
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h index a749d50..d6acc76 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file.h
@@ -36,7 +36,7 @@ explicit ElfFile(int fd) : fd_(fd), is_padding_relocations_(false), elf_(NULL), relocations_section_(NULL), dynamic_section_(NULL), - relocations_type_(NONE) {} + relocations_type_(NONE), has_android_relocations_(false) {} ~ElfFile() {} // Set padding mode. When padding, PackRelocations() will not shrink @@ -111,6 +111,9 @@ // Relocation type found, assigned by Load(). relocations_type_t relocations_type_; + + // Elf-file has android relocations section + bool has_android_relocations_; }; } // namespace relocation_packer
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc index 434f1010..5271eef 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/elf_file_unittest.cc
@@ -175,13 +175,19 @@ namespace relocation_packer { -TEST(ElfFile, PackRelocations) { +TEST(ElfFile, PackRelocationsArm32) { RunPackRelocationsTestFor("arm32"); +} + +TEST(ElfFile, PackRelocationsArm64) { RunPackRelocationsTestFor("arm64"); } -TEST(ElfFile, UnpackRelocations) { +TEST(ElfFile, UnpackRelocationsArm32) { RunUnpackRelocationsTestFor("arm32"); +} + +TEST(ElfFile, UnpackRelocationsArm64) { RunUnpackRelocationsTestFor("arm64"); }
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/leb128.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/leb128.cc deleted file mode 100644 index 101c557..0000000 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/leb128.cc +++ /dev/null
@@ -1,87 +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 "leb128.h" - -#include <stdint.h> -#include <vector> - -#include "elf_traits.h" - -namespace relocation_packer { - -// Empty constructor and destructor to silence chromium-style. -template <typename uint_t> -Leb128Encoder<uint_t>::Leb128Encoder() { } - -template <typename uint_t> -Leb128Encoder<uint_t>::~Leb128Encoder() { } - -// Add a single value to the encoding. Values are encoded with variable -// length. The least significant 7 bits of each byte hold 7 bits of data, -// and the most significant bit is set on each byte except the last. -template <typename uint_t> -void Leb128Encoder<uint_t>::Enqueue(uint_t value) { - uint_t uvalue = static_cast<uint_t>(value); - do { - const uint8_t byte = uvalue & 127; - uvalue >>= 7; - encoding_.push_back((uvalue ? 128 : 0) | byte); - } while (uvalue); -} - -// Add a vector of values to the encoding. -template <typename uint_t> -void Leb128Encoder<uint_t>::EnqueueAll(const std::vector<uint_t>& values) { - for (size_t i = 0; i < values.size(); ++i) { - Enqueue(values[i]); - } -} - -// Create a new decoder for the given encoded stream. -template <typename uint_t> -Leb128Decoder<uint_t>::Leb128Decoder(const std::vector<uint8_t>& encoding, size_t start_with) { - encoding_ = encoding; - cursor_ = start_with; -} - -// Empty destructor to silence chromium-style. -template <typename uint_t> -Leb128Decoder<uint_t>::~Leb128Decoder() { } - -// Decode and retrieve a single value from the encoding. Read forwards until -// a byte without its most significant bit is found, then read the 7 bit -// fields of the bytes spanned to re-form the value. -template <typename uint_t> -uint_t Leb128Decoder<uint_t>::Dequeue() { - uint_t value = 0; - - size_t shift = 0; - uint8_t byte; - - // Loop until we reach a byte with its high order bit clear. - do { - byte = encoding_[cursor_++]; - value |= static_cast<uint_t>(byte & 127) << shift; - shift += 7; - } while (byte & 128); - - return value; -} - -// Decode and retrieve all remaining values from the encoding. -template <typename uint_t> -void Leb128Decoder<uint_t>::DequeueAll(std::vector<uint_t>* values) { - while (cursor_ < encoding_.size()) { - values->push_back(Dequeue()); - } -} - -template class Leb128Encoder<uint32_t>; -template class Leb128Encoder<uint64_t>; - -template class Leb128Decoder<uint32_t>; -template class Leb128Decoder<uint64_t>; - -} // namespace relocation_packer
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/leb128.h b/third_party/android_platform/bionic/tools/relocation_packer/src/leb128.h deleted file mode 100644 index 67fc4b82..0000000 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/leb128.h +++ /dev/null
@@ -1,75 +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. - -// LEB128 encoder and decoder for packed relative relocations. -// -// Packed relocations consist of a large number of relatively small -// integer values. Encoding these as LEB128 saves space. -// -// For more on LEB128 see http://en.wikipedia.org/wiki/LEB128. - -#ifndef TOOLS_RELOCATION_PACKER_SRC_LEB128_H_ -#define TOOLS_RELOCATION_PACKER_SRC_LEB128_H_ - -#include <stdint.h> -#include <vector> - -#include "elf_traits.h" - -namespace relocation_packer { - -// Encode packed words as a LEB128 byte stream. -template <typename uint_t> -class Leb128Encoder { - public: - // Explicit (but empty) constructor and destructor, for chromium-style. - Leb128Encoder(); - ~Leb128Encoder(); - - // Add a value to the encoding stream. - // |value| is the unsigned int to add. - void Enqueue(uint_t value); - - // Add a vector of values to the encoding stream. - // |values| is the vector of unsigned ints to add. - void EnqueueAll(const std::vector<uint_t>& values); - - // Retrieve the encoded representation of the values. - // |encoding| is the returned vector of encoded data. - void GetEncoding(std::vector<uint8_t>* encoding) { *encoding = encoding_; } - - private: - // Growable vector holding the encoded LEB128 stream. - std::vector<uint8_t> encoding_; -}; - -// Decode a LEB128 byte stream to produce packed words. -template <typename uint_t> -class Leb128Decoder { - public: - // Create a new decoder for the given encoded stream. - // |encoding| is the vector of encoded data. - explicit Leb128Decoder(const std::vector<uint8_t>& encoding, size_t start_with); - - // Explicit (but empty) destructor, for chromium-style. - ~Leb128Decoder(); - - // Retrieve the next value from the encoded stream. - uint_t Dequeue(); - - // Retrieve all remaining values from the encoded stream. - // |values| is the vector of decoded data. - void DequeueAll(std::vector<uint_t>* values); - - private: - // Encoded LEB128 stream. - std::vector<uint8_t> encoding_; - - // Cursor indicating the current stream retrieval point. - size_t cursor_; -}; - -} // namespace relocation_packer - -#endif // TOOLS_RELOCATION_PACKER_SRC_LEB128_H_
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/leb128_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/leb128_unittest.cc deleted file mode 100644 index 8a7028c..0000000 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/leb128_unittest.cc +++ /dev/null
@@ -1,111 +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 "leb128.h" - -#include <vector> -#include "gtest/gtest.h" - -namespace relocation_packer { - -TEST(Leb128, Encoder64) { - std::vector<uint64_t> values; - values.push_back(624485); - values.push_back(0); - values.push_back(1); - values.push_back(127); - values.push_back(128); - - Leb128Encoder<uint64_t> encoder; - encoder.EnqueueAll(values); - - encoder.Enqueue(4294967295); - encoder.Enqueue(18446744073709551615ul); - - std::vector<uint8_t> encoding; - encoder.GetEncoding(&encoding); - - EXPECT_EQ(23U, encoding.size()); - // 624485 - EXPECT_EQ(0xe5, encoding[0]); - EXPECT_EQ(0x8e, encoding[1]); - EXPECT_EQ(0x26, encoding[2]); - // 0 - EXPECT_EQ(0x00, encoding[3]); - // 1 - EXPECT_EQ(0x01, encoding[4]); - // 127 - EXPECT_EQ(0x7f, encoding[5]); - // 128 - EXPECT_EQ(0x80, encoding[6]); - EXPECT_EQ(0x01, encoding[7]); - // 4294967295 - EXPECT_EQ(0xff, encoding[8]); - EXPECT_EQ(0xff, encoding[9]); - EXPECT_EQ(0xff, encoding[10]); - EXPECT_EQ(0xff, encoding[11]); - EXPECT_EQ(0x0f, encoding[12]); - // 18446744073709551615 - EXPECT_EQ(0xff, encoding[13]); - EXPECT_EQ(0xff, encoding[14]); - EXPECT_EQ(0xff, encoding[15]); - EXPECT_EQ(0xff, encoding[16]); - EXPECT_EQ(0xff, encoding[17]); - EXPECT_EQ(0xff, encoding[18]); - EXPECT_EQ(0xff, encoding[19]); - EXPECT_EQ(0xff, encoding[20]); - EXPECT_EQ(0xff, encoding[21]); - EXPECT_EQ(0x01, encoding[22]); -} - -TEST(Leb128, Decoder64) { - std::vector<uint8_t> encoding; - // 624485 - encoding.push_back(0xe5); - encoding.push_back(0x8e); - encoding.push_back(0x26); - // 0 - encoding.push_back(0x00); - // 1 - encoding.push_back(0x01); - // 127 - encoding.push_back(0x7f); - // 128 - encoding.push_back(0x80); - encoding.push_back(0x01); - // 4294967295 - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0x0f); - // 18446744073709551615 - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0xff); - encoding.push_back(0x01); - - Leb128Decoder<uint64_t> decoder(encoding, 0); - - EXPECT_EQ(624485U, decoder.Dequeue()); - - std::vector<uint64_t> dequeued; - decoder.DequeueAll(&dequeued); - - EXPECT_EQ(6U, dequeued.size()); - EXPECT_EQ(0U, dequeued[0]); - EXPECT_EQ(1U, dequeued[1]); - EXPECT_EQ(127U, dequeued[2]); - EXPECT_EQ(128U, dequeued[3]); - EXPECT_EQ(4294967295U, dequeued[4]); - EXPECT_EQ(18446744073709551615UL, dequeued[5]); -} - -} // namespace relocation_packer
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc index 8e30612..433611f 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/packer.cc
@@ -9,7 +9,6 @@ #include "debug.h" #include "delta_encoder.h" #include "elf_traits.h" -#include "leb128.h" #include "sleb128.h" namespace relocation_packer { @@ -28,32 +27,17 @@ return; Sleb128Encoder<typename ELF::Addr> sleb128_encoder; - Leb128Encoder<typename ELF::Addr> leb128_encoder; - std::vector<uint8_t> leb128_packed; std::vector<uint8_t> sleb128_packed; - leb128_encoder.EnqueueAll(packed_words); - leb128_encoder.GetEncoding(&leb128_packed); - sleb128_encoder.EnqueueAll(packed_words); sleb128_encoder.GetEncoding(&sleb128_packed); - // TODO (simonb): Estimate savings on current android system image and consider using - // one encoder for all packed relocations to reduce complexity. - if (leb128_packed.size() <= sleb128_packed.size()) { - packed->push_back('A'); - packed->push_back('P'); - packed->push_back('U'); - packed->push_back('2'); - packed->insert(packed->end(), leb128_packed.begin(), leb128_packed.end()); - } else { - packed->push_back('A'); - packed->push_back('P'); - packed->push_back('S'); - packed->push_back('2'); - packed->insert(packed->end(), sleb128_packed.begin(), sleb128_packed.end()); - } + packed->push_back('A'); + packed->push_back('P'); + packed->push_back('S'); + packed->push_back('2'); + packed->insert(packed->end(), sleb128_packed.begin(), sleb128_packed.end()); } // Unpack relative relocations from a run-length encoded packed @@ -67,16 +51,11 @@ CHECK(packed.size() > 4 && packed[0] == 'A' && packed[1] == 'P' && - (packed[2] == 'U' || packed[2] == 'S') && + packed[2] == 'S' && packed[3] == '2'); - if (packed[2] == 'U') { - Leb128Decoder<typename ELF::Addr> decoder(packed, 4); - decoder.DequeueAll(&packed_words); - } else { - Sleb128Decoder<typename ELF::Addr> decoder(packed, 4); - decoder.DequeueAll(&packed_words); - } + Sleb128Decoder<typename ELF::Addr> decoder(packed, 4); + decoder.DequeueAll(&packed_words); RelocationDeltaCodec<ELF> codec; codec.Decode(packed_words, relocations);
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc b/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc index 8dddd8b..424b92c 100644 --- a/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc +++ b/third_party/android_platform/bionic/tools/relocation_packer/src/packer_unittest.cc
@@ -39,6 +39,7 @@ static void DoPackNoAddend() { std::vector<typename ELF::Rela> relocations; std::vector<uint8_t> packed; + bool is_32 = sizeof(typename ELF::Addr) == 4; // Initial relocation. AddRelocation<ELF>(0xd1ce0000, 0x11, 0, &relocations); // Two more relocations, 4 byte deltas. @@ -59,16 +60,16 @@ size_t ndx = 0; EXPECT_EQ('A', packed[ndx++]); EXPECT_EQ('P', packed[ndx++]); - EXPECT_EQ('U', packed[ndx++]); + EXPECT_EQ('S', packed[ndx++]); EXPECT_EQ('2', packed[ndx++]); // relocation count EXPECT_EQ(6, packed[ndx++]); - // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d + // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit) EXPECT_EQ(0xfc, packed[ndx++]); EXPECT_EQ(0xff, packed[ndx++]); EXPECT_EQ(0xb7, packed[ndx++]); EXPECT_EQ(0x8e, packed[ndx++]); - EXPECT_EQ(0x0d, packed[ndx++]); + EXPECT_EQ(is_32 ? 0x7d : 0x0d, packed[ndx++]); // first group EXPECT_EQ(3, packed[ndx++]); // size EXPECT_EQ(3, packed[ndx++]); // flags @@ -83,8 +84,11 @@ EXPECT_EQ(ndx, packed.size()); } -TEST(Packer, PackNoAddend) { +TEST(Packer, PackNoAddend32) { DoPackNoAddend<ELF32_traits>(); +} + +TEST(Packer, PackNoAddend64) { DoPackNoAddend<ELF64_traits>(); } @@ -92,18 +96,19 @@ static void DoUnpackNoAddend() { std::vector<typename ELF::Rela> relocations; std::vector<uint8_t> packed; + bool is_32 = sizeof(typename ELF::Addr) == 4; packed.push_back('A'); packed.push_back('P'); - packed.push_back('U'); + packed.push_back('S'); packed.push_back('2'); // relocation count packed.push_back(6); - // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 0d + // base relocation = 0xd1cdfffc -> fc, ff, b7, 8e, 7d/0d (32/64bit) packed.push_back(0xfc); packed.push_back(0xff); packed.push_back(0xb7); packed.push_back(0x8e); - packed.push_back(0x0d); + packed.push_back(is_32 ? 0x7d : 0x0d); // first group packed.push_back(3); // size packed.push_back(3); // flags @@ -131,8 +136,11 @@ EXPECT_EQ(ndx, relocations.size()); } -TEST(Packer, UnpackNoAddend) { +TEST(Packer, UnpackNoAddend32) { DoUnpackNoAddend<ELF32_traits>(); +} + +TEST(Packer, UnpackNoAddend64) { DoUnpackNoAddend<ELF64_traits>(); }
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so index d97ef82..6ac2eef0 100755 --- a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm32_packed.so Binary files differ
diff --git a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so index e44e4597..a2b00391 100755 --- a/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so +++ b/third_party/android_platform/bionic/tools/relocation_packer/test_data/elf_file_unittest_relocs_arm64_packed.so Binary files differ
diff --git a/third_party/android_platform/relocation_packer.gyp b/third_party/android_platform/relocation_packer.gyp index 69136f5..a41253f 100644 --- a/third_party/android_platform/relocation_packer.gyp +++ b/third_party/android_platform/relocation_packer.gyp
@@ -9,7 +9,6 @@ 'bionic/tools/relocation_packer/src/debug.cc', 'bionic/tools/relocation_packer/src/delta_encoder.cc', 'bionic/tools/relocation_packer/src/elf_file.cc', - 'bionic/tools/relocation_packer/src/leb128.cc', 'bionic/tools/relocation_packer/src/packer.cc', 'bionic/tools/relocation_packer/src/sleb128.cc', ], @@ -20,7 +19,6 @@ 'bionic/tools/relocation_packer/src/debug_unittest.cc', 'bionic/tools/relocation_packer/src/delta_encoder_unittest.cc', 'bionic/tools/relocation_packer/src/elf_file_unittest.cc', - 'bionic/tools/relocation_packer/src/leb128_unittest.cc', 'bionic/tools/relocation_packer/src/packer_unittest.cc', 'bionic/tools/relocation_packer/src/sleb128_unittest.cc', 'bionic/tools/relocation_packer/src/run_all_unittests.cc',
diff --git a/third_party/brotli/README.chromium b/third_party/brotli/README.chromium index 73a720e..2a2fe66 100644 --- a/third_party/brotli/README.chromium +++ b/third_party/brotli/README.chromium
@@ -1,6 +1,6 @@ Name: Brotli URL: https://github.com/google/brotli -Version: 9e53d522a34bb8eabfda4a50f7e9da1d1e57a98f +Version: ec03509d6d5d18a57afe1254e713b6787ef1c516 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/brotli/dec/Makefile b/third_party/brotli/dec/Makefile index b033c5f..5a1fcd0 100644 --- a/third_party/brotli/dec/Makefile +++ b/third_party/brotli/dec/Makefile
@@ -2,7 +2,7 @@ include ../shared.mk -CPPFLAGS += -Wall +CFLAGS += -Wall OBJS = bit_reader.o decode.o huffman.o safe_malloc.o state.o streams.o
diff --git a/third_party/brotli/dec/decode.c b/third_party/brotli/dec/decode.c index 8dc55a0..674dbfb 100644 --- a/third_party/brotli/dec/decode.c +++ b/third_party/brotli/dec/decode.c
@@ -86,26 +86,61 @@ return 0; } -static void DecodeMetaBlockLength(BrotliBitReader* br, - int* meta_block_length, - int* input_end, - int* is_uncompressed) { +/* Advances the bit reader position to the next byte boundary and verifies + that any skipped bits are set to zero. */ +static BROTLI_INLINE int JumpToByteBoundary(BrotliBitReader* br) { + uint32_t new_bit_pos = (br->bit_pos_ + 7) & (uint32_t)(~7UL); + uint32_t pad_bits = BrotliReadBits(br, (int)(new_bit_pos - br->bit_pos_)); + return pad_bits == 0; +} + +static int DecodeMetaBlockLength(BrotliBitReader* br, + int* meta_block_length, + int* input_end, + int* is_metadata, + int* is_uncompressed) { int size_nibbles; + int size_bytes; int i; *input_end = (int)BrotliReadBits(br, 1); *meta_block_length = 0; *is_uncompressed = 0; + *is_metadata = 0; if (*input_end && BrotliReadBits(br, 1)) { - return; + return 1; } size_nibbles = (int)BrotliReadBits(br, 2) + 4; - for (i = 0; i < size_nibbles; ++i) { - *meta_block_length |= (int)BrotliReadBits(br, 4) << (i * 4); + if (size_nibbles == 7) { + *is_metadata = 1; + /* Verify reserved bit. */ + if (BrotliReadBits(br, 1) != 0) { + return 0; + } + size_bytes = (int)BrotliReadBits(br, 2); + if (size_bytes == 0) { + return 1; + } + for (i = 0; i < size_bytes; ++i) { + int next_byte = (int)BrotliReadBits(br, 8); + if (i + 1 == size_bytes && size_bytes > 1 && next_byte == 0) { + return 0; + } + *meta_block_length |= next_byte << (i * 8); + } + } else { + for (i = 0; i < size_nibbles; ++i) { + int next_nibble = (int)BrotliReadBits(br, 4); + if (i + 1 == size_nibbles && size_nibbles > 4 && next_nibble == 0) { + return 0; + } + *meta_block_length |= next_nibble << (i * 4); + } } ++(*meta_block_length); - if (!*input_end) { + if (!*input_end && !*is_metadata) { *is_uncompressed = (int)BrotliReadBits(br, 1); } + return 1; } /* Decodes the next Huffman code from bit-stream. */ @@ -156,7 +191,7 @@ const HuffmanCode* p = s->table; uint8_t code_len; if (!BrotliReadMoreInput(br)) { - return BROTLI_RESULT_PARTIAL; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } BrotliFillBitWindow(br); p += (br->val_ >> br->bit_pos_) & 31; @@ -224,7 +259,7 @@ switch(s->sub_state[1]) { case BROTLI_STATE_SUB_NONE: if (!BrotliReadMoreInput(br)) { - return BROTLI_RESULT_PARTIAL; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } s->code_lengths = (uint8_t*)BrotliSafeMalloc((uint64_t)alphabet_size, @@ -250,7 +285,10 @@ } memset(s->code_lengths, 0, (size_t)alphabet_size); for (i = 0; i < num_symbols; ++i) { - symbols[i] = (int)BrotliReadBits(br, max_bits) % alphabet_size; + symbols[i] = (int)BrotliReadBits(br, max_bits); + if (symbols[i] >= alphabet_size) { + return BROTLI_RESULT_ERROR; + } s->code_lengths[symbols[i]] = 2; } s->code_lengths[symbols[0]] = 1; @@ -375,13 +413,6 @@ return val; } -static void MoveToFront(uint8_t* v, uint8_t index) { - uint8_t value = v[index]; - uint8_t i = index; - for (; i; --i) v[i] = v[i - 1]; - v[0] = value; -} - static void InverseMoveToFrontTransform(uint8_t* v, int v_len) { uint8_t mtf[256]; int i; @@ -390,8 +421,12 @@ } for (i = 0; i < v_len; ++i) { uint8_t index = v[i]; - v[i] = mtf[index]; - if (index) MoveToFront(mtf, index); + uint8_t value = mtf[index]; + v[i] = value; + for (; index; --index) { + mtf[index] = mtf[index - 1]; + } + mtf[0] = value; } } @@ -436,7 +471,7 @@ switch(s->sub_state[0]) { case BROTLI_STATE_SUB_NONE: if (!BrotliReadMoreInput(br)) { - return BROTLI_RESULT_PARTIAL; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } *num_htrees = DecodeVarLenUint8(br) + 1; @@ -477,7 +512,7 @@ while (s->context_index < context_map_size) { int code; if (!BrotliReadMoreInput(br)) { - return BROTLI_RESULT_PARTIAL; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } code = ReadSymbol(s->context_map_table, br); if (code == 0) { @@ -612,6 +647,7 @@ int br_pos = s->br.pos_ & BROTLI_IBUF_MASK; uint32_t remaining_bits; int num_read; + int num_written; /* State machine */ for (;;) { @@ -656,13 +692,24 @@ rb_pos += s->nbytes; s->meta_block_remaining_len -= s->nbytes; + s->partially_written = 0; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_1; + /* No break, continue to next state */ + case BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_1: /* If we wrote past the logical end of the ringbuffer, copy the tail of the ringbuffer to its beginning and flush the ringbuffer to the output. */ if (rb_pos >= rb_size) { - if (BrotliWrite(output, s->ringbuffer, (size_t)rb_size) < rb_size) { + num_written = BrotliWrite(output, + s->ringbuffer + s->partially_written, + (size_t)(rb_size - s->partially_written)); + if (num_written < 0) { return BROTLI_RESULT_ERROR; } + s->partially_written += num_written; + if (s->partially_written < rb_size) { + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } rb_pos -= rb_size; s->meta_block_remaining_len += rb_size; memcpy(s->ringbuffer, ringbuffer_end, (size_t)rb_pos); @@ -672,37 +719,66 @@ case BROTLI_STATE_SUB_UNCOMPRESSED_SHORT: while (s->meta_block_remaining_len > 0) { if (!BrotliReadMoreInput(&s->br)) { - return BROTLI_RESULT_PARTIAL; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } s->ringbuffer[rb_pos++] = (uint8_t)BrotliReadBits(&s->br, 8); if (rb_pos == rb_size) { - if (BrotliWrite(output, s->ringbuffer, (size_t)rb_size) < rb_size) { - return BROTLI_RESULT_ERROR; - } - rb_pos = 0; + s->partially_written = 0; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_2; + break; } s->meta_block_remaining_len--; } - s->sub_state[0] = BROTLI_STATE_SUB_NONE; - return BROTLI_RESULT_SUCCESS; + if (s->sub_state[0] == BROTLI_STATE_SUB_UNCOMPRESSED_SHORT) { + s->sub_state[0] = BROTLI_STATE_SUB_NONE; + return BROTLI_RESULT_SUCCESS; + } + /* No break, if state is updated, continue to next state */ + case BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_2: + num_written = BrotliWrite(output, s->ringbuffer + s->partially_written, + (size_t)(rb_size - s->partially_written)); + if (num_written < 0) { + return BROTLI_RESULT_ERROR; + } + s->partially_written += num_written; + if (s->partially_written < rb_size) { + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + rb_pos = 0; + s->meta_block_remaining_len--; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_SHORT; + break; case BROTLI_STATE_SUB_UNCOMPRESSED_FILL: /* If we have more to copy than the remaining size of the ringbuffer, then we first fill the ringbuffer from the input and then flush the ringbuffer to the output */ - while (rb_pos + s->meta_block_remaining_len >= rb_size) { + if (rb_pos + s->meta_block_remaining_len >= rb_size) { s->nbytes = rb_size - rb_pos; if (BrotliRead(s->br.input_, &s->ringbuffer[rb_pos], (size_t)s->nbytes) < s->nbytes) { - return BROTLI_RESULT_PARTIAL; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } - if (BrotliWrite(output, s->ringbuffer, (size_t)rb_size) < s->nbytes) { - return BROTLI_RESULT_ERROR; - } - s->meta_block_remaining_len -= s->nbytes; - rb_pos = 0; + s->partially_written = 0; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_3; + } else { + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_COPY; + break; } - s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_COPY; /* No break, continue to next state */ + case BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_3: + num_written = BrotliWrite(output, s->ringbuffer + s->partially_written, + (size_t)(rb_size - s->partially_written)); + if (num_written < 0) { + return BROTLI_RESULT_ERROR; + } + s->partially_written += num_written; + if (s->partially_written < rb_size) { + return BROTLI_RESULT_NEEDS_MORE_OUTPUT; + } + s->meta_block_remaining_len -= s->nbytes; + rb_pos = 0; + s->sub_state[0] = BROTLI_STATE_SUB_UNCOMPRESSED_FILL; + break; case BROTLI_STATE_SUB_UNCOMPRESSED_COPY: /* Copy straight from the input onto the ringbuffer. The ringbuffer will be flushed to the output at a later time. */ @@ -710,7 +786,7 @@ (size_t)s->meta_block_remaining_len); s->meta_block_remaining_len -= num_read; if (s->meta_block_remaining_len > 0) { - return BROTLI_RESULT_PARTIAL; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } /* Restore the state of the bit reader. */ @@ -719,7 +795,7 @@ /* No break, continue to next state */ case BROTLI_STATE_SUB_UNCOMPRESSED_WARMUP: if (!BrotliWarmupBitReader(&s->br)) { - return BROTLI_RESULT_PARTIAL; + return BROTLI_RESULT_NEEDS_MORE_INPUT; } s->sub_state[0] = BROTLI_STATE_SUB_NONE; return BROTLI_RESULT_SUCCESS; @@ -810,7 +886,7 @@ BrotliResult result; BrotliStateInit(&s); result = BrotliDecompressStreaming(input, output, 1, &s); - if (result == BROTLI_RESULT_PARTIAL) { + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT) { /* Not ok: it didn't finish even though this is a non-streaming function. */ result = BROTLI_RESULT_ERROR; } @@ -854,6 +930,7 @@ BrotliBitReader* br = &s->br; int initial_remaining_len; int bytes_copied; + int num_written; /* We need the slack region for the following reasons: - always doing two 8-byte copies for fast backward copying @@ -866,7 +943,7 @@ /* State machine */ for (;;) { if (result != BROTLI_RESULT_SUCCESS) { - if (result == BROTLI_RESULT_PARTIAL && finish) { + if (result == BROTLI_RESULT_NEEDS_MORE_INPUT && finish) { printf("Unexpected end of input. State: %d\n", s->state); result = BROTLI_RESULT_ERROR; } @@ -895,7 +972,7 @@ /* No break, continue to next state */ case BROTLI_STATE_BITREADER_WARMUP: if (!BrotliWarmupBitReader(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } /* Decode window size. */ @@ -926,10 +1003,11 @@ /* No break, continue to next state */ case BROTLI_STATE_METABLOCK_BEGIN: if (!BrotliReadMoreInput(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } if (s->input_end) { + s->partially_written = 0; s->state = BROTLI_STATE_DONE; break; } @@ -967,19 +1045,36 @@ /* No break, continue to next state */ case BROTLI_STATE_METABLOCK_HEADER_1: if (!BrotliReadMoreInput(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } BROTLI_LOG_UINT(pos); - DecodeMetaBlockLength(br, &s->meta_block_remaining_len, - &s->input_end, &s->is_uncompressed); + if (!DecodeMetaBlockLength(br, + &s->meta_block_remaining_len, + &s->input_end, + &s->is_metadata, + &s->is_uncompressed)) { + result = BROTLI_RESULT_ERROR; + break; + } BROTLI_LOG_UINT(s->meta_block_remaining_len); + if (s->is_metadata) { + if (!JumpToByteBoundary(&s->br)) { + result = BROTLI_RESULT_ERROR; + break; + } + s->state = BROTLI_STATE_METADATA; + break; + } if (s->meta_block_remaining_len == 0) { s->state = BROTLI_STATE_METABLOCK_DONE; break; } if (s->is_uncompressed) { - BrotliSetBitPos(br, (s->br.bit_pos_ + 7) & (uint32_t)(~7UL)); + if (!JumpToByteBoundary(&s->br)) { + result = BROTLI_RESULT_ERROR; + break; + } s->state = BROTLI_STATE_UNCOMPRESSED; break; } @@ -990,6 +1085,9 @@ initial_remaining_len = s->meta_block_remaining_len; /* pos is given as argument since s->pos is only updated at the end. */ result = CopyUncompressedBlockToOutput(output, pos, s); + if (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + break; + } bytes_copied = initial_remaining_len - s->meta_block_remaining_len; pos += bytes_copied; if (bytes_copied > 0) { @@ -1000,6 +1098,17 @@ if (result != BROTLI_RESULT_SUCCESS) break; s->state = BROTLI_STATE_METABLOCK_DONE; break; + case BROTLI_STATE_METADATA: + for (; s->meta_block_remaining_len > 0; --s->meta_block_remaining_len) { + if (!BrotliReadMoreInput(&s->br)) { + result = BROTLI_RESULT_NEEDS_MORE_INPUT; + break; + } + /* Read one byte and ignore it. */ + BrotliReadBits(&s->br, 8); + } + s->state = BROTLI_STATE_METABLOCK_DONE; + break; case BROTLI_STATE_HUFFMAN_CODE_0: if (i >= 3) { BROTLI_LOG_UINT(s->num_block_types[0]); @@ -1041,7 +1150,7 @@ break; case BROTLI_STATE_METABLOCK_HEADER_2: if (!BrotliReadMoreInput(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } s->distance_postfix_bits = (int)BrotliReadBits(br, 2); @@ -1115,7 +1224,7 @@ /* Block decoding is the inner loop, jumping with goto makes it 3% faster */ BlockBegin: if (!BrotliReadMoreInput(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } if (s->meta_block_remaining_len <= 0) { @@ -1164,7 +1273,7 @@ if (s->trivial_literal_context) { while (i < s->insert_length) { if (!BrotliReadMoreInput(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } if (s->block_length[0] == 0) { @@ -1178,19 +1287,19 @@ BROTLI_LOG_UINT(s->literal_htree_index); BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) { - if (BrotliWrite(output, s->ringbuffer, - (size_t)s->ringbuffer_size) < 0) { - result = BROTLI_RESULT_ERROR; - break; - } + s->partially_written = 0; + s->state = BROTLI_STATE_BLOCK_INNER_WRITE; + break; } + /* Modifications to this code shold be reflected in + BROTLI_STATE_BLOCK_INNER_WRITE case */ ++pos; ++i; } } else { while (i < s->insert_length) { if (!BrotliReadMoreInput(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } if (s->block_length[0] == 0) { @@ -1210,18 +1319,18 @@ BROTLI_LOG_UINT(s->literal_htree_index); BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask); if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) { - if (BrotliWrite(output, s->ringbuffer, - (size_t)s->ringbuffer_size) < 0) { - result = BROTLI_RESULT_ERROR; - break; - } + s->partially_written = 0; + s->state = BROTLI_STATE_BLOCK_INNER_WRITE; + break; } + /* Modifications to this code shold be reflected in + BROTLI_STATE_BLOCK_INNER_WRITE case */ ++pos; ++i; } } - - if (result != BROTLI_RESULT_SUCCESS) break; + if (result != BROTLI_RESULT_SUCCESS || + s->state == BROTLI_STATE_BLOCK_INNER_WRITE) break; s->meta_block_remaining_len -= s->insert_length; if (s->meta_block_remaining_len <= 0) { @@ -1236,7 +1345,7 @@ /* No break, go to next state */ case BROTLI_STATE_BLOCK_DISTANCE: if (!BrotliReadMoreInput(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } assert(s->distance_code < 0); @@ -1274,7 +1383,7 @@ /* No break, go to next state */ case BROTLI_STATE_BLOCK_POST: if (!BrotliReadMoreInput(br)) { - result = BROTLI_RESULT_PARTIAL; + result = BROTLI_RESULT_NEEDS_MORE_INPUT; break; } /* Convert the distance code to the actual distance by possibly */ @@ -1314,11 +1423,21 @@ pos += len; s->meta_block_remaining_len -= len; if (s->copy_dst >= s->ringbuffer_end) { - if (BrotliWrite(output, s->ringbuffer, - (size_t)s->ringbuffer_size) < 0) { + s->partially_written = 0; + num_written = BrotliWrite(output, s->ringbuffer, + (size_t)s->ringbuffer_size); + if (num_written < 0) { result = BROTLI_RESULT_ERROR; break; } + s->partially_written += num_written; + if (s->partially_written < s->ringbuffer_size) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + s->state = BROTLI_STATE_BLOCK_POST_WRITE_1; + break; + } + /* Modifications to this code shold be reflected in + BROTLI_STATE_BLOCK_POST_WRITE_1 case */ memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)(s->copy_dst - s->ringbuffer_end)); } @@ -1368,22 +1487,35 @@ s->copy_length = 0; } #endif - + /* Modifications to this loop shold be reflected in + BROTLI_STATE_BLOCK_POST_WRITE_2 case */ for (i = 0; i < s->copy_length; ++i) { s->ringbuffer[pos & s->ringbuffer_mask] = s->ringbuffer[(pos - s->distance) & s->ringbuffer_mask]; if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) { - if (BrotliWrite(output, s->ringbuffer, - (size_t)s->ringbuffer_size) < 0) { + s->partially_written = 0; + num_written = BrotliWrite(output, s->ringbuffer, + (size_t)s->ringbuffer_size); + if (num_written < 0) { result = BROTLI_RESULT_ERROR; break; } + s->partially_written += num_written; + if (s->partially_written < s->ringbuffer_size) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + s->state = BROTLI_STATE_BLOCK_POST_WRITE_2; + break; + } } ++pos; --s->meta_block_remaining_len; } + if (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + break; + } } - + /* No break, continue to next state */ + case BROTLI_STATE_BLOCK_POST_CONTINUE: /* When we get here, we must have inserted at least one literal and */ /* made a copy of at least length two, therefore accessing the last 2 */ /* bytes is valid. */ @@ -1391,6 +1523,62 @@ s->prev_byte2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask]; s->state = BROTLI_STATE_BLOCK_BEGIN; goto BlockBegin; + case BROTLI_STATE_BLOCK_INNER_WRITE: + case BROTLI_STATE_BLOCK_POST_WRITE_1: + case BROTLI_STATE_BLOCK_POST_WRITE_2: + num_written = BrotliWrite( + output, s->ringbuffer + s->partially_written, + (size_t)(s->ringbuffer_size - s->partially_written)); + if (num_written < 0) { + result = BROTLI_RESULT_ERROR; + break; + } + s->partially_written += num_written; + if (s->partially_written < s->ringbuffer_size) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + break; + } + if (s->state == BROTLI_STATE_BLOCK_POST_WRITE_1) { + memcpy(s->ringbuffer, s->ringbuffer_end, + (size_t)(s->copy_dst - s->ringbuffer_end)); + s->state = BROTLI_STATE_BLOCK_POST_CONTINUE; + } else if (s->state == BROTLI_STATE_BLOCK_POST_WRITE_2) { + /* The tail of "i < s->copy_length" loop. */ + ++pos; + --s->meta_block_remaining_len; + ++i; + /* Reenter the loop. */ + for (; i < s->copy_length; ++i) { + s->ringbuffer[pos & s->ringbuffer_mask] = + s->ringbuffer[(pos - s->distance) & s->ringbuffer_mask]; + if ((pos & s->ringbuffer_mask) == s->ringbuffer_mask) { + s->partially_written = 0; + num_written = BrotliWrite(output, s->ringbuffer, + (size_t)s->ringbuffer_size); + if (num_written < 0) { + result = BROTLI_RESULT_ERROR; + break; + } + s->partially_written += num_written; + if (s->partially_written < s->ringbuffer_size) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + break; + } + } + ++pos; + --s->meta_block_remaining_len; + } + if (result == BROTLI_RESULT_NEEDS_MORE_OUTPUT) { + break; + } + s->state = BROTLI_STATE_BLOCK_POST_CONTINUE; + } else { /* BROTLI_STATE_BLOCK_INNER_WRITE */ + /* The tail of "i < s->insert_length" loop. */ + ++pos; + ++i; + s->state = BROTLI_STATE_BLOCK_INNER; + } + break; case BROTLI_STATE_METABLOCK_DONE: if (s->context_modes != 0) { free(s->context_modes); @@ -1413,10 +1601,20 @@ break; case BROTLI_STATE_DONE: if (s->ringbuffer != 0) { - if (BrotliWrite(output, s->ringbuffer, - (size_t)(pos & s->ringbuffer_mask)) < 0) { + num_written = BrotliWrite( + output, s->ringbuffer + s->partially_written, + (size_t)((pos & s->ringbuffer_mask) - s->partially_written)); + if (num_written < 0) { result = BROTLI_RESULT_ERROR; } + s->partially_written += num_written; + if (s->partially_written < (pos & s->ringbuffer_mask)) { + result = BROTLI_RESULT_NEEDS_MORE_OUTPUT; + break; + } + } + if (!JumpToByteBoundary(&s->br)) { + result = BROTLI_RESULT_ERROR; } return result; default:
diff --git a/third_party/brotli/dec/decode.h b/third_party/brotli/dec/decode.h index 9efd34a..834a7b5 100644 --- a/third_party/brotli/dec/decode.h +++ b/third_party/brotli/dec/decode.h
@@ -32,7 +32,9 @@ /* Successfully completely done */ BROTLI_RESULT_SUCCESS = 1, /* Partially done, but must be called again with more input */ - BROTLI_RESULT_PARTIAL = 2 + BROTLI_RESULT_NEEDS_MORE_INPUT = 2, + /* Partially done, but must be called again with more output */ + BROTLI_RESULT_NEEDS_MORE_OUTPUT = 3 } BrotliResult; /* Sets *decoded_size to the decompressed size of the given encoded stream. */
diff --git a/third_party/brotli/dec/state.h b/third_party/brotli/dec/state.h index 3b985ec0..e5d6b5a5 100644 --- a/third_party/brotli/dec/state.h +++ b/third_party/brotli/dec/state.h
@@ -39,7 +39,12 @@ BROTLI_STATE_BLOCK_DISTANCE = 15, BROTLI_STATE_BLOCK_POST = 16, BROTLI_STATE_UNCOMPRESSED = 17, + BROTLI_STATE_METADATA = 18, + BROTLI_STATE_BLOCK_INNER_WRITE = 19, BROTLI_STATE_METABLOCK_DONE = 20, + BROTLI_STATE_BLOCK_POST_WRITE_1 = 21, + BROTLI_STATE_BLOCK_POST_WRITE_2 = 22, + BROTLI_STATE_BLOCK_POST_CONTINUE = 23, BROTLI_STATE_HUFFMAN_CODE_0 = 30, BROTLI_STATE_HUFFMAN_CODE_1 = 31, BROTLI_STATE_HUFFMAN_CODE_2 = 32, @@ -51,6 +56,9 @@ BROTLI_STATE_SUB_UNCOMPRESSED_FILL = 52, BROTLI_STATE_SUB_UNCOMPRESSED_COPY = 53, BROTLI_STATE_SUB_UNCOMPRESSED_WARMUP = 54, + BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_1 = 55, + BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_2 = 56, + BROTLI_STATE_SUB_UNCOMPRESSED_WRITE_3 = 57, BROTLI_STATE_SUB_HUFFMAN_LENGTH_BEGIN = 60, BROTLI_STATE_SUB_HUFFMAN_LENGTH_SYMBOLS = 61, BROTLI_STATE_SUB_HUFFMAN_DONE = 62, @@ -91,6 +99,7 @@ int trivial_literal_context; int meta_block_remaining_len; + int is_metadata; int is_uncompressed; int block_length[3]; int block_type[3]; @@ -131,6 +140,9 @@ /* For CopyUncompressedBlockToOutput */ int nbytes; + /* For partial write operations */ + int partially_written; + /* For HuffmanTreeGroupDecode */ int htrees_decoded;
diff --git a/third_party/brotli/dec/streams.c b/third_party/brotli/dec/streams.c index 623d417..b33f7a4 100644 --- a/third_party/brotli/dec/streams.c +++ b/third_party/brotli/dec/streams.c
@@ -51,8 +51,9 @@ int BrotliMemOutputFunction(void* data, const uint8_t* buf, size_t count) { BrotliMemOutput* output = (BrotliMemOutput*)data; - if (output->pos + count > output->length) { - return -1; + size_t limit = output->length - output->pos; + if (count > limit) { + count = limit; } memcpy(output->buffer + output->pos, buf, count); output->pos += count;
diff --git a/third_party/closure_compiler/externs/autofill_private.js b/third_party/closure_compiler/externs/autofill_private.js new file mode 100644 index 0000000..84d25216 --- /dev/null +++ b/third_party/closure_compiler/externs/autofill_private.js
@@ -0,0 +1,171 @@ +// 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 Externs generated from namespace: autofillPrivate */ + +/** + * @const + */ +chrome.autofillPrivate = {}; + +/** + * @enum {string} + * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressField + */ +chrome.autofillPrivate.AddressField = { + FULL_NAME: 'FULL_NAME', + COMPANY_NAME: 'COMPANY_NAME', + ADDRESS_LINES: 'ADDRESS_LINES', + ADDRESS_LEVEL_1: 'ADDRESS_LEVEL_1', + ADDRESS_LEVEL_2: 'ADDRESS_LEVEL_2', + ADDRESS_LEVEL_3: 'ADDRESS_LEVEL_3', + POSTAL_CODE: 'POSTAL_CODE', + SORTING_CODE: 'SORTING_CODE', + COUNTRY_CODE: 'COUNTRY_CODE', +}; + +/** + * @typedef {{ + * summaryLabel: string, + * summarySublabel: (string|undefined), + * isLocal: (boolean|undefined), + * isCached: (boolean|undefined) + * }} + * @see https://developer.chrome.com/extensions/autofillPrivate#type-AutofillMetadata + */ +var AutofillMetadata; + +/** + * @typedef {{ + * guid: (string|undefined), + * fullNames: (!Array<string>|undefined), + * companyName: (string|undefined), + * addressLines: (string|undefined), + * addressLevel1: (string|undefined), + * addressLevel2: (string|undefined), + * addressLevel3: (string|undefined), + * postalCode: (string|undefined), + * sortingCode: (string|undefined), + * country: (string|undefined), + * phoneNumbers: (!Array<string>|undefined), + * emailAddresses: (!Array<string>|undefined), + * languageCode: (string|undefined), + * metadata: (AutofillMetadata|undefined) + * }} + * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressEntry + */ +var AddressEntry; + +/** + * @typedef {{ + * field: !chrome.autofillPrivate.AddressField, + * fieldName: string, + * isLongField: boolean + * }} + * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressComponent + */ +var AddressComponent; + +/** + * @typedef {{ + * components: !Array<AddressComponent>, + * languageCode: string + * }} + * @see https://developer.chrome.com/extensions/autofillPrivate#type-AddressComponents + */ +var AddressComponents; + +/** + * @typedef {{ + * guid: (string|undefined), + * name: (string|undefined), + * cardNumber: (string|undefined), + * expirationMonth: (string|undefined), + * expirationYear: (string|undefined), + * metadata: (AutofillMetadata|undefined) + * }} + * @see https://developer.chrome.com/extensions/autofillPrivate#type-CreditCardEntry + */ +var CreditCardEntry; + +/** + * @typedef {{ + * phoneNumbers: !Array<string>, + * indexOfNewNumber: number, + * countryCode: string + * }} + * @see https://developer.chrome.com/extensions/autofillPrivate#type-ValidatePhoneParams + */ +var ValidatePhoneParams; + +/** + * Saves the given address. If |address| has an empty string as its ID, it will + * be assigned a new one and added as a new entry. + * @param {AddressEntry} address The address entry to save. + * @see https://developer.chrome.com/extensions/autofillPrivate#method-saveAddress + */ +chrome.autofillPrivate.saveAddress = function(address) {}; + +/** + * Gets the address components for a given country code. + * @param {string} countryCode The country code for which to fetch the + * components. + * @param {function(AddressComponents):void} callback Callback which will be + * called with components. + * @see https://developer.chrome.com/extensions/autofillPrivate#method-getAddressComponents + */ +chrome.autofillPrivate.getAddressComponents = function(countryCode, callback) {}; + +/** + * Saves the given credit card. If |card| has an empty string as its ID, it will + * be assigned a new one and added as a new entry. + * @param {CreditCardEntry} card The card entry to save. + * @see https://developer.chrome.com/extensions/autofillPrivate#method-saveCreditCard + */ +chrome.autofillPrivate.saveCreditCard = function(card) {}; + +/** + * Removes the entry (address or credit card) with the given ID. + * @param {string} guid ID of the entry to remove. + * @see https://developer.chrome.com/extensions/autofillPrivate#method-removeEntry + */ +chrome.autofillPrivate.removeEntry = function(guid) {}; + +/** + * Validates a newly-added phone number and invokes the callback with a list of + * validated numbers. Note that if the newly-added number was invalid, it will + * not be returned in the list of valid numbers. + * @param {ValidatePhoneParams} params The parameters to this function. + * @param {function(!Array<string>):void} callback Callback which will be called + * with validated phone numbers. + * @return {!Array<string>} + * @see https://developer.chrome.com/extensions/autofillPrivate#method-validatePhoneNumbers + */ +chrome.autofillPrivate.validatePhoneNumbers = function(params, callback) {}; + +/** + * Clears the data associated with a wallet card which was saved locally so that + * the saved copy is masked (e.g., "Card ending in 1234"). + * @param {string} guid GUID of the credit card to mask. + * @see https://developer.chrome.com/extensions/autofillPrivate#method-maskCreditCard + */ +chrome.autofillPrivate.maskCreditCard = function(guid) {}; + +/** + * Fired when the address list has changed, meaning that an entry has been + * added, removed, or changed. |entries| The updated list of entries. + * @type {!ChromeEvent} + * @see https://developer.chrome.com/extensions/autofillPrivate#event-onAddressListChanged + */ +chrome.autofillPrivate.onAddressListChanged; + +/** + * Fired when the credit card list has changed, meaning that an entry has been + * added, removed, or changed. |entries| The updated list of entries. + * @type {!ChromeEvent} + * @see https://developer.chrome.com/extensions/autofillPrivate#event-onCreditCardListChanged + */ +chrome.autofillPrivate.onCreditCardListChanged; + +
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js index d1736ca0..761dc6c 100644 --- a/third_party/closure_compiler/externs/file_manager_private.js +++ b/third_party/closure_compiler/externs/file_manager_private.js
@@ -201,6 +201,16 @@ var DeviceEvent; /** + * @typedef {{ + * extensionId: string, + * name: string, + * canConfigure: boolean, + * canAdd: boolean + * }} + */ +var ProvidingExtension; + +/** * @const */ chrome.fileManagerPrivate = {}; @@ -580,6 +590,30 @@ */ chrome.fileManagerPrivate.isPiexLoaderEnabled = function(callback) {}; +/** + * Returns list of available providing extensions. + * @param {function(!Array<!ProvidingExtension>)} callback + */ +chrome.fileManagerPrivate.getProvidingExtensions = function(callback) {}; + +/** + * Requests adding a new provided file system. If not possible, then an error + * via chrome.runtime.lastError is returned. + * @param {string} extensionId + * @param {function()} callback + */ +chrome.fileManagerPrivate.addProvidedFileSystem = + function(extensionId, callback) {}; + +/** + * Requests configuring an existing file system. If not possible, then returns + * an error via chrome.runtime.lastError. + * @param {string} volumeId + * @param {function()} callback + */ +chrome.fileManagerPrivate.configureProvidedFileSystem = + function(volumeId, callback) {}; + /** @type {!ChromeEvent} */ chrome.fileManagerPrivate.onMountCompleted;
diff --git a/third_party/closure_compiler/externs/search_engines_private.js b/third_party/closure_compiler/externs/search_engines_private.js new file mode 100644 index 0000000..8d6bedd --- /dev/null +++ b/third_party/closure_compiler/externs/search_engines_private.js
@@ -0,0 +1,47 @@ +search_engines_private_externs.js + +// 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 Externs generated from namespace: searchEnginesPrivate */ + +/** + * @const + */ +chrome.searchEnginesPrivate = {}; + +/** + * @typedef {{ + * guid: string, + * name: string, + * isSelected: (boolean|undefined) + * }} + * @see https://developer.chrome.com/extensions/searchEnginesPrivate#type-SearchEngine + */ +var SearchEngine; + +/** + * Gets a list of the "default” search engines. Exactly one of the values + * should have default == true. + * @param {function(!Array<SearchEngine>):void} callback + * @see https://developer.chrome.com/extensions/searchEnginesPrivate#method-getDefaultSearchEngines + */ +chrome.searchEnginesPrivate.getDefaultSearchEngines = function(callback) {}; + +/** + * Sets the search engine with the given GUID as the selected default. + * @param {string} guid + * @see https://developer.chrome.com/extensions/searchEnginesPrivate#method-setSelectedSearchEngine + */ +chrome.searchEnginesPrivate.setSelectedSearchEngine = function(guid) {}; + +/** + * Fires when the list of default search engines changes or when the user + * selects a preferred default search engine. + * @type {!ChromeEvent} + * @see https://developer.chrome.com/extensions/searchEnginesPrivate#event-onDefaultSearchEnginesChanged + */ +chrome.searchEnginesPrivate.onDefaultSearchEnginesChanged; + +
diff --git a/third_party/freetype2/README.chromium b/third_party/freetype2/README.chromium index 9442685d..f1afa52 100644 --- a/third_party/freetype2/README.chromium +++ b/third_party/freetype2/README.chromium
@@ -1,6 +1,6 @@ Name: freetype2 URL: git://git.sv.nongnu.org/freetype/freetype2.git -Version: 2.4.8-1ubuntu2.1 +Version: 2.4.8-1ubuntu2.2 Security Critical: no License: BSD License File: NOT_SHIPPED @@ -10,10 +10,22 @@ This mirrors the version of Freetype2 that was distributed with Ubuntu Precise (Version 2.4.8, git hash 9d7f0957fbd10fdbabf9815e37857a910ad4f4ac, plus applicable debian/patches-freetype as seen in -https://launchpad.net/ubuntu/lucid/+source/freetype ). On Ubuntu Precise -this code should be the same as the result of +https://launchpad.net/ubuntu/lucid/+source/freetype ). -apt-get source freetype && cd freetype-2.4.8/ && ./debian/rules patch +To get the code and patches: + +sudo apt-add-repository -s "deb http://archive.ubuntu.com/ubuntu precise-security main" +sudo apt-key update +sudo apt-get update +apt-get source -t precise freetype=2.4.8-1ubuntu2.2 + +and then to apply the patches (quilt): + +cd freetype-2.4.8/ +./debian/rules patch + +The tree produced by this should match the tree in this repo on the +chromium/ubuntu/precise branch. The build files should approximate the output of
diff --git a/third_party/libevent/README.chromium b/third_party/libevent/README.chromium index a3e5c6e..939a3539 100644 --- a/third_party/libevent/README.chromium +++ b/third_party/libevent/README.chromium
@@ -24,3 +24,5 @@ nacl_nonsfi/random.c is also added to provide the random() function, which is missing in the newlib-based PNaCl toolchain. 8) Apply https://github.com/libevent/libevent/commit/ea6b1df +9) Stub out signal.c for nacl_helper_nonsfi. socketpair() will be prohibited + by sandbox in nacl_helper_nonsfi.
diff --git a/third_party/libevent/libevent_nacl_nonsfi.gyp b/third_party/libevent/libevent_nacl_nonsfi.gyp index 37a78ad6..2999ceb 100644 --- a/third_party/libevent/libevent_nacl_nonsfi.gyp +++ b/third_party/libevent/libevent_nacl_nonsfi.gyp
@@ -19,11 +19,11 @@ 'evutil.c', 'log.c', 'poll.c', - 'signal.c', 'strlcpy.c', 'nacl_nonsfi/config.h', 'nacl_nonsfi/event-config.h', 'nacl_nonsfi/random.c', + 'nacl_nonsfi/signal_stub.c', ], 'defines': [ 'HAVE_CONFIG_H',
diff --git a/third_party/libevent/nacl_nonsfi/signal_stub.c b/third_party/libevent/nacl_nonsfi/signal_stub.c new file mode 100644 index 0000000..8049030 --- /dev/null +++ b/third_party/libevent/nacl_nonsfi/signal_stub.c
@@ -0,0 +1,48 @@ +/* + * 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. + */ + +/* + * In nacl_helper_nonsfi, socketpair() is unavailable. In libevent, it is used + * to notify of a signal handler invocation, which is unused in + * nacl_helper_nonsfi. Unfortunately, there is no macro to disable the feature, + * so we stub out the signal module entirely. + */ + + +#include <signal.h> +#include <stdlib.h> +#include <sys/queue.h> + +/* config.h must be included before any other libevent header is included. */ +#include "config.h" + +#include "third_party/libevent/event-internal.h" +#include "third_party/libevent/event.h" +#include "third_party/libevent/evsignal.h" + + +struct event_base *evsignal_base = 0; + +int evsignal_init(struct event_base *base) { + /* Do nothing, and return success. */ + return 0; +} + +void evsignal_process(struct event_base *base) { +} + +int evsignal_add(struct event *event) { + /* Do nothing, and return an error. */ + return -1; +} + +int evsignal_del(struct event *event) { + /* Do nothing, and return an error. */ + return -1; +} + +void evsignal_dealloc(struct event_base *base) { +}
diff --git a/third_party/libjingle/BUILD.gn b/third_party/libjingle/BUILD.gn index f3991238..ade2f66 100644 --- a/third_party/libjingle/BUILD.gn +++ b/third_party/libjingle/BUILD.gn
@@ -491,6 +491,7 @@ public_configs = [ ":jingle_public_configs" ] deps = [ + ":libjingle", "//third_party/libsrtp", "//third_party/webrtc/modules/media_file", "//third_party/webrtc/modules/video_capture", @@ -530,6 +531,8 @@ configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ + # TODO(GYP): crbug.com/481633. Consider depending on :libjingle_webrtc + # instead. ":libjingle_webrtc_common", "//third_party/webrtc", "//third_party/webrtc/system_wrappers",
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium index 50c79fc..f914b6d 100644 --- a/third_party/libjingle/README.chromium +++ b/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@ Name: libjingle URL: http://code.google.com/p/webrtc/ Version: unknown -Revision: 9040 +Revision: 9081 License: BSD License File: source/talk/COPYING Security Critical: yes
diff --git a/third_party/mojo/mojo_public.gyp b/third_party/mojo/mojo_public.gyp index 683791d..673e1c4 100644 --- a/third_party/mojo/mojo_public.gyp +++ b/third_party/mojo/mojo_public.gyp
@@ -127,6 +127,8 @@ 'src/mojo/public/cpp/bindings/lib/validate_params.h', 'src/mojo/public/cpp/bindings/lib/validation_errors.cc', 'src/mojo/public/cpp/bindings/lib/validation_errors.h', + 'src/mojo/public/cpp/bindings/lib/validation_util.cc', + 'src/mojo/public/cpp/bindings/lib/validation_util.h', ], }, { @@ -155,9 +157,14 @@ 'src/mojo/public/cpp/environment/lib/default_async_waiter.h', 'src/mojo/public/cpp/environment/lib/default_logger.cc', 'src/mojo/public/cpp/environment/lib/default_logger.h', + 'src/mojo/public/cpp/environment/lib/default_task_tracker.cc', + 'src/mojo/public/cpp/environment/lib/default_task_tracker.h', 'src/mojo/public/cpp/environment/lib/environment.cc', 'src/mojo/public/cpp/environment/lib/logging.cc', + 'src/mojo/public/cpp/environment/lib/scoped_task_tracking.cc', + 'src/mojo/public/cpp/environment/lib/scoped_task_tracking.h', 'src/mojo/public/cpp/environment/logging.h', + 'src/mojo/public/cpp/environment/task_tracker.h', ], 'include_dirs': [ '../..',
diff --git a/third_party/mojo/src/mojo/public/VERSION b/third_party/mojo/src/mojo/public/VERSION index 686ad23f..d6b3e50c 100644 --- a/third_party/mojo/src/mojo/public/VERSION +++ b/third_party/mojo/src/mojo/public/VERSION
@@ -1 +1 @@ -8563c3d4162bd74e96783e823e076e99869d7385 \ No newline at end of file +e7270700d671fa8e458b4d8c9e47f7bcfb65da0b \ No newline at end of file
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn b/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn index f6a9b1bb..7de82a5e4 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn +++ b/third_party/mojo/src/mojo/public/cpp/bindings/BUILD.gn
@@ -27,6 +27,7 @@ "lib/filter_chain.h", "lib/fixed_buffer.cc", "lib/fixed_buffer.h", + "lib/interface_ptr_internal.h", "lib/map_data_internal.h", "lib/map_internal.h", "lib/map_serialization.h", @@ -48,6 +49,8 @@ "lib/validate_params.h", "lib/validation_errors.cc", "lib/validation_errors.h", + "lib/validation_util.cc", + "lib/validation_util.h", "map.h", "message.h", "message_filter.h",
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc index 257d129..9bfbd69 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc +++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.cc
@@ -4,8 +4,6 @@ #include "mojo/public/cpp/bindings/lib/bindings_serialization.h" -#include "mojo/public/cpp/bindings/lib/bounds_checker.h" -#include "mojo/public/cpp/bindings/lib/validation_errors.h" #include "mojo/public/cpp/environment/logging.h" namespace mojo { @@ -53,12 +51,6 @@ return reinterpret_cast<const char*>(offset) + *offset; } -bool ValidateEncodedPointer(const uint64_t* offset) { - // Cast to uintptr_t so overflow behavior is well defined. - return reinterpret_cast<uintptr_t>(offset) + *offset >= - reinterpret_cast<uintptr_t>(offset); -} - void EncodeHandle(Handle* handle, std::vector<Handle>* handles) { if (handle->is_valid()) { handles->push_back(*handle); @@ -86,31 +78,5 @@ DecodeHandle(&data->handle, handles); } -bool ValidateStructHeaderAndClaimMemory(const void* data, - BoundsChecker* bounds_checker) { - if (!IsAligned(data)) { - ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); - return false; - } - if (!bounds_checker->IsValidRange(data, sizeof(StructHeader))) { - ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - - const StructHeader* header = static_cast<const StructHeader*>(data); - - if (header->num_bytes < sizeof(StructHeader)) { - ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); - return false; - } - - if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { - ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); - return false; - } - - return true; -} - } // namespace internal } // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h index 34046a54..609a380e5 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h +++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/bindings_serialization.h
@@ -14,8 +14,6 @@ namespace mojo { namespace internal { -class BoundsChecker; - // Please note that this is a different value than |mojo::kInvalidHandleValue|, // which is the "decoded" invalid handle. const MojoHandle kEncodedInvalidHandleValue = static_cast<MojoHandle>(-1); @@ -43,10 +41,6 @@ *ptr = reinterpret_cast<T*>(const_cast<void*>(DecodePointerRaw(offset))); } -// Checks whether decoding the pointer will overflow and produce a pointer -// smaller than |offset|. -bool ValidateEncodedPointer(const uint64_t* offset); - // Handles are encoded as indices into a vector of handles. These functions // manipulate the value of |handle|, mapping it to and from an index. @@ -74,16 +68,6 @@ obj->ptr->DecodePointersAndHandles(handles); } -// Validates that |data| contains a valid struct header, in terms of alignment -// and size (i.e., the |num_bytes| field of the header is sufficient for storing -// the header itself). Besides, it checks that the memory range -// [data, data + num_bytes) is not marked as occupied by other objects in -// |bounds_checker|. On success, the memory range is marked as occupied. -// Note: Does not verify |version| or that |num_bytes| is correct for the -// claimed version. -bool ValidateStructHeaderAndClaimMemory(const void* data, - BoundsChecker* bounds_checker); - template <typename T> inline void InterfacePointerToData(InterfacePtr<T> input, Interface_Data* output) {
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h index cf0d5cc..97554b7 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h +++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_data_internal.h
@@ -8,6 +8,7 @@ #include "mojo/public/cpp/bindings/lib/array_internal.h" #include "mojo/public/cpp/bindings/lib/validate_params.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" +#include "mojo/public/cpp/bindings/lib/validation_util.h" namespace mojo { namespace internal {
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_serialization.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_serialization.h index 21567792..632da5d 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_serialization.h +++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/map_serialization.h
@@ -27,11 +27,13 @@ template <typename MapType, typename DataType, - bool kValueIsMoveOnlyType = IsMoveOnlyType<MapType>::value> + bool value_is_move_only_type = IsMoveOnlyType<MapType>::value, + bool is_union = + IsUnionDataType<typename RemovePointer<DataType>::type>::value> struct MapSerializer; template <typename MapType, typename DataType> -struct MapSerializer<MapType, DataType, false> { +struct MapSerializer<MapType, DataType, false, false> { static size_t GetBaseArraySize(size_t count) { return Align(count * sizeof(DataType)); } @@ -39,7 +41,7 @@ }; template <> -struct MapSerializer<bool, bool, false> { +struct MapSerializer<bool, bool, false, false> { static size_t GetBaseArraySize(size_t count) { return Align((count + 7) / 8); } @@ -47,7 +49,7 @@ }; template <typename H> -struct MapSerializer<ScopedHandleBase<H>, H, true> { +struct MapSerializer<ScopedHandleBase<H>, H, true, false> { static size_t GetBaseArraySize(size_t count) { return Align(count * sizeof(H)); } @@ -61,7 +63,8 @@ S, typename EnableIf<IsPointer<typename WrapperTraits<S>::DataType>::value, typename WrapperTraits<S>::DataType>::type, - true> { + true, + false> { typedef typename RemovePointer<typename WrapperTraits<S>::DataType>::type S_Data; static size_t GetBaseArraySize(size_t count) { @@ -70,8 +73,18 @@ static size_t GetItemSize(const S& item) { return GetSerializedSize_(item); } }; +template <typename U, typename U_Data> +struct MapSerializer<U, U_Data*, true, true> { + static size_t GetBaseArraySize(size_t count) { + return count * sizeof(U_Data); + } + static size_t GetItemSize(const U& item) { + return GetSerializedSize_(item, true); + } +}; + template <> -struct MapSerializer<String, String_Data*, false> { +struct MapSerializer<String, String_Data*, false, false> { static size_t GetBaseArraySize(size_t count) { return count * sizeof(StringPointer); }
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc index 0870d61..ff507f3 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc +++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/message_header_validator.cc
@@ -4,9 +4,9 @@ #include "mojo/public/cpp/bindings/lib/message_header_validator.h" -#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" #include "mojo/public/cpp/bindings/lib/bounds_checker.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" +#include "mojo/public/cpp/bindings/lib/validation_util.h" namespace mojo { namespace internal {
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_util.cc b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_util.cc new file mode 100644 index 0000000..5614cca4 --- /dev/null +++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_util.cc
@@ -0,0 +1,74 @@ +// 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/validation_util.h" + +#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" +#include "mojo/public/cpp/bindings/lib/message_internal.h" +#include "mojo/public/cpp/bindings/lib/validation_errors.h" + +namespace mojo { +namespace internal { + +bool ValidateEncodedPointer(const uint64_t* offset) { + // Cast to uintptr_t so overflow behavior is well defined. + return reinterpret_cast<uintptr_t>(offset) + *offset >= + reinterpret_cast<uintptr_t>(offset); +} + +bool ValidateStructHeaderAndClaimMemory(const void* data, + BoundsChecker* bounds_checker) { + if (!IsAligned(data)) { + ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); + return false; + } + if (!bounds_checker->IsValidRange(data, sizeof(StructHeader))) { + ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); + return false; + } + + const StructHeader* header = static_cast<const StructHeader*>(data); + + if (header->num_bytes < sizeof(StructHeader)) { + ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); + return false; + } + + if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { + ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); + return false; + } + + return true; +} + +bool ValidateMessageIsRequestWithoutResponse(const Message* message) { + if (message->has_flag(kMessageIsResponse) || + message->has_flag(kMessageExpectsResponse)) { + ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); + return false; + } + return true; +} + +bool ValidateMessageIsRequestExpectingResponse(const Message* message) { + if (message->has_flag(kMessageIsResponse) || + !message->has_flag(kMessageExpectsResponse)) { + ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); + return false; + } + return true; +} + +bool ValidateMessageIsResponse(const Message* message) { + if (message->has_flag(kMessageExpectsResponse) || + !message->has_flag(kMessageIsResponse)) { + ReportValidationError(VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); + return false; + } + return true; +} + +} // namespace internal +} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_util.h b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_util.h new file mode 100644 index 0000000..1b80a5b1 --- /dev/null +++ b/third_party/mojo/src/mojo/public/cpp/bindings/lib/validation_util.h
@@ -0,0 +1,48 @@ +// 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_VALIDATION_UTIL_H_ +#define MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_ + +#include <stdint.h> + +#include "mojo/public/cpp/bindings/lib/bounds_checker.h" +#include "mojo/public/cpp/bindings/message.h" + +namespace mojo { +namespace internal { + +// Checks whether decoding the pointer will overflow and produce a pointer +// smaller than |offset|. +bool ValidateEncodedPointer(const uint64_t* offset); + +// Validates that |data| contains a valid struct header, in terms of alignment +// and size (i.e., the |num_bytes| field of the header is sufficient for storing +// the header itself). Besides, it checks that the memory range +// [data, data + num_bytes) is not marked as occupied by other objects in +// |bounds_checker|. On success, the memory range is marked as occupied. +// Note: Does not verify |version| or that |num_bytes| is correct for the +// claimed version. +bool ValidateStructHeaderAndClaimMemory(const void* data, + BoundsChecker* bounds_checker); + +// Validates that the message is a request which doesn't expect a response. +bool ValidateMessageIsRequestWithoutResponse(const Message* message); +// Validates that the message is a request expecting a response. +bool ValidateMessageIsRequestExpectingResponse(const Message* message); +// Validates that the message is a response. +bool ValidateMessageIsResponse(const Message* message); + +// Validates that the message payload is a valid struct of type ParamsType. +template <typename ParamsType> +bool ValidateMessagePayload(const Message* message) { + BoundsChecker bounds_checker(message->payload(), message->payload_num_bytes(), + message->handles()->size()); + return ParamsType::Validate(message->payload(), &bounds_checker); +} + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_VALIDATION_UTIL_H_
diff --git a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc index 0803b99..5017d97 100644 --- a/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_unittest.cc +++ b/third_party/mojo/src/mojo/public/cpp/bindings/tests/union_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 <vector> #include "mojo/public/cpp/bindings/array.h" #include "mojo/public/cpp/bindings/lib/array_internal.h" #include "mojo/public/cpp/bindings/lib/array_serialization.h" @@ -524,5 +525,300 @@ free(raw_buf); } +// TODO(azani): Move back in map_unittest.cc when possible. +// Map Tests +TEST(UnionTest, PodUnionInMap) { + SmallStructPtr small_struct(SmallStruct::New()); + small_struct->pod_union_map = Map<String, PodUnionPtr>(); + small_struct->pod_union_map.insert("one", PodUnion::New()); + small_struct->pod_union_map.insert("two", PodUnion::New()); + + small_struct->pod_union_map["one"]->set_f_int8(8); + small_struct->pod_union_map["two"]->set_f_int16(16); + + EXPECT_EQ(8, small_struct->pod_union_map["one"]->get_f_int8()); + EXPECT_EQ(16, small_struct->pod_union_map["two"]->get_f_int16()); +} + +TEST(UnionTest, PodUnionInMapSerialization) { + Environment environment; + Map<String, PodUnionPtr> map; + map.insert("one", PodUnion::New()); + map.insert("two", PodUnion::New()); + + map["one"]->set_f_int8(8); + map["two"]->set_f_int16(16); + + size_t size = GetSerializedSize_(map); + EXPECT_EQ(120U, size); + + mojo::internal::FixedBuffer buf(size); + mojo::internal::Map_Data<mojo::internal::String_Data*, + internal::PodUnion_Data>* data; + mojo::internal::ArrayValidateParams validate_params(0, false, nullptr); + SerializeMap_(map.Pass(), &buf, &data, &validate_params); + + Map<String, PodUnionPtr> map2; + Deserialize_(data, &map2); + + EXPECT_EQ(8, map2["one"]->get_f_int8()); + EXPECT_EQ(16, map2["two"]->get_f_int16()); +} + +TEST(UnionTest, PodUnionInMapSerializationWithNull) { + Environment environment; + Map<String, PodUnionPtr> map; + map.insert("one", PodUnion::New()); + map.insert("two", nullptr); + + map["one"]->set_f_int8(8); + + size_t size = GetSerializedSize_(map); + EXPECT_EQ(120U, size); + + mojo::internal::FixedBuffer buf(size); + mojo::internal::Map_Data<mojo::internal::String_Data*, + internal::PodUnion_Data>* data; + mojo::internal::ArrayValidateParams validate_params(0, true, nullptr); + SerializeMap_(map.Pass(), &buf, &data, &validate_params); + + Map<String, PodUnionPtr> map2; + Deserialize_(data, &map2); + + EXPECT_EQ(8, map2["one"]->get_f_int8()); + EXPECT_TRUE(map2["two"].is_null()); +} + +TEST(UnionTest, StructInUnionGetterSetterPasser) { + DummyStructPtr dummy(DummyStruct::New()); + dummy->f_int8 = 8; + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_dummy(dummy.Pass()); + + EXPECT_EQ(8, obj->get_f_dummy()->f_int8); +} + +TEST(UnionTest, StructInUnionSerialization) { + Environment environment; + DummyStructPtr dummy(DummyStruct::New()); + dummy->f_int8 = 8; + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_dummy(dummy.Pass()); + + size_t size = GetSerializedSize_(obj, false); + EXPECT_EQ(32U, size); + + mojo::internal::FixedBuffer buf(size); + internal::ObjectUnion_Data* data = nullptr; + SerializeUnion_(obj.Pass(), &buf, &data, false); + + ObjectUnionPtr obj2; + Deserialize_(data, &obj2); + EXPECT_EQ(8, obj2->get_f_dummy()->f_int8); +} + +TEST(UnionTest, StructInUnionValidation) { + Environment environment; + DummyStructPtr dummy(DummyStruct::New()); + dummy->f_int8 = 8; + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_dummy(dummy.Pass()); + + size_t size = GetSerializedSize_(obj, false); + + mojo::internal::FixedBuffer buf(size); + internal::ObjectUnion_Data* data = nullptr; + SerializeUnion_(obj.Pass(), &buf, &data, false); + + void* raw_buf = buf.Leak(); + mojo::internal::BoundsChecker bounds_checker(data, + static_cast<uint32_t>(size), 0); + EXPECT_TRUE( + internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false)); + free(raw_buf); +} + +TEST(UnionTest, StructInUnionValidationNonNullable) { + Environment environment; + DummyStructPtr dummy(nullptr); + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_dummy(dummy.Pass()); + + size_t size = GetSerializedSize_(obj, false); + + mojo::internal::FixedBuffer buf(size); + internal::ObjectUnion_Data* data = nullptr; + SerializeUnion_(obj.Pass(), &buf, &data, false); + + void* raw_buf = buf.Leak(); + mojo::internal::BoundsChecker bounds_checker(data, + static_cast<uint32_t>(size), 0); + EXPECT_FALSE( + internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false)); + free(raw_buf); +} + +TEST(UnionTest, StructInUnionValidationNullable) { + Environment environment; + DummyStructPtr dummy(nullptr); + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_nullable(dummy.Pass()); + + size_t size = GetSerializedSize_(obj, false); + + mojo::internal::FixedBuffer buf(size); + internal::ObjectUnion_Data* data = nullptr; + SerializeUnion_(obj.Pass(), &buf, &data, false); + + void* raw_buf = buf.Leak(); + mojo::internal::BoundsChecker bounds_checker(data, + static_cast<uint32_t>(size), 0); + EXPECT_TRUE( + internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false)); + free(raw_buf); +} + +TEST(UnionTest, ArrayInUnionGetterSetter) { + Environment environment; + + Array<int8_t> array(2); + array[0] = 8; + array[1] = 9; + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_array_int8(array.Pass()); + + EXPECT_EQ(8, obj->get_f_array_int8()[0]); + EXPECT_EQ(9, obj->get_f_array_int8()[1]); +} + +TEST(UnionTest, ArrayInUnionSerialization) { + Environment environment; + + Array<int8_t> array(2); + array[0] = 8; + array[1] = 9; + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_array_int8(array.Pass()); + + size_t size = GetSerializedSize_(obj, false); + EXPECT_EQ(32U, size); + + mojo::internal::FixedBuffer buf(size); + internal::ObjectUnion_Data* data = nullptr; + SerializeUnion_(obj.Pass(), &buf, &data, false); + + std::vector<Handle> handles; + data->EncodePointersAndHandles(&handles); + data->DecodePointersAndHandles(&handles); + + ObjectUnionPtr obj2; + Deserialize_(data, &obj2); + + EXPECT_EQ(8, obj2->get_f_array_int8()[0]); + EXPECT_EQ(9, obj2->get_f_array_int8()[1]); +} + +TEST(UnionTest, ArrayInUnionValidation) { + Environment environment; + + Array<int8_t> array(2); + array[0] = 8; + array[1] = 9; + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_array_int8(array.Pass()); + + size_t size = GetSerializedSize_(obj, false); + mojo::internal::FixedBuffer buf(size); + internal::ObjectUnion_Data* data = nullptr; + SerializeUnion_(obj.Pass(), &buf, &data, false); + + std::vector<Handle> handles; + data->EncodePointersAndHandles(&handles); + + void* raw_buf = buf.Leak(); + mojo::internal::BoundsChecker bounds_checker(data, + static_cast<uint32_t>(size), 0); + + EXPECT_TRUE( + internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false)); + free(raw_buf); +} + +TEST(UnionTest, MapInUnionGetterSetter) { + Environment environment; + Map<String, int8_t> map; + map.insert("one", 1); + map.insert("two", 2); + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_map_int8(map.Pass()); + + EXPECT_EQ(1, obj->get_f_map_int8()["one"]); + EXPECT_EQ(2, obj->get_f_map_int8()["two"]); +} + +TEST(UnionTest, MapInUnionSerialization) { + Environment environment; + Map<String, int8_t> map; + map.insert("one", 1); + map.insert("two", 2); + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_map_int8(map.Pass()); + + size_t size = GetSerializedSize_(obj, false); + EXPECT_EQ(112U, size); + + mojo::internal::FixedBuffer buf(size); + internal::ObjectUnion_Data* data = nullptr; + SerializeUnion_(obj.Pass(), &buf, &data, false); + + std::vector<Handle> handles; + data->EncodePointersAndHandles(&handles); + data->DecodePointersAndHandles(&handles); + + ObjectUnionPtr obj2; + Deserialize_(data, &obj2); + + EXPECT_EQ(1, obj2->get_f_map_int8()["one"]); + EXPECT_EQ(2, obj2->get_f_map_int8()["two"]); +} + +TEST(UnionTest, MapInUnionValidation) { + Environment environment; + Map<String, int8_t> map; + map.insert("one", 1); + map.insert("two", 2); + + ObjectUnionPtr obj(ObjectUnion::New()); + obj->set_f_map_int8(map.Pass()); + + size_t size = GetSerializedSize_(obj, false); + EXPECT_EQ(112U, size); + + mojo::internal::FixedBuffer buf(size); + internal::ObjectUnion_Data* data = nullptr; + SerializeUnion_(obj.Pass(), &buf, &data, false); + + std::vector<Handle> handles; + data->EncodePointersAndHandles(&handles); + + void* raw_buf = buf.Leak(); + mojo::internal::BoundsChecker bounds_checker(data, + static_cast<uint32_t>(size), 0); + + EXPECT_TRUE( + internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false)); + free(raw_buf); +} + } // namespace test } // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/BUILD.gn b/third_party/mojo/src/mojo/public/cpp/environment/BUILD.gn index 87f24ff..fe3a011 100644 --- a/third_party/mojo/src/mojo/public/cpp/environment/BUILD.gn +++ b/third_party/mojo/src/mojo/public/cpp/environment/BUILD.gn
@@ -7,8 +7,9 @@ mojo_sdk_source_set("environment") { sources = [ "async_waiter.h", - "logging.h", "environment.h", + "logging.h", + "task_tracker.h", ] mojo_sdk_public_deps = [ "mojo/public/c/environment" ] @@ -26,8 +27,12 @@ "lib/default_async_waiter.h", "lib/default_logger.cc", "lib/default_logger.h", + "lib/default_task_tracker.cc", + "lib/default_task_tracker.h", "lib/environment.cc", "lib/logging.cc", + "lib/scoped_task_tracking.cc", + "lib/scoped_task_tracking.h", ] public_deps = [ @@ -36,6 +41,7 @@ mojo_sdk_deps = [ "mojo/public/c/environment", + "mojo/public/cpp/system", "mojo/public/cpp/utility", ] }
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/environment.h b/third_party/mojo/src/mojo/public/cpp/environment/environment.h index ce3f7d0..3a54428 100644 --- a/third_party/mojo/src/mojo/public/cpp/environment/environment.h +++ b/third_party/mojo/src/mojo/public/cpp/environment/environment.h
@@ -12,6 +12,8 @@ namespace mojo { +struct TaskTracker; + // Other parts of the Mojo C++ APIs use the *static* methods of this class. // // The "standalone" implementation of this class requires that this class (in @@ -26,11 +28,13 @@ // This constructor allows the standard implementations to be overridden (set // a parameter to null to get the standard implementation). Environment(const MojoAsyncWaiter* default_async_waiter, - const MojoLogger* default_logger); + const MojoLogger* default_logger, + const TaskTracker* default_task_tracker); ~Environment(); static const MojoAsyncWaiter* GetDefaultAsyncWaiter(); static const MojoLogger* GetDefaultLogger(); + static const TaskTracker* GetDefaultTaskTracker(); // These instantiate and destroy an environment-specific run loop for the // current thread, allowing |GetDefaultAsyncWaiter()| to be used. (The run
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/lib/default_task_tracker.cc b/third_party/mojo/src/mojo/public/cpp/environment/lib/default_task_tracker.cc new file mode 100644 index 0000000..17c814db --- /dev/null +++ b/third_party/mojo/src/mojo/public/cpp/environment/lib/default_task_tracker.cc
@@ -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. + +#include "mojo/public/cpp/environment/lib/default_task_tracker.h" + +namespace mojo { + +namespace { + +// +// The standalone task tracker does nothing. +// + +TaskTrackingId StartTracking(const char* function_name, + const char* file_name, + int line_number, + const void* program_counter) { + return TaskTrackingId(0); +} + +void EndTracking(const TaskTrackingId id) { +} + +void SetEnabled(bool enabled) { +} + +} // namespace + +namespace internal { + +const TaskTracker kDefaultTaskTracker = {&StartTracking, + &EndTracking, + &SetEnabled}; + +} // namespace internal + +} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/lib/default_task_tracker.h b/third_party/mojo/src/mojo/public/cpp/environment/lib/default_task_tracker.h new file mode 100644 index 0000000..83b9ae3 --- /dev/null +++ b/third_party/mojo/src/mojo/public/cpp/environment/lib/default_task_tracker.h
@@ -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. + +#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_TASK_TRACKER_H_ +#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_TASK_TRACKER_H_ + +#include "mojo/public/cpp/environment/task_tracker.h" + +namespace mojo { +namespace internal { + +extern const TaskTracker kDefaultTaskTracker; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_DEFAULT_TASK_TRACKER_H_
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/lib/environment.cc b/third_party/mojo/src/mojo/public/cpp/environment/lib/environment.cc index 6fb7e22a..8c7c9306 100644 --- a/third_party/mojo/src/mojo/public/cpp/environment/lib/environment.cc +++ b/third_party/mojo/src/mojo/public/cpp/environment/lib/environment.cc
@@ -9,6 +9,7 @@ #include "mojo/public/c/environment/logger.h" #include "mojo/public/cpp/environment/lib/default_async_waiter.h" #include "mojo/public/cpp/environment/lib/default_logger.h" +#include "mojo/public/cpp/environment/lib/default_task_tracker.h" #include "mojo/public/cpp/utility/run_loop.h" namespace mojo { @@ -17,27 +18,34 @@ const MojoAsyncWaiter* g_default_async_waiter = nullptr; const MojoLogger* g_default_logger = nullptr; +const TaskTracker* g_default_task_tracker = nullptr; void Init(const MojoAsyncWaiter* default_async_waiter, - const MojoLogger* default_logger) { + const MojoLogger* default_logger, + const TaskTracker* default_task_tracker) { g_default_async_waiter = default_async_waiter ? default_async_waiter : &internal::kDefaultAsyncWaiter; g_default_logger = default_logger ? default_logger : &internal::kDefaultLogger; + g_default_task_tracker = default_task_tracker + ? default_task_tracker + : &internal::kDefaultTaskTracker; + RunLoop::SetUp(); } } // namespace Environment::Environment() { - Init(nullptr, nullptr); + Init(nullptr, nullptr, nullptr); } Environment::Environment(const MojoAsyncWaiter* default_async_waiter, - const MojoLogger* default_logger) { - Init(default_async_waiter, default_logger); + const MojoLogger* default_logger, + const TaskTracker* default_task_tracker) { + Init(default_async_waiter, default_logger, default_task_tracker); } Environment::~Environment() { @@ -62,6 +70,11 @@ } // static +const TaskTracker* Environment::GetDefaultTaskTracker() { + return g_default_task_tracker; +} + +// static void Environment::InstantiateDefaultRunLoop() { assert(!RunLoop::current()); // Not leaked: accessible from |RunLoop::current()|.
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.cc b/third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.cc new file mode 100644 index 0000000..9e253d5 --- /dev/null +++ b/third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.cc
@@ -0,0 +1,37 @@ +// 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/environment/lib/scoped_task_tracking.h" + +#include "mojo/public/cpp/environment/environment.h" + +namespace mojo { +namespace internal { + +ScopedTaskTracking::ScopedTaskTracking(const char* function_name, + const char* file_name, + int line, + const void* program_counter) + : id_(Environment::GetDefaultTaskTracker()->StartTracking( + function_name, + file_name, + line, + program_counter)) { +} + +ScopedTaskTracking::ScopedTaskTracking(const char* function_name, + const char* file_name, + int line) + : id_(Environment::GetDefaultTaskTracker()->StartTracking(function_name, + file_name, + line, + nullptr)) { +} + +ScopedTaskTracking::~ScopedTaskTracking() { + Environment::GetDefaultTaskTracker()->EndTracking(id_); +} + +} // namespace internal +} // namespace mojo
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.h b/third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.h new file mode 100644 index 0000000..1b0411e --- /dev/null +++ b/third_party/mojo/src/mojo/public/cpp/environment/lib/scoped_task_tracking.h
@@ -0,0 +1,34 @@ +// 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_ENVIRONMENT_LIB_SCOPED_TASK_TRACKING_H_ +#define MOJO_PUBLIC_CPP_ENVIRONMENT_LIB_SCOPED_TASK_TRACKING_H_ + +#include "mojo/public/cpp/environment/task_tracker.h" +#include "mojo/public/cpp/system/macros.h" + +namespace mojo { +namespace internal { + +// An RAII wrapper for |TaskTrackingId|. +class ScopedTaskTracking { + public: + ScopedTaskTracking(const char* function_name, + const char* file_name, + int line, + const void* program_counter); + ScopedTaskTracking(const char* function_name, + const char* file_name, + int line); + ~ScopedTaskTracking(); + + private: + TaskTrackingId id_; + MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedTaskTracking); +}; + +} // namespace internal +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_SCOPED_TASK_TRACKING_H_
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/task_tracker.h b/third_party/mojo/src/mojo/public/cpp/environment/task_tracker.h new file mode 100644 index 0000000..771dc7f --- /dev/null +++ b/third_party/mojo/src/mojo/public/cpp/environment/task_tracker.h
@@ -0,0 +1,34 @@ +// 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_ENVIRONMENT_TASK_TRACKER_H_ +#define MOJO_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_ + +#include <sstream> + +#include "mojo/public/cpp/system/macros.h" + +namespace mojo { + +typedef intptr_t TaskTrackingId; + +// Interface for wiring task-level profiling, which is implemented through +// tracked_objects system in chrome. +// This API is mainly used from generated interface implementation. +struct TaskTracker { + public: + // Start tracking. The returned id must be reclaimed through |EndTracking()|. + TaskTrackingId (*StartTracking)(const char* function_name, + const char* file_name, + int line_number, + const void* program_counter); + // Finish tracking. The |id| is one that is returned from |StartTracking()|. + void (*EndTracking)(const TaskTrackingId id); + // Enable or disable tracking. It is disabled by default. + void (*SetEnabled)(bool enabled); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_ENVIRONMENT_TASK_TRACKER_H_
diff --git a/third_party/mojo/src/mojo/public/cpp/environment/tests/logging_unittest.cc b/third_party/mojo/src/mojo/public/cpp/environment/tests/logging_unittest.cc index 7ecc8b20..25ebb34 100644 --- a/third_party/mojo/src/mojo/public/cpp/environment/tests/logging_unittest.cc +++ b/third_party/mojo/src/mojo/public/cpp/environment/tests/logging_unittest.cc
@@ -31,7 +31,7 @@ class LoggingTest : public testing::Test { public: - LoggingTest() : environment_(nullptr, &kMockLogger) { + LoggingTest() : environment_(nullptr, &kMockLogger, nullptr) { minimum_log_level_ = MOJO_LOG_LEVEL_INFO; ResetMockLogger(); }
diff --git a/third_party/mojo/src/mojo/public/dart/README b/third_party/mojo/src/mojo/public/dart/README deleted file mode 100644 index fd75b8f..0000000 --- a/third_party/mojo/src/mojo/public/dart/README +++ /dev/null
@@ -1,17 +0,0 @@ -These are interim instructions for building and testing Dart's Mojo bindings. -These instructions currently only work for Linux, and assume you already have a -Mojo checkout. - -1.) Configure Mojo with Dart. - - $ ./mojo/tools/mojob.py gn --release --with-dart - - -2.) Build Mojo with Dart. - - $ ./mojo/tools/mojob.py build --release - - -3.) Run Dart tests. - - $ ./mojo/tools/mojob.py darttest --release
diff --git a/third_party/mojo/src/mojo/public/dart/README.md b/third_party/mojo/src/mojo/public/dart/README.md new file mode 100644 index 0000000..6de696b --- /dev/null +++ b/third_party/mojo/src/mojo/public/dart/README.md
@@ -0,0 +1,126 @@ +Dart Mojo Applications +==== + +## Mojo Application API + +*TODO(zra)* + +## Application Packaging + +All Dart sources for a Mojo application are collected in a specially formatted +zip file, which is understood by Dart's content handler in the Mojo shell. +This section describes what the various parts of that package are, and how they +all make it to the right place. + +### GN Template + +Dart Mojo applications are built with the GN template +'dart_packaged_application' defined in `//mojo/public/dart/rules.gni`. +Here is an example: + + +``` +dart_packaged_application("foo") { + output_name = "dart_foo" + uses_pub = true + sources = [ + "main.dart", + "foo.dart", + ] + deps = [ + "//mojo/public/dart", + "//mojo/services/network/public/interfaces", + ] +} +``` + +There are several parts: +* `output_name` is the name of the resulting .mojo file if it should be + different from the name of the target. (In this case we get dart_foo.mojo + instead of foo.mojo.) +* `uses_pub` should be true when the application depends on Dart packages pulled + down from pub. The application should have `pubspec.yaml` and `pubspec.lock` + files adjacent to `main.dart`. More on this below. +* `sources` is the list of Dart sources for the application. Each application + **must** contain a `main.dart` file. `main.dart` must be the library entry + point, and must contain the `main()` function. +* `deps` has the usual meaning. In the example above, + `//mojo/services/network/public/interfaces` indicates that the "foo" + application uses the Dart bindings generated for the network service. + +### pub packages + +Dart Mojo applications may use packages from the pub package repository at +pub.dartlang.org. + +The "foo" example above has `uses_pub` set to true. Suppose its `pubspec.yaml` +is as follows: + +``` +name: foo +version: 0.0.1 +description: Foo +dependencies: + crypto: ">=0.9.0 <0.10.0" +``` + +The script `//mojo/public/tools/git/dart_pub_get.py` should be run before build +time, e.g. as a "runhooks" action during `gclient sync`. The script traverses +a directory tree looking for `pubspec.yaml` files. On finding one, in the +containing directory, it runs `pub get`. This creates a "packages/" directory +in the source tree adjacent to the `pubspec.yaml` file containing the downloaded +Dart packages. `pub get` also creates a `pubspec.lock` file that locks down +pub packages to specific versions. This `pubspec.lock` file must be checked in +in order to have hermetic builds. + +During the build, The `dart_packaged_application` rule looks for a "packages/" +directory, and copies its contents into the zip file. + +### Generated bindings + +The script `//mojo/public/tools/bindings/generators/mojom_dart_generator.py` +and the templates under `//mojo/public/tools/bindings/generators/dart_templates` +govern how `.mojom` files are compiled into Dart code. + +Consider the `network_error.mojom` file from the network services used by our +"foo" example: + +``` +module mojo; + +struct NetworkError { + int32 code; + string? description; +}; +``` + +This contents of this file are in the `mojo` module. The Dart source generated +for this file will end up under, e.g. +`//out/Debug/gen/dart-gen/mojom/mojo/network_error.mojom.dart`, along with the +other Dart sources generated for `.mojom` files in the `mojo` module. + +### Resulting layout + +They layout for our "foo" example will be the following: + +``` +//main.dart +//foo.dart +//crypto/... # Dart's crypto pub package. +//mojo/public/dart/... # Mojo SDK Dart libraries. +//mojom/mojo/... # Generated bindings in the mojo module. +``` + +Where `//mojo/public/dart` contains Dart's Mojo bindings, `//crypto` contains +the `crypto` pub package, and `//mojom/mojo` contains the generated bindings in +the mojom module for the network service. + +Mojo's Dart content handler sets the package root for a Dart application to be +the root directory of the unpacked zip file. Therefore, Dart sources in this +application can use the following imports: + +```dart +import 'package:crypto/crypto.dart'; +import 'package:mojo/public/dart/application.dart'; +import 'package:mojom/mojo/network_error.mojom.dart'; +```
diff --git a/third_party/mojo/src/mojo/public/dart/application.dart b/third_party/mojo/src/mojo/public/dart/application.dart index ba7f497..37f923e 100644 --- a/third_party/mojo/src/mojo/public/dart/application.dart +++ b/third_party/mojo/src/mojo/public/dart/application.dart
@@ -10,9 +10,9 @@ import 'package:mojo/public/dart/bindings.dart' as bindings; import 'package:mojo/public/dart/core.dart' as core; -import 'package:mojo/application.mojom.dart' as application_mojom; -import 'package:mojo/service_provider.mojom.dart'; -import 'package:mojo/shell.mojom.dart' as shell_mojom; +import 'package:mojom/mojo/application.mojom.dart' as application_mojom; +import 'package:mojom/mojo/service_provider.mojom.dart'; +import 'package:mojom/mojo/shell.mojom.dart' as shell_mojom; part 'src/application.dart'; part 'src/application_connection.dart';
diff --git a/third_party/mojo/src/mojo/public/go/bindings/decoder.go b/third_party/mojo/src/mojo/public/go/bindings/decoder.go index 67ebe9e..2b12ff3 100644 --- a/third_party/mojo/src/mojo/public/go/bindings/decoder.go +++ b/third_party/mojo/src/mojo/public/go/bindings/decoder.go
@@ -40,7 +40,7 @@ // claimData claims a block of |size| bytes for a one-level value. func (d *Decoder) claimData(size int) error { if d.end+size > len(d.buf) { - return fmt.Errorf("data buffer is too small") + return &ValidationError{IllegalMemoryRange, "data buffer is too small"} } d.end += size return nil @@ -48,10 +48,10 @@ func (d *Decoder) claimHandle(index int) (system.UntypedHandle, error) { if index >= len(d.handles) { - return nil, fmt.Errorf("trying to access non present handle") + return nil, &ValidationError{IllegalHandle, "trying to access non present handle"} } if index < d.nextHandle { - return nil, fmt.Errorf("trying to access handle out of order") + return nil, &ValidationError{IllegalHandle, "trying to access handle out of order"} } d.nextHandle = index + 1 return d.handles[index], nil @@ -100,7 +100,9 @@ } minSize := bytesForBits(uint64(header.ElementsOrVersion) * uint64(elementBitSize)) if got, want := int(header.Size), dataHeaderSize+minSize; got < want { - return 0, fmt.Errorf("data header size is too small: is %d, but should be at least %d", got, want) + return 0, &ValidationError{UnexpectedArrayHeader, + fmt.Sprintf("data header size(%d) should be at least %d", got, want), + } } if err := d.pushState(header, elementBitSize); err != nil { return 0, err @@ -117,7 +119,9 @@ return err } if header != mapHeader { - return fmt.Errorf("invalid map header: %v", header) + return &ValidationError{UnexpectedStructHeader, + fmt.Sprintf("invalid map header: %v", header), + } } if err := d.pushState(header, pointerBitSize); err != nil { return err @@ -135,7 +139,9 @@ return DataHeader{}, err } if header.Size < dataHeaderSize { - return DataHeader{}, fmt.Errorf("data header size(%d) should be at least %d", header.Size, dataHeaderSize) + return DataHeader{}, &ValidationError{UnexpectedStructHeader, + fmt.Sprintf("data header size(%d) should be at least %d", header.Size, dataHeaderSize), + } } if err := d.pushState(header, 0); err != nil { return DataHeader{}, err @@ -299,14 +305,16 @@ } newEnd := uint64(d.state().offset-8) + pointer - if newEnd >= uint64(len(d.buf)) { - return 0, fmt.Errorf("trying to access out of range memory") + if pointer >= uint64(len(d.buf)) || newEnd >= uint64(len(d.buf)) { + return 0, &ValidationError{IllegalPointer, "trying to access out of range memory"} } if newEnd < uint64(d.end) { - return 0, fmt.Errorf("trying to access memory out of order") + return 0, &ValidationError{IllegalMemoryRange, "trying to access memory out of order"} } if newEnd%8 != 0 { - return 0, fmt.Errorf("incorrect pointer data alignment: %d", newEnd) + return 0, &ValidationError{MisalignedObject, + fmt.Sprintf("incorrect pointer data alignment: %d", newEnd), + } } d.claimData(int(newEnd) - d.end) return pointer, nil
diff --git a/third_party/mojo/src/mojo/public/go/bindings/message.go b/third_party/mojo/src/mojo/public/go/bindings/message.go index 8455cd4..f2dce2a 100644 --- a/third_party/mojo/src/mojo/public/go/bindings/message.go +++ b/third_party/mojo/src/mojo/public/go/bindings/message.go
@@ -31,6 +31,31 @@ mapHeader = DataHeader{24, 2} } +const ( + DifferentSizedArraysInMap = "VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP" + IllegalHandle = "VALIDATION_ERROR_ILLEGAL_HANDLE" + IllegalMemoryRange = "VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE" + IllegalPointer = "VALIDATION_ERROR_ILLEGAL_POINTER" + MessageHeaderInvalidFlags = "VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS" + MessageHeaderMissingRequestId = "VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID" + MessageHeaderUnknownMethod = "VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD" + MisalignedObject = "VALIDATION_ERROR_MISALIGNED_OBJECT" + UnexpectedArrayHeader = "VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER" + UnexpectedInvalidHandle = "VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE" + UnexpectedNullPointer = "VALIDATION_ERROR_UNEXPECTED_NULL_POINTER" + UnexpectedStructHeader = "VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER" +) + +// ValidationError is an error that can happen during message validation. +type ValidationError struct { + ErrorCode string + Message string +} + +func (e *ValidationError) Error() string { + return e.Message +} + // Payload is an interface implemented by a mojo struct that can encode/decode // itself into mojo archive format. type Payload interface { @@ -74,8 +99,20 @@ } numFields := header.ElementsOrVersion if numFields < 2 || numFields > 3 { - return fmt.Errorf("Invalid message header: it should have 2 or 3 fileds, but has %d", numFields) + return &ValidationError{UnexpectedStructHeader, + fmt.Sprintf("invalid message header: it should have 2 or 3 fileds, but has %d", numFields), + } } + expectedSize := uint32(dataHeaderSize + 2*4) + if numFields == 3 { + expectedSize += 8 + } + if expectedSize != header.Size { + return &ValidationError{UnexpectedStructHeader, + fmt.Sprintf("unexpected struct header size: expected %d, but got %d", expectedSize, header.Size), + } + } + if h.Type, err = decoder.ReadUint32(); err != nil { return err } @@ -84,14 +121,16 @@ } if numFields == 3 { if h.Flags != MessageExpectsResponseFlag && h.Flags != MessageIsResponseFlag { - return fmt.Errorf("Message header flags(%v) should be MessageExpectsResponseFlag or MessageIsResponseFlag", h.Flags) + return &ValidationError{MessageHeaderInvalidFlags, + fmt.Sprintf("message header flags(%v) should be MessageExpectsResponseFlag or MessageIsResponseFlag", h.Flags), + } } if h.RequestId, err = decoder.ReadUint64(); err != nil { return err } } else { if h.Flags != MessageNoFlag { - return fmt.Errorf("Message header flags(%v) should be MessageNoFlag", h.Flags) + return &ValidationError{MessageHeaderMissingRequestId, "missing request ID in message header"} } } return decoder.Finish()
diff --git a/third_party/mojo/src/mojo/public/go/system/core.go b/third_party/mojo/src/mojo/public/go/system/core.go index 4fc3df5..9e29cff 100644 --- a/third_party/mojo/src/mojo/public/go/system/core.go +++ b/third_party/mojo/src/mojo/public/go/system/core.go
@@ -117,7 +117,7 @@ if opts == nil { r, p, c = sysImpl.CreateDataPipeWithDefaultOptions() } else { - r, p, c = sysImpl.CreateDataPipe(uint32(opts.flags), uint32(opts.elemSize), uint32(opts.capacity)) + r, p, c = sysImpl.CreateDataPipe(uint32(opts.Flags), uint32(opts.ElemSize), uint32(opts.Capacity)) } impl.mu.Unlock() return MojoResult(r), impl.AcquireNativeHandle(MojoHandle(p)).ToProducerHandle(), impl.AcquireNativeHandle(MojoHandle(c)).ToConsumerHandle() @@ -127,7 +127,7 @@ var flags uint32 if opts != nil { - flags = uint32(opts.flags) + flags = uint32(opts.Flags) } impl.mu.Lock() r, handle0, handle1 := sysImpl.CreateMessagePipe(flags) @@ -138,7 +138,7 @@ func (impl *coreImpl) CreateSharedBuffer(opts *SharedBufferOptions, numBytes uint64) (MojoResult, SharedBufferHandle) { var flags uint32 if opts != nil { - flags = uint32(opts.flags) + flags = uint32(opts.Flags) } impl.mu.Lock() r, handle := sysImpl.CreateSharedBuffer(flags, numBytes)
diff --git a/third_party/mojo/src/mojo/public/go/system/mojo_types.go b/third_party/mojo/src/mojo/public/go/system/mojo_types.go index 69051e7..1eb5f732 100644 --- a/third_party/mojo/src/mojo/public/go/system/mojo_types.go +++ b/third_party/mojo/src/mojo/public/go/system/mojo_types.go
@@ -101,27 +101,27 @@ // DataPipeOptions is used to specify creation parameters for a data pipe. type DataPipeOptions struct { - flags MojoCreateDataPipeOptionsFlags + Flags MojoCreateDataPipeOptionsFlags // The size of an element in bytes. All transactions and buffers will // be an integral number of elements. - elemSize uint32 + ElemSize uint32 // The capacity of the data pipe in bytes. Must be a multiple of elemSize. - capacity uint32 + Capacity uint32 } // MessagePipeOptions is used to specify creation parameters for a message pipe. type MessagePipeOptions struct { - flags MojoCreateMessagePipeOptionsFlags + Flags MojoCreateMessagePipeOptionsFlags } // SharedBufferOptions is used to specify creation parameters for a // shared buffer. type SharedBufferOptions struct { - flags MojoCreateSharedBufferOptionsFlags + Flags MojoCreateSharedBufferOptionsFlags } // DuplicateBufferHandleOptions is used to specify parameters in // duplicating access to a shared buffer. type DuplicateBufferHandleOptions struct { - flags MojoDuplicateBufferHandleOptionsFlags + Flags MojoDuplicateBufferHandleOptionsFlags }
diff --git a/third_party/mojo/src/mojo/public/go/system/shared_buffer.go b/third_party/mojo/src/mojo/public/go/system/shared_buffer.go index 925ee35..f3048f87 100644 --- a/third_party/mojo/src/mojo/public/go/system/shared_buffer.go +++ b/third_party/mojo/src/mojo/public/go/system/shared_buffer.go
@@ -35,7 +35,7 @@ func (h *sharedBuffer) DuplicateBufferHandle(opts *DuplicateBufferHandleOptions) (MojoResult, SharedBufferHandle) { var flags uint32 if opts != nil { - flags = uint32(opts.flags) + flags = uint32(opts.Flags) } h.core.mu.Lock() r, dup := sysImpl.DuplicateBufferHandle(uint32(h.mojoHandle), flags)
diff --git a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom index 7250f65..cda5be4 100644 --- a/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom +++ b/third_party/mojo/src/mojo/public/interfaces/bindings/tests/test_unions.mojom
@@ -22,6 +22,10 @@ union ObjectUnion { int8 f_int8; string f_string; + DummyStruct f_dummy; + DummyStruct? f_nullable; + array<int8> f_array_int8; + map<string, int8> f_map_int8; }; struct DummyStruct { @@ -33,6 +37,7 @@ PodUnion? pod_union; array<PodUnion>? pod_union_array; array<DummyStruct>? s_array; + map<string, PodUnion>? pod_union_map; }; struct SmallStructNonNullableUnion {
diff --git a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java index 94f44457..23a61888 100644 --- a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java +++ b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Encoder.java
@@ -4,6 +4,7 @@ package org.chromium.mojo.bindings; +import org.chromium.mojo.bindings.Interface.AbstractProxy.HandlerImpl; import org.chromium.mojo.bindings.Struct.DataHeader; import org.chromium.mojo.system.Core; import org.chromium.mojo.system.Handle; @@ -261,9 +262,9 @@ } // If the instance is a proxy, pass the proxy's handle instead of creating a new stub. if (v instanceof Interface.AbstractProxy) { - Interface.AbstractProxy proxy = (Interface.AbstractProxy) v; - if (proxy.getMessageReceiver() instanceof HandleOwner) { - encode(((HandleOwner<?>) proxy.getMessageReceiver()).passHandle(), offset, + HandlerImpl handler = ((Interface.AbstractProxy) v).getProxyHandler(); + if (handler.getMessageReceiver() instanceof HandleOwner) { + encode(((HandleOwner<?>) handler.getMessageReceiver()).passHandle(), offset, nullable); return; }
diff --git a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java index c3b26a2..4c828db 100644 --- a/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java +++ b/third_party/mojo/src/mojo/public/java/bindings/src/org/chromium/mojo/bindings/Interface.java
@@ -30,84 +30,129 @@ * {@link MessageReceiverWithResponder}, along with the response callback if needed. */ public interface Proxy extends Interface { + /** + * Class allowing to interact with the proxy itself. + */ + public interface Handler extends Closeable { + /** + * Sets the {@link ConnectionErrorHandler} that will be notified of errors. + */ + public void setErrorHandler(ConnectionErrorHandler errorHandler); + } /** - * Set the {@link ConnectionErrorHandler} that will be notified of errors. + * Returns the {@link Handler} object allowing to interact with the proxy itself. */ - public void setErrorHandler(ConnectionErrorHandler errorHandler); - + public Handler getProxyHandler(); } /** * Base implementation of {@link Proxy}. */ abstract class AbstractProxy implements Proxy { - /** - * The {@link Core} implementation to use. + * Implementation of {@link Handler}. */ - private final Core mCore; + protected static class HandlerImpl implements Proxy.Handler, ConnectionErrorHandler { + /** + * The {@link Core} implementation to use. + */ + private final Core mCore; - /** - * The {@link MessageReceiverWithResponder} that will receive a serialized message for each - * method call. - */ - private final MessageReceiverWithResponder mMessageReceiver; + /** + * The {@link MessageReceiverWithResponder} that will receive a serialized message for + * each method call. + */ + private final MessageReceiverWithResponder mMessageReceiver; - /** - * The {@link ConnectionErrorHandler} that will be notified of errors. - */ - private ConnectionErrorHandler mErrorHandler = null; + /** + * The {@link ConnectionErrorHandler} that will be notified of errors. + */ + private ConnectionErrorHandler mErrorHandler = null; - /** - * Constructor. - * - * @param core the Core implementation used to create pipes and access the async waiter. - * @param messageReceiver the message receiver to send message to. - */ - protected AbstractProxy(Core core, MessageReceiverWithResponder messageReceiver) { - this.mCore = core; - this.mMessageReceiver = messageReceiver; - } + /** + * Constructor. + * + * @param core the Core implementation used to create pipes and access the async waiter. + * @param messageReceiver the message receiver to send message to. + */ + protected HandlerImpl(Core core, MessageReceiverWithResponder messageReceiver) { + this.mCore = core; + this.mMessageReceiver = messageReceiver; + } - /** - * Returns the message receiver to send message to. - */ - protected MessageReceiverWithResponder getMessageReceiver() { - return mMessageReceiver; - } + /** + * Returns the message receiver to send message to. + */ + public MessageReceiverWithResponder getMessageReceiver() { + return mMessageReceiver; + } - /** - * Returns the Core implementation. - */ - protected Core getCore() { - return mCore; - } + /** + * Returns the Core implementation. + */ + public Core getCore() { + return mCore; + } - /** - * @see Proxy#setErrorHandler(ConnectionErrorHandler) - */ - @Override - public void setErrorHandler(ConnectionErrorHandler errorHandler) { - this.mErrorHandler = errorHandler; - } + /** + * Sets the {@link ConnectionErrorHandler} that will be notified of errors. + */ + @Override + public void setErrorHandler(ConnectionErrorHandler errorHandler) { + this.mErrorHandler = errorHandler; + } - /** - * @see ConnectionErrorHandler#onConnectionError(MojoException) - */ - @Override - public void onConnectionError(MojoException e) { - if (mErrorHandler != null) { - mErrorHandler.onConnectionError(e); + /** + * @see ConnectionErrorHandler#onConnectionError(MojoException) + */ + @Override + public void onConnectionError(MojoException e) { + if (mErrorHandler != null) { + mErrorHandler.onConnectionError(e); + } + } + + /** + * @see Closeable#close() + */ + @Override + public void close() { + mMessageReceiver.close(); } } /** - * @see Closeable#close() + * The handler associated with this proxy. + */ + private final HandlerImpl mHandler; + + protected AbstractProxy(Core core, MessageReceiverWithResponder messageReceiver) { + mHandler = new HandlerImpl(core, messageReceiver); + } + + /** + * @see Interface#close() */ @Override public void close() { - mMessageReceiver.close(); + mHandler.close(); + } + + /** + * @see Proxy#getProxyHandler() + */ + @Override + public HandlerImpl getProxyHandler() { + return mHandler; + } + + /** + * @see ConnectionErrorHandler#onConnectionError(org.chromium.mojo.system.MojoException) + */ + @Override + public void onConnectionError(MojoException e) { + mHandler.onConnectionError(e); } }
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index 6e52c39..3cadeed 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -171,6 +171,7 @@ switch (message->header()->name) { {%- for method in interface.methods %} case internal::k{{class_name}}_{{method.name}}_Name: { + mojo::internal::ScopedTaskTracking task_id("mojo.{{namespace_as_string}}.{{class_name}}.{{method.name}}", __FILE__, __LINE__); {%- if method.response_parameters == None %} internal::{{class_name}}_{{method.name}}_Params_Data* params = reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>( @@ -198,6 +199,7 @@ switch (message->header()->name) { {%- for method in interface.methods %} case internal::k{{class_name}}_{{method.name}}_Name: { + mojo::internal::ScopedTaskTracking task_id("mojo::{{namespace_as_string}}::{{class_name}}::{{method.name}}", __FILE__, __LINE__); {%- if method.response_parameters != None %} internal::{{class_name}}_{{method.name}}_Params_Data* params = reinterpret_cast<internal::{{class_name}}_{{method.name}}_Params_Data*>( @@ -231,49 +233,32 @@ } bool {{class_name}}RequestValidator::Accept(mojo::Message* message) { -{%- if interface.methods %} - if (message->has_flag(mojo::internal::kMessageIsResponse)) { - ReportValidationError( - mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); - return false; - } - switch (message->header()->name) { -{%- for method in interface.methods %} - case internal::k{{class_name}}_{{method.name}}_Name: { -{%- if method.response_parameters != None %} - if (!message->has_flag(mojo::internal::kMessageExpectsResponse)) { - ReportValidationError( - mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); - return false; - } -{%- else %} - if (message->has_flag(mojo::internal::kMessageExpectsResponse)) { - ReportValidationError( - mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); - return false; - } -{%- endif %} - mojo::internal::BoundsChecker bounds_checker( - message->payload(), message->payload_num_bytes(), - message->handles()->size()); - if (!internal::{{class_name}}_{{method.name}}_Params_Data::Validate( - message->payload(), &bounds_checker)) { - return false; - } - break; - } -{%- endfor %} - default: { - // Unrecognized message. - ReportValidationError( - mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD); - return false; - } - } -{%- endif %} - assert(sink_); - return sink_->Accept(message); + switch (message->header()->name) { +{%- for method in interface.methods %} + case internal::k{{class_name}}_{{method.name}}_Name: { +{%- if method.response_parameters != None %} + if (!mojo::internal::ValidateMessageIsRequestExpectingResponse(message)) + return false; +{%- else %} + if (!mojo::internal::ValidateMessageIsRequestWithoutResponse(message)) + return false; +{%- endif %} + if (!mojo::internal::ValidateMessagePayload< + internal::{{class_name}}_{{method.name}}_Params_Data>(message)) { + return false; + } + return sink_->Accept(message); + } +{%- endfor %} + default: + break; + } + + // Unrecognized message. + ReportValidationError( + mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD); + return false; } {#--- Response validator definitions #} @@ -283,35 +268,26 @@ } bool {{class_name}}ResponseValidator::Accept(mojo::Message* message) { -{%- if interface.methods %} - if (!message->has_flag(mojo::internal::kMessageIsResponse)) { - ReportValidationError( - mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAGS); + assert(sink_); + if (!mojo::internal::ValidateMessageIsResponse(message)) return false; - } switch (message->header()->name) { -{%- for method in interface.methods if method.response_parameters != None %} +{%- for method in interface.methods if method.response_parameters != None %} case internal::k{{class_name}}_{{method.name}}_Name: { - mojo::internal::BoundsChecker bounds_checker( - message->payload(), message->payload_num_bytes(), - message->handles()->size()); - if (!internal::{{class_name}}_{{method.name}}_ResponseParams_Data::Validate( - message->payload(), &bounds_checker)) { + if (!mojo::internal::ValidateMessagePayload< + internal::{{class_name}}_{{method.name}}_ResponseParams_Data>(message)) { return false; } + return sink_->Accept(message); + } +{%- endfor %} + default: break; - } -{%- endfor %} - default: { - // Unrecognized message. - ReportValidationError( - mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD); - return false; - } } -{%- endif %} - assert(sink_); - return sink_->Accept(message); + // Unrecognized message. + ReportValidationError( + mojo::internal::VALIDATION_ERROR_MESSAGE_HEADER_UNKNOWN_METHOD); + return false; } {%- endif -%}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl index 3593ff6b..210ee2e5 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/module.cc.tmpl
@@ -25,6 +25,8 @@ #include "mojo/public/cpp/bindings/lib/string_serialization.h" #include "mojo/public/cpp/bindings/lib/validate_params.h" #include "mojo/public/cpp/bindings/lib/validation_errors.h" +#include "mojo/public/cpp/bindings/lib/validation_util.h" +#include "mojo/public/cpp/environment/lib/scoped_task_tracking.h" #include "mojo/public/cpp/environment/logging.h" {%- for namespace in namespaces_as_array %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl index bc77c112..f84f60a7 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -32,7 +32,7 @@ // a struct." - Section 9.5.2 ISO/IEC 14882:2011 (The C++ Spec) union MOJO_ALIGNAS(8) Union_ { {%- for field in union.fields %} -{%- if field.kind|is_string_kind %} +{%- if field.kind|is_object_kind %} uint64_t f_{{field.name}}; {%- elif field.kind.spec == 'b' %} uint8_t f_{{field.name}} : 1;
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl index 3e6b0ade..9ddcc51 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
@@ -57,10 +57,36 @@ void {{class_name}}::EncodePointersAndHandles( std::vector<mojo::Handle>* handles) { - // TODO(azani): Implement pointers and handles. + switch (tag) { +{%- for field in union.fields %} + case {{enum_name}}::{{field.name|upper}}: { +{%- if field.kind|is_object_kind and not field.kind|is_union_kind %} + mojo::internal::Encode( + reinterpret_cast<{{field.kind|cpp_field_type}}*>(&data.f_{{field.name}}), + handles); +{%- elif field.kind|is_any_handle_kind %} + mojo::internal::EncodeHandle(&data.f_{{field.name}}, handles); +{%- endif %} + return; + } +{%- endfor %} + } } void {{class_name}}::DecodePointersAndHandles( std::vector<mojo::Handle>* handles) { - // TODO(azani): Implement pointers and handles. + switch (tag) { +{%- for field in union.fields %} + case {{enum_name}}::{{field.name|upper}}: { +{%- if field.kind|is_object_kind and not field.kind|is_union_kind %} + mojo::internal::Decode( + reinterpret_cast<{{field.kind|cpp_field_type}}*>(&data.f_{{field.name}}), + handles); +{%- elif field.kind|is_any_handle_kind %} + mojo::internal::DecodeHandle(&data.f_{{field.name}}, handles); +{%- endif %} + return; + } +{%- endfor %} + } }
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl index f928eba..7df17c1f 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
@@ -7,11 +7,12 @@ if (!input) return size; + mojo::internal::UnionAccessor<{{union.name}}> input_acc(input.get()); switch (input->which()) { {% for field in union.fields %} -{% if field.kind|is_string_kind %} +{% if field.kind|is_object_kind %} case {{union.name}}::Tag::{{field.name|upper}}: - size += GetSerializedSize_(input->get_{{field.name}}()); + size += GetSerializedSize_(*(input_acc.data()->{{field.name}})); break; {%- endif %} {%- endfor %} @@ -35,14 +36,31 @@ result->tag = input->which(); switch (input->which()) { {% for field in union.fields %} - case {{union.name}}::Tag::{{field.name|upper}}: -{% if field.kind|is_string_kind %} + case {{union.name}}::Tag::{{field.name|upper}}: { +{% if field.kind|is_object_kind %} {{field.kind|cpp_field_type}}* {{field.name}}_ptr = reinterpret_cast<{{field.kind|cpp_field_type}}*>(&result->data.f_{{field.name}}); +{% if field.kind|is_string_kind %} Serialize_(*(input_acc.data()->{{field.name}}), buf, &{{field.name}}_ptr->ptr); +{% elif field.kind|is_struct_kind %} + Serialize_(mojo::internal::Forward(*(input_acc.data()->{{field.name}})), buf, &{{field.name}}_ptr->ptr); +{% elif field.kind|is_array_kind %} + const mojo::internal::ArrayValidateParams {{field.name}}_validate_params = + {{field.kind|get_array_validate_params|indent(16)}}; + SerializeArray_( + mojo::internal::Forward(*(input_acc.data()->{{field.name}})), + buf, &{{field.name}}_ptr->ptr, &{{field.name}}_validate_params); +{% elif field.kind|is_map_kind %} + const mojo::internal::ArrayValidateParams {{field.name}}_validate_params = + {{field.kind.value_kind|get_map_validate_params|indent(16)}}; + SerializeMap_( + mojo::internal::Forward(*(input_acc.data()->{{field.name}})), + buf, &{{field.name}}_ptr->ptr, &{{field.name}}_validate_params); +{%- endif %} {% else %} result->data.f_{{field.name}} = input_acc.data()->{{field.name}}; {%- endif %} break; + } {%- endfor %} } } else if (inlined) { @@ -60,8 +78,8 @@ mojo::internal::UnionAccessor<{{union.name}}> result_acc(result.get()); switch (input->tag) { {% for field in union.fields %} - case {{union.name}}::Tag::{{field.name|upper}}: -{% if field.kind|is_string_kind %} + case {{union.name}}::Tag::{{field.name|upper}}: { +{% if field.kind|is_object_kind %} result_acc.SwitchActive({{union.name}}::Tag::{{field.name|upper}}); {{field.kind|cpp_field_type}}* {{field.name}}_ptr = reinterpret_cast<{{field.kind|cpp_field_type}}*>(&input->data.f_{{field.name}}); Deserialize_({{field.name}}_ptr->ptr, result_acc.data()->{{field.name}}); @@ -69,6 +87,7 @@ result->set_{{field.name}}(input->data.f_{{field.name}}); {%- endif %} break; + } {%- endfor %} } *output = result.Pass();
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl index 107de09..2b4a7dde 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_declaration.tmpl
@@ -29,7 +29,7 @@ {% for field in union.fields %} bool is_{{field.name}}() const; - {{field.kind|cpp_result_type}} get_{{field.name}}() const; + {{field.kind|cpp_union_getter_return_type}} get_{{field.name}}() const; void set_{{field.name}}({{field.kind|cpp_const_wrapper_type}} {{field.name}}); {%- endfor %}
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl index b5e9c23..4355f41 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
@@ -21,8 +21,10 @@ switch (tag_) { {% for field in union.fields %} case Tag::{{field.name|upper}}: -{% if field.kind|is_object_kind %} +{% if field.kind|is_string_kind %} rv->set_{{field.name}}(*(data_.{{field.name}})); +{% elif field.kind|is_object_kind %} + rv->set_{{field.name}}(data_.{{field.name}}->Clone()); {%- else %} rv->set_{{field.name}}(data_.{{field.name}}); {%- endif %} @@ -57,7 +59,7 @@ return tag_ == Tag::{{field.name|upper}}; } -{{field.kind|cpp_result_type}} {{union.name}}::get_{{field.name}}() const { +{{field.kind|cpp_union_getter_return_type}} {{union.name}}::get_{{field.name}}() const { MOJO_DCHECK(tag_ == Tag::{{field.name|upper}}); {% if field.kind|is_object_kind %} return *(data_.{{field.name}}); @@ -70,6 +72,8 @@ SwitchActive(Tag::{{field.name|upper}}); {% if field.kind|is_string_kind %} *(data_.{{field.name}}) = {{field.name}}; +{% elif field.kind|is_object_kind %} + *(data_.{{field.name}}) = {{field.name}}.Pass(); {%- else %} data_.{{field.name}} = {{field.name}}; {%- endif %} @@ -89,8 +93,8 @@ switch (new_active) { {% for field in union.fields %} case Tag::{{field.name|upper}}: -{% if field.kind|is_string_kind %} - data_.{{field.name}} = new String(); +{% if field.kind|is_object_kind %} + data_.{{field.name}} = new {{field.kind|cpp_wrapper_type}}(); {%- endif %} break; {%- endfor %} @@ -103,7 +107,7 @@ switch (tag_) { {% for field in union.fields %} case Tag::{{field.name|upper}}: -{% if field.kind|is_string_kind %} +{% if field.kind|is_object_kind %} delete data_.{{field.name}}; {%- endif %} break;
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl index 4d4ea39..9c37873 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/interface.tmpl
@@ -81,7 +81,7 @@ } {% for method in interface.methods %} -const {{interface|name(False)}}_{{method|name}}_Name = {{method.ordinal}} +const {{interface|name(False)}}_{{method|name}}_Name uint32 = {{method.ordinal}} {% endfor %} type {{interface|name}}Proxy struct { @@ -130,9 +130,20 @@ p.Close_proxy() return } + if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag { + err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags, + fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags), + } + return + } + if got, want := readResult.Message.Header.Type, {{interface|name(False)}}_{{method|name}}_Name; got != want { + err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod, + fmt.Sprintf("invalid method in response: expected %v, got %v", want, got), + } + return + } var response {{method.response_param_struct|name(False)}} if err = readResult.Message.DecodePayload(&response); err != nil { - err = fmt.Errorf("can't decode response: %v", err.Error()) p.Close_proxy() return } @@ -163,9 +174,18 @@ switch message.Header.Type { {% for method in interface.methods %} case {{interface|name(False)}}_{{method|name}}_Name: +{% if method.response_parameters %} + if message.Header.Flags != bindings.MessageExpectsResponseFlag { +{% else %} + if message.Header.Flags != bindings.MessageNoFlag { +{% endif %} + return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags, + fmt.Sprintf("invalid message header flag: %v", message.Header.Flags), + } + } var request {{method.param_struct|name(False)}} if err := message.DecodePayload(&request); err != nil { - return fmt.Errorf("can't decode request: %v", err.Error()) + return err } {% if method.response_parameters %} var response {{method.response_param_struct|name(False)}} @@ -192,13 +212,16 @@ } message, err = bindings.EncodeMessage(header, &response) if err != nil { - return fmt.Errorf("can't encode response: %v", err.Error()) + return err } return s.connector.WriteMessage(message) {% endif %} {% endfor %} default: - return fmt.Errorf("unsupported request type %v", message.Header.Type); + return &bindings.ValidationError{ + bindings.MessageHeaderUnknownMethod, + fmt.Sprintf("unknown method %v", message.Header.Type), + } } return }
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl index 7f687d21..5e10011 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/go_templates/struct.tmpl
@@ -43,7 +43,9 @@ } expectedSize := {{struct|name(False)}}_Versions[index].Size if expectedSize != header.Size { - return fmt.Errorf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size) + return &bindings.ValidationError{bindings.UnexpectedStructHeader, + fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size), + } } } {% for byte in struct.bytes %} @@ -151,7 +153,7 @@ {{decodePointerValue('(*'~value~')', kind, level)|tab_indent()}} } {% else %} - return fmt.Errorf("unexpected null pointer") + return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"} } else { {{decodePointerValue(value, kind, level)|tab_indent()}} } @@ -172,7 +174,7 @@ {% if kind|is_nullable %} {{value}} = nil {% else %} - return fmt.Errorf("unexpected invalid handle") + return &bindings.ValidationError{bindings.UnexpectedInvalidHandle, "unexpected invalid handle"} {% endif %} } {% elif kind|is_enum %} @@ -204,7 +206,9 @@ } {% if kind.length %} if len{{level}} != {{kind.length}} { - return fmt.Errorf("invalid array length: expected %d, got %d", {{kind.length}}, len{{level}}) + return &bindings.ValidationError{bindings.UnexpectedArrayHeader, + fmt.Sprintf("invalid array length: expected %d, got %d", {{kind.length}}, len{{level}}), + } } {% else %} {{value}} = make({{kind|go_type(False)}}, len{{level}}) @@ -228,7 +232,9 @@ {{decode('values'~level, kind.value_kind|array, level+1)|tab_indent()}} } if len(keys{{level}}) != len(values{{level}}) { - return fmt.Errorf("Number of keys %d is different from number of values %d", len(keys{{level}}), len(values{{level}})) + return &bindings.ValidationError{bindings.DifferentSizedArraysInMap, + fmt.Sprintf("Number of keys %d is different from number of values %d", len(keys{{level}}), len(values{{level}})), + } } if err := decoder.Finish(); err != nil { return err
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl index c7aed1339..d666e66 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/java_templates/interface_definition.tmpl
@@ -168,18 +168,18 @@ _message.{{param|name}} = {{param|name}}; {% endfor %} {% if method.response_parameters != None %} - getMessageReceiver().acceptWithResponder( + getProxyHandler().getMessageReceiver().acceptWithResponder( _message.serializeWithHeader( - getCore(), + getProxyHandler().getCore(), new org.chromium.mojo.bindings.MessageHeader( {{method|method_ordinal_name}}, {{flags_for_method(method, True)}}, 0)), new {{method.response_param_struct|name}}ForwardToCallback(callback)); {% else %} - getMessageReceiver().accept( + getProxyHandler().getMessageReceiver().accept( _message.serializeWithHeader( - getCore(), + getProxyHandler().getCore(), new org.chromium.mojo.bindings.MessageHeader({{method|method_ordinal_name}}))); {% endif %} }
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py index 10ce582145..b5bf6a4 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -227,6 +227,12 @@ return "mojo::internal::StringPointer" return _kind_to_cpp_type[kind] +def GetUnionGetterReturnType(kind): + if (mojom.IsStructKind(kind) or mojom.IsArrayKind(kind) or + mojom.IsMapKind(kind)): + return "%s&" % GetCppWrapperType(kind) + return GetCppResultWrapperType(kind) + def IsStructWithHandles(struct): for pf in struct.packed.packed_fields: if mojom.IsAnyHandleKind(pf.field.kind): @@ -335,6 +341,7 @@ "cpp_pod_type": GetCppPodType, "cpp_result_type": GetCppResultWrapperType, "cpp_type": GetCppType, + "cpp_union_getter_return_type": GetUnionGetterReturnType, "cpp_wrapper_type": GetCppWrapperType, "default_value": DefaultValue, "expression_to_text": ExpressionToText, @@ -374,7 +381,7 @@ "kinds": self.module.kinds, "enums": self.module.enums, "structs": self.GetStructs(), - "unions": self.module.unions, + "unions": self.GetUnions(), "interfaces": self.GetInterfaces(), }
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py index 9d2fafe..ac27fa1d 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py +++ b/third_party/mojo/src/mojo/public/tools/bindings/generators/mojom_dart_generator.py
@@ -360,7 +360,7 @@ def GetImportUri(module): elements = module.namespace.split('.') elements.append("%s" % module.name) - return os.path.join(*elements) + return os.path.join("mojom", *elements) class Generator(generator.Generator): @@ -402,17 +402,24 @@ def GenerateFiles(self, args): elements = self.module.namespace.split('.') elements.append("%s.dart" % self.module.name) - path = os.path.join("dart-gen", *elements) + path = os.path.join("dart-gen", "mojom", *elements) self.Write(self.GenerateLibModule(args), path) link = self.MatchMojomFilePath("%s.dart" % self.module.name) if os.path.exists(os.path.join(self.output_dir, link)): os.unlink(os.path.join(self.output_dir, link)) - if sys.platform == "win32": - shutil.copy(os.path.join(self.output_dir, path), - os.path.join(self.output_dir, link)) - else: - os.symlink(os.path.join(self.output_dir, path), - os.path.join(self.output_dir, link)) + try: + if sys.platform == "win32": + shutil.copy(os.path.join(self.output_dir, path), + os.path.join(self.output_dir, link)) + else: + os.symlink(os.path.join(self.output_dir, path), + os.path.join(self.output_dir, link)) + except OSError as e: + # Errno 17 is file already exists. If the link fails because file already + # exists assume another instance of this script tried to create the same + # file and continue on. + if e.errno != 17: + raise e def GetImports(self, args): used_names = set()
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni index 6151ded..d00f632 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni +++ b/third_party/mojo/src/mojo/public/tools/bindings/mojom.gni
@@ -4,9 +4,9 @@ import("../../mojo_sdk.gni") -# Generate C++ and JavaScript source files from mojom files. The output files -# will go under the generated file directory tree with the same path as each -# input file. +# Generate C++/JavaScript/Java/Python/Dart/Go source files from mojom files. The +# output files will go under the generated file directory tree with the same +# path as each input file. # # If a mojom target is intended for use in a client repo where the location of # the Mojo SDK will be different than its location in the Mojo repo, @@ -48,6 +48,8 @@ defined(invoker.mojo_sdk_public_deps), "\"sources\" or \"deps\" must be defined for the $target_name template.") + cpp_sources_suffix = "cpp_sources" + cpp_sources_target_name = "${target_name}_${cpp_sources_suffix}" if (defined(invoker.sources)) { generator_root = rebase_path("mojo/public/tools/bindings", ".", mojo_root) generator_script = "$generator_root/mojom_bindings_generator.py" @@ -78,6 +80,11 @@ "$generator_root/generators/cpp_templates/wrapper_class_definition.tmpl", "$generator_root/generators/cpp_templates/wrapper_union_class_declaration.tmpl", "$generator_root/generators/cpp_templates/wrapper_union_class_definition.tmpl", + "$generator_root/generators/dart_templates/enum_definition.tmpl", + "$generator_root/generators/dart_templates/interface_definition.tmpl", + "$generator_root/generators/dart_templates/module.lib.tmpl", + "$generator_root/generators/dart_templates/module_definition.tmpl", + "$generator_root/generators/dart_templates/struct_definition.tmpl", "$generator_root/generators/go_templates/enum.tmpl", "$generator_root/generators/go_templates/interface.tmpl", "$generator_root/generators/go_templates/source.tmpl", @@ -100,6 +107,7 @@ "$generator_root/generators/python_templates/module.py.tmpl", "$generator_root/generators/python_templates/module_macros.tmpl", "$generator_root/generators/mojom_cpp_generator.py", + "$generator_root/generators/mojom_dart_generator.py", "$generator_root/generators/mojom_go_generator.py", "$generator_root/generators/mojom_js_generator.py", "$generator_root/generators/mojom_java_generator.py", @@ -126,12 +134,15 @@ ] generator_js_outputs = [ "{{source_gen_dir}}/{{source_name_part}}.mojom.js" ] + generator_dart_outputs = + [ "{{source_gen_dir}}/{{source_name_part}}.mojom.dart" ] generator_go_outputs = [ "${root_gen_dir}/go/src/{{source_dir}}/{{source_name_part}}/{{source_name_part}}.mojom.go" ] generator_python_outputs = [ "{{source_gen_dir}}/{{source_name_part}}_mojom.py" ] generator_java_outputs = [ "{{source_gen_dir}}/{{source_name_part}}.mojom.srcjar" ] } + generator_dart_zip_output = "$target_out_dir/$target_name.dartzip" generator_python_zip_output = "$target_out_dir/$target_name.pyzip" rebased_mojo_sdk_public_deps = [] @@ -163,12 +174,13 @@ generator_target_name = target_name + "__generator" action_foreach(generator_target_name) { if (defined(invoker.visibility)) { - visibility = target_visibility + invoker.visibility + visibility = target_visibility + invoker.visibility + + [ ":${cpp_sources_target_name}" ] } script = generator_script inputs = generator_sources sources = invoker.sources - outputs = generator_cpp_outputs + + outputs = generator_cpp_outputs + generator_dart_outputs + generator_go_outputs + generator_java_outputs + generator_js_outputs + generator_python_outputs args = [ @@ -203,7 +215,6 @@ testonly = invoker.testonly } if (defined(invoker.sources)) { - sources = process_file_template(invoker.sources, generator_cpp_outputs) data = process_file_template(invoker.sources, generator_js_outputs) } @@ -211,6 +222,9 @@ rebase_path([ "mojo/public/build/config:mojo_sdk" ], ".", mojo_root) public_deps = rebase_path([ "mojo/public/cpp/bindings" ], ".", mojo_root) + if (defined(invoker.sources)) { + public_deps += [ ":${cpp_sources_target_name}" ] + } public_deps += rebased_mojo_sdk_public_deps if (defined(invoker.public_deps)) { public_deps += invoker.public_deps @@ -226,6 +240,7 @@ } data_deps = [ ":${target_name}_python", + ":${target_name}_dart", ] if (defined(invoker.mojo_sdk_deps)) { foreach(sdk_dep, invoker.mojo_sdk_deps) { @@ -300,6 +315,79 @@ } } + action("${target_name}_dart") { + script = rebase_path("mojo/public/tools/gn/zip.py", ".", mojo_root) + + if (defined(invoker.sources)) { + inputs = process_file_template(invoker.sources, generator_dart_outputs) + } + + deps = [] + zip_inputs = [] + + foreach(d, all_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append "_dart" to get the dart + # dependency name. + full_name = get_label_info(d, "label_no_toolchain") + dep_name = get_label_info(d, "name") + dep_target_out_dir = get_label_info(d, "target_out_dir") + deps += [ "${full_name}_dart" ] + zip_inputs += [ "$dep_target_out_dir/$dep_name.dartzip" ] + } + + output = generator_dart_zip_output + outputs = [ + output, + ] + + rebase_import_from = + rebase_path("$root_build_dir/gen/dart-gen", root_build_dir) + if (defined(invoker.sources)) { + rebase_inputs = rebase_path(inputs, root_build_dir) + } + rebase_zip_inputs = rebase_path(zip_inputs, root_build_dir) + rebase_output = rebase_path(output, root_build_dir) + args = [ + "--base-dir=$rebase_import_from", + "--zip-inputs=$rebase_zip_inputs", + "--output=$rebase_output", + ] + if (defined(invoker.sources)) { + args += [ "--link-inputs=$rebase_inputs" ] + } + } + + if (defined(invoker.sources)) { + # The generated C++ source files. The main reason to introduce this target + # is so that mojo/public/cpp/bindings can depend on mojom interfaces without + # circular dependencies. It means that the target is missing the dependency + # on mojo/public/cpp/bindings. No external targets should depend directly on + # this target *except* mojo/public/cpp/bindings and other *_cpp_sources + # targets. + source_set(cpp_sources_target_name) { + if (defined(invoker.visibility)) { + visibility = target_visibility + invoker.visibility + } + if (defined(invoker.testonly)) { + testonly = invoker.testonly + } + sources = process_file_template(invoker.sources, generator_cpp_outputs) + public_configs = + rebase_path([ "mojo/public/build/config:mojo_sdk" ], ".", mojo_root) + deps = [ + ":$generator_target_name", + ] + foreach(d, all_deps) { + # Resolve the name, so that a target //mojo/something becomes + # //mojo/something:something and we can append cpp_sources_suffix to + # get the cpp dependency name. + full_name = get_label_info(d, "label_no_toolchain") + deps += [ "${full_name}_${cpp_sources_suffix}" ] + } + } + } + if (is_android) { import("//build/config/android/rules.gni")
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py b/third_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py index 64fcc7a..0498838 100755 --- a/third_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py +++ b/third_party/mojo/src/mojo/public/tools/bindings/mojom_bindings_generator.py
@@ -195,7 +195,7 @@ help="output directory for generated files") parser.add_argument("-g", "--generators", dest="generators_string", metavar="GENERATORS", - default="c++,go,javascript,java,python", + default="c++,dart,go,javascript,java,python", help="comma-separated list of generators") parser.add_argument("--debug_print_intermediate", action="store_true", help="print the intermediate representation")
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py index 9c2763dd..666ef439 100644 --- a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py +++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator.py
@@ -56,6 +56,9 @@ def GetStructs(self): return map(partial(self._AddStructComputedData, True), self.module.structs) + def GetUnions(self): + return map(self._AddUnionComputedData, self.module.unions) + def GetInterfaces(self): return map(self._AddInterfaceComputedData, self.module.interfaces) @@ -91,6 +94,17 @@ struct.exported = exported return struct + def _AddUnionComputedData(self, union): + """Adds computed data to the given union. The data is computed once and + used repeatedly in the generation process.""" + ordinal = 0 + for field in union.fields: + if field.ordinal is not None: + ordinal = field.ordinal + field.ordinal = ordinal + ordinal += 1 + return union + def _AddInterfaceComputedData(self, interface): """Adds computed data to the given interface. The data is computed once and used repeatedly in the generation process."""
diff --git a/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator_unittest.py b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator_unittest.py new file mode 100644 index 0000000..9966b0b --- /dev/null +++ b/third_party/mojo/src/mojo/public/tools/bindings/pylib/mojom/generate/generator_unittest.py
@@ -0,0 +1,24 @@ +# 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 module as mojom +import generator + +class TestGenerator(unittest.TestCase): + + def testGetUnionsAddsOrdinals(self): + module = mojom.Module() + union = module.AddUnion('a') + union.AddField('a', mojom.BOOL) + union.AddField('b', mojom.BOOL) + union.AddField('c', mojom.BOOL, ordinal=10) + union.AddField('d', mojom.BOOL) + + gen = generator.Generator(module) + union = gen.GetUnions()[0] + ordinals = [field.ordinal for field in union.fields] + + self.assertEquals([0, 1, 10, 11], ordinals)
diff --git a/third_party/mojo/src/mojo/public/tools/dart_analyze.py b/third_party/mojo/src/mojo/public/tools/dart_analyze.py index cb80804..b90cbef 100755 --- a/third_party/mojo/src/mojo/public/tools/dart_analyze.py +++ b/third_party/mojo/src/mojo/public/tools/dart_analyze.py
@@ -29,6 +29,8 @@ # TODO: It seems like this should be re-enabled evenutally. re.compile(r'.*is a part and can not|^Only libraries can be analyzed'), + # TODO: Remove this once dev SDK includes Uri.directory constructor. + re.compile(r'.*The class \'Uri\' does not have a constructor \'directory\''), ] def _success(stamp_file):
diff --git a/third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn b/third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn index 2b29c1a..d3f7b78 100644 --- a/third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn +++ b/third_party/mojo_services/src/accessibility/public/interfaces/BUILD.gn
@@ -3,7 +3,7 @@ # found in the LICENSE file. import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") mojom("interfaces") { sources = [ @@ -13,6 +13,6 @@ import_dirs = [ get_path_info("../../../", "abspath") ] deps = [ - "../../../geometry/public/interfaces", + "//ui/mojo/geometry:interfaces", ] }
diff --git a/third_party/mojo_services/src/accessibility/public/interfaces/accessibility.mojom b/third_party/mojo_services/src/accessibility/public/interfaces/accessibility.mojom index 3958388..048d6399 100644 --- a/third_party/mojo_services/src/accessibility/public/interfaces/accessibility.mojom +++ b/third_party/mojo_services/src/accessibility/public/interfaces/accessibility.mojom
@@ -4,7 +4,7 @@ module mojo; -import "geometry/public/interfaces/geometry.mojom"; +import "ui/mojo/geometry/geometry.mojom"; interface AxProvider { GetTree() => (array<AxNode> nodes);
diff --git a/third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn b/third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn index 16fe33b..6ee9bb7 100644 --- a/third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn +++ b/third_party/mojo_services/src/clipboard/public/interfaces/BUILD.gn
@@ -3,7 +3,7 @@ # found in the LICENSE file. import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") mojom("interfaces") { sources = [
diff --git a/third_party/mojo_services/src/geometry/public/cpp/BUILD.gn b/third_party/mojo_services/src/geometry/public/cpp/BUILD.gn deleted file mode 100644 index c527c93a..0000000 --- a/third_party/mojo_services/src/geometry/public/cpp/BUILD.gn +++ /dev/null
@@ -1,18 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/mojo_sdk.gni") - -mojo_sdk_source_set("cpp") { - restrict_external_deps = false - public_configs = [ "../../../public/build/config:mojo_services" ] - sources = [ - "geometry_util.h", - ] - - deps = [ - "../interfaces", - ] -}
diff --git a/third_party/mojo_services/src/geometry/public/cpp/geometry_util.h b/third_party/mojo_services/src/geometry/public/cpp/geometry_util.h deleted file mode 100644 index f69fac3..0000000 --- a/third_party/mojo_services/src/geometry/public/cpp/geometry_util.h +++ /dev/null
@@ -1,39 +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 MOJO_SERVICES_GEOMETRY_PUBLIC_CPP_GEOMETRY_UTIL_H_ -#define MOJO_SERVICES_GEOMETRY_PUBLIC_CPP_GEOMETRY_UTIL_H_ - -#include "geometry/public/interfaces/geometry.mojom.h" - -namespace mojo { - -inline bool operator==(const Rect& lhs, const Rect& rhs) { - return lhs.x == rhs.x && lhs.y == rhs.y && lhs.width == rhs.width && - lhs.height == lhs.height; -} - -inline bool operator!=(const Rect& lhs, const Rect& rhs) { - return !(lhs == rhs); -} - -inline bool operator==(const Size& lhs, const Size& rhs) { - return lhs.width == rhs.width && lhs.height == rhs.height; -} - -inline bool operator!=(const Size& lhs, const Size& rhs) { - return !(lhs == rhs); -} - -inline bool operator==(const Point& lhs, const Point& rhs) { - return lhs.x == rhs.x && lhs.y == rhs.y; -} - -inline bool operator!=(const Point& lhs, const Point& rhs) { - return !(lhs == rhs); -} - -} - -#endif // MOJO_SERVICES_GEOMETRY_PUBLIC_CPP_GEOMETRY_UTIL_H_
diff --git a/third_party/mojo_services/src/geometry/public/interfaces/BUILD.gn b/third_party/mojo_services/src/geometry/public/interfaces/BUILD.gn deleted file mode 100644 index 9047ee2..0000000 --- a/third_party/mojo_services/src/geometry/public/interfaces/BUILD.gn +++ /dev/null
@@ -1,12 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "geometry.mojom", - ] -}
diff --git a/third_party/mojo_services/src/gpu/public/interfaces/BUILD.gn b/third_party/mojo_services/src/gpu/public/interfaces/BUILD.gn deleted file mode 100644 index ec061df..0000000 --- a/third_party/mojo_services/src/gpu/public/interfaces/BUILD.gn +++ /dev/null
@@ -1,22 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "command_buffer.mojom", - "context_provider.mojom", - "gpu.mojom", - "gpu_capabilities.mojom", - "viewport_parameter_listener.mojom", - ] - - import_dirs = [ get_path_info("../../../", "abspath") ] - - deps = [ - "../../../geometry/public/interfaces", - ] -}
diff --git a/third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom b/third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom deleted file mode 100644 index aa2c5567..0000000 --- a/third_party/mojo_services/src/gpu/public/interfaces/command_buffer.mojom +++ /dev/null
@@ -1,55 +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 mojo; - -import "gpu/public/interfaces/gpu_capabilities.mojom"; - -struct CommandBufferState { - int32 num_entries; - int32 get_offset; - int32 put_offset; - int32 token; - int32 error; // TODO(piman): enum - int32 context_lost_reason; // TODO(piman): enum - uint32 generation; -}; - -interface CommandBufferSyncClient { - DidInitialize(bool success, GpuCapabilities capabilities); - DidMakeProgress(CommandBufferState state); -}; - -interface CommandBufferSyncPointClient { - DidInsertSyncPoint(uint32 sync_point); -}; - -interface CommandBufferLostContextObserver { - DidLoseContext(int32 context_lost_reason); -}; - -interface CommandBuffer { - // Initialize attempts to initialize the command buffer. Success or failure - // will be communicated via the CommandBufferSyncClient DidInitialize() call. - // If the context is lost after creation the LostContext method on the - // CommandBufferLostContextObserver's will be called then this pipe will be - // closed. - Initialize(CommandBufferSyncClient sync_client, - CommandBufferSyncPointClient sync_point_client, - CommandBufferLostContextObserver lost_observer, - handle<shared_buffer> shared_state); - SetGetBuffer(int32 buffer); - Flush(int32 put_offset); - MakeProgress(int32 last_get_offset); - RegisterTransferBuffer( - int32 id, handle<shared_buffer> transfer_buffer, uint32 size); - DestroyTransferBuffer(int32 id); - - // InsertSyncPoint returns the sync point returned via DidInsertSyncPoint. - // If |retire| is true, the sync point is retired on insertion. Otherwise, - // explicitly call RetireSyncPoint to retire it. - InsertSyncPoint(bool retire); - RetireSyncPoint(uint32 sync_point); - Echo() => (); -};
diff --git a/third_party/mojo_services/src/gpu/public/interfaces/context_provider.mojom b/third_party/mojo_services/src/gpu/public/interfaces/context_provider.mojom deleted file mode 100644 index 59d3b7b8..0000000 --- a/third_party/mojo_services/src/gpu/public/interfaces/context_provider.mojom +++ /dev/null
@@ -1,28 +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. - -module mojo; - -import "gpu/public/interfaces/command_buffer.mojom"; -import "gpu/public/interfaces/viewport_parameter_listener.mojom"; - -// A ContextProvider can be used to provide new command buffers related to a -// particular context, for instance configured to draw to a particular display. -interface ContextProvider { - // This initializes a new command buffer for this provider when available, - // closing connections to the previously created command buffer (if any). - // - // This call may not return for an extended period of time if a command - // buffer cannot be produced immediately, for example if it is associated - // with a view that is offscreen. - // - // If a viewport_parameter_listener is provided it will notified be when - // vsync parameters change for this context. - // - // The returned handle will be null if no command buffer can be created for - // this request, for example if another request is made on the same provider - // before a previous call returns. - Create(ViewportParameterListener? viewport_parameter_listener) - => (CommandBuffer? gles2_client); -};
diff --git a/third_party/mojo_services/src/gpu/public/interfaces/gpu.mojom b/third_party/mojo_services/src/gpu/public/interfaces/gpu.mojom deleted file mode 100644 index d3deb46..0000000 --- a/third_party/mojo_services/src/gpu/public/interfaces/gpu.mojom +++ /dev/null
@@ -1,12 +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 mojo; - -import "gpu/public/interfaces/command_buffer.mojom"; - -interface Gpu { - // Creates a new offscreen OpenGL ES 2.0 context. - CreateOffscreenGLES2Context(CommandBuffer& gles2_client); -};
diff --git a/third_party/mojo_services/src/http_server/public/cpp/BUILD.gn b/third_party/mojo_services/src/http_server/public/cpp/BUILD.gn deleted file mode 100644 index 4fca6c7..0000000 --- a/third_party/mojo_services/src/http_server/public/cpp/BUILD.gn +++ /dev/null
@@ -1,24 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/mojo_sdk.gni") - -mojo_sdk_source_set("cpp") { - restrict_external_deps = false - public_configs = [ "../../../public/build/config:mojo_services" ] - sources = [ - "http_server_util.h", - "lib/http_server_util.cc", - ] - - deps = [ - "../interfaces", - ] - - mojo_sdk_deps = [ - "mojo/public/cpp/environment", - "mojo/public/cpp/system", - ] -}
diff --git a/third_party/mojo_services/src/http_server/public/cpp/http_server_util.h b/third_party/mojo_services/src/http_server/public/cpp/http_server_util.h deleted file mode 100644 index e2041e8a..0000000 --- a/third_party/mojo_services/src/http_server/public/cpp/http_server_util.h +++ /dev/null
@@ -1,17 +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 SERVICES_HTTP_SERVER_PUBLIC_HTTP_SERVER_UTIL_H_ -#define SERVICES_HTTP_SERVER_PUBLIC_HTTP_SERVER_UTIL_H_ - -#include "http_server/public/interfaces/http_response.mojom.h" - -namespace http_server { - -// Helper method to create an HttpResponse given the status code and body. -HttpResponsePtr CreateHttpResponse(uint32_t status_code, - const std::string& body); -} // namespace http_server - -#endif // SERVICES_HTTP_SERVER_PUBLIC_HTTP_SERVER_UTIL_H_
diff --git a/third_party/mojo_services/src/http_server/public/cpp/lib/http_server_util.cc b/third_party/mojo_services/src/http_server/public/cpp/lib/http_server_util.cc deleted file mode 100644 index 4307bea..0000000 --- a/third_party/mojo_services/src/http_server/public/cpp/lib/http_server_util.cc +++ /dev/null
@@ -1,33 +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 "http_server/public/cpp/http_server_util.h" - -#include "mojo/public/cpp/environment/logging.h" -#include "mojo/public/cpp/system/data_pipe.h" - -namespace http_server { - -HttpResponsePtr CreateHttpResponse(uint32_t status_code, - const std::string& body) { - HttpResponsePtr response = HttpResponse::New(); - - mojo::ScopedDataPipeProducerHandle producer_handle; - uint32_t num_bytes = static_cast<uint32_t>(body.size()); - MojoCreateDataPipeOptions options = {sizeof(MojoCreateDataPipeOptions), - MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, - 1, - num_bytes}; - MojoResult result = - CreateDataPipe(&options, &producer_handle, &response->body); - MOJO_DCHECK(MOJO_RESULT_OK == result); - result = WriteDataRaw(producer_handle.get(), body.c_str(), &num_bytes, - MOJO_WRITE_DATA_FLAG_ALL_OR_NONE); - MOJO_DCHECK(MOJO_RESULT_OK == result); - response->status_code = status_code; - response->content_length = num_bytes; - return response.Pass(); -} - -} // namespace http_server
diff --git a/third_party/mojo_services/src/http_server/public/interfaces/BUILD.gn b/third_party/mojo_services/src/http_server/public/interfaces/BUILD.gn deleted file mode 100644 index 79aa6a6..0000000 --- a/third_party/mojo_services/src/http_server/public/interfaces/BUILD.gn +++ /dev/null
@@ -1,27 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "http_request.mojom", - "http_response.mojom", - "http_server.mojom", - "http_server_factory.mojom", - ] - - import_dirs = [ get_path_info("../../../", "abspath") ] - - if (defined(mojo_network_service_root)) { - import_dirs += [ mojo_network_service_root ] - } else { - mojo_network_service_root = "../../.." - } - - deps = [ - "$mojo_network_service_root/network/public/interfaces", - ] -}
diff --git a/third_party/mojo_services/src/http_server/public/interfaces/http_request.mojom b/third_party/mojo_services/src/http_server/public/interfaces/http_request.mojom deleted file mode 100644 index 63759e3..0000000 --- a/third_party/mojo_services/src/http_server/public/interfaces/http_request.mojom +++ /dev/null
@@ -1,18 +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 http_server; - -struct HttpRequest { - string relative_url; // Starts with '/'. Example: "/test?query=foo" - - // The HTTP method if applicable. - string method = "GET"; - - // Additional HTTP request headers. - map<string, string>? headers; - - // The payload for the request body. Only set for "POST" or "PUT". - handle<data_pipe_consumer>? body; -};
diff --git a/third_party/mojo_services/src/http_server/public/interfaces/http_response.mojom b/third_party/mojo_services/src/http_server/public/interfaces/http_response.mojom deleted file mode 100644 index ccc3dae0..0000000 --- a/third_party/mojo_services/src/http_server/public/interfaces/http_response.mojom +++ /dev/null
@@ -1,22 +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 http_server; - -struct HttpResponse { - // The HTTP status code. - uint32 status_code = 200; - - // The payload for the response body. - handle<data_pipe_consumer>? body; - - // This must be the number of bytes in |body|. - int64 content_length = 0; - - // The content type. - string content_type = "text/html; charset=utf-8"; - - // Additional HTTP response headers. - map<string, string>? custom_headers; -};
diff --git a/third_party/mojo_services/src/http_server/public/interfaces/http_server.mojom b/third_party/mojo_services/src/http_server/public/interfaces/http_server.mojom deleted file mode 100644 index e510457..0000000 --- a/third_party/mojo_services/src/http_server/public/interfaces/http_server.mojom +++ /dev/null
@@ -1,27 +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 http_server; - -import "http_server/public/interfaces/http_request.mojom"; -import "http_server/public/interfaces/http_response.mojom"; - -interface HttpServer { - // Sets a handler for URLs matching a regex pattern. Handlers are considered - // in the order they were registered. - // - // Returns false if there was already a handler registered for the given - // pattern. - // - // To unregister a handler, destroy the underlying pipe. - SetHandler(string pattern, HttpHandler handler) => (bool success); - - // Returns the TCP port at which the server is running. This will not return - // until the server is ready, ie. listening for connections. - GetPort() => (uint16 port); -}; - -interface HttpHandler { - HandleRequest(HttpRequest request) => (HttpResponse response); -};
diff --git a/third_party/mojo_services/src/http_server/public/interfaces/http_server_factory.mojom b/third_party/mojo_services/src/http_server/public/interfaces/http_server_factory.mojom deleted file mode 100644 index 501c32e..0000000 --- a/third_party/mojo_services/src/http_server/public/interfaces/http_server_factory.mojom +++ /dev/null
@@ -1,27 +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. - -module http_server; - -import "http_server/public/interfaces/http_server.mojom"; -import "network/public/interfaces/net_address.mojom"; - -interface HttpServerFactory { - // Creates an http server running on the specified local network address. If - // |local_address| is null, it will take the default value of 0.0.0.0 at a - // system-allocated port. - // - // Note that the port value of 0 means that the operating system will pick - // one of available ports. You can use HttpServer::GetPort() to retrieve the - // allocated port. - // - // Only one backing server will be created for each local network address. It - // will be shared among clients, if more than one client requests a server - // running on a particular network address. - // - // TODO(ppi): would it be better to create a server only for the first caller - // and require the access to it to be explicitly shared by the party that - // requests it first? - CreateHttpServer(HttpServer& server_request, mojo.NetAddress? local_address); -};
diff --git a/third_party/mojo_services/src/input_events/public/interfaces/BUILD.gn b/third_party/mojo_services/src/input_events/public/interfaces/BUILD.gn deleted file mode 100644 index 5ef09eb..0000000 --- a/third_party/mojo_services/src/input_events/public/interfaces/BUILD.gn +++ /dev/null
@@ -1,20 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "input_event_constants.mojom", - "input_events.mojom", - "input_key_codes.mojom", - ] - - import_dirs = [ get_path_info("../../../", "abspath") ] - - deps = [ - "../../../geometry/public/interfaces", - ] -}
diff --git a/third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom b/third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom deleted file mode 100644 index 9fa36303..0000000 --- a/third_party/mojo_services/src/input_events/public/interfaces/input_events.mojom +++ /dev/null
@@ -1,78 +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 mojo; - -import "geometry/public/interfaces/geometry.mojom"; -import "input_events/public/interfaces/input_event_constants.mojom"; -import "input_events/public/interfaces/input_key_codes.mojom"; - -struct KeyData { - // The chromium event key code; these values are from the ui/ KeyCode enum, - // which has the fun property of being neither consistently the Windows key - // code, nor the X11 keycodes. (This value is consistent across platforms - // for basic ASCII characters; it will differ for modifiers. We don't define - // this as a mojo enum because mojom doesn't appear to have a platform - // dependent preprocessor yet.) - // - // TODO(erg): Remove this, and declare Win32 keycodes correct by fiat. We can - // not do this until we remove ui::Event usage from within mojo. - int32 key_code; - - // Whether this is a character event, and the character value if it is. Note - // that this is different than |text|, which holds a value even when there - // isn't actually a character to insert. (For example, |text| will be set and - // have a value on backspace, and |character| won't.) - bool is_char; - uint16 character; - - // The Win32 key code. Because of the web, this is the closest thing that we - // have to a cross platform key state. - KeyboardCode windows_key_code; - - // The platform specific key code. - // - // TODO(erg): This exists only for NPAPI support, pepper USB keyboard support - // and IME on android support. Theoretically, we should be able to remove this - // in the medium to long term. - int32 native_key_code; - - // The text generated by this keystroke. Corresponds to - // blink::WebKeyboardEvent::text. - uint16 text; - - // Like |text|, but unmodified by concurrently held modifier keys (except - // shift). Corresponds to blink::WebKeyboardEvent::unmodifiedText. - uint16 unmodified_text; -}; - -struct PointerData { - int32 pointer_id; - PointerKind kind; - // |x| and |y| are in the coordinate system of the View. - float x; - float y; - // |screen_x| and |screen_y| are in screen coordinates. - float screen_x; - float screen_y; - float pressure; - float radius_major; - float radius_minor; - float orientation; - // Used for devices that support wheels. Ranges from -1 to 1. - float horizontal_wheel; - float vertical_wheel; -}; - -struct Event { - // TODO(sky): rename to type. - EventType action; - // TODO(sky): parts of this should move to PointerData. - EventFlags flags; - // Time the event was delivered. The time is in milliseconds and corresponds - // to the uptime of the machine. - int64 time_stamp; - KeyData? key_data; - PointerData? pointer_data; -};
diff --git a/third_party/mojo_services/src/native_viewport/public/cpp/BUILD.gn b/third_party/mojo_services/src/native_viewport/public/cpp/BUILD.gn deleted file mode 100644 index 855de712..0000000 --- a/third_party/mojo_services/src/native_viewport/public/cpp/BUILD.gn +++ /dev/null
@@ -1,14 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/mojo_sdk.gni") - -mojo_sdk_source_set("args") { - public_configs = [ "../../../public/build/config:mojo_services" ] - sources = [ - "args.h", - "lib/args.cc", - ] -}
diff --git a/third_party/mojo_services/src/native_viewport/public/cpp/args.h b/third_party/mojo_services/src/native_viewport/public/cpp/args.h deleted file mode 100644 index 2bad98d..0000000 --- a/third_party/mojo_services/src/native_viewport/public/cpp/args.h +++ /dev/null
@@ -1,18 +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 MOJO_SERVICES_NATIVE_VIEWPORT_PUBLIC_CPP_ARGS_H_ -#define MOJO_SERVICES_NATIVE_VIEWPORT_PUBLIC_CPP_ARGS_H_ - -namespace mojo { - -// All args in alphabetical order. The switches should be documented -// alongside the definition of their values in the .cc file. -extern const char kUseHeadlessConfig[]; -extern const char kUseOSMesa[]; -extern const char kUseTestConfig[]; - -} // namespace mojo - -#endif // MOJO_SERVICES_NATIVE_VIEWPORT_PUBLIC_CPP_ARGS_H_
diff --git a/third_party/mojo_services/src/native_viewport/public/cpp/lib/args.cc b/third_party/mojo_services/src/native_viewport/public/cpp/lib/args.cc deleted file mode 100644 index 25ee1ae..0000000 --- a/third_party/mojo_services/src/native_viewport/public/cpp/lib/args.cc +++ /dev/null
@@ -1,17 +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 "native_viewport/public/cpp/args.h" - -namespace mojo { - -// Instead of using the system GL implementation, use OSMesa. -const char kUseOSMesa[] = "--use-osmesa"; -// Loads an app from the specified directory and launches it. -// Force gl to be initialized in test mode. -const char kUseTestConfig[] = "--use-test-config"; -// Create native viewport in headless mode. -const char kUseHeadlessConfig[] = "--use-headless-config"; - -} // namespace mojo
diff --git a/third_party/mojo_services/src/native_viewport/public/interfaces/BUILD.gn b/third_party/mojo_services/src/native_viewport/public/interfaces/BUILD.gn deleted file mode 100644 index 86ff870..0000000 --- a/third_party/mojo_services/src/native_viewport/public/interfaces/BUILD.gn +++ /dev/null
@@ -1,21 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "native_viewport.mojom", - ] - - import_dirs = [ get_path_info("../../../", "abspath") ] - - public_deps = [ - "../../../geometry/public/interfaces", - "../../../gpu/public/interfaces", - "../../../input_events/public/interfaces", - "../../../surfaces/public/interfaces:surface_id", - ] -}
diff --git a/third_party/mojo_services/src/native_viewport/public/interfaces/native_viewport.mojom b/third_party/mojo_services/src/native_viewport/public/interfaces/native_viewport.mojom deleted file mode 100644 index 21cace630..0000000 --- a/third_party/mojo_services/src/native_viewport/public/interfaces/native_viewport.mojom +++ /dev/null
@@ -1,41 +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 mojo; - -import "geometry/public/interfaces/geometry.mojom"; -import "gpu/public/interfaces/context_provider.mojom"; -import "input_events/public/interfaces/input_events.mojom"; - -struct ViewportMetrics { - Size size; - float device_pixel_ratio = 1.0; -}; - -interface NativeViewport { - // TODO(sky): having a create function is awkward. Should there be a factory - // to create the NativeViewport that takes the size? - Create(Size size) => (ViewportMetrics metrics); - - Show(); - Hide(); - Close(); - SetSize(Size size); - SetEventDispatcher(NativeViewportEventDispatcher dispatcher); - - // Requests a ContextProvider capable of producing contexts that draw to - // this native viewport. - GetContextProvider(ContextProvider& provider); - - // The initial viewport metrics will be sent in the reply to the Create - // method. Call RequestMetrics() to receive updates when the viewport metrics - // change. The reply will be sent when the viewport metrics are different from - // the values last sent, so to receive continuous updates call this method - // again after receiving the callback. - RequestMetrics() => (ViewportMetrics metrics); -}; - -interface NativeViewportEventDispatcher { - OnEvent(Event event) => (); -};
diff --git a/third_party/mojo_services/src/navigation/public/interfaces/BUILD.gn b/third_party/mojo_services/src/navigation/public/interfaces/BUILD.gn deleted file mode 100644 index 19b9f8a..0000000 --- a/third_party/mojo_services/src/navigation/public/interfaces/BUILD.gn +++ /dev/null
@@ -1,24 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "navigation.mojom", - ] - - import_dirs = [ get_path_info("../../../", "abspath") ] - - if (defined(mojo_network_service_root)) { - import_dirs += [ mojo_network_service_root ] - } else { - mojo_network_service_root = "../../.." - } - - deps = [ - "$mojo_network_service_root/network/public/interfaces", - ] -}
diff --git a/third_party/mojo_services/src/surfaces/public/interfaces/BUILD.gn b/third_party/mojo_services/src/surfaces/public/interfaces/BUILD.gn deleted file mode 100644 index 7902a7a..0000000 --- a/third_party/mojo_services/src/surfaces/public/interfaces/BUILD.gn +++ /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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "display.mojom", - "quads.mojom", - "surfaces.mojom", - ] - - import_dirs = [ get_path_info("../../../", "abspath") ] - - deps = [ - ":surface_id", - "../../../geometry/public/interfaces", - "../../../gpu/public/interfaces", - "../../../native_viewport/public/interfaces", - ] -} - -mojom("surface_id") { - sources = [ - "surface_id.mojom", - ] -}
diff --git a/third_party/mojo_services/src/surfaces/public/interfaces/display.mojom b/third_party/mojo_services/src/surfaces/public/interfaces/display.mojom deleted file mode 100644 index cee3014b..0000000 --- a/third_party/mojo_services/src/surfaces/public/interfaces/display.mojom +++ /dev/null
@@ -1,33 +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. - -module mojo; - -import "gpu/public/interfaces/context_provider.mojom"; -import "gpu/public/interfaces/viewport_parameter_listener.mojom"; -import "surfaces/public/interfaces/surfaces.mojom"; - -interface Display { - // Submits a new frame to the display to be drawn when possible. The callback - // will be run after the frame has been issued to the display but possibly - // before the frame is actually visible. - // - // The Display will be resized to the size of the last entry in |frame|'s - // |passes| list (aka the root pass). - // - // Any resources submitted in the frame will be returned via the - // ResourceReturner associated with the Display at construction time. - SubmitFrame(Frame frame) => (); -}; - -// DisplayFactory creates new Display instances. -interface DisplayFactory { - // Create associates a Display that will draw to contexts produced by - // |context_provider|. Any resources submitted to the display will be - // returned via the |returner|, if supplied. - Create(ContextProvider context_provider, - ResourceReturner? returner, - Display& display_request); -}; -
diff --git a/third_party/mojo_services/src/surfaces/public/interfaces/quads.mojom b/third_party/mojo_services/src/surfaces/public/interfaces/quads.mojom deleted file mode 100644 index 3022df0a..0000000 --- a/third_party/mojo_services/src/surfaces/public/interfaces/quads.mojom +++ /dev/null
@@ -1,212 +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 mojo; - -import "geometry/public/interfaces/geometry.mojom"; -import "surfaces/public/interfaces/surface_id.mojom"; - -struct Color { - uint32 rgba; -}; - -// TODO(jamesr): Populate subtype fields. -struct CheckerboardQuadState {}; - -struct DebugBorderQuadState {}; - -struct IoSurfaceContentQuadState {}; - -struct RenderPassId { - int32 layer_id; - int32 index; -}; - -struct RenderPassQuadState { - RenderPassId render_pass_id; - - // If nonzero, resource id of mask to use when drawing this pass. - uint32 mask_resource_id; - PointF mask_uv_scale; - Size mask_texture_size; - - // Post-processing filters, applied to the pixels in the render pass' texture. - // TODO(jamesr): Support - // FilterOperations filters; - - // The scale from layer space of the root layer of the render pass to - // the render pass physical pixels. This scale is applied to the filter - // parameters for pixel-moving filters. This scale should include - // content-to-target-space scale, and device pixel ratio. - PointF filters_scale; - - // Post-processing filters, applied to the pixels showing through the - // background of the render pass, from behind it. - // TODO(jamesr): Support - // FilterOperations background_filters; -}; - -struct SolidColorQuadState { - Color color; - bool force_anti_aliasing_off; -}; - -struct SurfaceQuadState { - SurfaceId surface; -}; - -struct TextureQuadState { - uint32 resource_id; - bool premultiplied_alpha; - PointF uv_top_left; - PointF uv_bottom_right; - Color background_color; - array<float, 4> vertex_opacity; - bool flipped; - bool nearest_neighbor; -}; - -struct TileQuadState { - RectF tex_coord_rect; - Size texture_size; - bool swizzle_contents; - uint32 resource_id; - bool nearest_neighbor; -}; - -struct StreamVideoQuadState {}; - -enum YUVColorSpace { - REC_601, // SDTV standard with restricted "studio swing" color range. - REC_709, // HDTV standard with restricted "studio swing" color range. - JPEG, // Full color range [0, 255] JPEG color space. -}; - -struct YUVVideoQuadState { - RectF tex_coord_rect; - uint32 y_plane_resource_id; - uint32 u_plane_resource_id; - uint32 v_plane_resource_id; - uint32 a_plane_resource_id; - YUVColorSpace color_space; -}; - -enum Material { - CHECKERBOARD = 1, - DEBUG_BORDER, - IO_SURFACE_CONTENT, - PICTURE_CONTENT, - RENDER_PASS, - SOLID_COLOR, - STREAM_VIDEO_CONTENT, - SURFACE_CONTENT, - TEXTURE_CONTENT, - TILED_CONTENT, - YUV_VIDEO_CONTENT, -}; - -struct Quad { - Material material; - - // This rect, after applying the quad_transform(), gives the geometry that - // this quad should draw to. This rect lives in content space. - Rect rect; - - // This specifies the region of the quad that is opaque. This rect lives in - // content space. - Rect opaque_rect; - - // Allows changing the rect that gets drawn to make it smaller. This value - // should be clipped to |rect|. This rect lives in content space. - Rect visible_rect; - - // Allows changing the rect that gets drawn to make it smaller. This value - // should be clipped to |rect|. This rect lives in content space. - bool needs_blending; - - // Index into the containing pass' shared quad state array which has state - // (transforms etc) shared by multiple quads. - uint32 shared_quad_state_index; - - // Only one of the following will be set, depending on the material. - CheckerboardQuadState? checkerboard_quad_state; - DebugBorderQuadState? debug_border_quad_state; - IoSurfaceContentQuadState? io_surface_quad_state; - RenderPassQuadState? render_pass_quad_state; - SolidColorQuadState? solid_color_quad_state; - SurfaceQuadState? surface_quad_state; - TextureQuadState? texture_quad_state; - TileQuadState? tile_quad_state; - StreamVideoQuadState? stream_video_quad_state; - YUVVideoQuadState? yuv_video_quad_state; -}; - -enum SkXfermode { - kClear_Mode = 0, //!< [0, 0] - kSrc_Mode, //!< [Sa, Sc] - kDst_Mode, //!< [Da, Dc] - kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Sc + (1 - Sa)*Dc] - kDstOver_Mode, //!< [Sa + Da - Sa*Da, Rc = Dc + (1 - Da)*Sc] - kSrcIn_Mode, //!< [Sa * Da, Sc * Da] - kDstIn_Mode, //!< [Sa * Da, Sa * Dc] - kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] - kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] - kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] - kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] - kXor_Mode, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] - kPlus_Mode, //!< [Sa + Da, Sc + Dc] - kModulate_Mode, // multiplies all components (= alpha and color) - - // Following blend modes are defined in the CSS Compositing standard: - // https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blending - kScreen_Mode, - kLastCoeffMode = kScreen_Mode, - - kOverlay_Mode, - kDarken_Mode, - kLighten_Mode, - kColorDodge_Mode, - kColorBurn_Mode, - kHardLight_Mode, - kSoftLight_Mode, - kDifference_Mode, - kExclusion_Mode, - kMultiply_Mode, - kLastSeparableMode = kMultiply_Mode, - - kHue_Mode, - kSaturation_Mode, - kColor_Mode, - kLuminosity_Mode, - kLastMode = kLuminosity_Mode -}; - -struct SharedQuadState { - // Transforms from quad's original content space to its target content space. - Transform content_to_target_transform; - - // This size lives in the content space for the quad's originating layer. - Size content_bounds; - - // This rect lives in the content space for the quad's originating layer. - Rect visible_content_rect; - - // This rect lives in the target content space. - Rect clip_rect; - - bool is_clipped; - float opacity; - SkXfermode blend_mode; - int32 sorting_context_id; -}; - -struct Pass { - RenderPassId id; - Rect output_rect; - Rect damage_rect; - Transform transform_to_root_target; - bool has_transparent_background; - array<Quad> quads; - array<SharedQuadState> shared_quad_states; -};
diff --git a/third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom b/third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom deleted file mode 100644 index 8248469..0000000 --- a/third_party/mojo_services/src/surfaces/public/interfaces/surfaces.mojom +++ /dev/null
@@ -1,77 +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 mojo; - -import "geometry/public/interfaces/geometry.mojom"; -import "surfaces/public/interfaces/quads.mojom"; -import "surfaces/public/interfaces/surface_id.mojom"; - -enum ResourceFormat { - RGBA_8888, - RGBA_4444, - BGRA_8888, - ALPHA_8, - LUMINANCE_8, - RGB_565, - ETC1, -}; - -struct Mailbox { - array<int8, 64> name; -}; - -struct MailboxHolder { - Mailbox mailbox; - uint32 texture_target; - uint32 sync_point; -}; - -struct TransferableResource { - uint32 id; - ResourceFormat format; - uint32 filter; - Size size; - MailboxHolder mailbox_holder; - bool is_repeated; - bool is_software; -}; - -struct ReturnedResource { - uint32 id; - uint32 sync_point; - int32 count; - bool lost; -}; - -struct Frame { - array<TransferableResource> resources; - array<Pass> passes; -}; - -interface ResourceReturner { - ReturnResources(array<ReturnedResource> resources); -}; - -interface Surface { - // Request the id namespace for this connection. Fully qualified surface ids - // are the combination of the id_namespace for the connection that created the - // surface and the id_local component allocated by the caller. - GetIdNamespace() => (uint32 id_namespace); - - // Sets a ResourceReturner that will receive unused resources. - SetResourceReturner(ResourceReturner returner); - - // Creates a new surface with the given local identifier. Once a surface is - // created the caller may submit frames to it or destroy it using the local - // identifier. The caller can also produce a fully qualified surface id that - // can be embedded in frames produces by different connections. - CreateSurface(uint32 id_local); - - // After the submitted frame is drawn for the first time, the surface will - // respond to the SubmitFrame message. Clients should use this acknowledgement - // to ratelimit frame submissions. - SubmitFrame(uint32 id_local, Frame frame) => (); - DestroySurface(uint32 id_local); -};
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/BUILD.gn b/third_party/mojo_services/src/view_manager/public/cpp/BUILD.gn deleted file mode 100644 index cbab611..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/BUILD.gn +++ /dev/null
@@ -1,62 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/mojo_sdk.gni") - -mojo_sdk_source_set("cpp") { - restrict_external_deps = false - public_configs = [ "../../../public/build/config:mojo_services" ] - sources = [ - "lib/view.cc", - "lib/view_manager_client_factory.cc", - "lib/view_manager_client_impl.cc", - "lib/view_manager_client_impl.h", - "lib/view_manager_context.cc", - "lib/view_observer.cc", - "lib/view_private.cc", - "lib/view_private.h", - "view.h", - "view_manager.h", - "view_manager_client_factory.h", - "view_manager_context.h", - "view_manager_delegate.cc", - "view_manager_delegate.h", - "view_observer.h", - "view_property.h", - "view_tracker.cc", - "view_tracker.h", - ] - - public_deps = [ - ":common", - ] - - deps = [ - "../interfaces", - "../../../geometry/public/interfaces", - "../../../input_events/public/interfaces", - "../../../surfaces/public/interfaces:surface_id", - "../../../window_manager/public/interfaces", - "//base", - ] - - mojo_sdk_deps = [ - "mojo/public/c/gles2:headers", - "mojo/public/cpp/application", - "mojo/public/cpp/bindings:bindings", - "mojo/public/cpp/system", - "mojo/public/interfaces/application", - ] -} - -source_set("common") { - configs += [ "../../../public/build/config:mojo_services" ] - - sources = [ - "keys.cc", - "keys.h", - "types.h", - ] -}
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/keys.cc b/third_party/mojo_services/src/view_manager/public/cpp/keys.cc deleted file mode 100644 index 5ed54ef..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/keys.cc +++ /dev/null
@@ -1,12 +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 "view_manager/public/cpp/keys.h" - -namespace mojo { - -extern const char kViewManagerKeyWantsTouchEvents[] = - "view-manager-key-wants-touch-events"; - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/keys.h b/third_party/mojo_services/src/view_manager/public/cpp/keys.h deleted file mode 100644 index 77ca346f..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/keys.h +++ /dev/null
@@ -1,14 +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. - -#ifndef MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_KEYS_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_KEYS_H_ - -namespace mojo { - -extern const char kViewManagerKeyWantsTouchEvents[]; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_KEYS_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view.cc deleted file mode 100644 index 9ed458c7..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view.cc +++ /dev/null
@@ -1,589 +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 "view_manager/public/cpp/view.h" - -#include <set> -#include <string> - -#include "mojo/public/cpp/application/service_provider_impl.h" -#include "view_manager/public/cpp/lib/view_manager_client_impl.h" -#include "view_manager/public/cpp/lib/view_private.h" -#include "view_manager/public/cpp/view_observer.h" -#include "view_manager/public/cpp/view_tracker.h" - -namespace mojo { - -namespace { - -void NotifyViewTreeChangeAtReceiver( - View* receiver, - const ViewObserver::TreeChangeParams& params, - bool change_applied) { - ViewObserver::TreeChangeParams local_params = params; - local_params.receiver = receiver; - if (change_applied) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(receiver).observers(), - OnTreeChanged(local_params)); - } else { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(receiver).observers(), - OnTreeChanging(local_params)); - } -} - -void NotifyViewTreeChangeUp( - View* start_at, - const ViewObserver::TreeChangeParams& params, - bool change_applied) { - for (View* current = start_at; current; current = current->parent()) - NotifyViewTreeChangeAtReceiver(current, params, change_applied); -} - -void NotifyViewTreeChangeDown( - View* start_at, - const ViewObserver::TreeChangeParams& params, - bool change_applied) { - NotifyViewTreeChangeAtReceiver(start_at, params, change_applied); - View::Children::const_iterator it = start_at->children().begin(); - for (; it != start_at->children().end(); ++it) - NotifyViewTreeChangeDown(*it, params, change_applied); -} - -void NotifyViewTreeChange( - const ViewObserver::TreeChangeParams& params, - bool change_applied) { - NotifyViewTreeChangeDown(params.target, params, change_applied); - if (params.old_parent) - NotifyViewTreeChangeUp(params.old_parent, params, change_applied); - if (params.new_parent) - NotifyViewTreeChangeUp(params.new_parent, params, change_applied); -} - -class ScopedTreeNotifier { - public: - ScopedTreeNotifier(View* target, View* old_parent, View* new_parent) { - params_.target = target; - params_.old_parent = old_parent; - params_.new_parent = new_parent; - NotifyViewTreeChange(params_, false); - } - ~ScopedTreeNotifier() { - NotifyViewTreeChange(params_, true); - } - - private: - ViewObserver::TreeChangeParams params_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier); -}; - -void RemoveChildImpl(View* child, View::Children* children) { - View::Children::iterator it = - std::find(children->begin(), children->end(), child); - if (it != children->end()) { - children->erase(it); - ViewPrivate(child).ClearParent(); - } -} - -class ScopedOrderChangedNotifier { - public: - ScopedOrderChangedNotifier(View* view, - View* relative_view, - OrderDirection direction) - : view_(view), - relative_view_(relative_view), - direction_(direction) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(view_).observers(), - OnViewReordering(view_, relative_view_, direction_)); - } - ~ScopedOrderChangedNotifier() { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(view_).observers(), - OnViewReordered(view_, relative_view_, direction_)); - } - - private: - View* view_; - View* relative_view_; - OrderDirection direction_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedOrderChangedNotifier); -}; - -// Returns true if the order actually changed. -bool ReorderImpl(View::Children* children, - View* view, - View* relative, - OrderDirection direction) { - DCHECK(relative); - DCHECK_NE(view, relative); - DCHECK_EQ(view->parent(), relative->parent()); - - const size_t child_i = - std::find(children->begin(), children->end(), view) - children->begin(); - const size_t target_i = - std::find(children->begin(), children->end(), relative) - - children->begin(); - if ((direction == ORDER_DIRECTION_ABOVE && child_i == target_i + 1) || - (direction == ORDER_DIRECTION_BELOW && child_i + 1 == target_i)) { - return false; - } - - ScopedOrderChangedNotifier notifier(view, relative, direction); - - const size_t dest_i = direction == ORDER_DIRECTION_ABOVE - ? (child_i < target_i ? target_i : target_i + 1) - : (child_i < target_i ? target_i - 1 : target_i); - children->erase(children->begin() + child_i); - children->insert(children->begin() + dest_i, view); - - return true; -} - -class ScopedSetBoundsNotifier { - public: - ScopedSetBoundsNotifier(View* view, - const Rect& old_bounds, - const Rect& new_bounds) - : view_(view), - old_bounds_(old_bounds), - new_bounds_(new_bounds) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(view_).observers(), - OnViewBoundsChanging(view_, old_bounds_, new_bounds_)); - } - ~ScopedSetBoundsNotifier() { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(view_).observers(), - OnViewBoundsChanged(view_, old_bounds_, new_bounds_)); - } - - private: - View* view_; - const Rect old_bounds_; - const Rect new_bounds_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsNotifier); -}; - -// Some operations are only permitted in the connection that created the view. -bool OwnsView(ViewManager* manager, View* view) { - return !manager || - static_cast<ViewManagerClientImpl*>(manager)->OwnsView(view->id()); -} - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// View, public: - -void View::Destroy() { - if (!OwnsView(manager_, this)) - return; - - if (manager_) - static_cast<ViewManagerClientImpl*>(manager_)->DestroyView(id_); - while (!children_.empty()) { - View* child = children_.front(); - if (!OwnsView(manager_, child)) { - ViewPrivate(child).ClearParent(); - children_.erase(children_.begin()); - } else { - child->Destroy(); - DCHECK(std::find(children_.begin(), children_.end(), child) == - children_.end()); - } - } - LocalDestroy(); -} - -void View::SetBounds(const Rect& bounds) { - if (!OwnsView(manager_, this)) - return; - - if (bounds_.Equals(bounds)) - return; - - if (manager_) - static_cast<ViewManagerClientImpl*>(manager_)->SetBounds(id_, bounds); - LocalSetBounds(bounds_, bounds); -} - -void View::SetVisible(bool value) { - if (visible_ == value) - return; - - if (manager_) - static_cast<ViewManagerClientImpl*>(manager_)->SetVisible(id_, value); - LocalSetVisible(value); -} - -void View::SetSharedProperty(const std::string& name, - const std::vector<uint8_t>* value) { - std::vector<uint8_t> old_value; - std::vector<uint8_t>* old_value_ptr = nullptr; - auto it = properties_.find(name); - if (it != properties_.end()) { - old_value = it->second; - old_value_ptr = &old_value; - - if (value && old_value == *value) - return; - } else if (!value) { - // This property isn't set in |properties_| and |value| is NULL, so there's - // no change. - return; - } - - if (value) { - properties_[name] = *value; - } else if (it != properties_.end()) { - properties_.erase(it); - } - - // TODO: add test coverage of this (450303). - if (manager_) { - Array<uint8_t> transport_value; - if (value) { - transport_value.resize(value->size()); - if (value->size()) - memcpy(&transport_value.front(), &(value->front()), value->size()); - } - static_cast<ViewManagerClientImpl*>(manager_)->SetProperty( - id_, name, transport_value.Pass()); - } - - FOR_EACH_OBSERVER( - ViewObserver, observers_, - OnViewSharedPropertyChanged(this, name, old_value_ptr, value)); -} - -bool View::IsDrawn() const { - if (!visible_) - return false; - return parent_ ? parent_->IsDrawn() : drawn_; -} - -void View::AddObserver(ViewObserver* observer) { - observers_.AddObserver(observer); -} - -void View::RemoveObserver(ViewObserver* observer) { - observers_.RemoveObserver(observer); -} - -const View* View::GetRoot() const { - const View* root = this; - for (const View* parent = this; parent; parent = parent->parent()) - root = parent; - return root; -} - -void View::AddChild(View* child) { - // TODO(beng): not necessarily valid to all connections, but possibly to the - // embeddee in an embedder-embeddee relationship. - if (manager_) - CHECK_EQ(child->view_manager(), manager_); - LocalAddChild(child); - if (manager_) - static_cast<ViewManagerClientImpl*>(manager_)->AddChild(child->id(), id_); -} - -void View::RemoveChild(View* child) { - // TODO(beng): not necessarily valid to all connections, but possibly to the - // embeddee in an embedder-embeddee relationship. - if (manager_) - CHECK_EQ(child->view_manager(), manager_); - LocalRemoveChild(child); - if (manager_) { - static_cast<ViewManagerClientImpl*>(manager_)->RemoveChild(child->id(), - id_); - } -} - -void View::MoveToFront() { - if (!parent_ || parent_->children_.back() == this) - return; - Reorder(parent_->children_.back(), ORDER_DIRECTION_ABOVE); -} - -void View::MoveToBack() { - if (!parent_ || parent_->children_.front() == this) - return; - Reorder(parent_->children_.front(), ORDER_DIRECTION_BELOW); -} - -void View::Reorder(View* relative, OrderDirection direction) { - if (!LocalReorder(relative, direction)) - return; - if (manager_) { - static_cast<ViewManagerClientImpl*>(manager_)->Reorder(id_, - relative->id(), - direction); - } -} - -bool View::Contains(View* child) const { - if (!child) - return false; - if (child == this) - return true; - if (manager_) - CHECK_EQ(child->view_manager(), manager_); - for (View* p = child->parent(); p; p = p->parent()) { - if (p == this) - return true; - } - return false; -} - -View* View::GetChildById(Id id) { - if (id == id_) - return this; - // TODO(beng): this could be improved depending on how we decide to own views. - Children::const_iterator it = children_.begin(); - for (; it != children_.end(); ++it) { - View* view = (*it)->GetChildById(id); - if (view) - return view; - } - return NULL; -} - -void View::SetSurfaceId(SurfaceIdPtr id) { - if (manager_) { - static_cast<ViewManagerClientImpl*>(manager_)->SetSurfaceId(id_, id.Pass()); - } -} - -void View::SetFocus() { - if (manager_) - static_cast<ViewManagerClientImpl*>(manager_)->SetFocus(id_); -} - -void View::Embed(const String& url) { - static_cast<ViewManagerClientImpl*>(manager_)->Embed(url, id_); -} - -void View::Embed(const String& url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) { - static_cast<ViewManagerClientImpl*>(manager_) - ->Embed(url, id_, services.Pass(), exposed_services.Pass()); -} - -void View::Embed(ViewManagerClientPtr client) { - static_cast<ViewManagerClientImpl*>(manager_)->Embed(id_, client.Pass()); -} - -//////////////////////////////////////////////////////////////////////////////// -// View, protected: - -namespace { - -ViewportMetricsPtr CreateEmptyViewportMetrics() { - ViewportMetricsPtr metrics = ViewportMetrics::New(); - metrics->size = Size::New(); - // TODO(vtl): The |.Pass()| below is only needed due to an MSVS bug; remove it - // once that's fixed. - return metrics.Pass(); -} - -} // namespace - -View::View() - : manager_(NULL), - id_(static_cast<Id>(-1)), - parent_(NULL), - viewport_metrics_(CreateEmptyViewportMetrics()), - visible_(true), - drawn_(false) { -} - -View::~View() { - FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDestroying(this)); - if (parent_) - parent_->LocalRemoveChild(this); - - // We may still have children. This can happen if the embedder destroys the - // root while we're still alive. - while (!children_.empty()) { - View* child = children_.front(); - LocalRemoveChild(child); - DCHECK(children_.empty() || children_.front() != child); - } - - // TODO(beng): It'd be better to do this via a destruction observer in the - // ViewManagerClientImpl. - if (manager_) - static_cast<ViewManagerClientImpl*>(manager_)->RemoveView(id_); - - // Clear properties. - for (auto& pair : prop_map_) { - if (pair.second.deallocator) - (*pair.second.deallocator)(pair.second.value); - } - prop_map_.clear(); - - FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDestroyed(this)); -} - -//////////////////////////////////////////////////////////////////////////////// -// View, private: - -View::View(ViewManager* manager, Id id) - : manager_(manager), - id_(id), - parent_(nullptr), - viewport_metrics_(CreateEmptyViewportMetrics()), - visible_(false), - drawn_(false) { -} - -int64 View::SetLocalPropertyInternal(const void* key, - const char* name, - PropertyDeallocator deallocator, - int64 value, - int64 default_value) { - int64 old = GetLocalPropertyInternal(key, default_value); - if (value == default_value) { - prop_map_.erase(key); - } else { - Value prop_value; - prop_value.name = name; - prop_value.value = value; - prop_value.deallocator = deallocator; - prop_map_[key] = prop_value; - } - FOR_EACH_OBSERVER(ViewObserver, observers_, - OnViewLocalPropertyChanged(this, key, old)); - return old; -} - -int64 View::GetLocalPropertyInternal(const void* key, - int64 default_value) const { - std::map<const void*, Value>::const_iterator iter = prop_map_.find(key); - if (iter == prop_map_.end()) - return default_value; - return iter->second.value; -} - -void View::LocalDestroy() { - delete this; -} - -void View::LocalAddChild(View* child) { - ScopedTreeNotifier notifier(child, child->parent(), this); - if (child->parent()) - RemoveChildImpl(child, &child->parent_->children_); - children_.push_back(child); - child->parent_ = this; -} - -void View::LocalRemoveChild(View* child) { - DCHECK_EQ(this, child->parent()); - ScopedTreeNotifier notifier(child, this, NULL); - RemoveChildImpl(child, &children_); -} - -bool View::LocalReorder(View* relative, OrderDirection direction) { - return ReorderImpl(&parent_->children_, this, relative, direction); -} - -void View::LocalSetBounds(const Rect& old_bounds, - const Rect& new_bounds) { - DCHECK(old_bounds.x == bounds_.x); - DCHECK(old_bounds.y == bounds_.y); - DCHECK(old_bounds.width == bounds_.width); - DCHECK(old_bounds.height == bounds_.height); - ScopedSetBoundsNotifier notifier(this, old_bounds, new_bounds); - bounds_ = new_bounds; -} - -void View::LocalSetViewportMetrics(const ViewportMetrics& old_metrics, - const ViewportMetrics& new_metrics) { - // TODO(eseidel): We could check old_metrics against viewport_metrics_. - viewport_metrics_ = new_metrics.Clone(); - FOR_EACH_OBSERVER( - ViewObserver, observers_, - OnViewViewportMetricsChanged(this, old_metrics, new_metrics)); -} - -void View::LocalSetDrawn(bool value) { - if (drawn_ == value) - return; - - // As IsDrawn() is derived from |visible_| and |drawn_|, only send drawn - // notification is the value of IsDrawn() is really changing. - if (IsDrawn() == value) { - drawn_ = value; - return; - } - FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDrawnChanging(this)); - drawn_ = value; - FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewDrawnChanged(this)); -} - -void View::LocalSetVisible(bool visible) { - if (visible_ == visible) - return; - - FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanging(this)); - visible_ = visible; - NotifyViewVisibilityChanged(this); -} - -void View::NotifyViewVisibilityChanged(View* target) { - if (!NotifyViewVisibilityChangedDown(target)) { - return; // |this| has been deleted. - } - NotifyViewVisibilityChangedUp(target); -} - -bool View::NotifyViewVisibilityChangedAtReceiver(View* target) { - // |this| may be deleted during a call to OnViewVisibilityChanged() on one - // of the observers. We create an local observer for that. In that case we - // exit without further access to any members. - ViewTracker tracker; - tracker.Add(this); - FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChanged(target)); - return tracker.Contains(this); -} - -bool View::NotifyViewVisibilityChangedDown(View* target) { - if (!NotifyViewVisibilityChangedAtReceiver(target)) - return false; // |this| was deleted. - std::set<const View*> child_already_processed; - bool child_destroyed = false; - do { - child_destroyed = false; - for (View::Children::const_iterator it = children_.begin(); - it != children_.end(); ++it) { - if (!child_already_processed.insert(*it).second) - continue; - if (!(*it)->NotifyViewVisibilityChangedDown(target)) { - // |*it| was deleted, |it| is invalid and |children_| has changed. We - // exit the current for-loop and enter a new one. - child_destroyed = true; - break; - } - } - } while (child_destroyed); - return true; -} - -void View::NotifyViewVisibilityChangedUp(View* target) { - // Start with the parent as we already notified |this| - // in NotifyViewVisibilityChangedDown. - for (View* view = parent(); view; view = view->parent()) { - bool ret = view->NotifyViewVisibilityChangedAtReceiver(target); - DCHECK(ret); - } -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_factory.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_factory.cc deleted file mode 100644 index bb39fc9..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_factory.cc +++ /dev/null
@@ -1,42 +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 "view_manager/public/cpp/view_manager_client_factory.h" - -#include "mojo/public/interfaces/application/shell.mojom.h" -#include "view_manager/public/cpp/lib/view_manager_client_impl.h" - -namespace mojo { - -ViewManagerClientFactory::ViewManagerClientFactory( - Shell* shell, - ViewManagerDelegate* delegate) - : shell_(shell), delegate_(delegate) { -} - -ViewManagerClientFactory::~ViewManagerClientFactory() { -} - -// static -ViewManagerClient* ViewManagerClientFactory::WeakBindViewManagerToPipe( - InterfaceRequest<ViewManagerClient> request, - ViewManagerServicePtr view_manager_service, - Shell* shell, - ViewManagerDelegate* delegate) { - const bool delete_on_error = false; - auto client = new ViewManagerClientImpl(delegate, shell, request.Pass(), - delete_on_error); - client->SetViewManagerService(view_manager_service.Pass()); - return client; -} - -// InterfaceFactory<ViewManagerClient> implementation. -void ViewManagerClientFactory::Create( - ApplicationConnection* connection, - InterfaceRequest<ViewManagerClient> request) { - const bool delete_on_error = true; - new ViewManagerClientImpl(delegate_, shell_, request.Pass(), delete_on_error); -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.cc deleted file mode 100644 index 77dc293f..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.cc +++ /dev/null
@@ -1,511 +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 "view_manager/public/cpp/lib/view_manager_client_impl.h" - -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/application/connect.h" -#include "mojo/public/cpp/application/service_provider_impl.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" -#include "mojo/public/interfaces/application/shell.mojom.h" -#include "view_manager/public/cpp/lib/view_private.h" -#include "view_manager/public/cpp/util.h" -#include "view_manager/public/cpp/view_manager_delegate.h" -#include "view_manager/public/cpp/view_observer.h" - -namespace mojo { - -Id MakeTransportId(ConnectionSpecificId connection_id, - ConnectionSpecificId local_id) { - return (connection_id << 16) | local_id; -} - -// Helper called to construct a local view object from transport data. -View* AddViewToViewManager(ViewManagerClientImpl* client, - View* parent, - const ViewDataPtr& view_data) { - // We don't use the ctor that takes a ViewManager here, since it will call - // back to the service and attempt to create a new view. - View* view = ViewPrivate::LocalCreate(); - ViewPrivate private_view(view); - private_view.set_view_manager(client); - private_view.set_id(view_data->view_id); - private_view.set_visible(view_data->visible); - private_view.set_drawn(view_data->drawn); - private_view.LocalSetViewportMetrics(ViewportMetrics(), - *view_data->viewport_metrics); - private_view.set_properties( - view_data->properties.To<std::map<std::string, std::vector<uint8_t>>>()); - client->AddView(view); - private_view.LocalSetBounds(Rect(), *view_data->bounds); - if (parent) - ViewPrivate(parent).LocalAddChild(view); - return view; -} - -View* BuildViewTree(ViewManagerClientImpl* client, - const Array<ViewDataPtr>& views, - View* initial_parent) { - std::vector<View*> parents; - View* root = NULL; - View* last_view = NULL; - if (initial_parent) - parents.push_back(initial_parent); - for (size_t i = 0; i < views.size(); ++i) { - if (last_view && views[i]->parent_id == last_view->id()) { - parents.push_back(last_view); - } else if (!parents.empty()) { - while (parents.back()->id() != views[i]->parent_id) - parents.pop_back(); - } - View* view = AddViewToViewManager( - client, !parents.empty() ? parents.back() : NULL, views[i]); - if (!last_view) - root = view; - last_view = view; - } - return root; -} - -// Responsible for removing a root from the ViewManager when that view is -// destroyed. -class RootObserver : public ViewObserver { - public: - explicit RootObserver(View* root) : root_(root) {} - ~RootObserver() override {} - - private: - // Overridden from ViewObserver: - void OnViewDestroyed(View* view) override { - DCHECK_EQ(view, root_); - static_cast<ViewManagerClientImpl*>(root_->view_manager()) - ->RootDestroyed(root_); - view->RemoveObserver(this); - delete this; - } - - View* root_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(RootObserver); -}; - -ViewManagerClientImpl::ViewManagerClientImpl( - ViewManagerDelegate* delegate, - Shell* shell, - InterfaceRequest<ViewManagerClient> request, - bool delete_on_error) - : connection_id_(0), - next_id_(1), - delegate_(delegate), - root_(nullptr), - capture_view_(nullptr), - focused_view_(nullptr), - activated_view_(nullptr), - wm_observer_binding_(this), - binding_(this, request.Pass()), - delete_on_error_(delete_on_error) { -} - -ViewManagerClientImpl::~ViewManagerClientImpl() { - std::vector<View*> non_owned; - while (!views_.empty()) { - IdToViewMap::iterator it = views_.begin(); - if (OwnsView(it->second->id())) { - it->second->Destroy(); - } else { - non_owned.push_back(it->second); - views_.erase(it); - } - } - // Delete the non-owned views last. In the typical case these are roots. The - // exception is the window manager, which may know aboutother random views - // that it doesn't own. - // NOTE: we manually delete as we're a friend. - for (size_t i = 0; i < non_owned.size(); ++i) - delete non_owned[i]; - - delegate_->OnViewManagerDisconnected(this); -} - -void ViewManagerClientImpl::DestroyView(Id view_id) { - DCHECK(service_); - service_->DeleteView(view_id, ActionCompletedCallback()); -} - -void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) { - DCHECK(service_); - service_->AddView(parent_id, child_id, ActionCompletedCallback()); -} - -void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) { - DCHECK(service_); - service_->RemoveViewFromParent(child_id, ActionCompletedCallback()); -} - -void ViewManagerClientImpl::Reorder( - Id view_id, - Id relative_view_id, - OrderDirection direction) { - DCHECK(service_); - service_->ReorderView(view_id, relative_view_id, direction, - ActionCompletedCallback()); -} - -bool ViewManagerClientImpl::OwnsView(Id id) const { - return HiWord(id) == connection_id_; -} - -void ViewManagerClientImpl::SetBounds(Id view_id, const Rect& bounds) { - DCHECK(service_); - service_->SetViewBounds(view_id, bounds.Clone(), ActionCompletedCallback()); -} - -void ViewManagerClientImpl::SetSurfaceId(Id view_id, SurfaceIdPtr surface_id) { - DCHECK(service_); - if (surface_id.is_null()) - return; - service_->SetViewSurfaceId( - view_id, surface_id.Pass(), ActionCompletedCallback()); -} - -void ViewManagerClientImpl::SetFocus(Id view_id) { - // In order for us to get here we had to have exposed a view, which implies we - // got a connection. - DCHECK(service_); - service_->PerformAction(view_id, "focus", ActionCompletedCallback()); -} - -void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) { - DCHECK(service_); - service_->SetViewVisibility(view_id, visible, ActionCompletedCallback()); -} - -void ViewManagerClientImpl::SetProperty( - Id view_id, - const std::string& name, - const std::vector<uint8_t>& data) { - DCHECK(service_); - service_->SetViewProperty(view_id, - String(name), - Array<uint8_t>::From(data), - ActionCompletedCallback()); -} - -void ViewManagerClientImpl::Embed(const String& url, Id view_id) { - Embed(url, view_id, nullptr, nullptr); -} - -void ViewManagerClientImpl::Embed(const String& url, - Id view_id, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) { - DCHECK(service_); - service_->EmbedUrl(url, view_id, services.Pass(), exposed_services.Pass(), - ActionCompletedCallback()); -} - -void ViewManagerClientImpl::Embed(Id view_id, ViewManagerClientPtr client) { - DCHECK(service_); - service_->Embed(view_id, client.Pass(), ActionCompletedCallback()); -} - -void ViewManagerClientImpl::AddView(View* view) { - DCHECK(views_.find(view->id()) == views_.end()); - views_[view->id()] = view; -} - -void ViewManagerClientImpl::RemoveView(Id view_id) { - if (focused_view_ && focused_view_->id() == view_id) - OnFocusChanged(0); - if (capture_view_ && capture_view_->id() == view_id) - OnCaptureChanged(0); - if (activated_view_ && activated_view_->id() == view_id) - OnActiveWindowChanged(0); - - IdToViewMap::iterator it = views_.find(view_id); - if (it != views_.end()) - views_.erase(it); -} - -void ViewManagerClientImpl::SetViewManagerService( - ViewManagerServicePtr service) { - DCHECK(!service_); - DCHECK(service); - service_ = service.Pass(); -} -//////////////////////////////////////////////////////////////////////////////// -// ViewManagerClientImpl, ViewManager implementation: - -Id ViewManagerClientImpl::CreateViewOnServer() { - DCHECK(service_); - const Id view_id = MakeTransportId(connection_id_, ++next_id_); - service_->CreateView(view_id, [this](ErrorCode code) { - OnActionCompleted(code == ERROR_CODE_NONE); - }); - return view_id; -} - -const std::string& ViewManagerClientImpl::GetEmbedderURL() const { - return creator_url_; -} - -View* ViewManagerClientImpl::GetRoot() { - return root_; -} - -View* ViewManagerClientImpl::GetViewById(Id id) { - IdToViewMap::const_iterator it = views_.find(id); - return it != views_.end() ? it->second : NULL; -} - -View* ViewManagerClientImpl::GetFocusedView() { - return focused_view_; -} - -View* ViewManagerClientImpl::CreateView() { - View* view = new View(this, CreateViewOnServer()); - AddView(view); - return view; -} - -//////////////////////////////////////////////////////////////////////////////// -// ViewManagerClientImpl, ViewManagerClient implementation: - -void ViewManagerClientImpl::OnEmbed( - ConnectionSpecificId connection_id, - const String& creator_url, - ViewDataPtr root_data, - ViewManagerServicePtr view_manager_service, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - ScopedMessagePipeHandle window_manager_pipe) { - if (view_manager_service) { - DCHECK(!service_); - service_ = view_manager_service.Pass(); - } - connection_id_ = connection_id; - creator_url_ = String::From(creator_url); - - DCHECK(!root_); - root_ = AddViewToViewManager(this, nullptr, root_data); - root_->AddObserver(new RootObserver(root_)); - - window_manager_.Bind(window_manager_pipe.Pass()); - WindowManagerObserverPtr observer; - wm_observer_binding_.Bind(GetProxy(&observer)); - // binding to |this| is safe here as |window_manager_| is bound to our - // lifetime. - window_manager_->GetFocusedAndActiveViews( - observer.Pass(), - [this](uint32_t capture_view_id, uint32_t focused_view_id, - uint32_t active_view_id) { - if (GetViewById(capture_view_id) != capture_view_) - OnCaptureChanged(capture_view_id); - if (GetViewById(focused_view_id) != focused_view_) - OnFocusChanged(focused_view_id); - if (GetViewById(active_view_id) != activated_view_) - OnActiveWindowChanged(active_view_id); - }); - - delegate_->OnEmbed(root_, services.Pass(), exposed_services.Pass()); -} - -void ViewManagerClientImpl::OnEmbeddedAppDisconnected(Id view_id) { - View* view = GetViewById(view_id); - if (view) { - FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(), - OnViewEmbeddedAppDisconnected(view)); - } -} - -void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id, - RectPtr old_bounds, - RectPtr new_bounds) { - View* view = GetViewById(view_id); - ViewPrivate(view).LocalSetBounds(*old_bounds, *new_bounds); -} - -namespace { - -void SetViewportMetricsOnDecendants(View* root, - const ViewportMetrics& old_metrics, - const ViewportMetrics& new_metrics) { - ViewPrivate(root).LocalSetViewportMetrics(old_metrics, new_metrics); - const View::Children& children = root->children(); - for (size_t i = 0; i < children.size(); ++i) - SetViewportMetricsOnDecendants(children[i], old_metrics, new_metrics); -} -} - -void ViewManagerClientImpl::OnViewViewportMetricsChanged( - ViewportMetricsPtr old_metrics, - ViewportMetricsPtr new_metrics) { - View* view = GetRoot(); - if (view) - SetViewportMetricsOnDecendants(view, *old_metrics, *new_metrics); -} - -void ViewManagerClientImpl::OnViewHierarchyChanged( - Id view_id, - Id new_parent_id, - Id old_parent_id, - mojo::Array<ViewDataPtr> views) { - View* initial_parent = views.size() ? - GetViewById(views[0]->parent_id) : NULL; - - BuildViewTree(this, views, initial_parent); - - View* new_parent = GetViewById(new_parent_id); - View* old_parent = GetViewById(old_parent_id); - View* view = GetViewById(view_id); - if (new_parent) - ViewPrivate(new_parent).LocalAddChild(view); - else - ViewPrivate(old_parent).LocalRemoveChild(view); -} - -void ViewManagerClientImpl::OnViewReordered(Id view_id, - Id relative_view_id, - OrderDirection direction) { - View* view = GetViewById(view_id); - View* relative_view = GetViewById(relative_view_id); - if (view && relative_view) - ViewPrivate(view).LocalReorder(relative_view, direction); -} - -void ViewManagerClientImpl::OnViewDeleted(Id view_id) { - View* view = GetViewById(view_id); - if (view) - ViewPrivate(view).LocalDestroy(); -} - -void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) { - // TODO(sky): there is a race condition here. If this client and another - // client change the visibility at the same time the wrong value may be set. - // Deal with this some how. - View* view = GetViewById(view_id); - if (view) - ViewPrivate(view).LocalSetVisible(visible); -} - -void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) { - View* view = GetViewById(view_id); - if (view) - ViewPrivate(view).LocalSetDrawn(drawn); -} - -void ViewManagerClientImpl::OnViewSharedPropertyChanged( - Id view_id, - const String& name, - Array<uint8_t> new_data) { - View* view = GetViewById(view_id); - if (view) { - std::vector<uint8_t> data; - std::vector<uint8_t>* data_ptr = NULL; - if (!new_data.is_null()) { - data = new_data.To<std::vector<uint8_t>>(); - data_ptr = &data; - } - - view->SetSharedProperty(name, data_ptr); - } -} - -void ViewManagerClientImpl::OnViewInputEvent( - Id view_id, - EventPtr event, - const Callback<void()>& ack_callback) { - View* view = GetViewById(view_id); - if (view) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(view).observers(), - OnViewInputEvent(view, event)); - } - ack_callback.Run(); -} - -void ViewManagerClientImpl::OnPerformAction( - Id view_id, - const String& name, - const Callback<void(bool)>& callback) { - View* view = GetViewById(view_id); - callback.Run(delegate_->OnPerformAction(view, name)); -} - -//////////////////////////////////////////////////////////////////////////////// -// ViewManagerClientImpl, WindowManagerObserver implementation: - -void ViewManagerClientImpl::OnCaptureChanged(Id capture_view_id) { - View* gained_capture = GetViewById(capture_view_id); - View* lost_capture = capture_view_; - if (lost_capture) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(lost_capture).observers(), - OnViewFocusChanged(gained_capture, lost_capture)); - } - capture_view_ = gained_capture; - if (gained_capture) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(gained_capture).observers(), - OnViewFocusChanged(gained_capture, lost_capture)); - } -} - -void ViewManagerClientImpl::OnFocusChanged(Id focused_view_id) { - View* focused = GetViewById(focused_view_id); - View* blurred = focused_view_; - if (blurred) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(blurred).observers(), - OnViewFocusChanged(focused, blurred)); - } - focused_view_ = focused; - if (focused) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(focused).observers(), - OnViewFocusChanged(focused, blurred)); - } -} - -void ViewManagerClientImpl::OnActiveWindowChanged(Id active_view_id) { - View* activated = GetViewById(active_view_id); - View* deactivated = activated_view_; - if (deactivated) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(deactivated).observers(), - OnViewActivationChanged(activated, deactivated)); - } - activated_view_ = activated; - if (activated) { - FOR_EACH_OBSERVER(ViewObserver, - *ViewPrivate(activated).observers(), - OnViewActivationChanged(activated, deactivated)); - } -} - -//////////////////////////////////////////////////////////////////////////////// -// OnConnectionError, private: -void ViewManagerClientImpl::OnConnectionError() { - if (delete_on_error_) - delete this; -} - -//////////////////////////////////////////////////////////////////////////////// -// ViewManagerClientImpl, private: - -void ViewManagerClientImpl::RootDestroyed(View* root) { - DCHECK_EQ(root, root_); - root_ = nullptr; -} - -void ViewManagerClientImpl::OnActionCompleted(bool success) { - if (!change_acked_callback_.is_null()) - change_acked_callback_.Run(); -} - -Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() { - return [this](bool success) { OnActionCompleted(success); }; -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h deleted file mode 100644 index 3bdfd7f..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_client_impl.h +++ /dev/null
@@ -1,169 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_MANAGER_CLIENT_IMPL_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_MANAGER_CLIENT_IMPL_H_ - -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "view_manager/public/cpp/types.h" -#include "view_manager/public/cpp/view.h" -#include "view_manager/public/cpp/view_manager.h" -#include "view_manager/public/interfaces/view_manager.mojom.h" -#include "window_manager/public/interfaces/window_manager.mojom.h" - -namespace mojo { -class Shell; -class ViewManager; -class ViewManagerDelegate; -class ViewManagerTransaction; - -// Manages the connection with the View Manager service. -class ViewManagerClientImpl : public ViewManager, - public ViewManagerClient, - public WindowManagerObserver, - public ErrorHandler { - public: - ViewManagerClientImpl(ViewManagerDelegate* delegate, - Shell* shell, - InterfaceRequest<ViewManagerClient> request, - bool delete_on_error); - ~ViewManagerClientImpl() override; - - bool connected() const { return service_; } - ConnectionSpecificId connection_id() const { return connection_id_; } - - // API exposed to the view implementations that pushes local changes to the - // service. - void DestroyView(Id view_id); - - // These methods take TransportIds. For views owned by the current connection, - // the connection id high word can be zero. In all cases, the TransportId 0x1 - // refers to the root view. - void AddChild(Id child_id, Id parent_id); - void RemoveChild(Id child_id, Id parent_id); - - void Reorder(Id view_id, Id relative_view_id, OrderDirection direction); - - // Returns true if the specified view was created by this connection. - bool OwnsView(Id id) const; - - void SetBounds(Id view_id, const Rect& bounds); - void SetSurfaceId(Id view_id, SurfaceIdPtr surface_id); - void SetFocus(Id view_id); - void SetVisible(Id view_id, bool visible); - void SetProperty(Id view_id, - const std::string& name, - const std::vector<uint8_t>& data); - - void Embed(const String& url, Id view_id); - void Embed(const String& url, - Id view_id, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services); - void Embed(Id view_id, ViewManagerClientPtr client); - - void set_change_acked_callback(const Callback<void(void)>& callback) { - change_acked_callback_ = callback; - } - void ClearChangeAckedCallback() { change_acked_callback_.reset(); } - - // Start/stop tracking views. While tracked, they can be retrieved via - // ViewManager::GetViewById. - void AddView(View* view); - void RemoveView(Id view_id); - - void SetViewManagerService(ViewManagerServicePtr service); - - private: - friend class RootObserver; - - typedef std::map<Id, View*> IdToViewMap; - - Id CreateViewOnServer(); - - // Overridden from ViewManager: - const std::string& GetEmbedderURL() const override; - View* GetRoot() override; - View* GetViewById(Id id) override; - View* GetFocusedView() override; - View* CreateView() override; - - // Overridden from ViewManagerClient: - void OnEmbed(ConnectionSpecificId connection_id, - const String& creator_url, - ViewDataPtr root, - ViewManagerServicePtr view_manager_service, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - ScopedMessagePipeHandle window_manager_pipe) override; - void OnEmbeddedAppDisconnected(Id view_id) override; - void OnViewBoundsChanged(Id view_id, - RectPtr old_bounds, - RectPtr new_bounds) override; - void OnViewViewportMetricsChanged(ViewportMetricsPtr old_metrics, - ViewportMetricsPtr new_metrics) override; - void OnViewHierarchyChanged(Id view_id, - Id new_parent_id, - Id old_parent_id, - Array<ViewDataPtr> views) override; - void OnViewReordered(Id view_id, - Id relative_view_id, - OrderDirection direction) override; - void OnViewDeleted(Id view_id) override; - void OnViewVisibilityChanged(Id view_id, bool visible) override; - void OnViewDrawnStateChanged(Id view_id, bool drawn) override; - void OnViewSharedPropertyChanged(Id view_id, - const String& name, - Array<uint8_t> new_data) override; - void OnViewInputEvent(Id view_id, - EventPtr event, - const Callback<void()>& callback) override; - void OnPerformAction(Id view_id, - const String& name, - const Callback<void(bool)>& callback) override; - - // Overridden from WindowManagerObserver: - void OnCaptureChanged(Id capture_view_id) override; - void OnFocusChanged(Id focused_view_id) override; - void OnActiveWindowChanged(Id focused_view_id) override; - - // ErrorHandler implementation. - void OnConnectionError() override; - - void RootDestroyed(View* root); - - void OnActionCompleted(bool success); - - Callback<void(bool)> ActionCompletedCallback(); - - ConnectionSpecificId connection_id_; - ConnectionSpecificId next_id_; - - std::string creator_url_; - - Callback<void(void)> change_acked_callback_; - - ViewManagerDelegate* delegate_; - - View* root_; - - IdToViewMap views_; - - View* capture_view_; - View* focused_view_; - View* activated_view_; - - WindowManagerPtr window_manager_; - Binding<WindowManagerObserver> wm_observer_binding_; - - Binding<ViewManagerClient> binding_; - ViewManagerServicePtr service_; - const bool delete_on_error_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerClientImpl); -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_MANAGER_CLIENT_IMPL_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_context.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_context.cc deleted file mode 100644 index d1c2fd0..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_manager_context.cc +++ /dev/null
@@ -1,45 +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 "view_manager/public/cpp/view_manager_context.h" - -#include "mojo/public/cpp/application/application_impl.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "window_manager/public/interfaces/window_manager.mojom.h" - -namespace mojo { -class ApplicationImpl; - -class ViewManagerContext::InternalState { - public: - explicit InternalState(ApplicationImpl* application_impl) { - application_impl->ConnectToService("mojo:window_manager", &wm_); - } - ~InternalState() {} - - WindowManager* wm() { return wm_.get(); } - - private: - WindowManagerPtr wm_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(InternalState); -}; - -ViewManagerContext::ViewManagerContext(ApplicationImpl* application_impl) - : state_(new InternalState(application_impl)) {} -ViewManagerContext::~ViewManagerContext() { - delete state_; -} - -void ViewManagerContext::Embed(const String& url) { - Embed(url, nullptr, nullptr); -} - -void ViewManagerContext::Embed(const String& url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) { - state_->wm()->Embed(url, services.Pass(), exposed_services.Pass()); -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_observer.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_observer.cc deleted file mode 100644 index 7e6acc0..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_observer.cc +++ /dev/null
@@ -1,19 +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 "view_manager/public/cpp/view_observer.h" - -namespace mojo { - -//////////////////////////////////////////////////////////////////////////////// -// ViewObserver, public: - -ViewObserver::TreeChangeParams::TreeChangeParams() - : target(nullptr), - old_parent(nullptr), - new_parent(nullptr), - receiver(nullptr) { -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.cc b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.cc deleted file mode 100644 index 20232e8..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.cc +++ /dev/null
@@ -1,22 +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 "view_manager/public/cpp/lib/view_private.h" - -namespace mojo { - -ViewPrivate::ViewPrivate(View* view) - : view_(view) { - CHECK(view); -} - -ViewPrivate::~ViewPrivate() { -} - -// static -View* ViewPrivate::LocalCreate() { - return new View; -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h b/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h deleted file mode 100644 index 0b58280..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/lib/view_private.h +++ /dev/null
@@ -1,72 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_PRIVATE_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_PRIVATE_H_ - -#include "view_manager/public/cpp/view.h" - -namespace mojo { - -// This class is a friend of a View and contains functions to mutate internal -// state of View. -class ViewPrivate { - public: - explicit ViewPrivate(View* view); - ~ViewPrivate(); - - // Creates and returns a new View. Caller owns the return value. - static View* LocalCreate(); - - ObserverList<ViewObserver>* observers() { return &view_->observers_; } - - void ClearParent() { view_->parent_ = NULL; } - - void set_visible(bool visible) { view_->visible_ = visible; } - - void set_drawn(bool drawn) { view_->drawn_ = drawn; } - - void set_id(Id id) { view_->id_ = id; } - - void set_view_manager(ViewManager* manager) { - view_->manager_ = manager; - } - - void set_properties(const std::map<std::string, std::vector<uint8_t>>& data) { - view_->properties_ = data; - } - - void LocalSetViewportMetrics(const ViewportMetrics& old_metrics, - const ViewportMetrics& new_metrics) { - view_->LocalSetViewportMetrics(new_metrics, new_metrics); - } - - void LocalDestroy() { - view_->LocalDestroy(); - } - void LocalAddChild(View* child) { - view_->LocalAddChild(child); - } - void LocalRemoveChild(View* child) { - view_->LocalRemoveChild(child); - } - void LocalReorder(View* relative, OrderDirection direction) { - view_->LocalReorder(relative, direction); - } - void LocalSetBounds(const Rect& old_bounds, - const Rect& new_bounds) { - view_->LocalSetBounds(old_bounds, new_bounds); - } - void LocalSetDrawn(bool drawn) { view_->LocalSetDrawn(drawn); } - void LocalSetVisible(bool visible) { view_->LocalSetVisible(visible); } - - private: - View* view_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ViewPrivate); -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_LIB_VIEW_PRIVATE_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/BUILD.gn b/third_party/mojo_services/src/view_manager/public/cpp/tests/BUILD.gn deleted file mode 100644 index f0d80715..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/tests/BUILD.gn +++ /dev/null
@@ -1,35 +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. - -import("//build/config/ui.gni") -import("//testing/test.gni") - -test("mojo_view_manager_lib_unittests") { - sources = [ - "run_all_unittests.cc", - "view_manager_test_suite.cc", - "view_manager_test_suite.h", - "view_unittest.cc", - ] - - deps = [ - "//base", - "//base/test:test_support", - # TODO(vtl): These non-public deps are illegal here. This should be - # converted to an apptest. - "//mojo/application", - "//mojo/edk/system", - "//mojo/environment:chromium", - "//mojo/public/cpp/application", - "//mojo/public/cpp/system", - "//mojo/services/geometry/public/cpp", - "//mojo/services/geometry/public/interfaces", - "//mojo/services/view_manager/public/cpp", - "//testing/gtest", - ] - - if (use_x11) { - deps += [ "//ui/gfx/x" ] - } -}
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/run_all_unittests.cc b/third_party/mojo_services/src/view_manager/public/cpp/tests/run_all_unittests.cc deleted file mode 100644 index 95a7b5cd..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/tests/run_all_unittests.cc +++ /dev/null
@@ -1,14 +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 "base/bind.h" -#include "base/test/launcher/unit_test_launcher.h" -#include "mojo/services/view_manager/public/cpp/tests/view_manager_test_suite.h" - -int main(int argc, char** argv) { - mojo::ViewManagerTestSuite test_suite(argc, argv); - - return base::LaunchUnitTests( - argc, argv, base::Bind(&TestSuite::Run, base::Unretained(&test_suite))); -}
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.cc b/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.cc deleted file mode 100644 index 2bfdd1e9..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.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 "mojo/services/view_manager/public/cpp/tests/view_manager_test_suite.h" - -#include "base/i18n/icu_util.h" - -#if defined(USE_X11) -#include "ui/gfx/x/x11_connection.h" -#endif - -namespace mojo { - -ViewManagerTestSuite::ViewManagerTestSuite(int argc, char** argv) - : TestSuite(argc, argv) {} - -ViewManagerTestSuite::~ViewManagerTestSuite() { -} - -void ViewManagerTestSuite::Initialize() { -#if defined(USE_X11) - // Each test ends up creating a new thread for the native viewport service. - // In other words we'll use X on different threads, so tell it that. - gfx::InitializeThreadedX11(); -#endif - - base::TestSuite::Initialize(); - - // base::TestSuite and ViewsInit both try to load icu. That's ok for tests. - base::i18n::AllowMultipleInitializeCallsForTesting(); -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.h b/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.h deleted file mode 100644 index 547efc2..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_manager_test_suite.h +++ /dev/null
@@ -1,27 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_TESTS_VIEW_MANAGER_TEST_SUITE_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_TESTS_VIEW_MANAGER_TEST_SUITE_H_ - -#include "base/test/test_suite.h" -#include "mojo/public/cpp/system/macros.h" - -namespace mojo { - -class ViewManagerTestSuite : public base::TestSuite { - public: - ViewManagerTestSuite(int argc, char** argv); - ~ViewManagerTestSuite() override; - - protected: - void Initialize() override; - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerTestSuite); -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_TESTS_VIEW_MANAGER_TEST_SUITE_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_unittest.cc b/third_party/mojo_services/src/view_manager/public/cpp/tests/view_unittest.cc deleted file mode 100644 index 09d1bde..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/tests/view_unittest.cc +++ /dev/null
@@ -1,884 +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 "mojo/services/view_manager/public/cpp/view.h" - -#include "base/logging.h" -#include "base/strings/stringprintf.h" -#include "mojo/services/view_manager/public/cpp/lib/view_private.h" -#include "mojo/services/view_manager/public/cpp/util.h" -#include "mojo/services/view_manager/public/cpp/view_observer.h" -#include "mojo/services/view_manager/public/cpp/view_property.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace mojo { - -// View ------------------------------------------------------------------------ - -typedef testing::Test ViewTest; - -// Subclass with public ctor/dtor. -class TestView : public View { - public: - TestView() { - ViewPrivate(this).set_id(1); - } - ~TestView() {} - - private: - MOJO_DISALLOW_COPY_AND_ASSIGN(TestView); -}; - -TEST_F(ViewTest, AddChild) { - TestView v1; - TestView v11; - v1.AddChild(&v11); - EXPECT_EQ(1U, v1.children().size()); -} - -TEST_F(ViewTest, RemoveChild) { - TestView v1; - TestView v11; - v1.AddChild(&v11); - EXPECT_EQ(1U, v1.children().size()); - v1.RemoveChild(&v11); - EXPECT_EQ(0U, v1.children().size()); -} - -TEST_F(ViewTest, Reparent) { - TestView v1; - TestView v2; - TestView v11; - v1.AddChild(&v11); - EXPECT_EQ(1U, v1.children().size()); - v2.AddChild(&v11); - EXPECT_EQ(1U, v2.children().size()); - EXPECT_EQ(0U, v1.children().size()); -} - -TEST_F(ViewTest, Contains) { - TestView v1; - - // Direct descendant. - TestView v11; - v1.AddChild(&v11); - EXPECT_TRUE(v1.Contains(&v11)); - - // Indirect descendant. - TestView v111; - v11.AddChild(&v111); - EXPECT_TRUE(v1.Contains(&v111)); -} - -TEST_F(ViewTest, GetChildById) { - TestView v1; - ViewPrivate(&v1).set_id(1); - TestView v11; - ViewPrivate(&v11).set_id(11); - v1.AddChild(&v11); - TestView v111; - ViewPrivate(&v111).set_id(111); - v11.AddChild(&v111); - - // Find direct & indirect descendents. - EXPECT_EQ(&v11, v1.GetChildById(v11.id())); - EXPECT_EQ(&v111, v1.GetChildById(v111.id())); -} - -TEST_F(ViewTest, DrawnAndVisible) { - TestView v1; - EXPECT_TRUE(v1.visible()); - EXPECT_FALSE(v1.IsDrawn()); - - ViewPrivate(&v1).set_drawn(true); - - TestView v11; - v1.AddChild(&v11); - EXPECT_TRUE(v11.visible()); - EXPECT_TRUE(v11.IsDrawn()); - - v1.RemoveChild(&v11); - EXPECT_TRUE(v11.visible()); - EXPECT_FALSE(v11.IsDrawn()); -} - -namespace { -DEFINE_VIEW_PROPERTY_KEY(int, kIntKey, -2); -DEFINE_VIEW_PROPERTY_KEY(const char*, kStringKey, "squeamish"); -} - -TEST_F(ViewTest, Property) { - TestView v; - - // Non-existent properties should return the default values. - EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); - EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); - - // A set property value should be returned again (even if it's the default - // value). - v.SetLocalProperty(kIntKey, INT_MAX); - EXPECT_EQ(INT_MAX, v.GetLocalProperty(kIntKey)); - v.SetLocalProperty(kIntKey, -2); - EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); - v.SetLocalProperty(kIntKey, INT_MIN); - EXPECT_EQ(INT_MIN, v.GetLocalProperty(kIntKey)); - - v.SetLocalProperty(kStringKey, static_cast<const char*>(NULL)); - EXPECT_EQ(NULL, v.GetLocalProperty(kStringKey)); - v.SetLocalProperty(kStringKey, "squeamish"); - EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); - v.SetLocalProperty(kStringKey, "ossifrage"); - EXPECT_EQ(std::string("ossifrage"), v.GetLocalProperty(kStringKey)); - - // ClearProperty should restore the default value. - v.ClearLocalProperty(kIntKey); - EXPECT_EQ(-2, v.GetLocalProperty(kIntKey)); - v.ClearLocalProperty(kStringKey); - EXPECT_EQ(std::string("squeamish"), v.GetLocalProperty(kStringKey)); -} - -namespace { - -class TestProperty { - public: - TestProperty() {} - virtual ~TestProperty() { last_deleted_ = this; } - static TestProperty* last_deleted() { return last_deleted_; } - - private: - static TestProperty* last_deleted_; - MOJO_DISALLOW_COPY_AND_ASSIGN(TestProperty); -}; - -TestProperty* TestProperty::last_deleted_ = NULL; - -DEFINE_OWNED_VIEW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL); - -} // namespace - -TEST_F(ViewTest, OwnedProperty) { - TestProperty* p3 = NULL; - { - TestView v; - EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey)); - TestProperty* p1 = new TestProperty(); - v.SetLocalProperty(kOwnedKey, p1); - EXPECT_EQ(p1, v.GetLocalProperty(kOwnedKey)); - EXPECT_EQ(NULL, TestProperty::last_deleted()); - - TestProperty* p2 = new TestProperty(); - v.SetLocalProperty(kOwnedKey, p2); - EXPECT_EQ(p2, v.GetLocalProperty(kOwnedKey)); - EXPECT_EQ(p1, TestProperty::last_deleted()); - - v.ClearLocalProperty(kOwnedKey); - EXPECT_EQ(NULL, v.GetLocalProperty(kOwnedKey)); - EXPECT_EQ(p2, TestProperty::last_deleted()); - - p3 = new TestProperty(); - v.SetLocalProperty(kOwnedKey, p3); - EXPECT_EQ(p3, v.GetLocalProperty(kOwnedKey)); - EXPECT_EQ(p2, TestProperty::last_deleted()); - } - - EXPECT_EQ(p3, TestProperty::last_deleted()); -} - -// ViewObserver -------------------------------------------------------- - -typedef testing::Test ViewObserverTest; - -bool TreeChangeParamsMatch(const ViewObserver::TreeChangeParams& lhs, - const ViewObserver::TreeChangeParams& rhs) { - return lhs.target == rhs.target && lhs.old_parent == rhs.old_parent && - lhs.new_parent == rhs.new_parent && lhs.receiver == rhs.receiver; -} - -class TreeChangeObserver : public ViewObserver { - public: - explicit TreeChangeObserver(View* observee) : observee_(observee) { - observee_->AddObserver(this); - } - ~TreeChangeObserver() override { observee_->RemoveObserver(this); } - - void Reset() { - received_params_.clear(); - } - - const std::vector<TreeChangeParams>& received_params() { - return received_params_; - } - - private: - // Overridden from ViewObserver: - void OnTreeChanging(const TreeChangeParams& params) override { - received_params_.push_back(params); - } - void OnTreeChanged(const TreeChangeParams& params) override { - received_params_.push_back(params); - } - - View* observee_; - std::vector<TreeChangeParams> received_params_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(TreeChangeObserver); -}; - -// Adds/Removes v11 to v1. -TEST_F(ViewObserverTest, TreeChange_SimpleAddRemove) { - TestView v1; - TreeChangeObserver o1(&v1); - EXPECT_TRUE(o1.received_params().empty()); - - TestView v11; - TreeChangeObserver o11(&v11); - EXPECT_TRUE(o11.received_params().empty()); - - // Add. - - v1.AddChild(&v11); - - EXPECT_EQ(2U, o1.received_params().size()); - ViewObserver::TreeChangeParams p1; - p1.target = &v11; - p1.receiver = &v1; - p1.old_parent = NULL; - p1.new_parent = &v1; - EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); - - EXPECT_EQ(2U, o11.received_params().size()); - ViewObserver::TreeChangeParams p11 = p1; - p11.receiver = &v11; - EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); - - o1.Reset(); - o11.Reset(); - EXPECT_TRUE(o1.received_params().empty()); - EXPECT_TRUE(o11.received_params().empty()); - - // Remove. - - v1.RemoveChild(&v11); - - EXPECT_EQ(2U, o1.received_params().size()); - p1.target = &v11; - p1.receiver = &v1; - p1.old_parent = &v1; - p1.new_parent = NULL; - EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); - - EXPECT_EQ(2U, o11.received_params().size()); - p11 = p1; - p11.receiver = &v11; - EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); -} - -// Creates these two trees: -// v1 -// +- v11 -// v111 -// +- v1111 -// +- v1112 -// Then adds/removes v111 from v11. -TEST_F(ViewObserverTest, TreeChange_NestedAddRemove) { - TestView v1, v11, v111, v1111, v1112; - - // Root tree. - v1.AddChild(&v11); - - // Tree to be attached. - v111.AddChild(&v1111); - v111.AddChild(&v1112); - - TreeChangeObserver o1(&v1), o11(&v11), o111(&v111), o1111(&v1111), - o1112(&v1112); - ViewObserver::TreeChangeParams p1, p11, p111, p1111, p1112; - - // Add. - - v11.AddChild(&v111); - - EXPECT_EQ(2U, o1.received_params().size()); - p1.target = &v111; - p1.receiver = &v1; - p1.old_parent = NULL; - p1.new_parent = &v11; - EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); - - EXPECT_EQ(2U, o11.received_params().size()); - p11 = p1; - p11.receiver = &v11; - EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().back())); - - EXPECT_EQ(2U, o111.received_params().size()); - p111 = p11; - p111.receiver = &v111; - EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); - - EXPECT_EQ(2U, o1111.received_params().size()); - p1111 = p111; - p1111.receiver = &v1111; - EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); - - EXPECT_EQ(2U, o1112.received_params().size()); - p1112 = p111; - p1112.receiver = &v1112; - EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); - - // Remove. - o1.Reset(); - o11.Reset(); - o111.Reset(); - o1111.Reset(); - o1112.Reset(); - EXPECT_TRUE(o1.received_params().empty()); - EXPECT_TRUE(o11.received_params().empty()); - EXPECT_TRUE(o111.received_params().empty()); - EXPECT_TRUE(o1111.received_params().empty()); - EXPECT_TRUE(o1112.received_params().empty()); - - v11.RemoveChild(&v111); - - EXPECT_EQ(2U, o1.received_params().size()); - p1.target = &v111; - p1.receiver = &v1; - p1.old_parent = &v11; - p1.new_parent = NULL; - EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); - - EXPECT_EQ(2U, o11.received_params().size()); - p11 = p1; - p11.receiver = &v11; - EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); - - EXPECT_EQ(2U, o111.received_params().size()); - p111 = p11; - p111.receiver = &v111; - EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); - - EXPECT_EQ(2U, o1111.received_params().size()); - p1111 = p111; - p1111.receiver = &v1111; - EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p1111, o1111.received_params().back())); - - EXPECT_EQ(2U, o1112.received_params().size()); - p1112 = p111; - p1112.receiver = &v1112; - EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p1112, o1112.received_params().back())); -} - -TEST_F(ViewObserverTest, TreeChange_Reparent) { - TestView v1, v11, v12, v111; - v1.AddChild(&v11); - v1.AddChild(&v12); - v11.AddChild(&v111); - - TreeChangeObserver o1(&v1), o11(&v11), o12(&v12), o111(&v111); - - // Reparent. - v12.AddChild(&v111); - - // v1 (root) should see both changing and changed notifications. - EXPECT_EQ(4U, o1.received_params().size()); - ViewObserver::TreeChangeParams p1; - p1.target = &v111; - p1.receiver = &v1; - p1.old_parent = &v11; - p1.new_parent = &v12; - EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p1, o1.received_params().back())); - - // v11 should see changing notifications. - EXPECT_EQ(2U, o11.received_params().size()); - ViewObserver::TreeChangeParams p11; - p11 = p1; - p11.receiver = &v11; - EXPECT_TRUE(TreeChangeParamsMatch(p11, o11.received_params().front())); - - // v12 should see changed notifications. - EXPECT_EQ(2U, o12.received_params().size()); - ViewObserver::TreeChangeParams p12; - p12 = p1; - p12.receiver = &v12; - EXPECT_TRUE(TreeChangeParamsMatch(p12, o12.received_params().back())); - - // v111 should see both changing and changed notifications. - EXPECT_EQ(2U, o111.received_params().size()); - ViewObserver::TreeChangeParams p111; - p111 = p1; - p111.receiver = &v111; - EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().front())); - EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); -} - -namespace { - -class OrderChangeObserver : public ViewObserver { - public: - struct Change { - View* view; - View* relative_view; - OrderDirection direction; - }; - typedef std::vector<Change> Changes; - - explicit OrderChangeObserver(View* observee) : observee_(observee) { - observee_->AddObserver(this); - } - ~OrderChangeObserver() override { observee_->RemoveObserver(this); } - - Changes GetAndClearChanges() { - Changes changes; - changes_.swap(changes); - return changes; - } - - private: - // Overridden from ViewObserver: - void OnViewReordering(View* view, - View* relative_view, - OrderDirection direction) override { - OnViewReordered(view, relative_view, direction); - } - - void OnViewReordered(View* view, - View* relative_view, - OrderDirection direction) override { - Change change; - change.view = view; - change.relative_view = relative_view; - change.direction = direction; - changes_.push_back(change); - } - - View* observee_; - Changes changes_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver); -}; - -} // namespace - -TEST_F(ViewObserverTest, Order) { - TestView v1, v11, v12, v13; - v1.AddChild(&v11); - v1.AddChild(&v12); - v1.AddChild(&v13); - - // Order: v11, v12, v13 - EXPECT_EQ(3U, v1.children().size()); - EXPECT_EQ(&v11, v1.children().front()); - EXPECT_EQ(&v13, v1.children().back()); - - { - OrderChangeObserver observer(&v11); - - // Move v11 to front. - // Resulting order: v12, v13, v11 - v11.MoveToFront(); - EXPECT_EQ(&v12, v1.children().front()); - EXPECT_EQ(&v11, v1.children().back()); - - OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(2U, changes.size()); - EXPECT_EQ(&v11, changes[0].view); - EXPECT_EQ(&v13, changes[0].relative_view); - EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[0].direction); - - EXPECT_EQ(&v11, changes[1].view); - EXPECT_EQ(&v13, changes[1].relative_view); - EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[1].direction); - } - - { - OrderChangeObserver observer(&v11); - - // Move v11 to back. - // Resulting order: v11, v12, v13 - v11.MoveToBack(); - EXPECT_EQ(&v11, v1.children().front()); - EXPECT_EQ(&v13, v1.children().back()); - - OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(2U, changes.size()); - EXPECT_EQ(&v11, changes[0].view); - EXPECT_EQ(&v12, changes[0].relative_view); - EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[0].direction); - - EXPECT_EQ(&v11, changes[1].view); - EXPECT_EQ(&v12, changes[1].relative_view); - EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[1].direction); - } - - { - OrderChangeObserver observer(&v11); - - // Move v11 above v12. - // Resulting order: v12. v11, v13 - v11.Reorder(&v12, ORDER_DIRECTION_ABOVE); - EXPECT_EQ(&v12, v1.children().front()); - EXPECT_EQ(&v13, v1.children().back()); - - OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(2U, changes.size()); - EXPECT_EQ(&v11, changes[0].view); - EXPECT_EQ(&v12, changes[0].relative_view); - EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[0].direction); - - EXPECT_EQ(&v11, changes[1].view); - EXPECT_EQ(&v12, changes[1].relative_view); - EXPECT_EQ(ORDER_DIRECTION_ABOVE, changes[1].direction); - } - - { - OrderChangeObserver observer(&v11); - - // Move v11 below v12. - // Resulting order: v11, v12, v13 - v11.Reorder(&v12, ORDER_DIRECTION_BELOW); - EXPECT_EQ(&v11, v1.children().front()); - EXPECT_EQ(&v13, v1.children().back()); - - OrderChangeObserver::Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(2U, changes.size()); - EXPECT_EQ(&v11, changes[0].view); - EXPECT_EQ(&v12, changes[0].relative_view); - EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[0].direction); - - EXPECT_EQ(&v11, changes[1].view); - EXPECT_EQ(&v12, changes[1].relative_view); - EXPECT_EQ(ORDER_DIRECTION_BELOW, changes[1].direction); - } -} - -namespace { - -typedef std::vector<std::string> Changes; - -std::string ViewIdToString(Id id) { - return (id == 0) ? "null" : - base::StringPrintf("%d,%d", HiWord(id), LoWord(id)); -} - -std::string RectToString(const Rect& rect) { - return base::StringPrintf("%d,%d %dx%d", - rect.x, rect.y, rect.width, rect.height); -} - -class BoundsChangeObserver : public ViewObserver { - public: - explicit BoundsChangeObserver(View* view) : view_(view) { - view_->AddObserver(this); - } - ~BoundsChangeObserver() override { view_->RemoveObserver(this); } - - Changes GetAndClearChanges() { - Changes changes; - changes.swap(changes_); - return changes; - } - - private: - // Overridden from ViewObserver: - void OnViewBoundsChanging(View* view, - const Rect& old_bounds, - const Rect& new_bounds) override { - changes_.push_back( - base::StringPrintf( - "view=%s old_bounds=%s new_bounds=%s phase=changing", - ViewIdToString(view->id()).c_str(), - RectToString(old_bounds).c_str(), - RectToString(new_bounds).c_str())); - } - void OnViewBoundsChanged(View* view, - const Rect& old_bounds, - const Rect& new_bounds) override { - changes_.push_back( - base::StringPrintf( - "view=%s old_bounds=%s new_bounds=%s phase=changed", - ViewIdToString(view->id()).c_str(), - RectToString(old_bounds).c_str(), - RectToString(new_bounds).c_str())); - } - - View* view_; - Changes changes_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver); -}; - -} // namespace - -TEST_F(ViewObserverTest, SetBounds) { - TestView v1; - { - BoundsChangeObserver observer(&v1); - Rect rect; - rect.width = rect.height = 100; - v1.SetBounds(rect); - - Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(2U, changes.size()); - EXPECT_EQ( - "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing", - changes[0]); - EXPECT_EQ( - "view=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed", - changes[1]); - } -} - -namespace { - -class VisibilityChangeObserver : public ViewObserver { - public: - explicit VisibilityChangeObserver(View* view) : view_(view) { - view_->AddObserver(this); - } - ~VisibilityChangeObserver() override { view_->RemoveObserver(this); } - - Changes GetAndClearChanges() { - Changes changes; - changes.swap(changes_); - return changes; - } - - private: - // Overridden from ViewObserver: - void OnViewVisibilityChanging(View* view) override { - changes_.push_back( - base::StringPrintf("view=%s phase=changing visibility=%s", - ViewIdToString(view->id()).c_str(), - view->visible() ? "true" : "false")); - } - void OnViewVisibilityChanged(View* view) override { - changes_.push_back(base::StringPrintf("view=%s phase=changed visibility=%s", - ViewIdToString(view->id()).c_str(), - view->visible() ? "true" : "false")); - } - - View* view_; - Changes changes_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(VisibilityChangeObserver); -}; - -} // namespace - -TEST_F(ViewObserverTest, SetVisible) { - TestView v1; - EXPECT_TRUE(v1.visible()); - { - // Change visibility from true to false and make sure we get notifications. - VisibilityChangeObserver observer(&v1); - v1.SetVisible(false); - - Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(2U, changes.size()); - EXPECT_EQ("view=0,1 phase=changing visibility=true", changes[0]); - EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[1]); - } - { - // Set visible to existing value and verify no notifications. - VisibilityChangeObserver observer(&v1); - v1.SetVisible(false); - EXPECT_TRUE(observer.GetAndClearChanges().empty()); - } -} - -TEST_F(ViewObserverTest, SetVisibleParent) { - TestView parent; - ViewPrivate(&parent).set_id(1); - TestView child; - ViewPrivate(&child).set_id(2); - parent.AddChild(&child); - EXPECT_TRUE(parent.visible()); - EXPECT_TRUE(child.visible()); - { - // Change visibility from true to false and make sure we get notifications - // on the parent. - VisibilityChangeObserver observer(&parent); - child.SetVisible(false); - - Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(1U, changes.size()); - EXPECT_EQ("view=0,2 phase=changed visibility=false", changes[0]); - } -} - -TEST_F(ViewObserverTest, SetVisibleChild) { - TestView parent; - ViewPrivate(&parent).set_id(1); - TestView child; - ViewPrivate(&child).set_id(2); - parent.AddChild(&child); - EXPECT_TRUE(parent.visible()); - EXPECT_TRUE(child.visible()); - { - // Change visibility from true to false and make sure we get notifications - // on the child. - VisibilityChangeObserver observer(&child); - parent.SetVisible(false); - - Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(1U, changes.size()); - EXPECT_EQ("view=0,1 phase=changed visibility=false", changes[0]); - } -} - -namespace { - -class SharedPropertyChangeObserver : public ViewObserver { - public: - explicit SharedPropertyChangeObserver(View* view) : view_(view) { - view_->AddObserver(this); - } - ~SharedPropertyChangeObserver() override { view_->RemoveObserver(this); } - - Changes GetAndClearChanges() { - Changes changes; - changes.swap(changes_); - return changes; - } - - private: - // Overridden from ViewObserver: - void OnViewSharedPropertyChanged( - View* view, - const std::string& name, - const std::vector<uint8_t>* old_data, - const std::vector<uint8_t>* new_data) override { - changes_.push_back(base::StringPrintf( - "view=%s shared property changed key=%s old_value=%s new_value=%s", - ViewIdToString(view->id()).c_str(), name.c_str(), - VectorToString(old_data).c_str(), VectorToString(new_data).c_str())); - } - - std::string VectorToString(const std::vector<uint8_t>* data) { - if (!data) - return "NULL"; - std::string s; - for (char c : *data) - s += c; - return s; - } - - View* view_; - Changes changes_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(SharedPropertyChangeObserver); -}; - -} // namespace - -TEST_F(ViewObserverTest, SetLocalProperty) { - TestView v1; - std::vector<uint8_t> one(1, '1'); - - { - // Change visibility from true to false and make sure we get notifications. - SharedPropertyChangeObserver observer(&v1); - v1.SetSharedProperty("one", &one); - Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(1U, changes.size()); - EXPECT_EQ( - "view=0,1 shared property changed key=one old_value=NULL new_value=1", - changes[0]); - EXPECT_EQ(1U, v1.shared_properties().size()); - } - { - // Set visible to existing value and verify no notifications. - SharedPropertyChangeObserver observer(&v1); - v1.SetSharedProperty("one", &one); - EXPECT_TRUE(observer.GetAndClearChanges().empty()); - EXPECT_EQ(1U, v1.shared_properties().size()); - } - { - // Set the value to NULL to delete it. - // Change visibility from true to false and make sure we get notifications. - SharedPropertyChangeObserver observer(&v1); - v1.SetSharedProperty("one", NULL); - Changes changes = observer.GetAndClearChanges(); - ASSERT_EQ(1U, changes.size()); - EXPECT_EQ( - "view=0,1 shared property changed key=one old_value=1 new_value=NULL", - changes[0]); - EXPECT_EQ(0U, v1.shared_properties().size()); - } - { - // Setting a null property to null shouldn't update us. - SharedPropertyChangeObserver observer(&v1); - v1.SetSharedProperty("one", NULL); - EXPECT_TRUE(observer.GetAndClearChanges().empty()); - EXPECT_EQ(0U, v1.shared_properties().size()); - } -} - -namespace { - -typedef std::pair<const void*, intptr_t> PropertyChangeInfo; - -class LocalPropertyChangeObserver : public ViewObserver { - public: - explicit LocalPropertyChangeObserver(View* view) - : view_(view), - property_key_(nullptr), - old_property_value_(-1) { - view_->AddObserver(this); - } - ~LocalPropertyChangeObserver() override { view_->RemoveObserver(this); } - - PropertyChangeInfo PropertyChangeInfoAndClear() { - PropertyChangeInfo result(property_key_, old_property_value_); - property_key_ = NULL; - old_property_value_ = -3; - return result; - } - - private: - void OnViewLocalPropertyChanged(View* window, - const void* key, - intptr_t old) override { - property_key_ = key; - old_property_value_ = old; - } - - View* view_; - const void* property_key_; - intptr_t old_property_value_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(LocalPropertyChangeObserver); -}; - -} // namespace - -TEST_F(ViewObserverTest, LocalPropertyChanged) { - TestView v1; - LocalPropertyChangeObserver o(&v1); - - static const ViewProperty<int> prop = {-2}; - - v1.SetLocalProperty(&prop, 1); - EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear()); - v1.SetLocalProperty(&prop, -2); - EXPECT_EQ(PropertyChangeInfo(&prop, 1), o.PropertyChangeInfoAndClear()); - v1.SetLocalProperty(&prop, 3); - EXPECT_EQ(PropertyChangeInfo(&prop, -2), o.PropertyChangeInfoAndClear()); - v1.ClearLocalProperty(&prop); - EXPECT_EQ(PropertyChangeInfo(&prop, 3), o.PropertyChangeInfoAndClear()); - - // Sanity check to see if |PropertyChangeInfoAndClear| really clears. - EXPECT_EQ(PropertyChangeInfo( - reinterpret_cast<const void*>(NULL), -3), o.PropertyChangeInfoAndClear()); -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/types.h b/third_party/mojo_services/src/view_manager/public/cpp/types.h deleted file mode 100644 index 56526912..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/types.h +++ /dev/null
@@ -1,25 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_TYPES_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_TYPES_H_ - -#include <stdint.h> - -// Typedefs for the transport types. These typedefs match that of the mojom -// file, see it for specifics. - -namespace mojo { - -// Used to identify views and change ids. -typedef uint32_t Id; - -// Used to identify a connection as well as a connection specific view id. For -// example, the Id for a view consists of the ConnectionSpecificId of the -// connection and the ConnectionSpecificId of the view. -typedef uint16_t ConnectionSpecificId; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_TYPES_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/util.h b/third_party/mojo_services/src/view_manager/public/cpp/util.h deleted file mode 100644 index 33e75dd..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/util.h +++ /dev/null
@@ -1,30 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_UTIL_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_UTIL_H_ - -#include "view_manager/public/cpp/types.h" - -// TODO(beng): #$*&@#(@ MacOSX SDK! -#if defined(HiWord) -#undef HiWord -#endif -#if defined(LoWord) -#undef LoWord -#endif - -namespace mojo { - -inline uint16_t HiWord(uint32_t id) { - return static_cast<uint16_t>((id >> 16) & 0xFFFF); -} - -inline uint16_t LoWord(uint32_t id) { - return static_cast<uint16_t>(id & 0xFFFF); -} - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_UTIL_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view.h b/third_party/mojo_services/src/view_manager/public/cpp/view.h deleted file mode 100644 index fcb49bc..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view.h +++ /dev/null
@@ -1,210 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_H_ - -#include <stdint.h> -#include <vector> - -#include "base/observer_list.h" -#include "geometry/public/interfaces/geometry.mojom.h" -#include "mojo/public/cpp/bindings/array.h" -#include "mojo/public/cpp/system/macros.h" -#include "mojo/public/interfaces/application/service_provider.mojom.h" -#include "surfaces/public/interfaces/surface_id.mojom.h" -#include "view_manager/public/cpp/types.h" -#include "view_manager/public/interfaces/view_manager.mojom.h" -#include "view_manager/public/interfaces/view_manager_constants.mojom.h" - -namespace mojo { - -class ServiceProviderImpl; -class View; -class ViewManager; -class ViewObserver; - -// Defined in view_property.h (which we do not include) -template <typename T> -struct ViewProperty; - -// Views are owned by the ViewManager. -// TODO(beng): Right now, you'll have to implement a ViewObserver to track -// destruction and NULL any pointers you have. -// Investigate some kind of smart pointer or weak pointer for these. -class View { - public: - using Children = std::vector<View*>; - using SharedProperties = std::map<std::string, std::vector<uint8_t>>; - - // Destroys this view and all its children. - void Destroy(); - - ViewManager* view_manager() { return manager_; } - - // Configuration. - Id id() const { return id_; } - - // Geometric disposition. - const Rect& bounds() const { return bounds_; } - void SetBounds(const Rect& bounds); - - // Visibility (also see IsDrawn()). When created views are hidden. - bool visible() const { return visible_; } - void SetVisible(bool value); - - const ViewportMetrics& viewport_metrics() { return *viewport_metrics_; } - - // Returns the set of string to bag of byte properties. These properties are - // shared with the view manager. - const SharedProperties& shared_properties() const { return properties_; } - // Sets a property. If |data| is null, this property is deleted. - void SetSharedProperty(const std::string& name, - const std::vector<uint8_t>* data); - - // Sets the |value| of the given window |property|. Setting to the default - // value (e.g., NULL) removes the property. The caller is responsible for the - // lifetime of any object set as a property on the View. - // - // These properties are not visible to the view manager. - template <typename T> - void SetLocalProperty(const ViewProperty<T>* property, T value); - - // Returns the value of the given window |property|. Returns the - // property-specific default value if the property was not previously set. - // - // These properties are only visible in the current process and are not - // shared with other mojo services. - template <typename T> - T GetLocalProperty(const ViewProperty<T>* property) const; - - // Sets the |property| to its default value. Useful for avoiding a cast when - // setting to NULL. - // - // These properties are only visible in the current process and are not - // shared with other mojo services. - template <typename T> - void ClearLocalProperty(const ViewProperty<T>* property); - - // Type of a function to delete a property that this view owns. - typedef void (*PropertyDeallocator)(int64_t value); - - // A View is drawn if the View and all its ancestors are visible and the - // View is attached to the root. - bool IsDrawn() const; - - // Observation. - void AddObserver(ViewObserver* observer); - void RemoveObserver(ViewObserver* observer); - - // Tree. - View* parent() { return parent_; } - const View* parent() const { return parent_; } - const Children& children() const { return children_; } - View* GetRoot() { - return const_cast<View*>(const_cast<const View*>(this)->GetRoot()); - } - const View* GetRoot() const; - - void AddChild(View* child); - void RemoveChild(View* child); - - void Reorder(View* relative, OrderDirection direction); - void MoveToFront(); - void MoveToBack(); - - bool Contains(View* child) const; - - View* GetChildById(Id id); - - void SetSurfaceId(SurfaceIdPtr id); - - // Focus. - void SetFocus(); - - // Embedding. See view_manager.mojom for details. - void Embed(const String& url); - void Embed(const String& url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services); - void Embed(ViewManagerClientPtr client); - - protected: - // This class is subclassed only by test classes that provide a public ctor. - View(); - ~View(); - - private: - friend class ViewPrivate; - friend class ViewManagerClientImpl; - - View(ViewManager* manager, Id id); - - // Called by the public {Set,Get,Clear}Property functions. - int64_t SetLocalPropertyInternal(const void* key, - const char* name, - PropertyDeallocator deallocator, - int64_t value, - int64_t default_value); - int64_t GetLocalPropertyInternal(const void* key, - int64_t default_value) const; - - void LocalDestroy(); - void LocalAddChild(View* child); - void LocalRemoveChild(View* child); - // Returns true if the order actually changed. - bool LocalReorder(View* relative, OrderDirection direction); - void LocalSetBounds(const Rect& old_bounds, const Rect& new_bounds); - void LocalSetViewportMetrics(const ViewportMetrics& old_metrics, - const ViewportMetrics& new_metrics); - void LocalSetDrawn(bool drawn); - void LocalSetVisible(bool visible); - - // Methods implementing visibility change notifications. See ViewObserver - // for more details. - void NotifyViewVisibilityChanged(View* target); - // Notifies this view's observers. Returns false if |this| was deleted during - // the call (by an observer), otherwise true. - bool NotifyViewVisibilityChangedAtReceiver(View* target); - // Notifies this view and its child hierarchy. Returns false if |this| was - // deleted during the call (by an observer), otherwise true. - bool NotifyViewVisibilityChangedDown(View* target); - // Notifies this view and its parent hierarchy. - void NotifyViewVisibilityChangedUp(View* target); - - ViewManager* manager_; - Id id_; - View* parent_; - Children children_; - - ObserverList<ViewObserver> observers_; - - Rect bounds_; - ViewportMetricsPtr viewport_metrics_; - - bool visible_; - - SharedProperties properties_; - - // Drawn state is derived from the visible state and the parent's visible - // state. This field is only used if the view has no parent (eg it's a root). - bool drawn_; - - // Value struct to keep the name and deallocator for this property. - // Key cannot be used for this purpose because it can be char* or - // WindowProperty<>. - struct Value { - const char* name; - int64_t value; - PropertyDeallocator deallocator; - }; - - std::map<const void*, Value> prop_map_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(View); -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_manager.h b/third_party/mojo_services/src/view_manager/public/cpp/view_manager.h deleted file mode 100644 index 5852dd2..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_manager.h +++ /dev/null
@@ -1,42 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_H_ - -#include <string> - -#include "view_manager/public/cpp/types.h" - -namespace mojo { -class View; - -// Encapsulates a connection to the view manager service. A unique connection -// is made every time an app is embedded. -class ViewManager { - public: - // Returns the URL of the application that embedded this application. - virtual const std::string& GetEmbedderURL() const = 0; - - // Returns the root of this connection. - virtual View* GetRoot() = 0; - - // Returns a View known to this connection. - virtual View* GetViewById(Id id) = 0; - - // Returns the focused view; null if focus is not yet known or another app is - // focused. - virtual View* GetFocusedView() = 0; - - // Creates and returns a new View (which is owned by the ViewManager). Views - // are initially hidden, use SetVisible(true) to show. - virtual View* CreateView() = 0; - - protected: - virtual ~ViewManager() {} -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h b/third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h deleted file mode 100644 index e47da3d5..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_client_factory.h +++ /dev/null
@@ -1,43 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CLIENT_FACTORY_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CLIENT_FACTORY_H_ - -#include "mojo/public/cpp/application/interface_factory.h" -#include "view_manager/public/interfaces/view_manager.mojom.h" - -namespace mojo { - -class ViewManagerDelegate; -class Shell; - -// Add an instance of this class to an incoming connection to allow it to -// instantiate ViewManagerClient implementations in response to -// ViewManagerClient requests. -class ViewManagerClientFactory : public InterfaceFactory<ViewManagerClient> { - public: - ViewManagerClientFactory(Shell* shell, ViewManagerDelegate* delegate); - ~ViewManagerClientFactory() override; - - // Creates a ViewManagerClient from the supplied arguments. Returns ownership - // to the caller. - static ViewManagerClient* WeakBindViewManagerToPipe( - InterfaceRequest<ViewManagerClient> request, - ViewManagerServicePtr view_manager_service, - Shell* shell, - ViewManagerDelegate* delegate); - - // InterfaceFactory<ViewManagerClient> implementation. - void Create(ApplicationConnection* connection, - InterfaceRequest<ViewManagerClient> request) override; - - private: - Shell* shell_; - ViewManagerDelegate* delegate_; -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CLIENT_FACTORY_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h b/third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h deleted file mode 100644 index de7b84be..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_context.h +++ /dev/null
@@ -1,46 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CONTEXT_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CONTEXT_H_ - -#include <string> -#include <vector> - -#include "mojo/public/cpp/application/service_provider_impl.h" -#include "mojo/public/cpp/system/macros.h" - -namespace mojo { -class ApplicationImpl; - -class ViewManagerContext { - public: - explicit ViewManagerContext(ApplicationImpl* application_impl); - ~ViewManagerContext(); - - // Embed an application @ |url| at an appropriate View. - // The first time this method is called in the life time of the View Manager - // service the "appropriate View" is defined as being the service' root View. - // Subsequent times, the implementation of this method is delegated to the - // application embedded at the service root View. This application will have a - // specific definition of where within its View hierarchy to embed an - // un-parented URL. - // |services| encapsulates services offered by the embedder to the embedded - // app alongside this Embed() call. |exposed_services| provides a means for - // the embedder to connect to services exposed by the embedded app. - void Embed(const String& url); - void Embed(const String& url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_Services); - - private: - class InternalState; - InternalState* state_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ViewManagerContext); -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_CONTEXT_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.cc b/third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.cc deleted file mode 100644 index 4ae64a7b..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.cc +++ /dev/null
@@ -1,14 +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 "view_manager/public/cpp/view_manager_delegate.h" - -namespace mojo { - -bool ViewManagerDelegate::OnPerformAction(View* view, - const std::string& action) { - return false; -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h b/third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h deleted file mode 100644 index 1590a591..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_manager_delegate.h +++ /dev/null
@@ -1,52 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_DELEGATE_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_DELEGATE_H_ - -#include <string> - -#include "mojo/public/interfaces/application/service_provider.mojom.h" - -namespace mojo { - -class View; -class ViewManager; - -// Interface implemented by an application using the view manager. -class ViewManagerDelegate { - public: - // Called when the application implementing this interface is embedded at - // |root|. Every embed results in a new ViewManager and root View being - // created. |root| and it's corresponding ViewManager are valid until - // OnViewManagerDisconnected() is called with the same object. - // - // |services| exposes the services offered by the embedder to the delegate. - // - // |exposed_services| is an object that the delegate can add services to - // expose to the embedder. - // - // Note that if a different application is subsequently embedded at |root|, - // the pipes connecting |services| and |exposed_services| to the embedder and - // any services obtained from them are not broken and will continue to be - // valid. - virtual void OnEmbed(View* root, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services) = 0; - - // Called when a connection to the view manager service is closed. - // |view_manager| is not valid after this function returns. - virtual void OnViewManagerDisconnected(ViewManager* view_manager) = 0; - - // Asks the delegate to perform the specified action. - // TODO(sky): nuke! See comments in view_manager.mojom for details. - virtual bool OnPerformAction(View* view, const std::string& action); - - protected: - virtual ~ViewManagerDelegate() {} -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_MANAGER_DELEGATE_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_observer.h b/third_party/mojo_services/src/view_manager/public/cpp/view_observer.h deleted file mode 100644 index 341a4f00..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_observer.h +++ /dev/null
@@ -1,106 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_OBSERVER_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_OBSERVER_H_ - -#include <vector> - -#include "input_events/public/interfaces/input_events.mojom.h" -#include "view_manager/public/cpp/view.h" - -namespace mojo { - -class View; - -// A note on -ing and -ed suffixes: -// -// -ing methods are called before changes are applied to the local view model. -// -ed methods are called after changes are applied to the local view model. -// -// If the change originated from another connection to the view manager, it's -// possible that the change has already been applied to the service-side model -// prior to being called, so for example in the case of OnViewDestroying(), it's -// possible the view has already been destroyed on the service side. - -class ViewObserver { - public: - struct TreeChangeParams { - TreeChangeParams(); - View* target; - View* old_parent; - View* new_parent; - View* receiver; - }; - - virtual void OnTreeChanging(const TreeChangeParams& params) {} - virtual void OnTreeChanged(const TreeChangeParams& params) {} - - virtual void OnViewReordering(View* view, - View* relative_view, - OrderDirection direction) {} - virtual void OnViewReordered(View* view, - View* relative_view, - OrderDirection direction) {} - - virtual void OnViewDestroying(View* view) {} - virtual void OnViewDestroyed(View* view) {} - - virtual void OnViewBoundsChanging(View* view, - const Rect& old_bounds, - const Rect& new_bounds) {} - virtual void OnViewBoundsChanged(View* view, - const Rect& old_bounds, - const Rect& new_bounds) {} - - virtual void OnViewViewportMetricsChanged(View* view, - const ViewportMetrics& old_bounds, - const ViewportMetrics& new_bounds) { - } - - virtual void OnViewCaptureChanged(View* gained_capture, View* lost_capture) {} - virtual void OnViewFocusChanged(View* gained_focus, View* lost_focus) {} - virtual void OnViewActivationChanged(View* gained_active, View* lost_active) { - } - - virtual void OnViewInputEvent(View* view, const EventPtr& event) {} - - virtual void OnViewVisibilityChanging(View* view) {} - virtual void OnViewVisibilityChanged(View* view) {} - - // Invoked when this View's shared properties have changed. This can either - // be caused by SetSharedProperty() being called locally, or by us receiving - // a mojo message that this property has changed. If this property has been - // added, |old_data| is null. If this property was removed, |new_data| is - // null. - virtual void OnViewSharedPropertyChanged( - View* view, - const std::string& name, - const std::vector<uint8_t>* old_data, - const std::vector<uint8_t>* new_data) {} - - // Invoked when SetProperty() or ClearProperty() is called on the window. - // |key| is either a WindowProperty<T>* (SetProperty, ClearProperty). Either - // way, it can simply be compared for equality with the property - // constant. |old| is the old property value, which must be cast to the - // appropriate type before use. - virtual void OnViewLocalPropertyChanged( - View* view, - const void* key, - intptr_t old) {} - - virtual void OnViewEmbeddedAppDisconnected(View* view) {} - - // Sent when the drawn state changes. This is only sent for the root nodes - // when embedded. - virtual void OnViewDrawnChanging(View* view) {} - virtual void OnViewDrawnChanged(View* view) {} - - protected: - virtual ~ViewObserver() {} -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_OBSERVER_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_property.h b/third_party/mojo_services/src/view_manager/public/cpp/view_property.h deleted file mode 100644 index 2dbd317b..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_property.h +++ /dev/null
@@ -1,140 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_PROPERTY_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_PROPERTY_H_ - -#include <stdint.h> - -// This header should be included by code that defines ViewProperties. It -// should not be included by code that only gets and sets ViewProperties. -// -// To define a new ViewProperty: -// -// #include "view_manager/public/cpp/view_property.h" -// -// DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(FOO_EXPORT, MyType); -// namespace foo { -// // Use this to define an exported property that is premitive, -// // or a pointer you don't want automatically deleted. -// DEFINE_VIEW_PROPERTY_KEY(MyType, kMyKey, MyDefault); -// -// // Use this to define an exported property whose value is a heap -// // allocated object, and has to be owned and freed by the view. -// DEFINE_OWNED_VIEW_PROPERTY_KEY(gfx::Rect, kRestoreBoundsKey, nullptr); -// -// // Use this to define a non exported property that is primitive, -// // or a pointer you don't want to automatically deleted, and is used -// // only in a specific file. This will define the property in an unnamed -// // namespace which cannot be accessed from another file. -// DEFINE_LOCAL_VIEW_PROPERTY_KEY(MyType, kMyKey, MyDefault); -// -// } // foo namespace -// -// To define a new type used for ViewProperty. -// -// // outside all namespaces: -// DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(FOO_EXPORT, MyType) -// -// If a property type is not exported, use DECLARE_VIEW_PROPERTY_TYPE(MyType) -// which is a shorthand for DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(, MyType). - -namespace mojo { -namespace { - -// No single new-style cast works for every conversion to/from int64_t, so we -// need this helper class. A third specialization is needed for bool because -// MSVC warning C4800 (forcing value to bool) is not suppressed by an explicit -// cast (!). -template <typename T> -class ViewPropertyCaster { - public: - static int64_t ToInt64(T x) { return static_cast<int64_t>(x); } - static T FromInt64(int64_t x) { return static_cast<T>(x); } -}; -template <typename T> -class ViewPropertyCaster<T*> { - public: - static int64_t ToInt64(T* x) { return reinterpret_cast<int64_t>(x); } - static T* FromInt64(int64_t x) { return reinterpret_cast<T*>(x); } -}; -template <> -class ViewPropertyCaster<bool> { - public: - static int64_t ToInt64(bool x) { return static_cast<int64_t>(x); } - static bool FromInt64(int64_t x) { return x != 0; } -}; - -} // namespace - -template <typename T> -struct ViewProperty { - T default_value; - const char* name; - View::PropertyDeallocator deallocator; -}; - -template <typename T> -void View::SetLocalProperty(const ViewProperty<T>* property, T value) { - int64_t old = SetLocalPropertyInternal( - property, property->name, - value == property->default_value ? nullptr : property->deallocator, - ViewPropertyCaster<T>::ToInt64(value), - ViewPropertyCaster<T>::ToInt64(property->default_value)); - if (property->deallocator && - old != ViewPropertyCaster<T>::ToInt64(property->default_value)) { - (*property->deallocator)(old); - } -} - -template <typename T> -T View::GetLocalProperty(const ViewProperty<T>* property) const { - return ViewPropertyCaster<T>::FromInt64(GetLocalPropertyInternal( - property, ViewPropertyCaster<T>::ToInt64(property->default_value))); -} - -template <typename T> -void View::ClearLocalProperty(const ViewProperty<T>* property) { - SetLocalProperty(property, property->default_value); -} - -} // namespace mojo - -// Macros to instantiate the property getter/setter template functions. -#define DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(EXPORT, T) \ - template EXPORT void mojo::View::SetLocalProperty( \ - const mojo::ViewProperty<T>*, T); \ - template EXPORT T mojo::View::GetLocalProperty(const mojo::ViewProperty<T>*) \ - const; \ - template EXPORT void mojo::View::ClearLocalProperty( \ - const mojo::ViewProperty<T>*); -#define DECLARE_VIEW_PROPERTY_TYPE(T) DECLARE_EXPORTED_VIEW_PROPERTY_TYPE(, T) - -#define DEFINE_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ - COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64_t), property_type_too_large); \ - namespace { \ - const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \ - } \ - const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value; - -#define DEFINE_LOCAL_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ - COMPILE_ASSERT(sizeof(TYPE) <= sizeof(int64_t), property_type_too_large); \ - namespace { \ - const mojo::ViewProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \ - const mojo::ViewProperty<TYPE>* const NAME = &NAME##_Value; \ - } - -#define DEFINE_OWNED_VIEW_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ - namespace { \ - void Deallocator##NAME(int64_t p) { \ - enum { type_must_be_complete = sizeof(TYPE) }; \ - delete mojo::ViewPropertyCaster<TYPE*>::FromInt64(p); \ - } \ - const mojo::ViewProperty<TYPE*> NAME##_Value = {DEFAULT, \ - #NAME, \ - &Deallocator##NAME}; \ - } \ - const mojo::ViewProperty<TYPE*>* const NAME = &NAME##_Value; - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_PROPERTY_H_
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.cc b/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.cc deleted file mode 100644 index 317b97a..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.cc +++ /dev/null
@@ -1,41 +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 "view_manager/public/cpp/view_tracker.h" - -namespace mojo { - -ViewTracker::ViewTracker() { -} - -ViewTracker::~ViewTracker() { - for (Views::iterator i = views_.begin(); i != views_.end(); ++i) - (*i)->RemoveObserver(this); -} - -void ViewTracker::Add(View* view) { - if (views_.count(view)) - return; - - view->AddObserver(this); - views_.insert(view); -} - -void ViewTracker::Remove(View* view) { - if (views_.count(view)) { - views_.erase(view); - view->RemoveObserver(this); - } -} - -bool ViewTracker::Contains(View* view) { - return views_.count(view) > 0; -} - -void ViewTracker::OnViewDestroying(View* view) { - DCHECK_GT(views_.count(view), 0u); - Remove(view); -} - -} // namespace mojo
diff --git a/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h b/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h deleted file mode 100644 index cfc2b9d6..0000000 --- a/third_party/mojo_services/src/view_manager/public/cpp/view_tracker.h +++ /dev/null
@@ -1,47 +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 MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_TRACKER_H_ -#define MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_TRACKER_H_ - -#include <stdint.h> -#include <set> - -#include "mojo/public/cpp/system/macros.h" -#include "view_manager/public/cpp/view_observer.h" - -namespace mojo { - -class ViewTracker : public ViewObserver { - public: - using Views = std::set<View*>; - - ViewTracker(); - ~ViewTracker() override; - - // Returns the set of views being observed. - const std::set<View*>& views() const { return views_; } - - // Adds |view| to the set of Views being tracked. - void Add(View* view); - - // Removes |view| from the set of views being tracked. - void Remove(View* view); - - // Returns true if |view| was previously added and has not been removed or - // deleted. - bool Contains(View* view); - - // ViewObserver overrides: - void OnViewDestroying(View* view) override; - - private: - Views views_; - - MOJO_DISALLOW_COPY_AND_ASSIGN(ViewTracker); -}; - -} // namespace mojo - -#endif // MOJO_SERVICES_VIEW_MANAGER_PUBLIC_CPP_VIEW_TRACKER_H_
diff --git a/third_party/mojo_services/src/view_manager/public/interfaces/BUILD.gn b/third_party/mojo_services/src/view_manager/public/interfaces/BUILD.gn deleted file mode 100644 index 177066b8..0000000 --- a/third_party/mojo_services/src/view_manager/public/interfaces/BUILD.gn +++ /dev/null
@@ -1,25 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "animations.mojom", - "view_manager.mojom", - "view_manager_constants.mojom", - ] - - import_dirs = [ get_path_info("../../../", "abspath") ] - - mojo_sdk_deps = [ "mojo/public/interfaces/application" ] - - deps = [ - "../../../geometry/public/interfaces", - "../../../input_events/public/interfaces", - "../../../native_viewport/public/interfaces", - "../../../surfaces/public/interfaces:surface_id", - ] -}
diff --git a/third_party/mojo_services/src/view_manager/public/interfaces/animations.mojom b/third_party/mojo_services/src/view_manager/public/interfaces/animations.mojom deleted file mode 100644 index 59572c4..0000000 --- a/third_party/mojo_services/src/view_manager/public/interfaces/animations.mojom +++ /dev/null
@@ -1,61 +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 mojo; - -import "geometry/public/interfaces/geometry.mojom"; - -enum AnimationTweenType { - LINEAR, - EASE_IN, - EASE_OUT, - EASE_IN_OUT, -}; - -enum AnimationProperty { - // Used for pausing. - NONE, - OPACITY, - TRANSFORM, -}; - -struct AnimationValue { - float float_value; - Transform transform; -}; - -// Identifies how a particular property should be animated between a start and -// target value. -struct AnimationElement { - AnimationProperty property; - - // Duration is in microseconds. - int64 duration; - - AnimationTweenType tween_type; - - // If not specified the start value is taken from either the current value - // (for the first element) or the target_value of the previous element. - AnimationValue? start_value; - - // target_value may be null when property is NONE. - AnimationValue? target_value; -}; - -// An AnimationSequence consists of a number of AnimationElements to animate. -// Each element is animated serially. -struct AnimationSequence { - // Number of times to run the sequence. Value of 0 means run until - // explicitly stopped. - uint32 cycle_count; - - array<AnimationElement> elements; -}; - -// AnimationGroup identifies a view and a set of AnimationSequences to apply -// to the view. Each sequence is run in parallel. -struct AnimationGroup { - uint32 view_id; - array<AnimationSequence> sequences; -};
diff --git a/third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom b/third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom deleted file mode 100644 index 0a2564e..0000000 --- a/third_party/mojo_services/src/view_manager/public/interfaces/view_manager.mojom +++ /dev/null
@@ -1,230 +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 mojo; - -import "geometry/public/interfaces/geometry.mojom"; -import "input_events/public/interfaces/input_events.mojom"; -import "mojo/public/interfaces/application/service_provider.mojom"; -import "native_viewport/public/interfaces/native_viewport.mojom"; -import "surfaces/public/interfaces/surface_id.mojom"; -import "view_manager/public/interfaces/view_manager_constants.mojom"; - -struct ViewData { - uint32 parent_id; - uint32 view_id; - mojo.Rect bounds; - map<string, array<uint8>> properties; - // True if this view is visible. The view may not be drawn on screen (see - // drawn for specifics). - bool visible; - // True if this view is drawn on screen. A view is drawn if attached to the - // root and all ancestors (including this view) are visible. - bool drawn; - ViewportMetrics viewport_metrics; -}; - -enum ErrorCode { - NONE, - VALUE_IN_USE, - ILLEGAL_ARGUMENT, -}; - -// Views are identified by a uint32. The upper 16 bits are the connection id, -// and the lower 16 the id assigned by the client. -// -// The root view is identified with a connection id of 0, and value of 1. -interface ViewManagerService { - // Creates a new view with the specified id. It is up to the client to ensure - // the id is unique to the connection (the id need not be globally unique). - // Additionally the connection id (embedded in |view_id|) must match that of - // the connection. - // Errors: - // ERROR_CODE_VALUE_IN_USE: a view already exists with the specified id. - // ERROR_CODE_ILLEGAL_ARGUMENT: The connection part of |view_id| does not - // match the connection id of the client. - // - // TODO(erg): Once we have default values in mojo, make this take a map of - // properties. - CreateView(uint32 view_id) => (ErrorCode error_code); - - // Deletes a view. This does not recurse. No hierarchy change notifications - // are sent as a result of this. Only the connection that created the view can - // delete it. - DeleteView(uint32 view_id) => (bool success); - - // Sets the specified bounds of the specified view. - SetViewBounds(uint32 view_id, mojo.Rect bounds) => (bool success); - - // Sets the visibility of the specified view to |visible|. Connections are - // allowed to change the visibility of any view they have created, as well as - // any of their roots. - SetViewVisibility(uint32 view_id, bool visible) => (bool success); - - // Sets an individual named property. Setting an individual property to null - // deletes the property. - SetViewProperty(uint32 view_id, - string name, - array<uint8>? value) => (bool success); - - // Reparents a view. - // This fails for any of the following reasons: - // . |parent| or |child| does not identify a valid view. - // . |child| is an ancestor of |parent|. - // . |child| is already a child of |parent|. - // - // This may result in a connection getting OnViewDeleted(). See - // RemoveViewFromParent for details. - AddView(uint32 parent, uint32 child) => (bool success); - - // Removes a view from its current parent. This fails if the view is not - // valid or the view already has no parent. - // - // Removing a view from a parent may result in OnViewDeleted() being sent to - // other connections. For example, connection A has views 1 and 2, with 2 a - // child of 1. Connection B has a root 1. If 2 is removed from 1 then B gets - // OnViewDeleted(). This is done as view 2 is effectively no longer visible to - // connection B. - RemoveViewFromParent(uint32 view_id) => (bool success); - - // Reorders a view in its parent, relative to |relative_view_id| according to - // |direction|. - // Only the connection that created the view's parent can reorder its - // children. - ReorderView(uint32 view_id, - uint32 relative_view_id, - OrderDirection direction) => (bool success); - - // Returns the views comprising the tree starting at |view_id|. |view_id| is - // the first result in the return value, unless |view_id| is invalid, in which - // case an empty vector is returned. The views are visited using a depth first - // search (pre-order). - GetViewTree(uint32 view_id) => (array<ViewData> views); - - // Shows the surface in the specified view. - SetViewSurfaceId(uint32 view_id, SurfaceId surface_id) => (bool success); - - // A connection may grant access to a view from another connection by way of - // the embed functions. There are two variants of this call: - // - // . EmbedUrl: the ViewManager connects to the app at the supplied url and - // asks it for a ViewManagerClient. - // . With the second variant a ViewManagerClient is directly supplied. - // - // In both cases the new ViewManagerClient is configured with a root of - // |view_id|. - // - // The caller must have created |view_id|. If not the request fails and the - // response is false. - // - // A view may only be a root of one connection at a time. Subsequent calls to - // Embed() for the same view result in the view being removed from the - // currently embedded app. The embedded app is told this by way of - // OnViewDeleted(). - // - // The embedder can detect when the embedded app disconnects by way of - // OnEmbeddedAppDisconnected(). - // - // When a connection embeds an app the connection no longer has priviledges - // to access or see any of the children of the view. If the view had existing - // children the children are removed. The one exception is the root - // connection. - // - // |services| encapsulates services offered by the embedder to the embedded - // app alongside this Embed() call. |exposed_services| provides a means for - // the embedder to connect to services exposed by the embedded app. Note that - // if a different app is subsequently embedded at |view_id| the - // ServiceProvider connections to its client in the embedded app and any - // services it provided are not broken and continue to be valid. - EmbedUrl(string url, - uint32 view_id, - ServiceProvider&? services, - ServiceProvider? exposed_services) => (bool success); - Embed(uint32 view_id, ViewManagerClient client) => (bool success); - - // Requests the WindowManager to perform an action on the specified view. - // It's up to the WindowManager to decide what |action| is. - // - // TODO(sky): nuke this. This is here to guarantee the state of the - // WindowManager matches that of the ViewManager at the time the client - // invokes the function. When we can enforce ordering this won't be necessary. - PerformAction(uint32 view_id, string action) => (bool success); -}; - -// Changes to views are not sent to the connection that originated the -// change. For example, if connection 1 changes the bounds of a view by calling -// SetBounds(), connection 1 does not receive OnViewBoundsChanged(). -interface ViewManagerClient { - // Invoked when the client application has been embedded at |root|. - // See Embed() on ViewManagerService for more details. |view_manager_service| - // will be a handle back to the view manager service, unless the connection is - // to the WindowManager in which case it will be null. - // |window_manager_pipe| is a pipe to the WindowManager. - OnEmbed(uint16 connection_id, - string embedder_url, - ViewData root, - ViewManagerService? view_manager_service, - ServiceProvider&? services, - ServiceProvider? exposed_services, - handle<message_pipe> window_manager_pipe); - - // Invoked when the application embedded at |view| is disconnected. - OnEmbeddedAppDisconnected(uint32 view); - - // Invoked when a view's bounds have changed. - OnViewBoundsChanged(uint32 view, - mojo.Rect old_bounds, - mojo.Rect new_bounds); - - // Invoked when the viewport metrics for the view have changed. - // Clients are expected to propagate this to the view tree. - OnViewViewportMetricsChanged(mojo.ViewportMetrics old_metrics, - mojo.ViewportMetrics new_metrics); - - // Invoked when a change is done to the hierarchy. A value of 0 is used to - // identify a null view. For example, if the old_parent is NULL, 0 is - // supplied. - // |views| contains any views that are that the client has not been told - // about. This is not sent for hierarchy changes of views not known to this - // client or not attached to the tree. - OnViewHierarchyChanged(uint32 view, - uint32 new_parent, - uint32 old_parent, - array<ViewData> views); - - // Invoked when the order of views within a parent changes. - OnViewReordered(uint32 view_id, - uint32 relative_view_id, - OrderDirection direction); - - // Invoked when a view is deleted. - OnViewDeleted(uint32 view); - - // Invoked when the visibility of the specified view changes. - OnViewVisibilityChanged(uint32 view, bool visible); - - // Invoked when a change to the visibility of |view| or one if it's ancestors - // is done such that the drawn state changes. This is only invoked for the - // top most view of a particular connection. For example, if you have the - // hierarchy: A -> B1 -> B2 (B2 is a child of B1 and B1 a child of A), B1/B2 - // are from connection 2 and A from connection 1 with all views visible and - // drawn and the visiblity of A changes to false, then connection 2 is told - // the drawn state of B1 has changed (to false), but is not told anything - // about B2 as it's drawn state can be calculated from that of B1. - // - // NOTE: This is not invoked if OnViewVisibilityChanged() is invoked. - OnViewDrawnStateChanged(uint32 view, bool drawn); - - // Invoked when a view property is changed. If this change is a removal, - // |new_data| is null. - OnViewSharedPropertyChanged(uint32 view, string name, array<uint8>? new_data); - - // Invoked when an event is targeted at the specified view. - OnViewInputEvent(uint32 view, mojo.Event event) => (); - - // Invoked solely on the WindowManager. See comments in PerformAction() above - // for details. - // TODO(sky): nuke this. - OnPerformAction(uint32 view_id, string action) => (bool success); -};
diff --git a/third_party/mojo_services/src/window_manager/public/interfaces/BUILD.gn b/third_party/mojo_services/src/window_manager/public/interfaces/BUILD.gn deleted file mode 100644 index b97f069..0000000 --- a/third_party/mojo_services/src/window_manager/public/interfaces/BUILD.gn +++ /dev/null
@@ -1,22 +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. - -import("//build/module_args/mojo.gni") -import("$mojo_sdk_root/mojo/public/tools/bindings/mojom.gni") - -mojom("interfaces") { - sources = [ - "window_manager.mojom", - "window_manager_internal.mojom", - ] - - import_dirs = [ get_path_info("../../../", "abspath") ] - - mojo_sdk_deps = [ "mojo/public/interfaces/application" ] - - deps = [ - "../../../geometry/public/interfaces", - "../../../input_events/public/interfaces", - ] -}
diff --git a/third_party/mojo_services/src/window_manager/public/interfaces/window_manager.mojom b/third_party/mojo_services/src/window_manager/public/interfaces/window_manager.mojom deleted file mode 100644 index ee1b02e..0000000 --- a/third_party/mojo_services/src/window_manager/public/interfaces/window_manager.mojom +++ /dev/null
@@ -1,36 +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 mojo; - -import "input_events/public/interfaces/input_events.mojom"; -import "mojo/public/interfaces/application/service_provider.mojom"; - -interface WindowManager { - // Requests the WindowManager to embed the app for |url| at an appropriate - // View. See ViewMangerService::Embed() for details on |services| and - // |exposed_services|. - Embed(string url, - ServiceProvider&? services, - ServiceProvider? exposed_services); - - SetCapture(uint32 view_id) => (bool success); - FocusWindow(uint32 view_id) => (bool success); - ActivateWindow(uint32 view_id) => (bool success); - - // Requests the current focus and activation state and an interface to observe - // future changes. - // If |observer| is not null capture, focus and activation updates will be - // sent to it. - GetFocusedAndActiveViews(WindowManagerObserver? observer) - => (uint32 capture_view_id, - uint32 focused_view_id, - uint32 active_view_id); -}; - -interface WindowManagerObserver { - OnCaptureChanged(uint32 capture_view_id); - OnFocusChanged(uint32 focused_view_id); - OnActiveWindowChanged(uint32 focused_view_id); -};
diff --git a/third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom b/third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom deleted file mode 100644 index bdb655d6..0000000 --- a/third_party/mojo_services/src/window_manager/public/interfaces/window_manager_internal.mojom +++ /dev/null
@@ -1,39 +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 mojo; - -import "geometry/public/interfaces/geometry.mojom"; -import "input_events/public/interfaces/input_events.mojom"; - -// WindowManagerInternal is an interface provided by the WindowManager -// exclusively to the ViewManager. -interface WindowManagerInternal { - // Creates a connection to the WindowManager specifically for a connection to - // the ViewManager. |connection_id| is the id of the connection to the - // ViewManager. See view_manager.mojom for details on the id. - CreateWindowManagerForViewManagerClient( - uint16 connection_id, - handle<message_pipe> window_manager_pipe); - - SetViewManagerClient(handle<message_pipe> view_manager_client_request); -}; - -// WindowManagerInternalClient is an interface provide by the ViewManager -// exclusively to the WindowManager. It provides functionality only available -// to the WindowManager. -interface WindowManagerInternalClient { - // Dispatches the specified input event to the specified view. - DispatchInputEventToView(uint32 view_id, mojo.Event event); - - // Sets the native viewport size. - SetViewportSize(mojo.Size size); - - // Clones the tree rooted at |view_id|. When the animation completes the clone - // is destroyed. - // TODO(sky): add actual animation. - // TODO(sky): I think this only makes sense when destroying (view is - // already visible), should it be named to indicate this? - CloneAndAnimate(uint32 view_id); -};
diff --git a/third_party/omaha/BUILD.gn b/third_party/omaha/BUILD.gn new file mode 100644 index 0000000..fbed9fa --- /dev/null +++ b/third_party/omaha/BUILD.gn
@@ -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. + +source_set("extractor") { + sources = [ + "src/omaha/base/extractor.cc", + "src/omaha/base/extractor.h", + ] + + include_dirs = [ "src" ] +}
diff --git a/third_party/omaha/omaha.gyp b/third_party/omaha/omaha.gyp index e0d3fcd..de513f7 100644 --- a/third_party/omaha/omaha.gyp +++ b/third_party/omaha/omaha.gyp
@@ -5,6 +5,7 @@ { 'targets': [ { + # GN version: //third_party/omaha:extractor 'target_name': 'omaha_extractor', 'type': 'static_library', 'sources': [
diff --git a/third_party/polymer/v0_8/README.chromium b/third_party/polymer/v0_8/README.chromium new file mode 100644 index 0000000..d66fa7d --- /dev/null +++ b/third_party/polymer/v0_8/README.chromium
@@ -0,0 +1,53 @@ +Name: Polymer +Short Name: polymer +URL: http://www.polymer-project.org +Version: 0.8 +Revision: (See components/<component>/.bower.json) +License: BSD +License File: ../LICENSE.polymer +Security Critical: no + +Description: +This directory contains a copy of the following components which are a part of +the Polymer project: +-polymer +-Used Iron elements and their dependencies +-Used Paper elements and their dependencies +See bower.json for a full list of components. + +The version can be found in header of polymer/polymer.js. The license can +be found in polymer/LICENSE. + +The source git repositories can be found at: +Core Library - https://github.com/Polymer/polymer/tree/0.8-preview +Elements - https://github.com/PolymerElements/<element name> + +Polymer is comprised of two efforts: +1. A set of core platform features (Shadow DOM, Custom Elements, MDV). +Initially, these core features will be enabled with a set of polyfills. As +browsers begin to implement these new primitives, the polyfill platform layer +becomes smaller and better over time. +2. A next-generation web application framework built upon these core +technologies called the Polymer. + +Local Modifications: +- Removed executable bit from the files in 'components/iron-selector'. +- Created a copy 'components-chromium' of the 'components' directory with the +only difference that all inline JavaScript blocks are extracted from Polymer +HTML elements to external JS files. This version of the Polymer is used in a web +UI, where CSP forbids an execution of inline scripts. The extraction was made +with the help of the Vulcanize tool (https://github.com/Polymer/vulcanize). +- Replaced CRLF line endings with LF line endings in text files. + +To restore a content of the 'components', 'components-chromium' directorires +from scratch, run ./reproduce.sh (requires bower and vulcanize >= 1.2). + +Note on Bower: +The directory can be updated by running "bower update". A new component can be +installed by running "bower install -S Polymer/<component>#version". Be sure to +add the .bower.json file to the repository as it includes the revision +information of the polymer component. +Also be sure that you listed all the added packages and **all their +dependencies** in bower.json, and specified **exact** versions of every package +explicitly. That is needed because Bower can't handle recursive dependencies +correctly (see http://stackoverflow.com/q/25899532).
diff --git a/third_party/polymer/v0_8/bower.json b/third_party/polymer/v0_8/bower.json new file mode 100644 index 0000000..69affae --- /dev/null +++ b/third_party/polymer/v0_8/bower.json
@@ -0,0 +1,20 @@ +{ + "name": "chromium", + "private": true, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + + "iron-icon": "PolymerElements/iron-icon#^0.8.0", + "iron-icons": "PolymerElements/iron-icons#^0.8.0", + "iron-iconset": "PolymerElements/iron-iconset#^0.8.0", + + "paper-button": "PolymerElements/paper-button#^0.8.0", + "paper-card": "PolymerElements/paper-card#^0.8.0", + "paper-checkbox": "PolymerElements/paper-checkbox#^0.8.0", + "paper-drawer-panel": "PolymerElements/paper-drawer-panel#^0.8.0", + "paper-input": "PolymerElements/paper-input#^0.8.0", + "paper-menu": "PolymerElements/paper-menu#^0.8.0", + "paper-ripple": "PolymerElements/paper-ripple#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-behaviors/.bower.json new file mode 100644 index 0000000..f7783c2 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/.bower.json
@@ -0,0 +1,28 @@ +{ + "name": "iron-behaviors", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "license": "MIT", + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + }, + "homepage": "https://github.com/polymerelements/iron-behaviors", + "version": "0.8.0", + "_release": "0.8.0", + "_resolution": { + "type": "version", + "tag": "v0.8.0", + "commit": "bde97715665a35c467efd869174eaadf6acea2ff" + }, + "_source": "git://github.com/polymerelements/iron-behaviors.git", + "_target": "^0.8.0", + "_originalSource": "polymerelements/iron-behaviors" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-behaviors/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/README.md b/third_party/polymer/v0_8/components-chromium/iron-behaviors/README.md new file mode 100644 index 0000000..593986e --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/README.md
@@ -0,0 +1,4 @@ +iron-behaviors +============== + +This repository collects shared behaviors that are mixed in to other elements.
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/bower.json b/third_party/polymer/v0_8/components-chromium/iron-behaviors/bower.json new file mode 100644 index 0000000..bc0c213 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/bower.json
@@ -0,0 +1,17 @@ +{ + "name": "iron-behaviors", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "license": "MIT", + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/index.html b/third_party/polymer/v0_8/components-chromium/iron-behaviors/index.html new file mode 100644 index 0000000..0e01e8a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-component-page/iron-component-page.html"> + +</head> +<body> + + <iron-component-page></iron-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-button-state-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-button-state-extracted.js new file mode 100644 index 0000000..dd8057d2 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-button-state-extracted.js
@@ -0,0 +1,141 @@ + + + Polymer.IronButtonState = { + + properties: { + + /** + * If true, the user is currently holding down the button. + * + * @attribute pressed + * @type boolean + * @default false + */ + pressed: { + type: Boolean, + readOnly: true, + reflectToAttribute: true, + observer: '_pressedChanged' + }, + + /** + * If true, the button toggles the active state with each tap or press + * of the spacebar. + * + * @attribute toggles + * @type boolean + * @default false + */ + toggles: { + type: Boolean, + reflectToAttribute: true + }, + + /** + * If true, the button is a toggle and is currently in the active state. + * + * @attribute active + * @type boolean + * @default false + */ + active: { + type: Boolean, + notify: true, + reflectToAttribute: true, + observer: '_activeChanged' + } + + }, + + listeners: { + mousedown: '_downHandler', + mouseup: '_upHandler', + keydown: '_keyDownHandler', + keyup: '_keyUpHandler', + tap: '_tapHandler' + }, + + _tapHandler: function() { + if (this.toggles) { + // a tap is needed to toggle the active state + this._userActivate(!this.active); + } else { + this.active = false; + } + }, + + // to emulate native checkbox, (de-)activations from a user interaction fire + // 'change' events + _userActivate: function(active) { + this.active = active; + this.fire('change'); + }, + + _downHandler: function() { + this._setPressed(true); + }, + + _upHandler: function(e) { + this._setPressed(false); + }, + + _keyDownHandler: function(e) { + switch(e.keyCode) { + case this.keyCodes.ENTER_KEY: + this._asyncClick(); + break; + + case this.keyCodes.SPACE: + this._setPressed(true); + break; + + } + }, + + _keyUpHandler: function(e) { + if (e.keyCode == this.keyCodes.SPACE) { + if (this.pressed) { + this._asyncClick(); + } + this._setPressed(false); + } + }, + + // trigger click asynchronously, the asynchrony is useful to allow one + // event handler to unwind before triggering another event + _asyncClick: function() { + this.async(function() { + this.click(); + }, 1); + }, + + // any of these changes are considered a change to button state + + _pressedChanged: function(pressed) { + this._changedButtonState(); + }, + + _activeChanged: function(active) { + this.setAttribute('aria-pressed', active ? 'true' : 'false'); + this._changedButtonState(); + }, + + _controlStateChanged: function() { + if (this.disabled) { + this._setPressed(false); + this.active = false; + } else { + this._changedButtonState(); + } + }, + + // provide hook for follow-on behaviors to react to button-state + + _changedButtonState: function() { + if (this._buttonStateChanged) { + this._buttonStateChanged(); // abstract + } + } + + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-button-state.html b/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-button-state.html new file mode 100644 index 0000000..7ec57a7 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-button-state.html
@@ -0,0 +1,11 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="iron-control-state.html"> + +</head><body><script src="iron-button-state-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-control-state-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-control-state-extracted.js new file mode 100644 index 0000000..6e09eea --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-control-state-extracted.js
@@ -0,0 +1,87 @@ + + + Polymer.IronControlState = { + + properties: { + + /** + * If true, the element currently has focus. + * + * @attribute focused + * @type boolean + * @default false + */ + focused: { + type: Boolean, + value: false, + notify: true, + readOnly: true, + reflectToAttribute: true + }, + + /** + * If true, the user cannot interact with this element. + * + * @attribute disabled + * @type boolean + * @default false + */ + disabled: { + type: Boolean, + value: false, + notify: true, + observer: '_disabledChanged', + reflectToAttribute: true + }, + + _oldTabIndex: { + type: String + } + }, + + observers: [ + '_changedControlState(focused, disabled)' + ], + + listeners: { + focus: '_focusHandler', + blur: '_blurHandler' + }, + + ready: function() { + // TODO(sjmiles): ensure read-only property is valued so the compound + // observer will fire + if (this.focused === undefined) { + this._setFocused(false); + } + }, + + _focusHandler: function() { + this._setFocused(true); + }, + + _blurHandler: function() { + this._setFocused(false); + }, + + _disabledChanged: function(disabled, old) { + this.setAttribute('aria-disabled', disabled ? 'true' : 'false'); + this.style.pointerEvents = disabled ? 'none' : ''; + if (disabled) { + this._oldTabIndex = this.tabIndex; + this.focused = false; + this.tabIndex = -1; + } else if (this._oldTabIndex !== undefined) { + this.tabIndex = this._oldTabIndex; + } + }, + + _changedControlState: function() { + // _controlStateChanged is abstract, follow-on behaviors may implement it + if (this._controlStateChanged) { + this._controlStateChanged(); + } + } + + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-control-state.html b/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-control-state.html new file mode 100644 index 0000000..63f2e044 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-behaviors/iron-control-state.html
@@ -0,0 +1,10 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> + +</head><body><script src="iron-control-state-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icon/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-icon/.bower.json new file mode 100644 index 0000000..fc84e07 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icon/.bower.json
@@ -0,0 +1,27 @@ +{ + "name": "iron-icon", + "private": true, + "dependencies": { + "iron-meta": "polymerelements/iron-meta#^0.8.0", + "polymer": "polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "iron-iconset": "polymerelements/iron-iconset#^0.8.0", + "core-icons": "polymerelements/iron-icons#^0.8.0", + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/PolymerElements/iron-icon", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "8528f25c3d08a9e84e1cf96aebb6b5459e5e7af0" + }, + "_source": "git://github.com/PolymerElements/iron-icon.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-icon" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icon/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-icon/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icon/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icon/README.md b/third_party/polymer/v0_8/components-chromium/iron-icon/README.md new file mode 100644 index 0000000..65d93fb --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icon/README.md
@@ -0,0 +1,4 @@ +core-icon +========= + +See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-icon) for more information.
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icon/bower.json b/third_party/polymer/v0_8/components-chromium/iron-icon/bower.json new file mode 100644 index 0000000..f3763f0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icon/bower.json
@@ -0,0 +1,16 @@ +{ + "name": "iron-icon", + "private": true, + "dependencies": { + "iron-meta": "polymerelements/iron-meta#^0.8.0", + "polymer": "polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "iron-iconset": "polymerelements/iron-iconset#^0.8.0", + "core-icons": "polymerelements/iron-icons#^0.8.0", + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icon/index.html b/third_party/polymer/v0_8/components-chromium/iron-icon/index.html new file mode 100644 index 0000000..7aaf647 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icon/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="iron-icon.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icon/iron-icon-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-icon/iron-icon-extracted.js new file mode 100644 index 0000000..0ed3463b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icon/iron-icon-extracted.js
@@ -0,0 +1,68 @@ + + + Polymer({ + + is: 'iron-icon', + + properties: { + + icon: { + type: String, + //value: '', + observer: '_iconChanged' + }, + + theme: { + type: String, + //value: '', + observer: '_updateIcon' + }, + + src: { + type: String, + //value: '', + observer: '_srcChanged' + } + + }, + + _DEFAULT_ICONSET: 'icons', + + _iconChanged: function(icon) { + var parts = (icon || '').split(':'); + this._iconName = parts.pop(); + this._iconsetName = parts.pop() || this._DEFAULT_ICONSET; + this._updateIcon(); + }, + + _srcChanged: function(src) { + this._updateIcon(); + }, + + _usesIconset: function() { + return this.icon || !this.src; + }, + + _updateIcon: function() { + if (this._usesIconset()) { + this._iconset = this.$.meta.byKey(this._iconsetName); + if (this._iconset) { + this._iconset.applyIcon(this, this._iconName, this.theme); + } else { + console.warn('iron-icon: could not find iconset `' + + this._iconsetName + '`, did you import the iconset?'); + } + } else { + //if (this._iconset) { + // this._iconset.removeIcon(this.root); + //} + if (!this._img) { + this._img = document.createElement('img'); + } + this._img.src = this.src; + Polymer.dom(this.root).appendChild(this._img); + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icon/iron-icon.html b/third_party/polymer/v0_8/components-chromium/iron-icon/iron-icon.html new file mode 100644 index 0000000..b135d7c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icon/iron-icon.html
@@ -0,0 +1,83 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- + +The `iron-icon` element displays an icon. By default an icon renders as a 24px square. + +Example using src: + + <iron-icon src="star.png"></iron-icon> + +Example setting size to 32px x 32px: + + <iron-icon class="big" src="big_star.png"></iron-icon> + + <style> + .big { + height: 32px; + width: 32px; + } + </style> + +The iron elements include several sets of icons. +To use the default set of icons, import `iron-icons.html` and use the `icon` attribute to specify an icon: + + <!-- import default iconset and iron-icon --> + <link rel="import" href="/components/iron-icons/iron-icons.html"> + + <iron-icon icon="menu"></iron-icon> + +To use a different built-in set of icons, import `iron-icons/<iconset>-icons.html`, and +specify the icon as `<iconset>:<icon>`. For example: + + <!-- import communication iconset and iron-icon --> + <link rel="import" href="/components/iron-icons/communication-icons.html"> + + <iron-icon icon="communication:email"></iron-icon> + +You can also create custom icon sets of bitmap or SVG icons. + +Example of using an icon named `cherry` from a custom iconset with the ID `fruit`: + + <iron-icon icon="fruit:cherry"></iron-icon> + +See [iron-iconset](#iron-iconset) and [iron-iconset-svg](#iron-iconset-svg) for more information about +how to create a custom iconset. + +See [iron-icons](http://www.polymer-project.org/components/iron-icons/demo.html) for the default set of icons. + +@group Polymer Core Elements +@element iron-icon +@homepage polymer.github.io +--><html><head><link rel="import" href="../iron-meta/iron-meta.html"> + +</head><body><dom-module id="iron-icon"> + + <style> + :host { + display: inline-flex; + position: relative; + + vertical-align: middle; + align-items: center; + justify-content: center; + + fill: currentcolor; + + width: 24px; + height: 24px; + } + </style> + + <template> + <iron-meta id="meta" type="iconset"></iron-meta> + </template> + +</dom-module> + +<script src="iron-icon-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-icons/.bower.json new file mode 100644 index 0000000..1dd6ed9 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/.bower.json
@@ -0,0 +1,28 @@ +{ + "name": "iron-icons", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-iconset-svg": "polymerelements/iron-iconset-svg#^0.8.0" + }, + "devDependencies": { + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0" + }, + "ignore": [ + "util", + "update-icons.sh" + ], + "homepage": "https://github.com/PolymerElements/iron-icons", + "version": "0.8.3", + "_release": "0.8.3", + "_resolution": { + "type": "version", + "tag": "v0.8.3", + "commit": "76e6bbe3414c39c0e8260855a13bd018bfc0ddcd" + }, + "_source": "git://github.com/PolymerElements/iron-icons.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-icons" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-icons/.gitignore new file mode 100644 index 0000000..e21a66b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/.gitignore
@@ -0,0 +1,2 @@ +util/node_modules +material-design-icons
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/README.md b/third_party/polymer/v0_8/components-chromium/iron-icons/README.md new file mode 100644 index 0000000..ed473f7 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/README.md
@@ -0,0 +1,8 @@ +iron-icons +========= + +See the [component page](http://polymer-project.org/docs/elements/iron-elements.html#iron-icons) for more information. + +## Building +Running `update-icons.sh` will checkout [material-design-icons](https://github.com/google/material-design-icons), reduce +the fileset to 24px svgs, and compile the iconsets.
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/av-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/av-icons.html new file mode 100644 index 0000000..1fda7a7d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/av-icons.html
@@ -0,0 +1,65 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="av" size="24"> +<svg><defs> +<g id="album"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14.5c-2.49 0-4.5-2.01-4.5-4.5S9.51 7.5 12 7.5s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-5.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z"/></g> +<g id="av-timer"><path d="M11 17c0 .55.45 1 1 1s1-.45 1-1-.45-1-1-1-1 .45-1 1zm0-14v4h2V5.08c3.39.49 6 3.39 6 6.92 0 3.87-3.13 7-7 7s-7-3.13-7-7c0-1.68.59-3.22 1.58-4.42L12 13l1.41-1.41-6.8-6.8v.02C4.42 6.45 3 9.05 3 12c0 4.97 4.02 9 9 9 4.97 0 9-4.03 9-9s-4.03-9-9-9h-1zm7 9c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zM6 12c0 .55.45 1 1 1s1-.45 1-1-.45-1-1-1-1 .45-1 1z"/></g> +<g id="closed-caption"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z"/></g> +<g id="equalizer"><path d="M10 20h4V4h-4v16zm-6 0h4v-8H4v8zM16 9v11h4V9h-4z"/></g> +<g id="explicit"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 6h-4v2h4v2h-4v2h4v2H9V7h6v2z"/></g> +<g id="fast-forward"><path d="M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"/></g> +<g id="fast-rewind"><path d="M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"/></g> +<g id="games"><path d="M15 7.5V2H9v5.5l3 3 3-3zM7.5 9H2v6h5.5l3-3-3-3zM9 16.5V22h6v-5.5l-3-3-3 3zM16.5 9l-3 3 3 3H22V9h-5.5z"/></g> +<g id="hearing"><path d="M17 20c-.29 0-.56-.06-.76-.15-.71-.37-1.21-.88-1.71-2.38-.51-1.56-1.47-2.29-2.39-3-.79-.61-1.61-1.24-2.32-2.53C9.29 10.98 9 9.93 9 9c0-2.8 2.2-5 5-5s5 2.2 5 5h2c0-3.93-3.07-7-7-7S7 5.07 7 9c0 1.26.38 2.65 1.07 3.9.91 1.65 1.98 2.48 2.85 3.15.81.62 1.39 1.07 1.71 2.05.6 1.82 1.37 2.84 2.73 3.55.51.23 1.07.35 1.64.35 2.21 0 4-1.79 4-4h-2c0 1.1-.9 2-2 2zM7.64 2.64L6.22 1.22C4.23 3.21 3 5.96 3 9s1.23 5.79 3.22 7.78l1.41-1.41C6.01 13.74 5 11.49 5 9s1.01-4.74 2.64-6.36zM11.5 9c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5-2.5 1.12-2.5 2.5z"/></g> +<g id="high-quality"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 11H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/></g> +<g id="loop"><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/></g> +<g id="mic"><path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></g> +<g id="mic-none"><path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1.2-9.1c0-.66.54-1.2 1.2-1.2.66 0 1.2.54 1.2 1.2l-.01 6.2c0 .66-.53 1.2-1.19 1.2-.66 0-1.2-.54-1.2-1.2V4.9zm6.5 6.1c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></g> +<g id="mic-off"><path d="M19 11h-1.7c0 .74-.16 1.43-.43 2.05l1.23 1.23c.56-.98.9-2.09.9-3.28zm-4.02.17c0-.06.02-.11.02-.17V5c0-1.66-1.34-3-3-3S9 3.34 9 5v.18l5.98 5.99zM4.27 3L3 4.27l6.01 6.01V11c0 1.66 1.33 3 2.99 3 .22 0 .44-.03.65-.08l1.66 1.66c-.71.33-1.5.52-2.31.52-2.76 0-5.3-2.1-5.3-5.1H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c.91-.13 1.77-.45 2.54-.9L19.73 21 21 19.73 4.27 3z"/></g> +<g id="movie"><path d="M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4h-4z"/></g> +<g id="my-library-add"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/></g> +<g id="my-library-books"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9H9V9h10v2zm-4 4H9v-2h6v2zm4-8H9V5h10v2z"/></g> +<g id="my-library-music"><path d="M20 2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 5h-3v5.5c0 1.38-1.12 2.5-2.5 2.5S10 13.88 10 12.5s1.12-2.5 2.5-2.5c.57 0 1.08.19 1.5.51V5h4v2zM4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6z"/></g> +<g id="new-releases"><path d="M23 12l-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12 3 8.6 1.54 6.71 4.72l-3.61.81.34 3.68L1 12l2.44 2.78-.34 3.69 3.61.82 1.89 3.18L12 21l3.4 1.46 1.89-3.18 3.61-.82-.34-3.68L23 12zm-10 5h-2v-2h2v2zm0-4h-2V7h2v6z"/></g> +<g id="not-interested"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z"/></g> +<g id="pause"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></g> +<g id="pause-circle-fill"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 14H9V8h2v8zm4 0h-2V8h2v8z"/></g> +<g id="pause-circle-outline"><path d="M9 16h2V8H9v8zm3-14C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm1-4h2V8h-2v8z"/></g> +<g id="play-arrow"><path d="M8 5v14l11-7z"/></g> +<g id="play-circle-fill"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z"/></g> +<g id="play-circle-outline"><path d="M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="play-shopping-bag"><path d="M16 6V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H2v13c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6h-6zm-6-2h4v2h-4V4zM9 18V9l7.5 4L9 18z"/></g> +<g id="playlist-add"><path d="M14 10H2v2h12v-2zm0-4H2v2h12V6zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2 16h8v-2H2v2z"/></g> +<g id="queue"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/></g> +<g id="queue-music"><path d="M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z"/></g> +<g id="radio"><path d="M3.24 6.15C2.51 6.43 2 7.17 2 8v12c0 1.1.89 2 2 2h16c1.11 0 2-.9 2-2V8c0-1.11-.89-2-2-2H8.3l8.26-3.34L15.88 1 3.24 6.15zM7 20c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm13-8h-2v-2h-2v2H4V8h16v4z"/></g> +<g id="recent-actors"><path d="M21 5v14h2V5h-2zm-4 14h2V5h-2v14zM14 5H2c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zM8 7.75c1.24 0 2.25 1.01 2.25 2.25S9.24 12.25 8 12.25 5.75 11.24 5.75 10 6.76 7.75 8 7.75zM12.5 17h-9v-.75c0-1.5 3-2.25 4.5-2.25s4.5.75 4.5 2.25V17z"/></g> +<g id="repeat"><path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z"/></g> +<g id="repeat-one"><path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4zm-4-2V9h-1l-2 1v1h1.5v4H13z"/></g> +<g id="replay"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></g> +<g id="shuffle"><path d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z"/></g> +<g id="skip-next"><path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"/></g> +<g id="skip-previous"><path d="M6 6h2v12H6zm3.5 6l8.5 6V6z"/></g> +<g id="snooze"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm-3-9h3.63L9 15.2V17h6v-2h-3.63L15 10.8V9H9v2z"/></g> +<g id="stop"><path d="M6 6h12v12H6z"/></g> +<g id="subtitles"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM4 12h4v2H4v-2zm10 6H4v-2h10v2zm6 0h-4v-2h4v2zm0-4H10v-2h10v2z"/></g> +<g id="surround-sound"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM7.76 16.24l-1.41 1.41C4.78 16.1 4 14.05 4 12c0-2.05.78-4.1 2.34-5.66l1.41 1.41C6.59 8.93 6 10.46 6 12s.59 3.07 1.76 4.24zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm5.66 1.66l-1.41-1.41C17.41 15.07 18 13.54 18 12s-.59-3.07-1.76-4.24l1.41-1.41C19.22 7.9 20 9.95 20 12c0 2.05-.78 4.1-2.34 5.66zM12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="video-collection"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-8 12.5v-9l6 4.5-6 4.5z"/></g> +<g id="videocam"><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"/></g> +<g id="videocam-off"><path d="M21 6.5l-4 4V7c0-.55-.45-1-1-1H9.82L21 17.18V6.5zM3.27 2L2 3.27 4.73 6H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.21 0 .39-.08.54-.18L19.73 21 21 19.73 3.27 2z"/></g> +<g id="volume-down"><path d="M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z"/></g> +<g id="volume-mute"><path d="M7 9v6h4l5 5V4l-5 5H7z"/></g> +<g id="volume-off"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/></g> +<g id="volume-up"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/></g> +<g id="web"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/bower.json b/third_party/polymer/v0_8/components-chromium/iron-icons/bower.json new file mode 100644 index 0000000..636b56bb --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/bower.json
@@ -0,0 +1,17 @@ +{ + "name": "iron-icons", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-iconset-svg": "polymerelements/iron-iconset-svg#^0.8.0" + }, + "devDependencies": { + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0" + }, + "ignore": [ + "util", + "update-icons.sh" + ] +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/communication-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/communication-icons.html new file mode 100644 index 0000000..29ce611 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/communication-icons.html
@@ -0,0 +1,54 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="communication" size="24"> +<svg><defs> +<g id="business"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"/></g> +<g id="call"><path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></g> +<g id="call-end"><path d="M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08c-.18-.17-.29-.42-.29-.7 0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28-.79-.74-1.69-1.36-2.67-1.85-.33-.16-.56-.5-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z"/></g> +<g id="call-made"><path d="M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5z"/></g> +<g id="call-merge"><path d="M17 20.41L18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z"/></g> +<g id="call-missed"><path d="M19.59 7L12 14.59 6.41 9H11V7H3v8h2v-4.59l7 7 9-9z"/></g> +<g id="call-received"><path d="M20 5.41L18.59 4 7 15.59V9H5v10h10v-2H8.41z"/></g> +<g id="call-split"><path d="M14 4l2.29 2.29-2.88 2.88 1.42 1.42 2.88-2.88L20 10V4zm-4 0H4v6l2.29-2.29 4.71 4.7V20h2v-8.41l-5.29-5.3z"/></g> +<g id="chat"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 9h12v2H6V9zm8 5H6v-2h8v2zm4-6H6V6h12v2z"/></g> +<g id="clear-all"><path d="M5 13h14v-2H5v2zm-2 4h14v-2H3v2zM7 7v2h14V7H7z"/></g> +<g id="comment"><path d="M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4-.01-18zM18 14H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/></g> +<g id="contacts"><path d="M20 0H4v2h16V0zM4 24h16v-2H4v2zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 2.75c1.24 0 2.25 1.01 2.25 2.25s-1.01 2.25-2.25 2.25S9.75 10.24 9.75 9 10.76 6.75 12 6.75zM17 17H7v-1.5c0-1.67 3.33-2.5 5-2.5s5 .83 5 2.5V17z"/></g> +<g id="dialer-sip"><path d="M17 3h-1v5h1V3zm-2 2h-2V4h2V3h-3v3h2v1h-2v1h3V5zm3-2v5h1V6h2V3h-3zm2 2h-1V4h1v1zm0 10.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.01.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.27-.26.35-.65.24-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></g> +<g id="dialpad"><path d="M12 19c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zM6 1c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12-8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-6 8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="dnd-on"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z"/></g> +<g id="email"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></g> +<g id="forum"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"/></g> +<g id="import-export"><path d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/></g> +<g id="invert-colors-off"><path d="M20.65 20.87l-2.35-2.35-6.3-6.29-3.56-3.57-1.42-1.41L4.27 4.5 3 5.77l2.78 2.78c-2.55 3.14-2.36 7.76.56 10.69C7.9 20.8 9.95 21.58 12 21.58c1.79 0 3.57-.59 5.03-1.78l2.7 2.7L21 21.23l-.35-.36zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59c0-1.32.43-2.57 1.21-3.6L12 14.77v4.82zM12 5.1v4.58l7.25 7.26c1.37-2.96.84-6.57-1.6-9.01L12 2.27l-3.7 3.7 1.41 1.41L12 5.1z"/></g> +<g id="invert-colors-on"><path d="M17.66 7.93L12 2.27 6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58c2.05 0 4.1-.78 5.66-2.34 3.12-3.12 3.12-8.19 0-11.31zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"/></g> +<g id="live-help"><path d="M19 2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h4l3 3 3-3h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-6 16h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 11.9 13 12.5 13 14h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"/></g> +<g id="location-off"><path d="M12 6.5c1.38 0 2.5 1.12 2.5 2.5 0 .74-.33 1.39-.83 1.85l3.63 3.63c.98-1.86 1.7-3.8 1.7-5.48 0-3.87-3.13-7-7-7-1.98 0-3.76.83-5.04 2.15l3.19 3.19c.46-.52 1.11-.84 1.85-.84zm4.37 9.6l-4.63-4.63-.11-.11L3.27 3 2 4.27l3.18 3.18C5.07 7.95 5 8.47 5 9c0 5.25 7 13 7 13s1.67-1.85 3.38-4.35L18.73 21 20 19.73l-3.63-3.63z"/></g> +<g id="location-on"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></g> +<g id="message"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/></g> +<g id="messenger"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></g> +<g id="no-sim"><path d="M18.99 5c0-1.1-.89-2-1.99-2h-7L7.66 5.34 19 16.68 18.99 5zM3.65 3.88L2.38 5.15 5 7.77V19c0 1.1.9 2 2 2h10.01c.35 0 .67-.1.96-.26l1.88 1.88 1.27-1.27L3.65 3.88z"/></g> +<g id="phone"><path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></g> +<g id="portable-wifi-off"><path d="M17.56 14.24c.28-.69.44-1.45.44-2.24 0-3.31-2.69-6-6-6-.79 0-1.55.16-2.24.44l1.62 1.62c.2-.03.41-.06.62-.06 2.21 0 4 1.79 4 4 0 .21-.02.42-.05.63l1.61 1.61zM12 4c4.42 0 8 3.58 8 8 0 1.35-.35 2.62-.95 3.74l1.47 1.47C21.46 15.69 22 13.91 22 12c0-5.52-4.48-10-10-10-1.91 0-3.69.55-5.21 1.47l1.46 1.46C9.37 4.34 10.65 4 12 4zM3.27 2.5L2 3.77l2.1 2.1C2.79 7.57 2 9.69 2 12c0 3.7 2.01 6.92 4.99 8.65l1-1.73C5.61 17.53 4 14.96 4 12c0-1.76.57-3.38 1.53-4.69l1.43 1.44C6.36 9.68 6 10.8 6 12c0 2.22 1.21 4.15 3 5.19l1-1.74c-1.19-.7-2-1.97-2-3.45 0-.65.17-1.25.44-1.79l1.58 1.58L10 12c0 1.1.9 2 2 2l.21-.02.01.01 7.51 7.51L21 20.23 4.27 3.5l-1-1z"/></g> +<g id="quick-contacts-dialer"><path d="M22 3H2C.9 3 0 3.9 0 5v14c0 1.1.9 2 2 2h20c1.1 0 1.99-.9 1.99-2L24 5c0-1.1-.9-2-2-2zM8 6c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H2v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1zm3.85-4h1.64L21 16l-1.99 1.99c-1.31-.98-2.28-2.38-2.73-3.99-.18-.64-.28-1.31-.28-2s.1-1.36.28-2c.45-1.62 1.42-3.01 2.73-3.99L21 8l-1.51 2h-1.64c-.22.63-.35 1.3-.35 2s.13 1.37.35 2z"/></g> +<g id="quick-contacts-mail"><path d="M21 8V7l-3 2-3-2v1l3 2 3-2zm1-5H2C.9 3 0 3.9 0 5v14c0 1.1.9 2 2 2h20c1.1 0 1.99-.9 1.99-2L24 5c0-1.1-.9-2-2-2zM8 6c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H2v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1zm8-6h-8V6h8v6z"/></g> +<g id="ring-volume"><path d="M23.71 16.67C20.66 13.78 16.54 12 12 12 7.46 12 3.34 13.78.29 16.67c-.18.18-.29.43-.29.71 0 .28.11.53.29.71l2.48 2.48c.18.18.43.29.71.29.27 0 .52-.11.7-.28.79-.74 1.69-1.36 2.66-1.85.33-.16.56-.5.56-.9v-3.1c1.45-.48 3-.73 4.6-.73s3.15.25 4.6.72v3.1c0 .39.23.74.56.9.98.49 1.87 1.12 2.66 1.85.18.18.43.28.7.28.28 0 .53-.11.71-.29l2.48-2.48c.18-.18.29-.43.29-.71 0-.27-.11-.52-.29-.7zM21.16 6.26l-1.41-1.41-3.56 3.55 1.41 1.41s3.45-3.52 3.56-3.55zM13 2h-2v5h2V2zM6.4 9.81L7.81 8.4 4.26 4.84 2.84 6.26c.11.03 3.56 3.55 3.56 3.55z"/></g> +<g id="stay-current-landscape"><path d="M1.01 7L1 17c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2H3c-1.1 0-1.99.9-1.99 2zM19 7v10H5V7h14z"/></g> +<g id="stay-current-portrait"><path d="M17 1.01L7 1c-1.1 0-1.99.9-1.99 2v18c0 1.1.89 2 1.99 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></g> +<g id="stay-primary-landscape"><path d="M1.01 7L1 17c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2H3c-1.1 0-1.99.9-1.99 2zM19 7v10H5V7h14z"/></g> +<g id="stay-primary-portrait"><path d="M17 1.01L7 1c-1.1 0-1.99.9-1.99 2v18c0 1.1.89 2 1.99 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></g> +<g id="swap-calls"><path d="M18 4l-4 4h3v7c0 1.1-.9 2-2 2s-2-.9-2-2V8c0-2.21-1.79-4-4-4S5 5.79 5 8v7H2l4 4 4-4H7V8c0-1.1.9-2 2-2s2 .9 2 2v7c0 2.21 1.79 4 4 4s4-1.79 4-4V8h3l-4-4z"/></g> +<g id="textsms"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9 11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z"/></g> +<g id="voicemail"><path d="M18.5 6C15.46 6 13 8.46 13 11.5c0 1.33.47 2.55 1.26 3.5H9.74c.79-.95 1.26-2.17 1.26-3.5C11 8.46 8.54 6 5.5 6S0 8.46 0 11.5 2.46 17 5.5 17h13c3.04 0 5.5-2.46 5.5-5.5S21.54 6 18.5 6zm-13 9C3.57 15 2 13.43 2 11.5S3.57 8 5.5 8 9 9.57 9 11.5 7.43 15 5.5 15zm13 0c-1.93 0-3.5-1.57-3.5-3.5S16.57 8 18.5 8 22 9.57 22 11.5 20.43 15 18.5 15z"/></g> +<g id="vpn-key"><path d="M12.65 10C11.83 7.67 9.61 6 7 6c-3.31 0-6 2.69-6 6s2.69 6 6 6c2.61 0 4.83-1.67 5.65-4H17v4h4v-4h2v-4H12.65zM7 14c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/device-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/device-icons.html new file mode 100644 index 0000000..8e6d9ca5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/device-icons.html
@@ -0,0 +1,90 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="device" size="24"> +<svg><defs> +<g id="access-alarm"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="access-alarms"><path d="M22 5.7l-4.6-3.9-1.3 1.5 4.6 3.9L22 5.7zM7.9 3.4L6.6 1.9 2 5.7l1.3 1.5 4.6-3.8zM12.5 8H11v6l4.7 2.9.8-1.2-4-2.4V8zM12 4c-5 0-9 4-9 9s4 9 9 9 9-4 9-9-4-9-9-9zm0 16c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z"/></g> +<g id="access-time"><path fill-opacity=".9" d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zM12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></g> +<g id="add-alarm"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm1-11h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g> +<g id="airplanemode-off"><path d="M13 9V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v3.68l7.83 7.83L21 16v-2l-8-5zM3 5.27l4.99 4.99L2 14v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-3.73L18.73 21 20 19.73 4.27 4 3 5.27z"/></g> +<g id="airplanemode-on"><path d="M10.18 9"/><path d="M21 16v-2l-8-5V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5l8 2.5z"/></g> +<g id="battery-20"><path d="M7 17v3.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V17H7z"/><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V17h10V5.33z"/></g> +<g id="battery-30"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V15h10V5.33z"/><path d="M7 15v5.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V15H7z"/></g> +<g id="battery-50"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V13h10V5.33z"/><path d="M7 13v7.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V13H7z"/></g> +<g id="battery-60"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V11h10V5.33z"/><path d="M7 11v9.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V11H7z"/></g> +<g id="battery-80"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V9h10V5.33z"/><path d="M7 9v11.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V9H7z"/></g> +<g id="battery-90"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h10V5.33z"/><path d="M7 8v12.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V8H7z"/></g> +<g id="battery-alert"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM13 18h-2v-2h2v2zm0-4h-2V9h2v5z"/></g> +<g id="battery-charging-20"><path d="M11 20v-3H7v3.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V17h-4.4L11 20z"/><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V17h4v-2.5H9L13 7v5.5h2L12.6 17H17V5.33C17 4.6 16.4 4 15.67 4z"/></g> +<g id="battery-charging-30"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v9.17h2L13 7v5.5h2l-1.07 2H17V5.33C17 4.6 16.4 4 15.67 4z"/><path d="M11 20v-5.5H7v6.17C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V14.5h-3.07L11 20z"/></g> +<g id="battery-charging-50"><path d="M14.47 13.5L11 20v-5.5H9l.53-1H7v7.17C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V13.5h-2.53z"/><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v8.17h2.53L13 7v5.5h2l-.53 1H17V5.33C17 4.6 16.4 4 15.67 4z"/></g> +<g id="battery-charging-60"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V11h3.87L13 7v4h4V5.33C17 4.6 16.4 4 15.67 4z"/><path d="M13 12.5h2L11 20v-5.5H9l1.87-3.5H7v9.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V11h-4v1.5z"/></g> +<g id="battery-charging-80"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V9h4.93L13 7v2h4V5.33C17 4.6 16.4 4 15.67 4z"/><path d="M13 12.5h2L11 20v-5.5H9L11.93 9H7v11.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V9h-4v3.5z"/></g> +<g id="battery-charging-90"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h5.47L13 7v1h4V5.33C17 4.6 16.4 4 15.67 4z"/><path d="M13 12.5h2L11 20v-5.5H9L12.47 8H7v12.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V8h-4v4.5z"/></g> +<g id="battery-charging-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM11 20v-5.5H9L13 7v5.5h2L11 20z"/></g> +<g id="battery-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4z"/></g> +<g id="battery-std"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4z"/></g> +<g id="battery-unknown"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zm-2.72 13.95h-1.9v-1.9h1.9v1.9zm1.35-5.26s-.38.42-.67.71c-.48.48-.83 1.15-.83 1.6h-1.6c0-.83.46-1.52.93-2l.93-.94c.27-.27.44-.65.44-1.06 0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5H9c0-1.66 1.34-3 3-3s3 1.34 3 3c0 .66-.27 1.26-.7 1.69z"/></g> +<g id="bluetooth"><path d="M17.71 7.71L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88z"/></g> +<g id="bluetooth-connected"><path d="M7 12l-2-2-2 2 2 2 2-2zm10.71-4.29L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88zM19 10l-2 2 2 2 2-2-2-2z"/></g> +<g id="bluetooth-disabled"><path d="M13 5.83l1.88 1.88-1.6 1.6 1.41 1.41 3.02-3.02L12 2h-1v5.03l2 2v-3.2zM5.41 4L4 5.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l4.29-4.29 2.3 2.29L20 18.59 5.41 4zM13 18.17v-3.76l1.88 1.88L13 18.17z"/></g> +<g id="bluetooth-searching"><path d="M14.24 12.01l2.32 2.32c.28-.72.44-1.51.44-2.33 0-.82-.16-1.59-.43-2.31l-2.33 2.32zm5.29-5.3l-1.26 1.26c.63 1.21.98 2.57.98 4.02s-.36 2.82-.98 4.02l1.2 1.2c.97-1.54 1.54-3.36 1.54-5.31-.01-1.89-.55-3.67-1.48-5.19zm-3.82 1L10 2H9v7.59L4.41 5 3 6.41 8.59 12 3 17.59 4.41 19 9 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM11 5.83l1.88 1.88L11 9.59V5.83zm1.88 10.46L11 18.17v-3.76l1.88 1.88z"/></g> +<g id="brightness-auto"><path d="M10.85 12.65h2.3L12 9l-1.15 3.65zM20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM14.3 16l-.7-2h-3.2l-.7 2H7.8L11 7h2l3.2 9h-1.9z"/></g> +<g id="brightness-high"><path d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm0-10c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"/></g> +<g id="brightness-low"><path d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6z"/></g> +<g id="brightness-medium"><path d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18V6c3.31 0 6 2.69 6 6s-2.69 6-6 6z"/></g> +<g id="data-usage"><path d="M13 2.05v3.03c3.39.49 6 3.39 6 6.92 0 .9-.18 1.75-.48 2.54l2.6 1.53c.56-1.24.88-2.62.88-4.07 0-5.18-3.95-9.45-9-9.95zM12 19c-3.87 0-7-3.13-7-7 0-3.53 2.61-6.43 6-6.92V2.05c-5.06.5-9 4.76-9 9.95 0 5.52 4.47 10 9.99 10 3.31 0 6.24-1.61 8.06-4.09l-2.6-1.53C16.17 17.98 14.21 19 12 19z"/></g> +<g id="developer-mode"><path d="M7 5h10v2h2V3c0-1.1-.9-1.99-2-1.99L7 1c-1.1 0-2 .9-2 2v4h2V5zm8.41 11.59L20 12l-4.59-4.59L14 8.83 17.17 12 14 15.17l1.41 1.42zM10 15.17L6.83 12 10 8.83 8.59 7.41 4 12l4.59 4.59L10 15.17zM17 19H7v-2H5v4c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2v-4h-2v2z"/></g> +<g id="devices"><path d="M4 6h18V4H4c-1.1 0-2 .9-2 2v11H0v3h14v-3H4V6zm19 2h-6c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zm-1 9h-4v-7h4v7z"/></g> +<g id="dvr"><path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12zm-2-9H8v2h11V8zm0 4H8v2h11v-2zM7 8H5v2h2V8zm0 4H5v2h2v-2z"/></g> +<g id="gps-fixed"><path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="gps-not-fixed"><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="gps-off"><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06c-1.13.12-2.19.46-3.16.97l1.5 1.5C10.16 5.19 11.06 5 12 5c3.87 0 7 3.13 7 7 0 .94-.19 1.84-.52 2.65l1.5 1.5c.5-.96.84-2.02.97-3.15H23v-2h-2.06zM3 4.27l2.04 2.04C3.97 7.62 3.25 9.23 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c1.77-.2 3.38-.91 4.69-1.98L19.73 21 21 19.73 4.27 3 3 4.27zm13.27 13.27C15.09 18.45 13.61 19 12 19c-3.87 0-7-3.13-7-7 0-1.61.55-3.09 1.46-4.27l9.81 9.81z"/></g> +<g id="location-disabled"><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06c-1.13.12-2.19.46-3.16.97l1.5 1.5C10.16 5.19 11.06 5 12 5c3.87 0 7 3.13 7 7 0 .94-.19 1.84-.52 2.65l1.5 1.5c.5-.96.84-2.02.97-3.15H23v-2h-2.06zM3 4.27l2.04 2.04C3.97 7.62 3.25 9.23 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c1.77-.2 3.38-.91 4.69-1.98L19.73 21 21 19.73 4.27 3 3 4.27zm13.27 13.27C15.09 18.45 13.61 19 12 19c-3.87 0-7-3.13-7-7 0-1.61.55-3.09 1.46-4.27l9.81 9.81z"/></g> +<g id="location-searching"><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="multitrack-audio"><path d="M7 18h2V6H7v12zm4 4h2V2h-2v20zm-8-8h2v-4H3v4zm12 4h2V6h-2v12zm4-8v4h2v-4h-2z"/></g> +<g id="network-cell"><path fill-opacity=".3" d="M2 22h20V2z"/><path d="M17 7L2 22h15z"/></g> +<g id="network-wifi"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/><path d="M3.53 10.95l8.46 10.54.01.01.01-.01 8.46-10.54C20.04 10.62 16.81 8 12 8c-4.81 0-8.04 2.62-8.47 2.95z"/></g> +<g id="nfc"><path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 18H4V4h16v16zM18 6h-5c-1.1 0-2 .9-2 2v2.28c-.6.35-1 .98-1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V8h3v8H8V8h2V6H6v12h12V6z"/></g> +<g id="now-wallpaper"><path d="M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2V4zm6 9l-4 5h12l-3-4-2.03 2.71L10 13zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5zM20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2zm0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z"/></g> +<g id="now-widgets"><path d="M13 13v8h8v-8h-8zM3 21h8v-8H3v8zM3 3v8h8V3H3zm13.66-1.31L11 7.34 16.66 13l5.66-5.66-5.66-5.65z"/></g> +<g id="screen-lock-landscape"><path d="M21 5H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-2 12H5V7h14v10zm-9-1h4c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1v-1c0-1.11-.9-2-2-2-1.11 0-2 .9-2 2v1c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1zm.8-6c0-.66.54-1.2 1.2-1.2.66 0 1.2.54 1.2 1.2v1h-2.4v-1z"/></g> +<g id="screen-lock-portrait"><path d="M10 16h4c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1v-1c0-1.11-.9-2-2-2-1.11 0-2 .9-2 2v1c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1zm.8-6c0-.66.54-1.2 1.2-1.2.66 0 1.2.54 1.2 1.2v1h-2.4v-1zM17 1H7c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 18H7V5h10v14z"/></g> +<g id="screen-lock-rotation"><path d="M23.25 12.77l-2.57-2.57-1.41 1.41 2.22 2.22-5.66 5.66L4.51 8.17l5.66-5.66 2.1 2.1 1.41-1.41L11.23.75c-.59-.59-1.54-.59-2.12 0L2.75 7.11c-.59.59-.59 1.54 0 2.12l12.02 12.02c.59.59 1.54.59 2.12 0l6.36-6.36c.59-.59.59-1.54 0-2.12zM8.47 20.48C5.2 18.94 2.86 15.76 2.5 12H1c.51 6.16 5.66 11 11.95 11l.66-.03-3.81-3.82-1.33 1.33zM16 9h5c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1v-.5C21 1.12 19.88 0 18.5 0S16 1.12 16 2.5V3c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1zm.8-6.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V3h-3.4v-.5z"/></g> +<g id="screen-rotation"><path d="M16.48 2.52c3.27 1.55 5.61 4.72 5.97 8.48h1.5C23.44 4.84 18.29 0 12 0l-.66.03 3.81 3.81 1.33-1.32zm-6.25-.77c-.59-.59-1.54-.59-2.12 0L1.75 8.11c-.59.59-.59 1.54 0 2.12l12.02 12.02c.59.59 1.54.59 2.12 0l6.36-6.36c.59-.59.59-1.54 0-2.12L10.23 1.75zm4.6 19.44L2.81 9.17l6.36-6.36 12.02 12.02-6.36 6.36zm-7.31.29C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-3.81-3.81-1.33 1.32z"/></g> +<g id="sd-storage"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-6 6h-2V4h2v4zm3 0h-2V4h2v4zm3 0h-2V4h2v4z"/></g> +<g id="settings-system-daydream"><path d="M9 16h6.5c1.38 0 2.5-1.12 2.5-2.5S16.88 11 15.5 11h-.05c-.24-1.69-1.69-3-3.45-3-1.4 0-2.6.83-3.16 2.02h-.16C7.17 10.18 6 11.45 6 13c0 1.66 1.34 3 3 3zM21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"/></g> +<g id="signal-cellular-0-bar"><path fill-opacity=".3" d="M2 22h20V2z"/></g> +<g id="signal-cellular-1-bar"><path fill-opacity=".3" d="M2 22h20V2z"/><path d="M12 12L2 22h10z"/></g> +<g id="signal-cellular-2-bar"><path fill-opacity=".3" d="M2 22h20V2z"/><path d="M14 10L2 22h12z"/></g> +<g id="signal-cellular-3-bar"><path fill-opacity=".3" d="M2 22h20V2z"/><path d="M17 7L2 22h15z"/></g> +<g id="signal-cellular-4-bar"><path d="M2 22h20V2z"/></g> +<g id="signal-cellular-connected-no-internet-0-bar"><path fill-opacity=".3" d="M22 8V2L2 22h16V8z"/><path d="M20 22h2v-2h-2v2zm0-12v8h2v-8h-2z"/></g> +<g id="signal-cellular-connected-no-internet-1-bar"><path fill-opacity=".3" d="M22 8V2L2 22h16V8z"/><path d="M20 10v8h2v-8h-2zm-8 12V12L2 22h10zm8 0h2v-2h-2v2z"/></g> +<g id="signal-cellular-connected-no-internet-2-bar"><path fill-opacity=".3" d="M22 8V2L2 22h16V8z"/><path d="M14 22V10L2 22h12zm6-12v8h2v-8h-2zm0 12h2v-2h-2v2z"/></g> +<g id="signal-cellular-connected-no-internet-3-bar"><path fill-opacity=".3" d="M22 8V2L2 22h16V8z"/><path d="M17 22V7L2 22h15zm3-12v8h2v-8h-2zm0 12h2v-2h-2v2z"/></g> +<g id="signal-cellular-connected-no-internet-4-bar"><path d="M20 18h2v-8h-2v8zm0 4h2v-2h-2v2zM2 22h16V8h4V2L2 22z"/></g> +<g id="signal-cellular-no-sim"><path d="M18.99 5c0-1.1-.89-2-1.99-2h-7L7.66 5.34 19 16.68 18.99 5zM3.65 3.88L2.38 5.15 5 7.77V19c0 1.1.9 2 2 2h10.01c.35 0 .67-.1.96-.26l1.88 1.88 1.27-1.27L3.65 3.88z"/></g> +<g id="signal-cellular-null"><path d="M20 6.83V20H6.83L20 6.83M22 2L2 22h20V2z"/></g> +<g id="signal-cellular-off"><path d="M21 1l-8.59 8.59L21 18.18V1zM4.77 4.5L3.5 5.77l6.36 6.36L1 21h17.73l2 2L22 21.73 4.77 4.5z"/></g> +<g id="signal-wifi-0-bar"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/></g> +<g id="signal-wifi-1-bar"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/><path d="M6.67 14.86L12 21.49v.01l.01-.01 5.33-6.63C17.06 14.65 15.03 13 12 13s-5.06 1.65-5.33 1.86z"/></g> +<g id="signal-wifi-2-bar"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/><path d="M4.79 12.52l7.2 8.98H12l.01-.01 7.2-8.98C18.85 12.24 16.1 10 12 10s-6.85 2.24-7.21 2.52z"/></g> +<g id="signal-wifi-3-bar"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/><path d="M3.53 10.95l8.46 10.54.01.01.01-.01 8.46-10.54C20.04 10.62 16.81 8 12 8c-4.81 0-8.04 2.62-8.47 2.95z"/></g> +<g id="signal-wifi-4-bar"><path d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/></g> +<g id="signal-wifi-off"><path d="M23.64 7c-.45-.34-4.93-4-11.64-4-1.5 0-2.89.19-4.15.48L18.18 13.8 23.64 7zm-6.6 8.22L3.27 1.44 2 2.72l2.05 2.06C1.91 5.76.59 6.82.36 7l11.63 14.49.01.01.01-.01 3.9-4.86 3.32 3.32 1.27-1.27-3.46-3.46z"/></g> +<g id="storage"><path d="M2 20h20v-4H2v4zm2-3h2v2H4v-2zM2 4v4h20V4H2zm4 3H4V5h2v2zm-4 7h20v-4H2v4zm2-3h2v2H4v-2z"/></g> +<g id="usb"><path d="M15 7v4h1v2h-3V5h2l-3-4-3 4h2v8H8v-2.07c.7-.37 1.2-1.08 1.2-1.93 0-1.21-.99-2.2-2.2-2.2-1.21 0-2.2.99-2.2 2.2 0 .85.5 1.56 1.2 1.93V13c0 1.11.89 2 2 2h3v3.05c-.71.37-1.2 1.1-1.2 1.95 0 1.22.99 2.2 2.2 2.2 1.21 0 2.2-.98 2.2-2.2 0-.85-.49-1.58-1.2-1.95V15h3c1.11 0 2-.89 2-2v-2h1V7h-4z"/></g> +<g id="wifi-lock"><path d="M20.5 9.5c.28 0 .55.04.81.08L24 6c-3.34-2.51-7.5-4-12-4S3.34 3.49 0 6l12 16 3.5-4.67V14.5c0-2.76 2.24-5 5-5zM23 16v-1.5c0-1.38-1.12-2.5-2.5-2.5S18 13.12 18 14.5V16c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1v-4c0-.55-.45-1-1-1zm-1 0h-3v-1.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V16z"/></g> +<g id="wifi-tethering"><path d="M12 11c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 2c0-3.31-2.69-6-6-6s-6 2.69-6 6c0 2.22 1.21 4.15 3 5.19l1-1.74c-1.19-.7-2-1.97-2-3.45 0-2.21 1.79-4 4-4s4 1.79 4 4c0 1.48-.81 2.75-2 3.45l1 1.74c1.79-1.04 3-2.97 3-5.19zM12 3C6.48 3 2 7.48 2 13c0 3.7 2.01 6.92 4.99 8.65l1-1.73C5.61 18.53 4 15.96 4 13c0-4.42 3.58-8 8-8s8 3.58 8 8c0 2.96-1.61 5.53-4 6.92l1 1.73c2.99-1.73 5-4.95 5-8.65 0-5.52-4.48-10-10-10z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/editor-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/editor-icons.html new file mode 100644 index 0000000..a5170ea --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/editor-icons.html
@@ -0,0 +1,67 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="editor" size="24"> +<svg><defs> +<g id="attach-file"><path d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z"/></g> +<g id="attach-money"><path d="M11.8 10.9c-2.27-.59-3-1.2-3-2.15 0-1.09 1.01-1.85 2.7-1.85 1.78 0 2.44.85 2.5 2.1h2.21c-.07-1.72-1.12-3.3-3.21-3.81V3h-3v2.16c-1.94.42-3.5 1.68-3.5 3.61 0 2.31 1.91 3.46 4.7 4.13 2.5.6 3 1.48 3 2.41 0 .69-.49 1.79-2.7 1.79-2.06 0-2.87-.92-2.98-2.1h-2.2c.12 2.19 1.76 3.42 3.68 3.83V21h3v-2.15c1.95-.37 3.5-1.5 3.5-3.55 0-2.84-2.43-3.81-4.7-4.4z"/></g> +<g id="border-all"><path d="M3 3v18h18V3H3zm8 16H5v-6h6v6zm0-8H5V5h6v6zm8 8h-6v-6h6v6zm0-8h-6V5h6v6z"/></g> +<g id="border-bottom"><path d="M9 11H7v2h2v-2zm4 4h-2v2h2v-2zM9 3H7v2h2V3zm4 8h-2v2h2v-2zM5 3H3v2h2V3zm8 4h-2v2h2V7zm4 4h-2v2h2v-2zm-4-8h-2v2h2V3zm4 0h-2v2h2V3zm2 10h2v-2h-2v2zm0 4h2v-2h-2v2zM5 7H3v2h2V7zm14-4v2h2V3h-2zm0 6h2V7h-2v2zM5 11H3v2h2v-2zM3 21h18v-2H3v2zm2-6H3v2h2v-2z"/></g> +<g id="border-clear"><path d="M7 5h2V3H7v2zm0 8h2v-2H7v2zm0 8h2v-2H7v2zm4-4h2v-2h-2v2zm0 4h2v-2h-2v2zm-8 0h2v-2H3v2zm0-4h2v-2H3v2zm0-4h2v-2H3v2zm0-4h2V7H3v2zm0-4h2V3H3v2zm8 8h2v-2h-2v2zm8 4h2v-2h-2v2zm0-4h2v-2h-2v2zm0 8h2v-2h-2v2zm0-12h2V7h-2v2zm-8 0h2V7h-2v2zm8-6v2h2V3h-2zm-8 2h2V3h-2v2zm4 16h2v-2h-2v2zm0-8h2v-2h-2v2zm0-8h2V3h-2v2z"/></g> +<g id="border-color"><path d="M17.75 7L14 3.25l-10 10V17h3.75l10-10zm2.96-2.96c.39-.39.39-1.02 0-1.41L18.37.29c-.39-.39-1.02-.39-1.41 0L15 2.25 18.75 6l1.96-1.96z"/><path fill-opacity=".36" d="M0 20h24v4H0z"/></g> +<g id="border-horizontal"><path d="M3 21h2v-2H3v2zM5 7H3v2h2V7zM3 17h2v-2H3v2zm4 4h2v-2H7v2zM5 3H3v2h2V3zm4 0H7v2h2V3zm8 0h-2v2h2V3zm-4 4h-2v2h2V7zm0-4h-2v2h2V3zm6 14h2v-2h-2v2zm-8 4h2v-2h-2v2zm-8-8h18v-2H3v2zM19 3v2h2V3h-2zm0 6h2V7h-2v2zm-8 8h2v-2h-2v2zm4 4h2v-2h-2v2zm4 0h2v-2h-2v2z"/></g> +<g id="border-inner"><path d="M3 21h2v-2H3v2zm4 0h2v-2H7v2zM5 7H3v2h2V7zM3 17h2v-2H3v2zM9 3H7v2h2V3zM5 3H3v2h2V3zm12 0h-2v2h2V3zm2 6h2V7h-2v2zm0-6v2h2V3h-2zm-4 18h2v-2h-2v2zM13 3h-2v8H3v2h8v8h2v-8h8v-2h-8V3zm6 18h2v-2h-2v2zm0-4h2v-2h-2v2z"/></g> +<g id="border-left"><path d="M11 21h2v-2h-2v2zm0-4h2v-2h-2v2zm0-12h2V3h-2v2zm0 4h2V7h-2v2zm0 4h2v-2h-2v2zm-4 8h2v-2H7v2zM7 5h2V3H7v2zm0 8h2v-2H7v2zm-4 8h2V3H3v18zM19 9h2V7h-2v2zm-4 12h2v-2h-2v2zm4-4h2v-2h-2v2zm0-14v2h2V3h-2zm0 10h2v-2h-2v2zm0 8h2v-2h-2v2zm-4-8h2v-2h-2v2zm0-8h2V3h-2v2z"/></g> +<g id="border-outer"><path d="M13 7h-2v2h2V7zm0 4h-2v2h2v-2zm4 0h-2v2h2v-2zM3 3v18h18V3H3zm16 16H5V5h14v14zm-6-4h-2v2h2v-2zm-4-4H7v2h2v-2z"/></g> +<g id="border-right"><path d="M7 21h2v-2H7v2zM3 5h2V3H3v2zm4 0h2V3H7v2zm0 8h2v-2H7v2zm-4 8h2v-2H3v2zm8 0h2v-2h-2v2zm-8-8h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm8 8h2v-2h-2v2zm4-4h2v-2h-2v2zm4-10v18h2V3h-2zm-4 18h2v-2h-2v2zm0-16h2V3h-2v2zm-4 8h2v-2h-2v2zm0-8h2V3h-2v2zm0 4h2V7h-2v2z"/></g> +<g id="border-style"><path d="M15 21h2v-2h-2v2zm4 0h2v-2h-2v2zM7 21h2v-2H7v2zm4 0h2v-2h-2v2zm8-4h2v-2h-2v2zm0-4h2v-2h-2v2zM3 3v18h2V5h16V3H3zm16 6h2V7h-2v2z"/></g> +<g id="border-top"><path d="M7 21h2v-2H7v2zm0-8h2v-2H7v2zm4 0h2v-2h-2v2zm0 8h2v-2h-2v2zm-8-4h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2v-2H3v2zm0-4h2V7H3v2zm8 8h2v-2h-2v2zm8-8h2V7h-2v2zm0 4h2v-2h-2v2zM3 3v2h18V3H3zm16 14h2v-2h-2v2zm-4 4h2v-2h-2v2zM11 9h2V7h-2v2zm8 12h2v-2h-2v2zm-4-8h2v-2h-2v2z"/></g> +<g id="border-vertical"><path d="M3 9h2V7H3v2zm0-4h2V3H3v2zm4 16h2v-2H7v2zm0-8h2v-2H7v2zm-4 0h2v-2H3v2zm0 8h2v-2H3v2zm0-4h2v-2H3v2zM7 5h2V3H7v2zm12 12h2v-2h-2v2zm-8 4h2V3h-2v18zm8 0h2v-2h-2v2zm0-8h2v-2h-2v2zm0-10v2h2V3h-2zm0 6h2V7h-2v2zm-4-4h2V3h-2v2zm0 16h2v-2h-2v2zm0-8h2v-2h-2v2z"/></g> +<g id="format-align-center"><path d="M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z"/></g> +<g id="format-align-justify"><path d="M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zm0-6v2h18V3H3z"/></g> +<g id="format-align-left"><path d="M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z"/></g> +<g id="format-align-right"><path d="M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z"/></g> +<g id="format-bold"><path d="M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z"/></g> +<g id="format-clear"><path d="M3.27 5L2 6.27l6.97 6.97L6.5 19h3l1.57-3.66L16.73 21 18 19.73 3.55 5.27 3.27 5zM6 5v.18L8.82 8h2.4l-.72 1.68 2.1 2.1L14.21 8H20V5H6z"/></g> +<g id="format-color-fill"><path d="M16.56 8.94L7.62 0 6.21 1.41l2.38 2.38-5.15 5.15c-.59.59-.59 1.54 0 2.12l5.5 5.5c.29.29.68.44 1.06.44s.77-.15 1.06-.44l5.5-5.5c.59-.58.59-1.53 0-2.12zM5.21 10L10 5.21 14.79 10H5.21zM19 11.5s-2 2.17-2 3.5c0 1.1.9 2 2 2s2-.9 2-2c0-1.33-2-3.5-2-3.5z"/><path fill-opacity=".36" d="M0 20h24v4H0z"/></g> +<g id="format-color-reset"><path d="M18 14c0-4-6-10.8-6-10.8s-1.33 1.51-2.73 3.52l8.59 8.59c.09-.42.14-.86.14-1.31zm-.88 3.12L12.5 12.5 5.27 5.27 4 6.55l3.32 3.32C6.55 11.32 6 12.79 6 14c0 3.31 2.69 6 6 6 1.52 0 2.9-.57 3.96-1.5l2.63 2.63 1.27-1.27-2.74-2.74z"/></g> +<g id="format-color-text"><path fill-opacity=".36" d="M0 20h24v4H0z"/><path d="M11 3L5.5 17h2.25l1.12-3h6.25l1.12 3h2.25L13 3h-2zm-1.38 9L12 5.67 14.38 12H9.62z"/></g> +<g id="format-indent-decrease"><path d="M11 17h10v-2H11v2zm-8-5l4 4V8l-4 4zm0 9h18v-2H3v2zM3 3v2h18V3H3zm8 6h10V7H11v2zm0 4h10v-2H11v2z"/></g> +<g id="format-indent-increase"><path d="M3 21h18v-2H3v2zM3 8v8l4-4-4-4zm8 9h10v-2H11v2zM3 3v2h18V3H3zm8 6h10V7H11v2zm0 4h10v-2H11v2z"/></g> +<g id="format-italic"><path d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z"/></g> +<g id="format-line-spacing"><path d="M6 7h2.5L5 3.5 1.5 7H4v10H1.5L5 20.5 8.5 17H6V7zm4-2v2h12V5H10zm0 14h12v-2H10v2zm0-6h12v-2H10v2z"/></g> +<g id="format-list-bulleted"><path d="M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12.17c-.74 0-1.33.6-1.33 1.33s.6 1.33 1.33 1.33 1.33-.6 1.33-1.33-.59-1.33-1.33-1.33zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z"/></g> +<g id="format-list-numbered"><path d="M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 10.9V10H2v1zm5-6v2h14V5H7zm0 14h14v-2H7v2zm0-6h14v-2H7v2z"/></g> +<g id="format-paint"><path d="M18 4V3c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6h1v4H9v11c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-9h8V4h-3z"/></g> +<g id="format-quote"><path d="M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z"/></g> +<g id="format-size"><path d="M9 4v3h5v12h3V7h5V4H9zm-6 8h3v7h3v-7h3V9H3v3z"/></g> +<g id="format-strikethrough"><path d="M10 19h4v-3h-4v3zM5 4v3h5v3h4V7h5V4H5zM3 14h18v-2H3v2z"/></g> +<g id="format-textdirection-l-to-r"><path d="M9 10v5h2V4h2v11h2V4h2V2H9C6.79 2 5 3.79 5 6s1.79 4 4 4zm12 8l-4-4v3H5v2h12v3l4-4z"/></g> +<g id="format-textdirection-r-to-l"><path d="M10 10v5h2V4h2v11h2V4h2V2h-8C7.79 2 6 3.79 6 6s1.79 4 4 4zm-2 7v-3l-4 4 4 4v-3h12v-2H8z"/></g> +<g id="format-underline"><path d="M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z"/></g> +<g id="functions"><path d="M18 4H6v2l6.5 6L6 18v2h12v-3h-7l5-5-5-5h7z"/></g> +<g id="insert-chart"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/></g> +<g id="insert-comment"><path d="M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/></g> +<g id="insert-drive-file"><path d="M6 2c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6H6zm7 7V3.5L18.5 9H13z"/></g> +<g id="insert-emoticon"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></g> +<g id="insert-invitation"><path d="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"/></g> +<g id="insert-link"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></g> +<g id="insert-photo"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></g> +<g id="merge-type"><path d="M17 20.41L18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z"/></g> +<g id="mode-comment"><path d="M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4-.01-18z"/></g> +<g id="mode-edit"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></g> +<g id="publish"><path d="M5 4v2h14V4H5zm0 10h4v6h6v-6h4l-7-7-7 7z"/></g> +<g id="vertical-align-bottom"><path d="M16 13h-3V3h-2v10H8l4 4 4-4zM4 19v2h16v-2H4z"/></g> +<g id="vertical-align-center"><path d="M8 19h3v4h2v-4h3l-4-4-4 4zm8-14h-3V1h-2v4H8l4 4 4-4zM4 11v2h16v-2H4z"/></g> +<g id="vertical-align-top"><path d="M8 11h3v10h2V11h3l-4-4-4 4zM4 3v2h16V3H4z"/></g> +<g id="wrap-text"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/hardware-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/hardware-icons.html new file mode 100644 index 0000000..326cb98 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/hardware-icons.html
@@ -0,0 +1,56 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="hardware" size="24"> +<svg><defs> +<g id="cast"><path d="M21 3H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm0-4v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11z"/></g> +<g id="cast-connected"><path d="M1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm18-7H5v1.63c3.96 1.28 7.09 4.41 8.37 8.37H19V7zM1 10v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11zm20-7H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></g> +<g id="computer"><path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"/></g> +<g id="desktop-mac"><path d="M21 2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7l-2 3v1h8v-1l-2-3h7c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 12H3V4h18v10z"/></g> +<g id="desktop-windows"><path d="M21 2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7v2H8v2h8v-2h-2v-2h7c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H3V4h18v12z"/></g> +<g id="dock"><path d="M8 23h8v-2H8v2zm8-21.99L8 1c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM16 15H8V5h8v10z"/></g> +<g id="gamepad"><path d="M15 7.5V2H9v5.5l3 3 3-3zM7.5 9H2v6h5.5l3-3-3-3zM9 16.5V22h6v-5.5l-3-3-3 3zM16.5 9l-3 3 3 3H22V9h-5.5z"/></g> +<g id="headset"><path d="M12 1c-4.97 0-9 4.03-9 9v7c0 1.66 1.34 3 3 3h3v-8H5v-2c0-3.87 3.13-7 7-7s7 3.13 7 7v2h-4v8h3c1.66 0 3-1.34 3-3v-7c0-4.97-4.03-9-9-9z"/></g> +<g id="headset-mic"><path d="M12 1c-4.97 0-9 4.03-9 9v7c0 1.66 1.34 3 3 3h3v-8H5v-2c0-3.87 3.13-7 7-7s7 3.13 7 7v2h-4v8h4v1h-7v2h6c1.66 0 3-1.34 3-3V10c0-4.97-4.03-9-9-9z"/></g> +<g id="keyboard"><path d="M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9 7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z"/></g> +<g id="keyboard-alt"><path d="M15.5 10c.83 0 1.5-.67 1.5-1.5S16.33 7 15.5 7 14 7.67 14 8.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 7 8.5 7 7 7.67 7 8.5 7.67 10 8.5 10zm3.5 7c2.61 0 4.83-1.67 5.65-4H6.35c.82 2.33 3.04 4 5.65 4zm-.01-16C6.47 1 2 5.48 2 11s4.47 10 9.99 10C17.52 21 22 16.52 22 11S17.52 1 11.99 1zM12 19c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></g> +<g id="keyboard-arrow-down"><path d="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z"/></g> +<g id="keyboard-arrow-left"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"/></g> +<g id="keyboard-arrow-right"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"/></g> +<g id="keyboard-arrow-up"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"/></g> +<g id="keyboard-backspace"><path d="M21 11H6.83l3.58-3.59L9 6l-6 6 6 6 1.41-1.41L6.83 13H21z"/></g> +<g id="keyboard-capslock"><path d="M12 8.41L16.59 13 18 11.59l-6-6-6 6L7.41 13 12 8.41zM6 18h12v-2H6v2z"/></g> +<g id="keyboard-control"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="keyboard-hide"><path d="M20 3H4c-1.1 0-1.99.9-1.99 2L2 15c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-9 3h2v2h-2V6zm0 3h2v2h-2V9zM8 6h2v2H8V6zm0 3h2v2H8V9zm-1 2H5V9h2v2zm0-3H5V6h2v2zm9 7H8v-2h8v2zm0-4h-2V9h2v2zm0-3h-2V6h2v2zm3 3h-2V9h2v2zm0-3h-2V6h2v2zm-7 15l4-4H8l4 4z"/></g> +<g id="keyboard-return"><path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/></g> +<g id="keyboard-tab"><path d="M11.59 7.41L15.17 11H1v2h14.17l-3.59 3.59L13 18l6-6-6-6-1.41 1.41zM20 6v12h2V6h-2z"/></g> +<g id="keyboard-voice"><path d="M12 15c1.66 0 2.99-1.34 2.99-3L15 6c0-1.66-1.34-3-3-3S9 4.34 9 6v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 15 6.7 12H5c0 3.42 2.72 6.23 6 6.72V22h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></g> +<g id="laptop"><path d="M20 18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"/></g> +<g id="laptop-chromebook"><path d="M22 18V3H2v15H0v2h24v-2h-2zm-8 0h-4v-1h4v1zm6-3H4V5h16v10z"/></g> +<g id="laptop-mac"><path d="M20 18c1.1 0 1.99-.9 1.99-2L22 5c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2H0c0 1.1.9 2 2 2h20c1.1 0 2-.9 2-2h-4zM4 5h16v11H4V5zm8 14c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></g> +<g id="laptop-windows"><path d="M20 18v-1c1.1 0 1.99-.9 1.99-2L22 5c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2v1H0v2h24v-2h-4zM4 5h16v10H4V5z"/></g> +<g id="memory"><path d="M15 9H9v6h6V9zm-2 4h-2v-2h2v2zm8-2V9h-2V7c0-1.1-.9-2-2-2h-2V3h-2v2h-2V3H9v2H7c-1.1 0-2 .9-2 2v2H3v2h2v2H3v2h2v2c0 1.1.9 2 2 2h2v2h2v-2h2v2h2v-2h2c1.1 0 2-.9 2-2v-2h2v-2h-2v-2h2zm-4 6H7V7h10v10z"/></g> +<g id="mouse"><path d="M13 1.07V9h7c0-4.08-3.05-7.44-7-7.93zM4 15c0 4.42 3.58 8 8 8s8-3.58 8-8v-4H4v4zm7-13.93C7.05 1.56 4 4.92 4 9h7V1.07z"/></g> +<g id="phone-android"><path d="M16 1H8C6.34 1 5 2.34 5 4v16c0 1.66 1.34 3 3 3h8c1.66 0 3-1.34 3-3V4c0-1.66-1.34-3-3-3zm-2 20h-4v-1h4v1zm3.25-3H6.75V4h10.5v14z"/></g> +<g id="phone-iphone"><path d="M15.5 1h-8C6.12 1 5 2.12 5 3.5v17C5 21.88 6.12 23 7.5 23h8c1.38 0 2.5-1.12 2.5-2.5v-17C18 2.12 16.88 1 15.5 1zm-4 21c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm4.5-4H7V4h9v14z"/></g> +<g id="phonelink"><path d="M4 6h18V4H4c-1.1 0-2 .9-2 2v11H0v3h14v-3H4V6zm19 2h-6c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zm-1 9h-4v-7h4v7z"/></g> +<g id="phonelink-off"><path d="M22 6V4H6.82l2 2H22zM1.92 1.65L.65 2.92l1.82 1.82C2.18 5.08 2 5.52 2 6v11H0v3h17.73l2.35 2.35 1.27-1.27L3.89 3.62 1.92 1.65zM4 6.27L14.73 17H4V6.27zM23 8h-6c-.55 0-1 .45-1 1v4.18l2 2V10h4v7h-2.18l3 3H23c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1z"/></g> +<g id="security"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/></g> +<g id="sim-card"><path d="M19.99 4c0-1.1-.89-2-1.99-2h-8L4 8v12c0 1.1.9 2 2 2h12.01c1.1 0 1.99-.9 1.99-2l-.01-16zM9 19H7v-2h2v2zm8 0h-2v-2h2v2zm-8-4H7v-4h2v4zm4 4h-2v-4h2v4zm0-6h-2v-2h2v2zm4 2h-2v-4h2v4z"/></g> +<g id="smartphone"><path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></g> +<g id="speaker"><path d="M17 2H7c-1.1 0-2 .9-2 2v16c0 1.1.9 1.99 2 1.99L17 22c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 2c1.1 0 2 .9 2 2s-.9 2-2 2c-1.11 0-2-.9-2-2s.89-2 2-2zm0 16c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g> +<g id="tablet"><path d="M21 4H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 1.99-.9 1.99-2L23 6c0-1.1-.9-2-2-2zm-2 14H5V6h14v12z"/></g> +<g id="tablet-android"><path d="M18 0H6C4.34 0 3 1.34 3 3v18c0 1.66 1.34 3 3 3h12c1.66 0 3-1.34 3-3V3c0-1.66-1.34-3-3-3zm-4 22h-4v-1h4v1zm5.25-3H4.75V3h14.5v16z"/></g> +<g id="tablet-mac"><path d="M18.5 0h-14C3.12 0 2 1.12 2 2.5v19C2 22.88 3.12 24 4.5 24h14c1.38 0 2.5-1.12 2.5-2.5v-19C21 1.12 19.88 0 18.5 0zm-7 23c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm7.5-4H4V3h15v16z"/></g> +<g id="tv"><path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z"/></g> +<g id="watch"><path d="M20 12c0-2.54-1.19-4.81-3.04-6.27L16 0H8l-.95 5.73C5.19 7.19 4 9.45 4 12s1.19 4.81 3.05 6.27L8 24h8l.96-5.73C18.81 16.81 20 14.54 20 12zM6 12c0-3.31 2.69-6 6-6s6 2.69 6 6-2.69 6-6 6-6-2.69-6-6z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/image-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/image-icons.html new file mode 100644 index 0000000..a7ebc70 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/image-icons.html
@@ -0,0 +1,152 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="image" size="24"> +<svg><defs> +<g id="add-to-photos"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/></g> +<g id="adjust"><path d="M12 2C6.49 2 2 6.49 2 12s4.49 10 10 10 10-4.49 10-10S17.51 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3-8c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34 3 3z"/></g> +<g id="assistant-photo"><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/></g> +<g id="audiotrack"><path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z"/></g> +<g id="blur-circular"><path d="M10 9c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zM7 9.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm3 7c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm-3-3c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm3-6c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM14 9c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-1.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm3 6c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm0-4c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm2-3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm0-3.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z"/></g> +<g id="blur-linear"><path d="M5 17.5c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5.67 1.5 1.5 1.5zM9 13c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zM3 21h18v-2H3v2zM5 9.5c.83 0 1.5-.67 1.5-1.5S5.83 6.5 5 6.5 3.5 7.17 3.5 8 4.17 9.5 5 9.5zm0 4c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5.67 1.5 1.5 1.5zM9 17c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm8-.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM3 3v2h18V3H3zm14 5.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm0 4c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM13 9c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0 4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0 4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1z"/></g> +<g id="blur-off"><path d="M14 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm-.2 4.48l.2.02c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5l.02.2c.09.67.61 1.19 1.28 1.28zM14 3.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm-4 0c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm11 7c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM10 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm8 8c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm-4 13.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM2.5 5.27l3.78 3.78L6 9c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1c0-.1-.03-.19-.06-.28l2.81 2.81c-.71.11-1.25.73-1.25 1.47 0 .83.67 1.5 1.5 1.5.74 0 1.36-.54 1.47-1.25l2.81 2.81c-.09-.03-.18-.06-.28-.06-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1c0-.1-.03-.19-.06-.28l3.78 3.78L20 20.23 3.77 4 2.5 5.27zM10 17c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm11-3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM6 13c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zM3 9.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm7 11c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM6 17c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm-3-3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5z"/></g> +<g id="blur-on"><path d="M6 13c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-8c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm-3 .5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM6 5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm15 5.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM14 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-3.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm-11 10c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm7 7c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm0-17c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM10 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0 5.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm8 .5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-8c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm3 8.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM14 17c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm-4-12c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0 8.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm4-4.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-4c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"/></g> +<g id="brightness-1"><circle cx="12" cy="12" r="10"/></g> +<g id="brightness-2"><path d="M10 2c-1.82 0-3.53.5-5 1.35C7.99 5.08 10 8.3 10 12s-2.01 6.92-5 8.65C6.47 21.5 8.18 22 10 22c5.52 0 10-4.48 10-10S15.52 2 10 2z"/></g> +<g id="brightness-3"><path d="M9 2c-1.05 0-2.05.16-3 .46 4.06 1.27 7 5.06 7 9.54 0 4.48-2.94 8.27-7 9.54.95.3 1.95.46 3 .46 5.52 0 10-4.48 10-10S14.52 2 9 2z"/></g> +<g id="brightness-4"><path d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6c3.31 0 6 2.69 6 6s-2.69 6-6 6z"/></g> +<g id="brightness-5"><path d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6z"/></g> +<g id="brightness-6"><path d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18V6c3.31 0 6 2.69 6 6s-2.69 6-6 6z"/></g> +<g id="brightness-7"><path d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm0-10c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"/></g> +<g id="brush"><path d="M7 14c-1.66 0-3 1.34-3 3 0 1.31-1.16 2-2 2 .92 1.22 2.49 2 4 2 2.21 0 4-1.79 4-4 0-1.66-1.34-3-3-3zm13.71-9.37l-1.34-1.34c-.39-.39-1.02-.39-1.41 0L9 12.25 11.75 15l8.96-8.96c.39-.39.39-1.02 0-1.41z"/></g> +<g id="camera"><path d="M9.4 10.5l4.77-8.26C13.47 2.09 12.75 2 12 2c-2.4 0-4.6.85-6.32 2.25l3.66 6.35.06-.1zM21.54 9c-.92-2.92-3.15-5.26-6-6.34L11.88 9h9.66zm.26 1h-7.49l.29.5 4.76 8.25C21 16.97 22 14.61 22 12c0-.69-.07-1.35-.2-2zM8.54 12l-3.9-6.75C3.01 7.03 2 9.39 2 12c0 .69.07 1.35.2 2h7.49l-1.15-2zm-6.08 3c.92 2.92 3.15 5.26 6 6.34L12.12 15H2.46zm11.27 0l-3.9 6.76c.7.15 1.42.24 2.17.24 2.4 0 4.6-.85 6.32-2.25l-3.66-6.35-.93 1.6z"/></g> +<g id="camera-alt"><circle cx="12" cy="12" r="3.2"/><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></g> +<g id="camera-front"><path d="M10 20H5v2h5v2l3-3-3-3v2zm4 0v2h5v-2h-5zM12 8c1.1 0 2-.9 2-2s-.9-2-2-2-1.99.9-1.99 2S10.9 8 12 8zm5-8H7C5.9 0 5 .9 5 2v14c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V2c0-1.1-.9-2-2-2zM7 2h10v10.5c0-1.67-3.33-2.5-5-2.5s-5 .83-5 2.5V2z"/></g> +<g id="camera-rear"><path d="M10 20H5v2h5v2l3-3-3-3v2zm4 0v2h5v-2h-5zm3-20H7C5.9 0 5 .9 5 2v14c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V2c0-1.1-.9-2-2-2zm-5 6c-1.11 0-2-.9-2-2s.89-2 1.99-2 2 .9 2 2C14 5.1 13.1 6 12 6z"/></g> +<g id="camera-roll"><path d="M14 5c0-1.1-.9-2-2-2h-1V2c0-.55-.45-1-1-1H6c-.55 0-1 .45-1 1v1H4c-1.1 0-2 .9-2 2v15c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2h8V5h-8zm-2 13h-2v-2h2v2zm0-9h-2V7h2v2zm4 9h-2v-2h2v2zm0-9h-2V7h2v2zm4 9h-2v-2h2v2zm0-9h-2V7h2v2z"/></g> +<g id="center-focus-strong"><path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm-7 7H3v4c0 1.1.9 2 2 2h4v-2H5v-4zM5 5h4V3H5c-1.1 0-2 .9-2 2v4h2V5zm14-2h-4v2h4v4h2V5c0-1.1-.9-2-2-2zm0 16h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4z"/></g> +<g id="center-focus-weak"><path d="M5 15H3v4c0 1.1.9 2 2 2h4v-2H5v-4zM5 5h4V3H5c-1.1 0-2 .9-2 2v4h2V5zm14-2h-4v2h4v4h2V5c0-1.1-.9-2-2-2zm0 16h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zM12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="collections"><path d="M22 16V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2zm-11-4l2.03 2.71L16 11l4 5H8l3-4zM2 6v14c0 1.1.9 2 2 2h14v-2H4V6H2z"/></g> +<g id="color-lens"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="colorize"><path d="M20.71 5.63l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-3.12 3.12-1.93-1.91-1.41 1.41 1.42 1.42L3 16.25V21h4.75l8.92-8.92 1.42 1.42 1.41-1.41-1.92-1.92 3.12-3.12c.4-.4.4-1.03.01-1.42zM6.92 19L5 17.08l8.06-8.06 1.92 1.92L6.92 19z"/></g> +<g id="compare"><path d="M10 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h5v2h2V1h-2v2zm0 15H5l5-6v6zm9-15h-5v2h5v13l-5-6v9h5c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></g> +<g id="control-point"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.49 2 2 6.49 2 12s4.49 10 10 10 10-4.49 10-10S17.51 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="control-point-duplicate"><path d="M16 8h-2v3h-3v2h3v3h2v-3h3v-2h-3zM2 12c0-2.79 1.64-5.2 4.01-6.32V3.52C2.52 4.76 0 8.09 0 12s2.52 7.24 6.01 8.48v-2.16C3.64 17.2 2 14.79 2 12zm13-9c-4.96 0-9 4.04-9 9s4.04 9 9 9 9-4.04 9-9-4.04-9-9-9zm0 16c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7z"/></g> +<g id="crop"><path d="M17 15h2V7c0-1.1-.9-2-2-2H9v2h8v8zM7 17V1H5v4H1v2h4v10c0 1.1.9 2 2 2h10v4h2v-4h4v-2H7z"/></g> +<g id="crop-16-9"><path d="M19 6H5c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H5V8h14v8z"/></g> +<g id="crop-3-2"><path d="M19 4H5c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H5V6h14v12z"/></g> +<g id="crop-5-4"><path d="M19 5H5c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 12H5V7h14v10z"/></g> +<g id="crop-7-5"><path d="M19 7H5c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8H5V9h14v6z"/></g> +<g id="crop-din"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/></g> +<g id="crop-free"><path d="M3 5v4h2V5h4V3H5c-1.1 0-2 .9-2 2zm2 10H3v4c0 1.1.9 2 2 2h4v-2H5v-4zm14 4h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zm0-16h-4v2h4v4h2V5c0-1.1-.9-2-2-2z"/></g> +<g id="crop-landscape"><path d="M19 5H5c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 12H5V7h14v10z"/></g> +<g id="crop-original"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zm-5.04-6.71l-2.75 3.54-1.96-2.36L6.5 17h11l-3.54-4.71z"/></g> +<g id="crop-portrait"><path d="M17 3H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H7V5h10v14z"/></g> +<g id="crop-square"><path d="M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H6V6h12v12z"/></g> +<g id="dehaze"><path d="M2 15.5v2h20v-2H2zm0-5v2h20v-2H2zm0-5v2h20v-2H2z"/></g> +<g id="details"><path d="M3 4l9 16 9-16H3zm3.38 2h11.25L12 16 6.38 6z"/></g> +<g id="edit"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></g> +<g id="exposure"><path d="M15 17v2h2v-2h2v-2h-2v-2h-2v2h-2v2h2zm5-15H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM5 5h6v2H5V5zm15 15H4L20 4v16z"/></g> +<g id="exposure-minus-1"><path d="M4 11v2h8v-2H4zm15 7h-2V7.38L14 8.4V6.7L18.7 5h.3v13z"/></g> +<g id="exposure-minus-2"><path d="M15.05 16.29l2.86-3.07c.38-.39.72-.79 1.04-1.18.32-.39.59-.78.82-1.17.23-.39.41-.78.54-1.17s.19-.79.19-1.18c0-.53-.09-1.02-.27-1.46-.18-.44-.44-.81-.78-1.11-.34-.31-.77-.54-1.26-.71-.51-.16-1.08-.24-1.72-.24-.69 0-1.31.11-1.85.32-.54.21-1 .51-1.36.88-.37.37-.65.8-.84 1.3-.18.47-.27.97-.28 1.5h2.14c.01-.31.05-.6.13-.87.09-.29.23-.54.4-.75.18-.21.41-.37.68-.49.27-.12.6-.18.96-.18.31 0 .58.05.81.15.23.1.43.25.59.43.16.18.28.4.37.65.08.25.13.52.13.81 0 .22-.03.43-.08.65-.06.22-.15.45-.29.7-.14.25-.32.53-.56.83-.23.3-.52.65-.88 1.03l-4.17 4.55V18H21v-1.71h-5.95zM2 11v2h8v-2H2z"/></g> +<g id="exposure-plus-1"><path d="M10 7H8v4H4v2h4v4h2v-4h4v-2h-4V7zm10 11h-2V7.38L15 8.4V6.7L19.7 5h.3v13z"/></g> +<g id="exposure-plus-2"><path d="M16.05 16.29l2.86-3.07c.38-.39.72-.79 1.04-1.18.32-.39.59-.78.82-1.17.23-.39.41-.78.54-1.17.13-.39.19-.79.19-1.18 0-.53-.09-1.02-.27-1.46-.18-.44-.44-.81-.78-1.11-.34-.31-.77-.54-1.26-.71-.51-.16-1.08-.24-1.72-.24-.69 0-1.31.11-1.85.32-.54.21-1 .51-1.36.88-.37.37-.65.8-.84 1.3-.18.47-.27.97-.28 1.5h2.14c.01-.31.05-.6.13-.87.09-.29.23-.54.4-.75.18-.21.41-.37.68-.49.27-.12.6-.18.96-.18.31 0 .58.05.81.15.23.1.43.25.59.43.16.18.28.4.37.65.08.25.13.52.13.81 0 .22-.03.43-.08.65-.06.22-.15.45-.29.7-.14.25-.32.53-.56.83-.23.3-.52.65-.88 1.03l-4.17 4.55V18H22v-1.71h-5.95zM8 7H6v4H2v2h4v4h2v-4h4v-2H8V7z"/></g> +<g id="exposure-zero"><path d="M16.14 12.5c0 1-.1 1.85-.3 2.55-.2.7-.48 1.27-.83 1.7-.36.44-.79.75-1.3.95-.51.2-1.07.3-1.7.3-.62 0-1.18-.1-1.69-.3-.51-.2-.95-.51-1.31-.95-.36-.44-.65-1.01-.85-1.7-.2-.7-.3-1.55-.3-2.55v-2.04c0-1 .1-1.85.3-2.55.2-.7.48-1.26.84-1.69.36-.43.8-.74 1.31-.93C10.81 5.1 11.38 5 12 5c.63 0 1.19.1 1.7.29.51.19.95.5 1.31.93.36.43.64.99.84 1.69.2.7.3 1.54.3 2.55v2.04zm-2.11-2.36c0-.64-.05-1.18-.13-1.62-.09-.44-.22-.79-.4-1.06-.17-.27-.39-.46-.64-.58-.25-.13-.54-.19-.86-.19-.32 0-.61.06-.86.18s-.47.31-.64.58c-.17.27-.31.62-.4 1.06s-.13.98-.13 1.62v2.67c0 .64.05 1.18.14 1.62.09.45.23.81.4 1.09s.39.48.64.61.54.19.87.19c.33 0 .62-.06.87-.19s.46-.33.63-.61c.17-.28.3-.64.39-1.09.09-.45.13-.99.13-1.62v-2.66z"/></g> +<g id="filter"><path d="M15.96 10.29l-2.75 3.54-1.96-2.36L8.5 15h11l-3.54-4.71zM3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14z"/></g> +<g id="filter-1"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm11 10h2V5h-4v2h2v8zm7-14H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14z"/></g> +<g id="filter-2"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zm-4-4h-4v-2h2c1.1 0 2-.89 2-2V7c0-1.11-.9-2-2-2h-4v2h4v2h-2c-1.1 0-2 .89-2 2v4h6v-2z"/></g> +<g id="filter-3"><path d="M21 1H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zM3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm14 8v-1.5c0-.83-.67-1.5-1.5-1.5.83 0 1.5-.67 1.5-1.5V7c0-1.11-.9-2-2-2h-4v2h4v2h-2v2h2v2h-4v2h4c1.1 0 2-.89 2-2z"/></g> +<g id="filter-4"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm12 10h2V5h-2v4h-2V5h-2v6h4v4zm6-14H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14z"/></g> +<g id="filter-5"><path d="M21 1H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zM3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm14 8v-2c0-1.11-.9-2-2-2h-2V7h4V5h-6v6h4v2h-4v2h4c1.1 0 2-.89 2-2z"/></g> +<g id="filter-6"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zm-8-2h2c1.1 0 2-.89 2-2v-2c0-1.11-.9-2-2-2h-2V7h4V5h-4c-1.1 0-2 .89-2 2v6c0 1.11.9 2 2 2zm0-4h2v2h-2v-2z"/></g> +<g id="filter-7"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zm-8-2l4-8V5h-6v2h4l-4 8h2z"/></g> +<g id="filter-8"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zm-8-2h2c1.1 0 2-.89 2-2v-1.5c0-.83-.67-1.5-1.5-1.5.83 0 1.5-.67 1.5-1.5V7c0-1.11-.9-2-2-2h-2c-1.1 0-2 .89-2 2v1.5c0 .83.67 1.5 1.5 1.5-.83 0-1.5.67-1.5 1.5V13c0 1.11.9 2 2 2zm0-8h2v2h-2V7zm0 4h2v2h-2v-2z"/></g> +<g id="filter-9"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zM15 5h-2c-1.1 0-2 .89-2 2v2c0 1.11.9 2 2 2h2v2h-4v2h4c1.1 0 2-.89 2-2V7c0-1.11-.9-2-2-2zm0 4h-2V7h2v2z"/></g> +<g id="filter-9-plus"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm11 7V8c0-1.11-.9-2-2-2h-1c-1.1 0-2 .89-2 2v1c0 1.11.9 2 2 2h1v1H9v2h3c1.1 0 2-.89 2-2zm-3-3V8h1v1h-1zm10-8H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 8h-2V7h-2v2h-2v2h2v2h2v-2h2v6H7V3h14v6z"/></g> +<g id="filter-b-and-w"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16l-7-8v8H5l7-8V5h7v14z"/></g> +<g id="filter-center-focus"><path d="M5 15H3v4c0 1.1.9 2 2 2h4v-2H5v-4zM5 5h4V3H5c-1.1 0-2 .9-2 2v4h2V5zm14-2h-4v2h4v4h2V5c0-1.1-.9-2-2-2zm0 16h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zM12 9c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g> +<g id="filter-drama"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.61 5.64 5.36 8.04 2.35 8.36 0 10.9 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4h2c0-2.76-1.86-5.08-4.4-5.78C8.61 6.88 10.2 6 12 6c3.03 0 5.5 2.47 5.5 5.5v.5H19c1.65 0 3 1.35 3 3s-1.35 3-3 3z"/></g> +<g id="filter-frames"><path d="M20 4h-4l-4-4-4 4H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H4V6h4.52l3.52-3.5L15.52 6H20v14zM18 8H6v10h12"/></g> +<g id="filter-hdr"><path d="M14 6l-3.75 5 2.85 3.8-1.6 1.2C9.81 13.75 7 10 7 10l-6 8h22L14 6z"/></g> +<g id="filter-none"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14z"/></g> +<g id="filter-tilt-shift"><path d="M11 4.07V2.05c-2.01.2-3.84 1-5.32 2.21L7.1 5.69c1.11-.86 2.44-1.44 3.9-1.62zm7.32.19C16.84 3.05 15.01 2.25 13 2.05v2.02c1.46.18 2.79.76 3.9 1.62l1.42-1.43zM19.93 11h2.02c-.2-2.01-1-3.84-2.21-5.32L18.31 7.1c.86 1.11 1.44 2.44 1.62 3.9zM5.69 7.1L4.26 5.68C3.05 7.16 2.25 8.99 2.05 11h2.02c.18-1.46.76-2.79 1.62-3.9zM4.07 13H2.05c.2 2.01 1 3.84 2.21 5.32l1.43-1.43c-.86-1.1-1.44-2.43-1.62-3.89zM15 12c0-1.66-1.34-3-3-3s-3 1.34-3 3 1.34 3 3 3 3-1.34 3-3zm3.31 4.9l1.43 1.43c1.21-1.48 2.01-3.32 2.21-5.32h-2.02c-.18 1.45-.76 2.78-1.62 3.89zM13 19.93v2.02c2.01-.2 3.84-1 5.32-2.21l-1.43-1.43c-1.1.86-2.43 1.44-3.89 1.62zm-7.32-.19C7.16 20.95 9 21.75 11 21.95v-2.02c-1.46-.18-2.79-.76-3.9-1.62l-1.42 1.43z"/></g> +<g id="filter-vintage"><path d="M18.7 12.4c-.28-.16-.57-.29-.86-.4.29-.11.58-.24.86-.4 1.92-1.11 2.99-3.12 3-5.19-1.79-1.03-4.07-1.11-6 0-.28.16-.54.35-.78.54.05-.31.08-.63.08-.95 0-2.22-1.21-4.15-3-5.19C10.21 1.85 9 3.78 9 6c0 .32.03.64.08.95-.24-.2-.5-.39-.78-.55-1.92-1.11-4.2-1.03-6 0 0 2.07 1.07 4.08 3 5.19.28.16.57.29.86.4-.29.11-.58.24-.86.4-1.92 1.11-2.99 3.12-3 5.19 1.79 1.03 4.07 1.11 6 0 .28-.16.54-.35.78-.54-.05.32-.08.64-.08.96 0 2.22 1.21 4.15 3 5.19 1.79-1.04 3-2.97 3-5.19 0-.32-.03-.64-.08-.95.24.2.5.38.78.54 1.92 1.11 4.2 1.03 6 0-.01-2.07-1.08-4.08-3-5.19zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"/></g> +<g id="flare"><path d="M7 11H1v2h6v-2zm2.17-3.24L7.05 5.64 5.64 7.05l2.12 2.12 1.41-1.41zM13 1h-2v6h2V1zm5.36 6.05l-1.41-1.41-2.12 2.12 1.41 1.41 2.12-2.12zM17 11v2h6v-2h-6zm-5-2c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm2.83 7.24l2.12 2.12 1.41-1.41-2.12-2.12-1.41 1.41zm-9.19.71l1.41 1.41 2.12-2.12-1.41-1.41-2.12 2.12zM11 23h2v-6h-2v6z"/></g> +<g id="flash-auto"><path d="M3 2v12h3v9l7-12H9l4-9H3zm16 0h-2l-3.2 9h1.9l.7-2h3.2l.7 2h1.9L19 2zm-2.15 5.65L18 4l1.15 3.65h-2.3z"/></g> +<g id="flash-off"><path d="M3.27 3L2 4.27l5 5V13h3v9l3.58-6.14L17.73 20 19 18.73 3.27 3zM17 10h-4l4-8H7v2.18l8.46 8.46L17 10z"/></g> +<g id="flash-on"><path d="M7 2v11h3v9l7-12h-4l4-8z"/></g> +<g id="flip"><path d="M15 21h2v-2h-2v2zm4-12h2V7h-2v2zM3 5v14c0 1.1.9 2 2 2h4v-2H5V5h4V3H5c-1.1 0-2 .9-2 2zm16-2v2h2c0-1.1-.9-2-2-2zm-8 20h2V1h-2v22zm8-6h2v-2h-2v2zM15 5h2V3h-2v2zm4 8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2z"/></g> +<g id="gradient"><path d="M11 9h2v2h-2zm-2 2h2v2H9zm4 0h2v2h-2zm2-2h2v2h-2zM7 9h2v2H7zm12-6H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 18H7v-2h2v2zm4 0h-2v-2h2v2zm4 0h-2v-2h2v2zm2-7h-2v2h2v2h-2v-2h-2v2h-2v-2h-2v2H9v-2H7v2H5v-2h2v-2H5V5h14v6z"/></g> +<g id="grain"><path d="M10 12c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zM6 8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12-8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-4 8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm4-4c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-4-4c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-4-4c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="grid-off"><path d="M8 4v1.45l2 2V4h4v4h-3.45l2 2H14v1.45l2 2V10h4v4h-3.45l2 2H20v1.45l2 2V4c0-1.1-.9-2-2-2H4.55l2 2H8zm8 0h4v4h-4V4zM1.27 1.27L0 2.55l2 2V20c0 1.1.9 2 2 2h15.46l2 2 1.27-1.27L1.27 1.27zM10 12.55L11.45 14H10v-1.45zm-6-6L5.45 8H4V6.55zM8 20H4v-4h4v4zm0-6H4v-4h3.45l.55.55V14zm6 6h-4v-4h3.45l.55.54V20zm2 0v-1.46L17.46 20H16z"/></g> +<g id="grid-on"><path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM8 20H4v-4h4v4zm0-6H4v-4h4v4zm0-6H4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4z"/></g> +<g id="hdr-off"><path d="M18 17L3.27 2.27 2 3.55l4 4V11H4V7H2v10h2v-4h2v4h2V9.55l1 1V17h4c.67 0 1.26-.33 1.62-.84l6.34 6.34 1.27-1.27L18 17zm-5-2h-2v-2.45l2 2V15zm5-2h1l.82 3.27.73.73H22l-1.19-4.17c.7-.31 1.19-1.01 1.19-1.83V9c0-1.1-.9-2-2-2h-4v5.45l2 2V13zm0-4h2v2h-2V9zm-3 2.45V9c0-1.1-.9-2-2-2h-2.45L15 11.45z"/></g> +<g id="hdr-on"><path d="M6 11H4V7H2v10h2v-4h2v4h2V7H6v4zm7-4H9v10h4c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8h-2V9h2v6zm9-4V9c0-1.1-.9-2-2-2h-4v10h2v-4h1l1 4h2l-1.19-4.17c.7-.31 1.19-1.01 1.19-1.83zm-2 0h-2V9h2v2z"/></g> +<g id="hdr-strong"><path d="M17 6c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zM5 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="hdr-weak"><path d="M5 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm12-2c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm0 10c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"/></g> +<g id="healing"><path d="M17.73 12.02l3.98-3.98c.39-.39.39-1.02 0-1.41l-4.34-4.34c-.39-.39-1.02-.39-1.41 0l-3.98 3.98L8 2.29C7.8 2.1 7.55 2 7.29 2c-.25 0-.51.1-.7.29L2.25 6.63c-.39.39-.39 1.02 0 1.41l3.98 3.98L2.25 16c-.39.39-.39 1.02 0 1.41l4.34 4.34c.39.39 1.02.39 1.41 0l3.98-3.98 3.98 3.98c.2.2.45.29.71.29.26 0 .51-.1.71-.29l4.34-4.34c.39-.39.39-1.02 0-1.41l-3.99-3.98zM12 9c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-4.71 1.96L3.66 7.34l3.63-3.63 3.62 3.62-3.62 3.63zM10 13c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2 2c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2-4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2.66 9.34l-3.63-3.62 3.63-3.63 3.62 3.62-3.62 3.63z"/></g> +<g id="image"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></g> +<g id="image-aspect-ratio"><path d="M16 10h-2v2h2v-2zm0 4h-2v2h2v-2zm-8-4H6v2h2v-2zm4 0h-2v2h2v-2zm8-6H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H4V6h16v12z"/></g> +<g id="iso"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5.5 7.5h2v-2H9v2h2V9H9v2H7.5V9h-2V7.5zM19 19H5L19 5v14zm-2-2v-1.5h-5V17h5z"/></g> +<g id="landscape"><path d="M14 6l-3.75 5 2.85 3.8-1.6 1.2C9.81 13.75 7 10 7 10l-6 8h22L14 6z"/></g> +<g id="leak-add"><path d="M6 3H3v3c1.66 0 3-1.34 3-3zm8 0h-2c0 4.97-4.03 9-9 9v2c6.08 0 11-4.93 11-11zm-4 0H8c0 2.76-2.24 5-5 5v2c3.87 0 7-3.13 7-7zm0 18h2c0-4.97 4.03-9 9-9v-2c-6.07 0-11 4.93-11 11zm8 0h3v-3c-1.66 0-3 1.34-3 3zm-4 0h2c0-2.76 2.24-5 5-5v-2c-3.87 0-7 3.13-7 7z"/></g> +<g id="leak-remove"><path d="M10 3H8c0 .37-.04.72-.12 1.06l1.59 1.59C9.81 4.84 10 3.94 10 3zM3 4.27l2.84 2.84C5.03 7.67 4.06 8 3 8v2c1.61 0 3.09-.55 4.27-1.46L8.7 9.97C7.14 11.24 5.16 12 3 12v2c2.71 0 5.19-.99 7.11-2.62l2.5 2.5C10.99 15.81 10 18.29 10 21h2c0-2.16.76-4.14 2.03-5.69l1.43 1.43C14.55 17.91 14 19.39 14 21h2c0-1.06.33-2.03.89-2.84L19.73 21 21 19.73 4.27 3 3 4.27zM14 3h-2c0 1.5-.37 2.91-1.02 4.16l1.46 1.46C13.42 6.98 14 5.06 14 3zm5.94 13.12c.34-.08.69-.12 1.06-.12v-2c-.94 0-1.84.19-2.66.52l1.6 1.6zm-4.56-4.56l1.46 1.46C18.09 12.37 19.5 12 21 12v-2c-2.06 0-3.98.58-5.62 1.56z"/></g> +<g id="lens"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z"/></g> +<g id="looks"><path d="M12 10c-3.86 0-7 3.14-7 7h2c0-2.76 2.24-5 5-5s5 2.24 5 5h2c0-3.86-3.14-7-7-7zm0-4C5.93 6 1 10.93 1 17h2c0-4.96 4.04-9 9-9s9 4.04 9 9h2c0-6.07-4.93-11-11-11z"/></g> +<g id="looks-3"><path d="M19.01 3h-14c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 7.5c0 .83-.67 1.5-1.5 1.5.83 0 1.5.67 1.5 1.5V15c0 1.11-.9 2-2 2h-4v-2h4v-2h-2v-2h2V9h-4V7h4c1.1 0 2 .89 2 2v1.5z"/></g> +<g id="looks-4"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 14h-2v-4H9V7h2v4h2V7h2v10z"/></g> +<g id="looks-5"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 6h-4v2h2c1.1 0 2 .89 2 2v2c0 1.11-.9 2-2 2H9v-2h4v-2H9V7h6v2z"/></g> +<g id="looks-6"><path d="M11 15h2v-2h-2v2zm8-12H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 6h-4v2h2c1.1 0 2 .89 2 2v2c0 1.11-.9 2-2 2h-2c-1.1 0-2-.89-2-2V9c0-1.11.9-2 2-2h4v2z"/></g> +<g id="looks-one"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14h-2V9h-2V7h4v10z"/></g> +<g id="looks-two"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 8c0 1.11-.9 2-2 2h-2v2h4v2H9v-4c0-1.11.9-2 2-2h2V9H9V7h4c1.1 0 2 .89 2 2v2z"/></g> +<g id="loupe"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.49 2 2 6.49 2 12s4.49 10 10 10h8c1.1 0 2-.9 2-2v-8c0-5.51-4.49-10-10-10zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="movie-creation"><path d="M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4h-4z"/></g> +<g id="nature"><path d="M13 16.12c3.47-.41 6.17-3.36 6.17-6.95 0-3.87-3.13-7-7-7s-7 3.13-7 7c0 3.47 2.52 6.34 5.83 6.89V20H5v2h14v-2h-6v-3.88z"/></g> +<g id="nature-people"><path d="M22.17 9.17c0-3.87-3.13-7-7-7s-7 3.13-7 7c0 3.47 2.52 6.34 5.83 6.89V20H6v-3h1v-4c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v4h1v5h16v-2h-3v-3.88c3.47-.41 6.17-3.36 6.17-6.95zM4.5 11c.83 0 1.5-.67 1.5-1.5S5.33 8 4.5 8 3 8.67 3 9.5 3.67 11 4.5 11z"/></g> +<g id="navigate-before"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></g> +<g id="navigate-next"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></g> +<g id="palette"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="panorama"><path d="M23 18V6c0-1.1-.9-2-2-2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zM8.5 12.5l2.5 3.01L14.5 11l4.5 6H5l3.5-4.5z"/></g> +<g id="panorama-fisheye"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="panorama-horizontal"><path d="M20 6.54v10.91c-2.6-.77-5.28-1.16-8-1.16-2.72 0-5.4.39-8 1.16V6.54c2.6.77 5.28 1.16 8 1.16 2.72.01 5.4-.38 8-1.16M21.43 4c-.1 0-.2.02-.31.06C18.18 5.16 15.09 5.7 12 5.7c-3.09 0-6.18-.55-9.12-1.64-.11-.04-.22-.06-.31-.06-.34 0-.57.23-.57.63v14.75c0 .39.23.62.57.62.1 0 .2-.02.31-.06 2.94-1.1 6.03-1.64 9.12-1.64 3.09 0 6.18.55 9.12 1.64.11.04.21.06.31.06.33 0 .57-.23.57-.63V4.63c0-.4-.24-.63-.57-.63z"/></g> +<g id="panorama-vertical"><path d="M19.94 21.12c-1.1-2.94-1.64-6.03-1.64-9.12 0-3.09.55-6.18 1.64-9.12.04-.11.06-.22.06-.31 0-.34-.23-.57-.63-.57H4.63c-.4 0-.63.23-.63.57 0 .1.02.2.06.31C5.16 5.82 5.71 8.91 5.71 12c0 3.09-.55 6.18-1.64 9.12-.05.11-.07.22-.07.31 0 .33.23.57.63.57h14.75c.39 0 .63-.24.63-.57-.01-.1-.03-.2-.07-.31zM6.54 20c.77-2.6 1.16-5.28 1.16-8 0-2.72-.39-5.4-1.16-8h10.91c-.77 2.6-1.16 5.28-1.16 8 0 2.72.39 5.4 1.16 8H6.54z"/></g> +<g id="panorama-wide-angle"><path d="M12 6c2.45 0 4.71.2 7.29.64.47 1.78.71 3.58.71 5.36 0 1.78-.24 3.58-.71 5.36-2.58.44-4.84.64-7.29.64s-4.71-.2-7.29-.64C4.24 15.58 4 13.78 4 12c0-1.78.24-3.58.71-5.36C7.29 6.2 9.55 6 12 6m0-2c-2.73 0-5.22.24-7.95.72l-.93.16-.25.9C2.29 7.85 2 9.93 2 12s.29 4.15.87 6.22l.25.89.93.16c2.73.49 5.22.73 7.95.73s5.22-.24 7.95-.72l.93-.16.25-.89c.58-2.08.87-4.16.87-6.23s-.29-4.15-.87-6.22l-.25-.89-.93-.16C17.22 4.24 14.73 4 12 4z"/></g> +<g id="photo"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></g> +<g id="photo-album"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4zm0 15l3-3.86 2.14 2.58 3-3.86L18 19H6z"/></g> +<g id="photo-camera"><circle cx="12" cy="12" r="3.2"/><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></g> +<g id="photo-library"><path d="M22 16V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2zm-11-4l2.03 2.71L16 11l4 5H8l3-4zM2 6v14c0 1.1.9 2 2 2h14v-2H4V6H2z"/></g> +<g id="portrait"><path d="M12 12.25c1.24 0 2.25-1.01 2.25-2.25S13.24 7.75 12 7.75 9.75 8.76 9.75 10s1.01 2.25 2.25 2.25zm4.5 4c0-1.5-3-2.25-4.5-2.25s-4.5.75-4.5 2.25V17h9v-.75zM19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/></g> +<g id="remove-red-eye"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g> +<g id="rotate-left"><path d="M7.11 8.53L5.7 7.11C4.8 8.27 4.24 9.61 4.07 11h2.02c.14-.87.49-1.72 1.02-2.47zM6.09 13H4.07c.17 1.39.72 2.73 1.62 3.89l1.41-1.42c-.52-.75-.87-1.59-1.01-2.47zm1.01 5.32c1.16.9 2.51 1.44 3.9 1.61V17.9c-.87-.15-1.71-.49-2.46-1.03L7.1 18.32zM13 4.07V1L8.45 5.55 13 10V6.09c2.84.48 5 2.94 5 5.91s-2.16 5.43-5 5.91v2.02c3.95-.49 7-3.85 7-7.93s-3.05-7.44-7-7.93z"/></g> +<g id="rotate-right"><path d="M15.55 5.55L11 1v3.07C7.06 4.56 4 7.92 4 12s3.05 7.44 7 7.93v-2.02c-2.84-.48-5-2.94-5-5.91s2.16-5.43 5-5.91V10l4.55-4.45zM19.93 11c-.17-1.39-.72-2.73-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02c1.39-.17 2.74-.71 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41c.9-1.16 1.45-2.5 1.62-3.89h-2.02c-.14.87-.48 1.72-1.02 2.48z"/></g> +<g id="slideshow"><path d="M10 8v8l5-4-5-4zm9-5H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/></g> +<g id="straighten"><path d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"/></g> +<g id="style"><path d="M2.53 19.65l1.34.56v-9.03l-2.43 5.86c-.41 1.02.08 2.19 1.09 2.61zm19.5-3.7L17.07 3.98c-.31-.75-1.04-1.21-1.81-1.23-.26 0-.53.04-.79.15L7.1 5.95c-.75.31-1.21 1.03-1.23 1.8-.01.27.04.54.15.8l4.96 11.97c.31.76 1.05 1.22 1.83 1.23.26 0 .52-.05.77-.15l7.36-3.05c1.02-.42 1.51-1.59 1.09-2.6zM7.88 8.75c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-2 11c0 1.1.9 2 2 2h1.45l-3.45-8.34v6.34z"/></g> +<g id="switch-camera"><path d="M20 4h-3.17L15 2H9L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 11.5V13H9v2.5L5.5 12 9 8.5V11h6V8.5l3.5 3.5-3.5 3.5z"/></g> +<g id="switch-video"><path d="M18 9.5V6c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h14c.55 0 1-.45 1-1v-3.5l4 4v-13l-4 4zm-5 6V13H7v2.5L3.5 12 7 8.5V11h6V8.5l3.5 3.5-3.5 3.5z"/></g> +<g id="tag-faces"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></g> +<g id="texture"><path d="M19.51 3.08L3.08 19.51c.09.34.27.65.51.9.25.24.56.42.9.51L20.93 4.49c-.19-.69-.73-1.23-1.42-1.41zM11.88 3L3 11.88v2.83L14.71 3h-2.83zM5 3c-1.1 0-2 .9-2 2v2l4-4H5zm14 18c.55 0 1.05-.22 1.41-.59.37-.36.59-.86.59-1.41v-2l-4 4h2zm-9.71 0h2.83L21 12.12V9.29L9.29 21z"/></g> +<g id="timelapse"><path d="M16.24 7.76C15.07 6.59 13.54 6 12 6v6l-4.24 4.24c2.34 2.34 6.14 2.34 8.49 0 2.34-2.34 2.34-6.14-.01-8.48zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></g> +<g id="timer"><path d="M15 1H9v2h6V1zm-4 13h2V8h-2v6zm8.03-6.61l1.42-1.42c-.43-.51-.9-.99-1.41-1.41l-1.42 1.42C16.07 4.74 14.12 4 12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9 9-4.03 9-9c0-2.12-.74-4.07-1.97-5.61zM12 20c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="timer-10"><path d="M0 7.72V9.4l3-1V18h2V6h-.25L0 7.72zm23.78 6.65c-.14-.28-.35-.53-.63-.74-.28-.21-.61-.39-1.01-.53s-.85-.27-1.35-.38c-.35-.07-.64-.15-.87-.23-.23-.08-.41-.16-.55-.25-.14-.09-.23-.19-.28-.3-.05-.11-.08-.24-.08-.39 0-.14.03-.28.09-.41.06-.13.15-.25.27-.34.12-.1.27-.18.45-.24s.4-.09.64-.09c.25 0 .47.04.66.11.19.07.35.17.48.29.13.12.22.26.29.42.06.16.1.32.1.49h1.95c0-.39-.08-.75-.24-1.09-.16-.34-.39-.63-.69-.88-.3-.25-.66-.44-1.09-.59C21.49 9.07 21 9 20.46 9c-.51 0-.98.07-1.39.21-.41.14-.77.33-1.06.57-.29.24-.51.52-.67.84-.16.32-.23.65-.23 1.01s.08.69.23.96c.15.28.36.52.64.73.27.21.6.38.98.53.38.14.81.26 1.27.36.39.08.71.17.95.26s.43.19.57.29c.13.1.22.22.27.34.05.12.07.25.07.39 0 .32-.13.57-.4.77-.27.2-.66.29-1.17.29-.22 0-.43-.02-.64-.08-.21-.05-.4-.13-.56-.24-.17-.11-.3-.26-.41-.44-.11-.18-.17-.41-.18-.67h-1.89c0 .36.08.71.24 1.05.16.34.39.65.7.93.31.27.69.49 1.15.66.46.17.98.25 1.58.25.53 0 1.01-.06 1.44-.19.43-.13.8-.31 1.11-.54.31-.23.54-.51.71-.83.17-.32.25-.67.25-1.06-.02-.4-.09-.74-.24-1.02zm-9.96-7.32c-.34-.4-.75-.7-1.23-.88-.47-.18-1.01-.27-1.59-.27-.58 0-1.11.09-1.59.27-.48.18-.89.47-1.23.88-.34.41-.6.93-.79 1.59-.18.65-.28 1.45-.28 2.39v1.92c0 .94.09 1.74.28 2.39.19.66.45 1.19.8 1.6.34.41.75.71 1.23.89.48.18 1.01.28 1.59.28.59 0 1.12-.09 1.59-.28.48-.18.88-.48 1.22-.89.34-.41.6-.94.78-1.6.18-.65.28-1.45.28-2.39v-1.92c0-.94-.09-1.74-.28-2.39-.18-.66-.44-1.19-.78-1.59zm-.92 6.17c0 .6-.04 1.11-.12 1.53-.08.42-.2.76-.36 1.02-.16.26-.36.45-.59.57-.23.12-.51.18-.82.18-.3 0-.58-.06-.82-.18s-.44-.31-.6-.57c-.16-.26-.29-.6-.38-1.02-.09-.42-.13-.93-.13-1.53v-2.5c0-.6.04-1.11.13-1.52.09-.41.21-.74.38-1 .16-.25.36-.43.6-.55.24-.11.51-.17.81-.17.31 0 .58.06.81.17.24.11.44.29.6.55.16.25.29.58.37.99.08.41.13.92.13 1.52v2.51z"/></g> +<g id="timer-3"><path d="M11.61 12.97c-.16-.24-.36-.46-.62-.65-.25-.19-.56-.35-.93-.48.3-.14.57-.3.8-.5.23-.2.42-.41.57-.64.15-.23.27-.46.34-.71.08-.24.11-.49.11-.73 0-.55-.09-1.04-.28-1.46-.18-.42-.44-.77-.78-1.06-.33-.28-.73-.5-1.2-.64-.45-.13-.97-.2-1.53-.2-.55 0-1.06.08-1.52.24-.47.17-.87.4-1.2.69-.33.29-.6.63-.78 1.03-.2.39-.29.83-.29 1.29h1.98c0-.26.05-.49.14-.69.09-.2.22-.38.38-.52.17-.14.36-.25.58-.33.22-.08.46-.12.73-.12.61 0 1.06.16 1.36.47.3.31.44.75.44 1.32 0 .27-.04.52-.12.74-.08.22-.21.41-.38.57-.17.16-.38.28-.63.37-.25.09-.55.13-.89.13H6.72v1.57H7.9c.34 0 .64.04.91.11.27.08.5.19.69.35.19.16.34.36.44.61.1.24.16.54.16.87 0 .62-.18 1.09-.53 1.42-.35.33-.84.49-1.45.49-.29 0-.56-.04-.8-.13-.24-.08-.44-.2-.61-.36-.17-.16-.3-.34-.39-.56-.09-.22-.14-.46-.14-.72H4.19c0 .55.11 1.03.32 1.45.21.42.5.77.86 1.05s.77.49 1.24.63.96.21 1.48.21c.57 0 1.09-.08 1.58-.23.49-.15.91-.38 1.26-.68.36-.3.64-.66.84-1.1.2-.43.3-.93.3-1.48 0-.29-.04-.58-.11-.86-.08-.25-.19-.51-.35-.76zm9.26 1.4c-.14-.28-.35-.53-.63-.74-.28-.21-.61-.39-1.01-.53s-.85-.27-1.35-.38c-.35-.07-.64-.15-.87-.23-.23-.08-.41-.16-.55-.25-.14-.09-.23-.19-.28-.3-.05-.11-.08-.24-.08-.39s.03-.28.09-.41c.06-.13.15-.25.27-.34.12-.1.27-.18.45-.24s.4-.09.64-.09c.25 0 .47.04.66.11.19.07.35.17.48.29.13.12.22.26.29.42.06.16.1.32.1.49h1.95c0-.39-.08-.75-.24-1.09-.16-.34-.39-.63-.69-.88-.3-.25-.66-.44-1.09-.59-.43-.15-.92-.22-1.46-.22-.51 0-.98.07-1.39.21-.41.14-.77.33-1.06.57-.29.24-.51.52-.67.84-.16.32-.23.65-.23 1.01s.08.68.23.96c.15.28.37.52.64.73.27.21.6.38.98.53.38.14.81.26 1.27.36.39.08.71.17.95.26s.43.19.57.29c.13.1.22.22.27.34.05.12.07.25.07.39 0 .32-.13.57-.4.77-.27.2-.66.29-1.17.29-.22 0-.43-.02-.64-.08-.21-.05-.4-.13-.56-.24-.17-.11-.3-.26-.41-.44-.11-.18-.17-.41-.18-.67h-1.89c0 .36.08.71.24 1.05.16.34.39.65.7.93.31.27.69.49 1.15.66.46.17.98.25 1.58.25.53 0 1.01-.06 1.44-.19.43-.13.8-.31 1.11-.54.31-.23.54-.51.71-.83.17-.32.25-.67.25-1.06-.02-.4-.09-.74-.24-1.02z"/></g> +<g id="timer-auto"><path d="M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 10c-2.67 0-8 1.34-8 4v2h16v-2c0-2.67-5.33-4-8-4z"/></g> +<g id="timer-off"><path d="M19.04 4.55l-1.42 1.42C16.07 4.74 14.12 4 12 4c-1.83 0-3.53.55-4.95 1.48l1.46 1.46C9.53 6.35 10.73 6 12 6c3.87 0 7 3.13 7 7 0 1.27-.35 2.47-.94 3.49l1.45 1.45C20.45 16.53 21 14.83 21 13c0-2.12-.74-4.07-1.97-5.61l1.42-1.42-1.41-1.42zM15 1H9v2h6V1zm-4 8.44l2 2V8h-2v1.44zM3.02 4L1.75 5.27 4.5 8.03C3.55 9.45 3 11.16 3 13c0 4.97 4.02 9 9 9 1.84 0 3.55-.55 4.98-1.5l2.5 2.5 1.27-1.27-7.71-7.71L3.02 4zM12 20c-3.87 0-7-3.13-7-7 0-1.28.35-2.48.95-3.52l9.56 9.56c-1.03.61-2.23.96-3.51.96z"/></g> +<g id="tonality"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.94-.49-7-3.85-7-7.93s3.05-7.44 7-7.93v15.86zm2-15.86c1.03.13 2 .45 2.87.93H13v-.93zM13 7h5.24c.25.31.48.65.68 1H13V7zm0 3h6.74c.08.33.15.66.19 1H13v-1zm0 9.93V19h2.87c-.87.48-1.84.8-2.87.93zM18.24 17H13v-1h5.92c-.2.35-.43.69-.68 1zm1.5-3H13v-1h6.93c-.04.34-.11.67-.19 1z"/></g> +<g id="transform"><path d="M22 18v-2H8V4h2L7 1 4 4h2v2H2v2h4v8c0 1.1.9 2 2 2h8v2h-2l3 3 3-3h-2v-2h4zM10 8h6v6h2V8c0-1.1-.9-2-2-2h-6v2z"/></g> +<g id="tune"><path d="M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z"/></g> +<g id="wb-auto"><path d="M6.85 12.65h2.3L8 9l-1.15 3.65zM22 7l-1.2 6.29L19.3 7h-1.6l-1.49 6.29L15 7h-.76C12.77 5.17 10.53 4 8 4c-4.42 0-8 3.58-8 8s3.58 8 8 8c3.13 0 5.84-1.81 7.15-4.43l.1.43H17l1.5-6.1L20 16h1.75l2.05-9H22zm-11.7 9l-.7-2H6.4l-.7 2H3.8L7 7h2l3.2 9h-1.9z"/></g> +<g id="wb-cloudy"><path d="M19.36 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.64-4.96z"/></g> +<g id="wb-incandescent"><path d="M3.55 18.54l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8zM11 22.45h2V19.5h-2v2.95zM4 10.5H1v2h3v-2zm11-4.19V1.5H9v4.81C7.21 7.35 6 9.28 6 11.5c0 3.31 2.69 6 6 6s6-2.69 6-6c0-2.22-1.21-4.15-3-5.19zm5 4.19v2h3v-2h-3zm-2.76 7.66l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4z"/></g> +<g id="wb-irradescent"><path d="M5 14.5h14v-6H5v6zM11 .55V3.5h2V.55h-2zm8.04 2.5l-1.79 1.79 1.41 1.41 1.8-1.79-1.42-1.41zM13 22.45V19.5h-2v2.95h2zm7.45-3.91l-1.8-1.79-1.41 1.41 1.79 1.8 1.42-1.42zM3.55 4.46l1.79 1.79 1.41-1.41-1.79-1.79-1.41 1.41zm1.41 15.49l1.79-1.8-1.41-1.41-1.79 1.79 1.41 1.42z"/></g> +<g id="wb-sunny"><path d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/index.html b/third_party/polymer/v0_8/components-chromium/iron-icons/index.html new file mode 100644 index 0000000..95d1991 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-component-page/iron-component-page.html"> + +</head> +<body> + + <iron-component-page></iron-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/iron-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/iron-icons.html new file mode 100644 index 0000000..6134d5b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/iron-icons.html
@@ -0,0 +1,278 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- + +`iron-icons` is a utitliy import that includes the definition for the `iron-icon` element, `iron-iconset-svg` element, as well as an import for the default icon set. + +The `iron-icons` directory also includes imports for additional icon sets that can be loaded into your project. + +Example loading icon set: + + <link rel="import" href="../iron-icons/maps-icons.html"> + +To use an icon from one of these sets, first prefix your `iron-icon` with the icon set name, followed by a colon, ":", and then the icon id. + +Example using the directions-bus icon from the maps icon set: + + <iron-icon icon="maps:directions-bus"></iron-icon> + + +See [iron-icon](#iron-icon) for more information about working with icons. + +See [iron-iconset](#iron-iconset) and [iron-iconset-svg](#iron-iconset-svg) for more information about how to create a custom iconset. + +@group Polymer Core Elements +@homepage polymer.github.io +--> +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="icons" size="24"> +<svg><defs> +<g id="3d-rotation"><path d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-3.81-3.81-1.33 1.32zm.89-6.52c-.19 0-.37-.03-.52-.08-.16-.06-.29-.13-.4-.24-.11-.1-.2-.22-.26-.37-.06-.14-.09-.3-.09-.47h-1.3c0 .36.07.68.21.95.14.27.33.5.56.69.24.18.51.32.82.41.3.1.62.15.96.15.37 0 .72-.05 1.03-.15.32-.1.6-.25.83-.44s.42-.43.55-.72c.13-.29.2-.61.2-.97 0-.19-.02-.38-.07-.56-.05-.18-.12-.35-.23-.51-.1-.16-.24-.3-.4-.43-.17-.13-.37-.23-.61-.31.2-.09.37-.2.52-.33.15-.13.27-.27.37-.42.1-.15.17-.3.22-.46.05-.16.07-.32.07-.48 0-.36-.06-.68-.18-.96-.12-.28-.29-.51-.51-.69-.2-.19-.47-.33-.77-.43C9.1 8.05 8.76 8 8.39 8c-.36 0-.69.05-1 .16-.3.11-.57.26-.79.45-.21.19-.38.41-.51.67-.12.26-.18.54-.18.85h1.3c0-.17.03-.32.09-.45s.14-.25.25-.34c.11-.09.23-.17.38-.22.15-.05.3-.08.48-.08.4 0 .7.1.89.31.19.2.29.49.29.86 0 .18-.03.34-.08.49-.05.15-.14.27-.25.37-.11.1-.25.18-.41.24-.16.06-.36.09-.58.09H7.5v1.03h.77c.22 0 .42.02.6.07s.33.13.45.23c.12.11.22.24.29.4.07.16.1.35.1.57 0 .41-.12.72-.35.93-.23.23-.55.33-.95.33zm8.55-5.92c-.32-.33-.7-.59-1.14-.77-.43-.18-.92-.27-1.46-.27H12v8h2.3c.55 0 1.06-.09 1.51-.27.45-.18.84-.43 1.16-.76.32-.33.57-.73.74-1.19.17-.47.26-.99.26-1.57v-.4c0-.58-.09-1.1-.26-1.57-.18-.47-.43-.87-.75-1.2zm-.39 3.16c0 .42-.05.79-.14 1.13-.1.33-.24.62-.43.85-.19.23-.43.41-.71.53-.29.12-.62.18-.99.18h-.91V9.12h.97c.72 0 1.27.23 1.64.69.38.46.57 1.12.57 1.99v.4zM12 0l-.66.03 3.81 3.81 1.33-1.33c3.27 1.55 5.61 4.72 5.96 8.48h1.5C23.44 4.84 18.29 0 12 0z"/></g> +<g id="accessibility"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"/></g> +<g id="account-balance"><path d="M4 10v7h3v-7H4zm6 0v7h3v-7h-3zM2 22h19v-3H2v3zm14-12v7h3v-7h-3zm-4.5-9L2 6v2h19V6l-9.5-5z"/></g> +<g id="account-balance-wallet"><path d="M21 18v1c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2-2V5c0-1.1.89-2 2-2h14c1.1 0 2 .9 2 2v1h-9c-1.11 0-2 .9-2 2v8c0 1.1.89 2 2 2h9zm-9-2h10V8H12v8zm4-2.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="account-box"><path d="M3 5v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2H5c-1.11 0-2 .9-2 2zm12 4c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34 3 3zm-9 8c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6v-1z"/></g> +<g id="account-child"><circle cx="12" cy="13.49" r="1.5"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 2.5c1.24 0 2.25 1.01 2.25 2.25S13.24 9 12 9 9.75 7.99 9.75 6.75 10.76 4.5 12 4.5zm5 10.56v2.5c-.45.41-.96.77-1.5 1.05v-.68c0-.34-.17-.65-.46-.92-.65-.62-1.89-1.02-3.04-1.02-.96 0-1.96.28-2.65.73l-.17.12-.21.17c.78.47 1.63.72 2.54.82l1.33.15c.37.04.66.36.66.75 0 .29-.16.53-.4.66-.28.15-.64.09-.95.09-.35 0-.69-.01-1.03-.05-.5-.06-.99-.17-1.46-.33-.49-.16-.97-.38-1.42-.64-.22-.13-.44-.27-.65-.43l-.31-.24c-.04-.02-.28-.18-.28-.23v-4.28c0-1.58 2.63-2.78 5-2.78s5 1.2 5 2.78v1.78z"/></g> +<g id="account-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/></g> +<g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></g> +<g id="add-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/></g> +<g id="add-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/></g> +<g id="add-circle-outline"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="add-shopping-cart"><path d="M11 9h2V6h3V4h-3V1h-2v3H8v2h3v3zm-4 9c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2zm-9.83-3.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.86-7.01L19.42 4h-.01l-1.1 2-2.76 5H8.53l-.13-.27L6.16 6l-.95-2-.94-2H1v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.13 0-.25-.11-.25-.25z"/></g> +<g id="alarm"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="alarm-add"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm1-11h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g> +<g id="alarm-off"><path d="M12 6c3.87 0 7 3.13 7 7 0 .84-.16 1.65-.43 2.4l1.52 1.52c.58-1.19.91-2.51.91-3.92 0-4.97-4.03-9-9-9-1.41 0-2.73.33-3.92.91L9.6 6.43C10.35 6.16 11.16 6 12 6zm10-.28l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM2.92 2.29L1.65 3.57 2.98 4.9l-1.11.93 1.42 1.42 1.11-.94.8.8C3.83 8.69 3 10.75 3 13c0 4.97 4.02 9 9 9 2.25 0 4.31-.83 5.89-2.2l2.2 2.2 1.27-1.27L3.89 3.27l-.97-.98zm13.55 16.1C15.26 19.39 13.7 20 12 20c-3.87 0-7-3.13-7-7 0-1.7.61-3.26 1.61-4.47l9.86 9.86zM8.02 3.28L6.6 1.86l-.86.71 1.42 1.42.86-.71z"/></g> +<g id="alarm-on"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm-1.46-5.47L8.41 12.4l-1.06 1.06 3.18 3.18 6-6-1.06-1.06-4.93 4.95z"/></g> +<g id="android"><path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-.71 0-.2.2-.2.51 0 .71l1.31 1.31C6.97 3.26 6 5.01 6 7h12c0-1.99-.97-3.75-2.47-4.84zM10 5H9V4h1v1zm5 0h-1V4h1v1z"/></g> +<g id="announcement"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 9h-2V5h2v6zm0 4h-2v-2h2v2z"/></g> +<g id="apps"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"/></g> +<g id="archive"><path d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z"/></g> +<g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></g> +<g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"/></g> +<g id="arrow-drop-down-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 12l-4-4h8l-4 4z"/></g> +<g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"/></g> +<g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"/></g> +<g id="aspect-ratio"><path d="M19 12h-2v3h-3v2h5v-5zM7 9h3V7H5v5h2V9zm14-6H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"/></g> +<g id="assessment"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/></g> +<g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/></g> +<g id="assignment-ind"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 4c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1.4c0-2 4-3.1 6-3.1s6 1.1 6 3.1V19z"/></g> +<g id="assignment-late"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-6 15h-2v-2h2v2zm0-4h-2V8h2v6zm-1-9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></g> +<g id="assignment-return"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm4 12h-4v3l-5-5 5-5v3h4v4z"/></g> +<g id="assignment-returned"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 15l-5-5h3V9h4v4h3l-5 5z"/></g> +<g id="assignment-turned-in"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-2 14l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"/></g> +<g id="attachment"><path d="M7.5 18C4.46 18 2 15.54 2 12.5S4.46 7 7.5 7H18c2.21 0 4 1.79 4 4s-1.79 4-4 4H9.5C8.12 15 7 13.88 7 12.5S8.12 10 9.5 10H17v1.5H9.5c-.55 0-1 .45-1 1s.45 1 1 1H18c1.38 0 2.5-1.12 2.5-2.5S19.38 8.5 18 8.5H7.5c-2.21 0-4 1.79-4 4s1.79 4 4 4H17V18H7.5z"/></g> +<g id="autorenew"><path d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z"/></g> +<g id="backspace"><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.9.89 1.59.89h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z"/></g> +<g id="backup"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/></g> +<g id="block"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z"/></g> +<g id="book"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"/></g> +<g id="bookmark"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></g> +<g id="bookmark-outline"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"/></g> +<g id="bug-report"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></g> +<g id="cached"><path d="M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1.46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6 6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l4 4 4-4H6z"/></g> +<g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/></g> +<g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></g> +<g id="check-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></g> +<g id="check-box-outline-blank"><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></g> +<g id="check-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></g> +<g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></g> +<g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></g> +<g id="class"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"/></g> +<g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></g> +<g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></g> +<g id="cloud"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"/></g> +<g id="cloud-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.5 14H8c-1.66 0-3-1.34-3-3s1.34-3 3-3l.14.01C8.58 8.28 10.13 7 12 7c2.21 0 4 1.79 4 4h.5c1.38 0 2.5 1.12 2.5 2.5S17.88 16 16.5 16z"/></g> +<g id="cloud-done"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM10 17l-3.5-3.5 1.41-1.41L10 14.17 15.18 9l1.41 1.41L10 17z"/></g> +<g id="cloud-download"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"/></g> +<g id="cloud-off"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4c-1.48 0-2.85.43-4.01 1.17l1.46 1.46C10.21 6.23 11.08 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.64-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1.73z"/></g> +<g id="cloud-queue"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z"/></g> +<g id="cloud-upload"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/></g> +<g id="content-copy"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></g> +<g id="content-cut"><path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z"/></g> +<g id="content-paste"><path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"/></g> +<g id="create"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></g> +<g id="credit-card"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"/></g> +<g id="dashboard"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"/></g> +<g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></g> +<g id="description"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></g> +<g id="dns"><path d="M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zM7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM20 3H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zM7 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="done"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></g> +<g id="done-all"><path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L11.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41L1.83 12 .41 13.41z"/></g> +<g id="drafts"><path d="M21.99 8c0-.72-.37-1.35-.94-1.7L12 1 2.95 6.3C2.38 6.65 2 7.28 2 8v10c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2l-.01-10zM12 13L3.74 7.84 12 3l8.26 4.84L12 13z"/></g> +<g id="error"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></g> +<g id="event"><path d="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"/></g> +<g id="exit-to-app"><path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></g> +<g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"/></g> +<g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"/></g> +<g id="explore"><path d="M12 10.9c-.61 0-1.1.49-1.1 1.1s.49 1.1 1.1 1.1c.61 0 1.1-.49 1.1-1.1s-.49-1.1-1.1-1.1zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm2.19 12.19L6 18l3.81-8.19L18 6l-3.81 8.19z"/></g> +<g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"/></g> +<g id="face"><path d="M14.69 17.1c-.74.58-1.7.9-2.69.9s-1.95-.32-2.69-.9c-.22-.17-.53-.13-.7.09-.17.22-.13.53.09.7.91.72 2.09 1.11 3.3 1.11s2.39-.39 3.31-1.1c.22-.17.26-.48.09-.7-.17-.23-.49-.26-.71-.1z"/><circle cx="8.5" cy="12.5" r="1"/><path d="M12 0C5.37 0 0 5.37 0 12s5.37 12 12 12 12-5.37 12-12S18.63 0 12 0zm7.96 14.82c-1.09 3.74-4.27 6.46-8.04 6.46-3.78 0-6.96-2.72-8.04-6.47-1.19-.11-2.13-1.18-2.13-2.52 0-1.27.85-2.31 1.97-2.5 2.09-1.46 3.8-3.49 4.09-5.05v-.01c1.35 2.63 6.3 5.19 11.83 5.06l.3-.03c1.28 0 2.31 1.14 2.31 2.54 0 1.38-1.02 2.51-2.29 2.52z"/><circle cx="15.5" cy="12.5" r="1"/></g> +<g id="favorite"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></g> +<g id="favorite-outline"><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"/></g> +<g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></g> +<g id="file-upload"><path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/></g> +<g id="filter-list"><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/></g> +<g id="find-in-page"><path d="M20 19.59V8l-6-6H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c.45 0 .85-.15 1.19-.4l-4.43-4.43c-.8.52-1.74.83-2.76.83-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-.31 1.96-.83 2.75L20 19.59zM9 13c0 1.66 1.34 3 3 3s3-1.34 3-3-1.34-3-3-3-3 1.34-3 3z"/></g> +<g id="find-replace"><path d="M11 6c1.38 0 2.63.56 3.54 1.46L12 10h6V4l-2.05 2.05C14.68 4.78 12.93 4 11 4c-3.53 0-6.43 2.61-6.92 6H6.1c.46-2.28 2.48-4 4.9-4zm5.64 9.14c.66-.9 1.12-1.97 1.28-3.14H15.9c-.46 2.28-2.48 4-4.9 4-1.38 0-2.63-.56-3.54-1.46L10 12H4v6l2.05-2.05C7.32 17.22 9.07 18 11 18c1.55 0 2.98-.51 4.14-1.36L20 21.49 21.49 20l-4.85-4.86z"/></g> +<g id="flag"><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/></g> +<g id="flip-to-back"><path d="M9 7H7v2h2V7zm0 4H7v2h2v-2zm0-8c-1.11 0-2 .9-2 2h2V3zm4 12h-2v2h2v-2zm6-12v2h2c0-1.1-.9-2-2-2zm-6 0h-2v2h2V3zM9 17v-2H7c0 1.1.89 2 2 2zm10-4h2v-2h-2v2zm0-4h2V7h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zM5 7H3v12c0 1.1.89 2 2 2h12v-2H5V7zm10-2h2V3h-2v2zm0 12h2v-2h-2v2z"/></g> +<g id="flip-to-front"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3c0 1.1.89 2 2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9c-1.11 0-2 .9-2 2v10c0 1.1.89 2 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z"/></g> +<g id="folder"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></g> +<g id="folder-open"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"/></g> +<g id="folder-shared"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-5 3c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm4 8h-8v-1c0-1.33 2.67-2 4-2s4 .67 4 2v1z"/></g> +<g id="forward"><path d="M12 8V4l8 8-8 8v-4H4V8z"/></g> +<g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></g> +<g id="fullscreen-exit"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/></g> +<g id="gesture"><path d="M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52-.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1H21v-2.5h-2.47c-.15-1.65-1.09-4.2-4.03-4.2-2.25 0-4.18 1.91-4.94 2.84-.58.73-2.06 2.48-2.29 2.72-.25.3-.68.84-1.11.84-.45 0-.72-.83-.36-1.92.35-1.09 1.4-2.86 1.85-3.52.78-1.14 1.3-1.92 1.3-3.28C8.95 3.69 7.31 3 6.44 3 5.12 3 3.97 4 3.72 4.25c-.36.36-.66.66-.88.93l1.75 1.71zm9.29 11.66c-.31 0-.74-.26-.74-.72 0-.6.73-2.2 2.87-2.76-.3 2.69-1.43 3.48-2.13 3.48z"/></g> +<g id="get-app"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></g> +<g id="grade"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></g> +<g id="group-work"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM8 17.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5zM9.5 8c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5S9.5 9.38 9.5 8zm6.5 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></g> +<g id="help"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"/></g> +<g id="highlight-remove"><path d="M14.59 8L12 10.59 9.41 8 8 9.41 10.59 12 8 14.59 9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41 14.59 8zM12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="history"><path opacity=".9" d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/></g> +<g id="home"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></g> +<g id="https"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/></g> +<g id="inbox"><path d="M19 3H4.99c-1.1 0-1.98.9-1.98 2L3 19c0 1.1.89 2 1.99 2H19c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12h-4c0 1.66-1.34 3-3 3s-3-1.34-3-3H4.99V5H19v10zm-3-5h-2V7h-4v3H8l4 4 4-4z"/></g> +<g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></g> +<g id="info-outline"><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"/></g> +<g id="input"><path d="M21 3.01H3c-1.1 0-2 .9-2 2V9h2V4.99h18v14.03H3V15H1v4.01c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98v-14c0-1.11-.9-2-2-2zM11 16l4-4-4-4v3H1v2h10v3z"/></g> +<g id="invert-colors"><path d="M17.66 7.93L12 2.27 6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58c2.05 0 4.1-.78 5.66-2.34 3.12-3.12 3.12-8.19 0-11.31zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"/></g> +<g id="label"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></g> +<g id="label-outline"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></g> +<g id="language"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"/></g> +<g id="launch"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></g> +<g id="link"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></g> +<g id="list"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/></g> +<g id="lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/></g> +<g id="lock-open"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm0 12H6V10h12v10z"/></g> +<g id="lock-outline"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6-5.1c1.71 0 3.1 1.39 3.1 3.1v2H9V6h-.1c0-1.71 1.39-3.1 3.1-3.1zM18 20H6V10h12v10zm-6-3c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/></g> +<g id="loyalty"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7zm11.77 8.27L13 19.54l-4.27-4.27C8.28 14.81 8 14.19 8 13.5c0-1.38 1.12-2.5 2.5-2.5.69 0 1.32.28 1.77.74l.73.72.73-.73c.45-.45 1.08-.73 1.77-.73 1.38 0 2.5 1.12 2.5 2.5 0 .69-.28 1.32-.73 1.77z"/></g> +<g id="mail"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></g> +<g id="markunread"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></g> +<g id="markunread-mailbox"><path d="M20 6H10v6H8V4h6V0H6v6H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2z"/></g> +<g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></g> +<g id="more-horiz"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="note-add"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 14h-3v3h-2v-3H8v-2h3v-3h2v3h3v2zm-3-7V3.5L18.5 9H13z"/></g> +<g id="open-in-browser"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z"/></g> +<g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></g> +<g id="open-with"><path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"/></g> +<g id="pageview"><path d="M11 8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm8-5H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1.41 16l-3.83-3.83c-.8.52-1.74.83-2.76.83-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-.31 1.96-.83 2.75L19 17.59 17.59 19z"/></g> +<g id="payment"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"/></g> +<g id="perm-camera-mic"><path d="M20 5h-3.17L15 3H9L7.17 5H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7v-2.09c-2.83-.48-5-2.94-5-5.91h2c0 2.21 1.79 4 4 4s4-1.79 4-4h2c0 2.97-2.17 5.43-5 5.91V21h7c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-6 8c0 1.1-.9 2-2 2s-2-.9-2-2V9c0-1.1.9-2 2-2s2 .9 2 2v4z"/></g> +<g id="perm-contact-cal"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1z"/></g> +<g id="perm-data-setting"><path d="M18.99 11.5c.34 0 .67.03 1 .07L20 0 0 20h11.56c-.04-.33-.07-.66-.07-1 0-4.14 3.36-7.5 7.5-7.5zm3.71 7.99c.02-.16.04-.32.04-.49 0-.17-.01-.33-.04-.49l1.06-.83c.09-.08.12-.21.06-.32l-1-1.73c-.06-.11-.19-.15-.31-.11l-1.24.5c-.26-.2-.54-.37-.85-.49l-.19-1.32c-.01-.12-.12-.21-.24-.21h-2c-.12 0-.23.09-.25.21l-.19 1.32c-.3.13-.59.29-.85.49l-1.24-.5c-.11-.04-.24 0-.31.11l-1 1.73c-.06.11-.04.24.06.32l1.06.83c-.02.16-.03.32-.03.49 0 .17.01.33.03.49l-1.06.83c-.09.08-.12.21-.06.32l1 1.73c.06.11.19.15.31.11l1.24-.5c.26.2.54.37.85.49l.19 1.32c.02.12.12.21.25.21h2c.12 0 .23-.09.25-.21l.19-1.32c.3-.13.59-.29.84-.49l1.25.5c.11.04.24 0 .31-.11l1-1.73c.06-.11.03-.24-.06-.32l-1.07-.83zm-3.71 1.01c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="perm-device-info"><path d="M13 7h-2v2h2V7zm0 4h-2v6h2v-6zm4-9.99L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></g> +<g id="perm-identity"><path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"/></g> +<g id="perm-media"><path d="M2 6H0v5h.01L0 20c0 1.1.9 2 2 2h18v-2H2V6zm20-2h-8l-2-2H6c-1.1 0-1.99.9-1.99 2L4 16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM7 15l4.5-6 3.5 4.51 2.5-3.01L21 15H7z"/></g> +<g id="perm-phone-msg"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM12 3v10l3-3h6V3h-9z"/></g> +<g id="perm-scan-wifi"><path d="M12 3C6.95 3 3.15 4.85 0 7.23L12 22 24 7.25C20.85 4.87 17.05 3 12 3zm1 13h-2v-6h2v6zm-2-8V6h2v2h-2z"/></g> +<g id="picture-in-picture"><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z"/></g> +<g id="polymer"><path d="M19 4h-4L7.11 16.63 4.5 12 9 4H5L.5 12 5 20h4l7.89-12.63L19.5 12 15 20h4l4.5-8z"/></g> +<g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></g> +<g id="query-builder"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zM12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></g> +<g id="question-answer"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"/></g> +<g id="radio-button-off"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></g> +<g id="radio-button-on"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></g> +<g id="receipt"><path d="M18 17H6v-2h12v2zm0-4H6v-2h12v2zm0-4H6V7h12v2zM3 22l1.5-1.5L6 22l1.5-1.5L9 22l1.5-1.5L12 22l1.5-1.5L15 22l1.5-1.5L18 22l1.5-1.5L21 22V2l-1.5 1.5L18 2l-1.5 1.5L15 2l-1.5 1.5L12 2l-1.5 1.5L9 2 7.5 3.5 6 2 4.5 3.5 3 2v20z"/></g> +<g id="redeem"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"/></g> +<g id="redo"><path d="M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z"/></g> +<g id="refresh"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></g> +<g id="remove"><path d="M19 13H5v-2h14v2z"/></g> +<g id="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11H7v-2h10v2z"/></g> +<g id="remove-circle-outline"><path d="M7 11v2h10v-2H7zm5-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="reorder"><path d="M3 15h18v-2H3v2zm0 4h18v-2H3v2zm0-8h18V9H3v2zm0-6v2h18V5H3z"/></g> +<g id="reply"><path d="M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"/></g> +<g id="reply-all"><path d="M7 8V5l-7 7 7 7v-3l-4-4 4-4zm6 1V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"/></g> +<g id="report"><path d="M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.73 3zM12 17.3c-.72 0-1.3-.58-1.3-1.3 0-.72.58-1.3 1.3-1.3.72 0 1.3.58 1.3 1.3 0 .72-.58 1.3-1.3 1.3zm1-4.3h-2V7h2v6z"/></g> +<g id="report-problem"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></g> +<g id="restore"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/></g> +<g id="room"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></g> +<g id="save"><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></g> +<g id="schedule"><path fill-opacity=".9" d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zM12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></g> +<g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></g> +<g id="select-all"><path d="M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm2-8h6v6H9V9z"/></g> +<g id="send"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></g> +<g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></g> +<g id="settings-applications"><path d="M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm7-7H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-1.75 9c0 .23-.02.46-.05.68l1.48 1.16c.13.11.17.3.08.45l-1.4 2.42c-.09.15-.27.21-.43.15l-1.74-.7c-.36.28-.76.51-1.18.69l-.26 1.85c-.03.17-.18.3-.35.3h-2.8c-.17 0-.32-.13-.35-.29l-.26-1.85c-.43-.18-.82-.41-1.18-.69l-1.74.7c-.16.06-.34 0-.43-.15l-1.4-2.42c-.09-.15-.05-.34.08-.45l1.48-1.16c-.03-.23-.05-.46-.05-.69 0-.23.02-.46.05-.68l-1.48-1.16c-.13-.11-.17-.3-.08-.45l1.4-2.42c.09-.15.27-.21.43-.15l1.74.7c.36-.28.76-.51 1.18-.69l.26-1.85c.03-.17.18-.3.35-.3h2.8c.17 0 .32.13.35.29l.26 1.85c.43.18.82.41 1.18.69l1.74-.7c.16-.06.34 0 .43.15l1.4 2.42c.09.15.05.34-.08.45l-1.48 1.16c.03.23.05.46.05.69z"/></g> +<g id="settings-backup-restore"><path d="M14 12c0-1.1-.9-2-2-2s-2 .9-2 2 .9 2 2 2 2-.9 2-2zm-2-9c-4.97 0-9 4.03-9 9H0l4 4 4-4H5c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.51 0-2.91-.49-4.06-1.3l-1.42 1.44C8.04 20.3 9.94 21 12 21c4.97 0 9-4.03 9-9s-4.03-9-9-9z"/></g> +<g id="settings-bluetooth"><path d="M11 24h2v-2h-2v2zm-4 0h2v-2H7v2zm8 0h2v-2h-2v2zm2.71-18.29L12 0h-1v7.59L6.41 3 5 4.41 10.59 10 5 15.59 6.41 17 11 12.41V20h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 3.83l1.88 1.88L13 7.59V3.83zm1.88 10.46L13 16.17v-3.76l1.88 1.88z"/></g> +<g id="settings-cell"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM16 .01L8 0C6.9 0 6 .9 6 2v16c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V2c0-1.1-.9-1.99-2-1.99zM16 16H8V4h8v12z"/></g> +<g id="settings-display"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02zM8 16h2.5l1.5 1.5 1.5-1.5H16v-2.5l1.5-1.5-1.5-1.5V8h-2.5L12 6.5 10.5 8H8v2.5L6.5 12 8 13.5V16zm4-7c1.66 0 3 1.34 3 3s-1.34 3-3 3V9z"/></g> +<g id="settings-ethernet"><path d="M7.77 6.76L6.23 5.48.82 12l5.41 6.52 1.54-1.28L3.42 12l4.35-5.24zM7 13h2v-2H7v2zm10-2h-2v2h2v-2zm-6 2h2v-2h-2v2zm6.77-7.52l-1.54 1.28L20.58 12l-4.35 5.24 1.54 1.28L23.18 12l-5.41-6.52z"/></g> +<g id="settings-input-antenna"><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5 5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.12-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3 3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9h2c0-6.07-4.93-11-11-11z"/></g> +<g id="settings-input-component"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"/></g> +<g id="settings-input-composite"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"/></g> +<g id="settings-input-hdmi"><path d="M18 7V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v3H5v6l3 6v3h8v-3l3-6V7h-1zM8 4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"/></g> +<g id="settings-input-svideo"><path d="M8 11.5c0-.83-.67-1.5-1.5-1.5S5 10.67 5 11.5 5.67 13 6.5 13 8 12.33 8 11.5zm7-5c0-.83-.67-1.5-1.5-1.5h-3C9.67 5 9 5.67 9 6.5S9.67 8 10.5 8h3c.83 0 1.5-.67 1.5-1.5zM8.5 15c-.83 0-1.5.67-1.5 1.5S7.67 18 8.5 18s1.5-.67 1.5-1.5S9.33 15 8.5 15zM12 1C5.93 1 1 5.93 1 12s4.93 11 11 11 11-4.93 11-11S18.07 1 12 1zm0 20c-4.96 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 9zm5.5-11c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm-2 5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"/></g> +<g id="settings-overscan"><path d="M12.01 5.5L10 8h4l-1.99-2.5zM18 10v4l2.5-1.99L18 10zM6 10l-2.5 2.01L6 14v-4zm8 6h-4l2.01 2.5L14 16zm7-13H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"/></g> +<g id="settings-phone"><path d="M13 9h-2v2h2V9zm4 0h-2v2h2V9zm3 6.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 9v2h2V9h-2z"/></g> +<g id="settings-power"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm2-22h-2v10h2V2zm3.56 2.44l-1.45 1.45C16.84 6.94 18 8.83 18 11c0 3.31-2.69 6-6 6s-6-2.69-6-6c0-2.17 1.16-4.06 2.88-5.12L7.44 4.44C5.36 5.88 4 8.28 4 11c0 4.42 3.58 8 8 8s8-3.58 8-8c0-2.72-1.36-5.12-3.44-6.56zM15 24h2v-2h-2v2z"/></g> +<g id="settings-remote"><path d="M15 9H9c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V10c0-.55-.45-1-1-1zm-3 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM7.05 6.05l1.41 1.41C9.37 6.56 10.62 6 12 6s2.63.56 3.54 1.46l1.41-1.41C15.68 4.78 13.93 4 12 4s-3.68.78-4.95 2.05zM12 0C8.96 0 6.21 1.23 4.22 3.22l1.41 1.41C7.26 3.01 9.51 2 12 2s4.74 1.01 6.36 2.64l1.41-1.41C17.79 1.23 15.04 0 12 0z"/></g> +<g id="settings-voice"><path d="M7 24h2v-2H7v2zm5-11c1.66 0 2.99-1.34 2.99-3L15 4c0-1.66-1.34-3-3-3S9 2.34 9 4v6c0 1.66 1.34 3 3 3zm-1 11h2v-2h-2v2zm4 0h2v-2h-2v2zm4-14h-1.7c0 3-2.54 5.1-5.3 5.1S6.7 13 6.7 10H5c0 3.41 2.72 6.23 6 6.72V20h2v-3.28c3.28-.49 6-3.31 6-6.72z"/></g> +<g id="shop"><path d="M16 6V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H2v13c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6h-6zm-6-2h4v2h-4V4zM9 18V9l7.5 4L9 18z"/></g> +<g id="shop-two"><path d="M3 9H1v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2H3V9zm15-4V3c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H5v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2V5h-5zm-6-2h4v2h-4V3zm0 12V8l5.5 3-5.5 4z"/></g> +<g id="shopping-basket"><path d="M17.21 9l-4.38-6.56c-.19-.28-.51-.42-.83-.42-.32 0-.64.14-.83.43L6.79 9H2c-.55 0-1 .45-1 1 0 .09.01.18.04.27l2.54 9.27c.23.84 1 1.46 1.92 1.46h13c.92 0 1.69-.62 1.93-1.46l2.54-9.27L23 10c0-.55-.45-1-1-1h-4.79zM9 9l3-4.4L15 9H9zm3 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="shopping-cart"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="sort"><path d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"/></g> +<g id="speaker-notes"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM8 14H6v-2h2v2zm0-3H6V9h2v2zm0-3H6V6h2v2zm7 6h-5v-2h5v2zm3-3h-8V9h8v2zm0-3h-8V6h8v2z"/></g> +<g id="spellcheck"><path d="M12.45 16h2.09L9.43 3H7.57L2.46 16h2.09l1.12-3h5.64l1.14 3zm-6.02-5L8.5 5.48 10.57 11H6.43zm15.16.59l-8.09 8.09L9.83 16l-1.41 1.41 5.09 5.09L23 13l-1.41-1.41z"/></g> +<g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></g> +<g id="star-half"><path d="M22 9.74l-7.19-.62L12 2.5 9.19 9.13 2 9.74l5.46 4.73-1.64 7.03L12 17.77l6.18 3.73-1.63-7.03L22 9.74zM12 15.9V6.6l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.9z"/></g> +<g id="star-outline"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"/></g> +<g id="star-rate"><path d="M12 14.3l3.71 2.7-1.42-4.36L18 10h-4.55L12 5.5 10.55 10H6l3.71 2.64L8.29 17z"/></g> +<g id="stars"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm4.24 16L12 15.45 7.77 18l1.12-4.81-3.73-3.23 4.92-.42L12 5l1.92 4.53 4.92.42-3.73 3.23L16.23 18z"/></g> +<g id="store"><path d="M20 4H4v2h16V4zm1 10v-2l-1-5H4l-1 5v2h1v6h10v-6h4v6h2v-6h1zm-9 4H6v-4h6v4z"/></g> +<g id="subject"><path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h16V5H4z"/></g> +<g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 16.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.66 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"/></g> +<g id="swap-horiz"><path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"/></g> +<g id="swap-vert"><path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3V14h2V6.99h3L9 3z"/></g> +<g id="swap-vert-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM6.5 9L10 5.5 13.5 9H11v4H9V9H6.5zm11 6L14 18.5 10.5 15H13v-4h2v4h2.5z"/></g> +<g id="system-update-tv"><path d="M12 16.5l4-4h-3v-9h-2v9H8l4 4zm9-13h-6v1.99h6v14.03H3V5.49h6V3.5H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2z"/></g> +<g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"/></g> +<g id="tab-unselected"><path d="M1 9h2V7H1v2zm0 4h2v-2H1v2zm0-8h2V3c-1.1 0-2 .9-2 2zm8 16h2v-2H9v2zm-8-4h2v-2H1v2zm2 4v-2H1c0 1.1.9 2 2 2zM21 3h-8v6h10V5c0-1.1-.9-2-2-2zm0 14h2v-2h-2v2zM9 5h2V3H9v2zM5 21h2v-2H5v2zM5 5h2V3H5v2zm16 16c1.1 0 2-.9 2-2h-2v2zm0-8h2v-2h-2v2zm-8 8h2v-2h-2v2zm4 0h2v-2h-2v2z"/></g> +<g id="text-format"><path d="M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L6.5 15h2.1l.9-2.2zM12 5.98L13.87 11h-3.74L12 5.98z"/></g> +<g id="theaters"><path d="M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8 17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h2v2z"/></g> +<g id="thumb-down"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v1.91l.01.01L1 14c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></g> +<g id="thumb-up"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-1.91l-.01-.01L23 10z"/></g> +<g id="thumbs-up-down"><path d="M12 6c0-.55-.45-1-1-1H5.82l.66-3.18.02-.23c0-.31-.13-.59-.33-.8L5.38 0 .44 4.94C.17 5.21 0 5.59 0 6v6.5c0 .83.67 1.5 1.5 1.5h6.75c.62 0 1.15-.38 1.38-.91l2.26-5.29c.07-.17.11-.36.11-.55V6zm10.5 4h-6.75c-.62 0-1.15.38-1.38.91l-2.26 5.29c-.07.17-.11.36-.11.55V18c0 .55.45 1 1 1h5.18l-.66 3.18-.02.24c0 .31.13.59.33.8l.79.78 4.94-4.94c.27-.27.44-.65.44-1.06v-6.5c0-.83-.67-1.5-1.5-1.5z"/></g> +<g id="toc"><path d="M3 9h14V7H3v2zm0 4h14v-2H3v2zm0 4h14v-2H3v2zm16 0h2v-2h-2v2zm0-10v2h2V7h-2zm0 6h2v-2h-2v2z"/></g> +<g id="today"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/></g> +<g id="track-changes"><path fill="#231F20" d="M19.07 4.93l-1.41 1.41C19.1 7.79 20 9.79 20 12c0 4.42-3.58 8-8 8s-8-3.58-8-8c0-4.08 3.05-7.44 7-7.93v2.02C8.16 6.57 6 9.03 6 12c0 3.31 2.69 6 6 6s6-2.69 6-6c0-1.66-.67-3.16-1.76-4.24l-1.41 1.41C15.55 9.9 16 10.9 16 12c0 2.21-1.79 4-4 4s-4-1.79-4-4c0-1.86 1.28-3.41 3-3.86v2.14c-.6.35-1 .98-1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V2h-1C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10c0-2.76-1.12-5.26-2.93-7.07z"/></g> +<g id="translate"><path d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"/></g> +<g id="trending-down"><path d="M16 18l2.29-2.29-4.88-4.88-4 4L2 7.41 3.41 6l6 6 4-4 6.3 6.29L22 12v6z"/></g> +<g id="trending-neutral"><path d="M22 12l-4-4v3H3v2h15v3z"/></g> +<g id="trending-up"><path d="M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4 4 6.3-6.29L22 12V6z"/></g> +<g id="turned-in"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></g> +<g id="turned-in-not"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"/></g> +<g id="undo"><path d="M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z"/></g> +<g id="unfold-less"><path d="M7.41 18.59L8.83 20 12 16.83 15.17 20l1.41-1.41L12 14l-4.59 4.59zm9.18-13.18L15.17 4 12 7.17 8.83 4 7.41 5.41 12 10l4.59-4.59z"/></g> +<g id="unfold-more"><path d="M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12 5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z"/></g> +<g id="verified-user"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm-2 16l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"/></g> +<g id="view-agenda"><path d="M20 13H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zm0-10H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1z"/></g> +<g id="view-array"><path d="M4 18h3V5H4v13zM18 5v13h3V5h-3zM8 18h9V5H8v13z"/></g> +<g id="view-carousel"><path d="M7 19h10V4H7v15zm-5-2h4V6H2v11zM18 6v11h4V6h-4z"/></g> +<g id="view-column"><path d="M10 18h5V5h-5v13zm-6 0h5V5H4v13zM16 5v13h5V5h-5z"/></g> +<g id="view-day"><path d="M2 21h19v-3H2v3zM20 8H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zM2 3v3h19V3H2z"/></g> +<g id="view-headline"><path d="M4 15h17v-2H4v2zm0 4h17v-2H4v2zm0-8h17V9H4v2zm0-6v2h17V5H4z"/></g> +<g id="view-list"><path d="M4 14h4v-4H4v4zm0 5h4v-4H4v4zM4 9h4V5H4v4zm5 5h12v-4H9v4zm0 5h12v-4H9v4zM9 5v4h12V5H9z"/></g> +<g id="view-module"><path d="M4 11h5V5H4v6zm0 7h5v-6H4v6zm6 0h5v-6h-5v6zm6 0h5v-6h-5v6zm-6-7h5V5h-5v6zm6-6v6h5V5h-5z"/></g> +<g id="view-quilt"><path d="M10 18h5v-6h-5v6zm-6 0h5V5H4v13zm12 0h5v-6h-5v6zM10 5v6h11V5H10z"/></g> +<g id="view-stream"><path d="M4 18h17v-6H4v6zM4 5v6h17V5H4z"/></g> +<g id="view-week"><path d="M6 5H3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zm14 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zm-7 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1z"/></g> +<g id="visibility"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g> +<g id="visibility-off"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/></g> +<g id="wallet-giftcard"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"/></g> +<g id="wallet-membership"><path d="M20 2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h4v5l4-2 4 2v-5h4c1.11 0 2-.89 2-2V4c0-1.11-.89-2-2-2zm0 13H4v-2h16v2zm0-5H4V4h16v6z"/></g> +<g id="wallet-travel"><path d="M20 6h-3V4c0-1.11-.89-2-2-2H9c-1.11 0-2 .89-2 2v2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM9 4h6v2H9V4zm11 15H4v-2h16v2zm0-5H4V8h3v2h2V8h6v2h2V8h3v6z"/></g> +<g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></g> +<g id="work"><path d="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-6 0h-4V4h4v2z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/maps-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/maps-icons.html new file mode 100644 index 0000000..2fbbce3 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/maps-icons.html
@@ -0,0 +1,70 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="maps" size="24"> +<svg><defs> +<g id="beenhere"><path d="M19 1H5c-1.1 0-1.99.9-1.99 2L3 15.93c0 .69.35 1.3.88 1.66L12 23l8.11-5.41c.53-.36.88-.97.88-1.66L21 3c0-1.1-.9-2-2-2zm-9 15l-5-5 1.41-1.41L10 13.17l7.59-7.59L19 7l-9 9z"/></g> +<g id="directions"><path d="M21.71 11.29l-9-9c-.39-.39-1.02-.39-1.41 0l-9 9c-.39.39-.39 1.02 0 1.41l9 9c.39.39 1.02.39 1.41 0l9-9c.39-.38.39-1.01 0-1.41zM14 14.5V12h-4v3H8v-4c0-.55.45-1 1-1h5V7.5l3.5 3.5-3.5 3.5z"/></g> +<g id="directions-bike"><path d="M16 4.8c.99 0 1.8-.81 1.8-1.8s-.81-1.8-1.8-1.8c-1 0-1.8.81-1.8 1.8S15 4.8 16 4.8zm3 7.2c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0 8.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5zM14.8 10H19V8.2h-3.2l-1.93-3.27c-.3-.5-.84-.83-1.46-.83-.47 0-.89.19-1.2.5l-3.7 3.7c-.32.3-.51.73-.51 1.2 0 .63.33 1.16.85 1.47L11.2 13v5H13v-6.48l-2.25-1.67 2.32-2.33L14.8 10zM5 12c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0 8.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></g> +<g id="directions-bus"><path d="M4 16c0 .88.39 1.67 1 2.22V20c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h8v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1.78c.61-.55 1-1.34 1-2.22V6c0-3.5-3.58-4-8-4s-8 .5-8 4v10zm3.5 1c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm9 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6H6V6h12v5z"/></g> +<g id="directions-car"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/></g> +<g id="directions-ferry"><path d="M20 21c-1.39 0-2.78-.47-4-1.32-2.44 1.71-5.56 1.71-8 0C6.78 20.53 5.39 21 4 21H2v2h2c1.38 0 2.74-.35 4-.99 2.52 1.29 5.48 1.29 8 0 1.26.65 2.62.99 4 .99h2v-2h-2zM3.95 19H4c1.6 0 3.02-.88 4-2 .98 1.12 2.4 2 4 2s3.02-.88 4-2c.98 1.12 2.4 2 4 2h.05l1.89-6.68c.08-.26.06-.54-.06-.78s-.34-.42-.6-.5L20 10.62V6c0-1.1-.9-2-2-2h-3V1H9v3H6c-1.1 0-2 .9-2 2v4.62l-1.29.42c-.26.08-.48.26-.6.5s-.15.52-.06.78L3.95 19zM6 6h12v3.97L12 8 6 9.97V6z"/></g> +<g id="directions-subway"><path d="M12 2c-4.42 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-3.58-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/></g> +<g id="directions-train"><path d="M4 15.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V5c0-3.5-3.58-4-8-4s-8 .5-8 4v10.5zm8 1.5c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm6-7H6V5h12v5z"/></g> +<g id="directions-transit"><path d="M12 2c-4.42 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-3.58-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/></g> +<g id="directions-walk"><path d="M14 3.8c.99 0 1.8-.81 1.8-1.8 0-1-.81-1.8-1.8-1.8-1 0-1.8.81-1.8 1.8S13 3.8 14 3.8zm.12 6.2H19V8.2h-3.62l-2-3.33c-.3-.5-.84-.83-1.46-.83-.17 0-.34.03-.49.07L6 5.8V11h1.8V7.33l2.11-.66L6 22h1.8l2.87-8.11L13 17v5h1.8v-6.41l-2.49-4.54.73-2.87L14.12 10z"/></g> +<g id="flight"><path d="M10.18 9"/><path d="M21 16v-2l-8-5V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5l8 2.5z"/></g> +<g id="hotel"><path d="M7 13c1.66 0 3-1.34 3-3S8.66 7 7 7s-3 1.34-3 3 1.34 3 3 3zm12-6h-8v7H3V5H1v15h2v-3h18v3h2v-9c0-2.21-1.79-4-4-4z"/></g> +<g id="layers"><path d="M11.99 18.54l-7.37-5.73L3 14.07l9 7 9-7-1.63-1.27-7.38 5.74zM12 16l7.36-5.73L21 9l-9-7-9 7 1.63 1.27L12 16z"/></g> +<g id="layers-clear"><path d="M19.81 14.99l1.19-.92-1.43-1.43-1.19.92 1.43 1.43zm-.45-4.72L21 9l-9-7-2.91 2.27 7.87 7.88 2.4-1.88zM3.27 1L2 2.27l4.22 4.22L3 9l1.63 1.27L12 16l2.1-1.63 1.43 1.43L12 18.54l-7.37-5.73L3 14.07l9 7 4.95-3.85L20.73 21 22 19.73 3.27 1z"/></g> +<g id="local-airport"><path d="M21 16v-2l-8-5V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5l8 2.5z"/></g> +<g id="local-atm"><path d="M11 17h2v-1h1c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1h-3v-1h4V8h-2V7h-2v1h-1c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1h3v1H9v2h2v1zm9-13H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4V6h16v12z"/></g> +<g id="local-attraction"><path d="M20 12c0-1.1.9-2 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-1.99.9-1.99 2v4c1.1 0 1.99.9 1.99 2s-.89 2-2 2v4c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2v-4c-1.1 0-2-.9-2-2zm-4.42 4.8L12 14.5l-3.58 2.3 1.08-4.12-3.29-2.69 4.24-.25L12 5.8l1.54 3.95 4.24.25-3.29 2.69 1.09 4.11z"/></g> +<g id="local-bar"><path d="M11 13v6H6v2h12v-2h-5v-6l8-8V3H3v2l8 8zM7.5 7l-2-2h13l-2 2h-9z"/></g> +<g id="local-cafe"><path d="M20 3H4v10c0 2.21 1.79 4 4 4h6c2.21 0 4-1.79 4-4v-3h2c1.11 0 2-.89 2-2V5c0-1.11-.89-2-2-2zm0 5h-2V5h2v3zM2 21h18v-2H2v2z"/></g> +<g id="local-car-wash"><path d="M17 5c.83 0 1.5-.67 1.5-1.5 0-1-1.5-2.7-1.5-2.7s-1.5 1.7-1.5 2.7c0 .83.67 1.5 1.5 1.5zm-5 0c.83 0 1.5-.67 1.5-1.5 0-1-1.5-2.7-1.5-2.7s-1.5 1.7-1.5 2.7c0 .83.67 1.5 1.5 1.5zM7 5c.83 0 1.5-.67 1.5-1.5C8.5 2.5 7 .8 7 .8S5.5 2.5 5.5 3.5C5.5 4.33 6.17 5 7 5zm11.92 3.01C18.72 7.42 18.16 7 17.5 7h-11c-.66 0-1.21.42-1.42 1.01L3 14v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 18c-.83 0-1.5-.67-1.5-1.5S5.67 15 6.5 15s1.5.67 1.5 1.5S7.33 18 6.5 18zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 13l1.5-4.5h11L19 13H5z"/></g> +<g id="local-convenience-store"><path d="M19 7V4H5v3H2v13h8v-4h4v4h8V7h-3zm-8 3H9v1h2v1H8V9h2V8H8V7h3v3zm5 2h-1v-2h-2V7h1v2h1V7h1v5z"/></g> +<g id="local-drink"><path d="M3 2l2.01 18.23C5.13 21.23 5.97 22 7 22h10c1.03 0 1.87-.77 1.99-1.77L21 2H3zm9 17c-1.66 0-3-1.34-3-3 0-2 3-5.4 3-5.4s3 3.4 3 5.4c0 1.66-1.34 3-3 3zm6.33-11H5.67l-.44-4h13.53l-.43 4z"/></g> +<g id="local-florist"><path d="M12 22c4.97 0 9-4.03 9-9-4.97 0-9 4.03-9 9zM5.6 10.25c0 1.38 1.12 2.5 2.5 2.5.53 0 1.01-.16 1.42-.44l-.02.19c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5l-.02-.19c.4.28.89.44 1.42.44 1.38 0 2.5-1.12 2.5-2.5 0-1-.59-1.85-1.43-2.25.84-.4 1.43-1.25 1.43-2.25 0-1.38-1.12-2.5-2.5-2.5-.53 0-1.01.16-1.42.44l.02-.19C14.5 2.12 13.38 1 12 1S9.5 2.12 9.5 3.5l.02.19c-.4-.28-.89-.44-1.42-.44-1.38 0-2.5 1.12-2.5 2.5 0 1 .59 1.85 1.43 2.25-.84.4-1.43 1.25-1.43 2.25zM12 5.5c1.38 0 2.5 1.12 2.5 2.5s-1.12 2.5-2.5 2.5S9.5 9.38 9.5 8s1.12-2.5 2.5-2.5zM3 13c0 4.97 4.03 9 9 9 0-4.97-4.03-9-9-9z"/></g> +<g id="local-gas-station"><path d="M19.77 7.23l.01-.01-3.72-3.72L15 4.56l2.11 2.11c-.94.36-1.61 1.26-1.61 2.33 0 1.38 1.12 2.5 2.5 2.5.36 0 .69-.08 1-.21v7.21c0 .55-.45 1-1 1s-1-.45-1-1V14c0-1.1-.9-2-2-2h-1V5c0-1.1-.9-2-2-2H6c-1.1 0-2 .9-2 2v16h10v-7.5h1.5v5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V9c0-.69-.28-1.32-.73-1.77zM12 10H6V5h6v5zm6 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></g> +<g id="local-grocery-store"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="local-hospital"><path d="M19 3H5c-1.1 0-1.99.9-1.99 2L3 19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 11h-4v4h-4v-4H6v-4h4V6h4v4h4v4z"/></g> +<g id="local-hotel"><path d="M7 13c1.66 0 3-1.34 3-3S8.66 7 7 7s-3 1.34-3 3 1.34 3 3 3zm12-6h-8v7H3V5H1v15h2v-3h18v3h2v-9c0-2.21-1.79-4-4-4z"/></g> +<g id="local-laundry-service"><path d="M9.17 16.83c1.56 1.56 4.1 1.56 5.66 0 1.56-1.56 1.56-4.1 0-5.66l-5.66 5.66zM18 2.01L6 2c-1.11 0-2 .89-2 2v16c0 1.11.89 2 2 2h12c1.11 0 2-.89 2-2V4c0-1.11-.89-1.99-2-1.99zM10 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM7 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm5 16c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6z"/></g> +<g id="local-library"><path d="M12 11.55C9.64 9.35 6.48 8 3 8v11c3.48 0 6.64 1.35 9 3.55 2.36-2.19 5.52-3.55 9-3.55V8c-3.48 0-6.64 1.35-9 3.55zM12 8c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3z"/></g> +<g id="local-mall"><path d="M19 6h-2c0-2.76-2.24-5-5-5S7 3.24 7 6H5c-1.1 0-1.99.9-1.99 2L3 20c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-7-3c1.66 0 3 1.34 3 3H9c0-1.66 1.34-3 3-3zm0 10c-2.76 0-5-2.24-5-5h2c0 1.66 1.34 3 3 3s3-1.34 3-3h2c0 2.76-2.24 5-5 5z"/></g> +<g id="local-movies"><path d="M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8 17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h2v2z"/></g> +<g id="local-offer"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/></g> +<g id="local-parking"><path d="M13 3H6v18h4v-6h3c3.31 0 6-2.69 6-6s-2.69-6-6-6zm.2 8H10V7h3.2c1.1 0 2 .9 2 2s-.9 2-2 2z"/></g> +<g id="local-pharmacy"><path d="M21 5h-2.64l1.14-3.14L17.15 1l-1.46 4H3v2l2 6-2 6v2h18v-2l-2-6 2-6V5zm-5 9h-3v3h-2v-3H8v-2h3V9h2v3h3v2z"/></g> +<g id="local-phone"><path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></g> +<g id="local-pizza"><path d="M12 2C8.43 2 5.23 3.54 3.01 6L12 22l8.99-16C18.78 3.55 15.57 2 12 2zM7 7c0-1.1.9-2 2-2s2 .9 2 2-.9 2-2 2-2-.9-2-2zm5 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="local-play"><path d="M20 12c0-1.1.9-2 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-1.99.9-1.99 2v4c1.1 0 1.99.9 1.99 2s-.89 2-2 2v4c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2v-4c-1.1 0-2-.9-2-2zm-4.42 4.8L12 14.5l-3.58 2.3 1.08-4.12-3.29-2.69 4.24-.25L12 5.8l1.54 3.95 4.24.25-3.29 2.69 1.09 4.11z"/></g> +<g id="local-post-office"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></g> +<g id="local-print-shop"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></g> +<g id="local-restaurant"><path d="M8.1 13.34l2.83-2.83L3.91 3.5c-1.56 1.56-1.56 4.09 0 5.66l4.19 4.18zm6.78-1.81c1.53.71 3.68.21 5.27-1.38 1.91-1.91 2.28-4.65.81-6.12-1.46-1.46-4.2-1.1-6.12.81-1.59 1.59-2.09 3.74-1.38 5.27L3.7 19.87l1.41 1.41L12 14.41l6.88 6.88 1.41-1.41L13.41 13l1.47-1.47z"/></g> +<g id="local-see"><circle cx="12" cy="12" r="3.2"/><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></g> +<g id="local-shipping"><path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="local-taxi"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5H15V3H9v2H6.5c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/></g> +<g id="location-history"><path d="M19 2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h4l3 3 3-3h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 3.3c1.49 0 2.7 1.21 2.7 2.7 0 1.49-1.21 2.7-2.7 2.7-1.49 0-2.7-1.21-2.7-2.7 0-1.49 1.21-2.7 2.7-2.7zM18 16H6v-.9c0-2 4-3.1 6-3.1s6 1.1 6 3.1v.9z"/></g> +<g id="map"><path d="M20.5 3l-.16.03L15 5.1 9 3 3.36 4.9c-.21.07-.36.25-.36.48V20.5c0 .28.22.5.5.5l.16-.03L9 18.9l6 2.1 5.64-1.9c.21-.07.36-.25.36-.48V3.5c0-.28-.22-.5-.5-.5zM15 19l-6-2.11V5l6 2.11V19z"/></g> +<g id="my-location"><path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="navigation"><path d="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71z"/></g> +<g id="pin-drop"><path d="M18 8c0-3.31-2.69-6-6-6S6 4.69 6 8c0 4.5 6 11 6 11s6-6.5 6-11zm-8 0c0-1.1.9-2 2-2s2 .9 2 2-.89 2-2 2c-1.1 0-2-.9-2-2zM5 20v2h14v-2H5z"/></g> +<g id="place"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></g> +<g id="rate-review"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 14v-2.47l6.88-6.88c.2-.2.51-.2.71 0l1.77 1.77c.2.2.2.51 0 .71L8.47 14H6zm12 0h-7.5l2-2H18v2z"/></g> +<g id="restaurant-menu"><path d="M8.1 13.34l2.83-2.83L3.91 3.5c-1.56 1.56-1.56 4.09 0 5.66l4.19 4.18zm6.78-1.81c1.53.71 3.68.21 5.27-1.38 1.91-1.91 2.28-4.65.81-6.12-1.46-1.46-4.2-1.1-6.12.81-1.59 1.59-2.09 3.74-1.38 5.27L3.7 19.87l1.41 1.41L12 14.41l6.88 6.88 1.41-1.41L13.41 13l1.47-1.47z"/></g> +<g id="satellite"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5 4.99h3C8 6.65 6.66 8 5 8V4.99zM5 12v-2c2.76 0 5-2.25 5-5.01h2C12 8.86 8.87 12 5 12zm0 6l3.5-4.5 2.5 3.01L14.5 12l4.5 6H5z"/></g> +<g id="store-mall-directory"><path d="M20 4H4v2h16V4zm1 10v-2l-1-5H4l-1 5v2h1v6h10v-6h4v6h2v-6h1zm-9 4H6v-4h6v4z"/></g> +<g id="terrain"><path d="M14 6l-3.75 5 2.85 3.8-1.6 1.2C9.81 13.75 7 10 7 10l-6 8h22L14 6z"/></g> +<g id="traffic"><path d="M20 10h-3V8.86c1.72-.45 3-2 3-3.86h-3V4c0-.55-.45-1-1-1H8c-.55 0-1 .45-1 1v1H4c0 1.86 1.28 3.41 3 3.86V10H4c0 1.86 1.28 3.41 3 3.86V15H4c0 1.86 1.28 3.41 3 3.86V20c0 .55.45 1 1 1h8c.55 0 1-.45 1-1v-1.14c1.72-.45 3-2 3-3.86h-3v-1.14c1.72-.45 3-2 3-3.86zm-8 9c-1.11 0-2-.9-2-2s.89-2 2-2c1.1 0 2 .9 2 2s-.89 2-2 2zm0-5c-1.11 0-2-.9-2-2s.89-2 2-2c1.1 0 2 .9 2 2s-.89 2-2 2zm0-5c-1.11 0-2-.9-2-2 0-1.11.89-2 2-2 1.1 0 2 .89 2 2 0 1.1-.89 2-2 2z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/notification-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/notification-icons.html new file mode 100644 index 0000000..62712516 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/notification-icons.html
@@ -0,0 +1,49 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="notification" size="24"> +<svg><defs> +<g id="adb"><path d="M5 16c0 3.87 3.13 7 7 7s7-3.13 7-7v-4H5v4zM16.12 4.37l2.1-2.1-.82-.83-2.3 2.31C14.16 3.28 13.12 3 12 3s-2.16.28-3.09.75L6.6 1.44l-.82.83 2.1 2.1C6.14 5.64 5 7.68 5 10v1h14v-1c0-2.32-1.14-4.36-2.88-5.63zM9 9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm6 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></g> +<g id="bluetooth-audio"><path d="M14.24 12.01l2.32 2.32c.28-.72.44-1.51.44-2.33 0-.82-.16-1.59-.43-2.31l-2.33 2.32zm5.29-5.3l-1.26 1.26c.63 1.21.98 2.57.98 4.02s-.36 2.82-.98 4.02l1.2 1.2c.97-1.54 1.54-3.36 1.54-5.31-.01-1.89-.55-3.67-1.48-5.19zm-3.82 1L10 2H9v7.59L4.41 5 3 6.41 8.59 12 3 17.59 4.41 19 9 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM11 5.83l1.88 1.88L11 9.59V5.83zm1.88 10.46L11 18.17v-3.76l1.88 1.88z"/></g> +<g id="disc-full"><path d="M20 16h2v-2h-2v2zm0-9v5h2V7h-2zM10 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm0 10c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="dnd-forwardslash"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zM4 12c0-4.4 3.6-8 8-8 1.8 0 3.5.6 4.9 1.7L5.7 16.9C4.6 15.5 4 13.8 4 12zm8 8c-1.8 0-3.5-.6-4.9-1.7L18.3 7.1C19.4 8.5 20 10.2 20 12c0 4.4-3.6 8-8 8z"/></g> +<g id="do-not-disturb"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z"/></g> +<g id="drive-eta"><path d="M18.92 5.01C18.72 4.42 18.16 4 17.5 4h-11c-.66 0-1.21.42-1.42 1.01L3 11v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 15c-.83 0-1.5-.67-1.5-1.5S5.67 12 6.5 12s1.5.67 1.5 1.5S7.33 15 6.5 15zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 10l1.5-4.5h11L19 10H5z"/></g> +<g id="event-available"><path d="M16.53 11.06L15.47 10l-4.88 4.88-2.12-2.12-1.06 1.06L10.59 17l5.94-5.94zM19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z"/></g> +<g id="event-busy"><path d="M9.31 17l2.44-2.44L14.19 17l1.06-1.06-2.44-2.44 2.44-2.44L14.19 10l-2.44 2.44L9.31 10l-1.06 1.06 2.44 2.44-2.44 2.44L9.31 17zM19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z"/></g> +<g id="event-note"><path d="M17 10H7v2h10v-2zm2-7h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zm-5-5H7v2h7v-2z"/></g> +<g id="folder-special"><path d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-6.42 12L10 15.9 6.42 18l.95-4.07-3.16-2.74 4.16-.36L10 7l1.63 3.84 4.16.36-3.16 2.74.95 4.06z"/></g> +<g id="mms"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM5 14l3.5-4.5 2.5 3.01L14.5 8l4.5 6H5z"/></g> +<g id="more"><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.97.89 1.66.89H22c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 13.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm5 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm5 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="network-locked"><path d="M19.5 10c.17 0 .33.03.5.05V1L1 20h13v-3c0-.89.39-1.68 1-2.23v-.27c0-2.48 2.02-4.5 4.5-4.5zm2.5 6v-1.5c0-1.38-1.12-2.5-2.5-2.5S17 13.12 17 14.5V16c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1v-4c0-.55-.45-1-1-1zm-1 0h-3v-1.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V16z"/></g> +<g id="phone-bluetooth-speaker"><path d="M14.71 9.5L17 7.21V11h.5l2.85-2.85L18.21 6l2.15-2.15L17.5 1H17v3.79L14.71 2.5l-.71.71L16.79 6 14 8.79l.71.71zM18 2.91l.94.94-.94.94V2.91zm0 4.3l.94.94-.94.94V7.21zm2 8.29c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></g> +<g id="phone-forwarded"><path d="M18 11l5-5-5-5v3h-4v4h4v3zm2 4.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></g> +<g id="phone-in-talk"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 12h2c0-4.97-4.03-9-9-9v2c3.87 0 7 3.13 7 7zm-4 0h2c0-2.76-2.24-5-5-5v2c1.66 0 3 1.34 3 3z"/></g> +<g id="phone-locked"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM20 4v-.5C20 2.12 18.88 1 17.5 1S15 2.12 15 3.5V4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-.8 0h-3.4v-.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V4z"/></g> +<g id="phone-missed"><path d="M6.5 5.5L12 11l7-7-1-1-6 6-4.5-4.5H11V3H5v6h1.5V5.5zm17.21 11.17C20.66 13.78 16.54 12 12 12 7.46 12 3.34 13.78.29 16.67c-.18.18-.29.43-.29.71s.11.53.29.71l2.48 2.48c.18.18.43.29.71.29.27 0 .52-.11.7-.28.79-.74 1.69-1.36 2.66-1.85.33-.16.56-.5.56-.9v-3.1c1.45-.48 3-.73 4.6-.73 1.6 0 3.15.25 4.6.72v3.1c0 .39.23.74.56.9.98.49 1.87 1.12 2.67 1.85.18.18.43.28.7.28.28 0 .53-.11.71-.29l2.48-2.48c.18-.18.29-.43.29-.71s-.12-.52-.3-.7z"/></g> +<g id="phone-paused"><path d="M17 3h-2v7h2V3zm3 12.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 3v7h2V3h-2z"/></g> +<g id="play-download"><path d="M20 6h-4V4l-2-2h-4L8 4v2H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM10 4h4v2h-4V4zm2 15l-5-5h3v-4h4v4h3l-5 5z"/></g> +<g id="play-install"><path d="M20 6h-4V4l-2-2h-4L8 4v2H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM10 4h4v2h-4V4zm.5 13.5L7 14l1.41-1.41 2.09 2.09 5.18-5.18 1.41 1.41-6.59 6.59z"/></g> +<g id="sd-card"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-6 6h-2V4h2v4zm3 0h-2V4h2v4zm3 0h-2V4h2v4z"/></g> +<g id="sim-card-alert"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 15h-2v-2h2v2zm0-4h-2V8h2v5z"/></g> +<g id="sms"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9 11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z"/></g> +<g id="sms-failed"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 12h-2v-2h2v2zm0-4h-2V6h2v4z"/></g> +<g id="sync"><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/></g> +<g id="sync-disabled"><path d="M10 6.35V4.26c-.8.21-1.55.54-2.23.96l1.46 1.46c.25-.12.5-.24.77-.33zm-7.14-.94l2.36 2.36C4.45 8.99 4 10.44 4 12c0 2.21.91 4.2 2.36 5.64L4 20h6v-6l-2.24 2.24C6.68 15.15 6 13.66 6 12c0-1 .25-1.94.68-2.77l8.08 8.08c-.25.13-.5.25-.77.34v2.09c.8-.21 1.55-.54 2.23-.96l2.36 2.36 1.27-1.27L4.14 4.14 2.86 5.41zM20 4h-6v6l2.24-2.24C17.32 8.85 18 10.34 18 12c0 1-.25 1.94-.68 2.77l1.46 1.46C19.55 15.01 20 13.56 20 12c0-2.21-.91-4.2-2.36-5.64L20 4z"/></g> +<g id="sync-problem"><path d="M3 12c0 2.21.91 4.2 2.36 5.64L3 20h6v-6l-2.24 2.24C5.68 15.15 5 13.66 5 12c0-2.61 1.67-4.83 4-5.65V4.26C5.55 5.15 3 8.27 3 12zm8 5h2v-2h-2v2zM21 4h-6v6l2.24-2.24C18.32 8.85 19 10.34 19 12c0 2.61-1.67 4.83-4 5.65v2.09c3.45-.89 6-4.01 6-7.74 0-2.21-.91-4.2-2.36-5.64L21 4zm-10 9h2V7h-2v6z"/></g> +<g id="system-update"><path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14zm-1-6h-3V8h-2v5H8l4 4 4-4z"/></g> +<g id="tap-and-play"><path d="M2 16v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm0 4v3h3c0-1.66-1.34-3-3-3zm0-8v2c4.97 0 9 4.03 9 9h2c0-6.08-4.92-11-11-11zM17 1.01L7 1c-1.1 0-2 .9-2 2v7.37c.69.16 1.36.37 2 .64V5h10v13h-3.03c.52 1.25.84 2.59.95 4H17c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99z"/></g> +<g id="time-to-leave"><path d="M18.92 5.01C18.72 4.42 18.16 4 17.5 4h-11c-.66 0-1.21.42-1.42 1.01L3 11v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 15c-.83 0-1.5-.67-1.5-1.5S5.67 12 6.5 12s1.5.67 1.5 1.5S7.33 15 6.5 15zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 10l1.5-4.5h11L19 10H5z"/></g> +<g id="vibration"><path d="M0 15h2V9H0v6zm3 2h2V7H3v10zm19-8v6h2V9h-2zm-3 8h2V7h-2v10zM16.5 3h-9C6.67 3 6 3.67 6 4.5v15c0 .83.67 1.5 1.5 1.5h9c.83 0 1.5-.67 1.5-1.5v-15c0-.83-.67-1.5-1.5-1.5zM16 19H8V5h8v14z"/></g> +<g id="voice-chat"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12l-4-3.2V14H6V6h8v3.2L18 6v8z"/></g> +<g id="vpn-lock"><path d="M22 4v-.5C22 2.12 20.88 1 19.5 1S17 2.12 17 3.5V4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-.8 0h-3.4v-.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V4zm-2.28 8c.04.33.08.66.08 1 0 2.08-.8 3.97-2.1 5.39-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H7v-2h2c.55 0 1-.45 1-1V8h2c1.1 0 2-.9 2-2V3.46c-.95-.3-1.95-.46-3-.46C5.48 3 1 7.48 1 13s4.48 10 10 10 10-4.48 10-10c0-.34-.02-.67-.05-1h-2.03zM10 20.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L8 16v1c0 1.1.9 2 2 2v1.93z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-icons/social-icons.html b/third_party/polymer/v0_8/components-chromium/iron-icons/social-icons.html new file mode 100644 index 0000000..390603f9 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-icons/social-icons.html
@@ -0,0 +1,39 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="social" size="24"> +<svg><defs> +<g id="cake"><path d="M12 6c1.11 0 2-.9 2-2 0-.38-.1-.73-.29-1.03L12 0l-1.71 2.97c-.19.3-.29.65-.29 1.03 0 1.1.9 2 2 2zm4.6 9.99l-1.07-1.07-1.08 1.07c-1.3 1.3-3.58 1.31-4.89 0l-1.07-1.07-1.09 1.07C6.75 16.64 5.88 17 4.96 17c-.73 0-1.4-.23-1.96-.61V21c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-4.61c-.56.38-1.23.61-1.96.61-.92 0-1.79-.36-2.44-1.01zM18 9h-5V7h-2v2H6c-1.66 0-3 1.34-3 3v1.54c0 1.08.88 1.96 1.96 1.96.52 0 1.02-.2 1.38-.57l2.14-2.13 2.13 2.13c.74.74 2.03.74 2.77 0l2.14-2.13 2.13 2.13c.37.37.86.57 1.38.57 1.08 0 1.96-.88 1.96-1.96V12C21 10.34 19.66 9 18 9z"/></g> +<g id="domain"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"/></g> +<g id="group"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></g> +<g id="group-add"><path d="M8 10H5V7H3v3H0v2h3v3h2v-3h3v-2zm10 1c1.66 0 2.99-1.34 2.99-3S19.66 5 18 5c-.32 0-.63.05-.91.14.57.81.9 1.79.9 2.86s-.34 2.04-.9 2.86c.28.09.59.14.91.14zm-5 0c1.66 0 2.99-1.34 2.99-3S14.66 5 13 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm6.62 2.16c.83.73 1.38 1.66 1.38 2.84v2h3v-2c0-1.54-2.37-2.49-4.38-2.84zM13 13c-2 0-6 1-6 3v2h12v-2c0-2-4-3-6-3z"/></g> +<g id="location-city"><path d="M15 11V5l-3-3-3 3v2H3v14h18V11h-6zm-8 8H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm6 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm6 12h-2v-2h2v2zm0-4h-2v-2h2v2z"/></g> +<g id="mood"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></g> +<g id="notifications"><path d="M11.5 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6.5-6v-5.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-2.87.68-5 3.25-5 6.32V16l-2 2v1h17v-1l-2-2z"/></g> +<g id="notifications-none"><path d="M11.5 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6.5-6v-5.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-2.87.68-5 3.25-5 6.32V16l-2 2v1h17v-1l-2-2zm-2 1H7v-6.5C7 8.01 9.01 6 11.5 6S16 8.01 16 10.5V17z"/></g> +<g id="notifications-off"><path d="M11.5 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zM18 10.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-.51.12-.99.32-1.45.56L18 14.18V10.5zm-.27 8.5l2 2L21 19.73 4.27 3 3 4.27l2.92 2.92C5.34 8.16 5 9.29 5 10.5V16l-2 2v1h14.73z"/></g> +<g id="notifications-on"><path d="M6.58 3.58L5.15 2.15C2.76 3.97 1.18 6.8 1.03 10h2c.15-2.65 1.51-4.97 3.55-6.42zM19.97 10h2c-.15-3.2-1.73-6.03-4.13-7.85l-1.43 1.43c2.05 1.45 3.41 3.77 3.56 6.42zm-1.97.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-2.87.68-5 3.25-5 6.32V16l-2 2v1h17v-1l-2-2v-5.5zM11.5 22c.14 0 .27-.01.4-.04.65-.13 1.19-.58 1.44-1.18.1-.24.16-.5.16-.78h-4c0 1.1.9 2 2 2z"/></g> +<g id="notifications-paused"><path d="M11.5 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6.5-6v-5.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-2.87.68-5 3.25-5 6.32V16l-2 2v1h17v-1l-2-2zm-4-6.2l-2.8 3.4H14V15H9v-1.8l2.8-3.4H9V8h5v1.8z"/></g> +<g id="pages"><path d="M3 5v6h5L7 7l4 1V3H5c-1.1 0-2 .9-2 2zm5 8H3v6c0 1.1.9 2 2 2h6v-5l-4 1 1-4zm9 4l-4-1v5h6c1.1 0 2-.9 2-2v-6h-5l1 4zm2-14h-6v5l4-1-1 4h5V5c0-1.1-.9-2-2-2z"/></g> +<g id="party-mode"><path d="M20 4h-3.17L15 2H9L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 3c1.63 0 3.06.79 3.98 2H12c-1.66 0-3 1.34-3 3 0 .35.07.69.18 1H7.1c-.06-.32-.1-.66-.1-1 0-2.76 2.24-5 5-5zm0 10c-1.63 0-3.06-.79-3.98-2H12c1.66 0 3-1.34 3-3 0-.35-.07-.69-.18-1h2.08c.07.32.1.66.1 1 0 2.76-2.24 5-5 5z"/></g> +<g id="people"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></g> +<g id="people-outline"><path d="M16.5 13c-1.2 0-3.07.34-4.5 1-1.43-.67-3.3-1-4.5-1C5.33 13 1 14.08 1 16.25V19h22v-2.75c0-2.17-4.33-3.25-6.5-3.25zm-4 4.5h-10v-1.25c0-.54 2.56-1.75 5-1.75s5 1.21 5 1.75v1.25zm9 0H14v-1.25c0-.46-.2-.86-.52-1.22.88-.3 1.96-.53 3.02-.53 2.44 0 5 1.21 5 1.75v1.25zM7.5 12c1.93 0 3.5-1.57 3.5-3.5S9.43 5 7.5 5 4 6.57 4 8.5 5.57 12 7.5 12zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 5.5c1.93 0 3.5-1.57 3.5-3.5S18.43 5 16.5 5 13 6.57 13 8.5s1.57 3.5 3.5 3.5zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z"/></g> +<g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></g> +<g id="person-add"><path d="M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V7H4v3H1v2h3v3h2v-3h3v-2H6zm9 4c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></g> +<g id="person-outline"><path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"/></g> +<g id="plus-one"><path d="M10 8H8v4H4v2h4v4h2v-4h4v-2h-4zm4.5-1.92V7.9l2.5-.5V18h2V5z"/></g> +<g id="poll"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/></g> +<g id="public"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></g> +<g id="school"><path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z"/></g> +<g id="share"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"/></g> +<g id="whatshot"><path d="M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 17.41 3.8 13.5.67zM11.71 19c-1.78 0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 4.04 0 2.65-2.15 4.8-4.8 4.8z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/.bower.json new file mode 100644 index 0000000..1912846 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/.bower.json
@@ -0,0 +1,25 @@ +{ + "name": "iron-iconset-svg", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-meta": "polymerelements/iron-meta#^0.8.0" + }, + "devDependencies": { + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/polymerelements/iron-iconset-svg", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "4dfcbf0b1b6788cbe278402e01050960f6b5e894" + }, + "_source": "git://github.com/polymerelements/iron-iconset-svg.git", + "_target": "^0.8.0", + "_originalSource": "polymerelements/iron-iconset-svg" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/README.md b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/README.md new file mode 100644 index 0000000..37d603a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/README.md
@@ -0,0 +1,4 @@ +iron-iconset-svg +========= + +See the [component page](http://polymer-project.org/docs/elements/iron-elements.html#iron-iconset-svg) for more information.
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/bower.json b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/bower.json new file mode 100644 index 0000000..b37197a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/bower.json
@@ -0,0 +1,14 @@ +{ + "name": "iron-iconset-svg", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-meta": "polymerelements/iron-meta#^0.8.0" + }, + "devDependencies": { + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/index.html b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/index.html new file mode 100644 index 0000000..088bb04 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="iron-iconset-svg.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/iron-iconset-svg-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/iron-iconset-svg-extracted.js new file mode 100644 index 0000000..23d924a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/iron-iconset-svg-extracted.js
@@ -0,0 +1,149 @@ + + + Polymer({ + + is: 'iron-iconset-svg', + + properties: { + + /** + * The name of the iconset. + * + * @attribute name + * @type string + * @default '' + */ + name: { + type: String, + observer: '_nameChanged' + }, + + /** + * Array of fully-qualitifed icon names in the iconset. + */ + iconNames: { + type: Array, + notify: true + }, + + /** + * The size of an individual icon. Note that icons must be square. + * + * @attribute iconSize + * @type number + * @default 24 + */ + size: { + type: Number, + value: 24 + } + + }, + + /** + * Applies an icon to the given element. + * + * An svg icon is prepended to the element's shadowRoot if it exists, + * otherwise to the element itself. + * + * @method applyIcon + * @param {Element} element Element to which the icon is applied. + * @param {String} icon Name of the icon to apply. + * @return {Element} The svg element which renders the icon. + */ + applyIcon: function(element, iconName) { + // insert svg element into shadow root, if it exists + element = element.root || element; + // Remove old svg element + this.removeIcon(element); + // install new svg element + var svg = this._cloneIcon(iconName); + if (svg) { + // TODO(sjmiles): I know, `with` is the devil ... except it isn't + with (Polymer.dom(element)) { + insertBefore(svg, childNodes[0]); + } + return element._svgIcon = svg; + } + }, + + /** + * Remove an icon from the given element by undoing the changes effected + * by `applyIcon`. + * + * @param {Element} element The element from which the icon is removed. + */ + removeIcon: function(element) { + // Remove old svg element + if (element._svgIcon) { + Polymer.dom(element).removeChild(element._svgIcon); + element._svgIcon = null; + } + }, + + /** + * + * When name is changed, either register a new iconset with the included + * icons, or if there are no children, set up a meta-iconset. + * + */ + _nameChanged: function() { + new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); + // icons (descendents) must exist a-priori + this._icons = this._createIconMap(); + this.iconNames = this._getIconNames(); + }, + + /** + * Array of all icon names in this iconset. + * + * @return {Array} Array of icon names. + */ + _getIconNames: function() { + return Object.keys(this._icons).map(function(n) { + return this.name + ':' + n; + }, this); + }, + + /** + * Create a map of child SVG elements by id. + * + * @return {Object} Map of id's to SVG elements. + */ + _createIconMap: function() { + // Objects chained to Object.prototype (`{}`) have members. Specifically, + // on FF there is a `watch` method that confuses the icon map, so we + // need to use a null-based object here. + var icons = Object.create(null); + Polymer.dom(this).querySelectorAll('[id]') + .forEach(function(icon) { + icons[icon.id] = icon; + }); + return icons; + }, + + /** + * Produce installable clone of the SVG element matching `id` in this + * iconset, or `undefined` if there is no matching element. + * + * @return {Object} Returns an installable clone of the SVG element + * matching `id`. + */ + _cloneIcon: function(id) { + return this._prepareSvgClone(this._icons[id], this.size); + }, + + _prepareSvgClone: function(sourceSvg, size) { + if (sourceSvg) { + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('viewBox', ['0', '0', size, size].join(' ')); + svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); + // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/370136 + // TODO(sjmiles): inline style may not be ideal, but avoids requiring a shadow-root + svg.style.cssText = 'pointer-events: none; display: block; width: 100%; height: 100%;'; + svg.appendChild(sourceSvg.cloneNode(true)).removeAttribute('id'); + return svg; + } + } + + });
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/iron-iconset-svg.html b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/iron-iconset-svg.html new file mode 100644 index 0000000..282d1d6 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset-svg/iron-iconset-svg.html
@@ -0,0 +1,46 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- +/** + * @group Iron Elements + * + * The `iron-iconset-svg` element allows users to define their own icon sets + * that contain svg icons. The svg icon elements should be children of the + * `iron-iconset-svg` element. Multiple icons should be given distinct id's. + * + * Using svg elements to create icons has a few advantages over traditional + * bitmap graphics like jpg or png. Icons that use svg are vector based so they + * are resolution independent and should look good on any device. They are + * stylable via css. Icons can be themed, colorized, and even animated. + * + * Example: + * + * <iron-iconset-svg id="my-svg-icons" iconSize="24"> + * <svg> + * <defs> + * <g id="shape"> + * <rect x="50" y="50" width="50" height="50" /> + * <circle cx="50" cy="50" r="50" /> + * </g> + * </defs> + * </svg> + * </iron-iconset-svg> + * + * This will automatically register the icon set "my-svg-icons" to the iconset + * database. To use these icons from within another element, make a + * `iron-iconset` element and call the `byId` method + * to retrieve a given iconset. To apply a particular icon inside an + * element use the `applyIcon` method. For example: + * + * iconset.applyIcon(iconNode, 'car'); + * + * @element iron-iconset-svg + */ +--><html><head><link rel="import" href="../polymer/polymer.html"> + +</head><body><script src="iron-iconset-svg-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-iconset/.bower.json new file mode 100644 index 0000000..3caade23 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset/.bower.json
@@ -0,0 +1,25 @@ +{ + "name": "iron-iconset", + "private": true, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-meta": "PolymerElements/iron-meta#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/PolymerElements/iron-iconset", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "a496891222b88e06995558b6f678cbf41d01d9b4" + }, + "_source": "git://github.com/PolymerElements/iron-iconset.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-iconset" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-iconset/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset/README.md b/third_party/polymer/v0_8/components-chromium/iron-iconset/README.md new file mode 100644 index 0000000..3f46cf5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset/README.md
@@ -0,0 +1,4 @@ +iron-iconset +============ + +See the [component page](http://polymer-project.org/docs/elements/iron-elements.html#iron-iconset) for more information.
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset/bower.json b/third_party/polymer/v0_8/components-chromium/iron-iconset/bower.json new file mode 100644 index 0000000..0b9367f1 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset/bower.json
@@ -0,0 +1,14 @@ +{ + "name": "iron-iconset", + "private": true, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-meta": "PolymerElements/iron-meta#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset/index.html b/third_party/polymer/v0_8/components-chromium/iron-iconset/index.html new file mode 100644 index 0000000..c2ea8ca --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="iron-iconset.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset/iron-iconset-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-iconset/iron-iconset-extracted.js new file mode 100644 index 0000000..de3dbec --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset/iron-iconset-extracted.js
@@ -0,0 +1,277 @@ + + + Polymer({ + + is: 'iron-iconset', + + properties: { + + /** + * The URL of the iconset image. + * + * @attribute src + * @type string + * @default '' + */ + src: { + type: String, + observer: '_srcChanged' + }, + + /** + * The name of the iconset. + * + * @attribute name + * @type string + * @default 'no-name' + */ + name: { + type: String, + observer: '_nameChanged' + }, + + /** + * The width of the iconset image. This must only be specified if the + * icons are arranged into separate rows inside the image. + * + * @attribute width + * @type number + * @default 0 + */ + width: { + type: Number, + value: 0 + }, + + /** + * A space separated list of names corresponding to icons in the iconset + * image file. This list must be ordered the same as the icon images + * in the image file. + * + * @attribute icons + * @type string + * @default '' + */ + icons: { + type: String + }, + + /** + * The size of an individual icon. Note that icons must be square. + * + * @attribute size + * @type number + * @default 24 + */ + size: { + type: Number, + value: 24 + }, + + /** + * The horizontal offset of the icon images in the inconset src image. + * This is typically used if the image resource contains additional images + * beside those intended for the iconset. + * + * @attribute offset-x + * @type number + * @default 0 + */ + _offsetX: { + type: Number, + value: 0 + }, + + /** + * The vertical offset of the icon images in the inconset src image. + * This is typically used if the image resource contains additional images + * beside those intended for the iconset. + * + * @attribute offset-y + * @type number + * @default 0 + */ + _offsetY: { + type: Number, + value: 0 + }, + + /** + * Array of fully-qualified names of icons in this set. + */ + iconNames: { + type: Array, + notify: true + } + + }, + + hostAttributes: { + // non-visual + style: 'display: none;' + }, + + ready: function() { + // theme data must exist at ready-time + this._themes = this._mapThemes(); + }, + + /** + * Applies an icon to the given element as a css background image. This + * method does not size the element, and it's usually necessary to set + * the element's height and width so that the background image is visible. + * + * @method applyIcon + * @param {Element} element The element to which the icon is applied. + * @param {String|Number} icon The name or index of the icon to apply. + * @param {String} theme (optional) The name or index of the icon to apply. + * @param {Number} scale (optional, defaults to 1) Icon scaling factor. + * @return {Element} The applied icon element. + */ + applyIcon: function(element, icon, theme, scale) { + this._validateIconMap(); + var offset = this._getThemedOffset(icon, theme); + if (element && offset) { + this._addIconStyles(element, this._srcUrl, offset, scale || 1, + this.size, this.width); + } + }, + + /** + * Remove an icon from the given element by undoing the changes effected + * by `applyIcon`. + * + * @param {Element} element The element from which the icon is removed. + */ + removeIcon: function(element) { + this._removeIconStyles(element.style); + }, + + _mapThemes: function() { + var themes = Object.create(null); + Polymer.dom(this).querySelectorAll('property[theme]') + .forEach(function(property) { + var offsetX = window.parseInt( + property.getAttribute('offset-x'), 10 + ) || 0; + var offsetY = window.parseInt( + property.getAttribute('offset-y'), 10 + ) || 0; + themes[property.getAttribute('theme')] = { + offsetX: offsetX, + offsetY: offsetY + }; + }); + return themes; + }, + + _srcChanged: function(src) { + // ensure `srcUrl` is always relative to the main document + this._srcUrl = this.ownerDocument !== document + ? this.resolveUrl(src) : src; + this._prepareIconset(); + }, + + _nameChanged: function(name) { + this._prepareIconset(); + }, + + _prepareIconset: function() { + new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); + }, + + _invalidateIconMap: function() { + this._iconMapValid = false; + }, + + _validateIconMap: function() { + if (!this._iconMapValid) { + this._recomputeIconMap(); + this._iconMapValid = true; + } + }, + + _recomputeIconMap: function() { + this.iconNames = this._computeIconNames(this.icons); + this.iconMap = this._computeIconMap(this._offsetX, this._offsetY, + this.size, this.width, this.iconNames); + }, + + _computeIconNames: function(icons) { + return icons.split(/\s+/g); + }, + + _computeIconMap: function(offsetX, offsetY, size, width, iconNames) { + var iconMap = {}; + if (offsetX !== undefined && offsetY !== undefined) { + var x0 = offsetX; + iconNames.forEach(function(iconName) { + iconMap[iconName] = { + offsetX: offsetX, + offsetY: offsetY + }; + if ((offsetX + size) < width) { + offsetX += size; + } else { + offsetX = x0; + offsetY += size; + } + }, this); + } + return iconMap; + }, + + /** + * Returns an object containing `offsetX` and `offsetY` properties which + * specify the pixel location in the iconset's src file for the given + * `icon` and `theme`. It's uncommon to call this method. It is useful, + * for example, to manually position a css backgroundImage to the proper + * offset. It's more common to use the `applyIcon` method. + * + * @method getThemedOffset + * @param {String|Number} identifier The name of the icon or the index of + * the icon within in the icon image. + * @param {String} theme The name of the theme. + * @returns {Object} An object specifying the offset of the given icon + * within the icon resource file; `offsetX` is the horizontal offset and + * `offsetY` is the vertical offset. Both values are in pixel units. + */ + _getThemedOffset: function(identifier, theme) { + var iconOffset = this._getIconOffset(identifier); + var themeOffset = this._themes[theme]; + if (iconOffset && themeOffset) { + return { + offsetX: iconOffset.offsetX + themeOffset.offsetX, + offsetY: iconOffset.offsetY + themeOffset.offsetY + }; + } + return iconOffset; + }, + + _getIconOffset: function(identifier) { + // TODO(sjmiles): consider creating offsetArray (indexed by Number) + // and having iconMap map names to indices, then and index is just + // iconMap[identifier] || identifier (be careful of zero, store indices + // as 1-based) + return this.iconMap[identifier] || + this.iconMap[this.iconNames[Number(identifier)]]; + }, + + _addIconStyles: function(element, url, offset, scale, size, width) { + var style = element.style; + style.backgroundImage = 'url(' + url + ')'; + style.backgroundPosition = + (-offset.offsetX * scale + 'px') + ' ' + + (-offset.offsetY * scale + 'px'); + style.backgroundSize = (scale === 1) ? 'auto' : width * scale + 'px'; + style.width = size + 'px'; + style.height = size + 'px'; + element.setAttribute('role', 'img'); + }, + + _removeIconStyles: function(style) { + style.background = ''; + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-iconset/iron-iconset.html b/third_party/polymer/v0_8/components-chromium/iron-iconset/iron-iconset.html new file mode 100644 index 0000000..f6cffff --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-iconset/iron-iconset.html
@@ -0,0 +1,58 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- +/** + * @group Iron Elements + * + * The `iron-iconset` element allows users to define their own icon sets. + * The `src` property specifies the url of the icon image. Multiple icons may + * be included in this image and they may be organized into rows. + * The `icons` property is a space separated list of names corresponding to the + * icons. The names must be ordered as the icons are ordered in the icon image. + * Icons are expected to be square and are the size specified by the `size` + * property. The `width` property corresponds to the width of the icon image + * and must be specified if icons are arranged into multiple rows in the image. + * + * All `iron-iconset` elements are available for use by other `iron-iconset` + * elements via a database keyed by id. Typically, an element author that wants + * to support a set of custom icons uses a `iron-iconset` to retrieve + * and use another, user-defined iconset. + * + * Example: + * + * <iron-iconset id="my-icons" src="my-icons.png" width="96" size="24" + * icons="location place starta stopb bus car train walk"> + * </iron-iconset> + * + * This will automatically register the icon set "my-icons" to the iconset + * database. To use these icons from within another element, make a + * `iron-iconset` element and call the `byId` method to retrieve a + * given iconset. To apply a particular icon to an element, use the + * `applyIcon` method. For example: + * + * iconset.applyIcon(iconNode, 'car'); + * + * Themed icon sets are also supported. The `iron-iconset` can contain child + * `property` elements that specify a theme with an offsetX and offsetY of the + * theme within the icon resource. For example. + * + * <iron-iconset id="my-icons" src="my-icons.png" width="96" size="24" + * icons="location place starta stopb bus car train walk"> + * <property theme="special" offsetX="256" offsetY="24"></property> + * </iron-iconset> + * + * Then a themed icon can be applied like this: + * + * iconset.applyIcon(iconNode, 'car', 'special'); + * + * @element iron-iconset + */ +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-meta/iron-meta.html"> + +</head><body><script src="iron-iconset-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-input/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-input/.bower.json new file mode 100644 index 0000000..9a43046 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-input/.bower.json
@@ -0,0 +1,39 @@ +{ + "name": "iron-input", + "version": "0.8.1", + "authors": "The Polymer Authors", + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": [ + "iron-input.html" + ], + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-input.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/iron-input", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.6", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + }, + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "2aab343ceb47fd96e58c7898ae114deb7fefd20d" + }, + "_source": "git://github.com/PolymerElements/iron-input.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-input" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-input/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-input/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-input/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/iron-input/README.md b/third_party/polymer/v0_8/components-chromium/iron-input/README.md new file mode 100644 index 0000000..3ff15aca --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-input/README.md
@@ -0,0 +1,2 @@ +# iron-input +An input with data binding
diff --git a/third_party/polymer/v0_8/components-chromium/iron-input/bower.json b/third_party/polymer/v0_8/components-chromium/iron-input/bower.json new file mode 100644 index 0000000..a932ef5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-input/bower.json
@@ -0,0 +1,30 @@ +{ + "name": "iron-input", + "version": "0.8.0", + "authors": "The Polymer Authors", + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": [ + "iron-input.html" + ], + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-input.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/iron-input", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.6", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-input/index.html b/third_party/polymer/v0_8/components-chromium/iron-input/index.html new file mode 100644 index 0000000..f6900379 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-input/index.html
@@ -0,0 +1,30 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>iron-input</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-input/iron-input-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-input/iron-input-extracted.js new file mode 100644 index 0000000..5a8c0c3 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-input/iron-input-extracted.js
@@ -0,0 +1,39 @@ + + + Polymer({ + + is: 'iron-input', + + extends: 'input', + + properties: { + + /** + * Use this property instead of `value` for two-way data binding. + */ + bindValue: { + observer: '_bindValueChanged', + type: String + } + + }, + + listeners: { + 'input': '_onInput' + }, + + attached: function() { + this.bindValue = this.value; + }, + + _bindValueChanged: function() { + this.value = this.bindValue; + // manually notify because we don't want to notify until after setting value + this.fire('bind-value-changed', {value: this.bindValue}); + }, + + _onInput: function(event) { + this.bindValue = event.target.value; + } + + })
diff --git a/third_party/polymer/v0_8/components-chromium/iron-input/iron-input.html b/third_party/polymer/v0_8/components-chromium/iron-input/iron-input.html new file mode 100644 index 0000000..afd3735 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-input/iron-input.html
@@ -0,0 +1,22 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> + +<!-- +By default you can only get notified of changes to an `input`'s `value` due to user input: + + <input value="{{myValue::input}}"> + +`iron-input` adds the `bind-value` property that mirrors the `value` property, and can be used +for two-way data binding. `bind-value` will notify if it is changed either by user input or by script. + + <input is="iron-input" bind-value="{{myValue}}"> + +--> +</head><body><script src="iron-input-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-media-query/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-media-query/.bower.json new file mode 100644 index 0000000..f38b103 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-media-query/.bower.json
@@ -0,0 +1,39 @@ +{ + "name": "iron-media-query", + "version": "0.8.2", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-media-query" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/iron-media-query", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#~0.6.1", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0" + }, + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "250bedf7e068fcfeb65596f8d4735c3f6cd59d7b" + }, + "_source": "git://github.com/PolymerElements/iron-media-query.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-media-query" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-media-query/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-media-query/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-media-query/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/iron-media-query/README.md b/third_party/polymer/v0_8/components-chromium/iron-media-query/README.md new file mode 100644 index 0000000..37354d3 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-media-query/README.md
@@ -0,0 +1 @@ +# iron-media-query
diff --git a/third_party/polymer/v0_8/components-chromium/iron-media-query/bower.json b/third_party/polymer/v0_8/components-chromium/iron-media-query/bower.json new file mode 100644 index 0000000..e407932 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-media-query/bower.json
@@ -0,0 +1,31 @@ +{ + "name": "iron-media-query", + "version": "0.8.0", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-media-query" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/iron-media-query", + "ignore": [ + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#~0.6.1", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-media-query/index.html b/third_party/polymer/v0_8/components-chromium/iron-media-query/index.html new file mode 100644 index 0000000..d38ba75 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-media-query/index.html
@@ -0,0 +1,35 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> + <head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>iron-media-query</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + + <style> + body { + margin: 16px; + } + </style> + + </head> + <body> + + <iron-doc-viewer src="iron-media-query.html"></iron-doc-viewer> + + </body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-media-query/iron-media-query-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-media-query/iron-media-query-extracted.js new file mode 100644 index 0000000..6439d3a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-media-query/iron-media-query-extracted.js
@@ -0,0 +1,57 @@ + + + Polymer({ + + is: 'iron-media-query', + + properties: { + + /** + * The Boolean return value of the media query. + * + * @attribute queryMatches + * @type Boolean + * @default false + */ + queryMatches: { + type: Boolean, + value: false, + readOnly: true, + notify: true + }, + + /** + * The CSS media query to evaluate. + * + * @attribute query + * @type String + */ + query: { + type: String, + observer: 'queryChanged' + } + + }, + + created: function() { + this._mqHandler = this.queryHandler.bind(this); + }, + + queryChanged: function(query) { + if (this._mq) { + this._mq.removeListener(this._mqHandler); + } + if (query[0] !== '(') { + query = '(' + query + ')'; + } + this._mq = window.matchMedia(query); + this._mq.addListener(this._mqHandler); + this.queryHandler(this._mq); + }, + + queryHandler: function(mq) { + this._setQueryMatches(mq.matches); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-media-query/iron-media-query.html b/third_party/polymer/v0_8/components-chromium/iron-media-query/iron-media-query.html new file mode 100644 index 0000000..cb93454 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-media-query/iron-media-query.html
@@ -0,0 +1,23 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> + +<!-- +`iron-media-query` can be used to data bind to a CSS media query. +The `query` property is a bare CSS media query. +The `queryMatches` property is a boolean representing if the page matches that media query. + +Example: + + <iron-media-query query="(min-width: 600px)" queryMatches="{{queryMatches}}"></iron-media-query> + +@group Polymer Core Elements +@element iron-media-query +--> + +</head><body><script src="iron-media-query-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-meta/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-meta/.bower.json new file mode 100644 index 0000000..54e22390c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-meta/.bower.json
@@ -0,0 +1,27 @@ +{ + "name": "iron-meta", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/PolymerElements/iron-meta", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "c67091ccb5cca75ea4d103b5ce6ae9703676aa98" + }, + "_source": "git://github.com/PolymerElements/iron-meta.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-meta" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-meta/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-meta/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-meta/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/iron-meta/README.md b/third_party/polymer/v0_8/components-chromium/iron-meta/README.md new file mode 100644 index 0000000..819e336 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-meta/README.md
@@ -0,0 +1,4 @@ +iron-meta +========= + +See the [component page](http://polymerelements.github.io/iron-meta) for more information.
diff --git a/third_party/polymer/v0_8/components-chromium/iron-meta/bower.json b/third_party/polymer/v0_8/components-chromium/iron-meta/bower.json new file mode 100644 index 0000000..1734339 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-meta/bower.json
@@ -0,0 +1,16 @@ +{ + "name": "iron-meta", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-meta/index.html b/third_party/polymer/v0_8/components-chromium/iron-meta/index.html new file mode 100644 index 0000000..789042f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-meta/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="iron-meta.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-meta/iron-meta-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-meta/iron-meta-extracted.js new file mode 100644 index 0000000..579f9c0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-meta/iron-meta-extracted.js
@@ -0,0 +1,298 @@ + + + (function() { + + // monostate data + var metaDatas = {}; + var metaArrays = {}; + + Polymer.IronMeta = Polymer({ + + is: 'iron-meta', + + properties: { + + /** + * The type of meta-data. All meta-data of the same type is stored + * together. + * + * @attribute type + * @type String + * @default 'default' + */ + type: { + type: String, + value: 'default', + observer: '_typeChanged' + }, + + /** + * The key used to store `value` under the `type` namespace. + * + * @attribute key + * @type String + * @default '' + */ + key: { + type: String, + observer: '_keyChanged' + }, + + /** + * The meta-data to store or retrieve. + * + * @attribute value + * @type * + * @default this + */ + value: { + type: Object, + notify: true, + observer: '_valueChanged' + }, + + /** + * If true, `value` is set to the iron-meta instance itself. + * + * @attribute self + * @type Boolean + * @default false + */ + self: { + type: Boolean, + observer: '_selfChanged' + }, + + /** + * Array of all meta-data values for the given type. + * + * @property list + * @type Array + */ + list: { + type: Array, + notify: true + } + + }, + + /** + * Only runs if someone invokes the factory/constructor directly + * e.g. `new Polymer.IronMeta()` + */ + factoryImpl: function(config) { + if (config) { + for (var n in config) { + switch(n) { + case 'type': + case 'key': + case 'value': + this[n] = config[n]; + break; + } + } + } + }, + + created: function() { + // TODO(sjmiles): good for debugging? + this._metaDatas = metaDatas; + this._metaArrays = metaArrays; + }, + + _keyChanged: function(key, old) { + this._resetRegistration(old); + }, + + _valueChanged: function(value) { + this._resetRegistration(this.key); + }, + + _selfChanged: function(self) { + if (self) { + this.value = this; + } + }, + + _typeChanged: function(type) { + this._unregisterKey(this.key); + if (!metaDatas[type]) { + metaDatas[type] = {}; + } + this._metaData = metaDatas[type]; + if (!metaArrays[type]) { + metaArrays[type] = []; + } + this.list = metaArrays[type]; + this._registerKeyValue(this.key, this.value); + }, + + /** + * Retrieves meta data value by key. + * + * @method byKey + * @param {String} key The key of the meta-data to be returned. + * @returns * + */ + byKey: function(key) { + return this._metaData && this._metaData[key]; + }, + + _resetRegistration: function(oldKey) { + this._unregisterKey(oldKey); + this._registerKeyValue(this.key, this.value); + }, + + _unregisterKey: function(key) { + this._unregister(key, this._metaData, this.list); + }, + + _registerKeyValue: function(key, value) { + this._register(key, value, this._metaData, this.list); + }, + + _register: function(key, value, data, list) { + if (key && data && value !== undefined) { + data[key] = value; + list.push(value); + } + }, + + _unregister: function(key, data, list) { + if (key && data) { + if (key in data) { + var value = data[key]; + delete data[key]; + this.arrayDelete(list, value); + } + } + } + + }); + + /** + `iron-meta-query` can be used to access infomation stored in `iron-meta`. + + Examples: + + If I create an instance like this: + + <iron-meta key="info" value="foo/bar"></iron-meta> + + Note that keyUrl="foo/bar" is the metadata I've defined. I could define more + attributes or use child nodes to define additional metadata. + + Now I can access that element (and it's metadata) from any `iron-meta-query` instance: + + var value = new Polymer.IronMetaQuery({key: 'info'}).value; + + @group Polymer Iron Elements + @element iron-meta-query + */ + Polymer.IronMetaQuery = Polymer({ + + is: 'iron-meta-query', + + properties: { + + /** + * The type of meta-data. All meta-data of the same type is stored + * together. + * + * @attribute type + * @type String + * @default 'default' + */ + type: { + type: String, + value: 'default', + observer: '_typeChanged' + }, + + /** + * Specifies a key to use for retrieving `value` from the `type` + * namespace. + * + * @attribute key + * @type String + */ + key: { + type: String, + observer: '_keyChanged' + }, + + /** + * The meta-data to store or retrieve. + * + * @attribute value + * @type * + * @default this + */ + value: { + type: Object, + notify: true, + readOnly: true + }, + + /** + * Array of all meta-data values for the given type. + * + * @property list + * @type Array + */ + list: { + type: Array, + notify: true + } + + }, + + /** + * Actually a factory method, not a true constructor. Only runs if + * someone invokes it directly (via `new Polymer.IronMeta()`); + */ + constructor: function(config) { + if (config) { + for (var n in config) { + switch(n) { + case 'type': + case 'key': + this[n] = config[n]; + break; + } + } + } + }, + + created: function() { + // TODO(sjmiles): good for debugging? + this._metaDatas = metaDatas; + this._metaArrays = metaArrays; + }, + + _keyChanged: function(key) { + this._setValue(this._metaData && this._metaData[key]); + }, + + _typeChanged: function(type) { + this._metaData = metaDatas[type]; + this.list = metaArrays[type]; + if (this.key) { + this._keyChanged(this.key); + } + }, + + /** + * Retrieves meta data value by key. + * + * @method byKey + * @param {String} key The key of the meta-data to be returned. + * @returns * + */ + byKey: function(key) { + return this._metaData && this._metaData[key]; + } + + }); + + })();
diff --git a/third_party/polymer/v0_8/components-chromium/iron-meta/iron-meta.html b/third_party/polymer/v0_8/components-chromium/iron-meta/iron-meta.html new file mode 100644 index 0000000..b7bb6ab --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-meta/iron-meta.html
@@ -0,0 +1,47 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- +`iron-meta` is a generic element you can use for sharing information across the DOM tree. +It uses [monostate pattern](http://c2.com/cgi/wiki?MonostatePattern) such that any +instance of iron-meta has access to the shared +information. You can use `iron-meta` to share whatever you want (or create an extension +[like x-meta] for enhancements). + +The `iron-meta` instances containing your actual data can be loaded in an import, +or constructed in any way you see fit. The only requirement is that you create them +before you try to access them. + +Examples: + +If I create an instance like this: + + <iron-meta key="info" keyUrl="foo/bar"></iron-meta> + +Note that keyUrl="foo/bar" is the metadata I've defined. I could define more +attributes or use child nodes to define additional metadata. + +Now I can access that element (and it's metadata) from any iron-meta instance +via the byKey method, e.g. + + meta.byKey('info').getAttribute('keyUrl'). + +Pure imperative form would be like: + + document.createElement('iron-meta').byKey('info').getAttribute('keyUrl'); + +Or, in a Polymer element, you can include a meta in your template: + + <iron-meta id="meta"></iron-meta> + ... + this.$.meta.byKey('info').getAttribute('keyUrl'); + +@group Polymer Iron Elements +@element iron-meta +--><html><head><link rel="import" href="../polymer/polymer.html"> + +</head><body><script src="iron-meta-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/.bower.json b/third_party/polymer/v0_8/components-chromium/iron-selector/.bower.json new file mode 100644 index 0000000..3e060c5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/.bower.json
@@ -0,0 +1,31 @@ +{ + "name": "iron-selector", + "version": "0.8.3", + "private": true, + "main": [ + "iron-selector.html" + ], + "authors": "The Polymer Authors", + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-selector.git" + }, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0" + }, + "homepage": "https://github.com/PolymerElements/iron-selector", + "_release": "0.8.3", + "_resolution": { + "type": "version", + "tag": "v0.8.3", + "commit": "58f87005d6eb717b05668b8a78a7c51c0893eee3" + }, + "_source": "git://github.com/PolymerElements/iron-selector.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-selector" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/.gitignore b/third_party/polymer/v0_8/components-chromium/iron-selector/.gitignore new file mode 100644 index 0000000..b13058c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/.gitignore
@@ -0,0 +1,2 @@ +bower_components +.DS_Store
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/README.md b/third_party/polymer/v0_8/components-chromium/iron-selector/README.md new file mode 100644 index 0000000..31667a3d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/README.md
@@ -0,0 +1,2 @@ +iron-selector +=============
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/bower.json b/third_party/polymer/v0_8/components-chromium/iron-selector/bower.json new file mode 100644 index 0000000..646b3e0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/bower.json
@@ -0,0 +1,21 @@ +{ + "name": "iron-selector", + "version": "0.8.2", + "private": true, + "main": [ + "iron-selector.html" + ], + "authors": "The Polymer Authors", + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-selector.git" + }, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/index.html b/third_party/polymer/v0_8/components-chromium/iron-selector/index.html new file mode 100644 index 0000000..8c0d31d9 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/index.html
@@ -0,0 +1,23 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<html> +<head> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../core-component-page/core-component-page.html"> + +</head> +<body> + + <core-component-page></core-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/iron-multi-selectable-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-multi-selectable-extracted.js new file mode 100644 index 0000000..2aef4e49 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-multi-selectable-extracted.js
@@ -0,0 +1,114 @@ + + + Polymer.IronMultiSelectableBehavior = [ + Polymer.IronSelectableBehavior, { + + properties: { + + /** + * If true, multiple selections are allowed. + * + * @attribute multi + * @type Boolean + * @default false + */ + multi: { + type: Boolean, + value: false, + observer: 'multiChanged' + }, + + /** + * Gets or sets the selected elements. This is used instead of `selected` when `multi` + * is true. + * + * @attribute selectedValues + * @type Array + */ + selectedValues: { + type: Array, + notify: true + }, + + /** + * Returns an array of currently selected items. + * + * @attribute selectedItems + * @type Array + */ + selectedItems: { + type: Array, + readOnly: true, + notify: true + }, + + }, + + observers: [ + '_updateSelected(attrForSelected, selectedValues)' + ], + + /** + * Selects the given value. If the `multi` property is true, then the selected state of the + * `value` will be toggled; otherwise the `value` will be selected. + * + * @method select + * @param {String} value the value to select. + */ + select: function(value) { + if (this.multi) { + if (this.selectedValues) { + this._toggleSelected(value); + } else { + this.selectedValues = [value]; + } + } else { + this.selected = value; + } + }, + + multiChanged: function(multi) { + this._selection.multi = multi; + }, + + _updateSelected: function() { + if (this.multi) { + this._selectMulti(this.selectedValues); + } else { + this._selectSelected(this.selected); + } + }, + + _selectMulti: function(values) { + this._selection.clear(); + if (values) { + for (var i = 0; i < values.length; i++) { + this._selection.setItemSelected(this._valueToItem(values[i]), true); + } + } + }, + + _selectionChange: function() { + var s = this._selection.get(); + if (this.multi) { + this._setSelectedItems(s); + } else { + this._setSelectedItems([s]); + this._setSelectedItem(s); + } + }, + + _toggleSelected: function(value) { + var i = this.selectedValues.indexOf(value); + var unselected = i < 0; + if (unselected) { + this.selectedValues.push(value); + } else { + this.selectedValues.splice(i, 1); + } + this._selection.setItemSelected(this._valueToItem(value), unselected); + } + + } + ]; +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/iron-multi-selectable.html b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-multi-selectable.html new file mode 100644 index 0000000..7aac54c8 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-multi-selectable.html
@@ -0,0 +1,11 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="iron-selectable.html"> + +</head><body><script src="iron-multi-selectable-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selectable-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selectable-extracted.js new file mode 100644 index 0000000..8bcfbf38 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selectable-extracted.js
@@ -0,0 +1,287 @@ + + + Polymer.IronSelectableBehavior = { + + properties: { + + /** + * If you want to use the attribute value of an element for `selected` instead of the index, + * set this to the name of the attribute. + * + * @attribute attrForSelected + * @type String + */ + attrForSelected: { + type: String, + value: null + }, + + /** + * Gets or sets the selected element. The default is to use the index of the item. + * + * @attribute selected + * @type String + */ + selected: { + type: String, + notify: true + }, + + /** + * Returns the currently selected item. + * + * @attribute selectedItem + * @type Object + */ + selectedItem: { + type: Object, + readOnly: true, + notify: true + }, + + /** + * The event that fires from items when they are selected. Selectable + * will listen for this event from items and update the selection state. + * Set to empty string to listen to no events. + * + * @attribute activateEvent + * @type String + * @default 'click' + */ + activateEvent: { + type: String, + value: 'click', + observer: '_activateEventChanged' + }, + + /** + * This is a CSS selector sting. If this is set, only items that matches the CSS selector + * are selectable. + * + * @attribute selectable + * @type String + */ + selectable: String, + + /** + * The class to set on elements when selected. + * + * @attribute selectedClass + * @type String + */ + selectedClass: { + type: String, + value: 'iron-selected' + }, + + /** + * The attribute to set on elements when selected. + * + * @attribute selectedAttribute + * @type String + */ + selectedAttribute: { + type: String, + value: null + } + + }, + + observers: [ + '_updateSelected(attrForSelected, selected)' + ], + + excludedLocalNames: { + 'template': 1 + }, + + created: function() { + this._bindActivateHandler = this._activateHandler.bind(this); + this._bindFilterItem = this._filterItem.bind(this); + this._selection = new Polymer.IronSelection(this._applySelection.bind(this)); + }, + + attached: function() { + this._observer = this._observeItems(this); + this._contentObserver = this._observeContent(this); + }, + + detached: function() { + if (this._observer) { + this._observer.disconnect(); + } + if (this._contentObserver) { + this._contentObserver.disconnect(); + } + this._removeListener(this.activateEvent); + }, + + /** + * Returns an array of selectable items. + * + * @property items + * @type Array + */ + get items() { + var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*'); + return Array.prototype.filter.call(nodes, this._bindFilterItem); + }, + + /** + * Returns the index of the given item. + * + * @method indexOf + * @param {Object} item + * @returns Returns the index of the item + */ + indexOf: function(item) { + return this.items.indexOf(item); + }, + + /** + * Selects the given value. + * + * @method select + * @param {String} value the value to select. + */ + select: function(value) { + this.selected = value; + }, + + /** + * Selects the previous item. + * + * @method selectPrevious + */ + selectPrevious: function() { + var length = this.items.length; + var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % length; + this.selected = this._indexToValue(index); + }, + + /** + * Selects the next item. + * + * @method selectNext + */ + selectNext: function() { + var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.length; + this.selected = this._indexToValue(index); + }, + + _addListener: function(eventName) { + this.addEventListener(eventName, this._bindActivateHandler); + }, + + _removeListener: function(eventName) { + this.removeEventListener(eventName, this._bindActivateHandler); + }, + + _activateEventChanged: function(eventName, old) { + this._removeListener(old); + this._addListener(eventName); + }, + + _updateSelected: function() { + this._selectSelected(this.selected); + }, + + _selectSelected: function(selected) { + this._selection.select(this._valueToItem(this.selected)); + }, + + _filterItem: function(node) { + return !this.excludedLocalNames[node.localName]; + }, + + _valueToItem: function(value) { + return (value == null) ? null : this.items[this._valueToIndex(value)]; + }, + + _valueToIndex: function(value) { + if (this.attrForSelected) { + for (var i = 0, item; item = this.items[i]; i++) { + if (this._valueForItem(item) == value) { + return i; + } + } + } else { + return Number(value); + } + }, + + _indexToValue: function(index) { + if (this.attrForSelected) { + var item = this.items[index]; + if (item) { + return this._valueForItem(item); + } + } else { + return index; + } + }, + + _valueForItem: function(item) { + return item[this.attrForSelected] || item.getAttribute(this.attrForSelected); + }, + + _applySelection: function(item, isSelected) { + if (this.selectedClass) { + this.toggleClass(this.selectedClass, isSelected, item); + } + if (this.selectedAttribute) { + this.toggleAttribute(this.selectedAttribute, isSelected, item); + } + this._selectionChange(); + this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item}); + }, + + _selectionChange: function() { + this._setSelectedItem(this._selection.get()); + }, + + // observe content changes under the given node. + _observeContent: function(node) { + var content = node.querySelector('content'); + if (content && content.parentElement === node) { + return this._observeItems(node.host); + } + }, + + // observe items change under the given node. + _observeItems: function(node) { + var observer = new MutationObserver(function() { + if (this.selected != null) { + this._updateSelected(); + } + }.bind(this)); + observer.observe(node, { + childList: true, + subtree: true + }); + return observer; + }, + + _activateHandler: function(e) { + var t = e.target; + var items = this.items; + while (t && t != this) { + var i = items.indexOf(t); + if (i >= 0) { + var value = this._indexToValue(i); + this._itemActivate(value, t); + return; + } + t = t.parentNode; + } + }, + + _itemActivate: function(value, item) { + if (!this.fire('iron-activate', + {selected: value, item: item}, {cancelable: true}).defaultPrevented) { + this.select(value); + } + } + + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selectable.html b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selectable.html new file mode 100644 index 0000000..3d38f779 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selectable.html
@@ -0,0 +1,11 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="iron-selection.html"> + +</head><body><script src="iron-selectable-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selection-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selection-extracted.js new file mode 100644 index 0000000..f901d5d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selection-extracted.js
@@ -0,0 +1,98 @@ + + + Polymer.IronSelection = function(selectCallback) { + this.selection = []; + this.selectCallback = selectCallback; + }; + + Polymer.IronSelection.prototype = { + + /** + * Retrieves the selected item(s). + * + * @method get + * @returns Returns the selected item(s). If the multi property is true, + * `get` will return an array, otherwise it will return + * the selected item or undefined if there is no selection. + */ + get: function() { + return this.multi ? this.selection : this.selection[0]; + }, + + /** + * Clears all the selection except the ones indicated. + * + * @method clear + * @param {Array} excludes items to be excluded. + */ + clear: function(excludes) { + this.selection.slice().forEach(function(item) { + if (!excludes || excludes.indexOf(item) < 0) { + this.setItemSelected(item, false); + } + }, this); + }, + + /** + * Indicates if a given item is selected. + * + * @method isSelected + * @param {any} item The item whose selection state should be checked. + * @returns Returns true if `item` is selected. + */ + isSelected: function(item) { + return this.selection.indexOf(item) >= 0; + }, + + /** + * Sets the selection state for a given item to either selected or deselected. + * + * @method setItemSelected + * @param {any} item The item to select. + * @param {Boolean} isSelected True for selected, false for deselected. + */ + setItemSelected: function(item, isSelected) { + if (item != null) { + if (isSelected) { + this.selection.push(item); + } else { + var i = this.selection.indexOf(item); + if (i >= 0) { + this.selection.splice(i, 1); + } + } + if (this.selectCallback) { + this.selectCallback(item, isSelected); + } + } + }, + + /** + * Sets the selection state for a given item. If the `multi` property + * is true, then the selected state of `item` will be toggled; otherwise + * the `item` will be selected. + * + * @method select + * @param {any} item The item to select. + */ + select: function(item) { + if (this.multi) { + this.toggle(item); + } else if (this.get() !== item) { + this.setItemSelected(this.get(), false); + this.setItemSelected(item, true); + } + }, + + /** + * Toggles the selection state for `item`. + * + * @method toggle + * @param {any} item The item to toggle. + */ + toggle: function(item) { + this.setItemSelected(item, !this.isSelected(item)); + } + + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selection.html b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selection.html new file mode 100644 index 0000000..0fe482fa --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selection.html
@@ -0,0 +1,10 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> + +</head><body><script src="iron-selection-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selector-extracted.js b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selector-extracted.js new file mode 100644 index 0000000..28487fabf --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selector-extracted.js
@@ -0,0 +1,12 @@ + + + Polymer({ + + is: 'iron-selector', + + behaviors: [ + Polymer.IronMultiSelectableBehavior + ] + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selector.html b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selector.html new file mode 100644 index 0000000..1a8fa8f5b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/iron-selector/iron-selector.html
@@ -0,0 +1,57 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- +`iron-selector` is an element which can be used to manage a list of elements +that can be selected. Tapping on the item will make the item selected. The `selected` indicates +which item is being selected. The default is to use the index of the item. + +Example: + + <iron-selector selected="0"> + <div>Item 1</div> + <div>Item 2</div> + <div>Item 3</div> + </iron-selector> + +If you want to use the attribute value of an element for `selected` instead of the index, +set `attrForSelected` to the name of the attribute. For example, if you want to select item by +`name`, set `attrForSelected` to `name`. + +Example: + + <iron-selector attr-for-selected="name" selected="foo"> + <div name="foo">Foo</div> + <div name="bar">Bar</div> + <div name="zot">Zot</div> + </iron-selector> + +`iron-selector` is not styled. Use the `iron-selected` CSS class to style the selected element. + +Example: + + <style> + .iron-selected { + background: #eee; + } + </style> + + ... + + <iron-selector selected="0"> + <div>Item 1</div> + <div>Item 2</div> + <div>Item 3</div> + </iron-selector> + +@group Polymer Core Elements +@element iron-selector +@homepage github.io +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="iron-multi-selectable.html"> + +</head><body><script src="iron-selector-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-behaviors/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-behaviors/.bower.json new file mode 100644 index 0000000..3a9355d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-behaviors/.bower.json
@@ -0,0 +1,25 @@ +{ + "name": "paper-behaviors", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-behaviors": "polymerelements/iron-behaviors#^0.8.0" + }, + "devDependencies": { + "paper-card": "polymerelements/paper-card#v0.8.0", + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + }, + "homepage": "https://github.com/polymerelements/paper-behaviors", + "version": "0.8.1", + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "516c874900a1d51f7b9a82d8f251b17be0d93499" + }, + "_source": "git://github.com/polymerelements/paper-behaviors.git", + "_target": "^0.8.0", + "_originalSource": "polymerelements/paper-behaviors" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-behaviors/README.md b/third_party/polymer/v0_8/components-chromium/paper-behaviors/README.md new file mode 100644 index 0000000..e793a621 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-behaviors/README.md
@@ -0,0 +1,4 @@ +paper-behaviors +=============== + +These are common behaviors used across `paper-*` elements.
diff --git a/third_party/polymer/v0_8/components-chromium/paper-behaviors/bower.json b/third_party/polymer/v0_8/components-chromium/paper-behaviors/bower.json new file mode 100644 index 0000000..a89bfef --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-behaviors/bower.json
@@ -0,0 +1,14 @@ +{ + "name": "paper-behaviors", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-behaviors": "polymerelements/iron-behaviors#^0.8.0" + }, + "devDependencies": { + "paper-card": "polymerelements/paper-card#v0.8.0", + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-behaviors/index.html b/third_party/polymer/v0_8/components-chromium/paper-behaviors/index.html new file mode 100644 index 0000000..0e01e8a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-behaviors/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-component-page/iron-component-page.html"> + +</head> +<body> + + <iron-component-page></iron-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-behaviors/paper-button-behavior-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-behaviors/paper-button-behavior-extracted.js new file mode 100644 index 0000000..9c0fade --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-behaviors/paper-button-behavior-extracted.js
@@ -0,0 +1,32 @@ + + + Polymer.PaperButtonElevation = { + + properties: { + + _elevation: { + type: Number + } + + }, + + _calculateElevation: function() { + var e = 1; + if (this.disabled || !this.raised) { + e = 0; + } else if (this.active || this.pressed) { + e = 2; + } else if (this.focused) { + e = 3; + } + this._elevation = e; + } + + }; + + Polymer.PaperButtonBehavior = [ + Polymer.IronControlState, + Polymer.IronButtonState, + Polymer.PaperButtonElevation + ]; +
diff --git a/third_party/polymer/v0_8/components-chromium/paper-behaviors/paper-button-behavior.html b/third_party/polymer/v0_8/components-chromium/paper-behaviors/paper-button-behavior.html new file mode 100644 index 0000000..00b4e4c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-behaviors/paper-button-behavior.html
@@ -0,0 +1,12 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-behaviors/iron-button-state.html"> + +</head><body><script src="paper-button-behavior-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-button/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-button/.bower.json new file mode 100644 index 0000000..3613e40 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-button/.bower.json
@@ -0,0 +1,31 @@ +{ + "name": "paper-button", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-ripple": "polymerelements/paper-ripple#^0.8.0", + "paper-card": "polymerelements/paper-card#^0.8.0", + "paper-behaviors": "polymerelements/paper-behaviors#^0.8.0" + }, + "devDependencies": { + "iron-component-page": "polymerelements/iron-component-page#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-icons": "polymerelements/iron-icons#^0.8.0", + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + }, + "homepage": "https://github.com/PolymerElements/paper-button", + "version": "0.8.1", + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "1a985b374c6ba563e79ad1c0056b4df63491bd80" + }, + "_source": "git://github.com/PolymerElements/paper-button.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-button" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-button/.gitignore b/third_party/polymer/v0_8/components-chromium/paper-button/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-button/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/paper-button/README.md b/third_party/polymer/v0_8/components-chromium/paper-button/README.md new file mode 100644 index 0000000..c0d5e7b8 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-button/README.md
@@ -0,0 +1,4 @@ +paper-button +============ + +See the [component page](http://www.polymer-project.org/docs/elements/paper-elements.html#paper-button) for more information.
diff --git a/third_party/polymer/v0_8/components-chromium/paper-button/bower.json b/third_party/polymer/v0_8/components-chromium/paper-button/bower.json new file mode 100644 index 0000000..9997f3a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-button/bower.json
@@ -0,0 +1,20 @@ +{ + "name": "paper-button", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-ripple": "polymerelements/paper-ripple#^0.8.0", + "paper-card": "polymerelements/paper-card#^0.8.0", + "paper-behaviors": "polymerelements/paper-behaviors#^0.8.0" + }, + "devDependencies": { + "iron-component-page": "polymerelements/iron-component-page#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-icons": "polymerelements/iron-icons#^0.8.0", + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-button/index.html b/third_party/polymer/v0_8/components-chromium/paper-button/index.html new file mode 100644 index 0000000..0e01e8a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-button/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-component-page/iron-component-page.html"> + +</head> +<body> + + <iron-component-page></iron-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-button/paper-button-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-button/paper-button-extracted.js new file mode 100644 index 0000000..c3a9ab18 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-button/paper-button-extracted.js
@@ -0,0 +1,39 @@ + + + Polymer({ + + behaviors: [ + Polymer.PaperButtonBehavior + ], + + properties: { + + /** + * If true, the button should be styled with a shadow. + * + * @attribute raised + * @type boolean + * @default false + */ + raised: { + type: Boolean, + reflectToAttribute: true, + value: false, + observer: '_buttonStateChanged' + } + + }, + + ready: function() { + if (!this.hasAttribute('role')) { + this.setAttribute('role', 'button'); + } + }, + + _buttonStateChanged: function() { + this._calculateElevation(); + } + + }); + + \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-button/paper-button.html b/third_party/polymer/v0_8/components-chromium/paper-button/paper-button.html new file mode 100644 index 0000000..4833e37 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-button/paper-button.html
@@ -0,0 +1,117 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--><!-- + +Material Design: <a href="http://www.google.com/design/spec/components/buttons.html">Buttons</a> + +`paper-button` is a button. When the user touches the button, a ripple effect emanates +from the point of contact. It may be flat or raised. A raised button is styled with a +shadow. + +Example: + + <paper-button>flat button</paper-button> + <paper-button raised>raised button</paper-button> + <paper-button noink>No ripple effect</paper-button> + +You may use custom DOM in the button body to create a variety of buttons. For example, to +create a button with an icon and some text: + + <paper-button> + <core-icon icon="favorite"></core-icon> + custom button content + </paper-button> + +## Styling + +Style the button with CSS as you would a normal DOM element. + + /* make #my-button green with yellow text */ + #my-button { + background: green; + color: yellow; + } + +By default, the ripple is the same color as the foreground at 25% opacity. You may +customize the color using this selector: + + /* make #my-button use a blue ripple instead of foreground color */ + #my-button::shadow paper-ripple { + color: blue; + } + +The opacity of the ripple is not customizable via CSS. + +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-card/paper-card.html"> +<link rel="import" href="../paper-ripple/paper-ripple.html"> + +<link rel="import" href="../paper-behaviors/paper-button-behavior.html"> + +</head><body><dom-module id="paper-button"> + + <style> + + :host { + display: inline-block; + position: relative; + box-sizing: border-box; + min-width: 5.14em; + margin: 0 0.29em; + background: transparent; + text-align: center; + font: inherit; + text-transform: uppercase; + outline: none; + border-radius: 3px; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none; + cursor: pointer; + z-index: 0; + } + + :host([disabled]) { + background: #eaeaea; + color: #a8a8a8; + cursor: auto; + pointer-events: none; + } + + :host([noink]) paper-ripple { + display: none; + } + + paper-card { + border-radius: inherit; + } + + .content > ::content * { + text-transform: inherit; + } + + .content { + padding: 0.7em 0.57em + } + </style> + + <template> + + <paper-ripple></paper-ripple> + + <paper-card class="content" elevation="[[_elevation]]" animated=""> + <content></content> + </paper-card> + + </template> + + </dom-module> + +<script src="paper-button-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-card/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-card/.bower.json new file mode 100644 index 0000000..6aa4d5eb --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-card/.bower.json
@@ -0,0 +1,27 @@ +{ + "name": "paper-card", + "version": "0.8.2", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-styles": "polymerelements/paper-styles#^0.8.0" + }, + "devDependencies": { + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/PolymerElements/paper-card", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "ec06cea50b93ee58f0473cd2749e768aa63ff406" + }, + "_source": "git://github.com/PolymerElements/paper-card.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-card" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-card/.gitignore b/third_party/polymer/v0_8/components-chromium/paper-card/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-card/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/paper-card/bower.json b/third_party/polymer/v0_8/components-chromium/paper-card/bower.json new file mode 100644 index 0000000..e7fb92bd --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-card/bower.json
@@ -0,0 +1,17 @@ +{ + "name": "paper-card", + "version": "0.8.0", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-styles": "polymerelements/paper-styles#^0.8.0" + }, + "devDependencies": { + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-card/paper-card-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-card/paper-card-extracted.js new file mode 100644 index 0000000..4bd2b3e2 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-card/paper-card-extracted.js
@@ -0,0 +1,38 @@ + + Polymer({ + is: 'paper-card', + + enableCustomStyleProperties: true, + + properties: { + + /** + * The z-depth of this card, from 0-5. Setting to 0 will remove the + * shadow, and each increasing number greater than 0 will be "deeper" + * than the last. + * + * @attribute elevation + * @type number + * @default 1 + */ + elevation: { + type: Number, + reflectToAttribute: true, + value: 1 + }, + + /** + * Set this to true to animate the shadow when setting a new + * `elevation` value. + * + * @attribute animated + * @type boolean + * @default false + */ + animated: { + type: Boolean, + reflectToAttribute: true, + value: false + } + } + });
diff --git a/third_party/polymer/v0_8/components-chromium/paper-card/paper-card.html b/third_party/polymer/v0_8/components-chromium/paper-card/paper-card.html new file mode 100644 index 0000000..09e58c6d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-card/paper-card.html
@@ -0,0 +1,55 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- + +`paper-card` is a container that renders two shadows on top of each other to +create the effect of a lifted piece of paper. + +Example: + + <paper-card elevation="1"> + ... card content ... + </paper-card> + +@group Paper Elements +@class paper-card +--><html><head><link href="../polymer/polymer.html" rel="import"> +<link href="../paper-styles/shadow.html" rel="import"> +</head><body><dom-module id="paper-card"> + <style> + :host { + display: block; + position: relative; + mixin(--shadow-transition); + } + + :host([elevation="1"]) { + mixin(--shadow-elevation-1); + } + + :host([elevation="2"]) { + mixin(--shadow-elevation-2); + } + + :host([elevation="3"]) { + mixin(--shadow-elevation-3); + } + + :host([elevation="4"]) { + mixin(--shadow-elevation-4); + } + + :host([elevation="5"]) { + mixin(--shadow-elevation-5); + } + </style> + <template> + <content></content> + </template> +</dom-module> +<script src="paper-card-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-checkbox/.bower.json new file mode 100644 index 0000000..5a0ef5aa --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/.bower.json
@@ -0,0 +1,42 @@ +{ + "name": "paper-checkbox", + "version": "0.8.2", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-checkbox" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-checkbox", + "ignore": [], + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#~0.6.1", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^0.8.0" + }, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-ripple": "PolymerElements/paper-ripple#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "5e3c7d3b68bd13f711b1a6470ca1bda09f2dc9ae" + }, + "_source": "git://github.com/PolymerElements/paper-checkbox.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-checkbox" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/.gitignore b/third_party/polymer/v0_8/components-chromium/paper-checkbox/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/README.md b/third_party/polymer/v0_8/components-chromium/paper-checkbox/README.md new file mode 100644 index 0000000..0fb7283 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/README.md
@@ -0,0 +1 @@ +# paper-checkbox
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/bower.json b/third_party/polymer/v0_8/components-chromium/paper-checkbox/bower.json new file mode 100644 index 0000000..4f1f986 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/bower.json
@@ -0,0 +1,34 @@ +{ + "name": "paper-checkbox", + "version": "0.8.0", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-checkbox" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-checkbox", + "ignore": [ + ], + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#~0.6.1", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^0.8.0" + }, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-ripple": "PolymerElements/paper-ripple#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/index.html b/third_party/polymer/v0_8/components-chromium/paper-checkbox/index.html new file mode 100644 index 0000000..a2ad87c1 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/index.html
@@ -0,0 +1,30 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> + <head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>paper-checkbox</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + + </head> + <body> + + <iron-doc-viewer></iron-doc-viewer> + + </body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/metadata.html b/third_party/polymer/v0_8/components-chromium/paper-checkbox/metadata.html new file mode 100644 index 0000000..4d068e8 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/metadata.html
@@ -0,0 +1,17 @@ +<!-- + @license + Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<x-meta id="paper-checkbox" label="Checkbox" group="Paper"> + <template> + <paper-checkbox label="click me"></paper-checkbox> + </template> + <template id="imports"> + <link rel="import" href="paper-checkbox.html"> + </template> +</x-meta>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox-extracted.js new file mode 100644 index 0000000..acf136cb --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox-extracted.js
@@ -0,0 +1,103 @@ + + Polymer({ + is: 'paper-checkbox', + + // The custom properties shim is currently an opt-in feature. + enableCustomStyleProperties: true, + + hostAttributes: { + role: 'checkbox', + 'aria-checked': false, + tabindex: 0 + }, + + properties: { + /** + * Fired when the checked state changes due to user interaction. + * + * @event change + */ + + /** + * Fired when the checked state changes. + * + * @event iron-change + */ + + /** + * Gets or sets the state, `true` is checked and `false` is unchecked. + * + * @attribute checked + * @type boolean + * @default false + */ + checked: { + type: Boolean, + value: false, + reflectToAttribute: true, + observer: '_checkedChanged' + }, + + /** + * If true, the user cannot interact with this element. + * + * @attribute disabled + * @type boolean + * @default false + */ + disabled: { + type: Boolean + } + }, + + listeners: { + keydown: '_onKeyDown', + mousedown: '_onMouseDown' + }, + + ready: function() { + if (this.$.checkboxLabel.textContent == '') { + this.$.checkboxLabel.hidden = true; + } else { + this.setAttribute('aria-label', this.$.checkboxLabel.textContent); + } + }, + + _computeCheckboxClass: function(checked) { + if (checked) { + return 'checked'; + } + }, + + _computeCheckmarkClass: function(checked) { + if (!checked) { + return 'hidden'; + } + }, + + _onKeyDown: function(e) { + // Enter key. + if (e.keyCode === 13) { + this._onMouseDown(); + e.preventDefault(); + } + }, + + _onMouseDown: function() { + if (this.disabled) { + return; + } + + var old = this.checked; + this.checked = !this.checked; + + if (this.checked !== old) { + this.fire('iron-change'); + } + }, + + _checkedChanged: function() { + this.setAttribute('aria-checked', this.checked ? 'true' : 'false'); + this.fire('iron-change'); + } + })
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox.css b/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox.css new file mode 100644 index 0000000..b4fdad9 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox.css
@@ -0,0 +1,138 @@ +/* +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +:host { + display: inline-block; + white-space: nowrap; +} + +.hidden { + display: none; +} + +#checkboxContainer { + display: inline-block; + position: relative; + width: 18px; + height: 18px; + cursor: pointer; + -webkit-transform: translateZ(0); + transform: translateZ(0); + vertical-align: middle; +} + +:host #ink { + position: absolute; + top: -15px; + left: -15px; + width: 48px; + height: 48px; + color: var(--paper-checkbox-unchecked-ink-color); +} + +:host #ink[checked] { + color: var(--paper-checkbox-checked-ink-color); +} + +:host #checkbox { + position: relative; + box-sizing: border-box; + height: 100%; + border: solid 2px; + border-color: var(--paper-checkbox-unchecked-color); + border-radius: 2px; + pointer-events: none; + -webkit-transition: background-color 140ms, border-color 140ms; + transition: background-color 140ms, border-color 140ms; +} + +/* checkbox checked animations */ +#checkbox.checked #checkmark { + -webkit-animation: checkmark-expand 140ms ease-out forwards; + animation: checkmark-expand 140ms ease-out forwards; +} + +@-webkit-keyframes checkmark-expand { + 0% { + top: 9px; + left: 6px; + width: 0px; + height: 0px; + } + 100% { + top: -1px; + left: 4px; + width: 5px; + height: 10px; + } +} + +@keyframes checkmark-expand { + 0% { + top: 9px; + left: 6px; + width: 0px; + height: 0px; + } + 100% { + top: -1px; + left: 4px; + width: 5px; + height: 10px; + } +} + +:host #checkbox.checked { + background-color: var(--paper-checkbox-checked-color); + border-color: var(--paper-checkbox-checked-color); +} + +:host #checkmark { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + top: -1px; + left: 4px; + width: 5px; + height: 10px; + border-style: solid; + border-top: none; + border-left: none; + border-right-width: 2px; + border-bottom-width: 2px; + border-color: white; +} + +/* label */ +#checkboxLabel { + position: relative; + display: inline-block; + vertical-align: middle; + padding-left: 8px; + white-space: normal; + pointer-events: none; +} + +#checkboxLabel[hidden] { + display: none; +} + +/* disabled state */ +:host([disabled]) { + pointer-events: none; +} + +:host([disabled]) #checkbox { + opacity: 0.33; + border-color: var(--paper-checkbox-unchecked-color); +} + +:host([disabled][checked]) #checkbox { + background-color: var(--paper-checkbox-unchecked-color); +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox.html b/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox.html new file mode 100644 index 0000000..dd346b5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-checkbox/paper-checkbox.html
@@ -0,0 +1,72 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-ripple/paper-ripple.html"> +<link rel="import" href="../paper-styles/default-theme.html"> + +<!-- +`paper-checkbox` is a button that can be either checked or unchecked. User +can tap the checkbox to check or uncheck it. Usually you use checkboxes +to allow user to select multiple options from a set. If you have a single +ON/OFF option, avoid using a single checkbox and use `paper-toggle-button` +instead. + +Example: + + <paper-checkbox>label</paper-checkbox> + + <paper-checkbox checked> label</paper-checkbox> + +Styling a checkbox: + +<style is="x-style"> + * { + /* Unhecked state colors. */ + --paper-checkbox-unchecked-color: #5a5a5a; + --paper-checkbox-unchecked-ink-color: #5a5a5a; + + /* Checked state colors. */ + --paper-checkbox-checked-color: #009688; + --paper-checkbox-checked-ink-color: #009688; + } +</style> + +@group Paper Elements +@class paper-checkbox +--> + +</head><body>/* TODO: This needs to use core-focusable when it's ready. */ +<dom-module id="paper-checkbox"> + <style is="x-style"> + * { + --paper-checkbox-unchecked-color: var(--primary-text-color); + --paper-checkbox-unchecked-ink-color: var(--primary-text-color); + + --paper-checkbox-checked-color: var(--default-primary-color); + --paper-checkbox-checked-ink-color: var(--default-primary-color); + } + </style> + + <link rel="import" type="css" href="paper-checkbox.css"> + + <template> + + <div id="checkboxContainer"> + <paper-ripple id="ink" class="circle" recenters="" checked$="[[checked]]"></paper-ripple> + <div id="checkbox" class$="[[_computeCheckboxClass(checked)]]"> + <div id="checkmark" class$="[[_computeCheckmarkClass(checked)]]"></div> + </div> + </div> + + <div id="checkboxLabel" aria-hidden="true"><content></content></div> + + </template> +</dom-module> + +<script src="paper-checkbox-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/.bower.json new file mode 100644 index 0000000..869778b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/.bower.json
@@ -0,0 +1,39 @@ +{ + "name": "paper-drawer-panel", + "version": "0.8.1", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-drawer-panel.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-drawer-panel", + "dependencies": { + "iron-selector": "PolymerElements/iron-selector#^0.8.0", + "iron-media-query": "PolymerElements/iron-media-query#^0.8.0", + "polymer": "Polymer/polymer#v0.8.0-rc.6" + }, + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "e7a396050ffee2fdbc2997133e50f2c60f64f154" + }, + "_source": "git://github.com/PolymerElements/paper-drawer-panel.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-drawer-panel" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/.gitignore b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/.gitignore new file mode 100644 index 0000000..fbe05fc --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/.gitignore
@@ -0,0 +1 @@ +bower_components/
diff --git a/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/README.md b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/README.md new file mode 100644 index 0000000..91d479d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/README.md
@@ -0,0 +1 @@ +paper-drawer-panel
diff --git a/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/bower.json b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/bower.json new file mode 100644 index 0000000..0c46b57 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/bower.json
@@ -0,0 +1,30 @@ +{ + "name": "paper-drawer-panel", + "version": "0.8.0", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-drawer-panel.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-drawer-panel", + "dependencies": { + "iron-selector": "PolymerElements/iron-selector#^0.8.0", + "iron-media-query": "PolymerElements/iron-media-query#^0.8.0", + "polymer": "Polymer/polymer#v0.8.0-rc.6" + }, + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/index.html b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/index.html new file mode 100644 index 0000000..4f53214 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/index.html
@@ -0,0 +1,35 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>paper-drawer-panel</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + + <style> + body { + margin: 16px; + } + </style> + +</head> +<body> + + <iron-doc-viewer src="paper-drawer-panel.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/paper-drawer-panel-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/paper-drawer-panel-extracted.js new file mode 100644 index 0000000..4adf049 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/paper-drawer-panel-extracted.js
@@ -0,0 +1,463 @@ + + + (function() { + + 'use strict'; + + function classNames(obj) { + var classNames = []; + for (var key in obj) { + if (obj.hasOwnProperty(key) && obj[key]) { + classNames.push(key); + } + } + + return classNames.join(' '); + } + + Polymer({ + + is: 'paper-drawer-panel', + + /** + * Fired when the narrow layout changes. + * + * @event paper-responsive-change + * @param {Object} detail + * @param {boolean} detail.narrow true if the panel is in narrow layout. + */ + + /** + * Fired when the selected panel changes. + * + * Listening for this event is an alternative to observing changes in the `selected` attribute. + * This event is fired both when a panel is selected and deselected. + * The `isSelected` detail property contains the selection state. + * + * @event paper-select + * @param {Object} detail + * @param {boolean} detail.isSelected true for selection and false for deselection + * @param {Object} detail.item the panel that the event refers to + */ + + properties: { + + /** + * The panel to be selected when `paper-drawer-panel` changes to narrow + * layout. + * + * @attribute defaultSelected + * @type string + * @default 'main' + */ + defaultSelected: { + type: String, + value: 'main' + }, + + /** + * If true, swipe from the edge is disable. + * + * @attribute disableEdgeSwipe + * @type boolean + * @default false + */ + disableEdgeSwipe: Boolean, + + /** + * If true, swipe to open/close the drawer is disabled. + * + * @attribute disableSwipe + * @type boolean + * @default false + */ + disableSwipe: Boolean, + + // Whether the user is dragging the drawer interactively. + dragging: { + value: false + }, + + /** + * Width of the drawer panel. + * + * @attribute drawerWidth + * @type string + * @default '256px' + */ + drawerWidth: { + type: String, + value: '256px' + }, + + // How many pixels on the side of the screen are sensitive to edge + // swipes and peek. + edgeSwipeSensitivity: { + value: 30 + }, + + /** + * If true, ignore `responsiveWidth` setting and force the narrow layout. + * + * @attribute forceNarrow + * @type boolean + * @default false + */ + forceNarrow: { + observer: 'forceNarrowChanged', + type: Boolean, + value: false + }, + + // Whether the browser has support for the transform CSS property. + hasTransform: { + value: function() { + return 'transform' in this.style; + } + }, + + // Whether the browser has support for the will-change CSS property. + hasWillChange: { + value: function() { + return 'willChange' in this.style; + } + }, + + /** + * Returns true if the panel is in narrow layout. This is useful if you + * need to show/hide elements based on the layout. + * + * @attribute narrow + * @type boolean + * @default false + */ + narrow: { + reflectToAttribute: true, + type: Boolean, + value: false + }, + + // Whether the drawer is peeking out from the edge. + peeking: false, + + /** + * Max-width when the panel changes to narrow layout. + * + * @attribute responsiveWidth + * @type string + * @default '640px' + */ + responsiveWidth: { + type: String, + value: '640px' + }, + + /** + * If true, position the drawer to the right. + * + * @attribute rightDrawer + * @type boolean + * @default false + */ + rightDrawer: { + type: Boolean, + value: false + }, + + /** + * The panel that is being selected. `drawer` for the drawer panel and + * `main` for the main panel. + * + * @attribute selected + * @type string + * @default null + */ + selected: { + reflectToAttribute: true, + type: String, + value: null + }, + + /** + * The attribute on elements that should toggle the drawer on tap, also elements will + * automatically be hidden in wide layout. + */ + drawerToggleAttribute: { + value: 'paper-drawer-toggle' + }, + + /** + * Whether the transition is enabled. + */ + transition: false, + + /** + * Starting X coordinate of a tracking gesture. It is non-null only between trackStart and + * trackEnd events. + */ + _startX: { + value: null + } + + }, + + listeners: { + click: 'onClick', + track: 'onTrack' + + // TODO: Implement tap handlers when taps are supported. + // + // down: 'downHandler', + // up: 'upHandler' + }, + + _computeIronSelectorClass: function(narrow, transition, dragging, rightDrawer) { + return classNames({ + dragging: dragging, + 'narrow-layout': narrow, + 'right-drawer': rightDrawer, + transition: transition + }); + }, + + _computeDrawerStyle: function(drawerWidth) { + return 'width:' + drawerWidth + ';'; + }, + + _computeMainStyle: function(narrow, rightDrawer, drawerWidth) { + var style = ''; + + style += 'left:' + ((narrow || rightDrawer) ? '0' : drawerWidth) + ';' + + if (rightDrawer) { + style += 'right:' + (narrow ? '' : drawerWidth) + ';'; + } else { + style += 'right:;' + } + + return style; + }, + + _computeMediaQuery: function(forceNarrow, responsiveWidth) { + return forceNarrow ? '' : '(max-width: ' + responsiveWidth + ')'; + }, + + _computeSwipeOverlayHidden: function(narrow, disableEdgeSwipe) { + return !narrow || disableEdgeSwipe; + }, + + onTrack: function(event) { + switch (event.detail.state) { + case 'end': + this.trackEnd(event); + break; + case 'move': + this.trackX(event); + break; + case 'start': + this.trackStart(event); + break; + } + }, + + ready: function() { + // Avoid transition at the beginning e.g. page loads and enable + // transitions only after the element is rendered and ready. + this.transition = true; + }, + + /** + * Toggles the panel open and closed. + * + * @method togglePanel + */ + togglePanel: function() { + if (this.isMainSelected()) { + this.openDrawer(); + } else { + this.closeDrawer(); + } + }, + + /** + * Opens the drawer. + * + * @method openDrawer + */ + openDrawer: function() { + this.selected = 'drawer'; + }, + + /** + * Closes the drawer. + * + * @method closeDrawer + */ + closeDrawer: function() { + this.selected = 'main'; + }, + + _responsiveChange: function(narrow) { + this.narrow = narrow; + + if (this.narrow) { + this.selected = this.defaultSelected; + } + + this.setAttribute('touch-action', this.swipeAllowed() ? 'pan-y' : ''); + this.fire('paper-responsive-change', {narrow: this.narrow}); + }, + + onQueryMatchesChanged: function(e) { + this._responsiveChange(e.detail.value); + }, + + forceNarrowChanged: function() { + this._responsiveChange(this.forceNarrow); + }, + + swipeAllowed: function() { + return this.narrow && !this.disableSwipe; + }, + + isMainSelected: function() { + return this.selected === 'main'; + }, + + startEdgePeek: function() { + this.width = this.$.drawer.offsetWidth; + this.moveDrawer(this.translateXForDeltaX(this.rightDrawer ? + -this.edgeSwipeSensitivity : this.edgeSwipeSensitivity)); + this.peeking = true; + }, + + stopEdgePeek: function() { + if (this.peeking) { + this.peeking = false; + this.moveDrawer(null); + } + }, + + // TODO: Implement tap handlers when taps are supported. + // + // downHandler: function(e) { + // if (!this.dragging && this.isMainSelected() && this.isEdgeTouch(e)) { + // this.startEdgePeek(); + // } + // }, + // + // upHandler: function(e) { + // this.stopEdgePeek(); + // }, + + onClick: function(e) { + var isTargetToggleElement = e.target && + this.drawerToggleAttribute && + e.target.hasAttribute(this.drawerToggleAttribute); + + if (isTargetToggleElement) { + this.togglePanel(); + } + }, + + isEdgeTouch: function(event) { + var x = event.detail.x; + + return !this.disableEdgeSwipe && this.swipeAllowed() && + (this.rightDrawer ? + x >= this.offsetWidth - this.edgeSwipeSensitivity : + x <= this.edgeSwipeSensitivity); + }, + + trackStart: function(event) { + if (this.swipeAllowed()) { + this.dragging = true; + this._startX = event.detail.x; + + if (this.isMainSelected()) { + this.dragging = this.peeking || this.isEdgeTouch(event); + } + + if (this.dragging) { + this.width = this.$.drawer.offsetWidth; + this.transition = false; + + // TODO: Re-enable when tap gestures are implemented. + // + // e.preventTap(); + } + } + }, + + translateXForDeltaX: function(deltaX) { + var isMain = this.isMainSelected(); + + if (this.rightDrawer) { + return Math.max(0, isMain ? this.width + deltaX : deltaX); + } else { + return Math.min(0, isMain ? deltaX - this.width : deltaX); + } + }, + + trackX: function(event) { + var dx = event.detail.x - this._startX; + + if (this.dragging) { + if (this.peeking) { + if (Math.abs(dx) <= this.edgeSwipeSensitivity) { + // Ignore trackx until we move past the edge peek. + return; + } + + this.peeking = false; + } + + this.moveDrawer(this.translateXForDeltaX(dx)); + } + }, + + trackEnd: function(event) { + if (this.dragging) { + var xDirection = (event.detail.x - this._startX) > 0; + + this.dragging = false; + this._startX = null; + this.transition = true; + this.moveDrawer(null); + + if (this.rightDrawer) { + this[(xDirection > 0) ? 'closeDrawer' : 'openDrawer'](); + } else { + this[(xDirection > 0) ? 'openDrawer' : 'closeDrawer'](); + } + } + }, + + transformForTranslateX: function(translateX) { + if (translateX === null) { + return ''; + } + + return this.hasWillChange ? 'translateX(' + translateX + 'px)' : + 'translate3d(' + translateX + 'px, 0, 0)'; + }, + + moveDrawer: function(translateX) { + var s = this.$.drawer.style; + + if (this.hasTransform) { + s.transform = this.transformForTranslateX(translateX); + } else { + s.webkitTransform = this.transformForTranslateX(translateX); + } + }, + + onSelect: function(e) { + e.preventDefault(); + this.selected = e.detail.selected; + } + + }); + + }()); +
diff --git a/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/paper-drawer-panel.html b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/paper-drawer-panel.html new file mode 100644 index 0000000..107006c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-drawer-panel/paper-drawer-panel.html
@@ -0,0 +1,253 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-media-query/iron-media-query.html"> +<link rel="import" href="../iron-selector/iron-selector.html"> + +<!-- +`paper-drawer-panel` contains a drawer panel and a main panel. The drawer +and the main panel are side-by-side with drawer on the left. When the browser +window size is smaller than the `responsiveWidth`, `paper-drawer-panel` +changes to narrow layout. In narrow layout, the drawer will be stacked on top +of the main panel. The drawer will slide in/out to hide/reveal the main +panel. + +Use the attribute `drawer` to indicate that the element is the drawer panel and +`main` to indicate that the element is the main panel. + +Example: + + <paper-drawer-panel> + <div drawer> Drawer panel... </div> + <div main> Main panel... </div> + </paper-drawer-panel> + +The drawer and the main panels are not scrollable. You can set CSS overflow +property on the elements to make them scrollable or use `paper-header-panel`. + +Example: + + <paper-drawer-panel> + <paper-header-panel drawer> + <paper-toolbar></paper-toolbar> + <div> Drawer content... </div> + </paper-header-panel> + <paper-header-panel main> + <paper-toolbar></paper-toolbar> + <div> Main content... </div> + </paper-header-panel> + </paper-drawer-panel> + +An element that should toggle the drawer will automatically do so if it's +given the `paper-drawer-toggle` attribute. Also this element will automatically +be hidden in wide layout. + +Example: + + <paper-drawer-panel> + <paper-header-panel drawer> + <paper-toolbar> + <div>Application</div> + </paper-toolbar> + <div> Drawer content... </div> + </paper-header-panel> + <paper-header-panel main> + <paper-toolbar> + <paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button> + <div>Title</div> + </paper-toolbar> + <div> Main content... </div> + </paper-header-panel> + </paper-drawer-panel> + +To position the drawer to the right, add `rightDrawer` attribute. + + <paper-drawer-panel rightDrawer> + <div drawer> Drawer panel... </div> + <div main> Main panel... </div> + </paper-drawer-panel> + +@group Polymer Elements +@element paper-drawer-panel +@homepage github.io +--> + +</head><body><dom-module id="paper-drawer-panel"> + + <style> + :host { + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + } + + iron-selector > #drawer { + position: absolute; + top: 0; + left: 0; + height: 100%; + will-change: transform; + box-sizing: border-box; + -moz-box-sizing: border-box; + } + + .transition > #drawer { + transition: -webkit-transform ease-in-out 0.3s, width ease-in-out 0.3s; + transition: transform ease-in-out 0.3s, width ease-in-out 0.3s; + } + + /* + right-drawer: make drawer on the right side + */ + .right-drawer > #drawer { + left: auto; + right: 0; + } + + paper-drawer-panel #drawer > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + } + + iron-selector > #main { + position: absolute; + top: 0; + right: 0; + bottom: 0; + } + + .transition > #main { + transition: left ease-in-out 0.3s, padding ease-in-out 0.3s; + } + + .right-drawer > #main { + left: 0; + } + + .right-drawer.transition > #main { + transition: right ease-in-out 0.3s, padding ease-in-out 0.3s; + } + + #main > [main] { + height: 100%; + } + + #scrim { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.3); + visibility: hidden; + opacity: 0; + transition: opacity ease-in-out 0.38s, visibility ease-in-out 0.38s; + } + + #edgeSwipeOverlay { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 20px; + } + + .right-drawer > #main > #edgeSwipeOverlay { + right: 0; + left: auto; + } + + /* + narrow layout + */ + .narrow-layout > #drawer.iron-selected { + box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.15); + } + + .right-drawer.narrow-layout > #drawer.iron-selected { + box-shadow: -2px 2px 4px rgba(0, 0, 0, 0.15); + } + + .narrow-layout > #drawer > ::content[select="[drawer]"] > * { + border: 0; + } + + .narrow-layout > #drawer:not(.iron-selected) { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + } + + .right-drawer.narrow-layout > #drawer:not(.iron-selected) { + left: auto; + -webkit-transform: translateX(100%); + transform: translateX(100%); + } + + .narrow-layout > #main { + left: 0 !important; + padding: 0; + } + + .right-drawer.narrow-layout > #main { + left: 0; + right: 0; + padding: 0; + } + + .narrow-layout > #main:not(.iron-selected) > #scrim, + .dragging #scrim { + visibility: visible; + opacity: 1; + } + + .narrow-layout > #main > * { + margin: 0; + min-height: 100%; + left: 0; + right: 0; + box-sizing: border-box; + -moz-box-sizing: border-box; + } + + iron-selector:not(.narrow-layout) #main ::content [paper-drawer-toggle] { + display: none; + } + </style> + + <template> + <iron-media-query on-query-matches-changed="onQueryMatchesChanged" query="[[_computeMediaQuery(forceNarrow, responsiveWidth)]]"> + </iron-media-query> + + <iron-selector attr-for-selected="id" class$="[[_computeIronSelectorClass(narrow, transition, dragging, rightDrawer)]]" on-iron-activate="onSelect" selected="[[selected]]"> + + <div id="main" style$="[[_computeMainStyle(narrow, rightDrawer, drawerWidth)]]"> + <content select="[main]"></content> + <div id="scrim"></div> + <div id="edgeSwipeOverlay" hidden$="[[_computeSwipeOverlayHidden(narrow, disableEdgeSwipe)]]"> + </div> + </div> + + <div id="drawer" style$="[[_computeDrawerStyle(drawerWidth)]]"> + <content select="[drawer]"></content> + </div> + + </iron-selector> + </template> + +</dom-module> + +<script src="paper-drawer-panel-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-input/.bower.json new file mode 100644 index 0000000..9b2481a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/.bower.json
@@ -0,0 +1,44 @@ +{ + "name": "paper-input", + "version": "0.8.1", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": [ + "paper-input.html" + ], + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-input.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-input", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-input": "PolymerElements/iron-input#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.6", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^0.8.2", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + }, + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "a761e0a4f9abac125d7c150e71633fd6bdc07616" + }, + "_source": "git://github.com/PolymerElements/paper-input.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-input" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/.gitignore b/third_party/polymer/v0_8/components-chromium/paper-input/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/README.md b/third_party/polymer/v0_8/components-chromium/paper-input/README.md new file mode 100644 index 0000000..4bb13fc90 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/README.md
@@ -0,0 +1,3 @@ +# paper-input + +`<paper-input>` is a Material Design text field.
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/bower.json b/third_party/polymer/v0_8/components-chromium/paper-input/bower.json new file mode 100644 index 0000000..39d3ff0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/bower.json
@@ -0,0 +1,35 @@ +{ + "name": "paper-input", + "version": "0.8.0", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": [ + "paper-input.html" + ], + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-input.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-input", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-input": "PolymerElements/iron-input#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.6", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^0.8.2", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/index.html b/third_party/polymer/v0_8/components-chromium/paper-input/index.html new file mode 100644 index 0000000..d2f28bbc --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/index.html
@@ -0,0 +1,28 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <title>paper-input</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="paper-input.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-char-counter-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-char-counter-extracted.js new file mode 100644 index 0000000..ad120f8 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-char-counter-extracted.js
@@ -0,0 +1,56 @@ + + +(function() { + + Polymer({ + + is: 'paper-input-char-counter', + + enableCustomStyleProperties: true, + + hostAttributes: { + 'add-on': '' + }, + + properties: { + + /** + * The associated input element. + */ + inputElement: { + type: Object + }, + + /** + * The current value of the input element. + */ + value: { + type: String + }, + + /** + * The character counter string. + */ + charCounter: { + computed: '_computeCharCounter(inputElement,value)', + type: String + } + + }, + + attached: function() { + this.fire('addon-attached'); + }, + + _computeCharCounter: function(inputElement,value) { + var str = value.length; + if (inputElement.hasAttribute('maxlength')) { + str += '/' + inputElement.maxLength; + } + return str; + } + + }); + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-char-counter.html b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-char-counter.html new file mode 100644 index 0000000..29bf6c5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-char-counter.html
@@ -0,0 +1,39 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-styles/paper-styles.html"> + +<!-- +`<paper-input-char-counter>` is a character counter for use with `<paper-input-container>`. +--> +</head><body><dom-module id="paper-input-char-counter"> + + <style> + + :host { + display: inline-block; + float: right; + + mixin(--paper-input-container-add-on); + mixin(--paper-input-container-add-on-font); + + mixin(--paper-input-char-counter); + } + + </style> + + <template> + + <span>[[charCounter]]</span> + + </template> + +</dom-module> + +<script src="paper-input-char-counter-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-container-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-container-extracted.js new file mode 100644 index 0000000..3a7bbcd --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-container-extracted.js
@@ -0,0 +1,203 @@ + +(function() { + + Polymer({ + + is: 'paper-input-container', + + enableCustomStyleProperties: true, + + properties: { + + /** + * Set to true to disable the floating label. + */ + noLabelFloat: { + type: Boolean, + value: false + }, + + /** + * The attribute to listen for value changes on. + */ + attrForValue: { + type: String, + value: 'bind-value' + }, + + /** + * Set to true to auto-validate the input value. + */ + autoValidate: { + type: Boolean, + value: false + }, + + /** + * True if the input has focus. + */ + focused: { + readOnly: true, + type: Boolean, + value: false + }, + + _addons: { + type: Array, + value: function() { + return []; + } + }, + + _inputHasContent: { + type: Boolean, + value: false + }, + + _inputIsInvalid: { + type: Boolean, + value: false + }, + + _inputSelector: { + type: String, + value: 'input,textarea,.paper-input-input' + }, + + _boundOnFocus: { + type: Function, + value: function() { + return this._onFocus.bind(this); + } + }, + + _boundOnBlur: { + type: Function, + value: function() { + return this._onBlur.bind(this); + } + }, + + _boundValueChanged: { + type: Function, + value: function() { + return this._onValueChanged.bind(this); + } + } + + }, + + listeners: { + 'addon-attached': '_onAddonAttached', + 'input': '_onInput' + }, + + get _valueChangedEvent() { + return this.attrForValue + '-changed'; + }, + + get _propertyForValue() { + return Polymer.CaseMap.dashToCamelCase(this.attrForValue); + }, + + get _inputElement() { + return Polymer.dom(this).querySelector(this._inputSelector); + }, + + ready: function() { + this.addEventListener('focus', this._boundOnFocus, true); + this.addEventListener('blur', this._boundOnBlur, true); + this.addEventListener(this._valueChangedEvent, this._boundValueChanged, true); + }, + + attached: function() { + this._handleInput(this._inputElement); + }, + + _onAddonAttached: function(event) { + this._addons.push(event.target); + this._handleInput(this._inputElement); + }, + + _onFocus: function() { + this._setFocused(true); + }, + + _onBlur: function() { + this._setFocused(false); + }, + + _onInput: function(event) { + this._handleInput(event.target); + }, + + _onValueChanged: function(event) { + this._handleInput(event.target); + }, + + _handleInput: function(inputElement) { + var value = inputElement[this._propertyForValue] || inputElement.value; + var valid = inputElement.checkValidity(); + + // type="number" hack needed because this.value is empty until it's valid + if (value || inputElement.type === 'number' && !valid) { + this._inputHasContent = true; + } else { + this._inputHasContent = false; + } + + if (this.autoValidate) { + this._inputIsInvalid = !valid; + } + + // notify add-ons + for (var addon, i = 0; addon = this._addons[i]; i++) { + // need to set all of these, or call method... thanks input type="number"! + addon.inputElement = inputElement; + addon.value = value; + addon.invalid = !valid; + } + }, + + _computeInputContentClass: function(noLabelFloat, focused, _inputHasContent, _inputIsInvalid) { + var cls = 'input-content relative'; + if (!noLabelFloat) { + if (_inputHasContent) { + cls += ' label-is-floating'; + if (_inputIsInvalid) { + cls += ' is-invalid'; + } else if (focused) { + cls += " label-is-highlighted"; + } + } + } else { + if (_inputHasContent) { + cls += ' label-is-hidden'; + } + } + return cls; + }, + + _computeUnderlineClass: function(focused, _inputIsInvalid) { + var cls = 'relative'; + if (_inputIsInvalid) { + cls += ' is-invalid'; + } else if (focused) { + cls += ' is-highlighted' + } + return cls; + }, + + _computeAddOnContentClass: function(focused, _inputIsInvalid) { + var cls = 'add-on-content'; + if (_inputIsInvalid) { + cls += ' is-invalid'; + } else if (focused) { + cls += ' is-highlighted' + } + return cls; + } + + }); + +})();
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-container.html b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-container.html new file mode 100644 index 0000000..d4819e8d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-container.html
@@ -0,0 +1,192 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-styles/paper-styles.html"> + +<style is="x-style"> + + * { + + --paper-input-container-font: var(--paper-font-subhead); + --paper-input-container-floating-label-font: var(--paper-font-caption); + --paper-input-container-add-on-font: var(--paper-font-caption); + + --paper-input-container-focus-color: var(--default-primary-color); + --paper-input-container-color: var(--secondary-text-color); + --paper-input-container-invalid-color: var(--google-red-500); + --paper-input-container-input-color: var(--primary-text-color); + + } + +</style> + +<!-- +`<paper-input-container>` wraps an `<input>` and `<label>` element, decorating +them following the [Material Design spec](http://www.google.com/design/spec/components/text-fields.html#text-fields-single-line-text-field) + +For example: + + <paper-input-container> + <label>email address</label> + <input type="email"> + </paper-input-container> + +--> +</head><body><dom-module id="paper-input-container"> + + <style> + + :host { + display: block; + padding: 8px 0; + + --mixin(--paper-input-container); + } + + .floated-label-placeholder { + mixin(--paper-input-container-label-font); + } + + .focused-line { + height: 2px; + + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: scale3d(0,1,1); + transform: scale3d(0,1,1); + + background: var(--paper-input-container-focus-color); + } + + .is-highlighted .focused-line { + -webkit-transform: none; + transform: none; + -webkit-transition: -webkit-transform 0.25s; + transition: transform 0.25s; + + mixin(--paper-transition-easing); + } + + .is-invalid .focused-line { + background: var(--paper-input-container-invalid-color); + + -webkit-transform: none; + transform: none; + -webkit-transition: -webkit-transform 0.25s; + transition: transform 0.25s; + + mixin(--paper-transition-easing); + } + + .unfocused-line { + height: 1px; + background: var(--paper-input-container-color); + } + + .input-content ::content label, + .input-content ::content .paper-input-label { + position: absolute; + top: 0; + right: 0; + left: 0; + font: inherit; + color: var(--paper-input-container-color); + + mixin(--paper-input-container-font); + + mixin(--paper-input-container-label); + } + + .input-content.label-is-floating ::content label, + .input-content.label-is-floating ::content .paper-input-label { + -webkit-transform: translate3d(0, -75%, 0) scale(0.75); + transform: translate3d(0, -75%, 0) scale(0.75); + -webkit-transform-origin: left top; + transform-origin: left top; + -webkit-transition: -webkit-transform 0.25s; + transition: transform 0.25s; + + mixin(--paper-transition-easing); + } + + .input-content.label-is-highlighted ::content label, + .input-content.label-is-highlighted ::content .paper-input-label { + color: var(--paper-input-container-focus-color); + } + + .input-content.is-invalid ::content label, + .input-content.is-invalid ::content .paper-input-label { + color: var(--paper-input-container-invalid-color); + } + + .input-content.label-is-hidden ::content label, + .input-content.label-is-hidden ::content .paper-input-label { + visibility: hidden; + } + + .input-content ::content input, + .input-content ::content textarea, + .input-content ::content .paper-input-input { + position: relative; /* to make a stacking context */ + outline: none; + color: var(--paper-input-container-input-color); + + mixin(--paper-input-container-floating-label-font); + } + + .input-content ::content input, + .input-content ::content textarea { + padding: 0; + width: 100%; + background: transparent; + border: none; + + mixin(--paper-input-container-font); + + mixin(--paper-input-container-input); + } + + .input-content ::content textarea { + resize: none; + } + + .add-on-content.is-invalid ::content * { + color: var(--paper-input-container-invalid-color); + } + + .add-on-content.is-highlighted ::content * { + color: var(--paper-input-container-focus-color); + } + + </style> + + <template> + + <template is="x-if" if="[[!noLabelFloat]]"> + <div class="floated-label-placeholder"> </div> + </template> + + <div class$="[[_computeInputContentClass(noLabelFloat,focused,_inputHasContent,_inputIsInvalid)]]"> + <content select=":not([add-on])"></content> + </div> + + <div class$="[[_computeUnderlineClass(focused,_inputIsInvalid)]]"> + <div class="unfocused-line fit"></div> + <div class="focused-line fit"></div> + </div> + + <div class$="[[_computeAddOnContentClass(focused,_inputIsInvalid)]]"> + <content id="addOnContent" select="[add-on]"></content> + </div> + + </template> + +</dom-module> + +<script src="paper-input-container-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-error-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-error-extracted.js new file mode 100644 index 0000000..e447df1 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-error-extracted.js
@@ -0,0 +1,35 @@ + + +(function() { + + Polymer({ + + is: 'paper-input-error', + + enableCustomStyleProperties: true, + + hostAttributes: { + 'add-on': '', + 'role': 'alert' + }, + + properties: { + + /** + * Set to true to show the error. + */ + invalid: { + reflectToAttribute: true, + type: Boolean + } + + }, + + attached: function() { + this.fire('addon-attached'); + } + + }) + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-error.html b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-error.html new file mode 100644 index 0000000..5132be2 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-error.html
@@ -0,0 +1,46 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-styles/paper-styles.html"> + +<!-- +`<paper-input-error>` is an error message for use with `<paper-input-container>`. +--> +</head><body><dom-module id="paper-input-error"> + + <style> + + :host { + /* need to use display: none for role="alert" */ + display: none; + float: left; + + color: var(--paper-input-container-invalid-color); + + mixin(--paper-input-container-add-on); + mixin(--paper-input-container-add-on-font); + + mixin(--paper-input-error); + } + + :host([invalid]) { + display: inline-block; + }; + + </style> + + <template> + + <content></content> + + </template> + +</dom-module> + +<script src="paper-input-error-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-extracted.js new file mode 100644 index 0000000..9f85a72 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input-extracted.js
@@ -0,0 +1,105 @@ + + +(function() { + + Polymer({ + + is: 'paper-input', + + properties: { + + /** + * The label for this input. + */ + label: { + type: String + }, + + /** + * The value for this input. + */ + value: { + notify: true, + type: String + }, + + /** + * Set to true to prevent the user from entering invalid input. + */ + preventInvalidInput: { + type: Boolean + }, + + /** + * The type of the input. The supported types are `text`, `number` and `password`. + */ + type: { + type: String + }, + + /** + * A pattern to validate the `input` with. + */ + pattern: { + type: String + }, + + /** + * Set to true to mark the input as required. + */ + required: { + type: Boolean, + value: false + }, + + /** + * The maximum length of the input value. + */ + maxlength: { + type: Number + }, + + /** + * The error message to display when the input is invalid. + */ + errorMessage: { + type: String + }, + + /** + * Set to true to show a character counter. + */ + charCounter: { + type: Boolean, + value: false + }, + + /** + * Set to true to disable the floating label. + */ + noLabelFloat: { + type: Boolean, + value: false + }, + + /** + * Set to true to auto-validate the input value. + */ + autoValidate: { + type: Boolean, + value: false + } + + }, + + /** + * Returns a reference to the input element. + */ + get inputElement() { + return this.$.input; + } + + }) + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/paper-input/paper-input.html b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input.html new file mode 100644 index 0000000..2d8d785 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-input/paper-input.html
@@ -0,0 +1,45 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-input/iron-input.html"> +<link rel="import" href="paper-input-container.html"> +<link rel="import" href="paper-input-error.html"> +<link rel="import" href="paper-input-char-counter.html"> + +<!-- +`<paper-input>` is a text field. +--> + +</head><body><dom-module id="paper-input"> + + <template> + + <paper-input-container no-label-float$="[[noLabelFloat]]" auto-validate$="[[autoValidate]]"> + + <template is="x-if" if="[[label]]"> + <label>[[parent.label]]</label> + </template> + + <input is="iron-input" id="input" bind-value="{{value}}" prevent-invalid-input="[[preventInvalidInput]]" type$="[[type]]" pattern$="[[pattern]]" maxlength$="[[maxlength]]" required$="[[required]]"> + + <template is="x-if" if="[[errorMessage]]"> + <paper-input-error>[[parent.errorMessage]]</paper-input-error> + </template> + + <template is="x-if" if="[[charCounter]]"> + <paper-input-char-counter></paper-input-char-counter> + </template> + + </paper-input-container> + + </template> + +</dom-module> + +<script src="paper-input-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-menu/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-menu/.bower.json new file mode 100644 index 0000000..3bb8166 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-menu/.bower.json
@@ -0,0 +1,40 @@ +{ + "name": "paper-menu", + "version": "0.8.2", + "authors": "The Polymer Authors", + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "paper-menu.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-menu" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-menu", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-selector": "PolymerElements/iron-selector#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "paper-item": "PolymerElements/paper-item#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.0", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + }, + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "a10381891339cb021d1215bd3bcf0eb96251acd9" + }, + "_source": "git://github.com/PolymerElements/paper-menu.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-menu" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-menu/.gitignore b/third_party/polymer/v0_8/components-chromium/paper-menu/.gitignore new file mode 100644 index 0000000..fbe05fc --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-menu/.gitignore
@@ -0,0 +1 @@ +bower_components/
diff --git a/third_party/polymer/v0_8/components-chromium/paper-menu/README.md b/third_party/polymer/v0_8/components-chromium/paper-menu/README.md new file mode 100644 index 0000000..6360e79 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-menu/README.md
@@ -0,0 +1 @@ +# paper-menu
diff --git a/third_party/polymer/v0_8/components-chromium/paper-menu/bower.json b/third_party/polymer/v0_8/components-chromium/paper-menu/bower.json new file mode 100644 index 0000000..9f5a25e --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-menu/bower.json
@@ -0,0 +1,31 @@ +{ + "name": "paper-menu", + "version": "0.8.0", + "authors": "The Polymer Authors", + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "paper-menu.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-menu" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-menu", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-selector": "PolymerElements/iron-selector#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "paper-item": "PolymerElements/paper-item#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.0", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-menu/index.html b/third_party/polymer/v0_8/components-chromium/paper-menu/index.html new file mode 100644 index 0000000..1cf71f5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-menu/index.html
@@ -0,0 +1,38 @@ +<!doctype html> +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>paper-menu</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + + <style> + + body { + margin: 16px; + } + + </style> + +</head> +<body> + + <iron-doc-viewer src="paper-menu.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-menu/paper-menu-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-menu/paper-menu-extracted.js new file mode 100644 index 0000000..e509822 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-menu/paper-menu-extracted.js
@@ -0,0 +1,262 @@ + + +(function() { + + // FIXME menu control should be refactored to a more general element + + Polymer({ + + is: 'paper-menu', + + enableCustomStyleProperties: true, + + mixins: [ + Polymer.Core.Selectable + ], + + properties: { + + /** + * Returns the currently focused item. + * + * @attribute focusedItem + * @type Object + */ + focusedItem: { + observer: 'focusedItemChanged', + readOnly: true, + type: Object + }, + + /** + * The attribute to use on menu items to look up the item title. Typing the first + * letter of an item when the menu is open focuses that item. If unset, `textContent` + * will be used. + * + * @attribute attrForItemTitle + * @type String + */ + attrForItemTitle: { + type: String + }, + + /***********************************************************************/ + /* Polymer.Core.Selectable */ + /***********************************************************************/ + + /** + * If you want to use the attribute value of an element for `selected` instead of the index, + * set this to the name of the attribute. + * + * @attribute attrForSelected + * @type String + */ + attrForSelected: { + type: String + }, + + /** + * If true, multiple selections are allowed. + * + * @attribute multi + * @type Boolean + * @default false + */ + multi: { + observer: 'multiChanged', + type: Boolean, + value: false + }, + + /** + * Gets or sets the selected element. The default is to use the index of the item. In + * multi-selection this should be an array of values. + * + * @attribute selected + * @type String|Array + */ + selected: { + notify: true, + observer: 'selectedChanged', + type: String + }, + + /** + * Returns the currently selected item. In multi-selection this returns an array of + * selected items. + * + * @attribute selectedItem + * @type Object|Array + */ + selectedItem: { + notify: true, + observer: 'selectedItemChanged', + readOnly: true, + type: Object + }, + + /** + * The event that would be fired from the item to indicate it is being selected. Set this + * to empty string or null if you don't want to listen for any events. + * + * @attribute activateEvent + * @type String + * @default 'click' + */ + activateEvent: { + observer: 'activateEventChanged', + type: String, + value: 'click' + }, + + /** + * If this is set, only items with local name that matches the `selectable` are selectable. + * + * @attribute selectable + * @type String + */ + selectable: { + type: String + } + + }, + + hostAttributes: { + 'role': 'menu', + 'tabindex': '0' + }, + + listeners: { + 'focus': 'onFocus', + 'keydown': 'onKeydown' + }, + + created: function() { + this._bindActivateHandler = this.activateHandler.bind(this); + }, + + attached: function() { + this.selectableAttached(); + }, + + detached: function() { + this.selectableDetached(); + this.removeListener(this.activateEvent); + }, + + addListener: function(eventName) { + if (eventName) { + this.addEventListener(eventName, this._bindActivateHandler); + } + }, + + removeListener: function(eventName) { + if (eventName) { + this.removeEventListener(eventName, this._bindActivateHandler); + } + }, + + activateEventChanged: function(eventName, old) { + this.removeListener(old); + this.addListener(eventName); + }, + + focusedItemChanged: function(focusedItem, old) { + old && old.setAttribute('tabindex', '-1'); + if (focusedItem) { + focusedItem.setAttribute('tabindex', '0'); + focusedItem.focus(); + } + }, + + multiChanged: function(multi) { + this.selection.multi = multi; + this.selectedChanged(this.selected); + }, + + selectedChanged: function(selected, old) { + this._selectedChanged(selected, old); + }, + + selectedItemChanged: function(selectedItem) { + this._setFocusedItem(Array.isArray(selectedItem) ? selectedItem[0] : selectedItem); + }, + + activateHandler: function(e) { + var t = e.target; + var items = this.items; + while (t && t != this) { + var i = items.indexOf(t); + if (i >= 0) { + if (t.hasAttribute('disabled')) { + return; + } + var value = this.indexToValue(i); + if (!this.fire('iron-activate', {selected: value, item: t}).defaultPrevented) { + this.select(value); + } + return; + } + t = t.parentNode; + } + }, + + onFocus: function(event) { + // clear the cached focus item + this._setFocusedItem(null); + // focus the selected item when the menu receives focus, or the first item + // if no item is selected + var selectedItem = this.selectedItem; + selectedItem = Array.isArray(selectedItem) ? selectedItem[0] : selectedItem; + if (selectedItem) { + this._setFocusedItem(selectedItem); + } else { + this._setFocusedItem(this.items[0]); + } + }, + + onKeydown: function(event) { + // FIXME want to define these somewhere, core-a11y-keys? + var DOWN = 40; + var UP = 38; + var ESC = 27; + var ENTER = 13; + if (event.keyCode === DOWN) { + // up and down arrows moves the focus + this.focusNext(); + } else if (event.keyCode === UP) { + this.focusPrevious(); + } else if (event.keyCode === ESC) { + // esc blurs the control + this.focusedItem.blur(); + } else if (event.keyCode === ENTER) { + // enter activates the item + this.activateHandler(event); + } else { + // all other keys focus the menu item starting with that character + for (var i = 0, item; item = this.items[i]; i++) { + var attr = this.attrForItemTitle || 'textContent'; + var title = item[attr] || item.getAttribute(attr); + if (title && title.charAt(0).toLowerCase() === String.fromCharCode(event.keyCode).toLowerCase()) { + this._setFocusedItem(item); + break; + } + } + } + }, + + focusPrevious: function() { + var length = this.items.length; + var index = (Number(this.indexOf(this.focusedItem)) - 1 + length) % length; + this._setFocusedItem(this.items[index]); + }, + + focusNext: function() { + var index = (Number(this.indexOf(this.focusedItem)) + 1) % this.items.length; + this._setFocusedItem(this.items[index]); + } + + }); + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/paper-menu/paper-menu.html b/third_party/polymer/v0_8/components-chromium/paper-menu/paper-menu.html new file mode 100644 index 0000000..1055de2 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-menu/paper-menu.html
@@ -0,0 +1,65 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-selector/iron-selectable.html"> +<link rel="import" href="../paper-styles/paper-styles.html"> + +<!-- +@element paper-menu +--> + +</head><body><dom-module id="paper-menu"> + + <style> + + :host { + padding: 8px 0; + + background: var(--primary-background-color); + color: var(--primary-text-color); + + mixin(--paper-menu); + } + + :host > ::content > [disabled] { + color: var(--disabled-text-color); + } + + :host > ::content > .iron-selected { + position: relative; + } + + :host > ::content > .iron-selected::after { + mixin(--fit); + + background: currentColor; + /* FIXME move to paper-styles for next widget */ + opacity: 0.12; + content: ''; + + mixin(--paper-menu-selected-item); + } + + :host > ::content > .iron-selected[colored]::after { + opacity: 0.26; + + mixin(--paper-menu-colored-selected-item); + } + + </style> + + <template> + + <content></content> + + </template> + +</dom-module> + +<script src="paper-menu-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-ripple/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-ripple/.bower.json new file mode 100644 index 0000000..62815ae --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-ripple/.bower.json
@@ -0,0 +1,27 @@ +{ + "name": "paper-ripple", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-icons": "polymerelements/iron-icons#^0.8.0", + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.3" + }, + "homepage": "https://github.com/PolymerElements/paper-ripple", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "7f1399055ff05cc37e3b577d97d00d664816e1d2" + }, + "_source": "git://github.com/PolymerElements/paper-ripple.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-ripple" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-ripple/.gitignore b/third_party/polymer/v0_8/components-chromium/paper-ripple/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-ripple/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components-chromium/paper-ripple/README.md b/third_party/polymer/v0_8/components-chromium/paper-ripple/README.md new file mode 100644 index 0000000..a4ca437 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-ripple/README.md
@@ -0,0 +1,4 @@ +paper-ripple +============ + +See the [component page](http://www.polymer-project.org/docs/elements/paper-elements.html#paper-ripple) for more information.
diff --git a/third_party/polymer/v0_8/components-chromium/paper-ripple/bower.json b/third_party/polymer/v0_8/components-chromium/paper-ripple/bower.json new file mode 100644 index 0000000..5e261d5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-ripple/bower.json
@@ -0,0 +1,16 @@ +{ + "name": "paper-ripple", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-icons": "polymerelements/iron-icons#^0.8.0", + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.3" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-ripple/index.html b/third_party/polymer/v0_8/components-chromium/paper-ripple/index.html new file mode 100644 index 0000000..94102ef3 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-ripple/index.html
@@ -0,0 +1,26 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <title>paper-ripple</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="paper-ripple.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-ripple/paper-ripple-extracted.js b/third_party/polymer/v0_8/components-chromium/paper-ripple/paper-ripple-extracted.js new file mode 100644 index 0000000..af02d203f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-ripple/paper-ripple-extracted.js
@@ -0,0 +1,482 @@ + + (function() { + var Utility = { + cssColorWithAlpha: function(cssColor, alpha) { + var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); + + if (typeof alpha == 'undefined') { + alpha = 1; + } + + if (!parts) { + return 'rgba(255, 255, 255, ' + alpha + ')'; + } + + return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')'; + }, + + distance: function(x1, y1, x2, y2) { + var xDelta = (x1 - x2); + var yDelta = (y1 - y2); + + return Math.sqrt(xDelta * xDelta + yDelta * yDelta); + }, + + now: (function() { + if (window.performance && window.performance.now) { + return window.performance.now.bind(window.performance); + } + + return Date.now; + })() + }; + + /** + * @param {HTMLElement} element + * @constructor + */ + function ElementMetrics(element) { + this.element = element; + this.width = this.boundingRect.width; + this.height = this.boundingRect.height; + + this.size = Math.max(this.width, this.height); + } + + ElementMetrics.prototype = { + get boundingRect () { + return this.element.getBoundingClientRect(); + }, + + furthestCornerDistanceFrom: function(x, y) { + var topLeft = Utility.distance(x, y, 0, 0); + var topRight = Utility.distance(x, y, this.width, 0); + var bottomLeft = Utility.distance(x, y, 0, this.height); + var bottomRight = Utility.distance(x, y, this.width, this.height); + + return Math.max(topLeft, topRight, bottomLeft, bottomRight); + } + }; + + /** + * @param {HTMLElement} element + * @constructor + */ + function Ripple(element) { + this.element = element; + this.color = window.getComputedStyle(element).color; + + this.wave = document.createElement('div'); + this.waveContainer = document.createElement('div'); + this.wave.style.backgroundColor = this.color; + this.wave.classList.add('wave'); + this.waveContainer.classList.add('wave-container'); + Polymer.dom(this.waveContainer).appendChild(this.wave); + + this.resetInteractionState(); + } + + Ripple.MAX_RADIUS = 300; + + Ripple.prototype = { + get recenters() { + return this.element.recenters; + }, + + get mouseDownElapsed() { + var elapsed; + + if (!this.mouseDownStart) { + return 0; + } + + elapsed = Utility.now() - this.mouseDownStart; + + if (this.mouseUpStart) { + elapsed -= this.mouseUpElapsed; + } + + return elapsed; + }, + + get mouseUpElapsed() { + return this.mouseUpStart ? + Utility.now () - this.mouseUpStart : 0; + }, + + get mouseDownElapsedSeconds() { + return this.mouseDownElapsed / 1000; + }, + + get mouseUpElapsedSeconds() { + return this.mouseUpElapsed / 1000; + }, + + get mouseInteractionSeconds() { + return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds; + }, + + get initialOpacity() { + return this.element.initialOpacity; + }, + + get opacityDecayVelocity() { + return this.element.opacityDecayVelocity; + }, + + get radius() { + var width2 = this.containerMetrics.width * this.containerMetrics.width; + var height2 = this.containerMetrics.height * this.containerMetrics.height; + var waveRadius = Math.min( + Math.sqrt(width2 + height2), + Ripple.MAX_RADIUS + ) * 1.1 + 5; + + var duration = 1.1 - 0.2 * (waveRadius / Ripple.MAX_RADIUS); + var timeNow = this.mouseInteractionSeconds / duration; + var size = waveRadius * (1 - Math.pow(80, -timeNow)); + + return Math.abs(size); + }, + + get opacity() { + if (!this.mouseUpStart) { + return this.initialOpacity; + } + + return Math.max( + 0, + this.initialOpacity - this.mouseUpElapsedSeconds * this.opacityDecayVelocity + ); + }, + + get outerOpacity() { + // Linear increase in background opacity, capped at the opacity + // of the wavefront (waveOpacity). + var outerOpacity = this.mouseUpElapsedSeconds * 0.3; + var waveOpacity = this.opacity; + + return Math.max( + 0, + Math.min(outerOpacity, waveOpacity) + ); + }, + + get isOpacityFullyDecayed() { + return this.opacity < 0.01 && + this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); + }, + + get isRestingAtMaxRadius() { + return this.opacity >= this.initialOpacity && + this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); + }, + + get isAnimationComplete() { + return this.mouseUpStart ? + this.isOpacityFullyDecayed : this.isRestingAtMaxRadius; + }, + + get translationFraction() { + return Math.min( + 1, + this.radius / this.containerMetrics.size * 2 / Math.sqrt(2) + ); + }, + + get xNow() { + if (this.xEnd) { + return this.xStart + this.translationFraction * (this.xEnd - this.xStart); + } + + return this.xStart; + }, + + get yNow() { + if (this.yEnd) { + return this.yStart + this.translationFraction * (this.yEnd - this.yStart); + } + + return this.yStart; + }, + + get isMouseDown() { + return this.mouseDownStart && !this.mouseUpStart; + }, + + resetInteractionState: function() { + this.maxRadius = 0; + this.mouseDownStart = 0; + this.mouseUpStart = 0; + + this.xStart = 0; + this.yStart = 0; + this.xEnd = 0; + this.yEnd = 0; + this.slideDistance = 0; + + this.containerMetrics = new ElementMetrics(this.element); + }, + + draw: function() { + var scale; + var translateString; + var dx; + var dy; + + this.wave.style.opacity = this.opacity; + + scale = this.radius / (this.containerMetrics.size / 2); + dx = this.xNow - (this.containerMetrics.width / 2); + dy = this.yNow - (this.containerMetrics.height / 2); + + Polymer.Base.translate3d(this.waveContainer, dx + 'px', dy + 'px', 0); + + // 2d transform for safari because of border-radius and overflow:hidden clipping bug. + // https://bugs.webkit.org/show_bug.cgi?id=98538 + this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')'; + this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)'; + }, + + mousedownAction: function(event) { + this.resetInteractionState(); + this.mouseDownStart = Utility.now(); + + this.xStart = event ? + event.x - this.containerMetrics.boundingRect.left : + this.containerMetrics.width / 2; + this.yStart = event ? + event.y - this.containerMetrics.boundingRect.top : + this.containerMetrics.height / 2; + + if (this.recenters) { + this.xEnd = this.containerMetrics.width / 2; + this.yEnd = this.containerMetrics.height / 2; + this.slideDistance = Utility.distance( + this.xStart, this.yStart, this.xEnd, this.yEnd + ); + } + + this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom( + this.xStart, + this.yStart + ); + + this.waveContainer.style.top = + (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px'; + this.waveContainer.style.left = + (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px'; + + this.waveContainer.style.width = this.containerMetrics.size + 'px'; + this.waveContainer.style.height = this.containerMetrics.size + 'px'; + }, + + mouseupAction: function(event) { + if (!this.isMouseDown) { + return; + } + + this.mouseUpStart = Utility.now(); + }, + + remove: function() { + Polymer.dom(this.waveContainer.parentNode).removeChild( + this.waveContainer + ); + } + }; + + Polymer({ + is: 'paper-ripple', + + properties: { + /** + * The initial opacity set on the wave. + * + * @attribute initialOpacity + * @type number + * @default 0.25 + */ + initialOpacity: { + type: Number, + value: 0.25 + }, + + /** + * How fast (opacity per second) the wave fades out. + * + * @attribute opacityDecayVelocity + * @type number + * @default 0.8 + */ + opacityDecayVelocity: { + type: Number, + value: 0.8 + }, + + /** + * If true, ripples will exhibit a gravitational pull towards + * the center of their container as they fade away. + * + * @attribute recenters + * @type boolean + * @default false + */ + recenters: { + type: Boolean, + value: false + }, + + /** + * A list of the visual ripples. + * + * @attribute ripples + * @type Array + * @default [] + */ + ripples: { + type: Array, + value: function() { + return []; + } + }, + + _animating: { + type: Boolean + }, + + _boundAnimate: { + type: Function, + value: function() { + return this.animate.bind(this); + } + }, + + _boundMousedownAction: { + type: Function, + value: function() { + return this.mousedownAction.bind(this); + } + }, + + _boundMouseupAction: { + type: Function, + value: function() { + return this.mouseupAction.bind(this); + } + } + }, + + get target () { + return this.host || this.parentNode; + }, + + attached: function() { + this.target.addEventListener('mousedown', this._boundMousedownAction); + this.target.addEventListener('mouseup', this._boundMouseupAction); + }, + + detached: function() { + this.target.removeEventListener('mousedown', this._boundMousedownAction); + this.target.removeEventListener('mouseup', this._boundMouseupAction); + }, + + /* TODO(cdata): Replace the above attached / detached listeners when + PolymerGestures equivalent lands in 0.8. + listeners: { + mousedown: 'mousedownAction', + mouseup: 'mouseupAction' + }, + */ + + get shouldKeepAnimating () { + for (var index = 0; index < this.ripples.length; ++index) { + if (!this.ripples[index].isAnimationComplete) { + return true; + } + } + + return false; + }, + + simulatedRipple: function() { + this.mousedownAction(null); + + // Please see polymer/polymer#1305 + this.async(function() { + this.mouseupAction(); + }, 1); + }, + + mousedownAction: function(event) { + var ripple = this.addRipple(); + + ripple.mousedownAction(event); + + if (!this._animating) { + this.animate(); + } + }, + + mouseupAction: function(event) { + this.ripples.forEach(function(ripple) { + ripple.mouseupAction(event); + }); + + this.animate(); + }, + + onAnimationComplete: function() { + this._animating = false; + this.$.background.style.backgroundColor = null; + this.fire('transitionend'); + }, + + addRipple: function() { + var ripple = new Ripple(this); + + Polymer.dom(this.$.waves).appendChild(ripple.waveContainer); + this.$.background.style.backgroundColor = ripple.color; + this.ripples.push(ripple); + + return ripple; + }, + + removeRipple: function(ripple) { + var rippleIndex = this.ripples.indexOf(ripple); + + if (rippleIndex < 0) { + return; + } + + this.ripples.splice(rippleIndex, 1); + + ripple.remove(); + }, + + animate: function() { + var index; + var ripple; + + this._animating = true; + + for (index = 0; index < this.ripples.length; ++index) { + ripple = this.ripples[index]; + + ripple.draw(); + + this.$.background.style.opacity = ripple.outerOpacity; + + if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) { + this.removeRipple(ripple); + } + } + + if (this.shouldKeepAnimating) { + window.requestAnimationFrame(this._boundAnimate); + } else if (this.ripples.length === 0) { + this.onAnimationComplete(); + } + } + }); + })();
diff --git a/third_party/polymer/v0_8/components-chromium/paper-ripple/paper-ripple.html b/third_party/polymer/v0_8/components-chromium/paper-ripple/paper-ripple.html new file mode 100644 index 0000000..554f5ba --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-ripple/paper-ripple.html
@@ -0,0 +1,131 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- +`paper-ripple` provides a visual effect that other paper elements can +use to simulate a rippling effect emanating from the point of contact. The +effect can be visualized as a concentric circle with motion. + +Example: + + <paper-ripple></paper-ripple> + +`paper-ripple` listens to "down" and "up" events so it would display ripple +effect when touches on it. You can also defeat the default behavior and +manually route the down and up actions to the ripple element. Note that it is +important if you call downAction() you will have to make sure to call upAction() +so that `paper-ripple` would end the animation loop. + +Example: + + <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple> + ... + downAction: function(e) { + this.$.ripple.downAction({x: e.x, y: e.y}); + }, + upAction: function(e) { + this.$.ripple.upAction(); + } + +Styling ripple effect: + + Use CSS color property to style the ripple: + + paper-ripple { + color: #4285f4; + } + + Note that CSS color property is inherited so it is not required to set it on + the `paper-ripple` element directly. + +By default, the ripple is centered on the point of contact. Apply the `recenters` +attribute to have the ripple grow toward the center of its container. + + <paper-ripple recenters></paper-ripple> + +Apply `circle` class to make the rippling effect within a circle. + + <paper-ripple class="circle"></paper-ripple> + +@group Paper Elements +@element paper-ripple +@homepage github.io +--><!-- +Fired when the animation finishes. This is useful if you want to wait until the ripple +animation finishes to perform some action. + +@event transitionend +@param {Object} detail +@param {Object} detail.node The animated node +--><html><head><link rel="import" href="../polymer/polymer.html"> + +</head><body><dom-module id="paper-ripple"> + <style> + :host { + display: block; + position: absolute; + border-radius: inherit; + overflow: hidden; + top: 0; + left: 0; + right: 0; + bottom: 0; + + /* This resolves a rendering issue in Chrome 40 where the + ripple is not properly clipped by its parent (which may have + rounded corners. See: http://jsbin.com/temexa/4 */ + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + :host([noink]) { + pointer-events: none; + } + + #background, + #waves, + .wave-container, + .wave { + pointer-events: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + #background, + .wave { + opacity: 0; + } + + #waves, + .wave { + overflow: hidden; + } + + .wave-container, + .wave { + border-radius: 50%; + } + + :host(.circle) #background, + :host(.circle) #waves { + border-radius: 50%; + } + + :host(.circle) .wave-container { + overflow: hidden; + } + + </style> + <template> + <div id="background"></div> + <div id="waves"></div> + </template> +</dom-module> +<script src="paper-ripple-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/.bower.json b/third_party/polymer/v0_8/components-chromium/paper-styles/.bower.json new file mode 100644 index 0000000..a67e854 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/.bower.json
@@ -0,0 +1,33 @@ +{ + "name": "paper-styles", + "version": "0.8.6", + "authors": [ + "Ian MacLeod <imac@google.com>", + "The Polymer Authors" + ], + "description": "Common (global) styles for Material Design elements.", + "keywords": [ + "web-component", + "web-components", + "polymer" + ], + "main": "paper-styles.html", + "license": "MIT", + "homepage": "https://github.com/PolymerLabs/paper-styles/", + "ignore": [ + "/.*", + "/demo/" + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "_release": "0.8.6", + "_resolution": { + "type": "version", + "tag": "v0.8.6", + "commit": "d0cdb1ad31d9b97855db3020a55c0b731a742334" + }, + "_source": "git://github.com/PolymerElements/paper-styles.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-styles" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/README.md b/third_party/polymer/v0_8/components-chromium/paper-styles/README.md new file mode 100644 index 0000000..fcbd7e0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/README.md
@@ -0,0 +1 @@ +# paper-styles
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/bower.json b/third_party/polymer/v0_8/components-chromium/paper-styles/bower.json new file mode 100644 index 0000000..8c31410 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/bower.json
@@ -0,0 +1,24 @@ +{ + "name": "paper-styles", + "version": "0.8.6", + "authors": [ + "Ian MacLeod <imac@google.com>", + "The Polymer Authors" + ], + "description": "Common (global) styles for Material Design elements.", + "keywords": [ + "web-component", + "web-components", + "polymer" + ], + "main": "paper-styles.html", + "license": "MIT", + "homepage": "https://github.com/PolymerLabs/paper-styles/", + "ignore": [ + "/.*", + "/demo/" + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + } +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/classes/global.html b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/global.html new file mode 100644 index 0000000..6f0d5dd --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/global.html
@@ -0,0 +1,96 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../paper-styles-classes.html"> + +<!-- +A set of base styles that are applied to the document and standard elements that +match the Material Design spec. +--> +<style> +/* +Note that there is a lot of style duplication here. The hope is that the Polymer +0.8 styling solution will allow for inheritance of properties so that we can +eventually avoid it. +*/ + +/* Mixins */ + +/* [paper-font] */ +body { + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */ +} + +/* [paper-font=display2] */ +h1 { + font-size: 45px; + font-weight: 400; + letter-spacing: -.018em; + line-height: 48px; +} + +/* [paper-font=display1] */ +h2 { + font-size: 34px; + font-weight: 400; + letter-spacing: -.01em; + line-height: 40px; +} + +/* [paper-font=headline] */ +h3 { + font-size: 24px; + font-weight: 400; + letter-spacing: -.012em; + line-height: 32px; +} + +/* [paper-font=subhead] */ +h4 { + font-size: 16px; + font-weight: 400; + line-height: 24px; +} + +/* [paper-font=body2] */ +h5, h6 { + font-size: 14px; + font-weight: 500; + line-height: 24px; +} + +/* [paper-font=button] */ +a { + font-size: 14px; + font-weight: 500; + letter-spacing: 0.018em; + line-height: 24px; + text-transform: uppercase; +} + +/* Overrides */ + +body, a { + color: #212121; +} + +h1, h2, h3, h4, h5, h6, p { + margin: 0 0 20px 0; +} + +h1, h2, h3, h4, h5, h6, a { + text-rendering: optimizeLegibility; +} + +a { + text-decoration: none; +} + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/classes/layout.html b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/layout.html new file mode 100644 index 0000000..5e3755b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/layout.html
@@ -0,0 +1,307 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="shadow-layout.html"> + +<style> + + /******************************* + Flex Layout + *******************************/ + + .layout.horizontal, + .layout.horizontal-reverse, + .layout.vertical, + .layout.vertical-reverse { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + } + + .layout.inline { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + } + + .layout.horizontal { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + } + + .layout.horizontal-reverse { + -ms-flex-direction: row-reverse; + -webkit-flex-direction: row-reverse; + flex-direction: row-reverse; + } + + .layout.vertical { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + } + + .layout.vertical-reverse { + -ms-flex-direction: column-reverse; + -webkit-flex-direction: column-reverse; + flex-direction: column-reverse; + } + + .layout.wrap { + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + } + + .layout.wrap-reverse { + -ms-flex-wrap: wrap-reverse; + -webkit-flex-wrap: wrap-reverse; + flex-wrap: wrap-reverse; + } + + .flex-auto { + -ms-flex: 1 1 auto; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + } + + .flex-none { + -ms-flex: none; + -webkit-flex: none; + flex: none; + } + + .flex, + .flex-1 { + -ms-flex: 1; + -webkit-flex: 1; + flex: 1; + } + + .flex-2 { + -ms-flex: 2; + -webkit-flex: 2; + flex: 2; + } + + .flex-3 { + -ms-flex: 3; + -webkit-flex: 3; + flex: 3; + } + + .flex-4 { + -ms-flex: 4; + -webkit-flex: 4; + flex: 4; + } + + .flex-5 { + -ms-flex: 5; + -webkit-flex: 5; + flex: 5; + } + + .flex-6 { + -ms-flex: 6; + -webkit-flex: 6; + flex: 6; + } + + .flex-7 { + -ms-flex: 7; + -webkit-flex: 7; + flex: 7; + } + + .flex-8 { + -ms-flex: 8; + -webkit-flex: 8; + flex: 8; + } + + .flex-9 { + -ms-flex: 9; + -webkit-flex: 9; + flex: 9; + } + + .flex-10 { + -ms-flex: 10; + -webkit-flex: 10; + flex: 10; + } + + .flex-11 { + -ms-flex: 11; + -webkit-flex: 11; + flex: 11; + } + + .flex-12 { + -ms-flex: 12; + -webkit-flex: 12; + flex: 12; + } + + /* alignment in cross axis */ + + .layout.start { + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + } + + .layout.center, + .layout.center-center { + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + } + + .layout.end { + -ms-flex-align: end; + -webkit-align-items: flex-end; + align-items: flex-end; + } + + /* alignment in main axis */ + + .layout.start-justified { + -ms-flex-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start; + } + + .layout.center-justified, + .layout.center-center { + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } + + .layout.end-justified { + -ms-flex-pack: end; + -webkit-justify-content: flex-end; + justify-content: flex-end; + } + + .layout.around-justified { + -ms-flex-pack: around; + -webkit-justify-content: space-around; + justify-content: space-around; + } + + .layout.justified { + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + } + + /* self alignment */ + + .self-start { + -ms-align-self: flex-start; + -webkit-align-self: flex-start; + align-self: flex-start; + } + + .self-center { + -ms-align-self: center; + -webkit-align-self: center; + align-self: center; + } + + .self-end { + -ms-align-self: flex-end; + -webkit-align-self: flex-end; + align-self: flex-end; + } + + .self-stretch { + -ms-align-self: stretch; + -webkit-align-self: stretch; + align-self: stretch; + } + + /******************************* + Other Layout + *******************************/ + + .block { + display: block; + } + + /* IE 10 support for HTML5 hidden attr */ + [hidden] { + display: none !important; + } + + .invisible { + visibility: hidden !important; + } + + .relative { + position: relative; + } + + .fit { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + body.fullbleed { + margin: 0; + height: 100vh; + } + + .scroll { + -webkit-overflow-scrolling: touch; + overflow: auto; + } + + /* fixed position */ + + .fixed-bottom, + .fixed-left, + .fixed-right, + .fixed-top { + position: fixed; + } + + .fixed-top { + top: 0; + left: 0; + right: 0; + } + + .fixed-right { + top: 0; + right: 0; + bottom: 0; + } + + .fixed-bottom { + right: 0; + bottom: 0; + left: 0; + } + + .fixed-left { + top: 0; + bottom: 0; + left: 0; + } + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/classes/shadow-layout.html b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/shadow-layout.html new file mode 100644 index 0000000..c42067af5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/shadow-layout.html
@@ -0,0 +1,302 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<style> + + /******************************* + Flex Layout + *******************************/ + + html /deep/ .layout.horizontal, + html /deep/ .layout.horizontal-reverse, + html /deep/ .layout.vertical, + html /deep/ .layout.vertical-reverse { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + } + + html /deep/ .layout.inline { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + } + + html /deep/ .layout.horizontal { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + } + + html /deep/ .layout.horizontal-reverse { + -ms-flex-direction: row-reverse; + -webkit-flex-direction: row-reverse; + flex-direction: row-reverse; + } + + html /deep/ .layout.vertical { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + } + + html /deep/ .layout.vertical-reverse { + -ms-flex-direction: column-reverse; + -webkit-flex-direction: column-reverse; + flex-direction: column-reverse; + } + + html /deep/ .layout.wrap { + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + } + + html /deep/ .layout.wrap-reverse { + -ms-flex-wrap: wrap-reverse; + -webkit-flex-wrap: wrap-reverse; + flex-wrap: wrap-reverse; + } + + html /deep/ .flex-auto { + -ms-flex: 1 1 auto; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + } + + html /deep/ .flex-none { + -ms-flex: none; + -webkit-flex: none; + flex: none; + } + + html /deep/ .flex, + html /deep/ .flex-1 { + -ms-flex: 1; + -webkit-flex: 1; + flex: 1; + } + + html /deep/ .flex-2 { + -ms-flex: 2; + -webkit-flex: 2; + flex: 2; + } + + html /deep/ .flex-3 { + -ms-flex: 3; + -webkit-flex: 3; + flex: 3; + } + + html /deep/ .flex-4 { + -ms-flex: 4; + -webkit-flex: 4; + flex: 4; + } + + html /deep/ .flex-5 { + -ms-flex: 5; + -webkit-flex: 5; + flex: 5; + } + + html /deep/ .flex-6 { + -ms-flex: 6; + -webkit-flex: 6; + flex: 6; + } + + html /deep/ .flex-7 { + -ms-flex: 7; + -webkit-flex: 7; + flex: 7; + } + + html /deep/ .flex-8 { + -ms-flex: 8; + -webkit-flex: 8; + flex: 8; + } + + html /deep/ .flex-9 { + -ms-flex: 9; + -webkit-flex: 9; + flex: 9; + } + + html /deep/ .flex-10 { + -ms-flex: 10; + -webkit-flex: 10; + flex: 10; + } + + html /deep/ .flex-11 { + -ms-flex: 11; + -webkit-flex: 11; + flex: 11; + } + + html /deep/ .flex-12 { + -ms-flex: 12; + -webkit-flex: 12; + flex: 12; + } + + /* alignment in cross axis */ + + html /deep/ .layout.start { + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + } + + html /deep/ .layout.center, + html /deep/ .layout.center-center { + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + } + + html /deep/ .layout.end { + -ms-flex-align: end; + -webkit-align-items: flex-end; + align-items: flex-end; + } + + /* alignment in main axis */ + + html /deep/ .layout.start-justified { + -ms-flex-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start; + } + + html /deep/ .layout.center-justified, + html /deep/ .layout.center-center { + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } + + html /deep/ .layout.end-justified { + -ms-flex-pack: end; + -webkit-justify-content: flex-end; + justify-content: flex-end; + } + + html /deep/ .layout.around-justified { + -ms-flex-pack: around; + -webkit-justify-content: space-around; + justify-content: space-around; + } + + html /deep/ .layout.justified { + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + } + + /* self alignment */ + + html /deep/ .self-start { + -ms-align-self: flex-start; + -webkit-align-self: flex-start; + align-self: flex-start; + } + + html /deep/ .self-center { + -ms-align-self: center; + -webkit-align-self: center; + align-self: center; + } + + html /deep/ .self-end { + -ms-align-self: flex-end; + -webkit-align-self: flex-end; + align-self: flex-end; + } + + html /deep/ .self-stretch { + -ms-align-self: stretch; + -webkit-align-self: stretch; + align-self: stretch; + } + + /******************************* + Other Layout + *******************************/ + + html /deep/ .block { + display: block; + } + + /* IE 10 support for HTML5 hidden attr */ + html /deep/ [hidden] { + display: none !important; + } + + html /deep/ .invisible { + visibility: hidden !important; + } + + html /deep/ .relative { + position: relative; + } + + html /deep/ .fit { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + body.fullbleed { + margin: 0; + height: 100vh; + } + + html /deep/ .scroll { + -webkit-overflow-scrolling: touch; + overflow: auto; + } + + .fixed-bottom, + .fixed-left, + .fixed-right, + .fixed-top { + position: fixed; + } + + html /deep/ .fixed-top { + top: 0; + left: 0; + right: 0; + } + + html /deep/ .fixed-right { + top: 0; + right: 0; + botttom: 0; + } + + html /deep/ .fixed-bottom { + right: 0; + bottom: 0; + left: 0; + } + + html /deep/ .fixed-left { + top: 0; + botttom: 0; + left: 0; + } + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/classes/shadow.html b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/shadow.html new file mode 100644 index 0000000..b4c340d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/shadow.html
@@ -0,0 +1,39 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<style> +.shadow-transition { + transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); +} + +.shadow-elevation-1 { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); +} + +.shadow-elevation-2 { + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2), + 0 6px 10px 0 rgba(0, 0, 0, 0.3); +} + +.shadow-elevation-3 { + box-shadow: 0 11px 7px 0 rgba(0, 0, 0, 0.19), + 0 13px 25px 0 rgba(0, 0, 0, 0.3); +} + +.shadow-elevation-4 { + box-shadow: 0 14px 12px 0 rgba(0, 0, 0, 0.17), + 0 20px 40px 0 rgba(0, 0, 0, 0.3); +} + +.shadow-elevation-5 { + box-shadow: 0 17px 17px 0 rgba(0, 0, 0, 0.15), + 0 27px 55px 0 rgba(0, 0, 0, 0.3); +} +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/classes/typography.html b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/typography.html new file mode 100644 index 0000000..5514abb --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/classes/typography.html
@@ -0,0 +1,171 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- TODO(nevir): Should we upgrade Polymer/font-roboto to the final font? --> +<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic"> +<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Inconsolata:400,700"> + +<!-- +Typographic styles are provided matching the Material Design standard styles: +http://www.google.com/design/spec/style/typography.html#typography-standard-styles + +To make use of them, apply a `paper-font-<style>` class to elements, matching +the font style you wish it to inherit. + + <header class="paper-font-display2">Hey there!</header> + +Note that these are English/Latin centric styles. You may need to further adjust +line heights and weights for CJK typesetting. See the notes in the Material +Design typography section. +--> +<style> + +.paper-font-display4, +.paper-font-display3, +.paper-font-display2, +.paper-font-display1, +.paper-font-headline, +.paper-font-title, +.paper-font-subhead, +.paper-font-body2, +.paper-font-body1, +.paper-font-caption, +.paper-font-menu, +.paper-font-button { + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */ +} + +.paper-font-code2, +.paper-font-code1 { + font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace; + -webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */ +} + +/* Opt for better kerning for headers & other short labels. */ +.paper-font-display4, +.paper-font-display3, +.paper-font-display2, +.paper-font-display1, +.paper-font-headline, +.paper-font-title, +.paper-font-subhead, +.paper-font-menu, +.paper-font-button { + text-rendering: optimizeLegibility; +} + +/* +"Line wrapping only applies to Body, Subhead, Headline, and the smaller Display +styles. All other styles should exist as single lines." +*/ +.paper-font-display4, +.paper-font-display3, +.paper-font-title, +.paper-font-caption, +.paper-font-menu, +.paper-font-button { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.paper-font-display4 { + font-size: 112px; + font-weight: 300; + letter-spacing: -.044em; + line-height: 120px; +} + +.paper-font-display3 { + font-size: 56px; + font-weight: 400; + letter-spacing: -.026em; + line-height: 60px; +} + +.paper-font-display2 { + font-size: 45px; + font-weight: 400; + letter-spacing: -.018em; + line-height: 48px; +} + +.paper-font-display1 { + font-size: 34px; + font-weight: 400; + letter-spacing: -.01em; + line-height: 40px; +} + +.paper-font-headline { + font-size: 24px; + font-weight: 400; + letter-spacing: -.012em; + line-height: 32px; +} + +.paper-font-title { + font-size: 20px; + font-weight: 500; + line-height: 28px; +} + +.paper-font-subhead { + font-size: 16px; + font-weight: 400; + line-height: 24px; +} + +.paper-font-body2 { + font-size: 14px; + font-weight: 500; + line-height: 24px; +} + +.paper-font-body1 { + font-size: 14px; + font-weight: 400; + line-height: 20px; +} + +.paper-font-caption { + font-size: 12px; + font-weight: 400; + letter-spacing: 0.011em; + line-height: 20px; +} + +.paper-font-menu { + font-size: 13px; + font-weight: 500; + line-height: 24px; +} + +.paper-font-button { + font-size: 14px; + font-weight: 500; + letter-spacing: 0.018em; + line-height: 24px; + text-transform: uppercase; +} + +.paper-font-code2 { + font-size: 14px; + font-weight: 700; + line-height: 20px; +} + +.paper-font-code1 { + font-size: 14px; + font-weight: 700; + line-height: 20px; +} + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/color.html b/third_party/polymer/v0_8/components-chromium/paper-styles/color.html new file mode 100644 index 0000000..43e9ce2 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/color.html
@@ -0,0 +1,56 @@ +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<style is="x-style"> + + * { + + --google-red-100: #f4c7c3; + --google-red-300: #e67c73; + --google-red-500: #db4437; + --google-red-700: #c53929; + + --google-blue-100: #c6dafc; + --google-blue-300: #7baaf7; + --google-blue-500: #4285f4; + --google-blue-700: #3367d6; + + --google-green-100: #b7e1cd; + --google-green-300: #57bb8a; + --google-green-500: #0f9d58; + --google-green-700: #0b8043; + + --google-yellow-100: #fce8b2; + --google-yellow-300: #f7cb4d; + --google-yellow-500: #f4b400; + --google-yellow-700: #f09300; + + --google-grey-100: #f5f5f5; + --google-grey-300: #e0e0e0; + --google-grey-500: #9e9e9e; + --google-grey-700: #616161; + + /* opacity for dark text on a light background */ + --dark-divider-opacity: 12%; + --dark-disabled-opacity: 26%; /* or hint text */ + --dark-secondary-opacity: 54%; /* or icon */ + --dark-primary-opacity: 87%; + + /* opacity for light text on a dark background */ + --light-divider-opacity: 12%; + --light-disabled-opacity: 30%; /* or hint text */ + --light-secondary-opacity: 70%; /* or icon */ + --light-primary-opacity: 100%; + + } + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/default-theme.html b/third_party/polymer/v0_8/components-chromium/paper-styles/default-theme.html new file mode 100644 index 0000000..c17f8e8d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/default-theme.html
@@ -0,0 +1,39 @@ +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<style is="x-style"> + + * { + + --dark-primary-color: #303f9f; + + --default-primary-color: #3f51b5; + + --light-primary-color: #c5cae9; + + --text-primary-color: #ffffff; + + --accent-color: #ff4081; + + --primary-background-color: #ffffff; + + --primary-text-color: #212121; + + --secondary-text-color: #757575; + + --disabled-text-color: #bdbdbd; + + --divider-color: #e0e0e0; + + } + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/demo.css b/third_party/polymer/v0_8/components-chromium/paper-styles/demo.css new file mode 100644 index 0000000..c6756c4 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/demo.css
@@ -0,0 +1,15 @@ +body { + font-family: RobotoDraft, 'Helvetica Neue', Helvetica, Arial; + font-size: 14px; + margin: 0; + padding: 24px; +} + +section { + padding: 20px 0; +} + +section > div { + padding: 14px; + font-size: 16px; +}
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/layout.html b/third_party/polymer/v0_8/components-chromium/paper-styles/layout.html new file mode 100644 index 0000000..ae8fad6 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/layout.html
@@ -0,0 +1,77 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<link rel="import" href="classes/layout.html"> + +<style is="x-style"> + + * { + + --layout: { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + } + + --layout-horizontal: { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + } + + --layout-vertical: { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + } + + --layout-flex: { + -ms-flex: 1; + -webkit-flex: 1; + flex: 1; + } + + --layout-center: { + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + } + + --layout-center-justified: { + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } + + /******************************* + Other Layout + *******************************/ + + --fit: { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + } + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/paper-styles-classes.html b/third_party/polymer/v0_8/components-chromium/paper-styles/paper-styles-classes.html new file mode 100644 index 0000000..b91c0135 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/paper-styles-classes.html
@@ -0,0 +1,13 @@ +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="classes/layout.html"> +<link rel="import" href="classes/typography.html"> +<link rel="import" href="classes/shadow.html">
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/paper-styles.html b/third_party/polymer/v0_8/components-chromium/paper-styles/paper-styles.html new file mode 100644 index 0000000..828fffe --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/paper-styles.html
@@ -0,0 +1,15 @@ +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="color.html"> +<link rel="import" href="default-theme.html"> +<link rel="import" href="layout.html"> +<link rel="import" href="typography.html"> +<link rel="import" href="shadow.html">
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/shadow.html b/third_party/polymer/v0_8/components-chromium/paper-styles/shadow.html new file mode 100644 index 0000000..6d7ae7a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/shadow.html
@@ -0,0 +1,47 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<style is="x-style"> + + * { + + --shadow-transition: { + transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); + }; + + --shadow-elevation-1: { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); + }; + + --shadow-elevation-2: { + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2), + 0 6px 10px 0 rgba(0, 0, 0, 0.3); + }; + + --shadow-elevation-3: { + box-shadow: 0 11px 7px 0 rgba(0, 0, 0, 0.19), + 0 13px 25px 0 rgba(0, 0, 0, 0.3); + }; + + --shadow-elevation-4: { + box-shadow: 0 14px 12px 0 rgba(0, 0, 0, 0.17), + 0 20px 40px 0 rgba(0, 0, 0, 0.3); + }; + + --shadow-elevation-5: { + box-shadow: 0 17px 17px 0 rgba(0, 0, 0, 0.15), + 0 27px 55px 0 rgba(0, 0, 0, 0.3); + }; + + } + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/paper-styles/typography.html b/third_party/polymer/v0_8/components-chromium/paper-styles/typography.html new file mode 100644 index 0000000..aae1a94a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/paper-styles/typography.html
@@ -0,0 +1,240 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- TODO(nevir): Should we upgrade Polymer/font-roboto to the final font? --> +<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic"> + +<link rel="import" href="../polymer/polymer.html"> + +<style is="x-style"> + + * { + + /* Shared Styles */ + + /* + Unfortunately, we can't make use of these yet - sibling properties aren't + evaluated. See https://github.com/Polymer/polymer/issues/1399 + + --paper-font-common-base: { + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + } + + --paper-font-common-code: { + font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace; + -webkit-font-smoothing: antialiased; + } + + --paper-font-common-expensive-kerning: { + text-rendering: optimizeLegibility; + } + + --paper-font-common-nowrap: { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + */ + + /* Material Font Styles */ + + --paper-font-display4: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 112px; + font-weight: 300; + letter-spacing: -.044em; + line-height: 120px; + } + + --paper-font-display3: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 56px; + font-weight: 400; + letter-spacing: -.026em; + line-height: 60px; + } + + --paper-font-display2: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + + font-size: 45px; + font-weight: 400; + letter-spacing: -.018em; + line-height: 48px; + } + + --paper-font-display1: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + + font-size: 34px; + font-weight: 400; + letter-spacing: -.01em; + line-height: 40px; + } + + --paper-font-headline: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + + font-size: 24px; + font-weight: 400; + letter-spacing: -.012em; + line-height: 32px; + } + + --paper-font-title: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 20px; + font-weight: 500; + line-height: 28px; + } + + --paper-font-subhead: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + + font-size: 16px; + font-weight: 400; + line-height: 24px; + } + + --paper-font-body2: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + + font-size: 14px; + font-weight: 500; + line-height: 24px; + } + + --paper-font-body1: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + + font-size: 14px; + font-weight: 400; + line-height: 20px; + } + + --paper-font-caption: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 12px; + font-weight: 400; + letter-spacing: 0.011em; + line-height: 20px; + } + + --paper-font-menu: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 13px; + font-weight: 500; + line-height: 24px; + } + + --paper-font-button: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 14px; + font-weight: 500; + letter-spacing: 0.018em; + line-height: 24px; + text-transform: uppercase; + } + + --paper-font-code2: { + /* mixin(--paper-font-common-code); */ + font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace; + -webkit-font-smoothing: antialiased; + + font-size: 14px; + font-weight: 700; + line-height: 20px; + } + + --paper-font-code1: { + /* mixin(--paper-font-common-code); */ + font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace; + -webkit-font-smoothing: antialiased; + + font-size: 14px; + font-weight: 500; + line-height: 20px; + } + + } + +</style>
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/.bower.json b/third_party/polymer/v0_8/components-chromium/polymer/.bower.json new file mode 100644 index 0000000..ed9a244 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/.bower.json
@@ -0,0 +1,36 @@ +{ + "name": "polymer", + "version": "0.8.0-rc.7", + "main": [ + "polymer.html" + ], + "license": "http://polymer.github.io/LICENSE.txt", + "ignore": [ + "/.*", + "/test/" + ], + "authors": [ + "The Polymer Authors (http://polymer.github.io/AUTHORS.txt)" + ], + "repository": { + "type": "git", + "url": "https://github.com/Polymer/polymer.git" + }, + "dependencies": { + "webcomponentsjs": "^0.6.0" + }, + "devDependencies": { + "web-component-tester": "*" + }, + "private": true, + "homepage": "https://github.com/Polymer/polymer", + "_release": "0.8.0-rc.7", + "_resolution": { + "type": "version", + "tag": "v0.8.0-rc.7", + "commit": "ce138bc0bb96c74421ba76bf3b5f1aa46b126569" + }, + "_source": "git://github.com/Polymer/polymer.git", + "_target": "v0.8.0-rc.7", + "_originalSource": "Polymer/polymer" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/PRIMER.md b/third_party/polymer/v0_8/components-chromium/polymer/PRIMER.md new file mode 100644 index 0000000..9ec86d3f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/PRIMER.md
@@ -0,0 +1,2046 @@ +# Polymer 0.8 Primer + +Table of Contents: + +* [Feature list](#feature-list) +* [Migration notes](#migration-notes) + +# Feature list + +<a name="feature-list"></a> +Below is a description of the current Polymer features, followed by individual feature guides. + +<a name="polymer-micro"></a> +**Bare-minum Custom Element sugaring** + +| Feature | Usage +|---------|------- +| [Custom element constructor](#element-constructor) | Polymer.Class({ … }); +| [Custom element registration](#register-element) | Polymer({ is: ‘...’, … }}; +| [Bespoke constructor support](#bespoke-constructor) | factoryImpl: function() { … } +| [Basic lifecycle callbacks](#basic-callbacks) | created, attached, detached, attributeChanged +| [Native HTML element extension](#type-extension) | extends: ‘…’ +| [Configure properties](#property-config) | properties: { … } +| [Attribute deserialization to property](#attribute-deserialization) | properties: { \<property>: \<Type> } +| [Static attributes on host](#host-attributes) | hostAttributes: { \<attribute>: \<value> } +| [Behavior mixins](#behaviors) | behaviors: [ … ] + +<a name="polymer-mini"></a> +**Template stamped into "local DOM" and tree lifecycle** + +| Feature | Usage +|---------|------- +| [Template stamping into local DOM](#template-stamping) | \<dom-module>\<template>...\</template>\</dom-module> +| [Scoped styling](#scoped-styling) | \<style> in \<dom-module>, Shadow-DOM styling rules (:host, ...) +| [DOM (re-)distribution](#dom-distribution) | \<content> +| [DOM API](#dom-api) | Polymer.dom +| [Configuring default values](#configure-values) | properties: \<prop>: { value: \<primitive>\|\<function> } +| [Bottom-up callback after configuration](#ready-method) | ready: function() { … } + +<a name="polymer-standard"></a> +**Declarative data binding, events, and property effects** + +| Feature | Usage +|---------|------- +| [Local node marshalling](#node-marshalling) | this.$.\<id> +| [Event listener setup](#event-listeners)| listeners: { ‘\<node>.\<event>’: ‘function’, ... } +| [Annotated event listener setup](#annotated-listeners) | \<element on-[event]=”function”> +| [Property change callbacks](#change-callbacks) | properties: \<prop>: { observer: ‘function’ } +| [Annotated property binding](#property-binding) | \<element prop=”{{property\|path}}”> +| [Property change notification](#property-notification) | properties: { \<prop>: { notify: true } } +| [Binding to structured data](#path-binding) | \<element prop=”{{obj.sub.path}}”> +| [Path change notification](#set-path) | setPathValue(\<path>, \<value>) +| [Declarative attribute binding](#attribute-binding) | \<element attr$=”{{property\|path}}”> +| [Binding to native element attributes](#native-binding) | class$="{{...}}", style$="{{...}}"> +| [Reflecting properties to attributes](#attribute-reflection) | properties: \<prop>: { reflectToAttribute: true } } +| [Computed properties](#computed-properties) | computed: { \<property>: ‘computeFn(dep1, dep2)’ } +| [Annotated computed properties](#annotated-computed) | \<span>{{computeFn(dep1, dep2)}}\</span> +| [Read-only properties](#read-only) | properties: { \<prop>: { readOnly: true } } +| [Utility functions](#utility-functions) | toggleClass, toggleAttribute, fire, async, … +| [General polymer settings](#settings) | \<script> Polymer = { ... }; \</script> + +<a name="polymer-experimental"></a> +**Experimental elements and features** + +**<span style="color:red">These features are experimental and there is a higher liklihood for future API change.</span>** Names for custom elements starting with `x-` are placeholders while in experimental status; these will be renamed prior to 1.0. + +| Feature | Usage +|---------|------- +| [Template repeater](#x-repeat) | \<template is="x-repeat" items="{{arr}}"> +| [Array selector](#x-array-selector) | \<x-array-selector items="{{arr}}" selected="{{selected}}"> +| [Conditional template](#x-if) | \<template is="x-if"> +| [Auto-binding template](#x-autobind) | \<template is="x-autobind"> +| [Cross-scope styling](#xscope-styling) | --custom-prop: value, var(--custom-prop), mixin(--custom-mixin) +| [Custom element for styling features](#x-style) | \<style is="x-style"> +| [External stylesheets](#external-stylesheets) | \<link rel="import" type="css" href="..."> +| [Polymer feature layers](#feature-layering) | polymer-micro.html, polymer-mini.html, polymer.html + +# Bare-minum Custom Element sugaring + +<a name="element-constructor"></a> +## Custom Element Constructor + +The most basic Polymer API is `Polymer.Class({...})`, which takes an object expressing the prototype of your custom element, chains it to Polymer's `Base` prototype (which provides value-add features described below), and returns a constructor that can be passed to `document.registerElement()` to register your element with the HTML parser, and after which can be used to instantiate new instances of your element via code. + +The only requirement for the prototype passed to `Polymer.Class` is that `is` property specifies the HTML tag name the element will be registered as. + +Example: + +```js +var MyElement = Polymer.Class({ + + is: 'my-element', + + // See below for lifecycle callbacks + created: function() { + this.innerHTML = 'My element!'; + } + +}); + +document.registerElement('my-element', MyElement); + +// Equivalent: +var el1 = new MyElement(); +var el2 = document.createElement('my-element'); +``` + +`Polymer.Class` is designed to provide similar ergonomics to a speculative future where an ES6 class may be defined and provided to `document.registerElement` to achieve the same effect. + +<a name="register-element"></a> +## Custom Element Registration + +Because the vast majority of users will always want to register the custom element prototype generated by Polymer, Polymer provides a `Polymer({ ... })` function that wraps calling `Polymer.Class` and `document.registerElement`. + +Example: + +```js +MyElement = Polymer({ + + is: 'my-element', + + // See below for lifecycle callbacks + created: function() { + this.innerHTML = 'My element!'; + } + +}); + +var el1 = new MyElement(); +var el2 = document.createElement('my-element'); +``` + +<a name="bespoke-constructor"></a> +## Bespoke constructor support + +While the standard `Polymer.Class()` and `Polymer()` functions return a basic constructor that can be used to instance the custom element, Polymer also supports providing a `factoryImpl` function on the prototype that can, for example, accept arguments to configure the element. In this case, the actual constructor returned from `Polymer` will first create an instance using `document.createElement`, then invoke the user-supplied `factoryImpl` function with `this` bound to the element instance. + +Example: + +```js +MyElement = Polymer({ + + is: 'my-element', + + factoryImpl: function(foo, bar) { + el.foo = foo; + el.configureWithBar(bar); + }, + + configureWithBar: function(bar) { + ... + } + +}); + +var el = new MyElement(42, 'octopus'); +``` + +<a name="type-extension"></a> +## Native HTML element extension + +Polymer 0.8 currently only supports extending native HTML elements (e.g. `input`, `button`, etc., as opposed to [extending other custom elements](#todo-inheritance)). To extend a native HTML element, set the `extends` property to the tag name of the element to extend. + + +Example: + +```js +MyInput = Polymer({ + + is: 'my-input', + + extends: 'input', + + created: function() { + this.style.border = '1px solid red'; + } + +}); + +var el1 = new MyInput(); +console.log(el1 instanceof HTMLInputElement); // true + +var el2 = document.createElement('input', 'my-input'); +console.log(el2 instanceof HTMLInputElement); // true +``` + +<a name="basic-callbacks"></a> +## Basic lifecycle callbacks + +Polymer's Base prototype implements the standard Custom Element lifecycle callbacks to perform tasks necessary for Polymer's built-in features. The hooks in turn call shorter-named lifecycle methods on your prototype. + +- `created` instead of `createdCallback` +- `attached` instead of `attachedCallback` +- `detached` instead of `detachedCallback` +- `attributeChanged` instead of `attributeChangedCallback` + +You can always fallback to using the low-level methods if you wish (in other words, you could simply implement `createdCallback` in your prototype). + +Example: + +```js +MyElement = Polymer({ + + is: 'my-element', + + created: function() { + console.log(this.localName + '#' + this.id + ' was created'); + }, + + attached: function() { + console.log(this.localName + '#' + this.id + ' was attached'); + }, + + detached: function() { + console.log(this.localName + '#' + this.id + ' was detached'); + }, + + attributeChanged: function(name, type) { + console.log(this.localName + '#' + this.id + ' attribute ' + name + + ' was changed to ' + this.getAttribute(name)); + } + +}); +``` + +`Polymer.Base` also implements `registerCallback`, which will be called by `Polymer()` to allow `Polymer.Base` to supply a layering system for Polymer abstractions. + +See the [section on configuring elements](#configuring-elements) for a more in-depth description of the practical uses of each callback. + + +<a name="property-config"></a> +## Configuring properties + +Placing an object-valued `properties` property on your prototype allows you to define metadata regarding your Custom Element's properties, which can then be accessed via an API for use by other Polymer features. + +By itself, the `properties` feature **doesn't do anything**. It only provides API for asking questions about these special properties (see featues below for details). + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + user: String, + isHappy: Boolean, + count: { + type: Number, + readOnly: true, + notify: true + } + }, + + ready: function() { + this.innerHTML = 'Hello World, I am a <b>Custom Element!</b>'; + } + +}); +``` + +Remember that the fields assigned to `count`, such as `readOnly` and `notify` don't do anything by themselves, it requires other features to give them life, and may depend on which layer of Polymer is in use. + +<a name="attribute-deserialization"></a> +## Attribute deserialization + +If a property is configured in the `properties` object with a `type` field, an attribute on the instance matching the property name will be deserialized according to the type specified and assigned to a property of the same name on the element instance. If no other `properties` options are specified for a property, the `type` (specified using the type constructor, e.g. `Object`, `String`, etc.) can be set directly as the value of the property in the `properties` object; otherwise it should be provided as the value to the `type` key in the `properties` configuration object. + +The type system includes support for Object and Array values expressed as JSON, or Date objects expressed as any Date-parsable string representation. Boolean properties set based on the existence of the attribute: if the attribute exists at all, its value is true, regardless of its string-value (and the value is only false if the attribute does not exist). + +Example: + +```html +<script> + + Polymer({ + + is: 'x-custom', + + properties: { + user: String, + manager: { + type: Boolean, + notify: true + } + }, + + attached: function() { + // render + this.innerHTML = 'Hello World, my user is ' + (this.user || 'nobody') + '.\n' + + 'This user is ' + (this.manager ? '' : 'not') + ' a manager.'; + } + + }); + +</script> + +<x-custom user="Scott" manager></x-custom> +<!-- +<x-custom>'s innerHTML becomes: +Hello World, my user is Scott. +This user is a manager. +--> +``` + +In order to configure camel-case properties of elements using attributes, dash-case should be used in the attribute name. Example: + +```html +<script> + + Polymer({ + + is: 'x-custom', + + properties: { + userName: String, + } + + }); + +</script> + +<x-custom user-name="Scott"></x-custom> +<!-- Sets <x-custom>.userName = 'Scott'; --> +``` + + +Note: Deserialization occurs both at create time, as well as at runtime, e.g. when the attribute is changed via `setAttribute`. However, it is encouraged that attributes only be used for configuring properties in static markup, and instead that properties are set directly for changes at runtime. + +<a name="host-attributes"></a> +## Static attributes on host + +If a custom elements needs HTML attributes set on it at create-time, these may be declared in a `hostAttributes` property on the prototype, where keys are the attribtue name and values are the values to be assigned. Values should typically be provided as strings, as HTML attributes can only be strings; however, the standard `serialize` method is used to convert values to strings, so `true` will serialize to an empty attribute, and `false` will result in no attribtue set, and so forth (see [here](#attribute-serialization) for more details). + +Example: + +```html +<script> + + Polymer({ + + is: 'x-custom', + + hostAttributes: { + role: 'button', + 'aria-disabled': true + tabindex: 0 + } + + }); + +</script> +``` + +Results in: + +```html +<x-custom role="button" aria-disabled tabindex="0"></x-custom> +``` + +<a name="behaviors"></a> +## Behaviors + +Polymer supports extending custom element prototypes with shared code modules called "behaviors". + +A behavior is simply an object that looks very similar to a typical Polymer prototype. It may define lifecycle callbacks, `properties`, `hostAttributes`, or other features described later in this document like `observers` and `listeners`. To add a behavior to a Polymer element definition, include it in a `behaviors` array on the prototype. + +Lifecycle callbacks will be called on the base prototype first, then for each behavior in the order given in the `behaviors` array. Additionally, any non-lifecycle functions on the behavior object are mixed into the base prototype (and will overwrite the function on the prototype, if they exist); these may be useful for adding API or implementing observer or event listener callbacks defined by the behavior, for example. + +Example: `highlight-behavior.html` + +```js +HighlightBehavior = { + + properties: { + isHighlighted: { + type: Boolean, + value: false, + notify: true, + observer: '_highlightChanged' + } + }, + + listeners: { + click: '_toggleHighlight' + }, + + created: function() { + console.log('Highlighting for ', this, + 'enabled!'); + }, + + _toggleHighlight: function() { + this.isHighlighted = !this.isHighlighted; + }, + + _highlightChanged: function(value) { + this.toggleClass('highlighted', value); + } + +}; +``` + +Example: `my-element.html` + +```html +<link rel="import" href="highlight-behavior.html"> + +<script> + Polymer({ + is: 'my-element', + behaviors: [HighlightBehavior] + }); +</script> +``` + +# Template stamping and tree lifecycle + +<a name="template-stamping"></a> +## Template stamping into local DOM + +We call the dom which an element is in charge of creating and managing its `local DOM`. This is distinct from the element's children which are sometimes called its `light DOM` for clarity. + +When native Shadow DOM is used, "local DOM" is actually contained in a shadow root. When the Shady DOM system is used, "local DOM" is a virtual notion maintained by Polymer with similar semantics to Shadow DOM. Polymer normalizes these two systems via a common API, such that you can always think about the "local DOM" and "light DOM" trees in the same way regardless of the underlying implementation. + +To specify dom to use for an element's local DOM, use the `<dom-module>` element. +Give the `<dom-module>` an `id` attribute that matches its element's +`is` property and put a `<template>` inside the `<dom-module>`. +Polymer will automatically stamp this template into the element's local DOM. + +Example: + +```html +<dom-module id="x-foo"> + <template>I am x-foo!</template> +</dom-module> + +<script> + Polymer({ + is: 'x-foo' + }); +</script> +``` + +We say that an element definition has an imperative and declarative portion. The imperative +portion is the call to `Polymer({...})`, and the declarative portion is the `<dom-module>` +element. The imperative and declarative portions of an element's definition may be placed +in the same html file or in separate files. + +**NOTE:** Defining an element in the main html document is not currently supported. + +<a name="scoped-styling"></a> +## Scoped styling + +Polymer 0.8 uses "[Shadow DOM styling rules](http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/)" for providing scoped styling of the element's local DOM. Scoped styles should be provided via `<style>` tags placed inside the `<dom-module>` for an element (but not inside the `<template>` -- note this is a slight deviation from typical Shadow DOM rules). + +```html + +<dom-module id="my-element"> + + <style> + :host { + display: block; + border: 1px solid red; + } + #child-element { + background: yellow; + } + /* styling elements distributed to content (via ::content) requires */ + /* selecting the parent of the <content> element for compatibility with */ + /* shady DOM . This can be :host or a wrapper element. */ + .content-wrapper > ::content .special { + background: orange; + } + </style> + + <template> + <div id="child-element">In local Dom!</div> + <div class="content-wrapper"><content></content></div> + </template> + +</dom-module> + +<script> + + Polymer({ + is: 'my-element' + }); + +</script> +``` + +Loading external stylesheets (as opposed to defining them inline in HTML) for styling local DOM is currently supported via an [experimental feature](#external-stylesheets). + +<a name="dom-distribution"></a> +## DOM (re-)distribution + +To support composition of an element's light DOM with its local DOM, Polymer supports the `<content>` element. The `<content>` element provides an insertion point at which an element's light DOM is combined with its local DOM. The `<content>` element supports a `select` attribute which filters nodes via a simple selector. + +Polymer supports multiple local DOM implementations. On browsers that support ShadowDOM, ShadowDOM may be used to create local DOM. On other supported browsers, Polymer provides local DOM via a custom implementation called ShadyDOM which is inspired by and compatible with ShadowDOM. + +Example: + +```html +<template> + <header>Local dom header followed by distributed dom.</header> + <content select=".content"></content> + <footer>Footer after distributed dom.</footer> +</template> +``` +<a name="dom-api"></a> +## DOM API + +Polymer provides custom API for manipulating DOM such that local DOM and light DOM trees are properly maintained. + +**<div style="color:red">Note: All DOM manipulation must use this API, as opposed to DOM API directly on nodes.</div>** + +The following methods are provided: + + * `Polymer.dom(parent).appendChild(node)` + * `Polymer.dom(parent).insertBefore(node, beforeNode)` + * `Polymer.dom(parent).removeChild(node)` + * `Polymer.dom(parent).querySelector(selector)` + * `Polymer.dom(parent).querySelectorAll(selector)` + * `Polymer.dom(parent).childNodes` + * `Polymer.dom(node).parentNode` + * `Polymer.dom(contentElement).getDistributedNodes()` + * `Polymer.dom(node).getDestinationInsertionPoints()` + * `Polymer.dom.flush()` - The insert, append, and remove operations are trasnacted lazily in certain cases for performance. In order to interrogate the dom (e.g. `offsetHeight`, `getComputedStyle`, etc.) immediately after one of these operations, call `Polymer.dom.flush()` first. + +Calling `append`/`insertBefore` where `parent` is a custom Polymer element adds the node to the light DOM of the element. In order to insert/append into the shadow root of a custom element, use `this.root` as the parent. + +`Polymer.dom` properties and methods that return a list of nodes return an `Array`, not a `NodeList` like the standard DOM equivalent. + +Example: + +```js +var toLight = document.createElement('div'); +Polymer.dom(this).appendChild(toLight); + +var toLocal = document.createElement('div'); +var beforeNode = Polymer.dom(this.root).childNodes[0]; +Polymer.dom(this.root).insertBefore(toLocal, beforeNode); + +var allSpans = Polymer.dom(this).querySelectorAll('span'); +``` + +You can use `Polymer.dom` on any node, whether or not it has a local DOM tree: + +Example: + +```html +<template> + <div id="container"> + <div id="first"></div> + <content></content> + </div> +</template> + +... + +var insert = document.createElement('div'); +Polymer.dom(this.$.container).insertBefore(insert, this.$.first); + +``` + +Sometimes it's necessary to access the elements which have been distributed to a given `<content>` insertion point or to know to which `<content>` a given node has been distributed. The `getDistributedNodes` and `getDestinationInsertionPoints` respectively provide this information. + +Example: + +```html +<x-foo> + <div></div> +</x-foo> + +// x-foo's template +<template> + <content></content> +</template> +``` + +```js +var div = Polymer.dom(xFoo).querySelector('div'); +var content = Polymer.dom(xFoo.root).querySelector('content'); +var distributed = Polymer.dom(content).getDistributedNodes()[0]; +var insertedTo = Polymer.dom(div).getDestinationInsertionPoints(); + +// the following should be true: +assert.equal(distributed, div); +assert.equal(insertedTo, content) +``` + +<a name="configure-values"></a> +## Configuring default property values + +Default values for properties may be specified in the `properties` object using the `value` field. The value may either be a primitive value, or a function that returns a value (which should be used for initializing Objects and Arrays to avoid shared objects on instances). + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + + mode: { + type: String, + value: 'auto' + }, + + data: { + type: Object, + notify: true, + value: function() { return {}; } + } + + } + +}); +``` +<a name="ready-method"></a> +## Ready callback + +The `ready` method is part of an element's lifecycle and is automatically called 'bottom-up' after the element's template has been stamped and all elements inside the element's local DOM have been configured (with values bound from parents, deserialized attributes, or else default values) and had their `ready` method called. Implement `ready` when it's necessary to manipulate an element's local DOM when the element is constructed. + +Example: + +```js +ready: function() { + this.$.ajax.go(); +} +``` + +# Declarative data binding, event handlers, and property effects + +<a name="node-marshalling"></a> +## Local node marshalling + +Polymer automatically builds a map of instance nodes stamped into its local DOM, to provide convenient access to frequently used nodes without the need to query for (and memoize) them manually. Any node specified in the element's template with an `id` is stored on the `this.$` hash by `id`. + +Example: + +```html +<dom-module id="x-custom"> + <template> + Hello World from <span id="name"></span>! + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + this.$.name.textContent = this.name; + } + + }); + +</script> +``` + +<a name="event-listeners"></a> +## Event listener setup + +Event listeners can be added to the host element by providing an object-valued `listeners` property that maps events to event handler function names. + +Example: + +```html +<dom-module id="x-custom"> + <template> + <div>I will respond</div> + <div>to a click on</div> + <div>any of my children!</div> + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'x-custom', + + listeners: { + 'click': 'handleClick' + }, + + handleClick: function(e) { + alert("Thank you for clicking"); + } + + }); + +</script> +``` + +<a name="annotated-listeners"></a> +## Annotated event listener setup + +For adding event listeners to local-DOM children, a more convenient `on-<event>` annotation syntax is supported directly in the template. This often eliminates the need to give an element an `id` solely for the purpose of binding an event listener. + +Example: + +```html +<dom-module id="x-custom"> + <template> + <button on-click="handleClick">Kick Me</button> + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'x-custom', + + handleClick: function() { + alert('Ow!'); + } + + }); + +</script> +``` + +<a name="change-callbacks"></a> +## Property change callbacks (observers) + +### Single property observation + +Custom element properties may be observed for changes by specifying `observer` property in the `properties` for the property that gives the name of a funciton to call. When the property changes, the change handler will be called with the new and old values as arguments. + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + disabled: { + type: Boolean, + observer: 'disabledChanged' + }, + highlight: { + observer: 'highlightChanged' + } + }, + + disabledChanged: function(newValue, oldValue) { + this.toggleClass('disabled', newValue); + this.highlight = true; + }, + + highlightChanged: function() { + this.classList.add('highlight'); + setTimeout(function() { + this.classList.remove('highlight'); + }, 300); + } + +}); +``` + +Note that property change observation is achieved in Polymer by installing setters on the custom element prototype for properties with registered interest (as opposed to observation via Object.observe or dirty checking, for example). + +### Multiple property observation + +Observing changes to multiple properties is supported via the `observers` array on the prototype, using a string containing a method signature that includes any dependent arguments. Once all properties are defined (`!== undefined`), the observer method will be called once for each change to a dependent property. The current values of the dependent properties will be passed as arguments to the observer method in the order defined in the `observers` method signature. + +*Note, computing functions will only be called once all dependent properties are defined (`!=undefined`). If one or more of the properties are optional, they would need default `value`'s defined in `properties` to ensure the observer is called.* + +*Note that any observers defined in the `observers` array will not receive `old` values as arguments, only new values. Only single-property observers defined in the `properties` object received both `old` and `new` values.* + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + preload: Boolean, + src: String, + size: String + }, + + observers: [ + 'updateImage(preload, src, size)' + ], + + updateImage: function(preload, src, size) { + // ... do work using dependent values + } + +}); +``` + +### Path observation + +Observing changes to object sub-properties is also supported via the same `observers` array, by specifying a path (e.g. `user.manager.name`). + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + user: Object + }, + + observers: [ + 'userManagerChanged(user.manager)' + ], + + userManagerChanged: function(user) { + console.log('new manager name is ' + user.name); + } + +}); +``` + +*Note that observing changes to paths (object sub-properties) is dependent on one of two requirements: either the value at the path in question changed via a Polymer [property binding](#property-binding) to another element, or the value was changed using the [`setPathValue`](#set-path) API, which provides the required notification to elements with registered interest.* + +### Deep path observation + +Additionally, wildcard matching of path changes is also supported via the `observers` array, which allows notification when any (deep) sub-property of an object changes. Note that the argument passed for a path with a wildcard is a change record object containing the `path` that changed, the new `value` of the path that changed, and the `base` value of the wildcard expression. + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + user: Object + }, + + observers: [ + 'userManagerChanged(user.manager.*)' + ], + + userManagerChanged: function(changeRecord) { + if (changeRecord.path == 'user.manager') { + // user.manager object itself changed + console.log('new manager name is ' + newValue.name); + } else { + // sub-property of user.manager changed + console.log(changeRecord.path + ' changed to ' + changeRecord.value); + } + } + +}); +``` + +<a name="property-binding"></a> +## Annotated property binding + +### Basic property binding + +Properties of the custom element may be bound into text content or properties of local DOM elements using binding annotations in the template. + +To bind to textContent, the binding annotation must currently span the entire content of the tag: + +```html +<dom-module id="user-view"> + <template> + + <!-- Supported --> + First: <span>{{first}}</span><br> + Last: <span>{{last}}</span> + + <!-- Not currently supported! --> + <div>First: {{first}}</div> + <div>Last: {{last}}</div> + + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'user-view', + + properties: { + first: String, + last: String + } + + }); + +</script> + +<user-view first="Samuel" last="Adams"></user-view> + +``` + +To bind to properties, the binding annotation should be provided as the value to an attribute with the same name of the JS property to bind to: + +```html +<dom-module id="main-view"> + <template> + <user-view first="{{user.first}}" last="{{user.last}}"></user-view> + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'main-view', + + properties: { + user: Object + } + + }); + +</script> +``` + +As in the example above, paths to object sub-properties may also be specified in templates. See [Binding to structured data](#path-binding) for details. + +In order to bind to camel-case properties of elements, dash-case should be used in the attribute name. Example: + +```html +<user-view first-name="{{managerName}}"></user-view> +<!-- will set <user-view>.firstName = this.managerName; --> +``` + +Note that while HTML attributes are used to specify bindings, values are assigned directly to JS properties, not to the HTML attributes of the elements unless specific [attribute bindings](#attribute-binding) are used. + +<a name="property-notification"></a> +### Property change notification and Two-way binding + +Polymer supports cooperative two-way binding between elements, allowing elements that "produce" data or changes to data to propagate those changes upwards to hosts when desired. + +When a Polymer elements changes a property that was configured in `properties` with the `notify` flag set to true, it automatically fires a non-bubbling DOM event to indicate those changes to interested hosts. These events follow a naming convention of `<property>-changed`, and contain a `value` property in the `event.detail` object indicating the new value. + +As such, one could attach an `on-<property>-changed` listener to an element to be notified of changes to such properties, set the `event.detail.value` to a property on itself, and take necessary actions based on the new value. However, given this is a common pattern, bindings using "curly-braces" (e.g. `{{property}}`) will automatically perform this upwards binding automatically without the user needing to perform those tasks. This can be disabled by using "square-brace" syntax (e.g. `[[property]]`), which results in only one-way (downward) data-binding. + +To summarize, two-way data-binding is achieved when both the host and the child agree to participate, satisfying these three conditions: + +1. The host must use curly-brace `{{property}}` syntax. Square-brace `[[property]]` syntax results in one-way downward binding, regardless of the notify state of the child's property. +2. The child property being bound to must be configured with the `notify` flag set to true (or otherwise send a `<property>-changed` custom event). If the property being bound does not have the `notify` flag set, only one-way (downward) binding will occur. +3. The child property being bound to must not be configured with the `readOnly` flag set to true. If the child property is `notify: true` and `readOnly:true`, and the host binding uses curly-brace syntax, the binding will effectively be one-way (upward). + +Example 1: Two-way binding + +```html +<script> + + Polymer({ + is: 'custom-element', + properties: { + prop: { + type: String, + notify: true + } + } + }); + +</script> +... + +<!-- changes to `value` propagate downward to `prop` on child --> +<!-- changes to `prop` propagate upward to `value` on host --> +<custom-element prop="{{value}}"></custom-element> +``` + +Example 2: One-way binding (downward) + +```html +<script> + Polymer({ + is: 'custom-element', + properties: { + prop: { + type: String, + notify: true + } + } + }); +</script> + +... + +<!-- changes to `value` propagate downward to `prop` on child --> +<!-- changes to `prop` are ignored by host due to square-bracket syntax --> +<custom-element prop="[[value]]"></custom-element> +``` + +Example 3: One-way binding (downward) + +```html +<script> + + Polymer({ + is: 'custom-element', + properties: { + prop: String // no `notify:true`! + } + }); + +</script> +... + +<!-- changes to `value` propagate downward to `prop` on child --> +<!-- changes to `prop` are not notified to host due to notify:falsey --> +<custom-element prop="{{value}}"></custom-element> +``` + +Example 4: One-way binding (upward) + +```html +<script> + Polymer({ + is: 'custom-element', + properties: { + prop: { + type: String, + notify: true, + readOnly: true + } + } + }); +</script> + +... + +<!-- changes to `value` are ignored by child due to readOnly:true --> +<!-- changes to `prop` propagate upward to `value` on host --> +<custom-element prop="{{value}}"></custom-element> +``` + +Example 5: Error / non-sensical state + +```html +<script> + + Polymer({ + is: 'custom-element', + properties: { + prop: { + type: String, + notify: true, + readOnly: true + } + } + }); + +</script> + +... + +<!-- changes to `value` are ignored by child due to readOnly:true --> +<!-- changes to `prop` are ignored by host due to square-bracket syntax --> +<!-- binding serves no purpose --> +<custom-element prop="[[value]]"></custom-element> +``` + +### Custom notify event and binding to native elements + +As mentioned above, Polymer uses an event naming convention to achieve two-way binding. The act of two-way binding to a property using `target-prop={{hostProp}}` syntax results in Polymer adding a `<target-prop>-changed` event listener to the element by default. All properties of a Polymer element with `notify: true` send events using this convention to notify of changes. + +In order to two-way bind to native elements or non-Polymer elements that do not follow this event naming convention when notifying changes, you may specify a custom event name in the curley braces, delimited with `::`. + +Example: + +```html +<!-- Listens for `input` event and sets hostValue to <input>.value --> +<input value="{{hostValue::input}}"> + +<!-- Listens for `change` event and sets hostChecked to <input>.checked --> +<input type="checkbox" checked="{{hostChecked::change}}"> + +<!-- Listens for `timeupdate ` event and sets hostTime to <video>.currentTime --> +<video url="..." current-time="{{hostTime::timeupdate}}"> +``` + +Note: When binding to standard notifying properties on Polymer elements, specifying the event name is unnecessary, as the default convention will be used. The following constructions are equivalent: + +```html + +<!-- Listens for `value-changed` event --> +<my-element value="{{hostValue::value-changed}}"> + +<!-- Listens for `value-changed` event using Polymer convention by default --> +<my-element value="{{hostValue}}"> + +``` + + +<a name="path-binding"></a> +### Binding to structured data + +Sub-properties of objects may be two-way bound to properties of custom elements as well by specifying the path of interest to the binding annotation. + +Example: + +```html +<template> + <div>{{user.manager.name}}</div> + <user-element user="{{user}}"></user-element> +</template> +``` + +As with change handlers for paths, bindings to paths (object sub-properties) are dependent on one of two requirements: either the value at the path in question changed via a Polymer [property binding](#property-binding) to another element, or the value was changed using the [`setPathValue`](#set-path) API, which provides the required notification to elements with registered interest, as discussed below. + +Note that path bindings are distinct from property bindings in a subtle way: when a property's value changes, an assignment must occur for the value to propagate to the property on the element at the other side of the binding. However, if two elements are bound to the same path of a shared object and the value at that path changes (via a property binding or via `setPathValue`), the value seen by both elements actually changes with no additional assignment necessary, by virtue of it being a property on a shared object reference. In this case, the element who changed the path must notify the system so that other elements who have registered interest in the same path may take side effects. However, there is no concept of one-way binding in this case, since there is no concept of propagation. That is, all bindings and change handlers for the same path will always be notified and update when the value of the path changes. + +<a name="set-path"></a> +### Path change notification + +Two-way data-binding and observation of paths in Polymer is achieved using a similar strategy to the one described above for [2-way property binding](#property-notification): When a sub-property of a property configured with `type: Object` changes, an element fires a non-bubbling `<property>-changed` DOM event with a `detail.path` value indicating the path on the object that changed. Elements that have registered interest in that object (either via binding or change handler) may then take side effects based on knowledge of the path having changed. Finally, those elements will forward the notification on to any children they have bound the object to, and will also fire a new `<property>-changed` event where `property` is the root object, to notify any hosts that may have bound root object down. Through this method, a notification will reach any part of the tree that has registered interest in that path so that side effects occur. + +This system "just works" to the extent that changes to object sub-properties occur as a result of being bound to a notifying custom element property that changed. However, sometimes imperative code needs to "poke" at an object's sub-properties directly. As we avoid more sophisticated observation mechanisms such as Object.observe or dirty-checking in order to achieve the best startup and runtime performance cross-platform for the most common use cases, changing an object's sub-properties directly requires cooperation from the user. + +Specifically, Polymer provides two API's that allow such changes to be notified to the system: `notifyPath(path, value)` and `setPathValue(path, value)`. + +Example: + +```html +<dom-module id="custom-element"> + <template> + <div>{{user.manager.name}}</div> + </template> +</dom-module> + +<script> + Polymer({ + + is: 'custom-element', + + reassignManager: function(newManager) { + this.user.manager = newManager; + // Notification required for binding to update! + this.notifyPath('user.manager', this.user.manager); + } + + }); +</script> +``` + +Since in the majority of cases, notifyPath will be called directly after an assignment, a convenience function `setPathValue` is provided that performs both actions: + +```js +reassignManager: function(newManager) { + this.setPathValue('user.manager', newManager); +} +``` + +### Expressions in binding annotations + +Currently the only binding expression supported in Polymer binding annotations is negation using `!`: + +Example: + +```html +<template> + <div hidden="{{!enabled}}"></div> +</template> +``` + +<a name="attribute-binding"></a> +## Declarative attribute binding + +In the vast majority of cases, binding data to other elements should use property binding described above, where changes are propagated by setting the new value to the JavaScript property on the element. + +However, there may be cases where a user actually needs to set an attribute on an element, as opposed to a property. These include a handful of [problematic native HTML attributes](#native-binding), when attribute selectors are used for CSS or for for interoperability with elements that require using attribute-based API. + +Polymer provides an alternate binding annotation syntax to make it explicit when binding values to attributes is desired by using `$=` rather than `=`. This results in in a call to `element.setAttribute('<attr>', value);`, as opposed to `element.property = value;`. + +```html +<template> + + <!-- Attribute binding --> + <my-element selected$="{{value}}"></my-element> + <!-- results in <my-element>.setAttribute('selected', this.value); --> + + <!-- Property binding --> + <my-element selected="{{value}}"></my-element> + <!-- results in <my-element>.selected = this.value; --> + +</template> +``` + +Values will be serialized according to type: Arrays/Objects will be `JSON.stringify`'ed, booleans will result in a non-valued attribute to be either set or removed, and `Dates` and all primitive types will be serialized using the value returned from `toString`. + +Again, as values must be serialized to strings when binding to attributes, it is always more performant to use property binding for pure data propagation. + +<a name="native-binding"></a> +## Binding to native element attributes + +There are a handful of extremely common native element attributes which can also be modified as properties. Due to cross-browser limitations with the ability to place binding braces `{{...}}` in some of these attribute values, as well as the fact that some of these attributes map to differently named JS properties, it is recommended to always use attribute binding (using `$=`) when binding dynamic values to these specific attributes, rather than binding to their property names. + +Normal attribute assignment to static values: + +```html +<!-- class --> +<div class="foo"></div> + +<!-- style --> +<div style="background: red;"></div> + +<!-- href --> +<a href="http://foo.com"> + +<!-- label for --> +<label for="bar"></label> + +<!-- dataset --> +<div data-bar="baz"></div> +``` + +Attribute binding to dynamic values (use `$=`): + +```html +<!-- class --> +<div class$="{{foo}}"></div> + +<!-- style --> +<div style$="{{background}}"></div> + +<!-- href --> +<a href$="{{url}}"> + +<!-- label for --> +<label for$="{{bar}}"></label> + +<!-- dataset --> +<div data-bar$="{{baz}}"></div> +``` + +<a name="attribute-reflection"></a> +## Reflecting properties to attributes + +In specific cases, it may be useful to keep an HTML attribute value in sync with a property value. This may be achieved by setting `reflectToAttribute: true` on a property in the `properties` configuration object. This will cause any change to the property to be serialized out to an attribute of the same name. + +```html +<script> + Polymer({ + + properties: { + response: { + type: Object, + reflectToAttribute: true + } + }, + + responseHandler: function(response) { + this.response = 'loaded'; + // results in this.setAttribute('response', 'loaded'); + } + + }); +</script> +``` + +<a name="attribute-serialization'></a> +Values will be serialized according to type; by default Arrays/Objects will be `JSON.stringify`'ed, booleans will result in a non-valued attribute to be either set or removed, and `Dates` and all primitive types will be serialized using the value returned from `toString`. The `serialize` method may be overridden to supply custom object serialization. + +<a name="computed-properties"></a> +## Computed properties + +Polymer supports virtual properties whose values are calculated from other properties. Computed properties can be defined in the `properties` object by providing a `computed` key mapping to a computing function. The name of the function to compute the value is provided as a string with dependent properties as arguments in parenthesis. Once all properties are defined (`!== undefined`), the computing function will be called to update the computed property once for each change to a dependent property. + +*Note, computing functions will only be called once all dependent properties are defined (`!=undefined`). If one or more of the properties are optional, they would need default `value`'s defined in `properties` to ensure the property is computed.* + +```html +<dom-module id="x-custom"> + <template> + My name is <span>{{fullName}}</span> + </template> +<dom-module id="x-custom"> + +<script> + Polymer({ + + is: 'x-custom', + + properties: { + + first: String, + + last: String, + + fullName: { + type: String, + // when `first` or `last` changes `computeFullName` is called once + // (asynchronously) and the value it returns is stored as `fullName` + computed: 'computeFullName(first, last)' + } + + }, + + computeFullName: function(first, last) { + return first + ' ' + last; + } + + ... + + }); +</script> +``` + +Note: Only direct properties of the element (as opposed to sub-properties of an object) can be used as dependencies at this time. + +<a name="annotated-computed"></a> +## Annotated computed properties + +Anonymous computed properties may also be placed directly in template binding annotations. This is useful when the property need not be a part of the element's API or otherwise used by logic in the element, and is only used for downward data propagation. + +*Note: this is the only form of functions allowed in template bindings, and they must specify one or more dependent properties as arguments, otherwise the function will not be called.* + +*Note, computing functions will only be called once all dependent properties are defined (`!=undefined`). If one or more of the properties are optional, they would need default `value`'s defined in `properties` to ensure the property is computed.* + +Example: + +```html +<dom-module id="x-custom"> + <template> + My name is <span>{{computeFullName(first, last)}}</span> + </template> +<dom-module id="x-custom"> + +<script> + Polymer({ + + is: 'x-custom', + + properties: { + + first: String, + + last: String + + }, + + computeFullName: function(first, last) { + return first + ' ' + last; + } + + ... + + }); +</script> +``` + + + +<a name="read-only"></a> +## Read-only properties + +When a property only "produces" data and never consumes data, this can be made explicit to avoid accidental changes from the host by setting the `readOnly` flag to `true` in the `properties` property definition. In order for the element to actually change the value of the property, it must use a private generated setter of the convention `_set<Property>(value)`. + +```html +<script> + Polymer({ + + properties: { + response: { + type: Object, + readOnly: true, + notify: true + } + }, + + responseHandler: function(response) { + this._setResponse(response); + } + + ... + + }); +</script> +``` + +Generally, read-only properties should also be set to `notify: true` such that their changes are observable from above. + +<a name="utility-functions"></a> +## Utility Functions + +Polymer's Base prototype provides a set of useful convenience/utility functions for instances to use. See API documentation for more details. + +* toggleClass: function(name, bool, [node]) +* toggleAttribute: function(name, bool, [node]) +* attributeFollows: function(name, neo, old) +* fire: function(type, [detail], [onNode], [bubbles], [cancelable]) +* async: function(method) +* transform: function(node, transform) +* translate3d: function(node, x, y, z) +* importHref: function(href, onload, onerror) + +<a name="settings"></a> +## Global Polymer settings + +Document-level global Polymer settings can be set before loading by setting a `Polymer` object on window as the first script in the main document: + +```html +<html> +<head> + <meta charset="utf-8"> + <script> Polymer = { dom: 'shadow' }; </script> + <script src="../../../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/my-app.html"> +</head> +<body> + + ... + +``` + +Settings can also be switched on the URL query string: + +``` +http://myserver.com/test-app/index.html?dom=shadow +``` + +Available settings: + +* `dom` - options: + * `shady` - all local DOM will be rendered using Shady DOM (even where shadow-DOM supported (current default) + * `shadow` - local DOM will be rendered using Shadow DOM where supported (this will be made default soon) + +# Experimental Features & Elements + +<a name="x-repeat"></a> +## Template repeater (x-repeat) +EXPERIMENTAL - API MAY CHANGE + +Elements in a template can be automatically repeated and bound to array items using a custom `HTMLTemplateElement` type extension called `x-repeat`. `x-repeat` accepts an `items` property, and one instance of the template is stamped for each item into the DOM at the location of the `x-repeat` element. The `item` property will be set on each instance's binding scope, thus templates should bind to sub-properties of `item`. Example: + +```html +<dom-module id="employee-list"> + + <template> + + <div> Employee list: </div> + <template is="x-repeat" items="{{employees}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + </template> + + </template> + + <script> + Polymer({ + is: 'employee-list', + ready: function() { + this.employees = [ + {first: 'Bob', last: 'Smith'}, + {first: 'Sally', last: 'Johnson'}, + ... + ]; + } + }); + </script> + +</dom-module> +``` + +Notifications for changes to items sub-properties will be forwarded to template instances, which will update via the normal [structured data notification system](#path-binding). + +Mutations to the `items` array itself (`push`, `pop`, `splice`, `shift`, `unshift`) are observed via `Array.observe` (where supported, or an experimental shim of this API on unsupported browsers), and template instances are kept in sync with the data in the array. + +A view-specific filter/sort may be applied to each `x-repeat` by supplying a `filter` and/or `sort` property. This may be a string that names a function on the host, or a function may be assigned to the property directly. The functions should implemented following the standard `Array` filter/sort API. + +In order to re-run the filter or sort functions based on changes to sub-fields of `items`, the `observe` property may be set as a space-separated list of `item` sub-fields that should cause a re-filter/sort when modified. + +For example, for an `x-repeat` with a filter of the following: + +```js +isEngineer: function(item) { + return item.type == 'engineer' || item.manager.type == 'engineer'; +} +``` + +Then the `observe` property should be configured as follows: + +```html +<template is="x-repeat" items="{{employees}}" + filter="isEngineer" observe="type manager.type"> +``` + +Note, to reach the outer parent scope, bindings in an `x-repeat` template may be prefixed with `parent.<property>`. + +<a name="x-array-selector"></a> +## Array selector (x-array-selector) +EXPERIMENTAL - API MAY CHANGE + +Keeping structured data in sync requires that Polymer understand the path associations of data being bound. The `x-array-selector` element ensures path linkage when selecting specific items from an array (either single or multiple). The `items` property accepts an array of user data, and via the `select(item)` and `deselect(item)` API, updates the `selected` property which may be bound to other parts of the application, and any changes to sub-fields of `selected` item(s) will be kept in sync with items in the `items` array. When `multi` is false, `selected` is a property representing the last selected item. When `multi` is true, `selected` is an array of multiply selected items. + +```html +<dom-module id="employee-list"> + + <template> + + <div> Employee list: </div> + <template is="x-repeat" id="employeeList" items="{{employees}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + <button on-click="toggleSelection">Select</button> + </template> + + <x-array-selector id="selector" items="{{employees}}" selected="{{selected}}" multi toggle></x-array-selector> + + <div> Selected employees: </div> + <template is="x-repeat" items="{{selected}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + </template> + + </template> + + <script> + Polymer({ + is: 'employee-list', + ready: function() { + this.employees = [ + {first: 'Bob', last: 'Smith'}, + {first: 'Sally', last: 'Johnson'}, + ... + ]; + }, + toggleSelection: function(e) { + var item = this.$.employeeList.itemForElement(e.target); + this.$.selector.select(item); + } + }); + </script> + +</dom-module> +``` + +<a name="x-if"></a> +## Conditional template +EXPERIMENTAL - API MAY CHANGE + +Elements can be conditionally stamped based on a boolean property by wrapping them in a custom `HTMLTemplateElement` type extension called `x-if`. The `x-if` template stamps itself into the DOM only when its `if` property becomes truthy. + +If the `if` property becomes falsy again, by default all stamped elements will be hidden (but will remain in DOM) for faster performance should the `if` property become truthy again. This behavior may be disabled by setting the `restamp` property, which results in slower `if` switching behavior as the elements are destroyed and re-stamped each time. + +Note, to reach the outer parent scope, all bindings in an `x-if` template must be prefixed with `parent.<property>`, as shown below. + +Example: + +**Note, this is a simple example for illustrative purposes only. Read below for guidance on recommended usage of conditional templates.** + +```html +<dom-module id="user-page"> + + <template> + + All users will see this: + <div>{{user.name}}</div> + + <template is="x-if" if="{{user.isAdmin}}"> + Only admins will see this. + <div>{{parent.user.secretAdminStuff}}</div> + </template> + + </template> + + <script> + Polymer({ + is: 'user-page', + properties: { + user: Object + } + }); + </script> + +</dom-module> +``` + +Note, since it is generally much faster to hide/show elements rather than create/destroy them, conditional templates are only useful to save initial creation cost when the elements being stamped are relatively heavyweight and the conditional may rarely (or never) be true in given useages. Otherwise, liberal use of conditional templates can actually *add* significant runtime performance overhead. + +Consider an app with 4 screens, plus an optional admin screen. If most users will use all 4 screens during normal use of the app, it is generally better to incur the cost of stamping those elements once at startup (where some app initialization time is expected) and simply hide/show the screens as the user navigates through the app, rather than re-create and destroy all the elements of each screen as the user navigates. Using a conditional template here may be a poor choice, since although it may save time at startup by stamping only the first screen, that saved time gets shifted to runtime latency for each user interaction, since the time to show the second screen will be *slower* as it must create the second screen from scratch rather than simply showing that screen. Hiding/showing elements is as simple as attribute-binding to the `hidden` attribute (e.g. `<div hidden$="{{!shouldShow}}">`), and does not require conditional templating at all. + +However, using a conditional template may be appropriate in the case of an admin screen that should only be shown to admin users of an app. Since most users would not be admins, there may be performance benefits to not burdening most of the users with the cost of stamping the elements for the admin page, especially if it is relatively heavyweight. + +<a name="x-autobind"></a> +## Auto-binding template +EXPERIMENTAL - API MAY CHANGE + +Polymer's binding features are only available within templates that are managed by Polymer. As such, these features are available in templates used to define Polymer elements, for example, but not for elements placed directly in the main document. + +In order to use Polymer bindings without defining a new custom element, you may wrap the elements utilizing bindings with a custom template extension called `x-autobind`. This template will immediately stamp itself into the main document and bind elements to the template itself as the binding scope. + +```html +<!doctype html> +<html> +<head> + <meta charset="utf-8"> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + <link rel="import" href="components/core-ajax/core-ajax.html"> + +</head> +<body> + + <!-- Wrap elements in with auto-binding template to --> + <!-- allow use of Polymer bindings main document --> + <template is="x-autobind"> + + <core-ajax url="http://..." lastresponse="{{data}}"></core-ajax> + + <template is="x-repeat" items="{{data}}"> + <div><span>{{item.first}}</span> <span>{{item.last}}</span></div> + </template> + + </template> + +</body> +</html> +``` + +<a name="xscope-styling"></a> +## Cross-scope styling +EXPERIMENTAL - API MAY CHANGE + +### Background + +Shadow DOM (and its approximation via Shady DOM) bring much needed benefits of scoping and style encapsulation to web development, making it safer and easier to reason about the effects of CSS on parts of your application. Styles do not leak into the local DOM from above, and styles do not leak from one local DOM into the local DOM of other elements inside. + +This is great for *protecting* scopes from unwanted style leakage. But what about when you intentionally want to *customize* the style of a custom element's local DOM, as the user of an element? This often comes up under the umbrella of "theming". For example a "custom-checkbox" element that may interally use a `.checked` class can protect itself from being affected by CSS from other components that may also happen to use a `.checked` class. However, as the user of the checkbox you may wish to intentionally change the color of the check to match your product's branding, for example. The "protection" that Shadow DOM provides at the same time introduces a practical barrier to "theming" use cases. + +One solution the Shadow DOM spec authors provided to address the theming problem are the `/deep/` and `::shadow` combinators, which allow writing rules that pierce through the Shadow DOM encapsulation boundary. Although Polymer 0.5 promoted this mechanism for theming, it was ultimately unsatisfying for several reasons: + +* Using `/deep/` and `::shadow` for theming leaks details of an otherwise encapsulated element to the user, leading to brittle selectors piercing into the internal details of an element's Shadow DOM that are prone to breakage when the internal implementation changes. As a result, the structure of of an element's Shadow DOM inadvertently becomes API surface subject to breakage, diminishing the practical effectiveness of Shadow DOM as an encapsulation primitive. +* Although Shadow DOM's style encapsulation *improves* the predictability of style recalc performance since the side effects of a style change are limited to a small subset of the document, using `/deep/` and `::shadow` re-open the style invalidation area and reduce Shadow DOM's effectiveness as a performance primitive. +* Using `/deep/` and `::shadow` lead to verbose and difficult to understand selectors. + +For the reasons above, the Polymer team is currently exploring other options for theming that address the shortcomings above and provide a possible path to obsolescence of `/deep/` and `::shadow` altogether. + +<a name="xscope-styling-details"></a> +### Custom CSS properties + +Polymer 0.8 includes a highly experimental and opt-in shim for custom CSS properties inspired by (and compatible with) the future W3C [CSS Custom Properties for Cascading Variables](http://dev.w3.org/csswg/css-variables/) specification (see [explainer on MDN here](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables)). + +Rather than exposing the details of an element's internal implementation for theming, instead an element author would define one or more custom CSS properties as part of the element's API which it would consume to style internals of the element deemed important for theming by the element's author. These custom properties can be defined similar to other standard CSS properties and will inherit from the point of definition down the composed DOM tree, similar to the effect of `color` and `font-family`. + +In the simple example below, the author of `my-toolbar` identified the need for users of the toolbar to be able to change the color of the toolbar title. The author exposed a custom property called `--my-toolbar-title-color` which is assigned to the `color` property of the selector for the title element. Users of the toolbar may define this variable in a CSS rule anywhere up the tree, and the value of the property will inherit down to the toolbar where it is used if defined, similar to other standard inheriting CSS properties. + +Example: + +```html +<dom-module id="my-toolbar"> + + <style> + :host { + padding: 4px; + background-color: gray; + } + .title { + color: var(--my-toolbar-title-color); + } + </style> + + <template> + <span class="title">{{title}}</span> + </template> + + <script> + Polymer({ + is: 'my-toolbar', + properties: { + title: String + }, + // The custom properties shim is currently an opt-in feature + enableCustomStyleProperties: true + }); + </script> + +</dom-module> +``` + +Example usage of `my-toolbar`: + +```html +<dom-module id="my-element"> + + <style> + + /* Make all toolbar titles in this host green by default */ + :host { + --my-toolbar-title-color: green; + } + + /* Make only toolbars with the .warning class red */ + .warning { + --my-toolbar-title-color: red; + } + + </style> + + <template> + + <my-toolbar title="This one is green."></my-toolbar> + <my-toolbar title="This one is green too."></my-toolbar> + + <my-toolbar class="warning" title="This one is red."></my-toolbar> + + </template> + +</dom-module> +``` + +The `--my-toolbar-title-color` property will only affect the color of the title element encapsulated in `my-toolbar`'s internal implementation. If in the future the `my-toolbar` author chose to rename the `.title` class or otherwise restructure the internal details of `my-toolbar`, users are shielded from this change via the indirection afforded by custom properties. + +Thus, custom CSS properties introduce a powerful way for element authors to expose a theming API to their users in a way that naturally fits right alongside normal CSS styling and avoids the problems with `/deep/` and `::shadow`, and is already on a standards track with shipping implementation by Mozilla and planned support by Chrome. + +However, it may be tedious (or impossible) for an element author to anticipate and expose every possible CSS property that may be important for theming an element as individual CSS properties (for example, what if a user needed to adjust the `opacity` of the toolbar title?). For this reason, the custom properties shim included in Polymer includes an experimental extension allowing a bag of CSS properties to be defined as a custom property and allowing all properties in the bag to be applied to a specific CSS rule in an element's local DOM. For this, we introduce a `mixin` capability that is analogous to `var`, but allows an entire bag of properties to be mixed in. + +Example: + +```html +<dom-module id="my-toolbar"> + + <style> + :host { + padding: 4px; + background-color: gray; + mixin(--my-toolbar-theme); + } + .title { + mixin(--my-toolbar-title-theme); + } + </style> + + <template> + <span class="title">{{title}}</span> + </template> + + ... + +</dom-module> +``` + +Example usage of `my-toolbar`: + +```html +<dom-module id="my-element"> + + <style> + + /* Apply custom theme to toolbars */ + :host { + --my-toolbar-theme: { + background-color: green; + border-radius: 4px; + border: 1px solid gray; + } + --my-toolbar-title-theme: { + color: green; + } + } + + /* Make only toolbars with the .warning class red and bold */ + .warning { + --my-toolbar-title-theme: { + color: red; + font-weight: bold; + } + } + + </style> + + <template> + + <my-toolbar title="This one is green."></my-toolbar> + <my-toolbar title="This one is green too."></my-toolbar> + + <my-toolbar class="warning" title="This one is red."></my-toolbar> + + </template> + +</dom-module> +``` + +### Custom Properties Shim - Limitations and API details + +Experimental cross-platform support for custom properties is provided in Polymer by a Javascript library that approximates the capabilities of the CSS Variables specification *for the specific use case of theming custom elements*, while also extending it to add the mixin capability described above. **It is important to note that this is not a full polyfill**, as doing so would be prohibitively expensive; rather this is a shim that is inspired by that specification and trades off aspects of the full dynamism possible in CSS with practicality and performance. + +Below are current limitations of this experimental system. Improvements to performance and dynamism will continue to be explored. + +* As this feature is still experimental, custom properties are not currently applied to elements by default. To enable *usage* of custom properties, set an `enableCustomStyleProperties: true` property on the Polymer element prototype. + +* Only rules which match the element at *creation time* are applied. Any dynamic changes that update variable values are not applied automatically. + + ```html + <div class="container"> + <x-foo class="a"></x-foo> + </div> + ``` + + ```css + /* applies */ + x-foo.a { + --foo: brown; + } + /* does not apply */ + x-foo.b { + --foo: orange; + } + /* does not apply to x-foo */ + .container { + --nog: blue; + } + ``` +* Re-evaluation of custom property styles does not currently occur as a result of changes to the DOM. Re-evaluation can be forced by calling `this.updateStyles()` on a Polymer element. For example, if class `b` was added to `x-foo` above, the scope must call `this.updateStyles()` to apply the styling. This re-calcs/applies styles down the tree from this point. + +* Dynamic effects are reflected at the point of a variable’s application, but not its definition. + + For the following example, adding/removing the `highlighted` class on the `#title` element will have the desired effect, since the dynamism is related to *application* of a custom property. + + ```css + #title { + background-color: var(--title-background-normal); + } + + #title.highlighted { + background-color: var(--title-background-highlighted); + } + ``` + + However, the shim does not currently support dynamism at the point of *definition* of a custom property. In the following example, `this.updateStyles()` would be required to update the value of `--title-background` being applied to `#title` when the `highlighted` class was added or removed. + + ```css + #title { + --title-background: gray; + } + + #title.highlighted { + --title-background: yellow; + } + ``` + +<a name="x-style"></a> +## Custom element for document styling (x-style) +EXPERIMENTAL - API MAY CHANGE + +An experimental `<style is="x-style">` custom element is provided for defining styles in the main document that can take advantage of several special features of Polymer's styling system: + +* Document styles defined in an `x-style` will be shimmed to ensure they do not leak into local DOM when running on browsers without non-native Shadow DOM. +* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on browsers without non-native Shadow DOM. +* Custom properties used by Polymer's experimental [shim for cross-scope styling](#xscope-styling-details) may be defined in an `x-style`. + +Example: + +```html +<!doctype html> +<html> +<head> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + + <style is="x-style"> + + /* Will be prevented from affecting local DOM of Polymer elements */ + * { + box-sizing: border-box; + } + + /* Can use /deep/ and ::shadow combinators */ + body /deep/ .my-special-view::shadow #thing-inside { + background: yellow; + } + + /* Custom properties that inherit down the document tree may be defined */ + * { + --my-toolbar-title-color: green; + } + + </style> + +</head> +<body> + + ... + +</body> +</html> +``` + +Note, all features of `x-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `x-style` extension should only be used for defining document styles, outside of a custom element's local DOM. + +<a name="external-stylesheets"></a> +## External stylesheets +EXPERIMENTAL - API MAY CHANGE + +Polymer includes an experimental feature to support loading external stylesheets that will be applied to the local DOM of an element. This is typically convenient for developers who like to separate styles, share common styles between elements, or use style pre-processing tools. The syntax is slightly different from how stylesheets are typically loaded, as the feature leverages HTML Imports (or the HTML Imports polyfill, where appropriate) to load the stylesheet text such that it may be properly shimmed and/or injected as an inline style. + +To include a remote stylesheet that applies to your Polymer element's local DOM, place a special HTML import `<link>` tag with `type="css"` in your `<dom-module>` that refers to the external stylesheet to load. + +Example: + +```html +<dom-module id="my-awesome-button"> + + <!-- special import with type=css used to load remote CSS --> + <link rel="import" type="css" href="my-awesome-button.css"> + + <template> + ... + </template> + + <script> + Polymer({ + is: 'my-awesome-button', + ... + }); + </script> + +</dom-module> +``` + +<a name="feature-layering"></a> +## Feature layering +EXPERIMENTAL - API MAY CHANGE + +Polymer 0.8 is currently layered into 3 sets of features provided as 3 discrete HTML imports, such that an individual element developer can depend on a version of Polymer whose feature set matches their tastes/needs. For authors who opt out of the more opinionated local DOM or data-binding features, their element's dependencies would not be payload- or runtime-burdened by these higher-level features, to the extent that a user didn't depend on other elements using those features on that page. That said, all features are designed to have low runtime cost when unused by a given element. + +Higher layers depend on lower layers, and elements requiring lower layers will actually be imbued with features of the highest-level version of Polymer used on the page (those elements would simply not use/take advantage of those features). This provides a good tradeoff between element authors being able to avoid direct dependencies on unused features when their element is used standalone, while also allowing end users to mix-and-match elements created with different layers on the same page. + +* polymer-micro.html: [Polymer micro features](#polymer-micro) (bare-minum Custom Element sugaring) +* polymer-mini.html: [Polymer mini features](#polymer-mini) (template stamped into "local DOM" and tree lifecycle) +* polymer.html: [Polymer standard features](#polymer-standard) (all other features: declarative data binding and event handlers, property nofication, computed properties, and experimental features) + +This layering is subject to change in the future and the number of layers may be reduced. + +--- + +<a name="migration-notes"></a> +# Migration Notes + +This section covers how to deal with yet-unimplemented and/or de-scoped features in Polymer 0.8 as compared to 0.5. Many of these are simply un-implemented; that is, we will likely have a final "solution" that addresses the need, we just haven't tackled that feature yet as we address items in priority order. Other solutions in 0.8 may be lower-level as compared to 0.5, and will be explained here. + +As the final 0.8 API solidifies, this section will be updated accordingly. As such, this section should be considered answers "how do I solve problem xyz <em>TODAY</em>", rather than a representation of the final Polymer 0.8 API. + +## Property casing + +TL;DR: When binding to camel-cased properties, use "dash-case" attribute names to indicate the "camelCase" property to bind to. + +Example: bind `this.myValue` to `<x-foo>.thatValue`: + +BEFORE: 0.5 + +```html +<x-foo thatValue="{{myValue}}"></x-foo> +``` + +AFTER: 0.8 + +```html +<x-foo that-value="{{myValue}}"></x-foo> +``` + +In 0.5, binding annotations were allowed to mixed-case properties (despite the fact that attribute names always get converted to lower-case by the HTML parser), and the Node.bind implementation at the "receiving end" of the binding automatically inferred the mixed-case property it was assumed to refer to at instance time. + +In 0.8, "binding" is done at prorotype time before the type of the element being bound to is known, hence knowing the exact JS property to bind to allows better efficiency. + +## Binding limitations + +Current limitations that are on the backlog for evaluation/improvement are listed below, with current workarounds: + +* Sub-textContent/property binding + * You cannot currrently do any of the following: + + ```html + <div> stuff here: {{stuff}}</div> + <div class$="{{thing}} {{another}}"></div> + <x-custom prop="{{thing}} {{another}}"></x-custom> + ``` + + * Instead, use `<span>`'s to break up textContent into discrete elements: + + ```html + <div> stuff here: <span>{{stuff}}</span></div> + ``` + + * Use computed properties for concatenating into properties/attributes: + + ```html + <div class$="{{computeDivClass(thing, another)}}"></div> + <x-custom prop="{{computeCustomProp(thing, another}}"></x-custom> + ``` + +* CSS class binding: + * May bind entire class list from one property to `class` _attribute_: + `<div class$="{{classes}}">` + * Otherwise, `this.classList.add/remove` from change handlers +* CSS inline-style binding: + * May bind entire inline style from one property to `style` _attribute_: + `<div style$="{{styles}}">` + * Otherwise, assign `this.style.props` from change handlers + +## Structured data and path notification + +To notify non-bound structured data changes, use `setPathValue` and `notifyPath`: + +```js +this.setPathValue('user.manager', 'Matt'); +``` + +Which is equivalent to: + +```js +this.user.manager = 'Matt'; +this.notifyPath('user.manager', this.user.manager); +``` + +## Repeating elements + +Repeating templates is moved to a custom element (HTMLTemplateElement type extension called `x-repeat`): + +```html +<template is="x-repeat" items="{{users}}"> + <div>{{item.name}}</div> +</template> +``` + +## Array notification + +This area is in high flux. Arrays bound to `x-repeat` are currently observed using `Array.observe` (or equivalent shim) and `x-repeat` will reflect changes to array mutations (push, pop, shift, unshift, splice) asynchronously. + +**In-place sort of array is not supported**. Sorting/filtering will likely be provided as a feature of `x-repeat` (and possibly other array-aware elements such as `x-list`) in the future. + +Implementation and usage details will likely change, stay tuned. + +<a name="todo-inheritance"></a> +## Mixins / Inheritance + +TODO - use composition for now + +## Gesture support + +TODO - use standard DOM for now until gesture support is ported
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/README.md b/third_party/polymer/v0_8/components-chromium/polymer/README.md new file mode 100644 index 0000000..1149493a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/README.md
@@ -0,0 +1,330 @@ +# Polymer 0.8 Preview + +Authors interested in learning the core concepts in 0.8 may be interested in our [primer](https://github.com/Polymer/polymer/blob/0.8-preview/PRIMER.md). + +## From The Ground Up + +Let us begin this tale with a short stroll through the layers that Polymer is +built upon, and some of the rationale of how we got there. + +### Raw Custom Elements + +Custom Elements are a powerful emerging web standard that allows developers to create their own elements by attaching a class to a tag-name. + +#### document.registerElement + +The native API is very simple, it looks something like this: + +```js +document.registerElement(<name String>, {prototype: Object[, extends: String]}); +``` + +#### Typical Boilerplate + +There is a little bit of work one has to do to set up the class with the right prototypes and so on to construct a Custom Element. Here is an typical example (using ES5 syntax): + +```js +var ctor = function() { + return document.createElement('x-custom'); +}; +ctor.prototype = Object.create(HTMLElement.prototype); +ctor.prototype.constructor = ctor; +ctor.prototype.createdCallback = function() { + this.innerHTML = 'Hello World, I am a <b>Custom Element!</b>'; +} +document.registerElement('x-custom', ctor); +``` + +### Reluctant Polymer() Abstraction + +By principle, Polymer team tries to avoid abstracting DOM APIs, especially new ones. But in this case we finally decided the ergonomic benefit was worth it. By wrapping `registerElement` in our own function, we can reduce the above boilerplate to: + +```js +var ctor = Polymer({ + is: 'x-custom', + created: function() { + this.innerHTML = 'Hello World, I am a <b>Custom Element!</b>'; + } +}); +``` + +### Polymer() Does a Bit More + +You might notice the `Polymer()` invocation defines `created` instead of `createdCallback`. This is a feature of `Polymer.Base`, a tiny prototype that `Polymer()` adds to your prototype chain as it's handling the boilerplate above. `Polymer.Base` hooks the standard Custom Element lifecycle callbacks to provide helper implementations. The hooks in turn call shorter-named lifecycle methods on your prototype. + +- `created` instead of `createdCallback` +- `attached` instead of `attachedCallback` +- `detached` instead of `detachedCallback` +- `attributeChanged` instead of `attributeChangedCallback` + +You can always fallback to using the low-level methods if you wish (iow, you could simply implement `createdCallback` in your prototype). + +`Polymer.Base` also implements `registerCallback` on your prototype. `Polymer()` calls `registerCallback` which allows `Polymer.Base` to supply a layering system for Polymer abstractions so that no element needs to pay for features it doesn't use. + +## Features + +By default, the default Polymer distribution include several features. Although `Polymer.Base` itself is tiny, if you examine `Polymer.Base` you will probably see several methods that have been plugged-in to that prototype by feature definitions. The next few sections will explain these features and why we include them in the default set. Keep in mind that it's entirely possible to construct custom feature sets, or even use a trivial, featureless form of `Polymer()`. + +### Feature: _property-config_ + +The first feature implements support for the `properties` property. By placing a object-valued `properties` property on your prototype, let's you define various aspects of your custom-elements public API. + +By itself, the `properties` feature **doesn't do anything**. It only provides API for asking questions about these special properties (see [link to docs] for details). + +```js +Polymer({ + + is: 'x-custom', + + properties: { + user: String, + isHappy: Boolean, + count: { + type: Number, + readOnly: true, + notify: true + } + }, + + created: function() { + this.innerHTML = 'Hello World, I am a <b>Custom Element!</b>'; + } + +}); +``` + +Remember that the fields assigned to `count`, such as `readOnly` and `notify` don't do anything by themselves, it requires other features to give them life. + +### Feature: _attributes_ + +Many custom elements want to support configuration using HTML attributes. Custom Elements provides the `attributeChanged` callback gives us the raw API for this ability, but then we have to deal with initialization and type conversion (attributes are always strings). Here is an example of a custom element that supports a `user` attribute using the raw API. + +```js + Polymer({ + + is: 'x-custom', + + created: function() { + // handle any initial value + this.attributeChanged('user'); + // render + this.innerHTML = 'Hello World, my user is ' + (this.user || 'nobody') + '.'; + }, + + attributeChanged: function(name) { + switch(name) { + case 'user': + // pretty easy since user is a String, for other types + // we have to do more work + if (this.hasAttribute('user')) { + this.user = this.getAttribute('user'); + } + break; + } + } + + }); +``` + +Although it's relatively simple, having to write this code becomes annoying when working with multiple attributes or non-String types. It's also not very DRY. + +Instead, Polymer's `attributes` feature handles this work for you (using the `properties` feature data). If an attribute is set that matches a property listed in the `properties` object, the value is captured into the matching property. Strings are automatically converted to the specified type. + +The type system includes support for Object values expressed as JSON, or Date objects expressed as any Date-parsable string representation. Boolean properties are mapped to Boolean attributes, in other words, if the attribute exists at all, its value is true, regardless of its string-value (and the value is only false if the attribute does not exist). + +Here is the equivalent of the above code, taking advantage of the `attributes` feature. + +```html +<script> + + Polymer({ + + is: 'x-custom', + + properties: { + user: String + }, + + created: function() { + // render + this.innerHTML = 'Hello World, my user is ' + (this.user || 'nobody') + '.'; + } + + }); + +</script> + +<x-custom user="Scott"></x-custom> +``` + +### [ToDoc] attributes:hostAttributes + +### Feature: _template_ + +HTML templates are an emerging web standard that we like to consider part of the Web Components family. Templates are a great way to provide archetypal DOM content for your custom element, and this is where the `template` feature comes in. + +As usual, we started by writing basic template support by hand. It generally looks something like this: + +```html +<template> + + Hello World from x-custom! + + </template> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + var template = <find the template somehow>; + var instance = document.importNode(template.content, true); + this.appendChild(instance); + } + + }); + +</script> +``` + +Again, it's simple, but it's a common pattern, so the `template` feature does it automatically. By default it looks for a template as the first element before the script, so our code can look like this: + +```html +<template> + + Hello World from x-custom! + +</template> + +<script> + + Polymer({ + + is: 'x-custom' + + }); + +</script> +``` + +### Feature: _annotations_ + +Most elements need to customize the DOM instanced from a template. For this reason, it's handy to encode markers into your template to indicate special nodes, attributes, or text. Polymer calls these markers _annotations_. The `annotations` feature scans the template (once per element, at registration time) and builds a data-structure into the prototype that identifies markers it finds in the DOM (see [link to docs] for details). Normally you do not need to work with this data directly, Polymer does it for you. + +### Feature: _annotations-nodes_ + +Traditionally, modifying DOM is done by querying for elements to manipulate. Here is an example: + +```html +<template> + + Hello World from <span id="name"></span>! + +</template> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + this.querySelector("#name").textContent = this.name; + } + + }); + +</script> +``` + +This example is very simple. But in real projects, repeating queries is inefficient, so query results are often stored (memoized). Also, as DOM composition becomes more tricky, crafting correct queries can be difficult. For these reasons, automatically capturing nodes makes a good feature. + +The `annotations-nodes` feature builds a map of instance nodes by `id` in `this.$` (using the `annotations` feature data). Here is how the `annotations-nodes` feature simplifies the above example. + +```html +<template> + + Hello World from <span id="name"></span>! + +</template> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + this.$.name.textContent = this.name; + } + + }); + +</script> +``` + +### Feature: _annotations-events_ + +Most elements also need to listen for events. The standard DOM method `addEventListener` provides the low-level support: + +```html +<template> + + <button id="button">Kick Me</button> + +</template> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + this.$.button.addEventListener('click', function() { + alert('Ow!'); + }); + } + + }); + +</script> +``` + +Again, this is pretty simple, but it's so common that it's worth making even simpler. The `annotations-events` feature supports declaring event listeners directly in our template. + +Declaring listeners in the template is convenient, and also helps us decouple view from behavior. + +```html +<template> + + <button on-click="kickAction">Kick Me</button> + +</template> + +<script> + + Polymer({ + + is: 'x-custom', + + kickAction: function() { + alert('Ow!'); + } + + }); + +</script> +``` + +Notice that the `kickAction` method doesn't know anything about `button`. If we decided that kicking should be performed by a key-press, or a menu-item, the element code doesn't need to know. We can change the UI however we want. Also notice that by attaching the event declaratively, we have removed the need to give the button an id. + +### [ToDoc] events feature + +### [ToDoc] keys feature + +### [ToDoc] content feature + +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/bower.json b/third_party/polymer/v0_8/components-chromium/polymer/bower.json new file mode 100644 index 0000000..f2bb8f74 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/bower.json
@@ -0,0 +1,26 @@ +{ + "name": "polymer", + "version": "0.8.0-rc.7", + "main": [ + "polymer.html" + ], + "license": "http://polymer.github.io/LICENSE.txt", + "ignore": [ + "/.*", + "/test/" + ], + "authors": [ + "The Polymer Authors (http://polymer.github.io/AUTHORS.txt)" + ], + "repository": { + "type": "git", + "url": "https://github.com/Polymer/polymer.git" + }, + "dependencies": { + "webcomponentsjs": "^0.6.0" + }, + "devDependencies": { + "web-component-tester": "*" + }, + "private": true +}
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/build.bat b/third_party/polymer/v0_8/components-chromium/polymer/build.bat new file mode 100755 index 0000000..261afde --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/build.bat
@@ -0,0 +1,2 @@ +START /B vulcanize polymer-simplex.html --inline --strip -output dist/polymer-simplex.html +START /B vulcanize polymer.html --inline --strip -output dist/polymer.html
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/docs/index.html b/third_party/polymer/v0_8/components-chromium/polymer/docs/index.html new file mode 100644 index 0000000..b2fa016 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/docs/index.html
@@ -0,0 +1,48 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <title>x-doc-viewer</title> + + <script src="../perf-lib/perf.js"></script> + + <link rel="import" href="../x-elements/x-doc-viewer/x-doc-viewer.html"> + <link rel="import" href="../assets/icons.html"> + + <style> + + html, body { + font-family: Arial, sans-serif; + margin: 0; + } + + </style> + +</head> + +<body fullbleed vertical layout> + + <script>console.perf();</script> + + <x-doc-viewer flex sources='[ + "src/features/standard/bind.html", + "src/features/standard/notify-path.html", + "src/features/micro/properties.html", + "src/features/standard/annotations.html", + "../x-elements/x-doc-viewer/x-doc-viewer.html" + ]'></x-doc-viewer> + + <script>console.perfEnd();</script> + +</body> + +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/index.html b/third_party/polymer/v0_8/components-chromium/polymer/index.html new file mode 100644 index 0000000..77a180b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="polymer.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/polymer-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/polymer-extracted.js new file mode 100644 index 0000000..91fd869 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/polymer-extracted.js
@@ -0,0 +1,64 @@ + + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + // template + this._prepTemplate(); + // template markup + this._prepAnnotations(); + // accessors + this._prepEffects(); + // shared behaviors + this._prepBehaviors(); + // accessors part 2 + this._prepBindings(); + // dom encapsulation + this._prepShady(); + }, + + _prepBehavior: function(b) { + this._addPropertyEffects(b.properties || b.accessors); + this._addComplexObserverEffects(b.observers); + }, + + _initFeatures: function() { + // manage local dom + this._poolContent(); + // manage configuration + this._setupConfigure(); + // host stack + this._pushHost(); + // instantiate template + this._stampTemplate(); + // host stack + this._popHost(); + // concretize template references + this._marshalAnnotationReferences(); + // setup debouncers + this._setupDebouncers(); + // concretize effects on instance + this._marshalInstanceEffects(); + // acquire instance behaviors + this._marshalBehaviors(); + // acquire initial instance attribute values + this._marshalAttributes(); + // top-down initial distribution, configuration, & ready callback + this._tryReady(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + // establish listeners on instance + this._listenListeners(b.listeners); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/polymer-micro-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/polymer-micro-extracted.js new file mode 100644 index 0000000..1d2a0d50 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/polymer-micro-extracted.js
@@ -0,0 +1,31 @@ + + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // shared behaviors + this._prepBehaviors(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + }, + + _prepBehavior: function() {}, + + _initFeatures: function() { + // setup debouncers + this._setupDebouncers(); + // acquire behaviors + this._marshalBehaviors(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/polymer-micro.html b/third_party/polymer/v0_8/components-chromium/polymer/polymer-micro.html new file mode 100644 index 0000000..ce81a86 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/polymer-micro.html
@@ -0,0 +1,18 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="src/polymer-lib.html"> +<link rel="import" href="src/micro/tag.html"> +<link rel="import" href="src/micro/behaviors.html"> +<link rel="import" href="src/micro/extends.html"> +<link rel="import" href="src/micro/constructor.html"> +<link rel="import" href="src/micro/properties.html"> +<link rel="import" href="src/micro/attributes.html"> +<link rel="import" href="src/micro/debouncer.html"> + +</head><body><script src="polymer-micro-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/polymer-mini-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/polymer-mini-extracted.js new file mode 100644 index 0000000..6ec9644e --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/polymer-mini-extracted.js
@@ -0,0 +1,47 @@ + + + Polymer.DomModule = document.createElement('dom-module'); + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // shared behaviors + this._prepBehaviors(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + // template + this._prepTemplate(); + // dom encapsulation + this._prepShady(); + }, + + _prepBehavior: function() {}, + + _initFeatures: function() { + // manage local dom + this._poolContent(); + // host stack + this._pushHost(); + // instantiate template + this._stampTemplate(); + // host stack + this._popHost(); + // setup debouncers + this._setupDebouncers(); + // instance shared behaviors + this._marshalBehaviors(); + // top-down initial distribution, configuration, & ready callback + this._tryReady(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/polymer-mini.html b/third_party/polymer/v0_8/components-chromium/polymer/polymer-mini.html new file mode 100644 index 0000000..e9a540a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/polymer-mini.html
@@ -0,0 +1,16 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="polymer-micro.html"> + +<link rel="import" href="src/mini/template.html"> +<link rel="import" href="src/mini/ready.html"> +<link rel="import" href="src/mini/shady.html"> +<link rel="import" href="src/mini/shadow.html"> + +</head><body><script src="polymer-mini-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/polymer.html b/third_party/polymer/v0_8/components-chromium/polymer/polymer.html new file mode 100644 index 0000000..8d752ac --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/polymer.html
@@ -0,0 +1,64 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><meta charset="UTF-8"><!-- + +The `x-style` extension of the native `<style>` element allows defining styles +in the main document that can take advantage of several special features of +Polymer's styling system: + +* Document styles defined in an `x-style` will be shimmed to ensure they do +not leak into local DOM when running on browsers without non-native Shadow DOM. +* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on +browsers without non-native Shadow DOM. +* Custom properties used by Polymer's experimental shim for cross-scope styling +may be defined in an `x-style`. + +Example: + +```html +<!doctype html> +<html> +<head> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + + <style is="x-style"> + + /* Will be prevented from affecting local DOM of Polymer elements */ + * { + box-sizing: border-box; + } + + /* Can use /deep/ and ::shadow combinators */ + body /deep/ .my-special-view::shadow #thing-inside { + background: yellow; + } + + /* Custom properties that inherit down the document tree may be defined */ + body { + --my-toolbar-title-color: green; + } + + </style> + +</head> +<body> + + ... + +</body> +</html> +``` + +Note, all features of `x-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `x-style` extension should only be used for defining document styles, outside of a custom element's local DOM. + +--> + +</head><body> +<script src="polymer.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/polymer.js b/third_party/polymer/v0_8/components-chromium/polymer/polymer.js new file mode 100644 index 0000000..7a400f3 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/polymer.js
@@ -0,0 +1,6840 @@ + + + Polymer = { + Settings: (function() { + // NOTE: Users must currently opt into using ShadowDOM. They do so by doing: + // Polymer = {dom: 'shadow'}; + // TODO(sorvell): Decide if this should be auto-use when available. + // TODO(sorvell): if SD is auto-use, then the flag above should be something + // like: Polymer = {dom: 'shady'} + + // via Polymer object + var user = window.Polymer || {}; + + // via url + location.search.slice(1).split('&').forEach(function(o) { + o = o.split('='); + o[0] && (user[o[0]] = o[1] || true); + }); + + var wantShadow = (user.dom === 'shadow'); + var hasShadow = Boolean(Element.prototype.createShadowRoot); + var nativeShadow = hasShadow && !window.ShadowDOMPolyfill; + var useShadow = wantShadow && hasShadow; + + var hasNativeImports = Boolean('import' in document.createElement('link')); + var useNativeImports = hasNativeImports; + + var useNativeCustomElements = (!window.CustomElements || + window.CustomElements.useNative); + + return { + wantShadow: wantShadow, + hasShadow: hasShadow, + nativeShadow: nativeShadow, + useShadow: useShadow, + useNativeShadow: useShadow && nativeShadow, + useNativeImports: useNativeImports, + useNativeCustomElements: useNativeCustomElements + }; + })() + }; + + +; + + // until ES6 modules become standard, we follow Occam and simply stake out + // a global namespace + + // Polymer is a Function, but of course this is also an Object, so we + // hang various other objects off of Polymer.* + (function() { + var userPolymer = window.Polymer; + + window.Polymer = function(prototype) { + var ctor = desugar(prototype); + // native Custom Elements treats 'undefined' extends property + // as valued, the property must not exist to be ignored + var options = { + prototype: ctor.prototype + }; + if (prototype.extends) { + options.extends = prototype.extends; + } + Polymer.telemetry._registrate(prototype); + document.registerElement(prototype.is, options); + return ctor; + }; + + var desugar = function(prototype) { + prototype = Polymer.Base.chainObject(prototype, Polymer.Base); + prototype.registerCallback(); + return prototype.constructor; + }; + + window.Polymer = Polymer; + + if (userPolymer) { + for (var i in userPolymer) { + Polymer[i] = userPolymer[i]; + } + } + + Polymer.Class = desugar; + + })(); + /* + // Raw usage + [ctor =] Polymer.Class(prototype); + document.registerElement(name, ctor); + + // Simplified usage + [ctor = ] Polymer(prototype); + */ + + // telemetry: statistics, logging, and debug + + Polymer.telemetry = { + registrations: [], + _regLog: function(prototype) { + console.log('[' + prototype.is + ']: registered') + }, + _registrate: function(prototype) { + this.registrations.push(prototype); + Polymer.log && this._regLog(prototype); + }, + dumpRegistrations: function() { + this.registrations.forEach(this._regLog); + } + }; + + +; + + // a tiny bit of sugar for `document.currentScript.ownerDocument` + Object.defineProperty(window, 'currentImport', { + enumerable: true, + configurable: true, + get: function() { + return (document._currentScript || document.currentScript).ownerDocument; + } + }); + + +; + + Polymer.Base = { + + // pluggable features + // `this` context is a prototype, not an instance + _addFeature: function(feature) { + this.extend(this, feature); + }, + + // `this` context is a prototype, not an instance + registerCallback: function() { + this._registerFeatures(); // abstract + this._doBehavior('registered'); // abstract + }, + + createdCallback: function() { + Polymer.telemetry.instanceCount++; + this.root = this; + this._doBehavior('created'); // abstract + this._initFeatures(); // abstract + }, + + // reserved for canonical behavior + attachedCallback: function() { + this.isAttached = true; + this._doBehavior('attached'); // abstract + }, + + // reserved for canonical behavior + detachedCallback: function() { + this.isAttached = false; + this._doBehavior('detached'); // abstract + }, + + // reserved for canonical behavior + attributeChangedCallback: function(name) { + this.setAttributeToProperty(this, name); + this._doBehavior('attributeChanged', arguments); // abstract + }, + + // copy own properties from `api` to `prototype` + extend: function(prototype, api) { + if (prototype && api) { + Object.getOwnPropertyNames(api).forEach(function(n) { + this.copyOwnProperty(n, api, prototype); + }, this); + } + return prototype || api; + }, + + copyOwnProperty: function(name, source, target) { + var pd = Object.getOwnPropertyDescriptor(source, name); + if (pd) { + Object.defineProperty(target, name, pd); + } + } + + }; + + if (Object.__proto__) { + Polymer.Base.chainObject = function(object, inherited) { + if (object && inherited && object !== inherited) { + object.__proto__ = inherited; + } + return object; + }; + } else { + Polymer.Base.chainObject = function(object, inherited) { + if (object && inherited && object !== inherited) { + var chained = Object.create(inherited); + object = Polymer.Base.extend(chained, object); + } + return object; + }; + } + + Polymer.Base = Polymer.Base.chainObject(Polymer.Base, HTMLElement.prototype); + + // TODO(sjmiles): ad hoc telemetry + Polymer.telemetry.instanceCount = 0; + + +; + +(function() { + + var modules = {}; + + var DomModule = function() { + return document.createElement('dom-module'); + }; + + DomModule.prototype = Object.create(HTMLElement.prototype); + + DomModule.prototype.constructor = DomModule; + + DomModule.prototype.createdCallback = function() { + var id = this.id || this.getAttribute('name') || this.getAttribute('is'); + if (id) { + this.id = id; + modules[id] = this; + } + }; + + DomModule.prototype.import = function(id, slctr) { + var m = modules[id]; + if (!m) { + // If polyfilling, a script can run before a dom-module element + // is upgraded. We force the containing document to upgrade + // and try again to workaround this polyfill limitation. + forceDocumentUpgrade(); + m = modules[id]; + } + if (m && slctr) { + m = m.querySelector(slctr); + } + return m; + }; + + // NOTE: HTMLImports polyfill does not + // block scripts on upgrading elements. However, we want to ensure that + // any dom-module in the tree is available prior to a subsequent script + // processing. + // Therefore, we force any dom-modules in the tree to upgrade when dom-module + // is registered by temporarily setting CE polyfill to crawl the entire + // imports tree. (Note: this should only upgrade any imports that have been + // loaded by this point. In addition the HTMLImports polyfill should be + // changed to upgrade elements prior to running any scripts.) + var cePolyfill = window.CustomElements && !CustomElements.useNative; + if (cePolyfill) { + var ready = CustomElements.ready; + CustomElements.ready = true; + } + document.registerElement('dom-module', DomModule); + if (cePolyfill) { + CustomElements.ready = ready; + } + + function forceDocumentUpgrade() { + if (cePolyfill) { + var script = document._currentScript || document.currentScript; + if (script) { + CustomElements.upgradeAll(script.ownerDocument); + } + } + } + +})(); + + +; + + Polymer.Base._addFeature({ + + _prepIs: function() { + if (!this.is) { + var module = + (document._currentScript || document.currentScript).parentNode; + if (module.localName === 'dom-module') { + var id = module.id || module.getAttribute('name') + || module.getAttribute('is') + this.is = id; + } + } + } + + }); + + +; + + /** + * Automatically extend using objects referenced in `behaviors` array. + * + * someBehaviorObject = { + * accessors: { + * value: {type: Number, observer: '_numberChanged'} + * }, + * observers: [ + * // ... + * ], + * ready: function() { + * // called before prototoype's ready + * }, + * _numberChanged: function() {} + * }; + * + * Polymer({ + * + * behaviors: [ + * someBehaviorObject + * ] + * + * ... + * + * }); + * + * @class base feature: behaviors + */ + + Polymer.Base._addFeature({ + + behaviors: [], + + _prepBehaviors: function() { + this._flattenBehaviors(); + this._prepBehavior(this); + this.behaviors.forEach(function(b) { + this._mixinBehavior(b); + this._prepBehavior(b); + }, this); + }, + + _flattenBehaviors: function() { + var flat = []; + this.behaviors.forEach(function(b) { + if (!b) { + console.warn('Polymer: undefined behavior in [' + this.is + ']'); + } else if (b instanceof Array) { + flat = flat.concat(b); + } else { + flat.push(b); + } + }, this); + this.behaviors = flat; + }, + + _mixinBehavior: function(b) { + Object.getOwnPropertyNames(b).forEach(function(n) { + switch (n) { + case 'registered': + case 'properties': + case 'observers': + case 'listeners': + case 'keyPresses': + case 'hostAttributes': + case 'created': + case 'attached': + case 'detached': + case 'attributeChanged': + case 'configure': + case 'ready': + break; + default: + this.copyOwnProperty(n, b, this); + break; + } + }, this); + }, + + _doBehavior: function(name, args) { + this.behaviors.forEach(function(b) { + this._invokeBehavior(b, name, args); + }, this); + this._invokeBehavior(this, name, args); + }, + + _invokeBehavior: function(b, name, args) { + var fn = b[name]; + if (fn) { + fn.apply(this, args || Polymer.nar); + } + }, + + _marshalBehaviors: function() { + this.behaviors.forEach(function(b) { + this._marshalBehavior(b); + }, this); + this._marshalBehavior(this); + } + + }); + + +; + + /** + * Support `extends` property (for type-extension only). + * + * If the mixin is String-valued, the corresponding Polymer module + * is mixed in. + * + * Polymer({ + * is: 'pro-input', + * extends: 'input', + * ... + * }); + * + * Type-extension objects are created using `is` notation in HTML, or via + * the secondary argument to `document.createElement` (the type-extension + * rules are part of the Custom Elements specification, not something + * created by Polymer). + * + * Example: + * + * <!-- right: creates a pro-input element --> + * <input is="pro-input"> + * + * <!-- wrong: creates an unknown element --> + * <pro-input> + * + * <script> + * // right: creates a pro-input element + * var elt = document.createElement('input', 'pro-input'); + * + * // wrong: creates an unknown element + * var elt = document.createElement('pro-input'); + * <\script> + * + * @class base feature: extends + */ + + Polymer.Base._addFeature({ + + _prepExtends: function() { + if (this.extends) { + this.__proto__ = this.getExtendedPrototype(this.extends); + } + }, + + getExtendedPrototype: function(tag) { + return this.getExtendedNativePrototype(tag); + }, + + nativePrototypes: {}, // static + + getExtendedNativePrototype: function(tag) { + var p = this.nativePrototypes[tag]; + if (!p) { + var np = this.getNativePrototype(tag); + p = this.extend(Object.create(np), Polymer.Base); + this.nativePrototypes[tag] = p; + } + return p; + }, + + getNativePrototype: function(tag) { + // TODO(sjmiles): sad necessity + return Object.getPrototypeOf(document.createElement(tag)); + } + + }); + + +; + + /** + * Generates a boilerplate constructor. + * + * XFoo = Polymer({ + * is: 'x-foo' + * }); + * ASSERT(new XFoo() instanceof XFoo); + * + * You can supply a custom constructor on the prototype. But remember that + * this constructor will only run if invoked **manually**. Elements created + * via `document.createElement` or from HTML _will not invoke this method_. + * + * Instead, we reuse the concept of `constructor` for a factory method which + * can take arguments. + * + * MyFoo = Polymer({ + * is: 'my-foo', + * constructor: function(foo) { + * this.foo = foo; + * } + * ... + * }); + * + * @class base feature: constructor + */ + + Polymer.Base._addFeature({ + + // registration-time + + _prepConstructor: function() { + // support both possible `createElement` signatures + this._factoryArgs = this.extends ? [this.extends, this.is] : [this.is]; + // thunk the constructor to delegate allocation to `createElement` + var ctor = function() { + return this._factory(arguments); + }; + if (this.hasOwnProperty('extends')) { + ctor.extends = this.extends; + } + // ensure constructor is set. The `constructor` property is + // not writable on Safari; note: Chrome requires the property + // to be configurable. + Object.defineProperty(this, 'constructor', {value: ctor, + writable: true, configurable: true}); + ctor.prototype = this; + }, + + _factory: function(args) { + var elt = document.createElement.apply(document, this._factoryArgs); + if (this.factoryImpl) { + this.factoryImpl.apply(elt, args); + } + return elt; + } + + }); + + +; + + /** + * Define property metadata. + * + * properties: { + * <property>: <Type || Object>, + * ... + * } + * + * Example: + * + * properties: { + * // `foo` property can be assigned via attribute, will be deserialized to + * // the specified data-type. All `properties` properties have this behavior. + * foo: String, + * + * // `bar` property has additional behavior specifiers. + * // type: as above, type for (de-)serialization + * // notify: true to send a signal when a value is set to this property + * // reflectToAttribute: true to serialize the property to an attribute + * // readOnly: if true, the property has no setter + * bar: { + * type: Boolean, + * notify: true + * } + * } + * + * By itself the properties feature doesn't do anything but provide property + * information. Other features use this information to control behavior. + * + * The `type` information is used by the `attributes` feature to convert + * String values in attributes to typed properties. The `bind` feature uses + * property information to control property access. + * + * Marking a property as `notify` causes a change in the property to + * fire a non-bubbling event called `<property>-changed`. Elements that + * have enabled two-way binding to the property use this event to + * observe changes. + * + * `readOnly` properties have a getter, but no setter. To set a read-only + * property, use the private setter method `_set_<property>(value)`. + * + * @class base feature: properties + */ + + // null object + Polymer.nob = Object.create(null); + + Polymer.Base._addFeature({ + + properties: { + }, + + getPropertyInfo: function(property) { + var info = this._getPropertyInfo(property, this.properties); + if (!info) { + this.behaviors.some(function(b) { + return info = this._getPropertyInfo(property, b.properties); + }, this); + } + return info || Polymer.nob; + }, + + _getPropertyInfo: function(property, properties) { + var p = properties && properties[property]; + if (typeof(p) === 'function') { + p = properties[property] = { + type: p + }; + } + return p; + }, + + getPropertyType: function(property) { + return this.getPropertyInfo(property).type; + }, + + isReadOnlyProperty: function(property) { + return this.getPropertyInfo(property).readOnly; + }, + + isNotifyProperty: function(property) { + return this.getPropertyInfo(property).notify; + }, + + isReflectedProperty: function(property) { + return this.getPropertyInfo(property).reflectToAttribute; + } + + }); + + +; + + Polymer.CaseMap = { + + _caseMap: {}, + + dashToCamelCase: function(dash) { + var mapped = Polymer.CaseMap._caseMap[dash]; + if (mapped) { + return mapped; + } + // TODO(sjmiles): is rejection test actually helping perf? + if (dash.indexOf('-') < 0) { + return Polymer.CaseMap._caseMap[dash] = dash; + } + return Polymer.CaseMap._caseMap[dash] = dash.replace(/-([a-z])/g, + function(m) { + return m[1].toUpperCase(); + } + ); + }, + + camelToDashCase: function(camel) { + var mapped = Polymer.CaseMap._caseMap[camel]; + if (mapped) { + return mapped; + } + return Polymer.CaseMap._caseMap[camel] = camel.replace(/([a-z][A-Z])/g, + function (g) { + return g[0] + '-' + g[1].toLowerCase() + } + ); + } + + }; + + +; + + /** + * Support for `hostAttributes` property. + * + * hostAttributes: 'block vertical layout' + * + * `hostAttributes` is a space-delimited string of boolean attribute names to + * set true on each instance. + * + * Support for mapping attributes to properties. + * + * Properties that are configured in `properties` with a type are mapped + * to attributes. + * + * A value set in an attribute is deserialized into the specified + * data-type and stored into the matching property. + * + * Example: + * + * properties: { + * // values set to index attribute are converted to Number and propagated + * // to index property + * index: Number, + * // values set to label attribute are propagated to index property + * label: String + * } + * + * Types supported for deserialization: + * + * - Number + * - Boolean + * - String + * - Object (JSON) + * - Array (JSON) + * - Date + * + * This feature implements `attributeChanged` to support automatic + * propagation of attribute values at run-time. If you override + * `attributeChanged` be sure to call this base class method + * if you also want the standard behavior. + * + * @class base feature: attributes + */ + + Polymer.Base._addFeature({ + + _marshalAttributes: function() { + this._takeAttributes(); + }, + + _installHostAttributes: function(attributes) { + if (attributes) { + this.applyAttributes(this, attributes); + } + }, + + applyAttributes: function(node, attr$) { + for (var n in attr$) { + this.serializeValueToAttribute(attr$[n], n, this); + } + }, + + _takeAttributes: function() { + this._takeAttributesToModel(this); + }, + + _takeAttributesToModel: function(model) { + for (var i=0, l=this.attributes.length; i<l; i++) { + var a = this.attributes[i]; + var property = Polymer.CaseMap.dashToCamelCase(a.name); + var info = this.getPropertyInfo(property); + if (info || this._propertyEffects[property]) { + model[property] = + this.deserialize(a.value, info.type); + } + } + }, + + setAttributeToProperty: function(model, attrName) { + // Don't deserialize back to property if currently reflecting + if (!this._serializing) { + var propName = Polymer.CaseMap.dashToCamelCase(attrName); + if (propName in this.properties) { + var type = this.getPropertyType(propName); + var val = this.getAttribute(attrName); + model[propName] = this.deserialize(val, type); + } + } + }, + + _serializing: false, + reflectPropertyToAttribute: function(name) { + this._serializing = true; + this.serializeValueToAttribute(this[name], + Polymer.CaseMap.camelToDashCase(name)); + this._serializing = false; + }, + + serializeValueToAttribute: function(value, attribute, node) { + var str = this.serialize(value); + (node || this) + [str === undefined ? 'removeAttribute' : 'setAttribute'] + (attribute, str); + }, + + deserialize: function(value, type) { + switch (type) { + case Number: + value = Number(value); + break; + + case Boolean: + value = (value !== null); + break; + + case Object: + try { + value = JSON.parse(value); + } catch(x) { + // allow non-JSON literals like Strings and Numbers + } + break; + + case Array: + try { + value = JSON.parse(value); + } catch(x) { + value = null; + console.warn('Polymer::Attributes: couldn`t decode Array as JSON'); + } + break; + + case Date: + value = new Date(value); + break; + + case String: + default: + break; + } + return value; + }, + + serialize: function(value) { + switch (typeof value) { + case 'boolean': + return value ? '' : undefined; + + case 'object': + if (value instanceof Date) { + return value; + } else if (value) { + try { + return JSON.stringify(value); + } catch(x) { + return ''; + } + } + + default: + return value != null ? value : undefined; + } + } + + }); + + +; + + Polymer.Base._addFeature({ + + _setupDebouncers: function() { + this._debouncers = {}; + }, + + /** + * Debounce signals. + * + * Call `debounce` to collapse multiple requests for a named task into + * one invocation which is made after the wait time has elapsed with + * no new request. + * + * debouncedClickAction: function(e) { + * // will not call `processClick` more than once per 100ms + * this.debounce('click', function() { + * this.processClick; + * }, 100); + * } + * + * @method debounce + * @param String {String} jobName A string to indentify the debounce job. + * @param Function {Function} callback A function that is called (with `this` context) when the wait time elapses. + * @param Number {Number} wait Time in milliseconds (ms) after the last signal that must elapse before invoking `callback` + * @type Handle + */ + debounce: function(jobName, callback, wait) { + this._debouncers[jobName] = Polymer.Debounce.call(this, + this._debouncers[jobName], callback, wait); + }, + + isDebouncerActive: function(jobName) { + var debouncer = this._debouncers[jobName]; + return debouncer && debouncer.finish; + }, + + flushDebouncer: function(jobName) { + var debouncer = this._debouncers[jobName]; + if (debouncer) { + debouncer.complete(); + } + } + + }); + + +; + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // shared behaviors + this._prepBehaviors(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + }, + + _prepBehavior: function() {}, + + _initFeatures: function() { + // setup debouncers + this._setupDebouncers(); + // acquire behaviors + this._marshalBehaviors(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + } + + }); + + +; + + /** + * Automatic template management. + * + * The `template` feature locates and instances a `<template>` element + * corresponding to the current Polymer prototype. + * + * The `<template>` element may be immediately preceeding the script that + * invokes `Polymer()`. + * + * @class standard feature: template + */ + + Polymer.Base._addFeature({ + + _prepTemplate: function() { + // locate template using dom-module + this._template = + this._template || Polymer.DomModule.import(this.is, 'template'); + // fallback to look at the node previous to the currentScript. + if (!this._template) { + var script = document._currentScript || document.currentScript; + var prev = script && script.previousElementSibling; + if (prev && prev.localName === 'template') { + this._template = prev; + } + } + }, + + _stampTemplate: function() { + if (this._template) { + // note: root is now a fragment which can be manipulated + // while not attached to the element. + this.root = this.instanceTemplate(this._template); + } + }, + + instanceTemplate: function(template) { + var dom = + document.importNode(template._content || template.content, true); + return dom; + } + + }); + + +; + + /** + * Provides `ready` lifecycle callback which is called parent to child. + * + * This can be useful in a number of cases. Here are some examples: + * + * Setting a default property value that should have a side effect: To ensure + * the side effect, an element must set a default value no sooner than + * `created`; however, since `created` flows child to host, this is before the + * host has had a chance to set a property value on the child. The `ready` + * method solves this problem since it's called host to child. + * + * Dom distribution: To support reprojection efficiently, it's important to + * distribute from host to child in one shot. The `attachedCallback` mostly + * goes in the desired order except for elements that are in dom to start; in + * this case, all children are attached before the host element. Ready also + * addresses this case since it's guaranteed to be called host to child. + * + * @class standard feature: ready + */ + +(function() { + + var baseAttachedCallback = Polymer.Base.attachedCallback; + + Polymer.Base._addFeature({ + + hostStack: [], + + // for overriding + ready: function() { + }, + + // NOTE: The concept of 'host' is overloaded. There are two different + // notions: + // 1. an element hosts the elements in its local dom root. + // 2. an element hosts the elements on which it configures data. + // Practially, these notions are almost always coincident. + // Some special elements like templates may separate them. + // In order not to over-emphaisize this technical difference, we expose + // one concept to the user and it maps to the dom-related meaning of host. + // + // 1. set this element's `host` and push this element onto the `host`'s + // list of `client` elements + // 2. establish this element as the current hosting element (allows + // any elements we stamp to easily set host to us). + _pushHost: function(host) { + // NOTE: The `dataHost` of an element never changes. + this.dataHost = host = host || + Polymer.Base.hostStack[Polymer.Base.hostStack.length-1]; + // this.dataHost reflects the parent element who manages + // any bindings for the element. Only elements originally + // stamped from Polymer templates have a dataHost, and this + // never changes + if (host && host._clients) { + host._clients.push(this); + } + this._beginHost(); + }, + + _beginHost: function() { + Polymer.Base.hostStack.push(this); + if (!this._clients) { + this._clients = []; + } + }, + + _popHost: function() { + // this element is no longer the current hosting element + Polymer.Base.hostStack.pop(); + }, + + _tryReady: function() { + if (this._canReady()) { + this._ready(); + } + }, + + _canReady: function() { + return !this.dataHost || this.dataHost._clientsReadied; + }, + + _ready: function() { + // extension point + this._beforeClientsReady(); + this._readyClients(); + // extension point + this._afterClientsReady(); + this._readySelf(); + }, + + _readyClients: function() { + // prepare root + this._setupRoot(); + // logically distribute self + this._beginDistribute(); + // now fully prepare localChildren + var c$ = this._clients; + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + c._ready(); + } + // perform actual dom composition + this._finishDistribute(); + // ensure elements are attached if they are in the dom at ready time + // helps normalize attached ordering between native and polyfill ce. + // TODO(sorvell): worth perf cost? ~6% + // if (!Polymer.Settings.useNativeCustomElements) { + // CustomElements.takeRecords(); + // } + this._clientsReadied = true; + this._clients = null; + }, + + // mark readied and call `ready` + // note: called localChildren -> host + _readySelf: function() { + this._doBehavior('ready'); + this._readied = true; + if (this._attachedPending) { + this._attachedPending = false; + this.attachedCallback(); + } + }, + + // for system overriding + _beforeClientsReady: function() {}, + _afterClientsReady: function() {}, + + // normalize lifecycle: ensure attached occurs only after ready. + attachedCallback: function() { + if (this._readied) { + baseAttachedCallback.call(this); + } else { + this._attachedPending = true; + } + } + + }); + +})(); + + +; + +Polymer.ArraySplice = (function() { + + function newSplice(index, removed, addedCount) { + return { + index: index, + removed: removed, + addedCount: addedCount + }; + } + + var EDIT_LEAVE = 0; + var EDIT_UPDATE = 1; + var EDIT_ADD = 2; + var EDIT_DELETE = 3; + + function ArraySplice() {} + + ArraySplice.prototype = { + + // Note: This function is *based* on the computation of the Levenshtein + // "edit" distance. The one change is that "updates" are treated as two + // edits - not one. With Array splices, an update is really a delete + // followed by an add. By retaining this, we optimize for "keeping" the + // maximum array items in the original array. For example: + // + // 'xxxx123' -> '123yyyy' + // + // With 1-edit updates, the shortest path would be just to update all seven + // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This + // leaves the substring '123' intact. + calcEditDistances: function(current, currentStart, currentEnd, + old, oldStart, oldEnd) { + // "Deletion" columns + var rowCount = oldEnd - oldStart + 1; + var columnCount = currentEnd - currentStart + 1; + var distances = new Array(rowCount); + + // "Addition" rows. Initialize null column. + for (var i = 0; i < rowCount; i++) { + distances[i] = new Array(columnCount); + distances[i][0] = i; + } + + // Initialize null row + for (var j = 0; j < columnCount; j++) + distances[0][j] = j; + + for (var i = 1; i < rowCount; i++) { + for (var j = 1; j < columnCount; j++) { + if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1])) + distances[i][j] = distances[i - 1][j - 1]; + else { + var north = distances[i - 1][j] + 1; + var west = distances[i][j - 1] + 1; + distances[i][j] = north < west ? north : west; + } + } + } + + return distances; + }, + + // This starts at the final weight, and walks "backward" by finding + // the minimum previous weight recursively until the origin of the weight + // matrix. + spliceOperationsFromEditDistances: function(distances) { + var i = distances.length - 1; + var j = distances[0].length - 1; + var current = distances[i][j]; + var edits = []; + while (i > 0 || j > 0) { + if (i == 0) { + edits.push(EDIT_ADD); + j--; + continue; + } + if (j == 0) { + edits.push(EDIT_DELETE); + i--; + continue; + } + var northWest = distances[i - 1][j - 1]; + var west = distances[i - 1][j]; + var north = distances[i][j - 1]; + + var min; + if (west < north) + min = west < northWest ? west : northWest; + else + min = north < northWest ? north : northWest; + + if (min == northWest) { + if (northWest == current) { + edits.push(EDIT_LEAVE); + } else { + edits.push(EDIT_UPDATE); + current = northWest; + } + i--; + j--; + } else if (min == west) { + edits.push(EDIT_DELETE); + i--; + current = west; + } else { + edits.push(EDIT_ADD); + j--; + current = north; + } + } + + edits.reverse(); + return edits; + }, + + /** + * Splice Projection functions: + * + * A splice map is a representation of how a previous array of items + * was transformed into a new array of items. Conceptually it is a list of + * tuples of + * + * <index, removed, addedCount> + * + * which are kept in ascending index order of. The tuple represents that at + * the |index|, |removed| sequence of items were removed, and counting forward + * from |index|, |addedCount| items were added. + */ + + /** + * Lacking individual splice mutation information, the minimal set of + * splices can be synthesized given the previous state and final state of an + * array. The basic approach is to calculate the edit distance matrix and + * choose the shortest path through it. + * + * Complexity: O(l * p) + * l: The length of the current array + * p: The length of the old array + */ + calcSplices: function(current, currentStart, currentEnd, + old, oldStart, oldEnd) { + var prefixCount = 0; + var suffixCount = 0; + + var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart); + if (currentStart == 0 && oldStart == 0) + prefixCount = this.sharedPrefix(current, old, minLength); + + if (currentEnd == current.length && oldEnd == old.length) + suffixCount = this.sharedSuffix(current, old, minLength - prefixCount); + + currentStart += prefixCount; + oldStart += prefixCount; + currentEnd -= suffixCount; + oldEnd -= suffixCount; + + if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0) + return []; + + if (currentStart == currentEnd) { + var splice = newSplice(currentStart, [], 0); + while (oldStart < oldEnd) + splice.removed.push(old[oldStart++]); + + return [ splice ]; + } else if (oldStart == oldEnd) + return [ newSplice(currentStart, [], currentEnd - currentStart) ]; + + var ops = this.spliceOperationsFromEditDistances( + this.calcEditDistances(current, currentStart, currentEnd, + old, oldStart, oldEnd)); + + var splice = undefined; + var splices = []; + var index = currentStart; + var oldIndex = oldStart; + for (var i = 0; i < ops.length; i++) { + switch(ops[i]) { + case EDIT_LEAVE: + if (splice) { + splices.push(splice); + splice = undefined; + } + + index++; + oldIndex++; + break; + case EDIT_UPDATE: + if (!splice) + splice = newSplice(index, [], 0); + + splice.addedCount++; + index++; + + splice.removed.push(old[oldIndex]); + oldIndex++; + break; + case EDIT_ADD: + if (!splice) + splice = newSplice(index, [], 0); + + splice.addedCount++; + index++; + break; + case EDIT_DELETE: + if (!splice) + splice = newSplice(index, [], 0); + + splice.removed.push(old[oldIndex]); + oldIndex++; + break; + } + } + + if (splice) { + splices.push(splice); + } + return splices; + }, + + sharedPrefix: function(current, old, searchLength) { + for (var i = 0; i < searchLength; i++) + if (!this.equals(current[i], old[i])) + return i; + return searchLength; + }, + + sharedSuffix: function(current, old, searchLength) { + var index1 = current.length; + var index2 = old.length; + var count = 0; + while (count < searchLength && this.equals(current[--index1], old[--index2])) + count++; + + return count; + }, + + calculateSplices: function(current, previous) { + return this.calcSplices(current, 0, current.length, previous, 0, + previous.length); + }, + + equals: function(currentValue, previousValue) { + return currentValue === previousValue; + } + }; + + return new ArraySplice(); + +})(); + +; + + Polymer.EventApi = (function() { + + var Settings = Polymer.Settings; + + var EventApi = function(event) { + this.event = event; + }; + + if (Settings.useShadow) { + + EventApi.prototype = { + + get rootTarget() { + return this.event.path[0]; + }, + + get localTarget() { + return this.event.target; + }, + + get path() { + return this.event.path; + } + + }; + + } else { + + EventApi.prototype = { + + get rootTarget() { + return this.event.target; + }, + + get localTarget() { + var current = this.event.currentTarget; + var currentRoot = current && Polymer.dom(current).getOwnerRoot(); + var p$ = this.path; + for (var i=0; i < p$.length; i++) { + if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) { + return p$[i]; + } + } + }, + + // TODO(sorvell): simulate event.path. This probably incorrect for + // non-bubbling events. + get path() { + if (!this.event._path) { + var path = []; + var o = this.rootTarget; + while (o) { + path.push(o); + o = Polymer.dom(o).parentNode || o.host; + } + // event path includes window in most recent native implementations + path.push(window); + this.event._path = path; + } + return this.event._path; + } + + }; + + } + + var factory = function(event) { + if (!event.__eventApi) { + event.__eventApi = new EventApi(event); + } + return event.__eventApi; + }; + + return { + factory: factory + }; + + })(); + + +; + + Polymer.DomApi = (function() { + + var Debounce = Polymer.Debounce; + var Settings = Polymer.Settings; + + var nativeInsertBefore = Element.prototype.insertBefore; + var nativeRemoveChild = Element.prototype.removeChild; + var nativeAppendChild = Element.prototype.appendChild; + + var dirtyRoots = []; + + var DomApi = function(node, patch) { + this.node = node; + if (patch) { + this.patch(); + } + }; + + DomApi.prototype = { + + // experimental: support patching selected native api. + patch: function() { + var self = this; + this.node.appendChild = function(node) { + return self.appendChild(node); + }; + this.node.insertBefore = function(node, ref_node) { + return self.insertBefore(node, ref_node); + }; + this.node.removeChild = function(node) { + return self.removeChild(node); + }; + }, + + get childNodes() { + var c$ = getLightChildren(this.node); + return Array.isArray(c$) ? c$ : Array.prototype.slice.call(c$); + }, + + get children() { + return Array.prototype.filter.call(this.childNodes, function(n) { + return (n.nodeType === Node.ELEMENT_NODE); + }); + }, + + get parentNode() { + return this.node.lightParent || this.node.parentNode; + }, + + flush: function() { + for (var i=0, host; i<dirtyRoots.length; i++) { + host = dirtyRoots[i]; + host.flushDebouncer('_distribute'); + } + dirtyRoots = []; + }, + + _lazyDistribute: function(host) { + if (host.shadyRoot) { + host.shadyRoot._distributionClean = false; + } + // TODO(sorvell): optimize debounce so it does less work by default + // and then remove these checks... + // need to dirty distribution once. + if (!host.isDebouncerActive('_distribute')) { + host.debounce('_distribute', host._distributeContent); + dirtyRoots.push(host); + } + }, + + // cases in which we may not be able to just do standard appendChild + // 1. container has a shadyRoot (needsDistribution IFF the shadyRoot + // has an insertion point) + // 2. container is a shadyRoot (don't distribute, instead set + // container to container.host. + // 3. node is <content> (host of container needs distribution) + appendChild: function(node) { + var distributed; + this._removeNodeFromHost(node); + if (this._nodeIsInLogicalTree(this.node)) { + var host = this._hostForNode(this.node); + this._addLogicalInfo(node, this.node, host && host.shadyRoot); + this._addNodeToHost(node); + if (host) { + distributed = this._maybeDistribute(node, this.node, host); + } + } + if (!distributed) { + // if adding to a shadyRoot, add to host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeAppendChild.call(container, node); + } + return node; + }, + + insertBefore: function(node, ref_node) { + if (!ref_node) { + return this.appendChild(node); + } + var distributed; + this._removeNodeFromHost(node); + if (this._nodeIsInLogicalTree(this.node)) { + saveLightChildrenIfNeeded(this.node); + var children = this.childNodes; + var index = children.indexOf(ref_node); + if (index < 0) { + throw Error('The ref_node to be inserted before is not a child ' + + 'of this node'); + } + var host = this._hostForNode(this.node); + this._addLogicalInfo(node, this.node, host && host.shadyRoot, index); + this._addNodeToHost(node); + if (host) { + distributed = this._maybeDistribute(node, this.node, host); + } + } + if (!distributed) { + // if ref_node is <content> replace with first distributed node + ref_node = ref_node.localName === CONTENT ? + this._firstComposedNode(ref_node) : ref_node; + // if adding to a shadyRoot, add to host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeInsertBefore.call(container, node, ref_node); + } + return node; + }, + + /** + Removes the given `node` from the element's `lightChildren`. + This method also performs dom composition. + */ + removeChild: function(node) { + var distributed; + if (this._nodeIsInLogicalTree(this.node)) { + var host = this._hostForNode(this.node); + distributed = this._maybeDistribute(node, this.node, host); + this._removeNodeFromHost(node); + } + if (!distributed) { + // if removing from a shadyRoot, remove form host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeRemoveChild.call(container, node); + } + return node; + }, + + replaceChild: function(node, ref_node) { + this.insertBefore(node, ref_node); + this.removeChild(ref_node); + return node; + }, + + getOwnerRoot: function() { + return this._ownerShadyRootForNode(this.node); + }, + + _ownerShadyRootForNode: function(node) { + if (node._ownerShadyRoot === undefined) { + var root; + if (node._isShadyRoot) { + root = node; + } else { + var parent = Polymer.dom(node).parentNode; + if (parent) { + root = parent._isShadyRoot ? parent : + this._ownerShadyRootForNode(parent); + } else { + root = null; + } + } + node._ownerShadyRoot = root; + } + return node._ownerShadyRoot; + + }, + + _maybeDistribute: function(node, parent, host) { + var nodeNeedsDistribute = this._nodeNeedsDistribution(node); + var distribute = this._parentNeedsDistribution(parent) || + nodeNeedsDistribute; + if (nodeNeedsDistribute) { + this._updateInsertionPoints(host); + } + if (distribute) { + this._lazyDistribute(host); + } + return distribute; + }, + + _updateInsertionPoints: function(host) { + host.shadyRoot._insertionPoints = + factory(host.shadyRoot).querySelectorAll(CONTENT); + }, + + _nodeIsInLogicalTree: function(node) { + return Boolean(node._isShadyRoot || + this._ownerShadyRootForNode(node) || + node.shadyRoot); + }, + + // note: a node is its own host + _hostForNode: function(node) { + var root = node.shadyRoot || (node._isShadyRoot ? + node : this._ownerShadyRootForNode(node)); + return root && root.host; + }, + + _parentNeedsDistribution: function(parent) { + return parent.shadyRoot && hasInsertionPoint(parent.shadyRoot); + }, + + // TODO(sorvell): technically we should check non-fragment nodes for + // <content> children but since this case is assumed to be exceedingly + // rare, we avoid the cost and will address with some specific api + // when the need arises. + _nodeNeedsDistribution: function(node) { + return (node.localName === CONTENT) || + ((node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) && + node.querySelector(CONTENT)); + }, + + _removeNodeFromHost: function(node) { + if (node.lightParent) { + var root = this._ownerShadyRootForNode(node); + if (root) { + root.host._elementRemove(node); + } + this._removeLogicalInfo(node, node.lightParent); + } + this._removeOwnerShadyRoot(node); + }, + + _addNodeToHost: function(node) { + var checkNode = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? + node.firstChild : node; + var root = this._ownerShadyRootForNode(checkNode); + if (root) { + root.host._elementAdd(node); + } + }, + + _addLogicalInfo: function(node, container, root, index) { + saveLightChildrenIfNeeded(container); + var children = factory(container).childNodes; + index = index === undefined ? children.length : index; + // handle document fragments + if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { + var n = node.firstChild; + while (n) { + children.splice(index++, 0, n); + n.lightParent = container; + n = n.nextSibling; + } + } else { + children.splice(index, 0, node); + node.lightParent = container; + } + }, + + // NOTE: in general, we expect contents of the lists here to be small-ish + // and therefore indexOf to be nbd. Other optimizations can be made + // for larger lists (linked list) + _removeLogicalInfo: function(node, container) { + var children = factory(container).childNodes; + var index = children.indexOf(node); + if ((index < 0) || (container !== node.lightParent)) { + throw Error('The node to be removed is not a child of this node'); + } + children.splice(index, 1); + node.lightParent = null; + }, + + _removeOwnerShadyRoot: function(node) { + // TODO(sorvell): need to clear any children of element? + node._ownerShadyRoot = undefined; + }, + + // TODO(sorvell): This will fail if distribution that affects this + // question is pending; this is expected to be exceedingly rare, but if + // the issue comes up, we can force a flush in this case. + _firstComposedNode: function(content) { + var n$ = factory(content).getDistributedNodes(); + for (var i=0, l=n$.length, n, p$; (i<l) && (n=n$[i]); i++) { + p$ = factory(n).getDestinationInsertionPoints(); + // means that we're composed to this spot. + if (p$[p$.length-1] === content) { + return n; + } + } + }, + + // TODO(sorvell): consider doing native QSA and filtering results. + querySelector: function(selector) { + return this.querySelectorAll(selector)[0]; + }, + + querySelectorAll: function(selector) { + return this._query(function(n) { + return matchesSelector.call(n, selector); + }, this.node); + }, + + _query: function(matcher, node) { + var list = []; + this._queryElements(factory(node).childNodes, matcher, list); + return list; + }, + + _queryElements: function(elements, matcher, list) { + for (var i=0, l=elements.length, c; (i<l) && (c=elements[i]); i++) { + if (c.nodeType === Node.ELEMENT_NODE) { + this._queryElement(c, matcher, list); + } + } + }, + + _queryElement: function(node, matcher, list) { + if (matcher(node)) { + list.push(node); + } + this._queryElements(factory(node).childNodes, matcher, list); + }, + + getDestinationInsertionPoints: function() { + return this.node._destinationInsertionPoints || []; + }, + + getDistributedNodes: function() { + return this.node._distributedNodes || []; + }, + + /* + Returns a list of nodes distributed within this element. These can be + dom children or elements distributed to children that are insertion + points. + */ + queryDistributedElements: function(selector) { + var c$ = this.childNodes; + var list = []; + this._distributedFilter(selector, c$, list); + for (var i=0, l=c$.length, c; (i<l) && (c=c$[i]); i++) { + if (c.localName === CONTENT) { + this._distributedFilter(selector, factory(c).getDistributedNodes(), + list); + } + } + return list; + }, + + _distributedFilter: function(selector, list, results) { + results = results || []; + for (var i=0, l=list.length, d; (i<l) && (d=list[i]); i++) { + if ((d.nodeType === Node.ELEMENT_NODE) && + (d.localName !== CONTENT) && + matchesSelector.call(d, selector)) { + results.push(d); + } + } + return results; + } + + }; + + if (Settings.useShadow) { + + DomApi.prototype.querySelectorAll = function(selector) { + return Array.prototype.slice.call(this.node.querySelectorAll(selector)); + }; + + DomApi.prototype.patch = function() {}; + + DomApi.prototype.getOwnerRoot = function() { + var n = this.node; + while (n) { + if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) { + return n; + } + n = n.parentNode; + } + }; + + DomApi.prototype.getDestinationInsertionPoints = function() { + var n$ = this.node.getDestinationInsertionPoints(); + return n$ ? Array.prototype.slice.call(n$) : []; + }; + + DomApi.prototype.getDistributedNodes = function() { + var n$ = this.node.getDistributedNodes(); + return n$ ? Array.prototype.slice.call(n$) : []; + }; + + + } + + var CONTENT = 'content'; + + var factory = function(node, patch) { + node = node || document; + if (!node.__domApi) { + node.__domApi = new DomApi(node, patch); + } + return node.__domApi; + }; + + Polymer.dom = function(obj, patch) { + if (obj instanceof Event) { + return Polymer.EventApi.factory(obj); + } else { + return factory(obj, patch); + } + }; + + // make flush available directly. + Polymer.dom.flush = DomApi.prototype.flush; + + function getLightChildren(node) { + var children = node.lightChildren; + return children ? children : node.childNodes; + } + + function saveLightChildrenIfNeeded(node) { + // Capture the list of light children. It's important to do this before we + // start transforming the DOM into "rendered" state. + // + // Children may be added to this list dynamically. It will be treated as the + // source of truth for the light children of the element. This element's + // actual children will be treated as the rendered state once lightChildren + // is populated. + if (!node.lightChildren) { + var children = []; + for (var child = node.firstChild; child; child = child.nextSibling) { + children.push(child); + child.lightParent = child.lightParent || node; + } + node.lightChildren = children; + } + } + + function hasInsertionPoint(root) { + return Boolean(root._insertionPoints.length); + } + + var p = Element.prototype; + var matchesSelector = p.matches || p.matchesSelector || + p.mozMatchesSelector || p.msMatchesSelector || + p.oMatchesSelector || p.webkitMatchesSelector; + + return { + getLightChildren: getLightChildren, + saveLightChildrenIfNeeded: saveLightChildrenIfNeeded, + matchesSelector: matchesSelector, + hasInsertionPoint: hasInsertionPoint, + factory: factory + }; + + })(); + + +; + + (function() { + /** + + Implements a pared down version of ShadowDOM's scoping, which is easy to + polyfill across browsers. + + */ + Polymer.Base._addFeature({ + + _prepShady: function() { + // Use this system iff localDom is needed. + this._useContent = this._useContent || Boolean(this._template); + if (this._useContent) { + this._template._hasInsertionPoint = + this._template.content.querySelector('content'); + } + }, + + // called as part of content initialization, prior to template stamping + _poolContent: function() { + if (this._useContent) { + // capture lightChildren to help reify dom scoping + saveLightChildrenIfNeeded(this); + } + }, + + // called as part of content initialization, after template stamping + _setupRoot: function() { + if (this._useContent) { + this._createLocalRoot(); + } + }, + + _createLocalRoot: function() { + this.shadyRoot = this.root; + this.shadyRoot._distributionClean = false; + this.shadyRoot._isShadyRoot = true; + this.shadyRoot._dirtyRoots = []; + // capture insertion point list + // TODO(sorvell): it's faster to do this via native qSA than annotator. + this.shadyRoot._insertionPoints = this._template._hasInsertionPoint ? + this.shadyRoot.querySelectorAll('content') : []; + // save logical tree info for shadyRoot. + saveLightChildrenIfNeeded(this.shadyRoot); + this.shadyRoot.host = this; + }, + + /** + * Return the element whose local dom within which this element + * is contained. This is a shorthand for + * `Polymer.dom(this).getOwnerRoot().host`. + */ + get domHost() { + var root = Polymer.dom(this).getOwnerRoot(); + return root && root.host; + }, + + /** + * Force this element to distribute its children to its local dom. + * A user should call `distributeContent` if distribution has been + * invalidated due to changes to selectors on child elements that + * effect distribution. For example, if an element contains an + * insertion point with <content select=".foo"> and a `foo` class is + * added to a child, then `distributeContent` must be called to update + * local dom distribution. + */ + distributeContent: function() { + if (this._useContent) { + this.shadyRoot._distributionClean = false; + this._distributeContent(); + } + }, + + _distributeContent: function() { + if (this._useContent && !this.shadyRoot._distributionClean) { + // logically distribute self + this._beginDistribute(); + this._distributeDirtyRoots(); + this._finishDistribute(); + } + }, + + _beginDistribute: function() { + if (this._useContent && hasInsertionPoint(this.shadyRoot)) { + // reset distributions + this._resetDistribution(); + // compute which nodes should be distributed where + // TODO(jmesserly): this is simplified because we assume a single + // ShadowRoot per host and no `<shadow>`. + this._distributePool(this.shadyRoot, this._collectPool()); + } + }, + + _distributeDirtyRoots: function() { + var c$ = this.shadyRoot._dirtyRoots; + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + c._distributeContent(); + } + this.shadyRoot._dirtyRoots = []; + }, + + _finishDistribute: function() { + // compose self + if (this._useContent) { + if (hasInsertionPoint(this.shadyRoot)) { + this._composeTree(); + } else { + if (!this.shadyRoot._hasDistributed) { + this.textContent = ''; + this.appendChild(this.shadyRoot); + } else { + // simplified non-tree walk composition + var children = this._composeNode(this); + this._updateChildNodes(this, children); + } + } + this.shadyRoot._hasDistributed = true; + this.shadyRoot._distributionClean = true; + } + }, + + // This is a polyfill for Element.prototype.matches, which is sometimes + // still prefixed. Alternatively we could just polyfill it somewhere. + // Note that the arguments are reversed from what you might expect. + elementMatches: function(selector, node) { + if (node === undefined) { + node = this; + } + return matchesSelector.call(node, selector); + }, + + // Many of the following methods are all conceptually static, but they are + // included here as "protected" methods to allow overriding. + + _resetDistribution: function() { + // light children + var children = getLightChildren(this); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child._destinationInsertionPoints) { + child._destinationInsertionPoints = undefined; + } + } + // insertion points + var root = this.shadyRoot; + var p$ = root._insertionPoints; + for (var j = 0; j < p$.length; j++) { + p$[j]._distributedNodes = []; + } + }, + + // Gather the pool of nodes that should be distributed. We will combine + // these with the "content root" to arrive at the composed tree. + _collectPool: function() { + var pool = []; + var children = getLightChildren(this); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (isInsertionPoint(child)) { + pool.push.apply(pool, child._distributedNodes); + } else { + pool.push(child); + } + } + return pool; + }, + + // perform "logical" distribution; note, no actual dom is moved here, + // instead elements are distributed into a `content._distributedNodes` + // array where applicable. + _distributePool: function(node, pool) { + var p$ = node._insertionPoints; + for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) { + this._distributeInsertionPoint(p, pool); + } + }, + + _distributeInsertionPoint: function(content, pool) { + // distribute nodes from the pool that this selector matches + var anyDistributed = false; + for (var i=0, l=pool.length, node; i < l; i++) { + node=pool[i]; + // skip nodes that were already used + if (!node) { + continue; + } + // distribute this node if it matches + if (this._matchesContentSelect(node, content)) { + distributeNodeInto(node, content); + // remove this node from the pool + pool[i] = undefined; + // since at least one node matched, we won't need fallback content + anyDistributed = true; + var parent = content.lightParent; + // dirty a shadyRoot if a change may trigger reprojection! + if (parent && parent.shadyRoot && + hasInsertionPoint(parent.shadyRoot)) { + parent.shadyRoot._distributionClean = false; + this.shadyRoot._dirtyRoots.push(parent); + } + } + } + // Fallback content if nothing was distributed here + if (!anyDistributed) { + var children = getLightChildren(content); + for (var j = 0; j < children.length; j++) { + distributeNodeInto(children[j], content); + } + } + }, + + // Reify dom such that it is at its correct rendering position + // based on logical distribution. + _composeTree: function() { + this._updateChildNodes(this, this._composeNode(this)); + var p$ = this.shadyRoot._insertionPoints; + for (var i=0, l=p$.length, p, parent; (i<l) && (p=p$[i]); i++) { + parent = p.lightParent || p.parentNode; + if (!parent._useContent && (parent !== this) && + (parent !== this.shadyRoot)) { + this._updateChildNodes(parent, this._composeNode(parent)); + } + } + }, + + // Returns the list of nodes which should be rendered inside `node`. + _composeNode: function(node) { + var children = []; + var c$ = getLightChildren(node.shadyRoot || node); + for (var i = 0; i < c$.length; i++) { + var child = c$[i]; + if (isInsertionPoint(child)) { + var distributedNodes = child._distributedNodes; + for (var j = 0; j < distributedNodes.length; j++) { + var distributedNode = distributedNodes[j]; + if (isFinalDestination(child, distributedNode)) { + children.push(distributedNode); + } + } + } else { + children.push(child); + } + } + return children; + }, + + // Ensures that the rendered node list inside `node` is `children`. + _updateChildNodes: function(node, children) { + var splices = + Polymer.ArraySplice.calculateSplices(children, node.childNodes); + for (var i=0; i<splices.length; i++) { + var s = splices[i]; + // remove + for (var j=0, c; j < s.removed.length; j++) { + c = s.removed[j]; + if (c.previousSibling == children[s.index-1]) { + remove(c); + } + } + // insert + for (var idx=s.index, ch, o; idx < s.index + s.addedCount; idx++) { + ch = children[idx]; + o = node.childNodes[idx]; + while (o && o === ch) { + o = o.nextSibling; + } + insertBefore(node, ch, o); + } + } + }, + + _matchesContentSelect: function(node, contentElement) { + var select = contentElement.getAttribute('select'); + // no selector matches all nodes (including text) + if (!select) { + return true; + } + select = select.trim(); + // same thing if it had only whitespace + if (!select) { + return true; + } + // selectors can only match Elements + if (!(node instanceof Element)) { + return false; + } + // only valid selectors can match: + // TypeSelector + // * + // ClassSelector + // IDSelector + // AttributeSelector + // negation + var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/; + if (!validSelectors.test(select)) { + return false; + } + return this.elementMatches(select, node); + }, + + // system override point + _elementAdd: function() {}, + + // system override point + _elementRemove: function() {} + + }); + + var saveLightChildrenIfNeeded = Polymer.DomApi.saveLightChildrenIfNeeded; + var getLightChildren = Polymer.DomApi.getLightChildren; + var matchesSelector = Polymer.DomApi.matchesSelector; + var hasInsertionPoint = Polymer.DomApi.hasInsertionPoint; + + function distributeNodeInto(child, insertionPoint) { + insertionPoint._distributedNodes.push(child); + var points = child._destinationInsertionPoints; + if (!points) { + child._destinationInsertionPoints = [insertionPoint]; + // TODO(sorvell): _destinationInsertionPoints may not be cleared when + // nodes are dynamically added/removed, therefore test before adding + // insertion points. + } else if (points.indexOf(insertionPoint) < 0) { + points.push(insertionPoint); + } + } + + function isFinalDestination(insertionPoint, node) { + var points = node._destinationInsertionPoints; + return points && points[points.length - 1] === insertionPoint; + } + + function isInsertionPoint(node) { + // TODO(jmesserly): we could add back 'shadow' support here. + return node.localName == 'content'; + } + + var nativeInsertBefore = Element.prototype.insertBefore; + var nativeRemoveChild = Element.prototype.removeChild; + + function insertBefore(parentNode, newChild, refChild) { + // remove child from its old parent first + remove(newChild); + // make sure we never lose logical DOM information: + // if the parentNode doesn't have lightChildren, save that information now. + saveLightChildrenIfNeeded(parentNode); + // insert it into the real DOM + nativeInsertBefore.call(parentNode, newChild, refChild || null); + } + + function remove(node) { + var parentNode = node.parentNode; + if (parentNode) { + // make sure we never lose logical DOM information: + // if the parentNode doesn't have lightChildren, save that information now. + saveLightChildrenIfNeeded(parentNode); + // remove it from the real DOM + nativeRemoveChild.call(parentNode, node); + } + } + + })(); + + +; + + /** + Implements `shadyRoot` compatible dom scoping using native ShadowDOM. + */ + + // Transform styles if not using ShadowDOM or if flag is set. + + if (Polymer.Settings.useShadow) { + + Polymer.Base._addFeature({ + + // no-op's when ShadowDOM is in use + _poolContent: function() {}, + _beginDistribute: function() {}, + distributeContent: function() {}, + _distributeContent: function() {}, + _finishDistribute: function() {}, + + // create a shadowRoot + _createLocalRoot: function() { + this.createShadowRoot(); + this.shadowRoot.appendChild(this.root); + this.root = this.shadowRoot; + } + + }); + + } + + +; + + Polymer.DomModule = document.createElement('dom-module'); + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // shared behaviors + this._prepBehaviors(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + // template + this._prepTemplate(); + // dom encapsulation + this._prepShady(); + }, + + _prepBehavior: function() {}, + + _initFeatures: function() { + // manage local dom + this._poolContent(); + // host stack + this._pushHost(); + // instantiate template + this._stampTemplate(); + // host stack + this._popHost(); + // setup debouncers + this._setupDebouncers(); + // instance shared behaviors + this._marshalBehaviors(); + // top-down initial distribution, configuration, & ready callback + this._tryReady(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + } + + }); + + +; +(function(scope) { + + function withDependencies(task, depends) { + depends = depends || []; + if (!depends.map) { + depends = [depends]; + } + return task.apply(this, depends.map(marshal)); + } + + function module(name, dependsOrFactory, moduleFactory) { + var module = null; + switch (arguments.length) { + case 0: + return; + case 2: + // dependsOrFactory is `factory` in this case + module = dependsOrFactory.apply(this); + break; + default: + // dependsOrFactory is `depends` in this case + module = withDependencies(moduleFactory, dependsOrFactory); + break; + } + modules[name] = module; + }; + + function marshal(name) { + return modules[name]; + } + + var modules = {}; + + var using = function(depends, task) { + withDependencies(task, depends); + }; + + // exports + + scope.marshal = marshal; + // `module` confuses commonjs detectors + scope.modulate = module; + scope.using = using; + +})(this); + +; +/** + * Scans a template to produce an annotation list that that associates + * metadata culled from markup with tree locations + * metadata and information to associate the metadata with nodes in an instance. + * + * Supported expressions include: + * + * Double-mustache annotations in text content. The annotation must be the only + * content in the tag, compound expressions are not supported. + * + * <[tag]>{{annotation}}<[tag]> + * + * Double-escaped annotations in an attribute, either {{}} or [[]]. + * + * <[tag] someAttribute="{{annotation}}" another="[[annotation]]"><[tag]> + * + * `on-` style event declarations. + * + * <[tag] on-<event-name>="annotation"><[tag]> + * + * Note that the `annotations` feature does not implement any behaviors + * associated with these expressions, it only captures the data. + * + * Generated data-structure: + * + * [ + * { + * id: '<id>', + * events: [ + * { + * name: '<name>' + * value: '<annotation>' + * }, ... + * ], + * bindings: [ + * { + * kind: ['text'|'attribute'], + * mode: ['{'|'['], + * name: '<name>' + * value: '<annotation>' + * }, ... + * ], + * // TODO(sjmiles): this is annotation-parent, not node-parent + * parent: <reference to parent annotation object>, + * index: <integer index in parent's childNodes collection> + * }, + * ... + * ] + * + * @class Template feature + */ + + // null-array (shared empty array to avoid null-checks) + Polymer.nar = []; + + Polymer.Annotations = { + + // preprocess-time + + // construct and return a list of annotation records + // by scanning `template`'s content + // + parseAnnotations: function(template) { + var list = []; + var content = template._content || template.content; + this._parseNodeAnnotations(content, list); + return list; + }, + + // add annotations gleaned from subtree at `node` to `list` + _parseNodeAnnotations: function(node, list) { + return node.nodeType === Node.TEXT_NODE ? + this._parseTextNodeAnnotation(node, list) : + // TODO(sjmiles): are there other nodes we may encounter + // that are not TEXT_NODE but also not ELEMENT? + this._parseElementAnnotations(node, list); + }, + + // add annotations gleaned from TextNode `node` to `list` + _parseTextNodeAnnotation: function(node, list) { + var v = node.textContent, escape = v.slice(0, 2); + if (escape === '{{' || escape === '[[') { + // NOTE: use a space here so the textNode remains; some browsers + // (IE) evacipate an empty textNode. + node.textContent = ' '; + var annote = { + bindings: [{ + kind: 'text', + mode: escape[0], + value: v.slice(2, -2) + }] + }; + list.push(annote); + return annote; + } + }, + + // add annotations gleaned from Element `node` to `list` + _parseElementAnnotations: function(element, list) { + var annote = { + bindings: [], + events: [] + }; + this._parseChildNodesAnnotations(element, annote, list); + // TODO(sjmiles): is this for non-ELEMENT nodes? If so, we should + // change the contract of this method, or filter these out above. + if (element.attributes) { + this._parseNodeAttributeAnnotations(element, annote, list); + // TODO(sorvell): ad hoc callback for doing work on elements while + // leveraging annotator's tree walk. + // Consider adding an node callback registry and moving specific + // processing out of this module. + if (this.prepElement) { + this.prepElement(element); + } + } + if (annote.bindings.length || annote.events.length || annote.id) { + list.push(annote); + } + return annote; + }, + + // add annotations gleaned from children of `root` to `list`, `root`'s + // `annote` is supplied as it is the annote.parent of added annotations + _parseChildNodesAnnotations: function(root, annote, list, callback) { + if (root.firstChild) { + for (var i=0, node=root.firstChild; node; node=node.nextSibling, i++){ + if (node.localName === 'template' && + !node.hasAttribute('preserve-content')) { + this._parseTemplate(node, i, list, annote); + } + // + var childAnnotation = this._parseNodeAnnotations(node, list, callback); + if (childAnnotation) { + childAnnotation.parent = annote; + childAnnotation.index = i; + } + } + } + }, + + // 1. Parse annotations from the template and memoize them on + // content._notes (recurses into nested templates) + // 2. Parse template bindings for parent.* properties and memoize them on + // content._parentProps + // 3. Create bindings in current scope's annotation list to template for + // parent props found in template + // 4. Remove template.content and store it in annotation list, where it + // will be the responsibility of the host to set it back to the template + // (this is both an optimization to avoid re-stamping nested template + // children and avoids a bug in Chrome where nested template children + // upgrade) + _parseTemplate: function(node, index, list, parent) { + // TODO(sjmiles): simply altering the .content reference didn't + // work (there was some confusion, might need verification) + var content = document.createDocumentFragment(); + content._notes = this.parseAnnotations(node); + content.appendChild(node.content); + // Special-case treatment of 'parent.*' props for nested templates + // Automatically bind `prop` on host to `_parent_prop` on template + // for any `parent.prop`'s encountered in template binding; it is + // responsibility of the template implementation to forward + // these properties as appropriate + var bindings = []; + this._discoverTemplateParentProps(content); + for (var prop in content._parentProps) { + bindings.push({ + index: index, + kind: 'property', + mode: '{', + name: '_parent_' + prop, + value: prop + }); + } + // TODO(sjmiles): using `nar` to avoid unnecessary allocation; + // in general the handling of these arrays needs some cleanup + // in this module + list.push({ + bindings: bindings, + events: Polymer.nar, + templateContent: content, + parent: parent, + index: index + }); + }, + + // Finds all parent.* properties in template content and stores + // the path members in content._parentPropChain, which is an array + // of maps listing the properties of parent templates required at + // each level. Each outer template merges inner _parentPropChains to + // propagate inner parent property needs to outer templates. + // The top-level parent props from the chain (corresponding to this + // template) are stored in content._parentProps. + _discoverTemplateParentProps: function(content) { + var chain = content._parentPropChain = []; + content._notes.forEach(function(n) { + // Find all bindings to parent.* and spread them into _parentPropChain + n.bindings.forEach(function(b) { + var m; + if (m = b.value.match(/parent\.((parent\.)*[^.]*)/)) { + var parts = m[1].split('.'); + for (var i=0; i<parts.length; i++) { + var pp = chain[i] || (chain[i] = {}); + pp[parts[i]] = true; + } + } + }); + // Merge child _parentPropChain[n+1] into this _parentPropChain[n] + if (n.templateContent) { + var tpp = n.templateContent._parentPropChain; + for (var i=1; i<tpp.length; i++) { + if (tpp[i]) { + var pp = chain[i-1] || (chain[i-1] = {}); + Polymer.Base.simpleMixin(pp, tpp[i]); + } + } + } + }); + // Store this template's parentProps map + content._parentProps = chain[0]; + }, + + // add annotation data from attributes to the `annotation` for node `node` + // TODO(sjmiles): the distinction between an `annotation` and + // `annotation data` is not as clear as it could be + // Walk attributes backwards, since removeAttribute can be vetoed by + // IE in certain cases (e.g. <input value="foo">), resulting in the + // attribute staying in the attributes list + _parseNodeAttributeAnnotations: function(node, annotation) { + for (var i=node.attributes.length-1, a; (a=node.attributes[i]); i--) { + var n = a.name, v = a.value; + // id + if (n === 'id') { + annotation.id = v; + } + // events (on-*) + else if (n.slice(0, 3) === 'on-') { + node.removeAttribute(n); + annotation.events.push({ + name: n.slice(3), + value: v + }); + } + // bindings (other attributes) + else { + var b = this._parseNodeAttributeAnnotation(node, n, v); + if (b) { + annotation.bindings.push(b); + } + } + } + }, + + // construct annotation data from a generic attribute, or undefined + _parseNodeAttributeAnnotation: function(node, n, v) { + var mode = '', escape = v.slice(0, 2), name = n; + if (escape === '{{' || escape === '[[') { + // Mode (one-way or two) + mode = escape[0]; + v = v.slice(2, -2); + // Negate + var not = false; + if (v[0] == '!') { + v = v.substring(1); + not = true; + } + // Attribute or property + var kind = 'property'; + if (n[n.length-1] == '$') { + name = n.slice(0, -1); + kind = 'attribute'; + } + // Custom notification event + var notifyEvent, colon; + if (mode == '{' && (colon = v.indexOf('::')) > 0) { + notifyEvent = v.substring(colon + 2); + v = v.substring(0, colon); + } + // Remove annotation + node.removeAttribute(n); + // Case hackery: attributes are lower-case, but bind targets + // (properties) are case sensitive. Gambit is to map dash-case to + // camel-case: `foo-bar` becomes `fooBar`. + // Attribute bindings are excepted. + if (kind === 'property') { + name = Polymer.CaseMap.dashToCamelCase(name); + } + return { + kind: kind, + mode: mode, + name: name, + value: v, + negate: not, + event: notifyEvent + }; + } + }, + + // instance-time + + _localSubTree: function(node, host) { + return (node === host) ? node.childNodes : + (node.lightChildren || node.childNodes); + }, + + findAnnotatedNode: function(root, annote) { + // recursively ascend tree until we hit root + var parent = annote.parent && + Polymer.Annotations.findAnnotatedNode(root, annote.parent); + // unwind the stack, returning the indexed node at each level + return !parent ? root : + Polymer.Annotations._localSubTree(parent, root)[annote.index]; + } + + }; + + + +; + + (function() { + + // path fixup for urls in cssText that's expected to + // come from a given ownerDocument + function resolveCss(cssText, ownerDocument) { + return cssText.replace(CSS_URL_RX, function(m, pre, url, post) { + return pre + '\'' + + resolve(url.replace(/["']/g, ''), ownerDocument) + + '\'' + post; + }); + } + + // url fixup for urls in an element's attributes made relative to + // ownerDoc's base url + function resolveAttrs(element, ownerDocument) { + for (var name in URL_ATTRS) { + var a$ = URL_ATTRS[name]; + for (var i=0, l=a$.length, a, at, v; (i<l) && (a=a$[i]); i++) { + if (name === '*' || element.localName === name) { + at = element.attributes[a]; + v = at && at.value; + if (v && (v.search(BINDING_RX) < 0)) { + at.value = (a === 'style') ? + resolveCss(v, ownerDocument) : + resolve(v, ownerDocument); + } + } + } + } + } + + function resolve(url, ownerDocument) { + var resolver = getUrlResolver(ownerDocument); + resolver.href = url; + return resolver.href || url; + } + + var tempDoc; + var tempDocBase; + function resolveUrl(url, baseUri) { + if (!tempDoc) { + tempDoc = document.implementation.createHTMLDocument('temp'); + tempDocBase = tempDoc.createElement('base'); + tempDoc.head.appendChild(tempDocBase); + } + tempDocBase.href = baseUri; + return resolve(url, tempDoc); + } + + function getUrlResolver(ownerDocument) { + return ownerDocument.__urlResolver || + (ownerDocument.__urlResolver = ownerDocument.createElement('a')); + } + + var CSS_URL_RX = /(url\()([^)]*)(\))/g; + var URL_ATTRS = { + '*': ['href', 'src', 'style', 'url'], + form: ['action'] + }; + var BINDING_RX = /\{\{|\[\[/; + + // exports + Polymer.ResolveUrl = { + resolveCss: resolveCss, + resolveAttrs: resolveAttrs, + resolveUrl: resolveUrl + }; + + })(); + + +; + +/** + * Scans a template to produce an annotation object that stores expression + * metadata along with information to associate the metadata with nodes in an + * instance. + * + * Elements with `id` in the template are noted and marshaled into an + * the `$` hash in an instance. + * + * Example + * + * <template> + * <div id="foo"></div> + * </template> + * <script> + * Polymer({ + * task: function() { + * this.$.foo.style.color = 'red'; + * } + * }); + * </script> + * + * Other expressions that are noted include: + * + * Double-mustache annotations in text content. The annotation must be the only + * content in the tag, compound expressions are not (currently) supported. + * + * <[tag]>{{path.to.host.property}}<[tag]> + * + * Double-mustache annotations in an attribute. + * + * <[tag] someAttribute="{{path.to.host.property}}"><[tag]> + * + * Only immediate host properties can automatically trigger side-effects. + * Setting `host.path` in the example above triggers the binding, setting + * `host.path.to.host.property` does not. + * + * `on-` style event declarations. + * + * <[tag] on-<event-name>="{{hostMethodName}}"><[tag]> + * + * Note: **the `annotations` feature does not actually implement the behaviors + * associated with these expressions, it only captures the data**. + * + * Other optional features contain actual data implementations. + * + * @class standard feature: annotations + */ + +/* + +Scans a template to produce an annotation map that stores expression metadata +and information that associates the metadata to nodes in a template instance. + +Supported annotations are: + + * id attributes + * binding annotations in text nodes + * double-mustache expressions: {{expression}} + * double-bracket expressions: [[expression]] + * binding annotations in attributes + * attribute-bind expressions: name="{{expression}} || [[expression]]" + * property-bind expressions: name*="{{expression}} || [[expression]]" + * property-bind expressions: name:="expression" + * event annotations + * event delegation directives: on-<eventName>="expression" + +Generated data-structure: + + [ + { + id: '<id>', + events: [ + { + mode: ['auto'|''], + name: '<name>' + value: '<expression>' + }, ... + ], + bindings: [ + { + kind: ['text'|'attribute'|'property'], + mode: ['auto'|''], + name: '<name>' + value: '<expression>' + }, ... + ], + // TODO(sjmiles): confusingly, this is annotation-parent, not node-parent + parent: <reference to parent annotation>, + index: <integer index in parent's childNodes collection> + }, + ... + ] + +TODO(sjmiles): this module should produce either syntactic metadata +(e.g. double-mustache, double-bracket, star-attr), or semantic metadata +(e.g. manual-bind, auto-bind, property-bind). Right now it's half and half. + +*/ + + Polymer.Base._addFeature({ + + // registration-time + + _prepAnnotations: function() { + if (!this._template) { + this._notes = []; + } else { + // TODO(sorvell): ad hoc method of plugging behavior into Annotations + Polymer.Annotations.prepElement = this._prepElement.bind(this); + this._notes = Polymer.Annotations.parseAnnotations(this._template); + Polymer.Annotations.prepElement = null; + } + }, + + _prepElement: function(element) { + Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument); + }, + + // instance-time + + findAnnotatedNode: Polymer.Annotations.findAnnotatedNode, + + // marshal all teh things + _marshalAnnotationReferences: function() { + if (this._template) { + this._marshalIdNodes(); + this._marshalAnnotatedNodes(); + this._marshalAnnotatedListeners(); + } + }, + + // push configuration references at configure time + _configureAnnotationReferences: function() { + this._configureTemplateContent(); + }, + + // nested template contents have been stored prototypically to avoid + // unnecessary duplication, here we put references to the + // indirected contents onto the nested template instances + _configureTemplateContent: function() { + this._notes.forEach(function(note) { + if (note.templateContent) { + var template = this.findAnnotatedNode(this.root, note); + template._content = note.templateContent; + } + }, this); + }, + + // construct `$` map (from id annotations) + _marshalIdNodes: function() { + this.$ = {}; + this._notes.forEach(function(a) { + if (a.id) { + this.$[a.id] = this.findAnnotatedNode(this.root, a); + } + }, this); + }, + + // concretize `_nodes` map (from anonymous annotations) + _marshalAnnotatedNodes: function() { + if (this._nodes) { + this._nodes = this._nodes.map(function(a) { + return this.findAnnotatedNode(this.root, a); + }, this); + } + }, + + // install event listeners (from event annotations) + _marshalAnnotatedListeners: function() { + this._notes.forEach(function(a) { + if (a.events && a.events.length) { + var node = this.findAnnotatedNode(this.root, a); + a.events.forEach(function(e) { + this.listen(node, e.name, e.value); + }, this); + } + }, this); + } + + }); + + +; + +(function(scope) { + + 'use strict'; + + var async = scope.Base.async; + + var Gestures = { + gestures: {}, + + // automate the event listeners for the native events + // TODO(dfreedm): add a way to remove handlers. + add: function(evType, node, handler) { + // listen for events in order to "recognize" this event + var g = this.gestures[evType]; + var gn = '_' + evType; + var info = {started: false, abortTrack: false, oneshot: false}; + if (g && !node[gn]) { + if (g.touchaction) { + this._setupTouchAction(node, g.touchaction, info); + } + for (var i = 0, n, sn, fn; i < g.deps.length; i++) { + n = g.deps[i]; + fn = g[n].bind(g, info); + sn = '_' + evType + '-' + n; + // store the handler on the node for future removal + node[sn] = fn; + node.addEventListener(n, fn); + } + node[gn] = 0; + } + // listen for the gesture event + node[gn]++; + node.addEventListener(evType, handler); + }, + + remove: function(evType, node, handler) { + var g = this.gestures[evType]; + var gn = '_' + evType; + if (g && node[gn]) { + for (var i = 0, n, sn, fn; i < g.deps.length; i++) { + n = g.deps[i]; + sn = '_' + evType + '-' + n; + fn = node[sn]; + if (fn){ + node.removeEventListener(n, fn); + // remove stored handler to allow GC + node[sn] = undefined; + } + } + node[gn] = node[gn] ? (node[gn] - 1) : 0; + node.removeEventListener(evType, handler); + } + }, + + register: function(recog) { + this.gestures[recog.name] = recog; + }, + + // touch will make synthetic mouse events + // preventDefault on touchend will cancel them, + // but this breaks <input> focus and link clicks + // Disabling "mouse" handlers for 500ms is enough + + _cancelFunction: null, + + cancelNextClick: function(timeout) { + if (!this._cancelFunction) { + timeout = timeout || 500; + var self = this; + var reset = function() { + var cfn = self._cancelFunction; + if (cfn) { + clearTimeout(cfn.id); + document.removeEventListener('click', cfn, true); + self._cancelFunction = null; + } + }; + var canceller = function(e) { + e.tapPrevented = true; + reset(); + }; + canceller.id = setTimeout(reset, timeout); + this._cancelFunction = canceller; + document.addEventListener('click', canceller, true); + } + }, + + // try to use the native touch-action, if it exists + _hasNativeTA: typeof document.head.style.touchAction === 'string', + + // set scrolling direction on node to check later on first move + // must call this before adding event listeners! + setTouchAction: function(node, value) { + if (this._hasNativeTA) { + node.style.touchAction = value; + } + node.touchAction = value; + }, + + _setupTouchAction: function(node, value, info) { + // reuse custom value on node if set + var ta = node.touchAction; + value = ta || value; + // set an anchor point to see how far first move is + node.addEventListener('touchstart', function(e) { + var t = e.changedTouches[0]; + info.initialTouch = {x: t.clientX, y: t.clientY}; + info.abortTrack = false; + info.oneshot = false; + }); + node.addEventListener('touchmove', function(e) { + // only run this once + if (info.oneshot) { + return; + } + info.oneshot = true; + // "none" means always track + if (value === 'none') { + return; + } + // "auto" is default, always scroll + // bail-out if touch-action did its job + // the touchevent is non-cancelable if the page/area is scrolling + if (value === 'auto' || !value || (ta && !e.cancelable)) { + info.abortTrack = true; + return; + } + // check first move direction + // unfortunately, we can only make the decision in the first move, + // so we have to use whatever values are available. + // Typically, this can be a really small amount, :( + var t = e.changedTouches[0]; + var x = t.clientX, y = t.clientY; + var dx = Math.abs(info.initialTouch.x - x); + var dy = Math.abs(info.initialTouch.y - y); + // scroll in x axis, abort track if we move more in x direction + if (value === 'pan-x') { + info.abortTrack = dx >= dy; + // scroll in y axis, abort track if we move more in y direction + } else if (value === 'pan-y') { + info.abortTrack = dy >= dx; + } + }); + }, + + fire: function(target, type, detail, bubbles, cancelable) { + return target.dispatchEvent( + new CustomEvent(type, { + detail: detail, + bubbles: bubbles, + cancelable: cancelable + }) + ); + } + + }; + + Gestures.register({ + name: 'track', + touchaction: 'none', + deps: ['mousedown', 'touchmove', 'touchend'], + + mousedown: function(info, e) { + var t = e.currentTarget; + var self = this; + var movefn = function movefn(e, up) { + if (!info.tracking && !up) { + // set up tap prevention + Gestures.cancelNextClick(); + } + // first move is 'start', subsequent moves are 'move', mouseup is 'end' + var state = up ? 'end' : (!info.started ? 'start' : 'move'); + info.started = true; + self.fire(t, e, state); + e.preventDefault(); + }; + var upfn = function upfn(e) { + // call mousemove function with 'end' state + movefn(e, true); + info.started = false; + // remove the temporary listeners + document.removeEventListener('mousemove', movefn); + document.removeEventListener('mouseup', upfn); + }; + // add temporary document listeners as mouse retargets + document.addEventListener('mousemove', movefn); + document.addEventListener('mouseup', upfn); + }, + + touchmove: function(info, e) { + var t = e.currentTarget; + var ct = e.changedTouches[0]; + // if track was aborted, stop tracking + if (info.abortTrack) { + return; + } + e.preventDefault(); + // the first track event is sent after some hysteresis with touchmove. + // Use `started` state variable to differentiate the "first" move from + // the rest to make track.state == 'start' + // first move is 'start', subsequent moves are 'move' + var state = !info.started ? 'start' : 'move'; + info.started = true; + this.fire(t, ct, state); + }, + + touchend: function(info, e) { + var t = e.currentTarget; + var ct = e.changedTouches[0]; + // only trackend if track was started and not aborted + if (info.started && !info.abortTrack) { + // reset started state on up + info.started = false; + var ne = this.fire(t, ct, 'end'); + // iff tracking, always prevent tap + e.tapPrevented = true; + } + }, + + fire: function(target, touch, state) { + return Gestures.fire(target, 'track', { + state: state, + x: touch.clientX, + y: touch.clientY + }); + } + + }); + + // dispatch a *bubbling* "tap" only at the node that is the target of the + // generating event. + // dispatch *synchronously* so that we can implement prevention of native + // actions like links being followed. + // + // TODO(dfreedm): a tap should not occur when there's too much movement. + // Right now, a tap can occur when a touchend happens very far from the + // generating touch. + // This *should* obviate the need for tapPrevented via track. + Gestures.register({ + name: 'tap', + deps: ['click', 'touchend'], + + click: function(info, e) { + this.forward(e); + }, + + touchend: function(info, e) { + Gestures.cancelNextClick(); + this.forward(e); + }, + + forward: function(e) { + // prevent taps from being generated from events that have been + // canceled (e.g. via cancelNextClick) or already handled via + // a listener lower in the tree. + if (!e.tapPrevented) { + e.tapPrevented = true; + this.fire(e.target); + } + }, + + // fire a bubbling event from the generating target. + fire: function(target) { + Gestures.fire(target, 'tap', {}, true); + } + + }); + + scope.Gestures = Gestures; + +})(Polymer); + + +; + + /** + * Supports `listeners` and `keyPresses` objects. + * + * Example: + * + * using('Base', function(Base) { + * + * Polymer({ + * + * listeners: { + * // `click` events on the host are delegated to `clickHandler` + * 'click': 'clickHandler' + * }, + * + * keyPresses: { + * // 'ESC' key presses are delegated to `escHandler` + * Base.ESC_KEY: 'escHandler' + * }, + * + * ... + * + * }); + * + * }); + * + * @class standard feature: events + * + */ + + Polymer.Base._addFeature({ + + listeners: {}, + + _listenListeners: function(listeners) { + var node, name, key; + for (key in listeners) { + if (key.indexOf('.') < 0) { + node = this; + name = key; + } else { + name = key.split('.'); + node = this.$[name[0]]; + name = name[1]; + } + this.listen(node, name, listeners[key]); + } + }, + + listen: function(node, eventName, methodName) { + var host = this; + var handler = function(e) { + if (host[methodName]) { + host[methodName](e, e.detail); + } else { + console.warn('[%s].[%s]: event handler [%s] is null in scope (%o)', + node.localName, eventName, methodName, host); + } + }; + switch (eventName) { + case 'tap': + case 'track': + Polymer.Gestures.add(eventName, node, handler); + break; + + default: + node.addEventListener(eventName, handler); + break; + } + }, + + keyCodes: { + ESC_KEY: 27, + ENTER_KEY: 13, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + SPACE: 32 + } + + }); + + +; + +Polymer.Async = (function() { + + var currVal = 0; + var lastVal = 0; + var callbacks = []; + var twiddle = document.createTextNode(''); + + function runAsync(callback, waitTime) { + if (waitTime > 0) { + return ~setTimeout(callback, waitTime); + } else { + twiddle.textContent = currVal++; + callbacks.push(callback); + return currVal - 1; + } + } + + function cancelAsync(handle) { + if (handle < 0) { + clearTimeout(~handle); + } else { + var idx = handle - lastVal; + if (idx >= 0) { + if (!callbacks[idx]) { + throw 'invalid async handle: ' + handle; + } + callbacks[idx] = null; + } + } + } + + function atEndOfMicrotask() { + var len = callbacks.length; + for (var i=0; i<len; i++) { + var cb = callbacks[i]; + if (cb) { + cb(); + } + } + callbacks.splice(0, len); + lastVal += len; + } + + new (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask) + .observe(twiddle, {characterData: true}) + ; + + // exports + + return { + run: runAsync, + cancel: cancelAsync + }; + +})(); + + +; + +Polymer.Debounce = (function() { + + // usage + + // invoke cb.call(this) in 100ms, unless the job is re-registered, + // which resets the timer + // + // this.job = this.debounce(this.job, cb, 100) + // + // returns a handle which can be used to re-register a job + + var Async = Polymer.Async; + + var Debouncer = function(context) { + this.context = context; + this.boundComplete = this.complete.bind(this); + }; + + Debouncer.prototype = { + go: function(callback, wait) { + var h; + this.finish = function() { + Async.cancel(h); + }; + h = Async.run(this.boundComplete, wait); + this.callback = callback; + }, + stop: function() { + if (this.finish) { + this.finish(); + this.finish = null; + } + }, + complete: function() { + if (this.finish) { + this.stop(); + this.callback.call(this.context); + } + } + }; + + function debounce(debouncer, callback, wait) { + if (debouncer) { + debouncer.stop(); + } else { + debouncer = new Debouncer(this); + } + debouncer.go(callback, wait); + return debouncer; + } + + // exports + + return debounce; + +})(); + + +; + + Polymer.Base._addFeature({ + + $$: function(slctr) { + return Polymer.dom(this.root).querySelector(slctr); + }, + + toggleClass: function(name, bool, node) { + node = node || this; + if (arguments.length == 1) { + bool = !node.classList.contains(name); + } + if (bool) { + node.classList.add(name); + } else { + node.classList.remove(name); + } + }, + + toggleAttribute: function(name, bool, node) { + (node || this)[bool ? 'setAttribute' : 'removeAttribute'](name, ''); + }, + + classFollows: function(className, neo, old) { + if (old) { + old.classList.remove(className); + } + if (neo) { + neo.classList.add(className); + } + }, + + attributeFollows: function(name, neo, old) { + if (old) { + old.removeAttribute(name); + } + if (neo) { + neo.setAttribute(name, ''); + } + }, + + getContentChildNodes: function(slctr) { + return Polymer.dom(Polymer.dom(this.root).querySelector( + slctr || 'content')).getDistributedNodes(); + }, + + getContentChildren: function(slctr) { + return this.getContentChildNodes(slctr).filter(function(n) { + return (n.nodeType === Node.ELEMENT_NODE); + }); + }, + + fire: function(type, detail, options) { + options = options || Polymer.nob; + var node = options.node || this; + var detail = (detail === null || detail === undefined) ? Polymer.nob : detail; + var bubbles = options.bubbles === undefined ? true : options.bubbles; + var event = new CustomEvent(type, { + bubbles: Boolean(bubbles), + cancelable: Boolean(options.cancelable), + detail: detail + }); + node.dispatchEvent(event); + return event; + }, + + async: function(method, waitTime) { + return Polymer.Async.run(method.bind(this), waitTime); + }, + + cancelAsync: function(handle) { + Polymer.Async.cancel(handle); + }, + + arrayDelete: function(array, item) { + var index = array.indexOf(item); + if (index >= 0) { + return array.splice(index, 1); + } + }, + + transform: function(node, transform) { + node.style.webkitTransform = transform; + node.style.transform = transform; + }, + + translate3d: function(node, x, y, z) { + this.transform(node, 'translate3d(' + x + ',' + y + ',' + z + ')'); + }, + + importHref: function(href, onload, onerror) { + var l = document.createElement('link'); + l.rel = 'import'; + l.href = href; + if (onload) { + l.onload = onload.bind(this); + } + if (onerror) { + l.onerror = onerror.bind(this); + } + document.head.appendChild(l); + return l; + }, + + create: function(tag, props) { + var elt = document.createElement(tag); + if (props) { + for (var n in props) { + elt[n] = props[n]; + } + } + return elt; + }, + + simpleMixin: function(a, b) { + for (var i in b) { + a[i] = b[i]; + } + } + + }); + + +; + + Polymer.Bind = { + + // for prototypes (usually) + + prepareModel: function(model) { + model._propertyEffects = {}; + model._bindListeners = []; + // TODO(sjmiles): no mixin function? + var api = this._modelApi; + for (var n in api) { + model[n] = api[n]; + } + }, + + _modelApi: { + + _notifyChange: function(property) { + var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed'; + // TODO(sjmiles): oops, `fire` doesn't exist at this layer + this.fire(eventName, { + value: this[property] + }, {bubbles: false}); + }, + + // TODO(sjmiles): removing _notifyListener from here breaks accessors.html + // as a standalone lib. This is temporary, as standard/configure.html + // installs it's own version on Polymer.Base, and we need that to work + // right now. + // NOTE: exists as a hook for processing listeners + /* + _notifyListener: function(fn, e) { + // NOTE: pass e.target because e.target can get lost if this function + // is queued asynchrously + return fn.call(this, e, e.target); + }, + */ + + _propertySet: function(property, value, effects) { + var old = this._data[property]; + if (old !== value) { + this._data[property] = value; + if (typeof value == 'object') { + this._clearPath(property); + } + if (effects) { + this._effectEffects(property, value, effects, old); + } + } + return old; + }, + + _effectEffects: function(property, value, effects, old) { + effects.forEach(function(fx) { + //console.log(fx); + var fn = Polymer.Bind[fx.kind + 'Effect']; + if (fn) { + fn.call(this, property, value, fx.effect, old); + } + }, this); + }, + + _clearPath: function(path) { + for (var prop in this._data) { + if (prop.indexOf(path + '.') === 0) { + this._data[prop] = undefined; + } + } + } + + }, + + // a prepared model can acquire effects + + ensurePropertyEffects: function(model, property) { + var fx = model._propertyEffects[property]; + if (!fx) { + fx = model._propertyEffects[property] = []; + } + return fx; + }, + + addPropertyEffect: function(model, property, kind, effect) { + var fx = this.ensurePropertyEffects(model, property); + fx.push({ + kind: kind, + effect: effect + }); + }, + + createBindings: function(model) { + //console.group(model.is); + // map of properties to effects + var fx$ = model._propertyEffects; + if (fx$) { + // for each property with effects + for (var n in fx$) { + // array of effects + var fx = fx$[n]; + // effects have priority + fx.sort(this._sortPropertyEffects); + // create accessors + this._createAccessors(model, n, fx); + } + } + //console.groupEnd(); + }, + + _sortPropertyEffects: (function() { + // TODO(sjmiles): EFFECT_ORDER buried this way is not ideal, + // but presumably the sort method is going to be a hot path and not + // have a `this`. There is also a problematic dependency on effect.kind + // values here, which are otherwise pluggable. + var EFFECT_ORDER = { + 'compute': 0, + 'annotation': 1, + 'computedAnnotation': 2, + 'reflect': 3, + 'notify': 4, + 'observer': 5, + 'complexObserver': 6, + 'function': 7 + }; + return function(a, b) { + return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind]; + }; + })(), + + // create accessors that implement effects + + _createAccessors: function(model, property, effects) { + var defun = { + get: function() { + // TODO(sjmiles): elide delegation for performance, good ROI? + return this._data[property]; + } + }; + var setter = function(value) { + this._propertySet(property, value, effects); + }; + // ReadOnly properties have a private setter only + // TODO(kschaaf): Per current Bind factoring, we shouldn't + // be interrogating the prototype here + if (model.isReadOnlyProperty && model.isReadOnlyProperty(property)) { + //model['_' + property + 'Setter'] = setter; + //model['_set_' + property] = setter; + model['_set' + this.upper(property)] = setter; + } else { + defun.set = setter; + } + Object.defineProperty(model, property, defun); + }, + + upper: function(name) { + return name[0].toUpperCase() + name.substring(1); + }, + + _addAnnotatedListener: function(model, index, property, path, event) { + var fn = this._notedListenerFactory(property, path, + this._isStructured(path), this._isEventBogus); + var eventName = event || + (Polymer.CaseMap.camelToDashCase(property) + '-changed'); + model._bindListeners.push({ + index: index, + property: property, + path: path, + changedFn: fn, + event: eventName + }); + }, + + _isStructured: function(path) { + return path.indexOf('.') > 0; + }, + + _isEventBogus: function(e, target) { + return e.path && e.path[0] !== target; + }, + + _notedListenerFactory: function(property, path, isStructured, bogusTest) { + return function(e, target) { + if (!bogusTest(e, target)) { + if (e.detail && e.detail.path) { + this.notifyPath(this._fixPath(path, property, e.detail.path), + e.detail.value); + } else { + var value = target[property]; + if (!isStructured) { + this[path] = target[property]; + } else { + // TODO(kschaaf): dirty check avoids null references when the object has gone away + if (this._data[path] != value) { + this.setPathValue(path, value); + } + } + } + } + }; + }, + + // for instances + + prepareInstance: function(inst) { + inst._data = Object.create(null); + }, + + setupBindListeners: function(inst) { + inst._bindListeners.forEach(function(info) { + // Property listeners: + // <node>.on.<property>-changed: <path]> = e.detail.value + //console.log('[_setupBindListener]: [%s][%s] listening for [%s][%s-changed]', this.localName, info.path, info.id || info.index, info.property); + var node = inst._nodes[info.index]; + node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn)); + }); + } + + }; + + +; + + Polymer.Base.extend(Polymer.Bind, { + + _shouldAddListener: function(effect) { + return effect.name && + effect.mode === '{' && + !effect.negate && + effect.kind != 'attribute' + ; + }, + + annotationEffect: function(source, value, effect) { + if (source != effect.value) { + value = this.getPathValue(effect.value); + this._data[effect.value] = value; + } + var calc = effect.negate ? !value : value; + return this._applyEffectValue(calc, effect); + }, + + reflectEffect: function(source) { + this.reflectPropertyToAttribute(source); + }, + + notifyEffect: function(source) { + this._notifyChange(source); + }, + + // Raw effect for extension; effect.function is an actual function + functionEffect: function(source, value, effect, old) { + effect.function.call(this, source, value, effect, old); + }, + + observerEffect: function(source, value, effect, old) { + this[effect.method](value, old); + }, + + complexObserverEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + this[effect.method].apply(this, args); + } + }, + + computeEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + this[effect.property] = this[effect.method].apply(this, args); + } + }, + + annotatedComputationEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + var computedHost = this._rootDataHost || this; + var computedvalue = + computedHost[effect.method].apply(computedHost, args); + this._applyEffectValue(computedvalue, effect); + } + }, + + // path & value are used to fill in wildcard descriptor when effect is + // being called as a result of a path notification + _marshalArgs: function(model, effect, path, value) { + var values = []; + var args = effect.args; + for (var i=0, l=args.length; i<l; i++) { + var arg = args[i]; + var name = arg.name; + var v = arg.structured ? + Polymer.Base.getPathValue(name, model) : model[name]; + if (v === undefined) { + return; + } + if (arg.wildcard) { + // Only send the actual path changed info if the change that + // caused the observer to run matched the wildcard + var baseChanged = (name.indexOf(path + '.') === 0); + var matches = (effect.arg.name.indexOf(name) === 0 && !baseChanged); + values[i] = { + path: matches ? path : name, + value: matches ? value : v, + base: v + }; + } else { + values[i] = v; + } + } + return values; + } + + }); + + +; + + /** + * Support for property side effects. + * + * Key for effect objects: + * + * property | ann | anCmp | cmp | obs | cplxOb | description + * ---------|-----|-------|-----|-----|--------|---------------------------------------- + * method | | X | X | X | X | function name to call on instance + * args | | X | X | | X | list of all arg descriptors for fn + * arg | | X | X | | X | arg descriptor for effect + * property | | | X | X | | property for effect to set or get + * name | X | | | | | annotation value (text inside {{...}}) + * kind | X | X | | | | binding type (property or attribute) + * index | X | X | | | | node index to set + * + */ + + Polymer.Base._addFeature({ + + _addPropertyEffect: function(property, kind, effect) { + // TODO(sjmiles): everything to the right of the first '.' is lost, implies + // there is some duplicate information flow (not the only sign) + var model = property.split('.').shift(); + Polymer.Bind.addPropertyEffect(this, model, kind, effect); + }, + + // prototyping + + _prepEffects: function() { + Polymer.Bind.prepareModel(this); + this._addAnnotationEffects(this._notes); + }, + + _prepBindings: function() { + Polymer.Bind.createBindings(this); + }, + + _addPropertyEffects: function(effects) { + if (effects) { + for (var n in effects) { + var effect = effects[n]; + if (effect.observer) { + this._addObserverEffect(n, effect.observer); + } + if (effect.computed) { + this._addComputedEffect(n, effect.computed); + } + if (effect.notify) { + this._addPropertyEffect(n, 'notify'); + } + if (effect.reflectToAttribute) { + this._addPropertyEffect(n, 'reflect'); + } + if (this.isReadOnlyProperty(n)) { + // Ensure accessor is created + Polymer.Bind.ensurePropertyEffects(this, n); + } + } + } + }, + + _parseMethod: function(expression) { + var m = expression.match(/(\w*)\((.*)\)/); + if (m) { + return { + method: m[1], + args: m[2].split(/[^\w.*]+/).map(this._parseArg) + }; + } + }, + + _parseArg: function(arg) { + var a = { name: arg }; + a.structured = arg.indexOf('.') > 0; + if (a.structured) { + a.wildcard = (arg.slice(-2) == '.*'); + if (a.wildcard) { + a.name = arg.slice(0, -2); + } + } + return a; + }, + + _addComputedEffect: function(name, expression) { + var sig = this._parseMethod(expression); + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'compute', { + method: sig.method, + args: sig.args, + arg: arg, + property: name + }); + }, this); + }, + + _addObserverEffect: function(property, observer) { + this._addPropertyEffect(property, 'observer', { + method: observer, + property: property + }); + }, + + _addComplexObserverEffects: function(observers) { + if (observers) { + observers.forEach(function(observer) { + this._addComplexObserverEffect(observer); + }, this); + } + }, + + _addComplexObserverEffect: function(observer) { + var sig = this._parseMethod(observer); + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'complexObserver', { + method: sig.method, + args: sig.args, + arg: arg + }); + }, this); + }, + + _addAnnotationEffects: function(notes) { + // create a virtual annotation list, must be concretized at instance time + this._nodes = []; + // process annotations that have been parsed from template + notes.forEach(function(note) { + // where to find the node in the concretized list + var index = this._nodes.push(note) - 1; + note.bindings.forEach(function(binding) { + this._addAnnotationEffect(binding, index); + }, this); + }, this); + }, + + _addAnnotationEffect: function(note, index) { + // TODO(sjmiles): annotations have 'effects' proper and 'listener' + if (Polymer.Bind._shouldAddListener(note)) { + // <node>.on.<dash-case-property>-changed: <path> = e.detail.value + Polymer.Bind._addAnnotatedListener(this, index, + note.name, note.value, note.event); + } + var sig = this._parseMethod(note.value); + if (sig) { + this._addAnnotatedComputationEffect(sig, note, index); + } else { + // capture the node index + note.index = index; + // discover top-level property (model) from path + var model = note.value.split('.').shift(); + // add 'annotation' binding effect for property 'model' + this._addPropertyEffect(model, 'annotation', note); + } + }, + + _addAnnotatedComputationEffect: function(sig, note, index) { + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'annotatedComputation', { + kind: note.kind, + method: sig.method, + args: sig.args, + arg: arg, + property: note.name, + index: index + }); + }, this); + }, + + // instancing + + _marshalInstanceEffects: function() { + Polymer.Bind.prepareInstance(this); + Polymer.Bind.setupBindListeners(this); + }, + + _applyEffectValue: function(value, info) { + var node = this._nodes[info.index]; + // TODO(sorvell): ideally, the info object is normalized for easy + // lookup here. + var property = info.property || info.name || 'textContent'; + // special processing for 'class' and 'className'; 'class' handled + // when attr is serialized. + if (info.kind == 'attribute') { + this.serializeValueToAttribute(value, property, node); + } else { + // TODO(sorvell): consider pre-processing this step so we don't need + // this lookup. + if (property === 'className') { + value = this._scopeElementClass(node, value); + } + return node[property] = value; + } + } + + }); + + +; + + /* + Process inputs efficiently via a configure lifecycle callback. + Configure is called top-down, host before local dom. Users should + implement configure to supply a set of default values for the element by + returning an object containing the properties and values to set. + + Configured values are not immediately set, instead they are set when + an element becomes ready, after its local dom is ready. This ensures + that any user change handlers are not called before ready time. + + */ + + /* + Implementation notes: + + Configured values are collected into _config. At ready time, properties + are set to the values in _config. This ensures properties are set child + before host and change handlers are called only at ready time. The host + will reset a value already propagated to a child, but this is not + inefficient because of dirty checking at the set point. + + Bind notification events are sent when properties are set at ready time + and thus received by the host before it is ready. Since notifications result + in property updates and this triggers side effects, handling notifications + is deferred until ready time. + + In general, events can be heard before an element is ready. This may occur + when a user sends an event in a change handler or listens to a data event + directly (on-foo-changed). + */ + + Polymer.Base._addFeature({ + + // storage for configuration + _setupConfigure: function(initialConfig) { + this._config = initialConfig || {}; + this._handlers = []; + }, + + // static attributes are deserialized into _config + _takeAttributes: function() { + this._takeAttributesToModel(this._config); + }, + + // at configure time values are stored in _config + _configValue: function(name, value) { + this._config[name] = value; + }, + + // Override polymer-mini thunk + _beforeClientsReady: function() { + this._configure(); + }, + + // configure: returns user supplied default property values + // combines with _config to create final property values + _configure: function() { + this._configureAnnotationReferences(); + // get individual default values from property configs + var config = {}; + this._configureProperties(this.properties, config); + // behave! + this.behaviors.forEach(function(b) { + this._configureProperties(b.properties, config); + }, this); + // get add'l default values from central configure + // combine defaults returned from configure with inputs in _config + this._mixinConfigure(config, this._config); + // this is the new _config, which are the final values to be applied + this._config = config; + // pass configuration data to bindings + this._distributeConfig(this._config); + }, + + _configureProperties: function(properties, config) { + for (i in properties) { + var c = properties[i]; + if (c.value !== undefined) { + var value = c.value; + if (typeof value == 'function') { + // pass existing config values (this._config) to value function + value = value.call(this, this._config); + } + config[i] = value; + } + } + }, + + _mixinConfigure: function(a, b) { + for (var prop in b) { + if (!this.isReadOnlyProperty(prop)) { + a[prop] = b[prop]; + } + } + }, + + // distribute config values to bound nodes. + _distributeConfig: function(config) { + var fx$ = this._propertyEffects; + if (fx$) { + for (var p in config) { + var fx = fx$[p]; + if (fx) { + for (var i=0, l=fx.length, x; (i<l) && (x=fx[i]); i++) { + if (x.kind === 'annotation') { + var node = this._nodes[x.effect.index]; + // seeding configuration only + if (node._configValue) { + var value = (p === x.effect.value) ? config[p] : + this.getPathValue(x.effect.value, config); + node._configValue(x.effect.name, value); + } + } + } + } + } + } + }, + + // Override polymer-mini thunk + _afterClientsReady: function() { + this._applyConfig(this._config); + this._flushHandlers(); + }, + + // NOTE: values are already propagated to children via + // _distributeConfig so propagation triggered by effects here is + // redundant, but safe due to dirty checking + _applyConfig: function(config) { + for (var n in config) { + // Don't stomp on values that may have been set by other side effects + if (this[n] === undefined) { + // Call _propertySet for any properties with accessors, which will + // initialize read-only properties also + // TODO(kschaaf): consider passing fromAbove here to prevent + // unnecessary notify for: 1) possible perf, 2) debuggability + var effects = this._propertyEffects[n]; + if (effects) { + this._propertySet(n, config[n], effects); + } else { + this[n] = config[n]; + } + } + } + }, + + // NOTE: Notifications can be processed before ready since + // they are sent at *child* ready time. Since notifications cause side + // effects and side effects must not be processed before ready time, + // handling is queue/defered until then. + _notifyListener: function(fn, e) { + if (!this._clientsReadied) { + this._queueHandler([fn, e, e.target]); + } else { + return fn.call(this, e, e.target); + } + }, + + _queueHandler: function(args) { + this._handlers.push(args); + }, + + _flushHandlers: function() { + var h$ = this._handlers; + for (var i=0, l=h$.length, h; (i<l) && (h=h$[i]); i++) { + h[0].call(this, h[1], h[2]); + } + } + + }); + + +; + + /** + * Changes to an object sub-field (aka "path") via a binding + * (e.g. `<x-foo value="{{item.subfield}}"`) will notify other elements bound to + * the same object automatically. + * + * When modifying a sub-field of an object imperatively + * (e.g. `this.item.subfield = 42`), in order to have the new value propagated + * to other elements, a special `setPathValue(path, value)` API is provided. + * `setPathValue` sets the object field at the path specified, and then notifies the + * binding system so that other elements bound to the same path will update. + * + * Example: + * + * Polymer({ + * + * is: 'x-date', + * + * properties: { + * date: { + * type: Object, + * notify: true + * } + * }, + * + * attached: function() { + * this.date = {}; + * setInterval(function() { + * var d = new Date(); + * // Required to notify elements bound to date of changes to sub-fields + * // this.date.seconds = d.getSeconds(); <-- Will not notify + * this.setPathValue('date.seconds', d.getSeconds()); + * this.setPathValue('date.minutes', d.getMinutes()); + * this.setPathValue('date.hours', d.getHours() % 12); + * }.bind(this), 1000); + * } + * + * }); + * + * Allows bindings to `date` sub-fields to update on changes: + * + * <x-date date="{{date}}"></x-date> + * + * Hour: <span>{{date.hours}}</span> + * Min: <span>{{date.minutes}}</span> + * Sec: <span>{{date.seconds}}</span> + * + * @class data feature: path notification + */ + + Polymer.Base._addFeature({ + /** + Notify that a path has changed. For example: + + this.item.user.name = 'Bob'; + this.notifyPath('item.user.name', this.item.user.name); + + Returns true if notification actually took place, based on + a dirty check of whether the new value was already known + */ + notifyPath: function(path, value, fromAbove) { + var old = this._propertySet(path, value); + // manual dirty checking for now... + if (old !== value) { + // console.group((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value); + // Take path effects at this level for exact path matches, + // and notify down for any bindings to a subset of this path + this._pathEffector(path, value); + // Send event to notify the path change upwards + // Optimization: don't notify up if we know the notification + // is coming from above already (avoid wasted event dispatch) + if (!fromAbove) { + // TODO(sorvell): should only notify if notify: true? + this._notifyPath(path, value); + } + // console.groupEnd((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value); + } + }, + + /** + Convienence method for setting a value to a path and calling + notify path + */ + setPathValue: function(path, value) { + var parts = path.split('.'); + if (parts.length > 1) { + var last = parts.pop(); + var prop = this; + while (parts.length) { + prop = prop[parts.shift()]; + if (!prop) { + return; + } + } + // TODO(kschaaf): want dirty-check here? + // if (prop[last] !== value) { + prop[last] = value; + this.notifyPath(path, value); + // } + } else { + this[path] = value; + } + }, + + getPathValue: function(path, root) { + var parts = path.split('.'); + var last = parts.pop(); + var prop = root || this; + while (parts.length) { + prop = prop[parts.shift()]; + if (!prop) { + return; + } + } + return prop[last]; + }, + + // TODO(kschaaf): This machine can be optimized to memoize compiled path + // effectors as new paths are notified for performance, since it involves + // a fair amount of runtime lookup + _pathEffector: function(path, value) { + // get root property + var model = this._modelForPath(path); + // search property effects of the root property for 'annotation' effects + var fx$ = this._propertyEffects[model]; + if (fx$) { + fx$.forEach(function(fx) { + var fxFn = this[fx.kind + 'PathEffect']; + if (fxFn) { + fxFn.call(this, path, value, fx.effect); + } + }, this); + } + // notify runtime-bound paths + if (this._boundPaths) { + this._notifyBoundPaths(path, value); + } + }, + + annotationPathEffect: function(path, value, effect) { + if (effect.value === path || effect.value.indexOf(path + '.') === 0) { + // TODO(sorvell): ideally the effect function is on this prototype + // so we don't have to call it like this. + Polymer.Bind.annotationEffect.call(this, path, value, effect); + } else if ((path.indexOf(effect.value + '.') === 0) && !effect.negate) { + // locate the bound node + var node = this._nodes[effect.index]; + if (node && node.notifyPath) { + var p = this._fixPath(effect.name , effect.value, path); + node.notifyPath(p, value, true); + } + } + }, + + complexObserverPathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.complexObserverEffect.call(this, path, value, effect); + } + }, + + computePathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.computeEffect.call(this, path, value, effect); + } + }, + + annotatedComputationPathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.annotatedComputationEffect.call(this, path, value, effect); + } + }, + + _pathMatchesEffect: function(path, effect) { + var effectArg = effect.arg.name; + return (effectArg == path) || + (effectArg.indexOf(path + '.') === 0) || + (effect.arg.wildcard && path.indexOf(effectArg) === 0); + }, + + bindPaths: function(to, from) { + this._boundPaths = this._boundPaths || {}; + if (from) { + this._boundPaths[to] = from; + // this.setPathValue(to, this.getPathValue(from)); + } else { + this.unbindPath(to); + // this.setPathValue(to, from); + } + }, + + unbindPaths: function(path) { + if (this._boundPaths) { + delete this._boundPaths[path]; + } + }, + + _notifyBoundPaths: function(path, value) { + var from, to; + for (var a in this._boundPaths) { + var b = this._boundPaths[a]; + if (path.indexOf(a + '.') == 0) { + from = a; + to = b; + break; + } + if (path.indexOf(b + '.') == 0) { + from = b; + to = a; + break; + } + } + if (from && to) { + var p = this._fixPath(to, from, path); + this.notifyPath(p, value); + } + }, + + _fixPath: function(property, root, path) { + return property + path.slice(root.length); + }, + + _notifyPath: function(path, value) { + var rootName = this._modelForPath(path); + var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName); + var eventName = dashCaseName + this._EVENT_CHANGED; + this.fire(eventName, { + path: path, + value: value + }, {bubbles: false}); + }, + + _modelForPath: function(path) { + return path.split('.').shift(); + }, + + _EVENT_CHANGED: '-changed', + + }); + + +; + + Polymer.Base._addFeature({ + + resolveUrl: function(url) { + // TODO(sorvell): do we want to put the module reference on the prototype? + var module = Polymer.DomModule.import(this.is); + var root = ''; + if (module) { + var assetPath = module.getAttribute('assetpath') || ''; + root = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI); + } + return Polymer.ResolveUrl.resolveUrl(url, root); + } + + }); + + +; + +/* + Extremely simple css parser. Intended to be not more than what we need + and definitely not necessarly correct =). +*/ +(function() { + + // given a string of css, return a simple rule tree + function parse(text) { + text = clean(text); + return parseCss(lex(text), text); + } + + // remove stuff we don't care about that may hinder parsing + function clean(cssText) { + return cssText.replace(rx.comments, '').replace(rx.port, ''); + } + + // super simple {...} lexer that returns a node tree + function lex(text) { + var root = {start: 0, end: text.length}; + var n = root; + for (var i=0, s=0, l=text.length; i < l; i++) { + switch (text[i]) { + case OPEN_BRACE: + //console.group(i); + if (!n.rules) { + n.rules = []; + } + var p = n; + var previous = p.rules[p.rules.length-1]; + n = {start: i+1, parent: p, previous: previous}; + p.rules.push(n); + break; + case CLOSE_BRACE: + //console.groupEnd(n.start); + n.end = i+1; + n = n.parent || root; + break; + } + } + return root; + } + + // add selectors/cssText to node tree + function parseCss(node, text) { + var t = text.substring(node.start, node.end-1); + node.cssText = t.trim(); + if (node.parent) { + var ss = node.previous ? node.previous.end : node.parent.start; + t = text.substring(ss, node.start-1); + // TODO(sorvell): ad hoc; make selector include only after last ; + // helps with mixin syntax + t = t.substring(t.lastIndexOf(';')+1); + node.selector = t.trim(); + } + var r$ = node.rules; + if (r$) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + parseCss(r, text); + } + } + return node; + } + + // stringify parsed css. + function stringify(node, text) { + text = text || ''; + // calc rule cssText + var cssText = ''; + if (node.cssText || node.rules) { + var r$ = node.rules; + if (r$ && !hasMixinRules(r$)) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + cssText = stringify(r, cssText); + } + } else { + cssText = removeCustomProps(node.cssText).trim(); + if (cssText) { + cssText = ' ' + cssText + '\n'; + } + } + } + // emit rule iff there is cssText + if (cssText) { + if (node.selector) { + text += node.selector + ' ' + OPEN_BRACE + '\n'; + } + text += cssText; + if (node.selector) { + text += CLOSE_BRACE + '\n\n'; + } + } + return text; + } + + var OPEN_BRACE = '{'; + var CLOSE_BRACE = '}'; + + function hasMixinRules(rules) { + return (rules[0].selector.indexOf(VAR_START) >= 0); + } + + function removeCustomProps(cssText) { + return cssText + .replace(rx.customProp, '') + .replace(rx.mixinProp, '') + .replace(rx.mixinApply, ''); + } + + var VAR_START = '--'; + + // helper regexp's + var rx = { + comments: /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, + port: /@import[^;]*;/gim, + customProp: /--[^;{]*?:[^{};]*?;/gim, + mixinProp: /--[^;{]*?:[^{;]*?{[^}]*?}/gim, + mixinApply: /@mixin[\s]*\([^)]*?\)[\s]*;/gim + }; + + // exports + Polymer.CssParse = { + parse: parse, + stringify: stringify + }; + +})(); + + +; + + (function() { + + function toCssText(rules, callback) { + if (typeof rules === 'string') { + rules = Polymer.CssParse.parse(rules); + } + if (callback) { + forEachStyleRule(rules, callback); + } + return Polymer.CssParse.stringify(rules); + } + + function forEachStyleRule(node, cb) { + var s = node.selector; + var skipRules = false; + if (s) { + if ((s.indexOf(AT_RULE) !== 0) && (s.indexOf(MIXIN_SELECTOR) !== 0)) { + cb(node); + } + skipRules = (s.indexOf(KEYFRAME_RULE) >= 0) || + (s.indexOf(MIXIN_SELECTOR) >= 0); + } + var r$ = node.rules; + if (r$ && !skipRules) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + forEachStyleRule(r, cb); + } + } + } + + // add a string of cssText to the document. + function applyCss(cssText, moniker, target, lowPriority) { + var style = document.createElement('style'); + if (moniker) { + style.setAttribute('scope', moniker); + } + style.textContent = cssText; + target = target || document.head; + if (lowPriority) { + var n$ = target.querySelectorAll('style[scope]'); + var ref = n$.length ? n$[n$.length-1].nextSibling : target.firstChild; + target.insertBefore(style, ref); + } else { + target.appendChild(style); + } + return style; + } + + var AT_RULE = '@'; + var KEYFRAME_RULE = 'keyframe'; + var MIXIN_SELECTOR = '--'; + + // exports + Polymer.StyleUtil = { + parser: Polymer.CssParse, + applyCss: applyCss, + forEachStyleRule: forEachStyleRule, + toCssText: toCssText + }; + + })(); + + +; + + (function() { + + /* Transforms ShadowDOM styling into ShadyDOM styling + + * scoping: + + * elements in scope get scoping selector class="x-foo-scope" + * selectors re-written as follows: + + div button -> div.x-foo-scope button.x-foo-scope + + * :host -> scopeName + + * :host(...) -> scopeName... + + * ::content -> ' ' NOTE: requires use of scoping selector and selectors + cannot otherwise be scoped: + e.g. :host ::content > .bar -> x-foo > .bar + + * ::shadow, /deep/: processed simimlar to ::content + + * :host-context(...): NOT SUPPORTED + + */ + + // Given a node and scope name, add a scoping class to each node + // in the tree. This facilitates transforming css into scoped rules. + function transformDom(node, scope, useAttr, shouldRemoveScope) { + _transformDom(node, scope || '', useAttr, shouldRemoveScope); + } + + function _transformDom(node, selector, useAttr, shouldRemoveScope) { + if (node.setAttribute) { + transformElement(node, selector, useAttr, shouldRemoveScope); + } + var c$ = Polymer.dom(node).childNodes; + for (var i=0; i<c$.length; i++) { + _transformDom(c$[i], selector, useAttr, shouldRemoveScope); + } + } + + function transformElement(element, scope, useAttr, shouldRemoveScope) { + if (useAttr) { + if (shouldRemoveScope) { + element.removeAttribute(SCOPE_NAME); + } else { + element.setAttribute(SCOPE_NAME, scope); + } + } else { + // note: if using classes, we add both the general 'style-scope' class + // as well as the specific scope. This enables easy filtering of all + // `style-scope` elements + if (scope) { + if (shouldRemoveScope) { + element.classList.remove(SCOPE_NAME, scope); + } else { + element.classList.add(SCOPE_NAME, scope); + } + } + } + } + + function transformHost(host, scope) { + } + + // Given a string of cssText and a scoping string (scope), returns + // a string of scoped css where each selector is transformed to include + // a class created from the scope. ShadowDOM selectors are also transformed + // (e.g. :host) to use the scoping selector. + function transformCss(rules, scope, ext, callback, useAttr) { + var hostScope = calcHostScope(scope, ext); + scope = calcElementScope(scope, useAttr); + return Polymer.StyleUtil.toCssText(rules, function(rule) { + transformRule(rule, scope, hostScope); + if (callback) { + callback(rule, scope, hostScope); + } + }); + } + + function calcElementScope(scope, useAttr) { + if (scope) { + return useAttr ? + CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : + CSS_CLASS_PREFIX + scope; + } else { + return ''; + } + } + + function calcHostScope(scope, ext) { + return ext ? '[is=' + scope + ']' : scope; + } + + function transformRule(rule, scope, hostScope) { + _transformRule(rule, transformComplexSelector, + scope, hostScope); + } + + // transforms a css rule to a scoped rule. + function _transformRule(rule, transformer, scope, hostScope) { + var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP); + for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) { + p$[i] = transformer(p, scope, hostScope); + } + rule.selector = p$.join(COMPLEX_SELECTOR_SEP); + } + + function transformComplexSelector(selector, scope, hostScope) { + var stop = false; + selector = selector.replace(SIMPLE_SELECTOR_SEP, function(m, c, s) { + if (!stop) { + var o = transformCompoundSelector(s, c, scope, hostScope); + if (o.stop) { + stop = true; + } + c = o.combinator; + s = o.value; + } + return c + s; + }); + return selector; + } + + function transformCompoundSelector(selector, combinator, scope, hostScope) { + // replace :host with host scoping class + var jumpIndex = selector.search(SCOPE_JUMP); + if (selector.indexOf(HOST) >=0) { + // :host(...) + selector = selector.replace(HOST_PAREN, function(m, host, paren) { + return hostScope + paren; + }); + // now normal :host + selector = selector.replace(HOST, hostScope); + // replace other selectors with scoping class + } else if (jumpIndex !== 0) { + selector = scope ? transformSimpleSelector(selector, scope) : selector; + } + // remove left-side combinator when dealing with ::content. + if (selector.indexOf(CONTENT) >= 0) { + combinator = ''; + } + // process scope jumping selectors up to the scope jump and then stop + // e.g. .zonk ::content > .foo ==> .zonk.scope > .foo + var stop; + if (jumpIndex >= 0) { + selector = selector.replace(SCOPE_JUMP, ' '); + stop = true; + } + return {value: selector, combinator: combinator, stop: stop}; + } + + function transformSimpleSelector(selector, scope) { + var p$ = selector.split(PSEUDO_PREFIX); + p$[0] += scope; + return p$.join(PSEUDO_PREFIX); + } + + function transformRootRule(rule) { + _transformRule(rule, transformRootSelector); + } + + function transformRootSelector(selector) { + return selector.match(SCOPE_JUMP) ? + transformComplexSelector(selector) : + selector.trim() + SCOPE_ROOT_SELECTOR; + } + + var SCOPE_NAME = 'style-scope'; + var SCOPE_ROOT_SELECTOR = ':not([' + SCOPE_NAME + '])' + + ':not(.' + SCOPE_NAME + ')'; + var COMPLEX_SELECTOR_SEP = ','; + var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g; + var HOST = ':host'; + // NOTE: this supports 1 nested () pair for things like + // :host(:not([selected]), more general support requires + // parsing which seems like overkill + var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g; + var CONTENT = '::content'; + var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//; + var CSS_CLASS_PREFIX = '.'; + var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~='; + var CSS_ATTR_SUFFIX = ']'; + var PSEUDO_PREFIX = ':'; + + // exports + Polymer.StyleTransformer = { + element: transformElement, + dom: transformDom, + host: transformHost, + css: transformCss, + rule: transformRule, + rootRule: transformRootRule, + SCOPE_NAME: SCOPE_NAME + }; + + })(); + + +; + + (function() { + + var prepTemplate = Polymer.Base._prepTemplate; + var prepElement = Polymer.Base._prepElement; + var baseStampTemplate = Polymer.Base._stampTemplate; + var nativeShadow = Polymer.Settings.useNativeShadow; + + Polymer.Base._addFeature({ + + // declaration-y + _prepTemplate: function() { + prepTemplate.call(this); + var port = Polymer.DomModule.import(this.is); + if (this._encapsulateStyle === undefined) { + this._encapsulateStyle = + Boolean(port && !nativeShadow); + } + // scope css + // NOTE: dom scoped via annotations + if (nativeShadow || this._encapsulateStyle) { + this._scopeCss(); + } + }, + + _prepElement: function(element) { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.element(element, this.is, + this._scopeCssViaAttr); + } + prepElement.call(this, element); + }, + + _scopeCss: function() { + this._styles = this._prepareStyles(); + this._scopeStyles(this._styles); + }, + + // search for extra style modules via `styleModules` + _prepareStyles: function() { + var cssText = '', m$ = this.styleModules; + if (m$) { + for (var i=0, l=m$.length, m; (i<l) && (m=m$[i]); i++) { + cssText += this._cssFromModule(m); + } + } + cssText += this._cssFromModule(this.is); + var styles = []; + if (cssText) { + var s = document.createElement('style'); + s.textContent = cssText; + styles.push(s); + } + return styles; + }, + + // returns cssText of styles in a given module; also un-applies any + // styles that apply to the document. + _cssFromModule: function(moduleId) { + var m = Polymer.DomModule.import(moduleId); + if (m && !m._cssText) { + var cssText = ''; + var e$ = Array.prototype.slice.call(m.querySelectorAll('style')); + this._unapplyStyles(e$); + e$ = e$.concat(Array.prototype.map.call( + m.querySelectorAll(REMOTE_SHEET_SELECTOR), function(l) { + return l.import.body; + })); + m._cssText = this._cssFromStyles(e$); + } + return m && m._cssText || ''; + }, + + _cssFromStyles: function(styles) { + var cssText = ''; + for (var i=0, l=styles.length, s; (i<l) && (s = styles[i]); i++) { + if (s && s.textContent) { + cssText += + Polymer.ResolveUrl.resolveCss(s.textContent, s.ownerDocument); + } + } + return cssText; + }, + + _unapplyStyles: function(styles) { + for (var i=0, l=styles.length, s; (i<l) && (s = styles[i]); i++) { + s = s.__appliedElement || s; + s.parentNode.removeChild(s); + } + }, + + _scopeStyles: function(styles) { + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + // transform style if necessary and place in correct place + if (nativeShadow) { + if (this._template) { + this._template.content.appendChild(s); + } + } else { + var rules = this._rulesForStyle(s); + Polymer.StyleUtil.applyCss( + Polymer.StyleTransformer.css(rules, this.is, this.extends, + null, this._scopeCssViaAttr), + this.is, null, true); + } + } + }, + + _rulesForStyle: function(style) { + if (!style.__cssRules) { + style.__cssRules = Polymer.StyleUtil.parser.parse(style.textContent); + } + return style.__cssRules; + }, + + // instance-y + _stampTemplate: function() { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.host(this, this.is); + } + baseStampTemplate.call(this); + }, + + // add scoping class whenever an element is added to localDOM + _elementAdd: function(node) { + if (this._encapsulateStyle && !node.__styleScoped) { + Polymer.StyleTransformer.dom(node, this.is, this._scopeCssViaAttr); + } + }, + + // remove scoping class whenever an element is removed from localDOM + _elementRemove: function(node) { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.dom(node, this.is, this._scopeCssViaAttr, true); + } + }, + + /** + * Apply style scoping to the specified `container` and all its + * descendants. If `shoudlObserve` is true, changes to the container are + * monitored via mutation observer and scoping is applied. + */ + scopeSubtree: function(container, shouldObserve) { + if (nativeShadow) { + return; + } + var self = this; + var scopify = function(node) { + if (node.nodeType === Node.ELEMENT_NODE) { + node.className = self._scopeElementClass(node, node.className); + var n$ = node.querySelectorAll('*'); + Array.prototype.forEach.call(n$, function(n) { + n.className = self._scopeElementClass(n, n.className); + }); + } + }; + scopify(container); + if (shouldObserve) { + var mo = new MutationObserver(function(mxns) { + mxns.forEach(function(m) { + if (m.addedNodes) { + for (var i=0; i < m.addedNodes.length; i++) { + scopify(m.addedNodes[i]); + } + } + }); + }); + mo.observe(container, {childList: true, subtree: true}); + return mo; + } + } + + }); + + var REMOTE_SHEET_SELECTOR = 'link[rel=import][type~=css]'; + + })(); + + +; + + (function() { + + var defaultSheet = document.createElement('style'); + + function applyCss(cssText) { + defaultSheet.textContent += cssText; + defaultSheet.__cssRules = + Polymer.StyleUtil.parser.parse(defaultSheet.textContent); + } + + applyCss(''); + + // exports + Polymer.StyleDefaults = { + applyCss: applyCss, + defaultSheet: defaultSheet + }; + + })(); + +; + (function() { + + var baseAttachedCallback = Polymer.Base.attachedCallback; + var baseSerializeValueToAttribute = Polymer.Base.serializeValueToAttribute; + + var nativeShadow = Polymer.Settings.useNativeShadow; + + // TODO(sorvell): consider if calculating properties and applying + // styles with properties should be separate modules. + Polymer.Base._addFeature({ + + attachedCallback: function() { + baseAttachedCallback.call(this); + if (!this._xScopeSelector) { + this._updateOwnStyles(); + } + }, + + _updateOwnStyles: function() { + if (this.enableCustomStyleProperties) { + this._styleProperties = this._computeStyleProperties(); + this._applyStyleProperties(this._styleProperties); + } + }, + + _computeStyleProperties: function() { + var props = {}; + this.simpleMixin(props, this._computeStylePropertiesFromHost()); + this.simpleMixin(props, this._computeOwnStyleProperties()); + this._reifyCustomProperties(props); + return props; + }, + + _computeStylePropertiesFromHost: function() { + // TODO(sorvell): experimental feature, global defaults! + var props = {}, styles = [Polymer.StyleDefaults.defaultSheet]; + var host = this.domHost; + if (host) { + // enable finding styles in hosts without `enableStyleCustomProperties` + if (!host._styleProperties) { + host._styleProperties = host._computeStyleProperties(); + } + props = Object.create(host._styleProperties); + styles = host._styles; + } + this.simpleMixin(props, + this._customPropertiesFromStyles(styles, host)); + return props; + + }, + + _computeOwnStyleProperties: function() { + var props = {}; + this.simpleMixin(props, this._customPropertiesFromStyles(this._styles)); + if (this.styleProperties) { + for (var i in this.styleProperties) { + props[i] = this.styleProperties[i]; + } + } + return props; + }, + + _customPropertiesFromStyles: function(styles, hostNode) { + var props = {}; + var p = this._customPropertiesFromRule.bind(this, props, hostNode); + if (styles) { + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + Polymer.StyleUtil.forEachStyleRule(this._rulesForStyle(s), p); + } + } + return props; + }, + + // test if a rule matches the given node and if so, + // collect any custom properties + // TODO(sorvell): support custom variable assignment within mixins + _customPropertiesFromRule: function(props, hostNode, rule) { + hostNode = hostNode || this; + // TODO(sorvell): file crbug, ':host' does not match element. + if (this.elementMatches(rule.selector) || + ((hostNode === this) && (rule.selector === ':host'))) { + // --g: var(--b); or --g: 5; + this._collectPropertiesFromRule(rule, CUSTOM_VAR_ASSIGN, props); + // --g: { ... } + this._collectPropertiesFromRule(rule, CUSTOM_MIXIN_ASSIGN, props); + } + }, + + // given a rule and rx that matches key and value, set key in properties + // to value + _collectPropertiesFromRule: function(rule, rx, properties) { + var m; + while (m = rx.exec(rule.cssText)) { + properties[m[1]] = m[2].trim(); + } + }, + + _reifyCustomProperties: function(props) { + for (var i in props) { + props[i] = this._valueForCustomProperty(props[i], props); + } + }, + + _valueForCustomProperty: function(property, props) { + var cv; + while ((typeof property === 'string') && + (cv = property.match(CUSTOM_VAR_VALUE))) { + property = props[cv[1]]; + } + return property; + }, + + // apply styles + _applyStyleProperties: function(bag) { + var s$ = this._styles; + if (s$) { + var style = styleFromCache(this.is, bag, s$); + var old = this._xScopeSelector; + this._ensureScopeSelector(style ? style._scope : null); + if (!style) { + var cssText = this._generateCustomStyleCss(bag, s$); + style = cssText ? this._applyCustomCss(cssText) : {}; + cacheStyle(this.is, style, this._xScopeSelector, + this._styleProperties, s$); + } else if (nativeShadow) { + this._applyCustomCss(style.textContent); + } + if (style.textContent || old /*&& !nativeShadow*/) { + this._applyXScopeSelector(this._xScopeSelector, old); + } + } + }, + + _applyXScopeSelector: function(selector, old) { + var c = this._scopeCssViaAttr ? this.getAttribute(SCOPE_NAME) : + this.className; + v = old ? c.replace(old, selector) : + (c ? c + ' ' : '') + XSCOPE_NAME + ' ' + selector; + if (c !== v) { + if (this._scopeCssViaAttr) { + this.setAttribute(SCOPE_NAME, v); + } else { + this.className = v; + } + } + }, + + _generateCustomStyleCss: function(properties, styles) { + var b = this._applyPropertiesToRule.bind(this, properties); + var cssText = ''; + // TODO(sorvell): don't redo parsing work each time as below; + // instead create a sheet with just custom properties + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + cssText += this._transformCss(s.textContent, b) + '\n\n'; + } + return cssText.trim(); + }, + + _transformCss: function(cssText, callback) { + return nativeShadow ? + Polymer.StyleUtil.toCssText(cssText, callback) : + Polymer.StyleTransformer.css(cssText, this.is, this.extends, callback, + this._scopeCssViaAttr); + }, + + _xScopeCount: 0, + + _ensureScopeSelector: function(selector) { + selector = selector || (this.is + '-' + + (Object.getPrototypeOf(this)._xScopeCount++)); + this._xScopeSelector = selector; + }, + + _applyCustomCss: function(cssText) { + if (this._customStyle) { + this._customStyle.textContent = cssText; + } else if (cssText) { + this._customStyle = Polymer.StyleUtil.applyCss(cssText, + this._xScopeSelector, + nativeShadow ? this.root : null); + } + return this._customStyle; + }, + + _applyPropertiesToRule: function(properties, rule) { + if (!nativeShadow) { + this._scopifyRule(rule); + } + if (rule.cssText.match(CUSTOM_RULE_RX)) { + rule.cssText = this._applyPropertiesToText(rule.cssText, properties); + } else { + rule.cssText = ''; + } + //console.log(rule.cssText); + }, + + _applyPropertiesToText: function(cssText, props) { + var output = ''; + var m, v; + // e.g. color: var(--color); + while (m = CUSTOM_VAR_USE.exec(cssText)) { + v = props[m[2]]; + if (v) { + output += '\t' + m[1].trim() + ': ' + this._propertyToCss(v); + } + } + // e.g. @mixin(--stuff); + while (m = CUSTOM_MIXIN_USE.exec(cssText)) { + v = m[1]; + if (v) { + var parts = v.split(' '); + for (var i=0, p; i < parts.length; i++) { + p = props[parts[i].trim()]; + if (p) { + output += '\t' + this._propertyToCss(p); + } + } + } + } + return output; + }, + + _propertyToCss: function(property) { + var p = property.trim(); + p = p[p.length-1] === ';' ? p : p + ';'; + return p + '\n'; + }, + + // Strategy: x scope shim a selector e.g. to scope `.x-foo-42` (via classes): + // non-host selector: .a.x-foo -> .x-foo-42 .a.x-foo + // host selector: x-foo.wide -> x-foo.x-foo-42.wide + _scopifyRule: function(rule) { + var selector = rule.selector; + var host = this.is; + var rx = new RegExp(HOST_SELECTOR_PREFIX + host + HOST_SELECTOR_SUFFIX); + var parts = selector.split(','); + var scope = this._scopeCssViaAttr ? + SCOPE_PREFIX + this._xScopeSelector + SCOPE_SUFFIX : + '.' + this._xScopeSelector; + for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) { + parts[i] = p.match(rx) ? + p.replace(host, host + scope) : + scope + ' ' + p; + } + rule.selector = parts.join(','); + }, + + _scopeElementClass: function(element, selector) { + if (!nativeShadow && !this._scopeCssViaAttr) { + selector += (selector ? ' ' : '') + SCOPE_NAME + ' ' + this.is + + (element._xScopeSelector ? ' ' + XSCOPE_NAME + ' ' + + element._xScopeSelector : ''); + } + return selector; + }, + + // override to ensure whenever classes are set, we need to shim them. + serializeValueToAttribute: function(value, attribute, node) { + if (attribute === 'class') { + // host needed to scope styling. + var host = node === this ? + Polymer.dom(this).getOwnerRoot() || this.dataHost : + this; + if (host) { + value = host._scopeElementClass(node, value); + } + } + baseSerializeValueToAttribute.call(this, value, attribute, node); + }, + + updateStyles: function() { + this._updateOwnStyles(); + this._updateRootStyles(this.root); + }, + + updateHostStyles: function() { + var host = Polymer.dom(this).getOwnerRoot() || this.dataHost; + if (host) { + host.updateStyles(); + } else { + this._updateRootStyles(document); + } + }, + + _updateRootStyles: function(root) { + // TODO(sorvell): temporary way to find local dom that needs + // x-scope styling. + var scopeSelector = this._scopeCssViaAttr ? + '[' + SCOPE_NAME + '~=' + XSCOPE_NAME + ']' : '.' + XSCOPE_NAME; + var c$ = Polymer.dom(root).querySelectorAll(scopeSelector); + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + if (c.updateStyles) { + c.updateStyles(); + } + } + } + + }); + + var styleCache = {}; + function cacheStyle(is, style, scope, bag, styles) { + style._scope = scope; + style._properties = bag; + style._styles = styles; + var s$ = styleCache[is] = styleCache[is] || []; + s$.push(style); + } + + function styleFromCache(is, bag, checkStyles) { + var styles = styleCache[is]; + if (styles) { + for (var i=0, s; i < styles.length; i++) { + s = styles[i]; + if (objectsEqual(bag, s._properties) && + objectsEqual(checkStyles, s._styles)) { + return s; + } + } + } + } + + function objectsEqual(a, b) { + for (var i in a) { + if (a[i] !== b[i]) { + return false; + } + } + for (var i in b) { + if (a[i] !== b[i]) { + return false; + } + } + return true; + } + + var SCOPE_NAME= Polymer.StyleTransformer.SCOPE_NAME; + var XSCOPE_NAME = 'x-scope'; + var SCOPE_PREFIX = '[' + SCOPE_NAME + '~='; + var SCOPE_SUFFIX = ']'; + var HOST_SELECTOR_PREFIX = '(?:^|[^.])'; + var HOST_SELECTOR_SUFFIX = '($|[.:[\\s>+~])'; + var CUSTOM_RULE_RX = /mixin|var/; + var CUSTOM_VAR_ASSIGN = /(--[^\:;]*?):\s*?([^;{]*?);/g; + var CUSTOM_MIXIN_ASSIGN = /(--[^\:;]*?):[^{;]*?{([^}]*?)}/g; + var CUSTOM_VAR_VALUE = /^var\(([^)]*?)\)/; + var CUSTOM_VAR_USE = /(?:^|[;}\s])([^;{}]*?):[\s]*?var\(([^)]*)?\)/gim; + var CUSTOM_MIXIN_USE = /mixin\(([^)]*)\)/gim; + + })(); + +; + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + // template + this._prepTemplate(); + // template markup + this._prepAnnotations(); + // accessors + this._prepEffects(); + // shared behaviors + this._prepBehaviors(); + // accessors part 2 + this._prepBindings(); + // dom encapsulation + this._prepShady(); + }, + + _prepBehavior: function(b) { + this._addPropertyEffects(b.properties || b.accessors); + this._addComplexObserverEffects(b.observers); + }, + + _initFeatures: function() { + // manage local dom + this._poolContent(); + // manage configuration + this._setupConfigure(); + // host stack + this._pushHost(); + // instantiate template + this._stampTemplate(); + // host stack + this._popHost(); + // concretize template references + this._marshalAnnotationReferences(); + // setup debouncers + this._setupDebouncers(); + // concretize effects on instance + this._marshalInstanceEffects(); + // acquire instance behaviors + this._marshalBehaviors(); + // acquire initial instance attribute values + this._marshalAttributes(); + // top-down initial distribution, configuration, & ready callback + this._tryReady(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + // establish listeners on instance + this._listenListeners(b.listeners); + } + + }); + + +; +(function() { + + Polymer({ + + is: 'x-style', + extends: 'style', + + created: function() { + var rules = Polymer.StyleUtil.parser.parse(this.textContent); + this.applyProperties(rules); + // TODO(sorvell): since custom rules must match directly, they tend to be + // made with selectors like `*`. + // We *remove them here* so they don't apply too widely and nerf recalc. + // This means that normal properties mixe in rules with custom + // properties will *not* apply. + var cssText = Polymer.StyleUtil.parser.stringify(rules); + this.textContent = this.scopeCssText(cssText); + }, + + scopeCssText: function(cssText) { + return Polymer.Settings.useNativeShadow ? + cssText : + Polymer.StyleUtil.toCssText(cssText, function(rule) { + Polymer.StyleTransformer.rootRule(rule); + }); + }, + + applyProperties: function(rules) { + var cssText = ''; + Polymer.StyleUtil.forEachStyleRule(rules, function(rule) { + if (rule.cssText.match(CUSTOM_RULE)) { + // TODO(sorvell): use parser.stringify, it needs an option not to + // strip custom properties. + cssText += rule.selector + ' {\n' + rule.cssText + '\n}\n'; + } + }); + if (cssText) { + Polymer.StyleDefaults.applyCss(cssText); + } + } + + }); + + var CUSTOM_RULE = /--[^;{'"]*\:/; + +})(); + +; + + Polymer({ + + is: 'x-autobind', + + extends: 'template', + + _registerFeatures: function() { + this._prepExtends(); + this._prepConstructor(); + }, + + _finishDistribute: function() { + var parentDom = Polymer.dom(Polymer.dom(this).parentNode); + parentDom.insertBefore(this.root, this); + }, + + _initFeatures: function() { + this._template = this; + this._prepAnnotations(); + this._prepEffects(); + this._prepBehaviors(); + this._prepBindings(); + Polymer.Base._initFeatures.call(this); + } + + }); + + +; + + Polymer.Templatizer = { + + templatize: function(template) { + this._templatized = template; + // TODO(sjmiles): supply _alternate_ content reference missing from root + // templates (not nested). `_content` exists to provide content sharing + // for nested templates. + if (!template._content) { + template._content = template.content; + } + // fast path if template's anonymous class has been memoized + if (template._content._ctor) { + this.ctor = template._content._ctor; + //console.log('Templatizer.templatize: using memoized archetype'); + // forward parent properties to archetype + this._prepParentProperties(this.ctor.prototype); + return; + } + // `archetype` is the prototype of the anonymous + // class created by the templatizer + var archetype = Object.create(Polymer.Base); + // normally Annotations.parseAnnotations(template) but + // archetypes do special caching + this.customPrepAnnotations(archetype, template); + + // setup accessors + archetype._prepEffects(); + archetype._prepBehaviors(); + archetype._prepBindings(); + + // forward parent properties to archetype + this._prepParentProperties(archetype); + + // boilerplate code + archetype._notifyPath = this._notifyPathImpl; + archetype._scopeElementClass = this._scopeElementClassImpl; + // boilerplate code + var _constructor = this._constructorImpl; + var ctor = function TemplateInstance(model, host) { + _constructor.call(this, model, host); + }; + // standard references + ctor.prototype = archetype; + archetype.constructor = ctor; + // TODO(sjmiles): constructor cache? + template._content._ctor = ctor; + // TODO(sjmiles): choose less general name + this.ctor = ctor; + }, + + _getRootDataHost: function() { + return (this.dataHost && this.dataHost._rootDataHost) || this.dataHost; + }, + + _getAllStampedChildren: function(children) { + children = children || []; + if (this._getStampedChildren) { + var c$ = this._getStampedChildren(); + for (var i=0, c; c = c$[i]; i++) { + children.push(c); + if (c._getAllStampedChildren) { + c._getAllStampedChildren(children); + } + } + } + return children; + }, + + customPrepAnnotations: function(archetype, template) { + if (template) { + archetype._template = template; + var c = template._content; + if (c) { + var rootDataHost = archetype._rootDataHost; + if (rootDataHost) { + Polymer.Annotations.prepElement = + rootDataHost._prepElement.bind(rootDataHost); + } + archetype._notes = c._notes || + Polymer.Annotations.parseAnnotations(template); + c._notes = archetype._notes; + Polymer.Annotations.prepElement = null; + archetype._parentProps = c._parentProps; + } + else { + console.warn('no _content'); + } + } + else { + console.warn('no _template'); + } + }, + + // Sets up accessors on the template to call abstract _forwardParentProp + // API that should be implemented by Templatizer users to get parent + // properties to their template instances. These accessors are memoized + // on the archetype and copied to instances. + _prepParentProperties: function(archetype) { + var parentProps = this._parentProps = archetype._parentProps; + if (this._forwardParentProp && parentProps) { + // Prototype setup (memoized on archetype) + var proto = archetype._parentPropProto; + if (!proto) { + proto = archetype._parentPropProto = Object.create(null); + if (this._templatized != this) { + // Assumption: if `this` isn't the template being templatized, + // assume that the template is not a Poylmer.Base, so prep it + // for binding + Polymer.Bind.prepareModel(proto); + } + // Create accessors for each parent prop that forward the property + // to template instances through abstract _forwardParentProp API + // that should be implemented by Templatizer users + for (var prop in parentProps) { + var parentProp = '_parent_' + prop; + var effects = [{ + kind: 'function', + effect: { function: this._createForwardPropEffector(prop) } + }]; + Polymer.Bind._createAccessors(proto, parentProp, effects); + } + } + // Instance setup + if (this._templatized != this) { + Polymer.Bind.prepareInstance(this._templatized); + this._templatized._forwardParentProp = + this._forwardParentProp.bind(this); + } + this._extendTemplate(this._templatized, proto); + } + }, + + _createForwardPropEffector: function(prop) { + return function(source, value) { + this._forwardParentProp(prop, value); + }; + }, + + // Similar to Polymer.Base.extend, but retains any previously set instance + // values (_propertySet back on instance once accessor is installed) + _extendTemplate: function(template, proto) { + Object.getOwnPropertyNames(proto).forEach(function(n) { + var val = template[n]; + var pd = Object.getOwnPropertyDescriptor(proto, n); + Object.defineProperty(template, n, pd); + if (val !== undefined) { + template._propertySet(n, val); + } + }); + }, + + _notifyPathImpl: function(path, value) { + var p = path.match(/([^.]*)\.(([^.]*).*)/); + // 'root.sub.path' + var root = p[1]; // 'root' + var sub = p[3]; // 'sub' + var subPath = p[2]; // 'sub.path' + // Notify host of parent.* path/property changes + var dataHost = this.dataHost; + if (root == 'parent') { + if (sub == subPath) { + dataHost.dataHost[sub] = value; + } else { + dataHost.notifyPath('_parent_' + subPath, value); + } + } + // Extension point for Templatizer sub-classes + if (dataHost._forwardInstancePath) { + dataHost._forwardInstancePath.call(dataHost, this, root, subPath, value); + } + }, + + // Overrides Base notify-path module + _pathEffector: function(path, value, fromAbove) { + if (this._forwardParentPath) { + if (path.indexOf('_parent_') === 0) { + this._forwardParentPath(path.substring(8), value); + } + } + Polymer.Base._pathEffector.apply(this, arguments); + }, + + _constructorImpl: function(model, host) { + var rootDataHost = host._getRootDataHost(); + if (rootDataHost) { + this.listen = rootDataHost.listen.bind(rootDataHost); + this._rootDataHost = rootDataHost; + } + this._setupConfigure(model); + this._pushHost(host); + this.root = this.instanceTemplate(this._template); + this.root.__styleScoped = true; + this._popHost(); + this._marshalAnnotatedNodes(); + this._marshalInstanceEffects(); + this._marshalAnnotatedListeners(); + this._tryReady(); + }, + + _scopeElementClassImpl: function(node, value) { + var host = this._rootDataHost; + if (host) { + return host._scopeElementClass(node, value); + } + }, + + stamp: function(model) { + model = model || {}; + if (this._parentProps) { + // TODO(kschaaf): Maybe this is okay + // model.parent = this.dataHost; + model.parent = model.parent || {}; + for (var prop in this._parentProps) { + model.parent[prop] = this['_parent_' + prop]; + } + } + return new this.ctor(model, this); + } + + // TODO(sorvell): note, using the template as host is ~5-10% faster if + // elements have no default values. + // _constructorImpl: function(model, host) { + // this._setupConfigure(model); + // host._beginHost(); + // this.root = this.instanceTemplate(this._template); + // host._popHost(); + // this._marshalTemplateContent(); + // this._marshalAnnotatedNodes(); + // this._marshalInstanceEffects(); + // this._marshalAnnotatedListeners(); + // this._ready(); + // }, + + // stamp: function(model) { + // return new this.ctor(model, this.dataHost); + // } + + + }; + + +; + + /** + * Creates a pseudo-custom-element that maps property values to bindings + * in DOM. + * + * `stamp` method creates an instance of the pseudo-element. The instance + * references a document-fragment containing the stamped and bound dom + * via it's `root` property. + * + */ + Polymer({ + + is: 'x-template', + extends: 'template', + + behaviors: [ + Polymer.Templatizer + ], + + ready: function() { + this.templatize(this); + } + + }); + + +; + +(function() { + + var callbacks = new WeakMap(); + + function observe(array, cb) { + if (Array.observe) { + var ncb = function(changes) { + changes = changes.filter(function(o) { return o.type == 'splice'; }); + if (changes.length) { + cb(changes); + } + }; + callbacks.set(cb, ncb); + Array.observe(array, ncb); + } else { + if (!array.__polymerObservable) { + makeObservable(array); + } + callbacks.get(array).push(cb); + } + } + + function unobserve(array, cb) { + if (Array.observe) { + var ncb = callbacks.get(cb); + callbacks.delete(cb); + Array.unobserve(array, ncb); + } else { + var cbs = callbacks.get(array); + var idx = cbs.indexOf(cb); + if (idx >= 0) { + cbs.splice(idx, 1); + } + } + } + + function makeObservable(array) { + var splices = []; + var debounce; + var orig = { + push: array.push, + pop: array.pop, + splice: array.splice, + shift: array.shift, + unshift: array.unshift, + sort: array.sort + }; + var addSplice = function(index, added, removed) { + splices.push({ + index: index, + addedCount: added, + removed: removed, + object: array, + type: 'splice' + }); + }; + callbacks.set(array, []); + array.push = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(array.length, 1, []); + return orig.push.apply(this, arguments); + }; + array.pop = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(array.length - 1, 0, array.slice(-1)); + return orig.pop.apply(this, arguments); + }; + array.splice = function(start, deleteCount) { + debounce = Polymer.Debounce(debounce, fin); + addSplice(start, arguments.length - 2, array.slice(start, start + deleteCount)); + return orig.splice.apply(this, arguments); + }; + array.shift = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(0, 0, [array[0]]); + return orig.shift.apply(this, arguments); + }; + array.unshift = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(0, 1, []); + return orig.unshift.apply(this, arguments); + }; + array.sort = function() { + debounce = Polymer.Debounce(debounce, fin); + console.warn('[ArrayObserve]: sort not observable'); + return orig.sort.apply(this, arguments); + }; + var fin = function() { + var cbs = callbacks.get(array); + for (var i=0; i<cbs.length; i++) { + cbs[i](splices); + } + splices = []; + }; + array.__polymerObservable = true; + } + + Polymer.ArrayObserve = { + observe: observe, + unobserve: unobserve + }; + +})(); + + +; + + Polymer._collections = new WeakMap(); + + Polymer.Collection = function(userArray, noObserve) { + Polymer._collections.set(userArray, this); + this.userArray = userArray; + this.store = userArray.slice(); + this.callbacks = []; + this.debounce = null; + this.map = null; + this.added = []; + this.removed = []; + if (!noObserve) { + Polymer.ArrayObserve.observe(userArray, this.applySplices.bind(this)); + this.initMap(); + } + }; + + Polymer.Collection.prototype = { + constructor: Polymer.Collection, + + initMap: function() { + var map = this.map = new WeakMap(); + var s = this.store; + var u = this.userArray; + for (var i=0; i<s.length; i++) { + var v = s[i]; + if (v) { + switch (typeof v) { + case 'string': + v = s[i] = u[i]= new String(v); + break; + case 'number': + v = s[i] = u[i]= new Number(v); + break; + case 'boolean': + v = s[i] = u[i]= new Boolean(v); + break; + } + map.set(v, i); + } + } + }, + + add: function(item, squelch) { + var key = this.store.push(item) - 1; + if (item != null && this.map) { + this.map.set(item, key); + } + if (!squelch) { + this.added.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + } + return key; + }, + + removeKey: function(key) { + if (this.map) { + this.map.delete(this.store[key]); + } + delete this.store[key]; + this.removed.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + }, + + remove: function(item, squelch) { + var key = this.getKey(item); + if (item != null && this.map) { + this.map.delete(item); + } + delete this.store[key]; + if (!squelch) { + this.removed.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + } + return key; + }, + + notify: function(splices) { + if (!splices) { + splices = [{ + added: this.added, + removed: this.removed + }]; + this.added = []; + this.removed = []; + } + this.callbacks.forEach(function(cb) { + cb(splices); + }, this); + }, + + observe: function(callback) { + this.callbacks.push(callback); + }, + + unobserve: function(callback) { + this.callbacks.splice(this.callbacks.indexOf(callback), 1); + }, + + getKey: function(item) { + if (item != null && this.map) { + return this.map.get(item); + } else { + return this.store.indexOf(item); + } + }, + + getKeys: function() { + return Object.keys(this.store); + }, + + setItem: function(key, value) { + this.store[key] = value; + }, + + getItem: function(key) { + return this.store[key]; + }, + + getItems: function() { + var items = [], store = this.store; + for (var key in store) { + items.push(store[key]); + } + return items; + }, + + applySplices: function(splices) { + var map = this.map; + var keySplices = []; + for (var i=0; i<splices.length; i++) { + var j, o, key, s = splices[i]; + // Removed keys + var removed = []; + for (j=0; j<s.removed.length; j++) { + o = s.removed[j]; + key = this.remove(o, true); + removed.push(key); + } + // Added keys + var added = []; + for (j=0; j<s.addedCount; j++) { + o = this.userArray[s.index + j]; + key = this.add(o, true); + added.push(key); + } + // Record splice + keySplices.push({ + index: s.index, + removed: removed, + added: added + }); + } + this.notify(keySplices); + } + + }; + + Polymer.Collection.get = function(userArray, noObserve) { + return Polymer._collections.get(userArray) + || new Polymer.Collection(userArray, noObserve); + }; + + +; + + Polymer({ + + is: 'x-repeat', + extends: 'template', + + properties: { + + /** + * An array containing items determining how many instances of the template + * to stamp and that that each template instance should bind to. + */ + items: { + type: Array + }, + + /** + * A function that should determine the sort order of the items. This + * property should either be provided as a string, indicating a method + * name on the element's host, or else be an actual function. The + * function should match the sort function passed to `Array.sort`. + * Using a sort function has no effect on the underlying `items` array. + */ + sort: { + type: Function, + observer: '_sortChanged' + }, + + /** + * A function that can be used to filter items out of the view. This + * property should either be provided as a string, indicating a method + * name on the element's host, or else be an actual function. The + * function should match the sort function passed to `Array.filter`. + * Using a filter function has no effect on the underlying `items` array. + */ + filter: { + type: Function, + observer: '_filterChanged' + }, + + /** + * When using a `filter` or `sort` function, the `observe` property + * should be set to a space-separated list of the names of item + * sub-fields that should trigger a re-sort or re-filter when changed. + * These should generally be fields of `item` that the sort or filter + * function depends on. + */ + observe: { + type: String, + observer: '_observeChanged' + }, + + /** + * When using a `filter` or `sort` function, the `delay` property + * determines a debounce time after a change to observed item + * properties that must pass before the filter or sort is re-run. + * This is useful in rate-limiting shuffing of the view when + * item changes may be frequent. + */ + delay: Number + }, + + behaviors: [ + Polymer.Templatizer + ], + + observers: [ + '_itemsChanged(items.*)' + ], + + created: function() { + this.boundCollectionObserver = this.render.bind(this); + }, + + ready: function() { + // Templatizing (generating the instance constructor) needs to wait + // until attached, since it may not have its template content handed + // back to it until then, following its host template stamping + if (!this.ctor) { + this.templatize(this); + } + }, + + _sortChanged: function() { + var dataHost = this._getRootDataHost(); + this._sortFn = this.sort && (typeof this.sort == 'function' ? + this.sort : dataHost[this.sort].bind(this.host)); + if (this.items) { + this.debounce('render', this.render); + } + }, + + _filterChanged: function() { + var dataHost = this._getRootDataHost(); + this._filterFn = this.filter && (typeof this.filter == 'function' ? + this.filter : dataHost[this.filter].bind(this.host)); + if (this.items) { + this.debounce('render', this.render); + } + }, + + _observeChanged: function() { + this._observePaths = this.observe && + this.observe.replace('.*', '.').split(' '); + }, + + _itemsChanged: function(change) { + if (change.path == 'items') { + this._unobserveCollection(); + if (change.value) { + this._observeCollection(change.value); + this.debounce('render', this.render); + } + } else { + this._forwardItemPath(change.path, change.value); + this._checkObservedPaths(change.path); + } + }, + + _checkObservedPaths: function(path) { + if (this._observePaths && path.indexOf('items.') === 0) { + path = path.substring(path.indexOf('.', 6) + 1); + var paths = this._observePaths; + for (var i=0; i<paths.length; i++) { + if (path.indexOf(paths[i]) === 0) { + this.debounce('render', this.render, this.delay); + return; + } + } + } + }, + + _observeCollection: function(items) { + this.collection = Array.isArray(items) ? Polymer.Collection.get(items) : items; + this.collection.observe(this.boundCollectionObserver); + }, + + _unobserveCollection: function() { + if (this.collection) { + this.collection.unobserve(this.boundCollectionObserver); + } + }, + + render: function(splices) { + this.flushDebouncer('render'); + var c = this.collection; + if (splices) { + if (this._sortFn || splices[0].index == null) { + this._applySplicesViewSort(splices); + } else { + this._applySplicesArraySort(splices); + } + } else { + this._sortAndFilter(); + } + var rowForKey = this._rowForKey = {}; + var keys = this._orderedKeys; + // Assign items and keys + this.rows = this.rows || []; + for (var i=0; i<keys.length; i++) { + var key = keys[i]; + var item = c.getItem(key); + var row = this.rows[i]; + rowForKey[key] = i; + if (!row) { + this.rows.push(row = this._insertRow(i, null, item)); + } + row.item = item; + row.key = key; + row.index = i; + } + // Remove extra + for (; i<this.rows.length; i++) { + this._detachRow(i); + } + this.rows.splice(keys.length, this.rows.length-keys.length); + }, + + _sortAndFilter: function() { + var c = this.collection; + this._orderedKeys = c.getKeys(); + // Filter + if (this._filterFn) { + this._orderedKeys = this._orderedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + } + // Sort + if (this._sortFn) { + this._orderedKeys.sort(function(a, b) { + return this._sortFn(c.getItem(a), c.getItem(b)); + }.bind(this)); + } + }, + + _keySort: function(a, b) { + return this.collection.getKey(a) - this.collection.getKey(b); + }, + + _applySplicesViewSort: function(splices) { + var c = this.collection; + var keys = this._orderedKeys; + var rows = this.rows; + var removedRows = []; + var addedKeys = []; + var pool = []; + var sortFn = this._sortFn || this._keySort.bind(this); + splices.forEach(function(s) { + // Collect all removed row idx's + for (var i=0; i<s.removed.length; i++) { + var idx = this._rowForKey[s.removed[i]]; + if (idx != null) { + removedRows.push(idx); + } + } + // Collect all added keys + for (i=0; i<s.added.length; i++) { + addedKeys.push(s.added[i]); + } + }, this); + if (removedRows.length) { + // Sort removed rows idx's + removedRows.sort(); + // Remove keys and pool rows (backwards, so we don't invalidate rowForKey) + for (i=removedRows.length-1; i>=0 ; i--) { + var idx = removedRows[i]; + pool.push(this._detachRow(idx)); + rows.splice(idx, 1); + keys.splice(idx, 1); + } + } + if (addedKeys.length) { + // Filter added keys + if (this._filterFn) { + addedKeys = addedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + } + // Sort added keys + addedKeys.sort(function(a, b) { + return this.sortFn(c.getItem(a), c.getItem(b)); + }, this); + // Insert new rows using sort (from pool or newly created) + var start = 0; + for (i=0; i<addedKeys.length; i++) { + start = this._insertRowIntoViewSort(start, addedKeys[i], pool); + } + } + }, + + _insertRowIntoViewSort: function(start, key, pool) { + var c = this.collection; + var item = c.getItem(key); + var end = this.rows.length - 1; + var idx = -1; + var sortFn = this._sortFn || this._keySort.bind(this); + // Binary search for insertion point + while (start <= end) { + var mid = (start + end) >> 1; + var midKey = this._orderedKeys[mid]; + var cmp = sortFn(c.getItem(midKey), item); + if (cmp < 0) { + start = mid + 1; + } else if (cmp > 0) { + end = mid - 1; + } else { + idx = mid; + break; + } + } + if (idx < 0) { + idx = end + 1; + } + // Insert key & row at insertion point + this._orderedKeys.splice(idx, 0, key); + this.rows.splice(idx, 0, this._insertRow(idx, pool)); + return idx; + }, + + _applySplicesArraySort: function(splices) { + var keys = this._orderedKeys; + var pool = []; + splices.forEach(function(s) { + // Remove & pool rows first, to ensure we can fully reuse removed rows + for (var i=0; i<s.removed.length; i++) { + pool.push(this._detachRow(s.index + i)); + } + this.rows.splice(s.index, s.removed.length); + }, this); + var c = this.collection; + var filterDelta = 0; + splices.forEach(function(s) { + // Filter added keys + var addedKeys = s.added; + if (this._filterFn) { + addedKeys = addedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + filterDelta += (s.added.length - addedKeys.length); + } + var idx = s.index - filterDelta; + // Apply splices to keys + var args = [idx, s.removed.length].concat(addedKeys); + keys.splice.apply(keys, args); + // Insert new rows (from pool or newly created) + var addedRows = []; + for (i=0; i<s.added.length; i++) { + addedRows.push(this._insertRow(idx + i, pool)); + } + args = [s.index, 0].concat(addedRows); + this.rows.splice.apply(this.rows, args); + }, this); + }, + + _detachRow: function(idx) { + var row = this.rows[idx]; + var parentNode = Polymer.dom(this).parentNode; + for (var i=0; i<row._children.length; i++) { + var el = row._children[i]; + Polymer.dom(row.root).appendChild(el); + } + return row; + }, + + _insertRow: function(idx, pool, item) { + var row = (pool && pool.pop()) || this._generateRow(idx, item); + var beforeRow = this.rows[idx]; + var beforeNode = beforeRow ? beforeRow._children[0] : this; + var parentNode = Polymer.dom(this).parentNode; + Polymer.dom(parentNode).insertBefore(row.root, beforeNode); + return row; + }, + + _generateRow: function(idx, item) { + var row = this.stamp({ + index: idx, + key: this.collection.getKey(item), + item: item + }); + // each row is a document fragment which is lost when we appendChild, + // so we have to track each child individually + var children = []; + for (var n = row.root.firstChild; n; n=n.nextSibling) { + children.push(n); + n._templateInstance = row; + } + // Since archetype overrides Base/HTMLElement, Safari complains + // when accessing `children` + row._children = children; + return row; + }, + + // Implements extension point from Templatizer mixin + _getStampedChildren: function() { + var children = []; + if (this.rows) { + for (var i=0; i<this.rows.length; i++) { + var c = this.rows[i]._children; + for (var j=0; j<c.length; j++) + children.push(c[j]); + } + } + return children; + }, + + // Implements extension point from Templatizer + // Called as a side effect of a template instance path change, responsible + // for notifying items.<key-for-row>.<path> change up to host + _forwardInstancePath: function(row, root, subPath, value) { + if (root == 'item') { + this.notifyPath('items.' + row.key + '.' + subPath, value); + } + }, + + // Implements extension point from Templatizer mixin + // Called as side-effect of a host property change, responsible for + // notifying parent.<prop> path change on each row + _forwardParentProp: function(prop, value) { + if (this.rows) { + this.rows.forEach(function(row) { + row.parent[prop] = value; + row.notifyPath('parent.' + prop, value, true); + }, this); + } + }, + + // Implements extension point from Templatizer + // Called as side-effect of a host path change, responsible for + // notifying parent.<path> path change on each row + _forwardParentPath: function(path, value) { + if (this.rows) { + this.rows.forEach(function(row) { + row.notifyPath('parent.' + path, value, true); + }, this); + } + }, + + // Called as a side effect of a host items.<key>.<path> path change, + // responsible for notifying item.<path> changes to row for key + _forwardItemPath: function(path, value) { + if (this._rowForKey) { + // 'items.'.length == 6 + var dot = path.indexOf('.', 6); + var key = path.substring(6, dot < 0 ? path.length : dot); + var idx = this._rowForKey[key]; + var row = this.rows[idx]; + if (row) { + if (dot >= 0) { + path = 'item.' + path.substring(dot+1); + row.notifyPath(path, value, true); + } else { + row.item = value; + } + } + } + }, + + _instanceForElement: function(el) { + while (el && !el._templateInstance) { + el = el.parentNode; + } + return el && el._templateInstance; + }, + + /** + * Returns the item associated with a given element stamped by + * this `x-repeat`. + */ + itemForElement: function(el) { + var instance = this._instanceForElement(el); + return instance && instance.item; + }, + + /** + * Returns the `Polymer.Collection` key associated with a given + * element stamped by this `x-repeat`. + */ + keyForElement: function(el) { + var instance = this._instanceForElement(el); + return instance && instance.key; + }, + + /** + * Returns the index in `items` associated with a given element + * stamped by this `x-repeat`. + */ + indexForElement: function(el) { + var instance = this._instanceForElement(el); + return this.rows.indexOf(instance); + } + + }); + + + +; + + Polymer({ + is: 'x-array-selector', + + properties: { + + /** + * An array containing items from which selection will be made. + */ + items: { + type: Array, + observer: '_itemsChanged' + }, + + /** + * When `multi` is true, this is an array that contains any selected. + * When `multi` is false, this is the currently selected item, or `null` + * if no item is selected. + */ + selected: { + type: Object, + notify: true + }, + + /** + * When `true`, calling `select` on an item that is already selected + * will deselect the item. + */ + toggle: Boolean, + + /** + * When `true`, multiple items may be selected at once (in this case, + * `selected` is an array of currently selected items). When `false`, + * only one item may be selected at a time. + */ + multi: Boolean + }, + + _itemsChanged: function() { + // Unbind previous selection + if (Array.isArray(this.selected)) { + for (var i=0; i<this.selected.length; i++) { + this.unbindPaths('selected.' + i); + } + } else { + this.unbindPaths('selected'); + } + // Initialize selection + if (this.multi) { + this.selected = []; + } else { + this.selected = null; + } + }, + + /** + * Deselects the given item if it is already selected. + */ + deselect: function(item) { + if (this.multi) { + var scol = Polymer.Collection.get(this.selected); + // var skey = scol.getKey(item); + // if (skey >= 0) { + var sidx = this.selected.indexOf(item); + if (sidx >= 0) { + var skey = scol.getKey(item); + this.selected.splice(sidx, 1); + // scol.remove(item); + this.unbindPaths('selected.' + skey); + return true; + } + } else { + this.selected = null; + this.unbindPaths('selected'); + } + }, + + /** + * Selects the given item. When `toggle` is true, this will automatically + * deselect the item if already selected. + */ + select: function(item) { + var icol = Polymer.Collection.get(this.items); + var key = icol.getKey(item); + if (this.multi) { + // var sidx = this.selected.indexOf(item); + // if (sidx < 0) { + var scol = Polymer.Collection.get(this.selected); + var skey = scol.getKey(item); + if (skey >= 0) { + this.deselect(item); + } else if (this.toggle) { + this.selected.push(item); + // this.bindPaths('selected.' + sidx, 'items.' + skey); + // skey = Polymer.Collection.get(this.selected).add(item); + this.async(function() { + skey = scol.getKey(item); + this.bindPaths('selected.' + skey, 'items.' + key); + }); + } + } else { + if (this.toggle && item == this.selected) { + this.deselect(); + } else { + this.bindPaths('selected', 'items.' + key); + this.selected = item; + } + } + } + + }); + + +; + + /** + * Stamps the template iff the `if` property is truthy. + * + * When `if` becomes falsey, the stamped content is hidden but not + * removed from dom. When `if` subsequently becomes truthy again, the content + * is simply re-shown. This approach is used due to its favorable performance + * characteristics: the expense of creating template content is paid only + * once and lazily. + * + * Set the `restamp` property to true to force the stamped content to be + * created / destroyed when the `if` condition changes. + */ + Polymer({ + + is: 'x-if', + extends: 'template', + + properties: { + + 'if': { + type: Boolean, + value: false + }, + + restamp: { + type: Boolean, + value: false + } + + }, + + behaviors: [ + Polymer.Templatizer + ], + + observers: [ + 'render(if, restamp)' + ], + + render: function() { + this.debounce('render', function() { + if (this.if) { + if (!this.ctor) { + this._wrapTextNodes(this._content); + this.templatize(this); + } + this._ensureInstance(); + } else if (this.restamp) { + this._teardownInstance(); + } + if (!this.restamp && this._instance) { + this._showHideInstance(this.if); + } + }); + }, + + _ensureInstance: function() { + if (!this._instance) { + // TODO(sorvell): pickup stamping logic from x-repeat + this._instance = this.stamp(); + var root = this._instance.root; + this._instance._children = Array.prototype.slice.call(root.childNodes); + // TODO(sorvell): this incantation needs to be simpler. + var parent = Polymer.dom(Polymer.dom(this).parentNode); + parent.insertBefore(root, this); + } + }, + + _teardownInstance: function() { + if (this._instance) { + var parent = Polymer.dom(Polymer.dom(this).parentNode); + this._instance._children.forEach(function(n) { + parent.removeChild(n); + }); + this._instance = null; + } + }, + + _wrapTextNodes: function(root) { + // wrap text nodes in span so they can be hidden. + for (var n = root.firstChild; n; n=n.nextSibling) { + if (n.nodeType === Node.TEXT_NODE) { + var s = document.createElement('span'); + root.insertBefore(s, n); + s.appendChild(n); + n = s; + } + } + }, + + // Implements extension point from Templatizer mixin + _getStampedChildren: function() { + return this._instance._children; + }, + + _showHideInstance: function(showing) { + this._getAllStampedChildren().forEach(function(n) { + if (n.setAttribute) { + this.serializeValueToAttribute(!showing, 'hidden', n); + } + }, this); + }, + + // Implements extension point from Templatizer mixin + // Called as side-effect of a host property change, responsible for + // notifying parent.<prop> path change on instance + _forwardParentProp: function(prop, value) { + if (this._instance) { + this._instance.parent[prop] = value; + this._instance.notifyPath('parent.' + prop, value, true); + } + }, + + // Implements extension point from Templatizer + // Called as side-effect of a host path change, responsible for + // notifying parent.<path> path change on each row + _forwardParentPath: function(path, value) { + if (this._instance) { + this._instance.notifyPath('parent.' + path, value, true); + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations-extracted.js new file mode 100644 index 0000000..f69af185 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations-extracted.js
@@ -0,0 +1,318 @@ + +/** + * Scans a template to produce an annotation list that that associates + * metadata culled from markup with tree locations + * metadata and information to associate the metadata with nodes in an instance. + * + * Supported expressions include: + * + * Double-mustache annotations in text content. The annotation must be the only + * content in the tag, compound expressions are not supported. + * + * <[tag]>{{annotation}}<[tag]> + * + * Double-escaped annotations in an attribute, either {{}} or [[]]. + * + * <[tag] someAttribute="{{annotation}}" another="[[annotation]]"><[tag]> + * + * `on-` style event declarations. + * + * <[tag] on-<event-name>="annotation"><[tag]> + * + * Note that the `annotations` feature does not implement any behaviors + * associated with these expressions, it only captures the data. + * + * Generated data-structure: + * + * [ + * { + * id: '<id>', + * events: [ + * { + * name: '<name>' + * value: '<annotation>' + * }, ... + * ], + * bindings: [ + * { + * kind: ['text'|'attribute'], + * mode: ['{'|'['], + * name: '<name>' + * value: '<annotation>' + * }, ... + * ], + * // TODO(sjmiles): this is annotation-parent, not node-parent + * parent: <reference to parent annotation object>, + * index: <integer index in parent's childNodes collection> + * }, + * ... + * ] + * + * @class Template feature + */ + + // null-array (shared empty array to avoid null-checks) + Polymer.nar = []; + + Polymer.Annotations = { + + // preprocess-time + + // construct and return a list of annotation records + // by scanning `template`'s content + // + parseAnnotations: function(template) { + var list = []; + var content = template._content || template.content; + this._parseNodeAnnotations(content, list); + return list; + }, + + // add annotations gleaned from subtree at `node` to `list` + _parseNodeAnnotations: function(node, list) { + return node.nodeType === Node.TEXT_NODE ? + this._parseTextNodeAnnotation(node, list) : + // TODO(sjmiles): are there other nodes we may encounter + // that are not TEXT_NODE but also not ELEMENT? + this._parseElementAnnotations(node, list); + }, + + // add annotations gleaned from TextNode `node` to `list` + _parseTextNodeAnnotation: function(node, list) { + var v = node.textContent, escape = v.slice(0, 2); + if (escape === '{{' || escape === '[[') { + // NOTE: use a space here so the textNode remains; some browsers + // (IE) evacipate an empty textNode. + node.textContent = ' '; + var annote = { + bindings: [{ + kind: 'text', + mode: escape[0], + value: v.slice(2, -2) + }] + }; + list.push(annote); + return annote; + } + }, + + // add annotations gleaned from Element `node` to `list` + _parseElementAnnotations: function(element, list) { + var annote = { + bindings: [], + events: [] + }; + this._parseChildNodesAnnotations(element, annote, list); + // TODO(sjmiles): is this for non-ELEMENT nodes? If so, we should + // change the contract of this method, or filter these out above. + if (element.attributes) { + this._parseNodeAttributeAnnotations(element, annote, list); + // TODO(sorvell): ad hoc callback for doing work on elements while + // leveraging annotator's tree walk. + // Consider adding an node callback registry and moving specific + // processing out of this module. + if (this.prepElement) { + this.prepElement(element); + } + } + if (annote.bindings.length || annote.events.length || annote.id) { + list.push(annote); + } + return annote; + }, + + // add annotations gleaned from children of `root` to `list`, `root`'s + // `annote` is supplied as it is the annote.parent of added annotations + _parseChildNodesAnnotations: function(root, annote, list, callback) { + if (root.firstChild) { + for (var i=0, node=root.firstChild; node; node=node.nextSibling, i++){ + if (node.localName === 'template' && + !node.hasAttribute('preserve-content')) { + this._parseTemplate(node, i, list, annote); + } + // + var childAnnotation = this._parseNodeAnnotations(node, list, callback); + if (childAnnotation) { + childAnnotation.parent = annote; + childAnnotation.index = i; + } + } + } + }, + + // 1. Parse annotations from the template and memoize them on + // content._notes (recurses into nested templates) + // 2. Parse template bindings for parent.* properties and memoize them on + // content._parentProps + // 3. Create bindings in current scope's annotation list to template for + // parent props found in template + // 4. Remove template.content and store it in annotation list, where it + // will be the responsibility of the host to set it back to the template + // (this is both an optimization to avoid re-stamping nested template + // children and avoids a bug in Chrome where nested template children + // upgrade) + _parseTemplate: function(node, index, list, parent) { + // TODO(sjmiles): simply altering the .content reference didn't + // work (there was some confusion, might need verification) + var content = document.createDocumentFragment(); + content._notes = this.parseAnnotations(node); + content.appendChild(node.content); + // Special-case treatment of 'parent.*' props for nested templates + // Automatically bind `prop` on host to `_parent_prop` on template + // for any `parent.prop`'s encountered in template binding; it is + // responsibility of the template implementation to forward + // these properties as appropriate + var bindings = []; + this._discoverTemplateParentProps(content); + for (var prop in content._parentProps) { + bindings.push({ + index: index, + kind: 'property', + mode: '{', + name: '_parent_' + prop, + value: prop + }); + } + // TODO(sjmiles): using `nar` to avoid unnecessary allocation; + // in general the handling of these arrays needs some cleanup + // in this module + list.push({ + bindings: bindings, + events: Polymer.nar, + templateContent: content, + parent: parent, + index: index + }); + }, + + // Finds all parent.* properties in template content and stores + // the path members in content._parentPropChain, which is an array + // of maps listing the properties of parent templates required at + // each level. Each outer template merges inner _parentPropChains to + // propagate inner parent property needs to outer templates. + // The top-level parent props from the chain (corresponding to this + // template) are stored in content._parentProps. + _discoverTemplateParentProps: function(content) { + var chain = content._parentPropChain = []; + content._notes.forEach(function(n) { + // Find all bindings to parent.* and spread them into _parentPropChain + n.bindings.forEach(function(b) { + var m; + if (m = b.value.match(/parent\.((parent\.)*[^.]*)/)) { + var parts = m[1].split('.'); + for (var i=0; i<parts.length; i++) { + var pp = chain[i] || (chain[i] = {}); + pp[parts[i]] = true; + } + } + }); + // Merge child _parentPropChain[n+1] into this _parentPropChain[n] + if (n.templateContent) { + var tpp = n.templateContent._parentPropChain; + for (var i=1; i<tpp.length; i++) { + if (tpp[i]) { + var pp = chain[i-1] || (chain[i-1] = {}); + Polymer.Base.simpleMixin(pp, tpp[i]); + } + } + } + }); + // Store this template's parentProps map + content._parentProps = chain[0]; + }, + + // add annotation data from attributes to the `annotation` for node `node` + // TODO(sjmiles): the distinction between an `annotation` and + // `annotation data` is not as clear as it could be + // Walk attributes backwards, since removeAttribute can be vetoed by + // IE in certain cases (e.g. <input value="foo">), resulting in the + // attribute staying in the attributes list + _parseNodeAttributeAnnotations: function(node, annotation) { + for (var i=node.attributes.length-1, a; (a=node.attributes[i]); i--) { + var n = a.name, v = a.value; + // id + if (n === 'id') { + annotation.id = v; + } + // events (on-*) + else if (n.slice(0, 3) === 'on-') { + node.removeAttribute(n); + annotation.events.push({ + name: n.slice(3), + value: v + }); + } + // bindings (other attributes) + else { + var b = this._parseNodeAttributeAnnotation(node, n, v); + if (b) { + annotation.bindings.push(b); + } + } + } + }, + + // construct annotation data from a generic attribute, or undefined + _parseNodeAttributeAnnotation: function(node, n, v) { + var mode = '', escape = v.slice(0, 2), name = n; + if (escape === '{{' || escape === '[[') { + // Mode (one-way or two) + mode = escape[0]; + v = v.slice(2, -2); + // Negate + var not = false; + if (v[0] == '!') { + v = v.substring(1); + not = true; + } + // Attribute or property + var kind = 'property'; + if (n[n.length-1] == '$') { + name = n.slice(0, -1); + kind = 'attribute'; + } + // Custom notification event + var notifyEvent, colon; + if (mode == '{' && (colon = v.indexOf('::')) > 0) { + notifyEvent = v.substring(colon + 2); + v = v.substring(0, colon); + } + // Remove annotation + node.removeAttribute(n); + // Case hackery: attributes are lower-case, but bind targets + // (properties) are case sensitive. Gambit is to map dash-case to + // camel-case: `foo-bar` becomes `fooBar`. + // Attribute bindings are excepted. + if (kind === 'property') { + name = Polymer.CaseMap.dashToCamelCase(name); + } + return { + kind: kind, + mode: mode, + name: name, + value: v, + negate: not, + event: notifyEvent + }; + } + }, + + // instance-time + + _localSubTree: function(node, host) { + return (node === host) ? node.childNodes : + (node.lightChildren || node.childNodes); + }, + + findAnnotatedNode: function(root, annote) { + // recursively ascend tree until we hit root + var parent = annote.parent && + Polymer.Annotations.findAnnotatedNode(root, annote.parent); + // unwind the stack, returning the indexed node at each level + return !parent ? root : + Polymer.Annotations._localSubTree(parent, root)[annote.index]; + } + + }; + +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations.html new file mode 100644 index 0000000..9fcdd8e6 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations.html
@@ -0,0 +1,12 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../module.html"> +<link rel="import" href="../case-map.html"> + +</head><body><script src="annotations-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/demo/app-chrome-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/demo/app-chrome-extracted.js new file mode 100644 index 0000000..c405934 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/demo/app-chrome-extracted.js
@@ -0,0 +1,21 @@ +console.perf(); +; + + using('Annotations', function(Annotations) { + + var template = document.querySelector('template'); + var list = Annotations.parseAnnotations(template); + console.log(list); + + var out = document.querySelector('pre'); + out.textContent = JSON.stringify(list, function(key, value) { + if (key === 'parent') { + return '<parent reference>'; + } + return value; + }, ' '); + + }); + + +;console.perfEnd(); \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/demo/app-chrome.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/demo/app-chrome.html new file mode 100644 index 0000000..2b3f136 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/demo/app-chrome.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html><html><head> + + <script src="../../../../perf-lib/perf.js"></script> + + <title>Template Test</title> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <link rel="import" href="../../lang.html"> + <link rel="import" href="../../module.html"> + + <link rel="import" href="../annotations.html"> + + <style> + pre { + font-family: monospace; + font-size: 11px; + } + </style> + +</head> +<body> + + <template> + + <span id="foo" attribute="{{path}}" oneway="[[otherpath]]" style:="{{specialStyle}}">{{text}}</span> + + </template> + + <pre></pre> + + <script src="app-chrome-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-observe-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-observe-extracted.js new file mode 100644 index 0000000..e89ce32 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-observe-extracted.js
@@ -0,0 +1,106 @@ + + +(function() { + + var callbacks = new WeakMap(); + + function observe(array, cb) { + if (Array.observe) { + var ncb = function(changes) { + changes = changes.filter(function(o) { return o.type == 'splice'; }); + if (changes.length) { + cb(changes); + } + }; + callbacks.set(cb, ncb); + Array.observe(array, ncb); + } else { + if (!array.__polymerObservable) { + makeObservable(array); + } + callbacks.get(array).push(cb); + } + } + + function unobserve(array, cb) { + if (Array.observe) { + var ncb = callbacks.get(cb); + callbacks.delete(cb); + Array.unobserve(array, ncb); + } else { + var cbs = callbacks.get(array); + var idx = cbs.indexOf(cb); + if (idx >= 0) { + cbs.splice(idx, 1); + } + } + } + + function makeObservable(array) { + var splices = []; + var debounce; + var orig = { + push: array.push, + pop: array.pop, + splice: array.splice, + shift: array.shift, + unshift: array.unshift, + sort: array.sort + }; + var addSplice = function(index, added, removed) { + splices.push({ + index: index, + addedCount: added, + removed: removed, + object: array, + type: 'splice' + }); + }; + callbacks.set(array, []); + array.push = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(array.length, 1, []); + return orig.push.apply(this, arguments); + }; + array.pop = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(array.length - 1, 0, array.slice(-1)); + return orig.pop.apply(this, arguments); + }; + array.splice = function(start, deleteCount) { + debounce = Polymer.Debounce(debounce, fin); + addSplice(start, arguments.length - 2, array.slice(start, start + deleteCount)); + return orig.splice.apply(this, arguments); + }; + array.shift = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(0, 0, [array[0]]); + return orig.shift.apply(this, arguments); + }; + array.unshift = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(0, 1, []); + return orig.unshift.apply(this, arguments); + }; + array.sort = function() { + debounce = Polymer.Debounce(debounce, fin); + console.warn('[ArrayObserve]: sort not observable'); + return orig.sort.apply(this, arguments); + }; + var fin = function() { + var cbs = callbacks.get(array); + for (var i=0; i<cbs.length; i++) { + cbs[i](splices); + } + splices = []; + }; + array.__polymerObservable = true; + } + + Polymer.ArrayObserve = { + observe: observe, + unobserve: unobserve + }; + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-observe.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-observe.html new file mode 100644 index 0000000..7eaef829 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-observe.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="debounce.html"> + +</head><body><script src="array-observe-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-splice-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-splice-extracted.js new file mode 100644 index 0000000..a04f701 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-splice-extracted.js
@@ -0,0 +1,252 @@ + + +Polymer.ArraySplice = (function() { + + function newSplice(index, removed, addedCount) { + return { + index: index, + removed: removed, + addedCount: addedCount + }; + } + + var EDIT_LEAVE = 0; + var EDIT_UPDATE = 1; + var EDIT_ADD = 2; + var EDIT_DELETE = 3; + + function ArraySplice() {} + + ArraySplice.prototype = { + + // Note: This function is *based* on the computation of the Levenshtein + // "edit" distance. The one change is that "updates" are treated as two + // edits - not one. With Array splices, an update is really a delete + // followed by an add. By retaining this, we optimize for "keeping" the + // maximum array items in the original array. For example: + // + // 'xxxx123' -> '123yyyy' + // + // With 1-edit updates, the shortest path would be just to update all seven + // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This + // leaves the substring '123' intact. + calcEditDistances: function(current, currentStart, currentEnd, + old, oldStart, oldEnd) { + // "Deletion" columns + var rowCount = oldEnd - oldStart + 1; + var columnCount = currentEnd - currentStart + 1; + var distances = new Array(rowCount); + + // "Addition" rows. Initialize null column. + for (var i = 0; i < rowCount; i++) { + distances[i] = new Array(columnCount); + distances[i][0] = i; + } + + // Initialize null row + for (var j = 0; j < columnCount; j++) + distances[0][j] = j; + + for (var i = 1; i < rowCount; i++) { + for (var j = 1; j < columnCount; j++) { + if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1])) + distances[i][j] = distances[i - 1][j - 1]; + else { + var north = distances[i - 1][j] + 1; + var west = distances[i][j - 1] + 1; + distances[i][j] = north < west ? north : west; + } + } + } + + return distances; + }, + + // This starts at the final weight, and walks "backward" by finding + // the minimum previous weight recursively until the origin of the weight + // matrix. + spliceOperationsFromEditDistances: function(distances) { + var i = distances.length - 1; + var j = distances[0].length - 1; + var current = distances[i][j]; + var edits = []; + while (i > 0 || j > 0) { + if (i == 0) { + edits.push(EDIT_ADD); + j--; + continue; + } + if (j == 0) { + edits.push(EDIT_DELETE); + i--; + continue; + } + var northWest = distances[i - 1][j - 1]; + var west = distances[i - 1][j]; + var north = distances[i][j - 1]; + + var min; + if (west < north) + min = west < northWest ? west : northWest; + else + min = north < northWest ? north : northWest; + + if (min == northWest) { + if (northWest == current) { + edits.push(EDIT_LEAVE); + } else { + edits.push(EDIT_UPDATE); + current = northWest; + } + i--; + j--; + } else if (min == west) { + edits.push(EDIT_DELETE); + i--; + current = west; + } else { + edits.push(EDIT_ADD); + j--; + current = north; + } + } + + edits.reverse(); + return edits; + }, + + /** + * Splice Projection functions: + * + * A splice map is a representation of how a previous array of items + * was transformed into a new array of items. Conceptually it is a list of + * tuples of + * + * <index, removed, addedCount> + * + * which are kept in ascending index order of. The tuple represents that at + * the |index|, |removed| sequence of items were removed, and counting forward + * from |index|, |addedCount| items were added. + */ + + /** + * Lacking individual splice mutation information, the minimal set of + * splices can be synthesized given the previous state and final state of an + * array. The basic approach is to calculate the edit distance matrix and + * choose the shortest path through it. + * + * Complexity: O(l * p) + * l: The length of the current array + * p: The length of the old array + */ + calcSplices: function(current, currentStart, currentEnd, + old, oldStart, oldEnd) { + var prefixCount = 0; + var suffixCount = 0; + + var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart); + if (currentStart == 0 && oldStart == 0) + prefixCount = this.sharedPrefix(current, old, minLength); + + if (currentEnd == current.length && oldEnd == old.length) + suffixCount = this.sharedSuffix(current, old, minLength - prefixCount); + + currentStart += prefixCount; + oldStart += prefixCount; + currentEnd -= suffixCount; + oldEnd -= suffixCount; + + if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0) + return []; + + if (currentStart == currentEnd) { + var splice = newSplice(currentStart, [], 0); + while (oldStart < oldEnd) + splice.removed.push(old[oldStart++]); + + return [ splice ]; + } else if (oldStart == oldEnd) + return [ newSplice(currentStart, [], currentEnd - currentStart) ]; + + var ops = this.spliceOperationsFromEditDistances( + this.calcEditDistances(current, currentStart, currentEnd, + old, oldStart, oldEnd)); + + var splice = undefined; + var splices = []; + var index = currentStart; + var oldIndex = oldStart; + for (var i = 0; i < ops.length; i++) { + switch(ops[i]) { + case EDIT_LEAVE: + if (splice) { + splices.push(splice); + splice = undefined; + } + + index++; + oldIndex++; + break; + case EDIT_UPDATE: + if (!splice) + splice = newSplice(index, [], 0); + + splice.addedCount++; + index++; + + splice.removed.push(old[oldIndex]); + oldIndex++; + break; + case EDIT_ADD: + if (!splice) + splice = newSplice(index, [], 0); + + splice.addedCount++; + index++; + break; + case EDIT_DELETE: + if (!splice) + splice = newSplice(index, [], 0); + + splice.removed.push(old[oldIndex]); + oldIndex++; + break; + } + } + + if (splice) { + splices.push(splice); + } + return splices; + }, + + sharedPrefix: function(current, old, searchLength) { + for (var i = 0; i < searchLength; i++) + if (!this.equals(current[i], old[i])) + return i; + return searchLength; + }, + + sharedSuffix: function(current, old, searchLength) { + var index1 = current.length; + var index2 = old.length; + var count = 0; + while (count < searchLength && this.equals(current[--index1], old[--index2])) + count++; + + return count; + }, + + calculateSplices: function(current, previous) { + return this.calcSplices(current, 0, current.length, previous, 0, + previous.length); + }, + + equals: function(currentValue, previousValue) { + return currentValue === previousValue; + } + }; + + return new ArraySplice(); + +})();
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-splice.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-splice.html new file mode 100644 index 0000000..be59e398 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/array-splice.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="array-splice-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/async-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/async-extracted.js new file mode 100644 index 0000000..71126c8b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/async-extracted.js
@@ -0,0 +1,58 @@ + + +Polymer.Async = (function() { + + var currVal = 0; + var lastVal = 0; + var callbacks = []; + var twiddle = document.createTextNode(''); + + function runAsync(callback, waitTime) { + if (waitTime > 0) { + return ~setTimeout(callback, waitTime); + } else { + twiddle.textContent = currVal++; + callbacks.push(callback); + return currVal - 1; + } + } + + function cancelAsync(handle) { + if (handle < 0) { + clearTimeout(~handle); + } else { + var idx = handle - lastVal; + if (idx >= 0) { + if (!callbacks[idx]) { + throw 'invalid async handle: ' + handle; + } + callbacks[idx] = null; + } + } + } + + function atEndOfMicrotask() { + var len = callbacks.length; + for (var i=0; i<len; i++) { + var cb = callbacks[i]; + if (cb) { + cb(); + } + } + callbacks.splice(0, len); + lastVal += len; + } + + new (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask) + .observe(twiddle, {characterData: true}) + ; + + // exports + + return { + run: runAsync, + cancel: cancelAsync + }; + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/async.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/async.html new file mode 100644 index 0000000..86d3343 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/async.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="async-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/base-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/base-extracted.js new file mode 100644 index 0000000..5df6b71 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/base-extracted.js
@@ -0,0 +1,82 @@ + + + Polymer.Base = { + + // pluggable features + // `this` context is a prototype, not an instance + _addFeature: function(feature) { + this.extend(this, feature); + }, + + // `this` context is a prototype, not an instance + registerCallback: function() { + this._registerFeatures(); // abstract + this._doBehavior('registered'); // abstract + }, + + createdCallback: function() { + Polymer.telemetry.instanceCount++; + this.root = this; + this._doBehavior('created'); // abstract + this._initFeatures(); // abstract + }, + + // reserved for canonical behavior + attachedCallback: function() { + this.isAttached = true; + this._doBehavior('attached'); // abstract + }, + + // reserved for canonical behavior + detachedCallback: function() { + this.isAttached = false; + this._doBehavior('detached'); // abstract + }, + + // reserved for canonical behavior + attributeChangedCallback: function(name) { + this.setAttributeToProperty(this, name); + this._doBehavior('attributeChanged', arguments); // abstract + }, + + // copy own properties from `api` to `prototype` + extend: function(prototype, api) { + if (prototype && api) { + Object.getOwnPropertyNames(api).forEach(function(n) { + this.copyOwnProperty(n, api, prototype); + }, this); + } + return prototype || api; + }, + + copyOwnProperty: function(name, source, target) { + var pd = Object.getOwnPropertyDescriptor(source, name); + if (pd) { + Object.defineProperty(target, name, pd); + } + } + + }; + + if (Object.__proto__) { + Polymer.Base.chainObject = function(object, inherited) { + if (object && inherited && object !== inherited) { + object.__proto__ = inherited; + } + return object; + }; + } else { + Polymer.Base.chainObject = function(object, inherited) { + if (object && inherited && object !== inherited) { + var chained = Object.create(inherited); + object = Polymer.Base.extend(chained, object); + } + return object; + }; + } + + Polymer.Base = Polymer.Base.chainObject(Polymer.Base, HTMLElement.prototype); + + // TODO(sjmiles): ad hoc telemetry + Polymer.telemetry.instanceCount = 0; +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/base.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/base.html new file mode 100644 index 0000000..cb585a87 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/base.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="base-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/accessors-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/accessors-extracted.js new file mode 100644 index 0000000..e8ca599 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/accessors-extracted.js
@@ -0,0 +1,219 @@ + + + Polymer.Bind = { + + // for prototypes (usually) + + prepareModel: function(model) { + model._propertyEffects = {}; + model._bindListeners = []; + // TODO(sjmiles): no mixin function? + var api = this._modelApi; + for (var n in api) { + model[n] = api[n]; + } + }, + + _modelApi: { + + _notifyChange: function(property) { + var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed'; + // TODO(sjmiles): oops, `fire` doesn't exist at this layer + this.fire(eventName, { + value: this[property] + }, {bubbles: false}); + }, + + // TODO(sjmiles): removing _notifyListener from here breaks accessors.html + // as a standalone lib. This is temporary, as standard/configure.html + // installs it's own version on Polymer.Base, and we need that to work + // right now. + // NOTE: exists as a hook for processing listeners + /* + _notifyListener: function(fn, e) { + // NOTE: pass e.target because e.target can get lost if this function + // is queued asynchrously + return fn.call(this, e, e.target); + }, + */ + + _propertySet: function(property, value, effects) { + var old = this._data[property]; + if (old !== value) { + this._data[property] = value; + if (typeof value == 'object') { + this._clearPath(property); + } + if (effects) { + this._effectEffects(property, value, effects, old); + } + } + return old; + }, + + _effectEffects: function(property, value, effects, old) { + effects.forEach(function(fx) { + //console.log(fx); + var fn = Polymer.Bind[fx.kind + 'Effect']; + if (fn) { + fn.call(this, property, value, fx.effect, old); + } + }, this); + }, + + _clearPath: function(path) { + for (var prop in this._data) { + if (prop.indexOf(path + '.') === 0) { + this._data[prop] = undefined; + } + } + } + + }, + + // a prepared model can acquire effects + + ensurePropertyEffects: function(model, property) { + var fx = model._propertyEffects[property]; + if (!fx) { + fx = model._propertyEffects[property] = []; + } + return fx; + }, + + addPropertyEffect: function(model, property, kind, effect) { + var fx = this.ensurePropertyEffects(model, property); + fx.push({ + kind: kind, + effect: effect + }); + }, + + createBindings: function(model) { + //console.group(model.is); + // map of properties to effects + var fx$ = model._propertyEffects; + if (fx$) { + // for each property with effects + for (var n in fx$) { + // array of effects + var fx = fx$[n]; + // effects have priority + fx.sort(this._sortPropertyEffects); + // create accessors + this._createAccessors(model, n, fx); + } + } + //console.groupEnd(); + }, + + _sortPropertyEffects: (function() { + // TODO(sjmiles): EFFECT_ORDER buried this way is not ideal, + // but presumably the sort method is going to be a hot path and not + // have a `this`. There is also a problematic dependency on effect.kind + // values here, which are otherwise pluggable. + var EFFECT_ORDER = { + 'compute': 0, + 'annotation': 1, + 'computedAnnotation': 2, + 'reflect': 3, + 'notify': 4, + 'observer': 5, + 'complexObserver': 6, + 'function': 7 + }; + return function(a, b) { + return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind]; + }; + })(), + + // create accessors that implement effects + + _createAccessors: function(model, property, effects) { + var defun = { + get: function() { + // TODO(sjmiles): elide delegation for performance, good ROI? + return this._data[property]; + } + }; + var setter = function(value) { + this._propertySet(property, value, effects); + }; + // ReadOnly properties have a private setter only + // TODO(kschaaf): Per current Bind factoring, we shouldn't + // be interrogating the prototype here + if (model.isReadOnlyProperty && model.isReadOnlyProperty(property)) { + //model['_' + property + 'Setter'] = setter; + //model['_set_' + property] = setter; + model['_set' + this.upper(property)] = setter; + } else { + defun.set = setter; + } + Object.defineProperty(model, property, defun); + }, + + upper: function(name) { + return name[0].toUpperCase() + name.substring(1); + }, + + _addAnnotatedListener: function(model, index, property, path, event) { + var fn = this._notedListenerFactory(property, path, + this._isStructured(path), this._isEventBogus); + var eventName = event || + (Polymer.CaseMap.camelToDashCase(property) + '-changed'); + model._bindListeners.push({ + index: index, + property: property, + path: path, + changedFn: fn, + event: eventName + }); + }, + + _isStructured: function(path) { + return path.indexOf('.') > 0; + }, + + _isEventBogus: function(e, target) { + return e.path && e.path[0] !== target; + }, + + _notedListenerFactory: function(property, path, isStructured, bogusTest) { + return function(e, target) { + if (!bogusTest(e, target)) { + if (e.detail && e.detail.path) { + this.notifyPath(this._fixPath(path, property, e.detail.path), + e.detail.value); + } else { + var value = target[property]; + if (!isStructured) { + this[path] = target[property]; + } else { + // TODO(kschaaf): dirty check avoids null references when the object has gone away + if (this._data[path] != value) { + this.setPathValue(path, value); + } + } + } + } + }; + }, + + // for instances + + prepareInstance: function(inst) { + inst._data = Object.create(null); + }, + + setupBindListeners: function(inst) { + inst._bindListeners.forEach(function(info) { + // Property listeners: + // <node>.on.<property>-changed: <path]> = e.detail.value + //console.log('[_setupBindListener]: [%s][%s] listening for [%s][%s-changed]', this.localName, info.path, info.id || info.index, info.property); + var node = inst._nodes[info.index]; + node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn)); + }); + } + + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/accessors.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/accessors.html new file mode 100644 index 0000000..7a6d19c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/accessors.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="accessors-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/app-chrome.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/app-chrome.html new file mode 100644 index 0000000..47a5bb85 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/app-chrome.html
@@ -0,0 +1,28 @@ +<!doctype html> +<html> +<head> + + <title>Bind Test</title> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <style> + pre { + font-family: sans-serif; + font-size: 14px; + } + </style> + + <link rel="import" href="src/bind-demo.html"> + <link rel="import" href="src/annotations-bind-demo.html"> + +</head> +<body> + + <pre id="bd"></pre> + + <pre id="abd"></pre> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/app.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/app.html new file mode 100644 index 0000000..ffc161f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/app.html
@@ -0,0 +1,29 @@ +<!doctype html> +<html> +<head> + + <title>Bind Test</title> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../../../../webcomponentsjs/webcomponents-lite.js"></script> + + <style> + pre { + font-family: sans-serif; + font-size: 14px; + } + </style> + + <link rel="import" href="src/bind-demo.html"> + <link rel="import" href="src/annotations-bind-demo.html"> + +</head> +<body> + + <pre id="bd"></pre> + <pre id="abd"></pre> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/annotations-bind-demo-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/annotations-bind-demo-extracted.js new file mode 100644 index 0000000..2afcdd8 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/annotations-bind-demo-extracted.js
@@ -0,0 +1,59 @@ + + + // TODO(sjmiles): should 'bind-annotations' blend the other two modules + // somehow so we don't need to include all three here? + using(['Annotations', 'bind', 'bind-annotations'], + + function(Annotations, Bind, BindAnnotations) { + + var out = document.querySelector('#abd'); + out.innerHTML += '<hr><h3>annotations-bind demo</h3><hr>'; + + // phase one: prototyping + + var prototype = {}; + var template = currentImport.querySelector('template'); + var list = Templabindinate(prototype, template); + + // phase two: instancing + + var model = Object.create(prototype); + var dom = Instancinance(model, template); + document.body.appendChild(dom); + + // affect model + + model.text = 'Hello from Model'; + model.path = 'path'; + model.otherpath = 'other.path'; + model.specialStyle = {backgroundColor: "red"}; + + // effects visible in dom + + var foo = dom.querySelector('#foo'); + out.innerHTML += + 'foo.<b>path</b> = "' + model.path + '"<br>' + + 'foo.<b>otherpath</b> = "' + model.otherpath + '"<br>' + + 'foo.<b>specialStyle</b> = "' + JSON.stringify(model.specialStyle)+ '"<br>' + ; + + // ad hoc abstractions + + function Templabindinate(model, template) { + Bind.prepareModel(model); + var list = Annotations.parseAnnotations(template); + BindAnnotations.addEffects(model, list); + return list; + } + + function Instancinance(model, template) { + Bind.prepareInstance(model); + Bind.createBindings(model); + var dom = document.importNode(template.content, true); + model._nodes = BindAnnotations.marshalAnnotatedNodes(model._nodes, dom, + Annotations.findAnnotatedNode); + return dom; + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/annotations-bind-demo.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/annotations-bind-demo.html new file mode 100644 index 0000000..7c54c8e --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/annotations-bind-demo.html
@@ -0,0 +1,17 @@ +<html><head><link rel="import" href="../../../module.html"> +<link rel="import" href="../../../lang.html"> +<link rel="import" href="../../../annotations/annotations.html"> + +<link rel="import" href="../../bind.html"> +<link rel="import" href="../../bind-effects.html"> +<link rel="import" href="../../bind-annotations.html"> + +<template> + + <div>annotated #foo span:</div> + <br> + <span id="foo" attribute="{{path}}" oneway="[[otherpath]]" style="{{specialStyle}}">{{text}}</span> + +</template> + +</head><body><script src="annotations-bind-demo-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/bind-demo-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/bind-demo-extracted.js new file mode 100644 index 0000000..28419e4 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/bind-demo-extracted.js
@@ -0,0 +1,78 @@ + + + using(['bind'], function(Bind) { + + var out = document.querySelector('#bd'); + out.innerHTML += '<hr><h3>bind demo</h3><hr>'; + + // phase one: prototyping + + var model = {}; + + Bind.prepareModel(model); + + // 'observer' effects are called if foo changes value as fx(foo, old) + + Bind.addPropertyEffect(model, 'foo', 'observer', 'fooChange'); + Bind.addPropertyEffect(model, 'foo', 'observer', 'fooWork'); + + model.fooChange = function(foo) { + out.innerHTML += '<b>fooChange</b>: effect of changing foo to ' + foo + '\n'; + console.log('fooChange: effect of changing foo to %d', foo); + }; + + model.fooWork = function(foo) { + out.innerHTML += '<b>fooWork</b>: effect of changing foo to ' + foo + '\n'; + console.log('fooWork: effect of changing foo to %d', foo); + }; + + // 'compute' effect sets the value of bar to the result of computeBar when + // foo changes value + + /* + Bind.addPropertyEffect(model, 'foo', 'compute', { + method: 'computeBar', + property: 'bar' + }); + */ + Bind.addComputedPropertyEffect(model, 'bar', 'computeFooTimes2(foo)'); + + model.computeFooTimes2 = function(foo) { + var foo2 = foo * 2; + out.innerHTML += '<b>computeFooTimes2</b>: calculated ' + foo2 + ' as an effect of changing foo to ' + foo + '\n'; + console.log('computeFooTimes2: calculated %d as effect of changing foo to %d', foo2, foo); + return foo2; + }; + + // custom effect + + Bind.addBuilder('async', function(model, property, effect) { + var fn = function() { + var flag = '_propertyTask'; + clearTimeout(this[flag]); + this[flag] = setTimeout(function() { + this.effect(this.property); + this[flag] = 0; + }.bind(this)); + }; + var code = fn.toString().split('\n').slice(1, -1).join('\n'); + return code.replace(/property/g, property).replace(/effect/g, effect); + }); + + Bind.addPropertyEffect(model, 'foo', 'async', 'asyncFoo'); + + model.asyncFoo = function(foo) { + out.innerHTML += '<b>asyncFoo</b>: effect of changing foo to ' + foo + '\n'; + console.log('asyncFoo: effect of changing foo to %d', foo); + }; + + // phase two: instancing + + Bind.prepareInstance(model); + Bind.createBindings(model); + + model.foo = 3; + model.foo = 6; + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/bind-demo.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/bind-demo.html new file mode 100644 index 0000000..87520d1 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/demo/src/bind-demo.html
@@ -0,0 +1,5 @@ +<html><head><link rel="import" href="../../../module.html"> +<link rel="import" href="../../bind.html"> +<link rel="import" href="../../bind-effects.html"> + +</head><body><script src="bind-demo-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/effects-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/effects-extracted.js new file mode 100644 index 0000000..d106015 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/effects-extracted.js
@@ -0,0 +1,94 @@ + + + Polymer.Base.extend(Polymer.Bind, { + + _shouldAddListener: function(effect) { + return effect.name && + effect.mode === '{' && + !effect.negate && + effect.kind != 'attribute' + ; + }, + + annotationEffect: function(source, value, effect) { + if (source != effect.value) { + value = this.getPathValue(effect.value); + this._data[effect.value] = value; + } + var calc = effect.negate ? !value : value; + return this._applyEffectValue(calc, effect); + }, + + reflectEffect: function(source) { + this.reflectPropertyToAttribute(source); + }, + + notifyEffect: function(source) { + this._notifyChange(source); + }, + + // Raw effect for extension; effect.function is an actual function + functionEffect: function(source, value, effect, old) { + effect.function.call(this, source, value, effect, old); + }, + + observerEffect: function(source, value, effect, old) { + this[effect.method](value, old); + }, + + complexObserverEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + this[effect.method].apply(this, args); + } + }, + + computeEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + this[effect.property] = this[effect.method].apply(this, args); + } + }, + + annotatedComputationEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + var computedHost = this._rootDataHost || this; + var computedvalue = + computedHost[effect.method].apply(computedHost, args); + this._applyEffectValue(computedvalue, effect); + } + }, + + // path & value are used to fill in wildcard descriptor when effect is + // being called as a result of a path notification + _marshalArgs: function(model, effect, path, value) { + var values = []; + var args = effect.args; + for (var i=0, l=args.length; i<l; i++) { + var arg = args[i]; + var name = arg.name; + var v = arg.structured ? + Polymer.Base.getPathValue(name, model) : model[name]; + if (v === undefined) { + return; + } + if (arg.wildcard) { + // Only send the actual path changed info if the change that + // caused the observer to run matched the wildcard + var baseChanged = (name.indexOf(path + '.') === 0); + var matches = (effect.arg.name.indexOf(name) === 0 && !baseChanged); + values[i] = { + path: matches ? path : name, + value: matches ? value : v, + base: v + }; + } else { + values[i] = v; + } + } + return values; + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/effects.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/effects.html new file mode 100644 index 0000000..0699d6f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/bind/effects.html
@@ -0,0 +1,10 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../case-map.html"> +</head><body><script src="effects-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/case-map-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/case-map-extracted.js new file mode 100644 index 0000000..efa1ea5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/case-map-extracted.js
@@ -0,0 +1,36 @@ + + + Polymer.CaseMap = { + + _caseMap: {}, + + dashToCamelCase: function(dash) { + var mapped = Polymer.CaseMap._caseMap[dash]; + if (mapped) { + return mapped; + } + // TODO(sjmiles): is rejection test actually helping perf? + if (dash.indexOf('-') < 0) { + return Polymer.CaseMap._caseMap[dash] = dash; + } + return Polymer.CaseMap._caseMap[dash] = dash.replace(/-([a-z])/g, + function(m) { + return m[1].toUpperCase(); + } + ); + }, + + camelToDashCase: function(camel) { + var mapped = Polymer.CaseMap._caseMap[camel]; + if (mapped) { + return mapped; + } + return Polymer.CaseMap._caseMap[camel] = camel.replace(/([a-z][A-Z])/g, + function (g) { + return g[0] + '-' + g[1].toLowerCase() + } + ); + } + + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/case-map.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/case-map.html new file mode 100644 index 0000000..fcfad7f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/case-map.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="case-map-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/collection-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/collection-extracted.js new file mode 100644 index 0000000..7654647 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/collection-extracted.js
@@ -0,0 +1,165 @@ + + + Polymer._collections = new WeakMap(); + + Polymer.Collection = function(userArray, noObserve) { + Polymer._collections.set(userArray, this); + this.userArray = userArray; + this.store = userArray.slice(); + this.callbacks = []; + this.debounce = null; + this.map = null; + this.added = []; + this.removed = []; + if (!noObserve) { + Polymer.ArrayObserve.observe(userArray, this.applySplices.bind(this)); + this.initMap(); + } + }; + + Polymer.Collection.prototype = { + constructor: Polymer.Collection, + + initMap: function() { + var map = this.map = new WeakMap(); + var s = this.store; + var u = this.userArray; + for (var i=0; i<s.length; i++) { + var v = s[i]; + if (v) { + switch (typeof v) { + case 'string': + v = s[i] = u[i]= new String(v); + break; + case 'number': + v = s[i] = u[i]= new Number(v); + break; + case 'boolean': + v = s[i] = u[i]= new Boolean(v); + break; + } + map.set(v, i); + } + } + }, + + add: function(item, squelch) { + var key = this.store.push(item) - 1; + if (item != null && this.map) { + this.map.set(item, key); + } + if (!squelch) { + this.added.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + } + return key; + }, + + removeKey: function(key) { + if (this.map) { + this.map.delete(this.store[key]); + } + delete this.store[key]; + this.removed.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + }, + + remove: function(item, squelch) { + var key = this.getKey(item); + if (item != null && this.map) { + this.map.delete(item); + } + delete this.store[key]; + if (!squelch) { + this.removed.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + } + return key; + }, + + notify: function(splices) { + if (!splices) { + splices = [{ + added: this.added, + removed: this.removed + }]; + this.added = []; + this.removed = []; + } + this.callbacks.forEach(function(cb) { + cb(splices); + }, this); + }, + + observe: function(callback) { + this.callbacks.push(callback); + }, + + unobserve: function(callback) { + this.callbacks.splice(this.callbacks.indexOf(callback), 1); + }, + + getKey: function(item) { + if (item != null && this.map) { + return this.map.get(item); + } else { + return this.store.indexOf(item); + } + }, + + getKeys: function() { + return Object.keys(this.store); + }, + + setItem: function(key, value) { + this.store[key] = value; + }, + + getItem: function(key) { + return this.store[key]; + }, + + getItems: function() { + var items = [], store = this.store; + for (var key in store) { + items.push(store[key]); + } + return items; + }, + + applySplices: function(splices) { + var map = this.map; + var keySplices = []; + for (var i=0; i<splices.length; i++) { + var j, o, key, s = splices[i]; + // Removed keys + var removed = []; + for (j=0; j<s.removed.length; j++) { + o = s.removed[j]; + key = this.remove(o, true); + removed.push(key); + } + // Added keys + var added = []; + for (j=0; j<s.addedCount; j++) { + o = this.userArray[s.index + j]; + key = this.add(o, true); + added.push(key); + } + // Record splice + keySplices.push({ + index: s.index, + removed: removed, + added: added + }); + } + this.notify(keySplices); + } + + }; + + Polymer.Collection.get = function(userArray, noObserve) { + return Polymer._collections.get(userArray) + || new Polymer.Collection(userArray, noObserve); + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/collection.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/collection.html new file mode 100644 index 0000000..a7d8aba --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/collection.html
@@ -0,0 +1,12 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="array-observe.html"> +<link rel="import" href="debounce.html"> + +</head><body><script src="collection-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/css-parse-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/css-parse-extracted.js new file mode 100644 index 0000000..4003e669 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/css-parse-extracted.js
@@ -0,0 +1,130 @@ + + +/* + Extremely simple css parser. Intended to be not more than what we need + and definitely not necessarly correct =). +*/ +(function() { + + // given a string of css, return a simple rule tree + function parse(text) { + text = clean(text); + return parseCss(lex(text), text); + } + + // remove stuff we don't care about that may hinder parsing + function clean(cssText) { + return cssText.replace(rx.comments, '').replace(rx.port, ''); + } + + // super simple {...} lexer that returns a node tree + function lex(text) { + var root = {start: 0, end: text.length}; + var n = root; + for (var i=0, s=0, l=text.length; i < l; i++) { + switch (text[i]) { + case OPEN_BRACE: + //console.group(i); + if (!n.rules) { + n.rules = []; + } + var p = n; + var previous = p.rules[p.rules.length-1]; + n = {start: i+1, parent: p, previous: previous}; + p.rules.push(n); + break; + case CLOSE_BRACE: + //console.groupEnd(n.start); + n.end = i+1; + n = n.parent || root; + break; + } + } + return root; + } + + // add selectors/cssText to node tree + function parseCss(node, text) { + var t = text.substring(node.start, node.end-1); + node.cssText = t.trim(); + if (node.parent) { + var ss = node.previous ? node.previous.end : node.parent.start; + t = text.substring(ss, node.start-1); + // TODO(sorvell): ad hoc; make selector include only after last ; + // helps with mixin syntax + t = t.substring(t.lastIndexOf(';')+1); + node.selector = t.trim(); + } + var r$ = node.rules; + if (r$) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + parseCss(r, text); + } + } + return node; + } + + // stringify parsed css. + function stringify(node, text) { + text = text || ''; + // calc rule cssText + var cssText = ''; + if (node.cssText || node.rules) { + var r$ = node.rules; + if (r$ && !hasMixinRules(r$)) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + cssText = stringify(r, cssText); + } + } else { + cssText = removeCustomProps(node.cssText).trim(); + if (cssText) { + cssText = ' ' + cssText + '\n'; + } + } + } + // emit rule iff there is cssText + if (cssText) { + if (node.selector) { + text += node.selector + ' ' + OPEN_BRACE + '\n'; + } + text += cssText; + if (node.selector) { + text += CLOSE_BRACE + '\n\n'; + } + } + return text; + } + + var OPEN_BRACE = '{'; + var CLOSE_BRACE = '}'; + + function hasMixinRules(rules) { + return (rules[0].selector.indexOf(VAR_START) >= 0); + } + + function removeCustomProps(cssText) { + return cssText + .replace(rx.customProp, '') + .replace(rx.mixinProp, '') + .replace(rx.mixinApply, ''); + } + + var VAR_START = '--'; + + // helper regexp's + var rx = { + comments: /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, + port: /@import[^;]*;/gim, + customProp: /--[^;{]*?:[^{};]*?;/gim, + mixinProp: /--[^;{]*?:[^{;]*?{[^}]*?}/gim, + mixinApply: /@mixin[\s]*\([^)]*?\)[\s]*;/gim + }; + + // exports + Polymer.CssParse = { + parse: parse, + stringify: stringify + }; + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/css-parse.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/css-parse.html new file mode 100644 index 0000000..293b831 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/css-parse.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="css-parse-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/debounce-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/debounce-extracted.js new file mode 100644 index 0000000..d35da00 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/debounce-extracted.js
@@ -0,0 +1,59 @@ + + +Polymer.Debounce = (function() { + + // usage + + // invoke cb.call(this) in 100ms, unless the job is re-registered, + // which resets the timer + // + // this.job = this.debounce(this.job, cb, 100) + // + // returns a handle which can be used to re-register a job + + var Async = Polymer.Async; + + var Debouncer = function(context) { + this.context = context; + this.boundComplete = this.complete.bind(this); + }; + + Debouncer.prototype = { + go: function(callback, wait) { + var h; + this.finish = function() { + Async.cancel(h); + }; + h = Async.run(this.boundComplete, wait); + this.callback = callback; + }, + stop: function() { + if (this.finish) { + this.finish(); + this.finish = null; + } + }, + complete: function() { + if (this.finish) { + this.stop(); + this.callback.call(this.context); + } + } + }; + + function debounce(debouncer, callback, wait) { + if (debouncer) { + debouncer.stop(); + } else { + debouncer = new Debouncer(this); + } + debouncer.go(callback, wait); + return debouncer; + } + + // exports + + return debounce; + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/debounce.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/debounce.html new file mode 100644 index 0000000..6214852e --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/debounce.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="debounce-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-api-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-api-extracted.js new file mode 100644 index 0000000..e7dfa41 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-api-extracted.js
@@ -0,0 +1,459 @@ + + + Polymer.DomApi = (function() { + + var Debounce = Polymer.Debounce; + var Settings = Polymer.Settings; + + var nativeInsertBefore = Element.prototype.insertBefore; + var nativeRemoveChild = Element.prototype.removeChild; + var nativeAppendChild = Element.prototype.appendChild; + + var dirtyRoots = []; + + var DomApi = function(node, patch) { + this.node = node; + if (patch) { + this.patch(); + } + }; + + DomApi.prototype = { + + // experimental: support patching selected native api. + patch: function() { + var self = this; + this.node.appendChild = function(node) { + return self.appendChild(node); + }; + this.node.insertBefore = function(node, ref_node) { + return self.insertBefore(node, ref_node); + }; + this.node.removeChild = function(node) { + return self.removeChild(node); + }; + }, + + get childNodes() { + var c$ = getLightChildren(this.node); + return Array.isArray(c$) ? c$ : Array.prototype.slice.call(c$); + }, + + get children() { + return Array.prototype.filter.call(this.childNodes, function(n) { + return (n.nodeType === Node.ELEMENT_NODE); + }); + }, + + get parentNode() { + return this.node.lightParent || this.node.parentNode; + }, + + flush: function() { + for (var i=0, host; i<dirtyRoots.length; i++) { + host = dirtyRoots[i]; + host.flushDebouncer('_distribute'); + } + dirtyRoots = []; + }, + + _lazyDistribute: function(host) { + if (host.shadyRoot) { + host.shadyRoot._distributionClean = false; + } + // TODO(sorvell): optimize debounce so it does less work by default + // and then remove these checks... + // need to dirty distribution once. + if (!host.isDebouncerActive('_distribute')) { + host.debounce('_distribute', host._distributeContent); + dirtyRoots.push(host); + } + }, + + // cases in which we may not be able to just do standard appendChild + // 1. container has a shadyRoot (needsDistribution IFF the shadyRoot + // has an insertion point) + // 2. container is a shadyRoot (don't distribute, instead set + // container to container.host. + // 3. node is <content> (host of container needs distribution) + appendChild: function(node) { + var distributed; + this._removeNodeFromHost(node); + if (this._nodeIsInLogicalTree(this.node)) { + var host = this._hostForNode(this.node); + this._addLogicalInfo(node, this.node, host && host.shadyRoot); + this._addNodeToHost(node); + if (host) { + distributed = this._maybeDistribute(node, this.node, host); + } + } + if (!distributed) { + // if adding to a shadyRoot, add to host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeAppendChild.call(container, node); + } + return node; + }, + + insertBefore: function(node, ref_node) { + if (!ref_node) { + return this.appendChild(node); + } + var distributed; + this._removeNodeFromHost(node); + if (this._nodeIsInLogicalTree(this.node)) { + saveLightChildrenIfNeeded(this.node); + var children = this.childNodes; + var index = children.indexOf(ref_node); + if (index < 0) { + throw Error('The ref_node to be inserted before is not a child ' + + 'of this node'); + } + var host = this._hostForNode(this.node); + this._addLogicalInfo(node, this.node, host && host.shadyRoot, index); + this._addNodeToHost(node); + if (host) { + distributed = this._maybeDistribute(node, this.node, host); + } + } + if (!distributed) { + // if ref_node is <content> replace with first distributed node + ref_node = ref_node.localName === CONTENT ? + this._firstComposedNode(ref_node) : ref_node; + // if adding to a shadyRoot, add to host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeInsertBefore.call(container, node, ref_node); + } + return node; + }, + + /** + Removes the given `node` from the element's `lightChildren`. + This method also performs dom composition. + */ + removeChild: function(node) { + var distributed; + if (this._nodeIsInLogicalTree(this.node)) { + var host = this._hostForNode(this.node); + distributed = this._maybeDistribute(node, this.node, host); + this._removeNodeFromHost(node); + } + if (!distributed) { + // if removing from a shadyRoot, remove form host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeRemoveChild.call(container, node); + } + return node; + }, + + replaceChild: function(node, ref_node) { + this.insertBefore(node, ref_node); + this.removeChild(ref_node); + return node; + }, + + getOwnerRoot: function() { + return this._ownerShadyRootForNode(this.node); + }, + + _ownerShadyRootForNode: function(node) { + if (node._ownerShadyRoot === undefined) { + var root; + if (node._isShadyRoot) { + root = node; + } else { + var parent = Polymer.dom(node).parentNode; + if (parent) { + root = parent._isShadyRoot ? parent : + this._ownerShadyRootForNode(parent); + } else { + root = null; + } + } + node._ownerShadyRoot = root; + } + return node._ownerShadyRoot; + + }, + + _maybeDistribute: function(node, parent, host) { + var nodeNeedsDistribute = this._nodeNeedsDistribution(node); + var distribute = this._parentNeedsDistribution(parent) || + nodeNeedsDistribute; + if (nodeNeedsDistribute) { + this._updateInsertionPoints(host); + } + if (distribute) { + this._lazyDistribute(host); + } + return distribute; + }, + + _updateInsertionPoints: function(host) { + host.shadyRoot._insertionPoints = + factory(host.shadyRoot).querySelectorAll(CONTENT); + }, + + _nodeIsInLogicalTree: function(node) { + return Boolean(node._isShadyRoot || + this._ownerShadyRootForNode(node) || + node.shadyRoot); + }, + + // note: a node is its own host + _hostForNode: function(node) { + var root = node.shadyRoot || (node._isShadyRoot ? + node : this._ownerShadyRootForNode(node)); + return root && root.host; + }, + + _parentNeedsDistribution: function(parent) { + return parent.shadyRoot && hasInsertionPoint(parent.shadyRoot); + }, + + // TODO(sorvell): technically we should check non-fragment nodes for + // <content> children but since this case is assumed to be exceedingly + // rare, we avoid the cost and will address with some specific api + // when the need arises. + _nodeNeedsDistribution: function(node) { + return (node.localName === CONTENT) || + ((node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) && + node.querySelector(CONTENT)); + }, + + _removeNodeFromHost: function(node) { + if (node.lightParent) { + var root = this._ownerShadyRootForNode(node); + if (root) { + root.host._elementRemove(node); + } + this._removeLogicalInfo(node, node.lightParent); + } + this._removeOwnerShadyRoot(node); + }, + + _addNodeToHost: function(node) { + var checkNode = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? + node.firstChild : node; + var root = this._ownerShadyRootForNode(checkNode); + if (root) { + root.host._elementAdd(node); + } + }, + + _addLogicalInfo: function(node, container, root, index) { + saveLightChildrenIfNeeded(container); + var children = factory(container).childNodes; + index = index === undefined ? children.length : index; + // handle document fragments + if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { + var n = node.firstChild; + while (n) { + children.splice(index++, 0, n); + n.lightParent = container; + n = n.nextSibling; + } + } else { + children.splice(index, 0, node); + node.lightParent = container; + } + }, + + // NOTE: in general, we expect contents of the lists here to be small-ish + // and therefore indexOf to be nbd. Other optimizations can be made + // for larger lists (linked list) + _removeLogicalInfo: function(node, container) { + var children = factory(container).childNodes; + var index = children.indexOf(node); + if ((index < 0) || (container !== node.lightParent)) { + throw Error('The node to be removed is not a child of this node'); + } + children.splice(index, 1); + node.lightParent = null; + }, + + _removeOwnerShadyRoot: function(node) { + // TODO(sorvell): need to clear any children of element? + node._ownerShadyRoot = undefined; + }, + + // TODO(sorvell): This will fail if distribution that affects this + // question is pending; this is expected to be exceedingly rare, but if + // the issue comes up, we can force a flush in this case. + _firstComposedNode: function(content) { + var n$ = factory(content).getDistributedNodes(); + for (var i=0, l=n$.length, n, p$; (i<l) && (n=n$[i]); i++) { + p$ = factory(n).getDestinationInsertionPoints(); + // means that we're composed to this spot. + if (p$[p$.length-1] === content) { + return n; + } + } + }, + + // TODO(sorvell): consider doing native QSA and filtering results. + querySelector: function(selector) { + return this.querySelectorAll(selector)[0]; + }, + + querySelectorAll: function(selector) { + return this._query(function(n) { + return matchesSelector.call(n, selector); + }, this.node); + }, + + _query: function(matcher, node) { + var list = []; + this._queryElements(factory(node).childNodes, matcher, list); + return list; + }, + + _queryElements: function(elements, matcher, list) { + for (var i=0, l=elements.length, c; (i<l) && (c=elements[i]); i++) { + if (c.nodeType === Node.ELEMENT_NODE) { + this._queryElement(c, matcher, list); + } + } + }, + + _queryElement: function(node, matcher, list) { + if (matcher(node)) { + list.push(node); + } + this._queryElements(factory(node).childNodes, matcher, list); + }, + + getDestinationInsertionPoints: function() { + return this.node._destinationInsertionPoints || []; + }, + + getDistributedNodes: function() { + return this.node._distributedNodes || []; + }, + + /* + Returns a list of nodes distributed within this element. These can be + dom children or elements distributed to children that are insertion + points. + */ + queryDistributedElements: function(selector) { + var c$ = this.childNodes; + var list = []; + this._distributedFilter(selector, c$, list); + for (var i=0, l=c$.length, c; (i<l) && (c=c$[i]); i++) { + if (c.localName === CONTENT) { + this._distributedFilter(selector, factory(c).getDistributedNodes(), + list); + } + } + return list; + }, + + _distributedFilter: function(selector, list, results) { + results = results || []; + for (var i=0, l=list.length, d; (i<l) && (d=list[i]); i++) { + if ((d.nodeType === Node.ELEMENT_NODE) && + (d.localName !== CONTENT) && + matchesSelector.call(d, selector)) { + results.push(d); + } + } + return results; + } + + }; + + if (Settings.useShadow) { + + DomApi.prototype.querySelectorAll = function(selector) { + return Array.prototype.slice.call(this.node.querySelectorAll(selector)); + }; + + DomApi.prototype.patch = function() {}; + + DomApi.prototype.getOwnerRoot = function() { + var n = this.node; + while (n) { + if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) { + return n; + } + n = n.parentNode; + } + }; + + DomApi.prototype.getDestinationInsertionPoints = function() { + var n$ = this.node.getDestinationInsertionPoints(); + return n$ ? Array.prototype.slice.call(n$) : []; + }; + + DomApi.prototype.getDistributedNodes = function() { + var n$ = this.node.getDistributedNodes(); + return n$ ? Array.prototype.slice.call(n$) : []; + }; + + + } + + var CONTENT = 'content'; + + var factory = function(node, patch) { + node = node || document; + if (!node.__domApi) { + node.__domApi = new DomApi(node, patch); + } + return node.__domApi; + }; + + Polymer.dom = function(obj, patch) { + if (obj instanceof Event) { + return Polymer.EventApi.factory(obj); + } else { + return factory(obj, patch); + } + }; + + // make flush available directly. + Polymer.dom.flush = DomApi.prototype.flush; + + function getLightChildren(node) { + var children = node.lightChildren; + return children ? children : node.childNodes; + } + + function saveLightChildrenIfNeeded(node) { + // Capture the list of light children. It's important to do this before we + // start transforming the DOM into "rendered" state. + // + // Children may be added to this list dynamically. It will be treated as the + // source of truth for the light children of the element. This element's + // actual children will be treated as the rendered state once lightChildren + // is populated. + if (!node.lightChildren) { + var children = []; + for (var child = node.firstChild; child; child = child.nextSibling) { + children.push(child); + child.lightParent = child.lightParent || node; + } + node.lightChildren = children; + } + } + + function hasInsertionPoint(root) { + return Boolean(root._insertionPoints.length); + } + + var p = Element.prototype; + var matchesSelector = p.matches || p.matchesSelector || + p.mozMatchesSelector || p.msMatchesSelector || + p.oMatchesSelector || p.webkitMatchesSelector; + + return { + getLightChildren: getLightChildren, + saveLightChildrenIfNeeded: saveLightChildrenIfNeeded, + matchesSelector: matchesSelector, + hasInsertionPoint: hasInsertionPoint, + factory: factory + }; + + })(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-api.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-api.html new file mode 100644 index 0000000..e4002e05 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-api.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="settings.html"> +<link rel="import" href="event-api.html"> +</head><body><script src="dom-api-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-module-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-module-extracted.js new file mode 100644 index 0000000..d4a8715e --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-module-extracted.js
@@ -0,0 +1,67 @@ + + +(function() { + + var modules = {}; + + var DomModule = function() { + return document.createElement('dom-module'); + }; + + DomModule.prototype = Object.create(HTMLElement.prototype); + + DomModule.prototype.constructor = DomModule; + + DomModule.prototype.createdCallback = function() { + var id = this.id || this.getAttribute('name') || this.getAttribute('is'); + if (id) { + this.id = id; + modules[id] = this; + } + }; + + DomModule.prototype.import = function(id, slctr) { + var m = modules[id]; + if (!m) { + // If polyfilling, a script can run before a dom-module element + // is upgraded. We force the containing document to upgrade + // and try again to workaround this polyfill limitation. + forceDocumentUpgrade(); + m = modules[id]; + } + if (m && slctr) { + m = m.querySelector(slctr); + } + return m; + }; + + // NOTE: HTMLImports polyfill does not + // block scripts on upgrading elements. However, we want to ensure that + // any dom-module in the tree is available prior to a subsequent script + // processing. + // Therefore, we force any dom-modules in the tree to upgrade when dom-module + // is registered by temporarily setting CE polyfill to crawl the entire + // imports tree. (Note: this should only upgrade any imports that have been + // loaded by this point. In addition the HTMLImports polyfill should be + // changed to upgrade elements prior to running any scripts.) + var cePolyfill = window.CustomElements && !CustomElements.useNative; + if (cePolyfill) { + var ready = CustomElements.ready; + CustomElements.ready = true; + } + document.registerElement('dom-module', DomModule); + if (cePolyfill) { + CustomElements.ready = ready; + } + + function forceDocumentUpgrade() { + if (cePolyfill) { + var script = document._currentScript || document.currentScript; + if (script) { + CustomElements.upgradeAll(script.ownerDocument); + } + } + } + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-module.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-module.html new file mode 100644 index 0000000..27f79ab0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/dom-module.html
@@ -0,0 +1 @@ +<html><head></head><body><script src="dom-module-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/event-api-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/event-api-extracted.js new file mode 100644 index 0000000..9c46b79 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/event-api-extracted.js
@@ -0,0 +1,81 @@ + + + Polymer.EventApi = (function() { + + var Settings = Polymer.Settings; + + var EventApi = function(event) { + this.event = event; + }; + + if (Settings.useShadow) { + + EventApi.prototype = { + + get rootTarget() { + return this.event.path[0]; + }, + + get localTarget() { + return this.event.target; + }, + + get path() { + return this.event.path; + } + + }; + + } else { + + EventApi.prototype = { + + get rootTarget() { + return this.event.target; + }, + + get localTarget() { + var current = this.event.currentTarget; + var currentRoot = current && Polymer.dom(current).getOwnerRoot(); + var p$ = this.path; + for (var i=0; i < p$.length; i++) { + if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) { + return p$[i]; + } + } + }, + + // TODO(sorvell): simulate event.path. This probably incorrect for + // non-bubbling events. + get path() { + if (!this.event._path) { + var path = []; + var o = this.rootTarget; + while (o) { + path.push(o); + o = Polymer.dom(o).parentNode || o.host; + } + // event path includes window in most recent native implementations + path.push(window); + this.event._path = path; + } + return this.event._path; + } + + }; + + } + + var factory = function(event) { + if (!event.__eventApi) { + event.__eventApi = new EventApi(event); + } + return event.__eventApi; + }; + + return { + factory: factory + }; + + })(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/event-api.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/event-api.html new file mode 100644 index 0000000..c1c7f3f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/event-api.html
@@ -0,0 +1,10 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="settings.html"> +</head><body><script src="event-api-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/focus-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/focus-extracted.js new file mode 100644 index 0000000..20b506f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/focus-extracted.js
@@ -0,0 +1,12 @@ + + + Base._addFeature({ + + init: function() { + if (this.focusable) { + this.tabIndex = 0; + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/focus.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/focus.html new file mode 100644 index 0000000..ca05c5e4 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/focus.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="focus-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/gestures.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/gestures.html new file mode 100644 index 0000000..fd3f95f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/gestures.html
@@ -0,0 +1 @@ +<script src="../../polymer-gestures/polymer-gestures.js"></script>
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/log-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/log-extracted.js new file mode 100644 index 0000000..7147e47c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/log-extracted.js
@@ -0,0 +1,11 @@ + + + Base._addFeature({ + log: function() { + var args = Array.prototype.slice.call(arguments, 0); + args[0] = '[%s]: ' + args[0]; + args.splice(1, 0, this.localName); + console.log.apply(console, args); + } + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/log.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/log.html new file mode 100644 index 0000000..8be07a6 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/log.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="log-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/sinspect-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/sinspect-extracted.js new file mode 100644 index 0000000..ef13b0c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/sinspect-extracted.js
@@ -0,0 +1,225 @@ + + + (function(scope) { + + scope = scope || (window.Inspector = {}); + + var inspector; + + window.sinspect = function(inNode, inProxy) { + if (!inspector) { + inspector = window.open('', 'ShadowDOM Inspector', null, true); + inspector.document.write(inspectorHTML); + //inspector.document.close(); + inspector.api = { + shadowize: shadowize + }; + } + inspect(inNode || wrap(document.body), inProxy); + }; + + var inspectorHTML = [ + '<!DOCTYPE html>', + '<html>', + ' <head>', + ' <title>ShadowDOM Inspector</title>', + ' <style>', + ' body {', + ' }', + ' pre {', + ' font: 9pt "Courier New", monospace;', + ' line-height: 1.5em;', + ' }', + ' tag {', + ' color: purple;', + ' }', + ' ul {', + ' margin: 0;', + ' padding: 0;', + ' list-style: none;', + ' }', + ' li {', + ' display: inline-block;', + ' background-color: #f1f1f1;', + ' padding: 4px 6px;', + ' border-radius: 4px;', + ' margin-right: 4px;', + ' }', + ' button {', + ' display: inline-block;', + ' color: purple;', + ' font-weight: bold;', + ' background: none;', + ' border: none;', + ' outline: none;', + ' padding: 0;', + ' margin: 0;', + ' }', + ' </style>', + ' </head>', + ' <body>', + ' <ul id="crumbs">', + ' </ul>', + ' <div id="tree"></div>', + ' </body>', + '</html>' + ].join('\n'); + + var crumbs = []; + + var displayCrumbs = function() { + // alias our document + var d = inspector.document; + // get crumbbar + var cb = d.querySelector('#crumbs'); + // clear crumbs + cb.textContent = ''; + // build new crumbs + for (var i=0, c; c=crumbs[i]; i++) { + var a = d.createElement('a'); + a.href = '#'; + a.textContent = c.localName; + a.idx = i; + a.onclick = function(event) { + var c; + while (crumbs.length > this.idx) { + c = crumbs.pop(); + } + inspect(c.shadow || c, c); + event.preventDefault(); + }; + cb.appendChild(d.createElement('li')).appendChild(a); + } + }; + + var inspect = function(inNode, inProxy) { + // alias our document + var d = inspector.document; + // reset list of drillable nodes + drillable = []; + // memoize our crumb proxy + var proxy = inProxy || inNode; + crumbs.push(proxy); + // update crumbs + displayCrumbs(); + // reflect local tree + d.body.querySelector('#tree').innerHTML = + '<pre>' + output(inNode, getLocalNodes(inNode)) + '</pre>'; + }; + + var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); + + var blacklisted = {STYLE:1, SCRIPT:1, "#comment": 1, TEMPLATE: 1}; + var blacklist = function(inNode) { + return blacklisted[inNode.nodeName]; + }; + + var output = function(inNode, inChildNodes, inIndent) { + if (blacklist(inNode)) { + return ''; + } + var indent = inIndent || ''; + if (inNode.localName || inNode.domRoot) { + var name = inNode.localName || ROOT_NAME; + //inChildNodes = ShadowDOM.localNodes(inNode); + var info = indent + describe(inNode); + // if only textNodes + // TODO(sjmiles): make correct for ShadowDOM + /*if (!inNode.children.length && inNode.localName !== 'content' && inNode.localName !== 'shadow') { + info += catTextContent(inChildNodes); + } else*/ { + // TODO(sjmiles): native <shadow> has no reference to its projection + if (name == 'content' /*|| name == 'shadow'*/) { + inChildNodes = getDistributedNodes(inNode); + } + info += '<br/>'; + var ind = indent + ' '; + //console.group('output ' + inNode.localName); + //console.log(inChildNodes); + forEach(inChildNodes, function(n) { + info += output(n, getLightNodes(n), ind); + }); + //console.groupEnd('output ' + inNode.localName); + info += indent; + } + if (!({br:1}[name])) { + info += '<tag></' + name + '></tag>'; + info += '<br/>'; + } + } else { + var text = inNode.textContent.trim(); + info = text ? indent + '"' + text + '"' + '<br/>' : ''; + } + return info; + }; + + var catTextContent = function(inChildNodes) { + var info = ''; + forEach(inChildNodes, function(n) { + info += n.textContent.trim(); + }); + return info; + }; + + var drillable = []; + + var describe = function(inNode) { + var tag = '<tag>' + '<'; + var name = inNode.localName || ROOT_NAME; + if (hasRoot(inNode)) { + tag += '<button idx="' + drillable.length + + '" onclick="api.shadowize.call(this)">' + name + '</button>'; + drillable.push(inNode); + } else { + tag += name || ROOT_NAME; + } + if (inNode.attributes) { + forEach(inNode.attributes, function(a) { + tag += ' ' + a.name + (a.value ? '="' + a.value + '"' : ''); + }); + } + tag += '>'+ '</tag>'; + return tag; + }; + + // remote api + + shadowize = function() { + var idx = Number(this.attributes.idx.value); + //alert(idx); + var node = drillable[idx]; + if (node) { + inspect(node, node) + } else { + console.log("bad shadowize node"); + console.dir(this); + } + }; + + // util + + var ROOT_NAME = 'local-root'; + + function hasRoot(node) { + return (node.shadyRoot || node.shadowRoot); + } + + function getLocalNodes(n) { + return Polymer.dom.childNodes(n.root); + } + + function getLightNodes(n) { + return Polymer.dom.childNodes(n); + } + + function getDistributedNodes(node) { + Polymer.dom.distributedNodes(node); + } + + + // export + + scope.output = output; + +})(window.Inspector); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/sinspect.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/sinspect.html new file mode 100644 index 0000000..b67c28d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/sinspect.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="sinspect-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-auditor-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-auditor-extracted.js new file mode 100644 index 0000000..3255a5e --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-auditor-extracted.js
@@ -0,0 +1,122 @@ + +addEventListener('WebComponentsReady', function() { + + // given a list of elements, produce a report of rules that + // match those elements. + var auditor = { + + matchesForDocument: function(elements) { + var info = []; + this.documentSheets.forEach(function(sheet) { + var list = this.matchesForSheet(sheet, elements); + if (list.length) { + info.push({sheet: sheet, rules: list}); + } + }, this); + return info; + }, + + // TODO(sorvell): support stylesheets inside HTMLImports + documentSheets: Array.prototype.filter.call(document.styleSheets, + function(sheet) { + return !sheet.ownerNode.hasAttribute('scope'); + } + ), + + matchesForSheet: function(sheet, elements) { + var info = []; + Array.prototype.forEach.call(sheet.cssRules, function(rule) { + var list = this.matchesForRule(rule, elements); + if (list.length) { + info.push({selector: rule.selectorText, elements: list}); + } + }, this); + return info; + }, + + matchesForRule: function(rule, list) { + var info = []; + list.forEach(function(i) { + var elements = i.elements.filter(function(e) { + return matchesSelector.call(e, rule.selectorText); + }); + if (elements.length) { + info.push({host: i.host, elements: elements}); + } + }); + return info; + } + + }; + + var p = Element.prototype; + var matchesSelector = p.matches || p.matchesSelector || + p.mozMatchesSelector || p.msMatchesSelector || + p.oMatchesSelector || p.webkitMatchesSelector; + + + // crawl the document and return a list of custom elements with shadyRoots + // and their scoped contents + var crawler = { + // list of elements: array of {host, elements} + list: function() { + var list = []; + var elements = this.elementsWithShadyRoot(); + elements.forEach(function(e) { + list.push({host: e, elements: this.elementsInsideShadyRoot(e)}); + }, this); + return list; + }, + + elementsWithShadyRoot: function() { + var e$ = Polymer.dom(document).querySelectorAll('*'); + return this.filterElementsWithRoots(e$); + }, + + elementsInsideShadyRoot: function(e) { + var e$ = Polymer.dom(e.root || e).querySelectorAll('*'); + var roots = this.filterElementsWithRoots(e$); + roots.forEach(function(e) { + e$ = e$.concat(this.elementsInsideShadyRoot(e)); + }, this); + return e$; + }, + + filterElementsWithRoots: function(elements) { + return elements.filter(function(e) { + return e.shadyRoot; + }); + } + + }; + + // dump an auditor report + var logger = { + + dump: function(log) { + log.forEach(function(l) { + console.group(l.sheet.ownerNode); + this.dumpRules(l.rules); + console.groupEnd(l.sheet.ownerNode); + }, this); + }, + + dumpRules: function(rules) { + rules.forEach(function(i) { + console.group(i.selector); + console.log(i.elements); + console.groupEnd(i.selector); + }); + } + + }; + + // pruduces a style audit and reports results on the console. + function audit() { + var report = auditor.matchesForDocument(crawler.list()); + logger.dump(report); + } + + audit(); + +});
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-auditor.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-auditor.html new file mode 100644 index 0000000..7cf26228 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-auditor.html
@@ -0,0 +1 @@ +<html><head></head><body><script src="style-auditor-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-protector-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-protector-extracted.js new file mode 100644 index 0000000..c47726f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-protector-extracted.js
@@ -0,0 +1,50 @@ + +(function() { + + var transformer = document.createElement('style', 'x-style'); + + var styleProtector = { + + scopeDocumentSheets: function() { + this.scopeSheets(this.getSheetsToScope()); + }, + + getSheetsToScope: function() { + var s$ = document.styleSheets; + return Array.prototype.filter.call(s$, function(s) { + return s.ownerNode.hasAttribute(this.SCOPE_ATTR); + }, this); + }, + + scopeSheets: function(sheets) { + for (var i=0, l=sheets.length, s; (i<l) && (s=sheets[i]); i++) { + this.scopeSheet(s); + } + }, + + scopeSheet: function(sheet) { + var owner = sheet.ownerNode; + var cssText = transformer.scopeCssText(this.rulesToCss(sheet.cssRules)); + if (owner.localName === 'link') { + var style = document.createElement('style'); + style.textContent = cssText; + owner.parentNode.insertBefore(style, owner); + owner.parentNode.removeChild(owner); + } else { + owner.textContent = cssText; + } + }, + + rulesToCss: function(cssRules) { + for (var i=0, css=[]; i < cssRules.length; i++) { + css.push(cssRules[i].cssText); + } + return css.join('\n\n'); + }, + + SCOPE_ATTR: 'needs-scoping' + }; + + addEventListener('DOMContentLoaded', styleProtector.scopeDocumentSheets()); + +})();
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-protector.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-protector.html new file mode 100644 index 0000000..fd61424d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/expr/style-protector.html
@@ -0,0 +1,2 @@ +<html><head><link rel="import" href="../lib/x-style.html"> +</head><body><script src="style-protector-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/gestures-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/gestures-extracted.js new file mode 100644 index 0000000..6eb6f7d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/gestures-extracted.js
@@ -0,0 +1,274 @@ + + +(function(scope) { + + 'use strict'; + + var async = scope.Base.async; + + var Gestures = { + gestures: {}, + + // automate the event listeners for the native events + // TODO(dfreedm): add a way to remove handlers. + add: function(evType, node, handler) { + // listen for events in order to "recognize" this event + var g = this.gestures[evType]; + var gn = '_' + evType; + var info = {started: false, abortTrack: false, oneshot: false}; + if (g && !node[gn]) { + if (g.touchaction) { + this._setupTouchAction(node, g.touchaction, info); + } + for (var i = 0, n, sn, fn; i < g.deps.length; i++) { + n = g.deps[i]; + fn = g[n].bind(g, info); + sn = '_' + evType + '-' + n; + // store the handler on the node for future removal + node[sn] = fn; + node.addEventListener(n, fn); + } + node[gn] = 0; + } + // listen for the gesture event + node[gn]++; + node.addEventListener(evType, handler); + }, + + remove: function(evType, node, handler) { + var g = this.gestures[evType]; + var gn = '_' + evType; + if (g && node[gn]) { + for (var i = 0, n, sn, fn; i < g.deps.length; i++) { + n = g.deps[i]; + sn = '_' + evType + '-' + n; + fn = node[sn]; + if (fn){ + node.removeEventListener(n, fn); + // remove stored handler to allow GC + node[sn] = undefined; + } + } + node[gn] = node[gn] ? (node[gn] - 1) : 0; + node.removeEventListener(evType, handler); + } + }, + + register: function(recog) { + this.gestures[recog.name] = recog; + }, + + // touch will make synthetic mouse events + // preventDefault on touchend will cancel them, + // but this breaks <input> focus and link clicks + // Disabling "mouse" handlers for 500ms is enough + + _cancelFunction: null, + + cancelNextClick: function(timeout) { + if (!this._cancelFunction) { + timeout = timeout || 500; + var self = this; + var reset = function() { + var cfn = self._cancelFunction; + if (cfn) { + clearTimeout(cfn.id); + document.removeEventListener('click', cfn, true); + self._cancelFunction = null; + } + }; + var canceller = function(e) { + e.tapPrevented = true; + reset(); + }; + canceller.id = setTimeout(reset, timeout); + this._cancelFunction = canceller; + document.addEventListener('click', canceller, true); + } + }, + + // try to use the native touch-action, if it exists + _hasNativeTA: typeof document.head.style.touchAction === 'string', + + // set scrolling direction on node to check later on first move + // must call this before adding event listeners! + setTouchAction: function(node, value) { + if (this._hasNativeTA) { + node.style.touchAction = value; + } + node.touchAction = value; + }, + + _setupTouchAction: function(node, value, info) { + // reuse custom value on node if set + var ta = node.touchAction; + value = ta || value; + // set an anchor point to see how far first move is + node.addEventListener('touchstart', function(e) { + var t = e.changedTouches[0]; + info.initialTouch = {x: t.clientX, y: t.clientY}; + info.abortTrack = false; + info.oneshot = false; + }); + node.addEventListener('touchmove', function(e) { + // only run this once + if (info.oneshot) { + return; + } + info.oneshot = true; + // "none" means always track + if (value === 'none') { + return; + } + // "auto" is default, always scroll + // bail-out if touch-action did its job + // the touchevent is non-cancelable if the page/area is scrolling + if (value === 'auto' || !value || (ta && !e.cancelable)) { + info.abortTrack = true; + return; + } + // check first move direction + // unfortunately, we can only make the decision in the first move, + // so we have to use whatever values are available. + // Typically, this can be a really small amount, :( + var t = e.changedTouches[0]; + var x = t.clientX, y = t.clientY; + var dx = Math.abs(info.initialTouch.x - x); + var dy = Math.abs(info.initialTouch.y - y); + // scroll in x axis, abort track if we move more in x direction + if (value === 'pan-x') { + info.abortTrack = dx >= dy; + // scroll in y axis, abort track if we move more in y direction + } else if (value === 'pan-y') { + info.abortTrack = dy >= dx; + } + }); + }, + + fire: function(target, type, detail, bubbles, cancelable) { + return target.dispatchEvent( + new CustomEvent(type, { + detail: detail, + bubbles: bubbles, + cancelable: cancelable + }) + ); + } + + }; + + Gestures.register({ + name: 'track', + touchaction: 'none', + deps: ['mousedown', 'touchmove', 'touchend'], + + mousedown: function(info, e) { + var t = e.currentTarget; + var self = this; + var movefn = function movefn(e, up) { + if (!info.tracking && !up) { + // set up tap prevention + Gestures.cancelNextClick(); + } + // first move is 'start', subsequent moves are 'move', mouseup is 'end' + var state = up ? 'end' : (!info.started ? 'start' : 'move'); + info.started = true; + self.fire(t, e, state); + e.preventDefault(); + }; + var upfn = function upfn(e) { + // call mousemove function with 'end' state + movefn(e, true); + info.started = false; + // remove the temporary listeners + document.removeEventListener('mousemove', movefn); + document.removeEventListener('mouseup', upfn); + }; + // add temporary document listeners as mouse retargets + document.addEventListener('mousemove', movefn); + document.addEventListener('mouseup', upfn); + }, + + touchmove: function(info, e) { + var t = e.currentTarget; + var ct = e.changedTouches[0]; + // if track was aborted, stop tracking + if (info.abortTrack) { + return; + } + e.preventDefault(); + // the first track event is sent after some hysteresis with touchmove. + // Use `started` state variable to differentiate the "first" move from + // the rest to make track.state == 'start' + // first move is 'start', subsequent moves are 'move' + var state = !info.started ? 'start' : 'move'; + info.started = true; + this.fire(t, ct, state); + }, + + touchend: function(info, e) { + var t = e.currentTarget; + var ct = e.changedTouches[0]; + // only trackend if track was started and not aborted + if (info.started && !info.abortTrack) { + // reset started state on up + info.started = false; + var ne = this.fire(t, ct, 'end'); + // iff tracking, always prevent tap + e.tapPrevented = true; + } + }, + + fire: function(target, touch, state) { + return Gestures.fire(target, 'track', { + state: state, + x: touch.clientX, + y: touch.clientY + }); + } + + }); + + // dispatch a *bubbling* "tap" only at the node that is the target of the + // generating event. + // dispatch *synchronously* so that we can implement prevention of native + // actions like links being followed. + // + // TODO(dfreedm): a tap should not occur when there's too much movement. + // Right now, a tap can occur when a touchend happens very far from the + // generating touch. + // This *should* obviate the need for tapPrevented via track. + Gestures.register({ + name: 'tap', + deps: ['click', 'touchend'], + + click: function(info, e) { + this.forward(e); + }, + + touchend: function(info, e) { + Gestures.cancelNextClick(); + this.forward(e); + }, + + forward: function(e) { + // prevent taps from being generated from events that have been + // canceled (e.g. via cancelNextClick) or already handled via + // a listener lower in the tree. + if (!e.tapPrevented) { + e.tapPrevented = true; + this.fire(e.target); + } + }, + + // fire a bubbling event from the generating target. + fire: function(target) { + Gestures.fire(target, 'tap', {}, true); + } + + }); + + scope.Gestures = Gestures; + +})(Polymer); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/gestures.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/gestures.html new file mode 100644 index 0000000..ced40ae0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/gestures.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="gestures-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/lang-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/lang-extracted.js new file mode 100644 index 0000000..6c469eb --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/lang-extracted.js
@@ -0,0 +1,11 @@ + + + // a tiny bit of sugar for `document.currentScript.ownerDocument` + Object.defineProperty(window, 'currentImport', { + enumerable: true, + configurable: true, + get: function() { + return (document._currentScript || document.currentScript).ownerDocument; + } + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/lang.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/lang.html new file mode 100644 index 0000000..e0c431b76 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/lang.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="lang-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/module-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/module-extracted.js new file mode 100644 index 0000000..7fab9d7 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/module-extracted.js
@@ -0,0 +1,46 @@ + +(function(scope) { + + function withDependencies(task, depends) { + depends = depends || []; + if (!depends.map) { + depends = [depends]; + } + return task.apply(this, depends.map(marshal)); + } + + function module(name, dependsOrFactory, moduleFactory) { + var module = null; + switch (arguments.length) { + case 0: + return; + case 2: + // dependsOrFactory is `factory` in this case + module = dependsOrFactory.apply(this); + break; + default: + // dependsOrFactory is `depends` in this case + module = withDependencies(moduleFactory, dependsOrFactory); + break; + } + modules[name] = module; + }; + + function marshal(name) { + return modules[name]; + } + + var modules = {}; + + var using = function(depends, task) { + withDependencies(task, depends); + }; + + // exports + + scope.marshal = marshal; + // `module` confuses commonjs detectors + scope.modulate = module; + scope.using = using; + +})(this);
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/module.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/module.html new file mode 100644 index 0000000..dae98853 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/module.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="module-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/polymer-bootstrap-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/polymer-bootstrap-extracted.js new file mode 100644 index 0000000..a9190b45 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/polymer-bootstrap-extracted.js
@@ -0,0 +1,67 @@ + + + // until ES6 modules become standard, we follow Occam and simply stake out + // a global namespace + + // Polymer is a Function, but of course this is also an Object, so we + // hang various other objects off of Polymer.* + (function() { + var userPolymer = window.Polymer; + + window.Polymer = function(prototype) { + var ctor = desugar(prototype); + // native Custom Elements treats 'undefined' extends property + // as valued, the property must not exist to be ignored + var options = { + prototype: ctor.prototype + }; + if (prototype.extends) { + options.extends = prototype.extends; + } + Polymer.telemetry._registrate(prototype); + document.registerElement(prototype.is, options); + return ctor; + }; + + var desugar = function(prototype) { + prototype = Polymer.Base.chainObject(prototype, Polymer.Base); + prototype.registerCallback(); + return prototype.constructor; + }; + + window.Polymer = Polymer; + + if (userPolymer) { + for (var i in userPolymer) { + Polymer[i] = userPolymer[i]; + } + } + + Polymer.Class = desugar; + + })(); + /* + // Raw usage + [ctor =] Polymer.Class(prototype); + document.registerElement(name, ctor); + + // Simplified usage + [ctor = ] Polymer(prototype); + */ + + // telemetry: statistics, logging, and debug + + Polymer.telemetry = { + registrations: [], + _regLog: function(prototype) { + console.log('[' + prototype.is + ']: registered') + }, + _registrate: function(prototype) { + this.registrations.push(prototype); + Polymer.log && this._regLog(prototype); + }, + dumpRegistrations: function() { + this.registrations.forEach(this._regLog); + } + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/polymer-bootstrap.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/polymer-bootstrap.html new file mode 100644 index 0000000..3990a15 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/polymer-bootstrap.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="polymer-bootstrap-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/resolve-url-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/resolve-url-extracted.js new file mode 100644 index 0000000..9013ed5 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/resolve-url-extracted.js
@@ -0,0 +1,72 @@ + + + (function() { + + // path fixup for urls in cssText that's expected to + // come from a given ownerDocument + function resolveCss(cssText, ownerDocument) { + return cssText.replace(CSS_URL_RX, function(m, pre, url, post) { + return pre + '\'' + + resolve(url.replace(/["']/g, ''), ownerDocument) + + '\'' + post; + }); + } + + // url fixup for urls in an element's attributes made relative to + // ownerDoc's base url + function resolveAttrs(element, ownerDocument) { + for (var name in URL_ATTRS) { + var a$ = URL_ATTRS[name]; + for (var i=0, l=a$.length, a, at, v; (i<l) && (a=a$[i]); i++) { + if (name === '*' || element.localName === name) { + at = element.attributes[a]; + v = at && at.value; + if (v && (v.search(BINDING_RX) < 0)) { + at.value = (a === 'style') ? + resolveCss(v, ownerDocument) : + resolve(v, ownerDocument); + } + } + } + } + } + + function resolve(url, ownerDocument) { + var resolver = getUrlResolver(ownerDocument); + resolver.href = url; + return resolver.href || url; + } + + var tempDoc; + var tempDocBase; + function resolveUrl(url, baseUri) { + if (!tempDoc) { + tempDoc = document.implementation.createHTMLDocument('temp'); + tempDocBase = tempDoc.createElement('base'); + tempDoc.head.appendChild(tempDocBase); + } + tempDocBase.href = baseUri; + return resolve(url, tempDoc); + } + + function getUrlResolver(ownerDocument) { + return ownerDocument.__urlResolver || + (ownerDocument.__urlResolver = ownerDocument.createElement('a')); + } + + var CSS_URL_RX = /(url\()([^)]*)(\))/g; + var URL_ATTRS = { + '*': ['href', 'src', 'style', 'url'], + form: ['action'] + }; + var BINDING_RX = /\{\{|\[\[/; + + // exports + Polymer.ResolveUrl = { + resolveCss: resolveCss, + resolveAttrs: resolveAttrs, + resolveUrl: resolveUrl + }; + + })(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/resolve-url.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/resolve-url.html new file mode 100644 index 0000000..01d3d8e --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/resolve-url.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="resolve-url-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/settings-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/settings-extracted.js new file mode 100644 index 0000000..da738a4b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/settings-extracted.js
@@ -0,0 +1,42 @@ + + + Polymer = { + Settings: (function() { + // NOTE: Users must currently opt into using ShadowDOM. They do so by doing: + // Polymer = {dom: 'shadow'}; + // TODO(sorvell): Decide if this should be auto-use when available. + // TODO(sorvell): if SD is auto-use, then the flag above should be something + // like: Polymer = {dom: 'shady'} + + // via Polymer object + var user = window.Polymer || {}; + + // via url + location.search.slice(1).split('&').forEach(function(o) { + o = o.split('='); + o[0] && (user[o[0]] = o[1] || true); + }); + + var wantShadow = (user.dom === 'shadow'); + var hasShadow = Boolean(Element.prototype.createShadowRoot); + var nativeShadow = hasShadow && !window.ShadowDOMPolyfill; + var useShadow = wantShadow && hasShadow; + + var hasNativeImports = Boolean('import' in document.createElement('link')); + var useNativeImports = hasNativeImports; + + var useNativeCustomElements = (!window.CustomElements || + window.CustomElements.useNative); + + return { + wantShadow: wantShadow, + hasShadow: hasShadow, + nativeShadow: nativeShadow, + useShadow: useShadow, + useNativeShadow: useShadow && nativeShadow, + useNativeImports: useNativeImports, + useNativeCustomElements: useNativeCustomElements + }; + })() + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/settings.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/settings.html new file mode 100644 index 0000000..ee60b7a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/settings.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="settings-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-defaults-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-defaults-extracted.js new file mode 100644 index 0000000..e28fb37f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-defaults-extracted.js
@@ -0,0 +1,21 @@ + + + (function() { + + var defaultSheet = document.createElement('style'); + + function applyCss(cssText) { + defaultSheet.textContent += cssText; + defaultSheet.__cssRules = + Polymer.StyleUtil.parser.parse(defaultSheet.textContent); + } + + applyCss(''); + + // exports + Polymer.StyleDefaults = { + applyCss: applyCss, + defaultSheet: defaultSheet + }; + + })();
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-defaults.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-defaults.html new file mode 100644 index 0000000..e1f7173 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-defaults.html
@@ -0,0 +1,10 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="style-util.html"> +</head><body><script src="style-defaults-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-transformer-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-transformer-extracted.js new file mode 100644 index 0000000..ef62f594 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-transformer-extracted.js
@@ -0,0 +1,200 @@ + + + (function() { + + /* Transforms ShadowDOM styling into ShadyDOM styling + + * scoping: + + * elements in scope get scoping selector class="x-foo-scope" + * selectors re-written as follows: + + div button -> div.x-foo-scope button.x-foo-scope + + * :host -> scopeName + + * :host(...) -> scopeName... + + * ::content -> ' ' NOTE: requires use of scoping selector and selectors + cannot otherwise be scoped: + e.g. :host ::content > .bar -> x-foo > .bar + + * ::shadow, /deep/: processed simimlar to ::content + + * :host-context(...): NOT SUPPORTED + + */ + + // Given a node and scope name, add a scoping class to each node + // in the tree. This facilitates transforming css into scoped rules. + function transformDom(node, scope, useAttr, shouldRemoveScope) { + _transformDom(node, scope || '', useAttr, shouldRemoveScope); + } + + function _transformDom(node, selector, useAttr, shouldRemoveScope) { + if (node.setAttribute) { + transformElement(node, selector, useAttr, shouldRemoveScope); + } + var c$ = Polymer.dom(node).childNodes; + for (var i=0; i<c$.length; i++) { + _transformDom(c$[i], selector, useAttr, shouldRemoveScope); + } + } + + function transformElement(element, scope, useAttr, shouldRemoveScope) { + if (useAttr) { + if (shouldRemoveScope) { + element.removeAttribute(SCOPE_NAME); + } else { + element.setAttribute(SCOPE_NAME, scope); + } + } else { + // note: if using classes, we add both the general 'style-scope' class + // as well as the specific scope. This enables easy filtering of all + // `style-scope` elements + if (scope) { + if (shouldRemoveScope) { + element.classList.remove(SCOPE_NAME, scope); + } else { + element.classList.add(SCOPE_NAME, scope); + } + } + } + } + + function transformHost(host, scope) { + } + + // Given a string of cssText and a scoping string (scope), returns + // a string of scoped css where each selector is transformed to include + // a class created from the scope. ShadowDOM selectors are also transformed + // (e.g. :host) to use the scoping selector. + function transformCss(rules, scope, ext, callback, useAttr) { + var hostScope = calcHostScope(scope, ext); + scope = calcElementScope(scope, useAttr); + return Polymer.StyleUtil.toCssText(rules, function(rule) { + transformRule(rule, scope, hostScope); + if (callback) { + callback(rule, scope, hostScope); + } + }); + } + + function calcElementScope(scope, useAttr) { + if (scope) { + return useAttr ? + CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : + CSS_CLASS_PREFIX + scope; + } else { + return ''; + } + } + + function calcHostScope(scope, ext) { + return ext ? '[is=' + scope + ']' : scope; + } + + function transformRule(rule, scope, hostScope) { + _transformRule(rule, transformComplexSelector, + scope, hostScope); + } + + // transforms a css rule to a scoped rule. + function _transformRule(rule, transformer, scope, hostScope) { + var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP); + for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) { + p$[i] = transformer(p, scope, hostScope); + } + rule.selector = p$.join(COMPLEX_SELECTOR_SEP); + } + + function transformComplexSelector(selector, scope, hostScope) { + var stop = false; + selector = selector.replace(SIMPLE_SELECTOR_SEP, function(m, c, s) { + if (!stop) { + var o = transformCompoundSelector(s, c, scope, hostScope); + if (o.stop) { + stop = true; + } + c = o.combinator; + s = o.value; + } + return c + s; + }); + return selector; + } + + function transformCompoundSelector(selector, combinator, scope, hostScope) { + // replace :host with host scoping class + var jumpIndex = selector.search(SCOPE_JUMP); + if (selector.indexOf(HOST) >=0) { + // :host(...) + selector = selector.replace(HOST_PAREN, function(m, host, paren) { + return hostScope + paren; + }); + // now normal :host + selector = selector.replace(HOST, hostScope); + // replace other selectors with scoping class + } else if (jumpIndex !== 0) { + selector = scope ? transformSimpleSelector(selector, scope) : selector; + } + // remove left-side combinator when dealing with ::content. + if (selector.indexOf(CONTENT) >= 0) { + combinator = ''; + } + // process scope jumping selectors up to the scope jump and then stop + // e.g. .zonk ::content > .foo ==> .zonk.scope > .foo + var stop; + if (jumpIndex >= 0) { + selector = selector.replace(SCOPE_JUMP, ' '); + stop = true; + } + return {value: selector, combinator: combinator, stop: stop}; + } + + function transformSimpleSelector(selector, scope) { + var p$ = selector.split(PSEUDO_PREFIX); + p$[0] += scope; + return p$.join(PSEUDO_PREFIX); + } + + function transformRootRule(rule) { + _transformRule(rule, transformRootSelector); + } + + function transformRootSelector(selector) { + return selector.match(SCOPE_JUMP) ? + transformComplexSelector(selector) : + selector.trim() + SCOPE_ROOT_SELECTOR; + } + + var SCOPE_NAME = 'style-scope'; + var SCOPE_ROOT_SELECTOR = ':not([' + SCOPE_NAME + '])' + + ':not(.' + SCOPE_NAME + ')'; + var COMPLEX_SELECTOR_SEP = ','; + var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g; + var HOST = ':host'; + // NOTE: this supports 1 nested () pair for things like + // :host(:not([selected]), more general support requires + // parsing which seems like overkill + var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g; + var CONTENT = '::content'; + var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//; + var CSS_CLASS_PREFIX = '.'; + var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~='; + var CSS_ATTR_SUFFIX = ']'; + var PSEUDO_PREFIX = ':'; + + // exports + Polymer.StyleTransformer = { + element: transformElement, + dom: transformDom, + host: transformHost, + css: transformCss, + rule: transformRule, + rootRule: transformRootRule, + SCOPE_NAME: SCOPE_NAME + }; + + })(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-transformer.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-transformer.html new file mode 100644 index 0000000..650f540 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-transformer.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="style-util.html"> + +</head><body><script src="style-transformer-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-util-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-util-extracted.js new file mode 100644 index 0000000..a26a11bf --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-util-extracted.js
@@ -0,0 +1,64 @@ + + + (function() { + + function toCssText(rules, callback) { + if (typeof rules === 'string') { + rules = Polymer.CssParse.parse(rules); + } + if (callback) { + forEachStyleRule(rules, callback); + } + return Polymer.CssParse.stringify(rules); + } + + function forEachStyleRule(node, cb) { + var s = node.selector; + var skipRules = false; + if (s) { + if ((s.indexOf(AT_RULE) !== 0) && (s.indexOf(MIXIN_SELECTOR) !== 0)) { + cb(node); + } + skipRules = (s.indexOf(KEYFRAME_RULE) >= 0) || + (s.indexOf(MIXIN_SELECTOR) >= 0); + } + var r$ = node.rules; + if (r$ && !skipRules) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + forEachStyleRule(r, cb); + } + } + } + + // add a string of cssText to the document. + function applyCss(cssText, moniker, target, lowPriority) { + var style = document.createElement('style'); + if (moniker) { + style.setAttribute('scope', moniker); + } + style.textContent = cssText; + target = target || document.head; + if (lowPriority) { + var n$ = target.querySelectorAll('style[scope]'); + var ref = n$.length ? n$[n$.length-1].nextSibling : target.firstChild; + target.insertBefore(style, ref); + } else { + target.appendChild(style); + } + return style; + } + + var AT_RULE = '@'; + var KEYFRAME_RULE = 'keyframe'; + var MIXIN_SELECTOR = '--'; + + // exports + Polymer.StyleUtil = { + parser: Polymer.CssParse, + applyCss: applyCss, + forEachStyleRule: forEachStyleRule, + toCssText: toCssText + }; + + })(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-util.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-util.html new file mode 100644 index 0000000..3585521 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/style-util.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="css-parse.html"> + +</head><body><script src="style-util-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/templatizer-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/templatizer-extracted.js new file mode 100644 index 0000000..6dacd576 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/templatizer-extracted.js
@@ -0,0 +1,242 @@ + + + Polymer.Templatizer = { + + templatize: function(template) { + this._templatized = template; + // TODO(sjmiles): supply _alternate_ content reference missing from root + // templates (not nested). `_content` exists to provide content sharing + // for nested templates. + if (!template._content) { + template._content = template.content; + } + // fast path if template's anonymous class has been memoized + if (template._content._ctor) { + this.ctor = template._content._ctor; + //console.log('Templatizer.templatize: using memoized archetype'); + // forward parent properties to archetype + this._prepParentProperties(this.ctor.prototype); + return; + } + // `archetype` is the prototype of the anonymous + // class created by the templatizer + var archetype = Object.create(Polymer.Base); + // normally Annotations.parseAnnotations(template) but + // archetypes do special caching + this.customPrepAnnotations(archetype, template); + + // setup accessors + archetype._prepEffects(); + archetype._prepBehaviors(); + archetype._prepBindings(); + + // forward parent properties to archetype + this._prepParentProperties(archetype); + + // boilerplate code + archetype._notifyPath = this._notifyPathImpl; + archetype._scopeElementClass = this._scopeElementClassImpl; + // boilerplate code + var _constructor = this._constructorImpl; + var ctor = function TemplateInstance(model, host) { + _constructor.call(this, model, host); + }; + // standard references + ctor.prototype = archetype; + archetype.constructor = ctor; + // TODO(sjmiles): constructor cache? + template._content._ctor = ctor; + // TODO(sjmiles): choose less general name + this.ctor = ctor; + }, + + _getRootDataHost: function() { + return (this.dataHost && this.dataHost._rootDataHost) || this.dataHost; + }, + + _getAllStampedChildren: function(children) { + children = children || []; + if (this._getStampedChildren) { + var c$ = this._getStampedChildren(); + for (var i=0, c; c = c$[i]; i++) { + children.push(c); + if (c._getAllStampedChildren) { + c._getAllStampedChildren(children); + } + } + } + return children; + }, + + customPrepAnnotations: function(archetype, template) { + if (template) { + archetype._template = template; + var c = template._content; + if (c) { + var rootDataHost = archetype._rootDataHost; + if (rootDataHost) { + Polymer.Annotations.prepElement = + rootDataHost._prepElement.bind(rootDataHost); + } + archetype._notes = c._notes || + Polymer.Annotations.parseAnnotations(template); + c._notes = archetype._notes; + Polymer.Annotations.prepElement = null; + archetype._parentProps = c._parentProps; + } + else { + console.warn('no _content'); + } + } + else { + console.warn('no _template'); + } + }, + + // Sets up accessors on the template to call abstract _forwardParentProp + // API that should be implemented by Templatizer users to get parent + // properties to their template instances. These accessors are memoized + // on the archetype and copied to instances. + _prepParentProperties: function(archetype) { + var parentProps = this._parentProps = archetype._parentProps; + if (this._forwardParentProp && parentProps) { + // Prototype setup (memoized on archetype) + var proto = archetype._parentPropProto; + if (!proto) { + proto = archetype._parentPropProto = Object.create(null); + if (this._templatized != this) { + // Assumption: if `this` isn't the template being templatized, + // assume that the template is not a Poylmer.Base, so prep it + // for binding + Polymer.Bind.prepareModel(proto); + } + // Create accessors for each parent prop that forward the property + // to template instances through abstract _forwardParentProp API + // that should be implemented by Templatizer users + for (var prop in parentProps) { + var parentProp = '_parent_' + prop; + var effects = [{ + kind: 'function', + effect: { function: this._createForwardPropEffector(prop) } + }]; + Polymer.Bind._createAccessors(proto, parentProp, effects); + } + } + // Instance setup + if (this._templatized != this) { + Polymer.Bind.prepareInstance(this._templatized); + this._templatized._forwardParentProp = + this._forwardParentProp.bind(this); + } + this._extendTemplate(this._templatized, proto); + } + }, + + _createForwardPropEffector: function(prop) { + return function(source, value) { + this._forwardParentProp(prop, value); + }; + }, + + // Similar to Polymer.Base.extend, but retains any previously set instance + // values (_propertySet back on instance once accessor is installed) + _extendTemplate: function(template, proto) { + Object.getOwnPropertyNames(proto).forEach(function(n) { + var val = template[n]; + var pd = Object.getOwnPropertyDescriptor(proto, n); + Object.defineProperty(template, n, pd); + if (val !== undefined) { + template._propertySet(n, val); + } + }); + }, + + _notifyPathImpl: function(path, value) { + var p = path.match(/([^.]*)\.(([^.]*).*)/); + // 'root.sub.path' + var root = p[1]; // 'root' + var sub = p[3]; // 'sub' + var subPath = p[2]; // 'sub.path' + // Notify host of parent.* path/property changes + var dataHost = this.dataHost; + if (root == 'parent') { + if (sub == subPath) { + dataHost.dataHost[sub] = value; + } else { + dataHost.notifyPath('_parent_' + subPath, value); + } + } + // Extension point for Templatizer sub-classes + if (dataHost._forwardInstancePath) { + dataHost._forwardInstancePath.call(dataHost, this, root, subPath, value); + } + }, + + // Overrides Base notify-path module + _pathEffector: function(path, value, fromAbove) { + if (this._forwardParentPath) { + if (path.indexOf('_parent_') === 0) { + this._forwardParentPath(path.substring(8), value); + } + } + Polymer.Base._pathEffector.apply(this, arguments); + }, + + _constructorImpl: function(model, host) { + var rootDataHost = host._getRootDataHost(); + if (rootDataHost) { + this.listen = rootDataHost.listen.bind(rootDataHost); + this._rootDataHost = rootDataHost; + } + this._setupConfigure(model); + this._pushHost(host); + this.root = this.instanceTemplate(this._template); + this.root.__styleScoped = true; + this._popHost(); + this._marshalAnnotatedNodes(); + this._marshalInstanceEffects(); + this._marshalAnnotatedListeners(); + this._tryReady(); + }, + + _scopeElementClassImpl: function(node, value) { + var host = this._rootDataHost; + if (host) { + return host._scopeElementClass(node, value); + } + }, + + stamp: function(model) { + model = model || {}; + if (this._parentProps) { + // TODO(kschaaf): Maybe this is okay + // model.parent = this.dataHost; + model.parent = model.parent || {}; + for (var prop in this._parentProps) { + model.parent[prop] = this['_parent_' + prop]; + } + } + return new this.ctor(model, this); + } + + // TODO(sorvell): note, using the template as host is ~5-10% faster if + // elements have no default values. + // _constructorImpl: function(model, host) { + // this._setupConfigure(model); + // host._beginHost(); + // this.root = this.instanceTemplate(this._template); + // host._popHost(); + // this._marshalTemplateContent(); + // this._marshalAnnotatedNodes(); + // this._marshalInstanceEffects(); + // this._marshalAnnotatedListeners(); + // this._ready(); + // }, + + // stamp: function(model) { + // return new this.ctor(model, this.dataHost); + // } + + + }; +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/templatizer.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/templatizer.html new file mode 100644 index 0000000..c3d4dce --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/templatizer.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="templatizer-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-array-selector-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-array-selector-extracted.js new file mode 100644 index 0000000..c794f64 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-array-selector-extracted.js
@@ -0,0 +1,113 @@ + + + Polymer({ + is: 'x-array-selector', + + properties: { + + /** + * An array containing items from which selection will be made. + */ + items: { + type: Array, + observer: '_itemsChanged' + }, + + /** + * When `multi` is true, this is an array that contains any selected. + * When `multi` is false, this is the currently selected item, or `null` + * if no item is selected. + */ + selected: { + type: Object, + notify: true + }, + + /** + * When `true`, calling `select` on an item that is already selected + * will deselect the item. + */ + toggle: Boolean, + + /** + * When `true`, multiple items may be selected at once (in this case, + * `selected` is an array of currently selected items). When `false`, + * only one item may be selected at a time. + */ + multi: Boolean + }, + + _itemsChanged: function() { + // Unbind previous selection + if (Array.isArray(this.selected)) { + for (var i=0; i<this.selected.length; i++) { + this.unbindPaths('selected.' + i); + } + } else { + this.unbindPaths('selected'); + } + // Initialize selection + if (this.multi) { + this.selected = []; + } else { + this.selected = null; + } + }, + + /** + * Deselects the given item if it is already selected. + */ + deselect: function(item) { + if (this.multi) { + var scol = Polymer.Collection.get(this.selected); + // var skey = scol.getKey(item); + // if (skey >= 0) { + var sidx = this.selected.indexOf(item); + if (sidx >= 0) { + var skey = scol.getKey(item); + this.selected.splice(sidx, 1); + // scol.remove(item); + this.unbindPaths('selected.' + skey); + return true; + } + } else { + this.selected = null; + this.unbindPaths('selected'); + } + }, + + /** + * Selects the given item. When `toggle` is true, this will automatically + * deselect the item if already selected. + */ + select: function(item) { + var icol = Polymer.Collection.get(this.items); + var key = icol.getKey(item); + if (this.multi) { + // var sidx = this.selected.indexOf(item); + // if (sidx < 0) { + var scol = Polymer.Collection.get(this.selected); + var skey = scol.getKey(item); + if (skey >= 0) { + this.deselect(item); + } else if (this.toggle) { + this.selected.push(item); + // this.bindPaths('selected.' + sidx, 'items.' + skey); + // skey = Polymer.Collection.get(this.selected).add(item); + this.async(function() { + skey = scol.getKey(item); + this.bindPaths('selected.' + skey, 'items.' + key); + }); + } + } else { + if (this.toggle && item == this.selected) { + this.deselect(); + } else { + this.bindPaths('selected', 'items.' + key); + this.selected = item; + } + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-array-selector.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-array-selector.html new file mode 100644 index 0000000..b19c821 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-array-selector.html
@@ -0,0 +1,61 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- +Keeping structured data in sync requires that Polymer understand the path +associations of data being bound. The `x-array-selector` element ensures path +linkage when selecting specific items from an array (either single or multiple). +The `items` property accepts an array of user data, and via the `select(item)` +and `deselect(item)` API, updates the `selected` property which may be bound to +other parts of the application, and any changes to sub-fields of `selected` +item(s) will be kept in sync with items in the `items` array. When `multi` +is false, `selected` is a property representing the last selected item. When +`multi` is true, `selected` is an array of multiply selected items. + +```html +<dom-module id="employee-list"> + + <template> + + <div> Employee list: </div> + <template is="x-repeat" id="employeeList" items="{{employees}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + <button on-click="toggleSelection">Select</button> + </template> + + <x-array-selector id="selector" items="{{employees}}" selected="{{selected}}" multi toggle></x-array-selector> + + <div> Selected employees: </div> + <template is="x-repeat" items="{{selected}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + </template> + + </template> + + <script> + Polymer({ + is: 'employee-list', + ready: function() { + this.employees = [ + {first: 'Bob', last: 'Smith'}, + {first: 'Sally', last: 'Johnson'}, + ... + ]; + }, + toggleSelection: function(e) { + var item = this.$.employeeList.itemForElement(e.target); + this.$.selector.select(item); + } + }); + </script> + +</dom-module> +``` +--><html><head></head><body><script src="x-array-selector-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-autobind-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-autobind-extracted.js new file mode 100644 index 0000000..1cfde49 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-autobind-extracted.js
@@ -0,0 +1,29 @@ + + + Polymer({ + + is: 'x-autobind', + + extends: 'template', + + _registerFeatures: function() { + this._prepExtends(); + this._prepConstructor(); + }, + + _finishDistribute: function() { + var parentDom = Polymer.dom(Polymer.dom(this).parentNode); + parentDom.insertBefore(this.root, this); + }, + + _initFeatures: function() { + this._template = this; + this._prepAnnotations(); + this._prepEffects(); + this._prepBehaviors(); + this._prepBindings(); + Polymer.Base._initFeatures.call(this); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-autobind.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-autobind.html new file mode 100644 index 0000000..093fafd4 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-autobind.html
@@ -0,0 +1,49 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- + +**THIS ELEMENT IS EXPERIMENTAL. API AND NAME SUBJECT TO CHANGE.** + +Polymer's binding features are only available within templates that are managed +by Polymer. As such, these features are available in templates used to define +Polymer elements, for example, but not for elements placed directly in the main +document. + +In order to use Polymer bindings without defining a new custom element, elements +utilizing bindings may be wrapped with the `x-autobind` template extension. +This template will immediately stamp itself into the main document and bind +elements to the template itself as the binding scope. + +```html +<!doctype html> +<html> +<head> + <meta charset="utf-8"> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + <link rel="import" href="components/core-ajax/core-ajax.html"> + +</head> +<body> + + <template is="x-autobind"> + + <core-ajax url="http://..." lastresponse="{{data}}"></core-ajax> + + <template is="x-repeat" items="{{data}}"> + <div><span>{{item.first}}</span> <span>{{item.last}}</span></div> + </template> + + </template> + +</body> +</html> +``` + +--><html><head></head><body><script src="x-autobind-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-if-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-if-extracted.js new file mode 100644 index 0000000..d8cb6f3 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-if-extracted.js
@@ -0,0 +1,126 @@ + + + /** + * Stamps the template iff the `if` property is truthy. + * + * When `if` becomes falsey, the stamped content is hidden but not + * removed from dom. When `if` subsequently becomes truthy again, the content + * is simply re-shown. This approach is used due to its favorable performance + * characteristics: the expense of creating template content is paid only + * once and lazily. + * + * Set the `restamp` property to true to force the stamped content to be + * created / destroyed when the `if` condition changes. + */ + Polymer({ + + is: 'x-if', + extends: 'template', + + properties: { + + 'if': { + type: Boolean, + value: false + }, + + restamp: { + type: Boolean, + value: false + } + + }, + + behaviors: [ + Polymer.Templatizer + ], + + observers: [ + 'render(if, restamp)' + ], + + render: function() { + this.debounce('render', function() { + if (this.if) { + if (!this.ctor) { + this._wrapTextNodes(this._content); + this.templatize(this); + } + this._ensureInstance(); + } else if (this.restamp) { + this._teardownInstance(); + } + if (!this.restamp && this._instance) { + this._showHideInstance(this.if); + } + }); + }, + + _ensureInstance: function() { + if (!this._instance) { + // TODO(sorvell): pickup stamping logic from x-repeat + this._instance = this.stamp(); + var root = this._instance.root; + this._instance._children = Array.prototype.slice.call(root.childNodes); + // TODO(sorvell): this incantation needs to be simpler. + var parent = Polymer.dom(Polymer.dom(this).parentNode); + parent.insertBefore(root, this); + } + }, + + _teardownInstance: function() { + if (this._instance) { + var parent = Polymer.dom(Polymer.dom(this).parentNode); + this._instance._children.forEach(function(n) { + parent.removeChild(n); + }); + this._instance = null; + } + }, + + _wrapTextNodes: function(root) { + // wrap text nodes in span so they can be hidden. + for (var n = root.firstChild; n; n=n.nextSibling) { + if (n.nodeType === Node.TEXT_NODE) { + var s = document.createElement('span'); + root.insertBefore(s, n); + s.appendChild(n); + n = s; + } + } + }, + + // Implements extension point from Templatizer mixin + _getStampedChildren: function() { + return this._instance._children; + }, + + _showHideInstance: function(showing) { + this._getAllStampedChildren().forEach(function(n) { + if (n.setAttribute) { + this.serializeValueToAttribute(!showing, 'hidden', n); + } + }, this); + }, + + // Implements extension point from Templatizer mixin + // Called as side-effect of a host property change, responsible for + // notifying parent.<prop> path change on instance + _forwardParentProp: function(prop, value) { + if (this._instance) { + this._instance.parent[prop] = value; + this._instance.notifyPath('parent.' + prop, value, true); + } + }, + + // Implements extension point from Templatizer + // Called as side-effect of a host path change, responsible for + // notifying parent.<path> path change on each row + _forwardParentPath: function(path, value) { + if (this._instance) { + this._instance.notifyPath('parent.' + path, value, true); + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-if.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-if.html new file mode 100644 index 0000000..e75cc3b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-if.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="templatizer.html"> + +</head><body><script src="x-if-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-repeat-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-repeat-extracted.js new file mode 100644 index 0000000..51f4e82b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-repeat-extracted.js
@@ -0,0 +1,455 @@ + + + Polymer({ + + is: 'x-repeat', + extends: 'template', + + properties: { + + /** + * An array containing items determining how many instances of the template + * to stamp and that that each template instance should bind to. + */ + items: { + type: Array + }, + + /** + * A function that should determine the sort order of the items. This + * property should either be provided as a string, indicating a method + * name on the element's host, or else be an actual function. The + * function should match the sort function passed to `Array.sort`. + * Using a sort function has no effect on the underlying `items` array. + */ + sort: { + type: Function, + observer: '_sortChanged' + }, + + /** + * A function that can be used to filter items out of the view. This + * property should either be provided as a string, indicating a method + * name on the element's host, or else be an actual function. The + * function should match the sort function passed to `Array.filter`. + * Using a filter function has no effect on the underlying `items` array. + */ + filter: { + type: Function, + observer: '_filterChanged' + }, + + /** + * When using a `filter` or `sort` function, the `observe` property + * should be set to a space-separated list of the names of item + * sub-fields that should trigger a re-sort or re-filter when changed. + * These should generally be fields of `item` that the sort or filter + * function depends on. + */ + observe: { + type: String, + observer: '_observeChanged' + }, + + /** + * When using a `filter` or `sort` function, the `delay` property + * determines a debounce time after a change to observed item + * properties that must pass before the filter or sort is re-run. + * This is useful in rate-limiting shuffing of the view when + * item changes may be frequent. + */ + delay: Number + }, + + behaviors: [ + Polymer.Templatizer + ], + + observers: [ + '_itemsChanged(items.*)' + ], + + created: function() { + this.boundCollectionObserver = this.render.bind(this); + }, + + ready: function() { + // Templatizing (generating the instance constructor) needs to wait + // until attached, since it may not have its template content handed + // back to it until then, following its host template stamping + if (!this.ctor) { + this.templatize(this); + } + }, + + _sortChanged: function() { + var dataHost = this._getRootDataHost(); + this._sortFn = this.sort && (typeof this.sort == 'function' ? + this.sort : dataHost[this.sort].bind(this.host)); + if (this.items) { + this.debounce('render', this.render); + } + }, + + _filterChanged: function() { + var dataHost = this._getRootDataHost(); + this._filterFn = this.filter && (typeof this.filter == 'function' ? + this.filter : dataHost[this.filter].bind(this.host)); + if (this.items) { + this.debounce('render', this.render); + } + }, + + _observeChanged: function() { + this._observePaths = this.observe && + this.observe.replace('.*', '.').split(' '); + }, + + _itemsChanged: function(change) { + if (change.path == 'items') { + this._unobserveCollection(); + if (change.value) { + this._observeCollection(change.value); + this.debounce('render', this.render); + } + } else { + this._forwardItemPath(change.path, change.value); + this._checkObservedPaths(change.path); + } + }, + + _checkObservedPaths: function(path) { + if (this._observePaths && path.indexOf('items.') === 0) { + path = path.substring(path.indexOf('.', 6) + 1); + var paths = this._observePaths; + for (var i=0; i<paths.length; i++) { + if (path.indexOf(paths[i]) === 0) { + this.debounce('render', this.render, this.delay); + return; + } + } + } + }, + + _observeCollection: function(items) { + this.collection = Array.isArray(items) ? Polymer.Collection.get(items) : items; + this.collection.observe(this.boundCollectionObserver); + }, + + _unobserveCollection: function() { + if (this.collection) { + this.collection.unobserve(this.boundCollectionObserver); + } + }, + + render: function(splices) { + this.flushDebouncer('render'); + var c = this.collection; + if (splices) { + if (this._sortFn || splices[0].index == null) { + this._applySplicesViewSort(splices); + } else { + this._applySplicesArraySort(splices); + } + } else { + this._sortAndFilter(); + } + var rowForKey = this._rowForKey = {}; + var keys = this._orderedKeys; + // Assign items and keys + this.rows = this.rows || []; + for (var i=0; i<keys.length; i++) { + var key = keys[i]; + var item = c.getItem(key); + var row = this.rows[i]; + rowForKey[key] = i; + if (!row) { + this.rows.push(row = this._insertRow(i, null, item)); + } + row.item = item; + row.key = key; + row.index = i; + } + // Remove extra + for (; i<this.rows.length; i++) { + this._detachRow(i); + } + this.rows.splice(keys.length, this.rows.length-keys.length); + }, + + _sortAndFilter: function() { + var c = this.collection; + this._orderedKeys = c.getKeys(); + // Filter + if (this._filterFn) { + this._orderedKeys = this._orderedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + } + // Sort + if (this._sortFn) { + this._orderedKeys.sort(function(a, b) { + return this._sortFn(c.getItem(a), c.getItem(b)); + }.bind(this)); + } + }, + + _keySort: function(a, b) { + return this.collection.getKey(a) - this.collection.getKey(b); + }, + + _applySplicesViewSort: function(splices) { + var c = this.collection; + var keys = this._orderedKeys; + var rows = this.rows; + var removedRows = []; + var addedKeys = []; + var pool = []; + var sortFn = this._sortFn || this._keySort.bind(this); + splices.forEach(function(s) { + // Collect all removed row idx's + for (var i=0; i<s.removed.length; i++) { + var idx = this._rowForKey[s.removed[i]]; + if (idx != null) { + removedRows.push(idx); + } + } + // Collect all added keys + for (i=0; i<s.added.length; i++) { + addedKeys.push(s.added[i]); + } + }, this); + if (removedRows.length) { + // Sort removed rows idx's + removedRows.sort(); + // Remove keys and pool rows (backwards, so we don't invalidate rowForKey) + for (i=removedRows.length-1; i>=0 ; i--) { + var idx = removedRows[i]; + pool.push(this._detachRow(idx)); + rows.splice(idx, 1); + keys.splice(idx, 1); + } + } + if (addedKeys.length) { + // Filter added keys + if (this._filterFn) { + addedKeys = addedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + } + // Sort added keys + addedKeys.sort(function(a, b) { + return this.sortFn(c.getItem(a), c.getItem(b)); + }, this); + // Insert new rows using sort (from pool or newly created) + var start = 0; + for (i=0; i<addedKeys.length; i++) { + start = this._insertRowIntoViewSort(start, addedKeys[i], pool); + } + } + }, + + _insertRowIntoViewSort: function(start, key, pool) { + var c = this.collection; + var item = c.getItem(key); + var end = this.rows.length - 1; + var idx = -1; + var sortFn = this._sortFn || this._keySort.bind(this); + // Binary search for insertion point + while (start <= end) { + var mid = (start + end) >> 1; + var midKey = this._orderedKeys[mid]; + var cmp = sortFn(c.getItem(midKey), item); + if (cmp < 0) { + start = mid + 1; + } else if (cmp > 0) { + end = mid - 1; + } else { + idx = mid; + break; + } + } + if (idx < 0) { + idx = end + 1; + } + // Insert key & row at insertion point + this._orderedKeys.splice(idx, 0, key); + this.rows.splice(idx, 0, this._insertRow(idx, pool)); + return idx; + }, + + _applySplicesArraySort: function(splices) { + var keys = this._orderedKeys; + var pool = []; + splices.forEach(function(s) { + // Remove & pool rows first, to ensure we can fully reuse removed rows + for (var i=0; i<s.removed.length; i++) { + pool.push(this._detachRow(s.index + i)); + } + this.rows.splice(s.index, s.removed.length); + }, this); + var c = this.collection; + var filterDelta = 0; + splices.forEach(function(s) { + // Filter added keys + var addedKeys = s.added; + if (this._filterFn) { + addedKeys = addedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + filterDelta += (s.added.length - addedKeys.length); + } + var idx = s.index - filterDelta; + // Apply splices to keys + var args = [idx, s.removed.length].concat(addedKeys); + keys.splice.apply(keys, args); + // Insert new rows (from pool or newly created) + var addedRows = []; + for (i=0; i<s.added.length; i++) { + addedRows.push(this._insertRow(idx + i, pool)); + } + args = [s.index, 0].concat(addedRows); + this.rows.splice.apply(this.rows, args); + }, this); + }, + + _detachRow: function(idx) { + var row = this.rows[idx]; + var parentNode = Polymer.dom(this).parentNode; + for (var i=0; i<row._children.length; i++) { + var el = row._children[i]; + Polymer.dom(row.root).appendChild(el); + } + return row; + }, + + _insertRow: function(idx, pool, item) { + var row = (pool && pool.pop()) || this._generateRow(idx, item); + var beforeRow = this.rows[idx]; + var beforeNode = beforeRow ? beforeRow._children[0] : this; + var parentNode = Polymer.dom(this).parentNode; + Polymer.dom(parentNode).insertBefore(row.root, beforeNode); + return row; + }, + + _generateRow: function(idx, item) { + var row = this.stamp({ + index: idx, + key: this.collection.getKey(item), + item: item + }); + // each row is a document fragment which is lost when we appendChild, + // so we have to track each child individually + var children = []; + for (var n = row.root.firstChild; n; n=n.nextSibling) { + children.push(n); + n._templateInstance = row; + } + // Since archetype overrides Base/HTMLElement, Safari complains + // when accessing `children` + row._children = children; + return row; + }, + + // Implements extension point from Templatizer mixin + _getStampedChildren: function() { + var children = []; + if (this.rows) { + for (var i=0; i<this.rows.length; i++) { + var c = this.rows[i]._children; + for (var j=0; j<c.length; j++) + children.push(c[j]); + } + } + return children; + }, + + // Implements extension point from Templatizer + // Called as a side effect of a template instance path change, responsible + // for notifying items.<key-for-row>.<path> change up to host + _forwardInstancePath: function(row, root, subPath, value) { + if (root == 'item') { + this.notifyPath('items.' + row.key + '.' + subPath, value); + } + }, + + // Implements extension point from Templatizer mixin + // Called as side-effect of a host property change, responsible for + // notifying parent.<prop> path change on each row + _forwardParentProp: function(prop, value) { + if (this.rows) { + this.rows.forEach(function(row) { + row.parent[prop] = value; + row.notifyPath('parent.' + prop, value, true); + }, this); + } + }, + + // Implements extension point from Templatizer + // Called as side-effect of a host path change, responsible for + // notifying parent.<path> path change on each row + _forwardParentPath: function(path, value) { + if (this.rows) { + this.rows.forEach(function(row) { + row.notifyPath('parent.' + path, value, true); + }, this); + } + }, + + // Called as a side effect of a host items.<key>.<path> path change, + // responsible for notifying item.<path> changes to row for key + _forwardItemPath: function(path, value) { + if (this._rowForKey) { + // 'items.'.length == 6 + var dot = path.indexOf('.', 6); + var key = path.substring(6, dot < 0 ? path.length : dot); + var idx = this._rowForKey[key]; + var row = this.rows[idx]; + if (row) { + if (dot >= 0) { + path = 'item.' + path.substring(dot+1); + row.notifyPath(path, value, true); + } else { + row.item = value; + } + } + } + }, + + _instanceForElement: function(el) { + while (el && !el._templateInstance) { + el = el.parentNode; + } + return el && el._templateInstance; + }, + + /** + * Returns the item associated with a given element stamped by + * this `x-repeat`. + */ + itemForElement: function(el) { + var instance = this._instanceForElement(el); + return instance && instance.item; + }, + + /** + * Returns the `Polymer.Collection` key associated with a given + * element stamped by this `x-repeat`. + */ + keyForElement: function(el) { + var instance = this._instanceForElement(el); + return instance && instance.key; + }, + + /** + * Returns the index in `items` associated with a given element + * stamped by this `x-repeat`. + */ + indexForElement: function(el) { + var instance = this._instanceForElement(el); + return this.rows.indexOf(instance); + } + + }); + +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-repeat.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-repeat.html new file mode 100644 index 0000000..11712c65 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-repeat.html
@@ -0,0 +1,87 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- + +**THIS ELEMENT IS EXPERIMENTAL. API AND NAME SUBJECT TO CHANGE.** + +The `x-repeat` element is a custom `HTMLTemplateElement` type extension that +automatically stamps and binds one instance of template content to each object +in a user-provided array. `x-repeat` accepts an `items` property, and one +instance of the template is stamped for each item into the DOM at the location +of the `x-repeat` element. The `item` property will be set on each instance's +binding scope, thus templates should bind to sub-properties of `item`. + +Example: + +```html +<dom-module id="employee-list"> + + <template> + + <div> Employee list: </div> + <template is="x-repeat" items="{{employees}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + </template> + + </template> + + <script> + Polymer({ + is: 'employee-list', + ready: function() { + this.employees = [ + {first: 'Bob', last: 'Smith'}, + {first: 'Sally', last: 'Johnson'}, + ... + ]; + } + }); + </script> + +</dom-module> +``` + +Notifications for changes to items sub-properties will be forwarded to template +instances, which will update via the normal structured data notification system. + +Mutations to the `items` array itself (`push`, `pop`, `splice`, `shift`, +`unshift`) are observed via `Array.observe` (where supported, or an +shim of this API on unsupported browsers), and template instances are kept in +sync with the data in the array. + +A view-specific filter/sort may be applied to each `x-repeat` by supplying a +`filter` and/or `sort` property. This may be a string that names a function on +the host, or a function may be assigned to the property directly. The functions +should implemented following the standard `Array` filter/sort API. + +In order to re-run the filter or sort functions based on changes to sub-fields +of `items`, the `observe` property may be set as a space-separated list of +`item` sub-fields that should cause a re-filter/sort when modified. + +For example, for an `x-repeat` with a filter of the following: + +```js +isEngineer: function(item) { + return item.type == 'engineer' || item.manager.type == 'engineer'; +} +``` + +Then the `observe` property should be configured as follows: + +```html +<template is="x-repeat" items="{{employees}}" + filter="isEngineer" observe="type manager.type"> +``` + +--><html><head><link rel="import" href="templatizer.html"> +<link rel="import" href="../array-observe.html"> +<link rel="import" href="../collection.html"> + +</head><body><script src="x-repeat-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-template-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-template-extracted.js new file mode 100644 index 0000000..06af464 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-template-extracted.js
@@ -0,0 +1,26 @@ + + + /** + * Creates a pseudo-custom-element that maps property values to bindings + * in DOM. + * + * `stamp` method creates an instance of the pseudo-element. The instance + * references a document-fragment containing the stamped and bound dom + * via it's `root` property. + * + */ + Polymer({ + + is: 'x-template', + extends: 'template', + + behaviors: [ + Polymer.Templatizer + ], + + ready: function() { + this.templatize(this); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-template.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-template.html new file mode 100644 index 0000000..3b92a6a --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/template/x-template.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="templatizer.html"> + +</head><body><script src="x-template-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/x-style-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/x-style-extracted.js new file mode 100644 index 0000000..885e84a8 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/x-style-extracted.js
@@ -0,0 +1,47 @@ + +(function() { + + Polymer({ + + is: 'x-style', + extends: 'style', + + created: function() { + var rules = Polymer.StyleUtil.parser.parse(this.textContent); + this.applyProperties(rules); + // TODO(sorvell): since custom rules must match directly, they tend to be + // made with selectors like `*`. + // We *remove them here* so they don't apply too widely and nerf recalc. + // This means that normal properties mixe in rules with custom + // properties will *not* apply. + var cssText = Polymer.StyleUtil.parser.stringify(rules); + this.textContent = this.scopeCssText(cssText); + }, + + scopeCssText: function(cssText) { + return Polymer.Settings.useNativeShadow ? + cssText : + Polymer.StyleUtil.toCssText(cssText, function(rule) { + Polymer.StyleTransformer.rootRule(rule); + }); + }, + + applyProperties: function(rules) { + var cssText = ''; + Polymer.StyleUtil.forEachStyleRule(rules, function(rule) { + if (rule.cssText.match(CUSTOM_RULE)) { + // TODO(sorvell): use parser.stringify, it needs an option not to + // strip custom properties. + cssText += rule.selector + ' {\n' + rule.cssText + '\n}\n'; + } + }); + if (cssText) { + Polymer.StyleDefaults.applyCss(cssText); + } + } + + }); + + var CUSTOM_RULE = /--[^;{'"]*\:/; + +})();
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/x-style.html b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/x-style.html new file mode 100644 index 0000000..e89d4e7 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/x-style.html
@@ -0,0 +1,67 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="style-util.html"> +<link rel="import" href="style-transformer.html"> +<link rel="import" href="style-defaults.html"> + +<!-- + +The `x-style` extension of the native `<style>` element allows defining styles +in the main document that can take advantage of several special features of +Polymer's styling system: + +* Document styles defined in an `x-style` will be shimmed to ensure they do +not leak into local DOM when running on browsers without non-native Shadow DOM. +* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on +browsers without non-native Shadow DOM. +* Custom properties used by Polymer's experimental shim for cross-scope styling +may be defined in an `x-style`. + +Example: + +```html +<!doctype html> +<html> +<head> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + + <style is="x-style"> + + /* Will be prevented from affecting local DOM of Polymer elements */ + * { + box-sizing: border-box; + } + + /* Can use /deep/ and ::shadow combinators */ + body /deep/ .my-special-view::shadow #thing-inside { + background: yellow; + } + + /* Custom properties that inherit down the document tree may be defined */ + body { + --my-toolbar-title-color: green; + } + + </style> + +</head> +<body> + + ... + +</body> +</html> +``` + +Note, all features of `x-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `x-style` extension should only be used for defining document styles, outside of a custom element's local DOM. + +--> + +</head><body><script src="x-style-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/attributes-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/attributes-extracted.js new file mode 100644 index 0000000..bd71fe3d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/attributes-extracted.js
@@ -0,0 +1,167 @@ + + + /** + * Support for `hostAttributes` property. + * + * hostAttributes: 'block vertical layout' + * + * `hostAttributes` is a space-delimited string of boolean attribute names to + * set true on each instance. + * + * Support for mapping attributes to properties. + * + * Properties that are configured in `properties` with a type are mapped + * to attributes. + * + * A value set in an attribute is deserialized into the specified + * data-type and stored into the matching property. + * + * Example: + * + * properties: { + * // values set to index attribute are converted to Number and propagated + * // to index property + * index: Number, + * // values set to label attribute are propagated to index property + * label: String + * } + * + * Types supported for deserialization: + * + * - Number + * - Boolean + * - String + * - Object (JSON) + * - Array (JSON) + * - Date + * + * This feature implements `attributeChanged` to support automatic + * propagation of attribute values at run-time. If you override + * `attributeChanged` be sure to call this base class method + * if you also want the standard behavior. + * + * @class base feature: attributes + */ + + Polymer.Base._addFeature({ + + _marshalAttributes: function() { + this._takeAttributes(); + }, + + _installHostAttributes: function(attributes) { + if (attributes) { + this.applyAttributes(this, attributes); + } + }, + + applyAttributes: function(node, attr$) { + for (var n in attr$) { + this.serializeValueToAttribute(attr$[n], n, this); + } + }, + + _takeAttributes: function() { + this._takeAttributesToModel(this); + }, + + _takeAttributesToModel: function(model) { + for (var i=0, l=this.attributes.length; i<l; i++) { + var a = this.attributes[i]; + var property = Polymer.CaseMap.dashToCamelCase(a.name); + var info = this.getPropertyInfo(property); + if (info || this._propertyEffects[property]) { + model[property] = + this.deserialize(a.value, info.type); + } + } + }, + + setAttributeToProperty: function(model, attrName) { + // Don't deserialize back to property if currently reflecting + if (!this._serializing) { + var propName = Polymer.CaseMap.dashToCamelCase(attrName); + if (propName in this.properties) { + var type = this.getPropertyType(propName); + var val = this.getAttribute(attrName); + model[propName] = this.deserialize(val, type); + } + } + }, + + _serializing: false, + reflectPropertyToAttribute: function(name) { + this._serializing = true; + this.serializeValueToAttribute(this[name], + Polymer.CaseMap.camelToDashCase(name)); + this._serializing = false; + }, + + serializeValueToAttribute: function(value, attribute, node) { + var str = this.serialize(value); + (node || this) + [str === undefined ? 'removeAttribute' : 'setAttribute'] + (attribute, str); + }, + + deserialize: function(value, type) { + switch (type) { + case Number: + value = Number(value); + break; + + case Boolean: + value = (value !== null); + break; + + case Object: + try { + value = JSON.parse(value); + } catch(x) { + // allow non-JSON literals like Strings and Numbers + } + break; + + case Array: + try { + value = JSON.parse(value); + } catch(x) { + value = null; + console.warn('Polymer::Attributes: couldn`t decode Array as JSON'); + } + break; + + case Date: + value = new Date(value); + break; + + case String: + default: + break; + } + return value; + }, + + serialize: function(value) { + switch (typeof value) { + case 'boolean': + return value ? '' : undefined; + + case 'object': + if (value instanceof Date) { + return value; + } else if (value) { + try { + return JSON.stringify(value); + } catch(x) { + return ''; + } + } + + default: + return value != null ? value : undefined; + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/attributes.html b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/attributes.html new file mode 100644 index 0000000..aba20ef7 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/attributes.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/case-map.html"> + +</head><body><script src="attributes-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/behaviors-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/behaviors-extracted.js new file mode 100644 index 0000000..824d0ec1 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/behaviors-extracted.js
@@ -0,0 +1,104 @@ + + + /** + * Automatically extend using objects referenced in `behaviors` array. + * + * someBehaviorObject = { + * accessors: { + * value: {type: Number, observer: '_numberChanged'} + * }, + * observers: [ + * // ... + * ], + * ready: function() { + * // called before prototoype's ready + * }, + * _numberChanged: function() {} + * }; + * + * Polymer({ + * + * behaviors: [ + * someBehaviorObject + * ] + * + * ... + * + * }); + * + * @class base feature: behaviors + */ + + Polymer.Base._addFeature({ + + behaviors: [], + + _prepBehaviors: function() { + this._flattenBehaviors(); + this._prepBehavior(this); + this.behaviors.forEach(function(b) { + this._mixinBehavior(b); + this._prepBehavior(b); + }, this); + }, + + _flattenBehaviors: function() { + var flat = []; + this.behaviors.forEach(function(b) { + if (!b) { + console.warn('Polymer: undefined behavior in [' + this.is + ']'); + } else if (b instanceof Array) { + flat = flat.concat(b); + } else { + flat.push(b); + } + }, this); + this.behaviors = flat; + }, + + _mixinBehavior: function(b) { + Object.getOwnPropertyNames(b).forEach(function(n) { + switch (n) { + case 'registered': + case 'properties': + case 'observers': + case 'listeners': + case 'keyPresses': + case 'hostAttributes': + case 'created': + case 'attached': + case 'detached': + case 'attributeChanged': + case 'configure': + case 'ready': + break; + default: + this.copyOwnProperty(n, b, this); + break; + } + }, this); + }, + + _doBehavior: function(name, args) { + this.behaviors.forEach(function(b) { + this._invokeBehavior(b, name, args); + }, this); + this._invokeBehavior(this, name, args); + }, + + _invokeBehavior: function(b, name, args) { + var fn = b[name]; + if (fn) { + fn.apply(this, args || Polymer.nar); + } + }, + + _marshalBehaviors: function() { + this.behaviors.forEach(function(b) { + this._marshalBehavior(b); + }, this); + this._marshalBehavior(this); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/behaviors.html b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/behaviors.html new file mode 100644 index 0000000..817ff8ec --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/behaviors.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="behaviors-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/constructor-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/constructor-extracted.js new file mode 100644 index 0000000..03cc041 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/constructor-extracted.js
@@ -0,0 +1,60 @@ + + + /** + * Generates a boilerplate constructor. + * + * XFoo = Polymer({ + * is: 'x-foo' + * }); + * ASSERT(new XFoo() instanceof XFoo); + * + * You can supply a custom constructor on the prototype. But remember that + * this constructor will only run if invoked **manually**. Elements created + * via `document.createElement` or from HTML _will not invoke this method_. + * + * Instead, we reuse the concept of `constructor` for a factory method which + * can take arguments. + * + * MyFoo = Polymer({ + * is: 'my-foo', + * constructor: function(foo) { + * this.foo = foo; + * } + * ... + * }); + * + * @class base feature: constructor + */ + + Polymer.Base._addFeature({ + + // registration-time + + _prepConstructor: function() { + // support both possible `createElement` signatures + this._factoryArgs = this.extends ? [this.extends, this.is] : [this.is]; + // thunk the constructor to delegate allocation to `createElement` + var ctor = function() { + return this._factory(arguments); + }; + if (this.hasOwnProperty('extends')) { + ctor.extends = this.extends; + } + // ensure constructor is set. The `constructor` property is + // not writable on Safari; note: Chrome requires the property + // to be configurable. + Object.defineProperty(this, 'constructor', {value: ctor, + writable: true, configurable: true}); + ctor.prototype = this; + }, + + _factory: function(args) { + var elt = document.createElement.apply(document, this._factoryArgs); + if (this.factoryImpl) { + this.factoryImpl.apply(elt, args); + } + return elt; + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/constructor.html b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/constructor.html new file mode 100644 index 0000000..21b3cd3 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/constructor.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="constructor-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/debouncer-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/debouncer-extracted.js new file mode 100644 index 0000000..6a0e1bf --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/debouncer-extracted.js
@@ -0,0 +1,47 @@ + + + Polymer.Base._addFeature({ + + _setupDebouncers: function() { + this._debouncers = {}; + }, + + /** + * Debounce signals. + * + * Call `debounce` to collapse multiple requests for a named task into + * one invocation which is made after the wait time has elapsed with + * no new request. + * + * debouncedClickAction: function(e) { + * // will not call `processClick` more than once per 100ms + * this.debounce('click', function() { + * this.processClick; + * }, 100); + * } + * + * @method debounce + * @param String {String} jobName A string to indentify the debounce job. + * @param Function {Function} callback A function that is called (with `this` context) when the wait time elapses. + * @param Number {Number} wait Time in milliseconds (ms) after the last signal that must elapse before invoking `callback` + * @type Handle + */ + debounce: function(jobName, callback, wait) { + this._debouncers[jobName] = Polymer.Debounce.call(this, + this._debouncers[jobName], callback, wait); + }, + + isDebouncerActive: function(jobName) { + var debouncer = this._debouncers[jobName]; + return debouncer && debouncer.finish; + }, + + flushDebouncer: function(jobName) { + var debouncer = this._debouncers[jobName]; + if (debouncer) { + debouncer.complete(); + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/debouncer.html b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/debouncer.html new file mode 100644 index 0000000..d68677d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/debouncer.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="debouncer-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/extends-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/extends-extracted.js new file mode 100644 index 0000000..8e88c87 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/extends-extracted.js
@@ -0,0 +1,69 @@ + + + /** + * Support `extends` property (for type-extension only). + * + * If the mixin is String-valued, the corresponding Polymer module + * is mixed in. + * + * Polymer({ + * is: 'pro-input', + * extends: 'input', + * ... + * }); + * + * Type-extension objects are created using `is` notation in HTML, or via + * the secondary argument to `document.createElement` (the type-extension + * rules are part of the Custom Elements specification, not something + * created by Polymer). + * + * Example: + * + * <!-- right: creates a pro-input element --> + * <input is="pro-input"> + * + * <!-- wrong: creates an unknown element --> + * <pro-input> + * + * <script> + * // right: creates a pro-input element + * var elt = document.createElement('input', 'pro-input'); + * + * // wrong: creates an unknown element + * var elt = document.createElement('pro-input'); + * <\script> + * + * @class base feature: extends + */ + + Polymer.Base._addFeature({ + + _prepExtends: function() { + if (this.extends) { + this.__proto__ = this.getExtendedPrototype(this.extends); + } + }, + + getExtendedPrototype: function(tag) { + return this.getExtendedNativePrototype(tag); + }, + + nativePrototypes: {}, // static + + getExtendedNativePrototype: function(tag) { + var p = this.nativePrototypes[tag]; + if (!p) { + var np = this.getNativePrototype(tag); + p = this.extend(Object.create(np), Polymer.Base); + this.nativePrototypes[tag] = p; + } + return p; + }, + + getNativePrototype: function(tag) { + // TODO(sjmiles): sad necessity + return Object.getPrototypeOf(document.createElement(tag)); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/extends.html b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/extends.html new file mode 100644 index 0000000..74ca1d8c --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/extends.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="extends-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/mixins-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/mixins-extracted.js new file mode 100644 index 0000000..3812b1b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/mixins-extracted.js
@@ -0,0 +1,30 @@ + + + /** + * Automatically extend using objects referenced in `mixins` array. + * + * Polymer({ + * + * mixins: [ + * someMixinObject + * ] + * + * ... + * + * }); + * + * @class base feature: mixins + */ + + Polymer.Base._addFeature({ + + _prepMixins: function() { + if (this.mixins) { + this.mixins.forEach(function(m) { + Polymer.Base.extend(this, m); + }, this); + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/mixins.html b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/mixins.html new file mode 100644 index 0000000..d37c5397 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/mixins.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="mixins-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/properties-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/properties-extracted.js new file mode 100644 index 0000000..5e861c3 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/properties-extracted.js
@@ -0,0 +1,92 @@ + + + /** + * Define property metadata. + * + * properties: { + * <property>: <Type || Object>, + * ... + * } + * + * Example: + * + * properties: { + * // `foo` property can be assigned via attribute, will be deserialized to + * // the specified data-type. All `properties` properties have this behavior. + * foo: String, + * + * // `bar` property has additional behavior specifiers. + * // type: as above, type for (de-)serialization + * // notify: true to send a signal when a value is set to this property + * // reflectToAttribute: true to serialize the property to an attribute + * // readOnly: if true, the property has no setter + * bar: { + * type: Boolean, + * notify: true + * } + * } + * + * By itself the properties feature doesn't do anything but provide property + * information. Other features use this information to control behavior. + * + * The `type` information is used by the `attributes` feature to convert + * String values in attributes to typed properties. The `bind` feature uses + * property information to control property access. + * + * Marking a property as `notify` causes a change in the property to + * fire a non-bubbling event called `<property>-changed`. Elements that + * have enabled two-way binding to the property use this event to + * observe changes. + * + * `readOnly` properties have a getter, but no setter. To set a read-only + * property, use the private setter method `_set_<property>(value)`. + * + * @class base feature: properties + */ + + // null object + Polymer.nob = Object.create(null); + + Polymer.Base._addFeature({ + + properties: { + }, + + getPropertyInfo: function(property) { + var info = this._getPropertyInfo(property, this.properties); + if (!info) { + this.behaviors.some(function(b) { + return info = this._getPropertyInfo(property, b.properties); + }, this); + } + return info || Polymer.nob; + }, + + _getPropertyInfo: function(property, properties) { + var p = properties && properties[property]; + if (typeof(p) === 'function') { + p = properties[property] = { + type: p + }; + } + return p; + }, + + getPropertyType: function(property) { + return this.getPropertyInfo(property).type; + }, + + isReadOnlyProperty: function(property) { + return this.getPropertyInfo(property).readOnly; + }, + + isNotifyProperty: function(property) { + return this.getPropertyInfo(property).notify; + }, + + isReflectedProperty: function(property) { + return this.getPropertyInfo(property).reflectToAttribute; + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/properties.html b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/properties.html new file mode 100644 index 0000000..58c1450 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/properties.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="properties-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/tag-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/tag-extracted.js new file mode 100644 index 0000000..05503009 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/tag-extracted.js
@@ -0,0 +1,18 @@ + + + Polymer.Base._addFeature({ + + _prepIs: function() { + if (!this.is) { + var module = + (document._currentScript || document.currentScript).parentNode; + if (module.localName === 'dom-module') { + var id = module.id || module.getAttribute('name') + || module.getAttribute('is') + this.is = id; + } + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/micro/tag.html b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/tag.html new file mode 100644 index 0000000..e143a5e0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/micro/tag.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="tag-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/mini/ready-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/ready-extracted.js new file mode 100644 index 0000000..9f049ac --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/ready-extracted.js
@@ -0,0 +1,142 @@ + + + /** + * Provides `ready` lifecycle callback which is called parent to child. + * + * This can be useful in a number of cases. Here are some examples: + * + * Setting a default property value that should have a side effect: To ensure + * the side effect, an element must set a default value no sooner than + * `created`; however, since `created` flows child to host, this is before the + * host has had a chance to set a property value on the child. The `ready` + * method solves this problem since it's called host to child. + * + * Dom distribution: To support reprojection efficiently, it's important to + * distribute from host to child in one shot. The `attachedCallback` mostly + * goes in the desired order except for elements that are in dom to start; in + * this case, all children are attached before the host element. Ready also + * addresses this case since it's guaranteed to be called host to child. + * + * @class standard feature: ready + */ + +(function() { + + var baseAttachedCallback = Polymer.Base.attachedCallback; + + Polymer.Base._addFeature({ + + hostStack: [], + + // for overriding + ready: function() { + }, + + // NOTE: The concept of 'host' is overloaded. There are two different + // notions: + // 1. an element hosts the elements in its local dom root. + // 2. an element hosts the elements on which it configures data. + // Practially, these notions are almost always coincident. + // Some special elements like templates may separate them. + // In order not to over-emphaisize this technical difference, we expose + // one concept to the user and it maps to the dom-related meaning of host. + // + // 1. set this element's `host` and push this element onto the `host`'s + // list of `client` elements + // 2. establish this element as the current hosting element (allows + // any elements we stamp to easily set host to us). + _pushHost: function(host) { + // NOTE: The `dataHost` of an element never changes. + this.dataHost = host = host || + Polymer.Base.hostStack[Polymer.Base.hostStack.length-1]; + // this.dataHost reflects the parent element who manages + // any bindings for the element. Only elements originally + // stamped from Polymer templates have a dataHost, and this + // never changes + if (host && host._clients) { + host._clients.push(this); + } + this._beginHost(); + }, + + _beginHost: function() { + Polymer.Base.hostStack.push(this); + if (!this._clients) { + this._clients = []; + } + }, + + _popHost: function() { + // this element is no longer the current hosting element + Polymer.Base.hostStack.pop(); + }, + + _tryReady: function() { + if (this._canReady()) { + this._ready(); + } + }, + + _canReady: function() { + return !this.dataHost || this.dataHost._clientsReadied; + }, + + _ready: function() { + // extension point + this._beforeClientsReady(); + this._readyClients(); + // extension point + this._afterClientsReady(); + this._readySelf(); + }, + + _readyClients: function() { + // prepare root + this._setupRoot(); + // logically distribute self + this._beginDistribute(); + // now fully prepare localChildren + var c$ = this._clients; + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + c._ready(); + } + // perform actual dom composition + this._finishDistribute(); + // ensure elements are attached if they are in the dom at ready time + // helps normalize attached ordering between native and polyfill ce. + // TODO(sorvell): worth perf cost? ~6% + // if (!Polymer.Settings.useNativeCustomElements) { + // CustomElements.takeRecords(); + // } + this._clientsReadied = true; + this._clients = null; + }, + + // mark readied and call `ready` + // note: called localChildren -> host + _readySelf: function() { + this._doBehavior('ready'); + this._readied = true; + if (this._attachedPending) { + this._attachedPending = false; + this.attachedCallback(); + } + }, + + // for system overriding + _beforeClientsReady: function() {}, + _afterClientsReady: function() {}, + + // normalize lifecycle: ensure attached occurs only after ready. + attachedCallback: function() { + if (this._readied) { + baseAttachedCallback.call(this); + } else { + this._attachedPending = true; + } + } + + }); + +})(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/mini/ready.html b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/ready.html new file mode 100644 index 0000000..3a3ad84 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/ready.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="ready-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shadow-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shadow-extracted.js new file mode 100644 index 0000000..2166e19 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shadow-extracted.js
@@ -0,0 +1,30 @@ + + + /** + Implements `shadyRoot` compatible dom scoping using native ShadowDOM. + */ + + // Transform styles if not using ShadowDOM or if flag is set. + + if (Polymer.Settings.useShadow) { + + Polymer.Base._addFeature({ + + // no-op's when ShadowDOM is in use + _poolContent: function() {}, + _beginDistribute: function() {}, + distributeContent: function() {}, + _distributeContent: function() {}, + _finishDistribute: function() {}, + + // create a shadowRoot + _createLocalRoot: function() { + this.createShadowRoot(); + this.shadowRoot.appendChild(this.root); + this.root = this.shadowRoot; + } + + }); + + } +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shadow.html b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shadow.html new file mode 100644 index 0000000..9d849e1 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shadow.html
@@ -0,0 +1,10 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/settings.html"> +</head><body><script src="shadow-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shady-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shady-extracted.js new file mode 100644 index 0000000..f86e5d5f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shady-extracted.js
@@ -0,0 +1,364 @@ + + + (function() { + /** + + Implements a pared down version of ShadowDOM's scoping, which is easy to + polyfill across browsers. + + */ + Polymer.Base._addFeature({ + + _prepShady: function() { + // Use this system iff localDom is needed. + this._useContent = this._useContent || Boolean(this._template); + if (this._useContent) { + this._template._hasInsertionPoint = + this._template.content.querySelector('content'); + } + }, + + // called as part of content initialization, prior to template stamping + _poolContent: function() { + if (this._useContent) { + // capture lightChildren to help reify dom scoping + saveLightChildrenIfNeeded(this); + } + }, + + // called as part of content initialization, after template stamping + _setupRoot: function() { + if (this._useContent) { + this._createLocalRoot(); + } + }, + + _createLocalRoot: function() { + this.shadyRoot = this.root; + this.shadyRoot._distributionClean = false; + this.shadyRoot._isShadyRoot = true; + this.shadyRoot._dirtyRoots = []; + // capture insertion point list + // TODO(sorvell): it's faster to do this via native qSA than annotator. + this.shadyRoot._insertionPoints = this._template._hasInsertionPoint ? + this.shadyRoot.querySelectorAll('content') : []; + // save logical tree info for shadyRoot. + saveLightChildrenIfNeeded(this.shadyRoot); + this.shadyRoot.host = this; + }, + + /** + * Return the element whose local dom within which this element + * is contained. This is a shorthand for + * `Polymer.dom(this).getOwnerRoot().host`. + */ + get domHost() { + var root = Polymer.dom(this).getOwnerRoot(); + return root && root.host; + }, + + /** + * Force this element to distribute its children to its local dom. + * A user should call `distributeContent` if distribution has been + * invalidated due to changes to selectors on child elements that + * effect distribution. For example, if an element contains an + * insertion point with <content select=".foo"> and a `foo` class is + * added to a child, then `distributeContent` must be called to update + * local dom distribution. + */ + distributeContent: function() { + if (this._useContent) { + this.shadyRoot._distributionClean = false; + this._distributeContent(); + } + }, + + _distributeContent: function() { + if (this._useContent && !this.shadyRoot._distributionClean) { + // logically distribute self + this._beginDistribute(); + this._distributeDirtyRoots(); + this._finishDistribute(); + } + }, + + _beginDistribute: function() { + if (this._useContent && hasInsertionPoint(this.shadyRoot)) { + // reset distributions + this._resetDistribution(); + // compute which nodes should be distributed where + // TODO(jmesserly): this is simplified because we assume a single + // ShadowRoot per host and no `<shadow>`. + this._distributePool(this.shadyRoot, this._collectPool()); + } + }, + + _distributeDirtyRoots: function() { + var c$ = this.shadyRoot._dirtyRoots; + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + c._distributeContent(); + } + this.shadyRoot._dirtyRoots = []; + }, + + _finishDistribute: function() { + // compose self + if (this._useContent) { + if (hasInsertionPoint(this.shadyRoot)) { + this._composeTree(); + } else { + if (!this.shadyRoot._hasDistributed) { + this.textContent = ''; + this.appendChild(this.shadyRoot); + } else { + // simplified non-tree walk composition + var children = this._composeNode(this); + this._updateChildNodes(this, children); + } + } + this.shadyRoot._hasDistributed = true; + this.shadyRoot._distributionClean = true; + } + }, + + // This is a polyfill for Element.prototype.matches, which is sometimes + // still prefixed. Alternatively we could just polyfill it somewhere. + // Note that the arguments are reversed from what you might expect. + elementMatches: function(selector, node) { + if (node === undefined) { + node = this; + } + return matchesSelector.call(node, selector); + }, + + // Many of the following methods are all conceptually static, but they are + // included here as "protected" methods to allow overriding. + + _resetDistribution: function() { + // light children + var children = getLightChildren(this); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child._destinationInsertionPoints) { + child._destinationInsertionPoints = undefined; + } + } + // insertion points + var root = this.shadyRoot; + var p$ = root._insertionPoints; + for (var j = 0; j < p$.length; j++) { + p$[j]._distributedNodes = []; + } + }, + + // Gather the pool of nodes that should be distributed. We will combine + // these with the "content root" to arrive at the composed tree. + _collectPool: function() { + var pool = []; + var children = getLightChildren(this); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (isInsertionPoint(child)) { + pool.push.apply(pool, child._distributedNodes); + } else { + pool.push(child); + } + } + return pool; + }, + + // perform "logical" distribution; note, no actual dom is moved here, + // instead elements are distributed into a `content._distributedNodes` + // array where applicable. + _distributePool: function(node, pool) { + var p$ = node._insertionPoints; + for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) { + this._distributeInsertionPoint(p, pool); + } + }, + + _distributeInsertionPoint: function(content, pool) { + // distribute nodes from the pool that this selector matches + var anyDistributed = false; + for (var i=0, l=pool.length, node; i < l; i++) { + node=pool[i]; + // skip nodes that were already used + if (!node) { + continue; + } + // distribute this node if it matches + if (this._matchesContentSelect(node, content)) { + distributeNodeInto(node, content); + // remove this node from the pool + pool[i] = undefined; + // since at least one node matched, we won't need fallback content + anyDistributed = true; + var parent = content.lightParent; + // dirty a shadyRoot if a change may trigger reprojection! + if (parent && parent.shadyRoot && + hasInsertionPoint(parent.shadyRoot)) { + parent.shadyRoot._distributionClean = false; + this.shadyRoot._dirtyRoots.push(parent); + } + } + } + // Fallback content if nothing was distributed here + if (!anyDistributed) { + var children = getLightChildren(content); + for (var j = 0; j < children.length; j++) { + distributeNodeInto(children[j], content); + } + } + }, + + // Reify dom such that it is at its correct rendering position + // based on logical distribution. + _composeTree: function() { + this._updateChildNodes(this, this._composeNode(this)); + var p$ = this.shadyRoot._insertionPoints; + for (var i=0, l=p$.length, p, parent; (i<l) && (p=p$[i]); i++) { + parent = p.lightParent || p.parentNode; + if (!parent._useContent && (parent !== this) && + (parent !== this.shadyRoot)) { + this._updateChildNodes(parent, this._composeNode(parent)); + } + } + }, + + // Returns the list of nodes which should be rendered inside `node`. + _composeNode: function(node) { + var children = []; + var c$ = getLightChildren(node.shadyRoot || node); + for (var i = 0; i < c$.length; i++) { + var child = c$[i]; + if (isInsertionPoint(child)) { + var distributedNodes = child._distributedNodes; + for (var j = 0; j < distributedNodes.length; j++) { + var distributedNode = distributedNodes[j]; + if (isFinalDestination(child, distributedNode)) { + children.push(distributedNode); + } + } + } else { + children.push(child); + } + } + return children; + }, + + // Ensures that the rendered node list inside `node` is `children`. + _updateChildNodes: function(node, children) { + var splices = + Polymer.ArraySplice.calculateSplices(children, node.childNodes); + for (var i=0; i<splices.length; i++) { + var s = splices[i]; + // remove + for (var j=0, c; j < s.removed.length; j++) { + c = s.removed[j]; + if (c.previousSibling == children[s.index-1]) { + remove(c); + } + } + // insert + for (var idx=s.index, ch, o; idx < s.index + s.addedCount; idx++) { + ch = children[idx]; + o = node.childNodes[idx]; + while (o && o === ch) { + o = o.nextSibling; + } + insertBefore(node, ch, o); + } + } + }, + + _matchesContentSelect: function(node, contentElement) { + var select = contentElement.getAttribute('select'); + // no selector matches all nodes (including text) + if (!select) { + return true; + } + select = select.trim(); + // same thing if it had only whitespace + if (!select) { + return true; + } + // selectors can only match Elements + if (!(node instanceof Element)) { + return false; + } + // only valid selectors can match: + // TypeSelector + // * + // ClassSelector + // IDSelector + // AttributeSelector + // negation + var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/; + if (!validSelectors.test(select)) { + return false; + } + return this.elementMatches(select, node); + }, + + // system override point + _elementAdd: function() {}, + + // system override point + _elementRemove: function() {} + + }); + + var saveLightChildrenIfNeeded = Polymer.DomApi.saveLightChildrenIfNeeded; + var getLightChildren = Polymer.DomApi.getLightChildren; + var matchesSelector = Polymer.DomApi.matchesSelector; + var hasInsertionPoint = Polymer.DomApi.hasInsertionPoint; + + function distributeNodeInto(child, insertionPoint) { + insertionPoint._distributedNodes.push(child); + var points = child._destinationInsertionPoints; + if (!points) { + child._destinationInsertionPoints = [insertionPoint]; + // TODO(sorvell): _destinationInsertionPoints may not be cleared when + // nodes are dynamically added/removed, therefore test before adding + // insertion points. + } else if (points.indexOf(insertionPoint) < 0) { + points.push(insertionPoint); + } + } + + function isFinalDestination(insertionPoint, node) { + var points = node._destinationInsertionPoints; + return points && points[points.length - 1] === insertionPoint; + } + + function isInsertionPoint(node) { + // TODO(jmesserly): we could add back 'shadow' support here. + return node.localName == 'content'; + } + + var nativeInsertBefore = Element.prototype.insertBefore; + var nativeRemoveChild = Element.prototype.removeChild; + + function insertBefore(parentNode, newChild, refChild) { + // remove child from its old parent first + remove(newChild); + // make sure we never lose logical DOM information: + // if the parentNode doesn't have lightChildren, save that information now. + saveLightChildrenIfNeeded(parentNode); + // insert it into the real DOM + nativeInsertBefore.call(parentNode, newChild, refChild || null); + } + + function remove(node) { + var parentNode = node.parentNode; + if (parentNode) { + // make sure we never lose logical DOM information: + // if the parentNode doesn't have lightChildren, save that information now. + saveLightChildrenIfNeeded(parentNode); + // remove it from the real DOM + nativeRemoveChild.call(parentNode, node); + } + } + + })(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shady.html b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shady.html new file mode 100644 index 0000000..041ba0f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/shady.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/array-splice.html"> +<link rel="import" href="../lib/dom-api.html"> +</head><body><script src="shady-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/mini/template-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/template-extracted.js new file mode 100644 index 0000000..75d4c3d --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/template-extracted.js
@@ -0,0 +1,46 @@ + + + /** + * Automatic template management. + * + * The `template` feature locates and instances a `<template>` element + * corresponding to the current Polymer prototype. + * + * The `<template>` element may be immediately preceeding the script that + * invokes `Polymer()`. + * + * @class standard feature: template + */ + + Polymer.Base._addFeature({ + + _prepTemplate: function() { + // locate template using dom-module + this._template = + this._template || Polymer.DomModule.import(this.is, 'template'); + // fallback to look at the node previous to the currentScript. + if (!this._template) { + var script = document._currentScript || document.currentScript; + var prev = script && script.previousElementSibling; + if (prev && prev.localName === 'template') { + this._template = prev; + } + } + }, + + _stampTemplate: function() { + if (this._template) { + // note: root is now a fragment which can be manipulated + // while not attached to the element. + this.root = this.instanceTemplate(this._template); + } + }, + + instanceTemplate: function(template) { + var dom = + document.importNode(template._content || template.content, true); + return dom; + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/mini/template.html b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/template.html new file mode 100644 index 0000000..1849599e4 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/mini/template.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="template-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/polymer-lib.html b/third_party/polymer/v0_8/components-chromium/polymer/src/polymer-lib.html new file mode 100644 index 0000000..078f1d35 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/polymer-lib.html
@@ -0,0 +1,15 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="lib/settings.html"> +<link rel="import" href="lib/polymer-bootstrap.html"> +<link rel="import" href="lib/lang.html"> +<link rel="import" href="lib/base.html"> +<link rel="import" href="lib/dom-module.html">
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/annotations-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/annotations-extracted.js new file mode 100644 index 0000000..54230fe0 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/annotations-extracted.js
@@ -0,0 +1,183 @@ + + +/** + * Scans a template to produce an annotation object that stores expression + * metadata along with information to associate the metadata with nodes in an + * instance. + * + * Elements with `id` in the template are noted and marshaled into an + * the `$` hash in an instance. + * + * Example + * + * <template> + * <div id="foo"></div> + * </template> + * <script> + * Polymer({ + * task: function() { + * this.$.foo.style.color = 'red'; + * } + * }); + * </script> + * + * Other expressions that are noted include: + * + * Double-mustache annotations in text content. The annotation must be the only + * content in the tag, compound expressions are not (currently) supported. + * + * <[tag]>{{path.to.host.property}}<[tag]> + * + * Double-mustache annotations in an attribute. + * + * <[tag] someAttribute="{{path.to.host.property}}"><[tag]> + * + * Only immediate host properties can automatically trigger side-effects. + * Setting `host.path` in the example above triggers the binding, setting + * `host.path.to.host.property` does not. + * + * `on-` style event declarations. + * + * <[tag] on-<event-name>="{{hostMethodName}}"><[tag]> + * + * Note: **the `annotations` feature does not actually implement the behaviors + * associated with these expressions, it only captures the data**. + * + * Other optional features contain actual data implementations. + * + * @class standard feature: annotations + */ + +/* + +Scans a template to produce an annotation map that stores expression metadata +and information that associates the metadata to nodes in a template instance. + +Supported annotations are: + + * id attributes + * binding annotations in text nodes + * double-mustache expressions: {{expression}} + * double-bracket expressions: [[expression]] + * binding annotations in attributes + * attribute-bind expressions: name="{{expression}} || [[expression]]" + * property-bind expressions: name*="{{expression}} || [[expression]]" + * property-bind expressions: name:="expression" + * event annotations + * event delegation directives: on-<eventName>="expression" + +Generated data-structure: + + [ + { + id: '<id>', + events: [ + { + mode: ['auto'|''], + name: '<name>' + value: '<expression>' + }, ... + ], + bindings: [ + { + kind: ['text'|'attribute'|'property'], + mode: ['auto'|''], + name: '<name>' + value: '<expression>' + }, ... + ], + // TODO(sjmiles): confusingly, this is annotation-parent, not node-parent + parent: <reference to parent annotation>, + index: <integer index in parent's childNodes collection> + }, + ... + ] + +TODO(sjmiles): this module should produce either syntactic metadata +(e.g. double-mustache, double-bracket, star-attr), or semantic metadata +(e.g. manual-bind, auto-bind, property-bind). Right now it's half and half. + +*/ + + Polymer.Base._addFeature({ + + // registration-time + + _prepAnnotations: function() { + if (!this._template) { + this._notes = []; + } else { + // TODO(sorvell): ad hoc method of plugging behavior into Annotations + Polymer.Annotations.prepElement = this._prepElement.bind(this); + this._notes = Polymer.Annotations.parseAnnotations(this._template); + Polymer.Annotations.prepElement = null; + } + }, + + _prepElement: function(element) { + Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument); + }, + + // instance-time + + findAnnotatedNode: Polymer.Annotations.findAnnotatedNode, + + // marshal all teh things + _marshalAnnotationReferences: function() { + if (this._template) { + this._marshalIdNodes(); + this._marshalAnnotatedNodes(); + this._marshalAnnotatedListeners(); + } + }, + + // push configuration references at configure time + _configureAnnotationReferences: function() { + this._configureTemplateContent(); + }, + + // nested template contents have been stored prototypically to avoid + // unnecessary duplication, here we put references to the + // indirected contents onto the nested template instances + _configureTemplateContent: function() { + this._notes.forEach(function(note) { + if (note.templateContent) { + var template = this.findAnnotatedNode(this.root, note); + template._content = note.templateContent; + } + }, this); + }, + + // construct `$` map (from id annotations) + _marshalIdNodes: function() { + this.$ = {}; + this._notes.forEach(function(a) { + if (a.id) { + this.$[a.id] = this.findAnnotatedNode(this.root, a); + } + }, this); + }, + + // concretize `_nodes` map (from anonymous annotations) + _marshalAnnotatedNodes: function() { + if (this._nodes) { + this._nodes = this._nodes.map(function(a) { + return this.findAnnotatedNode(this.root, a); + }, this); + } + }, + + // install event listeners (from event annotations) + _marshalAnnotatedListeners: function() { + this._notes.forEach(function(a) { + if (a.events && a.events.length) { + var node = this.findAnnotatedNode(this.root, a); + a.events.forEach(function(e) { + this.listen(node, e.name, e.value); + }, this); + } + }, this); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/annotations.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/annotations.html new file mode 100644 index 0000000..6e51799 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/annotations.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><!-- employ 'Annotations' module --><html><head><link rel="import" href="../lib/annotations/annotations.html"> +<link rel="import" href="../lib/resolve-url.html"> +</head><body><script src="annotations-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/configure-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/configure-extracted.js new file mode 100644 index 0000000..e0ac937 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/configure-extracted.js
@@ -0,0 +1,173 @@ + + + /* + Process inputs efficiently via a configure lifecycle callback. + Configure is called top-down, host before local dom. Users should + implement configure to supply a set of default values for the element by + returning an object containing the properties and values to set. + + Configured values are not immediately set, instead they are set when + an element becomes ready, after its local dom is ready. This ensures + that any user change handlers are not called before ready time. + + */ + + /* + Implementation notes: + + Configured values are collected into _config. At ready time, properties + are set to the values in _config. This ensures properties are set child + before host and change handlers are called only at ready time. The host + will reset a value already propagated to a child, but this is not + inefficient because of dirty checking at the set point. + + Bind notification events are sent when properties are set at ready time + and thus received by the host before it is ready. Since notifications result + in property updates and this triggers side effects, handling notifications + is deferred until ready time. + + In general, events can be heard before an element is ready. This may occur + when a user sends an event in a change handler or listens to a data event + directly (on-foo-changed). + */ + + Polymer.Base._addFeature({ + + // storage for configuration + _setupConfigure: function(initialConfig) { + this._config = initialConfig || {}; + this._handlers = []; + }, + + // static attributes are deserialized into _config + _takeAttributes: function() { + this._takeAttributesToModel(this._config); + }, + + // at configure time values are stored in _config + _configValue: function(name, value) { + this._config[name] = value; + }, + + // Override polymer-mini thunk + _beforeClientsReady: function() { + this._configure(); + }, + + // configure: returns user supplied default property values + // combines with _config to create final property values + _configure: function() { + this._configureAnnotationReferences(); + // get individual default values from property configs + var config = {}; + this._configureProperties(this.properties, config); + // behave! + this.behaviors.forEach(function(b) { + this._configureProperties(b.properties, config); + }, this); + // get add'l default values from central configure + // combine defaults returned from configure with inputs in _config + this._mixinConfigure(config, this._config); + // this is the new _config, which are the final values to be applied + this._config = config; + // pass configuration data to bindings + this._distributeConfig(this._config); + }, + + _configureProperties: function(properties, config) { + for (i in properties) { + var c = properties[i]; + if (c.value !== undefined) { + var value = c.value; + if (typeof value == 'function') { + // pass existing config values (this._config) to value function + value = value.call(this, this._config); + } + config[i] = value; + } + } + }, + + _mixinConfigure: function(a, b) { + for (var prop in b) { + if (!this.isReadOnlyProperty(prop)) { + a[prop] = b[prop]; + } + } + }, + + // distribute config values to bound nodes. + _distributeConfig: function(config) { + var fx$ = this._propertyEffects; + if (fx$) { + for (var p in config) { + var fx = fx$[p]; + if (fx) { + for (var i=0, l=fx.length, x; (i<l) && (x=fx[i]); i++) { + if (x.kind === 'annotation') { + var node = this._nodes[x.effect.index]; + // seeding configuration only + if (node._configValue) { + var value = (p === x.effect.value) ? config[p] : + this.getPathValue(x.effect.value, config); + node._configValue(x.effect.name, value); + } + } + } + } + } + } + }, + + // Override polymer-mini thunk + _afterClientsReady: function() { + this._applyConfig(this._config); + this._flushHandlers(); + }, + + // NOTE: values are already propagated to children via + // _distributeConfig so propagation triggered by effects here is + // redundant, but safe due to dirty checking + _applyConfig: function(config) { + for (var n in config) { + // Don't stomp on values that may have been set by other side effects + if (this[n] === undefined) { + // Call _propertySet for any properties with accessors, which will + // initialize read-only properties also + // TODO(kschaaf): consider passing fromAbove here to prevent + // unnecessary notify for: 1) possible perf, 2) debuggability + var effects = this._propertyEffects[n]; + if (effects) { + this._propertySet(n, config[n], effects); + } else { + this[n] = config[n]; + } + } + } + }, + + // NOTE: Notifications can be processed before ready since + // they are sent at *child* ready time. Since notifications cause side + // effects and side effects must not be processed before ready time, + // handling is queue/defered until then. + _notifyListener: function(fn, e) { + if (!this._clientsReadied) { + this._queueHandler([fn, e, e.target]); + } else { + return fn.call(this, e, e.target); + } + }, + + _queueHandler: function(args) { + this._handlers.push(args); + }, + + _flushHandlers: function() { + var h$ = this._handlers; + for (var i=0, l=h$.length, h; (i<l) && (h=h$[i]); i++) { + h[0].call(this, h[1], h[2]); + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/configure.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/configure.html new file mode 100644 index 0000000..3bfff54 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/configure.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="configure-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/effects-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/effects-extracted.js new file mode 100644 index 0000000..7f8ce40 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/effects-extracted.js
@@ -0,0 +1,197 @@ + + + /** + * Support for property side effects. + * + * Key for effect objects: + * + * property | ann | anCmp | cmp | obs | cplxOb | description + * ---------|-----|-------|-----|-----|--------|---------------------------------------- + * method | | X | X | X | X | function name to call on instance + * args | | X | X | | X | list of all arg descriptors for fn + * arg | | X | X | | X | arg descriptor for effect + * property | | | X | X | | property for effect to set or get + * name | X | | | | | annotation value (text inside {{...}}) + * kind | X | X | | | | binding type (property or attribute) + * index | X | X | | | | node index to set + * + */ + + Polymer.Base._addFeature({ + + _addPropertyEffect: function(property, kind, effect) { + // TODO(sjmiles): everything to the right of the first '.' is lost, implies + // there is some duplicate information flow (not the only sign) + var model = property.split('.').shift(); + Polymer.Bind.addPropertyEffect(this, model, kind, effect); + }, + + // prototyping + + _prepEffects: function() { + Polymer.Bind.prepareModel(this); + this._addAnnotationEffects(this._notes); + }, + + _prepBindings: function() { + Polymer.Bind.createBindings(this); + }, + + _addPropertyEffects: function(effects) { + if (effects) { + for (var n in effects) { + var effect = effects[n]; + if (effect.observer) { + this._addObserverEffect(n, effect.observer); + } + if (effect.computed) { + this._addComputedEffect(n, effect.computed); + } + if (effect.notify) { + this._addPropertyEffect(n, 'notify'); + } + if (effect.reflectToAttribute) { + this._addPropertyEffect(n, 'reflect'); + } + if (this.isReadOnlyProperty(n)) { + // Ensure accessor is created + Polymer.Bind.ensurePropertyEffects(this, n); + } + } + } + }, + + _parseMethod: function(expression) { + var m = expression.match(/(\w*)\((.*)\)/); + if (m) { + return { + method: m[1], + args: m[2].split(/[^\w.*]+/).map(this._parseArg) + }; + } + }, + + _parseArg: function(arg) { + var a = { name: arg }; + a.structured = arg.indexOf('.') > 0; + if (a.structured) { + a.wildcard = (arg.slice(-2) == '.*'); + if (a.wildcard) { + a.name = arg.slice(0, -2); + } + } + return a; + }, + + _addComputedEffect: function(name, expression) { + var sig = this._parseMethod(expression); + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'compute', { + method: sig.method, + args: sig.args, + arg: arg, + property: name + }); + }, this); + }, + + _addObserverEffect: function(property, observer) { + this._addPropertyEffect(property, 'observer', { + method: observer, + property: property + }); + }, + + _addComplexObserverEffects: function(observers) { + if (observers) { + observers.forEach(function(observer) { + this._addComplexObserverEffect(observer); + }, this); + } + }, + + _addComplexObserverEffect: function(observer) { + var sig = this._parseMethod(observer); + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'complexObserver', { + method: sig.method, + args: sig.args, + arg: arg + }); + }, this); + }, + + _addAnnotationEffects: function(notes) { + // create a virtual annotation list, must be concretized at instance time + this._nodes = []; + // process annotations that have been parsed from template + notes.forEach(function(note) { + // where to find the node in the concretized list + var index = this._nodes.push(note) - 1; + note.bindings.forEach(function(binding) { + this._addAnnotationEffect(binding, index); + }, this); + }, this); + }, + + _addAnnotationEffect: function(note, index) { + // TODO(sjmiles): annotations have 'effects' proper and 'listener' + if (Polymer.Bind._shouldAddListener(note)) { + // <node>.on.<dash-case-property>-changed: <path> = e.detail.value + Polymer.Bind._addAnnotatedListener(this, index, + note.name, note.value, note.event); + } + var sig = this._parseMethod(note.value); + if (sig) { + this._addAnnotatedComputationEffect(sig, note, index); + } else { + // capture the node index + note.index = index; + // discover top-level property (model) from path + var model = note.value.split('.').shift(); + // add 'annotation' binding effect for property 'model' + this._addPropertyEffect(model, 'annotation', note); + } + }, + + _addAnnotatedComputationEffect: function(sig, note, index) { + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'annotatedComputation', { + kind: note.kind, + method: sig.method, + args: sig.args, + arg: arg, + property: note.name, + index: index + }); + }, this); + }, + + // instancing + + _marshalInstanceEffects: function() { + Polymer.Bind.prepareInstance(this); + Polymer.Bind.setupBindListeners(this); + }, + + _applyEffectValue: function(value, info) { + var node = this._nodes[info.index]; + // TODO(sorvell): ideally, the info object is normalized for easy + // lookup here. + var property = info.property || info.name || 'textContent'; + // special processing for 'class' and 'className'; 'class' handled + // when attr is serialized. + if (info.kind == 'attribute') { + this.serializeValueToAttribute(value, property, node); + } else { + // TODO(sorvell): consider pre-processing this step so we don't need + // this lookup. + if (property === 'className') { + value = this._scopeElementClass(node, value); + } + return node[property] = value; + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/effects.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/effects.html new file mode 100644 index 0000000..5ed58ecc --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/effects.html
@@ -0,0 +1,12 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/bind/accessors.html"> +<link rel="import" href="../lib/bind/effects.html"> + +</head><body><script src="effects-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/events-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/events-extracted.js new file mode 100644 index 0000000..4f6a3e7 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/events-extracted.js
@@ -0,0 +1,84 @@ + + + /** + * Supports `listeners` and `keyPresses` objects. + * + * Example: + * + * using('Base', function(Base) { + * + * Polymer({ + * + * listeners: { + * // `click` events on the host are delegated to `clickHandler` + * 'click': 'clickHandler' + * }, + * + * keyPresses: { + * // 'ESC' key presses are delegated to `escHandler` + * Base.ESC_KEY: 'escHandler' + * }, + * + * ... + * + * }); + * + * }); + * + * @class standard feature: events + * + */ + + Polymer.Base._addFeature({ + + listeners: {}, + + _listenListeners: function(listeners) { + var node, name, key; + for (key in listeners) { + if (key.indexOf('.') < 0) { + node = this; + name = key; + } else { + name = key.split('.'); + node = this.$[name[0]]; + name = name[1]; + } + this.listen(node, name, listeners[key]); + } + }, + + listen: function(node, eventName, methodName) { + var host = this; + var handler = function(e) { + if (host[methodName]) { + host[methodName](e, e.detail); + } else { + console.warn('[%s].[%s]: event handler [%s] is null in scope (%o)', + node.localName, eventName, methodName, host); + } + }; + switch (eventName) { + case 'tap': + case 'track': + Polymer.Gestures.add(eventName, node, handler); + break; + + default: + node.addEventListener(eventName, handler); + break; + } + }, + + keyCodes: { + ESC_KEY: 27, + ENTER_KEY: 13, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + SPACE: 32 + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/events.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/events.html new file mode 100644 index 0000000..28b6ca9 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/events.html
@@ -0,0 +1,11 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/gestures.html"> + +</head><body><script src="events-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/notify-path-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/notify-path-extracted.js new file mode 100644 index 0000000..2dc890cc --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/notify-path-extracted.js
@@ -0,0 +1,240 @@ + + + /** + * Changes to an object sub-field (aka "path") via a binding + * (e.g. `<x-foo value="{{item.subfield}}"`) will notify other elements bound to + * the same object automatically. + * + * When modifying a sub-field of an object imperatively + * (e.g. `this.item.subfield = 42`), in order to have the new value propagated + * to other elements, a special `setPathValue(path, value)` API is provided. + * `setPathValue` sets the object field at the path specified, and then notifies the + * binding system so that other elements bound to the same path will update. + * + * Example: + * + * Polymer({ + * + * is: 'x-date', + * + * properties: { + * date: { + * type: Object, + * notify: true + * } + * }, + * + * attached: function() { + * this.date = {}; + * setInterval(function() { + * var d = new Date(); + * // Required to notify elements bound to date of changes to sub-fields + * // this.date.seconds = d.getSeconds(); <-- Will not notify + * this.setPathValue('date.seconds', d.getSeconds()); + * this.setPathValue('date.minutes', d.getMinutes()); + * this.setPathValue('date.hours', d.getHours() % 12); + * }.bind(this), 1000); + * } + * + * }); + * + * Allows bindings to `date` sub-fields to update on changes: + * + * <x-date date="{{date}}"></x-date> + * + * Hour: <span>{{date.hours}}</span> + * Min: <span>{{date.minutes}}</span> + * Sec: <span>{{date.seconds}}</span> + * + * @class data feature: path notification + */ + + Polymer.Base._addFeature({ + /** + Notify that a path has changed. For example: + + this.item.user.name = 'Bob'; + this.notifyPath('item.user.name', this.item.user.name); + + Returns true if notification actually took place, based on + a dirty check of whether the new value was already known + */ + notifyPath: function(path, value, fromAbove) { + var old = this._propertySet(path, value); + // manual dirty checking for now... + if (old !== value) { + // console.group((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value); + // Take path effects at this level for exact path matches, + // and notify down for any bindings to a subset of this path + this._pathEffector(path, value); + // Send event to notify the path change upwards + // Optimization: don't notify up if we know the notification + // is coming from above already (avoid wasted event dispatch) + if (!fromAbove) { + // TODO(sorvell): should only notify if notify: true? + this._notifyPath(path, value); + } + // console.groupEnd((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value); + } + }, + + /** + Convienence method for setting a value to a path and calling + notify path + */ + setPathValue: function(path, value) { + var parts = path.split('.'); + if (parts.length > 1) { + var last = parts.pop(); + var prop = this; + while (parts.length) { + prop = prop[parts.shift()]; + if (!prop) { + return; + } + } + // TODO(kschaaf): want dirty-check here? + // if (prop[last] !== value) { + prop[last] = value; + this.notifyPath(path, value); + // } + } else { + this[path] = value; + } + }, + + getPathValue: function(path, root) { + var parts = path.split('.'); + var last = parts.pop(); + var prop = root || this; + while (parts.length) { + prop = prop[parts.shift()]; + if (!prop) { + return; + } + } + return prop[last]; + }, + + // TODO(kschaaf): This machine can be optimized to memoize compiled path + // effectors as new paths are notified for performance, since it involves + // a fair amount of runtime lookup + _pathEffector: function(path, value) { + // get root property + var model = this._modelForPath(path); + // search property effects of the root property for 'annotation' effects + var fx$ = this._propertyEffects[model]; + if (fx$) { + fx$.forEach(function(fx) { + var fxFn = this[fx.kind + 'PathEffect']; + if (fxFn) { + fxFn.call(this, path, value, fx.effect); + } + }, this); + } + // notify runtime-bound paths + if (this._boundPaths) { + this._notifyBoundPaths(path, value); + } + }, + + annotationPathEffect: function(path, value, effect) { + if (effect.value === path || effect.value.indexOf(path + '.') === 0) { + // TODO(sorvell): ideally the effect function is on this prototype + // so we don't have to call it like this. + Polymer.Bind.annotationEffect.call(this, path, value, effect); + } else if ((path.indexOf(effect.value + '.') === 0) && !effect.negate) { + // locate the bound node + var node = this._nodes[effect.index]; + if (node && node.notifyPath) { + var p = this._fixPath(effect.name , effect.value, path); + node.notifyPath(p, value, true); + } + } + }, + + complexObserverPathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.complexObserverEffect.call(this, path, value, effect); + } + }, + + computePathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.computeEffect.call(this, path, value, effect); + } + }, + + annotatedComputationPathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.annotatedComputationEffect.call(this, path, value, effect); + } + }, + + _pathMatchesEffect: function(path, effect) { + var effectArg = effect.arg.name; + return (effectArg == path) || + (effectArg.indexOf(path + '.') === 0) || + (effect.arg.wildcard && path.indexOf(effectArg) === 0); + }, + + bindPaths: function(to, from) { + this._boundPaths = this._boundPaths || {}; + if (from) { + this._boundPaths[to] = from; + // this.setPathValue(to, this.getPathValue(from)); + } else { + this.unbindPath(to); + // this.setPathValue(to, from); + } + }, + + unbindPaths: function(path) { + if (this._boundPaths) { + delete this._boundPaths[path]; + } + }, + + _notifyBoundPaths: function(path, value) { + var from, to; + for (var a in this._boundPaths) { + var b = this._boundPaths[a]; + if (path.indexOf(a + '.') == 0) { + from = a; + to = b; + break; + } + if (path.indexOf(b + '.') == 0) { + from = b; + to = a; + break; + } + } + if (from && to) { + var p = this._fixPath(to, from, path); + this.notifyPath(p, value); + } + }, + + _fixPath: function(property, root, path) { + return property + path.slice(root.length); + }, + + _notifyPath: function(path, value) { + var rootName = this._modelForPath(path); + var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName); + var eventName = dashCaseName + this._EVENT_CHANGED; + this.fire(eventName, { + path: path, + value: value + }, {bubbles: false}); + }, + + _modelForPath: function(path) { + return path.split('.').shift(); + }, + + _EVENT_CHANGED: '-changed', + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/notify-path.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/notify-path.html new file mode 100644 index 0000000..696a61df --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/notify-path.html
@@ -0,0 +1,10 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/case-map.html"> +</head><body><script src="notify-path-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/resolveUrl-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/resolveUrl-extracted.js new file mode 100644 index 0000000..eae6108 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/resolveUrl-extracted.js
@@ -0,0 +1,17 @@ + + + Polymer.Base._addFeature({ + + resolveUrl: function(url) { + // TODO(sorvell): do we want to put the module reference on the prototype? + var module = Polymer.DomModule.import(this.is); + var root = ''; + if (module) { + var assetPath = module.getAttribute('assetpath') || ''; + root = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI); + } + return Polymer.ResolveUrl.resolveUrl(url, root); + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/resolveUrl.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/resolveUrl.html new file mode 100644 index 0000000..fa12e4b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/resolveUrl.html
@@ -0,0 +1,9 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head></head><body><script src="resolveUrl-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/styling-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/styling-extracted.js new file mode 100644 index 0000000..6408590 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/styling-extracted.js
@@ -0,0 +1,179 @@ + + + (function() { + + var prepTemplate = Polymer.Base._prepTemplate; + var prepElement = Polymer.Base._prepElement; + var baseStampTemplate = Polymer.Base._stampTemplate; + var nativeShadow = Polymer.Settings.useNativeShadow; + + Polymer.Base._addFeature({ + + // declaration-y + _prepTemplate: function() { + prepTemplate.call(this); + var port = Polymer.DomModule.import(this.is); + if (this._encapsulateStyle === undefined) { + this._encapsulateStyle = + Boolean(port && !nativeShadow); + } + // scope css + // NOTE: dom scoped via annotations + if (nativeShadow || this._encapsulateStyle) { + this._scopeCss(); + } + }, + + _prepElement: function(element) { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.element(element, this.is, + this._scopeCssViaAttr); + } + prepElement.call(this, element); + }, + + _scopeCss: function() { + this._styles = this._prepareStyles(); + this._scopeStyles(this._styles); + }, + + // search for extra style modules via `styleModules` + _prepareStyles: function() { + var cssText = '', m$ = this.styleModules; + if (m$) { + for (var i=0, l=m$.length, m; (i<l) && (m=m$[i]); i++) { + cssText += this._cssFromModule(m); + } + } + cssText += this._cssFromModule(this.is); + var styles = []; + if (cssText) { + var s = document.createElement('style'); + s.textContent = cssText; + styles.push(s); + } + return styles; + }, + + // returns cssText of styles in a given module; also un-applies any + // styles that apply to the document. + _cssFromModule: function(moduleId) { + var m = Polymer.DomModule.import(moduleId); + if (m && !m._cssText) { + var cssText = ''; + var e$ = Array.prototype.slice.call(m.querySelectorAll('style')); + this._unapplyStyles(e$); + e$ = e$.concat(Array.prototype.map.call( + m.querySelectorAll(REMOTE_SHEET_SELECTOR), function(l) { + return l.import.body; + })); + m._cssText = this._cssFromStyles(e$); + } + return m && m._cssText || ''; + }, + + _cssFromStyles: function(styles) { + var cssText = ''; + for (var i=0, l=styles.length, s; (i<l) && (s = styles[i]); i++) { + if (s && s.textContent) { + cssText += + Polymer.ResolveUrl.resolveCss(s.textContent, s.ownerDocument); + } + } + return cssText; + }, + + _unapplyStyles: function(styles) { + for (var i=0, l=styles.length, s; (i<l) && (s = styles[i]); i++) { + s = s.__appliedElement || s; + s.parentNode.removeChild(s); + } + }, + + _scopeStyles: function(styles) { + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + // transform style if necessary and place in correct place + if (nativeShadow) { + if (this._template) { + this._template.content.appendChild(s); + } + } else { + var rules = this._rulesForStyle(s); + Polymer.StyleUtil.applyCss( + Polymer.StyleTransformer.css(rules, this.is, this.extends, + null, this._scopeCssViaAttr), + this.is, null, true); + } + } + }, + + _rulesForStyle: function(style) { + if (!style.__cssRules) { + style.__cssRules = Polymer.StyleUtil.parser.parse(style.textContent); + } + return style.__cssRules; + }, + + // instance-y + _stampTemplate: function() { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.host(this, this.is); + } + baseStampTemplate.call(this); + }, + + // add scoping class whenever an element is added to localDOM + _elementAdd: function(node) { + if (this._encapsulateStyle && !node.__styleScoped) { + Polymer.StyleTransformer.dom(node, this.is, this._scopeCssViaAttr); + } + }, + + // remove scoping class whenever an element is removed from localDOM + _elementRemove: function(node) { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.dom(node, this.is, this._scopeCssViaAttr, true); + } + }, + + /** + * Apply style scoping to the specified `container` and all its + * descendants. If `shoudlObserve` is true, changes to the container are + * monitored via mutation observer and scoping is applied. + */ + scopeSubtree: function(container, shouldObserve) { + if (nativeShadow) { + return; + } + var self = this; + var scopify = function(node) { + if (node.nodeType === Node.ELEMENT_NODE) { + node.className = self._scopeElementClass(node, node.className); + var n$ = node.querySelectorAll('*'); + Array.prototype.forEach.call(n$, function(n) { + n.className = self._scopeElementClass(n, n.className); + }); + } + }; + scopify(container); + if (shouldObserve) { + var mo = new MutationObserver(function(mxns) { + mxns.forEach(function(m) { + if (m.addedNodes) { + for (var i=0; i < m.addedNodes.length; i++) { + scopify(m.addedNodes[i]); + } + } + }); + }); + mo.observe(container, {childList: true, subtree: true}); + return mo; + } + } + + }); + + var REMOTE_SHEET_SELECTOR = 'link[rel=import][type~=css]'; + + })(); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/styling.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/styling.html new file mode 100644 index 0000000..3ad69c8b --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/styling.html
@@ -0,0 +1,14 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/style-util.html"> +<link rel="import" href="../lib/resolve-url.html"> +<link rel="import" href="../lib/style-transformer.html"> +<link rel="import" href="../lib/settings.html"> + +</head><body><script src="styling-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/utils-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/utils-extracted.js new file mode 100644 index 0000000..12480df --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/utils-extracted.js
@@ -0,0 +1,123 @@ + + + Polymer.Base._addFeature({ + + $$: function(slctr) { + return Polymer.dom(this.root).querySelector(slctr); + }, + + toggleClass: function(name, bool, node) { + node = node || this; + if (arguments.length == 1) { + bool = !node.classList.contains(name); + } + if (bool) { + node.classList.add(name); + } else { + node.classList.remove(name); + } + }, + + toggleAttribute: function(name, bool, node) { + (node || this)[bool ? 'setAttribute' : 'removeAttribute'](name, ''); + }, + + classFollows: function(className, neo, old) { + if (old) { + old.classList.remove(className); + } + if (neo) { + neo.classList.add(className); + } + }, + + attributeFollows: function(name, neo, old) { + if (old) { + old.removeAttribute(name); + } + if (neo) { + neo.setAttribute(name, ''); + } + }, + + getContentChildNodes: function(slctr) { + return Polymer.dom(Polymer.dom(this.root).querySelector( + slctr || 'content')).getDistributedNodes(); + }, + + getContentChildren: function(slctr) { + return this.getContentChildNodes(slctr).filter(function(n) { + return (n.nodeType === Node.ELEMENT_NODE); + }); + }, + + fire: function(type, detail, options) { + options = options || Polymer.nob; + var node = options.node || this; + var detail = (detail === null || detail === undefined) ? Polymer.nob : detail; + var bubbles = options.bubbles === undefined ? true : options.bubbles; + var event = new CustomEvent(type, { + bubbles: Boolean(bubbles), + cancelable: Boolean(options.cancelable), + detail: detail + }); + node.dispatchEvent(event); + return event; + }, + + async: function(method, waitTime) { + return Polymer.Async.run(method.bind(this), waitTime); + }, + + cancelAsync: function(handle) { + Polymer.Async.cancel(handle); + }, + + arrayDelete: function(array, item) { + var index = array.indexOf(item); + if (index >= 0) { + return array.splice(index, 1); + } + }, + + transform: function(node, transform) { + node.style.webkitTransform = transform; + node.style.transform = transform; + }, + + translate3d: function(node, x, y, z) { + this.transform(node, 'translate3d(' + x + ',' + y + ',' + z + ')'); + }, + + importHref: function(href, onload, onerror) { + var l = document.createElement('link'); + l.rel = 'import'; + l.href = href; + if (onload) { + l.onload = onload.bind(this); + } + if (onerror) { + l.onerror = onerror.bind(this); + } + document.head.appendChild(l); + return l; + }, + + create: function(tag, props) { + var elt = document.createElement(tag); + if (props) { + for (var n in props) { + elt[n] = props[n]; + } + } + return elt; + }, + + simpleMixin: function(a, b) { + for (var i in b) { + a[i] = b[i]; + } + } + + }); +
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/utils.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/utils.html new file mode 100644 index 0000000..b004e3f --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/utils.html
@@ -0,0 +1,12 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/async.html"> +<link rel="import" href="../lib/debounce.html"> + +</head><body><script src="utils-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/x-styling-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/x-styling-extracted.js new file mode 100644 index 0000000..45202d8 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/x-styling-extracted.js
@@ -0,0 +1,350 @@ + + (function() { + + var baseAttachedCallback = Polymer.Base.attachedCallback; + var baseSerializeValueToAttribute = Polymer.Base.serializeValueToAttribute; + + var nativeShadow = Polymer.Settings.useNativeShadow; + + // TODO(sorvell): consider if calculating properties and applying + // styles with properties should be separate modules. + Polymer.Base._addFeature({ + + attachedCallback: function() { + baseAttachedCallback.call(this); + if (!this._xScopeSelector) { + this._updateOwnStyles(); + } + }, + + _updateOwnStyles: function() { + if (this.enableCustomStyleProperties) { + this._styleProperties = this._computeStyleProperties(); + this._applyStyleProperties(this._styleProperties); + } + }, + + _computeStyleProperties: function() { + var props = {}; + this.simpleMixin(props, this._computeStylePropertiesFromHost()); + this.simpleMixin(props, this._computeOwnStyleProperties()); + this._reifyCustomProperties(props); + return props; + }, + + _computeStylePropertiesFromHost: function() { + // TODO(sorvell): experimental feature, global defaults! + var props = {}, styles = [Polymer.StyleDefaults.defaultSheet]; + var host = this.domHost; + if (host) { + // enable finding styles in hosts without `enableStyleCustomProperties` + if (!host._styleProperties) { + host._styleProperties = host._computeStyleProperties(); + } + props = Object.create(host._styleProperties); + styles = host._styles; + } + this.simpleMixin(props, + this._customPropertiesFromStyles(styles, host)); + return props; + + }, + + _computeOwnStyleProperties: function() { + var props = {}; + this.simpleMixin(props, this._customPropertiesFromStyles(this._styles)); + if (this.styleProperties) { + for (var i in this.styleProperties) { + props[i] = this.styleProperties[i]; + } + } + return props; + }, + + _customPropertiesFromStyles: function(styles, hostNode) { + var props = {}; + var p = this._customPropertiesFromRule.bind(this, props, hostNode); + if (styles) { + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + Polymer.StyleUtil.forEachStyleRule(this._rulesForStyle(s), p); + } + } + return props; + }, + + // test if a rule matches the given node and if so, + // collect any custom properties + // TODO(sorvell): support custom variable assignment within mixins + _customPropertiesFromRule: function(props, hostNode, rule) { + hostNode = hostNode || this; + // TODO(sorvell): file crbug, ':host' does not match element. + if (this.elementMatches(rule.selector) || + ((hostNode === this) && (rule.selector === ':host'))) { + // --g: var(--b); or --g: 5; + this._collectPropertiesFromRule(rule, CUSTOM_VAR_ASSIGN, props); + // --g: { ... } + this._collectPropertiesFromRule(rule, CUSTOM_MIXIN_ASSIGN, props); + } + }, + + // given a rule and rx that matches key and value, set key in properties + // to value + _collectPropertiesFromRule: function(rule, rx, properties) { + var m; + while (m = rx.exec(rule.cssText)) { + properties[m[1]] = m[2].trim(); + } + }, + + _reifyCustomProperties: function(props) { + for (var i in props) { + props[i] = this._valueForCustomProperty(props[i], props); + } + }, + + _valueForCustomProperty: function(property, props) { + var cv; + while ((typeof property === 'string') && + (cv = property.match(CUSTOM_VAR_VALUE))) { + property = props[cv[1]]; + } + return property; + }, + + // apply styles + _applyStyleProperties: function(bag) { + var s$ = this._styles; + if (s$) { + var style = styleFromCache(this.is, bag, s$); + var old = this._xScopeSelector; + this._ensureScopeSelector(style ? style._scope : null); + if (!style) { + var cssText = this._generateCustomStyleCss(bag, s$); + style = cssText ? this._applyCustomCss(cssText) : {}; + cacheStyle(this.is, style, this._xScopeSelector, + this._styleProperties, s$); + } else if (nativeShadow) { + this._applyCustomCss(style.textContent); + } + if (style.textContent || old /*&& !nativeShadow*/) { + this._applyXScopeSelector(this._xScopeSelector, old); + } + } + }, + + _applyXScopeSelector: function(selector, old) { + var c = this._scopeCssViaAttr ? this.getAttribute(SCOPE_NAME) : + this.className; + v = old ? c.replace(old, selector) : + (c ? c + ' ' : '') + XSCOPE_NAME + ' ' + selector; + if (c !== v) { + if (this._scopeCssViaAttr) { + this.setAttribute(SCOPE_NAME, v); + } else { + this.className = v; + } + } + }, + + _generateCustomStyleCss: function(properties, styles) { + var b = this._applyPropertiesToRule.bind(this, properties); + var cssText = ''; + // TODO(sorvell): don't redo parsing work each time as below; + // instead create a sheet with just custom properties + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + cssText += this._transformCss(s.textContent, b) + '\n\n'; + } + return cssText.trim(); + }, + + _transformCss: function(cssText, callback) { + return nativeShadow ? + Polymer.StyleUtil.toCssText(cssText, callback) : + Polymer.StyleTransformer.css(cssText, this.is, this.extends, callback, + this._scopeCssViaAttr); + }, + + _xScopeCount: 0, + + _ensureScopeSelector: function(selector) { + selector = selector || (this.is + '-' + + (Object.getPrototypeOf(this)._xScopeCount++)); + this._xScopeSelector = selector; + }, + + _applyCustomCss: function(cssText) { + if (this._customStyle) { + this._customStyle.textContent = cssText; + } else if (cssText) { + this._customStyle = Polymer.StyleUtil.applyCss(cssText, + this._xScopeSelector, + nativeShadow ? this.root : null); + } + return this._customStyle; + }, + + _applyPropertiesToRule: function(properties, rule) { + if (!nativeShadow) { + this._scopifyRule(rule); + } + if (rule.cssText.match(CUSTOM_RULE_RX)) { + rule.cssText = this._applyPropertiesToText(rule.cssText, properties); + } else { + rule.cssText = ''; + } + //console.log(rule.cssText); + }, + + _applyPropertiesToText: function(cssText, props) { + var output = ''; + var m, v; + // e.g. color: var(--color); + while (m = CUSTOM_VAR_USE.exec(cssText)) { + v = props[m[2]]; + if (v) { + output += '\t' + m[1].trim() + ': ' + this._propertyToCss(v); + } + } + // e.g. @mixin(--stuff); + while (m = CUSTOM_MIXIN_USE.exec(cssText)) { + v = m[1]; + if (v) { + var parts = v.split(' '); + for (var i=0, p; i < parts.length; i++) { + p = props[parts[i].trim()]; + if (p) { + output += '\t' + this._propertyToCss(p); + } + } + } + } + return output; + }, + + _propertyToCss: function(property) { + var p = property.trim(); + p = p[p.length-1] === ';' ? p : p + ';'; + return p + '\n'; + }, + + // Strategy: x scope shim a selector e.g. to scope `.x-foo-42` (via classes): + // non-host selector: .a.x-foo -> .x-foo-42 .a.x-foo + // host selector: x-foo.wide -> x-foo.x-foo-42.wide + _scopifyRule: function(rule) { + var selector = rule.selector; + var host = this.is; + var rx = new RegExp(HOST_SELECTOR_PREFIX + host + HOST_SELECTOR_SUFFIX); + var parts = selector.split(','); + var scope = this._scopeCssViaAttr ? + SCOPE_PREFIX + this._xScopeSelector + SCOPE_SUFFIX : + '.' + this._xScopeSelector; + for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) { + parts[i] = p.match(rx) ? + p.replace(host, host + scope) : + scope + ' ' + p; + } + rule.selector = parts.join(','); + }, + + _scopeElementClass: function(element, selector) { + if (!nativeShadow && !this._scopeCssViaAttr) { + selector += (selector ? ' ' : '') + SCOPE_NAME + ' ' + this.is + + (element._xScopeSelector ? ' ' + XSCOPE_NAME + ' ' + + element._xScopeSelector : ''); + } + return selector; + }, + + // override to ensure whenever classes are set, we need to shim them. + serializeValueToAttribute: function(value, attribute, node) { + if (attribute === 'class') { + // host needed to scope styling. + var host = node === this ? + Polymer.dom(this).getOwnerRoot() || this.dataHost : + this; + if (host) { + value = host._scopeElementClass(node, value); + } + } + baseSerializeValueToAttribute.call(this, value, attribute, node); + }, + + updateStyles: function() { + this._updateOwnStyles(); + this._updateRootStyles(this.root); + }, + + updateHostStyles: function() { + var host = Polymer.dom(this).getOwnerRoot() || this.dataHost; + if (host) { + host.updateStyles(); + } else { + this._updateRootStyles(document); + } + }, + + _updateRootStyles: function(root) { + // TODO(sorvell): temporary way to find local dom that needs + // x-scope styling. + var scopeSelector = this._scopeCssViaAttr ? + '[' + SCOPE_NAME + '~=' + XSCOPE_NAME + ']' : '.' + XSCOPE_NAME; + var c$ = Polymer.dom(root).querySelectorAll(scopeSelector); + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + if (c.updateStyles) { + c.updateStyles(); + } + } + } + + }); + + var styleCache = {}; + function cacheStyle(is, style, scope, bag, styles) { + style._scope = scope; + style._properties = bag; + style._styles = styles; + var s$ = styleCache[is] = styleCache[is] || []; + s$.push(style); + } + + function styleFromCache(is, bag, checkStyles) { + var styles = styleCache[is]; + if (styles) { + for (var i=0, s; i < styles.length; i++) { + s = styles[i]; + if (objectsEqual(bag, s._properties) && + objectsEqual(checkStyles, s._styles)) { + return s; + } + } + } + } + + function objectsEqual(a, b) { + for (var i in a) { + if (a[i] !== b[i]) { + return false; + } + } + for (var i in b) { + if (a[i] !== b[i]) { + return false; + } + } + return true; + } + + var SCOPE_NAME= Polymer.StyleTransformer.SCOPE_NAME; + var XSCOPE_NAME = 'x-scope'; + var SCOPE_PREFIX = '[' + SCOPE_NAME + '~='; + var SCOPE_SUFFIX = ']'; + var HOST_SELECTOR_PREFIX = '(?:^|[^.])'; + var HOST_SELECTOR_SUFFIX = '($|[.:[\\s>+~])'; + var CUSTOM_RULE_RX = /mixin|var/; + var CUSTOM_VAR_ASSIGN = /(--[^\:;]*?):\s*?([^;{]*?);/g; + var CUSTOM_MIXIN_ASSIGN = /(--[^\:;]*?):[^{;]*?{([^}]*?)}/g; + var CUSTOM_VAR_VALUE = /^var\(([^)]*?)\)/; + var CUSTOM_VAR_USE = /(?:^|[;}\s])([^;{}]*?):[\s]*?var\(([^)]*)?\)/gim; + var CUSTOM_MIXIN_USE = /mixin\(([^)]*)\)/gim; + + })();
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/standard/x-styling.html b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/x-styling.html new file mode 100644 index 0000000..7d30995 --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/src/standard/x-styling.html
@@ -0,0 +1,13 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--><html><head><link rel="import" href="../lib/style-util.html"> +<link rel="import" href="../lib/style-transformer.html"> +<link rel="import" href="../lib/settings.html"> +<link rel="import" href="../lib/style-defaults.html"> +</head><body><script src="x-styling-extracted.js"></script></body></html> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/wct.conf.js b/third_party/polymer/v0_8/components-chromium/polymer/wct.conf.js new file mode 100644 index 0000000..111deea --- /dev/null +++ b/third_party/polymer/v0_8/components-chromium/polymer/wct.conf.js
@@ -0,0 +1,3 @@ +module.exports = { + suites: ['test/runner.html'], +};
diff --git a/third_party/polymer/v0_8/components/iron-behaviors/.bower.json b/third_party/polymer/v0_8/components/iron-behaviors/.bower.json new file mode 100644 index 0000000..f7783c2 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-behaviors/.bower.json
@@ -0,0 +1,28 @@ +{ + "name": "iron-behaviors", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "license": "MIT", + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + }, + "homepage": "https://github.com/polymerelements/iron-behaviors", + "version": "0.8.0", + "_release": "0.8.0", + "_resolution": { + "type": "version", + "tag": "v0.8.0", + "commit": "bde97715665a35c467efd869174eaadf6acea2ff" + }, + "_source": "git://github.com/polymerelements/iron-behaviors.git", + "_target": "^0.8.0", + "_originalSource": "polymerelements/iron-behaviors" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-behaviors/.gitignore b/third_party/polymer/v0_8/components/iron-behaviors/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-behaviors/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/iron-behaviors/README.md b/third_party/polymer/v0_8/components/iron-behaviors/README.md new file mode 100644 index 0000000..593986e --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-behaviors/README.md
@@ -0,0 +1,4 @@ +iron-behaviors +============== + +This repository collects shared behaviors that are mixed in to other elements.
diff --git a/third_party/polymer/v0_8/components/iron-behaviors/bower.json b/third_party/polymer/v0_8/components/iron-behaviors/bower.json new file mode 100644 index 0000000..bc0c213 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-behaviors/bower.json
@@ -0,0 +1,17 @@ +{ + "name": "iron-behaviors", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "license": "MIT", + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + } +}
diff --git a/third_party/polymer/v0_8/components/iron-behaviors/index.html b/third_party/polymer/v0_8/components/iron-behaviors/index.html new file mode 100644 index 0000000..0e01e8a --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-behaviors/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-component-page/iron-component-page.html"> + +</head> +<body> + + <iron-component-page></iron-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-behaviors/iron-button-state.html b/third_party/polymer/v0_8/components/iron-behaviors/iron-button-state.html new file mode 100644 index 0000000..8036642 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-behaviors/iron-button-state.html
@@ -0,0 +1,154 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="iron-control-state.html"> + +<script> + + Polymer.IronButtonState = { + + properties: { + + /** + * If true, the user is currently holding down the button. + * + * @attribute pressed + * @type boolean + * @default false + */ + pressed: { + type: Boolean, + readOnly: true, + reflectToAttribute: true, + observer: '_pressedChanged' + }, + + /** + * If true, the button toggles the active state with each tap or press + * of the spacebar. + * + * @attribute toggles + * @type boolean + * @default false + */ + toggles: { + type: Boolean, + reflectToAttribute: true + }, + + /** + * If true, the button is a toggle and is currently in the active state. + * + * @attribute active + * @type boolean + * @default false + */ + active: { + type: Boolean, + notify: true, + reflectToAttribute: true, + observer: '_activeChanged' + } + + }, + + listeners: { + mousedown: '_downHandler', + mouseup: '_upHandler', + keydown: '_keyDownHandler', + keyup: '_keyUpHandler', + tap: '_tapHandler' + }, + + _tapHandler: function() { + if (this.toggles) { + // a tap is needed to toggle the active state + this._userActivate(!this.active); + } else { + this.active = false; + } + }, + + // to emulate native checkbox, (de-)activations from a user interaction fire + // 'change' events + _userActivate: function(active) { + this.active = active; + this.fire('change'); + }, + + _downHandler: function() { + this._setPressed(true); + }, + + _upHandler: function(e) { + this._setPressed(false); + }, + + _keyDownHandler: function(e) { + switch(e.keyCode) { + case this.keyCodes.ENTER_KEY: + this._asyncClick(); + break; + + case this.keyCodes.SPACE: + this._setPressed(true); + break; + + } + }, + + _keyUpHandler: function(e) { + if (e.keyCode == this.keyCodes.SPACE) { + if (this.pressed) { + this._asyncClick(); + } + this._setPressed(false); + } + }, + + // trigger click asynchronously, the asynchrony is useful to allow one + // event handler to unwind before triggering another event + _asyncClick: function() { + this.async(function() { + this.click(); + }, 1); + }, + + // any of these changes are considered a change to button state + + _pressedChanged: function(pressed) { + this._changedButtonState(); + }, + + _activeChanged: function(active) { + this.setAttribute('aria-pressed', active ? 'true' : 'false'); + this._changedButtonState(); + }, + + _controlStateChanged: function() { + if (this.disabled) { + this._setPressed(false); + this.active = false; + } else { + this._changedButtonState(); + } + }, + + // provide hook for follow-on behaviors to react to button-state + + _changedButtonState: function() { + if (this._buttonStateChanged) { + this._buttonStateChanged(); // abstract + } + } + + }; + +</script>
diff --git a/third_party/polymer/v0_8/components/iron-behaviors/iron-control-state.html b/third_party/polymer/v0_8/components/iron-behaviors/iron-control-state.html new file mode 100644 index 0000000..4b98a09a --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-behaviors/iron-control-state.html
@@ -0,0 +1,99 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<script> + + Polymer.IronControlState = { + + properties: { + + /** + * If true, the element currently has focus. + * + * @attribute focused + * @type boolean + * @default false + */ + focused: { + type: Boolean, + value: false, + notify: true, + readOnly: true, + reflectToAttribute: true + }, + + /** + * If true, the user cannot interact with this element. + * + * @attribute disabled + * @type boolean + * @default false + */ + disabled: { + type: Boolean, + value: false, + notify: true, + observer: '_disabledChanged', + reflectToAttribute: true + }, + + _oldTabIndex: { + type: String + } + }, + + observers: [ + '_changedControlState(focused, disabled)' + ], + + listeners: { + focus: '_focusHandler', + blur: '_blurHandler' + }, + + ready: function() { + // TODO(sjmiles): ensure read-only property is valued so the compound + // observer will fire + if (this.focused === undefined) { + this._setFocused(false); + } + }, + + _focusHandler: function() { + this._setFocused(true); + }, + + _blurHandler: function() { + this._setFocused(false); + }, + + _disabledChanged: function(disabled, old) { + this.setAttribute('aria-disabled', disabled ? 'true' : 'false'); + this.style.pointerEvents = disabled ? 'none' : ''; + if (disabled) { + this._oldTabIndex = this.tabIndex; + this.focused = false; + this.tabIndex = -1; + } else if (this._oldTabIndex !== undefined) { + this.tabIndex = this._oldTabIndex; + } + }, + + _changedControlState: function() { + // _controlStateChanged is abstract, follow-on behaviors may implement it + if (this._controlStateChanged) { + this._controlStateChanged(); + } + } + + }; + +</script>
diff --git a/third_party/polymer/v0_8/components/iron-icon/.bower.json b/third_party/polymer/v0_8/components/iron-icon/.bower.json new file mode 100644 index 0000000..fc84e07 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icon/.bower.json
@@ -0,0 +1,27 @@ +{ + "name": "iron-icon", + "private": true, + "dependencies": { + "iron-meta": "polymerelements/iron-meta#^0.8.0", + "polymer": "polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "iron-iconset": "polymerelements/iron-iconset#^0.8.0", + "core-icons": "polymerelements/iron-icons#^0.8.0", + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/PolymerElements/iron-icon", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "8528f25c3d08a9e84e1cf96aebb6b5459e5e7af0" + }, + "_source": "git://github.com/PolymerElements/iron-icon.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-icon" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-icon/.gitignore b/third_party/polymer/v0_8/components/iron-icon/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icon/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/iron-icon/README.md b/third_party/polymer/v0_8/components/iron-icon/README.md new file mode 100644 index 0000000..65d93fb --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icon/README.md
@@ -0,0 +1,4 @@ +core-icon +========= + +See the [component page](http://polymer-project.org/docs/elements/core-elements.html#core-icon) for more information.
diff --git a/third_party/polymer/v0_8/components/iron-icon/bower.json b/third_party/polymer/v0_8/components/iron-icon/bower.json new file mode 100644 index 0000000..f3763f0 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icon/bower.json
@@ -0,0 +1,16 @@ +{ + "name": "iron-icon", + "private": true, + "dependencies": { + "iron-meta": "polymerelements/iron-meta#^0.8.0", + "polymer": "polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "iron-iconset": "polymerelements/iron-iconset#^0.8.0", + "core-icons": "polymerelements/iron-icons#^0.8.0", + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components/iron-icon/index.html b/third_party/polymer/v0_8/components/iron-icon/index.html new file mode 100644 index 0000000..7aaf647 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icon/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="iron-icon.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-icon/iron-icon.html b/third_party/polymer/v0_8/components/iron-icon/iron-icon.html new file mode 100644 index 0000000..6d1cc1da --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icon/iron-icon.html
@@ -0,0 +1,154 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- + +The `iron-icon` element displays an icon. By default an icon renders as a 24px square. + +Example using src: + + <iron-icon src="star.png"></iron-icon> + +Example setting size to 32px x 32px: + + <iron-icon class="big" src="big_star.png"></iron-icon> + + <style> + .big { + height: 32px; + width: 32px; + } + </style> + +The iron elements include several sets of icons. +To use the default set of icons, import `iron-icons.html` and use the `icon` attribute to specify an icon: + + <!-- import default iconset and iron-icon --> + <link rel="import" href="/components/iron-icons/iron-icons.html"> + + <iron-icon icon="menu"></iron-icon> + +To use a different built-in set of icons, import `iron-icons/<iconset>-icons.html`, and +specify the icon as `<iconset>:<icon>`. For example: + + <!-- import communication iconset and iron-icon --> + <link rel="import" href="/components/iron-icons/communication-icons.html"> + + <iron-icon icon="communication:email"></iron-icon> + +You can also create custom icon sets of bitmap or SVG icons. + +Example of using an icon named `cherry` from a custom iconset with the ID `fruit`: + + <iron-icon icon="fruit:cherry"></iron-icon> + +See [iron-iconset](#iron-iconset) and [iron-iconset-svg](#iron-iconset-svg) for more information about +how to create a custom iconset. + +See [iron-icons](http://www.polymer-project.org/components/iron-icons/demo.html) for the default set of icons. + +@group Polymer Core Elements +@element iron-icon +@homepage polymer.github.io +--> + +<link rel="import" href="../iron-meta/iron-meta.html"> + +<dom-module id="iron-icon"> + + <style> + :host { + display: inline-flex; + position: relative; + + vertical-align: middle; + align-items: center; + justify-content: center; + + fill: currentcolor; + + width: 24px; + height: 24px; + } + </style> + + <template> + <iron-meta id="meta" type="iconset"></iron-meta> + </template> + +</dom-module> + +<script> + + Polymer({ + + is: 'iron-icon', + + properties: { + + icon: { + type: String, + //value: '', + observer: '_iconChanged' + }, + + theme: { + type: String, + //value: '', + observer: '_updateIcon' + }, + + src: { + type: String, + //value: '', + observer: '_srcChanged' + } + + }, + + _DEFAULT_ICONSET: 'icons', + + _iconChanged: function(icon) { + var parts = (icon || '').split(':'); + this._iconName = parts.pop(); + this._iconsetName = parts.pop() || this._DEFAULT_ICONSET; + this._updateIcon(); + }, + + _srcChanged: function(src) { + this._updateIcon(); + }, + + _usesIconset: function() { + return this.icon || !this.src; + }, + + _updateIcon: function() { + if (this._usesIconset()) { + this._iconset = this.$.meta.byKey(this._iconsetName); + if (this._iconset) { + this._iconset.applyIcon(this, this._iconName, this.theme); + } else { + console.warn('iron-icon: could not find iconset `' + + this._iconsetName + '`, did you import the iconset?'); + } + } else { + //if (this._iconset) { + // this._iconset.removeIcon(this.root); + //} + if (!this._img) { + this._img = document.createElement('img'); + } + this._img.src = this.src; + Polymer.dom(this.root).appendChild(this._img); + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/iron-icons/.bower.json b/third_party/polymer/v0_8/components/iron-icons/.bower.json new file mode 100644 index 0000000..1dd6ed9 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/.bower.json
@@ -0,0 +1,28 @@ +{ + "name": "iron-icons", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-iconset-svg": "polymerelements/iron-iconset-svg#^0.8.0" + }, + "devDependencies": { + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0" + }, + "ignore": [ + "util", + "update-icons.sh" + ], + "homepage": "https://github.com/PolymerElements/iron-icons", + "version": "0.8.3", + "_release": "0.8.3", + "_resolution": { + "type": "version", + "tag": "v0.8.3", + "commit": "76e6bbe3414c39c0e8260855a13bd018bfc0ddcd" + }, + "_source": "git://github.com/PolymerElements/iron-icons.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-icons" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-icons/.gitignore b/third_party/polymer/v0_8/components/iron-icons/.gitignore new file mode 100644 index 0000000..e21a66b --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/.gitignore
@@ -0,0 +1,2 @@ +util/node_modules +material-design-icons
diff --git a/third_party/polymer/v0_8/components/iron-icons/README.md b/third_party/polymer/v0_8/components/iron-icons/README.md new file mode 100644 index 0000000..ed473f7 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/README.md
@@ -0,0 +1,8 @@ +iron-icons +========= + +See the [component page](http://polymer-project.org/docs/elements/iron-elements.html#iron-icons) for more information. + +## Building +Running `update-icons.sh` will checkout [material-design-icons](https://github.com/google/material-design-icons), reduce +the fileset to 24px svgs, and compile the iconsets.
diff --git a/third_party/polymer/v0_8/components/iron-icons/av-icons.html b/third_party/polymer/v0_8/components/iron-icons/av-icons.html new file mode 100644 index 0000000..1fda7a7d --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/av-icons.html
@@ -0,0 +1,65 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="av" size="24"> +<svg><defs> +<g id="album"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 14.5c-2.49 0-4.5-2.01-4.5-4.5S9.51 7.5 12 7.5s4.5 2.01 4.5 4.5-2.01 4.5-4.5 4.5zm0-5.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z"/></g> +<g id="av-timer"><path d="M11 17c0 .55.45 1 1 1s1-.45 1-1-.45-1-1-1-1 .45-1 1zm0-14v4h2V5.08c3.39.49 6 3.39 6 6.92 0 3.87-3.13 7-7 7s-7-3.13-7-7c0-1.68.59-3.22 1.58-4.42L12 13l1.41-1.41-6.8-6.8v.02C4.42 6.45 3 9.05 3 12c0 4.97 4.02 9 9 9 4.97 0 9-4.03 9-9s-4.03-9-9-9h-1zm7 9c0-.55-.45-1-1-1s-1 .45-1 1 .45 1 1 1 1-.45 1-1zM6 12c0 .55.45 1 1 1s1-.45 1-1-.45-1-1-1-1 .45-1 1z"/></g> +<g id="closed-caption"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z"/></g> +<g id="equalizer"><path d="M10 20h4V4h-4v16zm-6 0h4v-8H4v8zM16 9v11h4V9h-4z"/></g> +<g id="explicit"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 6h-4v2h4v2h-4v2h4v2H9V7h6v2z"/></g> +<g id="fast-forward"><path d="M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"/></g> +<g id="fast-rewind"><path d="M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"/></g> +<g id="games"><path d="M15 7.5V2H9v5.5l3 3 3-3zM7.5 9H2v6h5.5l3-3-3-3zM9 16.5V22h6v-5.5l-3-3-3 3zM16.5 9l-3 3 3 3H22V9h-5.5z"/></g> +<g id="hearing"><path d="M17 20c-.29 0-.56-.06-.76-.15-.71-.37-1.21-.88-1.71-2.38-.51-1.56-1.47-2.29-2.39-3-.79-.61-1.61-1.24-2.32-2.53C9.29 10.98 9 9.93 9 9c0-2.8 2.2-5 5-5s5 2.2 5 5h2c0-3.93-3.07-7-7-7S7 5.07 7 9c0 1.26.38 2.65 1.07 3.9.91 1.65 1.98 2.48 2.85 3.15.81.62 1.39 1.07 1.71 2.05.6 1.82 1.37 2.84 2.73 3.55.51.23 1.07.35 1.64.35 2.21 0 4-1.79 4-4h-2c0 1.1-.9 2-2 2zM7.64 2.64L6.22 1.22C4.23 3.21 3 5.96 3 9s1.23 5.79 3.22 7.78l1.41-1.41C6.01 13.74 5 11.49 5 9s1.01-4.74 2.64-6.36zM11.5 9c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5-2.5 1.12-2.5 2.5z"/></g> +<g id="high-quality"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 11H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/></g> +<g id="loop"><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/></g> +<g id="mic"><path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></g> +<g id="mic-none"><path d="M12 14c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1.2-9.1c0-.66.54-1.2 1.2-1.2.66 0 1.2.54 1.2 1.2l-.01 6.2c0 .66-.53 1.2-1.19 1.2-.66 0-1.2-.54-1.2-1.2V4.9zm6.5 6.1c0 3-2.54 5.1-5.3 5.1S6.7 14 6.7 11H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></g> +<g id="mic-off"><path d="M19 11h-1.7c0 .74-.16 1.43-.43 2.05l1.23 1.23c.56-.98.9-2.09.9-3.28zm-4.02.17c0-.06.02-.11.02-.17V5c0-1.66-1.34-3-3-3S9 3.34 9 5v.18l5.98 5.99zM4.27 3L3 4.27l6.01 6.01V11c0 1.66 1.33 3 2.99 3 .22 0 .44-.03.65-.08l1.66 1.66c-.71.33-1.5.52-2.31.52-2.76 0-5.3-2.1-5.3-5.1H5c0 3.41 2.72 6.23 6 6.72V21h2v-3.28c.91-.13 1.77-.45 2.54-.9L19.73 21 21 19.73 4.27 3z"/></g> +<g id="movie"><path d="M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4h-4z"/></g> +<g id="my-library-add"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/></g> +<g id="my-library-books"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9H9V9h10v2zm-4 4H9v-2h6v2zm4-8H9V5h10v2z"/></g> +<g id="my-library-music"><path d="M20 2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 5h-3v5.5c0 1.38-1.12 2.5-2.5 2.5S10 13.88 10 12.5s1.12-2.5 2.5-2.5c.57 0 1.08.19 1.5.51V5h4v2zM4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6z"/></g> +<g id="new-releases"><path d="M23 12l-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12 3 8.6 1.54 6.71 4.72l-3.61.81.34 3.68L1 12l2.44 2.78-.34 3.69 3.61.82 1.89 3.18L12 21l3.4 1.46 1.89-3.18 3.61-.82-.34-3.68L23 12zm-10 5h-2v-2h2v2zm0-4h-2V7h2v6z"/></g> +<g id="not-interested"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z"/></g> +<g id="pause"><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></g> +<g id="pause-circle-fill"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 14H9V8h2v8zm4 0h-2V8h2v8z"/></g> +<g id="pause-circle-outline"><path d="M9 16h2V8H9v8zm3-14C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm1-4h2V8h-2v8z"/></g> +<g id="play-arrow"><path d="M8 5v14l11-7z"/></g> +<g id="play-circle-fill"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 14.5v-9l6 4.5-6 4.5z"/></g> +<g id="play-circle-outline"><path d="M10 16.5l6-4.5-6-4.5v9zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="play-shopping-bag"><path d="M16 6V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H2v13c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6h-6zm-6-2h4v2h-4V4zM9 18V9l7.5 4L9 18z"/></g> +<g id="playlist-add"><path d="M14 10H2v2h12v-2zm0-4H2v2h12V6zm4 8v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zM2 16h8v-2H2v2z"/></g> +<g id="queue"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/></g> +<g id="queue-music"><path d="M15 6H3v2h12V6zm0 4H3v2h12v-2zM3 16h8v-2H3v2zM17 6v8.18c-.31-.11-.65-.18-1-.18-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3V8h3V6h-5z"/></g> +<g id="radio"><path d="M3.24 6.15C2.51 6.43 2 7.17 2 8v12c0 1.1.89 2 2 2h16c1.11 0 2-.9 2-2V8c0-1.11-.89-2-2-2H8.3l8.26-3.34L15.88 1 3.24 6.15zM7 20c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm13-8h-2v-2h-2v2H4V8h16v4z"/></g> +<g id="recent-actors"><path d="M21 5v14h2V5h-2zm-4 14h2V5h-2v14zM14 5H2c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zM8 7.75c1.24 0 2.25 1.01 2.25 2.25S9.24 12.25 8 12.25 5.75 11.24 5.75 10 6.76 7.75 8 7.75zM12.5 17h-9v-.75c0-1.5 3-2.25 4.5-2.25s4.5.75 4.5 2.25V17z"/></g> +<g id="repeat"><path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4z"/></g> +<g id="repeat-one"><path d="M7 7h10v3l4-4-4-4v3H5v6h2V7zm10 10H7v-3l-4 4 4 4v-3h12v-6h-2v4zm-4-2V9h-1l-2 1v1h1.5v4H13z"/></g> +<g id="replay"><path d="M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z"/></g> +<g id="shuffle"><path d="M10.59 9.17L5.41 4 4 5.41l5.17 5.17 1.42-1.41zM14.5 4l2.04 2.04L4 18.59 5.41 20 17.96 7.46 20 9.5V4h-5.5zm.33 9.41l-1.41 1.41 3.13 3.13L14.5 20H20v-5.5l-2.04 2.04-3.13-3.13z"/></g> +<g id="skip-next"><path d="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"/></g> +<g id="skip-previous"><path d="M6 6h2v12H6zm3.5 6l8.5 6V6z"/></g> +<g id="snooze"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm-3-9h3.63L9 15.2V17h6v-2h-3.63L15 10.8V9H9v2z"/></g> +<g id="stop"><path d="M6 6h12v12H6z"/></g> +<g id="subtitles"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM4 12h4v2H4v-2zm10 6H4v-2h10v2zm6 0h-4v-2h4v2zm0-4H10v-2h10v2z"/></g> +<g id="surround-sound"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM7.76 16.24l-1.41 1.41C4.78 16.1 4 14.05 4 12c0-2.05.78-4.1 2.34-5.66l1.41 1.41C6.59 8.93 6 10.46 6 12s.59 3.07 1.76 4.24zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm5.66 1.66l-1.41-1.41C17.41 15.07 18 13.54 18 12s-.59-3.07-1.76-4.24l1.41-1.41C19.22 7.9 20 9.95 20 12c0 2.05-.78 4.1-2.34 5.66zM12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="video-collection"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-8 12.5v-9l6 4.5-6 4.5z"/></g> +<g id="videocam"><path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z"/></g> +<g id="videocam-off"><path d="M21 6.5l-4 4V7c0-.55-.45-1-1-1H9.82L21 17.18V6.5zM3.27 2L2 3.27 4.73 6H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.21 0 .39-.08.54-.18L19.73 21 21 19.73 3.27 2z"/></g> +<g id="volume-down"><path d="M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z"/></g> +<g id="volume-mute"><path d="M7 9v6h4l5 5V4l-5 5H7z"/></g> +<g id="volume-off"><path d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"/></g> +<g id="volume-up"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"/></g> +<g id="web"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 14H4v-4h11v4zm0-5H4V9h11v4zm5 5h-4V9h4v9z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/bower.json b/third_party/polymer/v0_8/components/iron-icons/bower.json new file mode 100644 index 0000000..636b56bb --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/bower.json
@@ -0,0 +1,17 @@ +{ + "name": "iron-icons", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-iconset-svg": "polymerelements/iron-iconset-svg#^0.8.0" + }, + "devDependencies": { + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0" + }, + "ignore": [ + "util", + "update-icons.sh" + ] +}
diff --git a/third_party/polymer/v0_8/components/iron-icons/communication-icons.html b/third_party/polymer/v0_8/components/iron-icons/communication-icons.html new file mode 100644 index 0000000..29ce611 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/communication-icons.html
@@ -0,0 +1,54 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="communication" size="24"> +<svg><defs> +<g id="business"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"/></g> +<g id="call"><path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></g> +<g id="call-end"><path d="M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08c-.18-.17-.29-.42-.29-.7 0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28-.79-.74-1.69-1.36-2.67-1.85-.33-.16-.56-.5-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z"/></g> +<g id="call-made"><path d="M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5z"/></g> +<g id="call-merge"><path d="M17 20.41L18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z"/></g> +<g id="call-missed"><path d="M19.59 7L12 14.59 6.41 9H11V7H3v8h2v-4.59l7 7 9-9z"/></g> +<g id="call-received"><path d="M20 5.41L18.59 4 7 15.59V9H5v10h10v-2H8.41z"/></g> +<g id="call-split"><path d="M14 4l2.29 2.29-2.88 2.88 1.42 1.42 2.88-2.88L20 10V4zm-4 0H4v6l2.29-2.29 4.71 4.7V20h2v-8.41l-5.29-5.3z"/></g> +<g id="chat"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 9h12v2H6V9zm8 5H6v-2h8v2zm4-6H6V6h12v2z"/></g> +<g id="clear-all"><path d="M5 13h14v-2H5v2zm-2 4h14v-2H3v2zM7 7v2h14V7H7z"/></g> +<g id="comment"><path d="M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4-.01-18zM18 14H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/></g> +<g id="contacts"><path d="M20 0H4v2h16V0zM4 24h16v-2H4v2zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 2.75c1.24 0 2.25 1.01 2.25 2.25s-1.01 2.25-2.25 2.25S9.75 10.24 9.75 9 10.76 6.75 12 6.75zM17 17H7v-1.5c0-1.67 3.33-2.5 5-2.5s5 .83 5 2.5V17z"/></g> +<g id="dialer-sip"><path d="M17 3h-1v5h1V3zm-2 2h-2V4h2V3h-3v3h2v1h-2v1h3V5zm3-2v5h1V6h2V3h-3zm2 2h-1V4h1v1zm0 10.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.01.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.27-.26.35-.65.24-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></g> +<g id="dialpad"><path d="M12 19c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zM6 1c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12-8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-6 8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="dnd-on"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z"/></g> +<g id="email"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></g> +<g id="forum"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"/></g> +<g id="import-export"><path d="M9 3L5 6.99h3V14h2V6.99h3L9 3zm7 14.01V10h-2v7.01h-3L15 21l4-3.99h-3z"/></g> +<g id="invert-colors-off"><path d="M20.65 20.87l-2.35-2.35-6.3-6.29-3.56-3.57-1.42-1.41L4.27 4.5 3 5.77l2.78 2.78c-2.55 3.14-2.36 7.76.56 10.69C7.9 20.8 9.95 21.58 12 21.58c1.79 0 3.57-.59 5.03-1.78l2.7 2.7L21 21.23l-.35-.36zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59c0-1.32.43-2.57 1.21-3.6L12 14.77v4.82zM12 5.1v4.58l7.25 7.26c1.37-2.96.84-6.57-1.6-9.01L12 2.27l-3.7 3.7 1.41 1.41L12 5.1z"/></g> +<g id="invert-colors-on"><path d="M17.66 7.93L12 2.27 6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58c2.05 0 4.1-.78 5.66-2.34 3.12-3.12 3.12-8.19 0-11.31zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"/></g> +<g id="live-help"><path d="M19 2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h4l3 3 3-3h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-6 16h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 11.9 13 12.5 13 14h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"/></g> +<g id="location-off"><path d="M12 6.5c1.38 0 2.5 1.12 2.5 2.5 0 .74-.33 1.39-.83 1.85l3.63 3.63c.98-1.86 1.7-3.8 1.7-5.48 0-3.87-3.13-7-7-7-1.98 0-3.76.83-5.04 2.15l3.19 3.19c.46-.52 1.11-.84 1.85-.84zm4.37 9.6l-4.63-4.63-.11-.11L3.27 3 2 4.27l3.18 3.18C5.07 7.95 5 8.47 5 9c0 5.25 7 13 7 13s1.67-1.85 3.38-4.35L18.73 21 20 19.73l-3.63-3.63z"/></g> +<g id="location-on"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></g> +<g id="message"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/></g> +<g id="messenger"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></g> +<g id="no-sim"><path d="M18.99 5c0-1.1-.89-2-1.99-2h-7L7.66 5.34 19 16.68 18.99 5zM3.65 3.88L2.38 5.15 5 7.77V19c0 1.1.9 2 2 2h10.01c.35 0 .67-.1.96-.26l1.88 1.88 1.27-1.27L3.65 3.88z"/></g> +<g id="phone"><path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></g> +<g id="portable-wifi-off"><path d="M17.56 14.24c.28-.69.44-1.45.44-2.24 0-3.31-2.69-6-6-6-.79 0-1.55.16-2.24.44l1.62 1.62c.2-.03.41-.06.62-.06 2.21 0 4 1.79 4 4 0 .21-.02.42-.05.63l1.61 1.61zM12 4c4.42 0 8 3.58 8 8 0 1.35-.35 2.62-.95 3.74l1.47 1.47C21.46 15.69 22 13.91 22 12c0-5.52-4.48-10-10-10-1.91 0-3.69.55-5.21 1.47l1.46 1.46C9.37 4.34 10.65 4 12 4zM3.27 2.5L2 3.77l2.1 2.1C2.79 7.57 2 9.69 2 12c0 3.7 2.01 6.92 4.99 8.65l1-1.73C5.61 17.53 4 14.96 4 12c0-1.76.57-3.38 1.53-4.69l1.43 1.44C6.36 9.68 6 10.8 6 12c0 2.22 1.21 4.15 3 5.19l1-1.74c-1.19-.7-2-1.97-2-3.45 0-.65.17-1.25.44-1.79l1.58 1.58L10 12c0 1.1.9 2 2 2l.21-.02.01.01 7.51 7.51L21 20.23 4.27 3.5l-1-1z"/></g> +<g id="quick-contacts-dialer"><path d="M22 3H2C.9 3 0 3.9 0 5v14c0 1.1.9 2 2 2h20c1.1 0 1.99-.9 1.99-2L24 5c0-1.1-.9-2-2-2zM8 6c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H2v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1zm3.85-4h1.64L21 16l-1.99 1.99c-1.31-.98-2.28-2.38-2.73-3.99-.18-.64-.28-1.31-.28-2s.1-1.36.28-2c.45-1.62 1.42-3.01 2.73-3.99L21 8l-1.51 2h-1.64c-.22.63-.35 1.3-.35 2s.13 1.37.35 2z"/></g> +<g id="quick-contacts-mail"><path d="M21 8V7l-3 2-3-2v1l3 2 3-2zm1-5H2C.9 3 0 3.9 0 5v14c0 1.1.9 2 2 2h20c1.1 0 1.99-.9 1.99-2L24 5c0-1.1-.9-2-2-2zM8 6c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H2v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1zm8-6h-8V6h8v6z"/></g> +<g id="ring-volume"><path d="M23.71 16.67C20.66 13.78 16.54 12 12 12 7.46 12 3.34 13.78.29 16.67c-.18.18-.29.43-.29.71 0 .28.11.53.29.71l2.48 2.48c.18.18.43.29.71.29.27 0 .52-.11.7-.28.79-.74 1.69-1.36 2.66-1.85.33-.16.56-.5.56-.9v-3.1c1.45-.48 3-.73 4.6-.73s3.15.25 4.6.72v3.1c0 .39.23.74.56.9.98.49 1.87 1.12 2.66 1.85.18.18.43.28.7.28.28 0 .53-.11.71-.29l2.48-2.48c.18-.18.29-.43.29-.71 0-.27-.11-.52-.29-.7zM21.16 6.26l-1.41-1.41-3.56 3.55 1.41 1.41s3.45-3.52 3.56-3.55zM13 2h-2v5h2V2zM6.4 9.81L7.81 8.4 4.26 4.84 2.84 6.26c.11.03 3.56 3.55 3.56 3.55z"/></g> +<g id="stay-current-landscape"><path d="M1.01 7L1 17c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2H3c-1.1 0-1.99.9-1.99 2zM19 7v10H5V7h14z"/></g> +<g id="stay-current-portrait"><path d="M17 1.01L7 1c-1.1 0-1.99.9-1.99 2v18c0 1.1.89 2 1.99 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></g> +<g id="stay-primary-landscape"><path d="M1.01 7L1 17c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2H3c-1.1 0-1.99.9-1.99 2zM19 7v10H5V7h14z"/></g> +<g id="stay-primary-portrait"><path d="M17 1.01L7 1c-1.1 0-1.99.9-1.99 2v18c0 1.1.89 2 1.99 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></g> +<g id="swap-calls"><path d="M18 4l-4 4h3v7c0 1.1-.9 2-2 2s-2-.9-2-2V8c0-2.21-1.79-4-4-4S5 5.79 5 8v7H2l4 4 4-4H7V8c0-1.1.9-2 2-2s2 .9 2 2v7c0 2.21 1.79 4 4 4s4-1.79 4-4V8h3l-4-4z"/></g> +<g id="textsms"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9 11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z"/></g> +<g id="voicemail"><path d="M18.5 6C15.46 6 13 8.46 13 11.5c0 1.33.47 2.55 1.26 3.5H9.74c.79-.95 1.26-2.17 1.26-3.5C11 8.46 8.54 6 5.5 6S0 8.46 0 11.5 2.46 17 5.5 17h13c3.04 0 5.5-2.46 5.5-5.5S21.54 6 18.5 6zm-13 9C3.57 15 2 13.43 2 11.5S3.57 8 5.5 8 9 9.57 9 11.5 7.43 15 5.5 15zm13 0c-1.93 0-3.5-1.57-3.5-3.5S16.57 8 18.5 8 22 9.57 22 11.5 20.43 15 18.5 15z"/></g> +<g id="vpn-key"><path d="M12.65 10C11.83 7.67 9.61 6 7 6c-3.31 0-6 2.69-6 6s2.69 6 6 6c2.61 0 4.83-1.67 5.65-4H17v4h4v-4h2v-4H12.65zM7 14c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/device-icons.html b/third_party/polymer/v0_8/components/iron-icons/device-icons.html new file mode 100644 index 0000000..8e6d9ca5 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/device-icons.html
@@ -0,0 +1,90 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="device" size="24"> +<svg><defs> +<g id="access-alarm"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="access-alarms"><path d="M22 5.7l-4.6-3.9-1.3 1.5 4.6 3.9L22 5.7zM7.9 3.4L6.6 1.9 2 5.7l1.3 1.5 4.6-3.8zM12.5 8H11v6l4.7 2.9.8-1.2-4-2.4V8zM12 4c-5 0-9 4-9 9s4 9 9 9 9-4 9-9-4-9-9-9zm0 16c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z"/></g> +<g id="access-time"><path fill-opacity=".9" d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zM12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></g> +<g id="add-alarm"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm1-11h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g> +<g id="airplanemode-off"><path d="M13 9V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v3.68l7.83 7.83L21 16v-2l-8-5zM3 5.27l4.99 4.99L2 14v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-3.73L18.73 21 20 19.73 4.27 4 3 5.27z"/></g> +<g id="airplanemode-on"><path d="M10.18 9"/><path d="M21 16v-2l-8-5V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5l8 2.5z"/></g> +<g id="battery-20"><path d="M7 17v3.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V17H7z"/><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V17h10V5.33z"/></g> +<g id="battery-30"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V15h10V5.33z"/><path d="M7 15v5.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V15H7z"/></g> +<g id="battery-50"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V13h10V5.33z"/><path d="M7 13v7.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V13H7z"/></g> +<g id="battery-60"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V11h10V5.33z"/><path d="M7 11v9.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V11H7z"/></g> +<g id="battery-80"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V9h10V5.33z"/><path d="M7 9v11.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V9H7z"/></g> +<g id="battery-90"><path fill-opacity=".3" d="M17 5.33C17 4.6 16.4 4 15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h10V5.33z"/><path d="M7 8v12.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V8H7z"/></g> +<g id="battery-alert"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM13 18h-2v-2h2v2zm0-4h-2V9h2v5z"/></g> +<g id="battery-charging-20"><path d="M11 20v-3H7v3.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V17h-4.4L11 20z"/><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V17h4v-2.5H9L13 7v5.5h2L12.6 17H17V5.33C17 4.6 16.4 4 15.67 4z"/></g> +<g id="battery-charging-30"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v9.17h2L13 7v5.5h2l-1.07 2H17V5.33C17 4.6 16.4 4 15.67 4z"/><path d="M11 20v-5.5H7v6.17C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V14.5h-3.07L11 20z"/></g> +<g id="battery-charging-50"><path d="M14.47 13.5L11 20v-5.5H9l.53-1H7v7.17C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V13.5h-2.53z"/><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v8.17h2.53L13 7v5.5h2l-.53 1H17V5.33C17 4.6 16.4 4 15.67 4z"/></g> +<g id="battery-charging-60"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V11h3.87L13 7v4h4V5.33C17 4.6 16.4 4 15.67 4z"/><path d="M13 12.5h2L11 20v-5.5H9l1.87-3.5H7v9.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V11h-4v1.5z"/></g> +<g id="battery-charging-80"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V9h4.93L13 7v2h4V5.33C17 4.6 16.4 4 15.67 4z"/><path d="M13 12.5h2L11 20v-5.5H9L11.93 9H7v11.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V9h-4v3.5z"/></g> +<g id="battery-charging-90"><path fill-opacity=".3" d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33V8h5.47L13 7v1h4V5.33C17 4.6 16.4 4 15.67 4z"/><path d="M13 12.5h2L11 20v-5.5H9L12.47 8H7v12.67C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V8h-4v4.5z"/></g> +<g id="battery-charging-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zM11 20v-5.5H9L13 7v5.5h2L11 20z"/></g> +<g id="battery-full"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4z"/></g> +<g id="battery-std"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4z"/></g> +<g id="battery-unknown"><path d="M15.67 4H14V2h-4v2H8.33C7.6 4 7 4.6 7 5.33v15.33C7 21.4 7.6 22 8.33 22h7.33c.74 0 1.34-.6 1.34-1.33V5.33C17 4.6 16.4 4 15.67 4zm-2.72 13.95h-1.9v-1.9h1.9v1.9zm1.35-5.26s-.38.42-.67.71c-.48.48-.83 1.15-.83 1.6h-1.6c0-.83.46-1.52.93-2l.93-.94c.27-.27.44-.65.44-1.06 0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5H9c0-1.66 1.34-3 3-3s3 1.34 3 3c0 .66-.27 1.26-.7 1.69z"/></g> +<g id="bluetooth"><path d="M17.71 7.71L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88z"/></g> +<g id="bluetooth-connected"><path d="M7 12l-2-2-2 2 2 2 2-2zm10.71-4.29L12 2h-1v7.59L6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 5.83l1.88 1.88L13 9.59V5.83zm1.88 10.46L13 18.17v-3.76l1.88 1.88zM19 10l-2 2 2 2 2-2-2-2z"/></g> +<g id="bluetooth-disabled"><path d="M13 5.83l1.88 1.88-1.6 1.6 1.41 1.41 3.02-3.02L12 2h-1v5.03l2 2v-3.2zM5.41 4L4 5.41 10.59 12 5 17.59 6.41 19 11 14.41V22h1l4.29-4.29 2.3 2.29L20 18.59 5.41 4zM13 18.17v-3.76l1.88 1.88L13 18.17z"/></g> +<g id="bluetooth-searching"><path d="M14.24 12.01l2.32 2.32c.28-.72.44-1.51.44-2.33 0-.82-.16-1.59-.43-2.31l-2.33 2.32zm5.29-5.3l-1.26 1.26c.63 1.21.98 2.57.98 4.02s-.36 2.82-.98 4.02l1.2 1.2c.97-1.54 1.54-3.36 1.54-5.31-.01-1.89-.55-3.67-1.48-5.19zm-3.82 1L10 2H9v7.59L4.41 5 3 6.41 8.59 12 3 17.59 4.41 19 9 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM11 5.83l1.88 1.88L11 9.59V5.83zm1.88 10.46L11 18.17v-3.76l1.88 1.88z"/></g> +<g id="brightness-auto"><path d="M10.85 12.65h2.3L12 9l-1.15 3.65zM20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM14.3 16l-.7-2h-3.2l-.7 2H7.8L11 7h2l3.2 9h-1.9z"/></g> +<g id="brightness-high"><path d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm0-10c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"/></g> +<g id="brightness-low"><path d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6z"/></g> +<g id="brightness-medium"><path d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18V6c3.31 0 6 2.69 6 6s-2.69 6-6 6z"/></g> +<g id="data-usage"><path d="M13 2.05v3.03c3.39.49 6 3.39 6 6.92 0 .9-.18 1.75-.48 2.54l2.6 1.53c.56-1.24.88-2.62.88-4.07 0-5.18-3.95-9.45-9-9.95zM12 19c-3.87 0-7-3.13-7-7 0-3.53 2.61-6.43 6-6.92V2.05c-5.06.5-9 4.76-9 9.95 0 5.52 4.47 10 9.99 10 3.31 0 6.24-1.61 8.06-4.09l-2.6-1.53C16.17 17.98 14.21 19 12 19z"/></g> +<g id="developer-mode"><path d="M7 5h10v2h2V3c0-1.1-.9-1.99-2-1.99L7 1c-1.1 0-2 .9-2 2v4h2V5zm8.41 11.59L20 12l-4.59-4.59L14 8.83 17.17 12 14 15.17l1.41 1.42zM10 15.17L6.83 12 10 8.83 8.59 7.41 4 12l4.59 4.59L10 15.17zM17 19H7v-2H5v4c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2v-4h-2v2z"/></g> +<g id="devices"><path d="M4 6h18V4H4c-1.1 0-2 .9-2 2v11H0v3h14v-3H4V6zm19 2h-6c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zm-1 9h-4v-7h4v7z"/></g> +<g id="dvr"><path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12zm-2-9H8v2h11V8zm0 4H8v2h11v-2zM7 8H5v2h2V8zm0 4H5v2h2v-2z"/></g> +<g id="gps-fixed"><path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="gps-not-fixed"><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="gps-off"><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06c-1.13.12-2.19.46-3.16.97l1.5 1.5C10.16 5.19 11.06 5 12 5c3.87 0 7 3.13 7 7 0 .94-.19 1.84-.52 2.65l1.5 1.5c.5-.96.84-2.02.97-3.15H23v-2h-2.06zM3 4.27l2.04 2.04C3.97 7.62 3.25 9.23 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c1.77-.2 3.38-.91 4.69-1.98L19.73 21 21 19.73 4.27 3 3 4.27zm13.27 13.27C15.09 18.45 13.61 19 12 19c-3.87 0-7-3.13-7-7 0-1.61.55-3.09 1.46-4.27l9.81 9.81z"/></g> +<g id="location-disabled"><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06c-1.13.12-2.19.46-3.16.97l1.5 1.5C10.16 5.19 11.06 5 12 5c3.87 0 7 3.13 7 7 0 .94-.19 1.84-.52 2.65l1.5 1.5c.5-.96.84-2.02.97-3.15H23v-2h-2.06zM3 4.27l2.04 2.04C3.97 7.62 3.25 9.23 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c1.77-.2 3.38-.91 4.69-1.98L19.73 21 21 19.73 4.27 3 3 4.27zm13.27 13.27C15.09 18.45 13.61 19 12 19c-3.87 0-7-3.13-7-7 0-1.61.55-3.09 1.46-4.27l9.81 9.81z"/></g> +<g id="location-searching"><path d="M20.94 11c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="multitrack-audio"><path d="M7 18h2V6H7v12zm4 4h2V2h-2v20zm-8-8h2v-4H3v4zm12 4h2V6h-2v12zm4-8v4h2v-4h-2z"/></g> +<g id="network-cell"><path fill-opacity=".3" d="M2 22h20V2z"/><path d="M17 7L2 22h15z"/></g> +<g id="network-wifi"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/><path d="M3.53 10.95l8.46 10.54.01.01.01-.01 8.46-10.54C20.04 10.62 16.81 8 12 8c-4.81 0-8.04 2.62-8.47 2.95z"/></g> +<g id="nfc"><path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 18H4V4h16v16zM18 6h-5c-1.1 0-2 .9-2 2v2.28c-.6.35-1 .98-1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V8h3v8H8V8h2V6H6v12h12V6z"/></g> +<g id="now-wallpaper"><path d="M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2V4zm6 9l-4 5h12l-3-4-2.03 2.71L10 13zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5zM20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2zm0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z"/></g> +<g id="now-widgets"><path d="M13 13v8h8v-8h-8zM3 21h8v-8H3v8zM3 3v8h8V3H3zm13.66-1.31L11 7.34 16.66 13l5.66-5.66-5.66-5.65z"/></g> +<g id="screen-lock-landscape"><path d="M21 5H3c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-2 12H5V7h14v10zm-9-1h4c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1v-1c0-1.11-.9-2-2-2-1.11 0-2 .9-2 2v1c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1zm.8-6c0-.66.54-1.2 1.2-1.2.66 0 1.2.54 1.2 1.2v1h-2.4v-1z"/></g> +<g id="screen-lock-portrait"><path d="M10 16h4c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1v-1c0-1.11-.9-2-2-2-1.11 0-2 .9-2 2v1c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1zm.8-6c0-.66.54-1.2 1.2-1.2.66 0 1.2.54 1.2 1.2v1h-2.4v-1zM17 1H7c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 18H7V5h10v14z"/></g> +<g id="screen-lock-rotation"><path d="M23.25 12.77l-2.57-2.57-1.41 1.41 2.22 2.22-5.66 5.66L4.51 8.17l5.66-5.66 2.1 2.1 1.41-1.41L11.23.75c-.59-.59-1.54-.59-2.12 0L2.75 7.11c-.59.59-.59 1.54 0 2.12l12.02 12.02c.59.59 1.54.59 2.12 0l6.36-6.36c.59-.59.59-1.54 0-2.12zM8.47 20.48C5.2 18.94 2.86 15.76 2.5 12H1c.51 6.16 5.66 11 11.95 11l.66-.03-3.81-3.82-1.33 1.33zM16 9h5c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1v-.5C21 1.12 19.88 0 18.5 0S16 1.12 16 2.5V3c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1zm.8-6.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V3h-3.4v-.5z"/></g> +<g id="screen-rotation"><path d="M16.48 2.52c3.27 1.55 5.61 4.72 5.97 8.48h1.5C23.44 4.84 18.29 0 12 0l-.66.03 3.81 3.81 1.33-1.32zm-6.25-.77c-.59-.59-1.54-.59-2.12 0L1.75 8.11c-.59.59-.59 1.54 0 2.12l12.02 12.02c.59.59 1.54.59 2.12 0l6.36-6.36c.59-.59.59-1.54 0-2.12L10.23 1.75zm4.6 19.44L2.81 9.17l6.36-6.36 12.02 12.02-6.36 6.36zm-7.31.29C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-3.81-3.81-1.33 1.32z"/></g> +<g id="sd-storage"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-6 6h-2V4h2v4zm3 0h-2V4h2v4zm3 0h-2V4h2v4z"/></g> +<g id="settings-system-daydream"><path d="M9 16h6.5c1.38 0 2.5-1.12 2.5-2.5S16.88 11 15.5 11h-.05c-.24-1.69-1.69-3-3.45-3-1.4 0-2.6.83-3.16 2.02h-.16C7.17 10.18 6 11.45 6 13c0 1.66 1.34 3 3 3zM21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"/></g> +<g id="signal-cellular-0-bar"><path fill-opacity=".3" d="M2 22h20V2z"/></g> +<g id="signal-cellular-1-bar"><path fill-opacity=".3" d="M2 22h20V2z"/><path d="M12 12L2 22h10z"/></g> +<g id="signal-cellular-2-bar"><path fill-opacity=".3" d="M2 22h20V2z"/><path d="M14 10L2 22h12z"/></g> +<g id="signal-cellular-3-bar"><path fill-opacity=".3" d="M2 22h20V2z"/><path d="M17 7L2 22h15z"/></g> +<g id="signal-cellular-4-bar"><path d="M2 22h20V2z"/></g> +<g id="signal-cellular-connected-no-internet-0-bar"><path fill-opacity=".3" d="M22 8V2L2 22h16V8z"/><path d="M20 22h2v-2h-2v2zm0-12v8h2v-8h-2z"/></g> +<g id="signal-cellular-connected-no-internet-1-bar"><path fill-opacity=".3" d="M22 8V2L2 22h16V8z"/><path d="M20 10v8h2v-8h-2zm-8 12V12L2 22h10zm8 0h2v-2h-2v2z"/></g> +<g id="signal-cellular-connected-no-internet-2-bar"><path fill-opacity=".3" d="M22 8V2L2 22h16V8z"/><path d="M14 22V10L2 22h12zm6-12v8h2v-8h-2zm0 12h2v-2h-2v2z"/></g> +<g id="signal-cellular-connected-no-internet-3-bar"><path fill-opacity=".3" d="M22 8V2L2 22h16V8z"/><path d="M17 22V7L2 22h15zm3-12v8h2v-8h-2zm0 12h2v-2h-2v2z"/></g> +<g id="signal-cellular-connected-no-internet-4-bar"><path d="M20 18h2v-8h-2v8zm0 4h2v-2h-2v2zM2 22h16V8h4V2L2 22z"/></g> +<g id="signal-cellular-no-sim"><path d="M18.99 5c0-1.1-.89-2-1.99-2h-7L7.66 5.34 19 16.68 18.99 5zM3.65 3.88L2.38 5.15 5 7.77V19c0 1.1.9 2 2 2h10.01c.35 0 .67-.1.96-.26l1.88 1.88 1.27-1.27L3.65 3.88z"/></g> +<g id="signal-cellular-null"><path d="M20 6.83V20H6.83L20 6.83M22 2L2 22h20V2z"/></g> +<g id="signal-cellular-off"><path d="M21 1l-8.59 8.59L21 18.18V1zM4.77 4.5L3.5 5.77l6.36 6.36L1 21h17.73l2 2L22 21.73 4.77 4.5z"/></g> +<g id="signal-wifi-0-bar"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/></g> +<g id="signal-wifi-1-bar"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/><path d="M6.67 14.86L12 21.49v.01l.01-.01 5.33-6.63C17.06 14.65 15.03 13 12 13s-5.06 1.65-5.33 1.86z"/></g> +<g id="signal-wifi-2-bar"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/><path d="M4.79 12.52l7.2 8.98H12l.01-.01 7.2-8.98C18.85 12.24 16.1 10 12 10s-6.85 2.24-7.21 2.52z"/></g> +<g id="signal-wifi-3-bar"><path fill-opacity=".3" d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/><path d="M3.53 10.95l8.46 10.54.01.01.01-.01 8.46-10.54C20.04 10.62 16.81 8 12 8c-4.81 0-8.04 2.62-8.47 2.95z"/></g> +<g id="signal-wifi-4-bar"><path d="M12.01 21.49L23.64 7c-.45-.34-4.93-4-11.64-4C5.28 3 .81 6.66.36 7l11.63 14.49.01.01.01-.01z"/></g> +<g id="signal-wifi-off"><path d="M23.64 7c-.45-.34-4.93-4-11.64-4-1.5 0-2.89.19-4.15.48L18.18 13.8 23.64 7zm-6.6 8.22L3.27 1.44 2 2.72l2.05 2.06C1.91 5.76.59 6.82.36 7l11.63 14.49.01.01.01-.01 3.9-4.86 3.32 3.32 1.27-1.27-3.46-3.46z"/></g> +<g id="storage"><path d="M2 20h20v-4H2v4zm2-3h2v2H4v-2zM2 4v4h20V4H2zm4 3H4V5h2v2zm-4 7h20v-4H2v4zm2-3h2v2H4v-2z"/></g> +<g id="usb"><path d="M15 7v4h1v2h-3V5h2l-3-4-3 4h2v8H8v-2.07c.7-.37 1.2-1.08 1.2-1.93 0-1.21-.99-2.2-2.2-2.2-1.21 0-2.2.99-2.2 2.2 0 .85.5 1.56 1.2 1.93V13c0 1.11.89 2 2 2h3v3.05c-.71.37-1.2 1.1-1.2 1.95 0 1.22.99 2.2 2.2 2.2 1.21 0 2.2-.98 2.2-2.2 0-.85-.49-1.58-1.2-1.95V15h3c1.11 0 2-.89 2-2v-2h1V7h-4z"/></g> +<g id="wifi-lock"><path d="M20.5 9.5c.28 0 .55.04.81.08L24 6c-3.34-2.51-7.5-4-12-4S3.34 3.49 0 6l12 16 3.5-4.67V14.5c0-2.76 2.24-5 5-5zM23 16v-1.5c0-1.38-1.12-2.5-2.5-2.5S18 13.12 18 14.5V16c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1v-4c0-.55-.45-1-1-1zm-1 0h-3v-1.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V16z"/></g> +<g id="wifi-tethering"><path d="M12 11c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 2c0-3.31-2.69-6-6-6s-6 2.69-6 6c0 2.22 1.21 4.15 3 5.19l1-1.74c-1.19-.7-2-1.97-2-3.45 0-2.21 1.79-4 4-4s4 1.79 4 4c0 1.48-.81 2.75-2 3.45l1 1.74c1.79-1.04 3-2.97 3-5.19zM12 3C6.48 3 2 7.48 2 13c0 3.7 2.01 6.92 4.99 8.65l1-1.73C5.61 18.53 4 15.96 4 13c0-4.42 3.58-8 8-8s8 3.58 8 8c0 2.96-1.61 5.53-4 6.92l1 1.73c2.99-1.73 5-4.95 5-8.65 0-5.52-4.48-10-10-10z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/editor-icons.html b/third_party/polymer/v0_8/components/iron-icons/editor-icons.html new file mode 100644 index 0000000..a5170ea --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/editor-icons.html
@@ -0,0 +1,67 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="editor" size="24"> +<svg><defs> +<g id="attach-file"><path d="M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z"/></g> +<g id="attach-money"><path d="M11.8 10.9c-2.27-.59-3-1.2-3-2.15 0-1.09 1.01-1.85 2.7-1.85 1.78 0 2.44.85 2.5 2.1h2.21c-.07-1.72-1.12-3.3-3.21-3.81V3h-3v2.16c-1.94.42-3.5 1.68-3.5 3.61 0 2.31 1.91 3.46 4.7 4.13 2.5.6 3 1.48 3 2.41 0 .69-.49 1.79-2.7 1.79-2.06 0-2.87-.92-2.98-2.1h-2.2c.12 2.19 1.76 3.42 3.68 3.83V21h3v-2.15c1.95-.37 3.5-1.5 3.5-3.55 0-2.84-2.43-3.81-4.7-4.4z"/></g> +<g id="border-all"><path d="M3 3v18h18V3H3zm8 16H5v-6h6v6zm0-8H5V5h6v6zm8 8h-6v-6h6v6zm0-8h-6V5h6v6z"/></g> +<g id="border-bottom"><path d="M9 11H7v2h2v-2zm4 4h-2v2h2v-2zM9 3H7v2h2V3zm4 8h-2v2h2v-2zM5 3H3v2h2V3zm8 4h-2v2h2V7zm4 4h-2v2h2v-2zm-4-8h-2v2h2V3zm4 0h-2v2h2V3zm2 10h2v-2h-2v2zm0 4h2v-2h-2v2zM5 7H3v2h2V7zm14-4v2h2V3h-2zm0 6h2V7h-2v2zM5 11H3v2h2v-2zM3 21h18v-2H3v2zm2-6H3v2h2v-2z"/></g> +<g id="border-clear"><path d="M7 5h2V3H7v2zm0 8h2v-2H7v2zm0 8h2v-2H7v2zm4-4h2v-2h-2v2zm0 4h2v-2h-2v2zm-8 0h2v-2H3v2zm0-4h2v-2H3v2zm0-4h2v-2H3v2zm0-4h2V7H3v2zm0-4h2V3H3v2zm8 8h2v-2h-2v2zm8 4h2v-2h-2v2zm0-4h2v-2h-2v2zm0 8h2v-2h-2v2zm0-12h2V7h-2v2zm-8 0h2V7h-2v2zm8-6v2h2V3h-2zm-8 2h2V3h-2v2zm4 16h2v-2h-2v2zm0-8h2v-2h-2v2zm0-8h2V3h-2v2z"/></g> +<g id="border-color"><path d="M17.75 7L14 3.25l-10 10V17h3.75l10-10zm2.96-2.96c.39-.39.39-1.02 0-1.41L18.37.29c-.39-.39-1.02-.39-1.41 0L15 2.25 18.75 6l1.96-1.96z"/><path fill-opacity=".36" d="M0 20h24v4H0z"/></g> +<g id="border-horizontal"><path d="M3 21h2v-2H3v2zM5 7H3v2h2V7zM3 17h2v-2H3v2zm4 4h2v-2H7v2zM5 3H3v2h2V3zm4 0H7v2h2V3zm8 0h-2v2h2V3zm-4 4h-2v2h2V7zm0-4h-2v2h2V3zm6 14h2v-2h-2v2zm-8 4h2v-2h-2v2zm-8-8h18v-2H3v2zM19 3v2h2V3h-2zm0 6h2V7h-2v2zm-8 8h2v-2h-2v2zm4 4h2v-2h-2v2zm4 0h2v-2h-2v2z"/></g> +<g id="border-inner"><path d="M3 21h2v-2H3v2zm4 0h2v-2H7v2zM5 7H3v2h2V7zM3 17h2v-2H3v2zM9 3H7v2h2V3zM5 3H3v2h2V3zm12 0h-2v2h2V3zm2 6h2V7h-2v2zm0-6v2h2V3h-2zm-4 18h2v-2h-2v2zM13 3h-2v8H3v2h8v8h2v-8h8v-2h-8V3zm6 18h2v-2h-2v2zm0-4h2v-2h-2v2z"/></g> +<g id="border-left"><path d="M11 21h2v-2h-2v2zm0-4h2v-2h-2v2zm0-12h2V3h-2v2zm0 4h2V7h-2v2zm0 4h2v-2h-2v2zm-4 8h2v-2H7v2zM7 5h2V3H7v2zm0 8h2v-2H7v2zm-4 8h2V3H3v18zM19 9h2V7h-2v2zm-4 12h2v-2h-2v2zm4-4h2v-2h-2v2zm0-14v2h2V3h-2zm0 10h2v-2h-2v2zm0 8h2v-2h-2v2zm-4-8h2v-2h-2v2zm0-8h2V3h-2v2z"/></g> +<g id="border-outer"><path d="M13 7h-2v2h2V7zm0 4h-2v2h2v-2zm4 0h-2v2h2v-2zM3 3v18h18V3H3zm16 16H5V5h14v14zm-6-4h-2v2h2v-2zm-4-4H7v2h2v-2z"/></g> +<g id="border-right"><path d="M7 21h2v-2H7v2zM3 5h2V3H3v2zm4 0h2V3H7v2zm0 8h2v-2H7v2zm-4 8h2v-2H3v2zm8 0h2v-2h-2v2zm-8-8h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm8 8h2v-2h-2v2zm4-4h2v-2h-2v2zm4-10v18h2V3h-2zm-4 18h2v-2h-2v2zm0-16h2V3h-2v2zm-4 8h2v-2h-2v2zm0-8h2V3h-2v2zm0 4h2V7h-2v2z"/></g> +<g id="border-style"><path d="M15 21h2v-2h-2v2zm4 0h2v-2h-2v2zM7 21h2v-2H7v2zm4 0h2v-2h-2v2zm8-4h2v-2h-2v2zm0-4h2v-2h-2v2zM3 3v18h2V5h16V3H3zm16 6h2V7h-2v2z"/></g> +<g id="border-top"><path d="M7 21h2v-2H7v2zm0-8h2v-2H7v2zm4 0h2v-2h-2v2zm0 8h2v-2h-2v2zm-8-4h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2v-2H3v2zm0-4h2V7H3v2zm8 8h2v-2h-2v2zm8-8h2V7h-2v2zm0 4h2v-2h-2v2zM3 3v2h18V3H3zm16 14h2v-2h-2v2zm-4 4h2v-2h-2v2zM11 9h2V7h-2v2zm8 12h2v-2h-2v2zm-4-8h2v-2h-2v2z"/></g> +<g id="border-vertical"><path d="M3 9h2V7H3v2zm0-4h2V3H3v2zm4 16h2v-2H7v2zm0-8h2v-2H7v2zm-4 0h2v-2H3v2zm0 8h2v-2H3v2zm0-4h2v-2H3v2zM7 5h2V3H7v2zm12 12h2v-2h-2v2zm-8 4h2V3h-2v18zm8 0h2v-2h-2v2zm0-8h2v-2h-2v2zm0-10v2h2V3h-2zm0 6h2V7h-2v2zm-4-4h2V3h-2v2zm0 16h2v-2h-2v2zm0-8h2v-2h-2v2z"/></g> +<g id="format-align-center"><path d="M7 15v2h10v-2H7zm-4 6h18v-2H3v2zm0-8h18v-2H3v2zm4-6v2h10V7H7zM3 3v2h18V3H3z"/></g> +<g id="format-align-justify"><path d="M3 21h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18v-2H3v2zm0-4h18V7H3v2zm0-6v2h18V3H3z"/></g> +<g id="format-align-left"><path d="M15 15H3v2h12v-2zm0-8H3v2h12V7zM3 13h18v-2H3v2zm0 8h18v-2H3v2zM3 3v2h18V3H3z"/></g> +<g id="format-align-right"><path d="M3 21h18v-2H3v2zm6-4h12v-2H9v2zm-6-4h18v-2H3v2zm6-4h12V7H9v2zM3 3v2h18V3H3z"/></g> +<g id="format-bold"><path d="M15.6 10.79c.97-.67 1.65-1.77 1.65-2.79 0-2.26-1.75-4-4-4H7v14h7.04c2.09 0 3.71-1.7 3.71-3.79 0-1.52-.86-2.82-2.15-3.42zM10 6.5h3c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5h-3v-3zm3.5 9H10v-3h3.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5z"/></g> +<g id="format-clear"><path d="M3.27 5L2 6.27l6.97 6.97L6.5 19h3l1.57-3.66L16.73 21 18 19.73 3.55 5.27 3.27 5zM6 5v.18L8.82 8h2.4l-.72 1.68 2.1 2.1L14.21 8H20V5H6z"/></g> +<g id="format-color-fill"><path d="M16.56 8.94L7.62 0 6.21 1.41l2.38 2.38-5.15 5.15c-.59.59-.59 1.54 0 2.12l5.5 5.5c.29.29.68.44 1.06.44s.77-.15 1.06-.44l5.5-5.5c.59-.58.59-1.53 0-2.12zM5.21 10L10 5.21 14.79 10H5.21zM19 11.5s-2 2.17-2 3.5c0 1.1.9 2 2 2s2-.9 2-2c0-1.33-2-3.5-2-3.5z"/><path fill-opacity=".36" d="M0 20h24v4H0z"/></g> +<g id="format-color-reset"><path d="M18 14c0-4-6-10.8-6-10.8s-1.33 1.51-2.73 3.52l8.59 8.59c.09-.42.14-.86.14-1.31zm-.88 3.12L12.5 12.5 5.27 5.27 4 6.55l3.32 3.32C6.55 11.32 6 12.79 6 14c0 3.31 2.69 6 6 6 1.52 0 2.9-.57 3.96-1.5l2.63 2.63 1.27-1.27-2.74-2.74z"/></g> +<g id="format-color-text"><path fill-opacity=".36" d="M0 20h24v4H0z"/><path d="M11 3L5.5 17h2.25l1.12-3h6.25l1.12 3h2.25L13 3h-2zm-1.38 9L12 5.67 14.38 12H9.62z"/></g> +<g id="format-indent-decrease"><path d="M11 17h10v-2H11v2zm-8-5l4 4V8l-4 4zm0 9h18v-2H3v2zM3 3v2h18V3H3zm8 6h10V7H11v2zm0 4h10v-2H11v2z"/></g> +<g id="format-indent-increase"><path d="M3 21h18v-2H3v2zM3 8v8l4-4-4-4zm8 9h10v-2H11v2zM3 3v2h18V3H3zm8 6h10V7H11v2zm0 4h10v-2H11v2z"/></g> +<g id="format-italic"><path d="M10 4v3h2.21l-3.42 8H6v3h8v-3h-2.21l3.42-8H18V4z"/></g> +<g id="format-line-spacing"><path d="M6 7h2.5L5 3.5 1.5 7H4v10H1.5L5 20.5 8.5 17H6V7zm4-2v2h12V5H10zm0 14h12v-2H10v2zm0-6h12v-2H10v2z"/></g> +<g id="format-list-bulleted"><path d="M4 10.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-6c-.83 0-1.5.67-1.5 1.5S3.17 7.5 4 7.5 5.5 6.83 5.5 6 4.83 4.5 4 4.5zm0 12.17c-.74 0-1.33.6-1.33 1.33s.6 1.33 1.33 1.33 1.33-.6 1.33-1.33-.59-1.33-1.33-1.33zM7 19h14v-2H7v2zm0-6h14v-2H7v2zm0-8v2h14V5H7z"/></g> +<g id="format-list-numbered"><path d="M2 17h2v.5H3v1h1v.5H2v1h3v-4H2v1zm1-9h1V4H2v1h1v3zm-1 3h1.8L2 13.1v.9h3v-1H3.2L5 10.9V10H2v1zm5-6v2h14V5H7zm0 14h14v-2H7v2zm0-6h14v-2H7v2z"/></g> +<g id="format-paint"><path d="M18 4V3c0-.55-.45-1-1-1H5c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6h1v4H9v11c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-9h8V4h-3z"/></g> +<g id="format-quote"><path d="M6 17h3l2-4V7H5v6h3zm8 0h3l2-4V7h-6v6h3z"/></g> +<g id="format-size"><path d="M9 4v3h5v12h3V7h5V4H9zm-6 8h3v7h3v-7h3V9H3v3z"/></g> +<g id="format-strikethrough"><path d="M10 19h4v-3h-4v3zM5 4v3h5v3h4V7h5V4H5zM3 14h18v-2H3v2z"/></g> +<g id="format-textdirection-l-to-r"><path d="M9 10v5h2V4h2v11h2V4h2V2H9C6.79 2 5 3.79 5 6s1.79 4 4 4zm12 8l-4-4v3H5v2h12v3l4-4z"/></g> +<g id="format-textdirection-r-to-l"><path d="M10 10v5h2V4h2v11h2V4h2V2h-8C7.79 2 6 3.79 6 6s1.79 4 4 4zm-2 7v-3l-4 4 4 4v-3h12v-2H8z"/></g> +<g id="format-underline"><path d="M12 17c3.31 0 6-2.69 6-6V3h-2.5v8c0 1.93-1.57 3.5-3.5 3.5S8.5 12.93 8.5 11V3H6v8c0 3.31 2.69 6 6 6zm-7 2v2h14v-2H5z"/></g> +<g id="functions"><path d="M18 4H6v2l6.5 6L6 18v2h12v-3h-7l5-5-5-5h7z"/></g> +<g id="insert-chart"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/></g> +<g id="insert-comment"><path d="M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z"/></g> +<g id="insert-drive-file"><path d="M6 2c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6H6zm7 7V3.5L18.5 9H13z"/></g> +<g id="insert-emoticon"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></g> +<g id="insert-invitation"><path d="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"/></g> +<g id="insert-link"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></g> +<g id="insert-photo"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></g> +<g id="merge-type"><path d="M17 20.41L18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z"/></g> +<g id="mode-comment"><path d="M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4-.01-18z"/></g> +<g id="mode-edit"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></g> +<g id="publish"><path d="M5 4v2h14V4H5zm0 10h4v6h6v-6h4l-7-7-7 7z"/></g> +<g id="vertical-align-bottom"><path d="M16 13h-3V3h-2v10H8l4 4 4-4zM4 19v2h16v-2H4z"/></g> +<g id="vertical-align-center"><path d="M8 19h3v4h2v-4h3l-4-4-4 4zm8-14h-3V1h-2v4H8l4 4 4-4zM4 11v2h16v-2H4z"/></g> +<g id="vertical-align-top"><path d="M8 11h3v10h2V11h3l-4-4-4 4zM4 3v2h16V3H4z"/></g> +<g id="wrap-text"><path d="M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3 3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/hardware-icons.html b/third_party/polymer/v0_8/components/iron-icons/hardware-icons.html new file mode 100644 index 0000000..326cb98 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/hardware-icons.html
@@ -0,0 +1,56 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="hardware" size="24"> +<svg><defs> +<g id="cast"><path d="M21 3H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm0-4v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11z"/></g> +<g id="cast-connected"><path d="M1 18v3h3c0-1.66-1.34-3-3-3zm0-4v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm18-7H5v1.63c3.96 1.28 7.09 4.41 8.37 8.37H19V7zM1 10v2c4.97 0 9 4.03 9 9h2c0-6.08-4.93-11-11-11zm20-7H3c-1.1 0-2 .9-2 2v3h2V5h18v14h-7v2h7c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></g> +<g id="computer"><path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"/></g> +<g id="desktop-mac"><path d="M21 2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7l-2 3v1h8v-1l-2-3h7c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 12H3V4h18v10z"/></g> +<g id="desktop-windows"><path d="M21 2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7v2H8v2h8v-2h-2v-2h7c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H3V4h18v12z"/></g> +<g id="dock"><path d="M8 23h8v-2H8v2zm8-21.99L8 1c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM16 15H8V5h8v10z"/></g> +<g id="gamepad"><path d="M15 7.5V2H9v5.5l3 3 3-3zM7.5 9H2v6h5.5l3-3-3-3zM9 16.5V22h6v-5.5l-3-3-3 3zM16.5 9l-3 3 3 3H22V9h-5.5z"/></g> +<g id="headset"><path d="M12 1c-4.97 0-9 4.03-9 9v7c0 1.66 1.34 3 3 3h3v-8H5v-2c0-3.87 3.13-7 7-7s7 3.13 7 7v2h-4v8h3c1.66 0 3-1.34 3-3v-7c0-4.97-4.03-9-9-9z"/></g> +<g id="headset-mic"><path d="M12 1c-4.97 0-9 4.03-9 9v7c0 1.66 1.34 3 3 3h3v-8H5v-2c0-3.87 3.13-7 7-7s7 3.13 7 7v2h-4v8h4v1h-7v2h6c1.66 0 3-1.34 3-3V10c0-4.97-4.03-9-9-9z"/></g> +<g id="keyboard"><path d="M20 5H4c-1.1 0-1.99.9-1.99 2L2 17c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-9 3h2v2h-2V8zm0 3h2v2h-2v-2zM8 8h2v2H8V8zm0 3h2v2H8v-2zm-1 2H5v-2h2v2zm0-3H5V8h2v2zm9 7H8v-2h8v2zm0-4h-2v-2h2v2zm0-3h-2V8h2v2zm3 3h-2v-2h2v2zm0-3h-2V8h2v2z"/></g> +<g id="keyboard-alt"><path d="M15.5 10c.83 0 1.5-.67 1.5-1.5S16.33 7 15.5 7 14 7.67 14 8.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 7 8.5 7 7 7.67 7 8.5 7.67 10 8.5 10zm3.5 7c2.61 0 4.83-1.67 5.65-4H6.35c.82 2.33 3.04 4 5.65 4zm-.01-16C6.47 1 2 5.48 2 11s4.47 10 9.99 10C17.52 21 22 16.52 22 11S17.52 1 11.99 1zM12 19c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></g> +<g id="keyboard-arrow-down"><path d="M7.41 7.84L12 12.42l4.59-4.58L18 9.25l-6 6-6-6z"/></g> +<g id="keyboard-arrow-left"><path d="M15.41 16.09l-4.58-4.59 4.58-4.59L14 5.5l-6 6 6 6z"/></g> +<g id="keyboard-arrow-right"><path d="M8.59 16.34l4.58-4.59-4.58-4.59L10 5.75l6 6-6 6z"/></g> +<g id="keyboard-arrow-up"><path d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"/></g> +<g id="keyboard-backspace"><path d="M21 11H6.83l3.58-3.59L9 6l-6 6 6 6 1.41-1.41L6.83 13H21z"/></g> +<g id="keyboard-capslock"><path d="M12 8.41L16.59 13 18 11.59l-6-6-6 6L7.41 13 12 8.41zM6 18h12v-2H6v2z"/></g> +<g id="keyboard-control"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="keyboard-hide"><path d="M20 3H4c-1.1 0-1.99.9-1.99 2L2 15c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-9 3h2v2h-2V6zm0 3h2v2h-2V9zM8 6h2v2H8V6zm0 3h2v2H8V9zm-1 2H5V9h2v2zm0-3H5V6h2v2zm9 7H8v-2h8v2zm0-4h-2V9h2v2zm0-3h-2V6h2v2zm3 3h-2V9h2v2zm0-3h-2V6h2v2zm-7 15l4-4H8l4 4z"/></g> +<g id="keyboard-return"><path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/></g> +<g id="keyboard-tab"><path d="M11.59 7.41L15.17 11H1v2h14.17l-3.59 3.59L13 18l6-6-6-6-1.41 1.41zM20 6v12h2V6h-2z"/></g> +<g id="keyboard-voice"><path d="M12 15c1.66 0 2.99-1.34 2.99-3L15 6c0-1.66-1.34-3-3-3S9 4.34 9 6v6c0 1.66 1.34 3 3 3zm5.3-3c0 3-2.54 5.1-5.3 5.1S6.7 15 6.7 12H5c0 3.42 2.72 6.23 6 6.72V22h2v-3.28c3.28-.48 6-3.3 6-6.72h-1.7z"/></g> +<g id="laptop"><path d="M20 18c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"/></g> +<g id="laptop-chromebook"><path d="M22 18V3H2v15H0v2h24v-2h-2zm-8 0h-4v-1h4v1zm6-3H4V5h16v10z"/></g> +<g id="laptop-mac"><path d="M20 18c1.1 0 1.99-.9 1.99-2L22 5c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v11c0 1.1.9 2 2 2H0c0 1.1.9 2 2 2h20c1.1 0 2-.9 2-2h-4zM4 5h16v11H4V5zm8 14c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></g> +<g id="laptop-windows"><path d="M20 18v-1c1.1 0 1.99-.9 1.99-2L22 5c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2v1H0v2h24v-2h-4zM4 5h16v10H4V5z"/></g> +<g id="memory"><path d="M15 9H9v6h6V9zm-2 4h-2v-2h2v2zm8-2V9h-2V7c0-1.1-.9-2-2-2h-2V3h-2v2h-2V3H9v2H7c-1.1 0-2 .9-2 2v2H3v2h2v2H3v2h2v2c0 1.1.9 2 2 2h2v2h2v-2h2v2h2v-2h2c1.1 0 2-.9 2-2v-2h2v-2h-2v-2h2zm-4 6H7V7h10v10z"/></g> +<g id="mouse"><path d="M13 1.07V9h7c0-4.08-3.05-7.44-7-7.93zM4 15c0 4.42 3.58 8 8 8s8-3.58 8-8v-4H4v4zm7-13.93C7.05 1.56 4 4.92 4 9h7V1.07z"/></g> +<g id="phone-android"><path d="M16 1H8C6.34 1 5 2.34 5 4v16c0 1.66 1.34 3 3 3h8c1.66 0 3-1.34 3-3V4c0-1.66-1.34-3-3-3zm-2 20h-4v-1h4v1zm3.25-3H6.75V4h10.5v14z"/></g> +<g id="phone-iphone"><path d="M15.5 1h-8C6.12 1 5 2.12 5 3.5v17C5 21.88 6.12 23 7.5 23h8c1.38 0 2.5-1.12 2.5-2.5v-17C18 2.12 16.88 1 15.5 1zm-4 21c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm4.5-4H7V4h9v14z"/></g> +<g id="phonelink"><path d="M4 6h18V4H4c-1.1 0-2 .9-2 2v11H0v3h14v-3H4V6zm19 2h-6c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zm-1 9h-4v-7h4v7z"/></g> +<g id="phonelink-off"><path d="M22 6V4H6.82l2 2H22zM1.92 1.65L.65 2.92l1.82 1.82C2.18 5.08 2 5.52 2 6v11H0v3h17.73l2.35 2.35 1.27-1.27L3.89 3.62 1.92 1.65zM4 6.27L14.73 17H4V6.27zM23 8h-6c-.55 0-1 .45-1 1v4.18l2 2V10h4v7h-2.18l3 3H23c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1z"/></g> +<g id="security"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/></g> +<g id="sim-card"><path d="M19.99 4c0-1.1-.89-2-1.99-2h-8L4 8v12c0 1.1.9 2 2 2h12.01c1.1 0 1.99-.9 1.99-2l-.01-16zM9 19H7v-2h2v2zm8 0h-2v-2h2v2zm-8-4H7v-4h2v4zm4 4h-2v-4h2v4zm0-6h-2v-2h2v2zm4 2h-2v-4h2v4z"/></g> +<g id="smartphone"><path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></g> +<g id="speaker"><path d="M17 2H7c-1.1 0-2 .9-2 2v16c0 1.1.9 1.99 2 1.99L17 22c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 2c1.1 0 2 .9 2 2s-.9 2-2 2c-1.11 0-2-.9-2-2s.89-2 2-2zm0 16c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g> +<g id="tablet"><path d="M21 4H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 1.99-.9 1.99-2L23 6c0-1.1-.9-2-2-2zm-2 14H5V6h14v12z"/></g> +<g id="tablet-android"><path d="M18 0H6C4.34 0 3 1.34 3 3v18c0 1.66 1.34 3 3 3h12c1.66 0 3-1.34 3-3V3c0-1.66-1.34-3-3-3zm-4 22h-4v-1h4v1zm5.25-3H4.75V3h14.5v16z"/></g> +<g id="tablet-mac"><path d="M18.5 0h-14C3.12 0 2 1.12 2 2.5v19C2 22.88 3.12 24 4.5 24h14c1.38 0 2.5-1.12 2.5-2.5v-19C21 1.12 19.88 0 18.5 0zm-7 23c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm7.5-4H4V3h15v16z"/></g> +<g id="tv"><path d="M21 3H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h5v2h8v-2h5c1.1 0 1.99-.9 1.99-2L23 5c0-1.1-.9-2-2-2zm0 14H3V5h18v12z"/></g> +<g id="watch"><path d="M20 12c0-2.54-1.19-4.81-3.04-6.27L16 0H8l-.95 5.73C5.19 7.19 4 9.45 4 12s1.19 4.81 3.05 6.27L8 24h8l.96-5.73C18.81 16.81 20 14.54 20 12zM6 12c0-3.31 2.69-6 6-6s6 2.69 6 6-2.69 6-6 6-6-2.69-6-6z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/image-icons.html b/third_party/polymer/v0_8/components/iron-icons/image-icons.html new file mode 100644 index 0000000..a7ebc70 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/image-icons.html
@@ -0,0 +1,152 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="image" size="24"> +<svg><defs> +<g id="add-to-photos"><path d="M4 6H2v14c0 1.1.9 2 2 2h14v-2H4V6zm16-4H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-1 9h-4v4h-2v-4H9V9h4V5h2v4h4v2z"/></g> +<g id="adjust"><path d="M12 2C6.49 2 2 6.49 2 12s4.49 10 10 10 10-4.49 10-10S17.51 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm3-8c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34 3 3z"/></g> +<g id="assistant-photo"><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/></g> +<g id="audiotrack"><path d="M12 3v9.28c-.47-.17-.97-.28-1.5-.28C8.01 12 6 14.01 6 16.5S8.01 21 10.5 21c2.31 0 4.2-1.75 4.45-4H15V6h4V3h-7z"/></g> +<g id="blur-circular"><path d="M10 9c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zM7 9.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm3 7c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm-3-3c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm3-6c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM14 9c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-1.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm3 6c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm0-4c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm2-3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm0-3.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1z"/></g> +<g id="blur-linear"><path d="M5 17.5c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5.67 1.5 1.5 1.5zM9 13c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zM3 21h18v-2H3v2zM5 9.5c.83 0 1.5-.67 1.5-1.5S5.83 6.5 5 6.5 3.5 7.17 3.5 8 4.17 9.5 5 9.5zm0 4c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5.67 1.5 1.5 1.5zM9 17c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm8-.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM3 3v2h18V3H3zm14 5.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm0 4c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM13 9c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0 4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0 4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1z"/></g> +<g id="blur-off"><path d="M14 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm-.2 4.48l.2.02c.83 0 1.5-.67 1.5-1.5s-.67-1.5-1.5-1.5-1.5.67-1.5 1.5l.02.2c.09.67.61 1.19 1.28 1.28zM14 3.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm-4 0c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm11 7c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM10 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm8 8c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-4c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm-4 13.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM2.5 5.27l3.78 3.78L6 9c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1c0-.1-.03-.19-.06-.28l2.81 2.81c-.71.11-1.25.73-1.25 1.47 0 .83.67 1.5 1.5 1.5.74 0 1.36-.54 1.47-1.25l2.81 2.81c-.09-.03-.18-.06-.28-.06-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1c0-.1-.03-.19-.06-.28l3.78 3.78L20 20.23 3.77 4 2.5 5.27zM10 17c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm11-3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM6 13c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zM3 9.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm7 11c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM6 17c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm-3-3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5z"/></g> +<g id="blur-on"><path d="M6 13c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-8c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm-3 .5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM6 5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm15 5.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM14 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0-3.5c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zm-11 10c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm7 7c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm0-17c.28 0 .5-.22.5-.5s-.22-.5-.5-.5-.5.22-.5.5.22.5.5.5zM10 7c.55 0 1-.45 1-1s-.45-1-1-1-1 .45-1 1 .45 1 1 1zm0 5.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm8 .5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-8c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0-4c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm3 8.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zM14 17c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm0 3.5c-.28 0-.5.22-.5.5s.22.5.5.5.5-.22.5-.5-.22-.5-.5-.5zm-4-12c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0 8.5c-.55 0-1 .45-1 1s.45 1 1 1 1-.45 1-1-.45-1-1-1zm4-4.5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm0-4c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"/></g> +<g id="brightness-1"><circle cx="12" cy="12" r="10"/></g> +<g id="brightness-2"><path d="M10 2c-1.82 0-3.53.5-5 1.35C7.99 5.08 10 8.3 10 12s-2.01 6.92-5 8.65C6.47 21.5 8.18 22 10 22c5.52 0 10-4.48 10-10S15.52 2 10 2z"/></g> +<g id="brightness-3"><path d="M9 2c-1.05 0-2.05.16-3 .46 4.06 1.27 7 5.06 7 9.54 0 4.48-2.94 8.27-7 9.54.95.3 1.95.46 3 .46 5.52 0 10-4.48 10-10S14.52 2 9 2z"/></g> +<g id="brightness-4"><path d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6c3.31 0 6 2.69 6 6s-2.69 6-6 6z"/></g> +<g id="brightness-5"><path d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6z"/></g> +<g id="brightness-6"><path d="M20 15.31L23.31 12 20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69zM12 18V6c3.31 0 6 2.69 6 6s-2.69 6-6 6z"/></g> +<g id="brightness-7"><path d="M20 8.69V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12 20 8.69zM12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zm0-10c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"/></g> +<g id="brush"><path d="M7 14c-1.66 0-3 1.34-3 3 0 1.31-1.16 2-2 2 .92 1.22 2.49 2 4 2 2.21 0 4-1.79 4-4 0-1.66-1.34-3-3-3zm13.71-9.37l-1.34-1.34c-.39-.39-1.02-.39-1.41 0L9 12.25 11.75 15l8.96-8.96c.39-.39.39-1.02 0-1.41z"/></g> +<g id="camera"><path d="M9.4 10.5l4.77-8.26C13.47 2.09 12.75 2 12 2c-2.4 0-4.6.85-6.32 2.25l3.66 6.35.06-.1zM21.54 9c-.92-2.92-3.15-5.26-6-6.34L11.88 9h9.66zm.26 1h-7.49l.29.5 4.76 8.25C21 16.97 22 14.61 22 12c0-.69-.07-1.35-.2-2zM8.54 12l-3.9-6.75C3.01 7.03 2 9.39 2 12c0 .69.07 1.35.2 2h7.49l-1.15-2zm-6.08 3c.92 2.92 3.15 5.26 6 6.34L12.12 15H2.46zm11.27 0l-3.9 6.76c.7.15 1.42.24 2.17.24 2.4 0 4.6-.85 6.32-2.25l-3.66-6.35-.93 1.6z"/></g> +<g id="camera-alt"><circle cx="12" cy="12" r="3.2"/><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></g> +<g id="camera-front"><path d="M10 20H5v2h5v2l3-3-3-3v2zm4 0v2h5v-2h-5zM12 8c1.1 0 2-.9 2-2s-.9-2-2-2-1.99.9-1.99 2S10.9 8 12 8zm5-8H7C5.9 0 5 .9 5 2v14c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V2c0-1.1-.9-2-2-2zM7 2h10v10.5c0-1.67-3.33-2.5-5-2.5s-5 .83-5 2.5V2z"/></g> +<g id="camera-rear"><path d="M10 20H5v2h5v2l3-3-3-3v2zm4 0v2h5v-2h-5zm3-20H7C5.9 0 5 .9 5 2v14c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V2c0-1.1-.9-2-2-2zm-5 6c-1.11 0-2-.9-2-2s.89-2 1.99-2 2 .9 2 2C14 5.1 13.1 6 12 6z"/></g> +<g id="camera-roll"><path d="M14 5c0-1.1-.9-2-2-2h-1V2c0-.55-.45-1-1-1H6c-.55 0-1 .45-1 1v1H4c-1.1 0-2 .9-2 2v15c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2h8V5h-8zm-2 13h-2v-2h2v2zm0-9h-2V7h2v2zm4 9h-2v-2h2v2zm0-9h-2V7h2v2zm4 9h-2v-2h2v2zm0-9h-2V7h2v2z"/></g> +<g id="center-focus-strong"><path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm-7 7H3v4c0 1.1.9 2 2 2h4v-2H5v-4zM5 5h4V3H5c-1.1 0-2 .9-2 2v4h2V5zm14-2h-4v2h4v4h2V5c0-1.1-.9-2-2-2zm0 16h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4z"/></g> +<g id="center-focus-weak"><path d="M5 15H3v4c0 1.1.9 2 2 2h4v-2H5v-4zM5 5h4V3H5c-1.1 0-2 .9-2 2v4h2V5zm14-2h-4v2h4v4h2V5c0-1.1-.9-2-2-2zm0 16h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zM12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="collections"><path d="M22 16V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2zm-11-4l2.03 2.71L16 11l4 5H8l3-4zM2 6v14c0 1.1.9 2 2 2h14v-2H4V6H2z"/></g> +<g id="color-lens"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="colorize"><path d="M20.71 5.63l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-3.12 3.12-1.93-1.91-1.41 1.41 1.42 1.42L3 16.25V21h4.75l8.92-8.92 1.42 1.42 1.41-1.41-1.92-1.92 3.12-3.12c.4-.4.4-1.03.01-1.42zM6.92 19L5 17.08l8.06-8.06 1.92 1.92L6.92 19z"/></g> +<g id="compare"><path d="M10 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h5v2h2V1h-2v2zm0 15H5l5-6v6zm9-15h-5v2h5v13l-5-6v9h5c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></g> +<g id="control-point"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.49 2 2 6.49 2 12s4.49 10 10 10 10-4.49 10-10S17.51 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="control-point-duplicate"><path d="M16 8h-2v3h-3v2h3v3h2v-3h3v-2h-3zM2 12c0-2.79 1.64-5.2 4.01-6.32V3.52C2.52 4.76 0 8.09 0 12s2.52 7.24 6.01 8.48v-2.16C3.64 17.2 2 14.79 2 12zm13-9c-4.96 0-9 4.04-9 9s4.04 9 9 9 9-4.04 9-9-4.04-9-9-9zm0 16c-3.86 0-7-3.14-7-7s3.14-7 7-7 7 3.14 7 7-3.14 7-7 7z"/></g> +<g id="crop"><path d="M17 15h2V7c0-1.1-.9-2-2-2H9v2h8v8zM7 17V1H5v4H1v2h4v10c0 1.1.9 2 2 2h10v4h2v-4h4v-2H7z"/></g> +<g id="crop-16-9"><path d="M19 6H5c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H5V8h14v8z"/></g> +<g id="crop-3-2"><path d="M19 4H5c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H5V6h14v12z"/></g> +<g id="crop-5-4"><path d="M19 5H5c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 12H5V7h14v10z"/></g> +<g id="crop-7-5"><path d="M19 7H5c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8H5V9h14v6z"/></g> +<g id="crop-din"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/></g> +<g id="crop-free"><path d="M3 5v4h2V5h4V3H5c-1.1 0-2 .9-2 2zm2 10H3v4c0 1.1.9 2 2 2h4v-2H5v-4zm14 4h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zm0-16h-4v2h4v4h2V5c0-1.1-.9-2-2-2z"/></g> +<g id="crop-landscape"><path d="M19 5H5c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 12H5V7h14v10z"/></g> +<g id="crop-original"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zm-5.04-6.71l-2.75 3.54-1.96-2.36L6.5 17h11l-3.54-4.71z"/></g> +<g id="crop-portrait"><path d="M17 3H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H7V5h10v14z"/></g> +<g id="crop-square"><path d="M18 4H6c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H6V6h12v12z"/></g> +<g id="dehaze"><path d="M2 15.5v2h20v-2H2zm0-5v2h20v-2H2zm0-5v2h20v-2H2z"/></g> +<g id="details"><path d="M3 4l9 16 9-16H3zm3.38 2h11.25L12 16 6.38 6z"/></g> +<g id="edit"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></g> +<g id="exposure"><path d="M15 17v2h2v-2h2v-2h-2v-2h-2v2h-2v2h2zm5-15H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM5 5h6v2H5V5zm15 15H4L20 4v16z"/></g> +<g id="exposure-minus-1"><path d="M4 11v2h8v-2H4zm15 7h-2V7.38L14 8.4V6.7L18.7 5h.3v13z"/></g> +<g id="exposure-minus-2"><path d="M15.05 16.29l2.86-3.07c.38-.39.72-.79 1.04-1.18.32-.39.59-.78.82-1.17.23-.39.41-.78.54-1.17s.19-.79.19-1.18c0-.53-.09-1.02-.27-1.46-.18-.44-.44-.81-.78-1.11-.34-.31-.77-.54-1.26-.71-.51-.16-1.08-.24-1.72-.24-.69 0-1.31.11-1.85.32-.54.21-1 .51-1.36.88-.37.37-.65.8-.84 1.3-.18.47-.27.97-.28 1.5h2.14c.01-.31.05-.6.13-.87.09-.29.23-.54.4-.75.18-.21.41-.37.68-.49.27-.12.6-.18.96-.18.31 0 .58.05.81.15.23.1.43.25.59.43.16.18.28.4.37.65.08.25.13.52.13.81 0 .22-.03.43-.08.65-.06.22-.15.45-.29.7-.14.25-.32.53-.56.83-.23.3-.52.65-.88 1.03l-4.17 4.55V18H21v-1.71h-5.95zM2 11v2h8v-2H2z"/></g> +<g id="exposure-plus-1"><path d="M10 7H8v4H4v2h4v4h2v-4h4v-2h-4V7zm10 11h-2V7.38L15 8.4V6.7L19.7 5h.3v13z"/></g> +<g id="exposure-plus-2"><path d="M16.05 16.29l2.86-3.07c.38-.39.72-.79 1.04-1.18.32-.39.59-.78.82-1.17.23-.39.41-.78.54-1.17.13-.39.19-.79.19-1.18 0-.53-.09-1.02-.27-1.46-.18-.44-.44-.81-.78-1.11-.34-.31-.77-.54-1.26-.71-.51-.16-1.08-.24-1.72-.24-.69 0-1.31.11-1.85.32-.54.21-1 .51-1.36.88-.37.37-.65.8-.84 1.3-.18.47-.27.97-.28 1.5h2.14c.01-.31.05-.6.13-.87.09-.29.23-.54.4-.75.18-.21.41-.37.68-.49.27-.12.6-.18.96-.18.31 0 .58.05.81.15.23.1.43.25.59.43.16.18.28.4.37.65.08.25.13.52.13.81 0 .22-.03.43-.08.65-.06.22-.15.45-.29.7-.14.25-.32.53-.56.83-.23.3-.52.65-.88 1.03l-4.17 4.55V18H22v-1.71h-5.95zM8 7H6v4H2v2h4v4h2v-4h4v-2H8V7z"/></g> +<g id="exposure-zero"><path d="M16.14 12.5c0 1-.1 1.85-.3 2.55-.2.7-.48 1.27-.83 1.7-.36.44-.79.75-1.3.95-.51.2-1.07.3-1.7.3-.62 0-1.18-.1-1.69-.3-.51-.2-.95-.51-1.31-.95-.36-.44-.65-1.01-.85-1.7-.2-.7-.3-1.55-.3-2.55v-2.04c0-1 .1-1.85.3-2.55.2-.7.48-1.26.84-1.69.36-.43.8-.74 1.31-.93C10.81 5.1 11.38 5 12 5c.63 0 1.19.1 1.7.29.51.19.95.5 1.31.93.36.43.64.99.84 1.69.2.7.3 1.54.3 2.55v2.04zm-2.11-2.36c0-.64-.05-1.18-.13-1.62-.09-.44-.22-.79-.4-1.06-.17-.27-.39-.46-.64-.58-.25-.13-.54-.19-.86-.19-.32 0-.61.06-.86.18s-.47.31-.64.58c-.17.27-.31.62-.4 1.06s-.13.98-.13 1.62v2.67c0 .64.05 1.18.14 1.62.09.45.23.81.4 1.09s.39.48.64.61.54.19.87.19c.33 0 .62-.06.87-.19s.46-.33.63-.61c.17-.28.3-.64.39-1.09.09-.45.13-.99.13-1.62v-2.66z"/></g> +<g id="filter"><path d="M15.96 10.29l-2.75 3.54-1.96-2.36L8.5 15h11l-3.54-4.71zM3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14z"/></g> +<g id="filter-1"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm11 10h2V5h-4v2h2v8zm7-14H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14z"/></g> +<g id="filter-2"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zm-4-4h-4v-2h2c1.1 0 2-.89 2-2V7c0-1.11-.9-2-2-2h-4v2h4v2h-2c-1.1 0-2 .89-2 2v4h6v-2z"/></g> +<g id="filter-3"><path d="M21 1H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zM3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm14 8v-1.5c0-.83-.67-1.5-1.5-1.5.83 0 1.5-.67 1.5-1.5V7c0-1.11-.9-2-2-2h-4v2h4v2h-2v2h2v2h-4v2h4c1.1 0 2-.89 2-2z"/></g> +<g id="filter-4"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm12 10h2V5h-2v4h-2V5h-2v6h4v4zm6-14H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14z"/></g> +<g id="filter-5"><path d="M21 1H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zM3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm14 8v-2c0-1.11-.9-2-2-2h-2V7h4V5h-6v6h4v2h-4v2h4c1.1 0 2-.89 2-2z"/></g> +<g id="filter-6"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zm-8-2h2c1.1 0 2-.89 2-2v-2c0-1.11-.9-2-2-2h-2V7h4V5h-4c-1.1 0-2 .89-2 2v6c0 1.11.9 2 2 2zm0-4h2v2h-2v-2z"/></g> +<g id="filter-7"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zm-8-2l4-8V5h-6v2h4l-4 8h2z"/></g> +<g id="filter-8"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zm-8-2h2c1.1 0 2-.89 2-2v-1.5c0-.83-.67-1.5-1.5-1.5.83 0 1.5-.67 1.5-1.5V7c0-1.11-.9-2-2-2h-2c-1.1 0-2 .89-2 2v1.5c0 .83.67 1.5 1.5 1.5-.83 0-1.5.67-1.5 1.5V13c0 1.11.9 2 2 2zm0-8h2v2h-2V7zm0 4h2v2h-2v-2z"/></g> +<g id="filter-9"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14zM15 5h-2c-1.1 0-2 .89-2 2v2c0 1.11.9 2 2 2h2v2h-4v2h4c1.1 0 2-.89 2-2V7c0-1.11-.9-2-2-2zm0 4h-2V7h2v2z"/></g> +<g id="filter-9-plus"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm11 7V8c0-1.11-.9-2-2-2h-1c-1.1 0-2 .89-2 2v1c0 1.11.9 2 2 2h1v1H9v2h3c1.1 0 2-.89 2-2zm-3-3V8h1v1h-1zm10-8H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 8h-2V7h-2v2h-2v2h2v2h2v-2h2v6H7V3h14v6z"/></g> +<g id="filter-b-and-w"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16l-7-8v8H5l7-8V5h7v14z"/></g> +<g id="filter-center-focus"><path d="M5 15H3v4c0 1.1.9 2 2 2h4v-2H5v-4zM5 5h4V3H5c-1.1 0-2 .9-2 2v4h2V5zm14-2h-4v2h4v4h2V5c0-1.1-.9-2-2-2zm0 16h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zM12 9c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g> +<g id="filter-drama"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.61 5.64 5.36 8.04 2.35 8.36 0 10.9 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4h2c0-2.76-1.86-5.08-4.4-5.78C8.61 6.88 10.2 6 12 6c3.03 0 5.5 2.47 5.5 5.5v.5H19c1.65 0 3 1.35 3 3s-1.35 3-3 3z"/></g> +<g id="filter-frames"><path d="M20 4h-4l-4-4-4 4H4c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 16H4V6h4.52l3.52-3.5L15.52 6H20v14zM18 8H6v10h12"/></g> +<g id="filter-hdr"><path d="M14 6l-3.75 5 2.85 3.8-1.6 1.2C9.81 13.75 7 10 7 10l-6 8h22L14 6z"/></g> +<g id="filter-none"><path d="M3 5H1v16c0 1.1.9 2 2 2h16v-2H3V5zm18-4H7c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V3c0-1.1-.9-2-2-2zm0 16H7V3h14v14z"/></g> +<g id="filter-tilt-shift"><path d="M11 4.07V2.05c-2.01.2-3.84 1-5.32 2.21L7.1 5.69c1.11-.86 2.44-1.44 3.9-1.62zm7.32.19C16.84 3.05 15.01 2.25 13 2.05v2.02c1.46.18 2.79.76 3.9 1.62l1.42-1.43zM19.93 11h2.02c-.2-2.01-1-3.84-2.21-5.32L18.31 7.1c.86 1.11 1.44 2.44 1.62 3.9zM5.69 7.1L4.26 5.68C3.05 7.16 2.25 8.99 2.05 11h2.02c.18-1.46.76-2.79 1.62-3.9zM4.07 13H2.05c.2 2.01 1 3.84 2.21 5.32l1.43-1.43c-.86-1.1-1.44-2.43-1.62-3.89zM15 12c0-1.66-1.34-3-3-3s-3 1.34-3 3 1.34 3 3 3 3-1.34 3-3zm3.31 4.9l1.43 1.43c1.21-1.48 2.01-3.32 2.21-5.32h-2.02c-.18 1.45-.76 2.78-1.62 3.89zM13 19.93v2.02c2.01-.2 3.84-1 5.32-2.21l-1.43-1.43c-1.1.86-2.43 1.44-3.89 1.62zm-7.32-.19C7.16 20.95 9 21.75 11 21.95v-2.02c-1.46-.18-2.79-.76-3.9-1.62l-1.42 1.43z"/></g> +<g id="filter-vintage"><path d="M18.7 12.4c-.28-.16-.57-.29-.86-.4.29-.11.58-.24.86-.4 1.92-1.11 2.99-3.12 3-5.19-1.79-1.03-4.07-1.11-6 0-.28.16-.54.35-.78.54.05-.31.08-.63.08-.95 0-2.22-1.21-4.15-3-5.19C10.21 1.85 9 3.78 9 6c0 .32.03.64.08.95-.24-.2-.5-.39-.78-.55-1.92-1.11-4.2-1.03-6 0 0 2.07 1.07 4.08 3 5.19.28.16.57.29.86.4-.29.11-.58.24-.86.4-1.92 1.11-2.99 3.12-3 5.19 1.79 1.03 4.07 1.11 6 0 .28-.16.54-.35.78-.54-.05.32-.08.64-.08.96 0 2.22 1.21 4.15 3 5.19 1.79-1.04 3-2.97 3-5.19 0-.32-.03-.64-.08-.95.24.2.5.38.78.54 1.92 1.11 4.2 1.03 6 0-.01-2.07-1.08-4.08-3-5.19zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"/></g> +<g id="flare"><path d="M7 11H1v2h6v-2zm2.17-3.24L7.05 5.64 5.64 7.05l2.12 2.12 1.41-1.41zM13 1h-2v6h2V1zm5.36 6.05l-1.41-1.41-2.12 2.12 1.41 1.41 2.12-2.12zM17 11v2h6v-2h-6zm-5-2c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm2.83 7.24l2.12 2.12 1.41-1.41-2.12-2.12-1.41 1.41zm-9.19.71l1.41 1.41 2.12-2.12-1.41-1.41-2.12 2.12zM11 23h2v-6h-2v6z"/></g> +<g id="flash-auto"><path d="M3 2v12h3v9l7-12H9l4-9H3zm16 0h-2l-3.2 9h1.9l.7-2h3.2l.7 2h1.9L19 2zm-2.15 5.65L18 4l1.15 3.65h-2.3z"/></g> +<g id="flash-off"><path d="M3.27 3L2 4.27l5 5V13h3v9l3.58-6.14L17.73 20 19 18.73 3.27 3zM17 10h-4l4-8H7v2.18l8.46 8.46L17 10z"/></g> +<g id="flash-on"><path d="M7 2v11h3v9l7-12h-4l4-8z"/></g> +<g id="flip"><path d="M15 21h2v-2h-2v2zm4-12h2V7h-2v2zM3 5v14c0 1.1.9 2 2 2h4v-2H5V5h4V3H5c-1.1 0-2 .9-2 2zm16-2v2h2c0-1.1-.9-2-2-2zm-8 20h2V1h-2v22zm8-6h2v-2h-2v2zM15 5h2V3h-2v2zm4 8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2z"/></g> +<g id="gradient"><path d="M11 9h2v2h-2zm-2 2h2v2H9zm4 0h2v2h-2zm2-2h2v2h-2zM7 9h2v2H7zm12-6H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 18H7v-2h2v2zm4 0h-2v-2h2v2zm4 0h-2v-2h2v2zm2-7h-2v2h2v2h-2v-2h-2v2h-2v-2h-2v2H9v-2H7v2H5v-2h2v-2H5V5h14v6z"/></g> +<g id="grain"><path d="M10 12c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zM6 8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12-8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-4 8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm4-4c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-4-4c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-4-4c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="grid-off"><path d="M8 4v1.45l2 2V4h4v4h-3.45l2 2H14v1.45l2 2V10h4v4h-3.45l2 2H20v1.45l2 2V4c0-1.1-.9-2-2-2H4.55l2 2H8zm8 0h4v4h-4V4zM1.27 1.27L0 2.55l2 2V20c0 1.1.9 2 2 2h15.46l2 2 1.27-1.27L1.27 1.27zM10 12.55L11.45 14H10v-1.45zm-6-6L5.45 8H4V6.55zM8 20H4v-4h4v4zm0-6H4v-4h3.45l.55.55V14zm6 6h-4v-4h3.45l.55.54V20zm2 0v-1.46L17.46 20H16z"/></g> +<g id="grid-on"><path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM8 20H4v-4h4v4zm0-6H4v-4h4v4zm0-6H4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4zm6 12h-4v-4h4v4zm0-6h-4v-4h4v4zm0-6h-4V4h4v4z"/></g> +<g id="hdr-off"><path d="M18 17L3.27 2.27 2 3.55l4 4V11H4V7H2v10h2v-4h2v4h2V9.55l1 1V17h4c.67 0 1.26-.33 1.62-.84l6.34 6.34 1.27-1.27L18 17zm-5-2h-2v-2.45l2 2V15zm5-2h1l.82 3.27.73.73H22l-1.19-4.17c.7-.31 1.19-1.01 1.19-1.83V9c0-1.1-.9-2-2-2h-4v5.45l2 2V13zm0-4h2v2h-2V9zm-3 2.45V9c0-1.1-.9-2-2-2h-2.45L15 11.45z"/></g> +<g id="hdr-on"><path d="M6 11H4V7H2v10h2v-4h2v4h2V7H6v4zm7-4H9v10h4c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm0 8h-2V9h2v6zm9-4V9c0-1.1-.9-2-2-2h-4v10h2v-4h1l1 4h2l-1.19-4.17c.7-.31 1.19-1.01 1.19-1.83zm-2 0h-2V9h2v2z"/></g> +<g id="hdr-strong"><path d="M17 6c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zM5 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="hdr-weak"><path d="M5 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm12-2c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm0 10c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"/></g> +<g id="healing"><path d="M17.73 12.02l3.98-3.98c.39-.39.39-1.02 0-1.41l-4.34-4.34c-.39-.39-1.02-.39-1.41 0l-3.98 3.98L8 2.29C7.8 2.1 7.55 2 7.29 2c-.25 0-.51.1-.7.29L2.25 6.63c-.39.39-.39 1.02 0 1.41l3.98 3.98L2.25 16c-.39.39-.39 1.02 0 1.41l4.34 4.34c.39.39 1.02.39 1.41 0l3.98-3.98 3.98 3.98c.2.2.45.29.71.29.26 0 .51-.1.71-.29l4.34-4.34c.39-.39.39-1.02 0-1.41l-3.99-3.98zM12 9c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-4.71 1.96L3.66 7.34l3.63-3.63 3.62 3.62-3.62 3.63zM10 13c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2 2c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm2-4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2.66 9.34l-3.63-3.62 3.63-3.63 3.62 3.62-3.62 3.63z"/></g> +<g id="image"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></g> +<g id="image-aspect-ratio"><path d="M16 10h-2v2h2v-2zm0 4h-2v2h2v-2zm-8-4H6v2h2v-2zm4 0h-2v2h2v-2zm8-6H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 14H4V6h16v12z"/></g> +<g id="iso"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5.5 7.5h2v-2H9v2h2V9H9v2H7.5V9h-2V7.5zM19 19H5L19 5v14zm-2-2v-1.5h-5V17h5z"/></g> +<g id="landscape"><path d="M14 6l-3.75 5 2.85 3.8-1.6 1.2C9.81 13.75 7 10 7 10l-6 8h22L14 6z"/></g> +<g id="leak-add"><path d="M6 3H3v3c1.66 0 3-1.34 3-3zm8 0h-2c0 4.97-4.03 9-9 9v2c6.08 0 11-4.93 11-11zm-4 0H8c0 2.76-2.24 5-5 5v2c3.87 0 7-3.13 7-7zm0 18h2c0-4.97 4.03-9 9-9v-2c-6.07 0-11 4.93-11 11zm8 0h3v-3c-1.66 0-3 1.34-3 3zm-4 0h2c0-2.76 2.24-5 5-5v-2c-3.87 0-7 3.13-7 7z"/></g> +<g id="leak-remove"><path d="M10 3H8c0 .37-.04.72-.12 1.06l1.59 1.59C9.81 4.84 10 3.94 10 3zM3 4.27l2.84 2.84C5.03 7.67 4.06 8 3 8v2c1.61 0 3.09-.55 4.27-1.46L8.7 9.97C7.14 11.24 5.16 12 3 12v2c2.71 0 5.19-.99 7.11-2.62l2.5 2.5C10.99 15.81 10 18.29 10 21h2c0-2.16.76-4.14 2.03-5.69l1.43 1.43C14.55 17.91 14 19.39 14 21h2c0-1.06.33-2.03.89-2.84L19.73 21 21 19.73 4.27 3 3 4.27zM14 3h-2c0 1.5-.37 2.91-1.02 4.16l1.46 1.46C13.42 6.98 14 5.06 14 3zm5.94 13.12c.34-.08.69-.12 1.06-.12v-2c-.94 0-1.84.19-2.66.52l1.6 1.6zm-4.56-4.56l1.46 1.46C18.09 12.37 19.5 12 21 12v-2c-2.06 0-3.98.58-5.62 1.56z"/></g> +<g id="lens"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z"/></g> +<g id="looks"><path d="M12 10c-3.86 0-7 3.14-7 7h2c0-2.76 2.24-5 5-5s5 2.24 5 5h2c0-3.86-3.14-7-7-7zm0-4C5.93 6 1 10.93 1 17h2c0-4.96 4.04-9 9-9s9 4.04 9 9h2c0-6.07-4.93-11-11-11z"/></g> +<g id="looks-3"><path d="M19.01 3h-14c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 7.5c0 .83-.67 1.5-1.5 1.5.83 0 1.5.67 1.5 1.5V15c0 1.11-.9 2-2 2h-4v-2h4v-2h-2v-2h2V9h-4V7h4c1.1 0 2 .89 2 2v1.5z"/></g> +<g id="looks-4"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 14h-2v-4H9V7h2v4h2V7h2v10z"/></g> +<g id="looks-5"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 6h-4v2h2c1.1 0 2 .89 2 2v2c0 1.11-.9 2-2 2H9v-2h4v-2H9V7h6v2z"/></g> +<g id="looks-6"><path d="M11 15h2v-2h-2v2zm8-12H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 6h-4v2h2c1.1 0 2 .89 2 2v2c0 1.11-.9 2-2 2h-2c-1.1 0-2-.89-2-2V9c0-1.11.9-2 2-2h4v2z"/></g> +<g id="looks-one"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14h-2V9h-2V7h4v10z"/></g> +<g id="looks-two"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4 8c0 1.11-.9 2-2 2h-2v2h4v2H9v-4c0-1.11.9-2 2-2h2V9H9V7h4c1.1 0 2 .89 2 2v2z"/></g> +<g id="loupe"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.49 2 2 6.49 2 12s4.49 10 10 10h8c1.1 0 2-.9 2-2v-8c0-5.51-4.49-10-10-10zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="movie-creation"><path d="M18 4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4h-4z"/></g> +<g id="nature"><path d="M13 16.12c3.47-.41 6.17-3.36 6.17-6.95 0-3.87-3.13-7-7-7s-7 3.13-7 7c0 3.47 2.52 6.34 5.83 6.89V20H5v2h14v-2h-6v-3.88z"/></g> +<g id="nature-people"><path d="M22.17 9.17c0-3.87-3.13-7-7-7s-7 3.13-7 7c0 3.47 2.52 6.34 5.83 6.89V20H6v-3h1v-4c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v4h1v5h16v-2h-3v-3.88c3.47-.41 6.17-3.36 6.17-6.95zM4.5 11c.83 0 1.5-.67 1.5-1.5S5.33 8 4.5 8 3 8.67 3 9.5 3.67 11 4.5 11z"/></g> +<g id="navigate-before"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></g> +<g id="navigate-next"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></g> +<g id="palette"><path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="panorama"><path d="M23 18V6c0-1.1-.9-2-2-2H3c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2zM8.5 12.5l2.5 3.01L14.5 11l4.5 6H5l3.5-4.5z"/></g> +<g id="panorama-fisheye"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="panorama-horizontal"><path d="M20 6.54v10.91c-2.6-.77-5.28-1.16-8-1.16-2.72 0-5.4.39-8 1.16V6.54c2.6.77 5.28 1.16 8 1.16 2.72.01 5.4-.38 8-1.16M21.43 4c-.1 0-.2.02-.31.06C18.18 5.16 15.09 5.7 12 5.7c-3.09 0-6.18-.55-9.12-1.64-.11-.04-.22-.06-.31-.06-.34 0-.57.23-.57.63v14.75c0 .39.23.62.57.62.1 0 .2-.02.31-.06 2.94-1.1 6.03-1.64 9.12-1.64 3.09 0 6.18.55 9.12 1.64.11.04.21.06.31.06.33 0 .57-.23.57-.63V4.63c0-.4-.24-.63-.57-.63z"/></g> +<g id="panorama-vertical"><path d="M19.94 21.12c-1.1-2.94-1.64-6.03-1.64-9.12 0-3.09.55-6.18 1.64-9.12.04-.11.06-.22.06-.31 0-.34-.23-.57-.63-.57H4.63c-.4 0-.63.23-.63.57 0 .1.02.2.06.31C5.16 5.82 5.71 8.91 5.71 12c0 3.09-.55 6.18-1.64 9.12-.05.11-.07.22-.07.31 0 .33.23.57.63.57h14.75c.39 0 .63-.24.63-.57-.01-.1-.03-.2-.07-.31zM6.54 20c.77-2.6 1.16-5.28 1.16-8 0-2.72-.39-5.4-1.16-8h10.91c-.77 2.6-1.16 5.28-1.16 8 0 2.72.39 5.4 1.16 8H6.54z"/></g> +<g id="panorama-wide-angle"><path d="M12 6c2.45 0 4.71.2 7.29.64.47 1.78.71 3.58.71 5.36 0 1.78-.24 3.58-.71 5.36-2.58.44-4.84.64-7.29.64s-4.71-.2-7.29-.64C4.24 15.58 4 13.78 4 12c0-1.78.24-3.58.71-5.36C7.29 6.2 9.55 6 12 6m0-2c-2.73 0-5.22.24-7.95.72l-.93.16-.25.9C2.29 7.85 2 9.93 2 12s.29 4.15.87 6.22l.25.89.93.16c2.73.49 5.22.73 7.95.73s5.22-.24 7.95-.72l.93-.16.25-.89c.58-2.08.87-4.16.87-6.23s-.29-4.15-.87-6.22l-.25-.89-.93-.16C17.22 4.24 14.73 4 12 4z"/></g> +<g id="photo"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></g> +<g id="photo-album"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4zm0 15l3-3.86 2.14 2.58 3-3.86L18 19H6z"/></g> +<g id="photo-camera"><circle cx="12" cy="12" r="3.2"/><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></g> +<g id="photo-library"><path d="M22 16V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2zm-11-4l2.03 2.71L16 11l4 5H8l3-4zM2 6v14c0 1.1.9 2 2 2h14v-2H4V6H2z"/></g> +<g id="portrait"><path d="M12 12.25c1.24 0 2.25-1.01 2.25-2.25S13.24 7.75 12 7.75 9.75 8.76 9.75 10s1.01 2.25 2.25 2.25zm4.5 4c0-1.5-3-2.25-4.5-2.25s-4.5.75-4.5 2.25V17h9v-.75zM19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/></g> +<g id="remove-red-eye"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g> +<g id="rotate-left"><path d="M7.11 8.53L5.7 7.11C4.8 8.27 4.24 9.61 4.07 11h2.02c.14-.87.49-1.72 1.02-2.47zM6.09 13H4.07c.17 1.39.72 2.73 1.62 3.89l1.41-1.42c-.52-.75-.87-1.59-1.01-2.47zm1.01 5.32c1.16.9 2.51 1.44 3.9 1.61V17.9c-.87-.15-1.71-.49-2.46-1.03L7.1 18.32zM13 4.07V1L8.45 5.55 13 10V6.09c2.84.48 5 2.94 5 5.91s-2.16 5.43-5 5.91v2.02c3.95-.49 7-3.85 7-7.93s-3.05-7.44-7-7.93z"/></g> +<g id="rotate-right"><path d="M15.55 5.55L11 1v3.07C7.06 4.56 4 7.92 4 12s3.05 7.44 7 7.93v-2.02c-2.84-.48-5-2.94-5-5.91s2.16-5.43 5-5.91V10l4.55-4.45zM19.93 11c-.17-1.39-.72-2.73-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02c1.39-.17 2.74-.71 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41c.9-1.16 1.45-2.5 1.62-3.89h-2.02c-.14.87-.48 1.72-1.02 2.48z"/></g> +<g id="slideshow"><path d="M10 8v8l5-4-5-4zm9-5H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14z"/></g> +<g id="straighten"><path d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"/></g> +<g id="style"><path d="M2.53 19.65l1.34.56v-9.03l-2.43 5.86c-.41 1.02.08 2.19 1.09 2.61zm19.5-3.7L17.07 3.98c-.31-.75-1.04-1.21-1.81-1.23-.26 0-.53.04-.79.15L7.1 5.95c-.75.31-1.21 1.03-1.23 1.8-.01.27.04.54.15.8l4.96 11.97c.31.76 1.05 1.22 1.83 1.23.26 0 .52-.05.77-.15l7.36-3.05c1.02-.42 1.51-1.59 1.09-2.6zM7.88 8.75c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-2 11c0 1.1.9 2 2 2h1.45l-3.45-8.34v6.34z"/></g> +<g id="switch-camera"><path d="M20 4h-3.17L15 2H9L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-5 11.5V13H9v2.5L5.5 12 9 8.5V11h6V8.5l3.5 3.5-3.5 3.5z"/></g> +<g id="switch-video"><path d="M18 9.5V6c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h14c.55 0 1-.45 1-1v-3.5l4 4v-13l-4 4zm-5 6V13H7v2.5L3.5 12 7 8.5V11h6V8.5l3.5 3.5-3.5 3.5z"/></g> +<g id="tag-faces"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></g> +<g id="texture"><path d="M19.51 3.08L3.08 19.51c.09.34.27.65.51.9.25.24.56.42.9.51L20.93 4.49c-.19-.69-.73-1.23-1.42-1.41zM11.88 3L3 11.88v2.83L14.71 3h-2.83zM5 3c-1.1 0-2 .9-2 2v2l4-4H5zm14 18c.55 0 1.05-.22 1.41-.59.37-.36.59-.86.59-1.41v-2l-4 4h2zm-9.71 0h2.83L21 12.12V9.29L9.29 21z"/></g> +<g id="timelapse"><path d="M16.24 7.76C15.07 6.59 13.54 6 12 6v6l-4.24 4.24c2.34 2.34 6.14 2.34 8.49 0 2.34-2.34 2.34-6.14-.01-8.48zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></g> +<g id="timer"><path d="M15 1H9v2h6V1zm-4 13h2V8h-2v6zm8.03-6.61l1.42-1.42c-.43-.51-.9-.99-1.41-1.41l-1.42 1.42C16.07 4.74 14.12 4 12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9 9-4.03 9-9c0-2.12-.74-4.07-1.97-5.61zM12 20c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="timer-10"><path d="M0 7.72V9.4l3-1V18h2V6h-.25L0 7.72zm23.78 6.65c-.14-.28-.35-.53-.63-.74-.28-.21-.61-.39-1.01-.53s-.85-.27-1.35-.38c-.35-.07-.64-.15-.87-.23-.23-.08-.41-.16-.55-.25-.14-.09-.23-.19-.28-.3-.05-.11-.08-.24-.08-.39 0-.14.03-.28.09-.41.06-.13.15-.25.27-.34.12-.1.27-.18.45-.24s.4-.09.64-.09c.25 0 .47.04.66.11.19.07.35.17.48.29.13.12.22.26.29.42.06.16.1.32.1.49h1.95c0-.39-.08-.75-.24-1.09-.16-.34-.39-.63-.69-.88-.3-.25-.66-.44-1.09-.59C21.49 9.07 21 9 20.46 9c-.51 0-.98.07-1.39.21-.41.14-.77.33-1.06.57-.29.24-.51.52-.67.84-.16.32-.23.65-.23 1.01s.08.69.23.96c.15.28.36.52.64.73.27.21.6.38.98.53.38.14.81.26 1.27.36.39.08.71.17.95.26s.43.19.57.29c.13.1.22.22.27.34.05.12.07.25.07.39 0 .32-.13.57-.4.77-.27.2-.66.29-1.17.29-.22 0-.43-.02-.64-.08-.21-.05-.4-.13-.56-.24-.17-.11-.3-.26-.41-.44-.11-.18-.17-.41-.18-.67h-1.89c0 .36.08.71.24 1.05.16.34.39.65.7.93.31.27.69.49 1.15.66.46.17.98.25 1.58.25.53 0 1.01-.06 1.44-.19.43-.13.8-.31 1.11-.54.31-.23.54-.51.71-.83.17-.32.25-.67.25-1.06-.02-.4-.09-.74-.24-1.02zm-9.96-7.32c-.34-.4-.75-.7-1.23-.88-.47-.18-1.01-.27-1.59-.27-.58 0-1.11.09-1.59.27-.48.18-.89.47-1.23.88-.34.41-.6.93-.79 1.59-.18.65-.28 1.45-.28 2.39v1.92c0 .94.09 1.74.28 2.39.19.66.45 1.19.8 1.6.34.41.75.71 1.23.89.48.18 1.01.28 1.59.28.59 0 1.12-.09 1.59-.28.48-.18.88-.48 1.22-.89.34-.41.6-.94.78-1.6.18-.65.28-1.45.28-2.39v-1.92c0-.94-.09-1.74-.28-2.39-.18-.66-.44-1.19-.78-1.59zm-.92 6.17c0 .6-.04 1.11-.12 1.53-.08.42-.2.76-.36 1.02-.16.26-.36.45-.59.57-.23.12-.51.18-.82.18-.3 0-.58-.06-.82-.18s-.44-.31-.6-.57c-.16-.26-.29-.6-.38-1.02-.09-.42-.13-.93-.13-1.53v-2.5c0-.6.04-1.11.13-1.52.09-.41.21-.74.38-1 .16-.25.36-.43.6-.55.24-.11.51-.17.81-.17.31 0 .58.06.81.17.24.11.44.29.6.55.16.25.29.58.37.99.08.41.13.92.13 1.52v2.51z"/></g> +<g id="timer-3"><path d="M11.61 12.97c-.16-.24-.36-.46-.62-.65-.25-.19-.56-.35-.93-.48.3-.14.57-.3.8-.5.23-.2.42-.41.57-.64.15-.23.27-.46.34-.71.08-.24.11-.49.11-.73 0-.55-.09-1.04-.28-1.46-.18-.42-.44-.77-.78-1.06-.33-.28-.73-.5-1.2-.64-.45-.13-.97-.2-1.53-.2-.55 0-1.06.08-1.52.24-.47.17-.87.4-1.2.69-.33.29-.6.63-.78 1.03-.2.39-.29.83-.29 1.29h1.98c0-.26.05-.49.14-.69.09-.2.22-.38.38-.52.17-.14.36-.25.58-.33.22-.08.46-.12.73-.12.61 0 1.06.16 1.36.47.3.31.44.75.44 1.32 0 .27-.04.52-.12.74-.08.22-.21.41-.38.57-.17.16-.38.28-.63.37-.25.09-.55.13-.89.13H6.72v1.57H7.9c.34 0 .64.04.91.11.27.08.5.19.69.35.19.16.34.36.44.61.1.24.16.54.16.87 0 .62-.18 1.09-.53 1.42-.35.33-.84.49-1.45.49-.29 0-.56-.04-.8-.13-.24-.08-.44-.2-.61-.36-.17-.16-.3-.34-.39-.56-.09-.22-.14-.46-.14-.72H4.19c0 .55.11 1.03.32 1.45.21.42.5.77.86 1.05s.77.49 1.24.63.96.21 1.48.21c.57 0 1.09-.08 1.58-.23.49-.15.91-.38 1.26-.68.36-.3.64-.66.84-1.1.2-.43.3-.93.3-1.48 0-.29-.04-.58-.11-.86-.08-.25-.19-.51-.35-.76zm9.26 1.4c-.14-.28-.35-.53-.63-.74-.28-.21-.61-.39-1.01-.53s-.85-.27-1.35-.38c-.35-.07-.64-.15-.87-.23-.23-.08-.41-.16-.55-.25-.14-.09-.23-.19-.28-.3-.05-.11-.08-.24-.08-.39s.03-.28.09-.41c.06-.13.15-.25.27-.34.12-.1.27-.18.45-.24s.4-.09.64-.09c.25 0 .47.04.66.11.19.07.35.17.48.29.13.12.22.26.29.42.06.16.1.32.1.49h1.95c0-.39-.08-.75-.24-1.09-.16-.34-.39-.63-.69-.88-.3-.25-.66-.44-1.09-.59-.43-.15-.92-.22-1.46-.22-.51 0-.98.07-1.39.21-.41.14-.77.33-1.06.57-.29.24-.51.52-.67.84-.16.32-.23.65-.23 1.01s.08.68.23.96c.15.28.37.52.64.73.27.21.6.38.98.53.38.14.81.26 1.27.36.39.08.71.17.95.26s.43.19.57.29c.13.1.22.22.27.34.05.12.07.25.07.39 0 .32-.13.57-.4.77-.27.2-.66.29-1.17.29-.22 0-.43-.02-.64-.08-.21-.05-.4-.13-.56-.24-.17-.11-.3-.26-.41-.44-.11-.18-.17-.41-.18-.67h-1.89c0 .36.08.71.24 1.05.16.34.39.65.7.93.31.27.69.49 1.15.66.46.17.98.25 1.58.25.53 0 1.01-.06 1.44-.19.43-.13.8-.31 1.11-.54.31-.23.54-.51.71-.83.17-.32.25-.67.25-1.06-.02-.4-.09-.74-.24-1.02z"/></g> +<g id="timer-auto"><path d="M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 10c-2.67 0-8 1.34-8 4v2h16v-2c0-2.67-5.33-4-8-4z"/></g> +<g id="timer-off"><path d="M19.04 4.55l-1.42 1.42C16.07 4.74 14.12 4 12 4c-1.83 0-3.53.55-4.95 1.48l1.46 1.46C9.53 6.35 10.73 6 12 6c3.87 0 7 3.13 7 7 0 1.27-.35 2.47-.94 3.49l1.45 1.45C20.45 16.53 21 14.83 21 13c0-2.12-.74-4.07-1.97-5.61l1.42-1.42-1.41-1.42zM15 1H9v2h6V1zm-4 8.44l2 2V8h-2v1.44zM3.02 4L1.75 5.27 4.5 8.03C3.55 9.45 3 11.16 3 13c0 4.97 4.02 9 9 9 1.84 0 3.55-.55 4.98-1.5l2.5 2.5 1.27-1.27-7.71-7.71L3.02 4zM12 20c-3.87 0-7-3.13-7-7 0-1.28.35-2.48.95-3.52l9.56 9.56c-1.03.61-2.23.96-3.51.96z"/></g> +<g id="tonality"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.94-.49-7-3.85-7-7.93s3.05-7.44 7-7.93v15.86zm2-15.86c1.03.13 2 .45 2.87.93H13v-.93zM13 7h5.24c.25.31.48.65.68 1H13V7zm0 3h6.74c.08.33.15.66.19 1H13v-1zm0 9.93V19h2.87c-.87.48-1.84.8-2.87.93zM18.24 17H13v-1h5.92c-.2.35-.43.69-.68 1zm1.5-3H13v-1h6.93c-.04.34-.11.67-.19 1z"/></g> +<g id="transform"><path d="M22 18v-2H8V4h2L7 1 4 4h2v2H2v2h4v8c0 1.1.9 2 2 2h8v2h-2l3 3 3-3h-2v-2h4zM10 8h6v6h2V8c0-1.1-.9-2-2-2h-6v2z"/></g> +<g id="tune"><path d="M3 17v2h6v-2H3zM3 5v2h10V5H3zm10 16v-2h8v-2h-8v-2h-2v6h2zM7 9v2H3v2h4v2h2V9H7zm14 4v-2H11v2h10zm-6-4h2V7h4V5h-4V3h-2v6z"/></g> +<g id="wb-auto"><path d="M6.85 12.65h2.3L8 9l-1.15 3.65zM22 7l-1.2 6.29L19.3 7h-1.6l-1.49 6.29L15 7h-.76C12.77 5.17 10.53 4 8 4c-4.42 0-8 3.58-8 8s3.58 8 8 8c3.13 0 5.84-1.81 7.15-4.43l.1.43H17l1.5-6.1L20 16h1.75l2.05-9H22zm-11.7 9l-.7-2H6.4l-.7 2H3.8L7 7h2l3.2 9h-1.9z"/></g> +<g id="wb-cloudy"><path d="M19.36 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.64-4.96z"/></g> +<g id="wb-incandescent"><path d="M3.55 18.54l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8zM11 22.45h2V19.5h-2v2.95zM4 10.5H1v2h3v-2zm11-4.19V1.5H9v4.81C7.21 7.35 6 9.28 6 11.5c0 3.31 2.69 6 6 6s6-2.69 6-6c0-2.22-1.21-4.15-3-5.19zm5 4.19v2h3v-2h-3zm-2.76 7.66l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4z"/></g> +<g id="wb-irradescent"><path d="M5 14.5h14v-6H5v6zM11 .55V3.5h2V.55h-2zm8.04 2.5l-1.79 1.79 1.41 1.41 1.8-1.79-1.42-1.41zM13 22.45V19.5h-2v2.95h2zm7.45-3.91l-1.8-1.79-1.41 1.41 1.79 1.8 1.42-1.42zM3.55 4.46l1.79 1.79 1.41-1.41-1.79-1.79-1.41 1.41zm1.41 15.49l1.79-1.8-1.41-1.41-1.79 1.79 1.41 1.42z"/></g> +<g id="wb-sunny"><path d="M6.76 4.84l-1.8-1.79-1.41 1.41 1.79 1.79 1.42-1.41zM4 10.5H1v2h3v-2zm9-9.95h-2V3.5h2V.55zm7.45 3.91l-1.41-1.41-1.79 1.79 1.41 1.41 1.79-1.79zm-3.21 13.7l1.79 1.8 1.41-1.41-1.8-1.79-1.4 1.4zM20 10.5v2h3v-2h-3zm-8-5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6zm-1 16.95h2V19.5h-2v2.95zm-7.45-3.91l1.41 1.41 1.79-1.8-1.41-1.41-1.79 1.8z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/index.html b/third_party/polymer/v0_8/components/iron-icons/index.html new file mode 100644 index 0000000..95d1991 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-component-page/iron-component-page.html"> + +</head> +<body> + + <iron-component-page></iron-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-icons/iron-icons.html b/third_party/polymer/v0_8/components/iron-icons/iron-icons.html new file mode 100644 index 0000000..6134d5b --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/iron-icons.html
@@ -0,0 +1,278 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- + +`iron-icons` is a utitliy import that includes the definition for the `iron-icon` element, `iron-iconset-svg` element, as well as an import for the default icon set. + +The `iron-icons` directory also includes imports for additional icon sets that can be loaded into your project. + +Example loading icon set: + + <link rel="import" href="../iron-icons/maps-icons.html"> + +To use an icon from one of these sets, first prefix your `iron-icon` with the icon set name, followed by a colon, ":", and then the icon id. + +Example using the directions-bus icon from the maps icon set: + + <iron-icon icon="maps:directions-bus"></iron-icon> + + +See [iron-icon](#iron-icon) for more information about working with icons. + +See [iron-iconset](#iron-iconset) and [iron-iconset-svg](#iron-iconset-svg) for more information about how to create a custom iconset. + +@group Polymer Core Elements +@homepage polymer.github.io +--> +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="icons" size="24"> +<svg><defs> +<g id="3d-rotation"><path d="M7.52 21.48C4.25 19.94 1.91 16.76 1.55 13H.05C.56 19.16 5.71 24 12 24l.66-.03-3.81-3.81-1.33 1.32zm.89-6.52c-.19 0-.37-.03-.52-.08-.16-.06-.29-.13-.4-.24-.11-.1-.2-.22-.26-.37-.06-.14-.09-.3-.09-.47h-1.3c0 .36.07.68.21.95.14.27.33.5.56.69.24.18.51.32.82.41.3.1.62.15.96.15.37 0 .72-.05 1.03-.15.32-.1.6-.25.83-.44s.42-.43.55-.72c.13-.29.2-.61.2-.97 0-.19-.02-.38-.07-.56-.05-.18-.12-.35-.23-.51-.1-.16-.24-.3-.4-.43-.17-.13-.37-.23-.61-.31.2-.09.37-.2.52-.33.15-.13.27-.27.37-.42.1-.15.17-.3.22-.46.05-.16.07-.32.07-.48 0-.36-.06-.68-.18-.96-.12-.28-.29-.51-.51-.69-.2-.19-.47-.33-.77-.43C9.1 8.05 8.76 8 8.39 8c-.36 0-.69.05-1 .16-.3.11-.57.26-.79.45-.21.19-.38.41-.51.67-.12.26-.18.54-.18.85h1.3c0-.17.03-.32.09-.45s.14-.25.25-.34c.11-.09.23-.17.38-.22.15-.05.3-.08.48-.08.4 0 .7.1.89.31.19.2.29.49.29.86 0 .18-.03.34-.08.49-.05.15-.14.27-.25.37-.11.1-.25.18-.41.24-.16.06-.36.09-.58.09H7.5v1.03h.77c.22 0 .42.02.6.07s.33.13.45.23c.12.11.22.24.29.4.07.16.1.35.1.57 0 .41-.12.72-.35.93-.23.23-.55.33-.95.33zm8.55-5.92c-.32-.33-.7-.59-1.14-.77-.43-.18-.92-.27-1.46-.27H12v8h2.3c.55 0 1.06-.09 1.51-.27.45-.18.84-.43 1.16-.76.32-.33.57-.73.74-1.19.17-.47.26-.99.26-1.57v-.4c0-.58-.09-1.1-.26-1.57-.18-.47-.43-.87-.75-1.2zm-.39 3.16c0 .42-.05.79-.14 1.13-.1.33-.24.62-.43.85-.19.23-.43.41-.71.53-.29.12-.62.18-.99.18h-.91V9.12h.97c.72 0 1.27.23 1.64.69.38.46.57 1.12.57 1.99v.4zM12 0l-.66.03 3.81 3.81 1.33-1.33c3.27 1.55 5.61 4.72 5.96 8.48h1.5C23.44 4.84 18.29 0 12 0z"/></g> +<g id="accessibility"><path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z"/></g> +<g id="account-balance"><path d="M4 10v7h3v-7H4zm6 0v7h3v-7h-3zM2 22h19v-3H2v3zm14-12v7h3v-7h-3zm-4.5-9L2 6v2h19V6l-9.5-5z"/></g> +<g id="account-balance-wallet"><path d="M21 18v1c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2-2V5c0-1.1.89-2 2-2h14c1.1 0 2 .9 2 2v1h-9c-1.11 0-2 .9-2 2v8c0 1.1.89 2 2 2h9zm-9-2h10V8H12v8zm4-2.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="account-box"><path d="M3 5v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2H5c-1.11 0-2 .9-2 2zm12 4c0 1.66-1.34 3-3 3s-3-1.34-3-3 1.34-3 3-3 3 1.34 3 3zm-9 8c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1H6v-1z"/></g> +<g id="account-child"><circle cx="12" cy="13.49" r="1.5"/><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 2.5c1.24 0 2.25 1.01 2.25 2.25S13.24 9 12 9 9.75 7.99 9.75 6.75 10.76 4.5 12 4.5zm5 10.56v2.5c-.45.41-.96.77-1.5 1.05v-.68c0-.34-.17-.65-.46-.92-.65-.62-1.89-1.02-3.04-1.02-.96 0-1.96.28-2.65.73l-.17.12-.21.17c.78.47 1.63.72 2.54.82l1.33.15c.37.04.66.36.66.75 0 .29-.16.53-.4.66-.28.15-.64.09-.95.09-.35 0-.69-.01-1.03-.05-.5-.06-.99-.17-1.46-.33-.49-.16-.97-.38-1.42-.64-.22-.13-.44-.27-.65-.43l-.31-.24c-.04-.02-.28-.18-.28-.23v-4.28c0-1.58 2.63-2.78 5-2.78s5 1.2 5 2.78v1.78z"/></g> +<g id="account-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"/></g> +<g id="add"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></g> +<g id="add-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/></g> +<g id="add-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/></g> +<g id="add-circle-outline"><path d="M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4V7zm-1-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="add-shopping-cart"><path d="M11 9h2V6h3V4h-3V1h-2v3H8v2h3v3zm-4 9c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zm10 0c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2zm-9.83-3.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.86-7.01L19.42 4h-.01l-1.1 2-2.76 5H8.53l-.13-.27L6.16 6l-.95-2-.94-2H1v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.13 0-.25-.11-.25-.25z"/></g> +<g id="alarm"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37V8zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="alarm-add"><path d="M7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm1-11h-2v3H8v2h3v3h2v-3h3v-2h-3V9z"/></g> +<g id="alarm-off"><path d="M12 6c3.87 0 7 3.13 7 7 0 .84-.16 1.65-.43 2.4l1.52 1.52c.58-1.19.91-2.51.91-3.92 0-4.97-4.03-9-9-9-1.41 0-2.73.33-3.92.91L9.6 6.43C10.35 6.16 11.16 6 12 6zm10-.28l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM2.92 2.29L1.65 3.57 2.98 4.9l-1.11.93 1.42 1.42 1.11-.94.8.8C3.83 8.69 3 10.75 3 13c0 4.97 4.02 9 9 9 2.25 0 4.31-.83 5.89-2.2l2.2 2.2 1.27-1.27L3.89 3.27l-.97-.98zm13.55 16.1C15.26 19.39 13.7 20 12 20c-3.87 0-7-3.13-7-7 0-1.7.61-3.26 1.61-4.47l9.86 9.86zM8.02 3.28L6.6 1.86l-.86.71 1.42 1.42.86-.71z"/></g> +<g id="alarm-on"><path d="M22 5.72l-4.6-3.86-1.29 1.53 4.6 3.86L22 5.72zM7.88 3.39L6.6 1.86 2 5.71l1.29 1.53 4.59-3.85zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9zm0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm-1.46-5.47L8.41 12.4l-1.06 1.06 3.18 3.18 6-6-1.06-1.06-4.93 4.95z"/></g> +<g id="android"><path d="M6 18c0 .55.45 1 1 1h1v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h2v3.5c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5V19h1c.55 0 1-.45 1-1V8H6v10zM3.5 8C2.67 8 2 8.67 2 9.5v7c0 .83.67 1.5 1.5 1.5S5 17.33 5 16.5v-7C5 8.67 4.33 8 3.5 8zm17 0c-.83 0-1.5.67-1.5 1.5v7c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5v-7c0-.83-.67-1.5-1.5-1.5zm-4.97-5.84l1.3-1.3c.2-.2.2-.51 0-.71-.2-.2-.51-.2-.71 0l-1.48 1.48C13.85 1.23 12.95 1 12 1c-.96 0-1.86.23-2.66.63L7.85.15c-.2-.2-.51-.2-.71 0-.2.2-.2.51 0 .71l1.31 1.31C6.97 3.26 6 5.01 6 7h12c0-1.99-.97-3.75-2.47-4.84zM10 5H9V4h1v1zm5 0h-1V4h1v1z"/></g> +<g id="announcement"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 9h-2V5h2v6zm0 4h-2v-2h2v2z"/></g> +<g id="apps"><path d="M4 8h4V4H4v4zm6 12h4v-4h-4v4zm-6 0h4v-4H4v4zm0-6h4v-4H4v4zm6 0h4v-4h-4v4zm6-10v4h4V4h-4zm-6 4h4V4h-4v4zm6 6h4v-4h-4v4zm0 6h4v-4h-4v4z"/></g> +<g id="archive"><path d="M20.54 5.23l-1.39-1.68C18.88 3.21 18.47 3 18 3H6c-.47 0-.88.21-1.16.55L3.46 5.23C3.17 5.57 3 6.02 3 6.5V19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V6.5c0-.48-.17-.93-.46-1.27zM12 17.5L6.5 12H10v-2h4v2h3.5L12 17.5zM5.12 5l.81-1h12l.94 1H5.12z"/></g> +<g id="arrow-back"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></g> +<g id="arrow-drop-down"><path d="M7 10l5 5 5-5z"/></g> +<g id="arrow-drop-down-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 12l-4-4h8l-4 4z"/></g> +<g id="arrow-drop-up"><path d="M7 14l5-5 5 5z"/></g> +<g id="arrow-forward"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"/></g> +<g id="aspect-ratio"><path d="M19 12h-2v3h-3v2h5v-5zM7 9h3V7H5v5h2V9zm14-6H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"/></g> +<g id="assessment"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/></g> +<g id="assignment"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm2 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"/></g> +<g id="assignment-ind"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 4c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1.4c0-2 4-3.1 6-3.1s6 1.1 6 3.1V19z"/></g> +<g id="assignment-late"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-6 15h-2v-2h2v2zm0-4h-2V8h2v6zm-1-9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></g> +<g id="assignment-return"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm4 12h-4v3l-5-5 5-5v3h4v4z"/></g> +<g id="assignment-returned"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm0 15l-5-5h3V9h4v4h3l-5 5z"/></g> +<g id="assignment-turned-in"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm-2 14l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"/></g> +<g id="attachment"><path d="M7.5 18C4.46 18 2 15.54 2 12.5S4.46 7 7.5 7H18c2.21 0 4 1.79 4 4s-1.79 4-4 4H9.5C8.12 15 7 13.88 7 12.5S8.12 10 9.5 10H17v1.5H9.5c-.55 0-1 .45-1 1s.45 1 1 1H18c1.38 0 2.5-1.12 2.5-2.5S19.38 8.5 18 8.5H7.5c-2.21 0-4 1.79-4 4s1.79 4 4 4H17V18H7.5z"/></g> +<g id="autorenew"><path d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z"/></g> +<g id="backspace"><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.9.89 1.59.89h15c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-3 12.59L17.59 17 14 13.41 10.41 17 9 15.59 12.59 12 9 8.41 10.41 7 14 10.59 17.59 7 19 8.41 15.41 12 19 15.59z"/></g> +<g id="backup"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/></g> +<g id="block"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM4 12c0-4.42 3.58-8 8-8 1.85 0 3.55.63 4.9 1.69L5.69 16.9C4.63 15.55 4 13.85 4 12zm8 8c-1.85 0-3.55-.63-4.9-1.69L18.31 7.1C19.37 8.45 20 10.15 20 12c0 4.42-3.58 8-8 8z"/></g> +<g id="book"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"/></g> +<g id="bookmark"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></g> +<g id="bookmark-outline"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"/></g> +<g id="bug-report"><path d="M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"/></g> +<g id="cached"><path d="M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1.46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6 6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l4 4 4-4H6z"/></g> +<g id="cancel"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/></g> +<g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></g> +<g id="check-box"><path d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></g> +<g id="check-box-outline-blank"><path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></g> +<g id="check-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/></g> +<g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></g> +<g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></g> +<g id="class"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"/></g> +<g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></g> +<g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></g> +<g id="cloud"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96z"/></g> +<g id="cloud-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.5 14H8c-1.66 0-3-1.34-3-3s1.34-3 3-3l.14.01C8.58 8.28 10.13 7 12 7c2.21 0 4 1.79 4 4h.5c1.38 0 2.5 1.12 2.5 2.5S17.88 16 16.5 16z"/></g> +<g id="cloud-done"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM10 17l-3.5-3.5 1.41-1.41L10 14.17 15.18 9l1.41 1.41L10 17z"/></g> +<g id="cloud-download"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z"/></g> +<g id="cloud-off"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4c-1.48 0-2.85.43-4.01 1.17l1.46 1.46C10.21 6.23 11.08 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3 0 1.13-.64 2.11-1.56 2.62l1.45 1.45C23.16 18.16 24 16.68 24 15c0-2.64-2.05-4.78-4.65-4.96zM3 5.27l2.75 2.74C2.56 8.15 0 10.77 0 14c0 3.31 2.69 6 6 6h11.73l2 2L21 20.73 4.27 4 3 5.27zM7.73 10l8 8H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h1.73z"/></g> +<g id="cloud-queue"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3z"/></g> +<g id="cloud-upload"><path d="M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z"/></g> +<g id="content-copy"><path d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></g> +<g id="content-cut"><path d="M9.64 7.64c.23-.5.36-1.05.36-1.64 0-2.21-1.79-4-4-4S2 3.79 2 6s1.79 4 4 4c.59 0 1.14-.13 1.64-.36L10 12l-2.36 2.36C7.14 14.13 6.59 14 6 14c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4c0-.59-.13-1.14-.36-1.64L12 14l7 7h3v-1L9.64 7.64zM6 8c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm0 12c-1.1 0-2-.89-2-2s.9-2 2-2 2 .89 2 2-.9 2-2 2zm6-7.5c-.28 0-.5-.22-.5-.5s.22-.5.5-.5.5.22.5.5-.22.5-.5.5zM19 3l-6 6 2 2 7-7V3z"/></g> +<g id="content-paste"><path d="M19 2h-4.18C14.4.84 13.3 0 12 0c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm7 18H5V4h2v3h10V4h2v16z"/></g> +<g id="create"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/></g> +<g id="credit-card"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"/></g> +<g id="dashboard"><path d="M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"/></g> +<g id="delete"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></g> +<g id="description"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 16H8v-2h8v2zm0-4H8v-2h8v2zm-3-5V3.5L18.5 9H13z"/></g> +<g id="dns"><path d="M20 13H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zM7 19c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM20 3H4c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h16c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zM7 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="done"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></g> +<g id="done-all"><path d="M18 7l-1.41-1.41-6.34 6.34 1.41 1.41L18 7zm4.24-1.41L11.66 16.17 7.48 12l-1.41 1.41L11.66 19l12-12-1.42-1.41zM.41 13.41L6 19l1.41-1.41L1.83 12 .41 13.41z"/></g> +<g id="drafts"><path d="M21.99 8c0-.72-.37-1.35-.94-1.7L12 1 2.95 6.3C2.38 6.65 2 7.28 2 8v10c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2l-.01-10zM12 13L3.74 7.84 12 3l8.26 4.84L12 13z"/></g> +<g id="error"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"/></g> +<g id="event"><path d="M17 12h-5v5h5v-5zM16 1v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2h-1V1h-2zm3 18H5V8h14v11z"/></g> +<g id="exit-to-app"><path d="M10.09 15.59L11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67l-2.58 2.59zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z"/></g> +<g id="expand-less"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"/></g> +<g id="expand-more"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"/></g> +<g id="explore"><path d="M12 10.9c-.61 0-1.1.49-1.1 1.1s.49 1.1 1.1 1.1c.61 0 1.1-.49 1.1-1.1s-.49-1.1-1.1-1.1zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm2.19 12.19L6 18l3.81-8.19L18 6l-3.81 8.19z"/></g> +<g id="extension"><path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"/></g> +<g id="face"><path d="M14.69 17.1c-.74.58-1.7.9-2.69.9s-1.95-.32-2.69-.9c-.22-.17-.53-.13-.7.09-.17.22-.13.53.09.7.91.72 2.09 1.11 3.3 1.11s2.39-.39 3.31-1.1c.22-.17.26-.48.09-.7-.17-.23-.49-.26-.71-.1z"/><circle cx="8.5" cy="12.5" r="1"/><path d="M12 0C5.37 0 0 5.37 0 12s5.37 12 12 12 12-5.37 12-12S18.63 0 12 0zm7.96 14.82c-1.09 3.74-4.27 6.46-8.04 6.46-3.78 0-6.96-2.72-8.04-6.47-1.19-.11-2.13-1.18-2.13-2.52 0-1.27.85-2.31 1.97-2.5 2.09-1.46 3.8-3.49 4.09-5.05v-.01c1.35 2.63 6.3 5.19 11.83 5.06l.3-.03c1.28 0 2.31 1.14 2.31 2.54 0 1.38-1.02 2.51-2.29 2.52z"/><circle cx="15.5" cy="12.5" r="1"/></g> +<g id="favorite"><path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z"/></g> +<g id="favorite-outline"><path d="M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z"/></g> +<g id="file-download"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></g> +<g id="file-upload"><path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/></g> +<g id="filter-list"><path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/></g> +<g id="find-in-page"><path d="M20 19.59V8l-6-6H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c.45 0 .85-.15 1.19-.4l-4.43-4.43c-.8.52-1.74.83-2.76.83-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-.31 1.96-.83 2.75L20 19.59zM9 13c0 1.66 1.34 3 3 3s3-1.34 3-3-1.34-3-3-3-3 1.34-3 3z"/></g> +<g id="find-replace"><path d="M11 6c1.38 0 2.63.56 3.54 1.46L12 10h6V4l-2.05 2.05C14.68 4.78 12.93 4 11 4c-3.53 0-6.43 2.61-6.92 6H6.1c.46-2.28 2.48-4 4.9-4zm5.64 9.14c.66-.9 1.12-1.97 1.28-3.14H15.9c-.46 2.28-2.48 4-4.9 4-1.38 0-2.63-.56-3.54-1.46L10 12H4v6l2.05-2.05C7.32 17.22 9.07 18 11 18c1.55 0 2.98-.51 4.14-1.36L20 21.49 21.49 20l-4.85-4.86z"/></g> +<g id="flag"><path d="M14.4 6L14 4H5v17h2v-7h5.6l.4 2h7V6z"/></g> +<g id="flip-to-back"><path d="M9 7H7v2h2V7zm0 4H7v2h2v-2zm0-8c-1.11 0-2 .9-2 2h2V3zm4 12h-2v2h2v-2zm6-12v2h2c0-1.1-.9-2-2-2zm-6 0h-2v2h2V3zM9 17v-2H7c0 1.1.89 2 2 2zm10-4h2v-2h-2v2zm0-4h2V7h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zM5 7H3v12c0 1.1.89 2 2 2h12v-2H5V7zm10-2h2V3h-2v2zm0 12h2v-2h-2v2z"/></g> +<g id="flip-to-front"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm2 4v-2H3c0 1.1.89 2 2 2zM3 9h2V7H3v2zm12 12h2v-2h-2v2zm4-18H9c-1.11 0-2 .9-2 2v10c0 1.1.89 2 2 2h10c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12H9V5h10v10zm-8 6h2v-2h-2v2zm-4 0h2v-2H7v2z"/></g> +<g id="folder"><path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/></g> +<g id="folder-open"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 12H4V8h16v10z"/></g> +<g id="folder-shared"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-5 3c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm4 8h-8v-1c0-1.33 2.67-2 4-2s4 .67 4 2v1z"/></g> +<g id="forward"><path d="M12 8V4l8 8-8 8v-4H4V8z"/></g> +<g id="fullscreen"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></g> +<g id="fullscreen-exit"><path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/></g> +<g id="gesture"><path d="M4.59 6.89c.7-.71 1.4-1.35 1.71-1.22.5.2 0 1.03-.3 1.52-.25.42-2.86 3.89-2.86 6.31 0 1.28.48 2.34 1.34 2.98.75.56 1.74.73 2.64.46 1.07-.31 1.95-1.4 3.06-2.77 1.21-1.49 2.83-3.44 4.08-3.44 1.63 0 1.65 1.01 1.76 1.79-3.78.64-5.38 3.67-5.38 5.37 0 1.7 1.44 3.09 3.21 3.09 1.63 0 4.29-1.33 4.69-6.1H21v-2.5h-2.47c-.15-1.65-1.09-4.2-4.03-4.2-2.25 0-4.18 1.91-4.94 2.84-.58.73-2.06 2.48-2.29 2.72-.25.3-.68.84-1.11.84-.45 0-.72-.83-.36-1.92.35-1.09 1.4-2.86 1.85-3.52.78-1.14 1.3-1.92 1.3-3.28C8.95 3.69 7.31 3 6.44 3 5.12 3 3.97 4 3.72 4.25c-.36.36-.66.66-.88.93l1.75 1.71zm9.29 11.66c-.31 0-.74-.26-.74-.72 0-.6.73-2.2 2.87-2.76-.3 2.69-1.43 3.48-2.13 3.48z"/></g> +<g id="get-app"><path d="M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"/></g> +<g id="grade"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></g> +<g id="group-work"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM8 17.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5zM9.5 8c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5S9.5 9.38 9.5 8zm6.5 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></g> +<g id="help"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z"/></g> +<g id="highlight-remove"><path d="M14.59 8L12 10.59 9.41 8 8 9.41 10.59 12 8 14.59 9.41 16 12 13.41 14.59 16 16 14.59 13.41 12 16 9.41 14.59 8zM12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="history"><path opacity=".9" d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/></g> +<g id="home"><path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/></g> +<g id="https"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/></g> +<g id="inbox"><path d="M19 3H4.99c-1.1 0-1.98.9-1.98 2L3 19c0 1.1.89 2 1.99 2H19c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 12h-4c0 1.66-1.34 3-3 3s-3-1.34-3-3H4.99V5H19v10zm-3-5h-2V7h-4v3H8l4 4 4-4z"/></g> +<g id="info"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"/></g> +<g id="info-outline"><path d="M11 17h2v-6h-2v6zm1-15C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zM11 9h2V7h-2v2z"/></g> +<g id="input"><path d="M21 3.01H3c-1.1 0-2 .9-2 2V9h2V4.99h18v14.03H3V15H1v4.01c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98v-14c0-1.11-.9-2-2-2zM11 16l4-4-4-4v3H1v2h10v3z"/></g> +<g id="invert-colors"><path d="M17.66 7.93L12 2.27 6.34 7.93c-3.12 3.12-3.12 8.19 0 11.31C7.9 20.8 9.95 21.58 12 21.58c2.05 0 4.1-.78 5.66-2.34 3.12-3.12 3.12-8.19 0-11.31zM12 19.59c-1.6 0-3.11-.62-4.24-1.76C6.62 16.69 6 15.19 6 13.59s.62-3.11 1.76-4.24L12 5.1v14.49z"/></g> +<g id="label"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16z"/></g> +<g id="label-outline"><path d="M17.63 5.84C17.27 5.33 16.67 5 16 5L5 5.01C3.9 5.01 3 5.9 3 7v10c0 1.1.9 1.99 2 1.99L16 19c.67 0 1.27-.33 1.63-.84L22 12l-4.37-6.16zM16 17H5V7h11l3.55 5L16 17z"/></g> +<g id="language"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm6.93 6h-2.95c-.32-1.25-.78-2.45-1.38-3.56 1.84.63 3.37 1.91 4.33 3.56zM12 4.04c.83 1.2 1.48 2.53 1.91 3.96h-3.82c.43-1.43 1.08-2.76 1.91-3.96zM4.26 14C4.1 13.36 4 12.69 4 12s.1-1.36.26-2h3.38c-.08.66-.14 1.32-.14 2 0 .68.06 1.34.14 2H4.26zm.82 2h2.95c.32 1.25.78 2.45 1.38 3.56-1.84-.63-3.37-1.9-4.33-3.56zm2.95-8H5.08c.96-1.66 2.49-2.93 4.33-3.56C8.81 5.55 8.35 6.75 8.03 8zM12 19.96c-.83-1.2-1.48-2.53-1.91-3.96h3.82c-.43 1.43-1.08 2.76-1.91 3.96zM14.34 14H9.66c-.09-.66-.16-1.32-.16-2 0-.68.07-1.35.16-2h4.68c.09.65.16 1.32.16 2 0 .68-.07 1.34-.16 2zm.25 5.56c.6-1.11 1.06-2.31 1.38-3.56h2.95c-.96 1.65-2.49 2.93-4.33 3.56zM16.36 14c.08-.66.14-1.32.14-2 0-.68-.06-1.34-.14-2h3.38c.16.64.26 1.31.26 2s-.1 1.36-.26 2h-3.38z"/></g> +<g id="launch"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></g> +<g id="link"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"/></g> +<g id="list"><path d="M3 13h2v-2H3v2zm0 4h2v-2H3v2zm0-8h2V7H3v2zm4 4h14v-2H7v2zm0 4h14v-2H7v2zM7 7v2h14V7H7z"/></g> +<g id="lock"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z"/></g> +<g id="lock-open"><path d="M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm0 12H6V10h12v10z"/></g> +<g id="lock-outline"><path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6-5.1c1.71 0 3.1 1.39 3.1 3.1v2H9V6h-.1c0-1.71 1.39-3.1 3.1-3.1zM18 20H6V10h12v10zm-6-3c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2z"/></g> +<g id="loyalty"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7zm11.77 8.27L13 19.54l-4.27-4.27C8.28 14.81 8 14.19 8 13.5c0-1.38 1.12-2.5 2.5-2.5.69 0 1.32.28 1.77.74l.73.72.73-.73c.45-.45 1.08-.73 1.77-.73 1.38 0 2.5 1.12 2.5 2.5 0 .69-.28 1.32-.73 1.77z"/></g> +<g id="mail"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></g> +<g id="markunread"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></g> +<g id="markunread-mailbox"><path d="M20 6H10v6H8V4h6V0H6v6H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2z"/></g> +<g id="menu"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/></g> +<g id="more-horiz"><path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="more-vert"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="note-add"><path d="M14 2H6c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6zm2 14h-3v3h-2v-3H8v-2h3v-3h2v3h3v2zm-3-7V3.5L18.5 9H13z"/></g> +<g id="open-in-browser"><path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h4v-2H5V8h14v10h-4v2h4c1.1 0 2-.9 2-2V6c0-1.1-.89-2-2-2zm-7 6l-4 4h3v6h2v-6h3l-4-4z"/></g> +<g id="open-in-new"><path d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"/></g> +<g id="open-with"><path d="M10 9h4V6h3l-5-5-5 5h3v3zm-1 1H6V7l-5 5 5 5v-3h3v-4zm14 2l-5-5v3h-3v4h3v3l5-5zm-9 3h-4v3H7l5 5 5-5h-3v-3z"/></g> +<g id="pageview"><path d="M11 8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm8-5H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1.41 16l-3.83-3.83c-.8.52-1.74.83-2.76.83-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-.31 1.96-.83 2.75L19 17.59 17.59 19z"/></g> +<g id="payment"><path d="M20 4H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4v-6h16v6zm0-10H4V6h16v2z"/></g> +<g id="perm-camera-mic"><path d="M20 5h-3.17L15 3H9L7.17 5H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h7v-2.09c-2.83-.48-5-2.94-5-5.91h2c0 2.21 1.79 4 4 4s4-1.79 4-4h2c0 2.97-2.17 5.43-5 5.91V21h7c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm-6 8c0 1.1-.9 2-2 2s-2-.9-2-2V9c0-1.1.9-2 2-2s2 .9 2 2v4z"/></g> +<g id="perm-contact-cal"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm6 12H6v-1c0-2 4-3.1 6-3.1s6 1.1 6 3.1v1z"/></g> +<g id="perm-data-setting"><path d="M18.99 11.5c.34 0 .67.03 1 .07L20 0 0 20h11.56c-.04-.33-.07-.66-.07-1 0-4.14 3.36-7.5 7.5-7.5zm3.71 7.99c.02-.16.04-.32.04-.49 0-.17-.01-.33-.04-.49l1.06-.83c.09-.08.12-.21.06-.32l-1-1.73c-.06-.11-.19-.15-.31-.11l-1.24.5c-.26-.2-.54-.37-.85-.49l-.19-1.32c-.01-.12-.12-.21-.24-.21h-2c-.12 0-.23.09-.25.21l-.19 1.32c-.3.13-.59.29-.85.49l-1.24-.5c-.11-.04-.24 0-.31.11l-1 1.73c-.06.11-.04.24.06.32l1.06.83c-.02.16-.03.32-.03.49 0 .17.01.33.03.49l-1.06.83c-.09.08-.12.21-.06.32l1 1.73c.06.11.19.15.31.11l1.24-.5c.26.2.54.37.85.49l.19 1.32c.02.12.12.21.25.21h2c.12 0 .23-.09.25-.21l.19-1.32c.3-.13.59-.29.84-.49l1.25.5c.11.04.24 0 .31-.11l1-1.73c.06-.11.03-.24-.06-.32l-1.07-.83zm-3.71 1.01c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="perm-device-info"><path d="M13 7h-2v2h2V7zm0 4h-2v6h2v-6zm4-9.99L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14z"/></g> +<g id="perm-identity"><path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"/></g> +<g id="perm-media"><path d="M2 6H0v5h.01L0 20c0 1.1.9 2 2 2h18v-2H2V6zm20-2h-8l-2-2H6c-1.1 0-1.99.9-1.99 2L4 16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM7 15l4.5-6 3.5 4.51 2.5-3.01L21 15H7z"/></g> +<g id="perm-phone-msg"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM12 3v10l3-3h6V3h-9z"/></g> +<g id="perm-scan-wifi"><path d="M12 3C6.95 3 3.15 4.85 0 7.23L12 22 24 7.25C20.85 4.87 17.05 3 12 3zm1 13h-2v-6h2v6zm-2-8V6h2v2h-2z"/></g> +<g id="picture-in-picture"><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z"/></g> +<g id="polymer"><path d="M19 4h-4L7.11 16.63 4.5 12 9 4H5L.5 12 5 20h4l7.89-12.63L19.5 12 15 20h4l4.5-8z"/></g> +<g id="print"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></g> +<g id="query-builder"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zM12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></g> +<g id="question-answer"><path d="M21 6h-2v9H6v2c0 .55.45 1 1 1h11l4 4V7c0-.55-.45-1-1-1zm-4 6V3c0-.55-.45-1-1-1H3c-.55 0-1 .45-1 1v14l4-4h10c.55 0 1-.45 1-1z"/></g> +<g id="radio-button-off"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></g> +<g id="radio-button-on"><path d="M12 7c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></g> +<g id="receipt"><path d="M18 17H6v-2h12v2zm0-4H6v-2h12v2zm0-4H6V7h12v2zM3 22l1.5-1.5L6 22l1.5-1.5L9 22l1.5-1.5L12 22l1.5-1.5L15 22l1.5-1.5L18 22l1.5-1.5L21 22V2l-1.5 1.5L18 2l-1.5 1.5L15 2l-1.5 1.5L12 2l-1.5 1.5L9 2 7.5 3.5 6 2 4.5 3.5 3 2v20z"/></g> +<g id="redeem"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"/></g> +<g id="redo"><path d="M18.4 10.6C16.55 8.99 14.15 8 11.5 8c-4.65 0-8.58 3.03-9.96 7.22L3.9 16c1.05-3.19 4.05-5.5 7.6-5.5 1.95 0 3.73.72 5.12 1.88L13 16h9V7l-3.6 3.6z"/></g> +<g id="refresh"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></g> +<g id="remove"><path d="M19 13H5v-2h14v2z"/></g> +<g id="remove-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11H7v-2h10v2z"/></g> +<g id="remove-circle-outline"><path d="M7 11v2h10v-2H7zm5-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></g> +<g id="reorder"><path d="M3 15h18v-2H3v2zm0 4h18v-2H3v2zm0-8h18V9H3v2zm0-6v2h18V5H3z"/></g> +<g id="reply"><path d="M10 9V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"/></g> +<g id="reply-all"><path d="M7 8V5l-7 7 7 7v-3l-4-4 4-4zm6 1V5l-7 7 7 7v-4.1c5 0 8.5 1.6 11 5.1-1-5-4-10-11-11z"/></g> +<g id="report"><path d="M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.73 3zM12 17.3c-.72 0-1.3-.58-1.3-1.3 0-.72.58-1.3 1.3-1.3.72 0 1.3.58 1.3 1.3 0 .72-.58 1.3-1.3 1.3zm1-4.3h-2V7h2v6z"/></g> +<g id="report-problem"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></g> +<g id="restore"><path d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"/></g> +<g id="room"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></g> +<g id="save"><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></g> +<g id="schedule"><path fill-opacity=".9" d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zM12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></g> +<g id="search"><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/></g> +<g id="select-all"><path d="M3 5h2V3c-1.1 0-2 .9-2 2zm0 8h2v-2H3v2zm4 8h2v-2H7v2zM3 9h2V7H3v2zm10-6h-2v2h2V3zm6 0v2h2c0-1.1-.9-2-2-2zM5 21v-2H3c0 1.1.9 2 2 2zm-2-4h2v-2H3v2zM9 3H7v2h2V3zm2 18h2v-2h-2v2zm8-8h2v-2h-2v2zm0 8c1.1 0 2-.9 2-2h-2v2zm0-12h2V7h-2v2zm0 8h2v-2h-2v2zm-4 4h2v-2h-2v2zm0-16h2V3h-2v2zM7 17h10V7H7v10zm2-8h6v6H9V9z"/></g> +<g id="send"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></g> +<g id="settings"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></g> +<g id="settings-applications"><path d="M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm7-7H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2zm-1.75 9c0 .23-.02.46-.05.68l1.48 1.16c.13.11.17.3.08.45l-1.4 2.42c-.09.15-.27.21-.43.15l-1.74-.7c-.36.28-.76.51-1.18.69l-.26 1.85c-.03.17-.18.3-.35.3h-2.8c-.17 0-.32-.13-.35-.29l-.26-1.85c-.43-.18-.82-.41-1.18-.69l-1.74.7c-.16.06-.34 0-.43-.15l-1.4-2.42c-.09-.15-.05-.34.08-.45l1.48-1.16c-.03-.23-.05-.46-.05-.69 0-.23.02-.46.05-.68l-1.48-1.16c-.13-.11-.17-.3-.08-.45l1.4-2.42c.09-.15.27-.21.43-.15l1.74.7c.36-.28.76-.51 1.18-.69l.26-1.85c.03-.17.18-.3.35-.3h2.8c.17 0 .32.13.35.29l.26 1.85c.43.18.82.41 1.18.69l1.74-.7c.16-.06.34 0 .43.15l1.4 2.42c.09.15.05.34-.08.45l-1.48 1.16c.03.23.05.46.05.69z"/></g> +<g id="settings-backup-restore"><path d="M14 12c0-1.1-.9-2-2-2s-2 .9-2 2 .9 2 2 2 2-.9 2-2zm-2-9c-4.97 0-9 4.03-9 9H0l4 4 4-4H5c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.51 0-2.91-.49-4.06-1.3l-1.42 1.44C8.04 20.3 9.94 21 12 21c4.97 0 9-4.03 9-9s-4.03-9-9-9z"/></g> +<g id="settings-bluetooth"><path d="M11 24h2v-2h-2v2zm-4 0h2v-2H7v2zm8 0h2v-2h-2v2zm2.71-18.29L12 0h-1v7.59L6.41 3 5 4.41 10.59 10 5 15.59 6.41 17 11 12.41V20h1l5.71-5.71-4.3-4.29 4.3-4.29zM13 3.83l1.88 1.88L13 7.59V3.83zm1.88 10.46L13 16.17v-3.76l1.88 1.88z"/></g> +<g id="settings-cell"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm4 0h2v-2h-2v2zM16 .01L8 0C6.9 0 6 .9 6 2v16c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V2c0-1.1-.9-1.99-2-1.99zM16 16H8V4h8v12z"/></g> +<g id="settings-display"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02zM8 16h2.5l1.5 1.5 1.5-1.5H16v-2.5l1.5-1.5-1.5-1.5V8h-2.5L12 6.5 10.5 8H8v2.5L6.5 12 8 13.5V16zm4-7c1.66 0 3 1.34 3 3s-1.34 3-3 3V9z"/></g> +<g id="settings-ethernet"><path d="M7.77 6.76L6.23 5.48.82 12l5.41 6.52 1.54-1.28L3.42 12l4.35-5.24zM7 13h2v-2H7v2zm10-2h-2v2h2v-2zm-6 2h2v-2h-2v2zm6.77-7.52l-1.54 1.28L20.58 12l-4.35 5.24 1.54 1.28L23.18 12l-5.41-6.52z"/></g> +<g id="settings-input-antenna"><path d="M12 5c-3.87 0-7 3.13-7 7h2c0-2.76 2.24-5 5-5s5 2.24 5 5h2c0-3.87-3.13-7-7-7zm1 9.29c.88-.39 1.5-1.26 1.5-2.29 0-1.38-1.12-2.5-2.5-2.5S9.5 10.62 9.5 12c0 1.02.62 1.9 1.5 2.29v3.3L7.59 21 9 22.41l3-3 3 3L16.41 21 13 17.59v-3.3zM12 1C5.93 1 1 5.93 1 12h2c0-4.97 4.03-9 9-9s9 4.03 9 9h2c0-6.07-4.93-11-11-11z"/></g> +<g id="settings-input-component"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"/></g> +<g id="settings-input-composite"><path d="M5 2c0-.55-.45-1-1-1s-1 .45-1 1v4H1v6h6V6H5V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2H9v2zm-8 0c0 1.3.84 2.4 2 2.82V23h2v-4.18C6.16 18.4 7 17.3 7 16v-2H1v2zM21 6V2c0-.55-.45-1-1-1s-1 .45-1 1v4h-2v6h6V6h-2zm-8-4c0-.55-.45-1-1-1s-1 .45-1 1v4H9v6h6V6h-2V2zm4 14c0 1.3.84 2.4 2 2.82V23h2v-4.18c1.16-.41 2-1.51 2-2.82v-2h-6v2z"/></g> +<g id="settings-input-hdmi"><path d="M18 7V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v3H5v6l3 6v3h8v-3l3-6V7h-1zM8 4h8v3h-2V5h-1v2h-2V5h-1v2H8V4z"/></g> +<g id="settings-input-svideo"><path d="M8 11.5c0-.83-.67-1.5-1.5-1.5S5 10.67 5 11.5 5.67 13 6.5 13 8 12.33 8 11.5zm7-5c0-.83-.67-1.5-1.5-1.5h-3C9.67 5 9 5.67 9 6.5S9.67 8 10.5 8h3c.83 0 1.5-.67 1.5-1.5zM8.5 15c-.83 0-1.5.67-1.5 1.5S7.67 18 8.5 18s1.5-.67 1.5-1.5S9.33 15 8.5 15zM12 1C5.93 1 1 5.93 1 12s4.93 11 11 11 11-4.93 11-11S18.07 1 12 1zm0 20c-4.96 0-9-4.04-9-9s4.04-9 9-9 9 4.04 9 9-4.04 9-9 9zm5.5-11c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5zm-2 5c-.83 0-1.5.67-1.5 1.5s.67 1.5 1.5 1.5 1.5-.67 1.5-1.5-.67-1.5-1.5-1.5z"/></g> +<g id="settings-overscan"><path d="M12.01 5.5L10 8h4l-1.99-2.5zM18 10v4l2.5-1.99L18 10zM6 10l-2.5 2.01L6 14v-4zm8 6h-4l2.01 2.5L14 16zm7-13H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16.01H3V4.99h18v14.02z"/></g> +<g id="settings-phone"><path d="M13 9h-2v2h2V9zm4 0h-2v2h2V9zm3 6.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.58l2.2-2.21c.28-.27.36-.66.25-1.01C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 9v2h2V9h-2z"/></g> +<g id="settings-power"><path d="M7 24h2v-2H7v2zm4 0h2v-2h-2v2zm2-22h-2v10h2V2zm3.56 2.44l-1.45 1.45C16.84 6.94 18 8.83 18 11c0 3.31-2.69 6-6 6s-6-2.69-6-6c0-2.17 1.16-4.06 2.88-5.12L7.44 4.44C5.36 5.88 4 8.28 4 11c0 4.42 3.58 8 8 8s8-3.58 8-8c0-2.72-1.36-5.12-3.44-6.56zM15 24h2v-2h-2v2z"/></g> +<g id="settings-remote"><path d="M15 9H9c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V10c0-.55-.45-1-1-1zm-3 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zM7.05 6.05l1.41 1.41C9.37 6.56 10.62 6 12 6s2.63.56 3.54 1.46l1.41-1.41C15.68 4.78 13.93 4 12 4s-3.68.78-4.95 2.05zM12 0C8.96 0 6.21 1.23 4.22 3.22l1.41 1.41C7.26 3.01 9.51 2 12 2s4.74 1.01 6.36 2.64l1.41-1.41C17.79 1.23 15.04 0 12 0z"/></g> +<g id="settings-voice"><path d="M7 24h2v-2H7v2zm5-11c1.66 0 2.99-1.34 2.99-3L15 4c0-1.66-1.34-3-3-3S9 2.34 9 4v6c0 1.66 1.34 3 3 3zm-1 11h2v-2h-2v2zm4 0h2v-2h-2v2zm4-14h-1.7c0 3-2.54 5.1-5.3 5.1S6.7 13 6.7 10H5c0 3.41 2.72 6.23 6 6.72V20h2v-3.28c3.28-.49 6-3.31 6-6.72z"/></g> +<g id="shop"><path d="M16 6V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H2v13c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6h-6zm-6-2h4v2h-4V4zM9 18V9l7.5 4L9 18z"/></g> +<g id="shop-two"><path d="M3 9H1v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2H3V9zm15-4V3c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H5v11c0 1.11.89 2 2 2h14c1.11 0 2-.89 2-2V5h-5zm-6-2h4v2h-4V3zm0 12V8l5.5 3-5.5 4z"/></g> +<g id="shopping-basket"><path d="M17.21 9l-4.38-6.56c-.19-.28-.51-.42-.83-.42-.32 0-.64.14-.83.43L6.79 9H2c-.55 0-1 .45-1 1 0 .09.01.18.04.27l2.54 9.27c.23.84 1 1.46 1.92 1.46h13c.92 0 1.69-.62 1.93-1.46l2.54-9.27L23 10c0-.55-.45-1-1-1h-4.79zM9 9l3-4.4L15 9H9zm3 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="shopping-cart"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="sort"><path d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"/></g> +<g id="speaker-notes"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM8 14H6v-2h2v2zm0-3H6V9h2v2zm0-3H6V6h2v2zm7 6h-5v-2h5v2zm3-3h-8V9h8v2zm0-3h-8V6h8v2z"/></g> +<g id="spellcheck"><path d="M12.45 16h2.09L9.43 3H7.57L2.46 16h2.09l1.12-3h5.64l1.14 3zm-6.02-5L8.5 5.48 10.57 11H6.43zm15.16.59l-8.09 8.09L9.83 16l-1.41 1.41 5.09 5.09L23 13l-1.41-1.41z"/></g> +<g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></g> +<g id="star-half"><path d="M22 9.74l-7.19-.62L12 2.5 9.19 9.13 2 9.74l5.46 4.73-1.64 7.03L12 17.77l6.18 3.73-1.63-7.03L22 9.74zM12 15.9V6.6l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.9z"/></g> +<g id="star-outline"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"/></g> +<g id="star-rate"><path d="M12 14.3l3.71 2.7-1.42-4.36L18 10h-4.55L12 5.5 10.55 10H6l3.71 2.64L8.29 17z"/></g> +<g id="stars"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zm4.24 16L12 15.45 7.77 18l1.12-4.81-3.73-3.23 4.92-.42L12 5l1.92 4.53 4.92.42-3.73 3.23L16.23 18z"/></g> +<g id="store"><path d="M20 4H4v2h16V4zm1 10v-2l-1-5H4l-1 5v2h1v6h10v-6h4v6h2v-6h1zm-9 4H6v-4h6v4z"/></g> +<g id="subject"><path d="M14 17H4v2h10v-2zm6-8H4v2h16V9zM4 15h16v-2H4v2zM4 5v2h16V5H4z"/></g> +<g id="supervisor-account"><path d="M16.5 12c1.38 0 2.49-1.12 2.49-2.5S17.88 7 16.5 7C15.12 7 14 8.12 14 9.5s1.12 2.5 2.5 2.5zM9 11c1.66 0 2.99-1.34 2.99-3S10.66 5 9 5C7.34 5 6 6.34 6 8s1.34 3 3 3zm7.5 3c-1.83 0-5.5.92-5.5 2.75V19h11v-2.25c0-1.83-3.67-2.75-5.5-2.75zM9 13c-2.33 0-7 1.17-7 3.5V19h7v-2.25c0-.85.33-2.34 2.37-3.47C10.5 13.1 9.66 13 9 13z"/></g> +<g id="swap-horiz"><path d="M6.99 11L3 15l3.99 4v-3H14v-2H6.99v-3zM21 9l-3.99-4v3H10v2h7.01v3L21 9z"/></g> +<g id="swap-vert"><path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3V14h2V6.99h3L9 3z"/></g> +<g id="swap-vert-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM6.5 9L10 5.5 13.5 9H11v4H9V9H6.5zm11 6L14 18.5 10.5 15H13v-4h2v4h2.5z"/></g> +<g id="system-update-tv"><path d="M12 16.5l4-4h-3v-9h-2v9H8l4 4zm9-13h-6v1.99h6v14.03H3V5.49h6V3.5H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2v-14c0-1.1-.9-2-2-2z"/></g> +<g id="tab"><path d="M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h10v4h8v10z"/></g> +<g id="tab-unselected"><path d="M1 9h2V7H1v2zm0 4h2v-2H1v2zm0-8h2V3c-1.1 0-2 .9-2 2zm8 16h2v-2H9v2zm-8-4h2v-2H1v2zm2 4v-2H1c0 1.1.9 2 2 2zM21 3h-8v6h10V5c0-1.1-.9-2-2-2zm0 14h2v-2h-2v2zM9 5h2V3H9v2zM5 21h2v-2H5v2zM5 5h2V3H5v2zm16 16c1.1 0 2-.9 2-2h-2v2zm0-8h2v-2h-2v2zm-8 8h2v-2h-2v2zm4 0h2v-2h-2v2z"/></g> +<g id="text-format"><path d="M5 17v2h14v-2H5zm4.5-4.2h5l.9 2.2h2.1L12.75 4h-1.5L6.5 15h2.1l.9-2.2zM12 5.98L13.87 11h-3.74L12 5.98z"/></g> +<g id="theaters"><path d="M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8 17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h2v2z"/></g> +<g id="thumb-down"><path d="M15 3H6c-.83 0-1.54.5-1.84 1.22l-3.02 7.05c-.09.23-.14.47-.14.73v1.91l.01.01L1 14c0 1.1.9 2 2 2h6.31l-.95 4.57-.03.32c0 .41.17.79.44 1.06L9.83 23l6.59-6.59c.36-.36.58-.86.58-1.41V5c0-1.1-.9-2-2-2zm4 0v12h4V3h-4z"/></g> +<g id="thumb-up"><path d="M1 21h4V9H1v12zm22-11c0-1.1-.9-2-2-2h-6.31l.95-4.57.03-.32c0-.41-.17-.79-.44-1.06L14.17 1 7.59 7.59C7.22 7.95 7 8.45 7 9v10c0 1.1.9 2 2 2h9c.83 0 1.54-.5 1.84-1.22l3.02-7.05c.09-.23.14-.47.14-.73v-1.91l-.01-.01L23 10z"/></g> +<g id="thumbs-up-down"><path d="M12 6c0-.55-.45-1-1-1H5.82l.66-3.18.02-.23c0-.31-.13-.59-.33-.8L5.38 0 .44 4.94C.17 5.21 0 5.59 0 6v6.5c0 .83.67 1.5 1.5 1.5h6.75c.62 0 1.15-.38 1.38-.91l2.26-5.29c.07-.17.11-.36.11-.55V6zm10.5 4h-6.75c-.62 0-1.15.38-1.38.91l-2.26 5.29c-.07.17-.11.36-.11.55V18c0 .55.45 1 1 1h5.18l-.66 3.18-.02.24c0 .31.13.59.33.8l.79.78 4.94-4.94c.27-.27.44-.65.44-1.06v-6.5c0-.83-.67-1.5-1.5-1.5z"/></g> +<g id="toc"><path d="M3 9h14V7H3v2zm0 4h14v-2H3v2zm0 4h14v-2H3v2zm16 0h2v-2h-2v2zm0-10v2h2V7h-2zm0 6h2v-2h-2v2z"/></g> +<g id="today"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zM7 10h5v5H7z"/></g> +<g id="track-changes"><path fill="#231F20" d="M19.07 4.93l-1.41 1.41C19.1 7.79 20 9.79 20 12c0 4.42-3.58 8-8 8s-8-3.58-8-8c0-4.08 3.05-7.44 7-7.93v2.02C8.16 6.57 6 9.03 6 12c0 3.31 2.69 6 6 6s6-2.69 6-6c0-1.66-.67-3.16-1.76-4.24l-1.41 1.41C15.55 9.9 16 10.9 16 12c0 2.21-1.79 4-4 4s-4-1.79-4-4c0-1.86 1.28-3.41 3-3.86v2.14c-.6.35-1 .98-1 1.72 0 1.1.9 2 2 2s2-.9 2-2c0-.74-.4-1.38-1-1.72V2h-1C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10c0-2.76-1.12-5.26-2.93-7.07z"/></g> +<g id="translate"><path d="M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"/></g> +<g id="trending-down"><path d="M16 18l2.29-2.29-4.88-4.88-4 4L2 7.41 3.41 6l6 6 4-4 6.3 6.29L22 12v6z"/></g> +<g id="trending-neutral"><path d="M22 12l-4-4v3H3v2h15v3z"/></g> +<g id="trending-up"><path d="M16 6l2.29 2.29-4.88 4.88-4-4L2 16.59 3.41 18l6-6 4 4 6.3-6.29L22 12V6z"/></g> +<g id="turned-in"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2z"/></g> +<g id="turned-in-not"><path d="M17 3H7c-1.1 0-1.99.9-1.99 2L5 21l7-3 7 3V5c0-1.1-.9-2-2-2zm0 15l-5-2.18L7 18V5h10v13z"/></g> +<g id="undo"><path d="M12.5 8c-2.65 0-5.05.99-6.9 2.6L2 7v9h9l-3.62-3.62c1.39-1.16 3.16-1.88 5.12-1.88 3.54 0 6.55 2.31 7.6 5.5l2.37-.78C21.08 11.03 17.15 8 12.5 8z"/></g> +<g id="unfold-less"><path d="M7.41 18.59L8.83 20 12 16.83 15.17 20l1.41-1.41L12 14l-4.59 4.59zm9.18-13.18L15.17 4 12 7.17 8.83 4 7.41 5.41 12 10l4.59-4.59z"/></g> +<g id="unfold-more"><path d="M12 5.83L15.17 9l1.41-1.41L12 3 7.41 7.59 8.83 9 12 5.83zm0 12.34L8.83 15l-1.41 1.41L12 21l4.59-4.59L15.17 15 12 18.17z"/></g> +<g id="verified-user"><path d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm-2 16l-4-4 1.41-1.41L10 14.17l6.59-6.59L18 9l-8 8z"/></g> +<g id="view-agenda"><path d="M20 13H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1v-6c0-.55-.45-1-1-1zm0-10H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1z"/></g> +<g id="view-array"><path d="M4 18h3V5H4v13zM18 5v13h3V5h-3zM8 18h9V5H8v13z"/></g> +<g id="view-carousel"><path d="M7 19h10V4H7v15zm-5-2h4V6H2v11zM18 6v11h4V6h-4z"/></g> +<g id="view-column"><path d="M10 18h5V5h-5v13zm-6 0h5V5H4v13zM16 5v13h5V5h-5z"/></g> +<g id="view-day"><path d="M2 21h19v-3H2v3zM20 8H3c-.55 0-1 .45-1 1v6c0 .55.45 1 1 1h17c.55 0 1-.45 1-1V9c0-.55-.45-1-1-1zM2 3v3h19V3H2z"/></g> +<g id="view-headline"><path d="M4 15h17v-2H4v2zm0 4h17v-2H4v2zm0-8h17V9H4v2zm0-6v2h17V5H4z"/></g> +<g id="view-list"><path d="M4 14h4v-4H4v4zm0 5h4v-4H4v4zM4 9h4V5H4v4zm5 5h12v-4H9v4zm0 5h12v-4H9v4zM9 5v4h12V5H9z"/></g> +<g id="view-module"><path d="M4 11h5V5H4v6zm0 7h5v-6H4v6zm6 0h5v-6h-5v6zm6 0h5v-6h-5v6zm-6-7h5V5h-5v6zm6-6v6h5V5h-5z"/></g> +<g id="view-quilt"><path d="M10 18h5v-6h-5v6zm-6 0h5V5H4v13zm12 0h5v-6h-5v6zM10 5v6h11V5H10z"/></g> +<g id="view-stream"><path d="M4 18h17v-6H4v6zM4 5v6h17V5H4z"/></g> +<g id="view-week"><path d="M6 5H3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zm14 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zm-7 0h-3c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h3c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1z"/></g> +<g id="visibility"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></g> +<g id="visibility-off"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/></g> +<g id="wallet-giftcard"><path d="M20 6h-2.18c.11-.31.18-.65.18-1 0-1.66-1.34-3-3-3-1.05 0-1.96.54-2.5 1.35l-.5.67-.5-.68C10.96 2.54 10.05 2 9 2 7.34 2 6 3.34 6 5c0 .35.07.69.18 1H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-5-2c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM9 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm11 15H4v-2h16v2zm0-5H4V8h5.08L7 10.83 8.62 12 11 8.76l1-1.36 1 1.36L15.38 12 17 10.83 14.92 8H20v6z"/></g> +<g id="wallet-membership"><path d="M20 2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h4v5l4-2 4 2v-5h4c1.11 0 2-.89 2-2V4c0-1.11-.89-2-2-2zm0 13H4v-2h16v2zm0-5H4V4h16v6z"/></g> +<g id="wallet-travel"><path d="M20 6h-3V4c0-1.11-.89-2-2-2H9c-1.11 0-2 .89-2 2v2H4c-1.11 0-2 .89-2 2v11c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM9 4h6v2H9V4zm11 15H4v-2h16v2zm0-5H4V8h3v2h2V8h6v2h2V8h3v6z"/></g> +<g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></g> +<g id="work"><path d="M20 6h-4V4c0-1.11-.89-2-2-2h-4c-1.11 0-2 .89-2 2v2H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zm-6 0h-4V4h4v2z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/maps-icons.html b/third_party/polymer/v0_8/components/iron-icons/maps-icons.html new file mode 100644 index 0000000..2fbbce3 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/maps-icons.html
@@ -0,0 +1,70 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="maps" size="24"> +<svg><defs> +<g id="beenhere"><path d="M19 1H5c-1.1 0-1.99.9-1.99 2L3 15.93c0 .69.35 1.3.88 1.66L12 23l8.11-5.41c.53-.36.88-.97.88-1.66L21 3c0-1.1-.9-2-2-2zm-9 15l-5-5 1.41-1.41L10 13.17l7.59-7.59L19 7l-9 9z"/></g> +<g id="directions"><path d="M21.71 11.29l-9-9c-.39-.39-1.02-.39-1.41 0l-9 9c-.39.39-.39 1.02 0 1.41l9 9c.39.39 1.02.39 1.41 0l9-9c.39-.38.39-1.01 0-1.41zM14 14.5V12h-4v3H8v-4c0-.55.45-1 1-1h5V7.5l3.5 3.5-3.5 3.5z"/></g> +<g id="directions-bike"><path d="M16 4.8c.99 0 1.8-.81 1.8-1.8s-.81-1.8-1.8-1.8c-1 0-1.8.81-1.8 1.8S15 4.8 16 4.8zm3 7.2c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0 8.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5zM14.8 10H19V8.2h-3.2l-1.93-3.27c-.3-.5-.84-.83-1.46-.83-.47 0-.89.19-1.2.5l-3.7 3.7c-.32.3-.51.73-.51 1.2 0 .63.33 1.16.85 1.47L11.2 13v5H13v-6.48l-2.25-1.67 2.32-2.33L14.8 10zM5 12c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5zm0 8.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></g> +<g id="directions-bus"><path d="M4 16c0 .88.39 1.67 1 2.22V20c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h8v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1.78c.61-.55 1-1.34 1-2.22V6c0-3.5-3.58-4-8-4s-8 .5-8 4v10zm3.5 1c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm9 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6H6V6h12v5z"/></g> +<g id="directions-car"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5h-11c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/></g> +<g id="directions-ferry"><path d="M20 21c-1.39 0-2.78-.47-4-1.32-2.44 1.71-5.56 1.71-8 0C6.78 20.53 5.39 21 4 21H2v2h2c1.38 0 2.74-.35 4-.99 2.52 1.29 5.48 1.29 8 0 1.26.65 2.62.99 4 .99h2v-2h-2zM3.95 19H4c1.6 0 3.02-.88 4-2 .98 1.12 2.4 2 4 2s3.02-.88 4-2c.98 1.12 2.4 2 4 2h.05l1.89-6.68c.08-.26.06-.54-.06-.78s-.34-.42-.6-.5L20 10.62V6c0-1.1-.9-2-2-2h-3V1H9v3H6c-1.1 0-2 .9-2 2v4.62l-1.29.42c-.26.08-.48.26-.6.5s-.15.52-.06.78L3.95 19zM6 6h12v3.97L12 8 6 9.97V6z"/></g> +<g id="directions-subway"><path d="M12 2c-4.42 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-3.58-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/></g> +<g id="directions-train"><path d="M4 15.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V5c0-3.5-3.58-4-8-4s-8 .5-8 4v10.5zm8 1.5c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm6-7H6V5h12v5z"/></g> +<g id="directions-transit"><path d="M12 2c-4.42 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h12v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-3.58-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/></g> +<g id="directions-walk"><path d="M14 3.8c.99 0 1.8-.81 1.8-1.8 0-1-.81-1.8-1.8-1.8-1 0-1.8.81-1.8 1.8S13 3.8 14 3.8zm.12 6.2H19V8.2h-3.62l-2-3.33c-.3-.5-.84-.83-1.46-.83-.17 0-.34.03-.49.07L6 5.8V11h1.8V7.33l2.11-.66L6 22h1.8l2.87-8.11L13 17v5h1.8v-6.41l-2.49-4.54.73-2.87L14.12 10z"/></g> +<g id="flight"><path d="M10.18 9"/><path d="M21 16v-2l-8-5V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5l8 2.5z"/></g> +<g id="hotel"><path d="M7 13c1.66 0 3-1.34 3-3S8.66 7 7 7s-3 1.34-3 3 1.34 3 3 3zm12-6h-8v7H3V5H1v15h2v-3h18v3h2v-9c0-2.21-1.79-4-4-4z"/></g> +<g id="layers"><path d="M11.99 18.54l-7.37-5.73L3 14.07l9 7 9-7-1.63-1.27-7.38 5.74zM12 16l7.36-5.73L21 9l-9-7-9 7 1.63 1.27L12 16z"/></g> +<g id="layers-clear"><path d="M19.81 14.99l1.19-.92-1.43-1.43-1.19.92 1.43 1.43zm-.45-4.72L21 9l-9-7-2.91 2.27 7.87 7.88 2.4-1.88zM3.27 1L2 2.27l4.22 4.22L3 9l1.63 1.27L12 16l2.1-1.63 1.43 1.43L12 18.54l-7.37-5.73L3 14.07l9 7 4.95-3.85L20.73 21 22 19.73 3.27 1z"/></g> +<g id="local-airport"><path d="M21 16v-2l-8-5V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1 3.5 1v-1.5L13 19v-5.5l8 2.5z"/></g> +<g id="local-atm"><path d="M11 17h2v-1h1c.55 0 1-.45 1-1v-3c0-.55-.45-1-1-1h-3v-1h4V8h-2V7h-2v1h-1c-.55 0-1 .45-1 1v3c0 .55.45 1 1 1h3v1H9v2h2v1zm9-13H4c-1.11 0-1.99.89-1.99 2L2 18c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V6c0-1.11-.89-2-2-2zm0 14H4V6h16v12z"/></g> +<g id="local-attraction"><path d="M20 12c0-1.1.9-2 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-1.99.9-1.99 2v4c1.1 0 1.99.9 1.99 2s-.89 2-2 2v4c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2v-4c-1.1 0-2-.9-2-2zm-4.42 4.8L12 14.5l-3.58 2.3 1.08-4.12-3.29-2.69 4.24-.25L12 5.8l1.54 3.95 4.24.25-3.29 2.69 1.09 4.11z"/></g> +<g id="local-bar"><path d="M11 13v6H6v2h12v-2h-5v-6l8-8V3H3v2l8 8zM7.5 7l-2-2h13l-2 2h-9z"/></g> +<g id="local-cafe"><path d="M20 3H4v10c0 2.21 1.79 4 4 4h6c2.21 0 4-1.79 4-4v-3h2c1.11 0 2-.89 2-2V5c0-1.11-.89-2-2-2zm0 5h-2V5h2v3zM2 21h18v-2H2v2z"/></g> +<g id="local-car-wash"><path d="M17 5c.83 0 1.5-.67 1.5-1.5 0-1-1.5-2.7-1.5-2.7s-1.5 1.7-1.5 2.7c0 .83.67 1.5 1.5 1.5zm-5 0c.83 0 1.5-.67 1.5-1.5 0-1-1.5-2.7-1.5-2.7s-1.5 1.7-1.5 2.7c0 .83.67 1.5 1.5 1.5zM7 5c.83 0 1.5-.67 1.5-1.5C8.5 2.5 7 .8 7 .8S5.5 2.5 5.5 3.5C5.5 4.33 6.17 5 7 5zm11.92 3.01C18.72 7.42 18.16 7 17.5 7h-11c-.66 0-1.21.42-1.42 1.01L3 14v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 18c-.83 0-1.5-.67-1.5-1.5S5.67 15 6.5 15s1.5.67 1.5 1.5S7.33 18 6.5 18zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 13l1.5-4.5h11L19 13H5z"/></g> +<g id="local-convenience-store"><path d="M19 7V4H5v3H2v13h8v-4h4v4h8V7h-3zm-8 3H9v1h2v1H8V9h2V8H8V7h3v3zm5 2h-1v-2h-2V7h1v2h1V7h1v5z"/></g> +<g id="local-drink"><path d="M3 2l2.01 18.23C5.13 21.23 5.97 22 7 22h10c1.03 0 1.87-.77 1.99-1.77L21 2H3zm9 17c-1.66 0-3-1.34-3-3 0-2 3-5.4 3-5.4s3 3.4 3 5.4c0 1.66-1.34 3-3 3zm6.33-11H5.67l-.44-4h13.53l-.43 4z"/></g> +<g id="local-florist"><path d="M12 22c4.97 0 9-4.03 9-9-4.97 0-9 4.03-9 9zM5.6 10.25c0 1.38 1.12 2.5 2.5 2.5.53 0 1.01-.16 1.42-.44l-.02.19c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5l-.02-.19c.4.28.89.44 1.42.44 1.38 0 2.5-1.12 2.5-2.5 0-1-.59-1.85-1.43-2.25.84-.4 1.43-1.25 1.43-2.25 0-1.38-1.12-2.5-2.5-2.5-.53 0-1.01.16-1.42.44l.02-.19C14.5 2.12 13.38 1 12 1S9.5 2.12 9.5 3.5l.02.19c-.4-.28-.89-.44-1.42-.44-1.38 0-2.5 1.12-2.5 2.5 0 1 .59 1.85 1.43 2.25-.84.4-1.43 1.25-1.43 2.25zM12 5.5c1.38 0 2.5 1.12 2.5 2.5s-1.12 2.5-2.5 2.5S9.5 9.38 9.5 8s1.12-2.5 2.5-2.5zM3 13c0 4.97 4.03 9 9 9 0-4.97-4.03-9-9-9z"/></g> +<g id="local-gas-station"><path d="M19.77 7.23l.01-.01-3.72-3.72L15 4.56l2.11 2.11c-.94.36-1.61 1.26-1.61 2.33 0 1.38 1.12 2.5 2.5 2.5.36 0 .69-.08 1-.21v7.21c0 .55-.45 1-1 1s-1-.45-1-1V14c0-1.1-.9-2-2-2h-1V5c0-1.1-.9-2-2-2H6c-1.1 0-2 .9-2 2v16h10v-7.5h1.5v5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V9c0-.69-.28-1.32-.73-1.77zM12 10H6V5h6v5zm6 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></g> +<g id="local-grocery-store"><path d="M7 18c-1.1 0-1.99.9-1.99 2S5.9 22 7 22s2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12.9-1.63h7.45c.75 0 1.41-.41 1.75-1.03l3.58-6.49c.08-.14.12-.31.12-.48 0-.55-.45-1-1-1H5.21l-.94-2H1zm16 16c-1.1 0-1.99.9-1.99 2s.89 2 1.99 2 2-.9 2-2-.9-2-2-2z"/></g> +<g id="local-hospital"><path d="M19 3H5c-1.1 0-1.99.9-1.99 2L3 19c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 11h-4v4h-4v-4H6v-4h4V6h4v4h4v4z"/></g> +<g id="local-hotel"><path d="M7 13c1.66 0 3-1.34 3-3S8.66 7 7 7s-3 1.34-3 3 1.34 3 3 3zm12-6h-8v7H3V5H1v15h2v-3h18v3h2v-9c0-2.21-1.79-4-4-4z"/></g> +<g id="local-laundry-service"><path d="M9.17 16.83c1.56 1.56 4.1 1.56 5.66 0 1.56-1.56 1.56-4.1 0-5.66l-5.66 5.66zM18 2.01L6 2c-1.11 0-2 .89-2 2v16c0 1.11.89 2 2 2h12c1.11 0 2-.89 2-2V4c0-1.11-.89-1.99-2-1.99zM10 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zM7 4c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm5 16c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6z"/></g> +<g id="local-library"><path d="M12 11.55C9.64 9.35 6.48 8 3 8v11c3.48 0 6.64 1.35 9 3.55 2.36-2.19 5.52-3.55 9-3.55V8c-3.48 0-6.64 1.35-9 3.55zM12 8c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3z"/></g> +<g id="local-mall"><path d="M19 6h-2c0-2.76-2.24-5-5-5S7 3.24 7 6H5c-1.1 0-1.99.9-1.99 2L3 20c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-7-3c1.66 0 3 1.34 3 3H9c0-1.66 1.34-3 3-3zm0 10c-2.76 0-5-2.24-5-5h2c0 1.66 1.34 3 3 3s3-1.34 3-3h2c0 2.76-2.24 5-5 5z"/></g> +<g id="local-movies"><path d="M18 3v2h-2V3H8v2H6V3H4v18h2v-2h2v2h8v-2h2v2h2V3h-2zM8 17H6v-2h2v2zm0-4H6v-2h2v2zm0-4H6V7h2v2zm10 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V7h2v2z"/></g> +<g id="local-offer"><path d="M21.41 11.58l-9-9C12.05 2.22 11.55 2 11 2H4c-1.1 0-2 .9-2 2v7c0 .55.22 1.05.59 1.42l9 9c.36.36.86.58 1.41.58.55 0 1.05-.22 1.41-.59l7-7c.37-.36.59-.86.59-1.41 0-.55-.23-1.06-.59-1.42zM5.5 7C4.67 7 4 6.33 4 5.5S4.67 4 5.5 4 7 4.67 7 5.5 6.33 7 5.5 7z"/></g> +<g id="local-parking"><path d="M13 3H6v18h4v-6h3c3.31 0 6-2.69 6-6s-2.69-6-6-6zm.2 8H10V7h3.2c1.1 0 2 .9 2 2s-.9 2-2 2z"/></g> +<g id="local-pharmacy"><path d="M21 5h-2.64l1.14-3.14L17.15 1l-1.46 4H3v2l2 6-2 6v2h18v-2l-2-6 2-6V5zm-5 9h-3v3h-2v-3H8v-2h3V9h2v3h3v2z"/></g> +<g id="local-phone"><path d="M6.62 10.79c1.44 2.83 3.76 5.14 6.59 6.59l2.2-2.2c.27-.27.67-.36 1.02-.24 1.12.37 2.33.57 3.57.57.55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17 0-.55.45-1 1-1h3.5c.55 0 1 .45 1 1 0 1.25.2 2.45.57 3.57.11.35.03.74-.25 1.02l-2.2 2.2z"/></g> +<g id="local-pizza"><path d="M12 2C8.43 2 5.23 3.54 3.01 6L12 22l8.99-16C18.78 3.55 15.57 2 12 2zM7 7c0-1.1.9-2 2-2s2 .9 2 2-.9 2-2 2-2-.9-2-2zm5 8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="local-play"><path d="M20 12c0-1.1.9-2 2-2V6c0-1.1-.9-2-2-2H4c-1.1 0-1.99.9-1.99 2v4c1.1 0 1.99.9 1.99 2s-.89 2-2 2v4c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2v-4c-1.1 0-2-.9-2-2zm-4.42 4.8L12 14.5l-3.58 2.3 1.08-4.12-3.29-2.69 4.24-.25L12 5.8l1.54 3.95 4.24.25-3.29 2.69 1.09 4.11z"/></g> +<g id="local-post-office"><path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z"/></g> +<g id="local-print-shop"><path d="M19 8H5c-1.66 0-3 1.34-3 3v6h4v4h12v-4h4v-6c0-1.66-1.34-3-3-3zm-3 11H8v-5h8v5zm3-7c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm-1-9H6v4h12V3z"/></g> +<g id="local-restaurant"><path d="M8.1 13.34l2.83-2.83L3.91 3.5c-1.56 1.56-1.56 4.09 0 5.66l4.19 4.18zm6.78-1.81c1.53.71 3.68.21 5.27-1.38 1.91-1.91 2.28-4.65.81-6.12-1.46-1.46-4.2-1.1-6.12.81-1.59 1.59-2.09 3.74-1.38 5.27L3.7 19.87l1.41 1.41L12 14.41l6.88 6.88 1.41-1.41L13.41 13l1.47-1.47z"/></g> +<g id="local-see"><circle cx="12" cy="12" r="3.2"/><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"/></g> +<g id="local-shipping"><path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2c0 1.66 1.34 3 3 3s3-1.34 3-3h6c0 1.66 1.34 3 3 3s3-1.34 3-3h2v-5l-3-4zM6 18.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm13.5-9l1.96 2.5H17V9.5h2.5zm-1.5 9c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="local-taxi"><path d="M18.92 6.01C18.72 5.42 18.16 5 17.5 5H15V3H9v2H6.5c-.66 0-1.21.42-1.42 1.01L3 12v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 16c-.83 0-1.5-.67-1.5-1.5S5.67 13 6.5 13s1.5.67 1.5 1.5S7.33 16 6.5 16zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 11l1.5-4.5h11L19 11H5z"/></g> +<g id="location-history"><path d="M19 2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h4l3 3 3-3h4c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 3.3c1.49 0 2.7 1.21 2.7 2.7 0 1.49-1.21 2.7-2.7 2.7-1.49 0-2.7-1.21-2.7-2.7 0-1.49 1.21-2.7 2.7-2.7zM18 16H6v-.9c0-2 4-3.1 6-3.1s6 1.1 6 3.1v.9z"/></g> +<g id="map"><path d="M20.5 3l-.16.03L15 5.1 9 3 3.36 4.9c-.21.07-.36.25-.36.48V20.5c0 .28.22.5.5.5l.16-.03L9 18.9l6 2.1 5.64-1.9c.21-.07.36-.25.36-.48V3.5c0-.28-.22-.5-.5-.5zM15 19l-6-2.11V5l6 2.11V19z"/></g> +<g id="my-location"><path d="M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2h-2.06zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7z"/></g> +<g id="navigation"><path d="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71z"/></g> +<g id="pin-drop"><path d="M18 8c0-3.31-2.69-6-6-6S6 4.69 6 8c0 4.5 6 11 6 11s6-6.5 6-11zm-8 0c0-1.1.9-2 2-2s2 .9 2 2-.89 2-2 2c-1.1 0-2-.9-2-2zM5 20v2h14v-2H5z"/></g> +<g id="place"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></g> +<g id="rate-review"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 14v-2.47l6.88-6.88c.2-.2.51-.2.71 0l1.77 1.77c.2.2.2.51 0 .71L8.47 14H6zm12 0h-7.5l2-2H18v2z"/></g> +<g id="restaurant-menu"><path d="M8.1 13.34l2.83-2.83L3.91 3.5c-1.56 1.56-1.56 4.09 0 5.66l4.19 4.18zm6.78-1.81c1.53.71 3.68.21 5.27-1.38 1.91-1.91 2.28-4.65.81-6.12-1.46-1.46-4.2-1.1-6.12.81-1.59 1.59-2.09 3.74-1.38 5.27L3.7 19.87l1.41 1.41L12 14.41l6.88 6.88 1.41-1.41L13.41 13l1.47-1.47z"/></g> +<g id="satellite"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM5 4.99h3C8 6.65 6.66 8 5 8V4.99zM5 12v-2c2.76 0 5-2.25 5-5.01h2C12 8.86 8.87 12 5 12zm0 6l3.5-4.5 2.5 3.01L14.5 12l4.5 6H5z"/></g> +<g id="store-mall-directory"><path d="M20 4H4v2h16V4zm1 10v-2l-1-5H4l-1 5v2h1v6h10v-6h4v6h2v-6h1zm-9 4H6v-4h6v4z"/></g> +<g id="terrain"><path d="M14 6l-3.75 5 2.85 3.8-1.6 1.2C9.81 13.75 7 10 7 10l-6 8h22L14 6z"/></g> +<g id="traffic"><path d="M20 10h-3V8.86c1.72-.45 3-2 3-3.86h-3V4c0-.55-.45-1-1-1H8c-.55 0-1 .45-1 1v1H4c0 1.86 1.28 3.41 3 3.86V10H4c0 1.86 1.28 3.41 3 3.86V15H4c0 1.86 1.28 3.41 3 3.86V20c0 .55.45 1 1 1h8c.55 0 1-.45 1-1v-1.14c1.72-.45 3-2 3-3.86h-3v-1.14c1.72-.45 3-2 3-3.86zm-8 9c-1.11 0-2-.9-2-2s.89-2 2-2c1.1 0 2 .9 2 2s-.89 2-2 2zm0-5c-1.11 0-2-.9-2-2s.89-2 2-2c1.1 0 2 .9 2 2s-.89 2-2 2zm0-5c-1.11 0-2-.9-2-2 0-1.11.89-2 2-2 1.1 0 2 .89 2 2 0 1.1-.89 2-2 2z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/notification-icons.html b/third_party/polymer/v0_8/components/iron-icons/notification-icons.html new file mode 100644 index 0000000..62712516 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/notification-icons.html
@@ -0,0 +1,49 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="notification" size="24"> +<svg><defs> +<g id="adb"><path d="M5 16c0 3.87 3.13 7 7 7s7-3.13 7-7v-4H5v4zM16.12 4.37l2.1-2.1-.82-.83-2.3 2.31C14.16 3.28 13.12 3 12 3s-2.16.28-3.09.75L6.6 1.44l-.82.83 2.1 2.1C6.14 5.64 5 7.68 5 10v1h14v-1c0-2.32-1.14-4.36-2.88-5.63zM9 9c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1zm6 0c-.55 0-1-.45-1-1s.45-1 1-1 1 .45 1 1-.45 1-1 1z"/></g> +<g id="bluetooth-audio"><path d="M14.24 12.01l2.32 2.32c.28-.72.44-1.51.44-2.33 0-.82-.16-1.59-.43-2.31l-2.33 2.32zm5.29-5.3l-1.26 1.26c.63 1.21.98 2.57.98 4.02s-.36 2.82-.98 4.02l1.2 1.2c.97-1.54 1.54-3.36 1.54-5.31-.01-1.89-.55-3.67-1.48-5.19zm-3.82 1L10 2H9v7.59L4.41 5 3 6.41 8.59 12 3 17.59 4.41 19 9 14.41V22h1l5.71-5.71-4.3-4.29 4.3-4.29zM11 5.83l1.88 1.88L11 9.59V5.83zm1.88 10.46L11 18.17v-3.76l1.88 1.88z"/></g> +<g id="disc-full"><path d="M20 16h2v-2h-2v2zm0-9v5h2V7h-2zM10 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm0 10c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/></g> +<g id="dnd-forwardslash"><path d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10 10-4.5 10-10S17.5 2 12 2zM4 12c0-4.4 3.6-8 8-8 1.8 0 3.5.6 4.9 1.7L5.7 16.9C4.6 15.5 4 13.8 4 12zm8 8c-1.8 0-3.5-.6-4.9-1.7L18.3 7.1C19.4 8.5 20 10.2 20 12c0 4.4-3.6 8-8 8z"/></g> +<g id="do-not-disturb"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8 0-1.85.63-3.55 1.69-4.9L16.9 18.31C15.55 19.37 13.85 20 12 20zm6.31-3.1L7.1 5.69C8.45 4.63 10.15 4 12 4c4.42 0 8 3.58 8 8 0 1.85-.63 3.55-1.69 4.9z"/></g> +<g id="drive-eta"><path d="M18.92 5.01C18.72 4.42 18.16 4 17.5 4h-11c-.66 0-1.21.42-1.42 1.01L3 11v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 15c-.83 0-1.5-.67-1.5-1.5S5.67 12 6.5 12s1.5.67 1.5 1.5S7.33 15 6.5 15zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 10l1.5-4.5h11L19 10H5z"/></g> +<g id="event-available"><path d="M16.53 11.06L15.47 10l-4.88 4.88-2.12-2.12-1.06 1.06L10.59 17l5.94-5.94zM19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z"/></g> +<g id="event-busy"><path d="M9.31 17l2.44-2.44L14.19 17l1.06-1.06-2.44-2.44 2.44-2.44L14.19 10l-2.44 2.44L9.31 10l-1.06 1.06 2.44 2.44-2.44 2.44L9.31 17zM19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z"/></g> +<g id="event-note"><path d="M17 10H7v2h10v-2zm2-7h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11zm-5-5H7v2h7v-2z"/></g> +<g id="folder-special"><path d="M20 6h-8l-2-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm-6.42 12L10 15.9 6.42 18l.95-4.07-3.16-2.74 4.16-.36L10 7l1.63 3.84 4.16.36-3.16 2.74.95 4.06z"/></g> +<g id="mms"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM5 14l3.5-4.5 2.5 3.01L14.5 8l4.5 6H5z"/></g> +<g id="more"><path d="M22 3H7c-.69 0-1.23.35-1.59.88L0 12l5.41 8.11c.36.53.97.89 1.66.89H22c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 13.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm5 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm5 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></g> +<g id="network-locked"><path d="M19.5 10c.17 0 .33.03.5.05V1L1 20h13v-3c0-.89.39-1.68 1-2.23v-.27c0-2.48 2.02-4.5 4.5-4.5zm2.5 6v-1.5c0-1.38-1.12-2.5-2.5-2.5S17 13.12 17 14.5V16c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1v-4c0-.55-.45-1-1-1zm-1 0h-3v-1.5c0-.83.67-1.5 1.5-1.5s1.5.67 1.5 1.5V16z"/></g> +<g id="phone-bluetooth-speaker"><path d="M14.71 9.5L17 7.21V11h.5l2.85-2.85L18.21 6l2.15-2.15L17.5 1H17v3.79L14.71 2.5l-.71.71L16.79 6 14 8.79l.71.71zM18 2.91l.94.94-.94.94V2.91zm0 4.3l.94.94-.94.94V7.21zm2 8.29c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></g> +<g id="phone-forwarded"><path d="M18 11l5-5-5-5v3h-4v4h4v3zm2 4.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1z"/></g> +<g id="phone-in-talk"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 12h2c0-4.97-4.03-9-9-9v2c3.87 0 7 3.13 7 7zm-4 0h2c0-2.76-2.24-5-5-5v2c1.66 0 3 1.34 3 3z"/></g> +<g id="phone-locked"><path d="M20 15.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM20 4v-.5C20 2.12 18.88 1 17.5 1S15 2.12 15 3.5V4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-.8 0h-3.4v-.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V4z"/></g> +<g id="phone-missed"><path d="M6.5 5.5L12 11l7-7-1-1-6 6-4.5-4.5H11V3H5v6h1.5V5.5zm17.21 11.17C20.66 13.78 16.54 12 12 12 7.46 12 3.34 13.78.29 16.67c-.18.18-.29.43-.29.71s.11.53.29.71l2.48 2.48c.18.18.43.29.71.29.27 0 .52-.11.7-.28.79-.74 1.69-1.36 2.66-1.85.33-.16.56-.5.56-.9v-3.1c1.45-.48 3-.73 4.6-.73 1.6 0 3.15.25 4.6.72v3.1c0 .39.23.74.56.9.98.49 1.87 1.12 2.67 1.85.18.18.43.28.7.28.28 0 .53-.11.71-.29l2.48-2.48c.18-.18.29-.43.29-.71s-.12-.52-.3-.7z"/></g> +<g id="phone-paused"><path d="M17 3h-2v7h2V3zm3 12.5c-1.25 0-2.45-.2-3.57-.57-.35-.11-.74-.03-1.02.24l-2.2 2.2c-2.83-1.44-5.15-3.75-6.59-6.59l2.2-2.21c.28-.26.36-.65.25-1C8.7 6.45 8.5 5.25 8.5 4c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1 0 9.39 7.61 17 17 17 .55 0 1-.45 1-1v-3.5c0-.55-.45-1-1-1zM19 3v7h2V3h-2z"/></g> +<g id="play-download"><path d="M20 6h-4V4l-2-2h-4L8 4v2H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM10 4h4v2h-4V4zm2 15l-5-5h3v-4h4v4h3l-5 5z"/></g> +<g id="play-install"><path d="M20 6h-4V4l-2-2h-4L8 4v2H4c-1.11 0-1.99.89-1.99 2L2 19c0 1.11.89 2 2 2h16c1.11 0 2-.89 2-2V8c0-1.11-.89-2-2-2zM10 4h4v2h-4V4zm.5 13.5L7 14l1.41-1.41 2.09 2.09 5.18-5.18 1.41 1.41-6.59 6.59z"/></g> +<g id="sd-card"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-6 6h-2V4h2v4zm3 0h-2V4h2v4zm3 0h-2V4h2v4z"/></g> +<g id="sim-card-alert"><path d="M18 2h-8L4.02 8 4 20c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-5 15h-2v-2h2v2zm0-4h-2V8h2v5z"/></g> +<g id="sms"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM9 11H7V9h2v2zm4 0h-2V9h2v2zm4 0h-2V9h2v2z"/></g> +<g id="sms-failed"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-7 12h-2v-2h2v2zm0-4h-2V6h2v4z"/></g> +<g id="sync"><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/></g> +<g id="sync-disabled"><path d="M10 6.35V4.26c-.8.21-1.55.54-2.23.96l1.46 1.46c.25-.12.5-.24.77-.33zm-7.14-.94l2.36 2.36C4.45 8.99 4 10.44 4 12c0 2.21.91 4.2 2.36 5.64L4 20h6v-6l-2.24 2.24C6.68 15.15 6 13.66 6 12c0-1 .25-1.94.68-2.77l8.08 8.08c-.25.13-.5.25-.77.34v2.09c.8-.21 1.55-.54 2.23-.96l2.36 2.36 1.27-1.27L4.14 4.14 2.86 5.41zM20 4h-6v6l2.24-2.24C17.32 8.85 18 10.34 18 12c0 1-.25 1.94-.68 2.77l1.46 1.46C19.55 15.01 20 13.56 20 12c0-2.21-.91-4.2-2.36-5.64L20 4z"/></g> +<g id="sync-problem"><path d="M3 12c0 2.21.91 4.2 2.36 5.64L3 20h6v-6l-2.24 2.24C5.68 15.15 5 13.66 5 12c0-2.61 1.67-4.83 4-5.65V4.26C5.55 5.15 3 8.27 3 12zm8 5h2v-2h-2v2zM21 4h-6v6l2.24-2.24C18.32 8.85 19 10.34 19 12c0 2.61-1.67 4.83-4 5.65v2.09c3.45-.89 6-4.01 6-7.74 0-2.21-.91-4.2-2.36-5.64L21 4zm-10 9h2V7h-2v6z"/></g> +<g id="system-update"><path d="M17 1.01L7 1c-1.1 0-2 .9-2 2v18c0 1.1.9 2 2 2h10c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99zM17 19H7V5h10v14zm-1-6h-3V8h-2v5H8l4 4 4-4z"/></g> +<g id="tap-and-play"><path d="M2 16v2c2.76 0 5 2.24 5 5h2c0-3.87-3.13-7-7-7zm0 4v3h3c0-1.66-1.34-3-3-3zm0-8v2c4.97 0 9 4.03 9 9h2c0-6.08-4.92-11-11-11zM17 1.01L7 1c-1.1 0-2 .9-2 2v7.37c.69.16 1.36.37 2 .64V5h10v13h-3.03c.52 1.25.84 2.59.95 4H17c1.1 0 2-.9 2-2V3c0-1.1-.9-1.99-2-1.99z"/></g> +<g id="time-to-leave"><path d="M18.92 5.01C18.72 4.42 18.16 4 17.5 4h-11c-.66 0-1.21.42-1.42 1.01L3 11v8c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-1h12v1c0 .55.45 1 1 1h1c.55 0 1-.45 1-1v-8l-2.08-5.99zM6.5 15c-.83 0-1.5-.67-1.5-1.5S5.67 12 6.5 12s1.5.67 1.5 1.5S7.33 15 6.5 15zm11 0c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zM5 10l1.5-4.5h11L19 10H5z"/></g> +<g id="vibration"><path d="M0 15h2V9H0v6zm3 2h2V7H3v10zm19-8v6h2V9h-2zm-3 8h2V7h-2v10zM16.5 3h-9C6.67 3 6 3.67 6 4.5v15c0 .83.67 1.5 1.5 1.5h9c.83 0 1.5-.67 1.5-1.5v-15c0-.83-.67-1.5-1.5-1.5zM16 19H8V5h8v14z"/></g> +<g id="voice-chat"><path d="M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-2 12l-4-3.2V14H6V6h8v3.2L18 6v8z"/></g> +<g id="vpn-lock"><path d="M22 4v-.5C22 2.12 20.88 1 19.5 1S17 2.12 17 3.5V4c-.55 0-1 .45-1 1v4c0 .55.45 1 1 1h5c.55 0 1-.45 1-1V5c0-.55-.45-1-1-1zm-.8 0h-3.4v-.5c0-.94.76-1.7 1.7-1.7s1.7.76 1.7 1.7V4zm-2.28 8c.04.33.08.66.08 1 0 2.08-.8 3.97-2.1 5.39-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H7v-2h2c.55 0 1-.45 1-1V8h2c1.1 0 2-.9 2-2V3.46c-.95-.3-1.95-.46-3-.46C5.48 3 1 7.48 1 13s4.48 10 10 10 10-4.48 10-10c0-.34-.02-.67-.05-1h-2.03zM10 20.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L8 16v1c0 1.1.9 2 2 2v1.93z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-icons/social-icons.html b/third_party/polymer/v0_8/components/iron-icons/social-icons.html new file mode 100644 index 0000000..390603f9 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-icons/social-icons.html
@@ -0,0 +1,39 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../iron-icon/iron-icon.html"> +<link rel="import" href="../iron-iconset-svg/iron-iconset-svg.html"> +<iron-iconset-svg name="social" size="24"> +<svg><defs> +<g id="cake"><path d="M12 6c1.11 0 2-.9 2-2 0-.38-.1-.73-.29-1.03L12 0l-1.71 2.97c-.19.3-.29.65-.29 1.03 0 1.1.9 2 2 2zm4.6 9.99l-1.07-1.07-1.08 1.07c-1.3 1.3-3.58 1.31-4.89 0l-1.07-1.07-1.09 1.07C6.75 16.64 5.88 17 4.96 17c-.73 0-1.4-.23-1.96-.61V21c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-4.61c-.56.38-1.23.61-1.96.61-.92 0-1.79-.36-2.44-1.01zM18 9h-5V7h-2v2H6c-1.66 0-3 1.34-3 3v1.54c0 1.08.88 1.96 1.96 1.96.52 0 1.02-.2 1.38-.57l2.14-2.13 2.13 2.13c.74.74 2.03.74 2.77 0l2.14-2.13 2.13 2.13c.37.37.86.57 1.38.57 1.08 0 1.96-.88 1.96-1.96V12C21 10.34 19.66 9 18 9z"/></g> +<g id="domain"><path d="M12 7V3H2v18h20V7H12zM6 19H4v-2h2v2zm0-4H4v-2h2v2zm0-4H4V9h2v2zm0-4H4V5h2v2zm4 12H8v-2h2v2zm0-4H8v-2h2v2zm0-4H8V9h2v2zm0-4H8V5h2v2zm10 12h-8v-2h2v-2h-2v-2h2v-2h-2V9h8v10zm-2-8h-2v2h2v-2zm0 4h-2v2h2v-2z"/></g> +<g id="group"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></g> +<g id="group-add"><path d="M8 10H5V7H3v3H0v2h3v3h2v-3h3v-2zm10 1c1.66 0 2.99-1.34 2.99-3S19.66 5 18 5c-.32 0-.63.05-.91.14.57.81.9 1.79.9 2.86s-.34 2.04-.9 2.86c.28.09.59.14.91.14zm-5 0c1.66 0 2.99-1.34 2.99-3S14.66 5 13 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm6.62 2.16c.83.73 1.38 1.66 1.38 2.84v2h3v-2c0-1.54-2.37-2.49-4.38-2.84zM13 13c-2 0-6 1-6 3v2h12v-2c0-2-4-3-6-3z"/></g> +<g id="location-city"><path d="M15 11V5l-3-3-3 3v2H3v14h18V11h-6zm-8 8H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm6 8h-2v-2h2v2zm0-4h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm6 12h-2v-2h2v2zm0-4h-2v-2h2v2z"/></g> +<g id="mood"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm3.5-9c.83 0 1.5-.67 1.5-1.5S16.33 8 15.5 8 14 8.67 14 9.5s.67 1.5 1.5 1.5zm-7 0c.83 0 1.5-.67 1.5-1.5S9.33 8 8.5 8 7 8.67 7 9.5 7.67 11 8.5 11zm3.5 6.5c2.33 0 4.31-1.46 5.11-3.5H6.89c.8 2.04 2.78 3.5 5.11 3.5z"/></g> +<g id="notifications"><path d="M11.5 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6.5-6v-5.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-2.87.68-5 3.25-5 6.32V16l-2 2v1h17v-1l-2-2z"/></g> +<g id="notifications-none"><path d="M11.5 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6.5-6v-5.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-2.87.68-5 3.25-5 6.32V16l-2 2v1h17v-1l-2-2zm-2 1H7v-6.5C7 8.01 9.01 6 11.5 6S16 8.01 16 10.5V17z"/></g> +<g id="notifications-off"><path d="M11.5 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zM18 10.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-.51.12-.99.32-1.45.56L18 14.18V10.5zm-.27 8.5l2 2L21 19.73 4.27 3 3 4.27l2.92 2.92C5.34 8.16 5 9.29 5 10.5V16l-2 2v1h14.73z"/></g> +<g id="notifications-on"><path d="M6.58 3.58L5.15 2.15C2.76 3.97 1.18 6.8 1.03 10h2c.15-2.65 1.51-4.97 3.55-6.42zM19.97 10h2c-.15-3.2-1.73-6.03-4.13-7.85l-1.43 1.43c2.05 1.45 3.41 3.77 3.56 6.42zm-1.97.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-2.87.68-5 3.25-5 6.32V16l-2 2v1h17v-1l-2-2v-5.5zM11.5 22c.14 0 .27-.01.4-.04.65-.13 1.19-.58 1.44-1.18.1-.24.16-.5.16-.78h-4c0 1.1.9 2 2 2z"/></g> +<g id="notifications-paused"><path d="M11.5 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6.5-6v-5.5c0-3.07-2.13-5.64-5-6.32V3.5c0-.83-.67-1.5-1.5-1.5S10 2.67 10 3.5v.68c-2.87.68-5 3.25-5 6.32V16l-2 2v1h17v-1l-2-2zm-4-6.2l-2.8 3.4H14V15H9v-1.8l2.8-3.4H9V8h5v1.8z"/></g> +<g id="pages"><path d="M3 5v6h5L7 7l4 1V3H5c-1.1 0-2 .9-2 2zm5 8H3v6c0 1.1.9 2 2 2h6v-5l-4 1 1-4zm9 4l-4-1v5h6c1.1 0 2-.9 2-2v-6h-5l1 4zm2-14h-6v5l4-1-1 4h5V5c0-1.1-.9-2-2-2z"/></g> +<g id="party-mode"><path d="M20 4h-3.17L15 2H9L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 3c1.63 0 3.06.79 3.98 2H12c-1.66 0-3 1.34-3 3 0 .35.07.69.18 1H7.1c-.06-.32-.1-.66-.1-1 0-2.76 2.24-5 5-5zm0 10c-1.63 0-3.06-.79-3.98-2H12c1.66 0 3-1.34 3-3 0-.35-.07-.69-.18-1h2.08c.07.32.1.66.1 1 0 2.76-2.24 5-5 5z"/></g> +<g id="people"><path d="M16 11c1.66 0 2.99-1.34 2.99-3S17.66 5 16 5c-1.66 0-3 1.34-3 3s1.34 3 3 3zm-8 0c1.66 0 2.99-1.34 2.99-3S9.66 5 8 5C6.34 5 5 6.34 5 8s1.34 3 3 3zm0 2c-2.33 0-7 1.17-7 3.5V19h14v-2.5c0-2.33-4.67-3.5-7-3.5zm8 0c-.29 0-.62.02-.97.05 1.16.84 1.97 1.97 1.97 3.45V19h6v-2.5c0-2.33-4.67-3.5-7-3.5z"/></g> +<g id="people-outline"><path d="M16.5 13c-1.2 0-3.07.34-4.5 1-1.43-.67-3.3-1-4.5-1C5.33 13 1 14.08 1 16.25V19h22v-2.75c0-2.17-4.33-3.25-6.5-3.25zm-4 4.5h-10v-1.25c0-.54 2.56-1.75 5-1.75s5 1.21 5 1.75v1.25zm9 0H14v-1.25c0-.46-.2-.86-.52-1.22.88-.3 1.96-.53 3.02-.53 2.44 0 5 1.21 5 1.75v1.25zM7.5 12c1.93 0 3.5-1.57 3.5-3.5S9.43 5 7.5 5 4 6.57 4 8.5 5.57 12 7.5 12zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 5.5c1.93 0 3.5-1.57 3.5-3.5S18.43 5 16.5 5 13 6.57 13 8.5s1.57 3.5 3.5 3.5zm0-5.5c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2z"/></g> +<g id="person"><path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></g> +<g id="person-add"><path d="M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V7H4v3H1v2h3v3h2v-3h3v-2H6zm9 4c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/></g> +<g id="person-outline"><path d="M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z"/></g> +<g id="plus-one"><path d="M10 8H8v4H4v2h4v4h2v-4h4v-2h-4zm4.5-1.92V7.9l2.5-.5V18h2V5z"/></g> +<g id="poll"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zM9 17H7v-7h2v7zm4 0h-2V7h2v10zm4 0h-2v-4h2v4z"/></g> +<g id="public"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/></g> +<g id="school"><path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z"/></g> +<g id="share"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z"/></g> +<g id="whatshot"><path d="M13.5.67s.74 2.65.74 4.8c0 2.06-1.35 3.73-3.41 3.73-2.07 0-3.63-1.67-3.63-3.73l.03-.36C5.21 7.51 4 10.62 4 14c0 4.42 3.58 8 8 8s8-3.58 8-8C20 8.61 17.41 3.8 13.5.67zM11.71 19c-1.78 0-3.22-1.4-3.22-3.14 0-1.62 1.05-2.76 2.81-3.12 1.77-.36 3.6-1.21 4.62-2.58.39 1.29.59 2.65.59 4.04 0 2.65-2.15 4.8-4.8 4.8z"/></g> +</defs></svg> +</iron-iconset-svg>
diff --git a/third_party/polymer/v0_8/components/iron-iconset-svg/.bower.json b/third_party/polymer/v0_8/components/iron-iconset-svg/.bower.json new file mode 100644 index 0000000..1912846 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset-svg/.bower.json
@@ -0,0 +1,25 @@ +{ + "name": "iron-iconset-svg", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-meta": "polymerelements/iron-meta#^0.8.0" + }, + "devDependencies": { + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/polymerelements/iron-iconset-svg", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "4dfcbf0b1b6788cbe278402e01050960f6b5e894" + }, + "_source": "git://github.com/polymerelements/iron-iconset-svg.git", + "_target": "^0.8.0", + "_originalSource": "polymerelements/iron-iconset-svg" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-iconset-svg/.gitignore b/third_party/polymer/v0_8/components/iron-iconset-svg/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset-svg/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/iron-iconset-svg/README.md b/third_party/polymer/v0_8/components/iron-iconset-svg/README.md new file mode 100644 index 0000000..37d603a --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset-svg/README.md
@@ -0,0 +1,4 @@ +iron-iconset-svg +========= + +See the [component page](http://polymer-project.org/docs/elements/iron-elements.html#iron-iconset-svg) for more information.
diff --git a/third_party/polymer/v0_8/components/iron-iconset-svg/bower.json b/third_party/polymer/v0_8/components/iron-iconset-svg/bower.json new file mode 100644 index 0000000..b37197a --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset-svg/bower.json
@@ -0,0 +1,14 @@ +{ + "name": "iron-iconset-svg", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-meta": "polymerelements/iron-meta#^0.8.0" + }, + "devDependencies": { + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components/iron-iconset-svg/index.html b/third_party/polymer/v0_8/components/iron-iconset-svg/index.html new file mode 100644 index 0000000..088bb04 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset-svg/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="iron-iconset-svg.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-iconset-svg/iron-iconset-svg.html b/third_party/polymer/v0_8/components/iron-iconset-svg/iron-iconset-svg.html new file mode 100644 index 0000000..b667629 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset-svg/iron-iconset-svg.html
@@ -0,0 +1,199 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +/** + * @group Iron Elements + * + * The `iron-iconset-svg` element allows users to define their own icon sets + * that contain svg icons. The svg icon elements should be children of the + * `iron-iconset-svg` element. Multiple icons should be given distinct id's. + * + * Using svg elements to create icons has a few advantages over traditional + * bitmap graphics like jpg or png. Icons that use svg are vector based so they + * are resolution independent and should look good on any device. They are + * stylable via css. Icons can be themed, colorized, and even animated. + * + * Example: + * + * <iron-iconset-svg id="my-svg-icons" iconSize="24"> + * <svg> + * <defs> + * <g id="shape"> + * <rect x="50" y="50" width="50" height="50" /> + * <circle cx="50" cy="50" r="50" /> + * </g> + * </defs> + * </svg> + * </iron-iconset-svg> + * + * This will automatically register the icon set "my-svg-icons" to the iconset + * database. To use these icons from within another element, make a + * `iron-iconset` element and call the `byId` method + * to retrieve a given iconset. To apply a particular icon inside an + * element use the `applyIcon` method. For example: + * + * iconset.applyIcon(iconNode, 'car'); + * + * @element iron-iconset-svg + */ +--> + +<link rel="import" href="../polymer/polymer.html"> + +<script> + + Polymer({ + + is: 'iron-iconset-svg', + + properties: { + + /** + * The name of the iconset. + * + * @attribute name + * @type string + * @default '' + */ + name: { + type: String, + observer: '_nameChanged' + }, + + /** + * Array of fully-qualitifed icon names in the iconset. + */ + iconNames: { + type: Array, + notify: true + }, + + /** + * The size of an individual icon. Note that icons must be square. + * + * @attribute iconSize + * @type number + * @default 24 + */ + size: { + type: Number, + value: 24 + } + + }, + + /** + * Applies an icon to the given element. + * + * An svg icon is prepended to the element's shadowRoot if it exists, + * otherwise to the element itself. + * + * @method applyIcon + * @param {Element} element Element to which the icon is applied. + * @param {String} icon Name of the icon to apply. + * @return {Element} The svg element which renders the icon. + */ + applyIcon: function(element, iconName) { + // insert svg element into shadow root, if it exists + element = element.root || element; + // Remove old svg element + this.removeIcon(element); + // install new svg element + var svg = this._cloneIcon(iconName); + if (svg) { + // TODO(sjmiles): I know, `with` is the devil ... except it isn't + with (Polymer.dom(element)) { + insertBefore(svg, childNodes[0]); + } + return element._svgIcon = svg; + } + }, + + /** + * Remove an icon from the given element by undoing the changes effected + * by `applyIcon`. + * + * @param {Element} element The element from which the icon is removed. + */ + removeIcon: function(element) { + // Remove old svg element + if (element._svgIcon) { + Polymer.dom(element).removeChild(element._svgIcon); + element._svgIcon = null; + } + }, + + /** + * + * When name is changed, either register a new iconset with the included + * icons, or if there are no children, set up a meta-iconset. + * + */ + _nameChanged: function() { + new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); + // icons (descendents) must exist a-priori + this._icons = this._createIconMap(); + this.iconNames = this._getIconNames(); + }, + + /** + * Array of all icon names in this iconset. + * + * @return {Array} Array of icon names. + */ + _getIconNames: function() { + return Object.keys(this._icons).map(function(n) { + return this.name + ':' + n; + }, this); + }, + + /** + * Create a map of child SVG elements by id. + * + * @return {Object} Map of id's to SVG elements. + */ + _createIconMap: function() { + // Objects chained to Object.prototype (`{}`) have members. Specifically, + // on FF there is a `watch` method that confuses the icon map, so we + // need to use a null-based object here. + var icons = Object.create(null); + Polymer.dom(this).querySelectorAll('[id]') + .forEach(function(icon) { + icons[icon.id] = icon; + }); + return icons; + }, + + /** + * Produce installable clone of the SVG element matching `id` in this + * iconset, or `undefined` if there is no matching element. + * + * @return {Object} Returns an installable clone of the SVG element + * matching `id`. + */ + _cloneIcon: function(id) { + return this._prepareSvgClone(this._icons[id], this.size); + }, + + _prepareSvgClone: function(sourceSvg, size) { + if (sourceSvg) { + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('viewBox', ['0', '0', size, size].join(' ')); + svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); + // TODO(dfreedm): `pointer-events: none` works around https://crbug.com/370136 + // TODO(sjmiles): inline style may not be ideal, but avoids requiring a shadow-root + svg.style.cssText = 'pointer-events: none; display: block; width: 100%; height: 100%;'; + svg.appendChild(sourceSvg.cloneNode(true)).removeAttribute('id'); + return svg; + } + } + + }); +</script>
diff --git a/third_party/polymer/v0_8/components/iron-iconset/.bower.json b/third_party/polymer/v0_8/components/iron-iconset/.bower.json new file mode 100644 index 0000000..3caade23 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset/.bower.json
@@ -0,0 +1,25 @@ +{ + "name": "iron-iconset", + "private": true, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-meta": "PolymerElements/iron-meta#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/PolymerElements/iron-iconset", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "a496891222b88e06995558b6f678cbf41d01d9b4" + }, + "_source": "git://github.com/PolymerElements/iron-iconset.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-iconset" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-iconset/.gitignore b/third_party/polymer/v0_8/components/iron-iconset/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/iron-iconset/README.md b/third_party/polymer/v0_8/components/iron-iconset/README.md new file mode 100644 index 0000000..3f46cf5 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset/README.md
@@ -0,0 +1,4 @@ +iron-iconset +============ + +See the [component page](http://polymer-project.org/docs/elements/iron-elements.html#iron-iconset) for more information.
diff --git a/third_party/polymer/v0_8/components/iron-iconset/bower.json b/third_party/polymer/v0_8/components/iron-iconset/bower.json new file mode 100644 index 0000000..0b9367f1 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset/bower.json
@@ -0,0 +1,14 @@ +{ + "name": "iron-iconset", + "private": true, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-meta": "PolymerElements/iron-meta#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components/iron-iconset/index.html b/third_party/polymer/v0_8/components/iron-iconset/index.html new file mode 100644 index 0000000..c2ea8ca --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="iron-iconset.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-iconset/iron-iconset.html b/third_party/polymer/v0_8/components/iron-iconset/iron-iconset.html new file mode 100644 index 0000000..e77f3aef --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-iconset/iron-iconset.html
@@ -0,0 +1,338 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +/** + * @group Iron Elements + * + * The `iron-iconset` element allows users to define their own icon sets. + * The `src` property specifies the url of the icon image. Multiple icons may + * be included in this image and they may be organized into rows. + * The `icons` property is a space separated list of names corresponding to the + * icons. The names must be ordered as the icons are ordered in the icon image. + * Icons are expected to be square and are the size specified by the `size` + * property. The `width` property corresponds to the width of the icon image + * and must be specified if icons are arranged into multiple rows in the image. + * + * All `iron-iconset` elements are available for use by other `iron-iconset` + * elements via a database keyed by id. Typically, an element author that wants + * to support a set of custom icons uses a `iron-iconset` to retrieve + * and use another, user-defined iconset. + * + * Example: + * + * <iron-iconset id="my-icons" src="my-icons.png" width="96" size="24" + * icons="location place starta stopb bus car train walk"> + * </iron-iconset> + * + * This will automatically register the icon set "my-icons" to the iconset + * database. To use these icons from within another element, make a + * `iron-iconset` element and call the `byId` method to retrieve a + * given iconset. To apply a particular icon to an element, use the + * `applyIcon` method. For example: + * + * iconset.applyIcon(iconNode, 'car'); + * + * Themed icon sets are also supported. The `iron-iconset` can contain child + * `property` elements that specify a theme with an offsetX and offsetY of the + * theme within the icon resource. For example. + * + * <iron-iconset id="my-icons" src="my-icons.png" width="96" size="24" + * icons="location place starta stopb bus car train walk"> + * <property theme="special" offsetX="256" offsetY="24"></property> + * </iron-iconset> + * + * Then a themed icon can be applied like this: + * + * iconset.applyIcon(iconNode, 'car', 'special'); + * + * @element iron-iconset + */ +--> +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-meta/iron-meta.html"> + +<script> + + Polymer({ + + is: 'iron-iconset', + + properties: { + + /** + * The URL of the iconset image. + * + * @attribute src + * @type string + * @default '' + */ + src: { + type: String, + observer: '_srcChanged' + }, + + /** + * The name of the iconset. + * + * @attribute name + * @type string + * @default 'no-name' + */ + name: { + type: String, + observer: '_nameChanged' + }, + + /** + * The width of the iconset image. This must only be specified if the + * icons are arranged into separate rows inside the image. + * + * @attribute width + * @type number + * @default 0 + */ + width: { + type: Number, + value: 0 + }, + + /** + * A space separated list of names corresponding to icons in the iconset + * image file. This list must be ordered the same as the icon images + * in the image file. + * + * @attribute icons + * @type string + * @default '' + */ + icons: { + type: String + }, + + /** + * The size of an individual icon. Note that icons must be square. + * + * @attribute size + * @type number + * @default 24 + */ + size: { + type: Number, + value: 24 + }, + + /** + * The horizontal offset of the icon images in the inconset src image. + * This is typically used if the image resource contains additional images + * beside those intended for the iconset. + * + * @attribute offset-x + * @type number + * @default 0 + */ + _offsetX: { + type: Number, + value: 0 + }, + + /** + * The vertical offset of the icon images in the inconset src image. + * This is typically used if the image resource contains additional images + * beside those intended for the iconset. + * + * @attribute offset-y + * @type number + * @default 0 + */ + _offsetY: { + type: Number, + value: 0 + }, + + /** + * Array of fully-qualified names of icons in this set. + */ + iconNames: { + type: Array, + notify: true + } + + }, + + hostAttributes: { + // non-visual + style: 'display: none;' + }, + + ready: function() { + // theme data must exist at ready-time + this._themes = this._mapThemes(); + }, + + /** + * Applies an icon to the given element as a css background image. This + * method does not size the element, and it's usually necessary to set + * the element's height and width so that the background image is visible. + * + * @method applyIcon + * @param {Element} element The element to which the icon is applied. + * @param {String|Number} icon The name or index of the icon to apply. + * @param {String} theme (optional) The name or index of the icon to apply. + * @param {Number} scale (optional, defaults to 1) Icon scaling factor. + * @return {Element} The applied icon element. + */ + applyIcon: function(element, icon, theme, scale) { + this._validateIconMap(); + var offset = this._getThemedOffset(icon, theme); + if (element && offset) { + this._addIconStyles(element, this._srcUrl, offset, scale || 1, + this.size, this.width); + } + }, + + /** + * Remove an icon from the given element by undoing the changes effected + * by `applyIcon`. + * + * @param {Element} element The element from which the icon is removed. + */ + removeIcon: function(element) { + this._removeIconStyles(element.style); + }, + + _mapThemes: function() { + var themes = Object.create(null); + Polymer.dom(this).querySelectorAll('property[theme]') + .forEach(function(property) { + var offsetX = window.parseInt( + property.getAttribute('offset-x'), 10 + ) || 0; + var offsetY = window.parseInt( + property.getAttribute('offset-y'), 10 + ) || 0; + themes[property.getAttribute('theme')] = { + offsetX: offsetX, + offsetY: offsetY + }; + }); + return themes; + }, + + _srcChanged: function(src) { + // ensure `srcUrl` is always relative to the main document + this._srcUrl = this.ownerDocument !== document + ? this.resolveUrl(src) : src; + this._prepareIconset(); + }, + + _nameChanged: function(name) { + this._prepareIconset(); + }, + + _prepareIconset: function() { + new Polymer.IronMeta({type: 'iconset', key: this.name, value: this}); + }, + + _invalidateIconMap: function() { + this._iconMapValid = false; + }, + + _validateIconMap: function() { + if (!this._iconMapValid) { + this._recomputeIconMap(); + this._iconMapValid = true; + } + }, + + _recomputeIconMap: function() { + this.iconNames = this._computeIconNames(this.icons); + this.iconMap = this._computeIconMap(this._offsetX, this._offsetY, + this.size, this.width, this.iconNames); + }, + + _computeIconNames: function(icons) { + return icons.split(/\s+/g); + }, + + _computeIconMap: function(offsetX, offsetY, size, width, iconNames) { + var iconMap = {}; + if (offsetX !== undefined && offsetY !== undefined) { + var x0 = offsetX; + iconNames.forEach(function(iconName) { + iconMap[iconName] = { + offsetX: offsetX, + offsetY: offsetY + }; + if ((offsetX + size) < width) { + offsetX += size; + } else { + offsetX = x0; + offsetY += size; + } + }, this); + } + return iconMap; + }, + + /** + * Returns an object containing `offsetX` and `offsetY` properties which + * specify the pixel location in the iconset's src file for the given + * `icon` and `theme`. It's uncommon to call this method. It is useful, + * for example, to manually position a css backgroundImage to the proper + * offset. It's more common to use the `applyIcon` method. + * + * @method getThemedOffset + * @param {String|Number} identifier The name of the icon or the index of + * the icon within in the icon image. + * @param {String} theme The name of the theme. + * @returns {Object} An object specifying the offset of the given icon + * within the icon resource file; `offsetX` is the horizontal offset and + * `offsetY` is the vertical offset. Both values are in pixel units. + */ + _getThemedOffset: function(identifier, theme) { + var iconOffset = this._getIconOffset(identifier); + var themeOffset = this._themes[theme]; + if (iconOffset && themeOffset) { + return { + offsetX: iconOffset.offsetX + themeOffset.offsetX, + offsetY: iconOffset.offsetY + themeOffset.offsetY + }; + } + return iconOffset; + }, + + _getIconOffset: function(identifier) { + // TODO(sjmiles): consider creating offsetArray (indexed by Number) + // and having iconMap map names to indices, then and index is just + // iconMap[identifier] || identifier (be careful of zero, store indices + // as 1-based) + return this.iconMap[identifier] || + this.iconMap[this.iconNames[Number(identifier)]]; + }, + + _addIconStyles: function(element, url, offset, scale, size, width) { + var style = element.style; + style.backgroundImage = 'url(' + url + ')'; + style.backgroundPosition = + (-offset.offsetX * scale + 'px') + ' ' + + (-offset.offsetY * scale + 'px'); + style.backgroundSize = (scale === 1) ? 'auto' : width * scale + 'px'; + style.width = size + 'px'; + style.height = size + 'px'; + element.setAttribute('role', 'img'); + }, + + _removeIconStyles: function(style) { + style.background = ''; + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/iron-input/.bower.json b/third_party/polymer/v0_8/components/iron-input/.bower.json new file mode 100644 index 0000000..9a43046 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-input/.bower.json
@@ -0,0 +1,39 @@ +{ + "name": "iron-input", + "version": "0.8.1", + "authors": "The Polymer Authors", + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": [ + "iron-input.html" + ], + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-input.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/iron-input", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.6", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + }, + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "2aab343ceb47fd96e58c7898ae114deb7fefd20d" + }, + "_source": "git://github.com/PolymerElements/iron-input.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-input" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-input/.gitignore b/third_party/polymer/v0_8/components/iron-input/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-input/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/iron-input/README.md b/third_party/polymer/v0_8/components/iron-input/README.md new file mode 100644 index 0000000..3ff15aca --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-input/README.md
@@ -0,0 +1,2 @@ +# iron-input +An input with data binding
diff --git a/third_party/polymer/v0_8/components/iron-input/bower.json b/third_party/polymer/v0_8/components/iron-input/bower.json new file mode 100644 index 0000000..a932ef5 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-input/bower.json
@@ -0,0 +1,30 @@ +{ + "name": "iron-input", + "version": "0.8.0", + "authors": "The Polymer Authors", + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": [ + "iron-input.html" + ], + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-input.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/iron-input", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.6", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + } +}
diff --git a/third_party/polymer/v0_8/components/iron-input/index.html b/third_party/polymer/v0_8/components/iron-input/index.html new file mode 100644 index 0000000..f6900379 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-input/index.html
@@ -0,0 +1,30 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>iron-input</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-input/iron-input.html b/third_party/polymer/v0_8/components/iron-input/iron-input.html new file mode 100644 index 0000000..78397679 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-input/iron-input.html
@@ -0,0 +1,63 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<!-- +By default you can only get notified of changes to an `input`'s `value` due to user input: + + <input value="{{myValue::input}}"> + +`iron-input` adds the `bind-value` property that mirrors the `value` property, and can be used +for two-way data binding. `bind-value` will notify if it is changed either by user input or by script. + + <input is="iron-input" bind-value="{{myValue}}"> + +--> +<script> + + Polymer({ + + is: 'iron-input', + + extends: 'input', + + properties: { + + /** + * Use this property instead of `value` for two-way data binding. + */ + bindValue: { + observer: '_bindValueChanged', + type: String + } + + }, + + listeners: { + 'input': '_onInput' + }, + + attached: function() { + this.bindValue = this.value; + }, + + _bindValueChanged: function() { + this.value = this.bindValue; + // manually notify because we don't want to notify until after setting value + this.fire('bind-value-changed', {value: this.bindValue}); + }, + + _onInput: function(event) { + this.bindValue = event.target.value; + } + + }) +</script>
diff --git a/third_party/polymer/v0_8/components/iron-media-query/.bower.json b/third_party/polymer/v0_8/components/iron-media-query/.bower.json new file mode 100644 index 0000000..f38b103 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-media-query/.bower.json
@@ -0,0 +1,39 @@ +{ + "name": "iron-media-query", + "version": "0.8.2", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-media-query" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/iron-media-query", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#~0.6.1", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0" + }, + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "250bedf7e068fcfeb65596f8d4735c3f6cd59d7b" + }, + "_source": "git://github.com/PolymerElements/iron-media-query.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-media-query" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-media-query/.gitignore b/third_party/polymer/v0_8/components/iron-media-query/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-media-query/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/iron-media-query/README.md b/third_party/polymer/v0_8/components/iron-media-query/README.md new file mode 100644 index 0000000..37354d3 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-media-query/README.md
@@ -0,0 +1 @@ +# iron-media-query
diff --git a/third_party/polymer/v0_8/components/iron-media-query/bower.json b/third_party/polymer/v0_8/components/iron-media-query/bower.json new file mode 100644 index 0000000..e407932 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-media-query/bower.json
@@ -0,0 +1,31 @@ +{ + "name": "iron-media-query", + "version": "0.8.0", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-media-query" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/iron-media-query", + "ignore": [ + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#~0.6.1", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0" + } +}
diff --git a/third_party/polymer/v0_8/components/iron-media-query/index.html b/third_party/polymer/v0_8/components/iron-media-query/index.html new file mode 100644 index 0000000..d38ba75 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-media-query/index.html
@@ -0,0 +1,35 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> + <head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>iron-media-query</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + + <style> + body { + margin: 16px; + } + </style> + + </head> + <body> + + <iron-doc-viewer src="iron-media-query.html"></iron-doc-viewer> + + </body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-media-query/iron-media-query.html b/third_party/polymer/v0_8/components/iron-media-query/iron-media-query.html new file mode 100644 index 0000000..a430fae --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-media-query/iron-media-query.html
@@ -0,0 +1,82 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<!-- +`iron-media-query` can be used to data bind to a CSS media query. +The `query` property is a bare CSS media query. +The `queryMatches` property is a boolean representing if the page matches that media query. + +Example: + + <iron-media-query query="(min-width: 600px)" queryMatches="{{queryMatches}}"></iron-media-query> + +@group Polymer Core Elements +@element iron-media-query +--> + +<script> + + Polymer({ + + is: 'iron-media-query', + + properties: { + + /** + * The Boolean return value of the media query. + * + * @attribute queryMatches + * @type Boolean + * @default false + */ + queryMatches: { + type: Boolean, + value: false, + readOnly: true, + notify: true + }, + + /** + * The CSS media query to evaluate. + * + * @attribute query + * @type String + */ + query: { + type: String, + observer: 'queryChanged' + } + + }, + + created: function() { + this._mqHandler = this.queryHandler.bind(this); + }, + + queryChanged: function(query) { + if (this._mq) { + this._mq.removeListener(this._mqHandler); + } + if (query[0] !== '(') { + query = '(' + query + ')'; + } + this._mq = window.matchMedia(query); + this._mq.addListener(this._mqHandler); + this.queryHandler(this._mq); + }, + + queryHandler: function(mq) { + this._setQueryMatches(mq.matches); + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/iron-meta/.bower.json b/third_party/polymer/v0_8/components/iron-meta/.bower.json new file mode 100644 index 0000000..54e22390c --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-meta/.bower.json
@@ -0,0 +1,27 @@ +{ + "name": "iron-meta", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/PolymerElements/iron-meta", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "c67091ccb5cca75ea4d103b5ce6ae9703676aa98" + }, + "_source": "git://github.com/PolymerElements/iron-meta.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-meta" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-meta/.gitignore b/third_party/polymer/v0_8/components/iron-meta/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-meta/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/iron-meta/README.md b/third_party/polymer/v0_8/components/iron-meta/README.md new file mode 100644 index 0000000..819e336 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-meta/README.md
@@ -0,0 +1,4 @@ +iron-meta +========= + +See the [component page](http://polymerelements.github.io/iron-meta) for more information.
diff --git a/third_party/polymer/v0_8/components/iron-meta/bower.json b/third_party/polymer/v0_8/components/iron-meta/bower.json new file mode 100644 index 0000000..1734339 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-meta/bower.json
@@ -0,0 +1,16 @@ +{ + "name": "iron-meta", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components/iron-meta/index.html b/third_party/polymer/v0_8/components/iron-meta/index.html new file mode 100644 index 0000000..789042f --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-meta/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="iron-meta.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-meta/iron-meta.html b/third_party/polymer/v0_8/components/iron-meta/iron-meta.html new file mode 100644 index 0000000..32a0849e --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-meta/iron-meta.html
@@ -0,0 +1,349 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +`iron-meta` is a generic element you can use for sharing information across the DOM tree. +It uses [monostate pattern](http://c2.com/cgi/wiki?MonostatePattern) such that any +instance of iron-meta has access to the shared +information. You can use `iron-meta` to share whatever you want (or create an extension +[like x-meta] for enhancements). + +The `iron-meta` instances containing your actual data can be loaded in an import, +or constructed in any way you see fit. The only requirement is that you create them +before you try to access them. + +Examples: + +If I create an instance like this: + + <iron-meta key="info" keyUrl="foo/bar"></iron-meta> + +Note that keyUrl="foo/bar" is the metadata I've defined. I could define more +attributes or use child nodes to define additional metadata. + +Now I can access that element (and it's metadata) from any iron-meta instance +via the byKey method, e.g. + + meta.byKey('info').getAttribute('keyUrl'). + +Pure imperative form would be like: + + document.createElement('iron-meta').byKey('info').getAttribute('keyUrl'); + +Or, in a Polymer element, you can include a meta in your template: + + <iron-meta id="meta"></iron-meta> + ... + this.$.meta.byKey('info').getAttribute('keyUrl'); + +@group Polymer Iron Elements +@element iron-meta +--> + +<link rel="import" href="../polymer/polymer.html"> + +<script> + + (function() { + + // monostate data + var metaDatas = {}; + var metaArrays = {}; + + Polymer.IronMeta = Polymer({ + + is: 'iron-meta', + + properties: { + + /** + * The type of meta-data. All meta-data of the same type is stored + * together. + * + * @attribute type + * @type String + * @default 'default' + */ + type: { + type: String, + value: 'default', + observer: '_typeChanged' + }, + + /** + * The key used to store `value` under the `type` namespace. + * + * @attribute key + * @type String + * @default '' + */ + key: { + type: String, + observer: '_keyChanged' + }, + + /** + * The meta-data to store or retrieve. + * + * @attribute value + * @type * + * @default this + */ + value: { + type: Object, + notify: true, + observer: '_valueChanged' + }, + + /** + * If true, `value` is set to the iron-meta instance itself. + * + * @attribute self + * @type Boolean + * @default false + */ + self: { + type: Boolean, + observer: '_selfChanged' + }, + + /** + * Array of all meta-data values for the given type. + * + * @property list + * @type Array + */ + list: { + type: Array, + notify: true + } + + }, + + /** + * Only runs if someone invokes the factory/constructor directly + * e.g. `new Polymer.IronMeta()` + */ + factoryImpl: function(config) { + if (config) { + for (var n in config) { + switch(n) { + case 'type': + case 'key': + case 'value': + this[n] = config[n]; + break; + } + } + } + }, + + created: function() { + // TODO(sjmiles): good for debugging? + this._metaDatas = metaDatas; + this._metaArrays = metaArrays; + }, + + _keyChanged: function(key, old) { + this._resetRegistration(old); + }, + + _valueChanged: function(value) { + this._resetRegistration(this.key); + }, + + _selfChanged: function(self) { + if (self) { + this.value = this; + } + }, + + _typeChanged: function(type) { + this._unregisterKey(this.key); + if (!metaDatas[type]) { + metaDatas[type] = {}; + } + this._metaData = metaDatas[type]; + if (!metaArrays[type]) { + metaArrays[type] = []; + } + this.list = metaArrays[type]; + this._registerKeyValue(this.key, this.value); + }, + + /** + * Retrieves meta data value by key. + * + * @method byKey + * @param {String} key The key of the meta-data to be returned. + * @returns * + */ + byKey: function(key) { + return this._metaData && this._metaData[key]; + }, + + _resetRegistration: function(oldKey) { + this._unregisterKey(oldKey); + this._registerKeyValue(this.key, this.value); + }, + + _unregisterKey: function(key) { + this._unregister(key, this._metaData, this.list); + }, + + _registerKeyValue: function(key, value) { + this._register(key, value, this._metaData, this.list); + }, + + _register: function(key, value, data, list) { + if (key && data && value !== undefined) { + data[key] = value; + list.push(value); + } + }, + + _unregister: function(key, data, list) { + if (key && data) { + if (key in data) { + var value = data[key]; + delete data[key]; + this.arrayDelete(list, value); + } + } + } + + }); + + /** + `iron-meta-query` can be used to access infomation stored in `iron-meta`. + + Examples: + + If I create an instance like this: + + <iron-meta key="info" value="foo/bar"></iron-meta> + + Note that keyUrl="foo/bar" is the metadata I've defined. I could define more + attributes or use child nodes to define additional metadata. + + Now I can access that element (and it's metadata) from any `iron-meta-query` instance: + + var value = new Polymer.IronMetaQuery({key: 'info'}).value; + + @group Polymer Iron Elements + @element iron-meta-query + */ + Polymer.IronMetaQuery = Polymer({ + + is: 'iron-meta-query', + + properties: { + + /** + * The type of meta-data. All meta-data of the same type is stored + * together. + * + * @attribute type + * @type String + * @default 'default' + */ + type: { + type: String, + value: 'default', + observer: '_typeChanged' + }, + + /** + * Specifies a key to use for retrieving `value` from the `type` + * namespace. + * + * @attribute key + * @type String + */ + key: { + type: String, + observer: '_keyChanged' + }, + + /** + * The meta-data to store or retrieve. + * + * @attribute value + * @type * + * @default this + */ + value: { + type: Object, + notify: true, + readOnly: true + }, + + /** + * Array of all meta-data values for the given type. + * + * @property list + * @type Array + */ + list: { + type: Array, + notify: true + } + + }, + + /** + * Actually a factory method, not a true constructor. Only runs if + * someone invokes it directly (via `new Polymer.IronMeta()`); + */ + constructor: function(config) { + if (config) { + for (var n in config) { + switch(n) { + case 'type': + case 'key': + this[n] = config[n]; + break; + } + } + } + }, + + created: function() { + // TODO(sjmiles): good for debugging? + this._metaDatas = metaDatas; + this._metaArrays = metaArrays; + }, + + _keyChanged: function(key) { + this._setValue(this._metaData && this._metaData[key]); + }, + + _typeChanged: function(type) { + this._metaData = metaDatas[type]; + this.list = metaArrays[type]; + if (this.key) { + this._keyChanged(this.key); + } + }, + + /** + * Retrieves meta data value by key. + * + * @method byKey + * @param {String} key The key of the meta-data to be returned. + * @returns * + */ + byKey: function(key) { + return this._metaData && this._metaData[key]; + } + + }); + + })(); +</script>
diff --git a/third_party/polymer/v0_8/components/iron-selector/.bower.json b/third_party/polymer/v0_8/components/iron-selector/.bower.json new file mode 100644 index 0000000..3e060c5 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/.bower.json
@@ -0,0 +1,31 @@ +{ + "name": "iron-selector", + "version": "0.8.3", + "private": true, + "main": [ + "iron-selector.html" + ], + "authors": "The Polymer Authors", + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-selector.git" + }, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0" + }, + "homepage": "https://github.com/PolymerElements/iron-selector", + "_release": "0.8.3", + "_resolution": { + "type": "version", + "tag": "v0.8.3", + "commit": "58f87005d6eb717b05668b8a78a7c51c0893eee3" + }, + "_source": "git://github.com/PolymerElements/iron-selector.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/iron-selector" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/iron-selector/.gitignore b/third_party/polymer/v0_8/components/iron-selector/.gitignore new file mode 100644 index 0000000..b13058c --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/.gitignore
@@ -0,0 +1,2 @@ +bower_components +.DS_Store
diff --git a/third_party/polymer/v0_8/components/iron-selector/README.md b/third_party/polymer/v0_8/components/iron-selector/README.md new file mode 100644 index 0000000..31667a3d --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/README.md
@@ -0,0 +1,2 @@ +iron-selector +=============
diff --git a/third_party/polymer/v0_8/components/iron-selector/bower.json b/third_party/polymer/v0_8/components/iron-selector/bower.json new file mode 100644 index 0000000..646b3e0 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/bower.json
@@ -0,0 +1,21 @@ +{ + "name": "iron-selector", + "version": "0.8.2", + "private": true, + "main": [ + "iron-selector.html" + ], + "authors": "The Polymer Authors", + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/iron-selector.git" + }, + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0" + } +}
diff --git a/third_party/polymer/v0_8/components/iron-selector/index.html b/third_party/polymer/v0_8/components/iron-selector/index.html new file mode 100644 index 0000000..8c0d31d9 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/index.html
@@ -0,0 +1,23 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<html> +<head> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../core-component-page/core-component-page.html"> + +</head> +<body> + + <core-component-page></core-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/iron-selector/iron-multi-selectable.html b/third_party/polymer/v0_8/components/iron-selector/iron-multi-selectable.html new file mode 100644 index 0000000..cdf16cf3 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/iron-multi-selectable.html
@@ -0,0 +1,127 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="iron-selectable.html"> + +<script> + + Polymer.IronMultiSelectableBehavior = [ + Polymer.IronSelectableBehavior, { + + properties: { + + /** + * If true, multiple selections are allowed. + * + * @attribute multi + * @type Boolean + * @default false + */ + multi: { + type: Boolean, + value: false, + observer: 'multiChanged' + }, + + /** + * Gets or sets the selected elements. This is used instead of `selected` when `multi` + * is true. + * + * @attribute selectedValues + * @type Array + */ + selectedValues: { + type: Array, + notify: true + }, + + /** + * Returns an array of currently selected items. + * + * @attribute selectedItems + * @type Array + */ + selectedItems: { + type: Array, + readOnly: true, + notify: true + }, + + }, + + observers: [ + '_updateSelected(attrForSelected, selectedValues)' + ], + + /** + * Selects the given value. If the `multi` property is true, then the selected state of the + * `value` will be toggled; otherwise the `value` will be selected. + * + * @method select + * @param {String} value the value to select. + */ + select: function(value) { + if (this.multi) { + if (this.selectedValues) { + this._toggleSelected(value); + } else { + this.selectedValues = [value]; + } + } else { + this.selected = value; + } + }, + + multiChanged: function(multi) { + this._selection.multi = multi; + }, + + _updateSelected: function() { + if (this.multi) { + this._selectMulti(this.selectedValues); + } else { + this._selectSelected(this.selected); + } + }, + + _selectMulti: function(values) { + this._selection.clear(); + if (values) { + for (var i = 0; i < values.length; i++) { + this._selection.setItemSelected(this._valueToItem(values[i]), true); + } + } + }, + + _selectionChange: function() { + var s = this._selection.get(); + if (this.multi) { + this._setSelectedItems(s); + } else { + this._setSelectedItems([s]); + this._setSelectedItem(s); + } + }, + + _toggleSelected: function(value) { + var i = this.selectedValues.indexOf(value); + var unselected = i < 0; + if (unselected) { + this.selectedValues.push(value); + } else { + this.selectedValues.splice(i, 1); + } + this._selection.setItemSelected(this._valueToItem(value), unselected); + } + + } + ]; + +</script>
diff --git a/third_party/polymer/v0_8/components/iron-selector/iron-selectable.html b/third_party/polymer/v0_8/components/iron-selector/iron-selectable.html new file mode 100644 index 0000000..6589ac9 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/iron-selectable.html
@@ -0,0 +1,300 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="iron-selection.html"> + +<script> + + Polymer.IronSelectableBehavior = { + + properties: { + + /** + * If you want to use the attribute value of an element for `selected` instead of the index, + * set this to the name of the attribute. + * + * @attribute attrForSelected + * @type String + */ + attrForSelected: { + type: String, + value: null + }, + + /** + * Gets or sets the selected element. The default is to use the index of the item. + * + * @attribute selected + * @type String + */ + selected: { + type: String, + notify: true + }, + + /** + * Returns the currently selected item. + * + * @attribute selectedItem + * @type Object + */ + selectedItem: { + type: Object, + readOnly: true, + notify: true + }, + + /** + * The event that fires from items when they are selected. Selectable + * will listen for this event from items and update the selection state. + * Set to empty string to listen to no events. + * + * @attribute activateEvent + * @type String + * @default 'click' + */ + activateEvent: { + type: String, + value: 'click', + observer: '_activateEventChanged' + }, + + /** + * This is a CSS selector sting. If this is set, only items that matches the CSS selector + * are selectable. + * + * @attribute selectable + * @type String + */ + selectable: String, + + /** + * The class to set on elements when selected. + * + * @attribute selectedClass + * @type String + */ + selectedClass: { + type: String, + value: 'iron-selected' + }, + + /** + * The attribute to set on elements when selected. + * + * @attribute selectedAttribute + * @type String + */ + selectedAttribute: { + type: String, + value: null + } + + }, + + observers: [ + '_updateSelected(attrForSelected, selected)' + ], + + excludedLocalNames: { + 'template': 1 + }, + + created: function() { + this._bindActivateHandler = this._activateHandler.bind(this); + this._bindFilterItem = this._filterItem.bind(this); + this._selection = new Polymer.IronSelection(this._applySelection.bind(this)); + }, + + attached: function() { + this._observer = this._observeItems(this); + this._contentObserver = this._observeContent(this); + }, + + detached: function() { + if (this._observer) { + this._observer.disconnect(); + } + if (this._contentObserver) { + this._contentObserver.disconnect(); + } + this._removeListener(this.activateEvent); + }, + + /** + * Returns an array of selectable items. + * + * @property items + * @type Array + */ + get items() { + var nodes = Polymer.dom(this).queryDistributedElements(this.selectable || '*'); + return Array.prototype.filter.call(nodes, this._bindFilterItem); + }, + + /** + * Returns the index of the given item. + * + * @method indexOf + * @param {Object} item + * @returns Returns the index of the item + */ + indexOf: function(item) { + return this.items.indexOf(item); + }, + + /** + * Selects the given value. + * + * @method select + * @param {String} value the value to select. + */ + select: function(value) { + this.selected = value; + }, + + /** + * Selects the previous item. + * + * @method selectPrevious + */ + selectPrevious: function() { + var length = this.items.length; + var index = (Number(this._valueToIndex(this.selected)) - 1 + length) % length; + this.selected = this._indexToValue(index); + }, + + /** + * Selects the next item. + * + * @method selectNext + */ + selectNext: function() { + var index = (Number(this._valueToIndex(this.selected)) + 1) % this.items.length; + this.selected = this._indexToValue(index); + }, + + _addListener: function(eventName) { + this.addEventListener(eventName, this._bindActivateHandler); + }, + + _removeListener: function(eventName) { + this.removeEventListener(eventName, this._bindActivateHandler); + }, + + _activateEventChanged: function(eventName, old) { + this._removeListener(old); + this._addListener(eventName); + }, + + _updateSelected: function() { + this._selectSelected(this.selected); + }, + + _selectSelected: function(selected) { + this._selection.select(this._valueToItem(this.selected)); + }, + + _filterItem: function(node) { + return !this.excludedLocalNames[node.localName]; + }, + + _valueToItem: function(value) { + return (value == null) ? null : this.items[this._valueToIndex(value)]; + }, + + _valueToIndex: function(value) { + if (this.attrForSelected) { + for (var i = 0, item; item = this.items[i]; i++) { + if (this._valueForItem(item) == value) { + return i; + } + } + } else { + return Number(value); + } + }, + + _indexToValue: function(index) { + if (this.attrForSelected) { + var item = this.items[index]; + if (item) { + return this._valueForItem(item); + } + } else { + return index; + } + }, + + _valueForItem: function(item) { + return item[this.attrForSelected] || item.getAttribute(this.attrForSelected); + }, + + _applySelection: function(item, isSelected) { + if (this.selectedClass) { + this.toggleClass(this.selectedClass, isSelected, item); + } + if (this.selectedAttribute) { + this.toggleAttribute(this.selectedAttribute, isSelected, item); + } + this._selectionChange(); + this.fire('iron-' + (isSelected ? 'select' : 'deselect'), {item: item}); + }, + + _selectionChange: function() { + this._setSelectedItem(this._selection.get()); + }, + + // observe content changes under the given node. + _observeContent: function(node) { + var content = node.querySelector('content'); + if (content && content.parentElement === node) { + return this._observeItems(node.host); + } + }, + + // observe items change under the given node. + _observeItems: function(node) { + var observer = new MutationObserver(function() { + if (this.selected != null) { + this._updateSelected(); + } + }.bind(this)); + observer.observe(node, { + childList: true, + subtree: true + }); + return observer; + }, + + _activateHandler: function(e) { + var t = e.target; + var items = this.items; + while (t && t != this) { + var i = items.indexOf(t); + if (i >= 0) { + var value = this._indexToValue(i); + this._itemActivate(value, t); + return; + } + t = t.parentNode; + } + }, + + _itemActivate: function(value, item) { + if (!this.fire('iron-activate', + {selected: value, item: item}, {cancelable: true}).defaultPrevented) { + this.select(value); + } + } + + }; + +</script>
diff --git a/third_party/polymer/v0_8/components/iron-selector/iron-selection.html b/third_party/polymer/v0_8/components/iron-selector/iron-selection.html new file mode 100644 index 0000000..0177199 --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/iron-selection.html
@@ -0,0 +1,111 @@ + +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<script> + + Polymer.IronSelection = function(selectCallback) { + this.selection = []; + this.selectCallback = selectCallback; + }; + + Polymer.IronSelection.prototype = { + + /** + * Retrieves the selected item(s). + * + * @method get + * @returns Returns the selected item(s). If the multi property is true, + * `get` will return an array, otherwise it will return + * the selected item or undefined if there is no selection. + */ + get: function() { + return this.multi ? this.selection : this.selection[0]; + }, + + /** + * Clears all the selection except the ones indicated. + * + * @method clear + * @param {Array} excludes items to be excluded. + */ + clear: function(excludes) { + this.selection.slice().forEach(function(item) { + if (!excludes || excludes.indexOf(item) < 0) { + this.setItemSelected(item, false); + } + }, this); + }, + + /** + * Indicates if a given item is selected. + * + * @method isSelected + * @param {any} item The item whose selection state should be checked. + * @returns Returns true if `item` is selected. + */ + isSelected: function(item) { + return this.selection.indexOf(item) >= 0; + }, + + /** + * Sets the selection state for a given item to either selected or deselected. + * + * @method setItemSelected + * @param {any} item The item to select. + * @param {Boolean} isSelected True for selected, false for deselected. + */ + setItemSelected: function(item, isSelected) { + if (item != null) { + if (isSelected) { + this.selection.push(item); + } else { + var i = this.selection.indexOf(item); + if (i >= 0) { + this.selection.splice(i, 1); + } + } + if (this.selectCallback) { + this.selectCallback(item, isSelected); + } + } + }, + + /** + * Sets the selection state for a given item. If the `multi` property + * is true, then the selected state of `item` will be toggled; otherwise + * the `item` will be selected. + * + * @method select + * @param {any} item The item to select. + */ + select: function(item) { + if (this.multi) { + this.toggle(item); + } else if (this.get() !== item) { + this.setItemSelected(this.get(), false); + this.setItemSelected(item, true); + } + }, + + /** + * Toggles the selection state for `item`. + * + * @method toggle + * @param {any} item The item to toggle. + */ + toggle: function(item) { + this.setItemSelected(item, !this.isSelected(item)); + } + + }; + +</script>
diff --git a/third_party/polymer/v0_8/components/iron-selector/iron-selector.html b/third_party/polymer/v0_8/components/iron-selector/iron-selector.html new file mode 100644 index 0000000..ded1837e --- /dev/null +++ b/third_party/polymer/v0_8/components/iron-selector/iron-selector.html
@@ -0,0 +1,73 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +`iron-selector` is an element which can be used to manage a list of elements +that can be selected. Tapping on the item will make the item selected. The `selected` indicates +which item is being selected. The default is to use the index of the item. + +Example: + + <iron-selector selected="0"> + <div>Item 1</div> + <div>Item 2</div> + <div>Item 3</div> + </iron-selector> + +If you want to use the attribute value of an element for `selected` instead of the index, +set `attrForSelected` to the name of the attribute. For example, if you want to select item by +`name`, set `attrForSelected` to `name`. + +Example: + + <iron-selector attr-for-selected="name" selected="foo"> + <div name="foo">Foo</div> + <div name="bar">Bar</div> + <div name="zot">Zot</div> + </iron-selector> + +`iron-selector` is not styled. Use the `iron-selected` CSS class to style the selected element. + +Example: + + <style> + .iron-selected { + background: #eee; + } + </style> + + ... + + <iron-selector selected="0"> + <div>Item 1</div> + <div>Item 2</div> + <div>Item 3</div> + </iron-selector> + +@group Polymer Core Elements +@element iron-selector +@homepage github.io +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="iron-multi-selectable.html"> + +<script> + + Polymer({ + + is: 'iron-selector', + + behaviors: [ + Polymer.IronMultiSelectableBehavior + ] + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/paper-behaviors/.bower.json b/third_party/polymer/v0_8/components/paper-behaviors/.bower.json new file mode 100644 index 0000000..3a9355d --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-behaviors/.bower.json
@@ -0,0 +1,25 @@ +{ + "name": "paper-behaviors", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-behaviors": "polymerelements/iron-behaviors#^0.8.0" + }, + "devDependencies": { + "paper-card": "polymerelements/paper-card#v0.8.0", + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + }, + "homepage": "https://github.com/polymerelements/paper-behaviors", + "version": "0.8.1", + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "516c874900a1d51f7b9a82d8f251b17be0d93499" + }, + "_source": "git://github.com/polymerelements/paper-behaviors.git", + "_target": "^0.8.0", + "_originalSource": "polymerelements/paper-behaviors" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-behaviors/README.md b/third_party/polymer/v0_8/components/paper-behaviors/README.md new file mode 100644 index 0000000..e793a621 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-behaviors/README.md
@@ -0,0 +1,4 @@ +paper-behaviors +=============== + +These are common behaviors used across `paper-*` elements.
diff --git a/third_party/polymer/v0_8/components/paper-behaviors/bower.json b/third_party/polymer/v0_8/components/paper-behaviors/bower.json new file mode 100644 index 0000000..a89bfef --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-behaviors/bower.json
@@ -0,0 +1,14 @@ +{ + "name": "paper-behaviors", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "iron-behaviors": "polymerelements/iron-behaviors#^0.8.0" + }, + "devDependencies": { + "paper-card": "polymerelements/paper-card#v0.8.0", + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-behaviors/index.html b/third_party/polymer/v0_8/components/paper-behaviors/index.html new file mode 100644 index 0000000..0e01e8a --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-behaviors/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-component-page/iron-component-page.html"> + +</head> +<body> + + <iron-component-page></iron-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/paper-behaviors/paper-button-behavior.html b/third_party/polymer/v0_8/components/paper-behaviors/paper-button-behavior.html new file mode 100644 index 0000000..a7664cb3 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-behaviors/paper-button-behavior.html
@@ -0,0 +1,46 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-behaviors/iron-button-state.html"> + +<script> + + Polymer.PaperButtonElevation = { + + properties: { + + _elevation: { + type: Number + } + + }, + + _calculateElevation: function() { + var e = 1; + if (this.disabled || !this.raised) { + e = 0; + } else if (this.active || this.pressed) { + e = 2; + } else if (this.focused) { + e = 3; + } + this._elevation = e; + } + + }; + + Polymer.PaperButtonBehavior = [ + Polymer.IronControlState, + Polymer.IronButtonState, + Polymer.PaperButtonElevation + ]; + +</script>
diff --git a/third_party/polymer/v0_8/components/paper-button/.bower.json b/third_party/polymer/v0_8/components/paper-button/.bower.json new file mode 100644 index 0000000..3613e40 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-button/.bower.json
@@ -0,0 +1,31 @@ +{ + "name": "paper-button", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-ripple": "polymerelements/paper-ripple#^0.8.0", + "paper-card": "polymerelements/paper-card#^0.8.0", + "paper-behaviors": "polymerelements/paper-behaviors#^0.8.0" + }, + "devDependencies": { + "iron-component-page": "polymerelements/iron-component-page#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-icons": "polymerelements/iron-icons#^0.8.0", + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + }, + "homepage": "https://github.com/PolymerElements/paper-button", + "version": "0.8.1", + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "1a985b374c6ba563e79ad1c0056b4df63491bd80" + }, + "_source": "git://github.com/PolymerElements/paper-button.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-button" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-button/.gitignore b/third_party/polymer/v0_8/components/paper-button/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-button/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/paper-button/README.md b/third_party/polymer/v0_8/components/paper-button/README.md new file mode 100644 index 0000000..c0d5e7b8 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-button/README.md
@@ -0,0 +1,4 @@ +paper-button +============ + +See the [component page](http://www.polymer-project.org/docs/elements/paper-elements.html#paper-button) for more information.
diff --git a/third_party/polymer/v0_8/components/paper-button/bower.json b/third_party/polymer/v0_8/components/paper-button/bower.json new file mode 100644 index 0000000..9997f3a --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-button/bower.json
@@ -0,0 +1,20 @@ +{ + "name": "paper-button", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-ripple": "polymerelements/paper-ripple#^0.8.0", + "paper-card": "polymerelements/paper-card#^0.8.0", + "paper-behaviors": "polymerelements/paper-behaviors#^0.8.0" + }, + "devDependencies": { + "iron-component-page": "polymerelements/iron-component-page#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-icons": "polymerelements/iron-icons#^0.8.0", + "iron-test-helpers": "polymerelements/iron-test-helpers#^0.8.0", + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "*" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-button/index.html b/third_party/polymer/v0_8/components/paper-button/index.html new file mode 100644 index 0000000..0e01e8a --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-button/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-component-page/iron-component-page.html"> + +</head> +<body> + + <iron-component-page></iron-component-page> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/paper-button/paper-button.html b/third_party/polymer/v0_8/components/paper-button/paper-button.html new file mode 100644 index 0000000..b76afe9 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-button/paper-button.html
@@ -0,0 +1,160 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> + +<!-- + +Material Design: <a href="http://www.google.com/design/spec/components/buttons.html">Buttons</a> + +`paper-button` is a button. When the user touches the button, a ripple effect emanates +from the point of contact. It may be flat or raised. A raised button is styled with a +shadow. + +Example: + + <paper-button>flat button</paper-button> + <paper-button raised>raised button</paper-button> + <paper-button noink>No ripple effect</paper-button> + +You may use custom DOM in the button body to create a variety of buttons. For example, to +create a button with an icon and some text: + + <paper-button> + <core-icon icon="favorite"></core-icon> + custom button content + </paper-button> + +## Styling + +Style the button with CSS as you would a normal DOM element. + + /* make #my-button green with yellow text */ + #my-button { + background: green; + color: yellow; + } + +By default, the ripple is the same color as the foreground at 25% opacity. You may +customize the color using this selector: + + /* make #my-button use a blue ripple instead of foreground color */ + #my-button::shadow paper-ripple { + color: blue; + } + +The opacity of the ripple is not customizable via CSS. + +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-card/paper-card.html"> +<link rel="import" href="../paper-ripple/paper-ripple.html"> + +<link rel="import" href="../paper-behaviors/paper-button-behavior.html"> + +<dom-module id="paper-button"> + + <style> + + :host { + display: inline-block; + position: relative; + box-sizing: border-box; + min-width: 5.14em; + margin: 0 0.29em; + background: transparent; + text-align: center; + font: inherit; + text-transform: uppercase; + outline: none; + border-radius: 3px; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none; + cursor: pointer; + z-index: 0; + } + + :host([disabled]) { + background: #eaeaea; + color: #a8a8a8; + cursor: auto; + pointer-events: none; + } + + :host([noink]) paper-ripple { + display: none; + } + + paper-card { + border-radius: inherit; + } + + .content > ::content * { + text-transform: inherit; + } + + .content { + padding: 0.7em 0.57em + } + </style> + + <template> + + <paper-ripple></paper-ripple> + + <paper-card class="content" elevation="[[_elevation]]" animated> + <content></content> + </paper-card> + + </template> + + <script> + + Polymer({ + + behaviors: [ + Polymer.PaperButtonBehavior + ], + + properties: { + + /** + * If true, the button should be styled with a shadow. + * + * @attribute raised + * @type boolean + * @default false + */ + raised: { + type: Boolean, + reflectToAttribute: true, + value: false, + observer: '_buttonStateChanged' + } + + }, + + ready: function() { + if (!this.hasAttribute('role')) { + this.setAttribute('role', 'button'); + } + }, + + _buttonStateChanged: function() { + this._calculateElevation(); + } + + }); + + </script> + +</dom-module> +
diff --git a/third_party/polymer/v0_8/components/paper-card/.bower.json b/third_party/polymer/v0_8/components/paper-card/.bower.json new file mode 100644 index 0000000..6aa4d5eb --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-card/.bower.json
@@ -0,0 +1,27 @@ +{ + "name": "paper-card", + "version": "0.8.2", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-styles": "polymerelements/paper-styles#^0.8.0" + }, + "devDependencies": { + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + }, + "homepage": "https://github.com/PolymerElements/paper-card", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "ec06cea50b93ee58f0473cd2749e768aa63ff406" + }, + "_source": "git://github.com/PolymerElements/paper-card.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-card" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-card/.gitignore b/third_party/polymer/v0_8/components/paper-card/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-card/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/paper-card/bower.json b/third_party/polymer/v0_8/components/paper-card/bower.json new file mode 100644 index 0000000..e7fb92bd --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-card/bower.json
@@ -0,0 +1,17 @@ +{ + "name": "paper-card", + "version": "0.8.0", + "private": true, + "authors": [ + "The Polymer Authors" + ], + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-styles": "polymerelements/paper-styles#^0.8.0" + }, + "devDependencies": { + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.6" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-card/paper-card.html b/third_party/polymer/v0_8/components/paper-card/paper-card.html new file mode 100644 index 0000000..76632a4 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-card/paper-card.html
@@ -0,0 +1,97 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- + +`paper-card` is a container that renders two shadows on top of each other to +create the effect of a lifted piece of paper. + +Example: + + <paper-card elevation="1"> + ... card content ... + </paper-card> + +@group Paper Elements +@class paper-card +--> + +<link href="../polymer/polymer.html" rel="import"> +<link href="../paper-styles/shadow.html" rel="import"> +<dom-module id="paper-card"> + <style> + :host { + display: block; + position: relative; + mixin(--shadow-transition); + } + + :host([elevation="1"]) { + mixin(--shadow-elevation-1); + } + + :host([elevation="2"]) { + mixin(--shadow-elevation-2); + } + + :host([elevation="3"]) { + mixin(--shadow-elevation-3); + } + + :host([elevation="4"]) { + mixin(--shadow-elevation-4); + } + + :host([elevation="5"]) { + mixin(--shadow-elevation-5); + } + </style> + <template> + <content></content> + </template> +</dom-module> +<script> + Polymer({ + is: 'paper-card', + + enableCustomStyleProperties: true, + + properties: { + + /** + * The z-depth of this card, from 0-5. Setting to 0 will remove the + * shadow, and each increasing number greater than 0 will be "deeper" + * than the last. + * + * @attribute elevation + * @type number + * @default 1 + */ + elevation: { + type: Number, + reflectToAttribute: true, + value: 1 + }, + + /** + * Set this to true to animate the shadow when setting a new + * `elevation` value. + * + * @attribute animated + * @type boolean + * @default false + */ + animated: { + type: Boolean, + reflectToAttribute: true, + value: false + } + } + }); +</script>
diff --git a/third_party/polymer/v0_8/components/paper-checkbox/.bower.json b/third_party/polymer/v0_8/components/paper-checkbox/.bower.json new file mode 100644 index 0000000..5a0ef5aa --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-checkbox/.bower.json
@@ -0,0 +1,42 @@ +{ + "name": "paper-checkbox", + "version": "0.8.2", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-checkbox" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-checkbox", + "ignore": [], + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#~0.6.1", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^0.8.0" + }, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-ripple": "PolymerElements/paper-ripple#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "5e3c7d3b68bd13f711b1a6470ca1bda09f2dc9ae" + }, + "_source": "git://github.com/PolymerElements/paper-checkbox.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-checkbox" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-checkbox/.gitignore b/third_party/polymer/v0_8/components/paper-checkbox/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-checkbox/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/paper-checkbox/README.md b/third_party/polymer/v0_8/components/paper-checkbox/README.md new file mode 100644 index 0000000..0fb7283 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-checkbox/README.md
@@ -0,0 +1 @@ +# paper-checkbox
diff --git a/third_party/polymer/v0_8/components/paper-checkbox/bower.json b/third_party/polymer/v0_8/components/paper-checkbox/bower.json new file mode 100644 index 0000000..4f1f986 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-checkbox/bower.json
@@ -0,0 +1,34 @@ +{ + "name": "paper-checkbox", + "version": "0.8.0", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-checkbox" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-checkbox", + "ignore": [ + ], + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#~0.6.1", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^0.8.0" + }, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7", + "paper-ripple": "PolymerElements/paper-ripple#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-checkbox/index.html b/third_party/polymer/v0_8/components/paper-checkbox/index.html new file mode 100644 index 0000000..a2ad87c1 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-checkbox/index.html
@@ -0,0 +1,30 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> + <head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>paper-checkbox</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + + </head> + <body> + + <iron-doc-viewer></iron-doc-viewer> + + </body> +</html>
diff --git a/third_party/polymer/v0_8/components/paper-checkbox/metadata.html b/third_party/polymer/v0_8/components/paper-checkbox/metadata.html new file mode 100644 index 0000000..4d068e8 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-checkbox/metadata.html
@@ -0,0 +1,17 @@ +<!-- + @license + Copyright (c) 2014 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<x-meta id="paper-checkbox" label="Checkbox" group="Paper"> + <template> + <paper-checkbox label="click me"></paper-checkbox> + </template> + <template id="imports"> + <link rel="import" href="paper-checkbox.html"> + </template> +</x-meta>
diff --git a/third_party/polymer/v0_8/components/paper-checkbox/paper-checkbox.css b/third_party/polymer/v0_8/components/paper-checkbox/paper-checkbox.css new file mode 100644 index 0000000..b4fdad9 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-checkbox/paper-checkbox.css
@@ -0,0 +1,138 @@ +/* +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +*/ + +:host { + display: inline-block; + white-space: nowrap; +} + +.hidden { + display: none; +} + +#checkboxContainer { + display: inline-block; + position: relative; + width: 18px; + height: 18px; + cursor: pointer; + -webkit-transform: translateZ(0); + transform: translateZ(0); + vertical-align: middle; +} + +:host #ink { + position: absolute; + top: -15px; + left: -15px; + width: 48px; + height: 48px; + color: var(--paper-checkbox-unchecked-ink-color); +} + +:host #ink[checked] { + color: var(--paper-checkbox-checked-ink-color); +} + +:host #checkbox { + position: relative; + box-sizing: border-box; + height: 100%; + border: solid 2px; + border-color: var(--paper-checkbox-unchecked-color); + border-radius: 2px; + pointer-events: none; + -webkit-transition: background-color 140ms, border-color 140ms; + transition: background-color 140ms, border-color 140ms; +} + +/* checkbox checked animations */ +#checkbox.checked #checkmark { + -webkit-animation: checkmark-expand 140ms ease-out forwards; + animation: checkmark-expand 140ms ease-out forwards; +} + +@-webkit-keyframes checkmark-expand { + 0% { + top: 9px; + left: 6px; + width: 0px; + height: 0px; + } + 100% { + top: -1px; + left: 4px; + width: 5px; + height: 10px; + } +} + +@keyframes checkmark-expand { + 0% { + top: 9px; + left: 6px; + width: 0px; + height: 0px; + } + 100% { + top: -1px; + left: 4px; + width: 5px; + height: 10px; + } +} + +:host #checkbox.checked { + background-color: var(--paper-checkbox-checked-color); + border-color: var(--paper-checkbox-checked-color); +} + +:host #checkmark { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + position: absolute; + top: -1px; + left: 4px; + width: 5px; + height: 10px; + border-style: solid; + border-top: none; + border-left: none; + border-right-width: 2px; + border-bottom-width: 2px; + border-color: white; +} + +/* label */ +#checkboxLabel { + position: relative; + display: inline-block; + vertical-align: middle; + padding-left: 8px; + white-space: normal; + pointer-events: none; +} + +#checkboxLabel[hidden] { + display: none; +} + +/* disabled state */ +:host([disabled]) { + pointer-events: none; +} + +:host([disabled]) #checkbox { + opacity: 0.33; + border-color: var(--paper-checkbox-unchecked-color); +} + +:host([disabled][checked]) #checkbox { + background-color: var(--paper-checkbox-unchecked-color); +}
diff --git a/third_party/polymer/v0_8/components/paper-checkbox/paper-checkbox.html b/third_party/polymer/v0_8/components/paper-checkbox/paper-checkbox.html new file mode 100644 index 0000000..84bb03f --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-checkbox/paper-checkbox.html
@@ -0,0 +1,177 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-ripple/paper-ripple.html"> +<link rel="import" href="../paper-styles/default-theme.html"> + +<!-- +`paper-checkbox` is a button that can be either checked or unchecked. User +can tap the checkbox to check or uncheck it. Usually you use checkboxes +to allow user to select multiple options from a set. If you have a single +ON/OFF option, avoid using a single checkbox and use `paper-toggle-button` +instead. + +Example: + + <paper-checkbox>label</paper-checkbox> + + <paper-checkbox checked> label</paper-checkbox> + +Styling a checkbox: + +<style is="x-style"> + * { + /* Unhecked state colors. */ + --paper-checkbox-unchecked-color: #5a5a5a; + --paper-checkbox-unchecked-ink-color: #5a5a5a; + + /* Checked state colors. */ + --paper-checkbox-checked-color: #009688; + --paper-checkbox-checked-ink-color: #009688; + } +</style> + +@group Paper Elements +@class paper-checkbox +--> + +/* TODO: This needs to use core-focusable when it's ready. */ +<dom-module id="paper-checkbox"> + <style is="x-style"> + * { + --paper-checkbox-unchecked-color: var(--primary-text-color); + --paper-checkbox-unchecked-ink-color: var(--primary-text-color); + + --paper-checkbox-checked-color: var(--default-primary-color); + --paper-checkbox-checked-ink-color: var(--default-primary-color); + } + </style> + + <link rel="import" type="css" href="paper-checkbox.css"> + + <template> + + <div id="checkboxContainer"> + <paper-ripple id="ink" class="circle" recenters checked$="[[checked]]"></paper-ripple> + <div id="checkbox" class$="[[_computeCheckboxClass(checked)]]"> + <div id="checkmark" class$="[[_computeCheckmarkClass(checked)]]"></div> + </div> + </div> + + <div id="checkboxLabel" aria-hidden="true"><content></content></div> + + </template> +</dom-module> + +<script> + Polymer({ + is: 'paper-checkbox', + + // The custom properties shim is currently an opt-in feature. + enableCustomStyleProperties: true, + + hostAttributes: { + role: 'checkbox', + 'aria-checked': false, + tabindex: 0 + }, + + properties: { + /** + * Fired when the checked state changes due to user interaction. + * + * @event change + */ + + /** + * Fired when the checked state changes. + * + * @event iron-change + */ + + /** + * Gets or sets the state, `true` is checked and `false` is unchecked. + * + * @attribute checked + * @type boolean + * @default false + */ + checked: { + type: Boolean, + value: false, + reflectToAttribute: true, + observer: '_checkedChanged' + }, + + /** + * If true, the user cannot interact with this element. + * + * @attribute disabled + * @type boolean + * @default false + */ + disabled: { + type: Boolean + } + }, + + listeners: { + keydown: '_onKeyDown', + mousedown: '_onMouseDown' + }, + + ready: function() { + if (this.$.checkboxLabel.textContent == '') { + this.$.checkboxLabel.hidden = true; + } else { + this.setAttribute('aria-label', this.$.checkboxLabel.textContent); + } + }, + + _computeCheckboxClass: function(checked) { + if (checked) { + return 'checked'; + } + }, + + _computeCheckmarkClass: function(checked) { + if (!checked) { + return 'hidden'; + } + }, + + _onKeyDown: function(e) { + // Enter key. + if (e.keyCode === 13) { + this._onMouseDown(); + e.preventDefault(); + } + }, + + _onMouseDown: function() { + if (this.disabled) { + return; + } + + var old = this.checked; + this.checked = !this.checked; + + if (this.checked !== old) { + this.fire('iron-change'); + } + }, + + _checkedChanged: function() { + this.setAttribute('aria-checked', this.checked ? 'true' : 'false'); + this.fire('iron-change'); + } + }) +</script>
diff --git a/third_party/polymer/v0_8/components/paper-drawer-panel/.bower.json b/third_party/polymer/v0_8/components/paper-drawer-panel/.bower.json new file mode 100644 index 0000000..869778b --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-drawer-panel/.bower.json
@@ -0,0 +1,39 @@ +{ + "name": "paper-drawer-panel", + "version": "0.8.1", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-drawer-panel.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-drawer-panel", + "dependencies": { + "iron-selector": "PolymerElements/iron-selector#^0.8.0", + "iron-media-query": "PolymerElements/iron-media-query#^0.8.0", + "polymer": "Polymer/polymer#v0.8.0-rc.6" + }, + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "e7a396050ffee2fdbc2997133e50f2c60f64f154" + }, + "_source": "git://github.com/PolymerElements/paper-drawer-panel.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-drawer-panel" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-drawer-panel/.gitignore b/third_party/polymer/v0_8/components/paper-drawer-panel/.gitignore new file mode 100644 index 0000000..fbe05fc --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-drawer-panel/.gitignore
@@ -0,0 +1 @@ +bower_components/
diff --git a/third_party/polymer/v0_8/components/paper-drawer-panel/README.md b/third_party/polymer/v0_8/components/paper-drawer-panel/README.md new file mode 100644 index 0000000..91d479d --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-drawer-panel/README.md
@@ -0,0 +1 @@ +paper-drawer-panel
diff --git a/third_party/polymer/v0_8/components/paper-drawer-panel/bower.json b/third_party/polymer/v0_8/components/paper-drawer-panel/bower.json new file mode 100644 index 0000000..0c46b57 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-drawer-panel/bower.json
@@ -0,0 +1,30 @@ +{ + "name": "paper-drawer-panel", + "version": "0.8.0", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "index.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-drawer-panel.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-drawer-panel", + "dependencies": { + "iron-selector": "PolymerElements/iron-selector#^0.8.0", + "iron-media-query": "PolymerElements/iron-media-query#^0.8.0", + "polymer": "Polymer/polymer#v0.8.0-rc.6" + }, + "devDependencies": { + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-drawer-panel/index.html b/third_party/polymer/v0_8/components/paper-drawer-panel/index.html new file mode 100644 index 0000000..4f53214 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-drawer-panel/index.html
@@ -0,0 +1,35 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>paper-drawer-panel</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + + <style> + body { + margin: 16px; + } + </style> + +</head> +<body> + + <iron-doc-viewer src="paper-drawer-panel.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/paper-drawer-panel/paper-drawer-panel.html b/third_party/polymer/v0_8/components/paper-drawer-panel/paper-drawer-panel.html new file mode 100644 index 0000000..d7d930c7 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-drawer-panel/paper-drawer-panel.html
@@ -0,0 +1,725 @@ +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-media-query/iron-media-query.html"> +<link rel="import" href="../iron-selector/iron-selector.html"> + +<!-- +`paper-drawer-panel` contains a drawer panel and a main panel. The drawer +and the main panel are side-by-side with drawer on the left. When the browser +window size is smaller than the `responsiveWidth`, `paper-drawer-panel` +changes to narrow layout. In narrow layout, the drawer will be stacked on top +of the main panel. The drawer will slide in/out to hide/reveal the main +panel. + +Use the attribute `drawer` to indicate that the element is the drawer panel and +`main` to indicate that the element is the main panel. + +Example: + + <paper-drawer-panel> + <div drawer> Drawer panel... </div> + <div main> Main panel... </div> + </paper-drawer-panel> + +The drawer and the main panels are not scrollable. You can set CSS overflow +property on the elements to make them scrollable or use `paper-header-panel`. + +Example: + + <paper-drawer-panel> + <paper-header-panel drawer> + <paper-toolbar></paper-toolbar> + <div> Drawer content... </div> + </paper-header-panel> + <paper-header-panel main> + <paper-toolbar></paper-toolbar> + <div> Main content... </div> + </paper-header-panel> + </paper-drawer-panel> + +An element that should toggle the drawer will automatically do so if it's +given the `paper-drawer-toggle` attribute. Also this element will automatically +be hidden in wide layout. + +Example: + + <paper-drawer-panel> + <paper-header-panel drawer> + <paper-toolbar> + <div>Application</div> + </paper-toolbar> + <div> Drawer content... </div> + </paper-header-panel> + <paper-header-panel main> + <paper-toolbar> + <paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button> + <div>Title</div> + </paper-toolbar> + <div> Main content... </div> + </paper-header-panel> + </paper-drawer-panel> + +To position the drawer to the right, add `rightDrawer` attribute. + + <paper-drawer-panel rightDrawer> + <div drawer> Drawer panel... </div> + <div main> Main panel... </div> + </paper-drawer-panel> + +@group Polymer Elements +@element paper-drawer-panel +@homepage github.io +--> + +<dom-module id="paper-drawer-panel"> + + <style> + :host { + display: block; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: hidden; + } + + iron-selector > #drawer { + position: absolute; + top: 0; + left: 0; + height: 100%; + will-change: transform; + box-sizing: border-box; + -moz-box-sizing: border-box; + } + + .transition > #drawer { + transition: -webkit-transform ease-in-out 0.3s, width ease-in-out 0.3s; + transition: transform ease-in-out 0.3s, width ease-in-out 0.3s; + } + + /* + right-drawer: make drawer on the right side + */ + .right-drawer > #drawer { + left: auto; + right: 0; + } + + paper-drawer-panel #drawer > * { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + } + + iron-selector > #main { + position: absolute; + top: 0; + right: 0; + bottom: 0; + } + + .transition > #main { + transition: left ease-in-out 0.3s, padding ease-in-out 0.3s; + } + + .right-drawer > #main { + left: 0; + } + + .right-drawer.transition > #main { + transition: right ease-in-out 0.3s, padding ease-in-out 0.3s; + } + + #main > [main] { + height: 100%; + } + + #scrim { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: rgba(0, 0, 0, 0.3); + visibility: hidden; + opacity: 0; + transition: opacity ease-in-out 0.38s, visibility ease-in-out 0.38s; + } + + #edgeSwipeOverlay { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 20px; + } + + .right-drawer > #main > #edgeSwipeOverlay { + right: 0; + left: auto; + } + + /* + narrow layout + */ + .narrow-layout > #drawer.iron-selected { + box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.15); + } + + .right-drawer.narrow-layout > #drawer.iron-selected { + box-shadow: -2px 2px 4px rgba(0, 0, 0, 0.15); + } + + .narrow-layout > #drawer > ::content[select="[drawer]"] > * { + border: 0; + } + + .narrow-layout > #drawer:not(.iron-selected) { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); + } + + .right-drawer.narrow-layout > #drawer:not(.iron-selected) { + left: auto; + -webkit-transform: translateX(100%); + transform: translateX(100%); + } + + .narrow-layout > #main { + left: 0 !important; + padding: 0; + } + + .right-drawer.narrow-layout > #main { + left: 0; + right: 0; + padding: 0; + } + + .narrow-layout > #main:not(.iron-selected) > #scrim, + .dragging #scrim { + visibility: visible; + opacity: 1; + } + + .narrow-layout > #main > * { + margin: 0; + min-height: 100%; + left: 0; + right: 0; + box-sizing: border-box; + -moz-box-sizing: border-box; + } + + iron-selector:not(.narrow-layout) #main ::content [paper-drawer-toggle] { + display: none; + } + </style> + + <template> + <iron-media-query + on-query-matches-changed="onQueryMatchesChanged" + query="[[_computeMediaQuery(forceNarrow, responsiveWidth)]]"> + </iron-media-query> + + <iron-selector + attr-for-selected="id" + class$="[[_computeIronSelectorClass(narrow, transition, dragging, rightDrawer)]]" + on-iron-activate="onSelect" + selected="[[selected]]"> + + <div id="main" style$="[[_computeMainStyle(narrow, rightDrawer, drawerWidth)]]"> + <content select="[main]"></content> + <div id="scrim"></div> + <div id="edgeSwipeOverlay" + hidden$="[[_computeSwipeOverlayHidden(narrow, disableEdgeSwipe)]]"> + </div> + </div> + + <div id="drawer" style$="[[_computeDrawerStyle(drawerWidth)]]"> + <content select="[drawer]"></content> + </div> + + </iron-selector> + </template> + +</dom-module> + +<script> + + (function() { + + 'use strict'; + + function classNames(obj) { + var classNames = []; + for (var key in obj) { + if (obj.hasOwnProperty(key) && obj[key]) { + classNames.push(key); + } + } + + return classNames.join(' '); + } + + Polymer({ + + is: 'paper-drawer-panel', + + /** + * Fired when the narrow layout changes. + * + * @event paper-responsive-change + * @param {Object} detail + * @param {boolean} detail.narrow true if the panel is in narrow layout. + */ + + /** + * Fired when the selected panel changes. + * + * Listening for this event is an alternative to observing changes in the `selected` attribute. + * This event is fired both when a panel is selected and deselected. + * The `isSelected` detail property contains the selection state. + * + * @event paper-select + * @param {Object} detail + * @param {boolean} detail.isSelected true for selection and false for deselection + * @param {Object} detail.item the panel that the event refers to + */ + + properties: { + + /** + * The panel to be selected when `paper-drawer-panel` changes to narrow + * layout. + * + * @attribute defaultSelected + * @type string + * @default 'main' + */ + defaultSelected: { + type: String, + value: 'main' + }, + + /** + * If true, swipe from the edge is disable. + * + * @attribute disableEdgeSwipe + * @type boolean + * @default false + */ + disableEdgeSwipe: Boolean, + + /** + * If true, swipe to open/close the drawer is disabled. + * + * @attribute disableSwipe + * @type boolean + * @default false + */ + disableSwipe: Boolean, + + // Whether the user is dragging the drawer interactively. + dragging: { + value: false + }, + + /** + * Width of the drawer panel. + * + * @attribute drawerWidth + * @type string + * @default '256px' + */ + drawerWidth: { + type: String, + value: '256px' + }, + + // How many pixels on the side of the screen are sensitive to edge + // swipes and peek. + edgeSwipeSensitivity: { + value: 30 + }, + + /** + * If true, ignore `responsiveWidth` setting and force the narrow layout. + * + * @attribute forceNarrow + * @type boolean + * @default false + */ + forceNarrow: { + observer: 'forceNarrowChanged', + type: Boolean, + value: false + }, + + // Whether the browser has support for the transform CSS property. + hasTransform: { + value: function() { + return 'transform' in this.style; + } + }, + + // Whether the browser has support for the will-change CSS property. + hasWillChange: { + value: function() { + return 'willChange' in this.style; + } + }, + + /** + * Returns true if the panel is in narrow layout. This is useful if you + * need to show/hide elements based on the layout. + * + * @attribute narrow + * @type boolean + * @default false + */ + narrow: { + reflectToAttribute: true, + type: Boolean, + value: false + }, + + // Whether the drawer is peeking out from the edge. + peeking: false, + + /** + * Max-width when the panel changes to narrow layout. + * + * @attribute responsiveWidth + * @type string + * @default '640px' + */ + responsiveWidth: { + type: String, + value: '640px' + }, + + /** + * If true, position the drawer to the right. + * + * @attribute rightDrawer + * @type boolean + * @default false + */ + rightDrawer: { + type: Boolean, + value: false + }, + + /** + * The panel that is being selected. `drawer` for the drawer panel and + * `main` for the main panel. + * + * @attribute selected + * @type string + * @default null + */ + selected: { + reflectToAttribute: true, + type: String, + value: null + }, + + /** + * The attribute on elements that should toggle the drawer on tap, also elements will + * automatically be hidden in wide layout. + */ + drawerToggleAttribute: { + value: 'paper-drawer-toggle' + }, + + /** + * Whether the transition is enabled. + */ + transition: false, + + /** + * Starting X coordinate of a tracking gesture. It is non-null only between trackStart and + * trackEnd events. + */ + _startX: { + value: null + } + + }, + + listeners: { + click: 'onClick', + track: 'onTrack' + + // TODO: Implement tap handlers when taps are supported. + // + // down: 'downHandler', + // up: 'upHandler' + }, + + _computeIronSelectorClass: function(narrow, transition, dragging, rightDrawer) { + return classNames({ + dragging: dragging, + 'narrow-layout': narrow, + 'right-drawer': rightDrawer, + transition: transition + }); + }, + + _computeDrawerStyle: function(drawerWidth) { + return 'width:' + drawerWidth + ';'; + }, + + _computeMainStyle: function(narrow, rightDrawer, drawerWidth) { + var style = ''; + + style += 'left:' + ((narrow || rightDrawer) ? '0' : drawerWidth) + ';' + + if (rightDrawer) { + style += 'right:' + (narrow ? '' : drawerWidth) + ';'; + } else { + style += 'right:;' + } + + return style; + }, + + _computeMediaQuery: function(forceNarrow, responsiveWidth) { + return forceNarrow ? '' : '(max-width: ' + responsiveWidth + ')'; + }, + + _computeSwipeOverlayHidden: function(narrow, disableEdgeSwipe) { + return !narrow || disableEdgeSwipe; + }, + + onTrack: function(event) { + switch (event.detail.state) { + case 'end': + this.trackEnd(event); + break; + case 'move': + this.trackX(event); + break; + case 'start': + this.trackStart(event); + break; + } + }, + + ready: function() { + // Avoid transition at the beginning e.g. page loads and enable + // transitions only after the element is rendered and ready. + this.transition = true; + }, + + /** + * Toggles the panel open and closed. + * + * @method togglePanel + */ + togglePanel: function() { + if (this.isMainSelected()) { + this.openDrawer(); + } else { + this.closeDrawer(); + } + }, + + /** + * Opens the drawer. + * + * @method openDrawer + */ + openDrawer: function() { + this.selected = 'drawer'; + }, + + /** + * Closes the drawer. + * + * @method closeDrawer + */ + closeDrawer: function() { + this.selected = 'main'; + }, + + _responsiveChange: function(narrow) { + this.narrow = narrow; + + if (this.narrow) { + this.selected = this.defaultSelected; + } + + this.setAttribute('touch-action', this.swipeAllowed() ? 'pan-y' : ''); + this.fire('paper-responsive-change', {narrow: this.narrow}); + }, + + onQueryMatchesChanged: function(e) { + this._responsiveChange(e.detail.value); + }, + + forceNarrowChanged: function() { + this._responsiveChange(this.forceNarrow); + }, + + swipeAllowed: function() { + return this.narrow && !this.disableSwipe; + }, + + isMainSelected: function() { + return this.selected === 'main'; + }, + + startEdgePeek: function() { + this.width = this.$.drawer.offsetWidth; + this.moveDrawer(this.translateXForDeltaX(this.rightDrawer ? + -this.edgeSwipeSensitivity : this.edgeSwipeSensitivity)); + this.peeking = true; + }, + + stopEdgePeek: function() { + if (this.peeking) { + this.peeking = false; + this.moveDrawer(null); + } + }, + + // TODO: Implement tap handlers when taps are supported. + // + // downHandler: function(e) { + // if (!this.dragging && this.isMainSelected() && this.isEdgeTouch(e)) { + // this.startEdgePeek(); + // } + // }, + // + // upHandler: function(e) { + // this.stopEdgePeek(); + // }, + + onClick: function(e) { + var isTargetToggleElement = e.target && + this.drawerToggleAttribute && + e.target.hasAttribute(this.drawerToggleAttribute); + + if (isTargetToggleElement) { + this.togglePanel(); + } + }, + + isEdgeTouch: function(event) { + var x = event.detail.x; + + return !this.disableEdgeSwipe && this.swipeAllowed() && + (this.rightDrawer ? + x >= this.offsetWidth - this.edgeSwipeSensitivity : + x <= this.edgeSwipeSensitivity); + }, + + trackStart: function(event) { + if (this.swipeAllowed()) { + this.dragging = true; + this._startX = event.detail.x; + + if (this.isMainSelected()) { + this.dragging = this.peeking || this.isEdgeTouch(event); + } + + if (this.dragging) { + this.width = this.$.drawer.offsetWidth; + this.transition = false; + + // TODO: Re-enable when tap gestures are implemented. + // + // e.preventTap(); + } + } + }, + + translateXForDeltaX: function(deltaX) { + var isMain = this.isMainSelected(); + + if (this.rightDrawer) { + return Math.max(0, isMain ? this.width + deltaX : deltaX); + } else { + return Math.min(0, isMain ? deltaX - this.width : deltaX); + } + }, + + trackX: function(event) { + var dx = event.detail.x - this._startX; + + if (this.dragging) { + if (this.peeking) { + if (Math.abs(dx) <= this.edgeSwipeSensitivity) { + // Ignore trackx until we move past the edge peek. + return; + } + + this.peeking = false; + } + + this.moveDrawer(this.translateXForDeltaX(dx)); + } + }, + + trackEnd: function(event) { + if (this.dragging) { + var xDirection = (event.detail.x - this._startX) > 0; + + this.dragging = false; + this._startX = null; + this.transition = true; + this.moveDrawer(null); + + if (this.rightDrawer) { + this[(xDirection > 0) ? 'closeDrawer' : 'openDrawer'](); + } else { + this[(xDirection > 0) ? 'openDrawer' : 'closeDrawer'](); + } + } + }, + + transformForTranslateX: function(translateX) { + if (translateX === null) { + return ''; + } + + return this.hasWillChange ? 'translateX(' + translateX + 'px)' : + 'translate3d(' + translateX + 'px, 0, 0)'; + }, + + moveDrawer: function(translateX) { + var s = this.$.drawer.style; + + if (this.hasTransform) { + s.transform = this.transformForTranslateX(translateX); + } else { + s.webkitTransform = this.transformForTranslateX(translateX); + } + }, + + onSelect: function(e) { + e.preventDefault(); + this.selected = e.detail.selected; + } + + }); + + }()); + +</script>
diff --git a/third_party/polymer/v0_8/components/paper-input/.bower.json b/third_party/polymer/v0_8/components/paper-input/.bower.json new file mode 100644 index 0000000..9b2481a --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/.bower.json
@@ -0,0 +1,44 @@ +{ + "name": "paper-input", + "version": "0.8.1", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": [ + "paper-input.html" + ], + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-input.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-input", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-input": "PolymerElements/iron-input#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.6", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^0.8.2", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + }, + "_release": "0.8.1", + "_resolution": { + "type": "version", + "tag": "v0.8.1", + "commit": "a761e0a4f9abac125d7c150e71633fd6bdc07616" + }, + "_source": "git://github.com/PolymerElements/paper-input.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-input" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-input/.gitignore b/third_party/polymer/v0_8/components/paper-input/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/paper-input/README.md b/third_party/polymer/v0_8/components/paper-input/README.md new file mode 100644 index 0000000..4bb13fc90 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/README.md
@@ -0,0 +1,3 @@ +# paper-input + +`<paper-input>` is a Material Design text field.
diff --git a/third_party/polymer/v0_8/components/paper-input/bower.json b/third_party/polymer/v0_8/components/paper-input/bower.json new file mode 100644 index 0000000..39d3ff0 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/bower.json
@@ -0,0 +1,35 @@ +{ + "name": "paper-input", + "version": "0.8.0", + "authors": [ + "The Polymer Authors" + ], + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": [ + "paper-input.html" + ], + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-input.git" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-input", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-input": "PolymerElements/iron-input#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.6", + "iron-test-helpers": "PolymerElements/iron-test-helpers#^0.8.2", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.3", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-input/index.html b/third_party/polymer/v0_8/components/paper-input/index.html new file mode 100644 index 0000000..d2f28bbc --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/index.html
@@ -0,0 +1,28 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <title>paper-input</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="paper-input.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/paper-input/paper-input-char-counter.html b/third_party/polymer/v0_8/components/paper-input/paper-input-char-counter.html new file mode 100644 index 0000000..38c3c77 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/paper-input-char-counter.html
@@ -0,0 +1,97 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-styles/paper-styles.html"> + +<!-- +`<paper-input-char-counter>` is a character counter for use with `<paper-input-container>`. +--> +<dom-module id="paper-input-char-counter"> + + <style> + + :host { + display: inline-block; + float: right; + + mixin(--paper-input-container-add-on); + mixin(--paper-input-container-add-on-font); + + mixin(--paper-input-char-counter); + } + + </style> + + <template> + + <span>[[charCounter]]</span> + + </template> + +</dom-module> + +<script> + +(function() { + + Polymer({ + + is: 'paper-input-char-counter', + + enableCustomStyleProperties: true, + + hostAttributes: { + 'add-on': '' + }, + + properties: { + + /** + * The associated input element. + */ + inputElement: { + type: Object + }, + + /** + * The current value of the input element. + */ + value: { + type: String + }, + + /** + * The character counter string. + */ + charCounter: { + computed: '_computeCharCounter(inputElement,value)', + type: String + } + + }, + + attached: function() { + this.fire('addon-attached'); + }, + + _computeCharCounter: function(inputElement,value) { + var str = value.length; + if (inputElement.hasAttribute('maxlength')) { + str += '/' + inputElement.maxLength; + } + return str; + } + + }); + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/paper-input/paper-input-container.html b/third_party/polymer/v0_8/components/paper-input/paper-input-container.html new file mode 100644 index 0000000..92e0b99 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/paper-input-container.html
@@ -0,0 +1,397 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-styles/paper-styles.html"> + +<style is="x-style"> + + * { + + --paper-input-container-font: var(--paper-font-subhead); + --paper-input-container-floating-label-font: var(--paper-font-caption); + --paper-input-container-add-on-font: var(--paper-font-caption); + + --paper-input-container-focus-color: var(--default-primary-color); + --paper-input-container-color: var(--secondary-text-color); + --paper-input-container-invalid-color: var(--google-red-500); + --paper-input-container-input-color: var(--primary-text-color); + + } + +</style> + +<!-- +`<paper-input-container>` wraps an `<input>` and `<label>` element, decorating +them following the [Material Design spec](http://www.google.com/design/spec/components/text-fields.html#text-fields-single-line-text-field) + +For example: + + <paper-input-container> + <label>email address</label> + <input type="email"> + </paper-input-container> + +--> +<dom-module id="paper-input-container"> + + <style> + + :host { + display: block; + padding: 8px 0; + + --mixin(--paper-input-container); + } + + .floated-label-placeholder { + mixin(--paper-input-container-label-font); + } + + .focused-line { + height: 2px; + + -webkit-transform-origin: center center; + transform-origin: center center; + -webkit-transform: scale3d(0,1,1); + transform: scale3d(0,1,1); + + background: var(--paper-input-container-focus-color); + } + + .is-highlighted .focused-line { + -webkit-transform: none; + transform: none; + -webkit-transition: -webkit-transform 0.25s; + transition: transform 0.25s; + + mixin(--paper-transition-easing); + } + + .is-invalid .focused-line { + background: var(--paper-input-container-invalid-color); + + -webkit-transform: none; + transform: none; + -webkit-transition: -webkit-transform 0.25s; + transition: transform 0.25s; + + mixin(--paper-transition-easing); + } + + .unfocused-line { + height: 1px; + background: var(--paper-input-container-color); + } + + .input-content ::content label, + .input-content ::content .paper-input-label { + position: absolute; + top: 0; + right: 0; + left: 0; + font: inherit; + color: var(--paper-input-container-color); + + mixin(--paper-input-container-font); + + mixin(--paper-input-container-label); + } + + .input-content.label-is-floating ::content label, + .input-content.label-is-floating ::content .paper-input-label { + -webkit-transform: translate3d(0, -75%, 0) scale(0.75); + transform: translate3d(0, -75%, 0) scale(0.75); + -webkit-transform-origin: left top; + transform-origin: left top; + -webkit-transition: -webkit-transform 0.25s; + transition: transform 0.25s; + + mixin(--paper-transition-easing); + } + + .input-content.label-is-highlighted ::content label, + .input-content.label-is-highlighted ::content .paper-input-label { + color: var(--paper-input-container-focus-color); + } + + .input-content.is-invalid ::content label, + .input-content.is-invalid ::content .paper-input-label { + color: var(--paper-input-container-invalid-color); + } + + .input-content.label-is-hidden ::content label, + .input-content.label-is-hidden ::content .paper-input-label { + visibility: hidden; + } + + .input-content ::content input, + .input-content ::content textarea, + .input-content ::content .paper-input-input { + position: relative; /* to make a stacking context */ + outline: none; + color: var(--paper-input-container-input-color); + + mixin(--paper-input-container-floating-label-font); + } + + .input-content ::content input, + .input-content ::content textarea { + padding: 0; + width: 100%; + background: transparent; + border: none; + + mixin(--paper-input-container-font); + + mixin(--paper-input-container-input); + } + + .input-content ::content textarea { + resize: none; + } + + .add-on-content.is-invalid ::content * { + color: var(--paper-input-container-invalid-color); + } + + .add-on-content.is-highlighted ::content * { + color: var(--paper-input-container-focus-color); + } + + </style> + + <template> + + <template is="x-if" if="[[!noLabelFloat]]"> + <div class="floated-label-placeholder"> </div> + </template> + + <div class$="[[_computeInputContentClass(noLabelFloat,focused,_inputHasContent,_inputIsInvalid)]]"> + <content select=":not([add-on])"></content> + </div> + + <div class$="[[_computeUnderlineClass(focused,_inputIsInvalid)]]"> + <div class="unfocused-line fit"></div> + <div class="focused-line fit"></div> + </div> + + <div class$="[[_computeAddOnContentClass(focused,_inputIsInvalid)]]"> + <content id="addOnContent" select="[add-on]"></content> + </div> + + </template> + +</dom-module> + +<script> +(function() { + + Polymer({ + + is: 'paper-input-container', + + enableCustomStyleProperties: true, + + properties: { + + /** + * Set to true to disable the floating label. + */ + noLabelFloat: { + type: Boolean, + value: false + }, + + /** + * The attribute to listen for value changes on. + */ + attrForValue: { + type: String, + value: 'bind-value' + }, + + /** + * Set to true to auto-validate the input value. + */ + autoValidate: { + type: Boolean, + value: false + }, + + /** + * True if the input has focus. + */ + focused: { + readOnly: true, + type: Boolean, + value: false + }, + + _addons: { + type: Array, + value: function() { + return []; + } + }, + + _inputHasContent: { + type: Boolean, + value: false + }, + + _inputIsInvalid: { + type: Boolean, + value: false + }, + + _inputSelector: { + type: String, + value: 'input,textarea,.paper-input-input' + }, + + _boundOnFocus: { + type: Function, + value: function() { + return this._onFocus.bind(this); + } + }, + + _boundOnBlur: { + type: Function, + value: function() { + return this._onBlur.bind(this); + } + }, + + _boundValueChanged: { + type: Function, + value: function() { + return this._onValueChanged.bind(this); + } + } + + }, + + listeners: { + 'addon-attached': '_onAddonAttached', + 'input': '_onInput' + }, + + get _valueChangedEvent() { + return this.attrForValue + '-changed'; + }, + + get _propertyForValue() { + return Polymer.CaseMap.dashToCamelCase(this.attrForValue); + }, + + get _inputElement() { + return Polymer.dom(this).querySelector(this._inputSelector); + }, + + ready: function() { + this.addEventListener('focus', this._boundOnFocus, true); + this.addEventListener('blur', this._boundOnBlur, true); + this.addEventListener(this._valueChangedEvent, this._boundValueChanged, true); + }, + + attached: function() { + this._handleInput(this._inputElement); + }, + + _onAddonAttached: function(event) { + this._addons.push(event.target); + this._handleInput(this._inputElement); + }, + + _onFocus: function() { + this._setFocused(true); + }, + + _onBlur: function() { + this._setFocused(false); + }, + + _onInput: function(event) { + this._handleInput(event.target); + }, + + _onValueChanged: function(event) { + this._handleInput(event.target); + }, + + _handleInput: function(inputElement) { + var value = inputElement[this._propertyForValue] || inputElement.value; + var valid = inputElement.checkValidity(); + + // type="number" hack needed because this.value is empty until it's valid + if (value || inputElement.type === 'number' && !valid) { + this._inputHasContent = true; + } else { + this._inputHasContent = false; + } + + if (this.autoValidate) { + this._inputIsInvalid = !valid; + } + + // notify add-ons + for (var addon, i = 0; addon = this._addons[i]; i++) { + // need to set all of these, or call method... thanks input type="number"! + addon.inputElement = inputElement; + addon.value = value; + addon.invalid = !valid; + } + }, + + _computeInputContentClass: function(noLabelFloat, focused, _inputHasContent, _inputIsInvalid) { + var cls = 'input-content relative'; + if (!noLabelFloat) { + if (_inputHasContent) { + cls += ' label-is-floating'; + if (_inputIsInvalid) { + cls += ' is-invalid'; + } else if (focused) { + cls += " label-is-highlighted"; + } + } + } else { + if (_inputHasContent) { + cls += ' label-is-hidden'; + } + } + return cls; + }, + + _computeUnderlineClass: function(focused, _inputIsInvalid) { + var cls = 'relative'; + if (_inputIsInvalid) { + cls += ' is-invalid'; + } else if (focused) { + cls += ' is-highlighted' + } + return cls; + }, + + _computeAddOnContentClass: function(focused, _inputIsInvalid) { + var cls = 'add-on-content'; + if (_inputIsInvalid) { + cls += ' is-invalid'; + } else if (focused) { + cls += ' is-highlighted' + } + return cls; + } + + }); + +})(); +</script>
diff --git a/third_party/polymer/v0_8/components/paper-input/paper-input-error.html b/third_party/polymer/v0_8/components/paper-input/paper-input-error.html new file mode 100644 index 0000000..fbdf2c7 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/paper-input-error.html
@@ -0,0 +1,83 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../paper-styles/paper-styles.html"> + +<!-- +`<paper-input-error>` is an error message for use with `<paper-input-container>`. +--> +<dom-module id="paper-input-error"> + + <style> + + :host { + /* need to use display: none for role="alert" */ + display: none; + float: left; + + color: var(--paper-input-container-invalid-color); + + mixin(--paper-input-container-add-on); + mixin(--paper-input-container-add-on-font); + + mixin(--paper-input-error); + } + + :host([invalid]) { + display: inline-block; + }; + + </style> + + <template> + + <content></content> + + </template> + +</dom-module> + +<script> + +(function() { + + Polymer({ + + is: 'paper-input-error', + + enableCustomStyleProperties: true, + + hostAttributes: { + 'add-on': '', + 'role': 'alert' + }, + + properties: { + + /** + * Set to true to show the error. + */ + invalid: { + reflectToAttribute: true, + type: Boolean + } + + }, + + attached: function() { + this.fire('addon-attached'); + } + + }) + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/paper-input/paper-input.html b/third_party/polymer/v0_8/components/paper-input/paper-input.html new file mode 100644 index 0000000..3f80d21 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-input/paper-input.html
@@ -0,0 +1,151 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-input/iron-input.html"> +<link rel="import" href="paper-input-container.html"> +<link rel="import" href="paper-input-error.html"> +<link rel="import" href="paper-input-char-counter.html"> + +<!-- +`<paper-input>` is a text field. +--> + +<dom-module id="paper-input"> + + <template> + + <paper-input-container no-label-float$="[[noLabelFloat]]" auto-validate$="[[autoValidate]]"> + + <template is="x-if" if="[[label]]"> + <label>[[parent.label]]</label> + </template> + + <input is="iron-input" id="input" bind-value="{{value}}" prevent-invalid-input="[[preventInvalidInput]]" type$="[[type]]" pattern$="[[pattern]]" maxlength$="[[maxlength]]" required$="[[required]]"> + + <template is="x-if" if="[[errorMessage]]"> + <paper-input-error>[[parent.errorMessage]]</paper-input-error> + </template> + + <template is="x-if" if="[[charCounter]]"> + <paper-input-char-counter></paper-input-char-counter> + </template> + + </paper-input-container> + + </template> + +</dom-module> + +<script> + +(function() { + + Polymer({ + + is: 'paper-input', + + properties: { + + /** + * The label for this input. + */ + label: { + type: String + }, + + /** + * The value for this input. + */ + value: { + notify: true, + type: String + }, + + /** + * Set to true to prevent the user from entering invalid input. + */ + preventInvalidInput: { + type: Boolean + }, + + /** + * The type of the input. The supported types are `text`, `number` and `password`. + */ + type: { + type: String + }, + + /** + * A pattern to validate the `input` with. + */ + pattern: { + type: String + }, + + /** + * Set to true to mark the input as required. + */ + required: { + type: Boolean, + value: false + }, + + /** + * The maximum length of the input value. + */ + maxlength: { + type: Number + }, + + /** + * The error message to display when the input is invalid. + */ + errorMessage: { + type: String + }, + + /** + * Set to true to show a character counter. + */ + charCounter: { + type: Boolean, + value: false + }, + + /** + * Set to true to disable the floating label. + */ + noLabelFloat: { + type: Boolean, + value: false + }, + + /** + * Set to true to auto-validate the input value. + */ + autoValidate: { + type: Boolean, + value: false + } + + }, + + /** + * Returns a reference to the input element. + */ + get inputElement() { + return this.$.input; + } + + }) + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/paper-menu/.bower.json b/third_party/polymer/v0_8/components/paper-menu/.bower.json new file mode 100644 index 0000000..3bb8166 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-menu/.bower.json
@@ -0,0 +1,40 @@ +{ + "name": "paper-menu", + "version": "0.8.2", + "authors": "The Polymer Authors", + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "paper-menu.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-menu" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-menu", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-selector": "PolymerElements/iron-selector#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "paper-item": "PolymerElements/paper-item#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.0", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + }, + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "a10381891339cb021d1215bd3bcf0eb96251acd9" + }, + "_source": "git://github.com/PolymerElements/paper-menu.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-menu" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-menu/.gitignore b/third_party/polymer/v0_8/components/paper-menu/.gitignore new file mode 100644 index 0000000..fbe05fc --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-menu/.gitignore
@@ -0,0 +1 @@ +bower_components/
diff --git a/third_party/polymer/v0_8/components/paper-menu/README.md b/third_party/polymer/v0_8/components/paper-menu/README.md new file mode 100644 index 0000000..6360e79 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-menu/README.md
@@ -0,0 +1 @@ +# paper-menu
diff --git a/third_party/polymer/v0_8/components/paper-menu/bower.json b/third_party/polymer/v0_8/components/paper-menu/bower.json new file mode 100644 index 0000000..9f5a25e --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-menu/bower.json
@@ -0,0 +1,31 @@ +{ + "name": "paper-menu", + "version": "0.8.0", + "authors": "The Polymer Authors", + "keywords": [ + "web-components", + "web-component", + "polymer" + ], + "main": "paper-menu.html", + "private": true, + "repository": { + "type": "git", + "url": "git://github.com/PolymerElements/paper-menu" + }, + "license": "MIT", + "homepage": "https://github.com/PolymerElements/paper-menu", + "ignore": [], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7", + "iron-selector": "PolymerElements/iron-selector#^0.8.0", + "paper-styles": "PolymerElements/paper-styles#^0.8.0" + }, + "devDependencies": { + "iron-doc-viewer": "PolymerElements/iron-doc-viewer#^0.8.0", + "paper-item": "PolymerElements/paper-item#^0.8.0", + "test-fixture": "PolymerElements/test-fixture#^0.8.0", + "web-component-tester": "Polymer/web-component-tester#^2.2.0", + "webcomponentsjs": "Polymer/webcomponentsjs#^0.6.0" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-menu/index.html b/third_party/polymer/v0_8/components/paper-menu/index.html new file mode 100644 index 0000000..1cf71f5 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-menu/index.html
@@ -0,0 +1,38 @@ +<!doctype html> +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> + + <title>paper-menu</title> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + + <link rel="import" href="../polymer/polymer.html"> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + + <style> + + body { + margin: 16px; + } + + </style> + +</head> +<body> + + <iron-doc-viewer src="paper-menu.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/paper-menu/paper-menu.html b/third_party/polymer/v0_8/components/paper-menu/paper-menu.html new file mode 100644 index 0000000..c9cf583 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-menu/paper-menu.html
@@ -0,0 +1,329 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> +<link rel="import" href="../iron-selector/iron-selectable.html"> +<link rel="import" href="../paper-styles/paper-styles.html"> + +<!-- +@element paper-menu +--> + +<dom-module id="paper-menu"> + + <style> + + :host { + padding: 8px 0; + + background: var(--primary-background-color); + color: var(--primary-text-color); + + mixin(--paper-menu); + } + + :host > ::content > [disabled] { + color: var(--disabled-text-color); + } + + :host > ::content > .iron-selected { + position: relative; + } + + :host > ::content > .iron-selected::after { + mixin(--fit); + + background: currentColor; + /* FIXME move to paper-styles for next widget */ + opacity: 0.12; + content: ''; + + mixin(--paper-menu-selected-item); + } + + :host > ::content > .iron-selected[colored]::after { + opacity: 0.26; + + mixin(--paper-menu-colored-selected-item); + } + + </style> + + <template> + + <content></content> + + </template> + +</dom-module> + +<script> + +(function() { + + // FIXME menu control should be refactored to a more general element + + Polymer({ + + is: 'paper-menu', + + enableCustomStyleProperties: true, + + mixins: [ + Polymer.Core.Selectable + ], + + properties: { + + /** + * Returns the currently focused item. + * + * @attribute focusedItem + * @type Object + */ + focusedItem: { + observer: 'focusedItemChanged', + readOnly: true, + type: Object + }, + + /** + * The attribute to use on menu items to look up the item title. Typing the first + * letter of an item when the menu is open focuses that item. If unset, `textContent` + * will be used. + * + * @attribute attrForItemTitle + * @type String + */ + attrForItemTitle: { + type: String + }, + + /***********************************************************************/ + /* Polymer.Core.Selectable */ + /***********************************************************************/ + + /** + * If you want to use the attribute value of an element for `selected` instead of the index, + * set this to the name of the attribute. + * + * @attribute attrForSelected + * @type String + */ + attrForSelected: { + type: String + }, + + /** + * If true, multiple selections are allowed. + * + * @attribute multi + * @type Boolean + * @default false + */ + multi: { + observer: 'multiChanged', + type: Boolean, + value: false + }, + + /** + * Gets or sets the selected element. The default is to use the index of the item. In + * multi-selection this should be an array of values. + * + * @attribute selected + * @type String|Array + */ + selected: { + notify: true, + observer: 'selectedChanged', + type: String + }, + + /** + * Returns the currently selected item. In multi-selection this returns an array of + * selected items. + * + * @attribute selectedItem + * @type Object|Array + */ + selectedItem: { + notify: true, + observer: 'selectedItemChanged', + readOnly: true, + type: Object + }, + + /** + * The event that would be fired from the item to indicate it is being selected. Set this + * to empty string or null if you don't want to listen for any events. + * + * @attribute activateEvent + * @type String + * @default 'click' + */ + activateEvent: { + observer: 'activateEventChanged', + type: String, + value: 'click' + }, + + /** + * If this is set, only items with local name that matches the `selectable` are selectable. + * + * @attribute selectable + * @type String + */ + selectable: { + type: String + } + + }, + + hostAttributes: { + 'role': 'menu', + 'tabindex': '0' + }, + + listeners: { + 'focus': 'onFocus', + 'keydown': 'onKeydown' + }, + + created: function() { + this._bindActivateHandler = this.activateHandler.bind(this); + }, + + attached: function() { + this.selectableAttached(); + }, + + detached: function() { + this.selectableDetached(); + this.removeListener(this.activateEvent); + }, + + addListener: function(eventName) { + if (eventName) { + this.addEventListener(eventName, this._bindActivateHandler); + } + }, + + removeListener: function(eventName) { + if (eventName) { + this.removeEventListener(eventName, this._bindActivateHandler); + } + }, + + activateEventChanged: function(eventName, old) { + this.removeListener(old); + this.addListener(eventName); + }, + + focusedItemChanged: function(focusedItem, old) { + old && old.setAttribute('tabindex', '-1'); + if (focusedItem) { + focusedItem.setAttribute('tabindex', '0'); + focusedItem.focus(); + } + }, + + multiChanged: function(multi) { + this.selection.multi = multi; + this.selectedChanged(this.selected); + }, + + selectedChanged: function(selected, old) { + this._selectedChanged(selected, old); + }, + + selectedItemChanged: function(selectedItem) { + this._setFocusedItem(Array.isArray(selectedItem) ? selectedItem[0] : selectedItem); + }, + + activateHandler: function(e) { + var t = e.target; + var items = this.items; + while (t && t != this) { + var i = items.indexOf(t); + if (i >= 0) { + if (t.hasAttribute('disabled')) { + return; + } + var value = this.indexToValue(i); + if (!this.fire('iron-activate', {selected: value, item: t}).defaultPrevented) { + this.select(value); + } + return; + } + t = t.parentNode; + } + }, + + onFocus: function(event) { + // clear the cached focus item + this._setFocusedItem(null); + // focus the selected item when the menu receives focus, or the first item + // if no item is selected + var selectedItem = this.selectedItem; + selectedItem = Array.isArray(selectedItem) ? selectedItem[0] : selectedItem; + if (selectedItem) { + this._setFocusedItem(selectedItem); + } else { + this._setFocusedItem(this.items[0]); + } + }, + + onKeydown: function(event) { + // FIXME want to define these somewhere, core-a11y-keys? + var DOWN = 40; + var UP = 38; + var ESC = 27; + var ENTER = 13; + if (event.keyCode === DOWN) { + // up and down arrows moves the focus + this.focusNext(); + } else if (event.keyCode === UP) { + this.focusPrevious(); + } else if (event.keyCode === ESC) { + // esc blurs the control + this.focusedItem.blur(); + } else if (event.keyCode === ENTER) { + // enter activates the item + this.activateHandler(event); + } else { + // all other keys focus the menu item starting with that character + for (var i = 0, item; item = this.items[i]; i++) { + var attr = this.attrForItemTitle || 'textContent'; + var title = item[attr] || item.getAttribute(attr); + if (title && title.charAt(0).toLowerCase() === String.fromCharCode(event.keyCode).toLowerCase()) { + this._setFocusedItem(item); + break; + } + } + } + }, + + focusPrevious: function() { + var length = this.items.length; + var index = (Number(this.indexOf(this.focusedItem)) - 1 + length) % length; + this._setFocusedItem(this.items[index]); + }, + + focusNext: function() { + var index = (Number(this.indexOf(this.focusedItem)) + 1) % this.items.length; + this._setFocusedItem(this.items[index]); + } + + }); + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/paper-ripple/.bower.json b/third_party/polymer/v0_8/components/paper-ripple/.bower.json new file mode 100644 index 0000000..62815ae --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-ripple/.bower.json
@@ -0,0 +1,27 @@ +{ + "name": "paper-ripple", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-icons": "polymerelements/iron-icons#^0.8.0", + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.3" + }, + "homepage": "https://github.com/PolymerElements/paper-ripple", + "version": "0.8.2", + "_release": "0.8.2", + "_resolution": { + "type": "version", + "tag": "v0.8.2", + "commit": "7f1399055ff05cc37e3b577d97d00d664816e1d2" + }, + "_source": "git://github.com/PolymerElements/paper-ripple.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-ripple" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-ripple/.gitignore b/third_party/polymer/v0_8/components/paper-ripple/.gitignore new file mode 100644 index 0000000..8d4ae25 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-ripple/.gitignore
@@ -0,0 +1 @@ +bower_components
diff --git a/third_party/polymer/v0_8/components/paper-ripple/README.md b/third_party/polymer/v0_8/components/paper-ripple/README.md new file mode 100644 index 0000000..a4ca437 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-ripple/README.md
@@ -0,0 +1,4 @@ +paper-ripple +============ + +See the [component page](http://www.polymer-project.org/docs/elements/paper-elements.html#paper-ripple) for more information.
diff --git a/third_party/polymer/v0_8/components/paper-ripple/bower.json b/third_party/polymer/v0_8/components/paper-ripple/bower.json new file mode 100644 index 0000000..5e261d5 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-ripple/bower.json
@@ -0,0 +1,16 @@ +{ + "name": "paper-ripple", + "private": true, + "dependencies": { + "polymer": "polymer/polymer#v0.8.0-rc.7" + }, + "devDependencies": { + "iron-doc-viewer": "polymerelements/iron-doc-viewer#^0.8.0", + "iron-icon": "polymerelements/iron-icon#^0.8.0", + "iron-icons": "polymerelements/iron-icons#^0.8.0", + "paper-styles": "polymerelements/paper-styles#^0.8.0", + "test-fixture": "polymerelements/test-fixture#^0.8.0", + "webcomponentsjs": "webcomponents/webcomponentsjs#^0.6.0", + "web-component-tester": "~2.2.3" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-ripple/index.html b/third_party/polymer/v0_8/components/paper-ripple/index.html new file mode 100644 index 0000000..94102ef3 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-ripple/index.html
@@ -0,0 +1,26 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <title>paper-ripple</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="paper-ripple.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/paper-ripple/paper-ripple.html b/third_party/polymer/v0_8/components/paper-ripple/paper-ripple.html new file mode 100644 index 0000000..3b0f24b4 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-ripple/paper-ripple.html
@@ -0,0 +1,620 @@ +<!-- +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +`paper-ripple` provides a visual effect that other paper elements can +use to simulate a rippling effect emanating from the point of contact. The +effect can be visualized as a concentric circle with motion. + +Example: + + <paper-ripple></paper-ripple> + +`paper-ripple` listens to "down" and "up" events so it would display ripple +effect when touches on it. You can also defeat the default behavior and +manually route the down and up actions to the ripple element. Note that it is +important if you call downAction() you will have to make sure to call upAction() +so that `paper-ripple` would end the animation loop. + +Example: + + <paper-ripple id="ripple" style="pointer-events: none;"></paper-ripple> + ... + downAction: function(e) { + this.$.ripple.downAction({x: e.x, y: e.y}); + }, + upAction: function(e) { + this.$.ripple.upAction(); + } + +Styling ripple effect: + + Use CSS color property to style the ripple: + + paper-ripple { + color: #4285f4; + } + + Note that CSS color property is inherited so it is not required to set it on + the `paper-ripple` element directly. + +By default, the ripple is centered on the point of contact. Apply the `recenters` +attribute to have the ripple grow toward the center of its container. + + <paper-ripple recenters></paper-ripple> + +Apply `circle` class to make the rippling effect within a circle. + + <paper-ripple class="circle"></paper-ripple> + +@group Paper Elements +@element paper-ripple +@homepage github.io +--> + +<!-- +Fired when the animation finishes. This is useful if you want to wait until the ripple +animation finishes to perform some action. + +@event transitionend +@param {Object} detail +@param {Object} detail.node The animated node +--> + +<link rel="import" href="../polymer/polymer.html"> + +<dom-module id="paper-ripple"> + <style> + :host { + display: block; + position: absolute; + border-radius: inherit; + overflow: hidden; + top: 0; + left: 0; + right: 0; + bottom: 0; + + /* This resolves a rendering issue in Chrome 40 where the + ripple is not properly clipped by its parent (which may have + rounded corners. See: http://jsbin.com/temexa/4 */ + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } + + :host([noink]) { + pointer-events: none; + } + + #background, + #waves, + .wave-container, + .wave { + pointer-events: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + #background, + .wave { + opacity: 0; + } + + #waves, + .wave { + overflow: hidden; + } + + .wave-container, + .wave { + border-radius: 50%; + } + + :host(.circle) #background, + :host(.circle) #waves { + border-radius: 50%; + } + + :host(.circle) .wave-container { + overflow: hidden; + } + + </style> + <template> + <div id="background"></div> + <div id="waves"></div> + </template> +</dom-module> +<script> + (function() { + var Utility = { + cssColorWithAlpha: function(cssColor, alpha) { + var parts = cssColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/); + + if (typeof alpha == 'undefined') { + alpha = 1; + } + + if (!parts) { + return 'rgba(255, 255, 255, ' + alpha + ')'; + } + + return 'rgba(' + parts[1] + ', ' + parts[2] + ', ' + parts[3] + ', ' + alpha + ')'; + }, + + distance: function(x1, y1, x2, y2) { + var xDelta = (x1 - x2); + var yDelta = (y1 - y2); + + return Math.sqrt(xDelta * xDelta + yDelta * yDelta); + }, + + now: (function() { + if (window.performance && window.performance.now) { + return window.performance.now.bind(window.performance); + } + + return Date.now; + })() + }; + + /** + * @param {HTMLElement} element + * @constructor + */ + function ElementMetrics(element) { + this.element = element; + this.width = this.boundingRect.width; + this.height = this.boundingRect.height; + + this.size = Math.max(this.width, this.height); + } + + ElementMetrics.prototype = { + get boundingRect () { + return this.element.getBoundingClientRect(); + }, + + furthestCornerDistanceFrom: function(x, y) { + var topLeft = Utility.distance(x, y, 0, 0); + var topRight = Utility.distance(x, y, this.width, 0); + var bottomLeft = Utility.distance(x, y, 0, this.height); + var bottomRight = Utility.distance(x, y, this.width, this.height); + + return Math.max(topLeft, topRight, bottomLeft, bottomRight); + } + }; + + /** + * @param {HTMLElement} element + * @constructor + */ + function Ripple(element) { + this.element = element; + this.color = window.getComputedStyle(element).color; + + this.wave = document.createElement('div'); + this.waveContainer = document.createElement('div'); + this.wave.style.backgroundColor = this.color; + this.wave.classList.add('wave'); + this.waveContainer.classList.add('wave-container'); + Polymer.dom(this.waveContainer).appendChild(this.wave); + + this.resetInteractionState(); + } + + Ripple.MAX_RADIUS = 300; + + Ripple.prototype = { + get recenters() { + return this.element.recenters; + }, + + get mouseDownElapsed() { + var elapsed; + + if (!this.mouseDownStart) { + return 0; + } + + elapsed = Utility.now() - this.mouseDownStart; + + if (this.mouseUpStart) { + elapsed -= this.mouseUpElapsed; + } + + return elapsed; + }, + + get mouseUpElapsed() { + return this.mouseUpStart ? + Utility.now () - this.mouseUpStart : 0; + }, + + get mouseDownElapsedSeconds() { + return this.mouseDownElapsed / 1000; + }, + + get mouseUpElapsedSeconds() { + return this.mouseUpElapsed / 1000; + }, + + get mouseInteractionSeconds() { + return this.mouseDownElapsedSeconds + this.mouseUpElapsedSeconds; + }, + + get initialOpacity() { + return this.element.initialOpacity; + }, + + get opacityDecayVelocity() { + return this.element.opacityDecayVelocity; + }, + + get radius() { + var width2 = this.containerMetrics.width * this.containerMetrics.width; + var height2 = this.containerMetrics.height * this.containerMetrics.height; + var waveRadius = Math.min( + Math.sqrt(width2 + height2), + Ripple.MAX_RADIUS + ) * 1.1 + 5; + + var duration = 1.1 - 0.2 * (waveRadius / Ripple.MAX_RADIUS); + var timeNow = this.mouseInteractionSeconds / duration; + var size = waveRadius * (1 - Math.pow(80, -timeNow)); + + return Math.abs(size); + }, + + get opacity() { + if (!this.mouseUpStart) { + return this.initialOpacity; + } + + return Math.max( + 0, + this.initialOpacity - this.mouseUpElapsedSeconds * this.opacityDecayVelocity + ); + }, + + get outerOpacity() { + // Linear increase in background opacity, capped at the opacity + // of the wavefront (waveOpacity). + var outerOpacity = this.mouseUpElapsedSeconds * 0.3; + var waveOpacity = this.opacity; + + return Math.max( + 0, + Math.min(outerOpacity, waveOpacity) + ); + }, + + get isOpacityFullyDecayed() { + return this.opacity < 0.01 && + this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); + }, + + get isRestingAtMaxRadius() { + return this.opacity >= this.initialOpacity && + this.radius >= Math.min(this.maxRadius, Ripple.MAX_RADIUS); + }, + + get isAnimationComplete() { + return this.mouseUpStart ? + this.isOpacityFullyDecayed : this.isRestingAtMaxRadius; + }, + + get translationFraction() { + return Math.min( + 1, + this.radius / this.containerMetrics.size * 2 / Math.sqrt(2) + ); + }, + + get xNow() { + if (this.xEnd) { + return this.xStart + this.translationFraction * (this.xEnd - this.xStart); + } + + return this.xStart; + }, + + get yNow() { + if (this.yEnd) { + return this.yStart + this.translationFraction * (this.yEnd - this.yStart); + } + + return this.yStart; + }, + + get isMouseDown() { + return this.mouseDownStart && !this.mouseUpStart; + }, + + resetInteractionState: function() { + this.maxRadius = 0; + this.mouseDownStart = 0; + this.mouseUpStart = 0; + + this.xStart = 0; + this.yStart = 0; + this.xEnd = 0; + this.yEnd = 0; + this.slideDistance = 0; + + this.containerMetrics = new ElementMetrics(this.element); + }, + + draw: function() { + var scale; + var translateString; + var dx; + var dy; + + this.wave.style.opacity = this.opacity; + + scale = this.radius / (this.containerMetrics.size / 2); + dx = this.xNow - (this.containerMetrics.width / 2); + dy = this.yNow - (this.containerMetrics.height / 2); + + Polymer.Base.translate3d(this.waveContainer, dx + 'px', dy + 'px', 0); + + // 2d transform for safari because of border-radius and overflow:hidden clipping bug. + // https://bugs.webkit.org/show_bug.cgi?id=98538 + this.wave.style.webkitTransform = 'scale(' + scale + ',' + scale + ')'; + this.wave.style.transform = 'scale3d(' + scale + ',' + scale + ',1)'; + }, + + mousedownAction: function(event) { + this.resetInteractionState(); + this.mouseDownStart = Utility.now(); + + this.xStart = event ? + event.x - this.containerMetrics.boundingRect.left : + this.containerMetrics.width / 2; + this.yStart = event ? + event.y - this.containerMetrics.boundingRect.top : + this.containerMetrics.height / 2; + + if (this.recenters) { + this.xEnd = this.containerMetrics.width / 2; + this.yEnd = this.containerMetrics.height / 2; + this.slideDistance = Utility.distance( + this.xStart, this.yStart, this.xEnd, this.yEnd + ); + } + + this.maxRadius = this.containerMetrics.furthestCornerDistanceFrom( + this.xStart, + this.yStart + ); + + this.waveContainer.style.top = + (this.containerMetrics.height - this.containerMetrics.size) / 2 + 'px'; + this.waveContainer.style.left = + (this.containerMetrics.width - this.containerMetrics.size) / 2 + 'px'; + + this.waveContainer.style.width = this.containerMetrics.size + 'px'; + this.waveContainer.style.height = this.containerMetrics.size + 'px'; + }, + + mouseupAction: function(event) { + if (!this.isMouseDown) { + return; + } + + this.mouseUpStart = Utility.now(); + }, + + remove: function() { + Polymer.dom(this.waveContainer.parentNode).removeChild( + this.waveContainer + ); + } + }; + + Polymer({ + is: 'paper-ripple', + + properties: { + /** + * The initial opacity set on the wave. + * + * @attribute initialOpacity + * @type number + * @default 0.25 + */ + initialOpacity: { + type: Number, + value: 0.25 + }, + + /** + * How fast (opacity per second) the wave fades out. + * + * @attribute opacityDecayVelocity + * @type number + * @default 0.8 + */ + opacityDecayVelocity: { + type: Number, + value: 0.8 + }, + + /** + * If true, ripples will exhibit a gravitational pull towards + * the center of their container as they fade away. + * + * @attribute recenters + * @type boolean + * @default false + */ + recenters: { + type: Boolean, + value: false + }, + + /** + * A list of the visual ripples. + * + * @attribute ripples + * @type Array + * @default [] + */ + ripples: { + type: Array, + value: function() { + return []; + } + }, + + _animating: { + type: Boolean + }, + + _boundAnimate: { + type: Function, + value: function() { + return this.animate.bind(this); + } + }, + + _boundMousedownAction: { + type: Function, + value: function() { + return this.mousedownAction.bind(this); + } + }, + + _boundMouseupAction: { + type: Function, + value: function() { + return this.mouseupAction.bind(this); + } + } + }, + + get target () { + return this.host || this.parentNode; + }, + + attached: function() { + this.target.addEventListener('mousedown', this._boundMousedownAction); + this.target.addEventListener('mouseup', this._boundMouseupAction); + }, + + detached: function() { + this.target.removeEventListener('mousedown', this._boundMousedownAction); + this.target.removeEventListener('mouseup', this._boundMouseupAction); + }, + + /* TODO(cdata): Replace the above attached / detached listeners when + PolymerGestures equivalent lands in 0.8. + listeners: { + mousedown: 'mousedownAction', + mouseup: 'mouseupAction' + }, + */ + + get shouldKeepAnimating () { + for (var index = 0; index < this.ripples.length; ++index) { + if (!this.ripples[index].isAnimationComplete) { + return true; + } + } + + return false; + }, + + simulatedRipple: function() { + this.mousedownAction(null); + + // Please see polymer/polymer#1305 + this.async(function() { + this.mouseupAction(); + }, 1); + }, + + mousedownAction: function(event) { + var ripple = this.addRipple(); + + ripple.mousedownAction(event); + + if (!this._animating) { + this.animate(); + } + }, + + mouseupAction: function(event) { + this.ripples.forEach(function(ripple) { + ripple.mouseupAction(event); + }); + + this.animate(); + }, + + onAnimationComplete: function() { + this._animating = false; + this.$.background.style.backgroundColor = null; + this.fire('transitionend'); + }, + + addRipple: function() { + var ripple = new Ripple(this); + + Polymer.dom(this.$.waves).appendChild(ripple.waveContainer); + this.$.background.style.backgroundColor = ripple.color; + this.ripples.push(ripple); + + return ripple; + }, + + removeRipple: function(ripple) { + var rippleIndex = this.ripples.indexOf(ripple); + + if (rippleIndex < 0) { + return; + } + + this.ripples.splice(rippleIndex, 1); + + ripple.remove(); + }, + + animate: function() { + var index; + var ripple; + + this._animating = true; + + for (index = 0; index < this.ripples.length; ++index) { + ripple = this.ripples[index]; + + ripple.draw(); + + this.$.background.style.opacity = ripple.outerOpacity; + + if (ripple.isOpacityFullyDecayed && !ripple.isRestingAtMaxRadius) { + this.removeRipple(ripple); + } + } + + if (this.shouldKeepAnimating) { + window.requestAnimationFrame(this._boundAnimate); + } else if (this.ripples.length === 0) { + this.onAnimationComplete(); + } + } + }); + })(); +</script> +
diff --git a/third_party/polymer/v0_8/components/paper-styles/.bower.json b/third_party/polymer/v0_8/components/paper-styles/.bower.json new file mode 100644 index 0000000..a67e854 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/.bower.json
@@ -0,0 +1,33 @@ +{ + "name": "paper-styles", + "version": "0.8.6", + "authors": [ + "Ian MacLeod <imac@google.com>", + "The Polymer Authors" + ], + "description": "Common (global) styles for Material Design elements.", + "keywords": [ + "web-component", + "web-components", + "polymer" + ], + "main": "paper-styles.html", + "license": "MIT", + "homepage": "https://github.com/PolymerLabs/paper-styles/", + "ignore": [ + "/.*", + "/demo/" + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + }, + "_release": "0.8.6", + "_resolution": { + "type": "version", + "tag": "v0.8.6", + "commit": "d0cdb1ad31d9b97855db3020a55c0b731a742334" + }, + "_source": "git://github.com/PolymerElements/paper-styles.git", + "_target": "^0.8.0", + "_originalSource": "PolymerElements/paper-styles" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/paper-styles/README.md b/third_party/polymer/v0_8/components/paper-styles/README.md new file mode 100644 index 0000000..fcbd7e0 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/README.md
@@ -0,0 +1 @@ +# paper-styles
diff --git a/third_party/polymer/v0_8/components/paper-styles/bower.json b/third_party/polymer/v0_8/components/paper-styles/bower.json new file mode 100644 index 0000000..8c31410 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/bower.json
@@ -0,0 +1,24 @@ +{ + "name": "paper-styles", + "version": "0.8.6", + "authors": [ + "Ian MacLeod <imac@google.com>", + "The Polymer Authors" + ], + "description": "Common (global) styles for Material Design elements.", + "keywords": [ + "web-component", + "web-components", + "polymer" + ], + "main": "paper-styles.html", + "license": "MIT", + "homepage": "https://github.com/PolymerLabs/paper-styles/", + "ignore": [ + "/.*", + "/demo/" + ], + "dependencies": { + "polymer": "Polymer/polymer#v0.8.0-rc.7" + } +}
diff --git a/third_party/polymer/v0_8/components/paper-styles/classes/global.html b/third_party/polymer/v0_8/components/paper-styles/classes/global.html new file mode 100644 index 0000000..6f0d5dd --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/classes/global.html
@@ -0,0 +1,96 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../paper-styles-classes.html"> + +<!-- +A set of base styles that are applied to the document and standard elements that +match the Material Design spec. +--> +<style> +/* +Note that there is a lot of style duplication here. The hope is that the Polymer +0.8 styling solution will allow for inheritance of properties so that we can +eventually avoid it. +*/ + +/* Mixins */ + +/* [paper-font] */ +body { + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */ +} + +/* [paper-font=display2] */ +h1 { + font-size: 45px; + font-weight: 400; + letter-spacing: -.018em; + line-height: 48px; +} + +/* [paper-font=display1] */ +h2 { + font-size: 34px; + font-weight: 400; + letter-spacing: -.01em; + line-height: 40px; +} + +/* [paper-font=headline] */ +h3 { + font-size: 24px; + font-weight: 400; + letter-spacing: -.012em; + line-height: 32px; +} + +/* [paper-font=subhead] */ +h4 { + font-size: 16px; + font-weight: 400; + line-height: 24px; +} + +/* [paper-font=body2] */ +h5, h6 { + font-size: 14px; + font-weight: 500; + line-height: 24px; +} + +/* [paper-font=button] */ +a { + font-size: 14px; + font-weight: 500; + letter-spacing: 0.018em; + line-height: 24px; + text-transform: uppercase; +} + +/* Overrides */ + +body, a { + color: #212121; +} + +h1, h2, h3, h4, h5, h6, p { + margin: 0 0 20px 0; +} + +h1, h2, h3, h4, h5, h6, a { + text-rendering: optimizeLegibility; +} + +a { + text-decoration: none; +} + +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/classes/layout.html b/third_party/polymer/v0_8/components/paper-styles/classes/layout.html new file mode 100644 index 0000000..5e3755b --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/classes/layout.html
@@ -0,0 +1,307 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="shadow-layout.html"> + +<style> + + /******************************* + Flex Layout + *******************************/ + + .layout.horizontal, + .layout.horizontal-reverse, + .layout.vertical, + .layout.vertical-reverse { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + } + + .layout.inline { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + } + + .layout.horizontal { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + } + + .layout.horizontal-reverse { + -ms-flex-direction: row-reverse; + -webkit-flex-direction: row-reverse; + flex-direction: row-reverse; + } + + .layout.vertical { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + } + + .layout.vertical-reverse { + -ms-flex-direction: column-reverse; + -webkit-flex-direction: column-reverse; + flex-direction: column-reverse; + } + + .layout.wrap { + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + } + + .layout.wrap-reverse { + -ms-flex-wrap: wrap-reverse; + -webkit-flex-wrap: wrap-reverse; + flex-wrap: wrap-reverse; + } + + .flex-auto { + -ms-flex: 1 1 auto; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + } + + .flex-none { + -ms-flex: none; + -webkit-flex: none; + flex: none; + } + + .flex, + .flex-1 { + -ms-flex: 1; + -webkit-flex: 1; + flex: 1; + } + + .flex-2 { + -ms-flex: 2; + -webkit-flex: 2; + flex: 2; + } + + .flex-3 { + -ms-flex: 3; + -webkit-flex: 3; + flex: 3; + } + + .flex-4 { + -ms-flex: 4; + -webkit-flex: 4; + flex: 4; + } + + .flex-5 { + -ms-flex: 5; + -webkit-flex: 5; + flex: 5; + } + + .flex-6 { + -ms-flex: 6; + -webkit-flex: 6; + flex: 6; + } + + .flex-7 { + -ms-flex: 7; + -webkit-flex: 7; + flex: 7; + } + + .flex-8 { + -ms-flex: 8; + -webkit-flex: 8; + flex: 8; + } + + .flex-9 { + -ms-flex: 9; + -webkit-flex: 9; + flex: 9; + } + + .flex-10 { + -ms-flex: 10; + -webkit-flex: 10; + flex: 10; + } + + .flex-11 { + -ms-flex: 11; + -webkit-flex: 11; + flex: 11; + } + + .flex-12 { + -ms-flex: 12; + -webkit-flex: 12; + flex: 12; + } + + /* alignment in cross axis */ + + .layout.start { + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + } + + .layout.center, + .layout.center-center { + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + } + + .layout.end { + -ms-flex-align: end; + -webkit-align-items: flex-end; + align-items: flex-end; + } + + /* alignment in main axis */ + + .layout.start-justified { + -ms-flex-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start; + } + + .layout.center-justified, + .layout.center-center { + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } + + .layout.end-justified { + -ms-flex-pack: end; + -webkit-justify-content: flex-end; + justify-content: flex-end; + } + + .layout.around-justified { + -ms-flex-pack: around; + -webkit-justify-content: space-around; + justify-content: space-around; + } + + .layout.justified { + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + } + + /* self alignment */ + + .self-start { + -ms-align-self: flex-start; + -webkit-align-self: flex-start; + align-self: flex-start; + } + + .self-center { + -ms-align-self: center; + -webkit-align-self: center; + align-self: center; + } + + .self-end { + -ms-align-self: flex-end; + -webkit-align-self: flex-end; + align-self: flex-end; + } + + .self-stretch { + -ms-align-self: stretch; + -webkit-align-self: stretch; + align-self: stretch; + } + + /******************************* + Other Layout + *******************************/ + + .block { + display: block; + } + + /* IE 10 support for HTML5 hidden attr */ + [hidden] { + display: none !important; + } + + .invisible { + visibility: hidden !important; + } + + .relative { + position: relative; + } + + .fit { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + body.fullbleed { + margin: 0; + height: 100vh; + } + + .scroll { + -webkit-overflow-scrolling: touch; + overflow: auto; + } + + /* fixed position */ + + .fixed-bottom, + .fixed-left, + .fixed-right, + .fixed-top { + position: fixed; + } + + .fixed-top { + top: 0; + left: 0; + right: 0; + } + + .fixed-right { + top: 0; + right: 0; + bottom: 0; + } + + .fixed-bottom { + right: 0; + bottom: 0; + left: 0; + } + + .fixed-left { + top: 0; + bottom: 0; + left: 0; + } + +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/classes/shadow-layout.html b/third_party/polymer/v0_8/components/paper-styles/classes/shadow-layout.html new file mode 100644 index 0000000..c42067af5 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/classes/shadow-layout.html
@@ -0,0 +1,302 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<style> + + /******************************* + Flex Layout + *******************************/ + + html /deep/ .layout.horizontal, + html /deep/ .layout.horizontal-reverse, + html /deep/ .layout.vertical, + html /deep/ .layout.vertical-reverse { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + } + + html /deep/ .layout.inline { + display: -ms-inline-flexbox; + display: -webkit-inline-flex; + display: inline-flex; + } + + html /deep/ .layout.horizontal { + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + } + + html /deep/ .layout.horizontal-reverse { + -ms-flex-direction: row-reverse; + -webkit-flex-direction: row-reverse; + flex-direction: row-reverse; + } + + html /deep/ .layout.vertical { + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + } + + html /deep/ .layout.vertical-reverse { + -ms-flex-direction: column-reverse; + -webkit-flex-direction: column-reverse; + flex-direction: column-reverse; + } + + html /deep/ .layout.wrap { + -ms-flex-wrap: wrap; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + } + + html /deep/ .layout.wrap-reverse { + -ms-flex-wrap: wrap-reverse; + -webkit-flex-wrap: wrap-reverse; + flex-wrap: wrap-reverse; + } + + html /deep/ .flex-auto { + -ms-flex: 1 1 auto; + -webkit-flex: 1 1 auto; + flex: 1 1 auto; + } + + html /deep/ .flex-none { + -ms-flex: none; + -webkit-flex: none; + flex: none; + } + + html /deep/ .flex, + html /deep/ .flex-1 { + -ms-flex: 1; + -webkit-flex: 1; + flex: 1; + } + + html /deep/ .flex-2 { + -ms-flex: 2; + -webkit-flex: 2; + flex: 2; + } + + html /deep/ .flex-3 { + -ms-flex: 3; + -webkit-flex: 3; + flex: 3; + } + + html /deep/ .flex-4 { + -ms-flex: 4; + -webkit-flex: 4; + flex: 4; + } + + html /deep/ .flex-5 { + -ms-flex: 5; + -webkit-flex: 5; + flex: 5; + } + + html /deep/ .flex-6 { + -ms-flex: 6; + -webkit-flex: 6; + flex: 6; + } + + html /deep/ .flex-7 { + -ms-flex: 7; + -webkit-flex: 7; + flex: 7; + } + + html /deep/ .flex-8 { + -ms-flex: 8; + -webkit-flex: 8; + flex: 8; + } + + html /deep/ .flex-9 { + -ms-flex: 9; + -webkit-flex: 9; + flex: 9; + } + + html /deep/ .flex-10 { + -ms-flex: 10; + -webkit-flex: 10; + flex: 10; + } + + html /deep/ .flex-11 { + -ms-flex: 11; + -webkit-flex: 11; + flex: 11; + } + + html /deep/ .flex-12 { + -ms-flex: 12; + -webkit-flex: 12; + flex: 12; + } + + /* alignment in cross axis */ + + html /deep/ .layout.start { + -ms-flex-align: start; + -webkit-align-items: flex-start; + align-items: flex-start; + } + + html /deep/ .layout.center, + html /deep/ .layout.center-center { + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + } + + html /deep/ .layout.end { + -ms-flex-align: end; + -webkit-align-items: flex-end; + align-items: flex-end; + } + + /* alignment in main axis */ + + html /deep/ .layout.start-justified { + -ms-flex-pack: start; + -webkit-justify-content: flex-start; + justify-content: flex-start; + } + + html /deep/ .layout.center-justified, + html /deep/ .layout.center-center { + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } + + html /deep/ .layout.end-justified { + -ms-flex-pack: end; + -webkit-justify-content: flex-end; + justify-content: flex-end; + } + + html /deep/ .layout.around-justified { + -ms-flex-pack: around; + -webkit-justify-content: space-around; + justify-content: space-around; + } + + html /deep/ .layout.justified { + -ms-flex-pack: justify; + -webkit-justify-content: space-between; + justify-content: space-between; + } + + /* self alignment */ + + html /deep/ .self-start { + -ms-align-self: flex-start; + -webkit-align-self: flex-start; + align-self: flex-start; + } + + html /deep/ .self-center { + -ms-align-self: center; + -webkit-align-self: center; + align-self: center; + } + + html /deep/ .self-end { + -ms-align-self: flex-end; + -webkit-align-self: flex-end; + align-self: flex-end; + } + + html /deep/ .self-stretch { + -ms-align-self: stretch; + -webkit-align-self: stretch; + align-self: stretch; + } + + /******************************* + Other Layout + *******************************/ + + html /deep/ .block { + display: block; + } + + /* IE 10 support for HTML5 hidden attr */ + html /deep/ [hidden] { + display: none !important; + } + + html /deep/ .invisible { + visibility: hidden !important; + } + + html /deep/ .relative { + position: relative; + } + + html /deep/ .fit { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + body.fullbleed { + margin: 0; + height: 100vh; + } + + html /deep/ .scroll { + -webkit-overflow-scrolling: touch; + overflow: auto; + } + + .fixed-bottom, + .fixed-left, + .fixed-right, + .fixed-top { + position: fixed; + } + + html /deep/ .fixed-top { + top: 0; + left: 0; + right: 0; + } + + html /deep/ .fixed-right { + top: 0; + right: 0; + botttom: 0; + } + + html /deep/ .fixed-bottom { + right: 0; + bottom: 0; + left: 0; + } + + html /deep/ .fixed-left { + top: 0; + botttom: 0; + left: 0; + } + +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/classes/shadow.html b/third_party/polymer/v0_8/components/paper-styles/classes/shadow.html new file mode 100644 index 0000000..b4c340d --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/classes/shadow.html
@@ -0,0 +1,39 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<style> +.shadow-transition { + transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); +} + +.shadow-elevation-1 { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); +} + +.shadow-elevation-2 { + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2), + 0 6px 10px 0 rgba(0, 0, 0, 0.3); +} + +.shadow-elevation-3 { + box-shadow: 0 11px 7px 0 rgba(0, 0, 0, 0.19), + 0 13px 25px 0 rgba(0, 0, 0, 0.3); +} + +.shadow-elevation-4 { + box-shadow: 0 14px 12px 0 rgba(0, 0, 0, 0.17), + 0 20px 40px 0 rgba(0, 0, 0, 0.3); +} + +.shadow-elevation-5 { + box-shadow: 0 17px 17px 0 rgba(0, 0, 0, 0.15), + 0 27px 55px 0 rgba(0, 0, 0, 0.3); +} +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/classes/typography.html b/third_party/polymer/v0_8/components/paper-styles/classes/typography.html new file mode 100644 index 0000000..5514abb --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/classes/typography.html
@@ -0,0 +1,171 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- TODO(nevir): Should we upgrade Polymer/font-roboto to the final font? --> +<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic"> +<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Inconsolata:400,700"> + +<!-- +Typographic styles are provided matching the Material Design standard styles: +http://www.google.com/design/spec/style/typography.html#typography-standard-styles + +To make use of them, apply a `paper-font-<style>` class to elements, matching +the font style you wish it to inherit. + + <header class="paper-font-display2">Hey there!</header> + +Note that these are English/Latin centric styles. You may need to further adjust +line heights and weights for CJK typesetting. See the notes in the Material +Design typography section. +--> +<style> + +.paper-font-display4, +.paper-font-display3, +.paper-font-display2, +.paper-font-display1, +.paper-font-headline, +.paper-font-title, +.paper-font-subhead, +.paper-font-body2, +.paper-font-body1, +.paper-font-caption, +.paper-font-menu, +.paper-font-button { + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */ +} + +.paper-font-code2, +.paper-font-code1 { + font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace; + -webkit-font-smoothing: antialiased; /* OS X subpixel AA bleed bug */ +} + +/* Opt for better kerning for headers & other short labels. */ +.paper-font-display4, +.paper-font-display3, +.paper-font-display2, +.paper-font-display1, +.paper-font-headline, +.paper-font-title, +.paper-font-subhead, +.paper-font-menu, +.paper-font-button { + text-rendering: optimizeLegibility; +} + +/* +"Line wrapping only applies to Body, Subhead, Headline, and the smaller Display +styles. All other styles should exist as single lines." +*/ +.paper-font-display4, +.paper-font-display3, +.paper-font-title, +.paper-font-caption, +.paper-font-menu, +.paper-font-button { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.paper-font-display4 { + font-size: 112px; + font-weight: 300; + letter-spacing: -.044em; + line-height: 120px; +} + +.paper-font-display3 { + font-size: 56px; + font-weight: 400; + letter-spacing: -.026em; + line-height: 60px; +} + +.paper-font-display2 { + font-size: 45px; + font-weight: 400; + letter-spacing: -.018em; + line-height: 48px; +} + +.paper-font-display1 { + font-size: 34px; + font-weight: 400; + letter-spacing: -.01em; + line-height: 40px; +} + +.paper-font-headline { + font-size: 24px; + font-weight: 400; + letter-spacing: -.012em; + line-height: 32px; +} + +.paper-font-title { + font-size: 20px; + font-weight: 500; + line-height: 28px; +} + +.paper-font-subhead { + font-size: 16px; + font-weight: 400; + line-height: 24px; +} + +.paper-font-body2 { + font-size: 14px; + font-weight: 500; + line-height: 24px; +} + +.paper-font-body1 { + font-size: 14px; + font-weight: 400; + line-height: 20px; +} + +.paper-font-caption { + font-size: 12px; + font-weight: 400; + letter-spacing: 0.011em; + line-height: 20px; +} + +.paper-font-menu { + font-size: 13px; + font-weight: 500; + line-height: 24px; +} + +.paper-font-button { + font-size: 14px; + font-weight: 500; + letter-spacing: 0.018em; + line-height: 24px; + text-transform: uppercase; +} + +.paper-font-code2 { + font-size: 14px; + font-weight: 700; + line-height: 20px; +} + +.paper-font-code1 { + font-size: 14px; + font-weight: 700; + line-height: 20px; +} + +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/color.html b/third_party/polymer/v0_8/components/paper-styles/color.html new file mode 100644 index 0000000..43e9ce2 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/color.html
@@ -0,0 +1,56 @@ +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<style is="x-style"> + + * { + + --google-red-100: #f4c7c3; + --google-red-300: #e67c73; + --google-red-500: #db4437; + --google-red-700: #c53929; + + --google-blue-100: #c6dafc; + --google-blue-300: #7baaf7; + --google-blue-500: #4285f4; + --google-blue-700: #3367d6; + + --google-green-100: #b7e1cd; + --google-green-300: #57bb8a; + --google-green-500: #0f9d58; + --google-green-700: #0b8043; + + --google-yellow-100: #fce8b2; + --google-yellow-300: #f7cb4d; + --google-yellow-500: #f4b400; + --google-yellow-700: #f09300; + + --google-grey-100: #f5f5f5; + --google-grey-300: #e0e0e0; + --google-grey-500: #9e9e9e; + --google-grey-700: #616161; + + /* opacity for dark text on a light background */ + --dark-divider-opacity: 12%; + --dark-disabled-opacity: 26%; /* or hint text */ + --dark-secondary-opacity: 54%; /* or icon */ + --dark-primary-opacity: 87%; + + /* opacity for light text on a dark background */ + --light-divider-opacity: 12%; + --light-disabled-opacity: 30%; /* or hint text */ + --light-secondary-opacity: 70%; /* or icon */ + --light-primary-opacity: 100%; + + } + +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/default-theme.html b/third_party/polymer/v0_8/components/paper-styles/default-theme.html new file mode 100644 index 0000000..c17f8e8d --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/default-theme.html
@@ -0,0 +1,39 @@ +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<style is="x-style"> + + * { + + --dark-primary-color: #303f9f; + + --default-primary-color: #3f51b5; + + --light-primary-color: #c5cae9; + + --text-primary-color: #ffffff; + + --accent-color: #ff4081; + + --primary-background-color: #ffffff; + + --primary-text-color: #212121; + + --secondary-text-color: #757575; + + --disabled-text-color: #bdbdbd; + + --divider-color: #e0e0e0; + + } + +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/demo.css b/third_party/polymer/v0_8/components/paper-styles/demo.css new file mode 100644 index 0000000..c6756c4 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/demo.css
@@ -0,0 +1,15 @@ +body { + font-family: RobotoDraft, 'Helvetica Neue', Helvetica, Arial; + font-size: 14px; + margin: 0; + padding: 24px; +} + +section { + padding: 20px 0; +} + +section > div { + padding: 14px; + font-size: 16px; +}
diff --git a/third_party/polymer/v0_8/components/paper-styles/layout.html b/third_party/polymer/v0_8/components/paper-styles/layout.html new file mode 100644 index 0000000..ae8fad6 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/layout.html
@@ -0,0 +1,77 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<link rel="import" href="classes/layout.html"> + +<style is="x-style"> + + * { + + --layout: { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + } + + --layout-horizontal: { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + -ms-flex-direction: row; + -webkit-flex-direction: row; + flex-direction: row; + } + + --layout-vertical: { + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + + -ms-flex-direction: column; + -webkit-flex-direction: column; + flex-direction: column; + } + + --layout-flex: { + -ms-flex: 1; + -webkit-flex: 1; + flex: 1; + } + + --layout-center: { + -ms-flex-align: center; + -webkit-align-items: center; + align-items: center; + } + + --layout-center-justified: { + -ms-flex-pack: center; + -webkit-justify-content: center; + justify-content: center; + } + + /******************************* + Other Layout + *******************************/ + + --fit: { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } + + } + +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/paper-styles-classes.html b/third_party/polymer/v0_8/components/paper-styles/paper-styles-classes.html new file mode 100644 index 0000000..b91c0135 --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/paper-styles-classes.html
@@ -0,0 +1,13 @@ +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="classes/layout.html"> +<link rel="import" href="classes/typography.html"> +<link rel="import" href="classes/shadow.html">
diff --git a/third_party/polymer/v0_8/components/paper-styles/paper-styles.html b/third_party/polymer/v0_8/components/paper-styles/paper-styles.html new file mode 100644 index 0000000..828fffe --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/paper-styles.html
@@ -0,0 +1,15 @@ +<!-- + @license + Copyright (c) 2015 The Polymer Project Authors. All rights reserved. + This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt + The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt + The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt + Code distributed by Google as part of the polymer project is also + subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="color.html"> +<link rel="import" href="default-theme.html"> +<link rel="import" href="layout.html"> +<link rel="import" href="typography.html"> +<link rel="import" href="shadow.html">
diff --git a/third_party/polymer/v0_8/components/paper-styles/shadow.html b/third_party/polymer/v0_8/components/paper-styles/shadow.html new file mode 100644 index 0000000..6d7ae7a --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/shadow.html
@@ -0,0 +1,47 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../polymer/polymer.html"> + +<style is="x-style"> + + * { + + --shadow-transition: { + transition: box-shadow 0.28s cubic-bezier(0.4, 0, 0.2, 1); + }; + + --shadow-elevation-1: { + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37); + }; + + --shadow-elevation-2: { + box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2), + 0 6px 10px 0 rgba(0, 0, 0, 0.3); + }; + + --shadow-elevation-3: { + box-shadow: 0 11px 7px 0 rgba(0, 0, 0, 0.19), + 0 13px 25px 0 rgba(0, 0, 0, 0.3); + }; + + --shadow-elevation-4: { + box-shadow: 0 14px 12px 0 rgba(0, 0, 0, 0.17), + 0 20px 40px 0 rgba(0, 0, 0, 0.3); + }; + + --shadow-elevation-5: { + box-shadow: 0 17px 17px 0 rgba(0, 0, 0, 0.15), + 0 27px 55px 0 rgba(0, 0, 0, 0.3); + }; + + } + +</style>
diff --git a/third_party/polymer/v0_8/components/paper-styles/typography.html b/third_party/polymer/v0_8/components/paper-styles/typography.html new file mode 100644 index 0000000..aae1a94a --- /dev/null +++ b/third_party/polymer/v0_8/components/paper-styles/typography.html
@@ -0,0 +1,240 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<!-- TODO(nevir): Should we upgrade Polymer/font-roboto to the final font? --> +<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:400,300,300italic,400italic,500,500italic,700,700italic"> + +<link rel="import" href="../polymer/polymer.html"> + +<style is="x-style"> + + * { + + /* Shared Styles */ + + /* + Unfortunately, we can't make use of these yet - sibling properties aren't + evaluated. See https://github.com/Polymer/polymer/issues/1399 + + --paper-font-common-base: { + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + } + + --paper-font-common-code: { + font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace; + -webkit-font-smoothing: antialiased; + } + + --paper-font-common-expensive-kerning: { + text-rendering: optimizeLegibility; + } + + --paper-font-common-nowrap: { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + */ + + /* Material Font Styles */ + + --paper-font-display4: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 112px; + font-weight: 300; + letter-spacing: -.044em; + line-height: 120px; + } + + --paper-font-display3: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 56px; + font-weight: 400; + letter-spacing: -.026em; + line-height: 60px; + } + + --paper-font-display2: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + + font-size: 45px; + font-weight: 400; + letter-spacing: -.018em; + line-height: 48px; + } + + --paper-font-display1: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + + font-size: 34px; + font-weight: 400; + letter-spacing: -.01em; + line-height: 40px; + } + + --paper-font-headline: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + + font-size: 24px; + font-weight: 400; + letter-spacing: -.012em; + line-height: 32px; + } + + --paper-font-title: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 20px; + font-weight: 500; + line-height: 28px; + } + + --paper-font-subhead: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + + font-size: 16px; + font-weight: 400; + line-height: 24px; + } + + --paper-font-body2: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + + font-size: 14px; + font-weight: 500; + line-height: 24px; + } + + --paper-font-body1: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + + font-size: 14px; + font-weight: 400; + line-height: 20px; + } + + --paper-font-caption: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 12px; + font-weight: 400; + letter-spacing: 0.011em; + line-height: 20px; + } + + --paper-font-menu: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 13px; + font-weight: 500; + line-height: 24px; + } + + --paper-font-button: { + /* mixin(--paper-font-common-base) */ + font-family: 'Roboto', 'Noto', sans-serif; + -webkit-font-smoothing: antialiased; + /* mixin(--paper-font-common-expensive-kerning); */ + text-rendering: optimizeLegibility; + /* mixin(--paper-font-common-nowrap); */ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + font-size: 14px; + font-weight: 500; + letter-spacing: 0.018em; + line-height: 24px; + text-transform: uppercase; + } + + --paper-font-code2: { + /* mixin(--paper-font-common-code); */ + font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace; + -webkit-font-smoothing: antialiased; + + font-size: 14px; + font-weight: 700; + line-height: 20px; + } + + --paper-font-code1: { + /* mixin(--paper-font-common-code); */ + font-family: 'Inconsolata', 'Consolas', 'Source Code Pro', 'Monaco', 'Menlo', monospace; + -webkit-font-smoothing: antialiased; + + font-size: 14px; + font-weight: 500; + line-height: 20px; + } + + } + +</style>
diff --git a/third_party/polymer/v0_8/components/polymer/.bower.json b/third_party/polymer/v0_8/components/polymer/.bower.json new file mode 100644 index 0000000..ed9a244 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/.bower.json
@@ -0,0 +1,36 @@ +{ + "name": "polymer", + "version": "0.8.0-rc.7", + "main": [ + "polymer.html" + ], + "license": "http://polymer.github.io/LICENSE.txt", + "ignore": [ + "/.*", + "/test/" + ], + "authors": [ + "The Polymer Authors (http://polymer.github.io/AUTHORS.txt)" + ], + "repository": { + "type": "git", + "url": "https://github.com/Polymer/polymer.git" + }, + "dependencies": { + "webcomponentsjs": "^0.6.0" + }, + "devDependencies": { + "web-component-tester": "*" + }, + "private": true, + "homepage": "https://github.com/Polymer/polymer", + "_release": "0.8.0-rc.7", + "_resolution": { + "type": "version", + "tag": "v0.8.0-rc.7", + "commit": "ce138bc0bb96c74421ba76bf3b5f1aa46b126569" + }, + "_source": "git://github.com/Polymer/polymer.git", + "_target": "v0.8.0-rc.7", + "_originalSource": "Polymer/polymer" +} \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/PRIMER.md b/third_party/polymer/v0_8/components/polymer/PRIMER.md new file mode 100644 index 0000000..9ec86d3f --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/PRIMER.md
@@ -0,0 +1,2046 @@ +# Polymer 0.8 Primer + +Table of Contents: + +* [Feature list](#feature-list) +* [Migration notes](#migration-notes) + +# Feature list + +<a name="feature-list"></a> +Below is a description of the current Polymer features, followed by individual feature guides. + +<a name="polymer-micro"></a> +**Bare-minum Custom Element sugaring** + +| Feature | Usage +|---------|------- +| [Custom element constructor](#element-constructor) | Polymer.Class({ … }); +| [Custom element registration](#register-element) | Polymer({ is: ‘...’, … }}; +| [Bespoke constructor support](#bespoke-constructor) | factoryImpl: function() { … } +| [Basic lifecycle callbacks](#basic-callbacks) | created, attached, detached, attributeChanged +| [Native HTML element extension](#type-extension) | extends: ‘…’ +| [Configure properties](#property-config) | properties: { … } +| [Attribute deserialization to property](#attribute-deserialization) | properties: { \<property>: \<Type> } +| [Static attributes on host](#host-attributes) | hostAttributes: { \<attribute>: \<value> } +| [Behavior mixins](#behaviors) | behaviors: [ … ] + +<a name="polymer-mini"></a> +**Template stamped into "local DOM" and tree lifecycle** + +| Feature | Usage +|---------|------- +| [Template stamping into local DOM](#template-stamping) | \<dom-module>\<template>...\</template>\</dom-module> +| [Scoped styling](#scoped-styling) | \<style> in \<dom-module>, Shadow-DOM styling rules (:host, ...) +| [DOM (re-)distribution](#dom-distribution) | \<content> +| [DOM API](#dom-api) | Polymer.dom +| [Configuring default values](#configure-values) | properties: \<prop>: { value: \<primitive>\|\<function> } +| [Bottom-up callback after configuration](#ready-method) | ready: function() { … } + +<a name="polymer-standard"></a> +**Declarative data binding, events, and property effects** + +| Feature | Usage +|---------|------- +| [Local node marshalling](#node-marshalling) | this.$.\<id> +| [Event listener setup](#event-listeners)| listeners: { ‘\<node>.\<event>’: ‘function’, ... } +| [Annotated event listener setup](#annotated-listeners) | \<element on-[event]=”function”> +| [Property change callbacks](#change-callbacks) | properties: \<prop>: { observer: ‘function’ } +| [Annotated property binding](#property-binding) | \<element prop=”{{property\|path}}”> +| [Property change notification](#property-notification) | properties: { \<prop>: { notify: true } } +| [Binding to structured data](#path-binding) | \<element prop=”{{obj.sub.path}}”> +| [Path change notification](#set-path) | setPathValue(\<path>, \<value>) +| [Declarative attribute binding](#attribute-binding) | \<element attr$=”{{property\|path}}”> +| [Binding to native element attributes](#native-binding) | class$="{{...}}", style$="{{...}}"> +| [Reflecting properties to attributes](#attribute-reflection) | properties: \<prop>: { reflectToAttribute: true } } +| [Computed properties](#computed-properties) | computed: { \<property>: ‘computeFn(dep1, dep2)’ } +| [Annotated computed properties](#annotated-computed) | \<span>{{computeFn(dep1, dep2)}}\</span> +| [Read-only properties](#read-only) | properties: { \<prop>: { readOnly: true } } +| [Utility functions](#utility-functions) | toggleClass, toggleAttribute, fire, async, … +| [General polymer settings](#settings) | \<script> Polymer = { ... }; \</script> + +<a name="polymer-experimental"></a> +**Experimental elements and features** + +**<span style="color:red">These features are experimental and there is a higher liklihood for future API change.</span>** Names for custom elements starting with `x-` are placeholders while in experimental status; these will be renamed prior to 1.0. + +| Feature | Usage +|---------|------- +| [Template repeater](#x-repeat) | \<template is="x-repeat" items="{{arr}}"> +| [Array selector](#x-array-selector) | \<x-array-selector items="{{arr}}" selected="{{selected}}"> +| [Conditional template](#x-if) | \<template is="x-if"> +| [Auto-binding template](#x-autobind) | \<template is="x-autobind"> +| [Cross-scope styling](#xscope-styling) | --custom-prop: value, var(--custom-prop), mixin(--custom-mixin) +| [Custom element for styling features](#x-style) | \<style is="x-style"> +| [External stylesheets](#external-stylesheets) | \<link rel="import" type="css" href="..."> +| [Polymer feature layers](#feature-layering) | polymer-micro.html, polymer-mini.html, polymer.html + +# Bare-minum Custom Element sugaring + +<a name="element-constructor"></a> +## Custom Element Constructor + +The most basic Polymer API is `Polymer.Class({...})`, which takes an object expressing the prototype of your custom element, chains it to Polymer's `Base` prototype (which provides value-add features described below), and returns a constructor that can be passed to `document.registerElement()` to register your element with the HTML parser, and after which can be used to instantiate new instances of your element via code. + +The only requirement for the prototype passed to `Polymer.Class` is that `is` property specifies the HTML tag name the element will be registered as. + +Example: + +```js +var MyElement = Polymer.Class({ + + is: 'my-element', + + // See below for lifecycle callbacks + created: function() { + this.innerHTML = 'My element!'; + } + +}); + +document.registerElement('my-element', MyElement); + +// Equivalent: +var el1 = new MyElement(); +var el2 = document.createElement('my-element'); +``` + +`Polymer.Class` is designed to provide similar ergonomics to a speculative future where an ES6 class may be defined and provided to `document.registerElement` to achieve the same effect. + +<a name="register-element"></a> +## Custom Element Registration + +Because the vast majority of users will always want to register the custom element prototype generated by Polymer, Polymer provides a `Polymer({ ... })` function that wraps calling `Polymer.Class` and `document.registerElement`. + +Example: + +```js +MyElement = Polymer({ + + is: 'my-element', + + // See below for lifecycle callbacks + created: function() { + this.innerHTML = 'My element!'; + } + +}); + +var el1 = new MyElement(); +var el2 = document.createElement('my-element'); +``` + +<a name="bespoke-constructor"></a> +## Bespoke constructor support + +While the standard `Polymer.Class()` and `Polymer()` functions return a basic constructor that can be used to instance the custom element, Polymer also supports providing a `factoryImpl` function on the prototype that can, for example, accept arguments to configure the element. In this case, the actual constructor returned from `Polymer` will first create an instance using `document.createElement`, then invoke the user-supplied `factoryImpl` function with `this` bound to the element instance. + +Example: + +```js +MyElement = Polymer({ + + is: 'my-element', + + factoryImpl: function(foo, bar) { + el.foo = foo; + el.configureWithBar(bar); + }, + + configureWithBar: function(bar) { + ... + } + +}); + +var el = new MyElement(42, 'octopus'); +``` + +<a name="type-extension"></a> +## Native HTML element extension + +Polymer 0.8 currently only supports extending native HTML elements (e.g. `input`, `button`, etc., as opposed to [extending other custom elements](#todo-inheritance)). To extend a native HTML element, set the `extends` property to the tag name of the element to extend. + + +Example: + +```js +MyInput = Polymer({ + + is: 'my-input', + + extends: 'input', + + created: function() { + this.style.border = '1px solid red'; + } + +}); + +var el1 = new MyInput(); +console.log(el1 instanceof HTMLInputElement); // true + +var el2 = document.createElement('input', 'my-input'); +console.log(el2 instanceof HTMLInputElement); // true +``` + +<a name="basic-callbacks"></a> +## Basic lifecycle callbacks + +Polymer's Base prototype implements the standard Custom Element lifecycle callbacks to perform tasks necessary for Polymer's built-in features. The hooks in turn call shorter-named lifecycle methods on your prototype. + +- `created` instead of `createdCallback` +- `attached` instead of `attachedCallback` +- `detached` instead of `detachedCallback` +- `attributeChanged` instead of `attributeChangedCallback` + +You can always fallback to using the low-level methods if you wish (in other words, you could simply implement `createdCallback` in your prototype). + +Example: + +```js +MyElement = Polymer({ + + is: 'my-element', + + created: function() { + console.log(this.localName + '#' + this.id + ' was created'); + }, + + attached: function() { + console.log(this.localName + '#' + this.id + ' was attached'); + }, + + detached: function() { + console.log(this.localName + '#' + this.id + ' was detached'); + }, + + attributeChanged: function(name, type) { + console.log(this.localName + '#' + this.id + ' attribute ' + name + + ' was changed to ' + this.getAttribute(name)); + } + +}); +``` + +`Polymer.Base` also implements `registerCallback`, which will be called by `Polymer()` to allow `Polymer.Base` to supply a layering system for Polymer abstractions. + +See the [section on configuring elements](#configuring-elements) for a more in-depth description of the practical uses of each callback. + + +<a name="property-config"></a> +## Configuring properties + +Placing an object-valued `properties` property on your prototype allows you to define metadata regarding your Custom Element's properties, which can then be accessed via an API for use by other Polymer features. + +By itself, the `properties` feature **doesn't do anything**. It only provides API for asking questions about these special properties (see featues below for details). + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + user: String, + isHappy: Boolean, + count: { + type: Number, + readOnly: true, + notify: true + } + }, + + ready: function() { + this.innerHTML = 'Hello World, I am a <b>Custom Element!</b>'; + } + +}); +``` + +Remember that the fields assigned to `count`, such as `readOnly` and `notify` don't do anything by themselves, it requires other features to give them life, and may depend on which layer of Polymer is in use. + +<a name="attribute-deserialization"></a> +## Attribute deserialization + +If a property is configured in the `properties` object with a `type` field, an attribute on the instance matching the property name will be deserialized according to the type specified and assigned to a property of the same name on the element instance. If no other `properties` options are specified for a property, the `type` (specified using the type constructor, e.g. `Object`, `String`, etc.) can be set directly as the value of the property in the `properties` object; otherwise it should be provided as the value to the `type` key in the `properties` configuration object. + +The type system includes support for Object and Array values expressed as JSON, or Date objects expressed as any Date-parsable string representation. Boolean properties set based on the existence of the attribute: if the attribute exists at all, its value is true, regardless of its string-value (and the value is only false if the attribute does not exist). + +Example: + +```html +<script> + + Polymer({ + + is: 'x-custom', + + properties: { + user: String, + manager: { + type: Boolean, + notify: true + } + }, + + attached: function() { + // render + this.innerHTML = 'Hello World, my user is ' + (this.user || 'nobody') + '.\n' + + 'This user is ' + (this.manager ? '' : 'not') + ' a manager.'; + } + + }); + +</script> + +<x-custom user="Scott" manager></x-custom> +<!-- +<x-custom>'s innerHTML becomes: +Hello World, my user is Scott. +This user is a manager. +--> +``` + +In order to configure camel-case properties of elements using attributes, dash-case should be used in the attribute name. Example: + +```html +<script> + + Polymer({ + + is: 'x-custom', + + properties: { + userName: String, + } + + }); + +</script> + +<x-custom user-name="Scott"></x-custom> +<!-- Sets <x-custom>.userName = 'Scott'; --> +``` + + +Note: Deserialization occurs both at create time, as well as at runtime, e.g. when the attribute is changed via `setAttribute`. However, it is encouraged that attributes only be used for configuring properties in static markup, and instead that properties are set directly for changes at runtime. + +<a name="host-attributes"></a> +## Static attributes on host + +If a custom elements needs HTML attributes set on it at create-time, these may be declared in a `hostAttributes` property on the prototype, where keys are the attribtue name and values are the values to be assigned. Values should typically be provided as strings, as HTML attributes can only be strings; however, the standard `serialize` method is used to convert values to strings, so `true` will serialize to an empty attribute, and `false` will result in no attribtue set, and so forth (see [here](#attribute-serialization) for more details). + +Example: + +```html +<script> + + Polymer({ + + is: 'x-custom', + + hostAttributes: { + role: 'button', + 'aria-disabled': true + tabindex: 0 + } + + }); + +</script> +``` + +Results in: + +```html +<x-custom role="button" aria-disabled tabindex="0"></x-custom> +``` + +<a name="behaviors"></a> +## Behaviors + +Polymer supports extending custom element prototypes with shared code modules called "behaviors". + +A behavior is simply an object that looks very similar to a typical Polymer prototype. It may define lifecycle callbacks, `properties`, `hostAttributes`, or other features described later in this document like `observers` and `listeners`. To add a behavior to a Polymer element definition, include it in a `behaviors` array on the prototype. + +Lifecycle callbacks will be called on the base prototype first, then for each behavior in the order given in the `behaviors` array. Additionally, any non-lifecycle functions on the behavior object are mixed into the base prototype (and will overwrite the function on the prototype, if they exist); these may be useful for adding API or implementing observer or event listener callbacks defined by the behavior, for example. + +Example: `highlight-behavior.html` + +```js +HighlightBehavior = { + + properties: { + isHighlighted: { + type: Boolean, + value: false, + notify: true, + observer: '_highlightChanged' + } + }, + + listeners: { + click: '_toggleHighlight' + }, + + created: function() { + console.log('Highlighting for ', this, + 'enabled!'); + }, + + _toggleHighlight: function() { + this.isHighlighted = !this.isHighlighted; + }, + + _highlightChanged: function(value) { + this.toggleClass('highlighted', value); + } + +}; +``` + +Example: `my-element.html` + +```html +<link rel="import" href="highlight-behavior.html"> + +<script> + Polymer({ + is: 'my-element', + behaviors: [HighlightBehavior] + }); +</script> +``` + +# Template stamping and tree lifecycle + +<a name="template-stamping"></a> +## Template stamping into local DOM + +We call the dom which an element is in charge of creating and managing its `local DOM`. This is distinct from the element's children which are sometimes called its `light DOM` for clarity. + +When native Shadow DOM is used, "local DOM" is actually contained in a shadow root. When the Shady DOM system is used, "local DOM" is a virtual notion maintained by Polymer with similar semantics to Shadow DOM. Polymer normalizes these two systems via a common API, such that you can always think about the "local DOM" and "light DOM" trees in the same way regardless of the underlying implementation. + +To specify dom to use for an element's local DOM, use the `<dom-module>` element. +Give the `<dom-module>` an `id` attribute that matches its element's +`is` property and put a `<template>` inside the `<dom-module>`. +Polymer will automatically stamp this template into the element's local DOM. + +Example: + +```html +<dom-module id="x-foo"> + <template>I am x-foo!</template> +</dom-module> + +<script> + Polymer({ + is: 'x-foo' + }); +</script> +``` + +We say that an element definition has an imperative and declarative portion. The imperative +portion is the call to `Polymer({...})`, and the declarative portion is the `<dom-module>` +element. The imperative and declarative portions of an element's definition may be placed +in the same html file or in separate files. + +**NOTE:** Defining an element in the main html document is not currently supported. + +<a name="scoped-styling"></a> +## Scoped styling + +Polymer 0.8 uses "[Shadow DOM styling rules](http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/)" for providing scoped styling of the element's local DOM. Scoped styles should be provided via `<style>` tags placed inside the `<dom-module>` for an element (but not inside the `<template>` -- note this is a slight deviation from typical Shadow DOM rules). + +```html + +<dom-module id="my-element"> + + <style> + :host { + display: block; + border: 1px solid red; + } + #child-element { + background: yellow; + } + /* styling elements distributed to content (via ::content) requires */ + /* selecting the parent of the <content> element for compatibility with */ + /* shady DOM . This can be :host or a wrapper element. */ + .content-wrapper > ::content .special { + background: orange; + } + </style> + + <template> + <div id="child-element">In local Dom!</div> + <div class="content-wrapper"><content></content></div> + </template> + +</dom-module> + +<script> + + Polymer({ + is: 'my-element' + }); + +</script> +``` + +Loading external stylesheets (as opposed to defining them inline in HTML) for styling local DOM is currently supported via an [experimental feature](#external-stylesheets). + +<a name="dom-distribution"></a> +## DOM (re-)distribution + +To support composition of an element's light DOM with its local DOM, Polymer supports the `<content>` element. The `<content>` element provides an insertion point at which an element's light DOM is combined with its local DOM. The `<content>` element supports a `select` attribute which filters nodes via a simple selector. + +Polymer supports multiple local DOM implementations. On browsers that support ShadowDOM, ShadowDOM may be used to create local DOM. On other supported browsers, Polymer provides local DOM via a custom implementation called ShadyDOM which is inspired by and compatible with ShadowDOM. + +Example: + +```html +<template> + <header>Local dom header followed by distributed dom.</header> + <content select=".content"></content> + <footer>Footer after distributed dom.</footer> +</template> +``` +<a name="dom-api"></a> +## DOM API + +Polymer provides custom API for manipulating DOM such that local DOM and light DOM trees are properly maintained. + +**<div style="color:red">Note: All DOM manipulation must use this API, as opposed to DOM API directly on nodes.</div>** + +The following methods are provided: + + * `Polymer.dom(parent).appendChild(node)` + * `Polymer.dom(parent).insertBefore(node, beforeNode)` + * `Polymer.dom(parent).removeChild(node)` + * `Polymer.dom(parent).querySelector(selector)` + * `Polymer.dom(parent).querySelectorAll(selector)` + * `Polymer.dom(parent).childNodes` + * `Polymer.dom(node).parentNode` + * `Polymer.dom(contentElement).getDistributedNodes()` + * `Polymer.dom(node).getDestinationInsertionPoints()` + * `Polymer.dom.flush()` - The insert, append, and remove operations are trasnacted lazily in certain cases for performance. In order to interrogate the dom (e.g. `offsetHeight`, `getComputedStyle`, etc.) immediately after one of these operations, call `Polymer.dom.flush()` first. + +Calling `append`/`insertBefore` where `parent` is a custom Polymer element adds the node to the light DOM of the element. In order to insert/append into the shadow root of a custom element, use `this.root` as the parent. + +`Polymer.dom` properties and methods that return a list of nodes return an `Array`, not a `NodeList` like the standard DOM equivalent. + +Example: + +```js +var toLight = document.createElement('div'); +Polymer.dom(this).appendChild(toLight); + +var toLocal = document.createElement('div'); +var beforeNode = Polymer.dom(this.root).childNodes[0]; +Polymer.dom(this.root).insertBefore(toLocal, beforeNode); + +var allSpans = Polymer.dom(this).querySelectorAll('span'); +``` + +You can use `Polymer.dom` on any node, whether or not it has a local DOM tree: + +Example: + +```html +<template> + <div id="container"> + <div id="first"></div> + <content></content> + </div> +</template> + +... + +var insert = document.createElement('div'); +Polymer.dom(this.$.container).insertBefore(insert, this.$.first); + +``` + +Sometimes it's necessary to access the elements which have been distributed to a given `<content>` insertion point or to know to which `<content>` a given node has been distributed. The `getDistributedNodes` and `getDestinationInsertionPoints` respectively provide this information. + +Example: + +```html +<x-foo> + <div></div> +</x-foo> + +// x-foo's template +<template> + <content></content> +</template> +``` + +```js +var div = Polymer.dom(xFoo).querySelector('div'); +var content = Polymer.dom(xFoo.root).querySelector('content'); +var distributed = Polymer.dom(content).getDistributedNodes()[0]; +var insertedTo = Polymer.dom(div).getDestinationInsertionPoints(); + +// the following should be true: +assert.equal(distributed, div); +assert.equal(insertedTo, content) +``` + +<a name="configure-values"></a> +## Configuring default property values + +Default values for properties may be specified in the `properties` object using the `value` field. The value may either be a primitive value, or a function that returns a value (which should be used for initializing Objects and Arrays to avoid shared objects on instances). + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + + mode: { + type: String, + value: 'auto' + }, + + data: { + type: Object, + notify: true, + value: function() { return {}; } + } + + } + +}); +``` +<a name="ready-method"></a> +## Ready callback + +The `ready` method is part of an element's lifecycle and is automatically called 'bottom-up' after the element's template has been stamped and all elements inside the element's local DOM have been configured (with values bound from parents, deserialized attributes, or else default values) and had their `ready` method called. Implement `ready` when it's necessary to manipulate an element's local DOM when the element is constructed. + +Example: + +```js +ready: function() { + this.$.ajax.go(); +} +``` + +# Declarative data binding, event handlers, and property effects + +<a name="node-marshalling"></a> +## Local node marshalling + +Polymer automatically builds a map of instance nodes stamped into its local DOM, to provide convenient access to frequently used nodes without the need to query for (and memoize) them manually. Any node specified in the element's template with an `id` is stored on the `this.$` hash by `id`. + +Example: + +```html +<dom-module id="x-custom"> + <template> + Hello World from <span id="name"></span>! + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + this.$.name.textContent = this.name; + } + + }); + +</script> +``` + +<a name="event-listeners"></a> +## Event listener setup + +Event listeners can be added to the host element by providing an object-valued `listeners` property that maps events to event handler function names. + +Example: + +```html +<dom-module id="x-custom"> + <template> + <div>I will respond</div> + <div>to a click on</div> + <div>any of my children!</div> + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'x-custom', + + listeners: { + 'click': 'handleClick' + }, + + handleClick: function(e) { + alert("Thank you for clicking"); + } + + }); + +</script> +``` + +<a name="annotated-listeners"></a> +## Annotated event listener setup + +For adding event listeners to local-DOM children, a more convenient `on-<event>` annotation syntax is supported directly in the template. This often eliminates the need to give an element an `id` solely for the purpose of binding an event listener. + +Example: + +```html +<dom-module id="x-custom"> + <template> + <button on-click="handleClick">Kick Me</button> + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'x-custom', + + handleClick: function() { + alert('Ow!'); + } + + }); + +</script> +``` + +<a name="change-callbacks"></a> +## Property change callbacks (observers) + +### Single property observation + +Custom element properties may be observed for changes by specifying `observer` property in the `properties` for the property that gives the name of a funciton to call. When the property changes, the change handler will be called with the new and old values as arguments. + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + disabled: { + type: Boolean, + observer: 'disabledChanged' + }, + highlight: { + observer: 'highlightChanged' + } + }, + + disabledChanged: function(newValue, oldValue) { + this.toggleClass('disabled', newValue); + this.highlight = true; + }, + + highlightChanged: function() { + this.classList.add('highlight'); + setTimeout(function() { + this.classList.remove('highlight'); + }, 300); + } + +}); +``` + +Note that property change observation is achieved in Polymer by installing setters on the custom element prototype for properties with registered interest (as opposed to observation via Object.observe or dirty checking, for example). + +### Multiple property observation + +Observing changes to multiple properties is supported via the `observers` array on the prototype, using a string containing a method signature that includes any dependent arguments. Once all properties are defined (`!== undefined`), the observer method will be called once for each change to a dependent property. The current values of the dependent properties will be passed as arguments to the observer method in the order defined in the `observers` method signature. + +*Note, computing functions will only be called once all dependent properties are defined (`!=undefined`). If one or more of the properties are optional, they would need default `value`'s defined in `properties` to ensure the observer is called.* + +*Note that any observers defined in the `observers` array will not receive `old` values as arguments, only new values. Only single-property observers defined in the `properties` object received both `old` and `new` values.* + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + preload: Boolean, + src: String, + size: String + }, + + observers: [ + 'updateImage(preload, src, size)' + ], + + updateImage: function(preload, src, size) { + // ... do work using dependent values + } + +}); +``` + +### Path observation + +Observing changes to object sub-properties is also supported via the same `observers` array, by specifying a path (e.g. `user.manager.name`). + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + user: Object + }, + + observers: [ + 'userManagerChanged(user.manager)' + ], + + userManagerChanged: function(user) { + console.log('new manager name is ' + user.name); + } + +}); +``` + +*Note that observing changes to paths (object sub-properties) is dependent on one of two requirements: either the value at the path in question changed via a Polymer [property binding](#property-binding) to another element, or the value was changed using the [`setPathValue`](#set-path) API, which provides the required notification to elements with registered interest.* + +### Deep path observation + +Additionally, wildcard matching of path changes is also supported via the `observers` array, which allows notification when any (deep) sub-property of an object changes. Note that the argument passed for a path with a wildcard is a change record object containing the `path` that changed, the new `value` of the path that changed, and the `base` value of the wildcard expression. + +Example: + +```js +Polymer({ + + is: 'x-custom', + + properties: { + user: Object + }, + + observers: [ + 'userManagerChanged(user.manager.*)' + ], + + userManagerChanged: function(changeRecord) { + if (changeRecord.path == 'user.manager') { + // user.manager object itself changed + console.log('new manager name is ' + newValue.name); + } else { + // sub-property of user.manager changed + console.log(changeRecord.path + ' changed to ' + changeRecord.value); + } + } + +}); +``` + +<a name="property-binding"></a> +## Annotated property binding + +### Basic property binding + +Properties of the custom element may be bound into text content or properties of local DOM elements using binding annotations in the template. + +To bind to textContent, the binding annotation must currently span the entire content of the tag: + +```html +<dom-module id="user-view"> + <template> + + <!-- Supported --> + First: <span>{{first}}</span><br> + Last: <span>{{last}}</span> + + <!-- Not currently supported! --> + <div>First: {{first}}</div> + <div>Last: {{last}}</div> + + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'user-view', + + properties: { + first: String, + last: String + } + + }); + +</script> + +<user-view first="Samuel" last="Adams"></user-view> + +``` + +To bind to properties, the binding annotation should be provided as the value to an attribute with the same name of the JS property to bind to: + +```html +<dom-module id="main-view"> + <template> + <user-view first="{{user.first}}" last="{{user.last}}"></user-view> + </template> +</dom-module> + +<script> + + Polymer({ + + is: 'main-view', + + properties: { + user: Object + } + + }); + +</script> +``` + +As in the example above, paths to object sub-properties may also be specified in templates. See [Binding to structured data](#path-binding) for details. + +In order to bind to camel-case properties of elements, dash-case should be used in the attribute name. Example: + +```html +<user-view first-name="{{managerName}}"></user-view> +<!-- will set <user-view>.firstName = this.managerName; --> +``` + +Note that while HTML attributes are used to specify bindings, values are assigned directly to JS properties, not to the HTML attributes of the elements unless specific [attribute bindings](#attribute-binding) are used. + +<a name="property-notification"></a> +### Property change notification and Two-way binding + +Polymer supports cooperative two-way binding between elements, allowing elements that "produce" data or changes to data to propagate those changes upwards to hosts when desired. + +When a Polymer elements changes a property that was configured in `properties` with the `notify` flag set to true, it automatically fires a non-bubbling DOM event to indicate those changes to interested hosts. These events follow a naming convention of `<property>-changed`, and contain a `value` property in the `event.detail` object indicating the new value. + +As such, one could attach an `on-<property>-changed` listener to an element to be notified of changes to such properties, set the `event.detail.value` to a property on itself, and take necessary actions based on the new value. However, given this is a common pattern, bindings using "curly-braces" (e.g. `{{property}}`) will automatically perform this upwards binding automatically without the user needing to perform those tasks. This can be disabled by using "square-brace" syntax (e.g. `[[property]]`), which results in only one-way (downward) data-binding. + +To summarize, two-way data-binding is achieved when both the host and the child agree to participate, satisfying these three conditions: + +1. The host must use curly-brace `{{property}}` syntax. Square-brace `[[property]]` syntax results in one-way downward binding, regardless of the notify state of the child's property. +2. The child property being bound to must be configured with the `notify` flag set to true (or otherwise send a `<property>-changed` custom event). If the property being bound does not have the `notify` flag set, only one-way (downward) binding will occur. +3. The child property being bound to must not be configured with the `readOnly` flag set to true. If the child property is `notify: true` and `readOnly:true`, and the host binding uses curly-brace syntax, the binding will effectively be one-way (upward). + +Example 1: Two-way binding + +```html +<script> + + Polymer({ + is: 'custom-element', + properties: { + prop: { + type: String, + notify: true + } + } + }); + +</script> +... + +<!-- changes to `value` propagate downward to `prop` on child --> +<!-- changes to `prop` propagate upward to `value` on host --> +<custom-element prop="{{value}}"></custom-element> +``` + +Example 2: One-way binding (downward) + +```html +<script> + Polymer({ + is: 'custom-element', + properties: { + prop: { + type: String, + notify: true + } + } + }); +</script> + +... + +<!-- changes to `value` propagate downward to `prop` on child --> +<!-- changes to `prop` are ignored by host due to square-bracket syntax --> +<custom-element prop="[[value]]"></custom-element> +``` + +Example 3: One-way binding (downward) + +```html +<script> + + Polymer({ + is: 'custom-element', + properties: { + prop: String // no `notify:true`! + } + }); + +</script> +... + +<!-- changes to `value` propagate downward to `prop` on child --> +<!-- changes to `prop` are not notified to host due to notify:falsey --> +<custom-element prop="{{value}}"></custom-element> +``` + +Example 4: One-way binding (upward) + +```html +<script> + Polymer({ + is: 'custom-element', + properties: { + prop: { + type: String, + notify: true, + readOnly: true + } + } + }); +</script> + +... + +<!-- changes to `value` are ignored by child due to readOnly:true --> +<!-- changes to `prop` propagate upward to `value` on host --> +<custom-element prop="{{value}}"></custom-element> +``` + +Example 5: Error / non-sensical state + +```html +<script> + + Polymer({ + is: 'custom-element', + properties: { + prop: { + type: String, + notify: true, + readOnly: true + } + } + }); + +</script> + +... + +<!-- changes to `value` are ignored by child due to readOnly:true --> +<!-- changes to `prop` are ignored by host due to square-bracket syntax --> +<!-- binding serves no purpose --> +<custom-element prop="[[value]]"></custom-element> +``` + +### Custom notify event and binding to native elements + +As mentioned above, Polymer uses an event naming convention to achieve two-way binding. The act of two-way binding to a property using `target-prop={{hostProp}}` syntax results in Polymer adding a `<target-prop>-changed` event listener to the element by default. All properties of a Polymer element with `notify: true` send events using this convention to notify of changes. + +In order to two-way bind to native elements or non-Polymer elements that do not follow this event naming convention when notifying changes, you may specify a custom event name in the curley braces, delimited with `::`. + +Example: + +```html +<!-- Listens for `input` event and sets hostValue to <input>.value --> +<input value="{{hostValue::input}}"> + +<!-- Listens for `change` event and sets hostChecked to <input>.checked --> +<input type="checkbox" checked="{{hostChecked::change}}"> + +<!-- Listens for `timeupdate ` event and sets hostTime to <video>.currentTime --> +<video url="..." current-time="{{hostTime::timeupdate}}"> +``` + +Note: When binding to standard notifying properties on Polymer elements, specifying the event name is unnecessary, as the default convention will be used. The following constructions are equivalent: + +```html + +<!-- Listens for `value-changed` event --> +<my-element value="{{hostValue::value-changed}}"> + +<!-- Listens for `value-changed` event using Polymer convention by default --> +<my-element value="{{hostValue}}"> + +``` + + +<a name="path-binding"></a> +### Binding to structured data + +Sub-properties of objects may be two-way bound to properties of custom elements as well by specifying the path of interest to the binding annotation. + +Example: + +```html +<template> + <div>{{user.manager.name}}</div> + <user-element user="{{user}}"></user-element> +</template> +``` + +As with change handlers for paths, bindings to paths (object sub-properties) are dependent on one of two requirements: either the value at the path in question changed via a Polymer [property binding](#property-binding) to another element, or the value was changed using the [`setPathValue`](#set-path) API, which provides the required notification to elements with registered interest, as discussed below. + +Note that path bindings are distinct from property bindings in a subtle way: when a property's value changes, an assignment must occur for the value to propagate to the property on the element at the other side of the binding. However, if two elements are bound to the same path of a shared object and the value at that path changes (via a property binding or via `setPathValue`), the value seen by both elements actually changes with no additional assignment necessary, by virtue of it being a property on a shared object reference. In this case, the element who changed the path must notify the system so that other elements who have registered interest in the same path may take side effects. However, there is no concept of one-way binding in this case, since there is no concept of propagation. That is, all bindings and change handlers for the same path will always be notified and update when the value of the path changes. + +<a name="set-path"></a> +### Path change notification + +Two-way data-binding and observation of paths in Polymer is achieved using a similar strategy to the one described above for [2-way property binding](#property-notification): When a sub-property of a property configured with `type: Object` changes, an element fires a non-bubbling `<property>-changed` DOM event with a `detail.path` value indicating the path on the object that changed. Elements that have registered interest in that object (either via binding or change handler) may then take side effects based on knowledge of the path having changed. Finally, those elements will forward the notification on to any children they have bound the object to, and will also fire a new `<property>-changed` event where `property` is the root object, to notify any hosts that may have bound root object down. Through this method, a notification will reach any part of the tree that has registered interest in that path so that side effects occur. + +This system "just works" to the extent that changes to object sub-properties occur as a result of being bound to a notifying custom element property that changed. However, sometimes imperative code needs to "poke" at an object's sub-properties directly. As we avoid more sophisticated observation mechanisms such as Object.observe or dirty-checking in order to achieve the best startup and runtime performance cross-platform for the most common use cases, changing an object's sub-properties directly requires cooperation from the user. + +Specifically, Polymer provides two API's that allow such changes to be notified to the system: `notifyPath(path, value)` and `setPathValue(path, value)`. + +Example: + +```html +<dom-module id="custom-element"> + <template> + <div>{{user.manager.name}}</div> + </template> +</dom-module> + +<script> + Polymer({ + + is: 'custom-element', + + reassignManager: function(newManager) { + this.user.manager = newManager; + // Notification required for binding to update! + this.notifyPath('user.manager', this.user.manager); + } + + }); +</script> +``` + +Since in the majority of cases, notifyPath will be called directly after an assignment, a convenience function `setPathValue` is provided that performs both actions: + +```js +reassignManager: function(newManager) { + this.setPathValue('user.manager', newManager); +} +``` + +### Expressions in binding annotations + +Currently the only binding expression supported in Polymer binding annotations is negation using `!`: + +Example: + +```html +<template> + <div hidden="{{!enabled}}"></div> +</template> +``` + +<a name="attribute-binding"></a> +## Declarative attribute binding + +In the vast majority of cases, binding data to other elements should use property binding described above, where changes are propagated by setting the new value to the JavaScript property on the element. + +However, there may be cases where a user actually needs to set an attribute on an element, as opposed to a property. These include a handful of [problematic native HTML attributes](#native-binding), when attribute selectors are used for CSS or for for interoperability with elements that require using attribute-based API. + +Polymer provides an alternate binding annotation syntax to make it explicit when binding values to attributes is desired by using `$=` rather than `=`. This results in in a call to `element.setAttribute('<attr>', value);`, as opposed to `element.property = value;`. + +```html +<template> + + <!-- Attribute binding --> + <my-element selected$="{{value}}"></my-element> + <!-- results in <my-element>.setAttribute('selected', this.value); --> + + <!-- Property binding --> + <my-element selected="{{value}}"></my-element> + <!-- results in <my-element>.selected = this.value; --> + +</template> +``` + +Values will be serialized according to type: Arrays/Objects will be `JSON.stringify`'ed, booleans will result in a non-valued attribute to be either set or removed, and `Dates` and all primitive types will be serialized using the value returned from `toString`. + +Again, as values must be serialized to strings when binding to attributes, it is always more performant to use property binding for pure data propagation. + +<a name="native-binding"></a> +## Binding to native element attributes + +There are a handful of extremely common native element attributes which can also be modified as properties. Due to cross-browser limitations with the ability to place binding braces `{{...}}` in some of these attribute values, as well as the fact that some of these attributes map to differently named JS properties, it is recommended to always use attribute binding (using `$=`) when binding dynamic values to these specific attributes, rather than binding to their property names. + +Normal attribute assignment to static values: + +```html +<!-- class --> +<div class="foo"></div> + +<!-- style --> +<div style="background: red;"></div> + +<!-- href --> +<a href="http://foo.com"> + +<!-- label for --> +<label for="bar"></label> + +<!-- dataset --> +<div data-bar="baz"></div> +``` + +Attribute binding to dynamic values (use `$=`): + +```html +<!-- class --> +<div class$="{{foo}}"></div> + +<!-- style --> +<div style$="{{background}}"></div> + +<!-- href --> +<a href$="{{url}}"> + +<!-- label for --> +<label for$="{{bar}}"></label> + +<!-- dataset --> +<div data-bar$="{{baz}}"></div> +``` + +<a name="attribute-reflection"></a> +## Reflecting properties to attributes + +In specific cases, it may be useful to keep an HTML attribute value in sync with a property value. This may be achieved by setting `reflectToAttribute: true` on a property in the `properties` configuration object. This will cause any change to the property to be serialized out to an attribute of the same name. + +```html +<script> + Polymer({ + + properties: { + response: { + type: Object, + reflectToAttribute: true + } + }, + + responseHandler: function(response) { + this.response = 'loaded'; + // results in this.setAttribute('response', 'loaded'); + } + + }); +</script> +``` + +<a name="attribute-serialization'></a> +Values will be serialized according to type; by default Arrays/Objects will be `JSON.stringify`'ed, booleans will result in a non-valued attribute to be either set or removed, and `Dates` and all primitive types will be serialized using the value returned from `toString`. The `serialize` method may be overridden to supply custom object serialization. + +<a name="computed-properties"></a> +## Computed properties + +Polymer supports virtual properties whose values are calculated from other properties. Computed properties can be defined in the `properties` object by providing a `computed` key mapping to a computing function. The name of the function to compute the value is provided as a string with dependent properties as arguments in parenthesis. Once all properties are defined (`!== undefined`), the computing function will be called to update the computed property once for each change to a dependent property. + +*Note, computing functions will only be called once all dependent properties are defined (`!=undefined`). If one or more of the properties are optional, they would need default `value`'s defined in `properties` to ensure the property is computed.* + +```html +<dom-module id="x-custom"> + <template> + My name is <span>{{fullName}}</span> + </template> +<dom-module id="x-custom"> + +<script> + Polymer({ + + is: 'x-custom', + + properties: { + + first: String, + + last: String, + + fullName: { + type: String, + // when `first` or `last` changes `computeFullName` is called once + // (asynchronously) and the value it returns is stored as `fullName` + computed: 'computeFullName(first, last)' + } + + }, + + computeFullName: function(first, last) { + return first + ' ' + last; + } + + ... + + }); +</script> +``` + +Note: Only direct properties of the element (as opposed to sub-properties of an object) can be used as dependencies at this time. + +<a name="annotated-computed"></a> +## Annotated computed properties + +Anonymous computed properties may also be placed directly in template binding annotations. This is useful when the property need not be a part of the element's API or otherwise used by logic in the element, and is only used for downward data propagation. + +*Note: this is the only form of functions allowed in template bindings, and they must specify one or more dependent properties as arguments, otherwise the function will not be called.* + +*Note, computing functions will only be called once all dependent properties are defined (`!=undefined`). If one or more of the properties are optional, they would need default `value`'s defined in `properties` to ensure the property is computed.* + +Example: + +```html +<dom-module id="x-custom"> + <template> + My name is <span>{{computeFullName(first, last)}}</span> + </template> +<dom-module id="x-custom"> + +<script> + Polymer({ + + is: 'x-custom', + + properties: { + + first: String, + + last: String + + }, + + computeFullName: function(first, last) { + return first + ' ' + last; + } + + ... + + }); +</script> +``` + + + +<a name="read-only"></a> +## Read-only properties + +When a property only "produces" data and never consumes data, this can be made explicit to avoid accidental changes from the host by setting the `readOnly` flag to `true` in the `properties` property definition. In order for the element to actually change the value of the property, it must use a private generated setter of the convention `_set<Property>(value)`. + +```html +<script> + Polymer({ + + properties: { + response: { + type: Object, + readOnly: true, + notify: true + } + }, + + responseHandler: function(response) { + this._setResponse(response); + } + + ... + + }); +</script> +``` + +Generally, read-only properties should also be set to `notify: true` such that their changes are observable from above. + +<a name="utility-functions"></a> +## Utility Functions + +Polymer's Base prototype provides a set of useful convenience/utility functions for instances to use. See API documentation for more details. + +* toggleClass: function(name, bool, [node]) +* toggleAttribute: function(name, bool, [node]) +* attributeFollows: function(name, neo, old) +* fire: function(type, [detail], [onNode], [bubbles], [cancelable]) +* async: function(method) +* transform: function(node, transform) +* translate3d: function(node, x, y, z) +* importHref: function(href, onload, onerror) + +<a name="settings"></a> +## Global Polymer settings + +Document-level global Polymer settings can be set before loading by setting a `Polymer` object on window as the first script in the main document: + +```html +<html> +<head> + <meta charset="utf-8"> + <script> Polymer = { dom: 'shadow' }; </script> + <script src="../../../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/my-app.html"> +</head> +<body> + + ... + +``` + +Settings can also be switched on the URL query string: + +``` +http://myserver.com/test-app/index.html?dom=shadow +``` + +Available settings: + +* `dom` - options: + * `shady` - all local DOM will be rendered using Shady DOM (even where shadow-DOM supported (current default) + * `shadow` - local DOM will be rendered using Shadow DOM where supported (this will be made default soon) + +# Experimental Features & Elements + +<a name="x-repeat"></a> +## Template repeater (x-repeat) +EXPERIMENTAL - API MAY CHANGE + +Elements in a template can be automatically repeated and bound to array items using a custom `HTMLTemplateElement` type extension called `x-repeat`. `x-repeat` accepts an `items` property, and one instance of the template is stamped for each item into the DOM at the location of the `x-repeat` element. The `item` property will be set on each instance's binding scope, thus templates should bind to sub-properties of `item`. Example: + +```html +<dom-module id="employee-list"> + + <template> + + <div> Employee list: </div> + <template is="x-repeat" items="{{employees}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + </template> + + </template> + + <script> + Polymer({ + is: 'employee-list', + ready: function() { + this.employees = [ + {first: 'Bob', last: 'Smith'}, + {first: 'Sally', last: 'Johnson'}, + ... + ]; + } + }); + </script> + +</dom-module> +``` + +Notifications for changes to items sub-properties will be forwarded to template instances, which will update via the normal [structured data notification system](#path-binding). + +Mutations to the `items` array itself (`push`, `pop`, `splice`, `shift`, `unshift`) are observed via `Array.observe` (where supported, or an experimental shim of this API on unsupported browsers), and template instances are kept in sync with the data in the array. + +A view-specific filter/sort may be applied to each `x-repeat` by supplying a `filter` and/or `sort` property. This may be a string that names a function on the host, or a function may be assigned to the property directly. The functions should implemented following the standard `Array` filter/sort API. + +In order to re-run the filter or sort functions based on changes to sub-fields of `items`, the `observe` property may be set as a space-separated list of `item` sub-fields that should cause a re-filter/sort when modified. + +For example, for an `x-repeat` with a filter of the following: + +```js +isEngineer: function(item) { + return item.type == 'engineer' || item.manager.type == 'engineer'; +} +``` + +Then the `observe` property should be configured as follows: + +```html +<template is="x-repeat" items="{{employees}}" + filter="isEngineer" observe="type manager.type"> +``` + +Note, to reach the outer parent scope, bindings in an `x-repeat` template may be prefixed with `parent.<property>`. + +<a name="x-array-selector"></a> +## Array selector (x-array-selector) +EXPERIMENTAL - API MAY CHANGE + +Keeping structured data in sync requires that Polymer understand the path associations of data being bound. The `x-array-selector` element ensures path linkage when selecting specific items from an array (either single or multiple). The `items` property accepts an array of user data, and via the `select(item)` and `deselect(item)` API, updates the `selected` property which may be bound to other parts of the application, and any changes to sub-fields of `selected` item(s) will be kept in sync with items in the `items` array. When `multi` is false, `selected` is a property representing the last selected item. When `multi` is true, `selected` is an array of multiply selected items. + +```html +<dom-module id="employee-list"> + + <template> + + <div> Employee list: </div> + <template is="x-repeat" id="employeeList" items="{{employees}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + <button on-click="toggleSelection">Select</button> + </template> + + <x-array-selector id="selector" items="{{employees}}" selected="{{selected}}" multi toggle></x-array-selector> + + <div> Selected employees: </div> + <template is="x-repeat" items="{{selected}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + </template> + + </template> + + <script> + Polymer({ + is: 'employee-list', + ready: function() { + this.employees = [ + {first: 'Bob', last: 'Smith'}, + {first: 'Sally', last: 'Johnson'}, + ... + ]; + }, + toggleSelection: function(e) { + var item = this.$.employeeList.itemForElement(e.target); + this.$.selector.select(item); + } + }); + </script> + +</dom-module> +``` + +<a name="x-if"></a> +## Conditional template +EXPERIMENTAL - API MAY CHANGE + +Elements can be conditionally stamped based on a boolean property by wrapping them in a custom `HTMLTemplateElement` type extension called `x-if`. The `x-if` template stamps itself into the DOM only when its `if` property becomes truthy. + +If the `if` property becomes falsy again, by default all stamped elements will be hidden (but will remain in DOM) for faster performance should the `if` property become truthy again. This behavior may be disabled by setting the `restamp` property, which results in slower `if` switching behavior as the elements are destroyed and re-stamped each time. + +Note, to reach the outer parent scope, all bindings in an `x-if` template must be prefixed with `parent.<property>`, as shown below. + +Example: + +**Note, this is a simple example for illustrative purposes only. Read below for guidance on recommended usage of conditional templates.** + +```html +<dom-module id="user-page"> + + <template> + + All users will see this: + <div>{{user.name}}</div> + + <template is="x-if" if="{{user.isAdmin}}"> + Only admins will see this. + <div>{{parent.user.secretAdminStuff}}</div> + </template> + + </template> + + <script> + Polymer({ + is: 'user-page', + properties: { + user: Object + } + }); + </script> + +</dom-module> +``` + +Note, since it is generally much faster to hide/show elements rather than create/destroy them, conditional templates are only useful to save initial creation cost when the elements being stamped are relatively heavyweight and the conditional may rarely (or never) be true in given useages. Otherwise, liberal use of conditional templates can actually *add* significant runtime performance overhead. + +Consider an app with 4 screens, plus an optional admin screen. If most users will use all 4 screens during normal use of the app, it is generally better to incur the cost of stamping those elements once at startup (where some app initialization time is expected) and simply hide/show the screens as the user navigates through the app, rather than re-create and destroy all the elements of each screen as the user navigates. Using a conditional template here may be a poor choice, since although it may save time at startup by stamping only the first screen, that saved time gets shifted to runtime latency for each user interaction, since the time to show the second screen will be *slower* as it must create the second screen from scratch rather than simply showing that screen. Hiding/showing elements is as simple as attribute-binding to the `hidden` attribute (e.g. `<div hidden$="{{!shouldShow}}">`), and does not require conditional templating at all. + +However, using a conditional template may be appropriate in the case of an admin screen that should only be shown to admin users of an app. Since most users would not be admins, there may be performance benefits to not burdening most of the users with the cost of stamping the elements for the admin page, especially if it is relatively heavyweight. + +<a name="x-autobind"></a> +## Auto-binding template +EXPERIMENTAL - API MAY CHANGE + +Polymer's binding features are only available within templates that are managed by Polymer. As such, these features are available in templates used to define Polymer elements, for example, but not for elements placed directly in the main document. + +In order to use Polymer bindings without defining a new custom element, you may wrap the elements utilizing bindings with a custom template extension called `x-autobind`. This template will immediately stamp itself into the main document and bind elements to the template itself as the binding scope. + +```html +<!doctype html> +<html> +<head> + <meta charset="utf-8"> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + <link rel="import" href="components/core-ajax/core-ajax.html"> + +</head> +<body> + + <!-- Wrap elements in with auto-binding template to --> + <!-- allow use of Polymer bindings main document --> + <template is="x-autobind"> + + <core-ajax url="http://..." lastresponse="{{data}}"></core-ajax> + + <template is="x-repeat" items="{{data}}"> + <div><span>{{item.first}}</span> <span>{{item.last}}</span></div> + </template> + + </template> + +</body> +</html> +``` + +<a name="xscope-styling"></a> +## Cross-scope styling +EXPERIMENTAL - API MAY CHANGE + +### Background + +Shadow DOM (and its approximation via Shady DOM) bring much needed benefits of scoping and style encapsulation to web development, making it safer and easier to reason about the effects of CSS on parts of your application. Styles do not leak into the local DOM from above, and styles do not leak from one local DOM into the local DOM of other elements inside. + +This is great for *protecting* scopes from unwanted style leakage. But what about when you intentionally want to *customize* the style of a custom element's local DOM, as the user of an element? This often comes up under the umbrella of "theming". For example a "custom-checkbox" element that may interally use a `.checked` class can protect itself from being affected by CSS from other components that may also happen to use a `.checked` class. However, as the user of the checkbox you may wish to intentionally change the color of the check to match your product's branding, for example. The "protection" that Shadow DOM provides at the same time introduces a practical barrier to "theming" use cases. + +One solution the Shadow DOM spec authors provided to address the theming problem are the `/deep/` and `::shadow` combinators, which allow writing rules that pierce through the Shadow DOM encapsulation boundary. Although Polymer 0.5 promoted this mechanism for theming, it was ultimately unsatisfying for several reasons: + +* Using `/deep/` and `::shadow` for theming leaks details of an otherwise encapsulated element to the user, leading to brittle selectors piercing into the internal details of an element's Shadow DOM that are prone to breakage when the internal implementation changes. As a result, the structure of of an element's Shadow DOM inadvertently becomes API surface subject to breakage, diminishing the practical effectiveness of Shadow DOM as an encapsulation primitive. +* Although Shadow DOM's style encapsulation *improves* the predictability of style recalc performance since the side effects of a style change are limited to a small subset of the document, using `/deep/` and `::shadow` re-open the style invalidation area and reduce Shadow DOM's effectiveness as a performance primitive. +* Using `/deep/` and `::shadow` lead to verbose and difficult to understand selectors. + +For the reasons above, the Polymer team is currently exploring other options for theming that address the shortcomings above and provide a possible path to obsolescence of `/deep/` and `::shadow` altogether. + +<a name="xscope-styling-details"></a> +### Custom CSS properties + +Polymer 0.8 includes a highly experimental and opt-in shim for custom CSS properties inspired by (and compatible with) the future W3C [CSS Custom Properties for Cascading Variables](http://dev.w3.org/csswg/css-variables/) specification (see [explainer on MDN here](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables)). + +Rather than exposing the details of an element's internal implementation for theming, instead an element author would define one or more custom CSS properties as part of the element's API which it would consume to style internals of the element deemed important for theming by the element's author. These custom properties can be defined similar to other standard CSS properties and will inherit from the point of definition down the composed DOM tree, similar to the effect of `color` and `font-family`. + +In the simple example below, the author of `my-toolbar` identified the need for users of the toolbar to be able to change the color of the toolbar title. The author exposed a custom property called `--my-toolbar-title-color` which is assigned to the `color` property of the selector for the title element. Users of the toolbar may define this variable in a CSS rule anywhere up the tree, and the value of the property will inherit down to the toolbar where it is used if defined, similar to other standard inheriting CSS properties. + +Example: + +```html +<dom-module id="my-toolbar"> + + <style> + :host { + padding: 4px; + background-color: gray; + } + .title { + color: var(--my-toolbar-title-color); + } + </style> + + <template> + <span class="title">{{title}}</span> + </template> + + <script> + Polymer({ + is: 'my-toolbar', + properties: { + title: String + }, + // The custom properties shim is currently an opt-in feature + enableCustomStyleProperties: true + }); + </script> + +</dom-module> +``` + +Example usage of `my-toolbar`: + +```html +<dom-module id="my-element"> + + <style> + + /* Make all toolbar titles in this host green by default */ + :host { + --my-toolbar-title-color: green; + } + + /* Make only toolbars with the .warning class red */ + .warning { + --my-toolbar-title-color: red; + } + + </style> + + <template> + + <my-toolbar title="This one is green."></my-toolbar> + <my-toolbar title="This one is green too."></my-toolbar> + + <my-toolbar class="warning" title="This one is red."></my-toolbar> + + </template> + +</dom-module> +``` + +The `--my-toolbar-title-color` property will only affect the color of the title element encapsulated in `my-toolbar`'s internal implementation. If in the future the `my-toolbar` author chose to rename the `.title` class or otherwise restructure the internal details of `my-toolbar`, users are shielded from this change via the indirection afforded by custom properties. + +Thus, custom CSS properties introduce a powerful way for element authors to expose a theming API to their users in a way that naturally fits right alongside normal CSS styling and avoids the problems with `/deep/` and `::shadow`, and is already on a standards track with shipping implementation by Mozilla and planned support by Chrome. + +However, it may be tedious (or impossible) for an element author to anticipate and expose every possible CSS property that may be important for theming an element as individual CSS properties (for example, what if a user needed to adjust the `opacity` of the toolbar title?). For this reason, the custom properties shim included in Polymer includes an experimental extension allowing a bag of CSS properties to be defined as a custom property and allowing all properties in the bag to be applied to a specific CSS rule in an element's local DOM. For this, we introduce a `mixin` capability that is analogous to `var`, but allows an entire bag of properties to be mixed in. + +Example: + +```html +<dom-module id="my-toolbar"> + + <style> + :host { + padding: 4px; + background-color: gray; + mixin(--my-toolbar-theme); + } + .title { + mixin(--my-toolbar-title-theme); + } + </style> + + <template> + <span class="title">{{title}}</span> + </template> + + ... + +</dom-module> +``` + +Example usage of `my-toolbar`: + +```html +<dom-module id="my-element"> + + <style> + + /* Apply custom theme to toolbars */ + :host { + --my-toolbar-theme: { + background-color: green; + border-radius: 4px; + border: 1px solid gray; + } + --my-toolbar-title-theme: { + color: green; + } + } + + /* Make only toolbars with the .warning class red and bold */ + .warning { + --my-toolbar-title-theme: { + color: red; + font-weight: bold; + } + } + + </style> + + <template> + + <my-toolbar title="This one is green."></my-toolbar> + <my-toolbar title="This one is green too."></my-toolbar> + + <my-toolbar class="warning" title="This one is red."></my-toolbar> + + </template> + +</dom-module> +``` + +### Custom Properties Shim - Limitations and API details + +Experimental cross-platform support for custom properties is provided in Polymer by a Javascript library that approximates the capabilities of the CSS Variables specification *for the specific use case of theming custom elements*, while also extending it to add the mixin capability described above. **It is important to note that this is not a full polyfill**, as doing so would be prohibitively expensive; rather this is a shim that is inspired by that specification and trades off aspects of the full dynamism possible in CSS with practicality and performance. + +Below are current limitations of this experimental system. Improvements to performance and dynamism will continue to be explored. + +* As this feature is still experimental, custom properties are not currently applied to elements by default. To enable *usage* of custom properties, set an `enableCustomStyleProperties: true` property on the Polymer element prototype. + +* Only rules which match the element at *creation time* are applied. Any dynamic changes that update variable values are not applied automatically. + + ```html + <div class="container"> + <x-foo class="a"></x-foo> + </div> + ``` + + ```css + /* applies */ + x-foo.a { + --foo: brown; + } + /* does not apply */ + x-foo.b { + --foo: orange; + } + /* does not apply to x-foo */ + .container { + --nog: blue; + } + ``` +* Re-evaluation of custom property styles does not currently occur as a result of changes to the DOM. Re-evaluation can be forced by calling `this.updateStyles()` on a Polymer element. For example, if class `b` was added to `x-foo` above, the scope must call `this.updateStyles()` to apply the styling. This re-calcs/applies styles down the tree from this point. + +* Dynamic effects are reflected at the point of a variable’s application, but not its definition. + + For the following example, adding/removing the `highlighted` class on the `#title` element will have the desired effect, since the dynamism is related to *application* of a custom property. + + ```css + #title { + background-color: var(--title-background-normal); + } + + #title.highlighted { + background-color: var(--title-background-highlighted); + } + ``` + + However, the shim does not currently support dynamism at the point of *definition* of a custom property. In the following example, `this.updateStyles()` would be required to update the value of `--title-background` being applied to `#title` when the `highlighted` class was added or removed. + + ```css + #title { + --title-background: gray; + } + + #title.highlighted { + --title-background: yellow; + } + ``` + +<a name="x-style"></a> +## Custom element for document styling (x-style) +EXPERIMENTAL - API MAY CHANGE + +An experimental `<style is="x-style">` custom element is provided for defining styles in the main document that can take advantage of several special features of Polymer's styling system: + +* Document styles defined in an `x-style` will be shimmed to ensure they do not leak into local DOM when running on browsers without non-native Shadow DOM. +* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on browsers without non-native Shadow DOM. +* Custom properties used by Polymer's experimental [shim for cross-scope styling](#xscope-styling-details) may be defined in an `x-style`. + +Example: + +```html +<!doctype html> +<html> +<head> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + + <style is="x-style"> + + /* Will be prevented from affecting local DOM of Polymer elements */ + * { + box-sizing: border-box; + } + + /* Can use /deep/ and ::shadow combinators */ + body /deep/ .my-special-view::shadow #thing-inside { + background: yellow; + } + + /* Custom properties that inherit down the document tree may be defined */ + * { + --my-toolbar-title-color: green; + } + + </style> + +</head> +<body> + + ... + +</body> +</html> +``` + +Note, all features of `x-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `x-style` extension should only be used for defining document styles, outside of a custom element's local DOM. + +<a name="external-stylesheets"></a> +## External stylesheets +EXPERIMENTAL - API MAY CHANGE + +Polymer includes an experimental feature to support loading external stylesheets that will be applied to the local DOM of an element. This is typically convenient for developers who like to separate styles, share common styles between elements, or use style pre-processing tools. The syntax is slightly different from how stylesheets are typically loaded, as the feature leverages HTML Imports (or the HTML Imports polyfill, where appropriate) to load the stylesheet text such that it may be properly shimmed and/or injected as an inline style. + +To include a remote stylesheet that applies to your Polymer element's local DOM, place a special HTML import `<link>` tag with `type="css"` in your `<dom-module>` that refers to the external stylesheet to load. + +Example: + +```html +<dom-module id="my-awesome-button"> + + <!-- special import with type=css used to load remote CSS --> + <link rel="import" type="css" href="my-awesome-button.css"> + + <template> + ... + </template> + + <script> + Polymer({ + is: 'my-awesome-button', + ... + }); + </script> + +</dom-module> +``` + +<a name="feature-layering"></a> +## Feature layering +EXPERIMENTAL - API MAY CHANGE + +Polymer 0.8 is currently layered into 3 sets of features provided as 3 discrete HTML imports, such that an individual element developer can depend on a version of Polymer whose feature set matches their tastes/needs. For authors who opt out of the more opinionated local DOM or data-binding features, their element's dependencies would not be payload- or runtime-burdened by these higher-level features, to the extent that a user didn't depend on other elements using those features on that page. That said, all features are designed to have low runtime cost when unused by a given element. + +Higher layers depend on lower layers, and elements requiring lower layers will actually be imbued with features of the highest-level version of Polymer used on the page (those elements would simply not use/take advantage of those features). This provides a good tradeoff between element authors being able to avoid direct dependencies on unused features when their element is used standalone, while also allowing end users to mix-and-match elements created with different layers on the same page. + +* polymer-micro.html: [Polymer micro features](#polymer-micro) (bare-minum Custom Element sugaring) +* polymer-mini.html: [Polymer mini features](#polymer-mini) (template stamped into "local DOM" and tree lifecycle) +* polymer.html: [Polymer standard features](#polymer-standard) (all other features: declarative data binding and event handlers, property nofication, computed properties, and experimental features) + +This layering is subject to change in the future and the number of layers may be reduced. + +--- + +<a name="migration-notes"></a> +# Migration Notes + +This section covers how to deal with yet-unimplemented and/or de-scoped features in Polymer 0.8 as compared to 0.5. Many of these are simply un-implemented; that is, we will likely have a final "solution" that addresses the need, we just haven't tackled that feature yet as we address items in priority order. Other solutions in 0.8 may be lower-level as compared to 0.5, and will be explained here. + +As the final 0.8 API solidifies, this section will be updated accordingly. As such, this section should be considered answers "how do I solve problem xyz <em>TODAY</em>", rather than a representation of the final Polymer 0.8 API. + +## Property casing + +TL;DR: When binding to camel-cased properties, use "dash-case" attribute names to indicate the "camelCase" property to bind to. + +Example: bind `this.myValue` to `<x-foo>.thatValue`: + +BEFORE: 0.5 + +```html +<x-foo thatValue="{{myValue}}"></x-foo> +``` + +AFTER: 0.8 + +```html +<x-foo that-value="{{myValue}}"></x-foo> +``` + +In 0.5, binding annotations were allowed to mixed-case properties (despite the fact that attribute names always get converted to lower-case by the HTML parser), and the Node.bind implementation at the "receiving end" of the binding automatically inferred the mixed-case property it was assumed to refer to at instance time. + +In 0.8, "binding" is done at prorotype time before the type of the element being bound to is known, hence knowing the exact JS property to bind to allows better efficiency. + +## Binding limitations + +Current limitations that are on the backlog for evaluation/improvement are listed below, with current workarounds: + +* Sub-textContent/property binding + * You cannot currrently do any of the following: + + ```html + <div> stuff here: {{stuff}}</div> + <div class$="{{thing}} {{another}}"></div> + <x-custom prop="{{thing}} {{another}}"></x-custom> + ``` + + * Instead, use `<span>`'s to break up textContent into discrete elements: + + ```html + <div> stuff here: <span>{{stuff}}</span></div> + ``` + + * Use computed properties for concatenating into properties/attributes: + + ```html + <div class$="{{computeDivClass(thing, another)}}"></div> + <x-custom prop="{{computeCustomProp(thing, another}}"></x-custom> + ``` + +* CSS class binding: + * May bind entire class list from one property to `class` _attribute_: + `<div class$="{{classes}}">` + * Otherwise, `this.classList.add/remove` from change handlers +* CSS inline-style binding: + * May bind entire inline style from one property to `style` _attribute_: + `<div style$="{{styles}}">` + * Otherwise, assign `this.style.props` from change handlers + +## Structured data and path notification + +To notify non-bound structured data changes, use `setPathValue` and `notifyPath`: + +```js +this.setPathValue('user.manager', 'Matt'); +``` + +Which is equivalent to: + +```js +this.user.manager = 'Matt'; +this.notifyPath('user.manager', this.user.manager); +``` + +## Repeating elements + +Repeating templates is moved to a custom element (HTMLTemplateElement type extension called `x-repeat`): + +```html +<template is="x-repeat" items="{{users}}"> + <div>{{item.name}}</div> +</template> +``` + +## Array notification + +This area is in high flux. Arrays bound to `x-repeat` are currently observed using `Array.observe` (or equivalent shim) and `x-repeat` will reflect changes to array mutations (push, pop, shift, unshift, splice) asynchronously. + +**In-place sort of array is not supported**. Sorting/filtering will likely be provided as a feature of `x-repeat` (and possibly other array-aware elements such as `x-list`) in the future. + +Implementation and usage details will likely change, stay tuned. + +<a name="todo-inheritance"></a> +## Mixins / Inheritance + +TODO - use composition for now + +## Gesture support + +TODO - use standard DOM for now until gesture support is ported
diff --git a/third_party/polymer/v0_8/components/polymer/README.md b/third_party/polymer/v0_8/components/polymer/README.md new file mode 100644 index 0000000..1149493a --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/README.md
@@ -0,0 +1,330 @@ +# Polymer 0.8 Preview + +Authors interested in learning the core concepts in 0.8 may be interested in our [primer](https://github.com/Polymer/polymer/blob/0.8-preview/PRIMER.md). + +## From The Ground Up + +Let us begin this tale with a short stroll through the layers that Polymer is +built upon, and some of the rationale of how we got there. + +### Raw Custom Elements + +Custom Elements are a powerful emerging web standard that allows developers to create their own elements by attaching a class to a tag-name. + +#### document.registerElement + +The native API is very simple, it looks something like this: + +```js +document.registerElement(<name String>, {prototype: Object[, extends: String]}); +``` + +#### Typical Boilerplate + +There is a little bit of work one has to do to set up the class with the right prototypes and so on to construct a Custom Element. Here is an typical example (using ES5 syntax): + +```js +var ctor = function() { + return document.createElement('x-custom'); +}; +ctor.prototype = Object.create(HTMLElement.prototype); +ctor.prototype.constructor = ctor; +ctor.prototype.createdCallback = function() { + this.innerHTML = 'Hello World, I am a <b>Custom Element!</b>'; +} +document.registerElement('x-custom', ctor); +``` + +### Reluctant Polymer() Abstraction + +By principle, Polymer team tries to avoid abstracting DOM APIs, especially new ones. But in this case we finally decided the ergonomic benefit was worth it. By wrapping `registerElement` in our own function, we can reduce the above boilerplate to: + +```js +var ctor = Polymer({ + is: 'x-custom', + created: function() { + this.innerHTML = 'Hello World, I am a <b>Custom Element!</b>'; + } +}); +``` + +### Polymer() Does a Bit More + +You might notice the `Polymer()` invocation defines `created` instead of `createdCallback`. This is a feature of `Polymer.Base`, a tiny prototype that `Polymer()` adds to your prototype chain as it's handling the boilerplate above. `Polymer.Base` hooks the standard Custom Element lifecycle callbacks to provide helper implementations. The hooks in turn call shorter-named lifecycle methods on your prototype. + +- `created` instead of `createdCallback` +- `attached` instead of `attachedCallback` +- `detached` instead of `detachedCallback` +- `attributeChanged` instead of `attributeChangedCallback` + +You can always fallback to using the low-level methods if you wish (iow, you could simply implement `createdCallback` in your prototype). + +`Polymer.Base` also implements `registerCallback` on your prototype. `Polymer()` calls `registerCallback` which allows `Polymer.Base` to supply a layering system for Polymer abstractions so that no element needs to pay for features it doesn't use. + +## Features + +By default, the default Polymer distribution include several features. Although `Polymer.Base` itself is tiny, if you examine `Polymer.Base` you will probably see several methods that have been plugged-in to that prototype by feature definitions. The next few sections will explain these features and why we include them in the default set. Keep in mind that it's entirely possible to construct custom feature sets, or even use a trivial, featureless form of `Polymer()`. + +### Feature: _property-config_ + +The first feature implements support for the `properties` property. By placing a object-valued `properties` property on your prototype, let's you define various aspects of your custom-elements public API. + +By itself, the `properties` feature **doesn't do anything**. It only provides API for asking questions about these special properties (see [link to docs] for details). + +```js +Polymer({ + + is: 'x-custom', + + properties: { + user: String, + isHappy: Boolean, + count: { + type: Number, + readOnly: true, + notify: true + } + }, + + created: function() { + this.innerHTML = 'Hello World, I am a <b>Custom Element!</b>'; + } + +}); +``` + +Remember that the fields assigned to `count`, such as `readOnly` and `notify` don't do anything by themselves, it requires other features to give them life. + +### Feature: _attributes_ + +Many custom elements want to support configuration using HTML attributes. Custom Elements provides the `attributeChanged` callback gives us the raw API for this ability, but then we have to deal with initialization and type conversion (attributes are always strings). Here is an example of a custom element that supports a `user` attribute using the raw API. + +```js + Polymer({ + + is: 'x-custom', + + created: function() { + // handle any initial value + this.attributeChanged('user'); + // render + this.innerHTML = 'Hello World, my user is ' + (this.user || 'nobody') + '.'; + }, + + attributeChanged: function(name) { + switch(name) { + case 'user': + // pretty easy since user is a String, for other types + // we have to do more work + if (this.hasAttribute('user')) { + this.user = this.getAttribute('user'); + } + break; + } + } + + }); +``` + +Although it's relatively simple, having to write this code becomes annoying when working with multiple attributes or non-String types. It's also not very DRY. + +Instead, Polymer's `attributes` feature handles this work for you (using the `properties` feature data). If an attribute is set that matches a property listed in the `properties` object, the value is captured into the matching property. Strings are automatically converted to the specified type. + +The type system includes support for Object values expressed as JSON, or Date objects expressed as any Date-parsable string representation. Boolean properties are mapped to Boolean attributes, in other words, if the attribute exists at all, its value is true, regardless of its string-value (and the value is only false if the attribute does not exist). + +Here is the equivalent of the above code, taking advantage of the `attributes` feature. + +```html +<script> + + Polymer({ + + is: 'x-custom', + + properties: { + user: String + }, + + created: function() { + // render + this.innerHTML = 'Hello World, my user is ' + (this.user || 'nobody') + '.'; + } + + }); + +</script> + +<x-custom user="Scott"></x-custom> +``` + +### [ToDoc] attributes:hostAttributes + +### Feature: _template_ + +HTML templates are an emerging web standard that we like to consider part of the Web Components family. Templates are a great way to provide archetypal DOM content for your custom element, and this is where the `template` feature comes in. + +As usual, we started by writing basic template support by hand. It generally looks something like this: + +```html +<template> + + Hello World from x-custom! + + </template> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + var template = <find the template somehow>; + var instance = document.importNode(template.content, true); + this.appendChild(instance); + } + + }); + +</script> +``` + +Again, it's simple, but it's a common pattern, so the `template` feature does it automatically. By default it looks for a template as the first element before the script, so our code can look like this: + +```html +<template> + + Hello World from x-custom! + +</template> + +<script> + + Polymer({ + + is: 'x-custom' + + }); + +</script> +``` + +### Feature: _annotations_ + +Most elements need to customize the DOM instanced from a template. For this reason, it's handy to encode markers into your template to indicate special nodes, attributes, or text. Polymer calls these markers _annotations_. The `annotations` feature scans the template (once per element, at registration time) and builds a data-structure into the prototype that identifies markers it finds in the DOM (see [link to docs] for details). Normally you do not need to work with this data directly, Polymer does it for you. + +### Feature: _annotations-nodes_ + +Traditionally, modifying DOM is done by querying for elements to manipulate. Here is an example: + +```html +<template> + + Hello World from <span id="name"></span>! + +</template> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + this.querySelector("#name").textContent = this.name; + } + + }); + +</script> +``` + +This example is very simple. But in real projects, repeating queries is inefficient, so query results are often stored (memoized). Also, as DOM composition becomes more tricky, crafting correct queries can be difficult. For these reasons, automatically capturing nodes makes a good feature. + +The `annotations-nodes` feature builds a map of instance nodes by `id` in `this.$` (using the `annotations` feature data). Here is how the `annotations-nodes` feature simplifies the above example. + +```html +<template> + + Hello World from <span id="name"></span>! + +</template> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + this.$.name.textContent = this.name; + } + + }); + +</script> +``` + +### Feature: _annotations-events_ + +Most elements also need to listen for events. The standard DOM method `addEventListener` provides the low-level support: + +```html +<template> + + <button id="button">Kick Me</button> + +</template> + +<script> + + Polymer({ + + is: 'x-custom', + + created: function() { + this.$.button.addEventListener('click', function() { + alert('Ow!'); + }); + } + + }); + +</script> +``` + +Again, this is pretty simple, but it's so common that it's worth making even simpler. The `annotations-events` feature supports declaring event listeners directly in our template. + +Declaring listeners in the template is convenient, and also helps us decouple view from behavior. + +```html +<template> + + <button on-click="kickAction">Kick Me</button> + +</template> + +<script> + + Polymer({ + + is: 'x-custom', + + kickAction: function() { + alert('Ow!'); + } + + }); + +</script> +``` + +Notice that the `kickAction` method doesn't know anything about `button`. If we decided that kicking should be performed by a key-press, or a menu-item, the element code doesn't need to know. We can change the UI however we want. Also notice that by attaching the event declaratively, we have removed the need to give the button an id. + +### [ToDoc] events feature + +### [ToDoc] keys feature + +### [ToDoc] content feature + +
diff --git a/third_party/polymer/v0_8/components/polymer/bower.json b/third_party/polymer/v0_8/components/polymer/bower.json new file mode 100644 index 0000000..f2bb8f74 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/bower.json
@@ -0,0 +1,26 @@ +{ + "name": "polymer", + "version": "0.8.0-rc.7", + "main": [ + "polymer.html" + ], + "license": "http://polymer.github.io/LICENSE.txt", + "ignore": [ + "/.*", + "/test/" + ], + "authors": [ + "The Polymer Authors (http://polymer.github.io/AUTHORS.txt)" + ], + "repository": { + "type": "git", + "url": "https://github.com/Polymer/polymer.git" + }, + "dependencies": { + "webcomponentsjs": "^0.6.0" + }, + "devDependencies": { + "web-component-tester": "*" + }, + "private": true +}
diff --git a/third_party/polymer/v0_8/components/polymer/build.bat b/third_party/polymer/v0_8/components/polymer/build.bat new file mode 100755 index 0000000..261afde --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/build.bat
@@ -0,0 +1,2 @@ +START /B vulcanize polymer-simplex.html --inline --strip -output dist/polymer-simplex.html +START /B vulcanize polymer.html --inline --strip -output dist/polymer.html
diff --git a/third_party/polymer/v0_8/components/polymer/docs/index.html b/third_party/polymer/v0_8/components/polymer/docs/index.html new file mode 100644 index 0000000..b2fa016 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/docs/index.html
@@ -0,0 +1,48 @@ +<!doctype html> +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<html> +<head> + + <title>x-doc-viewer</title> + + <script src="../perf-lib/perf.js"></script> + + <link rel="import" href="../x-elements/x-doc-viewer/x-doc-viewer.html"> + <link rel="import" href="../assets/icons.html"> + + <style> + + html, body { + font-family: Arial, sans-serif; + margin: 0; + } + + </style> + +</head> + +<body fullbleed vertical layout> + + <script>console.perf();</script> + + <x-doc-viewer flex sources='[ + "src/features/standard/bind.html", + "src/features/standard/notify-path.html", + "src/features/micro/properties.html", + "src/features/standard/annotations.html", + "../x-elements/x-doc-viewer/x-doc-viewer.html" + ]'></x-doc-viewer> + + <script>console.perfEnd();</script> + +</body> + +</html>
diff --git a/third_party/polymer/v0_8/components/polymer/index.html b/third_party/polymer/v0_8/components/polymer/index.html new file mode 100644 index 0000000..77a180b --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/index.html
@@ -0,0 +1,25 @@ +<!doctype html> +<!-- +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE +The complete set of authors may be found at http://polymer.github.io/AUTHORS +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS +--> +<html> +<head> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="../iron-doc-viewer/iron-doc-viewer.html"> + +</head> +<body> + + <iron-doc-viewer src="polymer.html"></iron-doc-viewer> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/polymer/polymer-micro.html b/third_party/polymer/v0_8/components/polymer/polymer-micro.html new file mode 100644 index 0000000..8cf5d389 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/polymer-micro.html
@@ -0,0 +1,51 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="src/polymer-lib.html"> +<link rel="import" href="src/micro/tag.html"> +<link rel="import" href="src/micro/behaviors.html"> +<link rel="import" href="src/micro/extends.html"> +<link rel="import" href="src/micro/constructor.html"> +<link rel="import" href="src/micro/properties.html"> +<link rel="import" href="src/micro/attributes.html"> +<link rel="import" href="src/micro/debouncer.html"> + +<script> + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // shared behaviors + this._prepBehaviors(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + }, + + _prepBehavior: function() {}, + + _initFeatures: function() { + // setup debouncers + this._setupDebouncers(); + // acquire behaviors + this._marshalBehaviors(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + } + + }); + +</script> +
diff --git a/third_party/polymer/v0_8/components/polymer/polymer-mini.html b/third_party/polymer/v0_8/components/polymer/polymer-mini.html new file mode 100644 index 0000000..7bfeb12 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/polymer-mini.html
@@ -0,0 +1,66 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="polymer-micro.html"> + +<link rel="import" href="src/mini/template.html"> +<link rel="import" href="src/mini/ready.html"> +<link rel="import" href="src/mini/shady.html"> +<link rel="import" href="src/mini/shadow.html"> + +<script> + + Polymer.DomModule = document.createElement('dom-module'); + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // shared behaviors + this._prepBehaviors(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + // template + this._prepTemplate(); + // dom encapsulation + this._prepShady(); + }, + + _prepBehavior: function() {}, + + _initFeatures: function() { + // manage local dom + this._poolContent(); + // host stack + this._pushHost(); + // instantiate template + this._stampTemplate(); + // host stack + this._popHost(); + // setup debouncers + this._setupDebouncers(); + // instance shared behaviors + this._marshalBehaviors(); + // top-down initial distribution, configuration, & ready callback + this._tryReady(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + } + + }); + +</script> +
diff --git a/third_party/polymer/v0_8/components/polymer/polymer.html b/third_party/polymer/v0_8/components/polymer/polymer.html new file mode 100644 index 0000000..0457787 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/polymer.html
@@ -0,0 +1,94 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="polymer-mini.html"> + +<link rel="import" href="src/standard/annotations.html"> +<link rel="import" href="src/standard/events.html"> +<link rel="import" href="src/standard/utils.html"> +<link rel="import" href="src/standard/effects.html"> +<link rel="import" href="src/standard/configure.html"> +<link rel="import" href="src/standard/notify-path.html"> +<link rel="import" href="src/standard/resolveUrl.html"> +<link rel="import" href="src/standard/styling.html"> +<link rel="import" href="src/standard/x-styling.html"> + +<script> + + Polymer.Base._addFeature({ + + _registerFeatures: function() { + // identity + this._prepIs(); + // inheritance + this._prepExtends(); + // factory + this._prepConstructor(); + // template + this._prepTemplate(); + // template markup + this._prepAnnotations(); + // accessors + this._prepEffects(); + // shared behaviors + this._prepBehaviors(); + // accessors part 2 + this._prepBindings(); + // dom encapsulation + this._prepShady(); + }, + + _prepBehavior: function(b) { + this._addPropertyEffects(b.properties || b.accessors); + this._addComplexObserverEffects(b.observers); + }, + + _initFeatures: function() { + // manage local dom + this._poolContent(); + // manage configuration + this._setupConfigure(); + // host stack + this._pushHost(); + // instantiate template + this._stampTemplate(); + // host stack + this._popHost(); + // concretize template references + this._marshalAnnotationReferences(); + // setup debouncers + this._setupDebouncers(); + // concretize effects on instance + this._marshalInstanceEffects(); + // acquire instance behaviors + this._marshalBehaviors(); + // acquire initial instance attribute values + this._marshalAttributes(); + // top-down initial distribution, configuration, & ready callback + this._tryReady(); + }, + + _marshalBehavior: function(b) { + // publish attributes to instance + this._installHostAttributes(b.hostAttributes); + // establish listeners on instance + this._listenListeners(b.listeners); + } + + }); + +</script> + +<link rel="import" href="src/lib/x-style.html"> +<link rel="import" href="src/lib/template/x-autobind.html"> +<link rel="import" href="src/lib/template/x-template.html"> +<link rel="import" href="src/lib/template/x-repeat.html"> +<link rel="import" href="src/lib/template/x-array-selector.html"> +<link rel="import" href="src/lib/template/x-if.html">
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/annotations/annotations.html b/third_party/polymer/v0_8/components/polymer/src/lib/annotations/annotations.html new file mode 100644 index 0000000..8ccd1d7 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/annotations/annotations.html
@@ -0,0 +1,331 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../module.html"> +<link rel="import" href="../case-map.html"> + +<script> +/** + * Scans a template to produce an annotation list that that associates + * metadata culled from markup with tree locations + * metadata and information to associate the metadata with nodes in an instance. + * + * Supported expressions include: + * + * Double-mustache annotations in text content. The annotation must be the only + * content in the tag, compound expressions are not supported. + * + * <[tag]>{{annotation}}<[tag]> + * + * Double-escaped annotations in an attribute, either {{}} or [[]]. + * + * <[tag] someAttribute="{{annotation}}" another="[[annotation]]"><[tag]> + * + * `on-` style event declarations. + * + * <[tag] on-<event-name>="annotation"><[tag]> + * + * Note that the `annotations` feature does not implement any behaviors + * associated with these expressions, it only captures the data. + * + * Generated data-structure: + * + * [ + * { + * id: '<id>', + * events: [ + * { + * name: '<name>' + * value: '<annotation>' + * }, ... + * ], + * bindings: [ + * { + * kind: ['text'|'attribute'], + * mode: ['{'|'['], + * name: '<name>' + * value: '<annotation>' + * }, ... + * ], + * // TODO(sjmiles): this is annotation-parent, not node-parent + * parent: <reference to parent annotation object>, + * index: <integer index in parent's childNodes collection> + * }, + * ... + * ] + * + * @class Template feature + */ + + // null-array (shared empty array to avoid null-checks) + Polymer.nar = []; + + Polymer.Annotations = { + + // preprocess-time + + // construct and return a list of annotation records + // by scanning `template`'s content + // + parseAnnotations: function(template) { + var list = []; + var content = template._content || template.content; + this._parseNodeAnnotations(content, list); + return list; + }, + + // add annotations gleaned from subtree at `node` to `list` + _parseNodeAnnotations: function(node, list) { + return node.nodeType === Node.TEXT_NODE ? + this._parseTextNodeAnnotation(node, list) : + // TODO(sjmiles): are there other nodes we may encounter + // that are not TEXT_NODE but also not ELEMENT? + this._parseElementAnnotations(node, list); + }, + + // add annotations gleaned from TextNode `node` to `list` + _parseTextNodeAnnotation: function(node, list) { + var v = node.textContent, escape = v.slice(0, 2); + if (escape === '{{' || escape === '[[') { + // NOTE: use a space here so the textNode remains; some browsers + // (IE) evacipate an empty textNode. + node.textContent = ' '; + var annote = { + bindings: [{ + kind: 'text', + mode: escape[0], + value: v.slice(2, -2) + }] + }; + list.push(annote); + return annote; + } + }, + + // add annotations gleaned from Element `node` to `list` + _parseElementAnnotations: function(element, list) { + var annote = { + bindings: [], + events: [] + }; + this._parseChildNodesAnnotations(element, annote, list); + // TODO(sjmiles): is this for non-ELEMENT nodes? If so, we should + // change the contract of this method, or filter these out above. + if (element.attributes) { + this._parseNodeAttributeAnnotations(element, annote, list); + // TODO(sorvell): ad hoc callback for doing work on elements while + // leveraging annotator's tree walk. + // Consider adding an node callback registry and moving specific + // processing out of this module. + if (this.prepElement) { + this.prepElement(element); + } + } + if (annote.bindings.length || annote.events.length || annote.id) { + list.push(annote); + } + return annote; + }, + + // add annotations gleaned from children of `root` to `list`, `root`'s + // `annote` is supplied as it is the annote.parent of added annotations + _parseChildNodesAnnotations: function(root, annote, list, callback) { + if (root.firstChild) { + for (var i=0, node=root.firstChild; node; node=node.nextSibling, i++){ + if (node.localName === 'template' && + !node.hasAttribute('preserve-content')) { + this._parseTemplate(node, i, list, annote); + } + // + var childAnnotation = this._parseNodeAnnotations(node, list, callback); + if (childAnnotation) { + childAnnotation.parent = annote; + childAnnotation.index = i; + } + } + } + }, + + // 1. Parse annotations from the template and memoize them on + // content._notes (recurses into nested templates) + // 2. Parse template bindings for parent.* properties and memoize them on + // content._parentProps + // 3. Create bindings in current scope's annotation list to template for + // parent props found in template + // 4. Remove template.content and store it in annotation list, where it + // will be the responsibility of the host to set it back to the template + // (this is both an optimization to avoid re-stamping nested template + // children and avoids a bug in Chrome where nested template children + // upgrade) + _parseTemplate: function(node, index, list, parent) { + // TODO(sjmiles): simply altering the .content reference didn't + // work (there was some confusion, might need verification) + var content = document.createDocumentFragment(); + content._notes = this.parseAnnotations(node); + content.appendChild(node.content); + // Special-case treatment of 'parent.*' props for nested templates + // Automatically bind `prop` on host to `_parent_prop` on template + // for any `parent.prop`'s encountered in template binding; it is + // responsibility of the template implementation to forward + // these properties as appropriate + var bindings = []; + this._discoverTemplateParentProps(content); + for (var prop in content._parentProps) { + bindings.push({ + index: index, + kind: 'property', + mode: '{', + name: '_parent_' + prop, + value: prop + }); + } + // TODO(sjmiles): using `nar` to avoid unnecessary allocation; + // in general the handling of these arrays needs some cleanup + // in this module + list.push({ + bindings: bindings, + events: Polymer.nar, + templateContent: content, + parent: parent, + index: index + }); + }, + + // Finds all parent.* properties in template content and stores + // the path members in content._parentPropChain, which is an array + // of maps listing the properties of parent templates required at + // each level. Each outer template merges inner _parentPropChains to + // propagate inner parent property needs to outer templates. + // The top-level parent props from the chain (corresponding to this + // template) are stored in content._parentProps. + _discoverTemplateParentProps: function(content) { + var chain = content._parentPropChain = []; + content._notes.forEach(function(n) { + // Find all bindings to parent.* and spread them into _parentPropChain + n.bindings.forEach(function(b) { + var m; + if (m = b.value.match(/parent\.((parent\.)*[^.]*)/)) { + var parts = m[1].split('.'); + for (var i=0; i<parts.length; i++) { + var pp = chain[i] || (chain[i] = {}); + pp[parts[i]] = true; + } + } + }); + // Merge child _parentPropChain[n+1] into this _parentPropChain[n] + if (n.templateContent) { + var tpp = n.templateContent._parentPropChain; + for (var i=1; i<tpp.length; i++) { + if (tpp[i]) { + var pp = chain[i-1] || (chain[i-1] = {}); + Polymer.Base.simpleMixin(pp, tpp[i]); + } + } + } + }); + // Store this template's parentProps map + content._parentProps = chain[0]; + }, + + // add annotation data from attributes to the `annotation` for node `node` + // TODO(sjmiles): the distinction between an `annotation` and + // `annotation data` is not as clear as it could be + // Walk attributes backwards, since removeAttribute can be vetoed by + // IE in certain cases (e.g. <input value="foo">), resulting in the + // attribute staying in the attributes list + _parseNodeAttributeAnnotations: function(node, annotation) { + for (var i=node.attributes.length-1, a; (a=node.attributes[i]); i--) { + var n = a.name, v = a.value; + // id + if (n === 'id') { + annotation.id = v; + } + // events (on-*) + else if (n.slice(0, 3) === 'on-') { + node.removeAttribute(n); + annotation.events.push({ + name: n.slice(3), + value: v + }); + } + // bindings (other attributes) + else { + var b = this._parseNodeAttributeAnnotation(node, n, v); + if (b) { + annotation.bindings.push(b); + } + } + } + }, + + // construct annotation data from a generic attribute, or undefined + _parseNodeAttributeAnnotation: function(node, n, v) { + var mode = '', escape = v.slice(0, 2), name = n; + if (escape === '{{' || escape === '[[') { + // Mode (one-way or two) + mode = escape[0]; + v = v.slice(2, -2); + // Negate + var not = false; + if (v[0] == '!') { + v = v.substring(1); + not = true; + } + // Attribute or property + var kind = 'property'; + if (n[n.length-1] == '$') { + name = n.slice(0, -1); + kind = 'attribute'; + } + // Custom notification event + var notifyEvent, colon; + if (mode == '{' && (colon = v.indexOf('::')) > 0) { + notifyEvent = v.substring(colon + 2); + v = v.substring(0, colon); + } + // Remove annotation + node.removeAttribute(n); + // Case hackery: attributes are lower-case, but bind targets + // (properties) are case sensitive. Gambit is to map dash-case to + // camel-case: `foo-bar` becomes `fooBar`. + // Attribute bindings are excepted. + if (kind === 'property') { + name = Polymer.CaseMap.dashToCamelCase(name); + } + return { + kind: kind, + mode: mode, + name: name, + value: v, + negate: not, + event: notifyEvent + }; + } + }, + + // instance-time + + _localSubTree: function(node, host) { + return (node === host) ? node.childNodes : + (node.lightChildren || node.childNodes); + }, + + findAnnotatedNode: function(root, annote) { + // recursively ascend tree until we hit root + var parent = annote.parent && + Polymer.Annotations.findAnnotatedNode(root, annote.parent); + // unwind the stack, returning the indexed node at each level + return !parent ? root : + Polymer.Annotations._localSubTree(parent, root)[annote.index]; + } + + }; + + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/annotations/demo/app-chrome.html b/third_party/polymer/v0_8/components/polymer/src/lib/annotations/demo/app-chrome.html new file mode 100644 index 0000000..c9d369d --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/annotations/demo/app-chrome.html
@@ -0,0 +1,60 @@ +<!doctype html> +<html> +<head> + + <script src="../../../../perf-lib/perf.js"></script> + + <title>Template Test</title> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <link rel="import" href="../../lang.html"> + <link rel="import" href="../../module.html"> + + <link rel="import" href="../annotations.html"> + + <style> + pre { + font-family: monospace; + font-size: 11px; + } + </style> + +</head> +<body> + + <script>console.perf();</script> + + <template> + + <span id="foo" attribute="{{path}}" oneway="[[otherpath]]" style:="{{specialStyle}}">{{text}}</span> + + </template> + + <pre></pre> + + <script> + + using('Annotations', function(Annotations) { + + var template = document.querySelector('template'); + var list = Annotations.parseAnnotations(template); + console.log(list); + + var out = document.querySelector('pre'); + out.textContent = JSON.stringify(list, function(key, value) { + if (key === 'parent') { + return '<parent reference>'; + } + return value; + }, ' '); + + }); + + </script> + + <script>console.perfEnd();</script> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/array-observe.html b/third_party/polymer/v0_8/components/polymer/src/lib/array-observe.html new file mode 100644 index 0000000..998f59f --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/array-observe.html
@@ -0,0 +1,118 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="debounce.html"> + +<script> + +(function() { + + var callbacks = new WeakMap(); + + function observe(array, cb) { + if (Array.observe) { + var ncb = function(changes) { + changes = changes.filter(function(o) { return o.type == 'splice'; }); + if (changes.length) { + cb(changes); + } + }; + callbacks.set(cb, ncb); + Array.observe(array, ncb); + } else { + if (!array.__polymerObservable) { + makeObservable(array); + } + callbacks.get(array).push(cb); + } + } + + function unobserve(array, cb) { + if (Array.observe) { + var ncb = callbacks.get(cb); + callbacks.delete(cb); + Array.unobserve(array, ncb); + } else { + var cbs = callbacks.get(array); + var idx = cbs.indexOf(cb); + if (idx >= 0) { + cbs.splice(idx, 1); + } + } + } + + function makeObservable(array) { + var splices = []; + var debounce; + var orig = { + push: array.push, + pop: array.pop, + splice: array.splice, + shift: array.shift, + unshift: array.unshift, + sort: array.sort + }; + var addSplice = function(index, added, removed) { + splices.push({ + index: index, + addedCount: added, + removed: removed, + object: array, + type: 'splice' + }); + }; + callbacks.set(array, []); + array.push = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(array.length, 1, []); + return orig.push.apply(this, arguments); + }; + array.pop = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(array.length - 1, 0, array.slice(-1)); + return orig.pop.apply(this, arguments); + }; + array.splice = function(start, deleteCount) { + debounce = Polymer.Debounce(debounce, fin); + addSplice(start, arguments.length - 2, array.slice(start, start + deleteCount)); + return orig.splice.apply(this, arguments); + }; + array.shift = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(0, 0, [array[0]]); + return orig.shift.apply(this, arguments); + }; + array.unshift = function() { + debounce = Polymer.Debounce(debounce, fin); + addSplice(0, 1, []); + return orig.unshift.apply(this, arguments); + }; + array.sort = function() { + debounce = Polymer.Debounce(debounce, fin); + console.warn('[ArrayObserve]: sort not observable'); + return orig.sort.apply(this, arguments); + }; + var fin = function() { + var cbs = callbacks.get(array); + for (var i=0; i<cbs.length; i++) { + cbs[i](splices); + } + splices = []; + }; + array.__polymerObservable = true; + } + + Polymer.ArrayObserve = { + observe: observe, + unobserve: unobserve + }; + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/array-splice.html b/third_party/polymer/v0_8/components/polymer/src/lib/array-splice.html new file mode 100644 index 0000000..f51279a --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/array-splice.html
@@ -0,0 +1,262 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + +Polymer.ArraySplice = (function() { + + function newSplice(index, removed, addedCount) { + return { + index: index, + removed: removed, + addedCount: addedCount + }; + } + + var EDIT_LEAVE = 0; + var EDIT_UPDATE = 1; + var EDIT_ADD = 2; + var EDIT_DELETE = 3; + + function ArraySplice() {} + + ArraySplice.prototype = { + + // Note: This function is *based* on the computation of the Levenshtein + // "edit" distance. The one change is that "updates" are treated as two + // edits - not one. With Array splices, an update is really a delete + // followed by an add. By retaining this, we optimize for "keeping" the + // maximum array items in the original array. For example: + // + // 'xxxx123' -> '123yyyy' + // + // With 1-edit updates, the shortest path would be just to update all seven + // characters. With 2-edit updates, we delete 4, leave 3, and add 4. This + // leaves the substring '123' intact. + calcEditDistances: function(current, currentStart, currentEnd, + old, oldStart, oldEnd) { + // "Deletion" columns + var rowCount = oldEnd - oldStart + 1; + var columnCount = currentEnd - currentStart + 1; + var distances = new Array(rowCount); + + // "Addition" rows. Initialize null column. + for (var i = 0; i < rowCount; i++) { + distances[i] = new Array(columnCount); + distances[i][0] = i; + } + + // Initialize null row + for (var j = 0; j < columnCount; j++) + distances[0][j] = j; + + for (var i = 1; i < rowCount; i++) { + for (var j = 1; j < columnCount; j++) { + if (this.equals(current[currentStart + j - 1], old[oldStart + i - 1])) + distances[i][j] = distances[i - 1][j - 1]; + else { + var north = distances[i - 1][j] + 1; + var west = distances[i][j - 1] + 1; + distances[i][j] = north < west ? north : west; + } + } + } + + return distances; + }, + + // This starts at the final weight, and walks "backward" by finding + // the minimum previous weight recursively until the origin of the weight + // matrix. + spliceOperationsFromEditDistances: function(distances) { + var i = distances.length - 1; + var j = distances[0].length - 1; + var current = distances[i][j]; + var edits = []; + while (i > 0 || j > 0) { + if (i == 0) { + edits.push(EDIT_ADD); + j--; + continue; + } + if (j == 0) { + edits.push(EDIT_DELETE); + i--; + continue; + } + var northWest = distances[i - 1][j - 1]; + var west = distances[i - 1][j]; + var north = distances[i][j - 1]; + + var min; + if (west < north) + min = west < northWest ? west : northWest; + else + min = north < northWest ? north : northWest; + + if (min == northWest) { + if (northWest == current) { + edits.push(EDIT_LEAVE); + } else { + edits.push(EDIT_UPDATE); + current = northWest; + } + i--; + j--; + } else if (min == west) { + edits.push(EDIT_DELETE); + i--; + current = west; + } else { + edits.push(EDIT_ADD); + j--; + current = north; + } + } + + edits.reverse(); + return edits; + }, + + /** + * Splice Projection functions: + * + * A splice map is a representation of how a previous array of items + * was transformed into a new array of items. Conceptually it is a list of + * tuples of + * + * <index, removed, addedCount> + * + * which are kept in ascending index order of. The tuple represents that at + * the |index|, |removed| sequence of items were removed, and counting forward + * from |index|, |addedCount| items were added. + */ + + /** + * Lacking individual splice mutation information, the minimal set of + * splices can be synthesized given the previous state and final state of an + * array. The basic approach is to calculate the edit distance matrix and + * choose the shortest path through it. + * + * Complexity: O(l * p) + * l: The length of the current array + * p: The length of the old array + */ + calcSplices: function(current, currentStart, currentEnd, + old, oldStart, oldEnd) { + var prefixCount = 0; + var suffixCount = 0; + + var minLength = Math.min(currentEnd - currentStart, oldEnd - oldStart); + if (currentStart == 0 && oldStart == 0) + prefixCount = this.sharedPrefix(current, old, minLength); + + if (currentEnd == current.length && oldEnd == old.length) + suffixCount = this.sharedSuffix(current, old, minLength - prefixCount); + + currentStart += prefixCount; + oldStart += prefixCount; + currentEnd -= suffixCount; + oldEnd -= suffixCount; + + if (currentEnd - currentStart == 0 && oldEnd - oldStart == 0) + return []; + + if (currentStart == currentEnd) { + var splice = newSplice(currentStart, [], 0); + while (oldStart < oldEnd) + splice.removed.push(old[oldStart++]); + + return [ splice ]; + } else if (oldStart == oldEnd) + return [ newSplice(currentStart, [], currentEnd - currentStart) ]; + + var ops = this.spliceOperationsFromEditDistances( + this.calcEditDistances(current, currentStart, currentEnd, + old, oldStart, oldEnd)); + + var splice = undefined; + var splices = []; + var index = currentStart; + var oldIndex = oldStart; + for (var i = 0; i < ops.length; i++) { + switch(ops[i]) { + case EDIT_LEAVE: + if (splice) { + splices.push(splice); + splice = undefined; + } + + index++; + oldIndex++; + break; + case EDIT_UPDATE: + if (!splice) + splice = newSplice(index, [], 0); + + splice.addedCount++; + index++; + + splice.removed.push(old[oldIndex]); + oldIndex++; + break; + case EDIT_ADD: + if (!splice) + splice = newSplice(index, [], 0); + + splice.addedCount++; + index++; + break; + case EDIT_DELETE: + if (!splice) + splice = newSplice(index, [], 0); + + splice.removed.push(old[oldIndex]); + oldIndex++; + break; + } + } + + if (splice) { + splices.push(splice); + } + return splices; + }, + + sharedPrefix: function(current, old, searchLength) { + for (var i = 0; i < searchLength; i++) + if (!this.equals(current[i], old[i])) + return i; + return searchLength; + }, + + sharedSuffix: function(current, old, searchLength) { + var index1 = current.length; + var index2 = old.length; + var count = 0; + while (count < searchLength && this.equals(current[--index1], old[--index2])) + count++; + + return count; + }, + + calculateSplices: function(current, previous) { + return this.calcSplices(current, 0, current.length, previous, 0, + previous.length); + }, + + equals: function(currentValue, previousValue) { + return currentValue === previousValue; + } + }; + + return new ArraySplice(); + +})(); +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/async.html b/third_party/polymer/v0_8/components/polymer/src/lib/async.html new file mode 100644 index 0000000..652bf53 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/async.html
@@ -0,0 +1,68 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + +Polymer.Async = (function() { + + var currVal = 0; + var lastVal = 0; + var callbacks = []; + var twiddle = document.createTextNode(''); + + function runAsync(callback, waitTime) { + if (waitTime > 0) { + return ~setTimeout(callback, waitTime); + } else { + twiddle.textContent = currVal++; + callbacks.push(callback); + return currVal - 1; + } + } + + function cancelAsync(handle) { + if (handle < 0) { + clearTimeout(~handle); + } else { + var idx = handle - lastVal; + if (idx >= 0) { + if (!callbacks[idx]) { + throw 'invalid async handle: ' + handle; + } + callbacks[idx] = null; + } + } + } + + function atEndOfMicrotask() { + var len = callbacks.length; + for (var i=0; i<len; i++) { + var cb = callbacks[i]; + if (cb) { + cb(); + } + } + callbacks.splice(0, len); + lastVal += len; + } + + new (window.MutationObserver || JsMutationObserver)(atEndOfMicrotask) + .observe(twiddle, {characterData: true}) + ; + + // exports + + return { + run: runAsync, + cancel: cancelAsync + }; + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/base.html b/third_party/polymer/v0_8/components/polymer/src/lib/base.html new file mode 100644 index 0000000..ca9ef47 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/base.html
@@ -0,0 +1,92 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Polymer.Base = { + + // pluggable features + // `this` context is a prototype, not an instance + _addFeature: function(feature) { + this.extend(this, feature); + }, + + // `this` context is a prototype, not an instance + registerCallback: function() { + this._registerFeatures(); // abstract + this._doBehavior('registered'); // abstract + }, + + createdCallback: function() { + Polymer.telemetry.instanceCount++; + this.root = this; + this._doBehavior('created'); // abstract + this._initFeatures(); // abstract + }, + + // reserved for canonical behavior + attachedCallback: function() { + this.isAttached = true; + this._doBehavior('attached'); // abstract + }, + + // reserved for canonical behavior + detachedCallback: function() { + this.isAttached = false; + this._doBehavior('detached'); // abstract + }, + + // reserved for canonical behavior + attributeChangedCallback: function(name) { + this.setAttributeToProperty(this, name); + this._doBehavior('attributeChanged', arguments); // abstract + }, + + // copy own properties from `api` to `prototype` + extend: function(prototype, api) { + if (prototype && api) { + Object.getOwnPropertyNames(api).forEach(function(n) { + this.copyOwnProperty(n, api, prototype); + }, this); + } + return prototype || api; + }, + + copyOwnProperty: function(name, source, target) { + var pd = Object.getOwnPropertyDescriptor(source, name); + if (pd) { + Object.defineProperty(target, name, pd); + } + } + + }; + + if (Object.__proto__) { + Polymer.Base.chainObject = function(object, inherited) { + if (object && inherited && object !== inherited) { + object.__proto__ = inherited; + } + return object; + }; + } else { + Polymer.Base.chainObject = function(object, inherited) { + if (object && inherited && object !== inherited) { + var chained = Object.create(inherited); + object = Polymer.Base.extend(chained, object); + } + return object; + }; + } + + Polymer.Base = Polymer.Base.chainObject(Polymer.Base, HTMLElement.prototype); + + // TODO(sjmiles): ad hoc telemetry + Polymer.telemetry.instanceCount = 0; + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/bind/accessors.html b/third_party/polymer/v0_8/components/polymer/src/lib/bind/accessors.html new file mode 100644 index 0000000..82b5cfb --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/bind/accessors.html
@@ -0,0 +1,229 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Polymer.Bind = { + + // for prototypes (usually) + + prepareModel: function(model) { + model._propertyEffects = {}; + model._bindListeners = []; + // TODO(sjmiles): no mixin function? + var api = this._modelApi; + for (var n in api) { + model[n] = api[n]; + } + }, + + _modelApi: { + + _notifyChange: function(property) { + var eventName = Polymer.CaseMap.camelToDashCase(property) + '-changed'; + // TODO(sjmiles): oops, `fire` doesn't exist at this layer + this.fire(eventName, { + value: this[property] + }, {bubbles: false}); + }, + + // TODO(sjmiles): removing _notifyListener from here breaks accessors.html + // as a standalone lib. This is temporary, as standard/configure.html + // installs it's own version on Polymer.Base, and we need that to work + // right now. + // NOTE: exists as a hook for processing listeners + /* + _notifyListener: function(fn, e) { + // NOTE: pass e.target because e.target can get lost if this function + // is queued asynchrously + return fn.call(this, e, e.target); + }, + */ + + _propertySet: function(property, value, effects) { + var old = this._data[property]; + if (old !== value) { + this._data[property] = value; + if (typeof value == 'object') { + this._clearPath(property); + } + if (effects) { + this._effectEffects(property, value, effects, old); + } + } + return old; + }, + + _effectEffects: function(property, value, effects, old) { + effects.forEach(function(fx) { + //console.log(fx); + var fn = Polymer.Bind[fx.kind + 'Effect']; + if (fn) { + fn.call(this, property, value, fx.effect, old); + } + }, this); + }, + + _clearPath: function(path) { + for (var prop in this._data) { + if (prop.indexOf(path + '.') === 0) { + this._data[prop] = undefined; + } + } + } + + }, + + // a prepared model can acquire effects + + ensurePropertyEffects: function(model, property) { + var fx = model._propertyEffects[property]; + if (!fx) { + fx = model._propertyEffects[property] = []; + } + return fx; + }, + + addPropertyEffect: function(model, property, kind, effect) { + var fx = this.ensurePropertyEffects(model, property); + fx.push({ + kind: kind, + effect: effect + }); + }, + + createBindings: function(model) { + //console.group(model.is); + // map of properties to effects + var fx$ = model._propertyEffects; + if (fx$) { + // for each property with effects + for (var n in fx$) { + // array of effects + var fx = fx$[n]; + // effects have priority + fx.sort(this._sortPropertyEffects); + // create accessors + this._createAccessors(model, n, fx); + } + } + //console.groupEnd(); + }, + + _sortPropertyEffects: (function() { + // TODO(sjmiles): EFFECT_ORDER buried this way is not ideal, + // but presumably the sort method is going to be a hot path and not + // have a `this`. There is also a problematic dependency on effect.kind + // values here, which are otherwise pluggable. + var EFFECT_ORDER = { + 'compute': 0, + 'annotation': 1, + 'computedAnnotation': 2, + 'reflect': 3, + 'notify': 4, + 'observer': 5, + 'complexObserver': 6, + 'function': 7 + }; + return function(a, b) { + return EFFECT_ORDER[a.kind] - EFFECT_ORDER[b.kind]; + }; + })(), + + // create accessors that implement effects + + _createAccessors: function(model, property, effects) { + var defun = { + get: function() { + // TODO(sjmiles): elide delegation for performance, good ROI? + return this._data[property]; + } + }; + var setter = function(value) { + this._propertySet(property, value, effects); + }; + // ReadOnly properties have a private setter only + // TODO(kschaaf): Per current Bind factoring, we shouldn't + // be interrogating the prototype here + if (model.isReadOnlyProperty && model.isReadOnlyProperty(property)) { + //model['_' + property + 'Setter'] = setter; + //model['_set_' + property] = setter; + model['_set' + this.upper(property)] = setter; + } else { + defun.set = setter; + } + Object.defineProperty(model, property, defun); + }, + + upper: function(name) { + return name[0].toUpperCase() + name.substring(1); + }, + + _addAnnotatedListener: function(model, index, property, path, event) { + var fn = this._notedListenerFactory(property, path, + this._isStructured(path), this._isEventBogus); + var eventName = event || + (Polymer.CaseMap.camelToDashCase(property) + '-changed'); + model._bindListeners.push({ + index: index, + property: property, + path: path, + changedFn: fn, + event: eventName + }); + }, + + _isStructured: function(path) { + return path.indexOf('.') > 0; + }, + + _isEventBogus: function(e, target) { + return e.path && e.path[0] !== target; + }, + + _notedListenerFactory: function(property, path, isStructured, bogusTest) { + return function(e, target) { + if (!bogusTest(e, target)) { + if (e.detail && e.detail.path) { + this.notifyPath(this._fixPath(path, property, e.detail.path), + e.detail.value); + } else { + var value = target[property]; + if (!isStructured) { + this[path] = target[property]; + } else { + // TODO(kschaaf): dirty check avoids null references when the object has gone away + if (this._data[path] != value) { + this.setPathValue(path, value); + } + } + } + } + }; + }, + + // for instances + + prepareInstance: function(inst) { + inst._data = Object.create(null); + }, + + setupBindListeners: function(inst) { + inst._bindListeners.forEach(function(info) { + // Property listeners: + // <node>.on.<property>-changed: <path]> = e.detail.value + //console.log('[_setupBindListener]: [%s][%s] listening for [%s][%s-changed]', this.localName, info.path, info.id || info.index, info.property); + var node = inst._nodes[info.index]; + node.addEventListener(info.event, inst._notifyListener.bind(inst, info.changedFn)); + }); + } + + }; + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/app-chrome.html b/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/app-chrome.html new file mode 100644 index 0000000..47a5bb85 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/app-chrome.html
@@ -0,0 +1,28 @@ +<!doctype html> +<html> +<head> + + <title>Bind Test</title> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <style> + pre { + font-family: sans-serif; + font-size: 14px; + } + </style> + + <link rel="import" href="src/bind-demo.html"> + <link rel="import" href="src/annotations-bind-demo.html"> + +</head> +<body> + + <pre id="bd"></pre> + + <pre id="abd"></pre> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/app.html b/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/app.html new file mode 100644 index 0000000..ffc161f --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/app.html
@@ -0,0 +1,29 @@ +<!doctype html> +<html> +<head> + + <title>Bind Test</title> + + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <script src="../../../../webcomponentsjs/webcomponents-lite.js"></script> + + <style> + pre { + font-family: sans-serif; + font-size: 14px; + } + </style> + + <link rel="import" href="src/bind-demo.html"> + <link rel="import" href="src/annotations-bind-demo.html"> + +</head> +<body> + + <pre id="bd"></pre> + <pre id="abd"></pre> + +</body> +</html>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/src/annotations-bind-demo.html b/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/src/annotations-bind-demo.html new file mode 100644 index 0000000..3f7d87d41 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/src/annotations-bind-demo.html
@@ -0,0 +1,76 @@ +<link rel="import" href="../../../module.html"> +<link rel="import" href="../../../lang.html"> +<link rel="import" href="../../../annotations/annotations.html"> + +<link rel="import" href="../../bind.html"> +<link rel="import" href="../../bind-effects.html"> +<link rel="import" href="../../bind-annotations.html"> + +<template> + + <div>annotated #foo span:</div> + <br> + <span id="foo" attribute="{{path}}" oneway="[[otherpath]]" style="{{specialStyle}}">{{text}}</span> + +</template> + +<script> + + // TODO(sjmiles): should 'bind-annotations' blend the other two modules + // somehow so we don't need to include all three here? + using(['Annotations', 'bind', 'bind-annotations'], + + function(Annotations, Bind, BindAnnotations) { + + var out = document.querySelector('#abd'); + out.innerHTML += '<hr><h3>annotations-bind demo</h3><hr>'; + + // phase one: prototyping + + var prototype = {}; + var template = currentImport.querySelector('template'); + var list = Templabindinate(prototype, template); + + // phase two: instancing + + var model = Object.create(prototype); + var dom = Instancinance(model, template); + document.body.appendChild(dom); + + // affect model + + model.text = 'Hello from Model'; + model.path = 'path'; + model.otherpath = 'other.path'; + model.specialStyle = {backgroundColor: "red"}; + + // effects visible in dom + + var foo = dom.querySelector('#foo'); + out.innerHTML += + 'foo.<b>path</b> = "' + model.path + '"<br>' + + 'foo.<b>otherpath</b> = "' + model.otherpath + '"<br>' + + 'foo.<b>specialStyle</b> = "' + JSON.stringify(model.specialStyle)+ '"<br>' + ; + + // ad hoc abstractions + + function Templabindinate(model, template) { + Bind.prepareModel(model); + var list = Annotations.parseAnnotations(template); + BindAnnotations.addEffects(model, list); + return list; + } + + function Instancinance(model, template) { + Bind.prepareInstance(model); + Bind.createBindings(model); + var dom = document.importNode(template.content, true); + model._nodes = BindAnnotations.marshalAnnotatedNodes(model._nodes, dom, + Annotations.findAnnotatedNode); + return dom; + } + + }); + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/src/bind-demo.html b/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/src/bind-demo.html new file mode 100644 index 0000000..561a683 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/bind/demo/src/bind-demo.html
@@ -0,0 +1,83 @@ +<link rel="import" href="../../../module.html"> +<link rel="import" href="../../bind.html"> +<link rel="import" href="../../bind-effects.html"> + +<script> + + using(['bind'], function(Bind) { + + var out = document.querySelector('#bd'); + out.innerHTML += '<hr><h3>bind demo</h3><hr>'; + + // phase one: prototyping + + var model = {}; + + Bind.prepareModel(model); + + // 'observer' effects are called if foo changes value as fx(foo, old) + + Bind.addPropertyEffect(model, 'foo', 'observer', 'fooChange'); + Bind.addPropertyEffect(model, 'foo', 'observer', 'fooWork'); + + model.fooChange = function(foo) { + out.innerHTML += '<b>fooChange</b>: effect of changing foo to ' + foo + '\n'; + console.log('fooChange: effect of changing foo to %d', foo); + }; + + model.fooWork = function(foo) { + out.innerHTML += '<b>fooWork</b>: effect of changing foo to ' + foo + '\n'; + console.log('fooWork: effect of changing foo to %d', foo); + }; + + // 'compute' effect sets the value of bar to the result of computeBar when + // foo changes value + + /* + Bind.addPropertyEffect(model, 'foo', 'compute', { + method: 'computeBar', + property: 'bar' + }); + */ + Bind.addComputedPropertyEffect(model, 'bar', 'computeFooTimes2(foo)'); + + model.computeFooTimes2 = function(foo) { + var foo2 = foo * 2; + out.innerHTML += '<b>computeFooTimes2</b>: calculated ' + foo2 + ' as an effect of changing foo to ' + foo + '\n'; + console.log('computeFooTimes2: calculated %d as effect of changing foo to %d', foo2, foo); + return foo2; + }; + + // custom effect + + Bind.addBuilder('async', function(model, property, effect) { + var fn = function() { + var flag = '_propertyTask'; + clearTimeout(this[flag]); + this[flag] = setTimeout(function() { + this.effect(this.property); + this[flag] = 0; + }.bind(this)); + }; + var code = fn.toString().split('\n').slice(1, -1).join('\n'); + return code.replace(/property/g, property).replace(/effect/g, effect); + }); + + Bind.addPropertyEffect(model, 'foo', 'async', 'asyncFoo'); + + model.asyncFoo = function(foo) { + out.innerHTML += '<b>asyncFoo</b>: effect of changing foo to ' + foo + '\n'; + console.log('asyncFoo: effect of changing foo to %d', foo); + }; + + // phase two: instancing + + Bind.prepareInstance(model); + Bind.createBindings(model); + + model.foo = 3; + model.foo = 6; + + }); + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/bind/effects.html b/third_party/polymer/v0_8/components/polymer/src/lib/bind/effects.html new file mode 100644 index 0000000..d33e8f95 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/bind/effects.html
@@ -0,0 +1,105 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../case-map.html"> +<script> + + Polymer.Base.extend(Polymer.Bind, { + + _shouldAddListener: function(effect) { + return effect.name && + effect.mode === '{' && + !effect.negate && + effect.kind != 'attribute' + ; + }, + + annotationEffect: function(source, value, effect) { + if (source != effect.value) { + value = this.getPathValue(effect.value); + this._data[effect.value] = value; + } + var calc = effect.negate ? !value : value; + return this._applyEffectValue(calc, effect); + }, + + reflectEffect: function(source) { + this.reflectPropertyToAttribute(source); + }, + + notifyEffect: function(source) { + this._notifyChange(source); + }, + + // Raw effect for extension; effect.function is an actual function + functionEffect: function(source, value, effect, old) { + effect.function.call(this, source, value, effect, old); + }, + + observerEffect: function(source, value, effect, old) { + this[effect.method](value, old); + }, + + complexObserverEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + this[effect.method].apply(this, args); + } + }, + + computeEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + this[effect.property] = this[effect.method].apply(this, args); + } + }, + + annotatedComputationEffect: function(source, value, effect) { + var args = Polymer.Bind._marshalArgs(this._data, effect, source, value); + if (args) { + var computedHost = this._rootDataHost || this; + var computedvalue = + computedHost[effect.method].apply(computedHost, args); + this._applyEffectValue(computedvalue, effect); + } + }, + + // path & value are used to fill in wildcard descriptor when effect is + // being called as a result of a path notification + _marshalArgs: function(model, effect, path, value) { + var values = []; + var args = effect.args; + for (var i=0, l=args.length; i<l; i++) { + var arg = args[i]; + var name = arg.name; + var v = arg.structured ? + Polymer.Base.getPathValue(name, model) : model[name]; + if (v === undefined) { + return; + } + if (arg.wildcard) { + // Only send the actual path changed info if the change that + // caused the observer to run matched the wildcard + var baseChanged = (name.indexOf(path + '.') === 0); + var matches = (effect.arg.name.indexOf(name) === 0 && !baseChanged); + values[i] = { + path: matches ? path : name, + value: matches ? value : v, + base: v + }; + } else { + values[i] = v; + } + } + return values; + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/case-map.html b/third_party/polymer/v0_8/components/polymer/src/lib/case-map.html new file mode 100644 index 0000000..396edbe --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/case-map.html
@@ -0,0 +1,46 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Polymer.CaseMap = { + + _caseMap: {}, + + dashToCamelCase: function(dash) { + var mapped = Polymer.CaseMap._caseMap[dash]; + if (mapped) { + return mapped; + } + // TODO(sjmiles): is rejection test actually helping perf? + if (dash.indexOf('-') < 0) { + return Polymer.CaseMap._caseMap[dash] = dash; + } + return Polymer.CaseMap._caseMap[dash] = dash.replace(/-([a-z])/g, + function(m) { + return m[1].toUpperCase(); + } + ); + }, + + camelToDashCase: function(camel) { + var mapped = Polymer.CaseMap._caseMap[camel]; + if (mapped) { + return mapped; + } + return Polymer.CaseMap._caseMap[camel] = camel.replace(/([a-z][A-Z])/g, + function (g) { + return g[0] + '-' + g[1].toLowerCase() + } + ); + } + + }; + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/collection.html b/third_party/polymer/v0_8/components/polymer/src/lib/collection.html new file mode 100644 index 0000000..494a4f2e --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/collection.html
@@ -0,0 +1,179 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="array-observe.html"> +<link rel="import" href="debounce.html"> + +<script> + + Polymer._collections = new WeakMap(); + + Polymer.Collection = function(userArray, noObserve) { + Polymer._collections.set(userArray, this); + this.userArray = userArray; + this.store = userArray.slice(); + this.callbacks = []; + this.debounce = null; + this.map = null; + this.added = []; + this.removed = []; + if (!noObserve) { + Polymer.ArrayObserve.observe(userArray, this.applySplices.bind(this)); + this.initMap(); + } + }; + + Polymer.Collection.prototype = { + constructor: Polymer.Collection, + + initMap: function() { + var map = this.map = new WeakMap(); + var s = this.store; + var u = this.userArray; + for (var i=0; i<s.length; i++) { + var v = s[i]; + if (v) { + switch (typeof v) { + case 'string': + v = s[i] = u[i]= new String(v); + break; + case 'number': + v = s[i] = u[i]= new Number(v); + break; + case 'boolean': + v = s[i] = u[i]= new Boolean(v); + break; + } + map.set(v, i); + } + } + }, + + add: function(item, squelch) { + var key = this.store.push(item) - 1; + if (item != null && this.map) { + this.map.set(item, key); + } + if (!squelch) { + this.added.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + } + return key; + }, + + removeKey: function(key) { + if (this.map) { + this.map.delete(this.store[key]); + } + delete this.store[key]; + this.removed.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + }, + + remove: function(item, squelch) { + var key = this.getKey(item); + if (item != null && this.map) { + this.map.delete(item); + } + delete this.store[key]; + if (!squelch) { + this.removed.push(key); + this.debounce = Polymer.Debounce(this.debounce, this.notify.bind(this)); + } + return key; + }, + + notify: function(splices) { + if (!splices) { + splices = [{ + added: this.added, + removed: this.removed + }]; + this.added = []; + this.removed = []; + } + this.callbacks.forEach(function(cb) { + cb(splices); + }, this); + }, + + observe: function(callback) { + this.callbacks.push(callback); + }, + + unobserve: function(callback) { + this.callbacks.splice(this.callbacks.indexOf(callback), 1); + }, + + getKey: function(item) { + if (item != null && this.map) { + return this.map.get(item); + } else { + return this.store.indexOf(item); + } + }, + + getKeys: function() { + return Object.keys(this.store); + }, + + setItem: function(key, value) { + this.store[key] = value; + }, + + getItem: function(key) { + return this.store[key]; + }, + + getItems: function() { + var items = [], store = this.store; + for (var key in store) { + items.push(store[key]); + } + return items; + }, + + applySplices: function(splices) { + var map = this.map; + var keySplices = []; + for (var i=0; i<splices.length; i++) { + var j, o, key, s = splices[i]; + // Removed keys + var removed = []; + for (j=0; j<s.removed.length; j++) { + o = s.removed[j]; + key = this.remove(o, true); + removed.push(key); + } + // Added keys + var added = []; + for (j=0; j<s.addedCount; j++) { + o = this.userArray[s.index + j]; + key = this.add(o, true); + added.push(key); + } + // Record splice + keySplices.push({ + index: s.index, + removed: removed, + added: added + }); + } + this.notify(keySplices); + } + + }; + + Polymer.Collection.get = function(userArray, noObserve) { + return Polymer._collections.get(userArray) + || new Polymer.Collection(userArray, noObserve); + }; + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/css-parse.html b/third_party/polymer/v0_8/components/polymer/src/lib/css-parse.html new file mode 100644 index 0000000..6b2a476 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/css-parse.html
@@ -0,0 +1,140 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + +/* + Extremely simple css parser. Intended to be not more than what we need + and definitely not necessarly correct =). +*/ +(function() { + + // given a string of css, return a simple rule tree + function parse(text) { + text = clean(text); + return parseCss(lex(text), text); + } + + // remove stuff we don't care about that may hinder parsing + function clean(cssText) { + return cssText.replace(rx.comments, '').replace(rx.port, ''); + } + + // super simple {...} lexer that returns a node tree + function lex(text) { + var root = {start: 0, end: text.length}; + var n = root; + for (var i=0, s=0, l=text.length; i < l; i++) { + switch (text[i]) { + case OPEN_BRACE: + //console.group(i); + if (!n.rules) { + n.rules = []; + } + var p = n; + var previous = p.rules[p.rules.length-1]; + n = {start: i+1, parent: p, previous: previous}; + p.rules.push(n); + break; + case CLOSE_BRACE: + //console.groupEnd(n.start); + n.end = i+1; + n = n.parent || root; + break; + } + } + return root; + } + + // add selectors/cssText to node tree + function parseCss(node, text) { + var t = text.substring(node.start, node.end-1); + node.cssText = t.trim(); + if (node.parent) { + var ss = node.previous ? node.previous.end : node.parent.start; + t = text.substring(ss, node.start-1); + // TODO(sorvell): ad hoc; make selector include only after last ; + // helps with mixin syntax + t = t.substring(t.lastIndexOf(';')+1); + node.selector = t.trim(); + } + var r$ = node.rules; + if (r$) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + parseCss(r, text); + } + } + return node; + } + + // stringify parsed css. + function stringify(node, text) { + text = text || ''; + // calc rule cssText + var cssText = ''; + if (node.cssText || node.rules) { + var r$ = node.rules; + if (r$ && !hasMixinRules(r$)) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + cssText = stringify(r, cssText); + } + } else { + cssText = removeCustomProps(node.cssText).trim(); + if (cssText) { + cssText = ' ' + cssText + '\n'; + } + } + } + // emit rule iff there is cssText + if (cssText) { + if (node.selector) { + text += node.selector + ' ' + OPEN_BRACE + '\n'; + } + text += cssText; + if (node.selector) { + text += CLOSE_BRACE + '\n\n'; + } + } + return text; + } + + var OPEN_BRACE = '{'; + var CLOSE_BRACE = '}'; + + function hasMixinRules(rules) { + return (rules[0].selector.indexOf(VAR_START) >= 0); + } + + function removeCustomProps(cssText) { + return cssText + .replace(rx.customProp, '') + .replace(rx.mixinProp, '') + .replace(rx.mixinApply, ''); + } + + var VAR_START = '--'; + + // helper regexp's + var rx = { + comments: /\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim, + port: /@import[^;]*;/gim, + customProp: /--[^;{]*?:[^{};]*?;/gim, + mixinProp: /--[^;{]*?:[^{;]*?{[^}]*?}/gim, + mixinApply: /@mixin[\s]*\([^)]*?\)[\s]*;/gim + }; + + // exports + Polymer.CssParse = { + parse: parse, + stringify: stringify + }; + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/debounce.html b/third_party/polymer/v0_8/components/polymer/src/lib/debounce.html new file mode 100644 index 0000000..f787670 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/debounce.html
@@ -0,0 +1,69 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + +Polymer.Debounce = (function() { + + // usage + + // invoke cb.call(this) in 100ms, unless the job is re-registered, + // which resets the timer + // + // this.job = this.debounce(this.job, cb, 100) + // + // returns a handle which can be used to re-register a job + + var Async = Polymer.Async; + + var Debouncer = function(context) { + this.context = context; + this.boundComplete = this.complete.bind(this); + }; + + Debouncer.prototype = { + go: function(callback, wait) { + var h; + this.finish = function() { + Async.cancel(h); + }; + h = Async.run(this.boundComplete, wait); + this.callback = callback; + }, + stop: function() { + if (this.finish) { + this.finish(); + this.finish = null; + } + }, + complete: function() { + if (this.finish) { + this.stop(); + this.callback.call(this.context); + } + } + }; + + function debounce(debouncer, callback, wait) { + if (debouncer) { + debouncer.stop(); + } else { + debouncer = new Debouncer(this); + } + debouncer.go(callback, wait); + return debouncer; + } + + // exports + + return debounce; + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/dom-api.html b/third_party/polymer/v0_8/components/polymer/src/lib/dom-api.html new file mode 100644 index 0000000..f24dada --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/dom-api.html
@@ -0,0 +1,471 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="settings.html"> +<link rel="import" href="event-api.html"> +<script> + + Polymer.DomApi = (function() { + + var Debounce = Polymer.Debounce; + var Settings = Polymer.Settings; + + var nativeInsertBefore = Element.prototype.insertBefore; + var nativeRemoveChild = Element.prototype.removeChild; + var nativeAppendChild = Element.prototype.appendChild; + + var dirtyRoots = []; + + var DomApi = function(node, patch) { + this.node = node; + if (patch) { + this.patch(); + } + }; + + DomApi.prototype = { + + // experimental: support patching selected native api. + patch: function() { + var self = this; + this.node.appendChild = function(node) { + return self.appendChild(node); + }; + this.node.insertBefore = function(node, ref_node) { + return self.insertBefore(node, ref_node); + }; + this.node.removeChild = function(node) { + return self.removeChild(node); + }; + }, + + get childNodes() { + var c$ = getLightChildren(this.node); + return Array.isArray(c$) ? c$ : Array.prototype.slice.call(c$); + }, + + get children() { + return Array.prototype.filter.call(this.childNodes, function(n) { + return (n.nodeType === Node.ELEMENT_NODE); + }); + }, + + get parentNode() { + return this.node.lightParent || this.node.parentNode; + }, + + flush: function() { + for (var i=0, host; i<dirtyRoots.length; i++) { + host = dirtyRoots[i]; + host.flushDebouncer('_distribute'); + } + dirtyRoots = []; + }, + + _lazyDistribute: function(host) { + if (host.shadyRoot) { + host.shadyRoot._distributionClean = false; + } + // TODO(sorvell): optimize debounce so it does less work by default + // and then remove these checks... + // need to dirty distribution once. + if (!host.isDebouncerActive('_distribute')) { + host.debounce('_distribute', host._distributeContent); + dirtyRoots.push(host); + } + }, + + // cases in which we may not be able to just do standard appendChild + // 1. container has a shadyRoot (needsDistribution IFF the shadyRoot + // has an insertion point) + // 2. container is a shadyRoot (don't distribute, instead set + // container to container.host. + // 3. node is <content> (host of container needs distribution) + appendChild: function(node) { + var distributed; + this._removeNodeFromHost(node); + if (this._nodeIsInLogicalTree(this.node)) { + var host = this._hostForNode(this.node); + this._addLogicalInfo(node, this.node, host && host.shadyRoot); + this._addNodeToHost(node); + if (host) { + distributed = this._maybeDistribute(node, this.node, host); + } + } + if (!distributed) { + // if adding to a shadyRoot, add to host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeAppendChild.call(container, node); + } + return node; + }, + + insertBefore: function(node, ref_node) { + if (!ref_node) { + return this.appendChild(node); + } + var distributed; + this._removeNodeFromHost(node); + if (this._nodeIsInLogicalTree(this.node)) { + saveLightChildrenIfNeeded(this.node); + var children = this.childNodes; + var index = children.indexOf(ref_node); + if (index < 0) { + throw Error('The ref_node to be inserted before is not a child ' + + 'of this node'); + } + var host = this._hostForNode(this.node); + this._addLogicalInfo(node, this.node, host && host.shadyRoot, index); + this._addNodeToHost(node); + if (host) { + distributed = this._maybeDistribute(node, this.node, host); + } + } + if (!distributed) { + // if ref_node is <content> replace with first distributed node + ref_node = ref_node.localName === CONTENT ? + this._firstComposedNode(ref_node) : ref_node; + // if adding to a shadyRoot, add to host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeInsertBefore.call(container, node, ref_node); + } + return node; + }, + + /** + Removes the given `node` from the element's `lightChildren`. + This method also performs dom composition. + */ + removeChild: function(node) { + var distributed; + if (this._nodeIsInLogicalTree(this.node)) { + var host = this._hostForNode(this.node); + distributed = this._maybeDistribute(node, this.node, host); + this._removeNodeFromHost(node); + } + if (!distributed) { + // if removing from a shadyRoot, remove form host instead + var container = this.node._isShadyRoot ? this.node.host : this.node; + nativeRemoveChild.call(container, node); + } + return node; + }, + + replaceChild: function(node, ref_node) { + this.insertBefore(node, ref_node); + this.removeChild(ref_node); + return node; + }, + + getOwnerRoot: function() { + return this._ownerShadyRootForNode(this.node); + }, + + _ownerShadyRootForNode: function(node) { + if (node._ownerShadyRoot === undefined) { + var root; + if (node._isShadyRoot) { + root = node; + } else { + var parent = Polymer.dom(node).parentNode; + if (parent) { + root = parent._isShadyRoot ? parent : + this._ownerShadyRootForNode(parent); + } else { + root = null; + } + } + node._ownerShadyRoot = root; + } + return node._ownerShadyRoot; + + }, + + _maybeDistribute: function(node, parent, host) { + var nodeNeedsDistribute = this._nodeNeedsDistribution(node); + var distribute = this._parentNeedsDistribution(parent) || + nodeNeedsDistribute; + if (nodeNeedsDistribute) { + this._updateInsertionPoints(host); + } + if (distribute) { + this._lazyDistribute(host); + } + return distribute; + }, + + _updateInsertionPoints: function(host) { + host.shadyRoot._insertionPoints = + factory(host.shadyRoot).querySelectorAll(CONTENT); + }, + + _nodeIsInLogicalTree: function(node) { + return Boolean(node._isShadyRoot || + this._ownerShadyRootForNode(node) || + node.shadyRoot); + }, + + // note: a node is its own host + _hostForNode: function(node) { + var root = node.shadyRoot || (node._isShadyRoot ? + node : this._ownerShadyRootForNode(node)); + return root && root.host; + }, + + _parentNeedsDistribution: function(parent) { + return parent.shadyRoot && hasInsertionPoint(parent.shadyRoot); + }, + + // TODO(sorvell): technically we should check non-fragment nodes for + // <content> children but since this case is assumed to be exceedingly + // rare, we avoid the cost and will address with some specific api + // when the need arises. + _nodeNeedsDistribution: function(node) { + return (node.localName === CONTENT) || + ((node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) && + node.querySelector(CONTENT)); + }, + + _removeNodeFromHost: function(node) { + if (node.lightParent) { + var root = this._ownerShadyRootForNode(node); + if (root) { + root.host._elementRemove(node); + } + this._removeLogicalInfo(node, node.lightParent); + } + this._removeOwnerShadyRoot(node); + }, + + _addNodeToHost: function(node) { + var checkNode = node.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? + node.firstChild : node; + var root = this._ownerShadyRootForNode(checkNode); + if (root) { + root.host._elementAdd(node); + } + }, + + _addLogicalInfo: function(node, container, root, index) { + saveLightChildrenIfNeeded(container); + var children = factory(container).childNodes; + index = index === undefined ? children.length : index; + // handle document fragments + if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) { + var n = node.firstChild; + while (n) { + children.splice(index++, 0, n); + n.lightParent = container; + n = n.nextSibling; + } + } else { + children.splice(index, 0, node); + node.lightParent = container; + } + }, + + // NOTE: in general, we expect contents of the lists here to be small-ish + // and therefore indexOf to be nbd. Other optimizations can be made + // for larger lists (linked list) + _removeLogicalInfo: function(node, container) { + var children = factory(container).childNodes; + var index = children.indexOf(node); + if ((index < 0) || (container !== node.lightParent)) { + throw Error('The node to be removed is not a child of this node'); + } + children.splice(index, 1); + node.lightParent = null; + }, + + _removeOwnerShadyRoot: function(node) { + // TODO(sorvell): need to clear any children of element? + node._ownerShadyRoot = undefined; + }, + + // TODO(sorvell): This will fail if distribution that affects this + // question is pending; this is expected to be exceedingly rare, but if + // the issue comes up, we can force a flush in this case. + _firstComposedNode: function(content) { + var n$ = factory(content).getDistributedNodes(); + for (var i=0, l=n$.length, n, p$; (i<l) && (n=n$[i]); i++) { + p$ = factory(n).getDestinationInsertionPoints(); + // means that we're composed to this spot. + if (p$[p$.length-1] === content) { + return n; + } + } + }, + + // TODO(sorvell): consider doing native QSA and filtering results. + querySelector: function(selector) { + return this.querySelectorAll(selector)[0]; + }, + + querySelectorAll: function(selector) { + return this._query(function(n) { + return matchesSelector.call(n, selector); + }, this.node); + }, + + _query: function(matcher, node) { + var list = []; + this._queryElements(factory(node).childNodes, matcher, list); + return list; + }, + + _queryElements: function(elements, matcher, list) { + for (var i=0, l=elements.length, c; (i<l) && (c=elements[i]); i++) { + if (c.nodeType === Node.ELEMENT_NODE) { + this._queryElement(c, matcher, list); + } + } + }, + + _queryElement: function(node, matcher, list) { + if (matcher(node)) { + list.push(node); + } + this._queryElements(factory(node).childNodes, matcher, list); + }, + + getDestinationInsertionPoints: function() { + return this.node._destinationInsertionPoints || []; + }, + + getDistributedNodes: function() { + return this.node._distributedNodes || []; + }, + + /* + Returns a list of nodes distributed within this element. These can be + dom children or elements distributed to children that are insertion + points. + */ + queryDistributedElements: function(selector) { + var c$ = this.childNodes; + var list = []; + this._distributedFilter(selector, c$, list); + for (var i=0, l=c$.length, c; (i<l) && (c=c$[i]); i++) { + if (c.localName === CONTENT) { + this._distributedFilter(selector, factory(c).getDistributedNodes(), + list); + } + } + return list; + }, + + _distributedFilter: function(selector, list, results) { + results = results || []; + for (var i=0, l=list.length, d; (i<l) && (d=list[i]); i++) { + if ((d.nodeType === Node.ELEMENT_NODE) && + (d.localName !== CONTENT) && + matchesSelector.call(d, selector)) { + results.push(d); + } + } + return results; + } + + }; + + if (Settings.useShadow) { + + DomApi.prototype.querySelectorAll = function(selector) { + return Array.prototype.slice.call(this.node.querySelectorAll(selector)); + }; + + DomApi.prototype.patch = function() {}; + + DomApi.prototype.getOwnerRoot = function() { + var n = this.node; + while (n) { + if (n.nodeType === Node.DOCUMENT_FRAGMENT_NODE && n.host) { + return n; + } + n = n.parentNode; + } + }; + + DomApi.prototype.getDestinationInsertionPoints = function() { + var n$ = this.node.getDestinationInsertionPoints(); + return n$ ? Array.prototype.slice.call(n$) : []; + }; + + DomApi.prototype.getDistributedNodes = function() { + var n$ = this.node.getDistributedNodes(); + return n$ ? Array.prototype.slice.call(n$) : []; + }; + + + } + + var CONTENT = 'content'; + + var factory = function(node, patch) { + node = node || document; + if (!node.__domApi) { + node.__domApi = new DomApi(node, patch); + } + return node.__domApi; + }; + + Polymer.dom = function(obj, patch) { + if (obj instanceof Event) { + return Polymer.EventApi.factory(obj); + } else { + return factory(obj, patch); + } + }; + + // make flush available directly. + Polymer.dom.flush = DomApi.prototype.flush; + + function getLightChildren(node) { + var children = node.lightChildren; + return children ? children : node.childNodes; + } + + function saveLightChildrenIfNeeded(node) { + // Capture the list of light children. It's important to do this before we + // start transforming the DOM into "rendered" state. + // + // Children may be added to this list dynamically. It will be treated as the + // source of truth for the light children of the element. This element's + // actual children will be treated as the rendered state once lightChildren + // is populated. + if (!node.lightChildren) { + var children = []; + for (var child = node.firstChild; child; child = child.nextSibling) { + children.push(child); + child.lightParent = child.lightParent || node; + } + node.lightChildren = children; + } + } + + function hasInsertionPoint(root) { + return Boolean(root._insertionPoints.length); + } + + var p = Element.prototype; + var matchesSelector = p.matches || p.matchesSelector || + p.mozMatchesSelector || p.msMatchesSelector || + p.oMatchesSelector || p.webkitMatchesSelector; + + return { + getLightChildren: getLightChildren, + saveLightChildrenIfNeeded: saveLightChildrenIfNeeded, + matchesSelector: matchesSelector, + hasInsertionPoint: hasInsertionPoint, + factory: factory + }; + + })(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/dom-module.html b/third_party/polymer/v0_8/components/polymer/src/lib/dom-module.html new file mode 100644 index 0000000..442dc15f --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/dom-module.html
@@ -0,0 +1,68 @@ +<script> + +(function() { + + var modules = {}; + + var DomModule = function() { + return document.createElement('dom-module'); + }; + + DomModule.prototype = Object.create(HTMLElement.prototype); + + DomModule.prototype.constructor = DomModule; + + DomModule.prototype.createdCallback = function() { + var id = this.id || this.getAttribute('name') || this.getAttribute('is'); + if (id) { + this.id = id; + modules[id] = this; + } + }; + + DomModule.prototype.import = function(id, slctr) { + var m = modules[id]; + if (!m) { + // If polyfilling, a script can run before a dom-module element + // is upgraded. We force the containing document to upgrade + // and try again to workaround this polyfill limitation. + forceDocumentUpgrade(); + m = modules[id]; + } + if (m && slctr) { + m = m.querySelector(slctr); + } + return m; + }; + + // NOTE: HTMLImports polyfill does not + // block scripts on upgrading elements. However, we want to ensure that + // any dom-module in the tree is available prior to a subsequent script + // processing. + // Therefore, we force any dom-modules in the tree to upgrade when dom-module + // is registered by temporarily setting CE polyfill to crawl the entire + // imports tree. (Note: this should only upgrade any imports that have been + // loaded by this point. In addition the HTMLImports polyfill should be + // changed to upgrade elements prior to running any scripts.) + var cePolyfill = window.CustomElements && !CustomElements.useNative; + if (cePolyfill) { + var ready = CustomElements.ready; + CustomElements.ready = true; + } + document.registerElement('dom-module', DomModule); + if (cePolyfill) { + CustomElements.ready = ready; + } + + function forceDocumentUpgrade() { + if (cePolyfill) { + var script = document._currentScript || document.currentScript; + if (script) { + CustomElements.upgradeAll(script.ownerDocument); + } + } + } + +})(); + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/event-api.html b/third_party/polymer/v0_8/components/polymer/src/lib/event-api.html new file mode 100644 index 0000000..1f66fb3 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/event-api.html
@@ -0,0 +1,92 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="settings.html"> +<script> + + Polymer.EventApi = (function() { + + var Settings = Polymer.Settings; + + var EventApi = function(event) { + this.event = event; + }; + + if (Settings.useShadow) { + + EventApi.prototype = { + + get rootTarget() { + return this.event.path[0]; + }, + + get localTarget() { + return this.event.target; + }, + + get path() { + return this.event.path; + } + + }; + + } else { + + EventApi.prototype = { + + get rootTarget() { + return this.event.target; + }, + + get localTarget() { + var current = this.event.currentTarget; + var currentRoot = current && Polymer.dom(current).getOwnerRoot(); + var p$ = this.path; + for (var i=0; i < p$.length; i++) { + if (Polymer.dom(p$[i]).getOwnerRoot() === currentRoot) { + return p$[i]; + } + } + }, + + // TODO(sorvell): simulate event.path. This probably incorrect for + // non-bubbling events. + get path() { + if (!this.event._path) { + var path = []; + var o = this.rootTarget; + while (o) { + path.push(o); + o = Polymer.dom(o).parentNode || o.host; + } + // event path includes window in most recent native implementations + path.push(window); + this.event._path = path; + } + return this.event._path; + } + + }; + + } + + var factory = function(event) { + if (!event.__eventApi) { + event.__eventApi = new EventApi(event); + } + return event.__eventApi; + }; + + return { + factory: factory + }; + + })(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/expr/focus.html b/third_party/polymer/v0_8/components/polymer/src/lib/expr/focus.html new file mode 100644 index 0000000..f3d5be8 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/expr/focus.html
@@ -0,0 +1,22 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Base._addFeature({ + + init: function() { + if (this.focusable) { + this.tabIndex = 0; + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/expr/gestures.html b/third_party/polymer/v0_8/components/polymer/src/lib/expr/gestures.html new file mode 100644 index 0000000..fd3f95f --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/expr/gestures.html
@@ -0,0 +1 @@ +<script src="../../polymer-gestures/polymer-gestures.js"></script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/expr/log.html b/third_party/polymer/v0_8/components/polymer/src/lib/expr/log.html new file mode 100644 index 0000000..4927950 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/expr/log.html
@@ -0,0 +1,21 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Base._addFeature({ + log: function() { + var args = Array.prototype.slice.call(arguments, 0); + args[0] = '[%s]: ' + args[0]; + args.splice(1, 0, this.localName); + console.log.apply(console, args); + } + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/expr/sinspect.html b/third_party/polymer/v0_8/components/polymer/src/lib/expr/sinspect.html new file mode 100644 index 0000000..009653a --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/expr/sinspect.html
@@ -0,0 +1,235 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + (function(scope) { + + scope = scope || (window.Inspector = {}); + + var inspector; + + window.sinspect = function(inNode, inProxy) { + if (!inspector) { + inspector = window.open('', 'ShadowDOM Inspector', null, true); + inspector.document.write(inspectorHTML); + //inspector.document.close(); + inspector.api = { + shadowize: shadowize + }; + } + inspect(inNode || wrap(document.body), inProxy); + }; + + var inspectorHTML = [ + '<!DOCTYPE html>', + '<html>', + ' <head>', + ' <title>ShadowDOM Inspector</title>', + ' <style>', + ' body {', + ' }', + ' pre {', + ' font: 9pt "Courier New", monospace;', + ' line-height: 1.5em;', + ' }', + ' tag {', + ' color: purple;', + ' }', + ' ul {', + ' margin: 0;', + ' padding: 0;', + ' list-style: none;', + ' }', + ' li {', + ' display: inline-block;', + ' background-color: #f1f1f1;', + ' padding: 4px 6px;', + ' border-radius: 4px;', + ' margin-right: 4px;', + ' }', + ' button {', + ' display: inline-block;', + ' color: purple;', + ' font-weight: bold;', + ' background: none;', + ' border: none;', + ' outline: none;', + ' padding: 0;', + ' margin: 0;', + ' }', + ' </style>', + ' </head>', + ' <body>', + ' <ul id="crumbs">', + ' </ul>', + ' <div id="tree"></div>', + ' </body>', + '</html>' + ].join('\n'); + + var crumbs = []; + + var displayCrumbs = function() { + // alias our document + var d = inspector.document; + // get crumbbar + var cb = d.querySelector('#crumbs'); + // clear crumbs + cb.textContent = ''; + // build new crumbs + for (var i=0, c; c=crumbs[i]; i++) { + var a = d.createElement('a'); + a.href = '#'; + a.textContent = c.localName; + a.idx = i; + a.onclick = function(event) { + var c; + while (crumbs.length > this.idx) { + c = crumbs.pop(); + } + inspect(c.shadow || c, c); + event.preventDefault(); + }; + cb.appendChild(d.createElement('li')).appendChild(a); + } + }; + + var inspect = function(inNode, inProxy) { + // alias our document + var d = inspector.document; + // reset list of drillable nodes + drillable = []; + // memoize our crumb proxy + var proxy = inProxy || inNode; + crumbs.push(proxy); + // update crumbs + displayCrumbs(); + // reflect local tree + d.body.querySelector('#tree').innerHTML = + '<pre>' + output(inNode, getLocalNodes(inNode)) + '</pre>'; + }; + + var forEach = Array.prototype.forEach.call.bind(Array.prototype.forEach); + + var blacklisted = {STYLE:1, SCRIPT:1, "#comment": 1, TEMPLATE: 1}; + var blacklist = function(inNode) { + return blacklisted[inNode.nodeName]; + }; + + var output = function(inNode, inChildNodes, inIndent) { + if (blacklist(inNode)) { + return ''; + } + var indent = inIndent || ''; + if (inNode.localName || inNode.domRoot) { + var name = inNode.localName || ROOT_NAME; + //inChildNodes = ShadowDOM.localNodes(inNode); + var info = indent + describe(inNode); + // if only textNodes + // TODO(sjmiles): make correct for ShadowDOM + /*if (!inNode.children.length && inNode.localName !== 'content' && inNode.localName !== 'shadow') { + info += catTextContent(inChildNodes); + } else*/ { + // TODO(sjmiles): native <shadow> has no reference to its projection + if (name == 'content' /*|| name == 'shadow'*/) { + inChildNodes = getDistributedNodes(inNode); + } + info += '<br/>'; + var ind = indent + ' '; + //console.group('output ' + inNode.localName); + //console.log(inChildNodes); + forEach(inChildNodes, function(n) { + info += output(n, getLightNodes(n), ind); + }); + //console.groupEnd('output ' + inNode.localName); + info += indent; + } + if (!({br:1}[name])) { + info += '<tag></' + name + '></tag>'; + info += '<br/>'; + } + } else { + var text = inNode.textContent.trim(); + info = text ? indent + '"' + text + '"' + '<br/>' : ''; + } + return info; + }; + + var catTextContent = function(inChildNodes) { + var info = ''; + forEach(inChildNodes, function(n) { + info += n.textContent.trim(); + }); + return info; + }; + + var drillable = []; + + var describe = function(inNode) { + var tag = '<tag>' + '<'; + var name = inNode.localName || ROOT_NAME; + if (hasRoot(inNode)) { + tag += '<button idx="' + drillable.length + + '" onclick="api.shadowize.call(this)">' + name + '</button>'; + drillable.push(inNode); + } else { + tag += name || ROOT_NAME; + } + if (inNode.attributes) { + forEach(inNode.attributes, function(a) { + tag += ' ' + a.name + (a.value ? '="' + a.value + '"' : ''); + }); + } + tag += '>'+ '</tag>'; + return tag; + }; + + // remote api + + shadowize = function() { + var idx = Number(this.attributes.idx.value); + //alert(idx); + var node = drillable[idx]; + if (node) { + inspect(node, node) + } else { + console.log("bad shadowize node"); + console.dir(this); + } + }; + + // util + + var ROOT_NAME = 'local-root'; + + function hasRoot(node) { + return (node.shadyRoot || node.shadowRoot); + } + + function getLocalNodes(n) { + return Polymer.dom.childNodes(n.root); + } + + function getLightNodes(n) { + return Polymer.dom.childNodes(n); + } + + function getDistributedNodes(node) { + Polymer.dom.distributedNodes(node); + } + + + // export + + scope.output = output; + +})(window.Inspector); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/expr/style-auditor.html b/third_party/polymer/v0_8/components/polymer/src/lib/expr/style-auditor.html new file mode 100644 index 0000000..576055e --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/expr/style-auditor.html
@@ -0,0 +1,123 @@ +<script> +addEventListener('WebComponentsReady', function() { + + // given a list of elements, produce a report of rules that + // match those elements. + var auditor = { + + matchesForDocument: function(elements) { + var info = []; + this.documentSheets.forEach(function(sheet) { + var list = this.matchesForSheet(sheet, elements); + if (list.length) { + info.push({sheet: sheet, rules: list}); + } + }, this); + return info; + }, + + // TODO(sorvell): support stylesheets inside HTMLImports + documentSheets: Array.prototype.filter.call(document.styleSheets, + function(sheet) { + return !sheet.ownerNode.hasAttribute('scope'); + } + ), + + matchesForSheet: function(sheet, elements) { + var info = []; + Array.prototype.forEach.call(sheet.cssRules, function(rule) { + var list = this.matchesForRule(rule, elements); + if (list.length) { + info.push({selector: rule.selectorText, elements: list}); + } + }, this); + return info; + }, + + matchesForRule: function(rule, list) { + var info = []; + list.forEach(function(i) { + var elements = i.elements.filter(function(e) { + return matchesSelector.call(e, rule.selectorText); + }); + if (elements.length) { + info.push({host: i.host, elements: elements}); + } + }); + return info; + } + + }; + + var p = Element.prototype; + var matchesSelector = p.matches || p.matchesSelector || + p.mozMatchesSelector || p.msMatchesSelector || + p.oMatchesSelector || p.webkitMatchesSelector; + + + // crawl the document and return a list of custom elements with shadyRoots + // and their scoped contents + var crawler = { + // list of elements: array of {host, elements} + list: function() { + var list = []; + var elements = this.elementsWithShadyRoot(); + elements.forEach(function(e) { + list.push({host: e, elements: this.elementsInsideShadyRoot(e)}); + }, this); + return list; + }, + + elementsWithShadyRoot: function() { + var e$ = Polymer.dom(document).querySelectorAll('*'); + return this.filterElementsWithRoots(e$); + }, + + elementsInsideShadyRoot: function(e) { + var e$ = Polymer.dom(e.root || e).querySelectorAll('*'); + var roots = this.filterElementsWithRoots(e$); + roots.forEach(function(e) { + e$ = e$.concat(this.elementsInsideShadyRoot(e)); + }, this); + return e$; + }, + + filterElementsWithRoots: function(elements) { + return elements.filter(function(e) { + return e.shadyRoot; + }); + } + + }; + + // dump an auditor report + var logger = { + + dump: function(log) { + log.forEach(function(l) { + console.group(l.sheet.ownerNode); + this.dumpRules(l.rules); + console.groupEnd(l.sheet.ownerNode); + }, this); + }, + + dumpRules: function(rules) { + rules.forEach(function(i) { + console.group(i.selector); + console.log(i.elements); + console.groupEnd(i.selector); + }); + } + + }; + + // pruduces a style audit and reports results on the console. + function audit() { + var report = auditor.matchesForDocument(crawler.list()); + logger.dump(report); + } + + audit(); + +}); +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/expr/style-protector.html b/third_party/polymer/v0_8/components/polymer/src/lib/expr/style-protector.html new file mode 100644 index 0000000..3a72b4a --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/expr/style-protector.html
@@ -0,0 +1,52 @@ +<link rel="import" href="../lib/x-style.html"> +<script> +(function() { + + var transformer = document.createElement('style', 'x-style'); + + var styleProtector = { + + scopeDocumentSheets: function() { + this.scopeSheets(this.getSheetsToScope()); + }, + + getSheetsToScope: function() { + var s$ = document.styleSheets; + return Array.prototype.filter.call(s$, function(s) { + return s.ownerNode.hasAttribute(this.SCOPE_ATTR); + }, this); + }, + + scopeSheets: function(sheets) { + for (var i=0, l=sheets.length, s; (i<l) && (s=sheets[i]); i++) { + this.scopeSheet(s); + } + }, + + scopeSheet: function(sheet) { + var owner = sheet.ownerNode; + var cssText = transformer.scopeCssText(this.rulesToCss(sheet.cssRules)); + if (owner.localName === 'link') { + var style = document.createElement('style'); + style.textContent = cssText; + owner.parentNode.insertBefore(style, owner); + owner.parentNode.removeChild(owner); + } else { + owner.textContent = cssText; + } + }, + + rulesToCss: function(cssRules) { + for (var i=0, css=[]; i < cssRules.length; i++) { + css.push(cssRules[i].cssText); + } + return css.join('\n\n'); + }, + + SCOPE_ATTR: 'needs-scoping' + }; + + addEventListener('DOMContentLoaded', styleProtector.scopeDocumentSheets()); + +})(); +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/gestures.html b/third_party/polymer/v0_8/components/polymer/src/lib/gestures.html new file mode 100644 index 0000000..c8ac3fb9 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/gestures.html
@@ -0,0 +1,284 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + +(function(scope) { + + 'use strict'; + + var async = scope.Base.async; + + var Gestures = { + gestures: {}, + + // automate the event listeners for the native events + // TODO(dfreedm): add a way to remove handlers. + add: function(evType, node, handler) { + // listen for events in order to "recognize" this event + var g = this.gestures[evType]; + var gn = '_' + evType; + var info = {started: false, abortTrack: false, oneshot: false}; + if (g && !node[gn]) { + if (g.touchaction) { + this._setupTouchAction(node, g.touchaction, info); + } + for (var i = 0, n, sn, fn; i < g.deps.length; i++) { + n = g.deps[i]; + fn = g[n].bind(g, info); + sn = '_' + evType + '-' + n; + // store the handler on the node for future removal + node[sn] = fn; + node.addEventListener(n, fn); + } + node[gn] = 0; + } + // listen for the gesture event + node[gn]++; + node.addEventListener(evType, handler); + }, + + remove: function(evType, node, handler) { + var g = this.gestures[evType]; + var gn = '_' + evType; + if (g && node[gn]) { + for (var i = 0, n, sn, fn; i < g.deps.length; i++) { + n = g.deps[i]; + sn = '_' + evType + '-' + n; + fn = node[sn]; + if (fn){ + node.removeEventListener(n, fn); + // remove stored handler to allow GC + node[sn] = undefined; + } + } + node[gn] = node[gn] ? (node[gn] - 1) : 0; + node.removeEventListener(evType, handler); + } + }, + + register: function(recog) { + this.gestures[recog.name] = recog; + }, + + // touch will make synthetic mouse events + // preventDefault on touchend will cancel them, + // but this breaks <input> focus and link clicks + // Disabling "mouse" handlers for 500ms is enough + + _cancelFunction: null, + + cancelNextClick: function(timeout) { + if (!this._cancelFunction) { + timeout = timeout || 500; + var self = this; + var reset = function() { + var cfn = self._cancelFunction; + if (cfn) { + clearTimeout(cfn.id); + document.removeEventListener('click', cfn, true); + self._cancelFunction = null; + } + }; + var canceller = function(e) { + e.tapPrevented = true; + reset(); + }; + canceller.id = setTimeout(reset, timeout); + this._cancelFunction = canceller; + document.addEventListener('click', canceller, true); + } + }, + + // try to use the native touch-action, if it exists + _hasNativeTA: typeof document.head.style.touchAction === 'string', + + // set scrolling direction on node to check later on first move + // must call this before adding event listeners! + setTouchAction: function(node, value) { + if (this._hasNativeTA) { + node.style.touchAction = value; + } + node.touchAction = value; + }, + + _setupTouchAction: function(node, value, info) { + // reuse custom value on node if set + var ta = node.touchAction; + value = ta || value; + // set an anchor point to see how far first move is + node.addEventListener('touchstart', function(e) { + var t = e.changedTouches[0]; + info.initialTouch = {x: t.clientX, y: t.clientY}; + info.abortTrack = false; + info.oneshot = false; + }); + node.addEventListener('touchmove', function(e) { + // only run this once + if (info.oneshot) { + return; + } + info.oneshot = true; + // "none" means always track + if (value === 'none') { + return; + } + // "auto" is default, always scroll + // bail-out if touch-action did its job + // the touchevent is non-cancelable if the page/area is scrolling + if (value === 'auto' || !value || (ta && !e.cancelable)) { + info.abortTrack = true; + return; + } + // check first move direction + // unfortunately, we can only make the decision in the first move, + // so we have to use whatever values are available. + // Typically, this can be a really small amount, :( + var t = e.changedTouches[0]; + var x = t.clientX, y = t.clientY; + var dx = Math.abs(info.initialTouch.x - x); + var dy = Math.abs(info.initialTouch.y - y); + // scroll in x axis, abort track if we move more in x direction + if (value === 'pan-x') { + info.abortTrack = dx >= dy; + // scroll in y axis, abort track if we move more in y direction + } else if (value === 'pan-y') { + info.abortTrack = dy >= dx; + } + }); + }, + + fire: function(target, type, detail, bubbles, cancelable) { + return target.dispatchEvent( + new CustomEvent(type, { + detail: detail, + bubbles: bubbles, + cancelable: cancelable + }) + ); + } + + }; + + Gestures.register({ + name: 'track', + touchaction: 'none', + deps: ['mousedown', 'touchmove', 'touchend'], + + mousedown: function(info, e) { + var t = e.currentTarget; + var self = this; + var movefn = function movefn(e, up) { + if (!info.tracking && !up) { + // set up tap prevention + Gestures.cancelNextClick(); + } + // first move is 'start', subsequent moves are 'move', mouseup is 'end' + var state = up ? 'end' : (!info.started ? 'start' : 'move'); + info.started = true; + self.fire(t, e, state); + e.preventDefault(); + }; + var upfn = function upfn(e) { + // call mousemove function with 'end' state + movefn(e, true); + info.started = false; + // remove the temporary listeners + document.removeEventListener('mousemove', movefn); + document.removeEventListener('mouseup', upfn); + }; + // add temporary document listeners as mouse retargets + document.addEventListener('mousemove', movefn); + document.addEventListener('mouseup', upfn); + }, + + touchmove: function(info, e) { + var t = e.currentTarget; + var ct = e.changedTouches[0]; + // if track was aborted, stop tracking + if (info.abortTrack) { + return; + } + e.preventDefault(); + // the first track event is sent after some hysteresis with touchmove. + // Use `started` state variable to differentiate the "first" move from + // the rest to make track.state == 'start' + // first move is 'start', subsequent moves are 'move' + var state = !info.started ? 'start' : 'move'; + info.started = true; + this.fire(t, ct, state); + }, + + touchend: function(info, e) { + var t = e.currentTarget; + var ct = e.changedTouches[0]; + // only trackend if track was started and not aborted + if (info.started && !info.abortTrack) { + // reset started state on up + info.started = false; + var ne = this.fire(t, ct, 'end'); + // iff tracking, always prevent tap + e.tapPrevented = true; + } + }, + + fire: function(target, touch, state) { + return Gestures.fire(target, 'track', { + state: state, + x: touch.clientX, + y: touch.clientY + }); + } + + }); + + // dispatch a *bubbling* "tap" only at the node that is the target of the + // generating event. + // dispatch *synchronously* so that we can implement prevention of native + // actions like links being followed. + // + // TODO(dfreedm): a tap should not occur when there's too much movement. + // Right now, a tap can occur when a touchend happens very far from the + // generating touch. + // This *should* obviate the need for tapPrevented via track. + Gestures.register({ + name: 'tap', + deps: ['click', 'touchend'], + + click: function(info, e) { + this.forward(e); + }, + + touchend: function(info, e) { + Gestures.cancelNextClick(); + this.forward(e); + }, + + forward: function(e) { + // prevent taps from being generated from events that have been + // canceled (e.g. via cancelNextClick) or already handled via + // a listener lower in the tree. + if (!e.tapPrevented) { + e.tapPrevented = true; + this.fire(e.target); + } + }, + + // fire a bubbling event from the generating target. + fire: function(target) { + Gestures.fire(target, 'tap', {}, true); + } + + }); + + scope.Gestures = Gestures; + +})(Polymer); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/lang.html b/third_party/polymer/v0_8/components/polymer/src/lib/lang.html new file mode 100644 index 0000000..d80e8fd --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/lang.html
@@ -0,0 +1,21 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + // a tiny bit of sugar for `document.currentScript.ownerDocument` + Object.defineProperty(window, 'currentImport', { + enumerable: true, + configurable: true, + get: function() { + return (document._currentScript || document.currentScript).ownerDocument; + } + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/module.html b/third_party/polymer/v0_8/components/polymer/src/lib/module.html new file mode 100644 index 0000000..1df04bf --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/module.html
@@ -0,0 +1,56 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> +(function(scope) { + + function withDependencies(task, depends) { + depends = depends || []; + if (!depends.map) { + depends = [depends]; + } + return task.apply(this, depends.map(marshal)); + } + + function module(name, dependsOrFactory, moduleFactory) { + var module = null; + switch (arguments.length) { + case 0: + return; + case 2: + // dependsOrFactory is `factory` in this case + module = dependsOrFactory.apply(this); + break; + default: + // dependsOrFactory is `depends` in this case + module = withDependencies(moduleFactory, dependsOrFactory); + break; + } + modules[name] = module; + }; + + function marshal(name) { + return modules[name]; + } + + var modules = {}; + + var using = function(depends, task) { + withDependencies(task, depends); + }; + + // exports + + scope.marshal = marshal; + // `module` confuses commonjs detectors + scope.modulate = module; + scope.using = using; + +})(this); +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/polymer-bootstrap.html b/third_party/polymer/v0_8/components/polymer/src/lib/polymer-bootstrap.html new file mode 100644 index 0000000..af542f1 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/polymer-bootstrap.html
@@ -0,0 +1,78 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + // until ES6 modules become standard, we follow Occam and simply stake out + // a global namespace + + // Polymer is a Function, but of course this is also an Object, so we + // hang various other objects off of Polymer.* + (function() { + var userPolymer = window.Polymer; + + window.Polymer = function(prototype) { + var ctor = desugar(prototype); + // native Custom Elements treats 'undefined' extends property + // as valued, the property must not exist to be ignored + var options = { + prototype: ctor.prototype + }; + if (prototype.extends) { + options.extends = prototype.extends; + } + Polymer.telemetry._registrate(prototype); + document.registerElement(prototype.is, options); + return ctor; + }; + + var desugar = function(prototype) { + prototype = Polymer.Base.chainObject(prototype, Polymer.Base); + prototype.registerCallback(); + return prototype.constructor; + }; + + window.Polymer = Polymer; + + if (userPolymer) { + for (var i in userPolymer) { + Polymer[i] = userPolymer[i]; + } + } + + Polymer.Class = desugar; + + })(); + /* + // Raw usage + [ctor =] Polymer.Class(prototype); + document.registerElement(name, ctor); + + // Simplified usage + [ctor = ] Polymer(prototype); + */ + + // telemetry: statistics, logging, and debug + + Polymer.telemetry = { + registrations: [], + _regLog: function(prototype) { + console.log('[' + prototype.is + ']: registered') + }, + _registrate: function(prototype) { + this.registrations.push(prototype); + Polymer.log && this._regLog(prototype); + }, + dumpRegistrations: function() { + this.registrations.forEach(this._regLog); + } + }; + +</script> +
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/resolve-url.html b/third_party/polymer/v0_8/components/polymer/src/lib/resolve-url.html new file mode 100644 index 0000000..3ca2618 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/resolve-url.html
@@ -0,0 +1,82 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + (function() { + + // path fixup for urls in cssText that's expected to + // come from a given ownerDocument + function resolveCss(cssText, ownerDocument) { + return cssText.replace(CSS_URL_RX, function(m, pre, url, post) { + return pre + '\'' + + resolve(url.replace(/["']/g, ''), ownerDocument) + + '\'' + post; + }); + } + + // url fixup for urls in an element's attributes made relative to + // ownerDoc's base url + function resolveAttrs(element, ownerDocument) { + for (var name in URL_ATTRS) { + var a$ = URL_ATTRS[name]; + for (var i=0, l=a$.length, a, at, v; (i<l) && (a=a$[i]); i++) { + if (name === '*' || element.localName === name) { + at = element.attributes[a]; + v = at && at.value; + if (v && (v.search(BINDING_RX) < 0)) { + at.value = (a === 'style') ? + resolveCss(v, ownerDocument) : + resolve(v, ownerDocument); + } + } + } + } + } + + function resolve(url, ownerDocument) { + var resolver = getUrlResolver(ownerDocument); + resolver.href = url; + return resolver.href || url; + } + + var tempDoc; + var tempDocBase; + function resolveUrl(url, baseUri) { + if (!tempDoc) { + tempDoc = document.implementation.createHTMLDocument('temp'); + tempDocBase = tempDoc.createElement('base'); + tempDoc.head.appendChild(tempDocBase); + } + tempDocBase.href = baseUri; + return resolve(url, tempDoc); + } + + function getUrlResolver(ownerDocument) { + return ownerDocument.__urlResolver || + (ownerDocument.__urlResolver = ownerDocument.createElement('a')); + } + + var CSS_URL_RX = /(url\()([^)]*)(\))/g; + var URL_ATTRS = { + '*': ['href', 'src', 'style', 'url'], + form: ['action'] + }; + var BINDING_RX = /\{\{|\[\[/; + + // exports + Polymer.ResolveUrl = { + resolveCss: resolveCss, + resolveAttrs: resolveAttrs, + resolveUrl: resolveUrl + }; + + })(); + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/settings.html b/third_party/polymer/v0_8/components/polymer/src/lib/settings.html new file mode 100644 index 0000000..1d662cf --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/settings.html
@@ -0,0 +1,52 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Polymer = { + Settings: (function() { + // NOTE: Users must currently opt into using ShadowDOM. They do so by doing: + // Polymer = {dom: 'shadow'}; + // TODO(sorvell): Decide if this should be auto-use when available. + // TODO(sorvell): if SD is auto-use, then the flag above should be something + // like: Polymer = {dom: 'shady'} + + // via Polymer object + var user = window.Polymer || {}; + + // via url + location.search.slice(1).split('&').forEach(function(o) { + o = o.split('='); + o[0] && (user[o[0]] = o[1] || true); + }); + + var wantShadow = (user.dom === 'shadow'); + var hasShadow = Boolean(Element.prototype.createShadowRoot); + var nativeShadow = hasShadow && !window.ShadowDOMPolyfill; + var useShadow = wantShadow && hasShadow; + + var hasNativeImports = Boolean('import' in document.createElement('link')); + var useNativeImports = hasNativeImports; + + var useNativeCustomElements = (!window.CustomElements || + window.CustomElements.useNative); + + return { + wantShadow: wantShadow, + hasShadow: hasShadow, + nativeShadow: nativeShadow, + useShadow: useShadow, + useNativeShadow: useShadow && nativeShadow, + useNativeImports: useNativeImports, + useNativeCustomElements: useNativeCustomElements + }; + })() + }; + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/style-defaults.html b/third_party/polymer/v0_8/components/polymer/src/lib/style-defaults.html new file mode 100644 index 0000000..68284f4 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/style-defaults.html
@@ -0,0 +1,32 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="style-util.html"> +<script> + + (function() { + + var defaultSheet = document.createElement('style'); + + function applyCss(cssText) { + defaultSheet.textContent += cssText; + defaultSheet.__cssRules = + Polymer.StyleUtil.parser.parse(defaultSheet.textContent); + } + + applyCss(''); + + // exports + Polymer.StyleDefaults = { + applyCss: applyCss, + defaultSheet: defaultSheet + }; + + })(); +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/style-transformer.html b/third_party/polymer/v0_8/components/polymer/src/lib/style-transformer.html new file mode 100644 index 0000000..68eb73cc --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/style-transformer.html
@@ -0,0 +1,213 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="style-util.html"> + +<script> + + (function() { + + /* Transforms ShadowDOM styling into ShadyDOM styling + + * scoping: + + * elements in scope get scoping selector class="x-foo-scope" + * selectors re-written as follows: + + div button -> div.x-foo-scope button.x-foo-scope + + * :host -> scopeName + + * :host(...) -> scopeName... + + * ::content -> ' ' NOTE: requires use of scoping selector and selectors + cannot otherwise be scoped: + e.g. :host ::content > .bar -> x-foo > .bar + + * ::shadow, /deep/: processed simimlar to ::content + + * :host-context(...): NOT SUPPORTED + + */ + + // Given a node and scope name, add a scoping class to each node + // in the tree. This facilitates transforming css into scoped rules. + function transformDom(node, scope, useAttr, shouldRemoveScope) { + _transformDom(node, scope || '', useAttr, shouldRemoveScope); + } + + function _transformDom(node, selector, useAttr, shouldRemoveScope) { + if (node.setAttribute) { + transformElement(node, selector, useAttr, shouldRemoveScope); + } + var c$ = Polymer.dom(node).childNodes; + for (var i=0; i<c$.length; i++) { + _transformDom(c$[i], selector, useAttr, shouldRemoveScope); + } + } + + function transformElement(element, scope, useAttr, shouldRemoveScope) { + if (useAttr) { + if (shouldRemoveScope) { + element.removeAttribute(SCOPE_NAME); + } else { + element.setAttribute(SCOPE_NAME, scope); + } + } else { + // note: if using classes, we add both the general 'style-scope' class + // as well as the specific scope. This enables easy filtering of all + // `style-scope` elements + if (scope) { + if (shouldRemoveScope) { + element.classList.remove(SCOPE_NAME, scope); + } else { + element.classList.add(SCOPE_NAME, scope); + } + } + } + } + + function transformHost(host, scope) { + } + + // Given a string of cssText and a scoping string (scope), returns + // a string of scoped css where each selector is transformed to include + // a class created from the scope. ShadowDOM selectors are also transformed + // (e.g. :host) to use the scoping selector. + function transformCss(rules, scope, ext, callback, useAttr) { + var hostScope = calcHostScope(scope, ext); + scope = calcElementScope(scope, useAttr); + return Polymer.StyleUtil.toCssText(rules, function(rule) { + transformRule(rule, scope, hostScope); + if (callback) { + callback(rule, scope, hostScope); + } + }); + } + + function calcElementScope(scope, useAttr) { + if (scope) { + return useAttr ? + CSS_ATTR_PREFIX + scope + CSS_ATTR_SUFFIX : + CSS_CLASS_PREFIX + scope; + } else { + return ''; + } + } + + function calcHostScope(scope, ext) { + return ext ? '[is=' + scope + ']' : scope; + } + + function transformRule(rule, scope, hostScope) { + _transformRule(rule, transformComplexSelector, + scope, hostScope); + } + + // transforms a css rule to a scoped rule. + function _transformRule(rule, transformer, scope, hostScope) { + var p$ = rule.selector.split(COMPLEX_SELECTOR_SEP); + for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) { + p$[i] = transformer(p, scope, hostScope); + } + rule.selector = p$.join(COMPLEX_SELECTOR_SEP); + } + + function transformComplexSelector(selector, scope, hostScope) { + var stop = false; + selector = selector.replace(SIMPLE_SELECTOR_SEP, function(m, c, s) { + if (!stop) { + var o = transformCompoundSelector(s, c, scope, hostScope); + if (o.stop) { + stop = true; + } + c = o.combinator; + s = o.value; + } + return c + s; + }); + return selector; + } + + function transformCompoundSelector(selector, combinator, scope, hostScope) { + // replace :host with host scoping class + var jumpIndex = selector.search(SCOPE_JUMP); + if (selector.indexOf(HOST) >=0) { + // :host(...) + selector = selector.replace(HOST_PAREN, function(m, host, paren) { + return hostScope + paren; + }); + // now normal :host + selector = selector.replace(HOST, hostScope); + // replace other selectors with scoping class + } else if (jumpIndex !== 0) { + selector = scope ? transformSimpleSelector(selector, scope) : selector; + } + // remove left-side combinator when dealing with ::content. + if (selector.indexOf(CONTENT) >= 0) { + combinator = ''; + } + // process scope jumping selectors up to the scope jump and then stop + // e.g. .zonk ::content > .foo ==> .zonk.scope > .foo + var stop; + if (jumpIndex >= 0) { + selector = selector.replace(SCOPE_JUMP, ' '); + stop = true; + } + return {value: selector, combinator: combinator, stop: stop}; + } + + function transformSimpleSelector(selector, scope) { + var p$ = selector.split(PSEUDO_PREFIX); + p$[0] += scope; + return p$.join(PSEUDO_PREFIX); + } + + function transformRootRule(rule) { + _transformRule(rule, transformRootSelector); + } + + function transformRootSelector(selector) { + return selector.match(SCOPE_JUMP) ? + transformComplexSelector(selector) : + selector.trim() + SCOPE_ROOT_SELECTOR; + } + + var SCOPE_NAME = 'style-scope'; + var SCOPE_ROOT_SELECTOR = ':not([' + SCOPE_NAME + '])' + + ':not(.' + SCOPE_NAME + ')'; + var COMPLEX_SELECTOR_SEP = ','; + var SIMPLE_SELECTOR_SEP = /(^|[\s>+~]+)([^\s>+~]+)/g; + var HOST = ':host'; + // NOTE: this supports 1 nested () pair for things like + // :host(:not([selected]), more general support requires + // parsing which seems like overkill + var HOST_PAREN = /(\:host)(?:\(((?:\([^)(]*\)|[^)(]*)+?)\))/g; + var CONTENT = '::content'; + var SCOPE_JUMP = /\:\:content|\:\:shadow|\/deep\//; + var CSS_CLASS_PREFIX = '.'; + var CSS_ATTR_PREFIX = '[' + SCOPE_NAME + '~='; + var CSS_ATTR_SUFFIX = ']'; + var PSEUDO_PREFIX = ':'; + + // exports + Polymer.StyleTransformer = { + element: transformElement, + dom: transformDom, + host: transformHost, + css: transformCss, + rule: transformRule, + rootRule: transformRootRule, + SCOPE_NAME: SCOPE_NAME + }; + + })(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/style-util.html b/third_party/polymer/v0_8/components/polymer/src/lib/style-util.html new file mode 100644 index 0000000..fd550c6 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/style-util.html
@@ -0,0 +1,77 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="css-parse.html"> + +<script> + + (function() { + + function toCssText(rules, callback) { + if (typeof rules === 'string') { + rules = Polymer.CssParse.parse(rules); + } + if (callback) { + forEachStyleRule(rules, callback); + } + return Polymer.CssParse.stringify(rules); + } + + function forEachStyleRule(node, cb) { + var s = node.selector; + var skipRules = false; + if (s) { + if ((s.indexOf(AT_RULE) !== 0) && (s.indexOf(MIXIN_SELECTOR) !== 0)) { + cb(node); + } + skipRules = (s.indexOf(KEYFRAME_RULE) >= 0) || + (s.indexOf(MIXIN_SELECTOR) >= 0); + } + var r$ = node.rules; + if (r$ && !skipRules) { + for (var i=0, l=r$.length, r; (i<l) && (r=r$[i]); i++) { + forEachStyleRule(r, cb); + } + } + } + + // add a string of cssText to the document. + function applyCss(cssText, moniker, target, lowPriority) { + var style = document.createElement('style'); + if (moniker) { + style.setAttribute('scope', moniker); + } + style.textContent = cssText; + target = target || document.head; + if (lowPriority) { + var n$ = target.querySelectorAll('style[scope]'); + var ref = n$.length ? n$[n$.length-1].nextSibling : target.firstChild; + target.insertBefore(style, ref); + } else { + target.appendChild(style); + } + return style; + } + + var AT_RULE = '@'; + var KEYFRAME_RULE = 'keyframe'; + var MIXIN_SELECTOR = '--'; + + // exports + Polymer.StyleUtil = { + parser: Polymer.CssParse, + applyCss: applyCss, + forEachStyleRule: forEachStyleRule, + toCssText: toCssText + }; + + })(); + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/template/templatizer.html b/third_party/polymer/v0_8/components/polymer/src/lib/template/templatizer.html new file mode 100644 index 0000000..2a5c5d80b --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/template/templatizer.html
@@ -0,0 +1,253 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<script> + + Polymer.Templatizer = { + + templatize: function(template) { + this._templatized = template; + // TODO(sjmiles): supply _alternate_ content reference missing from root + // templates (not nested). `_content` exists to provide content sharing + // for nested templates. + if (!template._content) { + template._content = template.content; + } + // fast path if template's anonymous class has been memoized + if (template._content._ctor) { + this.ctor = template._content._ctor; + //console.log('Templatizer.templatize: using memoized archetype'); + // forward parent properties to archetype + this._prepParentProperties(this.ctor.prototype); + return; + } + // `archetype` is the prototype of the anonymous + // class created by the templatizer + var archetype = Object.create(Polymer.Base); + // normally Annotations.parseAnnotations(template) but + // archetypes do special caching + this.customPrepAnnotations(archetype, template); + + // setup accessors + archetype._prepEffects(); + archetype._prepBehaviors(); + archetype._prepBindings(); + + // forward parent properties to archetype + this._prepParentProperties(archetype); + + // boilerplate code + archetype._notifyPath = this._notifyPathImpl; + archetype._scopeElementClass = this._scopeElementClassImpl; + // boilerplate code + var _constructor = this._constructorImpl; + var ctor = function TemplateInstance(model, host) { + _constructor.call(this, model, host); + }; + // standard references + ctor.prototype = archetype; + archetype.constructor = ctor; + // TODO(sjmiles): constructor cache? + template._content._ctor = ctor; + // TODO(sjmiles): choose less general name + this.ctor = ctor; + }, + + _getRootDataHost: function() { + return (this.dataHost && this.dataHost._rootDataHost) || this.dataHost; + }, + + _getAllStampedChildren: function(children) { + children = children || []; + if (this._getStampedChildren) { + var c$ = this._getStampedChildren(); + for (var i=0, c; c = c$[i]; i++) { + children.push(c); + if (c._getAllStampedChildren) { + c._getAllStampedChildren(children); + } + } + } + return children; + }, + + customPrepAnnotations: function(archetype, template) { + if (template) { + archetype._template = template; + var c = template._content; + if (c) { + var rootDataHost = archetype._rootDataHost; + if (rootDataHost) { + Polymer.Annotations.prepElement = + rootDataHost._prepElement.bind(rootDataHost); + } + archetype._notes = c._notes || + Polymer.Annotations.parseAnnotations(template); + c._notes = archetype._notes; + Polymer.Annotations.prepElement = null; + archetype._parentProps = c._parentProps; + } + else { + console.warn('no _content'); + } + } + else { + console.warn('no _template'); + } + }, + + // Sets up accessors on the template to call abstract _forwardParentProp + // API that should be implemented by Templatizer users to get parent + // properties to their template instances. These accessors are memoized + // on the archetype and copied to instances. + _prepParentProperties: function(archetype) { + var parentProps = this._parentProps = archetype._parentProps; + if (this._forwardParentProp && parentProps) { + // Prototype setup (memoized on archetype) + var proto = archetype._parentPropProto; + if (!proto) { + proto = archetype._parentPropProto = Object.create(null); + if (this._templatized != this) { + // Assumption: if `this` isn't the template being templatized, + // assume that the template is not a Poylmer.Base, so prep it + // for binding + Polymer.Bind.prepareModel(proto); + } + // Create accessors for each parent prop that forward the property + // to template instances through abstract _forwardParentProp API + // that should be implemented by Templatizer users + for (var prop in parentProps) { + var parentProp = '_parent_' + prop; + var effects = [{ + kind: 'function', + effect: { function: this._createForwardPropEffector(prop) } + }]; + Polymer.Bind._createAccessors(proto, parentProp, effects); + } + } + // Instance setup + if (this._templatized != this) { + Polymer.Bind.prepareInstance(this._templatized); + this._templatized._forwardParentProp = + this._forwardParentProp.bind(this); + } + this._extendTemplate(this._templatized, proto); + } + }, + + _createForwardPropEffector: function(prop) { + return function(source, value) { + this._forwardParentProp(prop, value); + }; + }, + + // Similar to Polymer.Base.extend, but retains any previously set instance + // values (_propertySet back on instance once accessor is installed) + _extendTemplate: function(template, proto) { + Object.getOwnPropertyNames(proto).forEach(function(n) { + var val = template[n]; + var pd = Object.getOwnPropertyDescriptor(proto, n); + Object.defineProperty(template, n, pd); + if (val !== undefined) { + template._propertySet(n, val); + } + }); + }, + + _notifyPathImpl: function(path, value) { + var p = path.match(/([^.]*)\.(([^.]*).*)/); + // 'root.sub.path' + var root = p[1]; // 'root' + var sub = p[3]; // 'sub' + var subPath = p[2]; // 'sub.path' + // Notify host of parent.* path/property changes + var dataHost = this.dataHost; + if (root == 'parent') { + if (sub == subPath) { + dataHost.dataHost[sub] = value; + } else { + dataHost.notifyPath('_parent_' + subPath, value); + } + } + // Extension point for Templatizer sub-classes + if (dataHost._forwardInstancePath) { + dataHost._forwardInstancePath.call(dataHost, this, root, subPath, value); + } + }, + + // Overrides Base notify-path module + _pathEffector: function(path, value, fromAbove) { + if (this._forwardParentPath) { + if (path.indexOf('_parent_') === 0) { + this._forwardParentPath(path.substring(8), value); + } + } + Polymer.Base._pathEffector.apply(this, arguments); + }, + + _constructorImpl: function(model, host) { + var rootDataHost = host._getRootDataHost(); + if (rootDataHost) { + this.listen = rootDataHost.listen.bind(rootDataHost); + this._rootDataHost = rootDataHost; + } + this._setupConfigure(model); + this._pushHost(host); + this.root = this.instanceTemplate(this._template); + this.root.__styleScoped = true; + this._popHost(); + this._marshalAnnotatedNodes(); + this._marshalInstanceEffects(); + this._marshalAnnotatedListeners(); + this._tryReady(); + }, + + _scopeElementClassImpl: function(node, value) { + var host = this._rootDataHost; + if (host) { + return host._scopeElementClass(node, value); + } + }, + + stamp: function(model) { + model = model || {}; + if (this._parentProps) { + // TODO(kschaaf): Maybe this is okay + // model.parent = this.dataHost; + model.parent = model.parent || {}; + for (var prop in this._parentProps) { + model.parent[prop] = this['_parent_' + prop]; + } + } + return new this.ctor(model, this); + } + + // TODO(sorvell): note, using the template as host is ~5-10% faster if + // elements have no default values. + // _constructorImpl: function(model, host) { + // this._setupConfigure(model); + // host._beginHost(); + // this.root = this.instanceTemplate(this._template); + // host._popHost(); + // this._marshalTemplateContent(); + // this._marshalAnnotatedNodes(); + // this._marshalInstanceEffects(); + // this._marshalAnnotatedListeners(); + // this._ready(); + // }, + + // stamp: function(model) { + // return new this.ctor(model, this.dataHost); + // } + + + }; + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/template/x-array-selector.html b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-array-selector.html new file mode 100644 index 0000000..536c38ee --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-array-selector.html
@@ -0,0 +1,178 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- +Keeping structured data in sync requires that Polymer understand the path +associations of data being bound. The `x-array-selector` element ensures path +linkage when selecting specific items from an array (either single or multiple). +The `items` property accepts an array of user data, and via the `select(item)` +and `deselect(item)` API, updates the `selected` property which may be bound to +other parts of the application, and any changes to sub-fields of `selected` +item(s) will be kept in sync with items in the `items` array. When `multi` +is false, `selected` is a property representing the last selected item. When +`multi` is true, `selected` is an array of multiply selected items. + +```html +<dom-module id="employee-list"> + + <template> + + <div> Employee list: </div> + <template is="x-repeat" id="employeeList" items="{{employees}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + <button on-click="toggleSelection">Select</button> + </template> + + <x-array-selector id="selector" items="{{employees}}" selected="{{selected}}" multi toggle></x-array-selector> + + <div> Selected employees: </div> + <template is="x-repeat" items="{{selected}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + </template> + + </template> + + <script> + Polymer({ + is: 'employee-list', + ready: function() { + this.employees = [ + {first: 'Bob', last: 'Smith'}, + {first: 'Sally', last: 'Johnson'}, + ... + ]; + }, + toggleSelection: function(e) { + var item = this.$.employeeList.itemForElement(e.target); + this.$.selector.select(item); + } + }); + </script> + +</dom-module> +``` +--> + +<script> + + Polymer({ + is: 'x-array-selector', + + properties: { + + /** + * An array containing items from which selection will be made. + */ + items: { + type: Array, + observer: '_itemsChanged' + }, + + /** + * When `multi` is true, this is an array that contains any selected. + * When `multi` is false, this is the currently selected item, or `null` + * if no item is selected. + */ + selected: { + type: Object, + notify: true + }, + + /** + * When `true`, calling `select` on an item that is already selected + * will deselect the item. + */ + toggle: Boolean, + + /** + * When `true`, multiple items may be selected at once (in this case, + * `selected` is an array of currently selected items). When `false`, + * only one item may be selected at a time. + */ + multi: Boolean + }, + + _itemsChanged: function() { + // Unbind previous selection + if (Array.isArray(this.selected)) { + for (var i=0; i<this.selected.length; i++) { + this.unbindPaths('selected.' + i); + } + } else { + this.unbindPaths('selected'); + } + // Initialize selection + if (this.multi) { + this.selected = []; + } else { + this.selected = null; + } + }, + + /** + * Deselects the given item if it is already selected. + */ + deselect: function(item) { + if (this.multi) { + var scol = Polymer.Collection.get(this.selected); + // var skey = scol.getKey(item); + // if (skey >= 0) { + var sidx = this.selected.indexOf(item); + if (sidx >= 0) { + var skey = scol.getKey(item); + this.selected.splice(sidx, 1); + // scol.remove(item); + this.unbindPaths('selected.' + skey); + return true; + } + } else { + this.selected = null; + this.unbindPaths('selected'); + } + }, + + /** + * Selects the given item. When `toggle` is true, this will automatically + * deselect the item if already selected. + */ + select: function(item) { + var icol = Polymer.Collection.get(this.items); + var key = icol.getKey(item); + if (this.multi) { + // var sidx = this.selected.indexOf(item); + // if (sidx < 0) { + var scol = Polymer.Collection.get(this.selected); + var skey = scol.getKey(item); + if (skey >= 0) { + this.deselect(item); + } else if (this.toggle) { + this.selected.push(item); + // this.bindPaths('selected.' + sidx, 'items.' + skey); + // skey = Polymer.Collection.get(this.selected).add(item); + this.async(function() { + skey = scol.getKey(item); + this.bindPaths('selected.' + skey, 'items.' + key); + }); + } + } else { + if (this.toggle && item == this.selected) { + this.deselect(); + } else { + this.bindPaths('selected', 'items.' + key); + this.selected = item; + } + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/template/x-autobind.html b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-autobind.html new file mode 100644 index 0000000..11b0af5f4 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-autobind.html
@@ -0,0 +1,82 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- + +**THIS ELEMENT IS EXPERIMENTAL. API AND NAME SUBJECT TO CHANGE.** + +Polymer's binding features are only available within templates that are managed +by Polymer. As such, these features are available in templates used to define +Polymer elements, for example, but not for elements placed directly in the main +document. + +In order to use Polymer bindings without defining a new custom element, elements +utilizing bindings may be wrapped with the `x-autobind` template extension. +This template will immediately stamp itself into the main document and bind +elements to the template itself as the binding scope. + +```html +<!doctype html> +<html> +<head> + <meta charset="utf-8"> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + <link rel="import" href="components/core-ajax/core-ajax.html"> + +</head> +<body> + + <template is="x-autobind"> + + <core-ajax url="http://..." lastresponse="{{data}}"></core-ajax> + + <template is="x-repeat" items="{{data}}"> + <div><span>{{item.first}}</span> <span>{{item.last}}</span></div> + </template> + + </template> + +</body> +</html> +``` + +--> + +<script> + + Polymer({ + + is: 'x-autobind', + + extends: 'template', + + _registerFeatures: function() { + this._prepExtends(); + this._prepConstructor(); + }, + + _finishDistribute: function() { + var parentDom = Polymer.dom(Polymer.dom(this).parentNode); + parentDom.insertBefore(this.root, this); + }, + + _initFeatures: function() { + this._template = this; + this._prepAnnotations(); + this._prepEffects(); + this._prepBehaviors(); + this._prepBindings(); + Polymer.Base._initFeatures.call(this); + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/template/x-if.html b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-if.html new file mode 100644 index 0000000..3a5bc27d --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-if.html
@@ -0,0 +1,139 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="templatizer.html"> + +<script> + + /** + * Stamps the template iff the `if` property is truthy. + * + * When `if` becomes falsey, the stamped content is hidden but not + * removed from dom. When `if` subsequently becomes truthy again, the content + * is simply re-shown. This approach is used due to its favorable performance + * characteristics: the expense of creating template content is paid only + * once and lazily. + * + * Set the `restamp` property to true to force the stamped content to be + * created / destroyed when the `if` condition changes. + */ + Polymer({ + + is: 'x-if', + extends: 'template', + + properties: { + + 'if': { + type: Boolean, + value: false + }, + + restamp: { + type: Boolean, + value: false + } + + }, + + behaviors: [ + Polymer.Templatizer + ], + + observers: [ + 'render(if, restamp)' + ], + + render: function() { + this.debounce('render', function() { + if (this.if) { + if (!this.ctor) { + this._wrapTextNodes(this._content); + this.templatize(this); + } + this._ensureInstance(); + } else if (this.restamp) { + this._teardownInstance(); + } + if (!this.restamp && this._instance) { + this._showHideInstance(this.if); + } + }); + }, + + _ensureInstance: function() { + if (!this._instance) { + // TODO(sorvell): pickup stamping logic from x-repeat + this._instance = this.stamp(); + var root = this._instance.root; + this._instance._children = Array.prototype.slice.call(root.childNodes); + // TODO(sorvell): this incantation needs to be simpler. + var parent = Polymer.dom(Polymer.dom(this).parentNode); + parent.insertBefore(root, this); + } + }, + + _teardownInstance: function() { + if (this._instance) { + var parent = Polymer.dom(Polymer.dom(this).parentNode); + this._instance._children.forEach(function(n) { + parent.removeChild(n); + }); + this._instance = null; + } + }, + + _wrapTextNodes: function(root) { + // wrap text nodes in span so they can be hidden. + for (var n = root.firstChild; n; n=n.nextSibling) { + if (n.nodeType === Node.TEXT_NODE) { + var s = document.createElement('span'); + root.insertBefore(s, n); + s.appendChild(n); + n = s; + } + } + }, + + // Implements extension point from Templatizer mixin + _getStampedChildren: function() { + return this._instance._children; + }, + + _showHideInstance: function(showing) { + this._getAllStampedChildren().forEach(function(n) { + if (n.setAttribute) { + this.serializeValueToAttribute(!showing, 'hidden', n); + } + }, this); + }, + + // Implements extension point from Templatizer mixin + // Called as side-effect of a host property change, responsible for + // notifying parent.<prop> path change on instance + _forwardParentProp: function(prop, value) { + if (this._instance) { + this._instance.parent[prop] = value; + this._instance.notifyPath('parent.' + prop, value, true); + } + }, + + // Implements extension point from Templatizer + // Called as side-effect of a host path change, responsible for + // notifying parent.<path> path change on each row + _forwardParentPath: function(path, value) { + if (this._instance) { + this._instance.notifyPath('parent.' + path, value, true); + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/template/x-repeat.html b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-repeat.html new file mode 100644 index 0000000..c584268 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-repeat.html
@@ -0,0 +1,546 @@ +<!-- +@license +Copyright (c) 2015 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- + +**THIS ELEMENT IS EXPERIMENTAL. API AND NAME SUBJECT TO CHANGE.** + +The `x-repeat` element is a custom `HTMLTemplateElement` type extension that +automatically stamps and binds one instance of template content to each object +in a user-provided array. `x-repeat` accepts an `items` property, and one +instance of the template is stamped for each item into the DOM at the location +of the `x-repeat` element. The `item` property will be set on each instance's +binding scope, thus templates should bind to sub-properties of `item`. + +Example: + +```html +<dom-module id="employee-list"> + + <template> + + <div> Employee list: </div> + <template is="x-repeat" items="{{employees}}"> + <div>First name: <span>{{item.first}}</span></div> + <div>Last name: <span>{{item.last}}</span></div> + </template> + + </template> + + <script> + Polymer({ + is: 'employee-list', + ready: function() { + this.employees = [ + {first: 'Bob', last: 'Smith'}, + {first: 'Sally', last: 'Johnson'}, + ... + ]; + } + }); + </script> + +</dom-module> +``` + +Notifications for changes to items sub-properties will be forwarded to template +instances, which will update via the normal structured data notification system. + +Mutations to the `items` array itself (`push`, `pop`, `splice`, `shift`, +`unshift`) are observed via `Array.observe` (where supported, or an +shim of this API on unsupported browsers), and template instances are kept in +sync with the data in the array. + +A view-specific filter/sort may be applied to each `x-repeat` by supplying a +`filter` and/or `sort` property. This may be a string that names a function on +the host, or a function may be assigned to the property directly. The functions +should implemented following the standard `Array` filter/sort API. + +In order to re-run the filter or sort functions based on changes to sub-fields +of `items`, the `observe` property may be set as a space-separated list of +`item` sub-fields that should cause a re-filter/sort when modified. + +For example, for an `x-repeat` with a filter of the following: + +```js +isEngineer: function(item) { + return item.type == 'engineer' || item.manager.type == 'engineer'; +} +``` + +Then the `observe` property should be configured as follows: + +```html +<template is="x-repeat" items="{{employees}}" + filter="isEngineer" observe="type manager.type"> +``` + +--> + +<link rel="import" href="templatizer.html"> +<link rel="import" href="../array-observe.html"> +<link rel="import" href="../collection.html"> + +<script> + + Polymer({ + + is: 'x-repeat', + extends: 'template', + + properties: { + + /** + * An array containing items determining how many instances of the template + * to stamp and that that each template instance should bind to. + */ + items: { + type: Array + }, + + /** + * A function that should determine the sort order of the items. This + * property should either be provided as a string, indicating a method + * name on the element's host, or else be an actual function. The + * function should match the sort function passed to `Array.sort`. + * Using a sort function has no effect on the underlying `items` array. + */ + sort: { + type: Function, + observer: '_sortChanged' + }, + + /** + * A function that can be used to filter items out of the view. This + * property should either be provided as a string, indicating a method + * name on the element's host, or else be an actual function. The + * function should match the sort function passed to `Array.filter`. + * Using a filter function has no effect on the underlying `items` array. + */ + filter: { + type: Function, + observer: '_filterChanged' + }, + + /** + * When using a `filter` or `sort` function, the `observe` property + * should be set to a space-separated list of the names of item + * sub-fields that should trigger a re-sort or re-filter when changed. + * These should generally be fields of `item` that the sort or filter + * function depends on. + */ + observe: { + type: String, + observer: '_observeChanged' + }, + + /** + * When using a `filter` or `sort` function, the `delay` property + * determines a debounce time after a change to observed item + * properties that must pass before the filter or sort is re-run. + * This is useful in rate-limiting shuffing of the view when + * item changes may be frequent. + */ + delay: Number + }, + + behaviors: [ + Polymer.Templatizer + ], + + observers: [ + '_itemsChanged(items.*)' + ], + + created: function() { + this.boundCollectionObserver = this.render.bind(this); + }, + + ready: function() { + // Templatizing (generating the instance constructor) needs to wait + // until attached, since it may not have its template content handed + // back to it until then, following its host template stamping + if (!this.ctor) { + this.templatize(this); + } + }, + + _sortChanged: function() { + var dataHost = this._getRootDataHost(); + this._sortFn = this.sort && (typeof this.sort == 'function' ? + this.sort : dataHost[this.sort].bind(this.host)); + if (this.items) { + this.debounce('render', this.render); + } + }, + + _filterChanged: function() { + var dataHost = this._getRootDataHost(); + this._filterFn = this.filter && (typeof this.filter == 'function' ? + this.filter : dataHost[this.filter].bind(this.host)); + if (this.items) { + this.debounce('render', this.render); + } + }, + + _observeChanged: function() { + this._observePaths = this.observe && + this.observe.replace('.*', '.').split(' '); + }, + + _itemsChanged: function(change) { + if (change.path == 'items') { + this._unobserveCollection(); + if (change.value) { + this._observeCollection(change.value); + this.debounce('render', this.render); + } + } else { + this._forwardItemPath(change.path, change.value); + this._checkObservedPaths(change.path); + } + }, + + _checkObservedPaths: function(path) { + if (this._observePaths && path.indexOf('items.') === 0) { + path = path.substring(path.indexOf('.', 6) + 1); + var paths = this._observePaths; + for (var i=0; i<paths.length; i++) { + if (path.indexOf(paths[i]) === 0) { + this.debounce('render', this.render, this.delay); + return; + } + } + } + }, + + _observeCollection: function(items) { + this.collection = Array.isArray(items) ? Polymer.Collection.get(items) : items; + this.collection.observe(this.boundCollectionObserver); + }, + + _unobserveCollection: function() { + if (this.collection) { + this.collection.unobserve(this.boundCollectionObserver); + } + }, + + render: function(splices) { + this.flushDebouncer('render'); + var c = this.collection; + if (splices) { + if (this._sortFn || splices[0].index == null) { + this._applySplicesViewSort(splices); + } else { + this._applySplicesArraySort(splices); + } + } else { + this._sortAndFilter(); + } + var rowForKey = this._rowForKey = {}; + var keys = this._orderedKeys; + // Assign items and keys + this.rows = this.rows || []; + for (var i=0; i<keys.length; i++) { + var key = keys[i]; + var item = c.getItem(key); + var row = this.rows[i]; + rowForKey[key] = i; + if (!row) { + this.rows.push(row = this._insertRow(i, null, item)); + } + row.item = item; + row.key = key; + row.index = i; + } + // Remove extra + for (; i<this.rows.length; i++) { + this._detachRow(i); + } + this.rows.splice(keys.length, this.rows.length-keys.length); + }, + + _sortAndFilter: function() { + var c = this.collection; + this._orderedKeys = c.getKeys(); + // Filter + if (this._filterFn) { + this._orderedKeys = this._orderedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + } + // Sort + if (this._sortFn) { + this._orderedKeys.sort(function(a, b) { + return this._sortFn(c.getItem(a), c.getItem(b)); + }.bind(this)); + } + }, + + _keySort: function(a, b) { + return this.collection.getKey(a) - this.collection.getKey(b); + }, + + _applySplicesViewSort: function(splices) { + var c = this.collection; + var keys = this._orderedKeys; + var rows = this.rows; + var removedRows = []; + var addedKeys = []; + var pool = []; + var sortFn = this._sortFn || this._keySort.bind(this); + splices.forEach(function(s) { + // Collect all removed row idx's + for (var i=0; i<s.removed.length; i++) { + var idx = this._rowForKey[s.removed[i]]; + if (idx != null) { + removedRows.push(idx); + } + } + // Collect all added keys + for (i=0; i<s.added.length; i++) { + addedKeys.push(s.added[i]); + } + }, this); + if (removedRows.length) { + // Sort removed rows idx's + removedRows.sort(); + // Remove keys and pool rows (backwards, so we don't invalidate rowForKey) + for (i=removedRows.length-1; i>=0 ; i--) { + var idx = removedRows[i]; + pool.push(this._detachRow(idx)); + rows.splice(idx, 1); + keys.splice(idx, 1); + } + } + if (addedKeys.length) { + // Filter added keys + if (this._filterFn) { + addedKeys = addedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + } + // Sort added keys + addedKeys.sort(function(a, b) { + return this.sortFn(c.getItem(a), c.getItem(b)); + }, this); + // Insert new rows using sort (from pool or newly created) + var start = 0; + for (i=0; i<addedKeys.length; i++) { + start = this._insertRowIntoViewSort(start, addedKeys[i], pool); + } + } + }, + + _insertRowIntoViewSort: function(start, key, pool) { + var c = this.collection; + var item = c.getItem(key); + var end = this.rows.length - 1; + var idx = -1; + var sortFn = this._sortFn || this._keySort.bind(this); + // Binary search for insertion point + while (start <= end) { + var mid = (start + end) >> 1; + var midKey = this._orderedKeys[mid]; + var cmp = sortFn(c.getItem(midKey), item); + if (cmp < 0) { + start = mid + 1; + } else if (cmp > 0) { + end = mid - 1; + } else { + idx = mid; + break; + } + } + if (idx < 0) { + idx = end + 1; + } + // Insert key & row at insertion point + this._orderedKeys.splice(idx, 0, key); + this.rows.splice(idx, 0, this._insertRow(idx, pool)); + return idx; + }, + + _applySplicesArraySort: function(splices) { + var keys = this._orderedKeys; + var pool = []; + splices.forEach(function(s) { + // Remove & pool rows first, to ensure we can fully reuse removed rows + for (var i=0; i<s.removed.length; i++) { + pool.push(this._detachRow(s.index + i)); + } + this.rows.splice(s.index, s.removed.length); + }, this); + var c = this.collection; + var filterDelta = 0; + splices.forEach(function(s) { + // Filter added keys + var addedKeys = s.added; + if (this._filterFn) { + addedKeys = addedKeys.filter(function(a) { + return this._filterFn(c.getItem(a)); + }, this); + filterDelta += (s.added.length - addedKeys.length); + } + var idx = s.index - filterDelta; + // Apply splices to keys + var args = [idx, s.removed.length].concat(addedKeys); + keys.splice.apply(keys, args); + // Insert new rows (from pool or newly created) + var addedRows = []; + for (i=0; i<s.added.length; i++) { + addedRows.push(this._insertRow(idx + i, pool)); + } + args = [s.index, 0].concat(addedRows); + this.rows.splice.apply(this.rows, args); + }, this); + }, + + _detachRow: function(idx) { + var row = this.rows[idx]; + var parentNode = Polymer.dom(this).parentNode; + for (var i=0; i<row._children.length; i++) { + var el = row._children[i]; + Polymer.dom(row.root).appendChild(el); + } + return row; + }, + + _insertRow: function(idx, pool, item) { + var row = (pool && pool.pop()) || this._generateRow(idx, item); + var beforeRow = this.rows[idx]; + var beforeNode = beforeRow ? beforeRow._children[0] : this; + var parentNode = Polymer.dom(this).parentNode; + Polymer.dom(parentNode).insertBefore(row.root, beforeNode); + return row; + }, + + _generateRow: function(idx, item) { + var row = this.stamp({ + index: idx, + key: this.collection.getKey(item), + item: item + }); + // each row is a document fragment which is lost when we appendChild, + // so we have to track each child individually + var children = []; + for (var n = row.root.firstChild; n; n=n.nextSibling) { + children.push(n); + n._templateInstance = row; + } + // Since archetype overrides Base/HTMLElement, Safari complains + // when accessing `children` + row._children = children; + return row; + }, + + // Implements extension point from Templatizer mixin + _getStampedChildren: function() { + var children = []; + if (this.rows) { + for (var i=0; i<this.rows.length; i++) { + var c = this.rows[i]._children; + for (var j=0; j<c.length; j++) + children.push(c[j]); + } + } + return children; + }, + + // Implements extension point from Templatizer + // Called as a side effect of a template instance path change, responsible + // for notifying items.<key-for-row>.<path> change up to host + _forwardInstancePath: function(row, root, subPath, value) { + if (root == 'item') { + this.notifyPath('items.' + row.key + '.' + subPath, value); + } + }, + + // Implements extension point from Templatizer mixin + // Called as side-effect of a host property change, responsible for + // notifying parent.<prop> path change on each row + _forwardParentProp: function(prop, value) { + if (this.rows) { + this.rows.forEach(function(row) { + row.parent[prop] = value; + row.notifyPath('parent.' + prop, value, true); + }, this); + } + }, + + // Implements extension point from Templatizer + // Called as side-effect of a host path change, responsible for + // notifying parent.<path> path change on each row + _forwardParentPath: function(path, value) { + if (this.rows) { + this.rows.forEach(function(row) { + row.notifyPath('parent.' + path, value, true); + }, this); + } + }, + + // Called as a side effect of a host items.<key>.<path> path change, + // responsible for notifying item.<path> changes to row for key + _forwardItemPath: function(path, value) { + if (this._rowForKey) { + // 'items.'.length == 6 + var dot = path.indexOf('.', 6); + var key = path.substring(6, dot < 0 ? path.length : dot); + var idx = this._rowForKey[key]; + var row = this.rows[idx]; + if (row) { + if (dot >= 0) { + path = 'item.' + path.substring(dot+1); + row.notifyPath(path, value, true); + } else { + row.item = value; + } + } + } + }, + + _instanceForElement: function(el) { + while (el && !el._templateInstance) { + el = el.parentNode; + } + return el && el._templateInstance; + }, + + /** + * Returns the item associated with a given element stamped by + * this `x-repeat`. + */ + itemForElement: function(el) { + var instance = this._instanceForElement(el); + return instance && instance.item; + }, + + /** + * Returns the `Polymer.Collection` key associated with a given + * element stamped by this `x-repeat`. + */ + keyForElement: function(el) { + var instance = this._instanceForElement(el); + return instance && instance.key; + }, + + /** + * Returns the index in `items` associated with a given element + * stamped by this `x-repeat`. + */ + indexForElement: function(el) { + var instance = this._instanceForElement(el); + return this.rows.indexOf(instance); + } + + }); + + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/template/x-template.html b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-template.html new file mode 100644 index 0000000..92e80f52 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/template/x-template.html
@@ -0,0 +1,39 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="templatizer.html"> + +<script> + + /** + * Creates a pseudo-custom-element that maps property values to bindings + * in DOM. + * + * `stamp` method creates an instance of the pseudo-element. The instance + * references a document-fragment containing the stamped and bound dom + * via it's `root` property. + * + */ + Polymer({ + + is: 'x-template', + extends: 'template', + + behaviors: [ + Polymer.Templatizer + ], + + ready: function() { + this.templatize(this); + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/lib/x-style.html b/third_party/polymer/v0_8/components/polymer/src/lib/x-style.html new file mode 100644 index 0000000..8eb192eb --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/lib/x-style.html
@@ -0,0 +1,115 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="style-util.html"> +<link rel="import" href="style-transformer.html"> +<link rel="import" href="style-defaults.html"> + +<!-- + +The `x-style` extension of the native `<style>` element allows defining styles +in the main document that can take advantage of several special features of +Polymer's styling system: + +* Document styles defined in an `x-style` will be shimmed to ensure they do +not leak into local DOM when running on browsers without non-native Shadow DOM. +* Shadow DOM-specific `/deep/` and `::shadow` combinators will be shimmed on +browsers without non-native Shadow DOM. +* Custom properties used by Polymer's experimental shim for cross-scope styling +may be defined in an `x-style`. + +Example: + +```html +<!doctype html> +<html> +<head> + <script src="components/webcomponentsjs/webcomponents-lite.js"></script> + <link rel="import" href="components/polymer/polymer.html"> + + <style is="x-style"> + + /* Will be prevented from affecting local DOM of Polymer elements */ + * { + box-sizing: border-box; + } + + /* Can use /deep/ and ::shadow combinators */ + body /deep/ .my-special-view::shadow #thing-inside { + background: yellow; + } + + /* Custom properties that inherit down the document tree may be defined */ + body { + --my-toolbar-title-color: green; + } + + </style> + +</head> +<body> + + ... + +</body> +</html> +``` + +Note, all features of `x-style` are available when defining styles as part of Polymer elements (e.g. `<style>` elements within `<dom-module>`'s used for defining Polymer elements. The `x-style` extension should only be used for defining document styles, outside of a custom element's local DOM. + +--> + +<script> +(function() { + + Polymer({ + + is: 'x-style', + extends: 'style', + + created: function() { + var rules = Polymer.StyleUtil.parser.parse(this.textContent); + this.applyProperties(rules); + // TODO(sorvell): since custom rules must match directly, they tend to be + // made with selectors like `*`. + // We *remove them here* so they don't apply too widely and nerf recalc. + // This means that normal properties mixe in rules with custom + // properties will *not* apply. + var cssText = Polymer.StyleUtil.parser.stringify(rules); + this.textContent = this.scopeCssText(cssText); + }, + + scopeCssText: function(cssText) { + return Polymer.Settings.useNativeShadow ? + cssText : + Polymer.StyleUtil.toCssText(cssText, function(rule) { + Polymer.StyleTransformer.rootRule(rule); + }); + }, + + applyProperties: function(rules) { + var cssText = ''; + Polymer.StyleUtil.forEachStyleRule(rules, function(rule) { + if (rule.cssText.match(CUSTOM_RULE)) { + // TODO(sorvell): use parser.stringify, it needs an option not to + // strip custom properties. + cssText += rule.selector + ' {\n' + rule.cssText + '\n}\n'; + } + }); + if (cssText) { + Polymer.StyleDefaults.applyCss(cssText); + } + } + + }); + + var CUSTOM_RULE = /--[^;{'"]*\:/; + +})(); +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/micro/attributes.html b/third_party/polymer/v0_8/components/polymer/src/micro/attributes.html new file mode 100644 index 0000000..67fe13a --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/micro/attributes.html
@@ -0,0 +1,180 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../lib/case-map.html"> + +<script> + + /** + * Support for `hostAttributes` property. + * + * hostAttributes: 'block vertical layout' + * + * `hostAttributes` is a space-delimited string of boolean attribute names to + * set true on each instance. + * + * Support for mapping attributes to properties. + * + * Properties that are configured in `properties` with a type are mapped + * to attributes. + * + * A value set in an attribute is deserialized into the specified + * data-type and stored into the matching property. + * + * Example: + * + * properties: { + * // values set to index attribute are converted to Number and propagated + * // to index property + * index: Number, + * // values set to label attribute are propagated to index property + * label: String + * } + * + * Types supported for deserialization: + * + * - Number + * - Boolean + * - String + * - Object (JSON) + * - Array (JSON) + * - Date + * + * This feature implements `attributeChanged` to support automatic + * propagation of attribute values at run-time. If you override + * `attributeChanged` be sure to call this base class method + * if you also want the standard behavior. + * + * @class base feature: attributes + */ + + Polymer.Base._addFeature({ + + _marshalAttributes: function() { + this._takeAttributes(); + }, + + _installHostAttributes: function(attributes) { + if (attributes) { + this.applyAttributes(this, attributes); + } + }, + + applyAttributes: function(node, attr$) { + for (var n in attr$) { + this.serializeValueToAttribute(attr$[n], n, this); + } + }, + + _takeAttributes: function() { + this._takeAttributesToModel(this); + }, + + _takeAttributesToModel: function(model) { + for (var i=0, l=this.attributes.length; i<l; i++) { + var a = this.attributes[i]; + var property = Polymer.CaseMap.dashToCamelCase(a.name); + var info = this.getPropertyInfo(property); + if (info || this._propertyEffects[property]) { + model[property] = + this.deserialize(a.value, info.type); + } + } + }, + + setAttributeToProperty: function(model, attrName) { + // Don't deserialize back to property if currently reflecting + if (!this._serializing) { + var propName = Polymer.CaseMap.dashToCamelCase(attrName); + if (propName in this.properties) { + var type = this.getPropertyType(propName); + var val = this.getAttribute(attrName); + model[propName] = this.deserialize(val, type); + } + } + }, + + _serializing: false, + reflectPropertyToAttribute: function(name) { + this._serializing = true; + this.serializeValueToAttribute(this[name], + Polymer.CaseMap.camelToDashCase(name)); + this._serializing = false; + }, + + serializeValueToAttribute: function(value, attribute, node) { + var str = this.serialize(value); + (node || this) + [str === undefined ? 'removeAttribute' : 'setAttribute'] + (attribute, str); + }, + + deserialize: function(value, type) { + switch (type) { + case Number: + value = Number(value); + break; + + case Boolean: + value = (value !== null); + break; + + case Object: + try { + value = JSON.parse(value); + } catch(x) { + // allow non-JSON literals like Strings and Numbers + } + break; + + case Array: + try { + value = JSON.parse(value); + } catch(x) { + value = null; + console.warn('Polymer::Attributes: couldn`t decode Array as JSON'); + } + break; + + case Date: + value = new Date(value); + break; + + case String: + default: + break; + } + return value; + }, + + serialize: function(value) { + switch (typeof value) { + case 'boolean': + return value ? '' : undefined; + + case 'object': + if (value instanceof Date) { + return value; + } else if (value) { + try { + return JSON.stringify(value); + } catch(x) { + return ''; + } + } + + default: + return value != null ? value : undefined; + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/micro/behaviors.html b/third_party/polymer/v0_8/components/polymer/src/micro/behaviors.html new file mode 100644 index 0000000..39601b65 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/micro/behaviors.html
@@ -0,0 +1,114 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + /** + * Automatically extend using objects referenced in `behaviors` array. + * + * someBehaviorObject = { + * accessors: { + * value: {type: Number, observer: '_numberChanged'} + * }, + * observers: [ + * // ... + * ], + * ready: function() { + * // called before prototoype's ready + * }, + * _numberChanged: function() {} + * }; + * + * Polymer({ + * + * behaviors: [ + * someBehaviorObject + * ] + * + * ... + * + * }); + * + * @class base feature: behaviors + */ + + Polymer.Base._addFeature({ + + behaviors: [], + + _prepBehaviors: function() { + this._flattenBehaviors(); + this._prepBehavior(this); + this.behaviors.forEach(function(b) { + this._mixinBehavior(b); + this._prepBehavior(b); + }, this); + }, + + _flattenBehaviors: function() { + var flat = []; + this.behaviors.forEach(function(b) { + if (!b) { + console.warn('Polymer: undefined behavior in [' + this.is + ']'); + } else if (b instanceof Array) { + flat = flat.concat(b); + } else { + flat.push(b); + } + }, this); + this.behaviors = flat; + }, + + _mixinBehavior: function(b) { + Object.getOwnPropertyNames(b).forEach(function(n) { + switch (n) { + case 'registered': + case 'properties': + case 'observers': + case 'listeners': + case 'keyPresses': + case 'hostAttributes': + case 'created': + case 'attached': + case 'detached': + case 'attributeChanged': + case 'configure': + case 'ready': + break; + default: + this.copyOwnProperty(n, b, this); + break; + } + }, this); + }, + + _doBehavior: function(name, args) { + this.behaviors.forEach(function(b) { + this._invokeBehavior(b, name, args); + }, this); + this._invokeBehavior(this, name, args); + }, + + _invokeBehavior: function(b, name, args) { + var fn = b[name]; + if (fn) { + fn.apply(this, args || Polymer.nar); + } + }, + + _marshalBehaviors: function() { + this.behaviors.forEach(function(b) { + this._marshalBehavior(b); + }, this); + this._marshalBehavior(this); + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/micro/constructor.html b/third_party/polymer/v0_8/components/polymer/src/micro/constructor.html new file mode 100644 index 0000000..e998544 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/micro/constructor.html
@@ -0,0 +1,70 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + /** + * Generates a boilerplate constructor. + * + * XFoo = Polymer({ + * is: 'x-foo' + * }); + * ASSERT(new XFoo() instanceof XFoo); + * + * You can supply a custom constructor on the prototype. But remember that + * this constructor will only run if invoked **manually**. Elements created + * via `document.createElement` or from HTML _will not invoke this method_. + * + * Instead, we reuse the concept of `constructor` for a factory method which + * can take arguments. + * + * MyFoo = Polymer({ + * is: 'my-foo', + * constructor: function(foo) { + * this.foo = foo; + * } + * ... + * }); + * + * @class base feature: constructor + */ + + Polymer.Base._addFeature({ + + // registration-time + + _prepConstructor: function() { + // support both possible `createElement` signatures + this._factoryArgs = this.extends ? [this.extends, this.is] : [this.is]; + // thunk the constructor to delegate allocation to `createElement` + var ctor = function() { + return this._factory(arguments); + }; + if (this.hasOwnProperty('extends')) { + ctor.extends = this.extends; + } + // ensure constructor is set. The `constructor` property is + // not writable on Safari; note: Chrome requires the property + // to be configurable. + Object.defineProperty(this, 'constructor', {value: ctor, + writable: true, configurable: true}); + ctor.prototype = this; + }, + + _factory: function(args) { + var elt = document.createElement.apply(document, this._factoryArgs); + if (this.factoryImpl) { + this.factoryImpl.apply(elt, args); + } + return elt; + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/micro/debouncer.html b/third_party/polymer/v0_8/components/polymer/src/micro/debouncer.html new file mode 100644 index 0000000..7afbfce --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/micro/debouncer.html
@@ -0,0 +1,57 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Polymer.Base._addFeature({ + + _setupDebouncers: function() { + this._debouncers = {}; + }, + + /** + * Debounce signals. + * + * Call `debounce` to collapse multiple requests for a named task into + * one invocation which is made after the wait time has elapsed with + * no new request. + * + * debouncedClickAction: function(e) { + * // will not call `processClick` more than once per 100ms + * this.debounce('click', function() { + * this.processClick; + * }, 100); + * } + * + * @method debounce + * @param String {String} jobName A string to indentify the debounce job. + * @param Function {Function} callback A function that is called (with `this` context) when the wait time elapses. + * @param Number {Number} wait Time in milliseconds (ms) after the last signal that must elapse before invoking `callback` + * @type Handle + */ + debounce: function(jobName, callback, wait) { + this._debouncers[jobName] = Polymer.Debounce.call(this, + this._debouncers[jobName], callback, wait); + }, + + isDebouncerActive: function(jobName) { + var debouncer = this._debouncers[jobName]; + return debouncer && debouncer.finish; + }, + + flushDebouncer: function(jobName) { + var debouncer = this._debouncers[jobName]; + if (debouncer) { + debouncer.complete(); + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/micro/extends.html b/third_party/polymer/v0_8/components/polymer/src/micro/extends.html new file mode 100644 index 0000000..a90f8e4 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/micro/extends.html
@@ -0,0 +1,79 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + /** + * Support `extends` property (for type-extension only). + * + * If the mixin is String-valued, the corresponding Polymer module + * is mixed in. + * + * Polymer({ + * is: 'pro-input', + * extends: 'input', + * ... + * }); + * + * Type-extension objects are created using `is` notation in HTML, or via + * the secondary argument to `document.createElement` (the type-extension + * rules are part of the Custom Elements specification, not something + * created by Polymer). + * + * Example: + * + * <!-- right: creates a pro-input element --> + * <input is="pro-input"> + * + * <!-- wrong: creates an unknown element --> + * <pro-input> + * + * <script> + * // right: creates a pro-input element + * var elt = document.createElement('input', 'pro-input'); + * + * // wrong: creates an unknown element + * var elt = document.createElement('pro-input'); + * <\script> + * + * @class base feature: extends + */ + + Polymer.Base._addFeature({ + + _prepExtends: function() { + if (this.extends) { + this.__proto__ = this.getExtendedPrototype(this.extends); + } + }, + + getExtendedPrototype: function(tag) { + return this.getExtendedNativePrototype(tag); + }, + + nativePrototypes: {}, // static + + getExtendedNativePrototype: function(tag) { + var p = this.nativePrototypes[tag]; + if (!p) { + var np = this.getNativePrototype(tag); + p = this.extend(Object.create(np), Polymer.Base); + this.nativePrototypes[tag] = p; + } + return p; + }, + + getNativePrototype: function(tag) { + // TODO(sjmiles): sad necessity + return Object.getPrototypeOf(document.createElement(tag)); + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/micro/mixins.html b/third_party/polymer/v0_8/components/polymer/src/micro/mixins.html new file mode 100644 index 0000000..4f0b274 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/micro/mixins.html
@@ -0,0 +1,40 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + /** + * Automatically extend using objects referenced in `mixins` array. + * + * Polymer({ + * + * mixins: [ + * someMixinObject + * ] + * + * ... + * + * }); + * + * @class base feature: mixins + */ + + Polymer.Base._addFeature({ + + _prepMixins: function() { + if (this.mixins) { + this.mixins.forEach(function(m) { + Polymer.Base.extend(this, m); + }, this); + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/micro/properties.html b/third_party/polymer/v0_8/components/polymer/src/micro/properties.html new file mode 100644 index 0000000..79a3825f --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/micro/properties.html
@@ -0,0 +1,102 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + /** + * Define property metadata. + * + * properties: { + * <property>: <Type || Object>, + * ... + * } + * + * Example: + * + * properties: { + * // `foo` property can be assigned via attribute, will be deserialized to + * // the specified data-type. All `properties` properties have this behavior. + * foo: String, + * + * // `bar` property has additional behavior specifiers. + * // type: as above, type for (de-)serialization + * // notify: true to send a signal when a value is set to this property + * // reflectToAttribute: true to serialize the property to an attribute + * // readOnly: if true, the property has no setter + * bar: { + * type: Boolean, + * notify: true + * } + * } + * + * By itself the properties feature doesn't do anything but provide property + * information. Other features use this information to control behavior. + * + * The `type` information is used by the `attributes` feature to convert + * String values in attributes to typed properties. The `bind` feature uses + * property information to control property access. + * + * Marking a property as `notify` causes a change in the property to + * fire a non-bubbling event called `<property>-changed`. Elements that + * have enabled two-way binding to the property use this event to + * observe changes. + * + * `readOnly` properties have a getter, but no setter. To set a read-only + * property, use the private setter method `_set_<property>(value)`. + * + * @class base feature: properties + */ + + // null object + Polymer.nob = Object.create(null); + + Polymer.Base._addFeature({ + + properties: { + }, + + getPropertyInfo: function(property) { + var info = this._getPropertyInfo(property, this.properties); + if (!info) { + this.behaviors.some(function(b) { + return info = this._getPropertyInfo(property, b.properties); + }, this); + } + return info || Polymer.nob; + }, + + _getPropertyInfo: function(property, properties) { + var p = properties && properties[property]; + if (typeof(p) === 'function') { + p = properties[property] = { + type: p + }; + } + return p; + }, + + getPropertyType: function(property) { + return this.getPropertyInfo(property).type; + }, + + isReadOnlyProperty: function(property) { + return this.getPropertyInfo(property).readOnly; + }, + + isNotifyProperty: function(property) { + return this.getPropertyInfo(property).notify; + }, + + isReflectedProperty: function(property) { + return this.getPropertyInfo(property).reflectToAttribute; + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/micro/tag.html b/third_party/polymer/v0_8/components/polymer/src/micro/tag.html new file mode 100644 index 0000000..885a24d --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/micro/tag.html
@@ -0,0 +1,28 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Polymer.Base._addFeature({ + + _prepIs: function() { + if (!this.is) { + var module = + (document._currentScript || document.currentScript).parentNode; + if (module.localName === 'dom-module') { + var id = module.id || module.getAttribute('name') + || module.getAttribute('is') + this.is = id; + } + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/mini/ready.html b/third_party/polymer/v0_8/components/polymer/src/mini/ready.html new file mode 100644 index 0000000..1cd611bd --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/mini/ready.html
@@ -0,0 +1,152 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + /** + * Provides `ready` lifecycle callback which is called parent to child. + * + * This can be useful in a number of cases. Here are some examples: + * + * Setting a default property value that should have a side effect: To ensure + * the side effect, an element must set a default value no sooner than + * `created`; however, since `created` flows child to host, this is before the + * host has had a chance to set a property value on the child. The `ready` + * method solves this problem since it's called host to child. + * + * Dom distribution: To support reprojection efficiently, it's important to + * distribute from host to child in one shot. The `attachedCallback` mostly + * goes in the desired order except for elements that are in dom to start; in + * this case, all children are attached before the host element. Ready also + * addresses this case since it's guaranteed to be called host to child. + * + * @class standard feature: ready + */ + +(function() { + + var baseAttachedCallback = Polymer.Base.attachedCallback; + + Polymer.Base._addFeature({ + + hostStack: [], + + // for overriding + ready: function() { + }, + + // NOTE: The concept of 'host' is overloaded. There are two different + // notions: + // 1. an element hosts the elements in its local dom root. + // 2. an element hosts the elements on which it configures data. + // Practially, these notions are almost always coincident. + // Some special elements like templates may separate them. + // In order not to over-emphaisize this technical difference, we expose + // one concept to the user and it maps to the dom-related meaning of host. + // + // 1. set this element's `host` and push this element onto the `host`'s + // list of `client` elements + // 2. establish this element as the current hosting element (allows + // any elements we stamp to easily set host to us). + _pushHost: function(host) { + // NOTE: The `dataHost` of an element never changes. + this.dataHost = host = host || + Polymer.Base.hostStack[Polymer.Base.hostStack.length-1]; + // this.dataHost reflects the parent element who manages + // any bindings for the element. Only elements originally + // stamped from Polymer templates have a dataHost, and this + // never changes + if (host && host._clients) { + host._clients.push(this); + } + this._beginHost(); + }, + + _beginHost: function() { + Polymer.Base.hostStack.push(this); + if (!this._clients) { + this._clients = []; + } + }, + + _popHost: function() { + // this element is no longer the current hosting element + Polymer.Base.hostStack.pop(); + }, + + _tryReady: function() { + if (this._canReady()) { + this._ready(); + } + }, + + _canReady: function() { + return !this.dataHost || this.dataHost._clientsReadied; + }, + + _ready: function() { + // extension point + this._beforeClientsReady(); + this._readyClients(); + // extension point + this._afterClientsReady(); + this._readySelf(); + }, + + _readyClients: function() { + // prepare root + this._setupRoot(); + // logically distribute self + this._beginDistribute(); + // now fully prepare localChildren + var c$ = this._clients; + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + c._ready(); + } + // perform actual dom composition + this._finishDistribute(); + // ensure elements are attached if they are in the dom at ready time + // helps normalize attached ordering between native and polyfill ce. + // TODO(sorvell): worth perf cost? ~6% + // if (!Polymer.Settings.useNativeCustomElements) { + // CustomElements.takeRecords(); + // } + this._clientsReadied = true; + this._clients = null; + }, + + // mark readied and call `ready` + // note: called localChildren -> host + _readySelf: function() { + this._doBehavior('ready'); + this._readied = true; + if (this._attachedPending) { + this._attachedPending = false; + this.attachedCallback(); + } + }, + + // for system overriding + _beforeClientsReady: function() {}, + _afterClientsReady: function() {}, + + // normalize lifecycle: ensure attached occurs only after ready. + attachedCallback: function() { + if (this._readied) { + baseAttachedCallback.call(this); + } else { + this._attachedPending = true; + } + } + + }); + +})(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/mini/shadow.html b/third_party/polymer/v0_8/components/polymer/src/mini/shadow.html new file mode 100644 index 0000000..396de0a --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/mini/shadow.html
@@ -0,0 +1,41 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../lib/settings.html"> +<script> + + /** + Implements `shadyRoot` compatible dom scoping using native ShadowDOM. + */ + + // Transform styles if not using ShadowDOM or if flag is set. + + if (Polymer.Settings.useShadow) { + + Polymer.Base._addFeature({ + + // no-op's when ShadowDOM is in use + _poolContent: function() {}, + _beginDistribute: function() {}, + distributeContent: function() {}, + _distributeContent: function() {}, + _finishDistribute: function() {}, + + // create a shadowRoot + _createLocalRoot: function() { + this.createShadowRoot(); + this.shadowRoot.appendChild(this.root); + this.root = this.shadowRoot; + } + + }); + + } + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/mini/shady.html b/third_party/polymer/v0_8/components/polymer/src/mini/shady.html new file mode 100644 index 0000000..79b7829 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/mini/shady.html
@@ -0,0 +1,376 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../lib/array-splice.html"> +<link rel="import" href="../lib/dom-api.html"> +<script> + + (function() { + /** + + Implements a pared down version of ShadowDOM's scoping, which is easy to + polyfill across browsers. + + */ + Polymer.Base._addFeature({ + + _prepShady: function() { + // Use this system iff localDom is needed. + this._useContent = this._useContent || Boolean(this._template); + if (this._useContent) { + this._template._hasInsertionPoint = + this._template.content.querySelector('content'); + } + }, + + // called as part of content initialization, prior to template stamping + _poolContent: function() { + if (this._useContent) { + // capture lightChildren to help reify dom scoping + saveLightChildrenIfNeeded(this); + } + }, + + // called as part of content initialization, after template stamping + _setupRoot: function() { + if (this._useContent) { + this._createLocalRoot(); + } + }, + + _createLocalRoot: function() { + this.shadyRoot = this.root; + this.shadyRoot._distributionClean = false; + this.shadyRoot._isShadyRoot = true; + this.shadyRoot._dirtyRoots = []; + // capture insertion point list + // TODO(sorvell): it's faster to do this via native qSA than annotator. + this.shadyRoot._insertionPoints = this._template._hasInsertionPoint ? + this.shadyRoot.querySelectorAll('content') : []; + // save logical tree info for shadyRoot. + saveLightChildrenIfNeeded(this.shadyRoot); + this.shadyRoot.host = this; + }, + + /** + * Return the element whose local dom within which this element + * is contained. This is a shorthand for + * `Polymer.dom(this).getOwnerRoot().host`. + */ + get domHost() { + var root = Polymer.dom(this).getOwnerRoot(); + return root && root.host; + }, + + /** + * Force this element to distribute its children to its local dom. + * A user should call `distributeContent` if distribution has been + * invalidated due to changes to selectors on child elements that + * effect distribution. For example, if an element contains an + * insertion point with <content select=".foo"> and a `foo` class is + * added to a child, then `distributeContent` must be called to update + * local dom distribution. + */ + distributeContent: function() { + if (this._useContent) { + this.shadyRoot._distributionClean = false; + this._distributeContent(); + } + }, + + _distributeContent: function() { + if (this._useContent && !this.shadyRoot._distributionClean) { + // logically distribute self + this._beginDistribute(); + this._distributeDirtyRoots(); + this._finishDistribute(); + } + }, + + _beginDistribute: function() { + if (this._useContent && hasInsertionPoint(this.shadyRoot)) { + // reset distributions + this._resetDistribution(); + // compute which nodes should be distributed where + // TODO(jmesserly): this is simplified because we assume a single + // ShadowRoot per host and no `<shadow>`. + this._distributePool(this.shadyRoot, this._collectPool()); + } + }, + + _distributeDirtyRoots: function() { + var c$ = this.shadyRoot._dirtyRoots; + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + c._distributeContent(); + } + this.shadyRoot._dirtyRoots = []; + }, + + _finishDistribute: function() { + // compose self + if (this._useContent) { + if (hasInsertionPoint(this.shadyRoot)) { + this._composeTree(); + } else { + if (!this.shadyRoot._hasDistributed) { + this.textContent = ''; + this.appendChild(this.shadyRoot); + } else { + // simplified non-tree walk composition + var children = this._composeNode(this); + this._updateChildNodes(this, children); + } + } + this.shadyRoot._hasDistributed = true; + this.shadyRoot._distributionClean = true; + } + }, + + // This is a polyfill for Element.prototype.matches, which is sometimes + // still prefixed. Alternatively we could just polyfill it somewhere. + // Note that the arguments are reversed from what you might expect. + elementMatches: function(selector, node) { + if (node === undefined) { + node = this; + } + return matchesSelector.call(node, selector); + }, + + // Many of the following methods are all conceptually static, but they are + // included here as "protected" methods to allow overriding. + + _resetDistribution: function() { + // light children + var children = getLightChildren(this); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (child._destinationInsertionPoints) { + child._destinationInsertionPoints = undefined; + } + } + // insertion points + var root = this.shadyRoot; + var p$ = root._insertionPoints; + for (var j = 0; j < p$.length; j++) { + p$[j]._distributedNodes = []; + } + }, + + // Gather the pool of nodes that should be distributed. We will combine + // these with the "content root" to arrive at the composed tree. + _collectPool: function() { + var pool = []; + var children = getLightChildren(this); + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (isInsertionPoint(child)) { + pool.push.apply(pool, child._distributedNodes); + } else { + pool.push(child); + } + } + return pool; + }, + + // perform "logical" distribution; note, no actual dom is moved here, + // instead elements are distributed into a `content._distributedNodes` + // array where applicable. + _distributePool: function(node, pool) { + var p$ = node._insertionPoints; + for (var i=0, l=p$.length, p; (i<l) && (p=p$[i]); i++) { + this._distributeInsertionPoint(p, pool); + } + }, + + _distributeInsertionPoint: function(content, pool) { + // distribute nodes from the pool that this selector matches + var anyDistributed = false; + for (var i=0, l=pool.length, node; i < l; i++) { + node=pool[i]; + // skip nodes that were already used + if (!node) { + continue; + } + // distribute this node if it matches + if (this._matchesContentSelect(node, content)) { + distributeNodeInto(node, content); + // remove this node from the pool + pool[i] = undefined; + // since at least one node matched, we won't need fallback content + anyDistributed = true; + var parent = content.lightParent; + // dirty a shadyRoot if a change may trigger reprojection! + if (parent && parent.shadyRoot && + hasInsertionPoint(parent.shadyRoot)) { + parent.shadyRoot._distributionClean = false; + this.shadyRoot._dirtyRoots.push(parent); + } + } + } + // Fallback content if nothing was distributed here + if (!anyDistributed) { + var children = getLightChildren(content); + for (var j = 0; j < children.length; j++) { + distributeNodeInto(children[j], content); + } + } + }, + + // Reify dom such that it is at its correct rendering position + // based on logical distribution. + _composeTree: function() { + this._updateChildNodes(this, this._composeNode(this)); + var p$ = this.shadyRoot._insertionPoints; + for (var i=0, l=p$.length, p, parent; (i<l) && (p=p$[i]); i++) { + parent = p.lightParent || p.parentNode; + if (!parent._useContent && (parent !== this) && + (parent !== this.shadyRoot)) { + this._updateChildNodes(parent, this._composeNode(parent)); + } + } + }, + + // Returns the list of nodes which should be rendered inside `node`. + _composeNode: function(node) { + var children = []; + var c$ = getLightChildren(node.shadyRoot || node); + for (var i = 0; i < c$.length; i++) { + var child = c$[i]; + if (isInsertionPoint(child)) { + var distributedNodes = child._distributedNodes; + for (var j = 0; j < distributedNodes.length; j++) { + var distributedNode = distributedNodes[j]; + if (isFinalDestination(child, distributedNode)) { + children.push(distributedNode); + } + } + } else { + children.push(child); + } + } + return children; + }, + + // Ensures that the rendered node list inside `node` is `children`. + _updateChildNodes: function(node, children) { + var splices = + Polymer.ArraySplice.calculateSplices(children, node.childNodes); + for (var i=0; i<splices.length; i++) { + var s = splices[i]; + // remove + for (var j=0, c; j < s.removed.length; j++) { + c = s.removed[j]; + if (c.previousSibling == children[s.index-1]) { + remove(c); + } + } + // insert + for (var idx=s.index, ch, o; idx < s.index + s.addedCount; idx++) { + ch = children[idx]; + o = node.childNodes[idx]; + while (o && o === ch) { + o = o.nextSibling; + } + insertBefore(node, ch, o); + } + } + }, + + _matchesContentSelect: function(node, contentElement) { + var select = contentElement.getAttribute('select'); + // no selector matches all nodes (including text) + if (!select) { + return true; + } + select = select.trim(); + // same thing if it had only whitespace + if (!select) { + return true; + } + // selectors can only match Elements + if (!(node instanceof Element)) { + return false; + } + // only valid selectors can match: + // TypeSelector + // * + // ClassSelector + // IDSelector + // AttributeSelector + // negation + var validSelectors = /^(:not\()?[*.#[a-zA-Z_|]/; + if (!validSelectors.test(select)) { + return false; + } + return this.elementMatches(select, node); + }, + + // system override point + _elementAdd: function() {}, + + // system override point + _elementRemove: function() {} + + }); + + var saveLightChildrenIfNeeded = Polymer.DomApi.saveLightChildrenIfNeeded; + var getLightChildren = Polymer.DomApi.getLightChildren; + var matchesSelector = Polymer.DomApi.matchesSelector; + var hasInsertionPoint = Polymer.DomApi.hasInsertionPoint; + + function distributeNodeInto(child, insertionPoint) { + insertionPoint._distributedNodes.push(child); + var points = child._destinationInsertionPoints; + if (!points) { + child._destinationInsertionPoints = [insertionPoint]; + // TODO(sorvell): _destinationInsertionPoints may not be cleared when + // nodes are dynamically added/removed, therefore test before adding + // insertion points. + } else if (points.indexOf(insertionPoint) < 0) { + points.push(insertionPoint); + } + } + + function isFinalDestination(insertionPoint, node) { + var points = node._destinationInsertionPoints; + return points && points[points.length - 1] === insertionPoint; + } + + function isInsertionPoint(node) { + // TODO(jmesserly): we could add back 'shadow' support here. + return node.localName == 'content'; + } + + var nativeInsertBefore = Element.prototype.insertBefore; + var nativeRemoveChild = Element.prototype.removeChild; + + function insertBefore(parentNode, newChild, refChild) { + // remove child from its old parent first + remove(newChild); + // make sure we never lose logical DOM information: + // if the parentNode doesn't have lightChildren, save that information now. + saveLightChildrenIfNeeded(parentNode); + // insert it into the real DOM + nativeInsertBefore.call(parentNode, newChild, refChild || null); + } + + function remove(node) { + var parentNode = node.parentNode; + if (parentNode) { + // make sure we never lose logical DOM information: + // if the parentNode doesn't have lightChildren, save that information now. + saveLightChildrenIfNeeded(parentNode); + // remove it from the real DOM + nativeRemoveChild.call(parentNode, node); + } + } + + })(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/mini/template.html b/third_party/polymer/v0_8/components/polymer/src/mini/template.html new file mode 100644 index 0000000..41e1144 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/mini/template.html
@@ -0,0 +1,56 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + /** + * Automatic template management. + * + * The `template` feature locates and instances a `<template>` element + * corresponding to the current Polymer prototype. + * + * The `<template>` element may be immediately preceeding the script that + * invokes `Polymer()`. + * + * @class standard feature: template + */ + + Polymer.Base._addFeature({ + + _prepTemplate: function() { + // locate template using dom-module + this._template = + this._template || Polymer.DomModule.import(this.is, 'template'); + // fallback to look at the node previous to the currentScript. + if (!this._template) { + var script = document._currentScript || document.currentScript; + var prev = script && script.previousElementSibling; + if (prev && prev.localName === 'template') { + this._template = prev; + } + } + }, + + _stampTemplate: function() { + if (this._template) { + // note: root is now a fragment which can be manipulated + // while not attached to the element. + this.root = this.instanceTemplate(this._template); + } + }, + + instanceTemplate: function(template) { + var dom = + document.importNode(template._content || template.content, true); + return dom; + } + + }); + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/polymer-lib.html b/third_party/polymer/v0_8/components/polymer/src/polymer-lib.html new file mode 100644 index 0000000..078f1d35 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/polymer-lib.html
@@ -0,0 +1,15 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="lib/settings.html"> +<link rel="import" href="lib/polymer-bootstrap.html"> +<link rel="import" href="lib/lang.html"> +<link rel="import" href="lib/base.html"> +<link rel="import" href="lib/dom-module.html">
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/annotations.html b/third_party/polymer/v0_8/components/polymer/src/standard/annotations.html new file mode 100644 index 0000000..53690e5 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/annotations.html
@@ -0,0 +1,198 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<!-- employ 'Annotations' module --> + +<link rel="import" href="../lib/annotations/annotations.html"> +<link rel="import" href="../lib/resolve-url.html"> +<script> + +/** + * Scans a template to produce an annotation object that stores expression + * metadata along with information to associate the metadata with nodes in an + * instance. + * + * Elements with `id` in the template are noted and marshaled into an + * the `$` hash in an instance. + * + * Example + * + * <template> + * <div id="foo"></div> + * </template> + * <script> + * Polymer({ + * task: function() { + * this.$.foo.style.color = 'red'; + * } + * }); + * </script> + * + * Other expressions that are noted include: + * + * Double-mustache annotations in text content. The annotation must be the only + * content in the tag, compound expressions are not (currently) supported. + * + * <[tag]>{{path.to.host.property}}<[tag]> + * + * Double-mustache annotations in an attribute. + * + * <[tag] someAttribute="{{path.to.host.property}}"><[tag]> + * + * Only immediate host properties can automatically trigger side-effects. + * Setting `host.path` in the example above triggers the binding, setting + * `host.path.to.host.property` does not. + * + * `on-` style event declarations. + * + * <[tag] on-<event-name>="{{hostMethodName}}"><[tag]> + * + * Note: **the `annotations` feature does not actually implement the behaviors + * associated with these expressions, it only captures the data**. + * + * Other optional features contain actual data implementations. + * + * @class standard feature: annotations + */ + +/* + +Scans a template to produce an annotation map that stores expression metadata +and information that associates the metadata to nodes in a template instance. + +Supported annotations are: + + * id attributes + * binding annotations in text nodes + * double-mustache expressions: {{expression}} + * double-bracket expressions: [[expression]] + * binding annotations in attributes + * attribute-bind expressions: name="{{expression}} || [[expression]]" + * property-bind expressions: name*="{{expression}} || [[expression]]" + * property-bind expressions: name:="expression" + * event annotations + * event delegation directives: on-<eventName>="expression" + +Generated data-structure: + + [ + { + id: '<id>', + events: [ + { + mode: ['auto'|''], + name: '<name>' + value: '<expression>' + }, ... + ], + bindings: [ + { + kind: ['text'|'attribute'|'property'], + mode: ['auto'|''], + name: '<name>' + value: '<expression>' + }, ... + ], + // TODO(sjmiles): confusingly, this is annotation-parent, not node-parent + parent: <reference to parent annotation>, + index: <integer index in parent's childNodes collection> + }, + ... + ] + +TODO(sjmiles): this module should produce either syntactic metadata +(e.g. double-mustache, double-bracket, star-attr), or semantic metadata +(e.g. manual-bind, auto-bind, property-bind). Right now it's half and half. + +*/ + + Polymer.Base._addFeature({ + + // registration-time + + _prepAnnotations: function() { + if (!this._template) { + this._notes = []; + } else { + // TODO(sorvell): ad hoc method of plugging behavior into Annotations + Polymer.Annotations.prepElement = this._prepElement.bind(this); + this._notes = Polymer.Annotations.parseAnnotations(this._template); + Polymer.Annotations.prepElement = null; + } + }, + + _prepElement: function(element) { + Polymer.ResolveUrl.resolveAttrs(element, this._template.ownerDocument); + }, + + // instance-time + + findAnnotatedNode: Polymer.Annotations.findAnnotatedNode, + + // marshal all teh things + _marshalAnnotationReferences: function() { + if (this._template) { + this._marshalIdNodes(); + this._marshalAnnotatedNodes(); + this._marshalAnnotatedListeners(); + } + }, + + // push configuration references at configure time + _configureAnnotationReferences: function() { + this._configureTemplateContent(); + }, + + // nested template contents have been stored prototypically to avoid + // unnecessary duplication, here we put references to the + // indirected contents onto the nested template instances + _configureTemplateContent: function() { + this._notes.forEach(function(note) { + if (note.templateContent) { + var template = this.findAnnotatedNode(this.root, note); + template._content = note.templateContent; + } + }, this); + }, + + // construct `$` map (from id annotations) + _marshalIdNodes: function() { + this.$ = {}; + this._notes.forEach(function(a) { + if (a.id) { + this.$[a.id] = this.findAnnotatedNode(this.root, a); + } + }, this); + }, + + // concretize `_nodes` map (from anonymous annotations) + _marshalAnnotatedNodes: function() { + if (this._nodes) { + this._nodes = this._nodes.map(function(a) { + return this.findAnnotatedNode(this.root, a); + }, this); + } + }, + + // install event listeners (from event annotations) + _marshalAnnotatedListeners: function() { + this._notes.forEach(function(a) { + if (a.events && a.events.length) { + var node = this.findAnnotatedNode(this.root, a); + a.events.forEach(function(e) { + this.listen(node, e.name, e.value); + }, this); + } + }, this); + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/configure.html b/third_party/polymer/v0_8/components/polymer/src/standard/configure.html new file mode 100644 index 0000000..27af16d --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/configure.html
@@ -0,0 +1,184 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<script> + + /* + Process inputs efficiently via a configure lifecycle callback. + Configure is called top-down, host before local dom. Users should + implement configure to supply a set of default values for the element by + returning an object containing the properties and values to set. + + Configured values are not immediately set, instead they are set when + an element becomes ready, after its local dom is ready. This ensures + that any user change handlers are not called before ready time. + + */ + + /* + Implementation notes: + + Configured values are collected into _config. At ready time, properties + are set to the values in _config. This ensures properties are set child + before host and change handlers are called only at ready time. The host + will reset a value already propagated to a child, but this is not + inefficient because of dirty checking at the set point. + + Bind notification events are sent when properties are set at ready time + and thus received by the host before it is ready. Since notifications result + in property updates and this triggers side effects, handling notifications + is deferred until ready time. + + In general, events can be heard before an element is ready. This may occur + when a user sends an event in a change handler or listens to a data event + directly (on-foo-changed). + */ + + Polymer.Base._addFeature({ + + // storage for configuration + _setupConfigure: function(initialConfig) { + this._config = initialConfig || {}; + this._handlers = []; + }, + + // static attributes are deserialized into _config + _takeAttributes: function() { + this._takeAttributesToModel(this._config); + }, + + // at configure time values are stored in _config + _configValue: function(name, value) { + this._config[name] = value; + }, + + // Override polymer-mini thunk + _beforeClientsReady: function() { + this._configure(); + }, + + // configure: returns user supplied default property values + // combines with _config to create final property values + _configure: function() { + this._configureAnnotationReferences(); + // get individual default values from property configs + var config = {}; + this._configureProperties(this.properties, config); + // behave! + this.behaviors.forEach(function(b) { + this._configureProperties(b.properties, config); + }, this); + // get add'l default values from central configure + // combine defaults returned from configure with inputs in _config + this._mixinConfigure(config, this._config); + // this is the new _config, which are the final values to be applied + this._config = config; + // pass configuration data to bindings + this._distributeConfig(this._config); + }, + + _configureProperties: function(properties, config) { + for (i in properties) { + var c = properties[i]; + if (c.value !== undefined) { + var value = c.value; + if (typeof value == 'function') { + // pass existing config values (this._config) to value function + value = value.call(this, this._config); + } + config[i] = value; + } + } + }, + + _mixinConfigure: function(a, b) { + for (var prop in b) { + if (!this.isReadOnlyProperty(prop)) { + a[prop] = b[prop]; + } + } + }, + + // distribute config values to bound nodes. + _distributeConfig: function(config) { + var fx$ = this._propertyEffects; + if (fx$) { + for (var p in config) { + var fx = fx$[p]; + if (fx) { + for (var i=0, l=fx.length, x; (i<l) && (x=fx[i]); i++) { + if (x.kind === 'annotation') { + var node = this._nodes[x.effect.index]; + // seeding configuration only + if (node._configValue) { + var value = (p === x.effect.value) ? config[p] : + this.getPathValue(x.effect.value, config); + node._configValue(x.effect.name, value); + } + } + } + } + } + } + }, + + // Override polymer-mini thunk + _afterClientsReady: function() { + this._applyConfig(this._config); + this._flushHandlers(); + }, + + // NOTE: values are already propagated to children via + // _distributeConfig so propagation triggered by effects here is + // redundant, but safe due to dirty checking + _applyConfig: function(config) { + for (var n in config) { + // Don't stomp on values that may have been set by other side effects + if (this[n] === undefined) { + // Call _propertySet for any properties with accessors, which will + // initialize read-only properties also + // TODO(kschaaf): consider passing fromAbove here to prevent + // unnecessary notify for: 1) possible perf, 2) debuggability + var effects = this._propertyEffects[n]; + if (effects) { + this._propertySet(n, config[n], effects); + } else { + this[n] = config[n]; + } + } + } + }, + + // NOTE: Notifications can be processed before ready since + // they are sent at *child* ready time. Since notifications cause side + // effects and side effects must not be processed before ready time, + // handling is queue/defered until then. + _notifyListener: function(fn, e) { + if (!this._clientsReadied) { + this._queueHandler([fn, e, e.target]); + } else { + return fn.call(this, e, e.target); + } + }, + + _queueHandler: function(args) { + this._handlers.push(args); + }, + + _flushHandlers: function() { + var h$ = this._handlers; + for (var i=0, l=h$.length, h; (i<l) && (h=h$[i]); i++) { + h[0].call(this, h[1], h[2]); + } + } + + }); + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/effects.html b/third_party/polymer/v0_8/components/polymer/src/standard/effects.html new file mode 100644 index 0000000..c1459d0 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/effects.html
@@ -0,0 +1,211 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../lib/bind/accessors.html"> +<link rel="import" href="../lib/bind/effects.html"> + +<script> + + /** + * Support for property side effects. + * + * Key for effect objects: + * + * property | ann | anCmp | cmp | obs | cplxOb | description + * ---------|-----|-------|-----|-----|--------|---------------------------------------- + * method | | X | X | X | X | function name to call on instance + * args | | X | X | | X | list of all arg descriptors for fn + * arg | | X | X | | X | arg descriptor for effect + * property | | | X | X | | property for effect to set or get + * name | X | | | | | annotation value (text inside {{...}}) + * kind | X | X | | | | binding type (property or attribute) + * index | X | X | | | | node index to set + * + */ + + Polymer.Base._addFeature({ + + _addPropertyEffect: function(property, kind, effect) { + // TODO(sjmiles): everything to the right of the first '.' is lost, implies + // there is some duplicate information flow (not the only sign) + var model = property.split('.').shift(); + Polymer.Bind.addPropertyEffect(this, model, kind, effect); + }, + + // prototyping + + _prepEffects: function() { + Polymer.Bind.prepareModel(this); + this._addAnnotationEffects(this._notes); + }, + + _prepBindings: function() { + Polymer.Bind.createBindings(this); + }, + + _addPropertyEffects: function(effects) { + if (effects) { + for (var n in effects) { + var effect = effects[n]; + if (effect.observer) { + this._addObserverEffect(n, effect.observer); + } + if (effect.computed) { + this._addComputedEffect(n, effect.computed); + } + if (effect.notify) { + this._addPropertyEffect(n, 'notify'); + } + if (effect.reflectToAttribute) { + this._addPropertyEffect(n, 'reflect'); + } + if (this.isReadOnlyProperty(n)) { + // Ensure accessor is created + Polymer.Bind.ensurePropertyEffects(this, n); + } + } + } + }, + + _parseMethod: function(expression) { + var m = expression.match(/(\w*)\((.*)\)/); + if (m) { + return { + method: m[1], + args: m[2].split(/[^\w.*]+/).map(this._parseArg) + }; + } + }, + + _parseArg: function(arg) { + var a = { name: arg }; + a.structured = arg.indexOf('.') > 0; + if (a.structured) { + a.wildcard = (arg.slice(-2) == '.*'); + if (a.wildcard) { + a.name = arg.slice(0, -2); + } + } + return a; + }, + + _addComputedEffect: function(name, expression) { + var sig = this._parseMethod(expression); + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'compute', { + method: sig.method, + args: sig.args, + arg: arg, + property: name + }); + }, this); + }, + + _addObserverEffect: function(property, observer) { + this._addPropertyEffect(property, 'observer', { + method: observer, + property: property + }); + }, + + _addComplexObserverEffects: function(observers) { + if (observers) { + observers.forEach(function(observer) { + this._addComplexObserverEffect(observer); + }, this); + } + }, + + _addComplexObserverEffect: function(observer) { + var sig = this._parseMethod(observer); + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'complexObserver', { + method: sig.method, + args: sig.args, + arg: arg + }); + }, this); + }, + + _addAnnotationEffects: function(notes) { + // create a virtual annotation list, must be concretized at instance time + this._nodes = []; + // process annotations that have been parsed from template + notes.forEach(function(note) { + // where to find the node in the concretized list + var index = this._nodes.push(note) - 1; + note.bindings.forEach(function(binding) { + this._addAnnotationEffect(binding, index); + }, this); + }, this); + }, + + _addAnnotationEffect: function(note, index) { + // TODO(sjmiles): annotations have 'effects' proper and 'listener' + if (Polymer.Bind._shouldAddListener(note)) { + // <node>.on.<dash-case-property>-changed: <path> = e.detail.value + Polymer.Bind._addAnnotatedListener(this, index, + note.name, note.value, note.event); + } + var sig = this._parseMethod(note.value); + if (sig) { + this._addAnnotatedComputationEffect(sig, note, index); + } else { + // capture the node index + note.index = index; + // discover top-level property (model) from path + var model = note.value.split('.').shift(); + // add 'annotation' binding effect for property 'model' + this._addPropertyEffect(model, 'annotation', note); + } + }, + + _addAnnotatedComputationEffect: function(sig, note, index) { + sig.args.forEach(function(arg) { + this._addPropertyEffect(arg.name, 'annotatedComputation', { + kind: note.kind, + method: sig.method, + args: sig.args, + arg: arg, + property: note.name, + index: index + }); + }, this); + }, + + // instancing + + _marshalInstanceEffects: function() { + Polymer.Bind.prepareInstance(this); + Polymer.Bind.setupBindListeners(this); + }, + + _applyEffectValue: function(value, info) { + var node = this._nodes[info.index]; + // TODO(sorvell): ideally, the info object is normalized for easy + // lookup here. + var property = info.property || info.name || 'textContent'; + // special processing for 'class' and 'className'; 'class' handled + // when attr is serialized. + if (info.kind == 'attribute') { + this.serializeValueToAttribute(value, property, node); + } else { + // TODO(sorvell): consider pre-processing this step so we don't need + // this lookup. + if (property === 'className') { + value = this._scopeElementClass(node, value); + } + return node[property] = value; + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/events.html b/third_party/polymer/v0_8/components/polymer/src/standard/events.html new file mode 100644 index 0000000..97deff87 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/events.html
@@ -0,0 +1,97 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../lib/gestures.html"> + +<script> + + /** + * Supports `listeners` and `keyPresses` objects. + * + * Example: + * + * using('Base', function(Base) { + * + * Polymer({ + * + * listeners: { + * // `click` events on the host are delegated to `clickHandler` + * 'click': 'clickHandler' + * }, + * + * keyPresses: { + * // 'ESC' key presses are delegated to `escHandler` + * Base.ESC_KEY: 'escHandler' + * }, + * + * ... + * + * }); + * + * }); + * + * @class standard feature: events + * + */ + + Polymer.Base._addFeature({ + + listeners: {}, + + _listenListeners: function(listeners) { + var node, name, key; + for (key in listeners) { + if (key.indexOf('.') < 0) { + node = this; + name = key; + } else { + name = key.split('.'); + node = this.$[name[0]]; + name = name[1]; + } + this.listen(node, name, listeners[key]); + } + }, + + listen: function(node, eventName, methodName) { + var host = this; + var handler = function(e) { + if (host[methodName]) { + host[methodName](e, e.detail); + } else { + console.warn('[%s].[%s]: event handler [%s] is null in scope (%o)', + node.localName, eventName, methodName, host); + } + }; + switch (eventName) { + case 'tap': + case 'track': + Polymer.Gestures.add(eventName, node, handler); + break; + + default: + node.addEventListener(eventName, handler); + break; + } + }, + + keyCodes: { + ESC_KEY: 27, + ENTER_KEY: 13, + LEFT: 37, + UP: 38, + RIGHT: 39, + DOWN: 40, + SPACE: 32 + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/notify-path.html b/third_party/polymer/v0_8/components/polymer/src/standard/notify-path.html new file mode 100644 index 0000000..574f75fe --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/notify-path.html
@@ -0,0 +1,251 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../lib/case-map.html"> +<script> + + /** + * Changes to an object sub-field (aka "path") via a binding + * (e.g. `<x-foo value="{{item.subfield}}"`) will notify other elements bound to + * the same object automatically. + * + * When modifying a sub-field of an object imperatively + * (e.g. `this.item.subfield = 42`), in order to have the new value propagated + * to other elements, a special `setPathValue(path, value)` API is provided. + * `setPathValue` sets the object field at the path specified, and then notifies the + * binding system so that other elements bound to the same path will update. + * + * Example: + * + * Polymer({ + * + * is: 'x-date', + * + * properties: { + * date: { + * type: Object, + * notify: true + * } + * }, + * + * attached: function() { + * this.date = {}; + * setInterval(function() { + * var d = new Date(); + * // Required to notify elements bound to date of changes to sub-fields + * // this.date.seconds = d.getSeconds(); <-- Will not notify + * this.setPathValue('date.seconds', d.getSeconds()); + * this.setPathValue('date.minutes', d.getMinutes()); + * this.setPathValue('date.hours', d.getHours() % 12); + * }.bind(this), 1000); + * } + * + * }); + * + * Allows bindings to `date` sub-fields to update on changes: + * + * <x-date date="{{date}}"></x-date> + * + * Hour: <span>{{date.hours}}</span> + * Min: <span>{{date.minutes}}</span> + * Sec: <span>{{date.seconds}}</span> + * + * @class data feature: path notification + */ + + Polymer.Base._addFeature({ + /** + Notify that a path has changed. For example: + + this.item.user.name = 'Bob'; + this.notifyPath('item.user.name', this.item.user.name); + + Returns true if notification actually took place, based on + a dirty check of whether the new value was already known + */ + notifyPath: function(path, value, fromAbove) { + var old = this._propertySet(path, value); + // manual dirty checking for now... + if (old !== value) { + // console.group((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value); + // Take path effects at this level for exact path matches, + // and notify down for any bindings to a subset of this path + this._pathEffector(path, value); + // Send event to notify the path change upwards + // Optimization: don't notify up if we know the notification + // is coming from above already (avoid wasted event dispatch) + if (!fromAbove) { + // TODO(sorvell): should only notify if notify: true? + this._notifyPath(path, value); + } + // console.groupEnd((this.localName || this.dataHost.id + '-' + this.dataHost.dataHost.index) + '#' + (this.id || this.index) + ' ' + path, value); + } + }, + + /** + Convienence method for setting a value to a path and calling + notify path + */ + setPathValue: function(path, value) { + var parts = path.split('.'); + if (parts.length > 1) { + var last = parts.pop(); + var prop = this; + while (parts.length) { + prop = prop[parts.shift()]; + if (!prop) { + return; + } + } + // TODO(kschaaf): want dirty-check here? + // if (prop[last] !== value) { + prop[last] = value; + this.notifyPath(path, value); + // } + } else { + this[path] = value; + } + }, + + getPathValue: function(path, root) { + var parts = path.split('.'); + var last = parts.pop(); + var prop = root || this; + while (parts.length) { + prop = prop[parts.shift()]; + if (!prop) { + return; + } + } + return prop[last]; + }, + + // TODO(kschaaf): This machine can be optimized to memoize compiled path + // effectors as new paths are notified for performance, since it involves + // a fair amount of runtime lookup + _pathEffector: function(path, value) { + // get root property + var model = this._modelForPath(path); + // search property effects of the root property for 'annotation' effects + var fx$ = this._propertyEffects[model]; + if (fx$) { + fx$.forEach(function(fx) { + var fxFn = this[fx.kind + 'PathEffect']; + if (fxFn) { + fxFn.call(this, path, value, fx.effect); + } + }, this); + } + // notify runtime-bound paths + if (this._boundPaths) { + this._notifyBoundPaths(path, value); + } + }, + + annotationPathEffect: function(path, value, effect) { + if (effect.value === path || effect.value.indexOf(path + '.') === 0) { + // TODO(sorvell): ideally the effect function is on this prototype + // so we don't have to call it like this. + Polymer.Bind.annotationEffect.call(this, path, value, effect); + } else if ((path.indexOf(effect.value + '.') === 0) && !effect.negate) { + // locate the bound node + var node = this._nodes[effect.index]; + if (node && node.notifyPath) { + var p = this._fixPath(effect.name , effect.value, path); + node.notifyPath(p, value, true); + } + } + }, + + complexObserverPathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.complexObserverEffect.call(this, path, value, effect); + } + }, + + computePathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.computeEffect.call(this, path, value, effect); + } + }, + + annotatedComputationPathEffect: function(path, value, effect) { + if (this._pathMatchesEffect(path, effect)) { + Polymer.Bind.annotatedComputationEffect.call(this, path, value, effect); + } + }, + + _pathMatchesEffect: function(path, effect) { + var effectArg = effect.arg.name; + return (effectArg == path) || + (effectArg.indexOf(path + '.') === 0) || + (effect.arg.wildcard && path.indexOf(effectArg) === 0); + }, + + bindPaths: function(to, from) { + this._boundPaths = this._boundPaths || {}; + if (from) { + this._boundPaths[to] = from; + // this.setPathValue(to, this.getPathValue(from)); + } else { + this.unbindPath(to); + // this.setPathValue(to, from); + } + }, + + unbindPaths: function(path) { + if (this._boundPaths) { + delete this._boundPaths[path]; + } + }, + + _notifyBoundPaths: function(path, value) { + var from, to; + for (var a in this._boundPaths) { + var b = this._boundPaths[a]; + if (path.indexOf(a + '.') == 0) { + from = a; + to = b; + break; + } + if (path.indexOf(b + '.') == 0) { + from = b; + to = a; + break; + } + } + if (from && to) { + var p = this._fixPath(to, from, path); + this.notifyPath(p, value); + } + }, + + _fixPath: function(property, root, path) { + return property + path.slice(root.length); + }, + + _notifyPath: function(path, value) { + var rootName = this._modelForPath(path); + var dashCaseName = Polymer.CaseMap.camelToDashCase(rootName); + var eventName = dashCaseName + this._EVENT_CHANGED; + this.fire(eventName, { + path: path, + value: value + }, {bubbles: false}); + }, + + _modelForPath: function(path) { + return path.split('.').shift(); + }, + + _EVENT_CHANGED: '-changed', + + }); + +</script> \ No newline at end of file
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/resolveUrl.html b/third_party/polymer/v0_8/components/polymer/src/standard/resolveUrl.html new file mode 100644 index 0000000..5e0caf5f --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/resolveUrl.html
@@ -0,0 +1,27 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<script> + + Polymer.Base._addFeature({ + + resolveUrl: function(url) { + // TODO(sorvell): do we want to put the module reference on the prototype? + var module = Polymer.DomModule.import(this.is); + var root = ''; + if (module) { + var assetPath = module.getAttribute('assetpath') || ''; + root = Polymer.ResolveUrl.resolveUrl(assetPath, module.ownerDocument.baseURI); + } + return Polymer.ResolveUrl.resolveUrl(url, root); + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/styling.html b/third_party/polymer/v0_8/components/polymer/src/standard/styling.html new file mode 100644 index 0000000..13b1b1b --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/styling.html
@@ -0,0 +1,195 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../lib/style-util.html"> +<link rel="import" href="../lib/resolve-url.html"> +<link rel="import" href="../lib/style-transformer.html"> +<link rel="import" href="../lib/settings.html"> + +<script> + + (function() { + + var prepTemplate = Polymer.Base._prepTemplate; + var prepElement = Polymer.Base._prepElement; + var baseStampTemplate = Polymer.Base._stampTemplate; + var nativeShadow = Polymer.Settings.useNativeShadow; + + Polymer.Base._addFeature({ + + // declaration-y + _prepTemplate: function() { + prepTemplate.call(this); + var port = Polymer.DomModule.import(this.is); + if (this._encapsulateStyle === undefined) { + this._encapsulateStyle = + Boolean(port && !nativeShadow); + } + // scope css + // NOTE: dom scoped via annotations + if (nativeShadow || this._encapsulateStyle) { + this._scopeCss(); + } + }, + + _prepElement: function(element) { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.element(element, this.is, + this._scopeCssViaAttr); + } + prepElement.call(this, element); + }, + + _scopeCss: function() { + this._styles = this._prepareStyles(); + this._scopeStyles(this._styles); + }, + + // search for extra style modules via `styleModules` + _prepareStyles: function() { + var cssText = '', m$ = this.styleModules; + if (m$) { + for (var i=0, l=m$.length, m; (i<l) && (m=m$[i]); i++) { + cssText += this._cssFromModule(m); + } + } + cssText += this._cssFromModule(this.is); + var styles = []; + if (cssText) { + var s = document.createElement('style'); + s.textContent = cssText; + styles.push(s); + } + return styles; + }, + + // returns cssText of styles in a given module; also un-applies any + // styles that apply to the document. + _cssFromModule: function(moduleId) { + var m = Polymer.DomModule.import(moduleId); + if (m && !m._cssText) { + var cssText = ''; + var e$ = Array.prototype.slice.call(m.querySelectorAll('style')); + this._unapplyStyles(e$); + e$ = e$.concat(Array.prototype.map.call( + m.querySelectorAll(REMOTE_SHEET_SELECTOR), function(l) { + return l.import.body; + })); + m._cssText = this._cssFromStyles(e$); + } + return m && m._cssText || ''; + }, + + _cssFromStyles: function(styles) { + var cssText = ''; + for (var i=0, l=styles.length, s; (i<l) && (s = styles[i]); i++) { + if (s && s.textContent) { + cssText += + Polymer.ResolveUrl.resolveCss(s.textContent, s.ownerDocument); + } + } + return cssText; + }, + + _unapplyStyles: function(styles) { + for (var i=0, l=styles.length, s; (i<l) && (s = styles[i]); i++) { + s = s.__appliedElement || s; + s.parentNode.removeChild(s); + } + }, + + _scopeStyles: function(styles) { + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + // transform style if necessary and place in correct place + if (nativeShadow) { + if (this._template) { + this._template.content.appendChild(s); + } + } else { + var rules = this._rulesForStyle(s); + Polymer.StyleUtil.applyCss( + Polymer.StyleTransformer.css(rules, this.is, this.extends, + null, this._scopeCssViaAttr), + this.is, null, true); + } + } + }, + + _rulesForStyle: function(style) { + if (!style.__cssRules) { + style.__cssRules = Polymer.StyleUtil.parser.parse(style.textContent); + } + return style.__cssRules; + }, + + // instance-y + _stampTemplate: function() { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.host(this, this.is); + } + baseStampTemplate.call(this); + }, + + // add scoping class whenever an element is added to localDOM + _elementAdd: function(node) { + if (this._encapsulateStyle && !node.__styleScoped) { + Polymer.StyleTransformer.dom(node, this.is, this._scopeCssViaAttr); + } + }, + + // remove scoping class whenever an element is removed from localDOM + _elementRemove: function(node) { + if (this._encapsulateStyle) { + Polymer.StyleTransformer.dom(node, this.is, this._scopeCssViaAttr, true); + } + }, + + /** + * Apply style scoping to the specified `container` and all its + * descendants. If `shoudlObserve` is true, changes to the container are + * monitored via mutation observer and scoping is applied. + */ + scopeSubtree: function(container, shouldObserve) { + if (nativeShadow) { + return; + } + var self = this; + var scopify = function(node) { + if (node.nodeType === Node.ELEMENT_NODE) { + node.className = self._scopeElementClass(node, node.className); + var n$ = node.querySelectorAll('*'); + Array.prototype.forEach.call(n$, function(n) { + n.className = self._scopeElementClass(n, n.className); + }); + } + }; + scopify(container); + if (shouldObserve) { + var mo = new MutationObserver(function(mxns) { + mxns.forEach(function(m) { + if (m.addedNodes) { + for (var i=0; i < m.addedNodes.length; i++) { + scopify(m.addedNodes[i]); + } + } + }); + }); + mo.observe(container, {childList: true, subtree: true}); + return mo; + } + } + + }); + + var REMOTE_SHEET_SELECTOR = 'link[rel=import][type~=css]'; + + })(); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/utils.html b/third_party/polymer/v0_8/components/polymer/src/standard/utils.html new file mode 100644 index 0000000..0374fc0b --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/utils.html
@@ -0,0 +1,137 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> + +<link rel="import" href="../lib/async.html"> +<link rel="import" href="../lib/debounce.html"> + +<script> + + Polymer.Base._addFeature({ + + $$: function(slctr) { + return Polymer.dom(this.root).querySelector(slctr); + }, + + toggleClass: function(name, bool, node) { + node = node || this; + if (arguments.length == 1) { + bool = !node.classList.contains(name); + } + if (bool) { + node.classList.add(name); + } else { + node.classList.remove(name); + } + }, + + toggleAttribute: function(name, bool, node) { + (node || this)[bool ? 'setAttribute' : 'removeAttribute'](name, ''); + }, + + classFollows: function(className, neo, old) { + if (old) { + old.classList.remove(className); + } + if (neo) { + neo.classList.add(className); + } + }, + + attributeFollows: function(name, neo, old) { + if (old) { + old.removeAttribute(name); + } + if (neo) { + neo.setAttribute(name, ''); + } + }, + + getContentChildNodes: function(slctr) { + return Polymer.dom(Polymer.dom(this.root).querySelector( + slctr || 'content')).getDistributedNodes(); + }, + + getContentChildren: function(slctr) { + return this.getContentChildNodes(slctr).filter(function(n) { + return (n.nodeType === Node.ELEMENT_NODE); + }); + }, + + fire: function(type, detail, options) { + options = options || Polymer.nob; + var node = options.node || this; + var detail = (detail === null || detail === undefined) ? Polymer.nob : detail; + var bubbles = options.bubbles === undefined ? true : options.bubbles; + var event = new CustomEvent(type, { + bubbles: Boolean(bubbles), + cancelable: Boolean(options.cancelable), + detail: detail + }); + node.dispatchEvent(event); + return event; + }, + + async: function(method, waitTime) { + return Polymer.Async.run(method.bind(this), waitTime); + }, + + cancelAsync: function(handle) { + Polymer.Async.cancel(handle); + }, + + arrayDelete: function(array, item) { + var index = array.indexOf(item); + if (index >= 0) { + return array.splice(index, 1); + } + }, + + transform: function(node, transform) { + node.style.webkitTransform = transform; + node.style.transform = transform; + }, + + translate3d: function(node, x, y, z) { + this.transform(node, 'translate3d(' + x + ',' + y + ',' + z + ')'); + }, + + importHref: function(href, onload, onerror) { + var l = document.createElement('link'); + l.rel = 'import'; + l.href = href; + if (onload) { + l.onload = onload.bind(this); + } + if (onerror) { + l.onerror = onerror.bind(this); + } + document.head.appendChild(l); + return l; + }, + + create: function(tag, props) { + var elt = document.createElement(tag); + if (props) { + for (var n in props) { + elt[n] = props[n]; + } + } + return elt; + }, + + simpleMixin: function(a, b) { + for (var i in b) { + a[i] = b[i]; + } + } + + }); + +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/src/standard/x-styling.html b/third_party/polymer/v0_8/components/polymer/src/standard/x-styling.html new file mode 100644 index 0000000..fef7cb26 --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/src/standard/x-styling.html
@@ -0,0 +1,364 @@ +<!-- +@license +Copyright (c) 2014 The Polymer Project Authors. All rights reserved. +This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt +The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt +The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt +Code distributed by Google as part of the polymer project is also +subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt +--> +<link rel="import" href="../lib/style-util.html"> +<link rel="import" href="../lib/style-transformer.html"> +<link rel="import" href="../lib/settings.html"> +<link rel="import" href="../lib/style-defaults.html"> +<script> + (function() { + + var baseAttachedCallback = Polymer.Base.attachedCallback; + var baseSerializeValueToAttribute = Polymer.Base.serializeValueToAttribute; + + var nativeShadow = Polymer.Settings.useNativeShadow; + + // TODO(sorvell): consider if calculating properties and applying + // styles with properties should be separate modules. + Polymer.Base._addFeature({ + + attachedCallback: function() { + baseAttachedCallback.call(this); + if (!this._xScopeSelector) { + this._updateOwnStyles(); + } + }, + + _updateOwnStyles: function() { + if (this.enableCustomStyleProperties) { + this._styleProperties = this._computeStyleProperties(); + this._applyStyleProperties(this._styleProperties); + } + }, + + _computeStyleProperties: function() { + var props = {}; + this.simpleMixin(props, this._computeStylePropertiesFromHost()); + this.simpleMixin(props, this._computeOwnStyleProperties()); + this._reifyCustomProperties(props); + return props; + }, + + _computeStylePropertiesFromHost: function() { + // TODO(sorvell): experimental feature, global defaults! + var props = {}, styles = [Polymer.StyleDefaults.defaultSheet]; + var host = this.domHost; + if (host) { + // enable finding styles in hosts without `enableStyleCustomProperties` + if (!host._styleProperties) { + host._styleProperties = host._computeStyleProperties(); + } + props = Object.create(host._styleProperties); + styles = host._styles; + } + this.simpleMixin(props, + this._customPropertiesFromStyles(styles, host)); + return props; + + }, + + _computeOwnStyleProperties: function() { + var props = {}; + this.simpleMixin(props, this._customPropertiesFromStyles(this._styles)); + if (this.styleProperties) { + for (var i in this.styleProperties) { + props[i] = this.styleProperties[i]; + } + } + return props; + }, + + _customPropertiesFromStyles: function(styles, hostNode) { + var props = {}; + var p = this._customPropertiesFromRule.bind(this, props, hostNode); + if (styles) { + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + Polymer.StyleUtil.forEachStyleRule(this._rulesForStyle(s), p); + } + } + return props; + }, + + // test if a rule matches the given node and if so, + // collect any custom properties + // TODO(sorvell): support custom variable assignment within mixins + _customPropertiesFromRule: function(props, hostNode, rule) { + hostNode = hostNode || this; + // TODO(sorvell): file crbug, ':host' does not match element. + if (this.elementMatches(rule.selector) || + ((hostNode === this) && (rule.selector === ':host'))) { + // --g: var(--b); or --g: 5; + this._collectPropertiesFromRule(rule, CUSTOM_VAR_ASSIGN, props); + // --g: { ... } + this._collectPropertiesFromRule(rule, CUSTOM_MIXIN_ASSIGN, props); + } + }, + + // given a rule and rx that matches key and value, set key in properties + // to value + _collectPropertiesFromRule: function(rule, rx, properties) { + var m; + while (m = rx.exec(rule.cssText)) { + properties[m[1]] = m[2].trim(); + } + }, + + _reifyCustomProperties: function(props) { + for (var i in props) { + props[i] = this._valueForCustomProperty(props[i], props); + } + }, + + _valueForCustomProperty: function(property, props) { + var cv; + while ((typeof property === 'string') && + (cv = property.match(CUSTOM_VAR_VALUE))) { + property = props[cv[1]]; + } + return property; + }, + + // apply styles + _applyStyleProperties: function(bag) { + var s$ = this._styles; + if (s$) { + var style = styleFromCache(this.is, bag, s$); + var old = this._xScopeSelector; + this._ensureScopeSelector(style ? style._scope : null); + if (!style) { + var cssText = this._generateCustomStyleCss(bag, s$); + style = cssText ? this._applyCustomCss(cssText) : {}; + cacheStyle(this.is, style, this._xScopeSelector, + this._styleProperties, s$); + } else if (nativeShadow) { + this._applyCustomCss(style.textContent); + } + if (style.textContent || old /*&& !nativeShadow*/) { + this._applyXScopeSelector(this._xScopeSelector, old); + } + } + }, + + _applyXScopeSelector: function(selector, old) { + var c = this._scopeCssViaAttr ? this.getAttribute(SCOPE_NAME) : + this.className; + v = old ? c.replace(old, selector) : + (c ? c + ' ' : '') + XSCOPE_NAME + ' ' + selector; + if (c !== v) { + if (this._scopeCssViaAttr) { + this.setAttribute(SCOPE_NAME, v); + } else { + this.className = v; + } + } + }, + + _generateCustomStyleCss: function(properties, styles) { + var b = this._applyPropertiesToRule.bind(this, properties); + var cssText = ''; + // TODO(sorvell): don't redo parsing work each time as below; + // instead create a sheet with just custom properties + for (var i=0, l=styles.length, s; (i<l) && (s=styles[i]); i++) { + cssText += this._transformCss(s.textContent, b) + '\n\n'; + } + return cssText.trim(); + }, + + _transformCss: function(cssText, callback) { + return nativeShadow ? + Polymer.StyleUtil.toCssText(cssText, callback) : + Polymer.StyleTransformer.css(cssText, this.is, this.extends, callback, + this._scopeCssViaAttr); + }, + + _xScopeCount: 0, + + _ensureScopeSelector: function(selector) { + selector = selector || (this.is + '-' + + (Object.getPrototypeOf(this)._xScopeCount++)); + this._xScopeSelector = selector; + }, + + _applyCustomCss: function(cssText) { + if (this._customStyle) { + this._customStyle.textContent = cssText; + } else if (cssText) { + this._customStyle = Polymer.StyleUtil.applyCss(cssText, + this._xScopeSelector, + nativeShadow ? this.root : null); + } + return this._customStyle; + }, + + _applyPropertiesToRule: function(properties, rule) { + if (!nativeShadow) { + this._scopifyRule(rule); + } + if (rule.cssText.match(CUSTOM_RULE_RX)) { + rule.cssText = this._applyPropertiesToText(rule.cssText, properties); + } else { + rule.cssText = ''; + } + //console.log(rule.cssText); + }, + + _applyPropertiesToText: function(cssText, props) { + var output = ''; + var m, v; + // e.g. color: var(--color); + while (m = CUSTOM_VAR_USE.exec(cssText)) { + v = props[m[2]]; + if (v) { + output += '\t' + m[1].trim() + ': ' + this._propertyToCss(v); + } + } + // e.g. @mixin(--stuff); + while (m = CUSTOM_MIXIN_USE.exec(cssText)) { + v = m[1]; + if (v) { + var parts = v.split(' '); + for (var i=0, p; i < parts.length; i++) { + p = props[parts[i].trim()]; + if (p) { + output += '\t' + this._propertyToCss(p); + } + } + } + } + return output; + }, + + _propertyToCss: function(property) { + var p = property.trim(); + p = p[p.length-1] === ';' ? p : p + ';'; + return p + '\n'; + }, + + // Strategy: x scope shim a selector e.g. to scope `.x-foo-42` (via classes): + // non-host selector: .a.x-foo -> .x-foo-42 .a.x-foo + // host selector: x-foo.wide -> x-foo.x-foo-42.wide + _scopifyRule: function(rule) { + var selector = rule.selector; + var host = this.is; + var rx = new RegExp(HOST_SELECTOR_PREFIX + host + HOST_SELECTOR_SUFFIX); + var parts = selector.split(','); + var scope = this._scopeCssViaAttr ? + SCOPE_PREFIX + this._xScopeSelector + SCOPE_SUFFIX : + '.' + this._xScopeSelector; + for (var i=0, l=parts.length, p; (i<l) && (p=parts[i]); i++) { + parts[i] = p.match(rx) ? + p.replace(host, host + scope) : + scope + ' ' + p; + } + rule.selector = parts.join(','); + }, + + _scopeElementClass: function(element, selector) { + if (!nativeShadow && !this._scopeCssViaAttr) { + selector += (selector ? ' ' : '') + SCOPE_NAME + ' ' + this.is + + (element._xScopeSelector ? ' ' + XSCOPE_NAME + ' ' + + element._xScopeSelector : ''); + } + return selector; + }, + + // override to ensure whenever classes are set, we need to shim them. + serializeValueToAttribute: function(value, attribute, node) { + if (attribute === 'class') { + // host needed to scope styling. + var host = node === this ? + Polymer.dom(this).getOwnerRoot() || this.dataHost : + this; + if (host) { + value = host._scopeElementClass(node, value); + } + } + baseSerializeValueToAttribute.call(this, value, attribute, node); + }, + + updateStyles: function() { + this._updateOwnStyles(); + this._updateRootStyles(this.root); + }, + + updateHostStyles: function() { + var host = Polymer.dom(this).getOwnerRoot() || this.dataHost; + if (host) { + host.updateStyles(); + } else { + this._updateRootStyles(document); + } + }, + + _updateRootStyles: function(root) { + // TODO(sorvell): temporary way to find local dom that needs + // x-scope styling. + var scopeSelector = this._scopeCssViaAttr ? + '[' + SCOPE_NAME + '~=' + XSCOPE_NAME + ']' : '.' + XSCOPE_NAME; + var c$ = Polymer.dom(root).querySelectorAll(scopeSelector); + for (var i=0, l= c$.length, c; (i<l) && (c=c$[i]); i++) { + if (c.updateStyles) { + c.updateStyles(); + } + } + } + + }); + + var styleCache = {}; + function cacheStyle(is, style, scope, bag, styles) { + style._scope = scope; + style._properties = bag; + style._styles = styles; + var s$ = styleCache[is] = styleCache[is] || []; + s$.push(style); + } + + function styleFromCache(is, bag, checkStyles) { + var styles = styleCache[is]; + if (styles) { + for (var i=0, s; i < styles.length; i++) { + s = styles[i]; + if (objectsEqual(bag, s._properties) && + objectsEqual(checkStyles, s._styles)) { + return s; + } + } + } + } + + function objectsEqual(a, b) { + for (var i in a) { + if (a[i] !== b[i]) { + return false; + } + } + for (var i in b) { + if (a[i] !== b[i]) { + return false; + } + } + return true; + } + + var SCOPE_NAME= Polymer.StyleTransformer.SCOPE_NAME; + var XSCOPE_NAME = 'x-scope'; + var SCOPE_PREFIX = '[' + SCOPE_NAME + '~='; + var SCOPE_SUFFIX = ']'; + var HOST_SELECTOR_PREFIX = '(?:^|[^.])'; + var HOST_SELECTOR_SUFFIX = '($|[.:[\\s>+~])'; + var CUSTOM_RULE_RX = /mixin|var/; + var CUSTOM_VAR_ASSIGN = /(--[^\:;]*?):\s*?([^;{]*?);/g; + var CUSTOM_MIXIN_ASSIGN = /(--[^\:;]*?):[^{;]*?{([^}]*?)}/g; + var CUSTOM_VAR_VALUE = /^var\(([^)]*?)\)/; + var CUSTOM_VAR_USE = /(?:^|[;}\s])([^;{}]*?):[\s]*?var\(([^)]*)?\)/gim; + var CUSTOM_MIXIN_USE = /mixin\(([^)]*)\)/gim; + + })(); +</script>
diff --git a/third_party/polymer/v0_8/components/polymer/wct.conf.js b/third_party/polymer/v0_8/components/polymer/wct.conf.js new file mode 100644 index 0000000..111deea --- /dev/null +++ b/third_party/polymer/v0_8/components/polymer/wct.conf.js
@@ -0,0 +1,3 @@ +module.exports = { + suites: ['test/runner.html'], +};
diff --git a/third_party/polymer/v0_8/extract_inline_scripts.sh b/third_party/polymer/v0_8/extract_inline_scripts.sh new file mode 100755 index 0000000..91fc6ea --- /dev/null +++ b/third_party/polymer/v0_8/extract_inline_scripts.sh
@@ -0,0 +1,49 @@ +#!/bin/bash + +# 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. + +set -e + +if [ "$#" -ne 2 ] +then + echo "Usage: $0 <src_dir> <dst_dir>" + echo + echo "Copies <src_dir> to <dst_dir> and extracts all inline scripts from" \ + "Polymer HTML files found in the destination directory to separate JS" \ + "files. A JS file extracted from the file with name 'foo.html' will" \ + "have a name 'foo-extracted.js'. Inclusion of the script file will be" \ + "added to 'foo.html': '<script src=\"foo-extracted.js\"></script>'." + exit 1 +fi + +src="$1" +dst="$2" + +if [ -e "$dst" ] +then + echo "ERROR: '$dst' already exists. Please remove it before running the" \ + "script." 1>&2 + exit 1 +fi + +cp -r "$src" "$dst" +find "$dst" -name "*.html" \ + -not -path "*/demos/*" \ + -not -path "*/test/*" \ + -not -path "*/tests/*" \ + -not -name "demo*.html" \ + -not -name "index.html" \ + -not -name "metadata.html" | \ +xargs grep -l "<script>" | \ +while read original_html_name +do + dir=$(dirname "$original_html_name") + name=$(basename "$original_html_name" .html) + + html_without_js="$dir/$name-extracted.html" + extracted_js="$dir/$name-extracted.js" + crisper --source "$original_html_name" --html "$html_without_js" --js "$extracted_js" + mv "$html_without_js" "$original_html_name" +done
diff --git a/third_party/polymer/v0_8/reproduce.sh b/third_party/polymer/v0_8/reproduce.sh new file mode 100755 index 0000000..5cae9310 --- /dev/null +++ b/third_party/polymer/v0_8/reproduce.sh
@@ -0,0 +1,46 @@ +#!/bin/bash + +# 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. + +# Reproduces the content of 'components' and 'components-chromium' using the +# list of dependencies from 'bower.json'. Downloads needed packages and makes +# Chromium specific modifications. To launch the script you need 'bower', +# 'crisper', and 'vulcanize' installed on your system. + +# IMPORTANT NOTE: The new vulcanize must be installed from +# https://github.com/Polymer/vulcanize/releases since it isn't on npm yet. + +set -e + +cd "$(dirname "$0")" + +rm -rf components components-chromium + +bower install + +# These components are deprecated or needed only for demos. +rm -rf components/{iron-component-page,webcomponentsjs} + +# Test and demo directories aren't needed. +rm -rf components/*/{test,demo} +rm -rf components/polymer/explainer + +# Make checkperms.py happy. +find components/iron-selector -type f -exec chmod -x {} \; +chmod +x components/polymer/build.bat + +# Remove carriage returns to make CQ happy. +find components -type f \( -name \*.html -o -name \*.css -o -name \*.js\ + -o -name \*.md -o -name \*.sh -o -name \*.json -o -name \*.gitignore \)\ + -print0 | xargs -0 sed -i -e $'s/\r$//g' + +./extract_inline_scripts.sh components components-chromium + +# Actually fully vulcanize polymer.html to avoid needing to serve each file in +# the library separately. +vulcanize --inline-scripts components/polymer/polymer.html > components-chromium/polymer/polymer.html +crisper --source components-chromium/polymer/polymer.html\ + --html "components-chromium/polymer/polymer.html"\ + --js "components-chromium/polymer/polymer.js"
diff --git a/third_party/speech-dispatcher/BUILD.gn b/third_party/speech-dispatcher/BUILD.gn index 41ae249..fce246e 100644 --- a/third_party/speech-dispatcher/BUILD.gn +++ b/third_party/speech-dispatcher/BUILD.gn
@@ -25,5 +25,6 @@ "spd_set_synthesis_voice", "spd_list_modules", "spd_set_output_module", + "spd_set_language", ] }
diff --git a/third_party/usrsctp/BUILD.gn b/third_party/usrsctp/BUILD.gn index 45567e2e..3e3cabb 100644 --- a/third_party/usrsctp/BUILD.gn +++ b/third_party/usrsctp/BUILD.gn
@@ -122,6 +122,11 @@ if (is_clang) { cflags = [ "-Wno-incompatible-pointer-types" ] + } else if (target_cpu == "mipsel") { + # mipsel is still using gcc (4.9), + # which does not support "-Wno-incompatible-pointer-types" + # so let's disable all warnings for this module. + cflags = [ "-w" ] } deps = [
diff --git a/third_party/widevine/cdm/widevine_cdm.gyp b/third_party/widevine/cdm/widevine_cdm.gyp index ac45547..97a416518b 100644 --- a/third_party/widevine/cdm/widevine_cdm.gyp +++ b/third_party/widevine/cdm/widevine_cdm.gyp
@@ -69,19 +69,9 @@ # GN version: //third_party/widevine/cdm:widevinecdmadapter_resources 'target_name': 'widevinecdmadapter_resources', 'type': 'none', - 'conditions': [ - ['branding == "Chrome"', { - 'variables': { - 'branding_path': '../../../chrome/app/theme/google_chrome/BRANDING', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_path': '../../../chrome/app/theme/chromium/BRANDING', - }, - }], - ], 'variables': { 'output_dir': '.', + 'branding_path': '../../../chrome/app/theme/<(branding_path_component)/BRANDING', 'template_input_path': '../../../chrome/app/chrome_version.rc.version', 'extra_variable_files_arguments': [ '-f', 'BRANDING' ], 'extra_variable_files': [ 'BRANDING' ], # NOTE: matches that above
diff --git a/tools/auto_bisect/bisect_printer.py b/tools/auto_bisect/bisect_printer.py index 27866913..34baa31 100644 --- a/tools/auto_bisect/bisect_printer.py +++ b/tools/auto_bisect/bisect_printer.py
@@ -64,7 +64,7 @@ REPRO_STEPS_TRYJOB = """ To reproduce on a performance try bot: 1. Edit run-perf-test.cfg - 2. $ git try -b <bot> --svn_repo='svn://svn.chromium.org/chrome-try/try-perf' + 2. git try -b bot-name --svn_repo='svn://svn.chromium.org/chrome-try/try-perf' Notes: a) Follow the in-file instructions in run-perf-test.cfg. @@ -81,7 +81,7 @@ REPRO_STEPS_TRYJOB_TELEMETRY = """ To reproduce on a performance try bot: %(command)s -(Where <bot-name> comes from tools/perf/run_benchmark --browser=list) +(Where bot-name comes from tools/perf/run_benchmark --browser=list) For more details please visit https://sites.google.com/a/chromium.org/dev/developers/performance-try-bots @@ -120,7 +120,8 @@ else: build_status = 'Bad' - print ' %20s %40s %s' % (revision_state.depot, revision_state.revision, + print ' %20s %40s %s' % (revision_state.depot, + revision_state.revision, build_status) print @@ -343,7 +344,7 @@ print REPRO_STEPS_LOCAL if bisect_utils.IsTelemetryCommand(self.opts.command): telemetry_command = re.sub(r'--browser=[^\s]+', - '--browser=<bot-name>', + '--browser=bot-name', command) print REPRO_STEPS_TRYJOB_TELEMETRY % {'command': telemetry_command} else:
diff --git a/tools/checklicenses/checklicenses.py b/tools/checklicenses/checklicenses.py index da3d794..559ff4be 100755 --- a/tools/checklicenses/checklicenses.py +++ b/tools/checklicenses/checklicenses.py
@@ -217,6 +217,10 @@ # https://github.com/open-source-parsers/jsoncpp/issues/234 'UNKNOWN', ], + 'third_party/junit/src': [ + # https://github.com/junit-team/junit/issues/1132 + 'UNKNOWN', + ], 'third_party/lcov': [ # http://crbug.com/98304 'UNKNOWN', ],
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp index 931da02..3744ef3 100644 --- a/tools/clang/plugins/ChromeClassTester.cpp +++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -130,9 +130,7 @@ } #if defined(LLVM_ON_UNIX) - // We need to munge the paths so that they are relative to the repository - // srcroot. We first resolve the symlinktastic relative path and then - // remove our known srcroot from it if needed. + // Resolve the symlinktastic relative path and make it absolute. char resolvedPath[MAXPATHLEN]; if (realpath(filename.c_str(), resolvedPath)) { filename = resolvedPath; @@ -141,6 +139,15 @@ #if defined(LLVM_ON_WIN32) std::replace(filename.begin(), filename.end(), '\\', '/'); + + // On Posix, realpath() has made the path absolute. On Windows, this isn't + // necessarily true, so prepend a '/' to the path to make sure the + // banned_directories_ loop below works correctly. + // This turns e.g. "gen/dir/file.cc" to "/gen/dir/file.cc" which lets the + // "/gen/" banned_dir work. + // This seems simpler than converting to utf16, calling GetFullPathNameW(), + // and converting back to utf8. + filename.insert(filename.begin(), '/'); #endif for (const std::string& banned_dir : banned_directories_) {
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 9e39885..30d9ce9 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -25,7 +25,7 @@ # in bringup. Use a pinned revision to make it slightly more stable. if (re.search(r'\b(asan)=1', os.environ.get('GYP_DEFINES', '')) and not 'LLVM_FORCE_HEAD_REVISION' in os.environ): - LLVM_WIN_REVISION = '235098' + LLVM_WIN_REVISION = '235793' # Path constants. (All of these should be absolute paths.) THIS_DIR = os.path.abspath(os.path.dirname(__file__))
diff --git a/tools/cr/cr/actions/gn.py b/tools/cr/cr/actions/gn.py index 516537ce..e532d1d7 100644 --- a/tools/cr/cr/actions/gn.py +++ b/tools/cr/cr/actions/gn.py
@@ -5,8 +5,8 @@ """A module to add gn support to cr.""" import cr -import shlex import os +import re GN_ARG_PREFIX = 'GN_ARG_' @@ -19,19 +19,33 @@ ) @property + def priority(self): + return -1 + + @property def enabled(self): # Disabled on Android for now. return not cr.AndroidPlatform.GetInstance().is_active def UpdateContext(self): - # Collapse GN_ARGS from all GN_ARG prefixes + # Collapse GN_ARGS from all GN_ARG prefixes. gn_args = cr.context.Find('GN_ARGS') or '' for key, value in cr.context.exported.items(): if key.startswith(GN_ARG_PREFIX): gn_args += ' %s=%s' % (key[len(GN_ARG_PREFIX):], value) gn_args += (' is_debug=%s' % - 'true' if cr.context['CR_BUILDTYPE'] == 'Debug' else 'false') + ('true' if cr.context['CR_BUILDTYPE'] == 'Debug' else 'false')) + + # Detect goma. + goma_binaries = cr.Host.SearchPath('gomacc', [ + '{GOMA_DIR}', + '/usr/local/google/code/goma', + os.path.expanduser('~/goma') + ]) + if goma_binaries: + gn_args += ' use_goma=true' + gn_args += ' goma_dir="%s"' % os.path.dirname(goma_binaries[0]) cr.context['GN_ARGS'] = gn_args.strip() if cr.context.verbose >= 1: @@ -45,7 +59,10 @@ cr.context['CR_OUT_FULL'], 'args.gn') args = {} - for arg in shlex.split(cr.context['GN_ARGS']): + # Split the argument list while preserving quotes, + # e.g., a="b c" becomes ('a', '"b c"'). + split_re = r'(?:[^\s,"]|"(?:\\.|[^"])*")+' + for arg in re.findall(split_re, cr.context['GN_ARGS']): key, value = arg.split('=', 1) args[key] = value
diff --git a/tools/gn/bin/gyp_flag_compare.py b/tools/gn/bin/gyp_flag_compare.py index 1af3aae..55ca4d35 100755 --- a/tools/gn/bin/gyp_flag_compare.py +++ b/tools/gn/bin/gyp_flag_compare.py
@@ -66,7 +66,7 @@ # Rename -g2 to -g. if '-g2' in command_line: - command_line[index('-g2')] = '-g' + command_line[command_line.index('-g2')] = '-g' def GetFlags(lines):
diff --git a/tools/gn/bootstrap/bootstrap.py b/tools/gn/bootstrap/bootstrap.py index 91cec02..b417dee2 100755 --- a/tools/gn/bootstrap/bootstrap.py +++ b/tools/gn/bootstrap/bootstrap.py
@@ -222,6 +222,7 @@ 'base/threading/thread_id_name_manager.cc', 'base/threading/thread_local_storage.cc', 'base/threading/thread_restrictions.cc', + 'base/threading/worker_pool.cc', 'base/time/time.cc', 'base/timer/elapsed_timer.cc', 'base/timer/timer.cc', @@ -254,9 +255,11 @@ 'base/synchronization/lock_impl_posix.cc', 'base/synchronization/waitable_event_posix.cc', 'base/sys_info_posix.cc', + 'base/threading/platform_thread_internal_posix.cc', 'base/threading/platform_thread_posix.cc', 'base/threading/thread_local_posix.cc', 'base/threading/thread_local_storage_posix.cc', + 'base/threading/worker_pool_posix.cc', 'base/time/time_posix.cc', ]) static_libraries['libevent'] = {
diff --git a/tools/gn/command_help.cc b/tools/gn/command_help.cc index 7679b17..fc4e4e1 100644 --- a/tools/gn/command_help.cc +++ b/tools/gn/command_help.cc
@@ -120,6 +120,7 @@ PrintLongHelp(kBuildArgs_Help); PrintLongHelp(kDotfile_Help); + PrintLongHelp(kGrammar_Help); PrintLongHelp(kInputConversion_Help); PrintLongHelp(kLabelPattern_Help); PrintLongHelp(kSourceExpansion_Help);
diff --git a/tools/gn/docs/reference.md b/tools/gn/docs/reference.md index a405a34..5df04a6 100644 --- a/tools/gn/docs/reference.md +++ b/tools/gn/docs/reference.md
@@ -4073,6 +4073,131 @@ ``` +## **GN build language grammar** + +### **Tokens** + +``` + GN build files are read as sequences of tokens. While splitting the + file into tokens, the next token is the longest sequence of characters + that form a valid token. + +``` + +### **White space and comments** + +``` + White space is comprised of spaces (U+0020), horizontal tabs (U+0009), + carriage returns (U+000D), and newlines (U+000A). + + Comments start at the character "#" and stop at the next newline. + + White space and comments are ignored except that they may separate + tokens that would otherwise combine into a single token. + +``` + +### **Identifiers** + +``` + Identifiers name variables and functions. + + identifier = letter { letter | digit } . + letter = "A" ... "Z" | "a" ... "z" | "_" . + digit = "0" ... "9" . + +``` + +### **Keywords** + +``` + The following keywords are reserved and may not be used as + identifiers: + + else false if true + +``` + +### **Integer literals** + +``` + An integer literal represents a decimal integer value. + + integer = [ "-" ] digit { digit } . + + Leading zeros and negative zero are disallowed. + +``` + +### **String literals** + +``` + A string literal represents a string value consisting of the quoted + characters with possible escape sequences and variable expansions. + + string = `"` { char | escape | expansion } `"` . + escape = `\` ( "$" | `"` | char ) . + expansion = "$" ( identifier | "{" identifier "}" ) . + char = /* any character except "$", `"`, or newline */ . + + After a backslash, certain sequences represent special characters: + + \" U+0022 quotation mark + \$ U+0024 dollar sign + \\ U+005C backslash + + All other backslashes represent themselves. + +``` + +### **Punctuation** + +``` + The following character sequences represent punctuation: + + + += == != ( ) + - -= < <= [ ] + ! = > >= { } + && || . , + +``` + +### **Grammar** + +``` + The input tokens form a syntax tree following a context-free grammar: + + File = StatementList . + + Statement = Assignment | Call | Condition . + Assignment = identifier AssignOp Expr . + Call = identifier "(" [ ExprList ] ")" [ Block ] . + Condition = "if" "(" Expr ")" Block + [ "else" ( Condition | Block ) ] . + Block = "{" StatementList "}" . + StatementList = { Statement } . + + Expr = UnaryExpr | Expr BinaryOp Expr . + UnaryExpr = PrimaryExpr | UnaryOp UnaryExpr . + PrimaryExpr = identifier | integer | string | Call + | identifier "[" Expr "]" + | identifier "." identifier + | "(" Expr ")" + | "[" [ ExprList [ "," ] ] "]" . + ExprList = Expr { "," Expr } . + + AssignOp = "=" | "+=" | "-=" . + UnaryOp = "!" . + BinaryOp = "+" | "-" // highest priority + | "<" | "<=" | ">" | ">=" + | "==" | "!=" + | "&&" + | "||" . // lowest priority + + All binary operators are left-associative. + + +``` ## **input_conversion**: Specifies how to transform input to a variable. ```
diff --git a/tools/gn/function_write_file.cc b/tools/gn/function_write_file.cc index 0d273fc..9f853f8 100644 --- a/tools/gn/function_write_file.cc +++ b/tools/gn/function_write_file.cc
@@ -8,6 +8,7 @@ #include "base/files/file_util.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" #include "tools/gn/err.h" #include "tools/gn/filesystem_utils.h" #include "tools/gn/functions.h" @@ -17,6 +18,51 @@ namespace functions { +namespace { + +// On Windows, provide a custom implementation of base::WriteFile. Sometimes +// the base version would fail, and this alternate implementation provides +// additional logging. See http://crbug.com/468437 +#if defined(OS_WIN) +int DoWriteFile(const base::FilePath& filename, const char* data, int size) { + base::win::ScopedHandle file(::CreateFile( + filename.value().c_str(), + GENERIC_WRITE, + FILE_SHARE_READ, // Not present in the base version, speculative fix. + NULL, + CREATE_ALWAYS, + 0, + NULL)); + if (!file.IsValid()) { + PLOG(ERROR) << "CreateFile failed for path " + << base::UTF16ToUTF8(filename.value()); + return -1; + } + + DWORD written; + BOOL result = ::WriteFile(file.Get(), data, size, &written, NULL); + if (result && static_cast<int>(written) == size) + return written; + + if (!result) { + // WriteFile failed. + PLOG(ERROR) << "writing file " << base::UTF16ToUTF8(filename.value()) + << " failed"; + } else { + // Didn't write all the bytes. + LOG(ERROR) << "wrote" << written << " bytes to " + << base::UTF16ToUTF8(filename.value()) << " expected " << size; + } + return -1; +} +#else +int DoWriteFile(const base::FilePath& filename, const char* data, int size) { + return base::WriteFile(filename, data, size); +} +#endif + +} // namespace + const char kWriteFile[] = "write_file"; const char kWriteFile_HelpShort[] = "write_file: Write a file to disk."; @@ -91,7 +137,7 @@ } int int_size = static_cast<int>(new_contents.size()); - if (base::WriteFile(file_path, new_contents.c_str(), int_size) + if (DoWriteFile(file_path, new_contents.c_str(), int_size) != int_size) { *err = Err(function->function(), "Unable to write file.", "I was writing \"" + FilePathToUTF8(file_path) + "\".");
diff --git a/tools/gn/ninja_build_writer.cc b/tools/gn/ninja_build_writer.cc index 3ed0a627..248a45a 100644 --- a/tools/gn/ninja_build_writer.cc +++ b/tools/gn/ninja_build_writer.cc
@@ -191,6 +191,7 @@ // isn't unique, also skip it. The exception is for the toplevel targets // which we also find. std::map<std::string, int> small_name_count; + std::map<std::string, int> exe_count; std::vector<const Target*> toplevel_targets; base::hash_set<std::string> target_files; for (const auto& target : default_toolchain_targets_) { @@ -208,6 +209,11 @@ dir_string[dir_string.size() - 1] == '/' && // "/" at end. dir_string.compare(2, label.name().size(), label.name()) == 0) toplevel_targets.push_back(target); + + // Look for executables; later we will generate phony rules for them + // even if there are non-executable targets with the same name. + if (target->output_type() == Target::EXECUTABLE) + exe_count[label.name()]++; } for (const auto& target : default_toolchain_targets_) { @@ -236,9 +242,13 @@ WritePhonyRule(target, target_file, medium_name); } - // Write short names for ones which are unique. - if (small_name_count[label.name()] == 1) + // Write short names for ones which are either completely unique or there + // at least only one of them in the default toolchain that is an exe. + if (small_name_count[label.name()] == 1 || + (target->output_type() == Target::EXECUTABLE && + exe_count[label.name()] == 1)) { WritePhonyRule(target, target_file, label.name()); + } if (!all_rules.empty()) all_rules.append(" $\n ");
diff --git a/tools/gn/setup.cc b/tools/gn/setup.cc index c70eab8e..d8d525a 100644 --- a/tools/gn/setup.cc +++ b/tools/gn/setup.cc
@@ -160,10 +160,10 @@ check_for_bad_items_(true), check_for_unused_overrides_(true), check_public_headers_(false), - empty_settings_(&empty_build_settings_, std::string()), - dotfile_scope_(&empty_settings_), + dotfile_settings_(&build_settings_, std::string()), + dotfile_scope_(&dotfile_settings_), fill_arguments_(true) { - empty_settings_.set_toolchain_label(Label()); + dotfile_settings_.set_toolchain_label(Label()); build_settings_.set_item_defined_callback( base::Bind(&ItemDefinedCallback, scheduler_.main_loop(), builder_)); @@ -340,7 +340,7 @@ return false; } - Scope arg_scope(&empty_settings_); + Scope arg_scope(&dotfile_settings_); args_root_->Execute(&arg_scope, &err); if (err.has_error()) { err.PrintToStdout();
diff --git a/tools/gn/setup.h b/tools/gn/setup.h index 2e0e367..2e028e33 100644 --- a/tools/gn/setup.h +++ b/tools/gn/setup.h
@@ -151,10 +151,9 @@ Scheduler scheduler_; - // These empty settings and toolchain are used to interpret the command line - // and dot file. - BuildSettings empty_build_settings_; - Settings empty_settings_; + // These settings and toolchain are used to interpret the command line and + // dot file. + Settings dotfile_settings_; Scope dotfile_scope_; // State for invoking the dotfile.
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py index 73413ef..6faac397 100644 --- a/tools/json_schema_compiler/cc_generator.py +++ b/tools/json_schema_compiler/cc_generator.py
@@ -363,11 +363,16 @@ for prop in type_.properties.values(): prop_var = 'this->%s' % prop.unix_name if prop.optional: - # Optional enum values are generated with a NONE enum value. underlying_type = self._type_helper.FollowRef(prop.type_) if underlying_type.property_type == PropertyType.ENUM: - c.Sblock('if (%s != %s) {' % + # Optional enum values are generated with a NONE enum value, + # potentially from another namespace. + maybe_namespace = '' + if underlying_type.namespace != self._namespace: + maybe_namespace = '%s::' % underlying_type.namespace.unix_name + c.Sblock('if (%s != %s%s) {' % (prop_var, + maybe_namespace, self._type_helper.GetEnumNoneValue(prop.type_))) else: c.Sblock('if (%s.get()) {' % prop_var)
diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py index 566df07..facd5e4e 100644 --- a/tools/json_schema_compiler/h_generator.py +++ b/tools/json_schema_compiler/h_generator.py
@@ -41,6 +41,12 @@ output_file = os.path.splitext(self._namespace.source_file)[0] + '.h' ifndef_name = cpp_util.GenerateIfndefName(output_file) + # Hack: tabs and windows have circular references, so only generate hard + # references for them (i.e. anything that can't be forward declared). In + # other cases, generate soft dependencies so that they can include + # non-optional types from other namespaces. + include_soft = self._namespace.name not in ('tabs', 'windows') + (c.Append('#ifndef %s' % ifndef_name) .Append('#define %s' % ifndef_name) .Append() @@ -53,15 +59,14 @@ .Append('#include "base/memory/linked_ptr.h"') .Append('#include "base/memory/scoped_ptr.h"') .Append('#include "base/values.h"') - .Cblock(self._type_helper.GenerateIncludes()) + .Cblock(self._type_helper.GenerateIncludes(include_soft=include_soft)) .Append() ) - # TODO(calamity): These forward declarations should be #includes to allow - # $ref types from other files to be used as required params. This requires - # some detangling of windows and tabs which will currently lead to circular - # #includes. - c.Cblock(self._type_helper.GenerateForwardDeclarations()) + # Hack: we're not generating soft includes for tabs and windows, so we need + # to generate forward declarations for them. + if not include_soft: + c.Cblock(self._type_helper.GenerateForwardDeclarations()) cpp_namespace = cpp_util.GetCppNamespace( self._namespace.environment.namespace_pattern,
diff --git a/tools/json_schema_compiler/test/crossref.json b/tools/json_schema_compiler/test/crossref.json index a1e994b..ca67a46 100644 --- a/tools/json_schema_compiler/test/crossref.json +++ b/tools/json_schema_compiler/test/crossref.json
@@ -9,7 +9,17 @@ "type": "object", "properties": { "testType": { - "$ref": "simple_api.TestType", + "$ref": "simple_api.TestType" + }, + "testEnumRequired": { + "$ref": "simple_api.TestEnum" + }, + "testEnumOptional": { + "$ref": "simple_api.TestEnum", + "optional": true + }, + "testEnumOptionalExtra": { + "$ref": "simple_api.TestEnum", "optional": true } }
diff --git a/tools/json_schema_compiler/test/crossref_unittest.cc b/tools/json_schema_compiler/test/crossref_unittest.cc index 7d8879d..cc20675 100644 --- a/tools/json_schema_compiler/test/crossref_unittest.cc +++ b/tools/json_schema_compiler/test/crossref_unittest.cc
@@ -7,63 +7,72 @@ #include "testing/gtest/include/gtest/gtest.h" -using namespace test::api::crossref; +using namespace test::api; namespace { -static scoped_ptr<base::DictionaryValue> CreateTestTypeDictionary() { +scoped_ptr<base::DictionaryValue> CreateTestTypeValue() { base::DictionaryValue* value(new base::DictionaryValue()); - value->SetWithoutPathExpansion("number", new base::FundamentalValue(1.1)); - value->SetWithoutPathExpansion("integer", new base::FundamentalValue(4)); - value->SetWithoutPathExpansion("string", new base::StringValue("bling")); - value->SetWithoutPathExpansion("boolean", new base::FundamentalValue(true)); + value->Set("number", new base::FundamentalValue(1.1)); + value->Set("integer", new base::FundamentalValue(4)); + value->Set("string", new base::StringValue("bling")); + value->Set("boolean", new base::FundamentalValue(true)); return scoped_ptr<base::DictionaryValue>(value); } } // namespace -TEST(JsonSchemaCompilerCrossrefTest, CrossrefTypePopulate) { - scoped_ptr<CrossrefType> crossref_type(new CrossrefType()); - scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); - value->Set("testType", CreateTestTypeDictionary().release()); - EXPECT_TRUE(CrossrefType::Populate(*value, crossref_type.get())); - EXPECT_TRUE(crossref_type->test_type.get()); - EXPECT_TRUE(CreateTestTypeDictionary()->Equals( - crossref_type->test_type->ToValue().get())); - EXPECT_TRUE(value->Equals(crossref_type->ToValue().get())); +TEST(JsonSchemaCompilerCrossrefTest, CrossrefTypePopulateAndToValue) { + base::DictionaryValue crossref_orig; + crossref_orig.Set("testType", CreateTestTypeValue().release()); + crossref_orig.Set("testEnumRequired", new base::StringValue("one")); + crossref_orig.Set("testEnumOptional", new base::StringValue("two")); + + // Test Populate of the value --> compiled type. + crossref::CrossrefType crossref_type; + ASSERT_TRUE(crossref::CrossrefType::Populate(crossref_orig, &crossref_type)); + EXPECT_EQ(1.1, crossref_type.test_type.number); + EXPECT_EQ(4, crossref_type.test_type.integer); + EXPECT_EQ("bling", crossref_type.test_type.string); + EXPECT_EQ(true, crossref_type.test_type.boolean); + EXPECT_EQ(simple_api::TEST_ENUM_ONE, crossref_type.test_enum_required); + EXPECT_EQ(simple_api::TEST_ENUM_TWO, crossref_type.test_enum_optional); + EXPECT_EQ(simple_api::TEST_ENUM_NONE, crossref_type.test_enum_optional_extra); + + // Test ToValue of the compiled type --> value. + scoped_ptr<base::DictionaryValue> crossref_value = crossref_type.ToValue(); + ASSERT_TRUE(crossref_value); + EXPECT_TRUE(crossref_orig.Equals(crossref_value.get())); } TEST(JsonSchemaCompilerCrossrefTest, TestTypeOptionalParamCreate) { scoped_ptr<base::ListValue> params_value(new base::ListValue()); - params_value->Append(CreateTestTypeDictionary().release()); - scoped_ptr<TestTypeOptionalParam::Params> params( - TestTypeOptionalParam::Params::Create(*params_value)); + params_value->Append(CreateTestTypeValue().release()); + scoped_ptr<crossref::TestTypeOptionalParam::Params> params( + crossref::TestTypeOptionalParam::Params::Create(*params_value)); EXPECT_TRUE(params.get()); EXPECT_TRUE(params->test_type.get()); EXPECT_TRUE( - CreateTestTypeDictionary()->Equals(params->test_type->ToValue().get())); + CreateTestTypeValue()->Equals(params->test_type->ToValue().get())); } TEST(JsonSchemaCompilerCrossrefTest, TestTypeOptionalParamFail) { scoped_ptr<base::ListValue> params_value(new base::ListValue()); - scoped_ptr<base::DictionaryValue> test_type_value = - CreateTestTypeDictionary(); + scoped_ptr<base::DictionaryValue> test_type_value = CreateTestTypeValue(); test_type_value->RemoveWithoutPathExpansion("number", NULL); params_value->Append(test_type_value.release()); - scoped_ptr<TestTypeOptionalParam::Params> params( - TestTypeOptionalParam::Params::Create(*params_value)); + scoped_ptr<crossref::TestTypeOptionalParam::Params> params( + crossref::TestTypeOptionalParam::Params::Create(*params_value)); EXPECT_FALSE(params.get()); } TEST(JsonSchemaCompilerCrossrefTest, GetTestType) { - scoped_ptr<base::DictionaryValue> value = CreateTestTypeDictionary(); - scoped_ptr<test::api::simple_api::TestType> test_type( - new test::api::simple_api::TestType()); - EXPECT_TRUE( - test::api::simple_api::TestType::Populate(*value, test_type.get())); + scoped_ptr<base::DictionaryValue> value = CreateTestTypeValue(); + scoped_ptr<simple_api::TestType> test_type(new simple_api::TestType()); + EXPECT_TRUE(simple_api::TestType::Populate(*value, test_type.get())); scoped_ptr<base::ListValue> results = - GetTestType::Results::Create(*test_type); + crossref::GetTestType::Results::Create(*test_type); base::DictionaryValue* result_dict = NULL; results->GetDictionary(0, &result_dict); EXPECT_TRUE(value->Equals(result_dict)); @@ -74,16 +83,16 @@ scoped_ptr<base::ListValue> params_value(new base::ListValue()); scoped_ptr<base::DictionaryValue> param_object_value( new base::DictionaryValue()); - param_object_value->Set("testType", CreateTestTypeDictionary().release()); + param_object_value->Set("testType", CreateTestTypeValue().release()); param_object_value->Set("boolean", new base::FundamentalValue(true)); params_value->Append(param_object_value.release()); - scoped_ptr<TestTypeInObject::Params> params( - TestTypeInObject::Params::Create(*params_value)); + scoped_ptr<crossref::TestTypeInObject::Params> params( + crossref::TestTypeInObject::Params::Create(*params_value)); EXPECT_TRUE(params.get()); EXPECT_TRUE(params->param_object.test_type.get()); EXPECT_TRUE(params->param_object.boolean); - EXPECT_TRUE(CreateTestTypeDictionary()->Equals( - params->param_object.test_type->ToValue().get())); + EXPECT_TRUE(CreateTestTypeValue()->Equals( + params->param_object.test_type->ToValue().get())); } { scoped_ptr<base::ListValue> params_value(new base::ListValue()); @@ -91,8 +100,8 @@ new base::DictionaryValue()); param_object_value->Set("boolean", new base::FundamentalValue(true)); params_value->Append(param_object_value.release()); - scoped_ptr<TestTypeInObject::Params> params( - TestTypeInObject::Params::Create(*params_value)); + scoped_ptr<crossref::TestTypeInObject::Params> params( + crossref::TestTypeInObject::Params::Create(*params_value)); EXPECT_TRUE(params.get()); EXPECT_FALSE(params->param_object.test_type.get()); EXPECT_TRUE(params->param_object.boolean); @@ -104,18 +113,18 @@ param_object_value->Set("testType", new base::StringValue("invalid")); param_object_value->Set("boolean", new base::FundamentalValue(true)); params_value->Append(param_object_value.release()); - scoped_ptr<TestTypeInObject::Params> params( - TestTypeInObject::Params::Create(*params_value)); + scoped_ptr<crossref::TestTypeInObject::Params> params( + crossref::TestTypeInObject::Params::Create(*params_value)); EXPECT_FALSE(params.get()); } { scoped_ptr<base::ListValue> params_value(new base::ListValue()); scoped_ptr<base::DictionaryValue> param_object_value( new base::DictionaryValue()); - param_object_value->Set("testType", CreateTestTypeDictionary().release()); + param_object_value->Set("testType", CreateTestTypeValue().release()); params_value->Append(param_object_value.release()); - scoped_ptr<TestTypeInObject::Params> params( - TestTypeInObject::Params::Create(*params_value)); + scoped_ptr<crossref::TestTypeInObject::Params> params( + crossref::TestTypeInObject::Params::Create(*params_value)); EXPECT_FALSE(params.get()); } }
diff --git a/tools/json_schema_compiler/test/simple_api.json b/tools/json_schema_compiler/test/simple_api.json index 9ab5403..7831187 100644 --- a/tools/json_schema_compiler/test/simple_api.json +++ b/tools/json_schema_compiler/test/simple_api.json
@@ -24,6 +24,11 @@ "description": "Some integer." } } + }, + { + "id": "TestEnum", + "type": "string", + "enum": ["one", "two", "three"] } ], "functions": [
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 5d6fe1b..bc43654e 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -122,12 +122,11 @@ def CmdGen(self): vals = self.GetConfig() if vals['type'] == 'gn': - self.RunGNGen(self.args.path[0], vals) - elif vals['type'] == 'gyp': - self.RunGYPGen(self.args.path[0], vals) - else: - raise MBErr('Unknown meta-build type "%s"' % vals['type']) - return 0 + return self.RunGNGen(self.args.path[0], vals) + if vals['type'] == 'gyp': + return self.RunGYPGen(self.args.path[0], vals) + + raise MBErr('Unknown meta-build type "%s"' % vals['type']) def CmdLookup(self): vals = self.GetConfig() @@ -430,7 +429,7 @@ cmd = self.GNCmd('refs', self.args.path[0]) + [ '//' + f, '--type=executable', '--all', '--as=output'] ret, out, _ = self.Run(cmd) - if ret: + if ret and not 'The input matches no targets' in out: self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out), output_path)
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 7fa3014..8972c5e 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -12,6 +12,8 @@ 'android_gn_release_bot': ['android', 'gn', 'release_bot'], 'android_gn_debug_bot': ['android', 'gn', 'debug_static_bot'], 'android_gn_release_trybot': ['android', 'gn', 'release_trybot'], + 'android_gyp_debug_bot': ['android', 'gyp', 'debug_bot'], + 'android_gyp_release_trybot': ['android', 'gyp', 'release_trybot'], 'chromeos_gn_debug_bot': ['chromeos', 'gn', 'debug_bot'], 'chromeos_gn_release_bot': ['chromeos', 'gn', 'release_bot'], 'chromeos_gn_release_trybot': ['chromeos', 'gn', 'release_trybot'], @@ -167,6 +169,8 @@ 'V8 Android GN (dbg)': 'android_gn_debug_bot', }, 'tryserver.blink': { + 'android_blink_compile_dbg': 'android_gyp_debug_bot', + 'android_blink_compile_rel': 'android_gyp_release_trybot', 'android_chromium_gn_compile_rel': 'android_gn_release_bot', 'linux_chromium_gn_rel': 'gn_release_bot', },
diff --git a/tools/mb/mb_unittest.py b/tools/mb/mb_unittest.py index 95513776..ac822ab4 100644 --- a/tools/mb/mb_unittest.py +++ b/tools/mb/mb_unittest.py
@@ -100,12 +100,12 @@ class UnitTest(unittest.TestCase): - def fake_mbw(self, files): + def fake_mbw(self, files=None): mbw = FakeMBW() + mbw.files.setdefault(mbw.default_config, TEST_CONFIG) if files: for path, contents in files.items(): mbw.files[path] = contents - mbw.files.setdefault(mbw.default_config, TEST_CONFIG) return mbw def check(self, args, mbw=None, files=None, out=None, err=None, ret=None): @@ -153,6 +153,24 @@ 'status': 'Found dependency (all)', }) + def test_gn_analyze_missing_file(self): + files = {'/tmp/in.json': """{\ + "files": ["foo/foo_unittest.cc"], + "targets": ["bar_unittests"] + }"""} + mbw = self.fake_mbw(files) + mbw.Call = lambda cmd: ( + 1, 'The input matches no targets, configs, or files\n', '') + + self.check(['analyze', '-c', 'gn_debug', '//out/Default', + '/tmp/in.json', '/tmp/out.json'], mbw=mbw, ret=0) + out = json.loads(mbw.files['/tmp/out.json']) + self.assertEqual(out, { + 'build_targets': [], + 'targets': [], + 'status': 'No dependency', + }) + def test_gyp_analyze(self): self.check(['analyze', '-c', 'gyp_rel_bot', '//out/Release', '/tmp/in.json', '/tmp/out.json'], @@ -162,6 +180,12 @@ self.check(['gen', '-c', 'gn_debug', '//out/Default'], ret=0) self.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], ret=0) + def test_gen_fails(self): + mbw = self.fake_mbw() + mbw.Call = lambda cmd: (1, '', '') + self.check(['gen', '-c', 'gn_debug', '//out/Default'], mbw=mbw, ret=1) + self.check(['gen', '-c', 'gyp_rel_bot', '//out/Release'], mbw=mbw, ret=1) + def test_goma_dir_expansion(self): self.check(['lookup', '-c', 'gyp_rel_bot', '-g', '/foo'], ret=0, out=("python build/gyp_chromium -G 'output_dir=<path>' "
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 327f44d..e86847be 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -7091,6 +7091,15 @@ </description> </action> +<action name="Launcher_MinimizeTask"> + <owner>bruthig@google.com</owner> + <owner>tdanderson@google.com</owner> + <description> + Recorded when the user minimizes an existing task by clicking an icon in the + shelf. + </description> +</action> + <action name="Launcher_SwitchTask"> <owner>bruthig@google.com</owner> <owner>tdanderson@google.com</owner>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 7ffa0ec..37cf7282 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -8140,6 +8140,10 @@ <histogram name="Event.Latency.TouchToFirstScrollUpdateSwap" units="microseconds"> <owner>rbyers@chromium.org</owner> + <obsolete> + Replaced by Event.Latency.TouchToFirstScrollUpdateSwapBegin. + crbug.com/478845 + </obsolete> <summary> Time between initial creation of a touch event and the frame swap caused by by the generated ScrollUpdate gesture event if that ScrollUpdate is the @@ -8148,8 +8152,22 @@ </summary> </histogram> +<histogram name="Event.Latency.TouchToFirstScrollUpdateSwapBegin" + units="microseconds"> + <owner>rbyers@chromium.org</owner> + <summary> + Time between initial creation of a touch event and the start of the frame + swap on the GPU service caused by the generated ScrollUpdate gesture event + if that ScrollUpdate is the first such event in a given scroll gesture event + sequence. If no swap was induced by the event, no recording is made. + </summary> +</histogram> + <histogram name="Event.Latency.TouchToScrollUpdateSwap" units="microseconds"> <owner>rbyers@chromium.org</owner> + <obsolete> + Replaced by Event.Latency.TouchToScrollUpdateSwapBegin. crbug.com/478845 + </obsolete> <summary> Time between initial creation of a touch event and the frame swap caused by by the generated ScrollUpdate gesture event. If no swap was induced by the @@ -8157,6 +8175,16 @@ </summary> </histogram> +<histogram name="Event.Latency.TouchToScrollUpdateSwapBegin" + units="microseconds"> + <owner>rbyers@chromium.org</owner> + <summary> + Time between initial creation of a touch event and start of the frame swap + on the GPU service caused by the generated ScrollUpdate gesture event. If no + swap was induced by the event, no recording is made. + </summary> +</histogram> + <histogram name="Event.SingleTapType" enum="TapDelayType"> <owner>rbyers@chromium.org</owner> <summary> @@ -8577,8 +8605,16 @@ </summary> </histogram> +<histogram name="ExtensionInstallSigner.InvalidCount"> + <owner>asargent@chromium.org</owner> + <summary> + This is a count of the number of ids that we asked to be signed which the + server response indicated were not in the webstore. + </summary> +</histogram> + <histogram name="ExtensionInstallSigner.RequestCount"> - <owner>Please list the metric's owners. Add more owner tags as needed.</owner> + <owner>asargent@chromium.org</owner> <summary> A count of the number of server requests since Chrome started running, recorded each time we do a request. NOTE: when interpreting these values, @@ -8588,7 +8624,7 @@ </histogram> <histogram name="ExtensionInstallSigner.ResultWasValid"> - <owner>Please list the metric's owners. Add more owner tags as needed.</owner> + <owner>asargent@chromium.org</owner> <summary> Whether the server result received by the extensions install signer was valid or invalid. @@ -8597,7 +8633,7 @@ <histogram name="ExtensionInstallSigner.SecondsSinceLastRequest" units="seconds"> - <owner>Please list the metric's owners. Add more owner tags as needed.</owner> + <owner>asargent@chromium.org</owner> <summary> This records the number of seconds since the last time we've done a request to the server (only during this run of the browser). @@ -8605,7 +8641,7 @@ </histogram> <histogram name="ExtensionInstallSigner.UptimeAtTimeOfRequest" units="seconds"> - <owner>Please list the metric's owners. Add more owner tags as needed.</owner> + <owner>asargent@chromium.org</owner> <summary> Records how many seconds the browser has been running at the time a request to the server is made to get a new install signature. @@ -9666,6 +9702,9 @@ <histogram name="Extensions.LoadContentPack"> <owner>asargent@chromium.org</owner> + <obsolete> + Deprecated as of 4/2015. Replaced by ManagedUsers.Whitelist.Count. + </obsolete> <summary> The number of content-pack extensions loaded at browser startup. </summary> @@ -11427,6 +11466,13 @@ </summary> </histogram> +<histogram name="GPU.ContextLost" enum="ContextLostReason"> + <owner>sievers@chromium.org</owner> + <summary> + The reason a GPU command buffer context of a given type was lost. + </summary> +</histogram> + <histogram name="GPU.CreateBrowserCompositor" units="microseconds"> <owner>vangelis@chromium.org</owner> <summary> @@ -12036,6 +12082,9 @@ </histogram> <histogram name="HttpCache.OfflineStatus" enum="OfflineStatus"> + <obsolete> + Deprecated 4/2015. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> Result of a main page HttpCacheTransaction if offline mode had been enabled. @@ -12568,6 +12617,11 @@ </histogram> <histogram name="InstallSigner.InvalidCount"> + <obsolete> + Deprecated 4/2015. It appears the code at some point changed to use the + histogram name 'ExtensionInstallSigner.InvalidCount' and we forgot to update + this histogram name. + </obsolete> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary> This is a count of the number of ids that we asked to be signed which the @@ -28611,6 +28665,15 @@ </summary> </histogram> +<histogram name="PluginFinder.BuiltInPluginList.ErrorCode" + enum="PluginListError"> + <owner>bauerb@chromium.org</owner> + <summary> + Error codes when parsing the built-in plugin list. Logged when the + PluginFinder singleton is created. + </summary> +</histogram> + <histogram name="Power.BacklightLevelOnAC" units="%"> <owner>derat@chromium.org</owner> <summary> @@ -30844,6 +30907,31 @@ </summary> </histogram> +<histogram name="Profile.ValidateMenuItemInvalidIndex.IsGuest" enum="Boolean"> + <owner>anthonyvd@chromium.org</owner> + <summary> + Whether the active profile is a guest profile when -validateMenuItem in the + ProfileMenuController gets an invalid value for the current profile's index. + </summary> +</histogram> + +<histogram name="Profile.ValidateMenuItemInvalidIndex.ProfileCount"> + <owner>anthonyvd@chromium.org</owner> + <summary> + The count of profiles in the avatar menu when -validateMenuItem in the + ProfileMenuController gets an invalid value for the current profile's index. + </summary> +</histogram> + +<histogram name="Profile.ValidateMenuItemInvalidIndex.Selector" + enum="ValidateMenuItemSelectorType"> + <owner>anthonyvd@chromium.org</owner> + <summary> + The selector associated with the menu item when -validateMenuItem in the + ProfileMenuController gets an invalid value for the current profile's index. + </summary> +</histogram> + <histogram name="Profile.VisitedLinksSize" units="MB"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary>Size of the visited links database.</summary> @@ -31349,6 +31437,9 @@ </histogram> <histogram name="Renderer.LayoutMs" units="milliseconds"> + <obsolete> + Deprecated as of 3/2015. + </obsolete> <owner>benjhayden@chromium.org</owner> <summary> Duration of the FrameView::performLayout trace event, which occurs at most @@ -31357,6 +31448,9 @@ </histogram> <histogram name="Renderer.LineLayoutMs" units="milliseconds"> + <obsolete> + Deprecated as of 3/2015. + </obsolete> <owner>benjhayden@chromium.org</owner> <summary> Amount of time spent doing line layout during FrameView::performLayout. @@ -35006,7 +35100,16 @@ <histogram name="ServiceWorker.ActivateEventExecutionTime" units="millisecond"> <owner>shimazu@chromium.org</owner> - <summary>Execution time of ServiceWorkerGlobalScope.onactivate.</summary> + <summary> + Execution time of ServiceWorkerGlobalScope.onactivate. Includes the time for + waitUntil() promise to settle. + </summary> +</histogram> + +<histogram name="ServiceWorker.ActivateEventStatus" + enum="ServiceWorkerStatusCode"> + <owner>falken@chromium.org</owner> + <summary>The result of dispatching the activate event to the worker.</summary> </histogram> <histogram name="ServiceWorker.Database.DestroyDatabaseResult" @@ -35064,12 +35167,24 @@ <histogram name="ServiceWorker.FetchEventExecutionTime" units="millisecond"> <owner>shimazu@chromium.org</owner> - <summary>Execution time of ServiceWorkerGlobalScope.onfetch.</summary> + <summary> + Execution time of ServiceWorkerGlobalScope.onfetch. Includes the time for + the respondWith() promise to settle. + </summary> </histogram> <histogram name="ServiceWorker.InstallEventExecutionTime" units="millisecond"> <owner>shimazu@chromium.org</owner> - <summary>Execution time of ServiceWorkerGlobalScope.oninstall.</summary> + <summary> + Execution time of ServiceWorkerGlobalScope.oninstall. Includes the time for + the waitUntil() promise to settle. + </summary> +</histogram> + +<histogram name="ServiceWorker.InstallEventStatus" + enum="ServiceWorkerStatusCode"> + <owner>falken@chromium.org</owner> + <summary>The result of dispatching the install event to the worker.</summary> </histogram> <histogram name="ServiceWorker.MessageEventExecutionTime" units="millisecond"> @@ -40331,6 +40446,15 @@ </summary> </histogram> +<histogram name="Sync.DeviceIdMismatchDetails" enum="DeviceIdMismatch"> + <owner>pavely@chromium.org</owner> + <summary> + When signin_scoped_device_id from pref doesn't match the one in + DeviceInfoSpecfics this histogram tells if sync or pref copy was empty. This + will indicate how often such mismatch happens and what was the state before. + </summary> +</histogram> + <histogram name="Sync.DictionaryAssociationTime" units="milliseconds"> <owner>zea@chromium.org</owner> <summary>Time taken during dictionary association.</summary> @@ -48057,6 +48181,22 @@ <int value="22" label="App banner setting (Android only)"/> </enum> +<enum name="ContextLostReason" type="int"> + <summary>The reason for losing a GPU context.</summary> + <int value="0" label="CONTEXT_INIT_FAILED"/> + <int value="1" label="CONTEXT_LOST_GPU_CHANNEL_ERROR"/> + <int value="2" label="CONTEXT_PARSE_ERROR_INVALID_SIZE"/> + <int value="3" label="CONTEXT_PARSE_ERROR_OUT_OF_BOUNDS"/> + <int value="4" label="CONTEXT_PARSE_ERROR_UNKNOWN_COMMAND"/> + <int value="5" label="CONTEXT_PARSE_ERROR_INVALID_ARGS"/> + <int value="6" label="CONTEXT_PARSE_ERROR_GENERIC_ERROR"/> + <int value="7" label="CONTEXT_LOST_GUILTY"/> + <int value="8" label="CONTEXT_LOST_INNOCENT"/> + <int value="9" label="CONTEXT_LOST_UNKNOWN"/> + <int value="10" label="CONTEXT_LOST_OUT_OF_MEMORY"/> + <int value="11" label="CONTEXT_LOST_MAKECURRENT_FAILED"/> +</enum> + <enum name="CookieDeletionCause" type="int"> <summary>Reason why a cookie was removed from the cookie store</summary> <int value="0" label="explicit"> @@ -48483,6 +48623,12 @@ <int value="5" label="First window capture call failed."/> </enum> +<enum name="DeviceIdMismatch" type="int"> + <int value="0" label="BOTH_NONEMPTY"/> + <int value="1" label="SYNC_EMPTY"/> + <int value="2" label="PREF_EMPTY"/> +</enum> + <enum name="DeviceOrientationSensorTypeAndroid" type="int"> <int value="0" label="Not Available"/> <int value="1" label="ROTATION_VECTOR"/> @@ -48642,6 +48788,7 @@ <int value="1763208296" label="safetynut.dll"/> <int value="1996673448" label="scdetour.dll"/> <int value="2060768492" label="libwinhook.dll"/> + <int value="2074150225" label="minisp32.dll"/> <int value="2117903235" label="cplushook.dll"/> <int value="2132270559" label="libsvn_tsvn32.dll"/> </enum> @@ -49437,8 +49584,8 @@ <int value="16" label="Install attributes timeout"> Lockbox initialization took too long to complete. </int> - <int value="17" label="Re-enrollment: lock domain mismatch"> - Lockbox error at re-enrollment: domain does not match install attributes. + <int value="17" label="Lockbox domain mismatch on re-enrollment"> + Lockbox error on re-enrollment: domain does not match install attributes. </int> <int value="18" label="Registration/fetch: missing licenses"> Registration / policy fetch failed: DM server reports licenses expired or @@ -49541,6 +49688,12 @@ <int value="49" label="Lockbox inconsistent read back"> Lockbox read back is inconsistent. </int> + <int value="50" label="Device attributes update failed"> + Failed to update device attributes. + </int> + <int value="51" label="Lockbox device mode mismatch on re-enrollment"> + Lockbox error on re-enrollment: mode does not match install attributes. + </int> </enum> <enum name="EnterprisePolicies" type="int"> @@ -49934,6 +50087,7 @@ <int value="298" label="Maximize the first browser window on first run"/> <int value="299" label="Allow users to opt in to Safe Browsing extended reporting"/> + <int value="300" label="Allow proceeding from the SSL warning page"/> </enum> <enum name="EnterprisePolicyInvalidations" type="int"> @@ -51248,6 +51402,19 @@ <int value="1008" label="DEVELOPERPRIVATE_SHOWPATH"/> <int value="1009" label="FILEMANAGERPRIVATE_ADDPROVIDEDFILESYSTEM"/> <int value="1010" label="FILEMANAGERPRIVATE_CONFIGUREPROVIDEDFILESYSTEM"/> + <int value="1011" label="SEARCHENGINESPRIVATE_GETDEFAULTSEARCHENGINES"/> + <int value="1012" label="SEARCHENGINESPRIVATE_SETSELECTEDSEARCHENGINE"/> + <int value="1013" label="AUTOFILLPRIVATE_SAVEADDRESS"/> + <int value="1014" label="AUTOFILLPRIVATE_GETADDRESSCOMPONENTS"/> + <int value="1015" label="AUTOFILLPRIVATE_SAVECREDITCARD"/> + <int value="1016" label="AUTOFILLPRIVATE_REMOVEENTRY"/> + <int value="1017" label="AUTOFILLPRIVATE_VALIDATEPHONENUMBERS"/> + <int value="1018" label="AUTOFILLPRIVATE_MASKCREDITCARD"/> + <int value="1019" label="INSTANCEID_GETID"/> + <int value="1020" label="INSTANCEID_GETCREATIONTIME"/> + <int value="1021" label="INSTANCEID_GETTOKEN"/> + <int value="1022" label="INSTANCEID_DELETETOKEN"/> + <int value="1023" label="INSTANCEID_DELETEID"/> </enum> <enum name="ExtensionInstallCause" type="int"> @@ -55277,6 +55444,7 @@ <int value="593707592" label="disable-network-portal-notification"/> <int value="598827460" label="enable-roboto-font-ui"/> <int value="606288133" label="enable-print-preview-register-promos"/> + <int value="609112512" label="touch-selection-strategy"/> <int value="610545308" label="enable-potentially-annoying-security-features"/> <int value="625273056" label="disable-boot-animation"/> <int value="630947363" label="touch-events"/> @@ -57440,6 +57608,9 @@ </enum> <enum name="OfflineStatus" type="int"> + <obsolete> + Deprecated 4/2015. + </obsolete> <int value="0" label="Fresh data load from Cache"/> <int value="1" label="Successful network request (validation or fetch)."/> <int value="2" label="Failed network request (non-offline error)."/> @@ -58854,6 +59025,19 @@ <int value="2" label="PLUGIN_DISABLED"/> </enum> +<enum name="PluginListError" type="int"> + <int value="0" label="NoError"/> + <int value="1" label="JsonInvalidEscape"/> + <int value="2" label="JsonSyntaxError"/> + <int value="3" label="JsonUnexpectedToken"/> + <int value="4" label="JsonTrailingComma"/> + <int value="5" label="JsonTooMuchNesting"/> + <int value="6" label="JsonUnexpectedDataAfterRoot"/> + <int value="7" label="JsonUnsupportedEncoding"/> + <int value="8" label="JsonUnquotedDictionaryKey"/> + <int value="9" label="SchemaError"/> +</enum> + <enum name="PluginLoadResult" type="int"> <int value="0" label="LOAD_SUCCESS"/> <int value="1" label="LOAD_FAILED"/> @@ -61301,6 +61485,7 @@ <int value="13" label="SERVICE_WORKER_ERROR_STATE"/> <int value="14" label="SERVICE_WORKER_ERROR_TIMEOUT"/> <int value="15" label="SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED"/> + <int value="16" label="SERVICE_WORKER_ERROR_DISK_CACHE"/> </enum> <enum name="ServiceWorkerWriteResponseResult" type="int"> @@ -63594,6 +63779,7 @@ <int value="44" label="kErrorCodeUnsupportedMajorPayloadVersion"/> <int value="45" label="kErrorCodeUnsupportedMinorPayloadVersion"/> <int value="46" label="kErrorCodeOmahaRequestXMLHasEntityDecl"/> + <int value="47" label="kErrorCodeFilesystemVerifierError"/> </enum> <enum name="UpdateEngineInstallDateProvisioningSource" type="int"> @@ -63692,6 +63878,17 @@ <int value="6" label="CHECKSUM_MISMATCH">Reject due to checksum mismatch</int> </enum> +<enum name="ValidateMenuItemSelectorType" type="int"> + <int value="0" + label="The menu items' associated action is an unknown selector."/> + <int value="1" label="The menu item's associated action is -newProfile."/> + <int value="2" label="The menu item's associated action is -editProfile."/> + <int value="3" + label="The menu item's associated action is -switchToProfileFromMenu."/> + <int value="4" + label="The menu item's associated action is -switchToProfileFromDock."/> +</enum> + <enum name="ValidationFailures" type="int"> <int value="0" label="DBus"/> <int value="1" label="Load Key"/> @@ -64663,6 +64860,26 @@ <affected-histogram name="PLT.LoadType"/> </histogram_suffixes> +<histogram_suffixes name="ContextType" separator="."> + <suffix name="BrowserCompositor" + label="A BrowserCompositor GPU command buffer context"/> + <suffix name="BrowserMainThread" + label="A BrowserMainThread GPU command buffer context"/> + <suffix name="RenderCompositor" + label="A RenderCompositor GPU command buffer context"/> + <suffix name="RenderMainThread" + label="A RenderMainThread GPU command buffer context"/> + <suffix name="RenderWorker" + label="A RenderWorker GPU command buffer context"/> + <suffix name="Unknown" label="A GPU command buffer context of unknown type"/> + <suffix name="VideoAccelerator" + label="A VideoAccelerator GPU command buffer context"/> + <suffix name="VideoCapture" + label="A VideoCapture GPU command buffer context"/> + <suffix name="WebGL" label="A WebGL GPU command buffer context"/> + <affected-histogram name="GPU.ContextLost"/> +</histogram_suffixes> + <histogram_suffixes name="CreditCardScanSuccess"> <suffix name="Completed" label="Credit card scan completed."/> <suffix name="Cancelled" label="Credit card scan was cancelled."/>
diff --git a/tools/perf/PRESUBMIT.py b/tools/perf/PRESUBMIT.py index ad11c24..6d01991 100644 --- a/tools/perf/PRESUBMIT.py +++ b/tools/perf/PRESUBMIT.py
@@ -9,6 +9,7 @@ """ import os +import re import sys @@ -76,3 +77,49 @@ report = [] report.extend(_CommonChecks(input_api, output_api)) return report + + +def _IsBenchmarksModified(change): + """Checks whether CL contains any modification to Telemetry benchmarks.""" + for affected_file in change.AffectedFiles(): + affected_file_path = affected_file.LocalPath() + file_path, _ = os.path.splitext(affected_file_path) + if (os.path.join('tools', 'perf', 'benchmarks') in file_path or + os.path.join('tools', 'perf', 'measurements') in file_path): + return True + return False + + +def PostUploadHook(cl, change, output_api): + """git cl upload will call this hook after the issue is created/modified. + + This hook adds extra try bots list to the CL description in order to run + Telemetry benchmarks on Perf trybots in addtion to CQ trybots if the CL + contains any changes to Telemetry benchmarks. + """ + benchmarks_modified = _IsBenchmarksModified(change) + rietveld_obj = cl.RpcServer() + issue = cl.issue + original_description = rietveld_obj.get_description(issue) + if not benchmarks_modified or re.search( + r'^CQ_EXTRA_TRYBOTS=.*', original_description, re.M | re.I): + return [] + + results = [] + bots = [ + 'linux_perf_bisect', + 'mac_perf_bisect', + 'win_perf_bisect', + 'android_nexus5_perf_bisect' + ] + bots = ['tryserver.chromium.perf:%s' % s for s in bots] + bots_string = ';'.join(bots) + description = original_description + description += '\nCQ_EXTRA_TRYBOTS=%s' % bots_string + results.append(output_api.PresubmitNotifyResult( + 'Automatically added Perf trybots to run Telemetry benchmarks on CQ.')) + + if description != original_description: + rietveld_obj.update_description(issue, description) + + return results
diff --git a/tools/perf/benchmarks/benchmark_unittest.py b/tools/perf/benchmarks/benchmark_unittest.py index 6d900ce..56f76702 100644 --- a/tools/perf/benchmarks/benchmark_unittest.py +++ b/tools/perf/benchmarks/benchmark_unittest.py
@@ -5,7 +5,6 @@ """For all the benchmarks that set options, test that the options are valid.""" from collections import defaultdict -import logging import os import unittest
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index dfb1653..8720aa7 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -194,6 +194,7 @@ return CreatePageSetFromPath(path, SKIPPED_FILE) +@benchmark.Disabled('release_x64') # http://crbug.com/480999 class BlinkPerfEvents(benchmark.Benchmark): tag = 'events' test = _BlinkPerfMeasurement
diff --git a/tools/perf/benchmarks/blink_style.py b/tools/perf/benchmarks/blink_style.py index 0dae4d15..827e81a0 100644 --- a/tools/perf/benchmarks/blink_style.py +++ b/tools/perf/benchmarks/blink_style.py
@@ -5,10 +5,8 @@ from telemetry import benchmark from measurements import blink_style -from measurements import smoothness import page_sets -@benchmark.Disabled # http://crbug.com/479048 class BlinkStyleTop25(benchmark.Benchmark): """Measures performance of Blink's style engine (CSS Parsing, Style Recalc, etc.) on the top 25 pages. @@ -34,7 +32,7 @@ return 'blink_style.key_mobile_sites' -@benchmark.Disabled('mac', 'reference') # http://crbug.com/479048 +@benchmark.Enabled('android') class BlinkStylePolymer(benchmark.Benchmark): """Measures performance of Blink's style engine (CSS Parsing, Style Recalc, etc.) for Polymer cases.
diff --git a/tools/perf/benchmarks/oilpan_gc_times.py b/tools/perf/benchmarks/oilpan_gc_times.py index f1577f9..9606aa7b 100644 --- a/tools/perf/benchmarks/oilpan_gc_times.py +++ b/tools/perf/benchmarks/oilpan_gc_times.py
@@ -5,7 +5,6 @@ import os from telemetry import benchmark -from telemetry import page from benchmarks import blink_perf from benchmarks import silk_flags
diff --git a/tools/perf/benchmarks/page_cycler.py b/tools/perf/benchmarks/page_cycler.py index 3986218..93138df 100644 --- a/tools/perf/benchmarks/page_cycler.py +++ b/tools/perf/benchmarks/page_cycler.py
@@ -232,6 +232,7 @@ def CreatePageSet(self, options): return page_sets.Typical25PageSet(run_no_page_interactions=True) + @benchmark.Disabled # crbug.com/443730 class PageCyclerBigJs(_PageCycler): page_set = page_sets.BigJsPageSet
diff --git a/tools/perf/benchmarks/power.py b/tools/perf/benchmarks/power.py index 9cbda538..d31403f 100644 --- a/tools/perf/benchmarks/power.py +++ b/tools/perf/benchmarks/power.py
@@ -18,7 +18,6 @@ return 'power.android_acceptance' - @benchmark.Enabled('android') class PowerTypical10Mobile(benchmark.Benchmark): """Android typical 10 mobile power test.""" @@ -29,3 +28,21 @@ return 'power.typical_10_mobile' +@benchmark.Enabled('mac') +class PowerTop10(benchmark.Benchmark): + """Top 10 quiescent power test.""" + test = power.QuiescentPower + page_set = page_sets.Top10PageSet + @classmethod + def Name(cls): + return 'power.top_10' + + +@benchmark.Enabled('mac') +class PowerTop25(benchmark.Benchmark): + """Top 25 quiescent power test.""" + test = power.QuiescentPower + page_set = page_sets.Top25PageSet + @classmethod + def Name(cls): + return 'power.top_25'
diff --git a/tools/perf/benchmarks/rasterize_and_record_micro.py b/tools/perf/benchmarks/rasterize_and_record_micro.py index e7eba0e9..4ed3748d 100644 --- a/tools/perf/benchmarks/rasterize_and_record_micro.py +++ b/tools/perf/benchmarks/rasterize_and_record_micro.py
@@ -100,6 +100,24 @@ return page_sets.KeySilkCasesPageSet(run_no_page_interactions=True) +@benchmark.Disabled('mac', 'win', 'android') +@benchmark.Disabled('reference') +class RasterizeAndRecordMicroKeySilkWithSlimmingPaint(_RasterizeAndRecordMicro): + """Measures rasterize and record on the silk sites with slimming paint. + + http://www.chromium.org/developers/design-documents/rendering-benchmarks""" + + def CustomizeBrowserOptions(self, options): + options.AppendExtraBrowserArgs(['--enable-slimming-paint']) + + @classmethod + def Name(cls): + return 'rasterize_and_record_micro.key_silk_cases_with_slimming_paint' + + def CreatePageSet(self, options): + return page_sets.KeySilkCasesPageSet(run_no_page_interactions=True) + + @benchmark.Enabled('android') class RasterizeAndRecordMicroPolymer(_RasterizeAndRecordMicro): """Measures rasterize and record performance on the Polymer cases.
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py index eaa16f34..c8379c4 100644 --- a/tools/perf/benchmarks/smoothness.py +++ b/tools/perf/benchmarks/smoothness.py
@@ -77,9 +77,6 @@ def Name(cls): return 'smoothness.maps' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Disabled('android') class SmoothnessKeyDesktopMoveCases(benchmark.Benchmark): @@ -97,15 +94,13 @@ http://www.chromium.org/developers/design-documents/rendering-benchmarks """ + test = smoothness.Smoothness page_set = page_sets.KeyMobileSitesSmoothPageSet @classmethod def Name(cls): return 'smoothness.key_mobile_sites_smooth' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - class SmoothnessToughAnimationCases(benchmark.Benchmark): test = smoothness.Smoothness @@ -121,21 +116,20 @@ """Measures rendering statistics for the key silk cases without GPU rasterization. """ + test = smoothness.Smoothness page_set = page_sets.KeySilkCasesPageSet @classmethod def Name(cls): return 'smoothness.key_silk_cases' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android') class SmoothnessGpuRasterizationTop25(benchmark.Benchmark): """Measures rendering statistics for the top 25 with GPU rasterization. """ tag = 'gpu_rasterization' + test = smoothness.Smoothness page_set = page_sets.Top25SmoothPageSet def CustomizeBrowserOptions(self, options): @@ -145,9 +139,6 @@ def Name(cls): return 'smoothness.gpu_rasterization.top_25_smooth' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android') class SmoothnessGpuRasterizationKeyMobileSites(benchmark.Benchmark): @@ -155,6 +146,7 @@ rasterization. """ tag = 'gpu_rasterization' + test = smoothness.Smoothness page_set = page_sets.KeyMobileSitesSmoothPageSet def CustomizeBrowserOptions(self, options): @@ -164,9 +156,6 @@ def Name(cls): return 'smoothness.gpu_rasterization.key_mobile_sites_smooth' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android') class SmoothnessSyncScrollKeyMobileSites(benchmark.Benchmark): @@ -174,6 +163,7 @@ (main thread) scrolling. """ tag = 'sync_scroll' + test = smoothness.Smoothness page_set = page_sets.KeyMobileSitesSmoothPageSet def CustomizeBrowserOptions(self, options): @@ -183,28 +173,24 @@ def Name(cls): return 'smoothness.sync_scroll.key_mobile_sites_smooth' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android') class SmoothnessSimpleMobilePages(benchmark.Benchmark): """Measures rendering statistics for simple mobile sites page set. """ + test = smoothness.Smoothness page_set = page_sets.SimpleMobileSitesPageSet @classmethod def Name(cls): return 'smoothness.simple_mobile_sites' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android') class SmoothnessFlingSimpleMobilePages(benchmark.Benchmark): """Measures rendering statistics for flinging a simple mobile sites page set. """ + test = smoothness.Smoothness page_set = page_sets.SimpleMobileSitesFlingPageSet def CustomizeBrowserOptions(self, options): @@ -217,57 +203,49 @@ def Name(cls): return 'smoothness.fling.simple_mobile_sites' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android', 'chromeos') class SmoothnessToughPinchZoomCases(benchmark.Benchmark): """Measures rendering statistics for pinch-zooming into the tough pinch zoom cases. """ + test = smoothness.Smoothness page_set = page_sets.ToughPinchZoomCasesPageSet @classmethod def Name(cls): return 'smoothness.tough_pinch_zoom_cases' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - -@benchmark.Enabled('chromeos') +@benchmark.Enabled('android', 'chromeos') class SmoothnessToughScrollingWhileZoomedInCases(benchmark.Benchmark): """Measures rendering statistics for pinch-zooming then diagonal scrolling""" + test = smoothness.Smoothness page_set = page_sets.ToughScrollingWhileZoomedInCasesPageSet @classmethod def Name(cls): return 'smoothness.tough_scrolling_while_zoomed_in_cases' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android') class SmoothnessPolymer(benchmark.Benchmark): """Measures rendering statistics for Polymer cases. """ + test = smoothness.Smoothness page_set = page_sets.PolymerPageSet @classmethod def Name(cls): return 'smoothness.polymer' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android') class SmoothnessGpuRasterizationPolymer(benchmark.Benchmark): """Measures rendering statistics for the Polymer cases with GPU rasterization. """ tag = 'gpu_rasterization' + test = smoothness.Smoothness page_set = page_sets.PolymerPageSet def CustomizeBrowserOptions(self, options): @@ -277,9 +255,6 @@ def Name(cls): return 'smoothness.gpu_rasterization.polymer' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - class SmoothnessToughFastScrollingCases(benchmark.Benchmark): test = smoothness.Smoothness @@ -327,15 +302,13 @@ class SmoothnessPathologicalMobileSites(benchmark.Benchmark): """Measures task execution statistics while scrolling pathological sites. """ + test = smoothness.Smoothness page_set = page_sets.PathologicalMobileSitesPageSet @classmethod def Name(cls): return 'smoothness.pathological_mobile_sites' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - @benchmark.Enabled('android') class SmoothnessSyncScrollPathologicalMobileSites(benchmark.Benchmark): @@ -343,6 +316,7 @@ """ tag = 'sync_scroll' page_set = page_sets.PathologicalMobileSitesPageSet + test = smoothness.Smoothness def CustomizeBrowserOptions(self, options): silk_flags.CustomizeBrowserOptionsForSyncScrolling(options) @@ -351,9 +325,6 @@ def Name(cls): return 'smoothness.sync_scroll.pathological_mobile_sites' - def CreatePageTest(self, options): # pylint: disable=unused-argument - return smoothness.Smoothness(enable_auto_issuing_marker=False) - class SmoothnessToughAnimatedImageCases(benchmark.Benchmark): test = smoothness.Smoothness
diff --git a/tools/perf/measurements/blink_style.py b/tools/perf/measurements/blink_style.py index d3d7d648..f9ef875 100644 --- a/tools/perf/measurements/blink_style.py +++ b/tools/perf/measurements/blink_style.py
@@ -4,11 +4,9 @@ from itertools import starmap from collections import defaultdict - -from telemetry.core.platform import tracing_options from telemetry.core import util +from telemetry.core import exceptions from telemetry.page import page_test -from telemetry.timeline.model import TimelineModel from telemetry.value import scalar from measurements import timeline_controller @@ -21,7 +19,7 @@ def WillNavigateToPage(self, page, tab): self._controller = timeline_controller.TimelineController() - self._controller.trace_categories = 'blink,benchmark,blink.console' + self._controller.trace_categories = 'blink_style,blink.console' self._controller.SetUp(page, tab) self._controller.Start(tab) @@ -30,9 +28,15 @@ self._controller.CleanUp(tab) def ValidateAndMeasurePage(self, page, tab, results): - tab.WaitForDocumentReadyStateToBeComplete() - if not util.WaitFor(tab.HasReachedQuiescence, 30): - raise page_test.MeasurementFailure('Failed to reach quiesence.') + tab.ExecuteJavaScript('console.time("wait-for-quiescence");') + try: + util.WaitFor(tab.HasReachedQuiescence, 15) + except exceptions.TimeoutException: + # Some sites never reach quiesence. As this benchmark normalizes/ + # categories results, it shouldn't be necessary to reach the same + # state on every run. + pass + tab.ExecuteJavaScript('console.timeEnd("wait-for-quiescence");') tab.ExecuteJavaScript( 'console.time("style-update");' @@ -64,7 +68,10 @@ if (event.name == 'Document::updateStyle' and event.start >= marker.start and event.end <= marker.end): - access_count = event.args['resolverAccessCount'] + access_count = event.args.get('resolverAccessCount') + if access_count is None: + # absent in earlier versions + continue min_access_count = 50 if access_count >= min_access_count:
diff --git a/tools/perf/measurements/blink_style_unittest.py b/tools/perf/measurements/blink_style_unittest.py index 7ba416c..6b711f96 100644 --- a/tools/perf/measurements/blink_style_unittest.py +++ b/tools/perf/measurements/blink_style_unittest.py
@@ -4,7 +4,6 @@ from measurements import blink_style -from telemetry import decorators from telemetry.unittest_util import options_for_unittests from telemetry.unittest_util import page_test_test_case @@ -20,7 +19,6 @@ def setUp(self): self._options = options_for_unittests.GetCopy() - @decorators.Disabled # http://crbug.com/479048 def testForParsing(self): ps = self.CreatePageSetFromFileInUnittestDataDir('blink_style.html') measurement = blink_style.BlinkStyle()
diff --git a/tools/perf/measurements/oilpan_gc_times.py b/tools/perf/measurements/oilpan_gc_times.py index b4b1c9f..3621241 100644 --- a/tools/perf/measurements/oilpan_gc_times.py +++ b/tools/perf/measurements/oilpan_gc_times.py
@@ -8,12 +8,9 @@ from telemetry.core.platform import tracing_options from telemetry.page import action_runner from telemetry.page import page_test -from telemetry.results import results_options from telemetry.timeline.model import TimelineModel -from telemetry.util import statistics from telemetry.value import list_of_scalar_values from telemetry.value import scalar -from telemetry.value import trace _CR_RENDERER_MAIN = 'CrRendererMain'
diff --git a/tools/perf/measurements/oilpan_gc_times_unittest.py b/tools/perf/measurements/oilpan_gc_times_unittest.py index 8e9a2cbd..9b448d8 100644 --- a/tools/perf/measurements/oilpan_gc_times_unittest.py +++ b/tools/perf/measurements/oilpan_gc_times_unittest.py
@@ -7,7 +7,6 @@ from telemetry.results import page_test_results from telemetry.timeline import model from telemetry.timeline import slice as slice_data -from telemetry.timeline.event import TimelineEvent from telemetry.unittest_util import options_for_unittests from telemetry.unittest_util import page_test_test_case from telemetry.page import page as page_module @@ -64,7 +63,6 @@ def ClearResults(self): self._results = page_test_results.PageTestResults() - class OilpanGCTimesTest(page_test_test_case.PageTestTestCase): """Smoke test for Oilpan GC pause time measurements. @@ -81,6 +79,8 @@ def setUp(self): self._options = options_for_unittests.GetCopy() + # Disable for accessing private API of _OilpanGCTimesBase. + # pylint: disable=protected-access def testForParsingOldFormat(self): def getMetric(results, name): metrics = results.FindAllPageSpecificValuesNamed(name) @@ -110,6 +110,8 @@ self.assertEquals(2, len(getMetric(results, 'oilpan_forced_complete_sweep'))) + # Disable for accessing private API of _OilpanGCTimesBase. + # pylint: disable=protected-access def testForParsing(self): def getMetric(results, name): metrics = results.FindAllPageSpecificValuesNamed(name)
diff --git a/tools/perf/measurements/page_cycler_unittest.py b/tools/perf/measurements/page_cycler_unittest.py index c6ce636..a29737a 100644 --- a/tools/perf/measurements/page_cycler_unittest.py +++ b/tools/perf/measurements/page_cycler_unittest.py
@@ -227,7 +227,7 @@ # On Mac, there is an additional measurement: the number of keychain # accesses. - value_count = 4 + value_count = 3 if sys.platform == 'darwin': value_count += 1 self.assertEqual(value_count, len(values)) @@ -237,7 +237,7 @@ self.assertEqual(values[0].name, '%s.page_load_time' % chart_name) self.assertEqual(values[0].units, 'ms') - expected_values = ['gpu', 'renderer', 'browser'] + expected_values = ['gpu', 'browser'] for value, expected in zip(values[1:len(expected_values) + 1], expected_values): self.assertEqual(value.page, page)
diff --git a/tools/perf/measurements/power.py b/tools/perf/measurements/power.py index 2552539..d5521fb 100644 --- a/tools/perf/measurements/power.py +++ b/tools/perf/measurements/power.py
@@ -2,22 +2,55 @@ # 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_test +import time +from metrics import network from metrics import power +from telemetry.core import util +from telemetry.page import page_test class Power(page_test.PageTest): + """Measures power draw and idle wakeups during the page's interactions.""" + def __init__(self): super(Power, self).__init__() self._power_metric = None + self._network_metric = None def WillStartBrowser(self, platform): self._power_metric = power.PowerMetric(platform) + self._network_metric = network.NetworkMetric(platform) + + def WillNavigateToPage(self, page, tab): + self._network_metric.Start(page, tab) def DidNavigateToPage(self, page, tab): self._power_metric.Start(page, tab) def ValidateAndMeasurePage(self, page, tab, results): + self._network_metric.Stop(page, tab) self._power_metric.Stop(page, tab) + self._network_metric.AddResults(tab, results) self._power_metric.AddResults(tab, results) + + +class QuiescentPower(page_test.PageTest): + """Measures power draw and idle wakeups after the page finished loading.""" + + # Amount of time to measure, in seconds. + SAMPLE_TIME = 30 + + def ValidateAndMeasurePage(self, page, tab, results): + if not tab.browser.platform.CanMonitorPower(): + return + + util.WaitFor(tab.HasReachedQuiescence, 60) + + metric = power.PowerMetric(tab.browser.platform) + metric.Start(page, tab) + + time.sleep(QuiescentPower.SAMPLE_TIME) + + metric.Stop(page, tab) + metric.AddResults(tab, results)
diff --git a/tools/perf/measurements/rasterize_and_record_micro.py b/tools/perf/measurements/rasterize_and_record_micro.py index 209b0415..131cc5e 100644 --- a/tools/perf/measurements/rasterize_and_record_micro.py +++ b/tools/perf/measurements/rasterize_and_record_micro.py
@@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import sys import time from telemetry.core import exceptions @@ -88,10 +87,12 @@ record_time_painting_disabled = data['record_time_painting_disabled_ms'] # TODO(schenney): Remove this workaround when reference builds get past # the change that adds this comment. - if ('record_time_caching_disabled_ms' in data): - record_time_caching_disabled = data['record_time_caching_disabled_ms'] - else: - record_time_caching_disabled = 0 + record_time_caching_disabled = \ + data.get('record_time_caching_disabled_ms', 0) + # TODO(schenney): Remove this workaround when reference builds get past + # the change that adds this comment. + record_time_construction_disabled = \ + data.get('record_time_construction_disabled_ms', 0) results.AddValue(scalar.ScalarValue( results.current_page, 'record_time_sk_null_canvas', 'ms', record_time_sk_null_canvas)) @@ -101,6 +102,9 @@ results.AddValue(scalar.ScalarValue( results.current_page, 'record_time_caching_disabled', 'ms', record_time_caching_disabled)) + results.AddValue(scalar.ScalarValue( + results.current_page, 'record_time_construction_disabled', 'ms', + record_time_construction_disabled)) if self._report_detailed_results: pixels_rasterized_with_non_solid_color = \
diff --git a/tools/perf/measurements/repaint.py b/tools/perf/measurements/repaint.py index ec4e5f1b..454fcaa 100644 --- a/tools/perf/measurements/repaint.py +++ b/tools/perf/measurements/repaint.py
@@ -21,10 +21,8 @@ def WillRunActions(self, page, tab): tab.WaitForDocumentReadyStateToBeComplete() - self._smoothness_controller = smoothness_controller.SmoothnessController( - auto_issuing_marker=False) - self._smoothness_controller.SetUp(page, tab) - self._smoothness_controller.Start(tab) + self._smoothness_controller = smoothness_controller.SmoothnessController() + self._smoothness_controller.Start(page, tab) def DidRunActions(self, page, tab): self._smoothness_controller.Stop(tab)
diff --git a/tools/perf/measurements/session_restore.py b/tools/perf/measurements/session_restore.py index 99f323d..a0f93601 100644 --- a/tools/perf/measurements/session_restore.py +++ b/tools/perf/measurements/session_restore.py
@@ -2,15 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import collections - from telemetry.core import util from telemetry.value import histogram from telemetry.value import histogram_util from measurements import startup from metrics import cpu -from metrics import startup_metric _HISTOGRAMS = [
diff --git a/tools/perf/measurements/smoothness.py b/tools/perf/measurements/smoothness.py index 6cf2741..da2392d4 100644 --- a/tools/perf/measurements/smoothness.py +++ b/tools/perf/measurements/smoothness.py
@@ -8,10 +8,9 @@ class Smoothness(page_test.PageTest): - def __init__(self, enable_auto_issuing_marker=False): + def __init__(self): super(Smoothness, self).__init__() self._smoothness_controller = None - self._enable_auto_issuing_marker = enable_auto_issuing_marker @classmethod def CustomizeBrowserOptions(cls, options): @@ -20,12 +19,8 @@ options.AppendExtraBrowserArgs('--running-performance-benchmark') def WillNavigateToPage(self, page, tab): - self._smoothness_controller = smoothness_controller.SmoothnessController( - auto_issuing_marker=self._enable_auto_issuing_marker) - self._smoothness_controller.SetUp(page, tab) - - def WillRunActions(self, page, tab): - self._smoothness_controller.Start(tab) + self._smoothness_controller = smoothness_controller.SmoothnessController() + self._smoothness_controller.Start(page, tab) def DidRunActions(self, page, tab): self._smoothness_controller.Stop(tab)
diff --git a/tools/perf/measurements/smoothness_controller.py b/tools/perf/measurements/smoothness_controller.py index 95c71df..31d2a5a 100644 --- a/tools/perf/measurements/smoothness_controller.py +++ b/tools/perf/measurements/smoothness_controller.py
@@ -1,23 +1,15 @@ # 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. -import sys - from telemetry.core.platform import tracing_category_filter from telemetry.core.platform import tracing_options -from telemetry.page import action_runner -from telemetry.page import page_test from telemetry.timeline.model import TimelineModel -from telemetry.timeline import trace_data as trace_data_module -from telemetry.value import list_of_scalar_values -from telemetry.value import scalar from telemetry.value import trace from telemetry.web_perf.metrics import smoothness from telemetry.web_perf import smooth_gesture_util from telemetry.web_perf import timeline_interaction_record as tir_module - -RUN_SMOOTH_ACTIONS = 'RunSmoothAllActions' +from telemetry.page import page_test class SmoothnessController(object): @@ -26,9 +18,8 @@ self._trace_data = None self._interaction = None self._surface_flinger_trace_data = None - self._auto_issuing_marker = auto_issuing_marker - def SetUp(self, page, tab): + def Start(self, page, tab): # FIXME: Remove webkit.console when blink.console lands in chromium and # the ref builds are updated. crbug.com/386847 custom_categories = ['webkit.console', 'blink.console', 'benchmark'] @@ -41,18 +32,7 @@ options.enable_platform_display_trace = True tab.browser.platform.tracing_controller.Start(options, category_filter, 60) - def Start(self, tab): - # Start the smooth marker for all smooth actions. - runner = action_runner.ActionRunner(tab) - if self._auto_issuing_marker: - self._interaction = runner.CreateInteraction( - RUN_SMOOTH_ACTIONS) - self._interaction.Begin() - def Stop(self, tab): - # End the smooth marker for all smooth actions. - if self._auto_issuing_marker: - self._interaction.End() self._trace_data = tab.browser.platform.tracing_controller.Stop() self._timeline_model = TimelineModel(self._trace_data) @@ -64,35 +44,35 @@ results.current_page, self._trace_data)) renderer_thread = self._timeline_model.GetRendererThreadFromTabId( tab.id) - run_smooth_actions_record = None smooth_records = [] for event in renderer_thread.async_slices: if not tir_module.IsTimelineInteractionRecord(event.name): continue r = tir_module.TimelineInteractionRecord.FromAsyncEvent(event) - if r.label == RUN_SMOOTH_ACTIONS: - assert run_smooth_actions_record is None, ( - 'SmoothnessController cannot issue more than 1 %s record' % - RUN_SMOOTH_ACTIONS) - run_smooth_actions_record = r - else: - smooth_records.append( - smooth_gesture_util.GetAdjustedInteractionIfContainGesture( - self._timeline_model, r)) + smooth_records.append( + smooth_gesture_util.GetAdjustedInteractionIfContainGesture( + self._timeline_model, r)) # If there is no other smooth records, we make measurements on time range # marked smoothness_controller itself. # TODO(nednguyen): when crbug.com/239179 is marked fixed, makes sure that # page sets are responsible for issueing the markers themselves. if len(smooth_records) == 0: - if run_smooth_actions_record is None: - sys.stderr.write('Raw tracing data:\n') - self._trace_data.Serialize(sys.stderr) - sys.stderr.write('\n') - raise Exception('SmoothnessController failed to issue markers for the ' - 'whole interaction.') - else: - smooth_records = [run_smooth_actions_record] + raise page_test.Failure('Page failed to issue any markers.') + + # Check to make sure all smooth records have same label and repeatable if + # there are more than one. + need_repeatable_flag = len(smooth_records) > 1 + record_label = smooth_records[0].label + for r in smooth_records: + if r.label != record_label: + raise page_test.Failure( + 'SmoothController does not support multiple interactions with ' + 'different label. Interactions: %s' % repr(smooth_records)) + if need_repeatable_flag and not r.repeatable: + raise page_test.Failure( + 'If there are more than one interaction record, each interaction ' + 'must has repeatable flag. Interactions: %s' % repr(smooth_records)) # Create an interaction_record for this legacy measurement. Since we don't # wrap the results that are sent to smoothness metric, the label will
diff --git a/tools/perf/measurements/smoothness_unittest.py b/tools/perf/measurements/smoothness_unittest.py index 1a4f4e9..dcfcc27 100644 --- a/tools/perf/measurements/smoothness_unittest.py +++ b/tools/perf/measurements/smoothness_unittest.py
@@ -3,7 +3,6 @@ # found in the LICENSE file. import sys -from telemetry.core import exceptions from telemetry.core import wpr_modes from telemetry import decorators from telemetry.page import page
diff --git a/tools/perf/measurements/task_execution_time_unittest.py b/tools/perf/measurements/task_execution_time_unittest.py index 827377f..8a763124 100644 --- a/tools/perf/measurements/task_execution_time_unittest.py +++ b/tools/perf/measurements/task_execution_time_unittest.py
@@ -25,6 +25,8 @@ action_runner.ScrollPage() +# Disable for accessing private API of task_execution_time. +# pylint: disable=protected-access class TaskExecutionTimeUnitTest(page_test_test_case.PageTestTestCase): def setUp(self):
diff --git a/tools/perf/measurements/v8_detached_context_age_in_gc.py b/tools/perf/measurements/v8_detached_context_age_in_gc.py index 0e0cf82..d36b1630 100644 --- a/tools/perf/measurements/v8_detached_context_age_in_gc.py +++ b/tools/perf/measurements/v8_detached_context_age_in_gc.py
@@ -5,7 +5,6 @@ import json from telemetry.page import page_test -from telemetry.value import histogram from telemetry.value import histogram_util from telemetry.value import scalar from telemetry.value import skip
diff --git a/tools/perf/measurements/v8_detached_context_age_in_gc_unittest.py b/tools/perf/measurements/v8_detached_context_age_in_gc_unittest.py index 4ae6f8d..79962a6f 100644 --- a/tools/perf/measurements/v8_detached_context_age_in_gc_unittest.py +++ b/tools/perf/measurements/v8_detached_context_age_in_gc_unittest.py
@@ -4,11 +4,9 @@ from telemetry.core import wpr_modes from telemetry.page import page as page_module -from telemetry.page import page_test from telemetry.results import page_test_results from telemetry.unittest_util import options_for_unittests from telemetry.unittest_util import page_test_test_case -from telemetry.value import skip from measurements import v8_detached_context_age_in_gc
diff --git a/tools/perf/measurements/v8_gc_times.py b/tools/perf/measurements/v8_gc_times.py index 1f3cb77..ebb36f4 100644 --- a/tools/perf/measurements/v8_gc_times.py +++ b/tools/perf/measurements/v8_gc_times.py
@@ -169,6 +169,7 @@ def _ParentIdleTask(event): parent = event.parent_slice while parent: + # pylint: disable=protected-access if parent.name == V8GCTimes._IDLE_TASK_PARENT: return parent parent = parent.parent_slice
diff --git a/tools/perf/measurements/v8_gc_times_unittest.py b/tools/perf/measurements/v8_gc_times_unittest.py index c13089c..9212277 100644 --- a/tools/perf/measurements/v8_gc_times_unittest.py +++ b/tools/perf/measurements/v8_gc_times_unittest.py
@@ -46,6 +46,7 @@ results.WillRunPage(page) v8_gc_times_metric = v8_gc_times.V8GCTimes() + # pylint: disable=protected-access v8_gc_times_metric._renderer_process = self._renderer_process # Finalize the timeline import.
diff --git a/tools/perf/metrics/cpu.py b/tools/perf/metrics/cpu.py index 35c3403..66424d4 100644 --- a/tools/perf/metrics/cpu.py +++ b/tools/perf/metrics/cpu.py
@@ -32,6 +32,12 @@ def AddResults(self, tab, results, trace_name='cpu_utilization'): assert self._stop_cpu, 'Must call Stop() first' cpu_stats = _SubtractCpuStats(self._stop_cpu, self._start_cpu) + + # FIXME: Renderer process CPU times are impossible to compare correctly. + # http://crbug.com/419786#c11 + if 'Renderer' in cpu_stats: + del cpu_stats['Renderer'] + # Add a result for each process type. for process_type in cpu_stats: trace_name_for_process = '%s_%s' % (trace_name, process_type.lower())
diff --git a/tools/perf/metrics/network.py b/tools/perf/metrics/network.py new file mode 100644 index 0000000..f71795d --- /dev/null +++ b/tools/perf/metrics/network.py
@@ -0,0 +1,68 @@ +# 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.value import scalar + +from metrics import Metric + + +NETWORK_DATA_NOT_FOUND = 'Network data could not be found.' + + +# This is experimental. crbug.com/480512 +# Will not be supported once network data is ported to TimelineBasedMetric. +class NetworkMetric(Metric): + """NetworkMetrics gathers network statistics.""" + + def __init__(self, platform): + super(NetworkMetric, self).__init__() + self._network_snd = None + self._network_rcv = None + self._platform = platform + self._browser = None + + def Start(self, _, tab): + """Start the per-page preparation for this metric. + + Here, this consists of recording the start value. + """ + self._browser = tab.browser + if not self._platform.CanMonitorNetworkData(): + return + + data = self._platform.GetNetworkData(self._browser) + if data is not None: + self._network_snd, self._network_rcv = data + + def Stop(self, _, tab): + """Prepare the results for this page. + + The results are the differences between the current values + and the values when Start() was called. + """ + if not self._platform.CanMonitorNetworkData(): + return + + data = self._platform.GetNetworkData(self._browser) + if data is not None: + snd, rcv = data + if self._network_snd is not None: + self._network_snd = snd - self._network_snd + if self._network_rcv is not None: + self._network_rcv = rcv - self._network_rcv + else: # If end data cannot be found, report none. + self._network_snd = None + self._network_rcv = None + + def AddResults(self, tab, results): + none_value_reason = ( + None if self._network_snd is not None else NETWORK_DATA_NOT_FOUND) + results.AddValue(scalar.ScalarValue( + results.current_page, 'network_data_sent', 'kb', self._network_snd, + important=False, none_value_reason=none_value_reason)) + none_value_reason = ( + None if self._network_rcv is not None else NETWORK_DATA_NOT_FOUND) + results.AddValue(scalar.ScalarValue( + results.current_page, 'network_data_received', 'kb', self._network_rcv, + important=False, none_value_reason=none_value_reason))
diff --git a/tools/perf/metrics/speedindex.py b/tools/perf/metrics/speedindex.py index 634c8bda..a069cd1 100644 --- a/tools/perf/metrics/speedindex.py +++ b/tools/perf/metrics/speedindex.py
@@ -2,9 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import collections -import logging - from telemetry.image_processing import image_util from telemetry.image_processing import rgba_color from telemetry.value import scalar
diff --git a/tools/perf/metrics/speedindex_unittest.py b/tools/perf/metrics/speedindex_unittest.py index 760ff73f..26e8412b 100644 --- a/tools/perf/metrics/speedindex_unittest.py +++ b/tools/perf/metrics/speedindex_unittest.py
@@ -5,8 +5,6 @@ # These tests access private methods in the speedindex module. # pylint: disable=W0212 -import json -import os import unittest from telemetry.image_processing import histogram
diff --git a/tools/perf/page_sets/key_hit_test_cases.py b/tools/perf/page_sets/key_hit_test_cases.py index e308de9..a0dd0ce1 100644 --- a/tools/perf/page_sets/key_hit_test_cases.py +++ b/tools/perf/page_sets/key_hit_test_cases.py
@@ -2,7 +2,6 @@ # 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 page_set as page_set_module from page_sets import polymer
diff --git a/tools/perf/page_sets/key_silk_cases.py b/tools/perf/page_sets/key_silk_cases.py index 347ed92..9c35a7cb 100644 --- a/tools/perf/page_sets/key_silk_cases.py +++ b/tools/perf/page_sets/key_silk_cases.py
@@ -319,13 +319,16 @@ self.StressHideyBars(action_runner) def StressHideyBars(self, action_runner): - with action_runner.CreateGestureInteraction('ScrollAction'): + with action_runner.CreateGestureInteraction( + 'ScrollAction', repeatable=True): action_runner.ScrollElement( selector='#messages', direction='down', speed_in_pixels_per_second=200) - with action_runner.CreateGestureInteraction('ScrollAction'): + with action_runner.CreateGestureInteraction( + 'ScrollAction', repeatable=True): action_runner.ScrollElement( selector='#messages', direction='up', speed_in_pixels_per_second=200) - with action_runner.CreateGestureInteraction('ScrollAction'): + with action_runner.CreateGestureInteraction( + 'ScrollAction', repeatable=True): action_runner.ScrollElement( selector='#messages', direction='down', speed_in_pixels_per_second=200) @@ -343,7 +346,7 @@ self.ToggleDrawer(action_runner) def ToggleDrawer(self, action_runner): - with action_runner.CreateInteraction('Action_TapAction'): + with action_runner.CreateInteraction('Action_TapAction', repeatable=True): action_runner.TapElement('#menu-button') action_runner.Wait(1) @@ -482,12 +485,14 @@ page_set=page_set, run_no_page_interactions=run_no_page_interactions) def PerformPageInteractions(self, action_runner): - with action_runner.CreateGestureInteraction('ScrollAction'): + with action_runner.CreateGestureInteraction('ScrollAction', + repeatable=True): action_runner.ScrollPage( distance_expr='window.innerHeight / 2', direction='down', use_touch=True) - with action_runner.CreateInteraction('Wait'): + with action_runner.CreateGestureInteraction('ScrollAction', + repeatable=True): action_runner.Wait(1) @@ -530,11 +535,11 @@ action_runner.Wait(1) def PerformPageInteractions(self, action_runner): - with action_runner.CreateGestureInteraction('SwipeAction'): + with action_runner.CreateGestureInteraction('SwipeAction', repeatable=True): action_runner.SwipeElement( direction='left', distance=100, element_function='document.getElementById(":f")') - with action_runner.CreateInteraction('Wait'): + with action_runner.CreateGestureInteraction('SwipeAction', repeatable=True): action_runner.Wait(1) @@ -577,7 +582,7 @@ for i in xrange(9): button_func = ('document.getElementById("demo").$.' 'buttons.children[%d]') % i - with action_runner.CreateInteraction('Action_TapAction'): + with action_runner.CreateInteraction('Action_TapAction', repeatable=True): action_runner.TapElement(element_function=button_func) action_runner.Wait(1)
diff --git a/tools/perf/page_sets/page_reload_cases.py b/tools/perf/page_sets/page_reload_cases.py index 25eeb24a..00765a7b 100644 --- a/tools/perf/page_sets/page_reload_cases.py +++ b/tools/perf/page_sets/page_reload_cases.py
@@ -1,7 +1,6 @@ # 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.page import page as page_module from telemetry.page import page_set as page_set_module from page_sets import top_pages
diff --git a/tools/perf/page_sets/polymer.py b/tools/perf/page_sets/polymer.py index bbab4d4..e75fc09c 100644 --- a/tools/perf/page_sets/polymer.py +++ b/tools/perf/page_sets/polymer.py
@@ -53,7 +53,7 @@ self.SlidePanel(action_runner) def TapButton(self, action_runner): - with action_runner.CreateInteraction('Action_TapAction'): + with action_runner.CreateInteraction('PolymerAnimation', repeatable=True): action_runner.TapElement(element_function=''' document.querySelector( 'body /deep/ #outerPanels' @@ -72,7 +72,7 @@ return outer.opened || outer.wideMode; }());''') if not opened: - with action_runner.CreateInteraction('Action_SwipeAction'): + with action_runner.CreateInteraction('PolymerAnimation', repeatable=True): action_runner.SwipeElement( left_start_ratio=0.1, top_start_ratio=0.2, direction='left', distance=300, speed_in_pixels_per_second=5000, @@ -155,12 +155,12 @@ def ScrollContentPane(self, action_runner): element_function = (self.iframe_js + '.querySelector(' '"core-scroll-header-panel").$.mainContainer') - with action_runner.CreateInteraction('Scroll_Page'): + with action_runner.CreateInteraction('Scroll_Page', repeatable=True): action_runner.ScrollElement(use_touch=True, direction='down', distance='900', element_function=element_function) - with action_runner.CreateInteraction('Scroll_Page'): + with action_runner.CreateInteraction('Scroll_Page', repeatable=True): action_runner.ScrollElement(use_touch=True, direction='up', distance='900', @@ -201,7 +201,7 @@ action_function(action_runner, element_query) def TapWidget(self, action_runner, element_function): - with action_runner.CreateInteraction('Tap_Widget'): + with action_runner.CreateInteraction('Tap_Widget', repeatable=True): action_runner.TapElement(element_function=element_function) action_runner.Wait(1) # wait for e.g. animations on the widget
diff --git a/tools/perf/page_sets/simple_mobile_sites_fling.py b/tools/perf/page_sets/simple_mobile_sites_fling.py index bc44765..7619944a 100644 --- a/tools/perf/page_sets/simple_mobile_sites_fling.py +++ b/tools/perf/page_sets/simple_mobile_sites_fling.py
@@ -3,7 +3,6 @@ # found in the LICENSE file. from page_sets import fling_gesture_supported_shared_state -from telemetry.page import shared_page_state from telemetry.page import page as page_module from telemetry.page import page_set as page_set_module
diff --git a/tools/perf/page_sets/tough_scrolling_while_zoomed_in_cases.py b/tools/perf/page_sets/tough_scrolling_while_zoomed_in_cases.py index 243e25a..bc8f5a4 100644 --- a/tools/perf/page_sets/tough_scrolling_while_zoomed_in_cases.py +++ b/tools/perf/page_sets/tough_scrolling_while_zoomed_in_cases.py
@@ -3,10 +3,8 @@ # found in the LICENSE file. from page_sets import diagonal_scrolling_supported_shared_state -from telemetry.page import shared_page_state from telemetry.page import page as page_module from telemetry.page import page_set as page_set_module -from telemetry.core.backends.chrome_inspector import devtools_client_backend class ToughScrollingWhileZoomedInCasesPage(page_module.Page):
diff --git a/tools/perf/page_sets/tough_webgl_cases.py b/tools/perf/page_sets/tough_webgl_cases.py index 099fb9a..843f9b2 100644 --- a/tools/perf/page_sets/tough_webgl_cases.py +++ b/tools/perf/page_sets/tough_webgl_cases.py
@@ -4,7 +4,6 @@ from telemetry.page import page as page_module from telemetry.page import page_set as page_set_module -from telemetry.page import shared_page_state from page_sets import webgl_supported_shared_state
diff --git a/tools/perf/page_sets/webrtc_cases.py b/tools/perf/page_sets/webrtc_cases.py index 6c09634f..41010b84 100644 --- a/tools/perf/page_sets/webrtc_cases.py +++ b/tools/perf/page_sets/webrtc_cases.py
@@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import os -import tempfile from telemetry.page import page as page_module from telemetry.page import page_set as page_set_module
diff --git a/tools/perf/profile_creators/cookie_profile_extender.py b/tools/perf/profile_creators/cookie_profile_extender.py index ad9e85d8..cb53363b 100644 --- a/tools/perf/profile_creators/cookie_profile_extender.py +++ b/tools/perf/profile_creators/cookie_profile_extender.py
@@ -8,7 +8,6 @@ import page_sets from profile_creators import fast_navigation_profile_extender -from profile_creators import profile_safe_url_list class CookieProfileExtender( fast_navigation_profile_extender.FastNavigationProfileExtender):
diff --git a/tools/perf/profile_creators/fast_navigation_profile_extender_unittest.py b/tools/perf/profile_creators/fast_navigation_profile_extender_unittest.py index c514947..86e6c81 100644 --- a/tools/perf/profile_creators/fast_navigation_profile_extender_unittest.py +++ b/tools/perf/profile_creators/fast_navigation_profile_extender_unittest.py
@@ -9,7 +9,7 @@ from telemetry.unittest_util import options_for_unittests util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'mock') -import mock +import mock # pylint: disable=import-error class FakeTab(object):
diff --git a/tools/perf/profile_creators/history_profile_extender_unittest.py b/tools/perf/profile_creators/history_profile_extender_unittest.py index 46997cd..022e957 100644 --- a/tools/perf/profile_creators/history_profile_extender_unittest.py +++ b/tools/perf/profile_creators/history_profile_extender_unittest.py
@@ -12,7 +12,7 @@ from telemetry.unittest_util import options_for_unittests util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'mock') -import mock +import mock # pylint: disable=import-error # Testing private method.
diff --git a/tools/perf/pylintrc b/tools/perf/pylintrc index b112c527..964cc02 100644 --- a/tools/perf/pylintrc +++ b/tools/perf/pylintrc
@@ -1,8 +1,8 @@ [MESSAGES CONTROL] # Disable the message, report, category or checker with the given id(s). -# TODO(nednguyen): Remove unusued-argument and unused-import from this list. -disable=I0010,I0011,abstract-class-little-used,abstract-class-not-used,anomalous-backslash-in-string,bad-builtin,bad-context-manager,bad-continuation,bad-indentation,bad-str-strip-call,bad-whitespace,broad-except,cell-var-from-loop,deprecated-lambda,deprecated-module,duplicate-code,eval-used,exec-used,fixme,function-redefined,global-statement,import-error,interface-not-implemented,invalid-name,locally-enabled,logging-not-lazy,missing-docstring,missing-final-newline,no-init,no-member,no-name-in-module,no-self-use,no-self-use,not-callable,old-style-class,protected-access,reimported,star-args,super-on-old-class,superfluous-parens,too-few-public-methods,too-many-ancestors,too-many-arguments,too-many-branches,too-many-function-args,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-return-statements,too-many-statements,trailing-whitespace,unnecessary-semicolon,unpacking-non-sequence,useless-else-on-loop,unused-argument,unused-import +# TODO(perf-owners): Reduce this list to as small as possible. +disable=I0010,I0011,abstract-class-little-used,abstract-class-not-used,anomalous-backslash-in-string,bad-builtin,bad-context-manager,bad-continuation,bad-indentation,bad-str-strip-call,bad-whitespace,broad-except,cell-var-from-loop,deprecated-lambda,deprecated-module,duplicate-code,eval-used,exec-used,fixme,function-redefined,global-statement,interface-not-implemented,invalid-name,locally-enabled,logging-not-lazy,missing-docstring,missing-final-newline,no-init,no-member,no-name-in-module,no-self-use,no-self-use,not-callable,old-style-class,reimported,star-args,super-on-old-class,superfluous-parens,too-few-public-methods,too-many-ancestors,too-many-arguments,too-many-branches,too-many-function-args,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-return-statements,too-many-statements,trailing-whitespace,unnecessary-semicolon,unpacking-non-sequence,useless-else-on-loop,unused-argument [REPORTS]
diff --git a/tools/perf/update_reference_build.py b/tools/perf/update_reference_build.py index d538f17..6997c481 100755 --- a/tools/perf/update_reference_build.py +++ b/tools/perf/update_reference_build.py
@@ -26,8 +26,6 @@ import shutil import subprocess import sys -import time -import urllib import urllib2 import zipfile
diff --git a/tools/perf/update_reference_build_unittest.py b/tools/perf/update_reference_build_unittest.py index 2eb9fb0..e02dee0 100644 --- a/tools/perf/update_reference_build_unittest.py +++ b/tools/perf/update_reference_build_unittest.py
@@ -6,6 +6,8 @@ import update_reference_build as update_ref_build +# Disable for accessing private API of update_reference_build class. +# pylint: disable=protected-access class UpdateReferenceBuildUnittest(unittest.TestCase): def testInit(self): @classmethod
diff --git a/tools/perf_expectations/perf_expectations.json b/tools/perf_expectations/perf_expectations.json index 858241e5..6bfbeb894 100644 --- a/tools/perf_expectations/perf_expectations.json +++ b/tools/perf_expectations/perf_expectations.json
@@ -381,9 +381,9 @@ "linux-release/sizes/nacl_helper_bootstrap-text/text": {"reva": 256743, "revb": 256743, "type": "absolute", "better": "lower", "improve": 4882, "regress": 5396, "sha1": "ffc106e5"}, "linux-release/sizes/nacl_helper_bootstrap/nacl_helper_bootstrap": {"reva": 114822, "revb": 115019, "type": "absolute", "better": "lower", "improve": 8776, "regress": 9700, "sha1": "3f284fed"}, "linux-release/sizes/totals-textrel/textrel": {"reva": 205083, "revb": 206071, "type": "absolute", "better": "lower", "improve": 1075, "regress": 1189, "sha1": "69d07fda"}, - "mac-release/sizes/Chromium.app/Chromium.app": {"reva": 305049, "revb": 305099, "type": "absolute", "better": "lower", "improve": 150118604, "regress": 165929165, "sha1": "6133e499"}, + "mac-release/sizes/Chromium.app/Chromium.app": {"reva": 326940, "revb": 326990, "type": "absolute", "better": "lower", "improve": 155912232, "regress": 159128167, "tolerance": 0.01, "sha1": "0e4899e7"}, "mac-release/sizes/Chromium/Chromium": {"reva": 165473, "revb": 165473, "type": "absolute", "better": "lower", "improve": 8132, "regress": 8988, "sha1": "8e448691"}, - "mac-release/sizes/ChromiumFramework/ChromiumFramework": {"reva": 314575, "revb": 314597, "type": "absolute", "better": "lower", "improve": 96029781, "regress": 106138196, "sha1": "e601ccfe"}, + "mac-release/sizes/ChromiumFramework/ChromiumFramework": {"reva": 326940, "revb": 326990, "type": "absolute", "better": "lower", "improve": 102571179, "regress": 104681006, "tolerance": 0.01, "sha1": "f9819a70"}, "mac-release/sizes/chrome-si/initializers": {"reva": 281731, "revb": 281731, "type": "absolute", "better": "lower", "improve": 0, "regress": 0, "tolerance": 0, "sha1": "01759b7f"}, "win-release/media_tests_av_perf/audio_latency/latency": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 57, "regress": 69, "sha1": "169d47dd"}, "win-release/media_tests_av_perf/audio_latency/latency_bg_clip": {"reva": 199840, "revb": 201303, "type": "absolute", "better": "lower", "improve": 66, "regress": 78, "sha1": "708a71af"},
diff --git a/tools/telemetry/pylintrc b/tools/telemetry/pylintrc index b112c527..b05eada8 100644 --- a/tools/telemetry/pylintrc +++ b/tools/telemetry/pylintrc
@@ -2,7 +2,7 @@ # Disable the message, report, category or checker with the given id(s). # TODO(nednguyen): Remove unusued-argument and unused-import from this list. -disable=I0010,I0011,abstract-class-little-used,abstract-class-not-used,anomalous-backslash-in-string,bad-builtin,bad-context-manager,bad-continuation,bad-indentation,bad-str-strip-call,bad-whitespace,broad-except,cell-var-from-loop,deprecated-lambda,deprecated-module,duplicate-code,eval-used,exec-used,fixme,function-redefined,global-statement,import-error,interface-not-implemented,invalid-name,locally-enabled,logging-not-lazy,missing-docstring,missing-final-newline,no-init,no-member,no-name-in-module,no-self-use,no-self-use,not-callable,old-style-class,protected-access,reimported,star-args,super-on-old-class,superfluous-parens,too-few-public-methods,too-many-ancestors,too-many-arguments,too-many-branches,too-many-function-args,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-return-statements,too-many-statements,trailing-whitespace,unnecessary-semicolon,unpacking-non-sequence,useless-else-on-loop,unused-argument,unused-import +disable=I0010,I0011,abstract-class-little-used,abstract-class-not-used,anomalous-backslash-in-string,bad-builtin,bad-continuation,bad-indentation,bad-str-strip-call,bad-whitespace,broad-except,cell-var-from-loop,deprecated-lambda,deprecated-module,duplicate-code,fixme,global-statement,import-error,interface-not-implemented,invalid-name,locally-enabled,logging-not-lazy,missing-docstring,no-init,no-member,no-name-in-module,no-self-use,not-callable,old-style-class,protected-access,star-args,superfluous-parens,too-few-public-methods,too-many-ancestors,too-many-arguments,too-many-branches,too-many-function-args,too-many-instance-attributes,too-many-lines,too-many-locals,too-many-public-methods,too-many-return-statements,too-many-statements,unpacking-non-sequence,unused-argument,unused-import [REPORTS]
diff --git a/tools/telemetry/telemetry/core/backends/chrome/oobe.py b/tools/telemetry/telemetry/core/backends/chrome/oobe.py index 5bf226f..16bb89c 100644 --- a/tools/telemetry/telemetry/core/backends/chrome/oobe.py +++ b/tools/telemetry/telemetry/core/backends/chrome/oobe.py
@@ -13,20 +13,30 @@ def __init__(self, inspector_backend): super(Oobe, self).__init__(inspector_backend) - def _GaiaLoginContext(self): + def _GaiaIFrameContext(self): max_context_id = self.EnableAllContexts() logging.debug('%d contexts in Gaia page' % max_context_id) - for gaia_context in range(max_context_id + 1): + for gaia_iframe_context in range(max_context_id + 1): try: if self.EvaluateJavaScriptInContext( "document.readyState == 'complete' && " "document.getElementById('Email') != null", - gaia_context): - return gaia_context + gaia_iframe_context): + return gaia_iframe_context except exceptions.EvaluateException: pass return None + def _GaiaWebViewContext(self): + devtools_context_map = ( + self._inspector_backend._devtools_client.GetUpdatedInspectableContexts() + ) + for context in devtools_context_map.contexts: + if context['type'] == 'webview': + return web_contents.WebContents( + devtools_context_map.GetInspectorBackend(context['id'])) + return None + def _ExecuteOobeApi(self, api, *args): logging.info('Invoking %s' % api) self.WaitForJavaScriptExpression("typeof Oobe == 'function'", 20) @@ -46,14 +56,58 @@ self._ExecuteOobeApi('Oobe.loginForTesting', username, password) def NavigateGaiaLogin(self, username, password): - """Logs in to GAIA with provided credentials.""" + """Logs in using the GAIA webview or IFrame, whichever is + present.""" self._ExecuteOobeApi('Oobe.addUserForTesting') + self._NavigateLogin(username, password) - gaia_context = util.WaitFor(self._GaiaLoginContext, timeout=30) + def NavigateEnterpriseEnrollment(self, username, password): + """Enterprise enrolls using the GAIA webview or IFrame, whichever + is present.""" + # TODO(resetswitch@chromium.org): Check if enrollment is open already. + self._ExecuteOobeApi('Oobe.switchToEnterpriseEnrollmentForTesting') + self._NavigateLogin(username, password) + + def _NavigateLogin(self, username, password): + def _GetGaiaFunction(): + if self._GaiaIFrameContext() is not None: + return Oobe._NavigateIFrameLogin + elif self._GaiaWebViewContext() is not None: + return Oobe._NavigateWebViewLogin + return None + util.WaitFor(_GetGaiaFunction, 20)(self, username, password) + + def _NavigateIFrameLogin(self, username, password): + """Logs into the IFrame-based GAIA screen""" + gaia_iframe_context = util.WaitFor(self._GaiaIFrameContext, timeout=30) self.ExecuteJavaScriptInContext(""" document.getElementById('Email').value='%s'; document.getElementById('Passwd').value='%s'; document.getElementById('signIn').click();""" % (username, password), - gaia_context) + gaia_iframe_context) + + def _NavigateWebViewLogin(self, username, password): + """Logs into the webview-based GAIA screen""" + self._NavigateWebViewEntry('identifierId', username) + self._GaiaWebViewContext().WaitForJavaScriptExpression( + "document.getElementById('identifierId') == null", 20) + + self._NavigateWebViewEntry('password', password) + util.WaitFor(lambda: self._GaiaWebViewContext() == None, 20) + + def _NavigateWebViewEntry(self, field, value): + self._WaitForField(field) + self._WaitForField('next') + gaia_webview_context = self._GaiaWebViewContext() + gaia_webview_context.EvaluateJavaScript(""" + document.getElementById('%s').value='%s'; + document.getElementById('next').click()""" + % (field, value)) + + def _WaitForField(self, field_id): + gaia_webview_context = util.WaitFor(self._GaiaWebViewContext, 5) + util.WaitFor(gaia_webview_context.HasReachedQuiescence, 20) + gaia_webview_context.WaitForJavaScriptExpression( + "document.getElementById('%s') != null" % field_id, 20)
diff --git a/tools/telemetry/telemetry/core/backends/chrome/tab_list_backend.py b/tools/telemetry/telemetry/core/backends/chrome/tab_list_backend.py index 480b6e7c..e63bacc 100644 --- a/tools/telemetry/telemetry/core/backends/chrome/tab_list_backend.py +++ b/tools/telemetry/telemetry/core/backends/chrome/tab_list_backend.py
@@ -28,7 +28,7 @@ self._browser_backend.devtools_client.CreateNewTab(timeout) return self[-1] - def CloseTab(self, tab_id, timeout=30): + def CloseTab(self, tab_id, timeout=300): """Closes the tab with the given debugger_url. Raises:
diff --git a/tools/telemetry/telemetry/core/browser.py b/tools/telemetry/telemetry/core/browser.py index 373f90a..91e3d94f 100644 --- a/tools/telemetry/telemetry/core/browser.py +++ b/tools/telemetry/telemetry/core/browser.py
@@ -205,11 +205,6 @@ result = self._GetStatsCommon(self._platform_backend.GetCpuStats) del result['ProcessCount'] - # FIXME: Renderer process CPU times are impossible to compare correctly. - # http://crbug.com/419786#c11 - if 'Renderer' in result: - del result['Renderer'] - # We want a single time value, not the sum for all processes. cpu_timestamp = self._platform_backend.GetCpuTimestamp() for process_type in result:
diff --git a/tools/telemetry/telemetry/core/platform/__init__.py b/tools/telemetry/telemetry/core/platform/__init__.py index 039910ba..59764672 100644 --- a/tools/telemetry/telemetry/core/platform/__init__.py +++ b/tools/telemetry/telemetry/core/platform/__init__.py
@@ -276,6 +276,19 @@ """ return self._platform_backend.StopMonitoringPower() + def CanMonitorNetworkData(self): + """Returns true if network data can be retrieved, false otherwise.""" + return self._platform_backend.CanMonitorNetworkData() + + def GetNetworkData(self, browser): + """Get current network data. + Returns: + Tuple of (sent_data, received_data) in kb if data can be found, + None otherwise. + """ + assert browser.platform == self + return self._platform_backend.GetNetworkData(browser) + def IsCooperativeShutdownSupported(self): """Indicates whether CooperativelyShutdown, below, is supported. It is not necessary to implement it on all platforms."""
diff --git a/tools/telemetry/telemetry/core/platform/android_platform_backend.py b/tools/telemetry/telemetry/core/platform/android_platform_backend.py index 00aad43..3648db9b 100644 --- a/tools/telemetry/telemetry/core/platform/android_platform_backend.py +++ b/tools/telemetry/telemetry/core/platform/android_platform_backend.py
@@ -44,6 +44,7 @@ from pylib.perf import perf_control # pylint: disable=F0401 from pylib.perf import thermal_throttle # pylint: disable=F0401 from pylib.utils import device_temp_file # pylint: disable=F0401 +from pylib import constants # pylint: disable=F0401 from pylib import screenshot # pylint: disable=F0401 try: @@ -346,6 +347,15 @@ def StopMonitoringPower(self): return self._power_monitor.StopMonitoringPower() + def CanMonitorNetworkData(self): + if (self._device.build_version_sdk < + constants.ANDROID_SDK_VERSION_CODES.LOLLIPOP): + return False + return True + + def GetNetworkData(self, browser): + return self._battery.GetNetworkData(browser._browser_backend.package) + def GetFileContents(self, fname): if not self._can_access_protected_file_contents: logging.warning('%s cannot be retrieved on non-rooted device.' % fname)
diff --git a/tools/telemetry/telemetry/core/platform/linux_based_platform_backend.py b/tools/telemetry/telemetry/core/platform/linux_based_platform_backend.py index 6da16284..4eb1d536 100644 --- a/tools/telemetry/telemetry/core/platform/linux_based_platform_backend.py +++ b/tools/telemetry/telemetry/core/platform/linux_based_platform_backend.py
@@ -7,6 +7,8 @@ except ImportError: resource = None # Not available on all platforms +import re + from telemetry.core import exceptions from telemetry.core.platform import platform_backend from telemetry import decorators @@ -53,8 +55,7 @@ return results def GetCpuTimestamp(self): - timer_list = self.GetFileContents('/proc/timer_list') - total_jiffies = float(self._GetProcJiffies(timer_list)) + total_jiffies = self._GetProcJiffies() clock_ticks = self.GetClockTicks() return {'TotalTime': total_jiffies / clock_ticks} @@ -146,15 +147,21 @@ retval[key.strip()] = value.strip() return retval - def _GetProcJiffies(self, timer_list): + def _GetProcJiffies(self): """Parse '/proc/timer_list' output and returns the first jiffies attribute. Multi-CPU machines will have multiple 'jiffies:' lines, all of which will be essentially the same. Return the first one.""" - if isinstance(timer_list, str): - timer_list = timer_list.splitlines() - for line in timer_list: - if line.startswith('jiffies:'): - _, value = line.split(':') - return value - raise Exception('Unable to find jiffies from /proc/timer_list') + jiffies_timer_lines = self.RunCommand( + ['grep', 'jiffies','/proc/timer_list']) + if not jiffies_timer_lines: + raise Exception('Unable to find jiffies from /proc/timer_list') + jiffies_timer_list = jiffies_timer_lines.splitlines() + # Each line should look something like 'jiffies: 4315883489'. + for line in jiffies_timer_list: + match = re.match('\s*jiffies\s*:\s*(\d+)', line) + if match: + value = match.group(1) + return float(value) + raise Exception('Unable to parse jiffies attribute: %s' % + repr(jiffies_timer_lines))
diff --git a/tools/telemetry/telemetry/core/platform/linux_based_platform_backend_unittest.py b/tools/telemetry/telemetry/core/platform/linux_based_platform_backend_unittest.py index 6e706a5..c76289d 100644 --- a/tools/telemetry/telemetry/core/platform/linux_based_platform_backend_unittest.py +++ b/tools/telemetry/telemetry/core/platform/linux_based_platform_backend_unittest.py
@@ -8,6 +8,10 @@ from telemetry.core.platform import linux_based_platform_backend from telemetry.core import util +util.AddDirToPythonPath(util.GetTelemetryDir(), 'third_party', 'mock') +import mock # pylint: disable=import-error + + class TestBackend(linux_based_platform_backend.LinuxBasedPlatformBackend): @@ -47,11 +51,22 @@ if not linux_based_platform_backend.resource: logging.warning('Test not supported') return - - backend = TestBackend() - self.SetMockFileInBackend(backend, 'timer_list', '/proc/timer_list') - result = backend.GetCpuTimestamp() - self.assertEquals(result, {'TotalTime': 105054633.0}) + jiffies_grep_string = """ + jiffies +jiffies a1111 + .last_jiffies : 4307239958 + .next_jiffies : 4307239968 + jiffies: 10505463300 + jiffies: 10505463333 + """ + with mock.patch.object( + linux_based_platform_backend.LinuxBasedPlatformBackend, + 'RunCommand', return_value=jiffies_grep_string) as mock_method: + backend = linux_based_platform_backend.LinuxBasedPlatformBackend() + result = backend.GetCpuTimestamp() + self.assertEquals(result, {'TotalTime': 105054633.0}) + mock_method.assert_call_once_with( + ['grep', '-m', '1', 'jiffies:','/proc/timer_list']) def testGetMemoryStatsBasic(self): if not linux_based_platform_backend.resource:
diff --git a/tools/telemetry/telemetry/core/platform/platform_backend.py b/tools/telemetry/telemetry/core/platform/platform_backend.py index 26f6da4..713f56f6 100644 --- a/tools/telemetry/telemetry/core/platform/platform_backend.py +++ b/tools/telemetry/telemetry/core/platform/platform_backend.py
@@ -260,6 +260,12 @@ def StopMonitoringPower(self): raise NotImplementedError() + def CanMonitorNetworkData(self): + return False + + def GetNetworkData(self, browser): + raise NotImplementedError() + def ReadMsr(self, msr_number, start=0, length=64): """Read a CPU model-specific register (MSR).
diff --git a/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor.py b/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor.py index f6da6ace..0b8c8ad9 100644 --- a/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor.py +++ b/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor.py
@@ -52,7 +52,17 @@ cpu_stats = super(DumpsysPowerMonitor, self).StopMonitoringPower() self._battery.EnableBatteryUpdates() power_data = self._battery.GetPackagePowerData(package) - power_results = self.ProcessPowerData(power_data, package) + battery_info = self._battery.GetBatteryInfo() + voltage = battery_info.get('voltage') + if voltage is None: + # Converting at a nominal voltage of 4.0V, as those values are obtained by + # a heuristic, and 4.0V is the voltage we set when using a monsoon device. + voltage = 4.0 + logging.warning('Unable to get device voltage. Using %s.', voltage) + else: + voltage = float(voltage) / 1000 + logging.info('Device voltage at %s', voltage) + power_results = self.ProcessPowerData(power_data, voltage, package) if power_results['energy_consumption_mwh'] == 0: logging.warning('Power data is returning 0 usage for %s. %s' % (package, self._battery.GetPowerData())) @@ -60,15 +70,13 @@ cpu_stats, power_results) @staticmethod - def ProcessPowerData(power_data, package): + def ProcessPowerData(power_data, voltage, package): power_results = {'identifier': 'dumpsys', 'power_samples_mw': []} if not power_data: logging.warning('Unable to find power data for %s in dumpsys output. ' 'Please upgrade the OS version of the device.' % package) power_results['energy_consumption_mwh'] = 0 return power_results - # Converting at a nominal voltage of 4.0V, as those values are obtained by a - # heuristic, and 4.0V is the voltage we set when using a monsoon device. - consumption_mwh = sum(power_data['data']) * 4.0 + consumption_mwh = sum(power_data['data']) * voltage power_results['energy_consumption_mwh'] = consumption_mwh return power_results
diff --git a/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor_unittest.py b/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor_unittest.py index be966b4..69059f5d 100644 --- a/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor_unittest.py +++ b/tools/telemetry/telemetry/core/platform/power_monitor/android_dumpsys_power_monitor_unittest.py
@@ -16,7 +16,7 @@ power_data = {'data': [23.9], 'uid': '12345'} results = ( android_dumpsys_power_monitor.DumpsysPowerMonitor.ProcessPowerData( - power_data, package)) + power_data, 4.0, package)) self.assertEqual(results['identifier'], 'dumpsys') self.assertAlmostEqual(results['energy_consumption_mwh'], 95.6) @@ -26,7 +26,7 @@ power_data = None results = ( android_dumpsys_power_monitor.DumpsysPowerMonitor.ProcessPowerData( - power_data, package)) + power_data, 4.0, package)) self.assertEqual(results['identifier'], 'dumpsys') self.assertEqual(results['energy_consumption_mwh'], 0)
diff --git a/tools/telemetry/telemetry/core/tab_list.py b/tools/telemetry/telemetry/core/tab_list.py index e692723..99bbaae 100644 --- a/tools/telemetry/telemetry/core/tab_list.py +++ b/tools/telemetry/telemetry/core/tab_list.py
@@ -5,7 +5,7 @@ def __init__(self, tab_list_backend): self._tab_list_backend = tab_list_backend - def New(self, timeout=30): + def New(self, timeout=300): return self._tab_list_backend.New(timeout) def __iter__(self):
diff --git a/tools/telemetry/telemetry/results/buildbot_output_formatter_unittest.py b/tools/telemetry/telemetry/results/buildbot_output_formatter_unittest.py deleted file mode 100644 index 835f589..0000000 --- a/tools/telemetry/telemetry/results/buildbot_output_formatter_unittest.py +++ /dev/null
@@ -1,443 +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. - -import os - -from telemetry import page as page_module -from telemetry.page import page_set -from telemetry.results import base_test_results_unittest -from telemetry.results import buildbot_output_formatter -from telemetry.results import page_test_results -from telemetry.value import failure -from telemetry.value import histogram -from telemetry.value import list_of_scalar_values -from telemetry.value import scalar - - -def _MakePageSet(): - ps = page_set.PageSet(file_path=os.path.dirname(__file__)) - ps.AddUserStory(page_module.Page('http://www.foo.com/', ps, ps.base_dir)) - ps.AddUserStory(page_module.Page('http://www.bar.com/', ps, ps.base_dir)) - ps.AddUserStory(page_module.Page('http://www.baz.com/', ps, ps.base_dir)) - return ps - -class BuildbotOutputFormatterTest( - base_test_results_unittest.BaseTestResultsUnittest): - def setUp(self): - self._test_output_stream = base_test_results_unittest.TestOutputStream() - - def test_basic_summary(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 3)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 7)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = ['RESULT a: http___www.bar.com_= 7 seconds\n', - 'RESULT a: http___www.foo.com_= 3 seconds\n', - '*RESULT a: a= [3,7] seconds\nAvg a: 5.000000seconds\n' + - 'Sd a: 2.828427seconds\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_basic_summary_with_only_one_page(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 3)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = ['*RESULT a: a= 3 seconds\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_basic_summary_nonuniform_results(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 3)) - measurement_results.AddValue( - scalar.ScalarValue(test_page_set.pages[0], 'b', 'seconds', 10)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 3)) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'b', 'seconds', 10)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - measurement_results.WillRunPage(test_page_set.pages[2]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[2], 'a', 'seconds', 7)) - # Note, page[2] does not report a 'b' metric. - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = ['RESULT a: http___www.bar.com_= 3 seconds\n', - 'RESULT a: http___www.baz.com_= 7 seconds\n', - 'RESULT a: http___www.foo.com_= 3 seconds\n', - '*RESULT a: a= [3,3,7] seconds\nAvg a: 4.333333seconds\n' + - 'Sd a: 2.309401seconds\n', - 'RESULT b: http___www.bar.com_= 10 seconds\n', - 'RESULT b: http___www.foo.com_= 10 seconds\n', - '*RESULT b: b= [10,10] seconds\nAvg b: 10.000000seconds\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_basic_summary_pass_and_fail_page(self): - """If a page failed, only print summary for individual pages.""" - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 3)) - measurement_results.AddValue( - failure.FailureValue.FromMessage(test_page_set.pages[0], 'message')) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 7)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = ['RESULT a: http___www.bar.com_= 7 seconds\n', - 'RESULT a: http___www.foo.com_= 3 seconds\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_failed= 1 count\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_repeated_pageset_one_iteration_one_page_fails(self): - """Page fails on one iteration, no averaged results should print.""" - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 3)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 7)) - measurement_results.AddValue( - failure.FailureValue.FromMessage(test_page_set.pages[1], 'message')) - measurement_results.DidRunPage(test_page_set.pages[1]) - - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 4)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 8)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = ['RESULT a: http___www.bar.com_= [7,8] seconds\n' + - 'Avg a: 7.500000seconds\n' + - 'Sd a: 0.707107seconds\n', - 'RESULT a: http___www.foo.com_= [3,4] seconds\n' + - 'Avg a: 3.500000seconds\n' + - 'Sd a: 0.707107seconds\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_failed= 1 count\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_repeated_pageset(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 3)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 7)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 4)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 8)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = ['RESULT a: http___www.bar.com_= [7,8] seconds\n' + - 'Avg a: 7.500000seconds\n' + - 'Sd a: 0.707107seconds\n', - 'RESULT a: http___www.foo.com_= [3,4] seconds\n' + - 'Avg a: 3.500000seconds\n' + - 'Sd a: 0.707107seconds\n', - '*RESULT a: a= [3,7,4,8] seconds\n' + - 'Avg a: 5.500000seconds\n' + - 'Sd a: 2.380476seconds\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_errored= 0 count\n' - ] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_repeated_pages(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 3)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'a', 'seconds', 4)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 7)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'a', 'seconds', 8)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = ['RESULT a: http___www.bar.com_= [7,8] seconds\n' + - 'Avg a: 7.500000seconds\n' + - 'Sd a: 0.707107seconds\n', - 'RESULT a: http___www.foo.com_= [3,4] seconds\n' + - 'Avg a: 3.500000seconds\n' + - 'Sd a: 0.707107seconds\n', - '*RESULT a: a= [3,4,7,8] seconds\n' + - 'Avg a: 5.500000seconds\n' + - 'Sd a: 2.380476seconds\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: ' + - 'num_errored= 0 count\n' - ] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_overall_results_trace_tag(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.AddSummaryValue( - scalar.ScalarValue(None, 'a', 'seconds', 1)) - - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'b', 'seconds', 2)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'b', 'seconds', 3)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - measurement_results.AddSummaryValue( - scalar.ScalarValue(None, 'c', 'seconds', 4)) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream, trace_tag='_ref') - formatter.Format(measurement_results) - - expected = [ - '*RESULT b: b_ref= [2,3] seconds\n' + - 'Avg b: 2.500000seconds\nSd b: 0.707107seconds\n', - '*RESULT a: a_ref= 1 seconds\n', - '*RESULT c: c_ref= 4 seconds\n', - 'RESULT telemetry_page_measurement_results: num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data) - - - def test_overall_results_page_runs_twice(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - - measurement_results.AddSummaryValue( - scalar.ScalarValue(None, 'a', 'seconds', 1)) - - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'b', 'seconds', 2)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'b', 'seconds', 3)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = [ - 'RESULT b: http___www.foo.com_= [2,3] seconds\n' + - 'Avg b: 2.500000seconds\nSd b: 0.707107seconds\n', - '*RESULT b: b= [2,3] seconds\n' + - 'Avg b: 2.500000seconds\nSd b: 0.707107seconds\n', - '*RESULT a: a= 1 seconds\n', - 'RESULT telemetry_page_measurement_results: num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_unimportant_results(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - - measurement_results.AddSummaryValue( - scalar.ScalarValue(None, 'a', 'seconds', 1, important=False)) - - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[0], 'b', 'seconds', 2, important=False)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(scalar.ScalarValue( - test_page_set.pages[1], 'b', 'seconds', 3, important=False)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - self.assertEquals( - self._test_output_stream.output_data, - ['RESULT b: http___www.bar.com_= 3 seconds\n', - 'RESULT b: http___www.foo.com_= 2 seconds\n', - 'RESULT b: b= [2,3] seconds\n' + - 'Avg b: 2.500000seconds\nSd b: 0.707107seconds\n', - 'RESULT a: a= 1 seconds\n', - 'RESULT telemetry_page_measurement_results: num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: num_errored= 0 count\n']) - - def test_list_value(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - - measurement_results.AddSummaryValue( - list_of_scalar_values.ListOfScalarValues(None, 'a', 'seconds', [1, 1])) - - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(list_of_scalar_values.ListOfScalarValues( - test_page_set.pages[0], 'b', 'seconds', [2, 2])) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(list_of_scalar_values.ListOfScalarValues( - test_page_set.pages[1], 'b', 'seconds', [3, 3])) - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = [ - 'RESULT b: http___www.bar.com_= [3,3] seconds\n' + - 'Avg b: 3.000000seconds\n', - 'RESULT b: http___www.foo.com_= [2,2] seconds\n' + - 'Avg b: 2.000000seconds\n', - '*RESULT b: b= [2,2,3,3] seconds\nAvg b: 2.500000seconds\n' + - 'Sd b: 0.577350seconds\n', - '*RESULT a: a= [1,1] seconds\nAvg a: 1.000000seconds\n', - 'RESULT telemetry_page_measurement_results: num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data) - - def test_histogram(self): - test_page_set = _MakePageSet() - - measurement_results = page_test_results.PageTestResults() - measurement_results.WillRunPage(test_page_set.pages[0]) - measurement_results.AddValue(histogram.HistogramValue( - test_page_set.pages[0], 'a', 'units', - raw_value_json='{"buckets": [{"low": 1, "high": 2, "count": 1}]}', - important=False)) - measurement_results.DidRunPage(test_page_set.pages[0]) - - measurement_results.WillRunPage(test_page_set.pages[1]) - measurement_results.AddValue(histogram.HistogramValue( - test_page_set.pages[1], 'a', 'units', - raw_value_json='{"buckets": [{"low": 2, "high": 3, "count": 1}]}', - important=False)) - measurement_results.DidRunPage(test_page_set.pages[1]) - - formatter = buildbot_output_formatter.BuildbotOutputFormatter( - self._test_output_stream) - formatter.Format(measurement_results) - - expected = [ - 'HISTOGRAM a: http___www.bar.com_= ' + - '{"buckets": [{"low": 2, "high": 3, "count": 1}]} units\n' + - 'Avg a: 2.500000units\n', - 'HISTOGRAM a: http___www.foo.com_= ' + - '{"buckets": [{"low": 1, "high": 2, "count": 1}]} units\n' + - 'Avg a: 1.500000units\n', - 'RESULT telemetry_page_measurement_results: num_failed= 0 count\n', - 'RESULT telemetry_page_measurement_results: num_errored= 0 count\n'] - self.assertEquals(expected, self._test_output_stream.output_data)
diff --git a/tools/telemetry/telemetry/util/bootstrap.py b/tools/telemetry/telemetry/util/bootstrap.py index 8afe43c..b1cbb69 100644 --- a/tools/telemetry/telemetry/util/bootstrap.py +++ b/tools/telemetry/telemetry/util/bootstrap.py
@@ -35,7 +35,7 @@ global davclient davclient_src = urllib.urlopen(_DAVCLIENT_URL).read() davclient = imp.new_module('davclient') - exec davclient_src in davclient.__dict__ + exec davclient_src in davclient.__dict__ # pylint: disable=exec-used class DAVClientWrapper(object): @@ -116,7 +116,7 @@ while os.path.basename(chrome_root) != 'src': chrome_root = os.path.abspath(os.path.join(chrome_root, os.pardir)) - exec open(deps_file).read() + exec open(deps_file).read() # pylint: disable=exec-used deps_paths = deps.keys() @@ -146,7 +146,7 @@ deps = {} deps_includes = {} - exec urllib.urlopen(url).read() + exec urllib.urlopen(url).read() # pylint: disable=exec-used for dst_path, src_path in deps.iteritems(): full_dst_path = os.path.join(destination_dir, dst_path)
diff --git a/tools/telemetry/telemetry/value/__init__.py b/tools/telemetry/telemetry/value/__init__.py index 77324c5..bbcfd5a 100644 --- a/tools/telemetry/telemetry/value/__init__.py +++ b/tools/telemetry/telemetry/value/__init__.py
@@ -81,6 +81,12 @@ self.description = description self.tir_label = tir_label + def __eq__(self, other): + return hash(self) == hash(other) + + def __hash__(self): + return hash(str(self)) + def IsMergableWith(self, that): return (self.units == that.units and type(self) == type(that) and
diff --git a/tools/telemetry/telemetry/value/summary_unittest.py b/tools/telemetry/telemetry/value/summary_unittest.py index 7ea755c..8905185 100644 --- a/tools/telemetry/telemetry/value/summary_unittest.py +++ b/tools/telemetry/telemetry/value/summary_unittest.py
@@ -2,7 +2,323 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# TODO(nduca): Convert preexisting unittests to be summary tests. Summary is -# currently very thoroughly unit tested by -# buildbot_output_formatter_unittest. It originated as part of that -# code, but was extracted because it proved useful. +import os +import unittest + +from telemetry import page as page_module +from telemetry.page import page_set +from telemetry.results import page_test_results +from telemetry.value import failure +from telemetry.value import histogram +from telemetry.value import list_of_scalar_values +from telemetry.value import scalar +from telemetry.value import summary as summary_module + +class TestBase(unittest.TestCase): + def setUp(self): + ps = page_set.PageSet(file_path=os.path.dirname(__file__)) + ps.AddUserStory(page_module.Page('http://www.bar.com/', ps, ps.base_dir)) + ps.AddUserStory(page_module.Page('http://www.baz.com/', ps, ps.base_dir)) + ps.AddUserStory(page_module.Page('http://www.foo.com/', ps, ps.base_dir)) + self.page_set = ps + + @property + def pages(self): + return self.page_set.pages + + +class SummaryTest(TestBase): + def testBasicSummary(self): + page0 = self.pages[0] + page1 = self.pages[1] + + results = page_test_results.PageTestResults() + + results.WillRunPage(page0) + v0 = scalar.ScalarValue(page0, 'a', 'seconds', 3) + results.AddValue(v0) + results.DidRunPage(page0) + + results.WillRunPage(page1) + v1 = scalar.ScalarValue(page1, 'a', 'seconds', 7) + results.AddValue(v1) + results.DidRunPage(page1) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + v0_list = list_of_scalar_values.ListOfScalarValues( + page0, 'a', 'seconds', [3]) + v1_list = list_of_scalar_values.ListOfScalarValues( + page1, 'a', 'seconds', [7]) + merged_value = list_of_scalar_values.ListOfScalarValues( + None, 'a', 'seconds', [3, 7]) + + self.assertEquals(3, len(values)) + self.assertIn(v0_list, values) + self.assertIn(v1_list, values) + self.assertIn(merged_value, values) + + def testBasicSummaryWithOnlyOnePage(self): + page0 = self.pages[0] + + results = page_test_results.PageTestResults() + + results.WillRunPage(page0) + v0 = scalar.ScalarValue(page0, 'a', 'seconds', 3) + results.AddValue(v0) + results.DidRunPage(page0) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + v0_list = list_of_scalar_values.ListOfScalarValues( + None, 'a', 'seconds', [3]) + + self.assertEquals([v0_list], values) + + def testBasicSummaryNonuniformResults(self): + page0 = self.pages[0] + page1 = self.pages[1] + page2 = self.pages[2] + + results = page_test_results.PageTestResults() + results.WillRunPage(page0) + v0 = scalar.ScalarValue(page0, 'a', 'seconds', 3) + results.AddValue(v0) + v1 = scalar.ScalarValue(page0, 'b', 'seconds', 10) + results.AddValue(v1) + results.DidRunPage(page0) + + results.WillRunPage(page1) + v2 = scalar.ScalarValue(page1, 'a', 'seconds', 3) + results.AddValue(v2) + v3 = scalar.ScalarValue(page1, 'b', 'seconds', 10) + results.AddValue(v3) + results.DidRunPage(page1) + + results.WillRunPage(page2) + v4 = scalar.ScalarValue(page2, 'a', 'seconds', 7) + results.AddValue(v4) + # Note, page[2] does not report a 'b' metric. + results.DidRunPage(page2) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + v0_list = list_of_scalar_values.ListOfScalarValues( + page0, 'a', 'seconds', [3]) + v1_list = list_of_scalar_values.ListOfScalarValues( + page0, 'b', 'seconds', [10]) + v2_list = list_of_scalar_values.ListOfScalarValues( + page1, 'a', 'seconds', [3]) + v3_list = list_of_scalar_values.ListOfScalarValues( + page1, 'b', 'seconds', [10]) + v4_list = list_of_scalar_values.ListOfScalarValues( + page2, 'a', 'seconds', [7]) + + a_summary = list_of_scalar_values.ListOfScalarValues( + None, 'a', 'seconds', [3, 3, 7]) + b_summary = list_of_scalar_values.ListOfScalarValues( + None, 'b', 'seconds', [10, 10]) + + self.assertEquals(7, len(values)) + self.assertIn(v0_list, values) + self.assertIn(v1_list, values) + self.assertIn(v2_list, values) + self.assertIn(v3_list, values) + self.assertIn(v4_list, values) + self.assertIn(a_summary, values) + self.assertIn(b_summary, values) + + def testBasicSummaryPassAndFailPage(self): + """If a page failed, only print summary for individual pages.""" + page0 = self.pages[0] + page1 = self.pages[1] + + results = page_test_results.PageTestResults() + results.WillRunPage(page0) + v0 = scalar.ScalarValue(page0, 'a', 'seconds', 3) + results.AddValue(v0) + v1 = failure.FailureValue.FromMessage(page0, 'message') + results.AddValue(v1) + results.DidRunPage(page0) + + results.WillRunPage(page1) + v2 = scalar.ScalarValue(page1, 'a', 'seconds', 7) + results.AddValue(v2) + results.DidRunPage(page1) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + v0_list = list_of_scalar_values.ListOfScalarValues( + page0, 'a', 'seconds', [3]) + v2_list = list_of_scalar_values.ListOfScalarValues( + page1, 'a', 'seconds', [7]) + + self.assertEquals(2, len(values)) + self.assertIn(v0_list, values) + self.assertIn(v2_list, values) + + def testRepeatedPagesetOneIterationOnePageFails(self): + """Page fails on one iteration, no averaged results should print.""" + page0 = self.pages[0] + page1 = self.pages[1] + + results = page_test_results.PageTestResults() + results.WillRunPage(page0) + v0 = scalar.ScalarValue(page0, 'a', 'seconds', 3) + results.AddValue(v0) + results.DidRunPage(page0) + + results.WillRunPage(page1) + v1 = scalar.ScalarValue(page1, 'a', 'seconds', 7) + results.AddValue(v1) + v2 = failure.FailureValue.FromMessage(page1, 'message') + results.AddValue(v2) + results.DidRunPage(page1) + + results.WillRunPage(page0) + v3 = scalar.ScalarValue(page0, 'a', 'seconds', 4) + results.AddValue(v3) + results.DidRunPage(page0) + + results.WillRunPage(page1) + v4 = scalar.ScalarValue(page1, 'a', 'seconds', 8) + results.AddValue(v4) + results.DidRunPage(page1) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + page0_aggregated = list_of_scalar_values.ListOfScalarValues( + page0, 'a', 'seconds', [3, 4]) + page1_aggregated = list_of_scalar_values.ListOfScalarValues( + page1, 'a', 'seconds', [7, 8]) + + self.assertEquals(2, len(values)) + self.assertIn(page0_aggregated, values) + self.assertIn(page1_aggregated, values) + + def testRepeatedPages(self): + page0 = self.pages[0] + page1 = self.pages[1] + + results = page_test_results.PageTestResults() + results.WillRunPage(page0) + v0 = scalar.ScalarValue(page0, 'a', 'seconds', 3) + results.AddValue(v0) + results.DidRunPage(page0) + + results.WillRunPage(page0) + v2 = scalar.ScalarValue(page0, 'a', 'seconds', 4) + results.AddValue(v2) + results.DidRunPage(page0) + + results.WillRunPage(page1) + v1 = scalar.ScalarValue(page1, 'a', 'seconds', 7) + results.AddValue(v1) + results.DidRunPage(page1) + + results.WillRunPage(page1) + v3 = scalar.ScalarValue(page1, 'a', 'seconds', 8) + results.AddValue(v3) + results.DidRunPage(page1) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + page0_aggregated = list_of_scalar_values.ListOfScalarValues( + page0, 'a', 'seconds', [3, 4]) + page1_aggregated = list_of_scalar_values.ListOfScalarValues( + page1, 'a', 'seconds', [7, 8]) + a_summary = list_of_scalar_values.ListOfScalarValues( + None, 'a', 'seconds', [3, 4, 7, 8]) + + self.assertEquals(3, len(values)) + self.assertIn(page0_aggregated, values) + self.assertIn(page1_aggregated, values) + self.assertIn(a_summary, values) + + def testPageRunsTwice(self): + page0 = self.pages[0] + + results = page_test_results.PageTestResults() + + results.WillRunPage(page0) + v0 = scalar.ScalarValue(page0, 'b', 'seconds', 2) + results.AddValue(v0) + results.DidRunPage(page0) + + results.WillRunPage(page0) + v1 = scalar.ScalarValue(page0, 'b', 'seconds', 3) + results.AddValue(v1) + results.DidRunPage(page0) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + page0_aggregated = list_of_scalar_values.ListOfScalarValues( + page0, 'b', 'seconds', [2, 3]) + b_summary = list_of_scalar_values.ListOfScalarValues( + None, 'b', 'seconds', [2, 3]) + + self.assertEquals(2, len(values)) + self.assertIn(page0_aggregated, values) + self.assertIn(b_summary, values) + + def testListValue(self): + page0 = self.pages[0] + page1 = self.pages[1] + + results = page_test_results.PageTestResults() + + results.WillRunPage(page0) + v0 = list_of_scalar_values.ListOfScalarValues(page0, 'b', 'seconds', [2, 2]) + results.AddValue(v0) + results.DidRunPage(page0) + + results.WillRunPage(page1) + v1 = list_of_scalar_values.ListOfScalarValues(page1, 'b', 'seconds', [3, 3]) + results.AddValue(v1) + results.DidRunPage(page1) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + b_summary = list_of_scalar_values.ListOfScalarValues( + None, 'b', 'seconds', [2, 2, 3, 3]) + + self.assertEquals(3, len(values)) + self.assertIn(v0, values) + self.assertIn(v1, values) + self.assertIn(b_summary, values) + + def testHistogram(self): + page0 = self.pages[0] + page1 = self.pages[1] + + results = page_test_results.PageTestResults() + results.WillRunPage(page0) + v0 = histogram.HistogramValue( + page0, 'a', 'units', + raw_value_json='{"buckets": [{"low": 1, "high": 2, "count": 1}]}', + important=False) + results.AddValue(v0) + results.DidRunPage(page0) + + results.WillRunPage(page1) + v1 = histogram.HistogramValue( + page1, 'a', 'units', + raw_value_json='{"buckets": [{"low": 2, "high": 3, "count": 1}]}', + important=False) + results.AddValue(v1) + results.DidRunPage(page1) + + summary = summary_module.Summary(results.all_page_specific_values) + values = summary.interleaved_computed_per_page_values_and_summaries + + self.assertEquals(2, len(values)) + self.assertIn(v0, values) + self.assertIn(v1, values)
diff --git a/tools/telemetry/telemetry/value/value_unittest.py b/tools/telemetry/telemetry/value/value_unittest.py index 21bd5af..6e8f7f43d 100644 --- a/tools/telemetry/telemetry/value/value_unittest.py +++ b/tools/telemetry/telemetry/value/value_unittest.py
@@ -177,7 +177,7 @@ d = v.AsDict() self.assertEqual('foo', d['tir_label']) - def testAsDictWithoutDescription(self): + def testAsDictWithoutInteractionRecord(self): v = ValueForAsDictTest(None, 'x', 'unit', important=False, description=None, tir_label=None) self.assertNotIn('tir_label', v.AsDict())
diff --git a/tools/telemetry/telemetry/web_perf/metrics/layout_unittest.py b/tools/telemetry/telemetry/web_perf/metrics/layout_unittest.py index 0b9fb14..d2227ef 100644 --- a/tools/telemetry/telemetry/web_perf/metrics/layout_unittest.py +++ b/tools/telemetry/telemetry/web_perf/metrics/layout_unittest.py
@@ -8,7 +8,6 @@ from telemetry.page import page from telemetry.results import page_test_results from telemetry.web_perf.metrics import layout -from collections import namedtuple from telemetry.web_perf import timeline_interaction_record FakeEvent = namedtuple('Event', 'name, start, end')
diff --git a/tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py b/tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py index 231f23e..cd76e9f 100644 --- a/tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py +++ b/tools/telemetry/telemetry/web_perf/metrics/rendering_stats.py
@@ -1,6 +1,8 @@ # 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. +import itertools + from operator import attrgetter from telemetry.web_perf.metrics import rendering_frame @@ -15,7 +17,7 @@ BEGIN_COMP_NAME = 'INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT' # This is when an input event is turned into a scroll update. BEGIN_SCROLL_UPDATE_COMP_NAME = ( - 'INPUT_EVENT_LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT') + 'LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT') # This is when a scroll update is forwarded to the main thread. FORWARD_SCROLL_UPDATE_COMP_NAME = ( 'INPUT_EVENT_LATENCY_FORWARD_SCROLL_UPDATE_TO_MAIN_COMPONENT') @@ -23,7 +25,7 @@ END_COMP_NAME = 'INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT' # Name for a main thread scroll update latency event. -SCROLL_UPDATE_EVENT_NAME = 'InputLatency::ScrollUpdate' +SCROLL_UPDATE_EVENT_NAME = 'Latency::ScrollUpdate' # Name for a gesture scroll update latency event. GESTURE_SCROLL_UPDATE_EVENT_NAME = 'InputLatency::GestureScrollUpdate' @@ -38,27 +40,30 @@ CHECKERBOARDED_PIXEL_ERROR = 'checkerboarded_pixel_percentages' -def GetInputLatencyEvents(process, timeline_range): - """Get input events' LatencyInfo from the process's trace buffer that are +def GetLatencyEvents(process, timeline_range): + """Get LatencyInfo trace events from the process's trace buffer that are within the timeline_range. Input events dump their LatencyInfo into trace buffer as async trace event - of name starting with "InputLatency". The trace event has a memeber 'data' - containing its latency history. + of name starting with "InputLatency". Non-input events with name starting + with "Latency". The trace event has a memeber 'data' containing its latency + history. """ - input_events = [] + latency_events = [] if not process: - return input_events - for event in process.IterAllAsyncSlicesStartsWithName('InputLatency'): + return latency_events + for event in itertools.chain( + process.IterAllAsyncSlicesStartsWithName('InputLatency'), + process.IterAllAsyncSlicesStartsWithName('Latency')): if event.start >= timeline_range.min and event.end <= timeline_range.max: for ss in event.sub_slices: if 'data' in ss.args: - input_events.append(ss) - return input_events + latency_events.append(ss) + return latency_events -def ComputeInputEventLatencies(input_events): +def ComputeEventLatencies(input_events): """ Compute input event latencies. Input event latency is the time from when the input event is created to @@ -71,7 +76,7 @@ 3. INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT -- when event reaches RenderWidget If the latency starts with a - INPUT_EVENT_LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT component, then it is + LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT component, then it is classified as a scroll update instead of a normal input latency measure. Returns: @@ -200,22 +205,21 @@ def _InitInputLatencyStatsFromTimeline( self, browser_process, renderer_process, timeline_range): - latency_events = GetInputLatencyEvents(browser_process, timeline_range) + latency_events = GetLatencyEvents(browser_process, timeline_range) # Plugin input event's latency slice is generated in renderer process. - latency_events.extend(GetInputLatencyEvents(renderer_process, - timeline_range)) - input_event_latencies = ComputeInputEventLatencies(latency_events) + latency_events.extend(GetLatencyEvents(renderer_process, timeline_range)) + event_latencies = ComputeEventLatencies(latency_events) # Don't include scroll updates in the overall input latency measurement, # because scroll updates can take much more time to process than other # input events and would therefore add noise to overall latency numbers. self.input_event_latency[-1] = [ - latency for name, latency in input_event_latencies + latency for name, latency in event_latencies if name != SCROLL_UPDATE_EVENT_NAME] self.scroll_update_latency[-1] = [ - latency for name, latency in input_event_latencies + latency for name, latency in event_latencies if name == SCROLL_UPDATE_EVENT_NAME] self.gesture_scroll_update_latency[-1] = [ - latency for name, latency in input_event_latencies + latency for name, latency in event_latencies if name == GESTURE_SCROLL_UPDATE_EVENT_NAME] def _GatherEvents(self, event_name, process, timeline_range):
diff --git a/tools/telemetry/telemetry/web_perf/metrics/rendering_stats_unittest.py b/tools/telemetry/telemetry/web_perf/metrics/rendering_stats_unittest.py index 7f78bd5..5755ecd 100644 --- a/tools/telemetry/telemetry/web_perf/metrics/rendering_stats_unittest.py +++ b/tools/telemetry/telemetry/web_perf/metrics/rendering_stats_unittest.py
@@ -20,10 +20,10 @@ SCROLL_UPDATE_EVENT_NAME, UI_COMP_NAME) from telemetry.web_perf.metrics.rendering_stats import ( - ComputeInputEventLatencies) -from telemetry.web_perf.metrics.rendering_stats import GetInputLatencyEvents -from telemetry.web_perf.metrics.rendering_stats import HasRenderingStats -from telemetry.web_perf.metrics.rendering_stats import RenderingStats + ComputeEventLatencies, + GetLatencyEvents, + HasRenderingStats, + RenderingStats) class MockTimer(object): @@ -512,7 +512,7 @@ browser.FinalizeImport() renderer.FinalizeImport() - input_events = [] + latency_events = [] timeline_markers = timeline.FindTimelineMarkers( ['ActionA', 'ActionB', 'ActionA']) @@ -521,11 +521,11 @@ for timeline_range in timeline_ranges: if timeline_range.is_empty: continue - input_events.extend(GetInputLatencyEvents(browser, timeline_range)) + latency_events.extend(GetLatencyEvents(browser, timeline_range)) - self.assertEquals(input_events, ref_latency.input_event) - input_event_latency_result = ComputeInputEventLatencies(input_events) - self.assertEquals(input_event_latency_result, + self.assertEquals(latency_events, ref_latency.input_event) + event_latency_result = ComputeEventLatencies(latency_events) + self.assertEquals(event_latency_result, ref_latency.input_event_latency) stats = RenderingStats(renderer, browser, None, timeline_ranges)
diff --git a/tools/telemetry/telemetry/web_perf/metrics/smoothness_unittest.py b/tools/telemetry/telemetry/web_perf/metrics/smoothness_unittest.py index 09bb9b1..11b817f7 100644 --- a/tools/telemetry/telemetry/web_perf/metrics/smoothness_unittest.py +++ b/tools/telemetry/telemetry/web_perf/metrics/smoothness_unittest.py
@@ -90,13 +90,13 @@ frame_times=[[10, 20], [30, 40, 50]]) avg_surface_fps, jank_count, max_frame_delay, frame_lengths = ( self.metric._ComputeSurfaceFlingerMetric(self.page, stats)) - self.assertEquals(None, avg_surface_fps.values) + self.assertEquals(None, avg_surface_fps.value) self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, avg_surface_fps.none_value_reason) - self.assertEquals(None, jank_count.values) + self.assertEquals(None, jank_count.value) self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, jank_count.none_value_reason) - self.assertEquals(None, max_frame_delay.values) + self.assertEquals(None, max_frame_delay.value) self.assertEquals(smoothness.NOT_ENOUGH_FRAMES_MESSAGE, max_frame_delay.none_value_reason) self.assertEquals(None, frame_lengths.values) @@ -206,7 +206,7 @@ self.assertEquals(30, mean_frame_time_value.value) self.assertEquals(20, percentage_smooth_value.value) - def testComputeFrameTimeMetricWithNotEnoughFrames(self): + def testComputeFrameTimeMetricWithNotEnoughFrames2(self): stats = _MockRenderingStats( frame_timestamps=self.not_enough_frames_timestamps, frame_times=[[10, 20], [30, 40, 50]])
diff --git a/tools/telemetry/telemetry/wpr/archive_info.py b/tools/telemetry/telemetry/wpr/archive_info.py index e90ae5e8..3468ed1 100644 --- a/tools/telemetry/telemetry/wpr/archive_info.py +++ b/tools/telemetry/telemetry/wpr/archive_info.py
@@ -127,8 +127,9 @@ shutil.move(self.temp_target_wpr_file_path, target_wpr_file_path) # Update the hash file. + target_wpr_file_hash = cloud_storage.CalculateHash(target_wpr_file_path) with open(target_wpr_file_path + '.sha1', 'wb') as f: - f.write(cloud_storage.CalculateHash(target_wpr_file_path)) + f.write(target_wpr_file_hash) f.flush() self._WriteToFile() @@ -141,7 +142,7 @@ 'user stories to cloud storage.') return try: - cloud_storage.Insert(self._bucket, target_wpr_file, + cloud_storage.Insert(self._bucket, target_wpr_file_hash, target_wpr_file_path) except cloud_storage.CloudStorageError, e: logging.warning('Failed to upload wpr file %s to cloud storage. '
diff --git a/tools/telemetry/unittest_data/timer_list b/tools/telemetry/unittest_data/timer_list deleted file mode 100644 index d7ff169..0000000 --- a/tools/telemetry/unittest_data/timer_list +++ /dev/null
@@ -1,62 +0,0 @@ -Timer List Version: v0.7 -HRTIMER_MAX_CLOCK_BASES: 4 -now at 49390649032656 nsecs - -cpu: 0 - clock 0: - .base: 0000000000000000 - .index: 0 - .resolution: 1 nsecs - .get_time: ktime_get - .offset: 0 nsecs -active timers: - #0: <0000000000000000>, hrtimer_wakeup, S:01, schedule_hrtimeout_range_clock, census_census_h/2343 - # expires at 49390651724646-49390651774646 nsecs [in 2691990 to 2741990 nsecs] - #1: <0000000000000000>, hrtimer_wakeup, S:01, schedule_hrtimeout_range_clock, census_census_h/3680 - # expires at 49390656983466-49390657033466 nsecs [in 7950810 to 8000810 nsecs] - clock 1: - .base: 0000000000000000 - .index: 1 - .resolution: 1 nsecs - .get_time: ktime_get_real - .offset: 1414432541083798144 nsecs -active timers: - #0: <0000000000000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, mysqld/27245 - # expires at 1414481934522781000-1414481934522831000 nsecs [in 1414432543873748344 to 1414432543873798344 nsecs] - #1: <0000000000000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, DNS Res~ver #14/21520 - # expires at 1414482222918140000-1414482222918190000 nsecs [in 1414432832269107344 to 1414432832269157344 nsecs] - clock 2: - .base: 0000000000000000 - .index: 2 - .resolution: 1 nsecs - .get_time: ktime_get_boottime - .offset: 0 nsecs -active timers: - clock 3: - .base: 0000000000000000 - .index: 3 - .resolution: 1 nsecs - .get_time: ktime_get_clocktai - .offset: 1414432541083798144 nsecs -active timers: - .expires_next : 49390651774646 nsecs - .hres_active : 1 - .nr_events : 9793846 - .nr_retries : 580 - .nr_hangs : 0 - .max_hang_time : 0 nsecs - .nohz_mode : 2 - .last_tick : 49390648000000 nsecs - .tick_stopped : 1 - .idle_jiffies : 4307239958 - .idle_calls : 16879086 - .idle_sleeps : 15799778 - .idle_entrytime : 49390647721066 nsecs - .idle_waketime : 49390647714831 nsecs - .idle_exittime : 49390647489308 nsecs - .idle_sleeptime : 44326049938322 nsecs - .iowait_sleeptime: 1007311574977 nsecs - .last_jiffies : 4307239958 - .next_jiffies : 4307239968 - .idle_expires : 49390684000000 nsecs -jiffies: 4307239953
diff --git a/tools/valgrind/drmemory/suppressions_full.txt b/tools/valgrind/drmemory/suppressions_full.txt index 71e88a1..b48c199 100644 --- a/tools/valgrind/drmemory/suppressions_full.txt +++ b/tools/valgrind/drmemory/suppressions_full.txt
@@ -1927,3 +1927,25 @@ name=bug_470848 blink_platform.dll!blink::Heap::RegionTree::lookup *!testing::internal::HandleExceptionsInMethodIfSupported<> + +HANDLE LEAK +name=https://crbug.com/480741 +system call NtDuplicateObject +KERNELBASE.dll!DuplicateHandle +KERNEL32.dll!DuplicateHandle +base.dll!base::SharedMemory::ShareToProcessCommon +gl_wrapper.dll!gfx::GLImageSharedMemory::Initialize +content.dll!content::GpuChannel::CreateImageForGpuMemoryBuffer +content.dll!content::GpuCommandBufferStub::OnCreateImage + +HANDLE LEAK +name=https://crbug.com/481305 +system call NtCreateSection +KERNELBASE.dll!CreateFileMappingW +base.dll!base::SharedMemory::Create +base.dll!base::SharedMemory::CreateAnonymous +content.dll!content::ChildThreadImpl::AllocateSharedMemory +content.dll!content::RenderThreadImpl::HostAllocateSharedMemoryBuffer +content.dll!content::RenderThreadImpl::AllocateSharedMemory +... +content.dll!content::WebGraphicsContext3DCommandBufferImpl::CreateContext
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt index cc442bc..ec243c5 100644 --- a/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt +++ b/tools/valgrind/gtest_exclude/base_unittests.gtest-drmemory_win32.txt
@@ -36,3 +36,5 @@ # so we can avoid excluding this for light mode. MessageLoopTestTypeUI.RecursiveDenial3 +# https://crbug.com/481231 +WinHeapDumpProviderTest.DumpInto
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt index 937bf28..ee2d424 100644 --- a/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt +++ b/tools/valgrind/gtest_exclude/base_unittests.gtest_mac.txt
@@ -18,3 +18,6 @@ MessageLoopTestTypeUI.RecursivePosts MessageLoopTestTypeIO.RecursivePosts MessageLoopTestTypeDefault.RecursivePosts + +# Check-fails on Valgrind/Mac, see https://crbug.com/481290 +MessagePumpLibeventTest.QuitWatcher
diff --git a/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt b/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt new file mode 100644 index 0000000..c080b7a --- /dev/null +++ b/tools/valgrind/gtest_exclude/blink_platform_unittests.gtest_win32.txt
@@ -0,0 +1,3 @@ +# https://crbug.com/480650: fails +HarfBuzzShaperTest.ResolveCandidateRunsLatin +HarfBuzzShaperTest.ResolveCandidateRunsLeadingCommon
diff --git a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt index 651e1506..c8b17b8f 100644 --- a/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt +++ b/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -32,3 +32,9 @@ # http://crbug.com/475172 BasicExtensionSettingsWebUITest.testUninstall + +# https://crbug.com/480721 +OutOfProcessProxyResolverBrowserTest.Verify + +# https://crbug.com/481687 +PluginPowerSaverBrowserTest.PluginMarkedEssentialAfterPosterClicked
diff --git a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt index 44f2bf8a..0e91022 100644 --- a/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt +++ b/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory_win32.txt
@@ -52,3 +52,6 @@ WebRtcBrowserTest.CanSetupVideoCallWith4To3AspectRatio WebRtcBrowserTest.NegotiateOfferWithBLine WebRtcBrowserTest.CanMakeAudioCallAndThenRenegotiateToVideo + +# https://crbug.com/480750 +MSE_ClearKey/EncryptedMediaTest.Playback_AudioClearVideo_WebM/0
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt index 3a72d3f0..56948ef 100644 --- a/tools/valgrind/memcheck/suppressions.txt +++ b/tools/valgrind/memcheck/suppressions.txt
@@ -2961,9 +2961,8 @@ fun:_Znw* fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_ fun:_ZN4base10WorkerPool16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_b - fun:_ZN3net16HostResolverImpl16LoopbackProbeJobC1ERKN4base7WeakPtrIS0_EE - fun:_ZN3net16HostResolverImplC1ERKNS_12HostResolver7OptionsEPNS_6NetLogE - fun:_ZN8chromeos24HostResolverImplChromeOSC1E13* + fun:_ZN3net16HostResolverImpl16LoopbackProbeJob* + fun:_ZN3net16HostResolverImplC* } { bug_387993 @@ -3025,18 +3024,6 @@ fun:_ZN14SkBitmapDevice8drawPathERK6SkDrawRK6SkPathRK7SkPaintPK8SkMatrixb } { - bug_392936 - Memcheck:Leak - fun:_Znw* - fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEESA_ - fun:_ZN4base10WorkerPool16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvEEES9_b - fun:_ZN3net16HostResolverImpl16LoopbackProbeJobC2ERKN4base7WeakPtrIS0_EE - fun:_ZN3net16HostResolverImplC1ERKNS_12HostResolver7OptionsEPNS_6NetLogE - fun:_ZN8chromeos24HostResolverImplChromeOSC1E13scoped_refptrIN4base16MessageLoopProxyEEPNS_19NetworkStateHandlerERKN3net12HostResolver7OptionsEPNS7_6NetLogE - fun:_ZN8chromeos24HostResolverImplChromeOS25CreateHostResolverForTestE13scoped_refptrIN4base16MessageLoopProxyEEPNS_19NetworkStateHandlerE - fun:_ZN28HostResolverImplChromeOSTest22InitializeHostResolverEv -} -{ bug_394558 Memcheck:Leak fun:_Znw*
diff --git a/tools/valgrind/memcheck/suppressions_mac.txt b/tools/valgrind/memcheck/suppressions_mac.txt index c9ed9bf..ac9c687 100644 --- a/tools/valgrind/memcheck/suppressions_mac.txt +++ b/tools/valgrind/memcheck/suppressions_mac.txt
@@ -94,6 +94,14 @@ fun:__CFRunLoopRun ... } +{ + # See also http://openradar.appspot.com/20698633 + bug_481286 + Memcheck:Leak + ... + fun:_ZN8Security13PluginSession6mallocEm + fun:_Z20CL_extractCSSMKeyNSSRK33cssm_x509_subject_public_key_infoRN8Security9AllocatorEPK11DecodedCert +} # Intentional leaks in AppKit, for an OS-level cache. Only appear on the first # run of each reboot. See also issues 105525, 257276, 340847. {
diff --git a/ui/accessibility/extensions/colorenhancer/manifest.json b/ui/accessibility/extensions/colorenhancer/manifest.json index 1e219c1..5a17d3d 100644 --- a/ui/accessibility/extensions/colorenhancer/manifest.json +++ b/ui/accessibility/extensions/colorenhancer/manifest.json
@@ -1,6 +1,6 @@ { "name": "__MSG_COLOR_ENHANCER_APPNAME__", - "version": "1.12.2", + "version": "1.12.3", "description": "__MSG_COLOR_ENHANCER_APPDESC__", "manifest_version": 2, "icons": { @@ -35,8 +35,7 @@ "<all_urls>" ], "css": [ - "res/cvd.css", - "res/setup.css" + "res/cvd.css" ], "js": [ "src/common.js",
diff --git a/ui/accessibility/extensions/colorenhancer/res/setup.css b/ui/accessibility/extensions/colorenhancer/res/setup.css index 89435115f..747b42b 100644 --- a/ui/accessibility/extensions/colorenhancer/res/setup.css +++ b/ui/accessibility/extensions/colorenhancer/res/setup.css
@@ -74,6 +74,7 @@ height: 40px; line-height: 1em; width: 40px; + pointer-events: none; } #severity {
diff --git a/ui/accessibility/extensions/colorenhancer/src/popup.html b/ui/accessibility/extensions/colorenhancer/src/popup.html index ff5e9906..6269f92 100644 --- a/ui/accessibility/extensions/colorenhancer/src/popup.html +++ b/ui/accessibility/extensions/colorenhancer/src/popup.html
@@ -16,14 +16,13 @@ <script type="text/javascript" src="popup.js"></script> </head> <body> - <h2><span i18n-content="IDS_COLOR_ENHANCER_APPNAME">Color Enhancer<span></h2> + <h2><span i18n-content="color_enhancer_appname"><span></h2> <table> <tr> - <th><span i18n-content="IDS_COLOR_ENHANCER_ENABLE">Enable?</span></th> + <th><span i18n-content="color_enhancer_enable"></span></th> <th> - <span i18n-content="IDS_COLOR_ENHANCER_ADJUSTMENT_FACTOR"> - Color adjustment + <span i18n-content="color_enhancer_adjustment_factor"> </span> </th> </tr> @@ -34,21 +33,19 @@ defaultValue="0.5"> </td> <td> - <!-- TOOD(kevers): i18n --> - <input id="setup" type="button" value="Setup"> + <button id="setup" i18n-content="color_enhancer_setup_button"></button> </td> </tr> </table> </div> - <div id="setup-panel" class = "collapsed"> - <h3><span i18n-content="IDS_COLOR_ENHANCER_ADVANCED">Setup:</span></h3> + <div id="setup-panel" class="collapsed"> + <h3><span i18n-content="color_enhancer_setup_heading"></span></h3> <section id="step-1"> <div> - <span i18n-content="IDS_COLOR_ENHANCER_TYPE_CHOICE"> - Step 1: Select the row with the faintest stars: + <span i18n-content="color_enhancer_type_choice"> </span> - </div> + </div> <div class="template swatch"> <span>⋆</span> </div> @@ -59,18 +56,15 @@ </section> <section id="step-2"> <div> - <span i18n-content="IDS_COLOR_ENHANCER_SEVERITY"> - Step 2: Adjust the slider until all of the stars are visible in the - selected row + <span i18n-content="color_enhancer_severity"> </span> <input id="severity" type="range" min=0 max=1.0 step=0.1 value="0"> </div> </section> <div id="setup-button-strip" class="row"> - <!-- TODO(kevers): i18n --> - <input id="reset" type="button" value="Reset"> - <input id="ok" type="button" value="OK"> - <input id="cancel" type="button" value="Cancel"> + <button id="reset" i18n-content="color_enhancer_reset"></button> + <button id="ok" i18n-content="color_enhancer_ok"></button> + <button id="cancel" i18n-content="color_enhancer_cancel"></button> </div> </div> </body>
diff --git a/ui/accessibility/extensions/colorenhancer/src/popup.js b/ui/accessibility/extensions/colorenhancer/src/popup.js index 0703714..06d3296 100644 --- a/ui/accessibility/extensions/colorenhancer/src/popup.js +++ b/ui/accessibility/extensions/colorenhancer/src/popup.js
@@ -107,7 +107,7 @@ var toCssColor = function(rgb) { return 'rgb(' + rgb.join(',') + ')'; }; - var row = document.createElement('div'); + var row = document.createElement('label'); row.classList.add('row'); var button = document.createElement('input'); @@ -120,6 +120,7 @@ button.addEventListener('change', function() { onTypeChange(this.value); }); + button.setAttribute('aria-label', type); SWATCH_COLORS.forEach(function(data) { var swatch = document.querySelector('.swatch.template').cloneNode(true); @@ -320,6 +321,13 @@ * currently visible tab. */ function initialize() { + var i18nElements = document.querySelectorAll('*[i18n-content]'); + for (var i = 0; i < i18nElements.length; i++) { + var elem = i18nElements[i]; + var msg = elem.getAttribute('i18n-content'); + elem.textContent = chrome.i18n.getMessage(msg); + } + $('setup').onclick = function() { $('setup-panel').classList.remove('collapsed'); // Store current settings in the event of a canceled setup.
diff --git a/ui/accessibility/extensions/strings/accessibility_extensions_strings.grd b/ui/accessibility/extensions/strings/accessibility_extensions_strings.grd index 35df95e..33c4f60c 100644 --- a/ui/accessibility/extensions/strings/accessibility_extensions_strings.grd +++ b/ui/accessibility/extensions/strings/accessibility_extensions_strings.grd
@@ -274,7 +274,7 @@ Degree </message> <message desc="Title for a dropdown selecting between colors to enhance." name="IDS_COLOR_ENHANCER_TYPE_CHOICE"> - Improve perception for: + Step 1: Select the row with the faintest stars: </message> <message desc="Choice to enhancing the red color." name="IDS_COLOR_ENHANCER_TYPE_RED"> Red @@ -285,20 +285,27 @@ <message desc="Choice to enhancing the blue color." name="IDS_COLOR_ENHANCER_TYPE_BLUE"> Blue </message> - <message desc="Title for button that will apply these settings to all currently open websites." name="IDS_COLOR_ENHANCER_RESET"> - Apply to all sites - </message> <message desc="Title for checkbox that enables the extension." name="IDS_COLOR_ENHANCER_ENABLE"> Enable? </message> - <message desc="Title for checkbox that enables color vision deficiency simulation." name="IDS_COLOR_ENHANCER_SIMULATE"> - Simulate? - </message> <message desc="Title for slider changes color vision deficiency severity." name="IDS_COLOR_ENHANCER_SEVERITY"> - Severity + Step 2: Adjust the slider until all of the stars are visible in the + selected row </message> - <message desc="Title for section containing advanced settings." name="IDS_COLOR_ENHANCER_ADVANCED"> - Advanced settings + <message desc="Title for the heading before the section containing setup." name="IDS_COLOR_ENHANCER_SETUP_HEADING"> + Setup: + </message> + <message desc="Button that resets the color enhancer extension to its default state." name="IDS_COLOR_ENHANCER_RESET"> + Reset + </message> + <message desc="OK button for the color enhancer setup." name="IDS_COLOR_ENHANCER_OK"> + OK + </message> + <message desc="Cancel button for the color enhancer setup." name="IDS_COLOR_ENHANCER_CANCEL"> + Cancel + </message> + <message desc="Button for the color enhancer popup that opens the Setup part of the popup." name="IDS_COLOR_ENHANCER_SETUP_BUTTON"> + Setup </message> </messages>
diff --git a/ui/accessibility/platform/atk_util_auralinux.cc b/ui/accessibility/platform/atk_util_auralinux.cc index 7fcaf219..5d25c51 100644 --- a/ui/accessibility/platform/atk_util_auralinux.cc +++ b/ui/accessibility/platform/atk_util_auralinux.cc
@@ -140,6 +140,14 @@ } AtkUtilAuraLinux::AtkUtilAuraLinux() { +} + +void AtkUtilAuraLinux::Initialize( + scoped_refptr<base::TaskRunner> init_task_runner) { + // TODO(k.czech): use |init_task_runner| to post a task to do the + // initialization rather than doing it on this thread. + // http://crbug.com/468112 + // Register our util class. g_type_class_unref(g_type_class_ref(ATK_UTIL_AURALINUX_TYPE));
diff --git a/ui/accessibility/platform/atk_util_auralinux.h b/ui/accessibility/platform/atk_util_auralinux.h index 349c41a..8ecb1668 100644 --- a/ui/accessibility/platform/atk_util_auralinux.h +++ b/ui/accessibility/platform/atk_util_auralinux.h
@@ -8,6 +8,10 @@ #include "base/memory/singleton.h" #include "ui/accessibility/ax_export.h" +namespace base { +class TaskRunner; +} + namespace ui { // This singleton class initializes ATK (accessibility toolkit) and @@ -21,6 +25,8 @@ AtkUtilAuraLinux(); virtual ~AtkUtilAuraLinux(); + void Initialize(scoped_refptr<base::TaskRunner> init_task_runner); + private: friend struct DefaultSingletonTraits<AtkUtilAuraLinux>; };
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index 8538200..56bdfbff 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/strings/sys_string_conversions.h" +#include "base/task_runner.h" #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/platform/atk_util_auralinux.h" #include "ui/accessibility/platform/ax_platform_node_delegate.h" @@ -287,7 +288,12 @@ // static void AXPlatformNodeAuraLinux::SetApplication(AXPlatformNode* application) { application_ = application; - AtkUtilAuraLinux::GetInstance(); +} + +// static +void AXPlatformNodeAuraLinux::StaticInitialize( + scoped_refptr<base::TaskRunner> init_task_runner) { + AtkUtilAuraLinux::GetInstance()->Initialize(init_task_runner); } AtkRole AXPlatformNodeAuraLinux::GetAtkRole() {
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h index 8f86bc71..7f70f84 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.h +++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -7,9 +7,14 @@ #include <atk/atk.h> +#include "base/memory/ref_counted.h" #include "ui/accessibility/ax_export.h" #include "ui/accessibility/platform/ax_platform_node_base.h" +namespace base { +class TaskRunner; +} + namespace ui { // Implements accessibility on Aura Linux using ATK. @@ -22,6 +27,10 @@ AX_EXPORT static void SetApplication(AXPlatformNode* application); static AXPlatformNode* application() { return application_; } + // Do static initialization using the given task runner for file operations. + AX_EXPORT static void StaticInitialize( + scoped_refptr<base::TaskRunner> init_task_runner); + AtkRole GetAtkRole(); void GetAtkState(AtkStateSet* state_set); void GetAtkRelations(AtkRelationSet* atk_relation_set);
diff --git a/ui/android/java/src/org/chromium/ui/VSyncMonitor.java b/ui/android/java/src/org/chromium/ui/VSyncMonitor.java index 8974b99..83d02d9 100644 --- a/ui/android/java/src/org/chromium/ui/VSyncMonitor.java +++ b/ui/android/java/src/org/chromium/ui/VSyncMonitor.java
@@ -4,9 +4,7 @@ package org.chromium.ui; -import android.annotation.SuppressLint; import android.content.Context; -import android.os.Build; import android.os.Handler; import android.view.Choreographer; import android.view.WindowManager; @@ -15,13 +13,9 @@ /** * Notifies clients of the default displays's vertical sync pulses. - * On ICS, VSyncMonitor relies on setVSyncPointForICS() being called to set a reasonable - * approximation of a vertical sync starting point; see also http://crbug.com/156397. */ -@SuppressLint("NewApi") public class VSyncMonitor { private static final long NANOSECONDS_PER_SECOND = 1000000000; - private static final long NANOSECONDS_PER_MILLISECOND = 1000000; private static final long NANOSECONDS_PER_MICROSECOND = 1000; private boolean mInsideVSync = false; @@ -49,14 +43,9 @@ private boolean mHaveRequestInFlight; - // Choreographer is used to detect vsync on >= JB. private final Choreographer mChoreographer; private final Choreographer.FrameCallback mVSyncFrameCallback; - - // On ICS we just post a task through the handler (http://crbug.com/156397) - private final Runnable mVSyncRunnableCallback; private long mGoodStartingPointNano; - private long mLastPostedNano; // If the monitor is activated after having been idle, we synthesize the first vsync to reduce // latency. @@ -70,16 +59,6 @@ * @param listener The listener receiving VSync notifications. */ public VSyncMonitor(Context context, VSyncMonitor.Listener listener) { - this(context, listener, true); - } - - /** - * Constructs a VSyncMonitor - * @param context The application context. - * @param listener The listener receiving VSync notifications. - * @param enableJBVsync Whether to allow Choreographer-based notifications on JB and up. - */ - public VSyncMonitor(Context context, VSyncMonitor.Listener listener, boolean enableJBVSync) { mListener = listener; float refreshRate = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay().getRefreshRate(); @@ -88,43 +67,25 @@ if (refreshRate <= 0) refreshRate = 60; mRefreshPeriodNano = (long) (NANOSECONDS_PER_SECOND / refreshRate); - if (enableJBVSync && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - // Use Choreographer on JB+ to get notified of vsync. - mChoreographer = Choreographer.getInstance(); - mVSyncFrameCallback = new Choreographer.FrameCallback() { - @Override - public void doFrame(long frameTimeNanos) { - TraceEvent.begin("VSync"); - if (useEstimatedRefreshPeriod && mConsecutiveVSync) { - // Display.getRefreshRate() is unreliable on some platforms. - // Adjust refresh period- initial value is based on Display.getRefreshRate() - // after that it asymptotically approaches the real value. - long lastRefreshDurationNano = frameTimeNanos - mGoodStartingPointNano; - float lastRefreshDurationWeight = 0.1f; - mRefreshPeriodNano += (long) (lastRefreshDurationWeight - * (lastRefreshDurationNano - mRefreshPeriodNano)); - } - mGoodStartingPointNano = frameTimeNanos; - onVSyncCallback(frameTimeNanos, getCurrentNanoTime()); - TraceEvent.end("VSync"); + mChoreographer = Choreographer.getInstance(); + mVSyncFrameCallback = new Choreographer.FrameCallback() { + @Override + public void doFrame(long frameTimeNanos) { + TraceEvent.begin("VSync"); + if (useEstimatedRefreshPeriod && mConsecutiveVSync) { + // Display.getRefreshRate() is unreliable on some platforms. + // Adjust refresh period- initial value is based on Display.getRefreshRate() + // after that it asymptotically approaches the real value. + long lastRefreshDurationNano = frameTimeNanos - mGoodStartingPointNano; + float lastRefreshDurationWeight = 0.1f; + mRefreshPeriodNano += (long) (lastRefreshDurationWeight + * (lastRefreshDurationNano - mRefreshPeriodNano)); } - }; - mVSyncRunnableCallback = null; - } else { - // On ICS we just hope that running tasks is relatively predictable. - mChoreographer = null; - mVSyncFrameCallback = null; - mVSyncRunnableCallback = new Runnable() { - @Override - public void run() { - TraceEvent.begin("VSyncTimer"); - final long currentTime = getCurrentNanoTime(); - onVSyncCallback(currentTime, currentTime); - TraceEvent.end("VSyncTimer"); - } - }; - mLastPostedNano = 0; - } + mGoodStartingPointNano = frameTimeNanos; + onVSyncCallback(frameTimeNanos, getCurrentNanoTime()); + TraceEvent.end("VSync"); + } + }; mSyntheticVSyncRunnable = new Runnable() { @Override public void run() { @@ -145,13 +106,6 @@ } /** - * Determine whether a true vsync signal is available on this platform. - */ - private boolean isVSyncSignalAvailable() { - return mChoreographer != null; - } - - /** * Request to be notified of the closest display vsync events. * Listener.onVSync() will be called soon after the upcoming vsync pulses. */ @@ -160,14 +114,6 @@ } /** - * Set the best guess of the point in the past when the vsync has happened. - * @param goodStartingPointNano Known vsync point in the past. - */ - public void setVSyncPointForICS(long goodStartingPointNano) { - mGoodStartingPointNano = goodStartingPointNano; - } - - /** * @return true if onVSync handler is executing. If onVSync handler * introduces invalidations, View#invalidate() should be called. If * View#postInvalidateOnAnimation is called instead, the corresponding onDraw @@ -200,12 +146,8 @@ if (mHaveRequestInFlight) return; mHaveRequestInFlight = true; if (postSyntheticVSync()) return; - if (isVSyncSignalAvailable()) { - mConsecutiveVSync = mInsideVSync; - mChoreographer.postFrameCallback(mVSyncFrameCallback); - } else { - postRunnableCallback(); - } + mConsecutiveVSync = mInsideVSync; + mChoreographer.postFrameCallback(mVSyncFrameCallback); } private boolean postSyntheticVSync() { @@ -224,20 +166,4 @@ * mRefreshPeriodNano; return lastRefreshTime; } - - private void postRunnableCallback() { - assert !isVSyncSignalAvailable(); - final long currentTime = getCurrentNanoTime(); - final long lastRefreshTime = estimateLastVSyncTime(currentTime); - long delay = (lastRefreshTime + mRefreshPeriodNano) - currentTime; - assert delay > 0 && delay <= mRefreshPeriodNano; - - if (currentTime + delay <= mLastPostedNano + mRefreshPeriodNano / 2) { - delay += mRefreshPeriodNano; - } - - mLastPostedNano = currentTime + delay; - if (delay == 0) mHandler.post(mVSyncRunnableCallback); - else mHandler.postDelayed(mVSyncRunnableCallback, delay / NANOSECONDS_PER_MILLISECOND); - } }
diff --git a/ui/android/java/src/org/chromium/ui/base/ActivityWindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/ActivityWindowAndroid.java index 5c20d72..b32cd9b 100644 --- a/ui/android/java/src/org/chromium/ui/base/ActivityWindowAndroid.java +++ b/ui/android/java/src/org/chromium/ui/base/ActivityWindowAndroid.java
@@ -10,9 +10,6 @@ import android.content.Intent; import android.content.IntentSender.SendIntentException; -import org.chromium.base.ActivityState; -import org.chromium.base.ApplicationStatus; - import java.lang.ref.WeakReference; /** @@ -20,8 +17,7 @@ * Activity Instance. * Only instantiate this class when you need the implemented features. */ -public class ActivityWindowAndroid - extends WindowAndroid implements ApplicationStatus.ActivityStateListener { +public class ActivityWindowAndroid extends WindowAndroid { // Constants used for intent request code bounding. private static final int REQUEST_CODE_PREFIX = 1000; private static final int REQUEST_CODE_RANGE_SIZE = 100; @@ -30,27 +26,9 @@ private final WeakReference<Activity> mActivityRef; private int mNextRequestCode = 0; - /** - * Creates an Activity-specific WindowAndroid with associated intent functionality. - * TODO(jdduke): Remove this overload when all callsites have been updated to - * indicate their activity state listening preference. - * @param activity The activity associated with the WindowAndroid. - */ public ActivityWindowAndroid(Activity activity) { - this(activity, true); - } - - /** - * Creates an Activity-specific WindowAndroid with associated intent functionality. - * @param activity The activity associated with the WindowAndroid. - * @param listenToActivityState Whether to listen to activity state changes. - */ - public ActivityWindowAndroid(Activity activity, boolean listenToActivityState) { super(activity.getApplicationContext()); mActivityRef = new WeakReference<Activity>(activity); - if (listenToActivityState) { - ApplicationStatus.registerStateListenerForActivity(this, activity); - } } @Override @@ -121,15 +99,6 @@ return new WeakReference<Activity>(mActivityRef.get()); } - @Override - public void onActivityStateChange(Activity activity, int newState) { - if (newState == ActivityState.PAUSED) { - onActivityPaused(); - } else if (newState == ActivityState.RESUMED) { - onActivityResumed(); - } - } - private int generateNextRequestCode() { int requestCode = REQUEST_CODE_PREFIX + mNextRequestCode; mNextRequestCode = (mNextRequestCode + 1) % REQUEST_CODE_RANGE_SIZE;
diff --git a/ui/android/java/src/org/chromium/ui/base/TouchDevice.java b/ui/android/java/src/org/chromium/ui/base/TouchDevice.java index 440e95c8..a5fc9793 100644 --- a/ui/android/java/src/org/chromium/ui/base/TouchDevice.java +++ b/ui/android/java/src/org/chromium/ui/base/TouchDevice.java
@@ -57,7 +57,10 @@ int pointerTypesVal = 0; for (int deviceId : InputDevice.getDeviceIds()) { - int sources = InputDevice.getDevice(deviceId).getSources(); + InputDevice inputDevice = InputDevice.getDevice(deviceId); + if (inputDevice == null) continue; + + int sources = inputDevice.getSources(); if (hasSource(sources, InputDevice.SOURCE_MOUSE) || hasSource(sources, InputDevice.SOURCE_STYLUS) @@ -84,7 +87,10 @@ int hoverTypesVal = 0; for (int deviceId : InputDevice.getDeviceIds()) { - int sources = InputDevice.getDevice(deviceId).getSources(); + InputDevice inputDevice = InputDevice.getDevice(deviceId); + if (inputDevice == null) continue; + + int sources = inputDevice.getSources(); if (hasSource(sources, InputDevice.SOURCE_MOUSE) || hasSource(sources, InputDevice.SOURCE_TOUCHPAD)
diff --git a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java index 0bf7bd1..0870221 100644 --- a/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java +++ b/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java
@@ -236,24 +236,6 @@ } /** - * For window instances associated with an activity, notifies any listeners - * that the activity has been paused. - */ - protected void onActivityPaused() { - if (mNativeWindowAndroid == 0) return; - nativeOnActivityPaused(mNativeWindowAndroid); - } - - /** - * For window instances associated with an activity, notifies any listeners - * that the activity has been paused. - */ - protected void onActivityResumed() { - if (mNativeWindowAndroid == 0) return; - nativeOnActivityResumed(mNativeWindowAndroid); - } - - /** * Responds to the intent result if the intent was created by the native window. * @param requestCode Request code of the requested intent. * @param resultCode Result code of the requested intent. @@ -369,8 +351,6 @@ private native void nativeOnVSync(long nativeWindowAndroid, long vsyncTimeMicros, long vsyncPeriodMicros); - private native void nativeOnActivityPaused(long nativeWindowAndroid); - private native void nativeOnActivityResumed(long nativeWindowAndroid); private native void nativeDestroy(long nativeWindowAndroid); }
diff --git a/ui/android/window_android.cc b/ui/android/window_android.cc index 9a476892..d8623a5 100644 --- a/ui/android/window_android.cc +++ b/ui/android/window_android.cc
@@ -43,11 +43,6 @@ OnCompositingDidCommit()); } -void WindowAndroid::OnVisibilityChanged(bool visible) { - FOR_EACH_OBSERVER(WindowAndroidObserver, observer_list_, - OnRootWindowVisibilityChanged(visible)); -} - void WindowAndroid::AddObserver(WindowAndroidObserver* observer) { if (!observer_list_.HasObserver(observer)) observer_list_.AddObserver(observer); @@ -105,14 +100,6 @@ compositor_->OnVSync(frame_time, vsync_period); } -void WindowAndroid::OnActivityResumed(JNIEnv* env, jobject obj) { - FOR_EACH_OBSERVER(WindowAndroidObserver, observer_list_, OnActivityResumed()); -} - -void WindowAndroid::OnActivityPaused(JNIEnv* env, jobject obj) { - FOR_EACH_OBSERVER(WindowAndroidObserver, observer_list_, OnActivityPaused()); -} - // ---------------------------------------------------------------------------- // Native JNI methods // ----------------------------------------------------------------------------
diff --git a/ui/android/window_android.h b/ui/android/window_android.h index 005f4d67..f464a11 100644 --- a/ui/android/window_android.h +++ b/ui/android/window_android.h
@@ -43,7 +43,6 @@ // Compositor callback relay. void OnCompositingDidCommit(); - void OnVisibilityChanged(bool visible); void AttachCompositor(WindowAndroidCompositor* compositor); void DetachCompositor(); @@ -60,8 +59,6 @@ jlong time_micros, jlong period_micros); void Animate(base::TimeTicks begin_frame_time); - void OnActivityPaused(JNIEnv* env, jobject obj); - void OnActivityResumed(JNIEnv* env, jobject obj); private: ~WindowAndroid();
diff --git a/ui/android/window_android_observer.h b/ui/android/window_android_observer.h index 4e97d2a5..05db5ce 100644 --- a/ui/android/window_android_observer.h +++ b/ui/android/window_android_observer.h
@@ -12,19 +12,12 @@ class UI_ANDROID_EXPORT WindowAndroidObserver { public: virtual void OnCompositingDidCommit() = 0; - virtual void OnRootWindowVisibilityChanged(bool visible) = 0; virtual void OnAttachCompositor() = 0; virtual void OnDetachCompositor() = 0; virtual void OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period) = 0; virtual void OnAnimate(base::TimeTicks frame_begin_time) {} - // Note that activity state callbacks will only be made if the WindowAndroid - // has been explicitly subscribed to receive them. The observer instance - // should account for whether or not this is the case. - virtual void OnActivityPaused() = 0; - virtual void OnActivityResumed() = 0; - protected: virtual ~WindowAndroidObserver() {} };
diff --git a/ui/aura/window_tree_host_mac.h b/ui/aura/window_tree_host_mac.h index 6505874..5c7ca98 100644 --- a/ui/aura/window_tree_host_mac.h +++ b/ui/aura/window_tree_host_mac.h
@@ -26,28 +26,28 @@ class AURA_EXPORT WindowTreeHostMac : public WindowTreeHost { public: explicit WindowTreeHostMac(const gfx::Rect& bounds); - virtual ~WindowTreeHostMac(); + ~WindowTreeHostMac() override; private: // WindowTreeHost Overrides. - virtual ui::EventSource* GetEventSource() override; - virtual gfx::AcceleratedWidget GetAcceleratedWidget() override; - virtual void Show() override; - virtual void Hide() override; - virtual void ToggleFullScreen() override; - virtual gfx::Rect GetBounds() const override; - virtual void SetBounds(const gfx::Rect& bounds) override; - virtual gfx::Insets GetInsets() const override; - virtual void SetInsets(const gfx::Insets& insets) override; - virtual gfx::Point GetLocationOnNativeScreen() const override; - virtual void SetCapture() override; - virtual void ReleaseCapture() override; - virtual bool ConfineCursorToRootWindow() override; - virtual void UnConfineCursor() override; - virtual void SetCursorNative(gfx::NativeCursor cursor_type) override; - virtual void MoveCursorToNative(const gfx::Point& location) override; - virtual void OnCursorVisibilityChangedNative(bool show) override; - virtual void OnDeviceScaleFactorChanged(float device_scale_factor) override; + ui::EventSource* GetEventSource() override; + gfx::AcceleratedWidget GetAcceleratedWidget() override; + void Show() override; + void Hide() override; + void ToggleFullScreen() override; + gfx::Rect GetBounds() const override; + void SetBounds(const gfx::Rect& bounds) override; + gfx::Insets GetInsets() const override; + void SetInsets(const gfx::Insets& insets) override; + gfx::Point GetLocationOnNativeScreen() const override; + void SetCapture() override; + void ReleaseCapture() override; + bool ConfineCursorToRootWindow() override; + void UnConfineCursor() override; + void SetCursorNative(gfx::NativeCursor cursor_type) override; + void MoveCursorToNative(const gfx::Point& location) override; + void OnCursorVisibilityChangedNative(bool show) override; + void OnDeviceScaleFactorChanged(float device_scale_factor) override; private: base::scoped_nsobject<NSWindow> window_;
diff --git a/ui/base/ime/chromeos/ime_keyboard_x11_unittest.cc b/ui/base/ime/chromeos/ime_keyboard_x11_unittest.cc index 358eab7..d746b639 100644 --- a/ui/base/ime/chromeos/ime_keyboard_x11_unittest.cc +++ b/ui/base/ime/chromeos/ime_keyboard_x11_unittest.cc
@@ -27,18 +27,18 @@ ImeKeyboardTest() { } - virtual void SetUp() { + void SetUp() override { xkey_.reset(ImeKeyboard::Create()); xkey_->AddObserver(this); caps_changed_ = false; } - virtual void TearDown() { + void TearDown() override { xkey_->RemoveObserver(this); xkey_.reset(); } - virtual void OnCapsLockChanged(bool enabled) override { + void OnCapsLockChanged(bool enabled) override { caps_changed_ = true; }
diff --git a/ui/base/ios/cru_context_menu_controller.h b/ui/base/ios/cru_context_menu_controller.h index 66fdf9d..cb966fa00 100644 --- a/ui/base/ios/cru_context_menu_controller.h +++ b/ui/base/ios/cru_context_menu_controller.h
@@ -11,8 +11,11 @@ // Abstracts displaying context menus for all device form factors, given a // CRUContextMenuHolder with the title and action to associate to each menu // item. Will show a sheet on the phone and use a popover on a tablet. -@interface CRUContextMenuController : NSObject<UIActionSheetDelegate, - UIPopoverControllerDelegate> +@interface CRUContextMenuController : NSObject + +// Whether the context menu is visible. +@property(nonatomic, readonly, getter=isVisible) BOOL visible; + // Displays a context menu. If on a tablet, |localPoint| is the point in // |view|'s coordinates to show the popup. If a phone, |localPoint| is unused // since the display is a sheet, but |view| is still used to attach the sheet to @@ -22,13 +25,6 @@ atPoint:(CGPoint)localPoint inView:(UIView*)view; -// Returns whether the context menu is visible. -- (BOOL)isVisible; - -@end - -@interface CRUContextMenuController (UsedForTesting) -@property (readonly) UIActionSheet* sheet; @end #endif // UI_BASE_IOS_CRU_CONTEXT_MENU_CONTROLLER_H_
diff --git a/ui/base/ios/cru_context_menu_controller.mm b/ui/base/ios/cru_context_menu_controller.mm index 40a08df..c81615c0 100644 --- a/ui/base/ios/cru_context_menu_controller.mm +++ b/ui/base/ios/cru_context_menu_controller.mm
@@ -7,70 +7,205 @@ #include <algorithm> #include "base/ios/ios_util.h" +#include "base/ios/weak_nsobject.h" #include "base/logging.h" #import "base/mac/scoped_nsobject.h" -#include "base/strings/sys_string_conversions.h" #include "ui/base/device_form_factor.h" #import "ui/base/ios/cru_context_menu_holder.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/font_list.h" #import "ui/gfx/ios/NSString+CrStringDrawing.h" -#include "ui/gfx/text_elider.h" #include "ui/strings/grit/ui_strings.h" -@implementation CRUContextMenuController { - // Holds all the titles and actions for the menu. - base::scoped_nsobject<CRUContextMenuHolder> menuHolder_; - // The action sheet controller used to display the UI. - base::scoped_nsobject<UIActionSheet> sheet_; - // Whether the context menu is visible. - BOOL visible_; -} +namespace { - -// Clean up and reset for the next time. -- (void)cleanup { - // iOS 8 fires multiple callbacks when a button is clicked; one round for the - // button that's clicked and a second round with |buttonIndex| equivalent to - // tapping outside the context menu. Here the sheet's delegate is reset so - // that only the first round of callbacks is processed. - // Note that iOS 8 needs the |sheet_| to stay alive so it's not reset until - // this CRUContextMenuController is dealloc'd. - [sheet_ setDelegate:nil]; - menuHolder_.reset(); - visible_ = NO; -} - -- (void)dealloc { - if (visible_) { - // Context menu must be dismissed explicitly if it is still visible at this - // stage. - NSUInteger cancelButtonIndex = [menuHolder_ itemCount]; - [sheet_ dismissWithClickedButtonIndex:cancelButtonIndex animated:NO]; +// Returns the screen's height in points. +CGFloat GetScreenHeight() { + DCHECK(!base::ios::IsRunningOnIOS8OrLater()); + switch ([[UIApplication sharedApplication] statusBarOrientation]) { + case UIInterfaceOrientationLandscapeLeft: + case UIInterfaceOrientationLandscapeRight: + return CGRectGetWidth([[UIScreen mainScreen] applicationFrame]); + case UIInterfaceOrientationPortraitUpsideDown: + case UIInterfaceOrientationPortrait: + case UIInterfaceOrientationUnknown: + return CGRectGetHeight([[UIScreen mainScreen] applicationFrame]); } - sheet_.reset(); - [super dealloc]; +} + +} // namespace + +// Abstracts system implementation of popovers and action sheets. +@protocol CRUContextMenuControllerImpl<NSObject> + +// Whether the context menu is visible. +@property(nonatomic, readonly, getter=isVisible) BOOL visible; + +// Displays a context menu. +- (void)showWithHolder:(CRUContextMenuHolder*)menuHolder + atPoint:(CGPoint)localPoint + inView:(UIView*)view; +@end + +// Backs up CRUContextMenuController on iOS 7 by using UIActionSheet. +@interface CRUActionSheetController + : NSObject<CRUContextMenuControllerImpl, UIActionSheetDelegate> { + // The action sheet used to display the UI. + base::scoped_nsobject<UIActionSheet> _sheet; + // Holds all the titles and actions for the menu. + base::scoped_nsobject<CRUContextMenuHolder> _menuHolder; +} +@end + +// Backs up CRUContextMenuController on iOS 8 and higher by using +// UIAlertController. +@interface CRUAlertController : NSObject<CRUContextMenuControllerImpl> +// Redefined to readwrite. +@property(nonatomic, readwrite, getter=isVisible) BOOL visible; +@end + +// Displays a context menu. Implements Bridge pattern. +@implementation CRUContextMenuController { + // Implementation specific for iOS version. + base::scoped_nsprotocol<id<CRUContextMenuControllerImpl>> _impl; } - (BOOL)isVisible { - return visible_; + return [_impl isVisible]; } +- (instancetype)init { + self = [super init]; + if (self) { + if (base::ios::IsRunningOnIOS8OrLater()) { + _impl.reset([[CRUAlertController alloc] init]); + } else { + _impl.reset([[CRUActionSheetController alloc] init]); + } + } + return self; +} + +- (void)showWithHolder:(CRUContextMenuHolder*)menuHolder + atPoint:(CGPoint)point + inView:(UIView*)view { + DCHECK(menuHolder.itemCount); + // Check that the view is still visible on screen, otherwise just return and + // don't show the context menu. + if (![view window] && ![view isKindOfClass:[UIWindow class]]) + return; + [_impl showWithHolder:menuHolder atPoint:point inView:view]; +} + +@end + +#pragma mark - iOS 7 + +@implementation CRUActionSheetController +@synthesize visible = _visible; + +- (void)dealloc { + if (_visible) { + // Context menu must be dismissed explicitly if it is still visible. + NSUInteger cancelButtonIndex = [_menuHolder itemCount]; + [_sheet dismissWithClickedButtonIndex:cancelButtonIndex animated:NO]; + } + [super dealloc]; +} + +- (void)showWithHolder:(CRUContextMenuHolder*)menuHolder + atPoint:(CGPoint)point + inView:(UIView*)view { + // If the content of UIActionSheet does not fit the screen then scrollbars + // are added to the menu items area. If that's the case, elide the title to + // avoid having scrollbars for menu items. + CGSize spaceAvailableForTitle = + [self sizeForTitleThatFitsMenuWithHolder:menuHolder + atPoint:point + inView:view]; + NSString* menuTitle = menuHolder.menuTitle; + if (menuTitle) { + // Show at least one line of text, even if that means the action sheet's + // items will need to scroll. + const CGFloat kMinimumVerticalSpace = 21; + spaceAvailableForTitle.height = + std::max(kMinimumVerticalSpace, spaceAvailableForTitle.height); + menuTitle = [menuTitle cr_stringByElidingToFitSize:spaceAvailableForTitle]; + } + + // Present UIActionSheet. + _sheet.reset( + [self newActionSheetWithHolder:menuHolder title:menuTitle delegate:self]); + [_sheet setCancelButtonIndex:menuHolder.itemCount]; + [_sheet showFromRect:CGRectMake(point.x, point.y, 1.0, 1.0) + inView:view + animated:YES]; + + _menuHolder.reset([menuHolder retain]); + _visible = YES; +} + +#pragma mark Implementation + +// Returns an approximation of the free space available for the title of an +// actionSheet filled with |menu| shown in |view| at |point|. +- (CGSize)sizeForTitleThatFitsMenuWithHolder:(CRUContextMenuHolder*)menuHolder + atPoint:(CGPoint)point + inView:(UIView*)view { + // Create a dummy UIActionSheet. + base::scoped_nsobject<UIActionSheet> dummySheet( + [self newActionSheetWithHolder:menuHolder title:nil delegate:nil]); + // Temporarily add the dummy UIActionSheet to |view|. + [dummySheet showFromRect:CGRectMake(point.x, point.y, 1.0, 1.0) + inView:view + animated:NO]; + // On iPad the actionsheet is positioned under or over |point| (as opposed + // to next to it) when the user clicks within approximately 200 points of + // respectively the top or bottom edge. This reduces the amount of vertical + // space available for the title, hence the large padding on ipad. + const CGFloat kPaddingiPad = 200; + const CGFloat kPaddingiPhone = 20; + BOOL isIPad = ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET; + const CGFloat padding = isIPad ? kPaddingiPad : kPaddingiPhone; + // A title uses the full width of the actionsheet and all the vertical + // space on the screen. + CGSize result = CGSizeMake( + CGRectGetWidth([dummySheet frame]), + GetScreenHeight() - CGRectGetHeight([dummySheet frame]) - padding); + [dummySheet dismissWithClickedButtonIndex:0 animated:NO]; + return result; +} + +// Returns an UIActionSheet. Callers responsible for releasing returned object. +- (UIActionSheet*)newActionSheetWithHolder:(CRUContextMenuHolder*)menuHolder + title:(NSString*)title + delegate:(id<UIActionSheetDelegate>)delegate { + UIActionSheet* sheet = [[UIActionSheet alloc] initWithTitle:title + delegate:delegate + cancelButtonTitle:nil + destructiveButtonTitle:nil + otherButtonTitles:nil]; + + for (NSString* itemTitle in menuHolder.itemTitles) { + [sheet addButtonWithTitle:itemTitle]; + } + [sheet addButtonWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL)]; + return sheet; +} + +#pragma mark UIActionSheetDelegate + // Called when the action sheet is dismissed in the modal context menu sheet. // There is no way to dismiss the sheet without going through this method. Note // that on iPad this method is called with the index of an nonexistent cancel // button when the user taps outside the sheet. - (void)actionSheet:(UIActionSheet*)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { - // On iOS 8, if the user taps an item in the context menu, then taps outside - // the context menu, the |buttonIndex| passed into this method may be - // different from the |buttonIndex| passed into - // |actionsheet:willDismissWithButtonIndex:|. See crbug.com/411894. - NSUInteger buttonIndexU = buttonIndex; + NSUInteger unsignedButtonIndex = buttonIndex; // Assumes "cancel" button is last in order. - if (buttonIndexU < [menuHolder_ itemCount]) - [menuHolder_ performActionAtIndex:buttonIndexU]; - [self cleanup]; + if (unsignedButtonIndex < [_menuHolder itemCount]) + [_menuHolder performActionAtIndex:unsignedButtonIndex]; + _menuHolder.reset(); + _visible = NO; } // Called when the user chooses a button in the modal context menu sheet. Note @@ -80,133 +215,71 @@ clickedButtonAtIndex:(NSInteger)buttonIndex { // Some use cases (e.g. opening a new tab on handset) should not wait for the // action sheet to animate away before executing the action. - if ([menuHolder_ shouldDismissImmediatelyOnClickedAtIndex:buttonIndex]) { - [sheet_ dismissWithClickedButtonIndex:buttonIndex animated:NO]; - } -} - -#pragma mark - -#pragma mark WebContextMenuDelegate methods - -// Displays a menu using a sheet with the given title. -- (void)showWithHolder:(CRUContextMenuHolder*)menuHolder - atPoint:(CGPoint)localPoint - inView:(UIView*)view { - DCHECK([menuHolder itemCount]); - menuHolder_.reset([menuHolder retain]); - // Check that the view is still visible on screen, otherwise just return and - // don't show the context menu. - DCHECK([view window] || [view isKindOfClass:[UIWindow class]]); - if (![view window] && ![view isKindOfClass:[UIWindow class]]) - return; - CGSize spaceAvailableForTitle = - [CRUContextMenuController - availableSpaceForTitleInActionSheetWithMenu:menuHolder_ - atPoint:localPoint - inView:view]; - NSString* title = menuHolder.menuTitle; - if (title) { - // Show at least one line of text, even if that means the UIActionSheet's - // items will need to scroll. - const CGFloat kMinimumVerticalSpace = 21; - spaceAvailableForTitle.height = - std::max(kMinimumVerticalSpace, spaceAvailableForTitle.height); - title = [title cr_stringByElidingToFitSize:spaceAvailableForTitle]; - } - // Create the sheet. - sheet_.reset( - [[UIActionSheet alloc] initWithTitle:title - delegate:self - cancelButtonTitle:nil - destructiveButtonTitle:nil - otherButtonTitles:nil]); - // Add the labels, in order, to the sheet. - for (NSString* label in [menuHolder_ itemTitles]) { - [sheet_ addButtonWithTitle:label]; - } - // Cancel button goes last, to match other browsers. - [sheet_ addButtonWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL)]; - [sheet_ setCancelButtonIndex:[menuHolder_ itemCount]]; - [sheet_ showFromRect:CGRectMake(localPoint.x, localPoint.y, 1.0, 1.0) - inView:view - animated:YES]; - - visible_ = YES; -} - -// Returns an approximation of the free space available for the title of an -// actionSheet filled with |menu| shown in |view| at |point|. -+ (CGSize) - availableSpaceForTitleInActionSheetWithMenu:(CRUContextMenuHolder*)menu - atPoint:(CGPoint)point - inView:(UIView*)view { - BOOL isIpad = ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET; - if (base::ios::IsRunningOnIOS8OrLater()) { - // On iOS8 presenting and dismissing a dummy UIActionSheet does not work - // (http://crbug.com/392245 and rdar://17677745). - // As a workaround we return an estimation of the space available depending - // on the device's type. - const CGFloat kAvailableWidth = 320; - const CGFloat kAvailableHeightTablet = 200; - const CGFloat kAvailableHeightPhone = 100; - if (isIpad) { - return CGSizeMake(kAvailableWidth, kAvailableHeightTablet); - } - return CGSizeMake(kAvailableWidth, kAvailableHeightPhone); - } else { - // Creates a dummy UIActionSheet. - base::scoped_nsobject<UIActionSheet> dummyActionSheet( - [[UIActionSheet alloc] initWithTitle:nil - delegate:nil - cancelButtonTitle:nil - destructiveButtonTitle:nil - otherButtonTitles:nil]); - for (NSString* label in [menu itemTitles]) { - [dummyActionSheet addButtonWithTitle:label]; - } - [dummyActionSheet addButtonWithTitle: - l10n_util::GetNSString(IDS_APP_CANCEL)]; - // Temporarily adds the dummy UIActionSheet to |view|. - [dummyActionSheet showFromRect:CGRectMake(point.x, point.y, 1.0, 1.0) - inView:view - animated:NO]; - // On iPad the actionsheet is positioned under or over |point| (as opposed - // to next to it) when the user clicks within approximately 200 points of - // respectively the top or bottom edge. This reduces the amount of vertical - // space available for the title, hence the large padding on ipad. - const int kPaddingiPad = 200; - const int kPaddingiPhone = 20; - CGFloat padding = isIpad ? kPaddingiPad : kPaddingiPhone; - // A title uses the full width of the actionsheet and all the vertical - // space on the screen. - CGSize availableSpaceForTitle = - CGSizeMake([dummyActionSheet frame].size.width, - [CRUContextMenuController screenHeight] - - [dummyActionSheet frame].size.height - - padding); - [dummyActionSheet dismissWithClickedButtonIndex:0 animated:NO]; - return availableSpaceForTitle; - } -} - -// Returns the screen's height in pixels. -+ (int)screenHeight { - DCHECK(!base::ios::IsRunningOnIOS8OrLater()); - switch ([[UIApplication sharedApplication] statusBarOrientation]) { - case UIInterfaceOrientationLandscapeLeft: - case UIInterfaceOrientationLandscapeRight: - return [[UIScreen mainScreen] applicationFrame].size.width; - case UIInterfaceOrientationPortraitUpsideDown: - case UIInterfaceOrientationPortrait: - case UIInterfaceOrientationUnknown: - return [[UIScreen mainScreen] applicationFrame].size.height; + if ([_menuHolder shouldDismissImmediatelyOnClickedAtIndex:buttonIndex]) { + [_sheet dismissWithClickedButtonIndex:buttonIndex animated:NO]; } } @end -@implementation CRUContextMenuController (UsedForTesting) -- (UIActionSheet*)sheet { - return sheet_.get(); +#pragma mark - iOS8 and higher + +@implementation CRUAlertController +@synthesize visible = _visible; + +- (CGSize)sizeForTitleThatFitsMenuWithHolder:(CRUContextMenuHolder*)menuHolder + atPoint:(CGPoint)point + inView:(UIView*)view { + // Presenting and dismissing a dummy UIAlertController flushes a screen. + // As a workaround return an estimation of the space available depending + // on the device's type. + const CGFloat kAvailableWidth = 320; + const CGFloat kAvailableHeightTablet = 200; + const CGFloat kAvailableHeightPhone = 100; + if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) { + return CGSizeMake(kAvailableWidth, kAvailableHeightTablet); + } + return CGSizeMake(kAvailableWidth, kAvailableHeightPhone); } + +- (void)showWithHolder:(CRUContextMenuHolder*)menuHolder + atPoint:(CGPoint)point + inView:(UIView*)view { + UIAlertController* alert = [UIAlertController + alertControllerWithTitle:menuHolder.menuTitle + message:nil + preferredStyle:UIAlertControllerStyleActionSheet]; + alert.popoverPresentationController.sourceView = view; + alert.popoverPresentationController.sourceRect = + CGRectMake(point.x, point.y, 1.0, 1.0); + + // Add the actions. + base::WeakNSObject<CRUAlertController> weakSelf(self); + [menuHolder.itemTitles enumerateObjectsUsingBlock:^(NSString* itemTitle, + NSUInteger itemIndex, + BOOL*) { + void (^actionHandler)(UIAlertAction*) = ^(UIAlertAction* action) { + [menuHolder performActionAtIndex:itemIndex]; + [weakSelf setVisible:NO]; + }; + [alert addAction:[UIAlertAction actionWithTitle:itemTitle + style:UIAlertActionStyleDefault + handler:actionHandler]]; + }]; + + // Cancel button goes last, to match other browsers. + UIAlertAction* cancel_action = + [UIAlertAction actionWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL) + style:UIAlertActionStyleCancel + handler:nil]; + [alert addAction:cancel_action]; + + // Present sheet/popover using controller that is added to view hierarchy. + UIViewController* topController = view.window.rootViewController; + while (topController.presentedViewController) + topController = topController.presentedViewController; + [topController presentViewController:alert animated:YES completion:nil]; + self.visible = YES; +} + @end
diff --git a/ui/base/ios/cru_context_menu_controller_unittest.mm b/ui/base/ios/cru_context_menu_controller_unittest.mm index d7b4534..31863d78 100644 --- a/ui/base/ios/cru_context_menu_controller_unittest.mm +++ b/ui/base/ios/cru_context_menu_controller_unittest.mm
@@ -41,13 +41,6 @@ [_menuController showWithHolder:holder atPoint:CGPointZero inView:_window]; EXPECT_TRUE([_menuController isVisible]); - - UIActionSheet* sheet = _menuController.get().sheet; - [sheet dismissWithClickedButtonIndex:0 animated:NO]; - [_menuController actionSheet:sheet didDismissWithButtonIndex:0]; - - EXPECT_TRUE(clicked); - EXPECT_FALSE([_menuController isVisible]); } TEST_F(ContextMenuControllerTest, ShouldDismissImmediately) {
diff --git a/ui/base/models/tree_node_model.h b/ui/base/models/tree_node_model.h index 5df2481..3ebbcee 100644 --- a/ui/base/models/tree_node_model.h +++ b/ui/base/models/tree_node_model.h
@@ -68,7 +68,7 @@ explicit TreeNode(const base::string16& title) : title_(title), parent_(NULL) {} - virtual ~TreeNode() {} + ~TreeNode() override {} // Adds |node| as a child of this node, at |index|. virtual void Add(NodeType* node, int index) { @@ -154,7 +154,7 @@ virtual void SetTitle(const base::string16& title) { title_ = title; } // TreeModelNode: - virtual const base::string16& GetTitle() const override { return title_; } + const base::string16& GetTitle() const override { return title_; } // Returns true if this == ancestor, or one of this nodes parents is // ancestor. @@ -212,7 +212,7 @@ // Creates a TreeNodeModel with the specified root node. The root is owned // by the TreeNodeModel. explicit TreeNodeModel(NodeType* root) : root_(root) {} - virtual ~TreeNodeModel() {} + virtual ~TreeNodeModel() override {} NodeType* AsNode(TreeModelNode* model_node) { return static_cast<NodeType*>(model_node); @@ -251,40 +251,40 @@ } // TreeModel: - virtual NodeType* GetRoot() override { + NodeType* GetRoot() override { return root_.get(); } - virtual int GetChildCount(TreeModelNode* parent) override { + int GetChildCount(TreeModelNode* parent) override { DCHECK(parent); return AsNode(parent)->child_count(); } - virtual NodeType* GetChild(TreeModelNode* parent, int index) override { + NodeType* GetChild(TreeModelNode* parent, int index) override { DCHECK(parent); return AsNode(parent)->GetChild(index); } - virtual int GetIndexOf(TreeModelNode* parent, TreeModelNode* child) override { + int GetIndexOf(TreeModelNode* parent, TreeModelNode* child) override { DCHECK(parent); return AsNode(parent)->GetIndexOf(AsNode(child)); } - virtual TreeModelNode* GetParent(TreeModelNode* node) override { + TreeModelNode* GetParent(TreeModelNode* node) override { DCHECK(node); return AsNode(node)->parent(); } - virtual void AddObserver(TreeModelObserver* observer) override { + void AddObserver(TreeModelObserver* observer) override { observer_list_.AddObserver(observer); } - virtual void RemoveObserver(TreeModelObserver* observer) override { + void RemoveObserver(TreeModelObserver* observer) override { observer_list_.RemoveObserver(observer); } - virtual void SetTitle(TreeModelNode* node, - const base::string16& title) override { + void SetTitle(TreeModelNode* node, + const base::string16& title) override { DCHECK(node); AsNode(node)->SetTitle(title); NotifyObserverTreeNodeChanged(node);
diff --git a/ui/base/resource/resource_bundle_unittest.cc b/ui/base/resource/resource_bundle_unittest.cc index 5aa5017..4362b7e 100644 --- a/ui/base/resource/resource_bundle_unittest.cc +++ b/ui/base/resource/resource_bundle_unittest.cc
@@ -59,7 +59,7 @@ public: MockResourceBundleDelegate() { } - virtual ~MockResourceBundleDelegate() { + ~MockResourceBundleDelegate() override { } MOCK_METHOD2(GetPathForResourcePack, base::FilePath( @@ -76,22 +76,21 @@ MOCK_METHOD2(GetRawDataResourceMock, base::StringPiece( int resource_id, ui::ScaleFactor scale_factor)); - virtual bool GetRawDataResource(int resource_id, - ui::ScaleFactor scale_factor, - base::StringPiece* value) override { + bool GetRawDataResource(int resource_id, + ui::ScaleFactor scale_factor, + base::StringPiece* value) override { *value = GetRawDataResourceMock(resource_id, scale_factor); return true; } MOCK_METHOD1(GetLocalizedStringMock, base::string16(int message_id)); - virtual bool GetLocalizedString(int message_id, - base::string16* value) override { + bool GetLocalizedString(int message_id, + base::string16* value) override { *value = GetLocalizedStringMock(message_id); return true; } MOCK_METHOD1(GetFontMock, gfx::Font*(ui::ResourceBundle::FontStyle style)); - virtual scoped_ptr<gfx::Font> GetFont( - ui::ResourceBundle::FontStyle style) override { + scoped_ptr<gfx::Font> GetFont(ui::ResourceBundle::FontStyle style) override { return make_scoped_ptr(GetFontMock(style)); } };
diff --git a/ui/base/test/ui_controls_mac.mm b/ui/base/test/ui_controls_mac.mm index 1a0f86c..002cb03e 100644 --- a/ui/base/test/ui_controls_mac.mm +++ b/ui/base/test/ui_controls_mac.mm
@@ -279,7 +279,7 @@ return (SendMouseEventsNotifyWhenDone(type, DOWN, base::Closure()) && SendMouseEventsNotifyWhenDone(type, UP, task)); } - NSEventType etype = 0; + NSEventType etype = NSLeftMouseDown; if (type == LEFT) { if (state == UP) { etype = NSLeftMouseUp;
diff --git a/ui/compositor/BUILD.gn b/ui/compositor/BUILD.gn index 590cb73..a0944fe 100644 --- a/ui/compositor/BUILD.gn +++ b/ui/compositor/BUILD.gn
@@ -47,6 +47,8 @@ "layer_tree_owner.cc", "layer_tree_owner.h", "layer_type.h", + "paint_cache.cc", + "paint_cache.h", "paint_context.cc", "paint_context.h", "paint_recorder.cc",
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc index 43dd4605..c50f9ef 100644 --- a/ui/compositor/compositor.cc +++ b/ui/compositor/compositor.cc
@@ -326,9 +326,16 @@ void Compositor::BeginMainFrameNotExpectedSoon() { } +static void SendDamagedRectsRecursive(ui::Layer* layer) { + layer->SendDamagedRects(); + for (auto* child : layer->children()) + SendDamagedRectsRecursive(child); +} + void Compositor::Layout() { - if (root_layer_) - root_layer_->SendDamagedRects(); + if (!root_layer()) + return; + SendDamagedRectsRecursive(root_layer()); } void Compositor::RequestNewOutputSurface() {
diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp index 11d6723e..92f5ef4e 100644 --- a/ui/compositor/compositor.gyp +++ b/ui/compositor/compositor.gyp
@@ -65,6 +65,8 @@ 'layer_tree_owner.cc', 'layer_tree_owner.h', 'layer_type.h', + 'paint_cache.cc', + 'paint_cache.h', 'paint_context.cc', 'paint_context.h', 'paint_recorder.cc',
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 3e61d40..2b6f9219 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -657,11 +657,7 @@ type_ == LAYER_NINE_PATCH || (!delegate_ && !mailbox_.IsValid())) return false; - damaged_region_.op(invalid_rect.x(), - invalid_rect.y(), - invalid_rect.right(), - invalid_rect.bottom(), - SkRegion::kUnion_Op); + damaged_region_.Union(invalid_rect); ScheduleDraw(); return true; } @@ -673,20 +669,17 @@ } void Layer::SendDamagedRects() { - if ((delegate_ || mailbox_.IsValid()) && !damaged_region_.isEmpty()) { - for (SkRegion::Iterator iter(damaged_region_); !iter.done(); iter.next()) { - const SkIRect& sk_damaged = iter.rect(); - gfx::Rect damaged( - sk_damaged.x(), - sk_damaged.y(), - sk_damaged.width(), - sk_damaged.height()); - cc_layer_->SetNeedsDisplayRect(damaged); - } - damaged_region_.setEmpty(); - } - for (size_t i = 0; i < children_.size(); ++i) - children_[i]->SendDamagedRects(); + if (damaged_region_.IsEmpty()) + return; + if (!delegate_ && !mailbox_.IsValid()) + return; + + for (cc::Region::Iterator iter(damaged_region_); iter.has_rect(); iter.next()) + cc_layer_->SetNeedsDisplayRect(iter.rect()); +} + +void Layer::ClearDamagedRects() { + damaged_region_.Clear(); } void Layer::CompleteAllAnimations() { @@ -745,6 +738,7 @@ const gfx::Rect& clip, ContentLayerClient::PaintingControlSetting painting_control) { TRACE_EVENT1("ui", "Layer::PaintContents", "name", name_); + ClearDamagedRects(); scoped_ptr<gfx::Canvas> canvas(gfx::Canvas::CreateCanvasWithoutScaling( sk_canvas, device_scale_factor_)); if (delegate_) @@ -756,15 +750,15 @@ const gfx::Rect& clip, ContentLayerClient::PaintingControlSetting painting_control) { TRACE_EVENT1("ui", "Layer::PaintContentsToDisplayList", "name", name_); - if (delegate_) { - // TODO(danakj): Save the invalidation on the layer and pass that down - // instead of the |clip| here. That will break everything until View - // early-outs emit cached display items instead of nothing. - gfx::Rect invalidation = clip; - DCHECK(clip.Contains(invalidation)); - delegate_->OnPaintLayer( - PaintContext(display_list, device_scale_factor_, clip, invalidation)); - } + gfx::Rect local_bounds(bounds().size()); + gfx::Rect invalidation( + gfx::IntersectRects(damaged_region_.bounds(), local_bounds)); + DCHECK(clip.Contains(invalidation)); + ClearDamagedRects(); + if (!delegate_) + return; + delegate_->OnPaintLayer( + PaintContext(display_list, device_scale_factor_, clip, invalidation)); } bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h index 381e982..bb8b1af 100644 --- a/ui/compositor/layer.h +++ b/ui/compositor/layer.h
@@ -14,6 +14,7 @@ #include "base/message_loop/message_loop.h" #include "cc/animation/animation_events.h" #include "cc/animation/layer_animation_event_observer.h" +#include "cc/base/region.h" #include "cc/base/scoped_ptr_vector.h" #include "cc/layers/content_layer_client.h" #include "cc/layers/layer_client.h" @@ -319,8 +320,9 @@ // Uses damaged rectangles recorded in |damaged_region_| to invalidate the // |cc_layer_|. void SendDamagedRects(); + void ClearDamagedRects(); - const SkRegion& damaged_region() const { return damaged_region_; } + const cc::Region& damaged_region() const { return damaged_region_; } void CompleteAllAnimations(); @@ -459,9 +461,9 @@ bool fills_bounds_opaquely_; bool fills_bounds_completely_; - // Union of damaged rects, in pixel coordinates, to be used when - // compositor is ready to paint the content. - SkRegion damaged_region_; + // Union of damaged rects, in layer space, to be used when compositor is ready + // to paint the content. + cc::Region damaged_region_; int background_blur_radius_;
diff --git a/ui/compositor/paint_cache.cc b/ui/compositor/paint_cache.cc new file mode 100644 index 0000000..ef0e5a7 --- /dev/null +++ b/ui/compositor/paint_cache.cc
@@ -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. + +#include "ui/compositor/paint_cache.h" + +#include "cc/resources/display_item_list.h" +#include "cc/resources/drawing_display_item.h" +#include "ui/compositor/paint_context.h" + +namespace ui { + +PaintCache::PaintCache() { +} + +PaintCache::~PaintCache() { +} + +bool PaintCache::UseCache(const PaintContext& context) { + if (!display_item_) + return false; + DCHECK(context.list_); + context.list_->AppendItem(display_item_->Clone()); + return true; +} + +void PaintCache::SetCache(scoped_ptr<cc::DrawingDisplayItem> item) { + display_item_ = item.Pass(); +} + +} // namespace ui
diff --git a/ui/compositor/paint_cache.h b/ui/compositor/paint_cache.h new file mode 100644 index 0000000..599a8ac --- /dev/null +++ b/ui/compositor/paint_cache.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 UI_COMPOSITOR_PAINT_CACHE_H_ +#define UI_COMPOSITOR_PAINT_CACHE_H_ + +#include "base/memory/scoped_ptr.h" +#include "ui/compositor/compositor_export.h" + +namespace cc { +class DrawingDisplayItem; +} + +namespace ui { +class PaintContext; +class PaintRecorder; + +// A class that holds the output of a PaintRecorder to be reused when the +// object that created the PaintRecorder has not been changed/invalidated. +class COMPOSITOR_EXPORT PaintCache { + public: + PaintCache(); + ~PaintCache(); + + // Returns true if the PaintCache was able to insert a previously-saved + // painting output into the PaintContext. If it returns false, the caller + // needs to do the work of painting, which can be stored into the PaintCache + // to be used next time. + bool UseCache(const PaintContext& context); + + private: + // Only PaintRecorder can modify these. + friend PaintRecorder; + + void SetCache(scoped_ptr<cc::DrawingDisplayItem> item); + + scoped_ptr<cc::DrawingDisplayItem> display_item_; + + DISALLOW_COPY_AND_ASSIGN(PaintCache); +}; + +} // namespace ui + +#endif // UI_COMPOSITOR_PAINT_CACHE_H_
diff --git a/ui/compositor/paint_context.h b/ui/compositor/paint_context.h index d63f11f7..a754ee4 100644 --- a/ui/compositor/paint_context.h +++ b/ui/compositor/paint_context.h
@@ -56,15 +56,20 @@ return PaintContext(canvas_); } - // When true, IsRectInvalidated() can be called, otherwise its result would be + // When true, IsRectInvalid() can be called, otherwise its result would be // invalid. - bool CanCheckInvalidated() const { return !invalidation_.IsEmpty(); } + bool CanCheckInvalid() const { return !invalidation_.IsEmpty(); } + + // When true, if a thing is not invalidated it does not need to paint itself. + // When false, everything should provide an output when painting regardless of + // being invalidated in order to remain visible. + bool ShouldEarlyOutOfPaintingWhenValid() const { return !!canvas_; } // When true, the |bounds| touches an invalidated area, so should be // re-painted. When false, re-painting can be skipped. Bounds should be in // the local space with offsets up to the painting root in the PaintContext. - bool IsRectInvalidated(const gfx::Rect& bounds) const { - DCHECK(CanCheckInvalidated()); + bool IsRectInvalid(const gfx::Rect& bounds) const { + DCHECK(CanCheckInvalid()); return invalidation_.Intersects(bounds + offset_); } @@ -86,6 +91,9 @@ friend class ClipTransformRecorder; friend class CompositingRecorder; friend class PaintRecorder; + // The Cache class also needs to access the DisplayItemList to append its + // cache contents. + friend class PaintCache; PaintContext& operator=(const PaintContext& other) = delete;
diff --git a/ui/compositor/paint_recorder.cc b/ui/compositor/paint_recorder.cc index 15aa0fb..80fb616 100644 --- a/ui/compositor/paint_recorder.cc +++ b/ui/compositor/paint_recorder.cc
@@ -7,14 +7,15 @@ #include "cc/resources/display_item_list.h" #include "cc/resources/drawing_display_item.h" #include "third_party/skia/include/core/SkPictureRecorder.h" +#include "ui/compositor/paint_cache.h" #include "ui/compositor/paint_context.h" #include "ui/gfx/canvas.h" #include "ui/gfx/skia_util.h" namespace ui { -PaintRecorder::PaintRecorder(const PaintContext& context) - : context_(context), canvas_(context.canvas_) { +PaintRecorder::PaintRecorder(const PaintContext& context, PaintCache* cache) + : context_(context), canvas_(context.canvas_), cache_(cache) { #if DCHECK_IS_ON() DCHECK(!context.inside_paint_recorder_); context.inside_paint_recorder_ = true; @@ -34,15 +35,23 @@ } } +PaintRecorder::PaintRecorder(const PaintContext& context) + : PaintRecorder(context, nullptr) { +} + PaintRecorder::~PaintRecorder() { #if DCHECK_IS_ON() context_.inside_paint_recorder_ = false; #endif - if (context_.list_) { - context_.list_->AppendItem(cc::DrawingDisplayItem::Create( - skia::AdoptRef(context_.recorder_->endRecordingAsPicture()))); - } + if (!context_.list_) + return; + + scoped_ptr<cc::DrawingDisplayItem> item = cc::DrawingDisplayItem::Create( + skia::AdoptRef(context_.recorder_->endRecordingAsPicture())); + if (cache_) + cache_->SetCache(item->Clone()); + context_.list_->AppendItem(item.Pass()); } } // namespace ui
diff --git a/ui/compositor/paint_recorder.h b/ui/compositor/paint_recorder.h index 7c3df82b..9cac7a8 100644 --- a/ui/compositor/paint_recorder.h +++ b/ui/compositor/paint_recorder.h
@@ -22,6 +22,7 @@ class SkPictureRecorder; namespace ui { +class PaintCache; class PaintContext; // A class to hide the complexity behind setting up a recording into a @@ -30,6 +31,9 @@ // recording is complete and can be cached. class COMPOSITOR_EXPORT PaintRecorder { public: + // The |cache| is owned by the caller and must be kept alive while + // PaintRecorder is in use. + PaintRecorder(const PaintContext& context, PaintCache* cache); explicit PaintRecorder(const PaintContext& context); ~PaintRecorder(); @@ -40,6 +44,7 @@ const PaintContext& context_; gfx::Canvas* canvas_; scoped_ptr<gfx::Canvas> owned_canvas_; + PaintCache* cache_; DISALLOW_COPY_AND_ASSIGN(PaintRecorder); };
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn index d3dcaa6..e664b1a 100644 --- a/ui/display/BUILD.gn +++ b/ui/display/BUILD.gn
@@ -5,70 +5,67 @@ import("//build/config/ui.gni") import("//testing/test.gni") -component("display") { - sources = [ - "chromeos/apply_content_protection_task.cc", - "chromeos/apply_content_protection_task.h", - "chromeos/configure_displays_task.cc", - "chromeos/configure_displays_task.h", - "chromeos/display_configurator.cc", - "chromeos/display_configurator.h", - "chromeos/display_layout_manager.h", - "chromeos/display_util.cc", - "chromeos/display_util.h", - "chromeos/ozone/display_configurator_ozone.cc", - "chromeos/query_content_protection_task.cc", - "chromeos/query_content_protection_task.h", - "chromeos/update_display_configuration_task.cc", - "chromeos/update_display_configuration_task.h", - "chromeos/x11/display_configurator_x11.cc", - "chromeos/x11/display_mode_x11.cc", - "chromeos/x11/display_mode_x11.h", - "chromeos/x11/display_snapshot_x11.cc", - "chromeos/x11/display_snapshot_x11.h", - "chromeos/x11/display_util_x11.cc", - "chromeos/x11/display_util_x11.h", - "chromeos/x11/native_display_delegate_x11.cc", - "chromeos/x11/native_display_delegate_x11.h", - "chromeos/x11/native_display_event_dispatcher_x11.cc", - "chromeos/x11/native_display_event_dispatcher_x11.h", - "display_export.h", - "display_switches.cc", - "display_switches.h", - ] - - defines = [ "DISPLAY_IMPLEMENTATION" ] - - deps = [ - "//base", - "//ui/display/util", - "//ui/gfx", - "//ui/gfx/geometry", - ] - - if (use_x11) { - configs += [ - "//build/config/linux:x11", - "//build/config/linux:xext", - "//build/config/linux:xi", - "//build/config/linux:xrandr", +if (is_chromeos) { + component("display") { + sources = [ + "chromeos/apply_content_protection_task.cc", + "chromeos/apply_content_protection_task.h", + "chromeos/configure_displays_task.cc", + "chromeos/configure_displays_task.h", + "chromeos/display_configurator.cc", + "chromeos/display_configurator.h", + "chromeos/display_layout_manager.h", + "chromeos/display_util.cc", + "chromeos/display_util.h", + "chromeos/ozone/display_configurator_ozone.cc", + "chromeos/query_content_protection_task.cc", + "chromeos/query_content_protection_task.h", + "chromeos/update_display_configuration_task.cc", + "chromeos/update_display_configuration_task.h", + "chromeos/x11/display_configurator_x11.cc", + "chromeos/x11/display_mode_x11.cc", + "chromeos/x11/display_mode_x11.h", + "chromeos/x11/display_snapshot_x11.cc", + "chromeos/x11/display_snapshot_x11.h", + "chromeos/x11/display_util_x11.cc", + "chromeos/x11/display_util_x11.h", + "chromeos/x11/native_display_delegate_x11.cc", + "chromeos/x11/native_display_delegate_x11.h", + "chromeos/x11/native_display_event_dispatcher_x11.cc", + "chromeos/x11/native_display_event_dispatcher_x11.h", + "display_export.h", + "display_switches.cc", + "display_switches.h", ] - deps += [ "//ui/events/platform" ] - if (is_chromeos) { - sources -= [ "chromeos/ozone/display_configurator_ozone.cc" ] - } - } - if (is_chromeos) { - deps += [ "//ui/display/types" ] + defines = [ "DISPLAY_IMPLEMENTATION" ] + + deps = [ + "//base", + "//ui/display/types", + "//ui/display/util", + "//ui/gfx", + "//ui/gfx/geometry", + ] + + if (use_x11) { + sources -= [ "chromeos/ozone/display_configurator_ozone.cc" ] + configs += [ + "//build/config/linux:x11", + "//build/config/linux:xext", + "//build/config/linux:xi", + "//build/config/linux:xrandr", + ] + deps += [ "//ui/events/platform" ] + } + + deps += [] if (use_x11) { deps += [ "//ui/gfx/x" ] } - } - if (use_ozone) { - deps += [ "//ui/ozone" ] - if (is_chromeos) { + if (use_ozone) { + deps += [ "//ui/ozone" ] sources -= [ "chromeos/x11/display_configurator_x11.cc", "chromeos/x11/display_mode_x11.cc", @@ -84,55 +81,54 @@ ] } } -} -component("test_util") { - output_name = "display_test_util" - sources = [ - "chromeos/test/test_display_snapshot.cc", - "chromeos/test/test_display_snapshot.h", - ] + component("test_util") { + output_name = "display_test_util" + sources = [ + "chromeos/test/test_display_snapshot.cc", + "chromeos/test/test_display_snapshot.h", + ] - defines = [ "DISPLAY_IMPLEMENTATION" ] + defines = [ "DISPLAY_IMPLEMENTATION" ] - public_deps = [ - ":display", - ] - deps = [ - "//base", - "//ui/gfx", - "//ui/gfx/geometry", - ] + public_deps = [ + ":display", + ] + deps = [ + "//base", + "//ui/display/types", + "//ui/gfx", + "//ui/gfx/geometry", + ] + } - if (is_chromeos) { - deps += [ "//ui/display/types" ] + source_set("test_support") { + testonly = true + sources = [ + "chromeos/test/action_logger.cc", + "chromeos/test/action_logger.h", + "chromeos/test/action_logger_util.cc", + "chromeos/test/action_logger_util.h", + "chromeos/test/test_display_layout_manager.cc", + "chromeos/test/test_display_layout_manager.h", + "chromeos/test/test_native_display_delegate.cc", + "chromeos/test/test_native_display_delegate.h", + ] + + public_deps = [ + ":display", + ] + deps = [ + "//base", + "//ui/display/types", + "//ui/gfx", + "//ui/gfx/geometry", + ] } } -source_set("test_support") { - testonly = true - sources = [ - "chromeos/test/action_logger.cc", - "chromeos/test/action_logger.h", - "chromeos/test/action_logger_util.cc", - "chromeos/test/action_logger_util.h", - "chromeos/test/test_display_layout_manager.cc", - "chromeos/test/test_display_layout_manager.h", - "chromeos/test/test_native_display_delegate.cc", - "chromeos/test/test_native_display_delegate.h", - ] - - public_deps = [ - ":display", - ] - deps = [ - "//base", - "//ui/display/types", - "//ui/gfx", - "//ui/gfx/geometry", - ] -} - +# This test covers the ChromeOS "display" target as well as the cross-platform +# //display/util target. test("display_unittests") { sources = [ "chromeos/apply_content_protection_task_unittest.cc", @@ -147,7 +143,6 @@ ] deps = [ - ":test_util", "//base", "//base/test:run_all_unittests", "//testing/gtest", @@ -159,6 +154,7 @@ deps += [ ":display", ":test_support", + ":test_util", "//base/test:test_support", "//ui/display/types", ]
diff --git a/ui/display/chromeos/display_configurator.cc b/ui/display/chromeos/display_configurator.cc index 48e31ab..c577fd0 100644 --- a/ui/display/chromeos/display_configurator.cc +++ b/ui/display/chromeos/display_configurator.cc
@@ -9,6 +9,7 @@ #include "base/logging.h" #include "base/sys_info.h" #include "base/time/time.h" +#include "ui/display/chromeos/apply_content_protection_task.h" #include "ui/display/chromeos/display_layout_manager.h" #include "ui/display/chromeos/display_util.h" #include "ui/display/chromeos/update_display_configuration_task.h" @@ -483,6 +484,16 @@ CallAndClearInProgressCallbacks(false); CallAndClearQueuedCallbacks(false); + + while (!query_protection_callbacks_.empty()) { + query_protection_callbacks_.front().Run(QueryProtectionResponse()); + query_protection_callbacks_.pop(); + } + + while (!enable_protection_callbacks_.empty()) { + enable_protection_callbacks_.front().Run(false); + enable_protection_callbacks_.pop(); + } } void DisplayConfigurator::SetDelegateForTesting( @@ -555,67 +566,6 @@ configuration_task_->Run(); } -bool DisplayConfigurator::IsMirroring() const { - return current_display_state_ == MULTIPLE_DISPLAY_STATE_DUAL_MIRROR || - (mirroring_controller_ && - mirroring_controller_->SoftwareMirroringEnabled()); -} - -bool DisplayConfigurator::ApplyProtections(const ContentProtections& requests) { - for (const DisplaySnapshot* display : cached_displays_) { - uint32_t all_desired = 0; - - // In mirror mode, protection request of all displays need to be fulfilled. - // In non-mirror mode, only request of client's display needs to be - // fulfilled. - if (IsMirroring()) { - for (const auto& protections_pair : requests) - all_desired |= protections_pair.second; - } else { - ContentProtections::const_iterator request_it = - requests.find(display->display_id()); - if (request_it != requests.end()) - all_desired = request_it->second; - } - - switch (display->type()) { - case DISPLAY_CONNECTION_TYPE_UNKNOWN: - return false; - // DisplayPort, DVI, and HDMI all support HDCP. - case DISPLAY_CONNECTION_TYPE_DISPLAYPORT: - case DISPLAY_CONNECTION_TYPE_DVI: - case DISPLAY_CONNECTION_TYPE_HDMI: { - HDCPState current_state; - // Need to poll the driver for updates since other applications may - // have updated the state. - if (!native_display_delegate_->GetHDCPState(*display, ¤t_state)) - return false; - bool current_desired = (current_state != HDCP_STATE_UNDESIRED); - bool new_desired = (all_desired & CONTENT_PROTECTION_METHOD_HDCP); - // Don't enable again if HDCP is already active. Some buggy drivers - // may disable and enable if setting "desired" in active state. - if (current_desired != new_desired) { - HDCPState new_state = - new_desired ? HDCP_STATE_DESIRED : HDCP_STATE_UNDESIRED; - if (!native_display_delegate_->SetHDCPState(*display, new_state)) - return false; - } - break; - } - case DISPLAY_CONNECTION_TYPE_INTERNAL: - case DISPLAY_CONNECTION_TYPE_VGA: - case DISPLAY_CONNECTION_TYPE_NETWORK: - // No protections for these types. Do nothing. - break; - case DISPLAY_CONNECTION_TYPE_NONE: - NOTREACHED(); - break; - } - } - - return true; -} - DisplayConfigurator::ContentProtectionClientId DisplayConfigurator::RegisterContentProtectionClient() { if (!configure_display_ || display_externally_controlled_) @@ -635,71 +585,78 @@ } } - ApplyProtections(protections); + enable_protection_callbacks_.push(base::Bind(&DoNothing)); + ApplyContentProtectionTask* task = new ApplyContentProtectionTask( + layout_manager_.get(), native_display_delegate_.get(), protections, + base::Bind(&DisplayConfigurator::OnContentProtectionClientUnregistered, + weak_ptr_factory_.GetWeakPtr())); + content_protection_tasks_.push( + base::Bind(&ApplyContentProtectionTask::Run, base::Owned(task))); + + if (content_protection_tasks_.size() == 1) + content_protection_tasks_.front().Run(); +} + +void DisplayConfigurator::OnContentProtectionClientUnregistered(bool success) { + DCHECK(!content_protection_tasks_.empty()); + content_protection_tasks_.pop(); + + DCHECK(!enable_protection_callbacks_.empty()); + EnableProtectionCallback callback = enable_protection_callbacks_.front(); + enable_protection_callbacks_.pop(); + + if (!content_protection_tasks_.empty()) + content_protection_tasks_.front().Run(); } void DisplayConfigurator::QueryContentProtectionStatus( ContentProtectionClientId client_id, int64_t display_id, const QueryProtectionCallback& callback) { - QueryProtectionResponse response; if (!configure_display_ || display_externally_controlled_) { - callback.Run(response); + callback.Run(QueryProtectionResponse()); return; } - uint32_t enabled = 0; - uint32_t unfulfilled = 0; - uint32_t link_mask = 0; - for (const DisplaySnapshot* display : cached_displays_) { - // Query display if it is in mirror mode or client on the same display. - if (!IsMirroring() && display->display_id() != display_id) - continue; + query_protection_callbacks_.push(callback); + QueryContentProtectionTask* task = new QueryContentProtectionTask( + layout_manager_.get(), native_display_delegate_.get(), display_id, + base::Bind(&DisplayConfigurator::OnContentProtectionQueried, + weak_ptr_factory_.GetWeakPtr(), client_id, display_id)); + content_protection_tasks_.push( + base::Bind(&QueryContentProtectionTask::Run, base::Owned(task))); + if (content_protection_tasks_.size() == 1) + content_protection_tasks_.front().Run(); +} - link_mask |= display->type(); - switch (display->type()) { - case DISPLAY_CONNECTION_TYPE_UNKNOWN: - callback.Run(response); - return; - // DisplayPort, DVI, and HDMI all support HDCP. - case DISPLAY_CONNECTION_TYPE_DISPLAYPORT: - case DISPLAY_CONNECTION_TYPE_DVI: - case DISPLAY_CONNECTION_TYPE_HDMI: { - HDCPState state; - if (!native_display_delegate_->GetHDCPState(*display, &state)) { - callback.Run(response); - return; - } - - if (state == HDCP_STATE_ENABLED) - enabled |= CONTENT_PROTECTION_METHOD_HDCP; - else - unfulfilled |= CONTENT_PROTECTION_METHOD_HDCP; - break; - } - case DISPLAY_CONNECTION_TYPE_INTERNAL: - case DISPLAY_CONNECTION_TYPE_VGA: - case DISPLAY_CONNECTION_TYPE_NETWORK: - // No protections for these types. Do nothing. - break; - case DISPLAY_CONNECTION_TYPE_NONE: - NOTREACHED(); - break; - } - } +void DisplayConfigurator::OnContentProtectionQueried( + ContentProtectionClientId client_id, + int64_t display_id, + QueryContentProtectionTask::Response task_response) { + QueryProtectionResponse response; + response.success = task_response.success; + response.link_mask = task_response.link_mask; // Don't reveal protections requested by other clients. ProtectionRequests::iterator it = client_protection_requests_.find(client_id); - if (it != client_protection_requests_.end()) { + if (response.success && it != client_protection_requests_.end()) { uint32_t requested_mask = 0; if (it->second.find(display_id) != it->second.end()) requested_mask = it->second[display_id]; - response.protection_mask = enabled & ~unfulfilled & requested_mask; + response.protection_mask = + task_response.enabled & ~task_response.unfulfilled & requested_mask; } - response.success = true; - response.link_mask = link_mask; + DCHECK(!content_protection_tasks_.empty()); + content_protection_tasks_.pop(); + + DCHECK(!query_protection_callbacks_.empty()); + QueryProtectionCallback callback = query_protection_callbacks_.front(); + query_protection_callbacks_.pop(); callback.Run(response); + + if (!content_protection_tasks_.empty()) + content_protection_tasks_.front().Run(); } void DisplayConfigurator::EnableContentProtection( @@ -724,7 +681,31 @@ } protections[display_id] |= desired_method_mask; - if (!ApplyProtections(protections)) { + enable_protection_callbacks_.push(callback); + ApplyContentProtectionTask* task = new ApplyContentProtectionTask( + layout_manager_.get(), native_display_delegate_.get(), protections, + base::Bind(&DisplayConfigurator::OnContentProtectionEnabled, + weak_ptr_factory_.GetWeakPtr(), client_id, display_id, + desired_method_mask)); + content_protection_tasks_.push( + base::Bind(&ApplyContentProtectionTask::Run, base::Owned(task))); + if (content_protection_tasks_.size() == 1) + content_protection_tasks_.front().Run(); +} + +void DisplayConfigurator::OnContentProtectionEnabled( + ContentProtectionClientId client_id, + int64_t display_id, + uint32_t desired_method_mask, + bool success) { + DCHECK(!content_protection_tasks_.empty()); + content_protection_tasks_.pop(); + + DCHECK(!enable_protection_callbacks_.empty()); + EnableProtectionCallback callback = enable_protection_callbacks_.front(); + enable_protection_callbacks_.pop(); + + if (!success) { callback.Run(false); return; } @@ -741,6 +722,8 @@ } callback.Run(true); + if (!content_protection_tasks_.empty()) + content_protection_tasks_.front().Run(); } std::vector<ui::ColorCalibrationProfile>
diff --git a/ui/display/chromeos/display_configurator.h b/ui/display/chromeos/display_configurator.h index 7c83dd2..3dc87f4 100644 --- a/ui/display/chromeos/display_configurator.h +++ b/ui/display/chromeos/display_configurator.h
@@ -8,6 +8,7 @@ #include <stdint.h> #include <map> +#include <queue> #include <string> #include <vector> @@ -17,6 +18,7 @@ #include "base/observer_list.h" #include "base/timer/timer.h" #include "third_party/cros_system_api/dbus/service_constants.h" +#include "ui/display/chromeos/query_content_protection_task.h" #include "ui/display/display_export.h" #include "ui/display/types/display_constants.h" #include "ui/display/types/native_display_observer.h" @@ -283,9 +285,6 @@ MultipleDisplayState ChooseDisplayState( chromeos::DisplayPowerState power_state) const; - // Returns true if in either hardware or software mirroring mode. - bool IsMirroring() const; - // Applies display protections according to requests. bool ApplyProtections(const ContentProtections& requests); @@ -313,6 +312,19 @@ void CallAndClearInProgressCallbacks(bool success); void CallAndClearQueuedCallbacks(bool success); + // Content protection callbacks called by the tasks when they finish. These + // are responsible for destroying the task, replying to the caller that made + // the task and starting the a new content protection task if one is queued. + void OnContentProtectionQueried( + ContentProtectionClientId client_id, + int64_t display_id, + QueryContentProtectionTask::Response response); + void OnContentProtectionEnabled(ContentProtectionClientId client_id, + int64_t display_id, + uint32_t desired_method_mask, + bool success); + void OnContentProtectionClientUnregistered(bool success); + StateController* state_controller_; SoftwareMirroringController* mirroring_controller_; scoped_ptr<NativeDisplayDelegate> native_display_delegate_; @@ -356,6 +368,10 @@ // task. std::vector<ConfigurationCallback> in_progress_configuration_callbacks_; + std::queue<base::Closure> content_protection_tasks_; + std::queue<QueryProtectionCallback> query_protection_callbacks_; + std::queue<EnableProtectionCallback> enable_protection_callbacks_; + // True if the caller wants to force the display configuration process. bool force_configure_;
diff --git a/ui/display/chromeos/test/test_native_display_delegate.cc b/ui/display/chromeos/test/test_native_display_delegate.cc index 5533961..f1b0101f 100644 --- a/ui/display/chromeos/test/test_native_display_delegate.cc +++ b/ui/display/chromeos/test/test_native_display_delegate.cc
@@ -106,24 +106,12 @@ outputs_.size() >= 2 ? outputs_[1] : NULL)); } -bool TestNativeDisplayDelegate::GetHDCPState(const DisplaySnapshot& output, - HDCPState* state) { - *state = hdcp_state_; - return get_hdcp_expectation_; -} - void TestNativeDisplayDelegate::GetHDCPState( const DisplaySnapshot& output, const GetHDCPStateCallback& callback) { callback.Run(get_hdcp_expectation_, hdcp_state_); } -bool TestNativeDisplayDelegate::SetHDCPState(const DisplaySnapshot& output, - HDCPState state) { - log_->AppendAction(GetSetHDCPStateAction(output, state)); - return set_hdcp_expectation_; -} - void TestNativeDisplayDelegate::SetHDCPState( const DisplaySnapshot& output, HDCPState state,
diff --git a/ui/display/chromeos/test/test_native_display_delegate.h b/ui/display/chromeos/test/test_native_display_delegate.h index a3ed4c64..f9e1767f 100644 --- a/ui/display/chromeos/test/test_native_display_delegate.h +++ b/ui/display/chromeos/test/test_native_display_delegate.h
@@ -63,8 +63,6 @@ const gfx::Point& origin, const ConfigureCallback& callback) override; void CreateFrameBuffer(const gfx::Size& size) override; - bool GetHDCPState(const DisplaySnapshot& output, HDCPState* state) override; - bool SetHDCPState(const DisplaySnapshot& output, HDCPState state) override; void GetHDCPState(const DisplaySnapshot& output, const GetHDCPStateCallback& callback) override; void SetHDCPState(const DisplaySnapshot& output,
diff --git a/ui/display/chromeos/x11/native_display_delegate_x11.h b/ui/display/chromeos/x11/native_display_delegate_x11.h index 036a121..5d49435 100644 --- a/ui/display/chromeos/x11/native_display_delegate_x11.h +++ b/ui/display/chromeos/x11/native_display_delegate_x11.h
@@ -86,8 +86,6 @@ const gfx::Point& origin, const ConfigureCallback& callback) override; void CreateFrameBuffer(const gfx::Size& size) override; - bool GetHDCPState(const DisplaySnapshot& output, HDCPState* state) override; - bool SetHDCPState(const DisplaySnapshot& output, HDCPState state) override; void GetHDCPState(const DisplaySnapshot& output, const GetHDCPStateCallback& callback) override; void SetHDCPState(const DisplaySnapshot& output, @@ -124,6 +122,10 @@ bool ConfigureCrtc(RRCrtc crtc, RRMode mode, RROutput output, int x, int y); + // Helper functions that perform the actual HDCP requests. + bool GetHDCPState(const DisplaySnapshot& output, HDCPState* state); + bool SetHDCPState(const DisplaySnapshot& output, HDCPState state); + // Returns whether |id| is configured to preserve aspect when scaling. bool IsOutputAspectPreservingScaling(RROutput id);
diff --git a/ui/display/types/display_constants.h b/ui/display/types/display_constants.h index f2361b38..aedb04b 100644 --- a/ui/display/types/display_constants.h +++ b/ui/display/types/display_constants.h
@@ -40,7 +40,14 @@ }; // HDCP protection state. -enum HDCPState { HDCP_STATE_UNDESIRED, HDCP_STATE_DESIRED, HDCP_STATE_ENABLED }; +enum HDCPState { + HDCP_STATE_UNDESIRED, + HDCP_STATE_DESIRED, + HDCP_STATE_ENABLED, + + // Update this when adding a new type. + HDCP_STATE_LAST = HDCP_STATE_ENABLED +}; // Color calibration profiles. Don't change the order, and edit // tools/metrics/histograms/histograms.xml when a new item is added.
diff --git a/ui/display/types/native_display_delegate.h b/ui/display/types/native_display_delegate.h index aff8feb..98aef26 100644 --- a/ui/display/types/native_display_delegate.h +++ b/ui/display/types/native_display_delegate.h
@@ -32,6 +32,10 @@ // Interface for classes that perform display configuration actions on behalf // of DisplayConfigurator. +// Implementations may perform calls asynchronously. In the case of functions +// taking callbacks, the callbacks may be called asynchronously when the results +// are available. The implementations must provide a strong guarantee that the +// callbacks are always called. class DISPLAY_TYPES_EXPORT NativeDisplayDelegate { public: virtual ~NativeDisplayDelegate() {} @@ -81,14 +85,10 @@ virtual void CreateFrameBuffer(const gfx::Size& size) = 0; // Gets HDCP state of output. - virtual bool GetHDCPState(const ui::DisplaySnapshot& output, - ui::HDCPState* state) = 0; virtual void GetHDCPState(const ui::DisplaySnapshot& output, const GetHDCPStateCallback& callback) = 0; // Sets HDCP state of output. - virtual bool SetHDCPState(const ui::DisplaySnapshot& output, - ui::HDCPState state) = 0; virtual void SetHDCPState(const ui::DisplaySnapshot& output, ui::HDCPState state, const SetHDCPStateCallback& callback) = 0;
diff --git a/ui/events/event_processor_unittest.cc b/ui/events/event_processor_unittest.cc index 56c205cd..4bf4f0d 100644 --- a/ui/events/event_processor_unittest.cc +++ b/ui/events/event_processor_unittest.cc
@@ -66,10 +66,10 @@ template<typename T> class BoundsEventTargeter : public EventTargeter { public: - virtual ~BoundsEventTargeter() {} + ~BoundsEventTargeter() override {} protected: - virtual bool SubtreeShouldBeExploredForEvent( + bool SubtreeShouldBeExploredForEvent( EventTarget* target, const LocatedEvent& event) override { T* t = static_cast<T*>(target); return (t->bounds().Contains(event.location()));
diff --git a/ui/events/event_target_iterator.h b/ui/events/event_target_iterator.h index 28b4a302..fe3eca6c 100644 --- a/ui/events/event_target_iterator.h +++ b/ui/events/event_target_iterator.h
@@ -28,9 +28,9 @@ : begin_(children.rbegin()), end_(children.rend()) { } - virtual ~EventTargetIteratorImpl() {} + ~EventTargetIteratorImpl() override {} - virtual EventTarget* GetNextTarget() override { + EventTarget* GetNextTarget() override { if (begin_ == end_) return NULL; EventTarget* target = *(begin_);
diff --git a/ui/events/gesture_detection/scale_gesture_detector.cc b/ui/events/gesture_detection/scale_gesture_detector.cc index 676d6a42..fb27cd94 100644 --- a/ui/events/gesture_detection/scale_gesture_detector.cc +++ b/ui/events/gesture_detection/scale_gesture_detector.cc
@@ -5,9 +5,9 @@ #include "ui/events/gesture_detection/scale_gesture_detector.h" #include <limits.h> + #include <cmath> -#include "base/float_util.h" #include "base/logging.h" #include "ui/events/gesture_detection/motion_event.h" #include "ui/events/gesture_detection/scale_gesture_listeners.h" @@ -286,7 +286,7 @@ float total = 0; int sample_count = 0; for (int i = 0; i < count; i++) { - const bool has_last_accepted = !base::IsNaN(touch_history_last_accepted_); + const bool has_last_accepted = !std::isnan(touch_history_last_accepted_); const int history_size = static_cast<int>(ev.GetHistorySize()); const int pointersample_count = history_size + 1; for (int h = 0; h < pointersample_count; h++) { @@ -302,10 +302,10 @@ major = touch_max_major_; total += major; - if (base::IsNaN(touch_upper_) || major > touch_upper_) { + if (std::isnan(touch_upper_) || major > touch_upper_) { touch_upper_ = major; } - if (base::IsNaN(touch_lower_) || major < touch_lower_) { + if (std::isnan(touch_lower_) || major < touch_lower_) { touch_lower_ = major; }
diff --git a/ui/events/latency_info.cc b/ui/events/latency_info.cc index 112cc462..24f12d4 100644 --- a/ui/events/latency_info.cc +++ b/ui/events/latency_info.cc
@@ -22,7 +22,7 @@ switch (type) { CASE_TYPE(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT); CASE_TYPE(INPUT_EVENT_LATENCY_BEGIN_PLUGIN_COMPONENT); - CASE_TYPE(INPUT_EVENT_LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT); + CASE_TYPE(LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT); CASE_TYPE(INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT); CASE_TYPE(INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT); CASE_TYPE(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT); @@ -71,7 +71,12 @@ bool IsBeginComponent(ui::LatencyComponentType type) { return (type == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT || type == ui::INPUT_EVENT_LATENCY_BEGIN_PLUGIN_COMPONENT || - type == ui::INPUT_EVENT_LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT); + type == ui::LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT); +} + +bool IsInputLatencyBeginComponent(ui::LatencyComponentType type) { + return (type == ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT || + type == ui::INPUT_EVENT_LATENCY_BEGIN_PLUGIN_COMPONENT); } // This class is for converting latency info to trace buffer friendly format. @@ -251,9 +256,6 @@ const unsigned char* benchmark_enabled = g_benchmark_enabled.Get().benchmark_enabled; - if (*benchmark_enabled && trace_name_str) - trace_name = trace_name_str; - if (IsBeginComponent(component)) { // Should only ever add begin component once. CHECK_EQ(-1, trace_id); @@ -265,14 +267,14 @@ // for an input event, we want to draw the beginning as when the event is // originally created, e.g. the timestamp of its ORIGINAL/UI_COMPONENT, // not when we actually issue the ASYNC_BEGIN trace event. - LatencyComponent component; + LatencyComponent begin_component; int64 ts = 0; if (FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, - &component) || + &begin_component) || FindLatency(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, - &component)) { + &begin_component)) { // The timestamp stored in ORIGINAL/UI_COMPONENT is using clock // CLOCK_MONOTONIC while TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP0 // expects timestamp using CLOCK_MONOTONIC or CLOCK_SYSTEM_TRACE (on @@ -281,13 +283,21 @@ // can't use a static value. int64 diff = base::TimeTicks::Now().ToInternalValue() - base::TimeTicks::NowFromSystemTraceTime().ToInternalValue(); - ts = component.event_time.ToInternalValue() - diff; + ts = begin_component.event_time.ToInternalValue() - diff; } else { ts = base::TimeTicks::NowFromSystemTraceTime().ToInternalValue(); } + + if (trace_name_str) { + if (IsInputLatencyBeginComponent(component)) + trace_name = std::string("InputLatency::") + trace_name_str; + else + trace_name = std::string("Latency::") + trace_name_str; + } + TRACE_EVENT_COPY_ASYNC_BEGIN_WITH_TIMESTAMP0( "benchmark", - ("InputLatency::" + trace_name).c_str(), + trace_name.c_str(), TRACE_ID_DONT_MANGLE(trace_id), ts); } @@ -322,7 +332,7 @@ if (*benchmark_enabled) { TRACE_EVENT_COPY_ASYNC_END1("benchmark", - ("InputLatency::" + trace_name).c_str(), + trace_name.c_str(), TRACE_ID_DONT_MANGLE(trace_id), "data", AsTraceableData(*this)); }
diff --git a/ui/events/latency_info.h b/ui/events/latency_info.h index 1c6ceef..ffc9bdbd 100644 --- a/ui/events/latency_info.h +++ b/ui/events/latency_info.h
@@ -23,8 +23,10 @@ INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, // Timestamp when the input event is received in plugin. INPUT_EVENT_LATENCY_BEGIN_PLUGIN_COMPONENT, - // Timestamp when a scroll update for the main thread is begun. - INPUT_EVENT_LATENCY_BEGIN_SCROLL_UPDATE_MAIN_COMPONENT, + // In threaded scrolling, main thread scroll listener update is async to + // scroll processing in impl thread. This is the timestamp when we consider + // the main thread scroll listener update is begun. + LATENCY_BEGIN_SCROLL_LISTENER_UPDATE_MAIN_COMPONENT, // ---------------------------NORMAL COMPONENT------------------------------- // The original timestamp of the touch event which converts to scroll update. INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
diff --git a/ui/events/ozone/evdev/event_converter_evdev_impl.cc b/ui/events/ozone/evdev/event_converter_evdev_impl.cc index 0e7c7f1..13a0bfbc 100644 --- a/ui/events/ozone/evdev/event_converter_evdev_impl.cc +++ b/ui/events/ozone/evdev/event_converter_evdev_impl.cc
@@ -7,6 +7,7 @@ #include <errno.h> #include <linux/input.h> +#include "base/trace_event/trace_event.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" #include "ui/events/keycodes/dom4/keycode_converter.h" @@ -53,6 +54,9 @@ } void EventConverterEvdevImpl::OnFileCanReadWithoutBlocking(int fd) { + TRACE_EVENT1("evdev", "EventConverterEvdevImpl::OnFileCanReadWithoutBlocking", + "fd", fd); + input_event inputs[4]; ssize_t read_size = read(fd, inputs, sizeof(inputs)); if (read_size < 0) {
diff --git a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc index 6d44ada..76c4f94c 100644 --- a/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc +++ b/ui/events/ozone/evdev/libgestures_glue/event_reader_libevdev_cros.cc
@@ -11,6 +11,7 @@ #include "base/message_loop/message_loop.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/trace_event/trace_event.h" namespace ui { @@ -70,6 +71,9 @@ EventReaderLibevdevCros::Delegate::~Delegate() {} void EventReaderLibevdevCros::OnFileCanReadWithoutBlocking(int fd) { + TRACE_EVENT1("evdev", "EventReaderLibevdevCros::OnFileCanReadWithoutBlocking", + "fd", fd); + if (EvdevRead(&evdev_)) { if (errno == EINTR || errno == EAGAIN) return;
diff --git a/ui/events/ozone/evdev/tablet_event_converter_evdev.cc b/ui/events/ozone/evdev/tablet_event_converter_evdev.cc index 3c265e0e..22e76ec 100644 --- a/ui/events/ozone/evdev/tablet_event_converter_evdev.cc +++ b/ui/events/ozone/evdev/tablet_event_converter_evdev.cc
@@ -8,6 +8,7 @@ #include <linux/input.h> #include "base/message_loop/message_loop.h" +#include "base/trace_event/trace_event.h" #include "ui/events/event.h" #include "ui/events/ozone/evdev/device_event_dispatcher_evdev.h" @@ -44,6 +45,10 @@ } void TabletEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { + TRACE_EVENT1("evdev", + "TabletEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd", + fd); + input_event inputs[4]; ssize_t read_size = read(fd, inputs, sizeof(inputs)); if (read_size < 0) {
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/ui/events/ozone/evdev/touch_event_converter_evdev.cc index 5b7b2596..2427f894 100644 --- a/ui/events/ozone/evdev/touch_event_converter_evdev.cc +++ b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -23,6 +23,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/trace_event/trace_event.h" #include "ui/events/devices/device_data_manager.h" #include "ui/events/devices/device_util_linux.h" #include "ui/events/event.h" @@ -214,6 +215,10 @@ } void TouchEventConverterEvdev::OnFileCanReadWithoutBlocking(int fd) { + TRACE_EVENT1("evdev", + "TouchEventConverterEvdev::OnFileCanReadWithoutBlocking", "fd", + fd); + input_event inputs[kNumTouchEvdevSlots * 6 + 1]; ssize_t read_size = read(fd, inputs, sizeof(inputs)); if (read_size < 0) {
diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc index 2d47cafe2..0b4cb734 100644 --- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc +++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
@@ -96,7 +96,7 @@ const PrintableSubEntry kU0023[] = { {DomCode::BACKQUOTE, 0, 0, kAny, kAny, VKEY_OEM_7}, {DomCode::BACKSLASH, 1, 0, 0x0027, kAny, VKEY_OEM_2}, // apostrophe - {DomCode::BACKSLASH, 1, 1, 0x007E, kNone, VKEY_OEM_7}}; // ~, NoSymbol + {DomCode::BACKSLASH, 1, 0, 0x007E, kAny, VKEY_OEM_7}}; // ~, NoSymbol // U+0024 dollar sign const PrintableSubEntry kU0024[] = { @@ -109,19 +109,17 @@ {DomCode::KEY_Q, 0, 0, kAny, kAny, VKEY_OEM_7}, {DomCode::BRACKET_RIGHT, 0, 0, kAny, kAny, VKEY_OEM_1}, {DomCode::SLASH, 0, 0, kAny, kAny, VKEY_OEM_7}, - {DomCode::QUOTE, 1, 0, 0x0022, kAny, VKEY_OEM_7}, // quote - {DomCode::BACKQUOTE, 1, 0, 0x0022, kAny, VKEY_OEM_3}, // quote - {DomCode::BACKQUOTE, 1, 0, 0x00B7, kAny, VKEY_OEM_5}, // middle dot - {DomCode::BACKSLASH, 1, 0, kNone, kAny, VKEY_OEM_5}, // NoSymbol - {DomCode::MINUS, 1, 1, 0x003F, kNone, VKEY_OEM_4}, // ?, NoSymbol - {DomCode::MINUS, 1, 1, 0x003F, 0x00DD, VKEY_OEM_4}, // ?, Y acute - {DomCode::EQUAL, 1, 1, 0x002A, kNone, VKEY_OEM_PLUS}, // *, NoSymbol - {DomCode::QUOTE, 1, 1, 0x0040, kNone, VKEY_OEM_3}, // @, NoSymbol - {DomCode::BACKSLASH, 1, 1, 0x002A, kNone, VKEY_OEM_2}, // *, NoSymbol + {DomCode::QUOTE, 1, 0, 0x0022, kAny, VKEY_OEM_7}, // quote + {DomCode::BACKQUOTE, 1, 0, 0x0022, kAny, VKEY_OEM_3}, // quote + {DomCode::BACKQUOTE, 1, 0, 0x00B7, kAny, VKEY_OEM_5}, // middle dot + {DomCode::BACKSLASH, 1, 0, kNone, kAny, VKEY_OEM_5}, // NoSymbol + {DomCode::MINUS, 1, 0, 0x003F, kAny, VKEY_OEM_4}, // ? + {DomCode::EQUAL, 1, 0, 0x002A, kAny, VKEY_OEM_PLUS}, // * + {DomCode::QUOTE, 1, 0, 0x0040, kAny, VKEY_OEM_3}, // @ {DomCode::BACKSLASH, 1, 1, 0x002A, 0x00BD, VKEY_OEM_5}, // *, one half - {DomCode::BACKSLASH, 1, 1, 0x002A, 0x0141, VKEY_OEM_2}, // *, L stroke - {DomCode::KEY_Z, 1, 1, 0x0022, kNone, VKEY_Z}, // quote, NoSymbol - {DomCode::KEY_Z, 1, 1, 0x0022, 0x0158, VKEY_OEM_7}}; // quote, R caron + {DomCode::BACKSLASH, 1, 0, 0x002A, kAny, VKEY_OEM_2}, // *, NoSymbol + {DomCode::KEY_Z, 1, 1, 0x0022, 0x0158, VKEY_OEM_7}, // quote, R caron + {DomCode::KEY_Z, 1, 0, 0x0022, kAny, VKEY_Z}}; // quote // U+0028 left parenthesis const PrintableSubEntry kU0028[] = { @@ -148,9 +146,8 @@ {DomCode::BRACKET_RIGHT, 0, 0, kAny, kAny, VKEY_OEM_PLUS}, {DomCode::SEMICOLON, 0, 0, kAny, kAny, VKEY_OEM_PLUS}, {DomCode::BACKSLASH, 0, 0, kAny, kAny, VKEY_OEM_2}, - {DomCode::MINUS, 1, 1, 0x003F, kNone, VKEY_OEM_PLUS}, // ?, NoSymbol {DomCode::MINUS, 1, 1, 0x003F, 0x005C, VKEY_OEM_MINUS}, // ?, backslash - {DomCode::MINUS, 1, 1, 0x003F, 0x0151, VKEY_OEM_PLUS}}; // ?, o'' + {DomCode::MINUS, 1, 0, 0x003F, kAny, VKEY_OEM_PLUS}}; // ? // U+002C comma const PrintableSubEntry kU002C[] = { @@ -171,12 +168,10 @@ {DomCode::KEY_A, 0, 0, kAny, kAny, VKEY_OEM_MINUS}, {DomCode::QUOTE, 0, 0, kAny, kAny, VKEY_OEM_MINUS}, {DomCode::SLASH, 1, 0, 0x003D, kAny, VKEY_OEM_MINUS}, // = - {DomCode::EQUAL, 1, 1, 0x005F, kNone, VKEY_OEM_MINUS}, // _, NoSymbol - {DomCode::EQUAL, 1, 1, 0x005F, 0x0157, VKEY_OEM_4}, // _, r cedilla - {DomCode::SLASH, 1, 1, 0x005F, kNone, VKEY_OEM_MINUS}, // _, NoSymbol - {DomCode::SLASH, 1, 1, 0x005F, 0x002A, VKEY_OEM_MINUS}, // _, * - {DomCode::SLASH, 1, 1, 0x005F, 0x002F, VKEY_OEM_2}, // _, / - {DomCode::SLASH, 1, 1, 0x005F, 0x006E, VKEY_OEM_MINUS}}; // _, n + {DomCode::EQUAL, 1, 1, 0x005F, 0x0157, VKEY_OEM_4}, // _, r cedilla + {DomCode::EQUAL, 1, 0, 0x005F, kAny, VKEY_OEM_MINUS}, // _ + {DomCode::SLASH, 1, 1, 0x005F, 0x002F, VKEY_OEM_2}, // _, / + {DomCode::SLASH, 1, 0, 0x005F, kAny, VKEY_OEM_MINUS}}; // _ // U+002E full stop const PrintableSubEntry kU002E[] = { @@ -220,16 +215,15 @@ {DomCode::KEY_Z, 0, 0, kAny, kAny, VKEY_OEM_1}, {DomCode::COMMA, 0, 0, kAny, kAny, VKEY_OEM_PERIOD}, {DomCode::SLASH, 0, 0, kAny, kAny, VKEY_OEM_2}}; - // U+003D = const PrintableSubEntry kU003D[] = { {DomCode::DIGIT8, 0, 0, kAny, kAny, VKEY_8}, {DomCode::EQUAL, 0, 0, kAny, kAny, VKEY_OEM_PLUS}, {DomCode::BRACKET_RIGHT, 0, 0, kAny, kAny, VKEY_OEM_PLUS}, - {DomCode::SLASH, 1, 0, 0x0025, kAny, VKEY_OEM_8}, // % - {DomCode::SLASH, 1, 0, 0x002B, kAny, VKEY_OEM_PLUS}, // + - {DomCode::MINUS, 1, 1, 0x0025, kNone, VKEY_OEM_PLUS}, // %, NoSymbol - {DomCode::MINUS, 1, 1, 0x0025, 0x002D, VKEY_OEM_MINUS}}; // %, - + {DomCode::SLASH, 1, 0, 0x0025, kAny, VKEY_OEM_8}, // % + {DomCode::SLASH, 1, 0, 0x002B, kAny, VKEY_OEM_PLUS}, // + + {DomCode::MINUS, 1, 1, 0x0025, 0x002D, VKEY_OEM_MINUS}, // %, - + {DomCode::MINUS, 1, 0, 0x0025, kAny, VKEY_OEM_PLUS}}; // %, NoSymbol // U+003F ? const PrintableSubEntry kU003F[] = { @@ -276,12 +270,7 @@ const PrintableSubEntry kU0060[] = { {DomCode::BACKQUOTE, 1, 0, kNone, kAny, VKEY_OEM_3}, // NoSymbol {DomCode::BACKQUOTE, 1, 0, 0x00AC, kAny, VKEY_OEM_8}, // not - {DomCode::BACKQUOTE, 1, 1, 0x007E, kNone, VKEY_OEM_3}, // ~, NoSymbol - {DomCode::BACKQUOTE, 1, 1, 0x007E, 0x0031, VKEY_OEM_3}, // ~, 1 - {DomCode::BACKQUOTE, 1, 1, 0x007E, 0x003B, VKEY_OEM_3}, // ~, ; - {DomCode::BACKQUOTE, 1, 1, 0x007E, 0x0060, VKEY_OEM_3}, // ~, ` - {DomCode::BACKQUOTE, 1, 1, 0x007E, 0x00BF, VKEY_OEM_3}, // ~, inverted ? - {DomCode::BACKQUOTE, 1, 1, 0x007E, 0x0151, VKEY_OEM_3}}; // ~, o'' + {DomCode::BACKQUOTE, 1, 0, 0x007E, kAny, VKEY_OEM_3}}; // ~ // U+00A7 section const PrintableSubEntry kU00A7[] = { @@ -327,9 +316,7 @@ const PrintableSubEntry kU00E4[] = { {DomCode::BRACKET_RIGHT, 0, 0, kAny, kAny, VKEY_OEM_6}, {DomCode::QUOTE, 1, 0, 0x00E0, kAny, VKEY_OEM_5}, // a grave - {DomCode::QUOTE, 1, 1, 0x00C4, kNone, VKEY_OEM_7}, // A dia., NoSymbol - {DomCode::QUOTE, 1, 1, 0x00C4, 0x015A, VKEY_OEM_7}, // A dia., S acute - {DomCode::QUOTE, 1, 1, 0x00C4, 0x0159, VKEY_OEM_7}}; // A dia., r caron + {DomCode::QUOTE, 1, 0, 0x00C4, kAny, VKEY_OEM_7}}; // A dia. // U+00E6 ae const PrintableSubEntry kU00E6[] = { @@ -344,8 +331,8 @@ {DomCode::QUOTE, 0, 0, kAny, kAny, VKEY_OEM_7}, {DomCode::BACKSLASH, 0, 0, kAny, kAny, VKEY_OEM_2}, {DomCode::COMMA, 0, 0, kAny, kAny, VKEY_OEM_COMMA}, - {DomCode::SEMICOLON, 1, 1, 0x00C7, kNone, VKEY_OEM_1}, // C ced., NoSy - {DomCode::SEMICOLON, 1, 1, 0x00C7, 0x00DE, VKEY_OEM_3}}; // C ced., Thorn + {DomCode::SEMICOLON, 1, 1, 0x00C7, 0x00DE, VKEY_OEM_3}, // C ced., Thorn + {DomCode::SEMICOLON, 1, 0, 0x00C7, kAny, VKEY_OEM_1}}; // C ced., NoSy // U+00E8 e grave const PrintableSubEntry kU00E8[] = { @@ -386,9 +373,9 @@ {DomCode::DIGIT0, 0, 0, kAny, kAny, VKEY_OEM_3}, {DomCode::MINUS, 0, 0, kAny, kAny, VKEY_OEM_PLUS}, {DomCode::BRACKET_LEFT, 0, 0, kAny, kAny, VKEY_OEM_4}, - {DomCode::SEMICOLON, 1, 0, 0x00E9, kAny, VKEY_OEM_7}, // e acute - {DomCode::SEMICOLON, 1, 1, 0x00D6, kNone, VKEY_OEM_3}, // O dia., NoSy - {DomCode::SEMICOLON, 1, 1, 0x00D6, 0x0162, VKEY_OEM_3}}; // O dia., T ced. + {DomCode::SEMICOLON, 1, 0, 0x00E9, kAny, VKEY_OEM_7}, // e acute + {DomCode::SEMICOLON, 1, 1, 0x00D6, 0x0162, VKEY_OEM_3}, // O dia., T ced. + {DomCode::SEMICOLON, 1, 0, 0x00D6, kAny, VKEY_OEM_3}}; // O diaresis // U+00F8 o stroke const PrintableSubEntry kU00F8[] = { @@ -408,10 +395,10 @@ // U+00FC u diaeresis const PrintableSubEntry kU00FC[] = { {DomCode::KEY_W, 0, 0, kAny, kAny, VKEY_W}, - {DomCode::BRACKET_LEFT, 1, 0, 0x00E8, kAny, VKEY_OEM_1}, // e grave - {DomCode::MINUS, 1, 1, 0x00DC, kNone, VKEY_OEM_2}, // U dia., NoSy - {DomCode::BRACKET_LEFT, 1, 1, 0x00DC, kNone, VKEY_OEM_1}, // U dia., NoSy - {DomCode::BRACKET_LEFT, 1, 1, 0x00DC, 0x0141, VKEY_OEM_3}}; // U dia., L- + {DomCode::BRACKET_LEFT, 1, 0, 0x00E8, kAny, VKEY_OEM_1}, // e grave + {DomCode::MINUS, 1, 0, 0x00DC, kAny, VKEY_OEM_2}, // U diaresis + {DomCode::BRACKET_LEFT, 1, 1, 0x00DC, 0x0141, VKEY_OEM_3}, // U dia., L- + {DomCode::BRACKET_LEFT, 1, 0, 0x00DC, kAny, VKEY_OEM_1}}; // U diaresis // U+0103 a breve const PrintableSubEntry kU0103[] = { @@ -445,13 +432,13 @@ // U+0119 e ogonek const PrintableSubEntry kU0119[] = { {DomCode::DIGIT3, 0, 0, kAny, kAny, VKEY_3}, - {DomCode::SLASH, 1, 1, 0x0118, kNone, VKEY_OEM_MINUS}, // E ogonek, NoSy - {DomCode::SLASH, 1, 1, 0x0118, 0x006E, VKEY_OEM_2}}; // E ogonek, n + {DomCode::SLASH, 1, 1, 0x0118, 0x006E, VKEY_OEM_2}, // E ogonek, n + {DomCode::SLASH, 1, 0, 0x0118, kAny, VKEY_OEM_MINUS}}; // E ogonek // U+012F i ogonek const PrintableSubEntry kU012F[] = { {DomCode::DIGIT5, 0, 0, kAny, kAny, VKEY_5}, - {DomCode::BRACKET_LEFT, 1, 1, 0x012E, kNone, VKEY_OEM_4}}; // Iogonek, NoSy + {DomCode::BRACKET_LEFT, 1, 0, 0x012E, kAny, VKEY_OEM_4}}; // Iogonek // U+0142 l stroke const PrintableSubEntry kU0142[] = { @@ -481,8 +468,8 @@ // U+0173 u ogonek const PrintableSubEntry kU0173[] = { {DomCode::DIGIT7, 0, 0, kAny, kAny, VKEY_7}, - {DomCode::SEMICOLON, 1, 1, 0x0172, kNone, VKEY_OEM_3}, // U ogo., NoSy - {DomCode::SEMICOLON, 1, 1, 0x0172, 0x0162, VKEY_OEM_1}}; // U ogo., T ced. + {DomCode::SEMICOLON, 1, 1, 0x0172, 0x0162, VKEY_OEM_1}, // U ogo., T ced. + {DomCode::SEMICOLON, 1, 0, 0x0172, kAny, VKEY_OEM_3}}; // U ogonek // U+017C z dot above const PrintableSubEntry kU017C[] = { @@ -788,12 +775,10 @@ if (*key_code == VKEY_UNKNOWN) *key_code = DomCodeToUsLayoutKeyboardCode(dom_code); } - - if ((flags & EF_CONTROL_DOWN) == EF_CONTROL_DOWN) { - // Use GetCharacterFromKeyCode() to set |character| to 0x0 for keys that - // are not part of the accepted set of Control+Key combinations. - *character = GetCharacterFromKeyCode(*key_code, flags); - } + // If the Control key is down, only allow ASCII control characters to be + // returned, regardless of the key layout. crbug.com/450849 + if ((flags & EF_CONTROL_DOWN) && (*character >= 0x20)) + *character = 0; } else if (*dom_key == DomKey::DEAD) { *character = DeadXkbKeySymToCombiningCharacter(xkb_keysym); *key_code = DomCodeToUsLayoutKeyboardCode(dom_code); @@ -975,4 +960,5 @@ *layout_variant = layout_name.substr(dash_index + 1); } } + } // namespace ui
diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc index f5195d0..69fe062 100644 --- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc +++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine_unittest.cc
@@ -142,7 +142,7 @@ // number sign, apostrophe, * /* 5 */ {0x0023, 0x0027, 0x2461, DomCode::BACKSLASH, VKEY_OEM_2}, // number sign, tilde, unmapped - /* 6 */ {0x0023, 0x007E, 0x0000, DomCode::BACKSLASH, VKEY_OEM_7}, + /* 6 */ {0x0023, 0x007E, 0x2461, DomCode::BACKSLASH, VKEY_OEM_7}, // number sign, *, * /* 7 */ {0x0023, 0x2460, 0x2461, DomCode::BACKQUOTE, VKEY_OEM_7}, // dollar sign, *, * @@ -156,7 +156,7 @@ // apostrophe, unmapped, * /* 12 */ {0x0027, 0x0000, 0x2461, DomCode::BACKSLASH, VKEY_OEM_5}, // apostrophe, quotation mark, unmapped - /* 13 */ {0x0027, 0x0022, 0x0000, DomCode::KEY_Z, VKEY_Z}, + /* 13 */ {0x0027, 0x0022, 0x2461, DomCode::KEY_Z, VKEY_Z}, // apostrophe, quotation mark, R caron /* 14 */ {0x0027, 0x0022, 0x0158, DomCode::KEY_Z, VKEY_OEM_7}, // apostrophe, quotation mark, * @@ -164,19 +164,19 @@ // apostrophe, quotation mark, * /* 16 */ {0x0027, 0x0022, 0x2461, DomCode::QUOTE, VKEY_OEM_7}, // apostrophe, asterisk, unmapped - /* 17 */ {0x0027, 0x002A, 0x0000, DomCode::BACKSLASH, VKEY_OEM_2}, + /* 17 */ {0x0027, 0x002A, 0x2461, DomCode::BACKSLASH, VKEY_OEM_2}, // apostrophe, asterisk, unmapped - /* 18 */ {0x0027, 0x002A, 0x0000, DomCode::EQUAL, VKEY_OEM_PLUS}, + /* 18 */ {0x0027, 0x002A, 0x2461, DomCode::EQUAL, VKEY_OEM_PLUS}, // apostrophe, asterisk, vulgar fraction one half /* 19 */ {0x0027, 0x002A, 0x00BD, DomCode::BACKSLASH, VKEY_OEM_5}, // apostrophe, asterisk, L stroke /* 20 */ {0x0027, 0x002A, 0x0141, DomCode::BACKSLASH, VKEY_OEM_2}, // apostrophe, question mark, unmapped - /* 21 */ {0x0027, 0x003F, 0x0000, DomCode::MINUS, VKEY_OEM_4}, + /* 21 */ {0x0027, 0x003F, 0x2461, DomCode::MINUS, VKEY_OEM_4}, // apostrophe, question mark, Y acute /* 22 */ {0x0027, 0x003F, 0x00DD, DomCode::MINUS, VKEY_OEM_4}, // apostrophe, commercial at, unmapped - /* 23 */ {0x0027, 0x0040, 0x0000, DomCode::QUOTE, VKEY_OEM_3}, + /* 23 */ {0x0027, 0x0040, 0x2461, DomCode::QUOTE, VKEY_OEM_3}, // apostrophe, middle dot, * /* 24 */ {0x0027, 0x00B7, 0x2461, DomCode::BACKQUOTE, VKEY_OEM_5}, // apostrophe, *, * @@ -204,7 +204,7 @@ // asterisk, *, * /* 36 */ {0x002A, 0x2460, 0x2461, DomCode::BRACKET_RIGHT, VKEY_OEM_1}, // plus sign, question mark, unmapped - /* 37 */ {0x002B, 0x003F, 0x0000, DomCode::MINUS, VKEY_OEM_PLUS}, + /* 37 */ {0x002B, 0x003F, 0x2461, DomCode::MINUS, VKEY_OEM_PLUS}, // plus sign, question mark, reverse solidus /* 38 */ {0x002B, 0x003F, 0x005C, DomCode::MINUS, VKEY_OEM_MINUS}, // plus sign, question mark, o double acute @@ -240,9 +240,9 @@ // hyphen-minus, equals sign, * /* 54 */ {0x002D, 0x003D, 0x2461, DomCode::SLASH, VKEY_OEM_MINUS}, // hyphen-minus, low line, unmapped - /* 55 */ {0x002D, 0x005F, 0x0000, DomCode::EQUAL, VKEY_OEM_MINUS}, + /* 55 */ {0x002D, 0x005F, 0x2461, DomCode::EQUAL, VKEY_OEM_MINUS}, // hyphen-minus, low line, unmapped - /* 56 */ {0x002D, 0x005F, 0x0000, DomCode::SLASH, VKEY_OEM_MINUS}, + /* 56 */ {0x002D, 0x005F, 0x2461, DomCode::SLASH, VKEY_OEM_MINUS}, // hyphen-minus, low line, asterisk /* 57 */ {0x002D, 0x005F, 0x002A, DomCode::SLASH, VKEY_OEM_MINUS}, // hyphen-minus, low line, solidus @@ -326,7 +326,7 @@ // less-than sign, *, * /* 97 */ {0x003C, 0x2460, 0x2461, DomCode::NONE, VKEY_OEM_5}, // equals sign, percent sign, unmapped - /* 98 */ {0x003D, 0x0025, 0x0000, DomCode::MINUS, VKEY_OEM_PLUS}, + /* 98 */ {0x003D, 0x0025, 0x2461, DomCode::MINUS, VKEY_OEM_PLUS}, // equals sign, percent sign, hyphen-minus /* 99 */ {0x003D, 0x0025, 0x002D, DomCode::MINUS, VKEY_OEM_MINUS}, // equals sign, percent sign, * @@ -388,7 +388,7 @@ // grave accent, unmapped, * /* 128 */ {0x0060, 0x0000, 0x2461, DomCode::BACKQUOTE, VKEY_OEM_3}, // grave accent, tilde, unmapped - /* 129 */ {0x0060, 0x007E, 0x0000, DomCode::BACKQUOTE, VKEY_OEM_3}, + /* 129 */ {0x0060, 0x007E, 0x2461, DomCode::BACKQUOTE, VKEY_OEM_3}, // grave accent, tilde, digit one /* 130 */ {0x0060, 0x007E, 0x0031, DomCode::BACKQUOTE, VKEY_OEM_3}, // grave accent, tilde, semicolon @@ -464,7 +464,7 @@ // a circumflex, *, * /* 166 */ {0x00E2, 0x2460, 0x2461, DomCode::DIGIT2, VKEY_2}, // a diaeresis, A diaeresis, unmapped - /* 167 */ {0x00E4, 0x00C4, 0x0000, DomCode::QUOTE, VKEY_OEM_7}, + /* 167 */ {0x00E4, 0x00C4, 0x2461, DomCode::QUOTE, VKEY_OEM_7}, // a diaeresis, A diaeresis, r caron /* 168 */ {0x00E4, 0x00C4, 0x0159, DomCode::QUOTE, VKEY_OEM_7}, // a diaeresis, A diaeresis, S acute @@ -480,7 +480,7 @@ // ae, *, * /* 174 */ {0x00E6, 0x2460, 0x2461, DomCode::SEMICOLON, VKEY_OEM_3}, // c cedilla, C cedilla, unmapped - /* 175 */ {0x00E7, 0x00C7, 0x0000, DomCode::SEMICOLON, VKEY_OEM_1}, + /* 175 */ {0x00E7, 0x00C7, 0x2461, DomCode::SEMICOLON, VKEY_OEM_1}, // c cedilla, C cedilla, Thorn /* 176 */ {0x00E7, 0x00C7, 0x00DE, DomCode::SEMICOLON, VKEY_OEM_3}, // c cedilla, *, * @@ -542,7 +542,7 @@ // o tilde, *, * /* 205 */ {0x00F5, 0x2460, 0x2461, DomCode::NONE, VKEY_OEM_4}, // o diaeresis, O diaeresis, unmapped - /* 206 */ {0x00F6, 0x00D6, 0x0000, DomCode::SEMICOLON, VKEY_OEM_3}, + /* 206 */ {0x00F6, 0x00D6, 0x2461, DomCode::SEMICOLON, VKEY_OEM_3}, // o diaeresis, O diaeresis, T cedilla /* 207 */ {0x00F6, 0x00D6, 0x0162, DomCode::SEMICOLON, VKEY_OEM_3}, // o diaeresis, e acute, * @@ -568,9 +568,9 @@ // u acute, *, * /* 218 */ {0x00FA, 0x2460, 0x2461, DomCode::BRACKET_RIGHT, VKEY_OEM_6}, // u diaeresis, U diaeresis, unmapped - /* 219 */ {0x00FC, 0x00DC, 0x0000, DomCode::BRACKET_LEFT, VKEY_OEM_1}, + /* 219 */ {0x00FC, 0x00DC, 0x2461, DomCode::BRACKET_LEFT, VKEY_OEM_1}, // u diaeresis, U diaeresis, unmapped - /* 220 */ {0x00FC, 0x00DC, 0x0000, DomCode::MINUS, VKEY_OEM_2}, + /* 220 */ {0x00FC, 0x00DC, 0x2461, DomCode::MINUS, VKEY_OEM_2}, // u diaeresis, U diaeresis, L stroke /* 221 */ {0x00FC, 0x00DC, 0x0141, DomCode::BRACKET_LEFT, VKEY_OEM_3}, // u diaeresis, e grave, * @@ -618,7 +618,7 @@ // e dot above, *, * /* 243 */ {0x0117, 0x2460, 0x2461, DomCode::QUOTE, VKEY_OEM_7}, // e ogonek, E ogonek, unmapped - /* 244 */ {0x0119, 0x0118, 0x0000, DomCode::SLASH, VKEY_OEM_MINUS}, + /* 244 */ {0x0119, 0x0118, 0x2461, DomCode::SLASH, VKEY_OEM_MINUS}, // e ogonek, E ogonek, n /* 245 */ {0x0119, 0x0118, 0x006E, DomCode::SLASH, VKEY_OEM_2}, // e ogonek, *, * @@ -634,7 +634,7 @@ // i macron, *, * /* 251 */ {0x012B, 0x2460, 0x2461, DomCode::NONE, VKEY_OEM_6}, // i ogonek, I ogonek, unmapped - /* 252 */ {0x012F, 0x012E, 0x0000, DomCode::BRACKET_LEFT, VKEY_OEM_4}, + /* 252 */ {0x012F, 0x012E, 0x2461, DomCode::BRACKET_LEFT, VKEY_OEM_4}, // i ogonek, *, * /* 253 */ {0x012F, 0x2460, 0x2461, DomCode::DIGIT5, VKEY_5}, // dotless i, *, * @@ -688,7 +688,7 @@ // u double acute, *, * /* 278 */ {0x0171, 0x2460, 0x2461, DomCode::NONE, VKEY_OEM_5}, // u ogonek, U ogonek, unmapped - /* 279 */ {0x0173, 0x0172, 0x0000, DomCode::SEMICOLON, VKEY_OEM_3}, + /* 279 */ {0x0173, 0x0172, 0x2461, DomCode::SEMICOLON, VKEY_OEM_3}, // u ogonek, U ogonek, T cedilla /* 280 */ {0x0173, 0x0172, 0x0162, DomCode::SEMICOLON, VKEY_OEM_1}, // u ogonek, *, *
diff --git a/ui/events/platform/x11/x11_hotplug_event_handler.cc b/ui/events/platform/x11/x11_hotplug_event_handler.cc index b4150586b..9d5a77b 100644 --- a/ui/events/platform/x11/x11_hotplug_event_handler.cc +++ b/ui/events/platform/x11/x11_hotplug_event_handler.cc
@@ -459,8 +459,10 @@ &bytes_after_return, reinterpret_cast<unsigned char**>(&product_info)) == 0 && product_info) { - vendor = product_info[0]; - product = product_info[1]; + if (num_items_return == 2) { + vendor = product_info[0]; + product = product_info[1]; + } XFree(product_info); }
diff --git a/ui/file_manager/file_manager/background/js/import_history.js b/ui/file_manager/file_manager/background/js/import_history.js index e69ce262ae..cb22333 100644 --- a/ui/file_manager/file_manager/background/js/import_history.js +++ b/ui/file_manager/file_manager/background/js/import_history.js
@@ -967,12 +967,10 @@ */ importer.DriveSyncWatcher.prototype.onFileTransfersUpdated_ = function(status) { - // TODO(smckay): What if the file isn't one we're interested in....? - // I guess we just let the call to markImportedByUrl fail for now. + // If the synced file it isn't one we copied, + // the call to mark by url will just fail...fine by us. if (status.transferState === 'completed') { - this.history_.markImportedByUrl(status.fileUrl) - .catch( - importer.getLogger().catcher('file-transfer-mark-imported-by-url')); + this.history_.markImportedByUrl(status.fileUrl); } };
diff --git a/ui/file_manager/file_manager/foreground/css/file_manager.css b/ui/file_manager/file_manager/foreground/css/file_manager.css index ff5f158b..d30d1cb 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -1130,7 +1130,7 @@ } .thumbnail-grid .shield { - background-color: rgba(27, 168, 243, 0.5); + background-color: rgba(160, 160, 160, 0.5); bottom: 0; display: none; left: 0; @@ -1139,6 +1139,10 @@ top: 0; } +.thumbnail-grid:focus .shield { + background-color: rgba(27, 168, 243, 0.5); +} + .thumbnail-grid .thumbnail-item[selected] .shield { display: block; } @@ -1154,6 +1158,10 @@ } .thumbnail-grid .thumbnail-item[selected].directory .thumbnail-bottom { + background-color: rgb(232, 232, 232); +} + +.thumbnail-grid:focus .thumbnail-item[selected].directory .thumbnail-bottom { background-color: rgb(232, 246, 253); }
diff --git a/ui/file_manager/file_manager/foreground/js/cws_container_client.js b/ui/file_manager/file_manager/foreground/js/cws_container_client.js index 403d716..9e319231 100644 --- a/ui/file_manager/file_manager/foreground/js/cws_container_client.js +++ b/ui/file_manager/file_manager/foreground/js/cws_container_client.js
@@ -194,13 +194,13 @@ */ CWSContainerClient.prototype.postInitializeMessage_ = function() { new Promise(function(fulfill, reject) { - chrome.management.getAll(function(items) { + chrome.fileManagerPrivate.getProvidingExtensions(function(items) { if (chrome.runtime.lastError) { reject(chrome.runtime.lastError.message); return; } fulfill(items.map(function(item) { - return item.id; + return item.extensionId; })); }) }).then(
diff --git a/ui/file_manager/file_manager/foreground/js/cws_widget_container.js b/ui/file_manager/file_manager/foreground/js/cws_widget_container.js index ad7eb42..9a46823 100644 --- a/ui/file_manager/file_manager/foreground/js/cws_widget_container.js +++ b/ui/file_manager/file_manager/foreground/js/cws_widget_container.js
@@ -305,6 +305,13 @@ }; /** + * @return {boolean} Whether the container is in initial state, i.e. inactive. + */ +CWSWidgetContainer.prototype.isInInitialState = function() { + return this.state_ === CWSWidgetContainer.State.UNINITIALIZED; +}; + +/** * Ensures that the widget container is in the state where it can properly * handle showing the Chrome Web Store webview. * @return {Promise} Resolved when the container is ready to be used. @@ -655,11 +662,15 @@ this.webviewClient_ = null; } - if (this.webview_) + if (this.webview_) { this.webviewContainer_.removeChild(this.webview_); + this.webview_ = null; + } - if (this.appInstaller_) + if (this.appInstaller_) { this.appInstaller_.cancel(); + this.appInstaller_ = null; + } this.options_ = null;
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index 070b1cd..743fb67 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -1251,14 +1251,23 @@ /** * @param {!Event} event Command event. * @param {!FileManager} fileManager FileManager to use. + * @suppress {checkTypes} */ execute: function(event, fileManager) { fileManager.ui.suggestAppsDialog.showProviders( function(result, itemId) { // If a new provider is installed, then launch it so the configuration // dialog is shown (if it's available). - if (result === SuggestAppsDialog.Result.SUCCESS) - chrome.management.launchApp(assert(itemId), function() {}); + if (result === SuggestAppsDialog.Result.SUCCESS) { + // TODO(mtomasz): Pass extension_id to addProvidedFileSystem. + chrome.fileManagerPrivate.addProvidedFileSystem(function() { + if (chrome.runtime.lastError) { + // TODO(mtomasz): Handle the error and let users uninstall the + // extension easily. + console.error(chrome.runtime.lastError.message); + } + }); + } }); }, canExecute: CommandUtil.canExecuteAlways
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners.js b/ui/file_manager/file_manager/foreground/js/ui/banners.js index 963d23ff..67624f8 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/banners.js +++ b/ui/file_manager/file_manager/foreground/js/ui/banners.js
@@ -49,6 +49,12 @@ parseInt(values[WELCOME_HEADER_COUNTER_KEY], 10) || 0; this.warningDismissedCounter_ = parseInt(values[WARNING_DISMISSED_KEY], 10) || 0; + + // If it's in test, override the counter to show the header by force. + if (window.IN_TEST) { + this.welcomeHeaderCounter_ = 0; + this.warningDismissedCounter_ = 0; + } }.bind(this)); // Authentication failed banner.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/location_line.js b/ui/file_manager/file_manager/foreground/js/ui/location_line.js index f3fe2fdb..feb8615e 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/location_line.js +++ b/ui/file_manager/file_manager/foreground/js/ui/location_line.js
@@ -117,6 +117,7 @@ newBreadcrumbs.appendChild(button); var ripple = document.createElement('paper-ripple'); + ripple.classList.add('recenteringTouch'); ripple.setAttribute('fit', ''); button.appendChild(ripple);
diff --git a/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js index 5873cda..ef98f0c 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js +++ b/ui/file_manager/file_manager/foreground/js/ui/suggest_apps_dialog.js
@@ -131,7 +131,10 @@ this.text_.hidden = true; this.dialogText_ = ''; - this.onDialogClosed_ = onDialogClosed; + if (!this.widget_.isInInitialState()) { + onDialogClosed(SuggestAppsDialog.Result.CANCELLED, null); + return; + } var dialogShown = false; @@ -145,6 +148,9 @@ /** @return {!Promise.<CWSWidgetContainer.ResolveReason>} */ function() { dialogShown = true; + // This is not set before so it doesn't polute state if the previous + // dialog hasn't finished hiding. + this.onDialogClosed_ = onDialogClosed; return this.widget_.start(options, webStoreUrl); }.bind(this)) .then( @@ -157,12 +163,20 @@ /** @param {string} error */ function(error) { console.error('Failed to start CWS widget: ' + error); - this.result_ = SuggestAppsDialog.Result.FAILED; - if (dialogShown) { - this.hide(); - } else { - this.onHide_(); + + // If the widget dialog was not shown, consider the widget + // canceled. + if (!dialogShown) { + // Reset any widget state set in |this.widget_.ready()|. The + // returned value is ignored because it doesn't influence the + // value reported by dialog. + this.widget_.finalizeAndGetResult(); + onDialogClosed(SuggestAppsDialog.Result.CANCELLED, null); + return; } + + this.result_ = SuggestAppsDialog.Result.FAILED; + this.hide(); }.bind(this)); };
diff --git a/ui/file_manager/file_manager/main.html b/ui/file_manager/file_manager/main.html index a4ae31d..c5d61ea 100644 --- a/ui/file_manager/file_manager/main.html +++ b/ui/file_manager/file_manager/main.html
@@ -346,7 +346,7 @@ <div id="files-selected-label"></div> <div class="spacer"></div> <button id="tasks" class="combobutton" menu="#tasks-menu" - tabindex="9" + tabindex="9" hidden i18n-values="aria-label:TASKS_BUTTON_LABEL"> <paper-ripple fit></paper-ripple> </button> @@ -496,8 +496,8 @@ </button> <div id="filename-input-box" visibleif="saveas-file"> <paper-input-decorator i18n-values="label:FILENAME_LABEL"> - <input is="core-input" class="entry-name" type="text" - spellcheck="false" tabindex="4"> + <input id="filename-input-textbox" is="core-input" tabindex="4" + class="entry-name" type="text" spellcheck="false"> </paper-input-decorator> </div> <div class="preparing-label" i18n-content="PREPARING_LABEL"></div>
diff --git a/ui/file_manager/file_manager/manifest.json b/ui/file_manager/file_manager/manifest.json index 674dd69..60712be 100644 --- a/ui/file_manager/file_manager/manifest.json +++ b/ui/file_manager/file_manager/manifest.json
@@ -36,7 +36,6 @@ "https://drive.google.com/", "https://www.google-analytics.com/", "launcherSearchProvider", - "management", "mediaPlayerPrivate", "metricsPrivate", "notifications",
diff --git a/ui/file_manager/gallery/css/gallery.css b/ui/file_manager/gallery/css/gallery.css index 7b933b20..37aa6fc9 100644 --- a/ui/file_manager/gallery/css/gallery.css +++ b/ui/file_manager/gallery/css/gallery.css
@@ -138,10 +138,10 @@ /* Print the full resolution image instead. */ .gallery .image-container > canvas.fullres { - display: block !important; height: auto !important; max-height: 100%; max-width: 100%; + opacity: 1 !important; position: static !important; transform: none !important; visibility: visible !important;
diff --git a/ui/file_manager/integration_tests/file_manager/background.js b/ui/file_manager/integration_tests/file_manager/background.js index 74a6b8a..d38a688 100644 --- a/ui/file_manager/integration_tests/file_manager/background.js +++ b/ui/file_manager/integration_tests/file_manager/background.js
@@ -228,6 +228,58 @@ } /** + * Opens a file dialog and waits for closing it. + * + * @param {Object} dialogParams Dialog parameters to be passed to chrome. + * fileSystem.chooseEntry() API. + * @param {string} volumeName Volume name passed to the selectVolume remote + * funciton. + * @param {Array.<TestEntryInfo>} expectedSet Expected set of the entries. + * @param {function(windowId:string):Promise} closeDialog Function to close the + * dialog. + * @return {Promise} Promise to be fulfilled with the result entry of the + * dialog. + */ +function openAndWaitForClosingDialog( + dialogParams, volumeName, expectedSet, closeDialog) { + var resultPromise = new Promise(function(fulfill) { + chrome.fileSystem.chooseEntry( + dialogParams, + function(entry) { fulfill(entry); }); + chrome.test.assertTrue(!chrome.runtime.lastError, 'chooseEntry failed.'); + }); + + return remoteCall.waitForWindow('dialog#').then(function(windowId) { + return remoteCall.waitForElement(windowId, '#file-list'). + then(function() { + // Wait for initialization of Files.app. + return remoteCall.waitForFiles( + windowId, TestEntryInfo.getExpectedRows(BASIC_LOCAL_ENTRY_SET)); + }). + then(function() { + return remoteCall.callRemoteTestUtil( + 'selectVolume', windowId, [volumeName]); + }). + then(function() { + var expectedRows = TestEntryInfo.getExpectedRows(expectedSet); + return remoteCall.waitForFiles(windowId, expectedRows); + }). + then(closeDialog.bind(null, windowId)). + then(function() { + return repeatUntil(function() { + return remoteCall.callRemoteTestUtil('getWindows', null, []). + then(function(windows) { + if (windows[windowId]) + return pending('Window %s does not hide.', windowId); + else + return resultPromise; + }); + }); + }); + }); +} + +/** * Opens a Files.app's main window and waits until it is initialized. Fills * the window with initial files. Should be called for the first window only. *
diff --git a/ui/file_manager/integration_tests/file_manager/file_dialog.js b/ui/file_manager/integration_tests/file_manager/file_dialog.js index 92f4c01..5990bfa 100644 --- a/ui/file_manager/integration_tests/file_manager/file_dialog.js +++ b/ui/file_manager/integration_tests/file_manager/file_dialog.js
@@ -5,58 +5,6 @@ 'use strict'; /** - * Opens a file dialog and waits for closing it. - * - * @param {string} volumeName Volume name passed to the selectVolume remote - * funciton. - * @param {Array.<TestEntryInfo>} expectedSet Expected set of the entries. - * @param {function(windowId:string):Promise} closeDialog Function to close the - * dialog. - * @return {Promise} Promise to be fulfilled with the result entry of the - * dialog. - */ -function openAndWaitForClosingDialog(volumeName, expectedSet, closeDialog) { - var resultPromise = new Promise(function(fulfill) { - chrome.fileSystem.chooseEntry( - {type: 'openFile'}, - function(entry) { fulfill(entry); }); - }); - - return remoteCall.waitForWindow('dialog#').then(function(windowId) { - return remoteCall.waitForElement(windowId, '#file-list'). - then(function() { - // Wait for initialization of Files.app. - return remoteCall.waitForFiles( - windowId, TestEntryInfo.getExpectedRows(BASIC_LOCAL_ENTRY_SET)); - }). - then(function() { - return remoteCall.callRemoteTestUtil( - 'selectVolume', windowId, [volumeName]); - }). - then(function() { - var expectedRows = TestEntryInfo.getExpectedRows(expectedSet); - return remoteCall.waitForFiles(windowId, expectedRows); - }). - then(function() { - return remoteCall.callRemoteTestUtil( - 'selectFile', windowId, ['hello.txt']); - }). - then(closeDialog.bind(null, windowId)). - then(function() { - return repeatUntil(function() { - return remoteCall.callRemoteTestUtil('getWindows', null, []). - then(function(windows) { - if (windows[windowId]) - return pending('Window %s does not hide.', windowId); - else - return resultPromise; - }); - }); - }); - }); -} - -/** * Tests to open and cancel the file dialog. * * @param {string} volumeName Volume name passed to the selectVolume remote @@ -72,17 +20,21 @@ var closeByCancelButtonPromise = setupPromise.then(function() { return openAndWaitForClosingDialog( + {type: 'openFile'}, volumeName, expectedSet, function(windowId) { - return remoteCall.waitForElement(windowId, - '.button-panel button.cancel'). - then(function() { - return remoteCall.callRemoteTestUtil( - 'fakeEvent', - windowId, - ['.button-panel button.cancel', 'click']); - }); + return remoteCall.callRemoteTestUtil( + 'selectFile', windowId, ['hello.txt'] + ).then(function() { + return remoteCall.waitForElement(windowId, + '.button-panel button.cancel'); + }).then(function() { + return remoteCall.callRemoteTestUtil( + 'fakeEvent', + windowId, + ['.button-panel button.cancel', 'click']); + }); }); }).then(function(result) { // Undefined means the dialog is canceled. @@ -91,13 +43,18 @@ var closeByEscKeyPromise = closeByCancelButtonPromise.then(function() { return openAndWaitForClosingDialog( + {type: 'openFile'}, volumeName, expectedSet, function(windowId) { return remoteCall.callRemoteTestUtil( - 'fakeKeyDown', - windowId, - ['#file-list', 'U+001B', false]); + 'selectFile', windowId, ['hello.txt'] + ).then(function() { + return remoteCall.callRemoteTestUtil( + 'fakeKeyDown', + windowId, + ['#file-list', 'U+001B', false]); + }); }); }).then(function(result) { // Undefined means the dialog is canceled. @@ -106,17 +63,21 @@ var closeByOkButtonPromise = closeByEscKeyPromise.then(function() { return openAndWaitForClosingDialog( + {type: 'openFile'}, volumeName, expectedSet, function(windowId) { - return remoteCall.waitForElement(windowId, - '.button-panel button.ok'). - then(function() { - return remoteCall.callRemoteTestUtil( - 'fakeEvent', - windowId, - ['.button-panel button.ok', 'click']); - }); + return remoteCall.callRemoteTestUtil( + 'selectFile', windowId, ['hello.txt'] + ).then(function() { + return remoteCall.waitForElement(windowId, + '.button-panel button.ok'); + }).then(function() { + return remoteCall.callRemoteTestUtil( + 'fakeEvent', + windowId, + ['.button-panel button.ok', 'click']); + }); }); }).then(function(result) { chrome.test.assertEq('hello.txt', result.name);
diff --git a/ui/file_manager/integration_tests/file_manager/suggest_app_dialog.js b/ui/file_manager/integration_tests/file_manager/suggest_app_dialog.js index 0c81507..bb5752294 100644 --- a/ui/file_manager/integration_tests/file_manager/suggest_app_dialog.js +++ b/ui/file_manager/integration_tests/file_manager/suggest_app_dialog.js
@@ -53,7 +53,7 @@ function(result) { chrome.test.assertTrue(!!result); remoteCall.waitForElement( - appId, '.cws-widget-webview-container:not(.cws-widget-show-spinner)'). + appId, '.cws-widget-spinner-layer:not(.cws-widget-show-spinner)'). then(this.next); }, // Override task APIs for test.
diff --git a/ui/file_manager/integration_tests/file_manager/tab_index.js b/ui/file_manager/integration_tests/file_manager/tab_index.js index 57b9c531..fd7ae6e 100644 --- a/ui/file_manager/integration_tests/file_manager/tab_index.js +++ b/ui/file_manager/integration_tests/file_manager/tab_index.js
@@ -191,21 +191,41 @@ /** * Tests the tab focus in the dialog and closes the dialog. + * + * @param {Object} dialogParams Dialog parameters to be passed to + * chrome.fileSystem.chooseEntry. + * @param {string} volumeName Volume name passed to the selectVolume remote + * function. + * @param {Array.<TestEntryInfo>} expectedSet Expected set of the entries. + * @param {boolean} selectFile True to select 'hello.txt' before the tab order + * check, false do not select any file before the check. + * @param {string} initialElement Selector of the element which shows ready. + * @param {Array.<string>} expectedTabOrder Array with the IDs of the element + * with the corresponding order of expected tab-indexes. */ -function tabindexFocus(volumeName, expectedSet, expectedTabOrder) { +function tabindexFocus(dialogParams, volumeName, expectedSet, selectFile, + initialElement, expectedTabOrder) { var localEntriesPromise = addEntries(['local'], BASIC_LOCAL_ENTRY_SET); var driveEntriesPromise = addEntries(['drive'], BASIC_DRIVE_ENTRY_SET); var setupPromise = Promise.all([localEntriesPromise, driveEntriesPromise]); - var checkAndClose = function(appId) { - var promise = remoteCall.callRemoteTestUtil('getActiveElement', appId, []); + var selectAndCheckAndClose = function(appId) { + var promise = Promise.resolve(); + + if (selectFile) { + promise = promise.then(function() { + return remoteCall.callRemoteTestUtil( + 'selectFile', appId, ['hello.txt']); + }); + } + promise = promise.then(function() { - return remoteCall.waitForElement(appId, ['#ok-button:not([disabled])']); + return remoteCall.callRemoteTestUtil('getActiveElement', appId, []); }); - // Checks initial focus. + // Waits for the initial element. promise = promise.then(function() { - return remoteCall.waitForElement(appId, ['#file-list:focus']); + return remoteCall.waitForElement(appId, [initialElement]); }); // Checks tabfocus. @@ -220,16 +240,15 @@ promise = promise.then(function() { // Closes the window by pressing Enter. return remoteCall.callRemoteTestUtil( - 'fakeKeyDown', - appId, - ['#file-list', 'Enter', false]); + 'fakeKeyDown', appId, ['#file-list', 'Enter', false]); }); return promise; }; return setupPromise.then(function() { - return openAndWaitForClosingDialog(volumeName, expectedSet, checkAndClose); + return openAndWaitForClosingDialog( + dialogParams, volumeName, expectedSet, selectAndCheckAndClose); }); } @@ -238,9 +257,10 @@ */ testcase.tabindexOpenDialogDownloads = function() { testPromise(tabindexFocus( - 'downloads', BASIC_LOCAL_ENTRY_SET, - ['ok-button', 'cancel-button', 'search-button', 'view-button', - 'gear-button', 'directory-tree', 'file-list'])); + {type: 'openFile'}, 'downloads', BASIC_LOCAL_ENTRY_SET, true, + '#ok-button:not([disabled])', + ['ok-button', 'cancel-button', 'search-button', 'view-button', + 'gear-button', 'directory-tree', 'file-list'])); }; /** @@ -248,7 +268,40 @@ */ testcase.tabindexOpenDialogDrive = function() { testPromise(tabindexFocus( - 'drive', BASIC_DRIVE_ENTRY_SET, - ['ok-button', 'cancel-button', 'search-button', 'view-button', - 'gear-button', 'directory-tree', 'file-list'])); + {type: 'openFile'}, 'drive', BASIC_DRIVE_ENTRY_SET, true, + '#ok-button:not([disabled])', + ['ok-button', 'cancel-button', 'search-button', 'view-button', + 'gear-button', 'directory-tree', 'file-list'])); +}; + +/** + * Tests the tab focus behavior of Save File Dialog (Downloads). + */ +testcase.tabindexSaveFileDialogDownloads = function() { + testPromise(tabindexFocus( + { + type: 'saveFile', + suggestedName: 'hoge.txt' // Prevent showing a override prompt + }, + 'downloads', BASIC_LOCAL_ENTRY_SET, false, + '#ok-button:not([disabled])', + ['ok-button', 'cancel-button', 'search-button', 'view-button', + 'gear-button', 'directory-tree', 'file-list', 'new-folder-button', + 'filename-input-textbox'])); +}; + +/** + * Tests the tab focus behavior of Save File Dialog (Drive). + */ +testcase.tabindexSaveFileDialogDrive = function() { + testPromise(tabindexFocus( + { + type: 'saveFile', + suggestedName: 'hoge.txt' // Prevent showing a override prompt + }, + 'drive', BASIC_DRIVE_ENTRY_SET, false, + '#ok-button:not([disabled])', + ['ok-button', 'cancel-button', 'search-button', 'view-button', + 'gear-button', 'directory-tree', 'file-list', 'new-folder-button', + 'filename-input-textbox'])); };
diff --git a/ui/file_manager/integration_tests/file_manager_test_manifest.json b/ui/file_manager/integration_tests/file_manager_test_manifest.json index 31cd27b1..d162f66 100644 --- a/ui/file_manager/integration_tests/file_manager_test_manifest.json +++ b/ui/file_manager/integration_tests/file_manager_test_manifest.json
@@ -36,7 +36,7 @@ ] }, "permissions": [ - "fileSystem", + {"fileSystem": ["write"]}, "tabs", "commandLinePrivate", "chrome-extension://oobinhbdbiehknkpbpejbbpdbkdjmoco/*",
diff --git a/ui/gfx/display.h b/ui/gfx/display.h index 6f29d42..adc11ad 100644 --- a/ui/gfx/display.h +++ b/ui/gfx/display.h
@@ -30,6 +30,18 @@ ROTATE_270, }; + // The display rotation can have multiple causes for change. A user can set a + // preference. On devices with accelerometers, they can change the rotation. + // RotationSource allows for the tracking of a Rotation per source of the + // change. ROTATION_SOURCE_ACTIVE is the current rotation of the display. + // Rotation changes not due to an accelerometer, nor the user, are to use this + // source directly. + enum RotationSource { + ROTATION_SOURCE_ACCELEROMETER = 0, + ROTATION_SOURCE_ACTIVE, + ROTATION_SOURCE_USER, + }; + // Touch support for the display. enum TouchSupport { TOUCH_SUPPORT_UNKNOWN,
diff --git a/ui/gfx/range/range_f.cc b/ui/gfx/range/range_f.cc index 8af832d..46f853d 100644 --- a/ui/gfx/range/range_f.cc +++ b/ui/gfx/range/range_f.cc
@@ -7,7 +7,6 @@ #include <algorithm> #include <limits> -#include "base/float_util.h" #include "base/format_macros.h" #include "base/strings/stringprintf.h"
diff --git a/ui/gfx/screen_mac.mm b/ui/gfx/screen_mac.mm index b5fdeb9..3039124e 100644 --- a/ui/gfx/screen_mac.mm +++ b/ui/gfx/screen_mac.mm
@@ -75,6 +75,10 @@ scale = [screen backingScaleFactor]; else scale = [screen userSpaceScaleFactor]; + + if (gfx::Display::HasForceDeviceScaleFactor()) + scale = gfx::Display::GetForcedDeviceScaleFactor(); + display.set_device_scale_factor(scale); // CGDisplayRotation returns a double. Display::SetRotationAsDegree will // handle the unexpected situations were the angle is not a multiple of 90.
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index 85a7da9..efee0ee 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -200,8 +200,7 @@ libs = [ "dwmapi.lib" ] ldflags = [ "/DELAYLOAD:dwmapi.dll" ] - # TODO(brettw) bug 477104: this should be data_deps" - deps += [ + data_deps = [ "//third_party/angle:libEGL", "//third_party/angle:libGLESv2", "//third_party/mesa:osmesa",
diff --git a/ui/gl/gl_bindings_skia_in_process.cc b/ui/gl/gl_bindings_skia_in_process.cc index 25dd698e..fe449542 100644 --- a/ui/gl/gl_bindings_skia_in_process.cc +++ b/ui/gl/gl_bindings_skia_in_process.cc
@@ -64,11 +64,19 @@ glBindVertexArrayOES(array); } +GLvoid StubGLBlendBarrier() { + glBlendBarrierKHR(); +} + GLvoid StubGLBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { glBlendColor(red, green, blue, alpha); } +GLvoid StubGLBlendEquation(GLenum mode) { + glBlendEquation(mode); +} + GLvoid StubGLBlendFunc(GLenum sfactor, GLenum dfactor) { glBlendFunc(sfactor, dfactor); } @@ -669,7 +677,9 @@ functions->fBindFragDataLocation = StubGLBindFragDataLocation; functions->fBindTexture = StubGLBindTexture; functions->fBindVertexArray = StubGLBindVertexArray; + functions->fBlendBarrier = StubGLBlendBarrier; functions->fBlendColor = StubGLBlendColor; + functions->fBlendEquation = StubGLBlendEquation; functions->fBlendFunc = StubGLBlendFunc; functions->fBufferData = StubGLBufferData; functions->fBufferSubData = StubGLBufferSubData;
diff --git a/ui/gl/gl_context_stub_with_extensions.cc b/ui/gl/gl_context_stub_with_extensions.cc index 1065df78..855eaa2 100644 --- a/ui/gl/gl_context_stub_with_extensions.cc +++ b/ui/gl/gl_context_stub_with_extensions.cc
@@ -27,4 +27,10 @@ return version_str_; } +bool GLContextStubWithExtensions::WasAllocatedUsingRobustnessExtension() { + return HasExtension("GL_ARB_robustness") || + HasExtension("GL_KHR_robustness") || + HasExtension("GL_EXT_robustness"); +} + } // namespace gfx
diff --git a/ui/gl/gl_context_stub_with_extensions.h b/ui/gl/gl_context_stub_with_extensions.h index 190e03e..d9da9d5 100644 --- a/ui/gl/gl_context_stub_with_extensions.h +++ b/ui/gl/gl_context_stub_with_extensions.h
@@ -19,6 +19,7 @@ void AddExtensionsString(const char* extensions); void SetGLVersionString(const char* version_str); + bool WasAllocatedUsingRobustnessExtension() override; protected: std::string GetGLVersion() override;
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc index ba7b02b..7dac123 100644 --- a/ui/gl/gl_surface_ozone.cc +++ b/ui/gl/gl_surface_ozone.cc
@@ -123,6 +123,7 @@ has_implicit_external_sync_( HasEGLExtension("EGL_ARM_implicit_external_sync")), last_swap_buffers_result_(true), + swap_buffers_pending_(false), weak_factory_(this) { unsubmitted_frames_.push_back(new PendingFrame()); } @@ -180,16 +181,23 @@ return true; } bool SwapBuffersAsync(const SwapCompletionCallback& callback) override { + // If last swap failed, don't try to schedule new ones. + if (!last_swap_buffers_result_) + return false; + glFlush(); + + base::Closure surface_swap_callback = + base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted, + weak_factory_.GetWeakPtr(), callback); + + PendingFrame* frame = unsubmitted_frames_.back(); + frame->callback = surface_swap_callback; + unsubmitted_frames_.push_back(new PendingFrame()); + // TODO: the following should be replaced by a per surface flush as it gets // implemented in GL drivers. if (has_implicit_external_sync_) { - // If last swap failed, don't try to schedule new ones. - if (!last_swap_buffers_result_) { - last_swap_buffers_result_ = true; - return false; - } - EGLSyncKHR fence = InsertFence(); if (!fence) return false; @@ -197,22 +205,20 @@ base::Closure fence_wait_task = base::Bind(&WaitForFence, GetDisplay(), fence); - PendingFrame* frame = unsubmitted_frames_.back(); - frame->callback = callback; base::Closure fence_retired_callback = base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired, weak_factory_.GetWeakPtr(), fence, frame); base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task, fence_retired_callback, false); - unsubmitted_frames_.push_back(new PendingFrame()); return true; } else if (ozone_surface_->IsUniversalDisplayLinkDevice()) { glFinish(); } - unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_); - unsubmitted_frames_.back()->overlays.clear(); - return ozone_surface_->OnSwapBuffersAsync(callback); + + frame->ready = true; + SubmitFrame(); + return last_swap_buffers_result_; } bool PostSubBufferAsync(int x, int y, @@ -265,13 +271,17 @@ Destroy(); // EGL surface must be destroyed before SurfaceOzone } - void SubmitFrames() { - while (!unsubmitted_frames_.empty() && unsubmitted_frames_.front()->ready) { - PendingFrame* frame = unsubmitted_frames_.front(); + void SubmitFrame() { + DCHECK(!unsubmitted_frames_.empty()); + + if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) { + scoped_ptr<PendingFrame> frame(unsubmitted_frames_.front()); + unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin()); + swap_buffers_pending_ = true; + last_swap_buffers_result_ = - last_swap_buffers_result_ && frame->ScheduleOverlayPlanes(widget_) && + frame->ScheduleOverlayPlanes(widget_) && ozone_surface_->OnSwapBuffersAsync(frame->callback); - unsubmitted_frames_.erase(unsubmitted_frames_.begin()); } } @@ -285,7 +295,14 @@ void FenceRetired(EGLSyncKHR fence, PendingFrame* frame) { eglDestroySyncKHR(GetDisplay(), fence); frame->ready = true; - SubmitFrames(); + SubmitFrame(); + } + + void SwapCompleted(const SwapCompletionCallback& callback) { + callback.Run(); + swap_buffers_pending_ = false; + + SubmitFrame(); } // The native surface. Deleting this is allowed to free the EGLNativeWindow. @@ -295,6 +312,7 @@ ScopedVector<PendingFrame> unsubmitted_frames_; bool has_implicit_external_sync_; bool last_swap_buffers_result_; + bool swap_buffers_pending_; base::WeakPtrFactory<GLSurfaceOzoneSurfaceless> weak_factory_;
diff --git a/ui/gl/gl_version_info.h b/ui/gl/gl_version_info.h index 1bfca20..561a94fc 100644 --- a/ui/gl/gl_version_info.h +++ b/ui/gl/gl_version_info.h
@@ -24,6 +24,11 @@ (major_version == major && minor_version >= minor)); } + bool IsLowerThanGL(unsigned major, unsigned minor) const { + return !is_es && (major_version < major || + (major_version == major && minor_version < minor)); + } + bool IsAtLeastGLES(unsigned major, unsigned minor) const { return is_es && (major_version > major || (major_version == major && minor_version >= minor));
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc index 5aa44bb..bdb4e42 100644 --- a/ui/keyboard/keyboard_controller.cc +++ b/ui/keyboard/keyboard_controller.cc
@@ -115,7 +115,7 @@ // KeyboardController. class CallbackAnimationObserver : public ui::LayerAnimationObserver { public: - CallbackAnimationObserver(ui::LayerAnimator* animator, + CallbackAnimationObserver(const scoped_refptr<ui::LayerAnimator>& animator, base::Callback<void(void)> callback); ~CallbackAnimationObserver() override; @@ -125,14 +125,15 @@ void OnLayerAnimationAborted(ui::LayerAnimationSequence* seq) override; void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) override {} - ui::LayerAnimator* animator_; + scoped_refptr<ui::LayerAnimator> animator_; base::Callback<void(void)> callback_; DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver); }; CallbackAnimationObserver::CallbackAnimationObserver( - ui::LayerAnimator* animator, base::Callback<void(void)> callback) + const scoped_refptr<ui::LayerAnimator>& animator, + base::Callback<void(void)> callback) : animator_(animator), callback_(callback) { }
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js index 958d72fc..777fab4 100644 --- a/ui/login/display_manager.js +++ b/ui/login/display_manager.js
@@ -63,6 +63,7 @@ SUPERVISED_USER_CREATION_FLOW: 4, SAML_PASSWORD_CONFIRM: 5, CONSUMER_MANAGEMENT_ENROLLMENT: 6, + PASSWORD_CHANGED: 7, }; /* Possible UI states of the error screen. */ @@ -1006,9 +1007,11 @@ /** * Shows password changed screen that offers migration. * @param {boolean} showError Whether to show the incorrect password error. + * @param {string} email What user does reauth. Being used for display in the + * new UI. */ - DisplayManager.showPasswordChangedScreen = function(showError) { - login.PasswordChangedScreen.show(showError); + DisplayManager.showPasswordChangedScreen = function(showError, email) { + login.PasswordChangedScreen.show(showError, email); }; /** @@ -1052,7 +1055,7 @@ * @param {string} assetId The device asset ID. */ DisplayManager.setEnterpriseInfo = function(messageText, assetId) { - $('newgaia-offline-login').enterpriseInfo = messageText; + $('offline-gaia').enterpriseInfo = messageText; $('enterprise-info-message').textContent = messageText; if (messageText) { $('enterprise-info').hidden = false;
diff --git a/ui/message_center/message_center_impl.cc b/ui/message_center/message_center_impl.cc index cb2f812..af3d3140 100644 --- a/ui/message_center/message_center_impl.cc +++ b/ui/message_center/message_center_impl.cc
@@ -58,20 +58,28 @@ scoped_ptr<Notification> PassNotification(); Notification* notification() const { return notification_.get(); } + // Returns the post-update ID. It means: + // - ADD event: ID of the notification to be added. + // - UPDATE event: ID of the notification after the change. If the change + // doesn't update its ID, this value is same as |notification_list_id|. + // - DELETE event: ID of the notification to be deleted. const std::string& id() const { return id_; } ChangeType type() const { return type_; } bool by_user() const { return by_user_; } void set_by_user(bool by_user) { by_user_ = by_user; } + // Returns the ID which is used in the notification list. In other word, it + // means the ID before the change. const std::string& notification_list_id() const { return notification_list_id_; } - void set_notification_list_id(const std::string& id) { - notification_list_id_ = id; + void set_type(const ChangeType new_type) { + type_ = new_type; } + void ReplaceNotification(scoped_ptr<Notification> new_notification); private: - const ChangeType type_; - const std::string id_; + ChangeType type_; + std::string id_; std::string notification_list_id_; bool by_user_; scoped_ptr<Notification> notification_; @@ -107,8 +115,6 @@ Notification* GetLatestNotification(const std::string& id) const; private: - void Replace(const std::string& id, scoped_ptr<Change> change); - ScopedVector<Change> changes_; DISALLOW_COPY_AND_ASSIGN(ChangeQueue); @@ -131,12 +137,13 @@ const std::string& id, scoped_ptr<Notification> notification) : type_(type), - id_(id), notification_list_id_(id), by_user_(false), notification_(notification.Pass()) { DCHECK(!id.empty()); DCHECK(type != CHANGE_TYPE_DELETE || notification_.get() == NULL); + + id_ = notification_ ? notification_->id() : notification_list_id_; } ChangeQueue::Change::~Change() {} @@ -145,6 +152,12 @@ return notification_.Pass(); } +void ChangeQueue::Change::ReplaceNotification( + scoped_ptr<Notification> new_notification) { + id_ = new_notification ? new_notification->id() : notification_list_id_; + notification_.swap(new_notification); +} + //////////////////////////////////////////////////////////////////////////////// // ChangeQueue @@ -180,24 +193,88 @@ void ChangeQueue::AddNotification(scoped_ptr<Notification> notification) { std::string id = notification->id(); - - scoped_ptr<Change> change( + changes_.push_back( new Change(CHANGE_TYPE_ADD, id, notification.Pass())); - Replace(id, change.Pass()); } void ChangeQueue::UpdateNotification(const std::string& old_id, scoped_ptr<Notification> notification) { - std::string new_id = notification->id(); - scoped_ptr<Change> change( - new Change(CHANGE_TYPE_UPDATE, new_id, notification.Pass())); - Replace(old_id, change.Pass()); + ScopedVector<Change>::reverse_iterator iter = + std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(old_id)); + if (iter == changes_.rend()) { + changes_.push_back( + new Change(CHANGE_TYPE_UPDATE, old_id, notification.Pass())); + return; + } + + Change* change = *iter; + switch (change->type()) { + case CHANGE_TYPE_ADD: { + std::string id = notification->id(); + // Needs to add the change at the last, because if this change updates + // its ID, some previous changes may affect new ID. + // (eg. Add A, Update B->C, and This update A->B). + changes_.erase(--(iter.base())); + changes_.push_back( + new Change(CHANGE_TYPE_ADD, id, notification.Pass())); + break; + } + case CHANGE_TYPE_UPDATE: + if (notification->id() == old_id) { + // Safe to place the change at the previous place. + change->ReplaceNotification(notification.Pass()); + } else if (change->id() == change->notification_list_id()) { + std::string id = notification->id(); + // Safe to place the change at the last. + changes_.erase(--(iter.base())); + changes_.push_back(new Change( + CHANGE_TYPE_ADD, id, notification.Pass())); + } else { + // Complex case: gives up to optimize. + changes_.push_back( + new Change(CHANGE_TYPE_UPDATE, old_id, notification.Pass())); + } + break; + case CHANGE_TYPE_DELETE: + // DELETE -> UPDATE. Something is wrong. Treats the UPDATE as ADD. + changes_.push_back( + new Change(CHANGE_TYPE_ADD, old_id, notification.Pass())); + break; + default: + NOTREACHED(); + } } void ChangeQueue::EraseNotification(const std::string& id, bool by_user) { - scoped_ptr<Change> change(new Change(CHANGE_TYPE_DELETE, id, nullptr)); - change->set_by_user(by_user); - Replace(id, change.Pass()); + ScopedVector<Change>::reverse_iterator iter = + std::find_if(changes_.rbegin(), changes_.rend(), ChangeFinder(id)); + if (iter == changes_.rend()) { + scoped_ptr<Change> change(new Change(CHANGE_TYPE_DELETE, id, nullptr)); + change->set_by_user(by_user); + changes_.push_back(change.release()); + return; + } + + Change* change = *iter; + switch (change->type()) { + case CHANGE_TYPE_ADD: + // ADD -> DELETE. Just removes both. + changes_.erase(--(iter.base())); + break; + case CHANGE_TYPE_UPDATE: + // UPDATE -> DELETE. Changes the previous UPDATE to DELETE. + change->set_type(CHANGE_TYPE_DELETE); + change->set_by_user(by_user); + change->ReplaceNotification(nullptr); + break; + case CHANGE_TYPE_DELETE: + // DELETE -> DELETE. Something is wrong. Combines them with overriding + // the |by_user| flag. + change->set_by_user(!change->by_user() && by_user); + break; + default: + NOTREACHED(); + } } bool ChangeQueue::Has(const std::string& id) const { @@ -215,21 +292,6 @@ return (*iter)->notification(); } -void ChangeQueue::Replace(const std::string& changed_id, - scoped_ptr<Change> new_change) { - ScopedVector<Change>::iterator iter = - std::find_if(changes_.begin(), changes_.end(), ChangeFinder(changed_id)); - if (iter != changes_.end()) { - Change* old_change = *iter; - new_change->set_notification_list_id(old_change->notification_list_id()); - changes_.erase(iter); - } else { - new_change->set_notification_list_id(changed_id); - } - - changes_.push_back(new_change.release()); -} - //////////////////////////////////////////////////////////////////////////////// // PopupTimer
diff --git a/ui/message_center/message_center_impl_unittest.cc b/ui/message_center/message_center_impl_unittest.cc index b056d8e..ccf8633 100644 --- a/ui/message_center/message_center_impl_unittest.cc +++ b/ui/message_center/message_center_impl_unittest.cc
@@ -635,7 +635,7 @@ } TEST_F(MessageCenterImplTest, ComplexQueueing) { - std::string ids[5] = {"0", "1", "2", "3", "4p"}; + std::string ids[6] = {"0", "1", "2", "3", "4p", "5"}; NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); scoped_ptr<Notification> notification; @@ -648,7 +648,7 @@ for (i = 0; i < 3; i++) { EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[i])); } - for (; i < 5; i++) { + for (; i < 6; i++) { EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[i])); } @@ -663,14 +663,17 @@ notification.reset(CreateSimpleNotification(ids[3])); message_center()->UpdateNotification(ids[1], notification.Pass()); - notification.reset(CreateSimpleNotification(ids[4])); + // Change the ID: "4p" -> "5", "5" -> "1", "1" -> "4p". They shouldn't + // override the previous change ("1" -> "3") nor the next one ("3" -> "5"). + notification.reset(CreateSimpleNotification(ids[5])); message_center()->UpdateNotification(ids[4], notification.Pass()); - + notification.reset(CreateSimpleNotification(ids[1])); + message_center()->UpdateNotification(ids[5], notification.Pass()); notification.reset(CreateNotification(ids[4], NOTIFICATION_TYPE_PROGRESS)); - message_center()->UpdateNotification(ids[4], notification.Pass()); + message_center()->UpdateNotification(ids[1], notification.Pass()); - // This should update notification "3" to a new ID after we go TRANSIENT. - notification.reset(CreateSimpleNotification("New id")); + // This should update notification "3" to "5" after we go TRANSIENT. + notification.reset(CreateSimpleNotification(ids[5])); message_center()->UpdateNotification(ids[3], notification.Pass()); // This should create a new "3", that doesn't overwrite the update to 3 @@ -684,6 +687,7 @@ EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[2])); EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[3])); EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[4])); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[5])); EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 4u); message_center()->SetVisibility(VISIBILITY_TRANSIENT); @@ -692,7 +696,156 @@ EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[2])); EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[3])); EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[4])); - EXPECT_TRUE(message_center()->FindVisibleNotificationById("New id")); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[5])); + EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 5u); +} + +TEST_F(MessageCenterImplTest, UpdateWhileQueueing) { + std::string ids[11] = + {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10p"}; + NotifierId notifier_id1(NotifierId::APPLICATION, "app1"); + + scoped_ptr<Notification> notification; + // Add some notifications + int i = 0; + for (; i < 6; i++) { + notification.reset(CreateSimpleNotification(ids[i])); + notification->set_title(base::ASCIIToUTF16("ORIGINAL TITLE")); + message_center()->AddNotification(notification.Pass()); + } + for (i = 0; i < 6; i++) { + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[i])); + } + for (; i < 8; i++) { + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[i])); + } + + notification.reset(CreateNotification(ids[10], NOTIFICATION_TYPE_PROGRESS)); + notification->set_progress(10); + message_center()->AddNotification(notification.Pass()); + + // Now start queueing. + message_center()->SetVisibility(VISIBILITY_MESSAGE_CENTER); + + // Notification 0: (Exists) -> Removed + message_center()->RemoveNotification(ids[0], false); + + // Notification 1: (Exists) -> Removed (by user) + message_center()->RemoveNotification(ids[1], true); // removed immediately + + // Notification 2: (Exists) -> Removed -> Added + message_center()->RemoveNotification(ids[2], false); + notification.reset(CreateSimpleNotification(ids[2])); + notification->set_title(base::ASCIIToUTF16("NEW TITLE 2")); + message_center()->UpdateNotification(ids[2], notification.Pass()); + + // Notification 3: (Exists) -> Removed -> Updated + message_center()->RemoveNotification(ids[3], false); + notification.reset(CreateSimpleNotification(ids[3])); + notification->set_title(base::ASCIIToUTF16("NEW TITLE 3")); + message_center()->UpdateNotification(ids[3], notification.Pass()); + + // Notification 4: (Exists) -> Removed -> Added -> Removed + message_center()->RemoveNotification(ids[4], false); + notification.reset(CreateSimpleNotification(ids[4])); + message_center()->AddNotification(notification.Pass()); + message_center()->RemoveNotification(ids[4], false); + + // Notification 5: (Exists) -> Updated + notification.reset(CreateSimpleNotification(ids[5])); + notification->set_title(base::ASCIIToUTF16("NEW TITLE 5")); + message_center()->UpdateNotification(ids[5], notification.Pass()); + + // Notification 6: Updated + notification.reset(CreateSimpleNotification(ids[6])); + message_center()->UpdateNotification(ids[6], notification.Pass()); + + // Notification 7: Updated -> Removed + notification.reset(CreateSimpleNotification(ids[7])); + message_center()->UpdateNotification(ids[7], notification.Pass()); + message_center()->RemoveNotification(ids[7], false); + + // Notification 8: Added -> Updated + notification.reset(CreateSimpleNotification(ids[8])); + notification->set_title(base::ASCIIToUTF16("UPDATING 8-1")); + message_center()->AddNotification(notification.Pass()); + notification.reset(CreateSimpleNotification(ids[8])); + notification->set_title(base::ASCIIToUTF16("NEW TITLE 8")); + message_center()->UpdateNotification(ids[8], notification.Pass()); + + // Notification 9: Added -> Updated -> Removed + notification.reset(CreateSimpleNotification(ids[9])); + message_center()->AddNotification(notification.Pass()); + notification.reset(CreateSimpleNotification(ids[9])); + message_center()->UpdateNotification(ids[9], notification.Pass()); + message_center()->RemoveNotification(ids[9], false); + + // Notification 10 (TYPE_PROGRESS): Updated -> Removed -> Added -> Updated + // Step 1) Progress is updated immediately before removed. + notification.reset(CreateNotification(ids[10], NOTIFICATION_TYPE_PROGRESS)); + notification->set_progress(20); + message_center()->UpdateNotification(ids[10], notification.Pass()); + EXPECT_EQ(20, + message_center()->FindVisibleNotificationById(ids[10])->progress()); + message_center()->RemoveNotification(ids[10], false); + // Step 2) Progress isn't updated after removed. + notification.reset(CreateSimpleNotification(ids[10])); + message_center()->AddNotification(notification.Pass()); + EXPECT_EQ(20, + message_center()->FindVisibleNotificationById(ids[10])->progress()); + notification.reset(CreateSimpleNotification(ids[10])); + notification->set_progress(40); + message_center()->UpdateNotification(ids[10], notification.Pass()); + EXPECT_EQ(20, + message_center()->FindVisibleNotificationById(ids[10])->progress()); + + // All changes except the notification 1 and 10 are not refrected. + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[0])); + EXPECT_EQ(base::ASCIIToUTF16("ORIGINAL TITLE"), + message_center()->FindVisibleNotificationById(ids[0])->title()); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[1])); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[2])); + EXPECT_EQ(base::ASCIIToUTF16("ORIGINAL TITLE"), + message_center()->FindVisibleNotificationById(ids[2])->title()); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[3])); + EXPECT_EQ(base::ASCIIToUTF16("ORIGINAL TITLE"), + message_center()->FindVisibleNotificationById(ids[3])->title()); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[4])); + EXPECT_EQ(base::ASCIIToUTF16("ORIGINAL TITLE"), + message_center()->FindVisibleNotificationById(ids[4])->title()); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[5])); + EXPECT_EQ(base::ASCIIToUTF16("ORIGINAL TITLE"), + message_center()->FindVisibleNotificationById(ids[5])->title()); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[6])); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[7])); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[8])); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[9])); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[10])); + EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 6u); + + message_center()->SetVisibility(VISIBILITY_TRANSIENT); + + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[0])); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[1])); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[2])); + EXPECT_EQ(base::ASCIIToUTF16("NEW TITLE 2"), + message_center()->FindVisibleNotificationById(ids[2])->title()); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[3])); + EXPECT_EQ(base::ASCIIToUTF16("NEW TITLE 3"), + message_center()->FindVisibleNotificationById(ids[3])->title()); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[4])); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[5])); + EXPECT_EQ(base::ASCIIToUTF16("NEW TITLE 5"), + message_center()->FindVisibleNotificationById(ids[5])->title()); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[6])); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[7])); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[8])); + EXPECT_EQ(base::ASCIIToUTF16("NEW TITLE 8"), + message_center()->FindVisibleNotificationById(ids[8])->title()); + EXPECT_FALSE(message_center()->FindVisibleNotificationById(ids[9])); + EXPECT_TRUE(message_center()->FindVisibleNotificationById(ids[10])); + EXPECT_EQ(40, + message_center()->FindVisibleNotificationById(ids[10])->progress()); EXPECT_EQ(message_center()->GetVisibleNotifications().size(), 5u); }
diff --git a/ui/mojo/events/BUILD.gn b/ui/mojo/events/BUILD.gn new file mode 100644 index 0000000..679509c --- /dev/null +++ b/ui/mojo/events/BUILD.gn
@@ -0,0 +1,18 @@ +# 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. + +import("//build/module_args/mojo.gni") +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "input_event_constants.mojom", + "input_events.mojom", + "input_key_codes.mojom", + ] + + deps = [ + "//ui/mojo/geometry:interfaces", + ] +}
diff --git a/third_party/mojo_services/src/input_events/public/interfaces/input_event_constants.mojom b/ui/mojo/events/input_event_constants.mojom similarity index 100% rename from third_party/mojo_services/src/input_events/public/interfaces/input_event_constants.mojom rename to ui/mojo/events/input_event_constants.mojom
diff --git a/ui/mojo/events/input_events.mojom b/ui/mojo/events/input_events.mojom new file mode 100644 index 0000000..f7d56b5 --- /dev/null +++ b/ui/mojo/events/input_events.mojom
@@ -0,0 +1,78 @@ +// 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 mojo; + +import "ui/mojo/events/input_event_constants.mojom"; +import "ui/mojo/events/input_key_codes.mojom"; +import "ui/mojo/geometry/geometry.mojom"; + +struct KeyData { + // The chromium event key code; these values are from the ui/ KeyCode enum, + // which has the fun property of being neither consistently the Windows key + // code, nor the X11 keycodes. (This value is consistent across platforms + // for basic ASCII characters; it will differ for modifiers. We don't define + // this as a mojo enum because mojom doesn't appear to have a platform + // dependent preprocessor yet.) + // + // TODO(erg): Remove this, and declare Win32 keycodes correct by fiat. We can + // not do this until we remove ui::Event usage from within mojo. + int32 key_code; + + // Whether this is a character event, and the character value if it is. Note + // that this is different than |text|, which holds a value even when there + // isn't actually a character to insert. (For example, |text| will be set and + // have a value on backspace, and |character| won't.) + bool is_char; + uint16 character; + + // The Win32 key code. Because of the web, this is the closest thing that we + // have to a cross platform key state. + KeyboardCode windows_key_code; + + // The platform specific key code. + // + // TODO(erg): This exists only for NPAPI support, pepper USB keyboard support + // and IME on android support. Theoretically, we should be able to remove this + // in the medium to long term. + int32 native_key_code; + + // The text generated by this keystroke. Corresponds to + // blink::WebKeyboardEvent::text. + uint16 text; + + // Like |text|, but unmodified by concurrently held modifier keys (except + // shift). Corresponds to blink::WebKeyboardEvent::unmodifiedText. + uint16 unmodified_text; +}; + +struct PointerData { + int32 pointer_id; + PointerKind kind; + // |x| and |y| are in the coordinate system of the View. + float x; + float y; + // |screen_x| and |screen_y| are in screen coordinates. + float screen_x; + float screen_y; + float pressure; + float radius_major; + float radius_minor; + float orientation; + // Used for devices that support wheels. Ranges from -1 to 1. + float horizontal_wheel; + float vertical_wheel; +}; + +struct Event { + // TODO(sky): rename to type. + EventType action; + // TODO(sky): parts of this should move to PointerData. + EventFlags flags; + // Time the event was delivered. The time is in milliseconds and corresponds + // to the uptime of the machine. + int64 time_stamp; + KeyData? key_data; + PointerData? pointer_data; +};
diff --git a/third_party/mojo_services/src/input_events/public/interfaces/input_key_codes.mojom b/ui/mojo/events/input_key_codes.mojom similarity index 100% rename from third_party/mojo_services/src/input_events/public/interfaces/input_key_codes.mojom rename to ui/mojo/events/input_key_codes.mojom
diff --git a/ui/mojo/geometry/BUILD.gn b/ui/mojo/geometry/BUILD.gn new file mode 100644 index 0000000..1d7d4d5 --- /dev/null +++ b/ui/mojo/geometry/BUILD.gn
@@ -0,0 +1,17 @@ +# 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. + +import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni") + +mojom("interfaces") { + sources = [ + "geometry.mojom", + ] +} + +source_set("util") { + sources = [ + "geometry_util.h", + ] +}
diff --git a/third_party/mojo_services/src/geometry/public/interfaces/geometry.mojom b/ui/mojo/geometry/geometry.mojom similarity index 100% rename from third_party/mojo_services/src/geometry/public/interfaces/geometry.mojom rename to ui/mojo/geometry/geometry.mojom
diff --git a/ui/mojo/geometry/geometry_util.h b/ui/mojo/geometry/geometry_util.h new file mode 100644 index 0000000..2606be83 --- /dev/null +++ b/ui/mojo/geometry/geometry_util.h
@@ -0,0 +1,39 @@ +// 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 UI_MOJO_GEOMETRY_GEOMETRY_UTIL_H_ +#define UI_MOJO_GEOMETRY_GEOMETRY_UTIL_H_ + +#include "ui/mojo/geometry/geometry.mojom.h" + +namespace mojo { + +inline bool operator==(const Rect& lhs, const Rect& rhs) { + return lhs.x == rhs.x && lhs.y == rhs.y && lhs.width == rhs.width && + lhs.height == lhs.height; +} + +inline bool operator!=(const Rect& lhs, const Rect& rhs) { + return !(lhs == rhs); +} + +inline bool operator==(const Size& lhs, const Size& rhs) { + return lhs.width == rhs.width && lhs.height == rhs.height; +} + +inline bool operator!=(const Size& lhs, const Size& rhs) { + return !(lhs == rhs); +} + +inline bool operator==(const Point& lhs, const Point& rhs) { + return lhs.x == rhs.x && lhs.y == rhs.y; +} + +inline bool operator!=(const Point& lhs, const Point& rhs) { + return !(lhs == rhs); +} + +} + +#endif // UI_MOJO_GEOMETRY_GEOMETRY_UTIL_H_
diff --git a/ui/ozone/common/gpu/ozone_gpu_messages.h b/ui/ozone/common/gpu/ozone_gpu_messages.h index 14d2a107..bc9a465d 100644 --- a/ui/ozone/common/gpu/ozone_gpu_messages.h +++ b/ui/ozone/common/gpu/ozone_gpu_messages.h
@@ -10,6 +10,7 @@ #include "base/file_descriptor_posix.h" #include "ipc/ipc_message_macros.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/display/types/display_constants.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/ipc/gfx_param_traits.h" @@ -25,6 +26,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(ui::DisplayConnectionType, ui::DISPLAY_CONNECTION_TYPE_LAST) +IPC_ENUM_TRAITS_MAX_VALUE(ui::HDCPState, ui::HDCP_STATE_LAST) + IPC_STRUCT_TRAITS_BEGIN(ui::DisplayMode_Params) IPC_STRUCT_TRAITS_MEMBER(size) IPC_STRUCT_TRAITS_MEMBER(is_interlaced) @@ -102,6 +105,12 @@ // Let other entity control the display IPC_MESSAGE_CONTROL0(OzoneGpuMsg_RelinquishDisplayControl) +IPC_MESSAGE_CONTROL1(OzoneGpuMsg_GetHDCPState, int64_t /* display_id */) + +IPC_MESSAGE_CONTROL2(OzoneGpuMsg_SetHDCPState, + int64_t /* display_id */, + ui::HDCPState /* state */) + //------------------------------------------------------------------------------ // Browser Messages // These messages are from the GPU to the browser process. @@ -113,3 +122,14 @@ IPC_MESSAGE_CONTROL2(OzoneHostMsg_DisplayConfigured, int64_t /* display_id */, bool /* status */) + +// Response for OzoneGpuMsg_GetHDCPState. +IPC_MESSAGE_CONTROL3(OzoneHostMsg_HDCPStateReceived, + int64_t /* display_id */, + bool /* success */, + ui::HDCPState /* state */) + +// Response for OzoneGpuMsg_SetHDCPState. +IPC_MESSAGE_CONTROL2(OzoneHostMsg_HDCPStateUpdated, + int64_t /* display_id */, + bool /* success */)
diff --git a/ui/ozone/common/native_display_delegate_ozone.cc b/ui/ozone/common/native_display_delegate_ozone.cc index 0aa8e33..d85b641a 100644 --- a/ui/ozone/common/native_display_delegate_ozone.cc +++ b/ui/ozone/common/native_display_delegate_ozone.cc
@@ -76,18 +76,6 @@ NOTIMPLEMENTED(); } -bool NativeDisplayDelegateOzone::GetHDCPState(const DisplaySnapshot& output, - HDCPState* state) { - NOTIMPLEMENTED(); - return false; -} - -bool NativeDisplayDelegateOzone::SetHDCPState(const DisplaySnapshot& output, - HDCPState state) { - NOTIMPLEMENTED(); - return false; -} - void NativeDisplayDelegateOzone::GetHDCPState( const ui::DisplaySnapshot& output, const GetHDCPStateCallback& callback) {
diff --git a/ui/ozone/common/native_display_delegate_ozone.h b/ui/ozone/common/native_display_delegate_ozone.h index a9e17dd..74c87853 100644 --- a/ui/ozone/common/native_display_delegate_ozone.h +++ b/ui/ozone/common/native_display_delegate_ozone.h
@@ -33,8 +33,6 @@ const gfx::Point& origin, const ConfigureCallback& callback) override; void CreateFrameBuffer(const gfx::Size& size) override; - bool GetHDCPState(const DisplaySnapshot& output, HDCPState* state) override; - bool SetHDCPState(const DisplaySnapshot& output, HDCPState state) override; void GetHDCPState(const ui::DisplaySnapshot& output, const GetHDCPStateCallback& callback) override; void SetHDCPState(const ui::DisplaySnapshot& output,
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn index 9cc58f8..007a318 100644 --- a/ui/ozone/platform/drm/BUILD.gn +++ b/ui/ozone/platform/drm/BUILD.gn
@@ -59,6 +59,8 @@ "gpu/hardware_display_plane_manager_legacy.h", "gpu/overlay_plane.cc", "gpu/overlay_plane.h", + "gpu/page_flip_request.cc", + "gpu/page_flip_request.h", "gpu/scanout_buffer.h", "gpu/scoped_drm_types.cc", "gpu/scoped_drm_types.h",
diff --git a/ui/ozone/platform/drm/drm.gypi b/ui/ozone/platform/drm/drm.gypi index 6c16544..8fdc41f 100644 --- a/ui/ozone/platform/drm/drm.gypi +++ b/ui/ozone/platform/drm/drm.gypi
@@ -81,6 +81,8 @@ 'gpu/hardware_display_plane_manager_legacy.h', 'gpu/overlay_plane.cc', 'gpu/overlay_plane.h', + 'gpu/page_flip_request.cc', + 'gpu/page_flip_request.h', 'gpu/scoped_drm_types.cc', 'gpu/scoped_drm_types.h', 'gpu/screen_manager.cc',
diff --git a/ui/ozone/platform/drm/gpu/crtc_controller.cc b/ui/ozone/platform/drm/gpu/crtc_controller.cc index ef49295..6c912c647 100644 --- a/ui/ozone/platform/drm/gpu/crtc_controller.cc +++ b/ui/ozone/platform/drm/gpu/crtc_controller.cc
@@ -7,7 +7,7 @@ #include "base/logging.h" #include "base/time/time.h" #include "ui/ozone/platform/drm/gpu/drm_device.h" -#include "ui/ozone/platform/drm/gpu/page_flip_observer.h" +#include "ui/ozone/platform/drm/gpu/page_flip_request.h" #include "ui/ozone/platform/drm/gpu/scanout_buffer.h" namespace ui { @@ -20,7 +20,6 @@ connector_(connector), saved_crtc_(drm->GetCrtc(crtc)), is_disabled_(true), - page_flip_pending_(false), time_of_last_flip_(0) { } @@ -28,6 +27,7 @@ if (!is_disabled_) { drm_->SetCrtc(saved_crtc_.get(), std::vector<uint32_t>(1, connector_)); SetCursor(nullptr); + SignalPageFlipRequest(); } } @@ -51,7 +51,7 @@ // pending planes to the same values so that the callback keeps the correct // state. current_planes_ = std::vector<OverlayPlane>(1, plane); - if (page_flip_pending_) + if (page_flip_request_.get()) pending_planes_ = current_planes_; ResetCursor(); @@ -67,14 +67,16 @@ return drm_->DisableCrtc(crtc_); } -bool CrtcController::SchedulePageFlip(HardwareDisplayPlaneList* plane_list, - const OverlayPlaneList& overlays) { - DCHECK(!page_flip_pending_); +bool CrtcController::SchedulePageFlip( + HardwareDisplayPlaneList* plane_list, + const OverlayPlaneList& overlays, + scoped_refptr<PageFlipRequest> page_flip_request) { + DCHECK(!page_flip_request_.get()); DCHECK(!is_disabled_); const OverlayPlane* primary = OverlayPlane::GetPrimaryPlane(overlays); if (!primary) { LOG(ERROR) << "No primary plane to display on crtc " << crtc_; - FOR_EACH_OBSERVER(PageFlipObserver, observers_, OnPageFlipEvent()); + page_flip_request->Signal(); return true; } DCHECK(primary->buffer.get()); @@ -84,31 +86,31 @@ << mode_.hdisplay << "x" << mode_.vdisplay << " got " << primary->buffer->GetSize().ToString() << " for" << " crtc=" << crtc_ << " connector=" << connector_; - FOR_EACH_OBSERVER(PageFlipObserver, observers_, OnPageFlipEvent()); + page_flip_request->Signal(); return true; } if (!drm_->plane_manager()->AssignOverlayPlanes(plane_list, overlays, crtc_, this)) { PLOG(ERROR) << "Failed to assign overlay planes for crtc " << crtc_; + page_flip_request->Signal(); return false; } - page_flip_pending_ = true; pending_planes_ = overlays; + page_flip_request_ = page_flip_request; return true; } void CrtcController::PageFlipFailed() { pending_planes_.clear(); - page_flip_pending_ = false; + SignalPageFlipRequest(); } void CrtcController::OnPageFlipEvent(unsigned int frame, unsigned int seconds, unsigned int useconds) { - page_flip_pending_ = false; time_of_last_flip_ = static_cast<uint64_t>(seconds) * base::Time::kMicrosecondsPerSecond + useconds; @@ -116,7 +118,7 @@ current_planes_.clear(); current_planes_.swap(pending_planes_); - FOR_EACH_OBSERVER(PageFlipObserver, observers_, OnPageFlipEvent()); + SignalPageFlipRequest(); } bool CrtcController::SetCursor(const scoped_refptr<ScanoutBuffer>& buffer) { @@ -131,14 +133,6 @@ return drm_->MoveCursor(crtc_, location); } -void CrtcController::AddObserver(PageFlipObserver* observer) { - observers_.AddObserver(observer); -} - -void CrtcController::RemoveObserver(PageFlipObserver* observer) { - observers_.RemoveObserver(observer); -} - bool CrtcController::ResetCursor() { uint32_t handle = 0; gfx::Size size; @@ -158,4 +152,16 @@ return status; } +void CrtcController::SignalPageFlipRequest() { + if (page_flip_request_.get()) { + // If another frame is queued up and available immediately, calling Signal() + // may result in a call to SchedulePageFlip(), which will override + // page_flip_request_ and possibly release the ref. Stash previous request + // locally to avoid deleting the object we are making a call on. + scoped_refptr<PageFlipRequest> last_request; + last_request.swap(page_flip_request_); + last_request->Signal(); + } +} + } // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/crtc_controller.h b/ui/ozone/platform/drm/gpu/crtc_controller.h index 4404bfa..7caae4e0 100644 --- a/ui/ozone/platform/drm/gpu/crtc_controller.h +++ b/ui/ozone/platform/drm/gpu/crtc_controller.h
@@ -19,7 +19,7 @@ namespace ui { class DrmDevice; -class PageFlipObserver; +class PageFlipRequest; // Wrapper around a CRTC. // @@ -38,7 +38,6 @@ uint32_t connector() const { return connector_; } const scoped_refptr<DrmDevice>& drm() const { return drm_; } bool is_disabled() const { return is_disabled_; } - bool page_flip_pending() const { return page_flip_pending_; } uint64_t time_of_last_flip() const { return time_of_last_flip_; } drmModeCrtc* saved_crtc() const { return saved_crtc_.get(); } @@ -52,7 +51,8 @@ // Schedule a page flip event and present the overlays in |planes|. bool SchedulePageFlip(HardwareDisplayPlaneList* plane_list, - const OverlayPlaneList& planes); + const OverlayPlaneList& planes, + scoped_refptr<PageFlipRequest> page_flip_request); // Called if the page flip for this CRTC fails after being scheduled. void PageFlipFailed(); @@ -70,12 +70,11 @@ bool SetCursor(const scoped_refptr<ScanoutBuffer>& buffer); bool MoveCursor(const gfx::Point& location); - void AddObserver(PageFlipObserver* observer); - void RemoveObserver(PageFlipObserver* observer); - private: bool ResetCursor(); + void SignalPageFlipRequest(); + scoped_refptr<DrmDevice> drm_; HardwareDisplayPlaneManager* overlay_plane_manager_; // Not owned. @@ -85,6 +84,7 @@ OverlayPlaneList current_planes_; OverlayPlaneList pending_planes_; scoped_refptr<ScanoutBuffer> cursor_buffer_; + scoped_refptr<PageFlipRequest> page_flip_request_; uint32_t crtc_; @@ -101,15 +101,9 @@ // is set to false. Otherwise it is true. bool is_disabled_; - // True if a successful SchedulePageFlip occurred. Reset to false by a modeset - // operation or when the OnPageFlipEvent callback is triggered. - bool page_flip_pending_; - // The time of the last page flip event as reported by the kernel callback. uint64_t time_of_last_flip_; - ObserverList<PageFlipObserver> observers_; - DISALLOW_COPY_AND_ASSIGN(CrtcController); };
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc index 477ae7a..526b200 100644 --- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc +++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -336,17 +336,22 @@ return true; } -bool DrmGpuDisplayManager::GetHDCPState(const DrmDisplaySnapshot& output, - HDCPState* state) { +bool DrmGpuDisplayManager::GetHDCPState(int64_t display_id, HDCPState* state) { + DrmDisplaySnapshot* output = FindDisplaySnapshot(display_id); + if (!output) { + LOG(ERROR) << "There is no display with ID " << display_id; + return false; + } + ScopedDrmConnectorPtr connector( - output.drm()->GetConnector(output.connector())); + output->drm()->GetConnector(output->connector())); if (!connector) { - PLOG(ERROR) << "Failed to get connector " << output.connector(); + PLOG(ERROR) << "Failed to get connector " << output->connector(); return false; } ScopedDrmPropertyPtr hdcp_property( - output.drm()->GetProperty(connector.get(), kContentProtection)); + output->drm()->GetProperty(connector.get(), kContentProtection)); if (!hdcp_property) { PLOG(ERROR) << "'" << kContentProtection << "' property doesn't exist."; return false; @@ -366,24 +371,29 @@ return false; } -bool DrmGpuDisplayManager::SetHDCPState(const DrmDisplaySnapshot& output, - HDCPState state) { +bool DrmGpuDisplayManager::SetHDCPState(int64_t display_id, HDCPState state) { + DrmDisplaySnapshot* output = FindDisplaySnapshot(display_id); + if (!output) { + LOG(ERROR) << "There is no display with ID " << display_id; + return false; + } + ScopedDrmConnectorPtr connector( - output.drm()->GetConnector(output.connector())); + output->drm()->GetConnector(output->connector())); if (!connector) { - PLOG(ERROR) << "Failed to get connector " << output.connector(); + PLOG(ERROR) << "Failed to get connector " << output->connector(); return false; } ScopedDrmPropertyPtr hdcp_property( - output.drm()->GetProperty(connector.get(), kContentProtection)); + output->drm()->GetProperty(connector.get(), kContentProtection)); if (!hdcp_property) { PLOG(ERROR) << "'" << kContentProtection << "' property doesn't exist."; return false; } - return output.drm()->SetProperty( - output.connector(), hdcp_property->prop_id, + return output->drm()->SetProperty( + output->connector(), hdcp_property->prop_id, GetContentProtectionValue(hdcp_property.get(), state)); }
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h index bbfa508..5267b6f 100644 --- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h +++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
@@ -54,6 +54,9 @@ const base::FileDescriptor& fd); void RemoveGraphicsDevice(const base::FilePath& path); + bool GetHDCPState(int64_t display_id, HDCPState* state); + bool SetHDCPState(int64_t display_id, HDCPState state); + private: DrmDisplaySnapshot* FindDisplaySnapshot(int64_t id); const DrmDisplayMode* FindDisplayMode(const gfx::Size& size, @@ -65,9 +68,6 @@ const DrmDisplayMode* mode, const gfx::Point& origin); - bool GetHDCPState(const DrmDisplaySnapshot& output, HDCPState* state); - bool SetHDCPState(const DrmDisplaySnapshot& output, HDCPState state); - // Notify ScreenManager of all the displays that were present before the // update but are gone after the update. void NotifyScreenManager(
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_platform_support.cc b/ui/ozone/platform/drm/gpu/drm_gpu_platform_support.cc index 495307f8..fdf9980 100644 --- a/ui/ozone/platform/drm/gpu/drm_gpu_platform_support.cc +++ b/ui/ozone/platform/drm/gpu/drm_gpu_platform_support.cc
@@ -213,6 +213,8 @@ OnRelinquishDisplayControl) IPC_MESSAGE_HANDLER(OzoneGpuMsg_AddGraphicsDevice, OnAddGraphicsDevice) IPC_MESSAGE_HANDLER(OzoneGpuMsg_RemoveGraphicsDevice, OnRemoveGraphicsDevice) + IPC_MESSAGE_HANDLER(OzoneGpuMsg_GetHDCPState, OnGetHDCPState) + IPC_MESSAGE_HANDLER(OzoneGpuMsg_SetHDCPState, OnSetHDCPState) IPC_MESSAGE_UNHANDLED(handled = false); IPC_END_MESSAGE_MAP() @@ -296,6 +298,18 @@ callback.Run(); } +void DrmGpuPlatformSupport::OnGetHDCPState(int64_t display_id) { + HDCPState state = HDCP_STATE_UNDESIRED; + bool success = ndd_->GetHDCPState(display_id, &state); + sender_->Send(new OzoneHostMsg_HDCPStateReceived(display_id, success, state)); +} + +void DrmGpuPlatformSupport::OnSetHDCPState(int64_t display_id, + HDCPState state) { + sender_->Send(new OzoneHostMsg_HDCPStateUpdated( + display_id, ndd_->SetHDCPState(display_id, state))); +} + void DrmGpuPlatformSupport::SetIOTaskRunner( const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) { ndd_->InitializeIOTaskRunner(io_task_runner);
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_platform_support.h b/ui/ozone/platform/drm/gpu/drm_gpu_platform_support.h index 2c844db..abd6978 100644 --- a/ui/ozone/platform/drm/gpu/drm_gpu_platform_support.h +++ b/ui/ozone/platform/drm/gpu/drm_gpu_platform_support.h
@@ -9,6 +9,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "ipc/message_filter.h" +#include "ui/display/types/display_constants.h" #include "ui/gfx/native_widget_types.h" #include "ui/ozone/public/gpu_platform_support.h" @@ -75,6 +76,8 @@ void OnAddGraphicsDevice(const base::FilePath& path, const base::FileDescriptor& fd); void OnRemoveGraphicsDevice(const base::FilePath& path); + void OnGetHDCPState(int64_t display_id); + void OnSetHDCPState(int64_t display_id, HDCPState state); void SetIOTaskRunner( const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc index 278dc156..a2d1b8e 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_controller.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -17,20 +17,11 @@ #include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/drm_buffer.h" #include "ui/ozone/platform/drm/gpu/drm_device.h" +#include "ui/ozone/platform/drm/gpu/page_flip_request.h" #include "ui/ozone/public/native_pixmap.h" namespace ui { -HardwareDisplayController::PageFlipRequest::PageFlipRequest( - const OverlayPlaneList& planes, - bool is_sync, - const base::Closure& callback) - : planes(planes), is_sync(is_sync), callback(callback) { -} - -HardwareDisplayController::PageFlipRequest::~PageFlipRequest() { -} - HardwareDisplayController::HardwareDisplayController( scoped_ptr<CrtcController> controller) : is_disabled_(true) { @@ -41,7 +32,6 @@ HardwareDisplayController::~HardwareDisplayController() { // Reset the cursor. UnsetCursor(); - ClearPendingRequests(); } bool HardwareDisplayController::Modeset(const OverlayPlane& primary, @@ -55,15 +45,6 @@ is_disabled_ = false; mode_ = mode; - current_planes_ = std::vector<OverlayPlane>(1, primary); - ClearPendingRequests(); - - // Because a page flip is pending we need to leave some state for the - // callback. We use the modeset state since it is the only valid state. - if (HasPendingPageFlips()) - requests_.push_back( - PageFlipRequest(current_planes_, false, base::Bind(&base::DoNothing))); - return status; } @@ -72,12 +53,6 @@ for (size_t i = 0; i < crtc_controllers_.size(); ++i) crtc_controllers_[i]->Disable(); - // Don't hold onto any requests because we don't track fron buffer while - // disabled. - while (requests_.size()) - ProcessPageFlipRequest(); - - current_planes_.clear(); is_disabled_ = true; } @@ -88,23 +63,35 @@ const base::Closure& callback) { TRACE_EVENT0("drm", "HDC::SchedulePageFlip"); + DCHECK(!is_disabled_); + // Ignore requests with no planes to schedule. if (plane_list.empty()) { callback.Run(); return true; } - requests_.push_back(PageFlipRequest(plane_list, is_sync, callback)); + scoped_refptr<PageFlipRequest> page_flip_request = + new PageFlipRequest(crtc_controllers_.size(), callback); - // A request is being serviced right now. - if (HasPendingPageFlips()) - return true; + OverlayPlaneList pending_planes = plane_list; + std::sort(pending_planes.begin(), pending_planes.end(), + [](const OverlayPlane& l, const OverlayPlane& r) { + return l.z_order < r.z_order; + }); - bool status = ActualSchedulePageFlip(); + bool status = true; + for (size_t i = 0; i < crtc_controllers_.size(); ++i) { + status &= crtc_controllers_[i]->SchedulePageFlip( + owned_hardware_planes_.get(crtc_controllers_[i]->drm().get()), + pending_planes, page_flip_request); + } - // No page flip event on failure so discard failed request. - if (!status) - requests_.pop_front(); + for (const auto& planes : owned_hardware_planes_) { + if (!planes.first->plane_manager()->Commit(planes.second, is_sync)) { + status = false; + } + } return status; } @@ -145,7 +132,6 @@ owned_hardware_planes_.add( controller->drm().get(), scoped_ptr<HardwareDisplayPlaneList>(new HardwareDisplayPlaneList())); - controller->AddObserver(this); crtc_controllers_.push_back(controller.release()); } @@ -170,13 +156,6 @@ if (!found) owned_hardware_planes_.erase(controller->drm().get()); - controller->RemoveObserver(this); - // If a display configuration happens mid page flip we want to make sure - // the HDC won't wait for an event from a CRTC that is no longer - // associated with it. - if (controller->page_flip_pending()) - OnPageFlipEvent(); - return controller.Pass(); } } @@ -215,44 +194,6 @@ return time; } -void HardwareDisplayController::OnPageFlipEvent() { - TRACE_EVENT0("drm", "HDC::OnPageFlipEvent"); - // OnPageFlipEvent() needs to handle 2 cases: - // 1) Normal page flips in which case: - // a) HasPendingPageFlips() may return false if we're in mirror mode and - // one of the CRTCs hasn't finished page flipping. In this case we want - // to wait for all the CRTCs. - // b) HasPendingPageFlips() returns true in which case all CRTCs are ready - // for the next request. In this case we expect that |requests_| isn't - // empty. - // 2) A CRTC was added while it was page flipping. In this case a modeset - // must be performed. Modesetting clears all pending requests, however the - // CRTCs will honor the scheduled page flip. Thus we need to handle page - // flip events with no requests. - - if (HasPendingPageFlips()) - return; - - if (!requests_.empty()) - ProcessPageFlipRequest(); - - // ProcessPageFlipRequest() consumes a request. - if (requests_.empty()) - return; - - // At this point we still have requests pending, so schedule the next request. - bool status = ActualSchedulePageFlip(); - if (!status) { - PageFlipRequest request = requests_.front(); - requests_.pop_front(); - - // Normally the caller would handle the error call, but because we're in a - // delayed schedule the initial SchedulePageFlip() already returned true, - // thus we need to run the callback. - request.callback.Run(); - } -} - scoped_refptr<DrmDevice> HardwareDisplayController::GetAllocationDrmDevice() const { DCHECK(!crtc_controllers_.empty()); @@ -261,61 +202,4 @@ return crtc_controllers_[0]->drm(); } -bool HardwareDisplayController::HasPendingPageFlips() const { - for (size_t i = 0; i < crtc_controllers_.size(); ++i) - if (crtc_controllers_[i]->page_flip_pending()) - return true; - - return false; -} - -bool HardwareDisplayController::ActualSchedulePageFlip() { - TRACE_EVENT0("drm", "HDC::ActualSchedulePageFlip"); - DCHECK(!requests_.empty()); - - if (is_disabled_) { - ProcessPageFlipRequest(); - return true; - } - - OverlayPlaneList pending_planes = requests_.front().planes; - std::sort(pending_planes.begin(), pending_planes.end(), - [](const OverlayPlane& l, const OverlayPlane& r) { - return l.z_order < r.z_order; - }); - - bool status = true; - for (size_t i = 0; i < crtc_controllers_.size(); ++i) { - status &= crtc_controllers_[i]->SchedulePageFlip( - owned_hardware_planes_.get(crtc_controllers_[i]->drm().get()), - pending_planes); - } - - bool is_sync = requests_.front().is_sync; - for (const auto& planes : owned_hardware_planes_) { - if (!planes.first->plane_manager()->Commit(planes.second, is_sync)) { - status = false; - } - } - - return status; -} - -void HardwareDisplayController::ProcessPageFlipRequest() { - DCHECK(!requests_.empty()); - PageFlipRequest request = requests_.front(); - requests_.pop_front(); - - current_planes_.swap(request.planes); - request.callback.Run(); -} - -void HardwareDisplayController::ClearPendingRequests() { - while (!requests_.empty()) { - PageFlipRequest request = requests_.front(); - requests_.pop_front(); - request.callback.Run(); - } -} - } // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller.h b/ui/ozone/platform/drm/gpu/hardware_display_controller.h index 196b2dd..ee08ebb 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_controller.h +++ b/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -17,11 +17,9 @@ #include "base/containers/scoped_ptr_hash_map.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" -#include "base/memory/weak_ptr.h" #include "ui/ozone/ozone_export.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h" #include "ui/ozone/platform/drm/gpu/overlay_plane.h" -#include "ui/ozone/platform/drm/gpu/page_flip_observer.h" namespace gfx { class Point; @@ -87,12 +85,10 @@ // only a subset of connectors can be active independently, showing different // framebuffers. Though, in this case, it would be possible to have all // connectors active if some use the same CRTC to mirror the display. -class OZONE_EXPORT HardwareDisplayController - : public base::SupportsWeakPtr<HardwareDisplayController>, - public PageFlipObserver { +class OZONE_EXPORT HardwareDisplayController { public: explicit HardwareDisplayController(scoped_ptr<CrtcController> controller); - ~HardwareDisplayController() override; + ~HardwareDisplayController(); // Performs the initial CRTC configuration. If successful, it will display the // framebuffer for |primary| with |mode|. @@ -151,39 +147,6 @@ scoped_refptr<DrmDevice> GetAllocationDrmDevice() const; private: - // Returns true if any of the CRTCs is waiting for a page flip. - bool HasPendingPageFlips() const; - - bool ActualSchedulePageFlip(); - - void ProcessPageFlipRequest(); - - void ClearPendingRequests(); - - // PageFlipObserver: - void OnPageFlipEvent() override; - - struct PageFlipRequest { - PageFlipRequest(const OverlayPlaneList& planes, - bool is_sync, - const base::Closure& callback); - ~PageFlipRequest(); - - OverlayPlaneList planes; - bool is_sync; - base::Closure callback; - }; - - // Buffers need to be declared first so that they are destroyed last. Needed - // since the controllers may reference the buffers. - OverlayPlaneList current_planes_; - // Planes currently being queued without having SchedulePageFlip() called. - OverlayPlaneList pending_planes_; - // Plane lists for which SchedulePageFlip() was called. They are waiting for - // previous page flip events to be completed before they can be serviced. - std::deque<PageFlipRequest> requests_; - scoped_refptr<ScanoutBuffer> cursor_buffer_; - base::ScopedPtrHashMap<DrmDevice*, HardwareDisplayPlaneList> owned_hardware_planes_;
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc index c325f8b..0cf9dd5 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
@@ -147,32 +147,6 @@ EXPECT_TRUE(plane2.buffer->HasOneRef()); } -TEST_F(HardwareDisplayControllerTest, VerifyNoDRMCallsWhenDisabled) { - ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>( - new MockScanoutBuffer(kDefaultModeSize))); - - EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode)); - controller_->Disable(); - ui::OverlayPlane plane2(scoped_refptr<ui::ScanoutBuffer>( - new MockScanoutBuffer(kDefaultModeSize))); - std::vector<ui::OverlayPlane> planes = - std::vector<ui::OverlayPlane>(1, plane2); - EXPECT_TRUE(controller_->SchedulePageFlip( - planes, false, - base::Bind(&HardwareDisplayControllerTest::PageFlipCallback, - base::Unretained(this)))); - drm_->RunCallbacks(); - EXPECT_EQ(0, drm_->get_page_flip_call_count()); - - EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode)); - EXPECT_TRUE(controller_->SchedulePageFlip( - planes, false, - base::Bind(&HardwareDisplayControllerTest::PageFlipCallback, - base::Unretained(this)))); - drm_->RunCallbacks(); - EXPECT_EQ(1, drm_->get_page_flip_call_count()); -} - TEST_F(HardwareDisplayControllerTest, CheckOverlayPresent) { ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>( new MockScanoutBuffer(kDefaultModeSize)));
diff --git a/ui/ozone/platform/drm/gpu/page_flip_observer.h b/ui/ozone/platform/drm/gpu/page_flip_observer.h deleted file mode 100644 index f8c066a5..0000000 --- a/ui/ozone/platform/drm/gpu/page_flip_observer.h +++ /dev/null
@@ -1,19 +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. - -#ifndef UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_OBSERVER_H_ -#define UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_OBSERVER_H_ - -namespace ui { - -class PageFlipObserver { - public: - virtual ~PageFlipObserver() {} - - virtual void OnPageFlipEvent() = 0; -}; - -} // namespace ui - -#endif // UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_OBSERVER_H_
diff --git a/ui/ozone/platform/drm/gpu/page_flip_request.cc b/ui/ozone/platform/drm/gpu/page_flip_request.cc new file mode 100644 index 0000000..dfca208 --- /dev/null +++ b/ui/ozone/platform/drm/gpu/page_flip_request.cc
@@ -0,0 +1,22 @@ +// 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 "ui/ozone/platform/drm/gpu/page_flip_request.h" + +#include "base/barrier_closure.h" + +namespace ui { + +PageFlipRequest::PageFlipRequest(int crtc_count, const base::Closure& callback) + : callback_(base::BarrierClosure(crtc_count, callback)) { +} + +PageFlipRequest::~PageFlipRequest() { +} + +void PageFlipRequest::Signal() { + callback_.Run(); +} + +} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/page_flip_request.h b/ui/ozone/platform/drm/gpu/page_flip_request.h new file mode 100644 index 0000000..c1a63b2 --- /dev/null +++ b/ui/ozone/platform/drm/gpu/page_flip_request.h
@@ -0,0 +1,30 @@ +// 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 UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_ +#define UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_ + +#include "base/callback.h" +#include "base/memory/scoped_ptr.h" + +namespace ui { + +class PageFlipRequest : public base::RefCounted<PageFlipRequest> { + public: + PageFlipRequest(int crtc_count, const base::Closure& callback); + + void Signal(); + + private: + friend class base::RefCounted<PageFlipRequest>; + ~PageFlipRequest(); + + base::Closure callback_; + + DISALLOW_COPY_AND_ASSIGN(PageFlipRequest); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_DRM_GPU_PAGE_FLIP_REQUEST_H_
diff --git a/ui/ozone/platform/drm/host/drm_native_display_delegate.cc b/ui/ozone/platform/drm/host/drm_native_display_delegate.cc index 0a2a4c2..709ade8 100644 --- a/ui/ozone/platform/drm/host/drm_native_display_delegate.cc +++ b/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
@@ -184,31 +184,21 @@ void DrmNativeDisplayDelegate::CreateFrameBuffer(const gfx::Size& size) { } -bool DrmNativeDisplayDelegate::GetHDCPState(const DisplaySnapshot& output, - HDCPState* state) { - NOTIMPLEMENTED(); - return false; -} - -bool DrmNativeDisplayDelegate::SetHDCPState(const DisplaySnapshot& output, - HDCPState state) { - NOTIMPLEMENTED(); - return false; -} - void DrmNativeDisplayDelegate::GetHDCPState( - const ui::DisplaySnapshot& output, + const DisplaySnapshot& output, const GetHDCPStateCallback& callback) { - NOTIMPLEMENTED(); - callback.Run(false, HDCP_STATE_UNDESIRED); + get_hdcp_state_callback_map_[output.display_id()] = callback; + if (!proxy_->Send(new OzoneGpuMsg_GetHDCPState(output.display_id()))) + OnHDCPStateReceived(output.display_id(), false, HDCP_STATE_UNDESIRED); } void DrmNativeDisplayDelegate::SetHDCPState( - const ui::DisplaySnapshot& output, - ui::HDCPState state, + const DisplaySnapshot& output, + HDCPState state, const SetHDCPStateCallback& callback) { - NOTIMPLEMENTED(); - callback.Run(false); + set_hdcp_state_callback_map_[output.display_id()] = callback; + if (!proxy_->Send(new OzoneGpuMsg_SetHDCPState(output.display_id(), state))) + OnHDCPStateUpdated(output.display_id(), false); } std::vector<ColorCalibrationProfile> @@ -316,6 +306,8 @@ IPC_BEGIN_MESSAGE_MAP(DrmNativeDisplayDelegate, message) IPC_MESSAGE_HANDLER(OzoneHostMsg_UpdateNativeDisplays, OnUpdateNativeDisplays) IPC_MESSAGE_HANDLER(OzoneHostMsg_DisplayConfigured, OnDisplayConfigured) + IPC_MESSAGE_HANDLER(OzoneHostMsg_HDCPStateReceived, OnHDCPStateReceived) + IPC_MESSAGE_HANDLER(OzoneHostMsg_HDCPStateUpdated, OnHDCPStateUpdated) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -349,6 +341,27 @@ } } +void DrmNativeDisplayDelegate::OnHDCPStateReceived(int64_t display_id, + bool status, + HDCPState state) { + auto it = get_hdcp_state_callback_map_.find(display_id); + if (it != get_hdcp_state_callback_map_.end()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(it->second, status, state)); + get_hdcp_state_callback_map_.erase(it); + } +} + +void DrmNativeDisplayDelegate::OnHDCPStateUpdated(int64_t display_id, + bool status) { + auto it = set_hdcp_state_callback_map_.find(display_id); + if (it != set_hdcp_state_callback_map_.end()) { + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::Bind(it->second, status)); + set_hdcp_state_callback_map_.erase(it); + } +} + void DrmNativeDisplayDelegate::RunUpdateDisplaysCallback( const GetDisplaysCallback& callback) const { callback.Run(displays_.get());
diff --git a/ui/ozone/platform/drm/host/drm_native_display_delegate.h b/ui/ozone/platform/drm/host/drm_native_display_delegate.h index 986f28a..d28ea68 100644 --- a/ui/ozone/platform/drm/host/drm_native_display_delegate.h +++ b/ui/ozone/platform/drm/host/drm_native_display_delegate.h
@@ -50,8 +50,6 @@ const gfx::Point& origin, const ConfigureCallback& callback) override; void CreateFrameBuffer(const gfx::Size& size) override; - bool GetHDCPState(const DisplaySnapshot& output, HDCPState* state) override; - bool SetHDCPState(const DisplaySnapshot& output, HDCPState state) override; void GetHDCPState(const DisplaySnapshot& output, const GetHDCPStateCallback& callback) override; void SetHDCPState(const DisplaySnapshot& output, @@ -84,6 +82,9 @@ void OnNewGraphicsDevice(const base::FilePath& path, base::File file); + void OnHDCPStateReceived(int64_t display_id, bool status, HDCPState state); + void OnHDCPStateUpdated(int64_t display_id, bool status); + void RunUpdateDisplaysCallback(const GetDisplaysCallback& callback) const; DrmGpuPlatformSupportHost* proxy_; // Not owned. @@ -107,6 +108,10 @@ // Map between display_id and the configuration callback. std::map<int64_t, ConfigureCallback> configure_callback_map_; + std::map<int64_t, GetHDCPStateCallback> get_hdcp_state_callback_map_; + + std::map<int64_t, SetHDCPStateCallback> set_hdcp_state_callback_map_; + base::WeakPtrFactory<DrmNativeDisplayDelegate> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DrmNativeDisplayDelegate);
diff --git a/ui/shell_dialogs/select_file_dialog_win.cc b/ui/shell_dialogs/select_file_dialog_win.cc index 7218d68..2ada0ce1 100644 --- a/ui/shell_dialogs/select_file_dialog_win.cc +++ b/ui/shell_dialogs/select_file_dialog_win.cc
@@ -166,12 +166,12 @@ const base::Callback<bool(OPENFILENAME*)>& get_save_file_name_impl); // BaseShellDialog implementation: - virtual bool IsRunning(gfx::NativeWindow owning_window) const override; - virtual void ListenerDestroyed() override; + bool IsRunning(gfx::NativeWindow owning_window) const override; + void ListenerDestroyed() override; protected: // SelectFileDialog implementation: - virtual void SelectFileImpl( + void SelectFileImpl( Type type, const base::string16& title, const base::FilePath& default_path, @@ -182,7 +182,7 @@ void* params) override; private: - virtual ~SelectFileDialogImpl(); + ~SelectFileDialogImpl() override; // A struct for holding all the state necessary for displaying a Save dialog. struct ExecuteSelectParams { @@ -287,7 +287,7 @@ LPARAM parameter, LPARAM data); - virtual bool HasMultipleFileTypeChoicesImpl() override; + bool HasMultipleFileTypeChoicesImpl() override; // Returns the filter to be used while displaying the open/save file dialog. // This is computed from the extensions for the file types being opened.
diff --git a/ui/views/accessibility/native_view_accessibility_auralinux.cc b/ui/views/accessibility/native_view_accessibility_auralinux.cc index afee535..b7fbf9c9 100644 --- a/ui/views/accessibility/native_view_accessibility_auralinux.cc +++ b/ui/views/accessibility/native_view_accessibility_auralinux.cc
@@ -125,6 +125,13 @@ ViewsDelegate::views_delegate->GetApplicationName()); } ui::AXPlatformNodeAuraLinux::SetApplication(platform_node_); + if (ViewsDelegate::views_delegate) { + scoped_refptr<base::TaskRunner> init_task_runner = + ViewsDelegate::views_delegate-> + GetTaskRunnerForAuraLinuxAccessibilityInit(); + if (init_task_runner) + ui::AXPlatformNodeAuraLinux::StaticInitialize(init_task_runner); + } } ~AuraLinuxApplication() override {
diff --git a/ui/views/border.cc b/ui/views/border.cc index 6e28caf..ed02476 100644 --- a/ui/views/border.cc +++ b/ui/views/border.cc
@@ -44,13 +44,15 @@ // Top border. canvas->FillRect(gfx::Rect(0, 0, view.width(), insets_.top()), color_); // Left border. - canvas->FillRect(gfx::Rect(0, 0, insets_.left(), view.height()), color_); + canvas->FillRect(gfx::Rect(0, insets_.top(), insets_.left(), + view.height() - insets_.height()), color_); // Bottom border. canvas->FillRect(gfx::Rect(0, view.height() - insets_.bottom(), view.width(), insets_.bottom()), color_); // Right border. - canvas->FillRect(gfx::Rect(view.width() - insets_.right(), 0, insets_.right(), - view.height()), color_); + canvas->FillRect(gfx::Rect(view.width() - insets_.right(), insets_.top(), + insets_.right(), view.height() - insets_.height()), + color_); } gfx::Insets SidedSolidBorder::GetInsets() const {
diff --git a/ui/views/controls/menu/native_menu_win.cc b/ui/views/controls/menu/native_menu_win.cc index fa8a3e61..78f8a379 100644 --- a/ui/views/controls/menu/native_menu_win.cc +++ b/ui/views/controls/menu/native_menu_win.cc
@@ -400,9 +400,9 @@ menu_action_(MENU_ACTION_NONE), menu_to_select_(NULL), position_to_select_(-1), - menu_to_select_factory_(this), parent_(NULL), - destroyed_flag_(NULL) { + destroyed_flag_(NULL), + menu_to_select_factory_(this) { } NativeMenuWin::~NativeMenuWin() {
diff --git a/ui/views/controls/menu/native_menu_win.h b/ui/views/controls/menu/native_menu_win.h index 7d4dea9a..3cbc25f8 100644 --- a/ui/views/controls/menu/native_menu_win.h +++ b/ui/views/controls/menu/native_menu_win.h
@@ -146,7 +146,6 @@ // See comment in MenuMessageHook for details on these. NativeMenuWin* menu_to_select_; int position_to_select_; - base::WeakPtrFactory<NativeMenuWin> menu_to_select_factory_; // If we're a submenu, this is our parent. NativeMenuWin* parent_; @@ -156,6 +155,8 @@ // running. bool* destroyed_flag_; + base::WeakPtrFactory<NativeMenuWin> menu_to_select_factory_; + // Ugly: a static pointer to the instance of this class that currently // has a menu open, because our hook function that receives keyboard // events doesn't have a mechanism to get a user data pointer.
diff --git a/ui/views/controls/throbber.cc b/ui/views/controls/throbber.cc index 30cfb3b3..b2a26fcc 100644 --- a/ui/views/controls/throbber.cc +++ b/ui/views/controls/throbber.cc
@@ -4,24 +4,19 @@ #include "ui/views/controls/throbber.h" -#include "base/time/time.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/animation/tween.h" #include "ui/gfx/canvas.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" #include "ui/resources/grit/ui_resources.h" -using base::Time; -using base::TimeDelta; - namespace views { -Throbber::Throbber(int frame_time_ms, - bool paint_while_stopped) - : running_(false), - paint_while_stopped_(paint_while_stopped), +Throbber::Throbber(int frame_time_ms, bool paint_while_stopped) + : paint_while_stopped_(paint_while_stopped), frames_(NULL), - frame_time_(TimeDelta::FromMilliseconds(frame_time_ms)) { + frame_time_(base::TimeDelta::FromMilliseconds(frame_time_ms)) { SetFrames(ui::ResourceBundle::GetSharedInstance().GetImageNamed( IDR_THROBBER).ToImageSkia()); } @@ -31,26 +26,20 @@ } void Throbber::Start() { - if (running_) + if (IsRunning()) return; - start_time_ = Time::Now(); - - timer_.Start(FROM_HERE, frame_time_ - TimeDelta::FromMilliseconds(10), - this, &Throbber::Run); - - running_ = true; - + start_time_ = base::TimeTicks::Now(); + timer_.Start(FROM_HERE, frame_time_ - base::TimeDelta::FromMilliseconds(10), + this, &Throbber::SchedulePaint); SchedulePaint(); // paint right away } void Throbber::Stop() { - if (!running_) + if (!IsRunning()) return; timer_.Stop(); - - running_ = false; SchedulePaint(); // Important if we're not painting while stopped } @@ -62,21 +51,15 @@ PreferredSizeChanged(); } -void Throbber::Run() { - DCHECK(running_); - - SchedulePaint(); -} - gfx::Size Throbber::GetPreferredSize() const { return gfx::Size(frames_->height(), frames_->height()); } void Throbber::OnPaint(gfx::Canvas* canvas) { - if (!running_ && !paint_while_stopped_) + if (!IsRunning() && !paint_while_stopped_) return; - const TimeDelta elapsed_time = Time::Now() - start_time_; + const base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time_; const int current_frame = static_cast<int>(elapsed_time / frame_time_) % frame_count_; @@ -88,18 +71,18 @@ false); } - +bool Throbber::IsRunning() const { + return timer_.IsRunning(); +} // Smoothed throbber --------------------------------------------------------- - // Delay after work starts before starting throbber, in milliseconds. static const int kStartDelay = 200; // Delay after work stops before stopping, in milliseconds. static const int kStopDelay = 50; - SmoothedThrobber::SmoothedThrobber(int frame_time_ms) : Throbber(frame_time_ms, /* paint_while_stopped= */ false), start_delay_ms_(kStartDelay), @@ -111,9 +94,10 @@ void SmoothedThrobber::Start() { stop_timer_.Stop(); - if (!running() && !start_timer_.IsRunning()) { - start_timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(start_delay_ms_), - this, &SmoothedThrobber::StartDelayOver); + if (!IsRunning() && !start_timer_.IsRunning()) { + start_timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(start_delay_ms_), this, + &SmoothedThrobber::StartDelayOver); } } @@ -122,12 +106,13 @@ } void SmoothedThrobber::Stop() { - if (!running()) + if (!IsRunning()) start_timer_.Stop(); stop_timer_.Stop(); - stop_timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(stop_delay_ms_), - this, &SmoothedThrobber::StopDelayOver); + stop_timer_.Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(stop_delay_ms_), this, + &SmoothedThrobber::StopDelayOver); } void SmoothedThrobber::StopDelayOver() { @@ -170,7 +155,7 @@ } void MaterialThrobber::OnPaint(gfx::Canvas* canvas) { - if (!running()) { + if (!IsRunning()) { if (checked_) { if (!checkmark_) { checkmark_ = ui::ResourceBundle::GetSharedInstance().GetImageNamed( @@ -184,6 +169,69 @@ return; } + PaintSpinning(canvas); +} + +void MaterialThrobber::PaintSpinning(gfx::Canvas* canvas) { + base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time(); + + // This is a Skia port of the MD spinner SVG. The |start_angle| rotation + // here corresponds to the 'rotate' animation. + base::TimeDelta rotation_time = base::TimeDelta::FromMilliseconds(1568); + int64_t start_angle = 270 + 360 * elapsed_time / rotation_time; + + // The sweep angle ranges from -|arc_size| to |arc_size| over 1333ms. CSS + // animation timing functions apply in between key frames, so we have to + // break up the |arc_time| into two keyframes (-arc_size to 0, then 0 to + // arc_size). + int64_t arc_size = 270; + base::TimeDelta arc_time = base::TimeDelta::FromMilliseconds(666); + double arc_size_progress = static_cast<double>(elapsed_time.InMicroseconds() % + arc_time.InMicroseconds()) / + arc_time.InMicroseconds(); + // This tween is equivalent to cubic-bezier(0.4, 0.0, 0.2, 1). + double sweep = + arc_size * gfx::Tween::CalculateValue(gfx::Tween::FAST_OUT_SLOW_IN, + arc_size_progress); + int64_t sweep_keyframe = (elapsed_time / arc_time) % 2; + if (sweep_keyframe == 0) + sweep -= arc_size; + + // This part makes sure the sweep is at least 5 degrees long. Roughly + // equivalent to the "magic constants" in SVG's fillunfill animation. + const double min_sweep_length = 5.0; + if (sweep >= 0.0 && sweep < min_sweep_length) { + start_angle -= (min_sweep_length - sweep); + sweep = min_sweep_length; + } else if (sweep <= 0.0 && sweep > -min_sweep_length) { + start_angle += (-min_sweep_length - sweep); + sweep = -min_sweep_length; + } + + // To keep the sweep smooth, we have an additional rotation after each + // |arc_time| period has elapsed. See SVG's 'rot' animation. + int64_t rot_keyframe = (elapsed_time / (arc_time * 2)) % 4; + PaintArc(canvas, start_angle + rot_keyframe * arc_size, sweep); +} + +void MaterialThrobber::PaintWaiting(gfx::Canvas* canvas) { + // Calculate start and end points. The angles are counter-clockwise because + // the throbber spins counter-clockwise. The finish angle starts at 12 o'clock + // (90 degrees) and rotates steadily. The start angle trails 180 degrees + // behind, except for the first half revolution, when it stays at 12 o'clock. + base::TimeDelta revolution_time = base::TimeDelta::FromMilliseconds(1320); + base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time(); + int64_t twelve_oclock = 90; + int64_t finish_angle = twelve_oclock + 360 * elapsed_time / revolution_time; + int64_t start_angle = std::max(finish_angle - 180, twelve_oclock); + + // Negate the angles to convert to the clockwise numbers Skia expects. + PaintArc(canvas, -start_angle, -(finish_angle - start_angle)); +} + +void MaterialThrobber::PaintArc(gfx::Canvas* canvas, + SkScalar start_angle, + SkScalar sweep) { gfx::Rect bounds = GetContentsBounds(); // Inset by half the stroke width to make sure the whole arc is inside // the visible rect. @@ -192,20 +240,8 @@ int inset = SkScalarCeilToInt(stroke_width / 2.0); oval.Inset(inset, inset); - // Calculate start and end points. The angles are counter-clockwise because - // the throbber spins counter-clockwise. The finish angle starts at 12 o'clock - // (90 degrees) and rotates steadily. The start angle trails 180 degrees - // behind, except for the first half revolution, when it stays at 12 o'clock. - base::TimeDelta revolution_time = base::TimeDelta::FromMilliseconds(1320); - base::TimeDelta elapsed_time = base::Time::Now() - start_time(); - int64_t twelve_oclock = 90; - int64_t finish_angle = twelve_oclock + 360 * elapsed_time / revolution_time; - int64_t start_angle = std::max(finish_angle - 180, twelve_oclock); - SkPath path; - // Negate the angles to convert to the clockwise numbers Skia expects. - path.arcTo(gfx::RectToSkRect(oval), -start_angle, - -(finish_angle - start_angle), true); + path.arcTo(gfx::RectToSkRect(oval), start_angle, sweep, true); SkPaint paint; // TODO(estade): find a place for this color.
diff --git a/ui/views/controls/throbber.h b/ui/views/controls/throbber.h index 73eedb9..8c8bb91 100644 --- a/ui/views/controls/throbber.h +++ b/ui/views/controls/throbber.h
@@ -41,18 +41,14 @@ void OnPaint(gfx::Canvas* canvas) override; protected: - bool running() const { return running_; } - base::Time start_time() const { return start_time_; } - // Specifies whether the throbber is currently animating or not + bool IsRunning() const; + base::TimeTicks start_time() const { return start_time_; } private: - void Run(); - - bool running_; bool paint_while_stopped_; int frame_count_; // How many frames we have. - base::Time start_time_; // Time when Start was called. + base::TimeTicks start_time_; // Time when Start was called. const gfx::ImageSkia* frames_; // Frames images. base::TimeDelta frame_time_; // How long one frame is displayed. base::RepeatingTimer<Throbber> timer_; // Used to schedule Run calls. @@ -116,6 +112,16 @@ void OnPaint(gfx::Canvas* canvas) override; private: + // Paints this throbber in the "waiting" state, for example when waiting for + // an initial network response. + void PaintWaiting(gfx::Canvas* canvas); + + // Paints this throbber in its normal state. Corresponds to MD throbber. + void PaintSpinning(gfx::Canvas* canvas); + + // Common painting code for PaintWaiting and PaintSpinning. + void PaintArc(gfx::Canvas* canvas, SkScalar start_angle, SkScalar sweep); + // The preferred width and height for this view. Zero indicates the size is // set by the parent class (i.e. matches the size of the pre-material // sprites).
diff --git a/ui/views/test/event_generator_delegate_mac.mm b/ui/views/test/event_generator_delegate_mac.mm index b36eb53..18f81c0 100644 --- a/ui/views/test/event_generator_delegate_mac.mm +++ b/ui/views/test/event_generator_delegate_mac.mm
@@ -78,8 +78,6 @@ if (modifiers) *modifiers = EventFlagsToModifiers(flags); switch (ui_event_type) { - case ui::ET_UNKNOWN: - return 0; case ui::ET_KEY_PRESSED: return NSKeyDown; case ui::ET_KEY_RELEASED: @@ -111,7 +109,7 @@ return NSEventTypeSwipe; default: NOTREACHED(); - return 0; + return NSApplicationDefined; } } @@ -128,6 +126,8 @@ case NSKeyUp: [responder keyUp:event]; return; + default: + break; } // For mouse events, NSWindow will use -[NSView hitTest:] for the initial
diff --git a/ui/views/view.cc b/ui/views/view.cc index 78659ca..c79cc6c8 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -748,7 +748,8 @@ ui::PaintContext context = parent_context.CloneWithPaintOffset(offset_to_parent); - if (context.CanCheckInvalidated()) { + bool is_invalidated = true; + if (context.CanCheckInvalid()) { #if DCHECK_IS_ON() gfx::Vector2d offset; context.Visited(this); @@ -770,10 +771,12 @@ // If the View wasn't invalidated, don't waste time painting it, the output // would be culled. - if (!context.IsRectInvalidated(GetLocalBounds())) - return; + is_invalidated = context.IsRectInvalid(GetLocalBounds()); } + if (!is_invalidated && context.ShouldEarlyOutOfPaintingWhenValid()) + return; + TRACE_EVENT1("views", "View::Paint", "class", GetClassName()); // If the view is backed by a layer, it should paint with itself as the origin @@ -803,8 +806,8 @@ clip_transform_recorder->Transform(transform_from_parent); } - { - ui::PaintRecorder recorder(context); + if (is_invalidated || !paint_cache_.UseCache(context)) { + ui::PaintRecorder recorder(context, &paint_cache_); gfx::Canvas* canvas = recorder.canvas(); gfx::ScopedCanvas scoped_canvas(canvas);
diff --git a/ui/views/view.h b/ui/views/view.h index 00813e0..1a56db5 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -24,6 +24,7 @@ #include "ui/base/ui_base_types.h" #include "ui/compositor/layer_delegate.h" #include "ui/compositor/layer_owner.h" +#include "ui/compositor/paint_cache.h" #include "ui/events/event.h" #include "ui/events/event_target.h" #include "ui/gfx/geometry/insets.h" @@ -1509,6 +1510,9 @@ // Border. scoped_ptr<Border> border_; + // Cached output of painting to be reused in future frames until invalidated. + ui::PaintCache paint_cache_; + // RTL painting -------------------------------------------------------------- // Indicates whether or not the gfx::Canvas object passed to View::Paint()
diff --git a/ui/views/views_delegate.cc b/ui/views/views_delegate.cc index 4c1ae4f..c801d36a 100644 --- a/ui/views/views_delegate.cc +++ b/ui/views/views_delegate.cc
@@ -91,6 +91,13 @@ return program.BaseName().AsUTF8Unsafe(); } +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) +scoped_refptr<base::TaskRunner> + ViewsDelegate::GetTaskRunnerForAuraLinuxAccessibilityInit() { + return nullptr; +} +#endif + #if defined(OS_WIN) int ViewsDelegate::GetAppbarAutohideEdges(HMONITOR monitor, const base::Closure& callback) {
diff --git a/ui/views/views_delegate.h b/ui/views/views_delegate.h index ea14e78..d31ea03 100644 --- a/ui/views/views_delegate.h +++ b/ui/views/views_delegate.h
@@ -19,6 +19,7 @@ #include "ui/views/widget/widget.h" namespace base { +class TaskRunner; class TimeDelta; } @@ -138,6 +139,13 @@ // Returns the user-visible name of the application. virtual std::string GetApplicationName(); +#if defined(OS_LINUX) && !defined(OS_CHROMEOS) + // Get a task runner suitable for posting initialization tasks for + // Aura Linux accessibility. + virtual scoped_refptr<base::TaskRunner> + GetTaskRunnerForAuraLinuxAccessibilityInit(); +#endif + #if defined(OS_WIN) // Starts a query for the appbar autohide edges of the specified monitor and // returns the current value. If the query finds the edges have changed from
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc index f55c3756..9fbb62a4 100644 --- a/ui/views/widget/widget_interactive_uitest.cc +++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -659,9 +659,9 @@ WidgetActivationTest() : active_(false) {} - virtual ~WidgetActivationTest() {} + ~WidgetActivationTest() override {} - virtual void OnNativeWidgetActivationChanged(bool active) override { + void OnNativeWidgetActivationChanged(bool active) override { active_ = active; } @@ -1343,7 +1343,7 @@ class MouseEventTrackingWidget : public Widget { public: MouseEventTrackingWidget() : got_mouse_event_(false) {} - virtual ~MouseEventTrackingWidget() {} + ~MouseEventTrackingWidget() override {} bool GetAndClearGotMouseEvent() { bool value = got_mouse_event_; @@ -1352,7 +1352,7 @@ } // Widget: - virtual void OnMouseEvent(ui::MouseEvent* event) override { + void OnMouseEvent(ui::MouseEvent* event) override { got_mouse_event_ = true; Widget::OnMouseEvent(event); }
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html new file mode 100644 index 0000000..3aa61ab --- /dev/null +++ b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.html
@@ -0,0 +1,12 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/core-icon/core-icon.html"> +<link rel="import" href="chrome://resources/polymer/paper-icon-button/paper-icon-button.html"> + +<polymer-element name="cr-expand-button"> + <template> + <paper-icon-button toggle active="{{expanded}}" disabled="{{disabled}}" + icon="{{expanded ? 'expand-less' : 'expand-more'}}"> + </paper-icon-button> + </template> + <script src="cr_expand_button.js"></script> +</polymer-element>
diff --git a/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js new file mode 100644 index 0000000..dfb312a --- /dev/null +++ b/ui/webui/resources/cr_elements/cr_expand_button/cr_expand_button.js
@@ -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. + +/** + * @fileoverview + * 'cr-expand-button' is a chrome-specific wrapper around paper-button that + * toggles between an opened (expanded) and closed state. + * + * Example: + * + * <cr-expand-button expanded="{{sectionIsExpanded}}"></cr-expand-button> + * + * @group Chrome Elements + * @element cr-expand-button + */ +Polymer('cr-expand-button', { + publish: { + /** + * If true, the button is in the expanded state and will show the + * 'expand-less' icon. If false, the button shows the 'expand-more' icon. + * + * @attribute expanded + * @type {boolean} + * @default false + */ + expanded: false, + + /** + * If true, the button will be disabled and greyed out. + * + * @attribute disabled + * @type {boolean} + * @default false + */ + disabled: {value: false, reflect: true}, + }, +});
diff --git a/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.css b/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.css new file mode 100644 index 0000000..b4d5de05 --- /dev/null +++ b/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.css
@@ -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. */ + +#container { + border: 1px solid; + max-height: 1000px; + min-height: 50px; + overflow-y: auto; +} + +/* Note: the 'flex' attribute on core-list doesn't work as expected. */ +#networkList { + flex: 1; +}
diff --git a/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.html b/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.html new file mode 100644 index 0000000..0c685700 --- /dev/null +++ b/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.html
@@ -0,0 +1,23 @@ +<link rel="import" href="chrome://resources/polymer/polymer/polymer.html"> +<link rel="import" href="chrome://resources/polymer/core-list/core-list.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_collapse/cr_collapse.html"> +<link rel="import" href="chrome://resources/cr_elements/cr_network_list_item/cr_network_list_item.html"> + +<polymer-element name="cr-network-list"> + <template> + <link rel="stylesheet" href="cr_network_list.css"> + <cr-collapse on-core-resize="{{onResized_}}" opened="{{opened}}"> + <div id="container" vertical layout flex> + <core-list id="networkList" + data="{{networks}}" + on-core-activate="{{onSelected_}}"> + <template> + <cr-network-list-item networkState="{{model}}" isListItem> + </cr-network-list-item> + </template> + </core-list> + </div> + </cr-collapse> + </template> + <script src="cr_network_list.js"></script> +</polymer-element>
diff --git a/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.js b/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.js new file mode 100644 index 0000000..4fcd048 --- /dev/null +++ b/ui/webui/resources/cr_elements/cr_network_list/cr_network_list.js
@@ -0,0 +1,72 @@ +// 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 Polymer element for displaying a collapsable list of networks. + */ + +/** + * Polymer class definition for 'cr-network-list'. + * @element cr-network-list + */ +Polymer('cr-network-list', { + publish: { + /** + * The maximum height in pixels for the list. + * + * @attribute maxHeight + * @type {number} + * @default 1000 + */ + maxHeight: 1000, + + /** + * The list of network state properties for the items to display. + * + * @attribute networks + * @type {?Array<!CrOncDataElement>} + * @default null + */ + networks: null, + + /** + * True if the list is opened. + * + * @attribute opened + * @type {boolean} + * @default false + */ + opened: false, + }, + + /** @override */ + created: function() { + this.networks = []; + }, + + /** + * Polymer maxHeight changed method. + */ + maxHeightChanged: function() { + this.$.container.style.maxHeight = this.maxHeight + "px"; + }, + + /** + * Called when the cr-collapse element changes size (i.e. is opened). + * @private + */ + onResized_: function() { + if (this.opened) + this.$.networkList.updateSize(); + }, + + /** + * Event triggered when a list item is selected. + * @param {!{detail: CrOncDataElement}} event + * @private + */ + onSelected_: function(event) { + this.fire('selected', event.detail.item.networkState); + } +});
diff --git a/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.css b/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.css index 828c09e..b4d8466 100644 --- a/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.css +++ b/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.css
@@ -8,10 +8,9 @@ flex-direction: row; margin: 0; padding: 4px; - width: 100%; } -#divOuter:hover { +#divOuter.listItem:hover { background-color: lightgrey; }
diff --git a/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.html b/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.html index cd790f5..3e9532ab 100644 --- a/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.html +++ b/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.html
@@ -4,9 +4,10 @@ <polymer-element name="cr-network-list-item"> <template> <link rel="stylesheet" href="cr_network_list_item.css"> - <div id="divOuter"> + <div id="divOuter" class="{{ {listItem: isListItem} | tokenList }}"> <div id="divIcon"> - <cr-network-icon id="icon" networkState="{{networkState}}"> + <cr-network-icon id="icon" + networkState="{{networkState}}" isListItem="{{isListItem}}"> </cr-network-icon> </div> <div id="divText">
diff --git a/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.js b/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.js index 39786b7f..5180403 100644 --- a/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.js +++ b/ui/webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.js
@@ -14,7 +14,7 @@ * Performs argument substitution, replacing %1, %2, etc in 'text' with * corresponding entries in |args|. * @param {string} text The string to perform the substitution on. - * @param {Array<string>} args The arguments to replace %1, %2, etc with. + * @param {?Array<string>} args The arguments to replace %1, %2, etc with. */ function getText(text, args) { var res = text; @@ -52,7 +52,7 @@ * The ONC data properties used to display the list item. * * @attribute networkState - * @type CrOncDataElement + * @type {?CrOncDataElement} * @default null */ networkState: null, @@ -64,7 +64,7 @@ * of the network type plus the network name and connection state. * * @attribute isListItem - * @type boolean + * @type {boolean} * @default false */ isListItem: false, @@ -83,12 +83,17 @@ if (this.isListItem) { this.$.networkName.textContent = getText(network.Name); this.$.networkName.classList.toggle('connected', !isDisconnected); - } else { + } else if (network.Name && network.ConnectionState) { this.$.networkName.textContent = getText(network.Type); this.$.networkName.classList.toggle('connected', false); this.$.networkState.textContent = getConnectionStateText(network.ConnectionState, network.Name); this.$.networkState.classList.toggle('connected', !isDisconnected); + } else { + this.$.networkName.textContent = getText(network.Type); + this.$.networkName.classList.toggle('connected', false); + this.$.networkState.textContent = getText('Disabled'); + this.$.networkState.classList.toggle('connected', false); } }, });
diff --git a/ui/webui/resources/cr_elements_resources.grdp b/ui/webui/resources/cr_elements_resources.grdp index 960cc81..eb39a7f7 100644 --- a/ui/webui/resources/cr_elements_resources.grdp +++ b/ui/webui/resources/cr_elements_resources.grdp
@@ -36,6 +36,12 @@ <structure name="IDR_CR_ELEMENTS_CR_DROPDOWN_MENU_JS" file="../../webui/resources/cr_elements/cr_dropdown_menu/cr_dropdown_menu.js" type="chrome_html" /> + <structure name="IDR_CR_ELEMENTS_CR_EXPAND_BUTTON_HTML" + file="../../webui/resources/cr_elements/cr_expand_button/cr_expand_button.html" + type="chrome_html" /> + <structure name="IDR_CR_ELEMENTS_CR_EXPAND_BUTTON_JS" + file="../../webui/resources/cr_elements/cr_expand_button/cr_expand_button.js" + type="chrome_html" /> <structure name="IDR_CR_ELEMENTS_CR_NETWORK_ICON_CSS" file="../../webui/resources/cr_elements/cr_network_icon/cr_network_icon.css" type="chrome_html" /> @@ -45,6 +51,15 @@ <structure name="IDR_CR_ELEMENTS_CR_NETWORK_ICON_JS" file="../../webui/resources/cr_elements/cr_network_icon/cr_network_icon.js" type="chrome_html" /> + <structure name="IDR_CR_ELEMENTS_CR_NETWORK_LIST_CSS" + file="../../webui/resources/cr_elements/cr_network_list/cr_network_list.css" + type="chrome_html" /> + <structure name="IDR_CR_ELEMENTS_CR_NETWORK_LIST_HTML" + file="../../webui/resources/cr_elements/cr_network_list/cr_network_list.html" + type="chrome_html" /> + <structure name="IDR_CR_ELEMENTS_CR_NETWORK_LIST_JS" + file="../../webui/resources/cr_elements/cr_network_list/cr_network_list.js" + type="chrome_html" /> <structure name="IDR_CR_ELEMENTS_CR_NETWORK_LIST_ITEM_CSS" file="../../webui/resources/cr_elements/cr_network_list_item/cr_network_list_item.css" type="chrome_html" />
diff --git a/ui/webui/resources/js/cr/ui/context_menu_handler.js b/ui/webui/resources/js/cr/ui/context_menu_handler.js index d165b69..1ff7b6e 100644 --- a/ui/webui/resources/js/cr/ui/context_menu_handler.js +++ b/ui/webui/resources/js/cr/ui/context_menu_handler.js
@@ -93,7 +93,7 @@ this.hideTimestamp_ = cr.isWindows ? Date.now() : 0; var ev = new Event('hide'); - ev.element = menu.contextElement; + ev.element = originalContextElement; ev.menu = menu; this.dispatchEvent(ev); },
diff --git a/ui/webui/resources/js/cr/ui/menu.js b/ui/webui/resources/js/cr/ui/menu.js index 22d93b4..d54f5430 100644 --- a/ui/webui/resources/js/cr/ui/menu.js +++ b/ui/webui/resources/js/cr/ui/menu.js
@@ -88,7 +88,7 @@ * @private */ findMenuItem_: function(node) { - while (node && node.parentNode != this) { + while (node && node.parentNode != this && !(node instanceof MenuItem)) { node = node.parentNode; } return node ? assertInstanceof(node, MenuItem) : null;
diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc index edcf4b7d..3665760 100644 --- a/win8/metro_driver/chrome_app_view_ash.cc +++ b/win8/metro_driver/chrome_app_view_ash.cc
@@ -146,7 +146,7 @@ : ui_proxy_(ui_loop->message_loop_proxy()), app_view_(app_view) {} - virtual bool OnMessageReceived(const IPC::Message& message) override { + bool OnMessageReceived(const IPC::Message& message) override { IPC_BEGIN_MESSAGE_MAP(ChromeChannelListener, message) IPC_MESSAGE_HANDLER(MetroViewerHostMsg_ActivateDesktop, OnActivateDesktop) @@ -170,7 +170,7 @@ return true; } - virtual void OnChannelError() override { + void OnChannelError() override { DVLOG(1) << "Channel error. Exiting."; ui_proxy_->PostTask(FROM_HERE, base::Bind(&ChromeAppViewAsh::OnMetroExit, base::Unretained(app_view_),
diff --git a/win8/metro_driver/chrome_app_view_ash.h b/win8/metro_driver/chrome_app_view_ash.h index 4ad011f..366f507 100644 --- a/win8/metro_driver/chrome_app_view_ash.h +++ b/win8/metro_driver/chrome_app_view_ash.h
@@ -59,7 +59,7 @@ public metro_driver::TextServiceDelegate { public: ChromeAppViewAsh(); - ~ChromeAppViewAsh(); + ~ChromeAppViewAsh() override; // IViewProvider overrides. IFACEMETHOD(Initialize)(winapp::Core::ICoreApplicationView* view); @@ -120,18 +120,18 @@ class PointerInfoHandler; // ImePopupObserver overrides. - virtual void OnImePopupChanged(ImePopupObserver::EventType event) override; + void OnImePopupChanged(ImePopupObserver::EventType event) override; // InputSourceObserver overrides. - virtual void OnInputSourceChanged() override; + void OnInputSourceChanged() override; // TextServiceDelegate overrides. - virtual void OnCompositionChanged( + void OnCompositionChanged( const base::string16& text, int32 selection_start, int32 selection_end, const std::vector<metro_viewer::UnderlineInfo>& underlines) override; - virtual void OnTextCommitted(const base::string16& text) override; + void OnTextCommitted(const base::string16& text) override; // Convenience for sending a MetroViewerHostMsg_MouseButton with the specified // parameters.
diff --git a/win8/metro_driver/file_picker.cc b/win8/metro_driver/file_picker.cc index 978386e..1ccfbb9 100644 --- a/win8/metro_driver/file_picker.cc +++ b/win8/metro_driver/file_picker.cc
@@ -114,7 +114,7 @@ explicit OpenFilePickerSession(OPENFILENAME* open_file_name); private: - virtual HRESULT StartFilePicker() override; + HRESULT StartFilePicker() override; typedef winfoundtn::IAsyncOperation<winstorage::StorageFile*> SingleFileAsyncOp; @@ -142,7 +142,7 @@ explicit SaveFilePickerSession(OPENFILENAME* open_file_name); private: - virtual HRESULT StartFilePicker() override; + HRESULT StartFilePicker() override; typedef winfoundtn::IAsyncOperation<winstorage::StorageFile*> SaveFileAsyncOp;
diff --git a/win8/metro_driver/file_picker_ash.h b/win8/metro_driver/file_picker_ash.h index 2f5d996..91eee2f7 100644 --- a/win8/metro_driver/file_picker_ash.h +++ b/win8/metro_driver/file_picker_ash.h
@@ -92,7 +92,7 @@ } private: - virtual HRESULT StartFilePicker() override; + HRESULT StartFilePicker() override; typedef winfoundtn::IAsyncOperation<winstorage::StorageFile*> SingleFileAsyncOp; @@ -132,7 +132,7 @@ int SaveFilePickerSession::filter_index() const; private: - virtual HRESULT StartFilePicker() override; + HRESULT StartFilePicker() override; typedef winfoundtn::IAsyncOperation<winstorage::StorageFile*> SaveFileAsyncOp; @@ -152,7 +152,7 @@ const base::string16& title); private: - virtual HRESULT StartFilePicker() override; + HRESULT StartFilePicker() override; typedef winfoundtn::IAsyncOperation<winstorage::StorageFolder*> FolderPickerAsyncOp;
diff --git a/win8/metro_driver/ime/input_source.cc b/win8/metro_driver/ime/input_source.cc index 6a63751..c734ad2d 100644 --- a/win8/metro_driver/ime/input_source.cc +++ b/win8/metro_driver/ime/input_source.cc
@@ -92,14 +92,14 @@ monitor_->SetCallback(base::Bind(&InputSourceImpl::OnLanguageChanged, base::Unretained(this))); } - virtual ~InputSourceImpl() { + ~InputSourceImpl() override { monitor_->SetCallback(base::Closure()); monitor_->Unadvise(); } private: // InputSource overrides. - virtual bool GetActiveSource(LANGID* langid, bool* is_ime) override { + bool GetActiveSource(LANGID* langid, bool* is_ime) override { TF_INPUTPROCESSORPROFILE profile = {}; HRESULT hr = profile_manager_->GetActiveProfile(GUID_TFCAT_TIP_KEYBOARD, &profile); @@ -112,10 +112,10 @@ *is_ime = profile.dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR; return true; } - virtual void AddObserver(InputSourceObserver* observer) override { + void AddObserver(InputSourceObserver* observer) override { observer_list_.AddObserver(observer); } - virtual void RemoveObserver(InputSourceObserver* observer) override { + void RemoveObserver(InputSourceObserver* observer) override { observer_list_.RemoveObserver(observer); } void OnLanguageChanged() {
diff --git a/win8/metro_driver/ime/text_service.cc b/win8/metro_driver/ime/text_service.cc index 4601f27..ebfc23a 100644 --- a/win8/metro_driver/ime/text_service.cc +++ b/win8/metro_driver/ime/text_service.cc
@@ -326,13 +326,13 @@ DCHECK(window_handle != NULL); DCHECK(thread_manager_.get()); } - virtual ~TextServiceImpl() { + ~TextServiceImpl() override { thread_manager_->Deactivate(); } private: // TextService overrides: - virtual void CancelComposition() override { + void CancelComposition() override { if (!current_document_) { VLOG(0) << "|current_document_| is NULL due to the previous error."; return; @@ -343,7 +343,7 @@ text_store->CancelComposition(); } - virtual void OnDocumentChanged( + void OnDocumentChanged( const std::vector<int32>& input_scopes, const std::vector<metro_viewer::CharacterBounds>& character_bounds) override { @@ -354,7 +354,7 @@ OnDocumentTypeChanged(input_scopes); } - virtual void OnWindowActivated() override { + void OnWindowActivated() override { if (!current_document_) { VLOG(0) << "|current_document_| is NULL due to the previous error."; return; @@ -371,7 +371,7 @@ } } - virtual void OnCompositionChanged( + void OnCompositionChanged( const base::string16& text, int32 selection_start, int32 selection_end, @@ -384,13 +384,13 @@ underlines); } - virtual void OnTextCommitted(const base::string16& text) override { + void OnTextCommitted(const base::string16& text) override { if (!delegate_) return; delegate_->OnTextCommitted(text); } - virtual RECT GetCaretBounds() override { + RECT GetCaretBounds() override { if (composition_character_bounds_.empty()) { const RECT rect = {}; return rect; @@ -410,8 +410,7 @@ return rect; } - virtual bool GetCompositionCharacterBounds(uint32 index, - RECT* rect) override { + bool GetCompositionCharacterBounds(uint32 index, RECT* rect) override { if (index >= composition_character_bounds_.size()) { return false; }
diff --git a/win8/metro_driver/metro_driver.gyp b/win8/metro_driver/metro_driver.gyp index ce09c1d..1a815e4 100644 --- a/win8/metro_driver/metro_driver.gyp +++ b/win8/metro_driver/metro_driver.gyp
@@ -31,19 +31,9 @@ { 'target_name': 'metro_driver_version_resources', 'type': 'none', - 'conditions': [ - ['branding == "Chrome"', { - 'variables': { - 'branding_path': '../../chrome/app/theme/google_chrome/BRANDING', - }, - }, { # else branding!="Chrome" - 'variables': { - 'branding_path': '../../chrome/app/theme/chromium/BRANDING', - }, - }], - ], 'variables': { 'output_dir': 'metro_driver', + 'branding_path': '../../chrome/app/theme/<(branding_path_component)/BRANDING', 'template_input_path': '../../chrome/app/chrome_version.rc.version', }, 'sources': [
diff --git a/win8/metro_driver/metro_driver_win7.cc b/win8/metro_driver/metro_driver_win7.cc index d5496d6..4dde00bd 100644 --- a/win8/metro_driver/metro_driver_win7.cc +++ b/win8/metro_driver/metro_driver_win7.cc
@@ -569,7 +569,7 @@ ::SetProp(core_hwnd_, kAshWin7CoreWindowHandler, this); } - ~CoreWindowEmulation() { + ~CoreWindowEmulation() override { if (core_hwnd_) { ::RemoveProp(core_hwnd_, kAshWin7CoreWindowHandler); ::DestroyWindow(core_hwnd_); @@ -642,38 +642,38 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE Activate(void) override { + HRESULT STDMETHODCALLTYPE Activate(void) override { // After we fire OnActivate on the View, Chrome calls us back here. return S_OK; } - virtual HRESULT STDMETHODCALLTYPE Close(void) override { + HRESULT STDMETHODCALLTYPE Close(void) override { ::PostMessage(core_hwnd_, WM_CLOSE, 0, 0); core_hwnd_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE GetAsyncKeyState( + HRESULT STDMETHODCALLTYPE GetAsyncKeyState( ABI::Windows::System::VirtualKey virtualKey, winui::Core::CoreVirtualKeyStates* KeyState) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE GetKeyState( + HRESULT STDMETHODCALLTYPE GetKeyState( ABI::Windows::System::VirtualKey virtualKey, winui::Core::CoreVirtualKeyStates* KeyState) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE ReleasePointerCapture(void) override { + HRESULT STDMETHODCALLTYPE ReleasePointerCapture(void) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE SetPointerCapture(void) override { + HRESULT STDMETHODCALLTYPE SetPointerCapture(void) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_Activated( + HRESULT STDMETHODCALLTYPE add_Activated( WindowActivatedHandler* handler, EventRegistrationToken* pCookie) override { window_activated_handler_ = handler; @@ -681,25 +681,25 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_Activated( + HRESULT STDMETHODCALLTYPE remove_Activated( EventRegistrationToken cookie) override { window_activated_handler_->Release(); window_activated_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_AutomationProviderRequested( + HRESULT STDMETHODCALLTYPE add_AutomationProviderRequested( AutomationProviderHandler* handler, EventRegistrationToken* cookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_AutomationProviderRequested( + HRESULT STDMETHODCALLTYPE remove_AutomationProviderRequested( EventRegistrationToken cookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_CharacterReceived( + HRESULT STDMETHODCALLTYPE add_CharacterReceived( CharEventHandler* handler, EventRegistrationToken* pCookie) override { character_received_handler_ = handler; @@ -707,36 +707,36 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_CharacterReceived( + HRESULT STDMETHODCALLTYPE remove_CharacterReceived( EventRegistrationToken cookie) override { character_received_handler_->Release(); character_received_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_Closed( + HRESULT STDMETHODCALLTYPE add_Closed( CoreWindowEventHandler* handler, EventRegistrationToken* pCookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_Closed( + HRESULT STDMETHODCALLTYPE remove_Closed( EventRegistrationToken cookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_InputEnabled( + HRESULT STDMETHODCALLTYPE add_InputEnabled( InputEnabledEventHandler* handler, EventRegistrationToken* pCookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_InputEnabled( + HRESULT STDMETHODCALLTYPE remove_InputEnabled( EventRegistrationToken cookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_KeyDown( + HRESULT STDMETHODCALLTYPE add_KeyDown( KeyEventHandler* handler, EventRegistrationToken* pCookie) override { key_down_handler_ = handler; @@ -744,14 +744,14 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_KeyDown( + HRESULT STDMETHODCALLTYPE remove_KeyDown( EventRegistrationToken cookie) override { key_down_handler_->Release(); key_down_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_KeyUp( + HRESULT STDMETHODCALLTYPE add_KeyUp( KeyEventHandler* handler, EventRegistrationToken* pCookie) override { key_up_handler_ = handler; @@ -759,53 +759,53 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_KeyUp( + HRESULT STDMETHODCALLTYPE remove_KeyUp( EventRegistrationToken cookie) override { key_up_handler_->Release(); key_up_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_PointerCaptureLost( + HRESULT STDMETHODCALLTYPE add_PointerCaptureLost( PointerEventHandler* handler, EventRegistrationToken* cookie) override { mouse_capture_lost_handler_ = handler; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_PointerCaptureLost( + HRESULT STDMETHODCALLTYPE remove_PointerCaptureLost( EventRegistrationToken cookie) override { mouse_capture_lost_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_PointerEntered( + HRESULT STDMETHODCALLTYPE add_PointerEntered( PointerEventHandler* handler, EventRegistrationToken* cookie) override { mouse_entered_handler_ = handler; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_PointerEntered( + HRESULT STDMETHODCALLTYPE remove_PointerEntered( EventRegistrationToken cookie) override { mouse_entered_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_PointerExited( + HRESULT STDMETHODCALLTYPE add_PointerExited( PointerEventHandler* handler, EventRegistrationToken* cookie) override { mouse_exited_handler_ = handler; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_PointerExited( + HRESULT STDMETHODCALLTYPE remove_PointerExited( EventRegistrationToken cookie) override { mouse_exited_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_PointerMoved( + HRESULT STDMETHODCALLTYPE add_PointerMoved( PointerEventHandler* handler, EventRegistrationToken* cookie) override { mouse_moved_handler_ = handler; @@ -813,14 +813,14 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_PointerMoved( + HRESULT STDMETHODCALLTYPE remove_PointerMoved( EventRegistrationToken cookie) override { mouse_moved_handler_->Release(); mouse_moved_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_PointerPressed( + HRESULT STDMETHODCALLTYPE add_PointerPressed( PointerEventHandler* handler, EventRegistrationToken* cookie) override { mouse_pressed_handler_ = handler; @@ -828,14 +828,14 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_PointerPressed( + HRESULT STDMETHODCALLTYPE remove_PointerPressed( EventRegistrationToken cookie) override { mouse_pressed_handler_->Release(); mouse_pressed_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_PointerReleased( + HRESULT STDMETHODCALLTYPE add_PointerReleased( PointerEventHandler* handler, EventRegistrationToken* cookie) override { mouse_released_handler_ = handler; @@ -843,25 +843,25 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_PointerReleased( + HRESULT STDMETHODCALLTYPE remove_PointerReleased( EventRegistrationToken cookie) override { mouse_released_handler_->Release(); mouse_released_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_TouchHitTesting( + HRESULT STDMETHODCALLTYPE add_TouchHitTesting( TouchHitTestHandler* handler, EventRegistrationToken* pCookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_TouchHitTesting( + HRESULT STDMETHODCALLTYPE remove_TouchHitTesting( EventRegistrationToken cookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_PointerWheelChanged( + HRESULT STDMETHODCALLTYPE add_PointerWheelChanged( PointerEventHandler* handler, EventRegistrationToken* cookie) override { mouse_wheel_changed_handler_ = handler; @@ -869,51 +869,50 @@ return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_PointerWheelChanged( + HRESULT STDMETHODCALLTYPE remove_PointerWheelChanged( EventRegistrationToken cookie) override { mouse_wheel_changed_handler_->Release(); mouse_wheel_changed_handler_ = NULL; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_SizeChanged( + HRESULT STDMETHODCALLTYPE add_SizeChanged( SizeChangedHandler* handler, EventRegistrationToken* pCookie) override { // TODO(cpu): implement this. return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_SizeChanged( + HRESULT STDMETHODCALLTYPE remove_SizeChanged( EventRegistrationToken cookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged( + HRESULT STDMETHODCALLTYPE add_VisibilityChanged( VisibilityChangedHandler* handler, EventRegistrationToken* pCookie) override { return S_OK; } - virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged( + HRESULT STDMETHODCALLTYPE remove_VisibilityChanged( EventRegistrationToken cookie) override { return S_OK; } // ICoreWindowInterop implementation: - virtual HRESULT STDMETHODCALLTYPE get_WindowHandle(HWND* hwnd) override { + HRESULT STDMETHODCALLTYPE get_WindowHandle(HWND* hwnd) override { if (!core_hwnd_) return E_FAIL; *hwnd = core_hwnd_; return S_OK; } - virtual HRESULT STDMETHODCALLTYPE put_MessageHandled( - boolean value) override { + HRESULT STDMETHODCALLTYPE put_MessageHandled(boolean value) override { return S_OK; } // InputHandler - virtual bool HandleKeyboardMessage(const MSG& msg) override { + bool HandleKeyboardMessage(const MSG& msg) override { switch (msg.message) { case WM_KEYDOWN: case WM_KEYUP: { @@ -944,7 +943,7 @@ return true; } - virtual bool HandleMouseMessage(const MSG& msg) override { + bool HandleMouseMessage(const MSG& msg) override { PointerEventHandler* handler = NULL; mswr::ComPtr<winui::Core::IPointerEventArgs> event_args; event_args = mswr::Make<MouseEvent>(msg);
diff --git a/win8/viewer/metro_viewer_process_host.h b/win8/viewer/metro_viewer_process_host.h index 95f3688..12f4c88 100644 --- a/win8/viewer/metro_viewer_process_host.h +++ b/win8/viewer/metro_viewer_process_host.h
@@ -57,7 +57,7 @@ // LaunchViewerAndWaitForConnection(). explicit MetroViewerProcessHost( const scoped_refptr<base::SingleThreadTaskRunner>& ipc_task_runner); - virtual ~MetroViewerProcessHost(); + ~MetroViewerProcessHost() override; // Returns the process id of the viewer process if one is connected to this // host, returns base::kNullProcessId otherwise. @@ -120,11 +120,11 @@ protected: // IPC::Sender implementation: - virtual bool Send(IPC::Message* msg) override; + bool Send(IPC::Message* msg) override; // IPC::Listener implementation: - virtual bool OnMessageReceived(const IPC::Message& message) override; - virtual void OnChannelError() override = 0; + bool OnMessageReceived(const IPC::Message& message) override; + void OnChannelError() override = 0; private: // The following are the implementation for the corresponding static methods @@ -188,7 +188,7 @@ InternalMessageFilter(MetroViewerProcessHost* owner); // IPC::MessageFilter implementation. - virtual void OnChannelConnected(int32 peer_pid) override; + void OnChannelConnected(int32 peer_pid) override; private: MetroViewerProcessHost* owner_;